commit 7428184f013ae392e234c4a51d8b44bf129d5903 Author: Yoga <1836051468@qq.com> Date: Thu Sep 24 16:25:09 2026 +0800 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..97b3f27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +/unpackage/ +/docweb/node_modules/ +/docweb/dist/ +/docs/node_modules/ +.DS_Store +/uni_modules/x-ocr-s/utssdk/app-ios/Resources/ +*._ +._.* +._. +._* \ No newline at end of file diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json new file mode 100644 index 0000000..07b129c --- /dev/null +++ b/.hbuilderx/launch.json @@ -0,0 +1,10 @@ +{ + "version" : "1.0", + "configurations" : [ + { + "customPlaygroundType" : "device", + "playground" : "standard", + "type" : "uni-app:app-android" + } + ] +} diff --git a/.workbuddy/badge-fix-preview.html b/.workbuddy/badge-fix-preview.html new file mode 100644 index 0000000..b76ec31 --- /dev/null +++ b/.workbuddy/badge-fix-preview.html @@ -0,0 +1,262 @@ + + + + + tabbar 角标遮挡 icon · 方案对照 + + + + +

底部 tabbar 角标 · 定位方案对照(375 逻辑宽,1rpx = 0.5px)

+
+
+ + + + diff --git a/.workbuddy/badge-fix-preview.png b/.workbuddy/badge-fix-preview.png new file mode 100644 index 0000000..17d2ead Binary files /dev/null and b/.workbuddy/badge-fix-preview.png differ diff --git a/.workbuddy/badge-preview.html b/.workbuddy/badge-preview.html new file mode 100644 index 0000000..dc7d082 --- /dev/null +++ b/.workbuddy/badge-preview.html @@ -0,0 +1,143 @@ + + + + +

角标尺寸统一 · 效果对照

+
基准 = 「我的」页 · 消息中心 item 右侧角标(高 36rpx / 圆角 18rpx / 字号 22.4rpx)· 375 逻辑宽按 1rpx = 0.5px 渲染
+ +
+

① 角标特写:改前 / 改后 / 基准

+
+
+
+
+
+ 4 +
+
+
+
改前 · xBadge 默认偏小
26 × 13.5 px
+
+
+
+
+
+ 4 +
+
+
+
改后 · 组件库角标已统一
28 × 18 px
+
+
+
4
+
基准 · 列表行自写角标
28 × 18 px
+
+
+
+ +
+
+
进行中 +
2
+
+
待接收 +
4
+
+
历史 +
7
+
+
+
② 事件列表页 · 顶部切换栏(x-tabs 角标)已统一
+
+
首页
+
+
+
4
+
+ 事件 +
+
我的
+
+
③ 事件页 · 底部 tabbar(x-tabbar 角标)已统一
+
+ +
+

④ 与基准同源的两处列表行角标

+
+
+
消息中心
4 条未读
+
4
+ +
+
+
+
事件告警
新的派单会推送给你
+
4
+ +
+
+ + diff --git a/.workbuddy/badge-preview.png b/.workbuddy/badge-preview.png new file mode 100644 index 0000000..eab9b0b Binary files /dev/null and b/.workbuddy/badge-preview.png differ diff --git a/.workbuddy/batch-transfer-preview.html b/.workbuddy/batch-transfer-preview.html new file mode 100644 index 0000000..29a35e6 --- /dev/null +++ b/.workbuddy/batch-transfer-preview.html @@ -0,0 +1,291 @@ + + + + +批量转运 · 点击开启相机 / 接收医院 hr-sheet 预览 + + + +

批量转运 · 顶部点击开启相机 + 接收医院 hr-sheet 弹层

+
设计基准 375 × 812。左:进入页面(相机未启动,接收医院为折叠字段);右:点击「接收医院」整行后唤起底部弹层。
+ +
+ +
+
状态 A · 初始态 — 取景区显示 「点击开启摄像头」,不再自动占有摄像头
+
+ + +
+
+
+ + + + +
点击开启摄像头
+
对准伤员腕带二维码,自动连续识别
+
+
已识别 4
+
+
+
+ + 开启扫码 +
+
+ + 手动输入编号 +
+
+
+ +
+
+ 已扫码伤员4 / 12 + 清空 +
+
王建国危重
男 · 52 岁 · TRIAGE-20260922-0001
+
李华重伤
男 · 35 岁 · TRIAGE-20260922-0003
+
陈小梅轻伤
女 · 28 岁 · TRIAGE-20260922-0006
+
赵国强重伤
男 · 41 岁 · TRIAGE-20260922-0008
+
+ +
+
接收医院
+
+ 协和医院 · 急诊创伤中心 + 床位 2 + +
+
转运方式
+
+
救护车 🚑
+
直升机 🚁
+
+
随车联系人
+
+
姓名
刘伟
+
联系电话
13800006621
+
+
+
+
+
+ + +
+
状态 B · 点击「接收医院」— 唤起 hr-sheet(名称 + 距离,满员置灰不可选)
+
+ + +
+
+
+
+
+
+
已识别 6
+
+
+
+ + 连续扫码中 +
+
+ + 手动输入编号 +
+
+
+ +
+
+ 已扫码伤员6 / 12 + 清空 +
+
王建国危重
男 · 52 岁 · TRIAGE-20260922-0001
+
李华重伤
男 · 35 岁 · TRIAGE-20260922-0003
+
陈小梅轻伤
女 · 28 岁 · TRIAGE-20260922-0006
+
+ +
+
接收医院
+
+ 协和医院 · 急诊创伤中心 + 床位 2 + +
+
转运方式
+
+
救护车 🚑
+
直升机 🚁
+
+
随车联系人
+
+
姓名
刘伟
+
联系电话
13800006621
+
+
+
+ + +
+
+
+ 选择接收医院 + +
+
+
协和医院 · 急诊创伤中心距现场 6.2 km · 约 14 分钟
+ 床位 2 +
+
+
市第一人民医院 · 急诊距现场 8.9 km · 约 21 分钟
+ 床位 5 +
+
+
同仁医院 · 急诊距现场 4.1 km · 但急诊已满
+ 满员 ✕ +
+
+
+
+
+ +
+

改动说明

+ +
+ + diff --git a/.workbuddy/batch-transfer-preview.png b/.workbuddy/batch-transfer-preview.png new file mode 100644 index 0000000..8bef34a Binary files /dev/null and b/.workbuddy/batch-transfer-preview.png differ diff --git a/.workbuddy/bodymap-preview.html b/.workbuddy/bodymap-preview.html new file mode 100644 index 0000000..33f603b --- /dev/null +++ b/.workbuddy/bodymap-preview.html @@ -0,0 +1,271 @@ + + + + +检伤建档 · 2D 人体图鉴 & 伤情抽屉(静态预览) + + + + +
+ +
伤情标记(2D 人体图鉴)+ 手动添加
+
+
+
+
+
正面 · 点部位即标记
+
+
+
+
背面 · 点部位即标记
+
+
+
+ + 查看 JSON › +
+
+
+ +
伤情录入抽屉(xDrawer · 底部弹出)
+
+
+
4
+
+
新增伤情
+
部位已自动填入,其余按默认值预填,可直接保存
+
+
+
+
+
取消
+
保存标记
+
+
+ +
※ 预览为 create.uvue 的静态还原:绿色虚线框是热区(实际运行不可见,这里画出来核对是否覆盖人体轮廓)
+
+ + + + diff --git a/.workbuddy/bodymap-preview.png b/.workbuddy/bodymap-preview.png new file mode 100644 index 0000000..08d796f Binary files /dev/null and b/.workbuddy/bodymap-preview.png differ diff --git a/.workbuddy/dump.html b/.workbuddy/dump.html new file mode 100644 index 0000000..8107622 --- /dev/null +++ b/.workbuddy/dump.html @@ -0,0 +1,308 @@ + + + + tabbar 角标遮挡 icon · 方案对照 + + + + +

底部 tabbar 角标 · 定位方案对照(375 逻辑宽,1rpx = 0.5px)

+
A 本轮修复前(right:0 + 取消出血)
+  item(60px)  {"l":44,"t":110,"r":76,"b":170,"w":32,"h":60}
+  .xBadgeWrap {"l":44,"t":114.5,"r":76,"b":165.5,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":44,"t":114.5,"r":76,"b":165.5,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":48,"t":114.5,"r":72,"b":138.5,"w":24,"h":24}
+  角标        {"l":48,"t":114.5,"r":76,"b":132.5,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:24.0 × 18.0 px(横向占 icon 的 100%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 0.0 px  ✓ 不会被裁
+
+B 上一轮的错解(right:-20rpx,按角标宽 18px 推算)
+  item(60px)  {"l":44,"t":215.8,"r":76,"b":275.8,"w":32,"h":60}
+  .xBadgeWrap {"l":44,"t":220.3,"r":76,"b":271.3,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":44,"t":220.3,"r":76,"b":271.3,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":48,"t":220.3,"r":72,"b":244.3,"w":24,"h":24}
+  角标        {"l":58,"t":218.3,"r":86,"b":236.3,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:14.0 × 16.0 px(横向占 icon 的 58%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 10.0 px  ⚠ 有被裁风险
+
+C 本轮定稿(left:44rpx,3 Tab)
+  item(60px)  {"l":44,"t":321.5,"r":76,"b":381.5,"w":32,"h":60}
+  .xBadgeWrap {"l":44,"t":326,"r":76,"b":377,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":44,"t":326,"r":76,"b":377,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":48,"t":326,"r":72,"b":350,"w":24,"h":24}
+  角标        {"l":66,"t":324,"r":94,"b":342,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:6.0 × 16.0 px(横向占 icon 的 25%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 18.0 px  ⚠ 有被裁风险
+
+C 本轮定稿(left:44rpx,5 Tab 仓管端)
+  item(60px)  {"l":76,"t":427.3,"r":108,"b":487.3,"w":32,"h":60}
+  .xBadgeWrap {"l":76,"t":431.8,"r":108,"b":482.8,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":76,"t":431.8,"r":108,"b":482.8,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":80,"t":431.8,"r":104,"b":455.8,"w":24,"h":24}
+  角标        {"l":98,"t":429.8,"r":126,"b":447.8,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:6.0 × 16.0 px(横向占 icon 的 25%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 18.0 px  ⚠ 有被裁风险
+
+C 本轮定稿(两位数角标,验证向右生长不回头)
+  item(60px)  {"l":76,"t":533,"r":108,"b":593,"w":32,"h":60}
+  .xBadgeWrap {"l":76,"t":537.5,"r":108,"b":588.5,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":76,"t":537.5,"r":108,"b":588.5,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":80,"t":537.5,"r":104,"b":561.5,"w":24,"h":24}
+  角标        {"l":98,"t":535.5,"r":126,"b":553.5,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:6.0 × 16.0 px(横向占 icon 的 25%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 18.0 px  ⚠ 有被裁风险
+
+D 库默认「半出血」(对照:需要上方留白)
+  item(60px)  {"l":44,"t":638.8,"r":76,"b":698.8,"w":32,"h":60}
+  .xBadgeWrap {"l":44,"t":643.3,"r":76,"b":694.3,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":44,"t":643.3,"r":76,"b":694.3,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":48,"t":643.3,"r":72,"b":667.3,"w":24,"h":24}
+  角标        {"l":62,"t":639.3,"r":90,"b":657.3,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:10.0 × 14.0 px(横向占 icon 的 42%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 14.0 px  ⚠ 有被裁风险
+
A 本轮修复前(right:0 + 取消出血)
首页
4
事件
我的
B 上一轮的错解(right:-20rpx,按角标宽 18px 推算)
首页
4
事件
我的
C 本轮定稿(left:44rpx,3 Tab)
首页
4
事件
我的
C 本轮定稿(left:44rpx,5 Tab 仓管端)
扫码
仓库
4
事件
消息
C 本轮定稿(两位数角标,验证向右生长不回头)
扫码
仓库
99
事件
消息
D 库默认「半出血」(对照:需要上方留白)
首页
4
事件
我的
+ + + + + diff --git a/.workbuddy/dump2.html b/.workbuddy/dump2.html new file mode 100644 index 0000000..e5b053a --- /dev/null +++ b/.workbuddy/dump2.html @@ -0,0 +1,314 @@ + + + + tabbar 角标遮挡 icon · 方案对照 + + + + +

底部 tabbar 角标 · 定位方案对照(375 逻辑宽,1rpx = 0.5px)

+
A 本轮修复前(right:0 + 取消出血)
+  item(60px)  {"l":137,"t":110,"r":262,"b":170,"w":125,"h":60}
+  .xBadgeWrap {"l":183.5,"t":114.5,"r":215.5,"b":165.5,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":183.5,"t":114.5,"r":215.5,"b":165.5,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":187.5,"t":114.5,"r":211.5,"b":138.5,"w":24,"h":24}
+  角标        {"l":187.5,"t":114.5,"r":215.5,"b":132.5,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:24.0 × 18.0 px(横向占 icon 的 100%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 0.0 px  ✓ 不会被裁
+
+B 上一轮的错解(right:-20rpx,按角标宽 18px 推算)
+  item(60px)  {"l":137,"t":215.8,"r":262,"b":275.8,"w":125,"h":60}
+  .xBadgeWrap {"l":183.5,"t":220.3,"r":215.5,"b":271.3,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":183.5,"t":220.3,"r":215.5,"b":271.3,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":187.5,"t":220.3,"r":211.5,"b":244.3,"w":24,"h":24}
+  角标        {"l":197.5,"t":218.3,"r":225.5,"b":236.3,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:14.0 × 16.0 px(横向占 icon 的 58%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 0.0 px  ✓ 不会被裁
+
+C 本轮定稿(left:44rpx,3 Tab)
+  item(60px)  {"l":137,"t":321.5,"r":262,"b":381.5,"w":125,"h":60}
+  .xBadgeWrap {"l":183.5,"t":326,"r":215.5,"b":377,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":183.5,"t":326,"r":215.5,"b":377,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":187.5,"t":326,"r":211.5,"b":350,"w":24,"h":24}
+  角标        {"l":205.5,"t":324,"r":233.5,"b":342,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:6.0 × 16.0 px(横向占 icon 的 25%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 0.0 px  ✓ 不会被裁
+
+C 本轮定稿(left:44rpx,5 Tab 仓管端)
+  item(60px)  {"l":162,"t":427.3,"r":237,"b":487.3,"w":75,"h":60}
+  .xBadgeWrap {"l":183.5,"t":431.8,"r":215.5,"b":482.8,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":183.5,"t":431.8,"r":215.5,"b":482.8,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":187.5,"t":431.8,"r":211.5,"b":455.8,"w":24,"h":24}
+  角标        {"l":205.5,"t":429.8,"r":233.5,"b":447.8,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:6.0 × 16.0 px(横向占 icon 的 25%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 0.0 px  ✓ 不会被裁
+
+C 本轮定稿(两位数角标,验证向右生长不回头)
+  item(60px)  {"l":162,"t":533,"r":237,"b":593,"w":75,"h":60}
+  .xBadgeWrap {"l":183.5,"t":537.5,"r":215.5,"b":588.5,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":183.5,"t":537.5,"r":215.5,"b":588.5,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":187.5,"t":537.5,"r":211.5,"b":561.5,"w":24,"h":24}
+  角标        {"l":205.5,"t":535.5,"r":233.5,"b":553.5,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:6.0 × 16.0 px(横向占 icon 的 25%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 0.0 px  ✓ 不会被裁
+
+D 库默认「半出血」(对照:需要上方留白)
+  item(60px)  {"l":137,"t":638.8,"r":262,"b":698.8,"w":125,"h":60}
+  .xBadgeWrap {"l":183.5,"t":643.3,"r":215.5,"b":694.3,"w":32,"h":51}   ← 角标的定位基准(半宽 16.0px)
+  .xBadge     {"l":183.5,"t":643.3,"r":215.5,"b":694.3,"w":32,"h":51}  ✓ 在 item 内
+  icon        {"l":187.5,"t":643.3,"r":211.5,"b":667.3,"w":24,"h":24}
+  角标        {"l":201.5,"t":639.3,"r":229.5,"b":657.3,"w":28,"h":18}   ← 实际宽 28px
+  ⇒ 角标压住 icon:10.0 × 14.0 px(横向占 icon 的 42%)
+  ⇒ 裁切检查:上溢 0.0 / 下溢 0.0 / 右溢 0.0 px  ✓ 不会被裁
+
A 本轮修复前(right:0 + 取消出血)
首页
4
事件
我的
B 上一轮的错解(right:-20rpx,按角标宽 18px 推算)
首页
4
事件
我的
C 本轮定稿(left:44rpx,3 Tab)
首页
4
事件
我的
C 本轮定稿(left:44rpx,5 Tab 仓管端)
扫码
仓库
4
事件
消息
C 本轮定稿(两位数角标,验证向右生长不回头)
扫码
仓库
99
事件
消息
D 库默认「半出血」(对照:需要上方留白)
首页
4
事件
我的
+ + + + + diff --git a/.workbuddy/event-index-preview.html b/.workbuddy/event-index-preview.html new file mode 100644 index 0000000..850d8ce --- /dev/null +++ b/.workbuddy/event-index-preview.html @@ -0,0 +1,109 @@ + + + + +事件中心 · 进行中 / 历史 + + + +

事件中心 · 只保留「进行中 / 历史」

+

Tab 由 3 个变 2 个(各占 50%),点标签可切换查看

+

已移除:「待接收」Tab | P0 全屏推送整块(60 秒倒计时 / 立即接收 / 稍后处理)| 卡片 pending 分支与 footer 守卫 | 空态与注释里对「全屏告警推送」的描述

+ +
+
+
+
进行中
+
历史
+
+
+
+ + + + diff --git a/.workbuddy/event-index-preview.png b/.workbuddy/event-index-preview.png new file mode 100644 index 0000000..65b875c Binary files /dev/null and b/.workbuddy/event-index-preview.png differ diff --git a/.workbuddy/memory/2026-09-24.md b/.workbuddy/memory/2026-09-24.md new file mode 100644 index 0000000..60b7e74 --- /dev/null +++ b/.workbuddy/memory/2026-09-24.md @@ -0,0 +1,695 @@ +# 2026-09-24 医院救援 APP(uniappx + Tmui4)UI 全量重构 + +## 目标 +按 `mobile-design/v2/hospital-rescue-ui-v2.html`(35 屏设计稿)在 uniappx 项目中 1:1 还原 UI,并实现全部交互,兼容 APP + H5,双角色(救援端 / 仓管端)。 + +## 已完成 +- **清空 pages/** 并重建:33 个页面(35 屏中 s07/s42 合并为事件中心同一页的执行状态 Tab) +- **设计令牌落地**:新增 `common/styles/hr-design.css`(App.uvue 全局 @import),因 uvue 限制做了三类适配: + 1. 不支持 `::before/::after` → 全部改为实体元素(如 `.hr-sec-bar`、`.bm-*` 人体图鉴) + 2. 不支持 CSS 变量 `var()` → 颜色全部写实 + 3. 不用 `grid` / `gap` → 全部 flex + margin;只使用 class 选择器(避免复合/后代选择器风险) +- **全局配置**:main.uts 设 `designSize:375 / unit:'px' / color:'#2563EB' / dark:'light'`;manifest 改为「医院救援管理平台 v2.0.0」 +- **mock 数据层**:`mock/types.uts`(类型)+ `mock/index.uts`(数据),页面只依赖类型,后续换接口只改 mock 层 +- **角色体系**:`utils/role.uts`(hrSession / 双角色 TabBar / canAccess 权限拦截)、`utils/nav.uts`(统一跳转+权限拦截)、`utils/quiz.uts`(答题态,供答题页与答题卡共享) +- **16 个通用组件**(components/,easycom):hr-page / hr-statusbar / hr-card / hr-sec / hr-lrow / hr-chip / hr-wb / hr-pc / hr-timeline / hr-tip / hr-empty / hr-progress / hr-wband / hr-tabbar / hr-scan-cam / hr-rec-list +- **复杂交互**:真实相机连续扫码(x-mlkit-scannig-u,批量处置/批量转运/出入库)、P0 全屏推送 60s 倒计时接单、2D 人体图鉴伤情标记增删、多模态上传(chooseImage)、答题卡联动、离线队列模拟重传、设备 5 项自检门禁、接收医院床位满员拦截 +- **双角色 TabBar**:救援端 3 Tab(首页/事件/我的)、仓管端 5 Tab(扫码/仓库/设备/消息/我),登录页可切换角色演示 + +## 关键坑(务必记住) +- uvue 语法:`computed() : T => {}` 是**非法**写法,必须 `computed(() : T => { ... })`——本次批量修了 17 处 +- Vue API 需要**显式** `import { ref, computed } from 'vue'`,不能依赖自动注入 +- `onLoad` 参数用下标访问:`opt['id']`(官方示例 `event["post_id"] ?? ""`),不要用 `getString` +- 视频/取景框不能用 `aspect-ratio` → 用 `uni.getWindowInfo().windowWidth` 计算像素高度 +- 覆盖层(底部选择器/全屏推送)通过 hr-page 的 `overlay` 具名插槽渲染,且在根节点上需 `position:relative` +- 三段式作业页(批量处置/转运)用 hr-page 的 `no-scroll`,内部自管滚动区 +- 图片/图表类设计元素(圆环→x-circle-progress、人体图→几何 view 拼装)不能照搬 SVG + +## 静态校验方法(可复用) +用 esbuild 的 `transformSync(code,{loader:'ts'})` 校验 ` + + diff --git a/.workbuddy/radiobutton-preview.png b/.workbuddy/radiobutton-preview.png new file mode 100644 index 0000000..e35abb6 Binary files /dev/null and b/.workbuddy/radiobutton-preview.png differ diff --git a/.workbuddy/uvue-anim-preview.html b/.workbuddy/uvue-anim-preview.html new file mode 100644 index 0000000..01b93ef --- /dev/null +++ b/.workbuddy/uvue-anim-preview.html @@ -0,0 +1,391 @@ + + + + + + + uvue 动效改写验证 · 红点呼吸 / 扫描线 / 手风琴 + + + + +
+

uvue App 端动效改写 · 效果验证

+

下方三个动效与 App 里 完全相同 的算法在跑(定时器逐帧推进 → 下发内联 style), + 只是把 rpx 折算成 px(1rpx = 0.5px @375)。

+
+ 背景:App 端 uvue 的 CSS 编译器不接受 @keyframes(0%/75%/from/to 选择器直接报 + ERROR)与 animation 属性, + 因此这 3 处动效已全部改为 setInterval + ref 驱动内联样式的等价实现。 +
+ +
+ +
+

① 待接收红点「呼吸」

+

pages/event/index.uvue · evtPulse

+
+
+
+
+ 车祸伤 · 多人受伤 + P0 +
+
+
+
半径 0rpx · 透明度 0.55
+
+ + +
+

② 取景框扫描线

+

pages/warehouse/scan.uvue · hrScanMove

+
+
+
+
+
+
+
+
+
+
将条码对准框内 · 自动识别
+
+
+
top 60rpx → 313rpx · 32 帧 × 68ms = 2.18s
+
+ + +
+

③ 手风琴展开入场

+

pages/study/center.uvue · qa-acc-in

+
+
+
成人胸外按压的深度应为?
+
点击展开解析
+
+
+
+
opacity 0 → 1 · translateY -16rpx → 0 · 240ms
+
+
+
+ + + + + diff --git a/.workbuddy/uvue-anim-preview.png b/.workbuddy/uvue-anim-preview.png new file mode 100644 index 0000000..65b1da9 Binary files /dev/null and b/.workbuddy/uvue-anim-preview.png differ diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..20e4636 --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/App.uvue b/App.uvue new file mode 100644 index 0000000..bb1f417 --- /dev/null +++ b/App.uvue @@ -0,0 +1,62 @@ + + + diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..69e3890 --- /dev/null +++ b/README.en.md @@ -0,0 +1,36 @@ +# x-ui + +#### Description +x-ui基于uniappx ui库,核心工具库等原生开发。 + +#### Software Architecture +Software architecture description + +#### Installation + +1. xxxx +2. xxxx +3. xxxx + +#### Instructions + +1. xxxx +2. xxxx +3. xxxx + +#### Contribution + +1. Fork the repository +2. Create Feat_xxx branch +3. Commit your code +4. Create Pull Request + + +#### Gitee Feature + +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md +2. Gitee blog [blog.gitee.com](https://blog.gitee.com) +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) +4. The most valuable open source project [GVP](https://gitee.com/gvp) +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md new file mode 100644 index 0000000..c526029 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# x-ui + +#### 介绍 +x-ui基于uniappx ui库,核心工具库等原生开发。 + +#### 软件架构 +软件架构说明 + + +#### 安装教程 + +1. xxxx +2. xxxx +3. xxxx + +#### 使用说明 + +1. xxxx +2. xxxx +3. xxxx + +#### 参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 +4. 新建 Pull Request + + +#### 特技 + +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md +2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 +4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 +5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/common/styles/hr-design.css b/common/styles/hr-design.css new file mode 100644 index 0000000..c2e00a7 --- /dev/null +++ b/common/styles/hr-design.css @@ -0,0 +1,1221 @@ +/* ============================================================ + 医院救援管理平台 · 移动端设计系统(uni-app x / uvue 适配版) + Hospital Rescue Management Platform · Mobile Design System + 基准画布 375 × 812 · 主色 #2563EB + ------------------------------------------------------------ + ⚠ uvue 约束: + 1) 不支持 ::before / ::after 伪元素 —— 全部改为实体元素承担装饰; + 2) 不支持 CSS 变量 var() —— 颜色全部写实; + 3) 不使用 display:grid —— 栅格一律 flex + 百分比宽度; + 4) 不使用 gap —— 间距一律 margin(跨端最稳); + 5) 只使用 class 选择器,不使用后代/复合选择器。 + ============================================================ */ + +/* ---------- 页面容器 ---------- */ +.hr-page { + flex: 1; + background-color: #F3F4F6; + flex-direction: column; + position: relative; +} + +.hr-page-white { + flex: 1; + background-color: #FFFFFF; + flex-direction: column; +} + +/* 页面滚动体 */ +.hr-scroll { + flex: 1; + min-height: 0; +} + +/* 内容区容器:作为骨架屏覆盖层的定位基准,范围=导航栏以下、底栏以上 */ +.hr-flow { + flex: 1; + min-height: 0; + position: relative; +} + +/* 加载中覆盖层:绝对定位铺满内容区并居中 xLoading,不参与 flex 布局,因此不会被压缩 */ +.hr-loading-mask { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background-color: #F3F4F6; + z-index: 20; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +} + +/* 关键布局约束:scroll-view 是 flex 容器,直接子项默认 flex-shrink:1, + 内容高于容器时会被压缩到「刚好装下」,表现为页面/骨架屏只显示顶部一小截。 + 因此滚动体的直接子元素必须显式禁止收缩。 */ +.hr-body { + padding: 24rpx 32rpx 44rpx 32rpx; + flex-shrink: 0; + flex-grow: 0; +} + +.hr-body-nopad { + padding: 24rpx 0 44rpx 0; +} + +.hr-body-flush { + padding: 0 0 44rpx 0; +} + +.hr-body-tab { + padding: 24rpx 32rpx 20rpx 32rpx; +} + +/* ---------- 基础布局 ---------- */ +.hr-row { + display: flex; + flex-direction: row; + align-items: center; +} + +.hr-row-top { + display: flex; + flex-direction: row; + align-items: flex-start; +} + +.hr-row-between { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +} + +.hr-col { + display: flex; + flex-direction: column; +} + +.hr-center { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +} + +.hr-flex1 { + flex: 1; +} + +.hr-wrap { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +/* ---------- 文本 ---------- */ +.hr-t1 { + color: #1F2937; +} + +.hr-t2 { + color: #6B7280; +} + +.hr-t3 { + color: #9CA3AF; +} + +.hr-t-pri { + color: #2563EB; +} + +.hr-t-red { + color: #DC2626; +} + +.hr-t-amb { + color: #D97706; +} + +.hr-t-grn { + color: #059669; +} + +.hr-fs10 { + font-size: 22.4rpx; +} + +.hr-fs11 { + font-size: 24.6rpx; +} + +.hr-fs12 { + font-size: 26.8rpx; +} + +.hr-fs13 { + font-size: 29.2rpx; +} + +.hr-fs14 { + font-size: 31.4rpx; +} + +.hr-fs15 { + font-size: 33.6rpx; +} + +.hr-fs17 { + font-size: 38rpx; +} + +.hr-bold { + font-weight: bold; +} + +.hr-mono { + font-family: monospace; + letter-spacing: 0.6rpx; +} + +/* ---------- 卡片 ---------- */ +.hr-card { + background-color: #FFFFFF; + border-radius: 26rpx; + padding: 24rpx 26rpx 24rpx 26rpx; + border: 2rpx solid #F3F4F6; +} + +.hr-card-gap { + margin-bottom: 20rpx; +} + +.hr-card-tight { + padding: 20rpx; +} + +.hr-card-list { + padding: 14rpx 18rpx 14rpx 18rpx; +} + +.hr-card-line { + border: 2rpx solid #E5E7EB; +} + +.hr-card-danger { + border: 2rpx solid #FECACA; + background-color: #FFFBFB; +} + +/* ---------- 小节标题 ---------- */ +.hr-sec { + display: flex; + flex-direction: row; + align-items: center; + margin-top: 32rpx; + margin-bottom: 16rpx; +} + +.hr-sec-first { + margin-top: 8rpx; +} + +.hr-sec-bar { + width: 6rpx; + height: 26rpx; + border-radius: 4rpx; + background-color: #2563EB; + margin-right: 14rpx; +} + +.hr-sec-t { + font-size: 31.4rpx; + font-weight: bold; + color: #1F2937; +} + +.hr-sec-more { + margin-left: auto; + font-size: 25.8rpx; + color: #9CA3AF; +} + +/* ---------- 底部分隔区 ---------- */ +/* xCell 内部 .xCellWrap 写死了 padding:12px 0(且不随 rpx 缩放), + 会让列表行比设计稿明显高一截、文字块也比左侧图标高。 + 这里按项目设计稿收紧,行高由左侧图标(64rpx)决定。 */ +.xCellWrap { + padding: 0 !important; +} + +.xCellAvatar { + margin-right: 20rpx !important; +} + +/* ---------- 列表行 ---------- */ +.hr-lrow { + display: flex; + flex-direction: row; + align-items: center; + padding-top: 22rpx; + padding-bottom: 22rpx; + border-bottom: 2rpx solid #F3F4F6; + min-height: 88rpx; +} + +.hr-lrow-last { + border-bottom-width: 0rpx; +} + +.hr-lrow-first { + padding-top: 8rpx; +} + +.hr-lic { + width: 64rpx; + height: 64rpx; + border-radius: 18rpx; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + font-size: 33.6rpx; + background-color: #F3F4F6; + color: #6B7280; + margin-right: 20rpx; +} + +.hr-lic-lg { + width: 72rpx; + height: 72rpx; + border-radius: 20rpx; + font-size: 35.8rpx; +} + +.hr-lic-pri { + background-color: #EFF6FF; + color: #2563EB; +} + +.hr-lic-red { + background-color: #FEF2F2; + color: #DC2626; +} + +.hr-lic-amb { + background-color: #FEF3C7; + color: #D97706; +} + +.hr-lic-grn { + background-color: #ECFDF5; + color: #059669; +} + +.hr-lmain { + flex: 1; + flex-direction: column; +} + +.hr-lmain-b { + font-size: 31.4rpx; + font-weight: bold; + color: #1F2937; + lines: 1; +} + +.hr-lmain-s { + font-size: 24rpx; + color: #9CA3AF; + margin-top: 2rpx; + lines: 1; +} + +.hr-lval { + font-size: 28rpx; + color: #9CA3AF; + margin-left: 16rpx; +} + +/* ---------- 按钮 ---------- */ +.hr-btn { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + height: 88rpx; + border-radius: 24rpx; + font-size: 32.4rpx; + font-weight: bold; + background-color: #F3F4F6; + color: #1F2937; +} + +.hr-btn-primary { + background-color: #2563EB; + color: #FFFFFF; +} + +.hr-btn-danger { + background-color: #DC2626; + color: #FFFFFF; +} + +.hr-btn-ghost { + background-color: #FFFFFF; + color: #1F2937; + border: 2rpx solid #E5E7EB; +} + +.hr-btn-soft { + background-color: #EFF6FF; + color: #2563EB; +} + +.hr-btn-lg { + height: 104rpx; + font-size: 35.8rpx; + border-radius: 28rpx; +} + +.hr-btn-sm { + height: 68rpx; + font-size: 28rpx; + border-radius: 18rpx; +} + +.hr-btn-disabled { + background-color: #F3F4F6; + color: #9CA3AF; + border: 2rpx solid #E5E7EB; +} + +/* ---------- 底部固定操作条 ---------- */ +.hr-fixedbar { + background-color: #FFFFFF; + border-top: 2rpx solid #F3F4F6; + padding: 22rpx 32rpx 28rpx 32rpx; + display: flex; + flex-direction: row; +} + +.hr-fixedbar-btn { + flex: 1; + margin-right: 18rpx; +} + +.hr-fixedbar-btn-last { + flex: 1; + margin-right: 0rpx; +} + +/* ---------- chip ---------- */ +.hr-chip { + display: flex; + flex-direction: row; + align-items: center; + height: 56rpx; + padding-left: 22rpx; + padding-right: 22rpx; + border-radius: 18rpx; + font-size: 26.8rpx; + font-weight: bold; + color: #6B7280; + background-color: #FFFFFF; + border: 2rpx solid #E5E7EB; + margin-right: 14rpx; +} + +.hr-chip-active { + background-color: #2563EB; + border: 2rpx solid #2563EB; + color: #FFFFFF; +} + +.hr-chip-red { + color: #B91C1C; + background-color: #FEF2F2; + border: 2rpx solid #FECACA; +} + +.hr-chip-amb { + color: #92400E; + background-color: #FEF3C7; + border: 2rpx solid #FDE68A; +} + +.hr-chip-grn { + color: #059669; + background-color: #ECFDF5; + border: 2rpx solid #A7F3D0; +} + +.hr-chip-lg { + height: 80rpx; + padding-left: 26rpx; + padding-right: 26rpx; + border-radius: 20rpx; +} + +/* chip 横向滚动条 */ +.hr-chiprow { + flex-direction: row; + display: flex; +} + +/* ---------- 腕带分级 ---------- */ +.hr-wb { + display: flex; + flex-direction: row; + align-items: center; + height: 48rpx; + padding-left: 18rpx; + padding-right: 18rpx; + border-radius: 14rpx; + font-size: 25.8rpx; + font-weight: bold; +} + +.hr-wb-dot { + width: 14rpx; + height: 14rpx; + border-radius: 4rpx; + margin-right: 10rpx; + background-color: #FFFFFF; +} + +.hr-wb1 { + background-color: #FEE2E2; + color: #B91C1C; +} + +.hr-wb2 { + background-color: #FEF3C7; + color: #92400E; +} + +.hr-wb3 { + background-color: #D1FAE5; + color: #065F46; +} + +.hr-wb4 { + background-color: #E5E7EB; + color: #111827; +} + +.hr-wb-sm { + height: 40rpx; + font-size: 23.6rpx; + border-radius: 12rpx; + padding-left: 14rpx; + padding-right: 14rpx; +} + +/* ---------- 优先级 ---------- */ +.hr-pc { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + height: 42rpx; + padding-left: 16rpx; + padding-right: 16rpx; + border-radius: 12rpx; + font-size: 23.6rpx; + font-weight: bold; +} + +.hr-pc0 { + background-color: #DC2626; + color: #FFFFFF; +} + +.hr-pc1 { + background-color: #F59E0B; + color: #FFFFFF; +} + +.hr-pc2 { + background-color: #2563EB; + color: #FFFFFF; +} + +/* ---------- 角标(全站统一样式) ---------- + 基准 = 我的页「消息中心」右侧角标:高/圆角 36rpx、字号 22.4rpx、红底白字。 + 组件库 xBadge(x-tabbar / x-tabs 内部使用)尺寸由它自己的 padding + 字号决定, + 且以 inline style 下发,因此只能用 !important 覆盖 + (!important 的样式声明优先级高于 inline style)。 */ +.hr-badge { + min-width: 36rpx; + height: 36rpx; + padding-left: 10rpx; + padding-right: 10rpx; + border-radius: 18rpx; + background-color: #DC2626; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + margin-left: 16rpx; +} + +.hr-badge-t { + font-size: 22.4rpx; + font-weight: bold; + color: #FFFFFF; +} + +/* 组件库 xBadge 统一到同一尺寸(tabbar 角标 / tabs 角标) */ +.xBadge-countAndLabel { + min-width: 36rpx !important; + height: 36rpx !important; + padding: 0 10rpx !important; + border-radius: 18rpx !important; + /* + 定位(数值实测自 uni_modules 源码 + 375 逻辑宽换算,1rpx = 0.5px): + 1) 库默认是「半出血」:x-tabbar 给 x-badge 传 :offset="[0,5]",再叠加 + transform: translate(50%,-50%),等于「角标中心 = 容器右上角」, + 需要容器上方留出半个角标高度。而 x-tabbar 的 Tab 项高度写死 60px, + 内容(icon 盒 30px + 文字 ≈23px ≈ 53px)上下各只剩 ~3.5px 余量, + 出血超出 Tab 项的部分会被裁掉 → 故先取消出血(transform:none)。 + 2) 取消出血后若停在库默认的 right:0,角标会大面积压住 icon: + 角标实际宽 28px —— min-width 36rpx 是「内容盒」最小值,还要加左右各 + 10rpx 内边距 ⇒ 18 + 10 = 28px,不是 18px(这点最容易算错); + 而 .xBadgeWrap 宽度 ≈ 左侧 icon 盒宽 = icon 24px + 左右各 4px = 32px。 + right:0 时角标左缘 = wrap.right - 28,几乎完全盖在 icon 上 + —— 这正是用户反馈的「角标遮挡 icon」。 + 3) 故改为「左锚定」,复刻设计稿 .dot 的 left: calc(50% + 6px): + 角标定位基准 .xBadgeWrap 的水平中心与 Tab 项水平中心重合 + (.xBadge / .xBadgeWrap / .xTabbarItem 均为 align-items:center), + 所以 left = wrap 半宽 16px + 6px = 22px = 44rpx, + 角标左缘落在中心右侧 6px 处,与 icon 只重叠 ~6px(设计稿 5px)。 + 左锚定的好处:角标内容变宽(两位数/三位数)只向右生长, + 不会回头盖住 icon,也不用再按「角标自身宽度」重算。 + 4) 上提只取 2px(=4rpx):Tab 项上下余量 ~3.5px,取 2px 后角标顶边仍在 + Tab 项内约 1.5px;即便某些平台文字行高更高,也还有下面的 + overflow:visible 兜底,不会被裁。右侧余量充足: + 角标右缘 = 中心 + 34px,仍小于 5 Tab 布局的项右缘(中心 + 37.5px)。 + */ + top: -4rpx !important; + left: 44rpx !important; + right: auto !important; + transform: none !important; +} + +.xBadge-countAndLabelText { + font-size: 22.4rpx !important; + line-height: 1 !important; +} + +/* + 角标出血:库内 .xBadge 的内边距是 getNodeInfo() 量出来的, + 量到的尺寸可能早于上面 !important 覆盖生效 → 预留空间不足, + 角标超出容器的部分会被裁掉(tabbar 上最明显)。 + view 在 uvue / H5 上的默认裁剪行为不一致,这里统一放开。 +*/ +.xBadge, +.xBadgeWrap, +.xTabbarBox, +.xTabbarWrap, +.xTabbarItem { + overflow: visible !important; +} + +/* + .xBadge 的内边距(getNodeInfo() 量出 ≈ 半个角标)只是库为「半出血」预留的空间。 + 本项目已取消出血(transform:none),去掉该内边距后: + .xBadge 盒子由「内容 53px + 上下内边距 18px = 71px」缩到 53px, + 从「超出 60px 的 Tab 项」变成「完整落在 Tab 项内」→ 任何平台都不会被裁。 + 内容位置不变:.xTabbarItem 是 justify-content:center,两种盒高下内容都垂直居中。 +*/ +.xBadge { + padding: 0 !important; +} + +/* ---------- 提示条 ---------- */ +.hr-tip { + display: flex; + flex-direction: row; + align-items: flex-start; + padding: 20rpx 24rpx 20rpx 24rpx; + border-radius: 22rpx; + font-size: 26.8rpx; +} + +.hr-tip-ic { + margin-right: 16rpx; + font-size: 26.8rpx; +} + +.hr-tip-tx { + flex: 1; + font-size: 26.8rpx; + line-height: 1.5; +} + +.hr-tip-info { + background-color: #EFF6FF; + color: #1E40AF; +} + +.hr-tip-warn { + background-color: #FFFBEB; + color: #92400E; +} + +.hr-tip-err { + background-color: #FEF2F2; + color: #991B1B; +} + +.hr-tip-ok { + background-color: #ECFDF5; + color: #065F46; +} + +/* ---------- 表单 ---------- */ +.hr-field { + background-color: #FFFFFF; + border: 2rpx solid #E5E7EB; + border-radius: 22rpx; + padding: 16rpx 24rpx 16rpx 24rpx; + min-height: 104rpx; + display: flex; + flex-direction: column; + justify-content: center; +} + +.hr-field-label { + font-size: 23.6rpx; + color: #9CA3AF; +} + +.hr-field-input { + font-size: 31.4rpx; + color: #1F2937; + font-weight: bold; + height: 52rpx; + padding: 0 0 0 0; +} + +.hr-field-err { + border: 2rpx solid #DC2626; + background-color: #FFFBFB; +} + +.hr-field-ro { + background-color: #F9FAFB; +} + +/* ---------- 分段控件 ---------- */ +.hr-seg { + display: flex; + flex-direction: row; + background-color: #F3F4F6; + padding: 6rpx 6rpx 6rpx 6rpx; + border-radius: 22rpx; +} + +.hr-seg-i { + flex: 1; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding-top: 16rpx; + padding-bottom: 16rpx; + border-radius: 18rpx; + font-size: 29.2rpx; + font-weight: bold; + color: #6B7280; +} + +.hr-seg-i-on { + background-color: #FFFFFF; + color: #2563EB; +} + +/* ---------- 进度条 ---------- */ +.hr-pbar { + height: 8rpx; + border-radius: 4rpx; + background-color: #F3F4F6; + overflow: hidden; + display: flex; + flex-direction: row; +} + +.hr-pbar-i { + height: 8rpx; + border-radius: 4rpx; + background-color: #2563EB; +} + +/* ---------- 统计块 ---------- */ +.hr-stat-row { + display: flex; + flex-direction: row; +} + +.hr-stat { + flex: 1; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.hr-stat-b { + font-size: 47rpx; + font-weight: bold; + color: #1F2937; +} + +.hr-stat-s { + font-size: 23.6rpx; + color: #6B7280; + margin-top: 6rpx; +} + +.hr-stat-sep { + width: 2rpx; + background-color: #F3F4F6; + height: 60rpx; + margin-top: 8rpx; +} + +/* ---------- 时间线 ---------- */ +.hr-tl { + position: relative; + padding-left: 44rpx; +} + +.hr-tl-line { + position: absolute; + left: 12rpx; + top: 12rpx; + width: 4rpx; + background-color: #E5E7EB; +} + +.hr-tl-item { + position: relative; + padding-bottom: 30rpx; +} + +.hr-tl-dot { + position: absolute; + left: -42rpx; + top: 8rpx; + width: 20rpx; + height: 20rpx; + border-radius: 10rpx; + background-color: #2563EB; +} + +.hr-tl-dot-warn { + background-color: #DC2626; +} + +.hr-tl-dot-ok { + background-color: #10B981; +} + +.hr-tl-time { + font-size: 23.6rpx; + color: #9CA3AF; +} + +.hr-tl-tx { + font-size: 28rpx; + color: #1F2937; + font-weight: bold; + margin-top: 6rpx; +} + +.hr-tl-sub { + font-size: 24.6rpx; + color: #6B7280; + margin-top: 4rpx; +} + +/* ---------- 空状态 / 加载 ---------- */ +.hr-empty { + padding: 88rpx 40rpx 88rpx 40rpx; + display: flex; + flex-direction: column; + align-items: center; +} + +.hr-empty-ic { + width: 112rpx; + height: 112rpx; + border-radius: 36rpx; + background-color: #F3F4F6; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + font-size: 56rpx; + color: #9CA3AF; + margin-bottom: 16rpx; +} + +.hr-empty-b { + font-size: 31.4rpx; + font-weight: bold; + color: #6B7280; +} + +.hr-empty-s { + font-size: 25.8rpx; + color: #9CA3AF; + margin-top: 10rpx; + text-align: center; + lines: 2; +} + +/* ---------- 头像 ---------- */ +.hr-avt { + width: 76rpx; + height: 76rpx; + border-radius: 22rpx; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + background-color: #2563EB; + color: #FFFFFF; + font-size: 33.6rpx; + font-weight: bold; +} + +.hr-avt-sm { + width: 60rpx; + height: 60rpx; + border-radius: 18rpx; + font-size: 28rpx; +} + +.hr-avt-lg { + width: 108rpx; + height: 108rpx; + border-radius: 32rpx; + font-size: 49.2rpx; +} + +.hr-avt-red { + background-color: #DC2626; +} + +.hr-avt-amb { + background-color: #D97706; +} + +.hr-avt-grn { + background-color: #059669; +} + +.hr-avt-gy { + background-color: #94A3B8; +} + +/* ---------- 开关(自绘,兜底用) ---------- */ +.hr-sw { + width: 88rpx; + height: 52rpx; + border-radius: 26rpx; + background-color: #E5E7EB; + padding: 6rpx 6rpx 6rpx 6rpx; + display: flex; + flex-direction: row; + align-items: center; +} + +.hr-sw-on { + background-color: #10B981; + justify-content: flex-end; +} + +.hr-sw-knob { + width: 40rpx; + height: 40rpx; + border-radius: 20rpx; + background-color: #FFFFFF; +} + +/* ---------- 分隔线 ---------- */ +.hr-hr { + height: 2rpx; + background-color: #F3F4F6; +} + +/* ---------- 覆盖层 ---------- */ +.hr-mask { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.45); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.hr-toast { + position: absolute; + left: 50%; + top: 156rpx; + margin-left: -160rpx; + width: 320rpx; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding: 18rpx 30rpx 18rpx 30rpx; + border-radius: 22rpx; + background-color: rgba(17, 24, 39, 0.93); + color: #FFFFFF; + font-size: 28rpx; + font-weight: bold; +} + +.hr-toast-ok { + background-color: rgba(5, 150, 105, 0.95); +} + +.hr-toast-warn { + background-color: rgba(217, 119, 6, 0.95); +} + +.hr-toast-err { + background-color: rgba(185, 28, 28, 0.95); +} + +/* ---------- 离线条 ---------- */ +.hr-offbar { + display: flex; + flex-direction: row; + align-items: center; + padding: 18rpx 32rpx 18rpx 32rpx; + background-color: #FFFBEB; + border-bottom: 2rpx solid #FDE68A; + font-size: 26.8rpx; + font-weight: bold; + color: #92400E; +} + +.hr-offbar-cnt { + background-color: #F59E0B; + color: #FFFFFF; + font-size: 22.4rpx; + font-weight: bold; + padding: 4rpx 12rpx 4rpx 12rpx; + border-radius: 18rpx; + margin-left: 16rpx; + margin-right: 16rpx; +} + +.hr-offbar-go { + margin-left: auto; + font-size: 26.8rpx; + color: #B45309; + font-weight: bold; +} + +/* ---------- 底部弹层 ---------- */ +.hr-sheet-mask { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background-color: rgba(15, 23, 42, 0.42); +} + +.hr-sheet { + position: absolute; + left: 0; + right: 0; + bottom: 0; + background-color: #FFFFFF; + border-radius: 36rpx 36rpx 0rpx 0rpx; + padding: 28rpx 32rpx 40rpx 32rpx; +} + +.hr-sheet-h { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 20rpx; +} + +.hr-sheet-h-b { + font-size: 33.6rpx; + font-weight: bold; + color: #1F2937; +} + +.hr-sheet-h-x { + margin-left: auto; + font-size: 35.8rpx; + color: #9CA3AF; +} + +.hr-sheet-opt { + display: flex; + flex-direction: row; + align-items: center; + padding-top: 26rpx; + padding-bottom: 26rpx; + border-bottom: 2rpx solid #F3F4F6; +} + +.hr-sheet-opt-t { + flex: 1; + font-size: 31.4rpx; + color: #1F2937; +} + +.hr-sheet-opt-on { + color: #2563EB; + font-weight: bold; +} + +.hr-sheet-opt-last { + border-bottom-width: 0rpx; +} + +/* ---------- 2D 人体图鉴(uvue 无 SVG,用几何图形拼装人体示意) ---------- */ +.bm-row { + display: flex; + flex-direction: row; +} + +.bm-col { + flex: 1; + background-color: #FAFBFC; + border: 2rpx dashed #E5E7EB; + border-radius: 24rpx; + padding: 20rpx 12rpx 16rpx 12rpx; + align-items: center; + position: relative; + margin-right: 20rpx; +} + +.bm-col-last { + margin-right: 0rpx; +} + +.bm-figure { + width: 192rpx; + height: 368rpx; + position: relative; +} + +.bm-head { + position: absolute; + left: 66rpx; + top: 0rpx; + width: 60rpx; + height: 60rpx; + border-radius: 30rpx; + border: 5rpx solid #CBD5E1; +} + +.bm-torso { + position: absolute; + left: 52rpx; + top: 66rpx; + width: 88rpx; + height: 124rpx; + border-radius: 28rpx; + border: 5rpx solid #CBD5E1; +} + +.bm-arm-l { + position: absolute; + left: 16rpx; + top: 72rpx; + width: 24rpx; + height: 116rpx; + border-radius: 12rpx; + border: 5rpx solid #CBD5E1; +} + +.bm-arm-r { + position: absolute; + left: 152rpx; + top: 72rpx; + width: 24rpx; + height: 116rpx; + border-radius: 12rpx; + border: 5rpx solid #CBD5E1; +} + +.bm-leg-l { + position: absolute; + left: 56rpx; + top: 192rpx; + width: 26rpx; + height: 168rpx; + border-radius: 14rpx; + border: 5rpx solid #CBD5E1; +} + +.bm-leg-r { + position: absolute; + left: 110rpx; + top: 192rpx; + width: 26rpx; + height: 168rpx; + border-radius: 14rpx; + border: 5rpx solid #CBD5E1; +} + +.bm-mark { + position: absolute; + width: 38rpx; + height: 38rpx; + border-radius: 20rpx; + background-color: #DC2626; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +} + +.bm-mark-t { + font-size: 22.4rpx; + font-weight: bold; + color: #FFFFFF; +} + +.bm-tag { + font-size: 23.6rpx; + color: #9CA3AF; + margin-top: 14rpx; +} + +/* ---------- 加载动画 ---------- */ +.hr-spin { + width: 60rpx; + height: 60rpx; + border-radius: 30rpx; + border: 6rpx solid rgba(255, 255, 255, 0.25); + border-top-color: #FFFFFF; +} + +/* ---------- 骨架屏 ---------- */ +.hr-sk { + height: 22rpx; + border-radius: 14rpx; + background-color: #F3F4F6; + margin-bottom: 14rpx; +} \ No newline at end of file diff --git a/components/hr-bodymap/hr-bodymap.uvue b/components/hr-bodymap/hr-bodymap.uvue new file mode 100644 index 0000000..bef34d5 --- /dev/null +++ b/components/hr-bodymap/hr-bodymap.uvue @@ -0,0 +1,187 @@ + + + + + diff --git a/components/hr-card/hr-card.uvue b/components/hr-card/hr-card.uvue new file mode 100644 index 0000000..c59021f --- /dev/null +++ b/components/hr-card/hr-card.uvue @@ -0,0 +1,36 @@ + + + diff --git a/components/hr-chip/hr-chip.uvue b/components/hr-chip/hr-chip.uvue new file mode 100644 index 0000000..c8cc310 --- /dev/null +++ b/components/hr-chip/hr-chip.uvue @@ -0,0 +1,52 @@ + + + diff --git a/components/hr-empty/hr-empty.uvue b/components/hr-empty/hr-empty.uvue new file mode 100644 index 0000000..9f03b3d --- /dev/null +++ b/components/hr-empty/hr-empty.uvue @@ -0,0 +1,96 @@ + + + + + diff --git a/components/hr-lrow/hr-lrow.uvue b/components/hr-lrow/hr-lrow.uvue new file mode 100644 index 0000000..16bc236 --- /dev/null +++ b/components/hr-lrow/hr-lrow.uvue @@ -0,0 +1,124 @@ + + + + + diff --git a/components/hr-page/hr-page.uvue b/components/hr-page/hr-page.uvue new file mode 100644 index 0000000..94f5370 --- /dev/null +++ b/components/hr-page/hr-page.uvue @@ -0,0 +1,115 @@ + + + + + diff --git a/components/hr-pc/hr-pc.uvue b/components/hr-pc/hr-pc.uvue new file mode 100644 index 0000000..0005430 --- /dev/null +++ b/components/hr-pc/hr-pc.uvue @@ -0,0 +1,36 @@ + + + diff --git a/components/hr-progress/hr-progress.uvue b/components/hr-progress/hr-progress.uvue new file mode 100644 index 0000000..c90de6e --- /dev/null +++ b/components/hr-progress/hr-progress.uvue @@ -0,0 +1,56 @@ + + + + + diff --git a/components/hr-rec-list/hr-rec-list.uvue b/components/hr-rec-list/hr-rec-list.uvue new file mode 100644 index 0000000..112516d --- /dev/null +++ b/components/hr-rec-list/hr-rec-list.uvue @@ -0,0 +1,191 @@ + + + + + diff --git a/components/hr-scan-cam/hr-scan-cam.uvue b/components/hr-scan-cam/hr-scan-cam.uvue new file mode 100644 index 0000000..9247611 --- /dev/null +++ b/components/hr-scan-cam/hr-scan-cam.uvue @@ -0,0 +1,279 @@ + + + + + \ No newline at end of file diff --git a/components/hr-sec/hr-sec.uvue b/components/hr-sec/hr-sec.uvue new file mode 100644 index 0000000..e09c1a0 --- /dev/null +++ b/components/hr-sec/hr-sec.uvue @@ -0,0 +1,38 @@ + + + diff --git a/components/hr-statusbar/hr-statusbar.uvue b/components/hr-statusbar/hr-statusbar.uvue new file mode 100644 index 0000000..29f3856 --- /dev/null +++ b/components/hr-statusbar/hr-statusbar.uvue @@ -0,0 +1,30 @@ + + + diff --git a/components/hr-tabbar/hr-tabbar.uvue b/components/hr-tabbar/hr-tabbar.uvue new file mode 100644 index 0000000..89ebc53 --- /dev/null +++ b/components/hr-tabbar/hr-tabbar.uvue @@ -0,0 +1,41 @@ + + + diff --git a/components/hr-timeline/hr-timeline.uvue b/components/hr-timeline/hr-timeline.uvue new file mode 100644 index 0000000..82d7b6b --- /dev/null +++ b/components/hr-timeline/hr-timeline.uvue @@ -0,0 +1,50 @@ + + + diff --git a/components/hr-tip/hr-tip.uvue b/components/hr-tip/hr-tip.uvue new file mode 100644 index 0000000..24424fe --- /dev/null +++ b/components/hr-tip/hr-tip.uvue @@ -0,0 +1,59 @@ + + + + + diff --git a/components/hr-wb/hr-wb.uvue b/components/hr-wb/hr-wb.uvue new file mode 100644 index 0000000..0a89836 --- /dev/null +++ b/components/hr-wb/hr-wb.uvue @@ -0,0 +1,52 @@ + + + diff --git a/components/hr-wband/hr-wband.uvue b/components/hr-wband/hr-wband.uvue new file mode 100644 index 0000000..2088be7 --- /dev/null +++ b/components/hr-wband/hr-wband.uvue @@ -0,0 +1,88 @@ + + + + + diff --git a/env.js b/env.js new file mode 100644 index 0000000..f92c0a4 --- /dev/null +++ b/env.js @@ -0,0 +1,39 @@ +module.exports = { + "is-custom-runtime": false, + "UNI_TEST_CUSTOM_ENV": {}, + "compile": true, + "h5": { + "options": { + "headless": true + }, + "executablePath": "" + }, + "mp-weixin": { + "port": 9520, + "account": "", + "args": "", + "cwd": "", + "launch": true, + "teardown": "disconnect", + "remote": false, + "executablePath": "D:\\app\\微信web开发者工具\\微信开发者工具.exe" + }, + "app-plus": { + "android": { + "id": "", + "executablePath": "" + }, + "version": "", + "ios": { + "id": "", + "executablePath": "" + }, + "uni-app-x": { + "version": "D:\\app\\HBuilderX.4.27.2024091305-alpha\\HBuilderX\\plugins\\uniappx-launcher\\base\\version.txt", + "android": { + "id": "emulator-5554", + "executablePath": "D:\\app\\HBuilderX.4.27.2024091305-alpha\\HBuilderX\\plugins\\uniappx-launcher\\base\\android_base.apk" + } + } + } +} \ No newline at end of file diff --git a/hybrid/html/css/default.min.css b/hybrid/html/css/default.min.css new file mode 100644 index 0000000..f6d5457 --- /dev/null +++ b/hybrid/html/css/default.min.css @@ -0,0 +1,30 @@ +/*! + Theme: Default + Description: Original highlight.js style + Author: (c) Ivan Sagalaev + Maintainer: @highlightjs/core-team + Website: https://highlightjs.org/ + License: see project LICENSE + Touched: 2021 +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:6rpx 10rpx}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} +table { + width: 100%; + border-collapse: collapse; + border: 2rpx solid #ddd; +} + +tr { + text-align: center; + border: 2rpx solid #ddd; +} + +/* 表格隔行变色 */ +tr:nth-child(even) { + background-color: #f2f2f2; +} + +td, th { + border: 2rpx solid #ddd; + padding: 8rpx 16rpx; + font-size:31.4rpx; +} \ No newline at end of file diff --git a/hybrid/html/css/katex.min.css b/hybrid/html/css/katex.min.css new file mode 100644 index 0000000..b2e5008 --- /dev/null +++ b/hybrid/html/css/katex.min.css @@ -0,0 +1 @@ +@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(fonts/KaTeX_AMS-Regular.woff) format("woff"),url(fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(fonts/KaTeX_Main-Bold.woff) format("woff"),url(fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(fonts/KaTeX_Main-Italic.woff) format("woff"),url(fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(fonts/KaTeX_Main-Regular.woff) format("woff"),url(fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(fonts/KaTeX_Math-Italic.woff) format("woff"),url(fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(fonts/KaTeX_Script-Regular.woff) format("woff"),url(fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size1-Regular.woff) format("woff"),url(fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size2-Regular.woff) format("woff"),url(fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size3-Regular.woff) format("woff"),url(fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size4-Regular.woff) format("woff"),url(fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.16.22"}.katex .katex-mathml{clip:rect(2rpx,2rpx,2rpx,2rpx);border:0;height:2rpx;overflow:hidden;padding:0;position:absolute;width:2rpx}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathboldfrak,.katex .textboldfrak{font-family:KaTeX_Fraktur;font-weight:700}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .mathsfit,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-4rpx}.katex .vlist-s{display:table-cell;font-size:2.2rpx;min-width:4rpx;vertical-align:bottom;width:4rpx}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:2rpx}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.2777777778em;margin-right:-.5555555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.1666666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.6666666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.4566666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.1466666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.7142857143em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.8571428571em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.1428571429em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.2857142857em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.4285714286em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.7142857143em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.0571428571em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.4685714286em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.9628571429em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.5542857143em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.7777777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.8888888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.1111111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.3333333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.3044444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.7644444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.5833333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.6666666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.7283333333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.0733333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.4166666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.4861111111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.5555555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.4402777778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.7277777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.2893518519em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.3472222222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.4050925926em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.462962963em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.5208333333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.6944444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.8333333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.2002314815em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.4398148148em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.2410800386em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.2892960463em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.337512054em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.3857280617em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.4339440694em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.4821600771em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.5785920926em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.6943105111em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.8331726133em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.1996142719em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.2009646302em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.2411575563em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.2813504823em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.3215434084em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.3617363344em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.4019292605em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.4823151125em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.578778135em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.6945337621em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.8336012862em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:2rpx}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo} diff --git a/hybrid/html/css/qulliCore.css b/hybrid/html/css/qulliCore.css new file mode 100644 index 0000000..654a0ed --- /dev/null +++ b/hybrid/html/css/qulliCore.css @@ -0,0 +1,8 @@ +/*! + * Quill Editor v2.0.3 + * https://quilljs.com + * Copyright (c) 2017-2024, Slab + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */ +.ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:29.2rpx;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container:not(.ql-disabled) li[data-list=checked] > .ql-ui,.ql-container:not(.ql-disabled) li[data-list=unchecked] > .ql-ui{cursor:pointer}.ql-clipboard{left:-200000rpx;height:2rpx;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;line-height:1.42;height:100%;outline:none;overflow-y:auto;padding:24rpx 30rpx;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor > *{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0}@supports (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-set:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor table{border-collapse:collapse}.ql-editor td{border:2rpx solid #000;padding:4rpx 10rpx}.ql-editor ol{padding-left:1.5em}.ql-editor li{list-style-type:none;padding-left:1.5em;position:relative}.ql-editor li > .ql-ui:before{display:inline-block;margin-left:-1.5em;margin-right:.3em;text-align:right;white-space:nowrap;width:1.2em}.ql-editor li[data-list=checked] > .ql-ui,.ql-editor li[data-list=unchecked] > .ql-ui{color:#777}.ql-editor li[data-list=bullet] > .ql-ui:before{content:'\2022'}.ql-editor li[data-list=checked] > .ql-ui:before{content:'\2611'}.ql-editor li[data-list=unchecked] > .ql-ui:before{content:'\2610'}@supports (counter-set:none){.ql-editor li[data-list]{counter-set:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list]{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered]{counter-increment:list-0}.ql-editor li[data-list=ordered] > .ql-ui:before{content:counter(list-0, decimal) '. '}.ql-editor li[data-list=ordered].ql-indent-1{counter-increment:list-1}.ql-editor li[data-list=ordered].ql-indent-1 > .ql-ui:before{content:counter(list-1, lower-alpha) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-set:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-2{counter-increment:list-2}.ql-editor li[data-list=ordered].ql-indent-2 > .ql-ui:before{content:counter(list-2, lower-roman) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-set:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-3{counter-increment:list-3}.ql-editor li[data-list=ordered].ql-indent-3 > .ql-ui:before{content:counter(list-3, decimal) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-set:list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-4{counter-increment:list-4}.ql-editor li[data-list=ordered].ql-indent-4 > .ql-ui:before{content:counter(list-4, lower-alpha) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-set:list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-5{counter-increment:list-5}.ql-editor li[data-list=ordered].ql-indent-5 > .ql-ui:before{content:counter(list-5, lower-roman) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-set:list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-6{counter-increment:list-6}.ql-editor li[data-list=ordered].ql-indent-6 > .ql-ui:before{content:counter(list-6, decimal) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-set:list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-reset:list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-7{counter-increment:list-7}.ql-editor li[data-list=ordered].ql-indent-7 > .ql-ui:before{content:counter(list-7, lower-alpha) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-set:list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-reset:list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-8{counter-increment:list-8}.ql-editor li[data-list=ordered].ql-indent-8 > .ql-ui:before{content:counter(list-8, lower-roman) '. '}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-set:list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-reset:list-9}}.ql-editor li[data-list=ordered].ql-indent-9{counter-increment:list-9}.ql-editor li[data-list=ordered].ql-indent-9 > .ql-ui:before{content:counter(list-9, decimal) '. '}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor li.ql-direction-rtl{padding-right:1.5em}.ql-editor li.ql-direction-rtl > .ql-ui:before{margin-left:.3em;margin-right:-1.5em;text-align:left}.ql-editor table{table-layout:fixed;width:100%}.ql-editor table td{outline:none}.ql-editor .ql-code-block-container{font-family:monospace}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor .ql-ui{position:absolute}.ql-editor.ql-blank::before{color:rgba(0,0,0,0.6);content:attr(data-placeholder);font-style:italic;left:30rpx;pointer-events:none;position:absolute;right:30rpx}.ql-bubble.ql-toolbar:after,.ql-bubble .ql-toolbar:after{clear:both;content:'';display:table}.ql-bubble.ql-toolbar button,.ql-bubble .ql-toolbar button{background:none;border:none;cursor:pointer;display:inline-block;float:left;height:48rpx;padding:6rpx 10rpx;width:56rpx}.ql-bubble.ql-toolbar button svg,.ql-bubble .ql-toolbar button svg{float:left;height:100%}.ql-bubble.ql-toolbar button:active:hover,.ql-bubble .ql-toolbar button:active:hover{outline:none}.ql-bubble.ql-toolbar input.ql-image[type=file],.ql-bubble .ql-toolbar input.ql-image[type=file]{display:none}.ql-bubble.ql-toolbar button:hover,.ql-bubble .ql-toolbar button:hover,.ql-bubble.ql-toolbar button:focus,.ql-bubble .ql-toolbar button:focus,.ql-bubble.ql-toolbar button.ql-active,.ql-bubble .ql-toolbar button.ql-active,.ql-bubble.ql-toolbar .ql-picker-label:hover,.ql-bubble .ql-toolbar .ql-picker-label:hover,.ql-bubble.ql-toolbar .ql-picker-label.ql-active,.ql-bubble .ql-toolbar .ql-picker-label.ql-active,.ql-bubble.ql-toolbar .ql-picker-item:hover,.ql-bubble .ql-toolbar .ql-picker-item:hover,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected{color:#fff}.ql-bubble.ql-toolbar button:hover .ql-fill,.ql-bubble .ql-toolbar button:hover .ql-fill,.ql-bubble.ql-toolbar button:focus .ql-fill,.ql-bubble .ql-toolbar button:focus .ql-fill,.ql-bubble.ql-toolbar button.ql-active .ql-fill,.ql-bubble .ql-toolbar button.ql-active .ql-fill,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-bubble.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-bubble.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-bubble.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#fff}.ql-bubble.ql-toolbar button:hover .ql-stroke,.ql-bubble .ql-toolbar button:hover .ql-stroke,.ql-bubble.ql-toolbar button:focus .ql-stroke,.ql-bubble .ql-toolbar button:focus .ql-stroke,.ql-bubble.ql-toolbar button.ql-active .ql-stroke,.ql-bubble .ql-toolbar button.ql-active .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-bubble.ql-toolbar button:hover .ql-stroke-miter,.ql-bubble .ql-toolbar button:hover .ql-stroke-miter,.ql-bubble.ql-toolbar button:focus .ql-stroke-miter,.ql-bubble .ql-toolbar button:focus .ql-stroke-miter,.ql-bubble.ql-toolbar button.ql-active .ql-stroke-miter,.ql-bubble .ql-toolbar button.ql-active .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-bubble.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-bubble .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#fff}@media (pointer:coarse){.ql-bubble.ql-toolbar button:hover:not(.ql-active),.ql-bubble .ql-toolbar button:hover:not(.ql-active){color:#ccc}.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#ccc}.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-bubble.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-bubble .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#ccc}}.ql-bubble{box-sizing:border-box}.ql-bubble *{box-sizing:border-box}.ql-bubble .ql-hidden{display:none}.ql-bubble .ql-out-bottom,.ql-bubble .ql-out-top{visibility:hidden}.ql-bubble .ql-tooltip{position:absolute;transform:translateY(20rpx)}.ql-bubble .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-bubble .ql-tooltip.ql-flip{transform:translateY(-20rpx)}.ql-bubble .ql-formats{display:inline-block;vertical-align:middle}.ql-bubble .ql-formats:after{clear:both;content:'';display:table}.ql-bubble .ql-stroke{fill:none;stroke:#ccc;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-bubble .ql-stroke-miter{fill:none;stroke:#ccc;stroke-miterlimit:10;stroke-width:2}.ql-bubble .ql-fill,.ql-bubble .ql-stroke.ql-fill{fill:#ccc}.ql-bubble .ql-empty{fill:none}.ql-bubble .ql-even{fill-rule:evenodd}.ql-bubble .ql-thin,.ql-bubble .ql-stroke.ql-thin{stroke-width:1}.ql-bubble .ql-transparent{opacity:.4}.ql-bubble .ql-direction svg:last-child{display:none}.ql-bubble .ql-direction.ql-active svg:last-child{display:inline}.ql-bubble .ql-direction.ql-active svg:first-child{display:none}.ql-bubble .ql-editor h1{font-size:2em}.ql-bubble .ql-editor h2{font-size:1.5em}.ql-bubble .ql-editor h3{font-size:1.17em}.ql-bubble .ql-editor h4{font-size:1em}.ql-bubble .ql-editor h5{font-size:.83em}.ql-bubble .ql-editor h6{font-size:.67em}.ql-bubble .ql-editor a{text-decoration:underline}.ql-bubble .ql-editor blockquote{border-left:8rpx solid #ccc;margin-bottom:10rpx;margin-top:10rpx;padding-left:32rpx}.ql-bubble .ql-editor code,.ql-bubble .ql-editor .ql-code-block-container{background-color:#f0f0f0;border-radius:6rpx}.ql-bubble .ql-editor .ql-code-block-container{margin-bottom:10rpx;margin-top:10rpx;padding:10rpx 20rpx}.ql-bubble .ql-editor code{font-size:85%;padding:4rpx 8rpx}.ql-bubble .ql-editor .ql-code-block-container{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-bubble .ql-editor img{max-width:100%}.ql-bubble .ql-picker{color:#ccc;display:inline-block;float:left;font-size:31.4rpx;font-weight:500;height:48rpx;position:relative;vertical-align:middle}.ql-bubble .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:16rpx;padding-right:4rpx;position:relative;width:100%}.ql-bubble .ql-picker-label::before{display:inline-block;line-height:44rpx}.ql-bubble .ql-picker-options{background-color:#444;display:none;min-width:100%;padding:8rpx 16rpx;position:absolute;white-space:nowrap}.ql-bubble .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:10rpx;padding-top:10rpx}.ql-bubble .ql-picker.ql-expanded .ql-picker-label{color:#777;z-index:2}.ql-bubble .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#777}.ql-bubble .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#777}.ql-bubble .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-2rpx;top:100%;z-index:1}.ql-bubble .ql-color-picker,.ql-bubble .ql-icon-picker{width:56rpx}.ql-bubble .ql-color-picker .ql-picker-label,.ql-bubble .ql-icon-picker .ql-picker-label{padding:4rpx 8rpx}.ql-bubble .ql-color-picker .ql-picker-label svg,.ql-bubble .ql-icon-picker .ql-picker-label svg{right:8rpx}.ql-bubble .ql-icon-picker .ql-picker-options{padding:8rpx 0}.ql-bubble .ql-icon-picker .ql-picker-item{height:48rpx;width:48rpx;padding:4rpx 8rpx}.ql-bubble .ql-color-picker .ql-picker-options{padding:6rpx 10rpx;width:304rpx}.ql-bubble .ql-color-picker .ql-picker-item{border:2rpx solid transparent;float:left;height:32rpx;margin:4rpx;padding:0;width:32rpx}.ql-bubble .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-18rpx;right:0;top:50%;width:36rpx}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before,.ql-bubble .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before,.ql-bubble .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before,.ql-bubble .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before{content:attr(data-label)}.ql-bubble .ql-picker.ql-header{width:196rpx}.ql-bubble .ql-picker.ql-header .ql-picker-label::before,.ql-bubble .ql-picker.ql-header .ql-picker-item::before{content:'Normal'}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="1"]::before{content:'Heading 1'}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="2"]::before{content:'Heading 2'}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="3"]::before{content:'Heading 3'}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="4"]::before{content:'Heading 4'}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="5"]::before{content:'Heading 5'}.ql-bubble .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="6"]::before{content:'Heading 6'}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="1"]::before{font-size:2em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="2"]::before{font-size:1.5em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="3"]::before{font-size:1.17em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="4"]::before{font-size:1em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="5"]::before{font-size:.83em}.ql-bubble .ql-picker.ql-header .ql-picker-item[data-value="6"]::before{font-size:.67em}.ql-bubble .ql-picker.ql-font{width:216rpx}.ql-bubble .ql-picker.ql-font .ql-picker-label::before,.ql-bubble .ql-picker.ql-font .ql-picker-item::before{content:'Sans Serif'}.ql-bubble .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=serif]::before{content:'Serif'}.ql-bubble .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before{content:'Monospace'}.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=serif]::before{font-family:Georgia,Times New Roman,serif}.ql-bubble .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before{font-family:Monaco,Courier New,monospace}.ql-bubble .ql-picker.ql-size{width:196rpx}.ql-bubble .ql-picker.ql-size .ql-picker-label::before,.ql-bubble .ql-picker.ql-size .ql-picker-item::before{content:'Normal'}.ql-bubble .ql-picker.ql-size .ql-picker-label[data-value=small]::before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=small]::before{content:'Small'}.ql-bubble .ql-picker.ql-size .ql-picker-label[data-value=large]::before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=large]::before{content:'Large'}.ql-bubble .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=huge]::before{content:'Huge'}.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=small]::before{font-size:22.4rpx}.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=large]::before{font-size:40.4rpx}.ql-bubble .ql-picker.ql-size .ql-picker-item[data-value=huge]::before{font-size:71.6rpx}.ql-bubble .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-bubble .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-code-block-container{position:relative}.ql-code-block-container .ql-ui{right:10rpx;top:10rpx}.ql-bubble .ql-toolbar .ql-formats{margin:16rpx 24rpx 16rpx 0}.ql-bubble .ql-toolbar .ql-formats:first-child{margin-left:24rpx}.ql-bubble .ql-color-picker svg{margin:2rpx}.ql-bubble .ql-color-picker .ql-picker-item.ql-selected,.ql-bubble .ql-color-picker .ql-picker-item:hover{border-color:#fff}.ql-bubble .ql-tooltip{background-color:#444;border-radius:50rpx;color:#fff}.ql-bubble .ql-tooltip-arrow{border-left:12rpx solid transparent;border-right:12rpx solid transparent;content:" ";display:block;left:50%;margin-left:-12rpx;position:absolute}.ql-bubble .ql-tooltip:not(.ql-flip) .ql-tooltip-arrow{border-bottom:12rpx solid #444;top:-12rpx}.ql-bubble .ql-tooltip.ql-flip .ql-tooltip-arrow{border-top:12rpx solid #444;bottom:-12rpx}.ql-bubble .ql-tooltip.ql-editing .ql-tooltip-editor{display:block}.ql-bubble .ql-tooltip.ql-editing .ql-formats{visibility:hidden}.ql-bubble .ql-tooltip-editor{display:none}.ql-bubble .ql-tooltip-editor input[type=text]{background:transparent;border:none;color:#fff;font-size:29.2rpx;height:100%;outline:none;padding:20rpx 40rpx;position:absolute;width:100%}.ql-bubble .ql-tooltip-editor a{top:20rpx;position:absolute;right:40rpx}.ql-bubble .ql-tooltip-editor a:before{color:#ccc;content:"\00D7";font-size:35.8rpx;font-weight:bold}.ql-container.ql-bubble:not(.ql-disabled) a:not(.ql-close){position:relative;white-space:nowrap}.ql-container.ql-bubble:not(.ql-disabled) a:not(.ql-close)::before{background-color:#444;border-radius:30rpx;top:-10rpx;font-size:26.8rpx;color:#fff;content:attr(href);font-weight:normal;overflow:hidden;padding:10rpx 30rpx;text-decoration:none;z-index:1}.ql-container.ql-bubble:not(.ql-disabled) a:not(.ql-close)::after{border-top:12rpx solid #444;border-left:12rpx solid transparent;border-right:12rpx solid transparent;top:0;content:" ";height:0;width:0}.ql-container.ql-bubble:not(.ql-disabled) a:not(.ql-close)::before,.ql-container.ql-bubble:not(.ql-disabled) a:not(.ql-close)::after{left:0;margin-left:50%;position:absolute;transform:translate(-50%,-100%);transition:visibility 0s ease 200ms;visibility:hidden}.ql-container.ql-bubble:not(.ql-disabled) a:not(.ql-close):hover::before,.ql-container.ql-bubble:not(.ql-disabled) a:not(.ql-close):hover::after{visibility:visible} diff --git a/hybrid/html/edite.html b/hybrid/html/edite.html new file mode 100644 index 0000000..893d973 --- /dev/null +++ b/hybrid/html/edite.html @@ -0,0 +1,283 @@ + + + + + + + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/hybrid/html/js/echarts.min.js b/hybrid/html/js/echarts.min.js new file mode 100644 index 0000000..22b33ff --- /dev/null +++ b/hybrid/html/js/echarts.min.js @@ -0,0 +1,45 @@ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you 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(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).echarts={})}(this,(function(t){"use strict"; +/*! ***************************************************************************** + 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. + ***************************************************************************** */var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},e(t,n)};function n(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var i=function(){this.firefox=!1,this.ie=!1,this.edge=!1,this.newEdge=!1,this.weChat=!1},r=new function(){this.browser=new i,this.node=!1,this.wxa=!1,this.worker=!1,this.svgSupported=!1,this.touchEventsSupported=!1,this.pointerEventsSupported=!1,this.domSupported=!1,this.transformSupported=!1,this.transform3dSupported=!1,this.hasGlobalWindow="undefined"!=typeof window};"object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?(r.wxa=!0,r.touchEventsSupported=!0):"undefined"==typeof document&&"undefined"!=typeof self?r.worker=!0:!r.hasGlobalWindow||"Deno"in window||"undefined"!=typeof navigator&&"string"==typeof navigator.userAgent&&navigator.userAgent.indexOf("Node.js")>-1?(r.node=!0,r.svgSupported=!0):function(t,e){var n=e.browser,i=t.match(/Firefox\/([\d.]+)/),r=t.match(/MSIE\s([\d.]+)/)||t.match(/Trident\/.+?rv:(([\d.]+))/),o=t.match(/Edge?\/([\d.]+)/),a=/micromessenger/i.test(t);i&&(n.firefox=!0,n.version=i[1]);r&&(n.ie=!0,n.version=r[1]);o&&(n.edge=!0,n.version=o[1],n.newEdge=+o[1].split(".")[0]>18);a&&(n.weChat=!0);e.svgSupported="undefined"!=typeof SVGRect,e.touchEventsSupported="ontouchstart"in window&&!n.ie&&!n.edge,e.pointerEventsSupported="onpointerdown"in window&&(n.edge||n.ie&&+n.version>=11);var s=e.domSupported="undefined"!=typeof document;if(s){var l=document.documentElement.style;e.transform3dSupported=(n.ie&&"transition"in l||n.edge||"WebKitCSSMatrix"in window&&"m11"in new WebKitCSSMatrix||"MozPerspective"in l)&&!("OTransition"in l),e.transformSupported=e.transform3dSupported||n.ie&&+n.version>=9}}(navigator.userAgent,r);var o="sans-serif",a="12px "+o;var s,l,u=function(t){var e={};if("undefined"==typeof JSON)return e;for(var n=0;n=0)o=r*t.length;else for(var h=0;h>1)%2;a.style.cssText=["position: absolute","visibility: hidden","padding: 0","margin: 0","border-width: 0","user-select: none","width:0","height:0",i[s]+":0",r[l]+":0",i[1-s]+":auto",r[1-l]+":auto",""].join("!important;"),t.appendChild(a),n.push(a)}return e.clearMarkers=function(){z(n,(function(t){t.parentNode&&t.parentNode.removeChild(t)}))},n}(e,a),l=function(t,e,n){for(var i=n?"invTrans":"trans",r=e[i],o=e.srcCoords,a=[],s=[],l=!0,u=0;u<4;u++){var c=t[u].getBoundingClientRect(),h=2*u,d=c.left,p=c.top;a.push(d,p),l=l&&o&&d===o[h]&&p===o[h+1],s.push(t[u].offsetLeft,t[u].offsetTop)}return l&&r?r:(e.srcCoords=a,e[i]=n?Jt(s,a):Jt(a,s))}(s,a,o);if(l)return l(t,n,i),!0}return!1}function ne(t){return"CANVAS"===t.nodeName.toUpperCase()}var ie=/([&<>"'])/g,re={"&":"&","<":"<",">":">",'"':""","'":"'"};function oe(t){return null==t?"":(t+"").replace(ie,(function(t,e){return re[e]}))}var ae=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,se=[],le=r.browser.firefox&&+r.browser.version.split(".")[0]<39;function ue(t,e,n,i){return n=n||{},i?ce(t,e,n):le&&null!=e.layerX&&e.layerX!==e.offsetX?(n.zrX=e.layerX,n.zrY=e.layerY):null!=e.offsetX?(n.zrX=e.offsetX,n.zrY=e.offsetY):ce(t,e,n),n}function ce(t,e,n){if(r.domSupported&&t.getBoundingClientRect){var i=e.clientX,o=e.clientY;if(ne(t)){var a=t.getBoundingClientRect();return n.zrX=i-a.left,void(n.zrY=o-a.top)}if(ee(se,t,i,o))return n.zrX=se[0],void(n.zrY=se[1])}n.zrX=n.zrY=0}function he(t){return t||window.event}function de(t,e,n){if(null!=(e=he(e)).zrX)return e;var i=e.type;if(i&&i.indexOf("touch")>=0){var r="touchend"!==i?e.targetTouches[0]:e.changedTouches[0];r&&ue(t,r,e,n)}else{ue(t,e,e,n);var o=function(t){var e=t.wheelDelta;if(e)return e;var n=t.deltaX,i=t.deltaY;if(null==n||null==i)return e;return 3*(0!==i?Math.abs(i):Math.abs(n))*(i>0?-1:i<0?1:n>0?-1:1)}(e);e.zrDelta=o?o/120:-(e.detail||0)/3}var a=e.button;return null==e.which&&void 0!==a&&ae.test(e.type)&&(e.which=1&a?1:2&a?3:4&a?2:0),e}function pe(t,e,n,i){t.addEventListener(e,n,i)}var fe=function(t){t.preventDefault(),t.stopPropagation(),t.cancelBubble=!0};function ge(t){return 2===t.which||3===t.which}var ye=function(){function t(){this._track=[]}return t.prototype.recognize=function(t,e,n){return this._doTrack(t,e,n),this._recognize(t)},t.prototype.clear=function(){return this._track.length=0,this},t.prototype._doTrack=function(t,e,n){var i=t.touches;if(i){for(var r={points:[],touches:[],target:e,event:t},o=0,a=i.length;o1&&r&&r.length>1){var a=ve(r)/ve(o);!isFinite(a)&&(a=1),e.pinchScale=a;var s=[((i=r)[0][0]+i[1][0])/2,(i[0][1]+i[1][1])/2];return e.pinchX=s[0],e.pinchY=s[1],{type:"pinch",target:t[0].target,event:e}}}}};function xe(){return[1,0,0,1,0,0]}function _e(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t}function be(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t}function we(t,e,n){var i=e[0]*n[0]+e[2]*n[1],r=e[1]*n[0]+e[3]*n[1],o=e[0]*n[2]+e[2]*n[3],a=e[1]*n[2]+e[3]*n[3],s=e[0]*n[4]+e[2]*n[5]+e[4],l=e[1]*n[4]+e[3]*n[5]+e[5];return t[0]=i,t[1]=r,t[2]=o,t[3]=a,t[4]=s,t[5]=l,t}function Se(t,e,n){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4]+n[0],t[5]=e[5]+n[1],t}function Me(t,e,n,i){void 0===i&&(i=[0,0]);var r=e[0],o=e[2],a=e[4],s=e[1],l=e[3],u=e[5],c=Math.sin(n),h=Math.cos(n);return t[0]=r*h+s*c,t[1]=-r*c+s*h,t[2]=o*h+l*c,t[3]=-o*c+h*l,t[4]=h*(a-i[0])+c*(u-i[1])+i[0],t[5]=h*(u-i[1])-c*(a-i[0])+i[1],t}function Ie(t,e,n){var i=n[0],r=n[1];return t[0]=e[0]*i,t[1]=e[1]*r,t[2]=e[2]*i,t[3]=e[3]*r,t[4]=e[4]*i,t[5]=e[5]*r,t}function Te(t,e){var n=e[0],i=e[2],r=e[4],o=e[1],a=e[3],s=e[5],l=n*a-o*i;return l?(l=1/l,t[0]=a*l,t[1]=-o*l,t[2]=-i*l,t[3]=n*l,t[4]=(i*s-a*r)*l,t[5]=(o*r-n*s)*l,t):null}function Ce(t){var e=[1,0,0,1,0,0];return be(e,t),e}var De=Object.freeze({__proto__:null,create:xe,identity:_e,copy:be,mul:we,translate:Se,rotate:Me,scale:Ie,invert:Te,clone:Ce}),Ae=function(){function t(t,e){this.x=t||0,this.y=e||0}return t.prototype.copy=function(t){return this.x=t.x,this.y=t.y,this},t.prototype.clone=function(){return new t(this.x,this.y)},t.prototype.set=function(t,e){return this.x=t,this.y=e,this},t.prototype.equal=function(t){return t.x===this.x&&t.y===this.y},t.prototype.add=function(t){return this.x+=t.x,this.y+=t.y,this},t.prototype.scale=function(t){this.x*=t,this.y*=t},t.prototype.scaleAndAdd=function(t,e){this.x+=t.x*e,this.y+=t.y*e},t.prototype.sub=function(t){return this.x-=t.x,this.y-=t.y,this},t.prototype.dot=function(t){return this.x*t.x+this.y*t.y},t.prototype.len=function(){return Math.sqrt(this.x*this.x+this.y*this.y)},t.prototype.lenSquare=function(){return this.x*this.x+this.y*this.y},t.prototype.normalize=function(){var t=this.len();return this.x/=t,this.y/=t,this},t.prototype.distance=function(t){var e=this.x-t.x,n=this.y-t.y;return Math.sqrt(e*e+n*n)},t.prototype.distanceSquare=function(t){var e=this.x-t.x,n=this.y-t.y;return e*e+n*n},t.prototype.negate=function(){return this.x=-this.x,this.y=-this.y,this},t.prototype.transform=function(t){if(t){var e=this.x,n=this.y;return this.x=t[0]*e+t[2]*n+t[4],this.y=t[1]*e+t[3]*n+t[5],this}},t.prototype.toArray=function(t){return t[0]=this.x,t[1]=this.y,t},t.prototype.fromArray=function(t){this.x=t[0],this.y=t[1]},t.set=function(t,e,n){t.x=e,t.y=n},t.copy=function(t,e){t.x=e.x,t.y=e.y},t.len=function(t){return Math.sqrt(t.x*t.x+t.y*t.y)},t.lenSquare=function(t){return t.x*t.x+t.y*t.y},t.dot=function(t,e){return t.x*e.x+t.y*e.y},t.add=function(t,e,n){t.x=e.x+n.x,t.y=e.y+n.y},t.sub=function(t,e,n){t.x=e.x-n.x,t.y=e.y-n.y},t.scale=function(t,e,n){t.x=e.x*n,t.y=e.y*n},t.scaleAndAdd=function(t,e,n,i){t.x=e.x+n.x*i,t.y=e.y+n.y*i},t.lerp=function(t,e,n,i){var r=1-i;t.x=r*e.x+i*n.x,t.y=r*e.y+i*n.y},t}(),ke=Math.min,Le=Math.max,Pe=Math.abs,Oe=["x","y"],Re=["width","height"],Ne=new Ae,ze=new Ae,Ee=new Ae,Be=new Ae,Ve=Ze(),Ge=Ve.minTv,Fe=Ve.maxTv,We=[0,0],He=function(){function t(e,n,i,r){t.set(this,e,n,i,r)}return t.set=function(t,e,n,i,r){return i<0&&(e+=i,i=-i),r<0&&(n+=r,r=-r),t.x=e,t.y=n,t.width=i,t.height=r,t},t.prototype.union=function(t){var e=ke(t.x,this.x),n=ke(t.y,this.y);isFinite(this.x)&&isFinite(this.width)?this.width=Le(t.x+t.width,this.x+this.width)-e:this.width=t.width,isFinite(this.y)&&isFinite(this.height)?this.height=Le(t.y+t.height,this.y+this.height)-n:this.height=t.height,this.x=e,this.y=n},t.prototype.applyTransform=function(e){t.applyTransform(this,this,e)},t.prototype.calculateTransform=function(t){var e=this,n=t.width/e.width,i=t.height/e.height,r=[1,0,0,1,0,0];return Se(r,r,[-e.x,-e.y]),Ie(r,r,[n,i]),Se(r,r,[t.x,t.y]),r},t.prototype.intersect=function(e,n,i){return t.intersect(this,e,n,i)},t.intersect=function(e,n,i,r){i&&Ae.set(i,0,0);var o=r&&r.outIntersectRect||null,a=r&&r.clamp;if(o&&(o.x=o.y=o.width=o.height=NaN),!e||!n)return!1;e instanceof t||(e=t.set(Ue,e.x,e.y,e.width,e.height)),n instanceof t||(n=t.set(Ye,n.x,n.y,n.width,n.height));var s=!!i;Ve.reset(r,s);var l=Ve.touchThreshold,u=e.x+l,c=e.x+e.width-l,h=e.y+l,d=e.y+e.height-l,p=n.x+l,f=n.x+n.width-l,g=n.y+l,y=n.y+n.height-l;if(u>c||h>d||p>f||g>y)return!1;var v=!(c=t.x&&e<=t.x+t.width&&n>=t.y&&n<=t.y+t.height},t.prototype.contain=function(e,n){return t.contain(this,e,n)},t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height)},t.prototype.copy=function(e){t.copy(this,e)},t.prototype.plain=function(){return{x:this.x,y:this.y,width:this.width,height:this.height}},t.prototype.isFinite=function(){return isFinite(this.x)&&isFinite(this.y)&&isFinite(this.width)&&isFinite(this.height)},t.prototype.isZero=function(){return 0===this.width||0===this.height},t.create=function(e){return new t(e.x,e.y,e.width,e.height)},t.copy=function(t,e){return t.x=e.x,t.y=e.y,t.width=e.width,t.height=e.height,t},t.applyTransform=function(e,n,i){if(i){if(i[1]<1e-5&&i[1]>-1e-5&&i[2]<1e-5&&i[2]>-1e-5){var r=i[0],o=i[3],a=i[4],s=i[5];return e.x=n.x*r+a,e.y=n.y*o+s,e.width=n.width*r,e.height=n.height*o,e.width<0&&(e.x+=e.width,e.width=-e.width),void(e.height<0&&(e.y+=e.height,e.height=-e.height))}Ne.x=Ee.x=n.x,Ne.y=Be.y=n.y,ze.x=Be.x=n.x+n.width,ze.y=Ee.y=n.y+n.height,Ne.transform(i),Be.transform(i),ze.transform(i),Ee.transform(i),e.x=ke(Ne.x,ze.x,Ee.x,Be.x),e.y=ke(Ne.y,ze.y,Ee.y,Be.y);var l=Le(Ne.x,ze.x,Ee.x,Be.x),u=Le(Ne.y,ze.y,Ee.y,Be.y);e.width=l-e.x,e.height=u-e.y}else e!==n&&t.copy(e,n)},t}(),Ue=new He(0,0,0,0),Ye=new He(0,0,0,0);function Xe(t,e,n,i,r,o,a,s){var l=Pe(e-n),u=Pe(i-t),c=ke(l,u),h=Oe[r],d=Oe[1-r],p=Re[r];e=u||!Ve.bidirectional)&&(Ge[h]=-u,Ge[d]=0,Ve.useDir&&Ve.calcDirMTV())))}function Ze(){var t=0,e=new Ae,n=new Ae,i={minTv:new Ae,maxTv:new Ae,useDir:!1,dirMinTv:new Ae,touchThreshold:0,bidirectional:!0,negativeSize:!1,reset:function(r,o){i.touchThreshold=0,r&&null!=r.touchThreshold&&(i.touchThreshold=Le(0,r.touchThreshold)),i.negativeSize=!1,o&&(i.minTv.set(1/0,1/0),i.maxTv.set(0,0),i.useDir=!1,r&&null!=r.direction&&(i.useDir=!0,i.dirMinTv.copy(i.minTv),n.copy(i.minTv),t=r.direction,i.bidirectional=null==r.bidirectional||!!r.bidirectional,i.bidirectional||e.set(Math.cos(t),Math.sin(t))))},calcDirMTV:function(){var o=i.minTv,a=i.dirMinTv,s=o.y*o.y+o.x*o.x,l=Math.sin(t),u=Math.cos(t),c=l*o.y+u*o.x;r(c)?r(o.x)&&r(o.y)&&a.set(0,0):(n.x=s*u/c,n.y=s*l/c,r(n.x)&&r(n.y)?a.set(0,0):(i.bidirectional||e.dot(n)>0)&&n.len()=0;u--){var c=i[u];c===n||c.ignore||c.ignoreCoarsePointer||c.parent&&c.parent.ignoreCoarsePointer||(Qe.copy(c.getBoundingRect()),c.transform&&Qe.applyTransform(c.transform),Qe.intersect(l)&&o.push(c))}if(o.length)for(var h=Math.PI/12,d=2*Math.PI,p=0;p=0;o--){var a=t[o],s=void 0;if(a!==r&&!a.ignore&&(s=en(a,n,i))&&(!e.topTarget&&(e.topTarget=a),s!==je)){e.target=a;break}}}function rn(t,e,n){var i=t.painter;return e<0||e>i.getWidth()||n<0||n>i.getHeight()}z(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],(function(t){tn.prototype[t]=function(e){var n,i,r=e.zrX,o=e.zrY,a=rn(this,r,o);if("mouseup"===t&&a||(i=(n=this.findHover(r,o)).target),"mousedown"===t)this._downEl=i,this._downPoint=[e.zrX,e.zrY],this._upEl=i;else if("mouseup"===t)this._upEl=i;else if("click"===t){if(this._downEl!==this._upEl||!this._downPoint||Vt(this._downPoint,[e.zrX,e.zrY])>4)return;this._downPoint=null}this.dispatchToElement(n,t,e)}}));function on(t,e,n,i){var r=e+1;if(r===n)return 1;if(i(t[r++],t[e])<0){for(;r=0;)r++;return r-e}function an(t,e,n,i,r){for(i===e&&i++;i>>1])<0?l=o:s=o+1;var u=i-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;u>0;)t[s+u]=t[s+u-1],u--}t[s]=a}}function sn(t,e,n,i,r,o){var a=0,s=0,l=1;if(o(t,e[n+r])>0){for(s=i-r;l0;)a=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),a+=r,l+=r}else{for(s=r+1;ls&&(l=s);var u=a;a=r-l,l=r-u}for(a++;a>>1);o(t,e[n+c])>0?a=c+1:l=c}return l}function ln(t,e,n,i,r,o){var a=0,s=0,l=1;if(o(t,e[n+r])<0){for(s=r+1;ls&&(l=s);var u=a;a=r-l,l=r-u}else{for(s=i-r;l=0;)a=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),a+=r,l+=r}for(a++;a>>1);o(t,e[n+c])<0?l=c:a=c+1}return l}function un(t,e){var n,i,r=7,o=0,a=[];function s(s){var l=n[s],u=i[s],c=n[s+1],h=i[s+1];i[s]=u+h,s===o-3&&(n[s+1]=n[s+2],i[s+1]=i[s+2]),o--;var d=ln(t[c],t,l,u,0,e);l+=d,0!==(u-=d)&&0!==(h=sn(t[l+u-1],t,c,h,h-1,e))&&(u<=h?function(n,i,o,s){var l=0;for(l=0;l=7||p>=7);if(f)break;g<0&&(g=0),g+=2}if((r=g)<1&&(r=1),1===i){for(l=0;l=0;l--)t[p+l]=t[d+l];return void(t[h]=a[c])}var f=r;for(;;){var g=0,y=0,v=!1;do{if(e(a[c],t[u])<0){if(t[h--]=t[u--],g++,y=0,0==--i){v=!0;break}}else if(t[h--]=a[c--],y++,g=0,1==--s){v=!0;break}}while((g|y)=0;l--)t[p+l]=t[d+l];if(0===i){v=!0;break}}if(t[h--]=a[c--],1==--s){v=!0;break}if(0!==(y=s-sn(t[u],a,0,s,s-1,e))){for(s-=y,p=(h-=y)+1,d=(c-=y)+1,l=0;l=7||y>=7);if(v)break;f<0&&(f=0),f+=2}(r=f)<1&&(r=1);if(1===s){for(p=(h-=i)+1,d=(u-=i)+1,l=i-1;l>=0;l--)t[p+l]=t[d+l];t[h]=a[c]}else{if(0===s)throw new Error;for(d=h-(s-1),l=0;l1;){var t=o-2;if(t>=1&&i[t-1]<=i[t]+i[t+1]||t>=2&&i[t-2]<=i[t]+i[t-1])i[t-1]i[t+1])break;s(t)}},forceMergeRuns:function(){for(;o>1;){var t=o-2;t>0&&i[t-1]=32;)e|=1&t,t>>=1;return t+e}(r);do{if((o=on(t,n,i,e))s&&(l=s),an(t,n,n+l,n+o,e),o=l}a.pushRun(n,o),a.mergeRuns(),r-=o,n+=o}while(0!==r);a.forceMergeRuns()}}}var hn=!1;function dn(){hn||(hn=!0,console.warn("z / z2 / zlevel of displayable is invalid, which may cause unexpected errors"))}function pn(t,e){return t.zlevel===e.zlevel?t.z===e.z?t.z2-e.z2:t.z-e.z:t.zlevel-e.zlevel}var fn=function(){function t(){this._roots=[],this._displayList=[],this._displayListLen=0,this.displayableSortFunc=pn}return t.prototype.traverse=function(t,e){for(var n=0;n=0&&this._roots.splice(i,1)}},t.prototype.delAllRoots=function(){this._roots=[],this._displayList=[],this._displayListLen=0},t.prototype.getRoots=function(){return this._roots},t.prototype.dispose=function(){this._displayList=null,this._roots=null},t}(),gn=r.hasGlobalWindow&&(window.requestAnimationFrame&&window.requestAnimationFrame.bind(window)||window.msRequestAnimationFrame&&window.msRequestAnimationFrame.bind(window)||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame)||function(t){return setTimeout(t,16)},yn={linear:function(t){return t},quadraticIn:function(t){return t*t},quadraticOut:function(t){return t*(2-t)},quadraticInOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)},cubicIn:function(t){return t*t*t},cubicOut:function(t){return--t*t*t+1},cubicInOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},quarticIn:function(t){return t*t*t*t},quarticOut:function(t){return 1- --t*t*t*t},quarticInOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},quinticIn:function(t){return t*t*t*t*t},quinticOut:function(t){return--t*t*t*t*t+1},quinticInOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},sinusoidalIn:function(t){return 1-Math.cos(t*Math.PI/2)},sinusoidalOut:function(t){return Math.sin(t*Math.PI/2)},sinusoidalInOut:function(t){return.5*(1-Math.cos(Math.PI*t))},exponentialIn:function(t){return 0===t?0:Math.pow(1024,t-1)},exponentialOut:function(t){return 1===t?1:1-Math.pow(2,-10*t)},exponentialInOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))},circularIn:function(t){return 1-Math.sqrt(1-t*t)},circularOut:function(t){return Math.sqrt(1- --t*t)},circularInOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},elasticIn:function(t){var e,n=.1;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=.4*Math.asin(1/n)/(2*Math.PI),-n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4))},elasticOut:function(t){var e,n=.1;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=.4*Math.asin(1/n)/(2*Math.PI),n*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/.4)+1)},elasticInOut:function(t){var e,n=.1,i=.4;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=i*Math.asin(1/n)/(2*Math.PI),(t*=2)<1?n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*-.5:n*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*.5+1)},backIn:function(t){var e=1.70158;return t*t*((e+1)*t-e)},backOut:function(t){var e=1.70158;return--t*t*((e+1)*t+e)+1},backInOut:function(t){var e=2.5949095;return(t*=2)<1?t*t*((e+1)*t-e)*.5:.5*((t-=2)*t*((e+1)*t+e)+2)},bounceIn:function(t){return 1-yn.bounceOut(1-t)},bounceOut:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bounceInOut:function(t){return t<.5?.5*yn.bounceIn(2*t):.5*yn.bounceOut(2*t-1)+.5}},vn=Math.pow,mn=Math.sqrt,xn=1e-8,_n=1e-4,bn=mn(3),wn=1/3,Sn=It(),Mn=It(),In=It();function Tn(t){return t>-1e-8&&txn||t<-1e-8}function Dn(t,e,n,i,r){var o=1-r;return o*o*(o*t+3*r*e)+r*r*(r*i+3*o*n)}function An(t,e,n,i,r){var o=1-r;return 3*(((e-t)*o+2*(n-e)*r)*o+(i-n)*r*r)}function kn(t,e,n,i,r,o){var a=i+3*(e-n)-t,s=3*(n-2*e+t),l=3*(e-t),u=t-r,c=s*s-3*a*l,h=s*l-9*a*u,d=l*l-3*s*u,p=0;if(Tn(c)&&Tn(h)){if(Tn(s))o[0]=0;else(M=-l/s)>=0&&M<=1&&(o[p++]=M)}else{var f=h*h-4*c*d;if(Tn(f)){var g=h/c,y=-g/2;(M=-s/a+g)>=0&&M<=1&&(o[p++]=M),y>=0&&y<=1&&(o[p++]=y)}else if(f>0){var v=mn(f),m=c*s+1.5*a*(-h+v),x=c*s+1.5*a*(-h-v);(M=(-s-((m=m<0?-vn(-m,wn):vn(m,wn))+(x=x<0?-vn(-x,wn):vn(x,wn))))/(3*a))>=0&&M<=1&&(o[p++]=M)}else{var _=(2*c*s-3*a*h)/(2*mn(c*c*c)),b=Math.acos(_)/3,w=mn(c),S=Math.cos(b),M=(-s-2*w*S)/(3*a),I=(y=(-s+w*(S+bn*Math.sin(b)))/(3*a),(-s+w*(S-bn*Math.sin(b)))/(3*a));M>=0&&M<=1&&(o[p++]=M),y>=0&&y<=1&&(o[p++]=y),I>=0&&I<=1&&(o[p++]=I)}}return p}function Ln(t,e,n,i,r){var o=6*n-12*e+6*t,a=9*e+3*i-3*t-9*n,s=3*e-3*t,l=0;if(Tn(a)){if(Cn(o))(c=-s/o)>=0&&c<=1&&(r[l++]=c)}else{var u=o*o-4*a*s;if(Tn(u))r[0]=-o/(2*a);else if(u>0){var c,h=mn(u),d=(-o-h)/(2*a);(c=(-o+h)/(2*a))>=0&&c<=1&&(r[l++]=c),d>=0&&d<=1&&(r[l++]=d)}}return l}function Pn(t,e,n,i,r,o){var a=(e-t)*r+t,s=(n-e)*r+e,l=(i-n)*r+n,u=(s-a)*r+a,c=(l-s)*r+s,h=(c-u)*r+u;o[0]=t,o[1]=a,o[2]=u,o[3]=h,o[4]=h,o[5]=c,o[6]=l,o[7]=i}function On(t,e,n,i,r,o,a,s,l,u,c){var h,d,p,f,g,y=.005,v=1/0;Sn[0]=l,Sn[1]=u;for(var m=0;m<1;m+=.05)Mn[0]=Dn(t,n,r,a,m),Mn[1]=Dn(e,i,o,s,m),(f=Ft(Sn,Mn))=0&&f=0&&y=1?1:kn(0,i,o,1,t,s)&&Dn(0,r,a,1,s[0])}}}var Hn=function(){function t(t){this._inited=!1,this._startTime=0,this._pausedTime=0,this._paused=!1,this._life=t.life||1e3,this._delay=t.delay||0,this.loop=t.loop||!1,this.onframe=t.onframe||bt,this.ondestroy=t.ondestroy||bt,this.onrestart=t.onrestart||bt,t.easing&&this.setEasing(t.easing)}return t.prototype.step=function(t,e){if(this._inited||(this._startTime=t+this._delay,this._inited=!0),!this._paused){var n=this._life,i=t-this._startTime-this._pausedTime,r=i/n;r<0&&(r=0),r=Math.min(r,1);var o=this.easingFunc,a=o?o(r):r;if(this.onframe(a),1===r){if(!this.loop)return!0;var s=i%n;this._startTime=t-s,this._pausedTime=0,this.onrestart()}return!1}this._pausedTime+=e},t.prototype.pause=function(){this._paused=!0},t.prototype.resume=function(){this._paused=!1},t.prototype.setEasing=function(t){this.easing=t,this.easingFunc=Y(t)?t:yn[t]||Wn(t)},t}(),Un=function(t){this.value=t},Yn=function(){function t(){this._len=0}return t.prototype.insert=function(t){var e=new Un(t);return this.insertEntry(e),e},t.prototype.insertEntry=function(t){this.head?(this.tail.next=t,t.prev=this.tail,t.next=null,this.tail=t):this.head=this.tail=t,this._len++},t.prototype.remove=function(t){var e=t.prev,n=t.next;e?e.next=n:this.head=n,n?n.prev=e:this.tail=e,t.next=t.prev=null,this._len--},t.prototype.len=function(){return this._len},t.prototype.clear=function(){this.head=this.tail=null,this._len=0},t}(),Xn=function(){function t(t){this._list=new Yn,this._maxSize=10,this._map={},this._maxSize=t}return t.prototype.put=function(t,e){var n=this._list,i=this._map,r=null;if(null==i[t]){var o=n.len(),a=this._lastRemovedEntry;if(o>=this._maxSize&&o>0){var s=n.head;n.remove(s),delete i[s.key],r=s.value,this._lastRemovedEntry=s}a?a.value=e:a=new Un(e),a.key=t,n.insertEntry(a),i[t]=a}return r},t.prototype.get=function(t){var e=this._map[t],n=this._list;if(null!=e)return e!==n.tail&&(n.remove(e),n.insertEntry(e)),e.value},t.prototype.clear=function(){this._list.clear(),this._map={}},t.prototype.len=function(){return this._list.len()},t}(),Zn={transparent:[0,0,0,0],aliceblue:[240,248,255,1],antiquewhite:[250,235,215,1],aqua:[0,255,255,1],aquamarine:[127,255,212,1],azure:[240,255,255,1],beige:[245,245,220,1],bisque:[255,228,196,1],black:[0,0,0,1],blanchedalmond:[255,235,205,1],blue:[0,0,255,1],blueviolet:[138,43,226,1],brown:[165,42,42,1],burlywood:[222,184,135,1],cadetblue:[95,158,160,1],chartreuse:[127,255,0,1],chocolate:[210,105,30,1],coral:[255,127,80,1],cornflowerblue:[100,149,237,1],cornsilk:[255,248,220,1],crimson:[220,20,60,1],cyan:[0,255,255,1],darkblue:[0,0,139,1],darkcyan:[0,139,139,1],darkgoldenrod:[184,134,11,1],darkgray:[169,169,169,1],darkgreen:[0,100,0,1],darkgrey:[169,169,169,1],darkkhaki:[189,183,107,1],darkmagenta:[139,0,139,1],darkolivegreen:[85,107,47,1],darkorange:[255,140,0,1],darkorchid:[153,50,204,1],darkred:[139,0,0,1],darksalmon:[233,150,122,1],darkseagreen:[143,188,143,1],darkslateblue:[72,61,139,1],darkslategray:[47,79,79,1],darkslategrey:[47,79,79,1],darkturquoise:[0,206,209,1],darkviolet:[148,0,211,1],deeppink:[255,20,147,1],deepskyblue:[0,191,255,1],dimgray:[105,105,105,1],dimgrey:[105,105,105,1],dodgerblue:[30,144,255,1],firebrick:[178,34,34,1],floralwhite:[255,250,240,1],forestgreen:[34,139,34,1],fuchsia:[255,0,255,1],gainsboro:[220,220,220,1],ghostwhite:[248,248,255,1],gold:[255,215,0,1],goldenrod:[218,165,32,1],gray:[128,128,128,1],green:[0,128,0,1],greenyellow:[173,255,47,1],grey:[128,128,128,1],honeydew:[240,255,240,1],hotpink:[255,105,180,1],indianred:[205,92,92,1],indigo:[75,0,130,1],ivory:[255,255,240,1],khaki:[240,230,140,1],lavender:[230,230,250,1],lavenderblush:[255,240,245,1],lawngreen:[124,252,0,1],lemonchiffon:[255,250,205,1],lightblue:[173,216,230,1],lightcoral:[240,128,128,1],lightcyan:[224,255,255,1],lightgoldenrodyellow:[250,250,210,1],lightgray:[211,211,211,1],lightgreen:[144,238,144,1],lightgrey:[211,211,211,1],lightpink:[255,182,193,1],lightsalmon:[255,160,122,1],lightseagreen:[32,178,170,1],lightskyblue:[135,206,250,1],lightslategray:[119,136,153,1],lightslategrey:[119,136,153,1],lightsteelblue:[176,196,222,1],lightyellow:[255,255,224,1],lime:[0,255,0,1],limegreen:[50,205,50,1],linen:[250,240,230,1],magenta:[255,0,255,1],maroon:[128,0,0,1],mediumaquamarine:[102,205,170,1],mediumblue:[0,0,205,1],mediumorchid:[186,85,211,1],mediumpurple:[147,112,219,1],mediumseagreen:[60,179,113,1],mediumslateblue:[123,104,238,1],mediumspringgreen:[0,250,154,1],mediumturquoise:[72,209,204,1],mediumvioletred:[199,21,133,1],midnightblue:[25,25,112,1],mintcream:[245,255,250,1],mistyrose:[255,228,225,1],moccasin:[255,228,181,1],navajowhite:[255,222,173,1],navy:[0,0,128,1],oldlace:[253,245,230,1],olive:[128,128,0,1],olivedrab:[107,142,35,1],orange:[255,165,0,1],orangered:[255,69,0,1],orchid:[218,112,214,1],palegoldenrod:[238,232,170,1],palegreen:[152,251,152,1],paleturquoise:[175,238,238,1],palevioletred:[219,112,147,1],papayawhip:[255,239,213,1],peachpuff:[255,218,185,1],peru:[205,133,63,1],pink:[255,192,203,1],plum:[221,160,221,1],powderblue:[176,224,230,1],purple:[128,0,128,1],red:[255,0,0,1],rosybrown:[188,143,143,1],royalblue:[65,105,225,1],saddlebrown:[139,69,19,1],salmon:[250,128,114,1],sandybrown:[244,164,96,1],seagreen:[46,139,87,1],seashell:[255,245,238,1],sienna:[160,82,45,1],silver:[192,192,192,1],skyblue:[135,206,235,1],slateblue:[106,90,205,1],slategray:[112,128,144,1],slategrey:[112,128,144,1],snow:[255,250,250,1],springgreen:[0,255,127,1],steelblue:[70,130,180,1],tan:[210,180,140,1],teal:[0,128,128,1],thistle:[216,191,216,1],tomato:[255,99,71,1],turquoise:[64,224,208,1],violet:[238,130,238,1],wheat:[245,222,179,1],white:[255,255,255,1],whitesmoke:[245,245,245,1],yellow:[255,255,0,1],yellowgreen:[154,205,50,1]};function jn(t){return(t=Math.round(t))<0?0:t>255?255:t}function qn(t){return t<0?0:t>1?1:t}function Kn(t){var e=t;return e.length&&"%"===e.charAt(e.length-1)?jn(parseFloat(e)/100*255):jn(parseInt(e,10))}function $n(t){var e=t;return e.length&&"%"===e.charAt(e.length-1)?qn(parseFloat(e)/100):qn(parseFloat(e))}function Jn(t,e,n){return n<0?n+=1:n>1&&(n-=1),6*n<1?t+(e-t)*n*6:2*n<1?e:3*n<2?t+(e-t)*(2/3-n)*6:t}function Qn(t,e,n){return t+(e-t)*n}function ti(t,e,n,i,r){return t[0]=e,t[1]=n,t[2]=i,t[3]=r,t}function ei(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}var ni=new Xn(20),ii=null;function ri(t,e){ii&&ei(ii,e),ii=ni.put(t,ii||e.slice())}function oi(t,e){if(t){e=e||[];var n=ni.get(t);if(n)return ei(e,n);var i=(t+="").replace(/ /g,"").toLowerCase();if(i in Zn)return ei(e,Zn[i]),ri(t,e),e;var r,o=i.length;if("#"===i.charAt(0))return 4===o||5===o?(r=parseInt(i.slice(1,4),16))>=0&&r<=4095?(ti(e,(3840&r)>>4|(3840&r)>>8,240&r|(240&r)>>4,15&r|(15&r)<<4,5===o?parseInt(i.slice(4),16)/15:1),ri(t,e),e):void ti(e,0,0,0,1):7===o||9===o?(r=parseInt(i.slice(1,7),16))>=0&&r<=16777215?(ti(e,(16711680&r)>>16,(65280&r)>>8,255&r,9===o?parseInt(i.slice(7),16)/255:1),ri(t,e),e):void ti(e,0,0,0,1):void 0;var a=i.indexOf("("),s=i.indexOf(")");if(-1!==a&&s+1===o){var l=i.substr(0,a),u=i.substr(a+1,s-(a+1)).split(","),c=1;switch(l){case"rgba":if(4!==u.length)return 3===u.length?ti(e,+u[0],+u[1],+u[2],1):ti(e,0,0,0,1);c=$n(u.pop());case"rgb":return u.length>=3?(ti(e,Kn(u[0]),Kn(u[1]),Kn(u[2]),3===u.length?c:$n(u[3])),ri(t,e),e):void ti(e,0,0,0,1);case"hsla":return 4!==u.length?void ti(e,0,0,0,1):(u[3]=$n(u[3]),ai(u,e),ri(t,e),e);case"hsl":return 3!==u.length?void ti(e,0,0,0,1):(ai(u,e),ri(t,e),e);default:return}}ti(e,0,0,0,1)}}function ai(t,e){var n=(parseFloat(t[0])%360+360)%360/360,i=$n(t[1]),r=$n(t[2]),o=r<=.5?r*(i+1):r+i-r*i,a=2*r-o;return ti(e=e||[],jn(255*Jn(a,o,n+1/3)),jn(255*Jn(a,o,n)),jn(255*Jn(a,o,n-1/3)),1),4===t.length&&(e[3]=t[3]),e}function si(t,e){var n=oi(t);if(n){for(var i=0;i<3;i++)n[i]=e<0?n[i]*(1-e)|0:(255-n[i])*e+n[i]|0,n[i]>255?n[i]=255:n[i]<0&&(n[i]=0);return fi(n,4===n.length?"rgba":"rgb")}}function li(t,e,n){if(e&&e.length&&t>=0&&t<=1){n=n||[];var i=t*(e.length-1),r=Math.floor(i),o=Math.ceil(i),a=e[r],s=e[o],l=i-r;return n[0]=jn(Qn(a[0],s[0],l)),n[1]=jn(Qn(a[1],s[1],l)),n[2]=jn(Qn(a[2],s[2],l)),n[3]=qn(Qn(a[3],s[3],l)),n}}var ui=li;function ci(t,e,n){if(e&&e.length&&t>=0&&t<=1){var i=t*(e.length-1),r=Math.floor(i),o=Math.ceil(i),a=oi(e[r]),s=oi(e[o]),l=i-r,u=fi([jn(Qn(a[0],s[0],l)),jn(Qn(a[1],s[1],l)),jn(Qn(a[2],s[2],l)),qn(Qn(a[3],s[3],l))],"rgba");return n?{color:u,leftIndex:r,rightIndex:o,value:i}:u}}var hi=ci;function di(t,e,n,i){var r=oi(t);if(t)return r=function(t){if(t){var e,n,i=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(i,r,o),s=Math.max(i,r,o),l=s-a,u=(s+a)/2;if(0===l)e=0,n=0;else{n=u<.5?l/(s+a):l/(2-s-a);var c=((s-i)/6+l/2)/l,h=((s-r)/6+l/2)/l,d=((s-o)/6+l/2)/l;i===s?e=d-h:r===s?e=1/3+c-d:o===s&&(e=2/3+h-c),e<0&&(e+=1),e>1&&(e-=1)}var p=[360*e,n,u];return null!=t[3]&&p.push(t[3]),p}}(r),null!=e&&(r[0]=function(t){return(t=Math.round(t))<0?0:t>360?360:t}(Y(e)?e(r[0]):e)),null!=n&&(r[1]=$n(Y(n)?n(r[1]):n)),null!=i&&(r[2]=$n(Y(i)?i(r[2]):i)),fi(ai(r),"rgba")}function pi(t,e){var n=oi(t);if(n&&null!=e)return n[3]=qn(e),fi(n,"rgba")}function fi(t,e){if(t&&t.length){var n=t[0]+","+t[1]+","+t[2];return"rgba"!==e&&"hsva"!==e&&"hsla"!==e||(n+=","+t[3]),e+"("+n+")"}}function gi(t,e){var n=oi(t);return n?(.299*n[0]+.587*n[1]+.114*n[2])*n[3]/255+(1-n[3])*e:0}var yi=new Xn(100);function vi(t){if(X(t)){var e=yi.get(t);return e||(e=si(t,-.1),yi.put(t,e)),e}if(Q(t)){var n=A({},t);return n.colorStops=E(t.colorStops,(function(t){return{offset:t.offset,color:si(t.color,-.1)}})),n}return t}var mi=Object.freeze({__proto__:null,parseCssInt:Kn,parseCssFloat:$n,parse:oi,lift:si,toHex:function(t){var e=oi(t);if(e)return((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1)},fastLerp:li,fastMapToColor:ui,lerp:ci,mapToColor:hi,modifyHSL:di,modifyAlpha:pi,stringify:fi,lum:gi,random:function(){return fi([Math.round(255*Math.random()),Math.round(255*Math.random()),Math.round(255*Math.random())],"rgb")},liftColor:vi}),xi=Math.round;function _i(t){var e;if(t&&"transparent"!==t){if("string"==typeof t&&t.indexOf("rgba")>-1){var n=oi(t);n&&(t="rgb("+n[0]+","+n[1]+","+n[2]+")",e=n[3])}}else t="none";return{color:t,opacity:null==e?1:e}}var bi=1e-4;function wi(t){return t-1e-4}function Si(t){return xi(1e3*t)/1e3}function Mi(t){return xi(1e4*t)/1e4}var Ii={left:"start",right:"end",center:"middle",middle:"middle"};function Ti(t){return t&&!!t.image}function Ci(t){return Ti(t)||function(t){return t&&!!t.svgElement}(t)}function Di(t){return"linear"===t.type}function Ai(t){return"radial"===t.type}function ki(t){return t&&("linear"===t.type||"radial"===t.type)}function Li(t){return"url(#"+t+")"}function Pi(t){var e=t.getGlobalScale(),n=Math.max(e[0],e[1]);return Math.max(Math.ceil(Math.log(n)/Math.log(10)),1)}function Oi(t){var e=t.x||0,n=t.y||0,i=(t.rotation||0)*wt,r=rt(t.scaleX,1),o=rt(t.scaleY,1),a=t.skewX||0,s=t.skewY||0,l=[];return(e||n)&&l.push("translate("+e+"px,"+n+"px)"),i&&l.push("rotate("+i+")"),1===r&&1===o||l.push("scale("+r+","+o+")"),(a||s)&&l.push("skew("+xi(a*wt)+"deg, "+xi(s*wt)+"deg)"),l.join(" ")}var Ri=r.hasGlobalWindow&&Y(window.btoa)?function(t){return window.btoa(unescape(encodeURIComponent(t)))}:"undefined"!=typeof Buffer?function(t){return Buffer.from(t).toString("base64")}:function(t){return null},Ni=Array.prototype.slice;function zi(t,e,n){return(e-t)*n+t}function Ei(t,e,n,i){for(var r=e.length,o=0;oi?e:t,o=Math.min(n,i),a=r[o-1]||{color:[0,0,0,0],offset:0},s=o;sa)i.length=a;else for(var s=o;s=1},t.prototype.getAdditiveTrack=function(){return this._additiveTrack},t.prototype.addKeyframe=function(t,e,n){this._needsSort=!0;var i=this.keyframes,r=i.length,o=!1,a=6,s=e;if(N(e)){var l=function(t){return N(t&&t[0])?2:1}(e);a=l,(1===l&&!j(e[0])||2===l&&!j(e[0][0]))&&(o=!0)}else if(j(e)&&!nt(e))a=0;else if(X(e))if(isNaN(+e)){var u=oi(e);u&&(s=u,a=3)}else a=0;else if(Q(e)){var c=A({},s);c.colorStops=E(e.colorStops,(function(t){return{offset:t.offset,color:oi(t.color)}})),Di(e)?a=4:Ai(e)&&(a=5),s=c}0===r?this.valType=a:a===this.valType&&6!==a||(o=!0),this.discrete=this.discrete||o;var h={time:t,value:s,rawValue:e,percent:0};return n&&(h.easing=n,h.easingFunc=Y(n)?n:yn[n]||Wn(n)),i.push(h),h},t.prototype.prepare=function(t,e){var n=this.keyframes;this._needsSort&&n.sort((function(t,e){return t.time-e.time}));for(var i=this.valType,r=n.length,o=n[r-1],a=this.discrete,s=Yi(i),l=Ui(i),u=0;u=0&&!(l[n].percent<=e);n--);n=p(n,u-2)}else{for(n=d;ne);n++);n=p(n-1,u-2)}r=l[n+1],i=l[n]}if(i&&r){this._lastFr=n,this._lastFrP=e;var f=r.percent-i.percent,g=0===f?1:p((e-i.percent)/f,1);r.easingFunc&&(g=r.easingFunc(g));var y=o?this._additiveValue:h?Xi:t[c];if(!Yi(s)&&!h||y||(y=this._additiveValue=[]),this.discrete)t[c]=g<1?i.rawValue:r.rawValue;else if(Yi(s))1===s?Ei(y,i[a],r[a],g):function(t,e,n,i){for(var r=e.length,o=r&&e[0].length,a=0;a0&&s.addKeyframe(0,Wi(l),i),this._trackKeys.push(a)}s.addKeyframe(t,Wi(e[a]),i)}return this._maxTime=Math.max(this._maxTime,t),this},t.prototype.pause=function(){this._clip.pause(),this._paused=!0},t.prototype.resume=function(){this._clip.resume(),this._paused=!1},t.prototype.isPaused=function(){return!!this._paused},t.prototype.duration=function(t){return this._maxTime=t,this._force=!0,this},t.prototype._doneCallback=function(){this._setTracksFinished(),this._clip=null;var t=this._doneCbs;if(t)for(var e=t.length,n=0;n0)){this._started=1;for(var e=this,n=[],i=this._maxTime||0,r=0;r1){var a=o.pop();r.addKeyframe(a.time,t[i]),r.prepare(this._maxTime,r.getAdditiveTrack())}}}},t}();function qi(){return(new Date).getTime()}var Ki,$i,Ji=function(t){function e(e){var n=t.call(this)||this;return n._running=!1,n._time=0,n._pausedTime=0,n._pauseStart=0,n._paused=!1,e=e||{},n.stage=e.stage||{},n}return n(e,t),e.prototype.addClip=function(t){t.animation&&this.removeClip(t),this._head?(this._tail.next=t,t.prev=this._tail,t.next=null,this._tail=t):this._head=this._tail=t,t.animation=this},e.prototype.addAnimator=function(t){t.animation=this;var e=t.getClip();e&&this.addClip(e)},e.prototype.removeClip=function(t){if(t.animation){var e=t.prev,n=t.next;e?e.next=n:this._head=n,n?n.prev=e:this._tail=e,t.next=t.prev=t.animation=null}},e.prototype.removeAnimator=function(t){var e=t.getClip();e&&this.removeClip(e),t.animation=null},e.prototype.update=function(t){for(var e=qi()-this._pausedTime,n=e-this._time,i=this._head;i;){var r=i.next;i.step(e,n)?(i.ondestroy(),this.removeClip(i),i=r):i=r}this._time=e,t||(this.trigger("frame",n),this.stage.update&&this.stage.update())},e.prototype._startLoop=function(){var t=this;this._running=!0,gn((function e(){t._running&&(gn(e),!t._paused&&t.update())}))},e.prototype.start=function(){this._running||(this._time=qi(),this._pausedTime=0,this._startLoop())},e.prototype.stop=function(){this._running=!1},e.prototype.pause=function(){this._paused||(this._pauseStart=qi(),this._paused=!0)},e.prototype.resume=function(){this._paused&&(this._pausedTime+=qi()-this._pauseStart,this._paused=!1)},e.prototype.clear=function(){for(var t=this._head;t;){var e=t.next;t.prev=t.next=t.animation=null,t=e}this._head=this._tail=null},e.prototype.isFinished=function(){return null==this._head},e.prototype.animate=function(t,e){e=e||{},this.start();var n=new ji(t,e.loop);return this.addAnimator(n),n},e}(qt),Qi=r.domSupported,tr=($i={pointerdown:1,pointerup:1,pointermove:1,pointerout:1},{mouse:Ki=["click","dblclick","mousewheel","wheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],touch:["touchstart","touchend","touchmove"],pointer:E(Ki,(function(t){var e=t.replace("mouse","pointer");return $i.hasOwnProperty(e)?e:t}))}),er=["mousemove","mouseup"],nr=["pointermove","pointerup"],ir=!1;function rr(t){var e=t.pointerType;return"pen"===e||"touch"===e}function or(t){t&&(t.zrByTouch=!0)}function ar(t,e){for(var n=e,i=!1;n&&9!==n.nodeType&&!(i=n.domBelongToZr||n!==e&&n===t.painterRoot);)n=n.parentNode;return i}var sr=function(t,e){this.stopPropagation=bt,this.stopImmediatePropagation=bt,this.preventDefault=bt,this.type=e.type,this.target=this.currentTarget=t.dom,this.pointerType=e.pointerType,this.clientX=e.clientX,this.clientY=e.clientY},lr={mousedown:function(t){t=de(this.dom,t),this.__mayPointerCapture=[t.zrX,t.zrY],this.trigger("mousedown",t)},mousemove:function(t){t=de(this.dom,t);var e=this.__mayPointerCapture;!e||t.zrX===e[0]&&t.zrY===e[1]||this.__togglePointerCapture(!0),this.trigger("mousemove",t)},mouseup:function(t){t=de(this.dom,t),this.__togglePointerCapture(!1),this.trigger("mouseup",t)},mouseout:function(t){ar(this,(t=de(this.dom,t)).toElement||t.relatedTarget)||(this.__pointerCapturing&&(t.zrEventControl="no_globalout"),this.trigger("mouseout",t))},wheel:function(t){ir=!0,t=de(this.dom,t),this.trigger("mousewheel",t)},mousewheel:function(t){ir||(t=de(this.dom,t),this.trigger("mousewheel",t))},touchstart:function(t){or(t=de(this.dom,t)),this.__lastTouchMoment=new Date,this.handler.processGesture(t,"start"),lr.mousemove.call(this,t),lr.mousedown.call(this,t)},touchmove:function(t){or(t=de(this.dom,t)),this.handler.processGesture(t,"change"),lr.mousemove.call(this,t)},touchend:function(t){or(t=de(this.dom,t)),this.handler.processGesture(t,"end"),lr.mouseup.call(this,t),+new Date-+this.__lastTouchMoment<300&&lr.click.call(this,t)},pointerdown:function(t){lr.mousedown.call(this,t)},pointermove:function(t){rr(t)||lr.mousemove.call(this,t)},pointerup:function(t){lr.mouseup.call(this,t)},pointerout:function(t){rr(t)||lr.mouseout.call(this,t)}};z(["click","dblclick","contextmenu"],(function(t){lr[t]=function(e){e=de(this.dom,e),this.trigger(t,e)}}));var ur={pointermove:function(t){rr(t)||ur.mousemove.call(this,t)},pointerup:function(t){ur.mouseup.call(this,t)},mousemove:function(t){this.trigger("mousemove",t)},mouseup:function(t){var e=this.__pointerCapturing;this.__togglePointerCapture(!1),this.trigger("mouseup",t),e&&(t.zrEventControl="only_globalout",this.trigger("mouseout",t))}};function cr(t,e){var n=e.domHandlers;r.pointerEventsSupported?z(tr.pointer,(function(i){dr(e,i,(function(e){n[i].call(t,e)}))})):(r.touchEventsSupported&&z(tr.touch,(function(i){dr(e,i,(function(r){n[i].call(t,r),function(t){t.touching=!0,null!=t.touchTimer&&(clearTimeout(t.touchTimer),t.touchTimer=null),t.touchTimer=setTimeout((function(){t.touching=!1,t.touchTimer=null}),700)}(e)}))})),z(tr.mouse,(function(i){dr(e,i,(function(r){r=he(r),e.touching||n[i].call(t,r)}))})))}function hr(t,e){function n(n){dr(e,n,(function(i){i=he(i),ar(t,i.target)||(i=function(t,e){return de(t.dom,new sr(t,e),!0)}(t,i),e.domHandlers[n].call(t,i))}),{capture:!0})}r.pointerEventsSupported?z(nr,n):r.touchEventsSupported||z(er,n)}function dr(t,e,n,i){t.mounted[e]=n,t.listenerOpts[e]=i,pe(t.domTarget,e,n,i)}function pr(t){var e,n,i,r,o=t.mounted;for(var a in o)o.hasOwnProperty(a)&&(e=t.domTarget,n=a,i=o[a],r=t.listenerOpts[a],e.removeEventListener(n,i,r));t.mounted={}}var fr=function(t,e){this.mounted={},this.listenerOpts={},this.touching=!1,this.domTarget=t,this.domHandlers=e},gr=function(t){function e(e,n){var i=t.call(this)||this;return i.__pointerCapturing=!1,i.dom=e,i.painterRoot=n,i._localHandlerScope=new fr(e,lr),Qi&&(i._globalHandlerScope=new fr(document,ur)),cr(i,i._localHandlerScope),i}return n(e,t),e.prototype.dispose=function(){pr(this._localHandlerScope),Qi&&pr(this._globalHandlerScope)},e.prototype.setCursor=function(t){this.dom.style&&(this.dom.style.cursor=t||"default")},e.prototype.__togglePointerCapture=function(t){if(this.__mayPointerCapture=null,Qi&&+this.__pointerCapturing^+t){this.__pointerCapturing=t;var e=this._globalHandlerScope;t?hr(this,e):pr(e)}},e}(qt),yr=1;r.hasGlobalWindow&&(yr=Math.max(window.devicePixelRatio||window.screen&&window.screen.deviceXDPI/window.screen.logicalXDPI||1,1));var vr=yr,mr="#333",xr="#ccc",_r=_e,br=5e-5;function wr(t){return t>br||t<-5e-5}var Sr,Mr=[],Ir=[],Tr=[1,0,0,1,0,0],Cr=Math.abs,Dr=function(){function t(){}var e;return t.prototype.getLocalTransform=function(e){return t.getLocalTransform(this,e)},t.prototype.setPosition=function(t){this.x=t[0],this.y=t[1]},t.prototype.setScale=function(t){this.scaleX=t[0],this.scaleY=t[1]},t.prototype.setSkew=function(t){this.skewX=t[0],this.skewY=t[1]},t.prototype.setOrigin=function(t){this.originX=t[0],this.originY=t[1]},t.prototype.needLocalTransform=function(){return wr(this.rotation)||wr(this.x)||wr(this.y)||wr(this.scaleX-1)||wr(this.scaleY-1)||wr(this.skewX)||wr(this.skewY)},t.prototype.updateTransform=function(){var t=this.parent&&this.parent.transform,e=this.needLocalTransform(),n=this.transform;e||t?(n=n||[1,0,0,1,0,0],e?this.getLocalTransform(n):_r(n),t&&(e?we(n,t,n):be(n,t)),this.transform=n,this._resolveGlobalScaleRatio(n)):n&&(_r(n),this.invTransform=null)},t.prototype._resolveGlobalScaleRatio=function(t){var e=this.globalScaleRatio;if(null!=e&&1!==e){this.getGlobalScale(Mr);var n=Mr[0]<0?-1:1,i=Mr[1]<0?-1:1,r=((Mr[0]-n)*e+n)/Mr[0]||0,o=((Mr[1]-i)*e+i)/Mr[1]||0;t[0]*=r,t[1]*=r,t[2]*=o,t[3]*=o}this.invTransform=this.invTransform||[1,0,0,1,0,0],Te(this.invTransform,t)},t.prototype.getComputedTransform=function(){for(var t=this,e=[];t;)e.push(t),t=t.parent;for(;t=e.pop();)t.updateTransform();return this.transform},t.prototype.setLocalTransform=function(t){if(t){var e=t[0]*t[0]+t[1]*t[1],n=t[2]*t[2]+t[3]*t[3],i=Math.atan2(t[1],t[0]),r=Math.PI/2+i-Math.atan2(t[3],t[2]);n=Math.sqrt(n)*Math.cos(r),e=Math.sqrt(e),this.skewX=r,this.skewY=0,this.rotation=-i,this.x=+t[4],this.y=+t[5],this.scaleX=e,this.scaleY=n,this.originX=0,this.originY=0}},t.prototype.decomposeTransform=function(){if(this.transform){var t=this.parent,e=this.transform;t&&t.transform&&(t.invTransform=t.invTransform||[1,0,0,1,0,0],we(Ir,t.invTransform,e),e=Ir);var n=this.originX,i=this.originY;(n||i)&&(Tr[4]=n,Tr[5]=i,we(Ir,e,Tr),Ir[4]-=n,Ir[5]-=i,e=Ir),this.setLocalTransform(e)}},t.prototype.getGlobalScale=function(t){var e=this.transform;return t=t||[],e?(t[0]=Math.sqrt(e[0]*e[0]+e[1]*e[1]),t[1]=Math.sqrt(e[2]*e[2]+e[3]*e[3]),e[0]<0&&(t[0]=-t[0]),e[3]<0&&(t[1]=-t[1]),t):(t[0]=1,t[1]=1,t)},t.prototype.transformCoordToLocal=function(t,e){var n=[t,e],i=this.invTransform;return i&&Ht(n,n,i),n},t.prototype.transformCoordToGlobal=function(t,e){var n=[t,e],i=this.transform;return i&&Ht(n,n,i),n},t.prototype.getLineScale=function(){var t=this.transform;return t&&Cr(t[0]-1)>1e-10&&Cr(t[3]-1)>1e-10?Math.sqrt(Cr(t[0]*t[3]-t[2]*t[1])):1},t.prototype.copyTransform=function(t){kr(this,t)},t.getLocalTransform=function(t,e){e=e||[];var n=t.originX||0,i=t.originY||0,r=t.scaleX,o=t.scaleY,a=t.anchorX,s=t.anchorY,l=t.rotation||0,u=t.x,c=t.y,h=t.skewX?Math.tan(t.skewX):0,d=t.skewY?Math.tan(-t.skewY):0;if(n||i||a||s){var p=n+a,f=i+s;e[4]=-p*r-h*f*o,e[5]=-f*o-d*p*r}else e[4]=e[5]=0;return e[0]=r,e[3]=o,e[1]=d*r,e[2]=h*o,l&&Me(e,e,l),e[4]+=n+u,e[5]+=i+c,e},t.initDefaultProps=((e=t.prototype).scaleX=e.scaleY=e.globalScaleRatio=1,void(e.x=e.y=e.originX=e.originY=e.skewX=e.skewY=e.rotation=e.anchorX=e.anchorY=0)),t}(),Ar=["x","y","originX","originY","anchorX","anchorY","rotation","scaleX","scaleY","skewX","skewY"];function kr(t,e){for(var n=0;n=Or)){t=t||a;for(var e=[],n=+new Date,i=0;i<=127;i++)e[i]=c.measureText(String.fromCharCode(i),t).width;var r=+new Date-n;return r>16?Pr=Or:r>2&&Pr++,e}}(t.font),t.asciiWidthMapTried=!0),0<=e&&e<=127?null!=t.asciiWidthMap?t.asciiWidthMap[e]:t.asciiCharWidth:t.stWideCharWidth}function Nr(t,e){var n=t.strWidthCache,i=n.get(e);return null==i&&(i=c.measureText(e,t.font).width,n.put(e,i)),i}function zr(t,e,n,i){var r=Nr(Lr(e),t),o=Gr(e),a=Br(0,r,n),s=Vr(0,o,i);return new He(a,s,r,o)}function Er(t,e,n,i){var r=((t||"")+"").split("\n");if(1===r.length)return zr(r[0],e,n,i);for(var o=new He(0,0,0,0),a=0;a=0?parseFloat(t)/100*e:parseFloat(t):t}function Wr(t,e,n){var i=e.position||"inside",r=null!=e.distance?e.distance:5,o=n.height,a=n.width,s=o/2,l=n.x,u=n.y,c="left",h="top";if(i instanceof Array)l+=Fr(i[0],n.width),u+=Fr(i[1],n.height),c=null,h=null;else switch(i){case"left":l-=r,u+=s,c="right",h="middle";break;case"right":l+=r+a,u+=s,h="middle";break;case"top":l+=a/2,u-=r,c="center",h="bottom";break;case"bottom":l+=a/2,u+=o+r,c="center";break;case"inside":l+=a/2,u+=s,c="center",h="middle";break;case"insideLeft":l+=r,u+=s,h="middle";break;case"insideRight":l+=a-r,u+=s,c="right",h="middle";break;case"insideTop":l+=a/2,u+=r,c="center";break;case"insideBottom":l+=a/2,u+=o-r,c="center",h="bottom";break;case"insideTopLeft":l+=r,u+=r;break;case"insideTopRight":l+=a-r,u+=r,c="right";break;case"insideBottomLeft":l+=r,u+=o-r,h="bottom";break;case"insideBottomRight":l+=a-r,u+=o-r,c="right",h="bottom"}return(t=t||{}).x=l,t.y=u,t.align=c,t.verticalAlign=h,t}var Hr="__zr_normal__",Ur=Ar.concat(["ignore"]),Yr=B(Ar,(function(t,e){return t[e]=!0,t}),{ignore:!1}),Xr={},Zr=new He(0,0,0,0),jr=[],qr=function(){function t(t){this.id=M(),this.animators=[],this.currentStates=[],this.states={},this._init(t)}return t.prototype._init=function(t){this.attr(t)},t.prototype.drift=function(t,e,n){switch(this.draggable){case"horizontal":e=0;break;case"vertical":t=0}var i=this.transform;i||(i=this.transform=[1,0,0,1,0,0]),i[4]+=t,i[5]+=e,this.decomposeTransform(),this.markRedraw()},t.prototype.beforeUpdate=function(){},t.prototype.afterUpdate=function(){},t.prototype.update=function(){this.updateTransform(),this.__dirty&&this.updateInnerText()},t.prototype.updateInnerText=function(t){var e=this._textContent;if(e&&(!e.ignore||t)){this.textConfig||(this.textConfig={});var n=this.textConfig,i=n.local,r=e.innerTransformable,o=void 0,a=void 0,s=!1;r.parent=i?this:null;var l=!1;r.copyTransform(e);var u=null!=n.position,c=n.autoOverflowArea,h=void 0;if((c||u)&&(h=Zr,n.layoutRect?h.copy(n.layoutRect):h.copy(this.getBoundingRect()),i||h.applyTransform(this.transform)),u){this.calculateTextPosition?this.calculateTextPosition(Xr,n,h):Wr(Xr,n,h),r.x=Xr.x,r.y=Xr.y,o=Xr.align,a=Xr.verticalAlign;var d=n.origin;if(d&&null!=n.rotation){var p=void 0,f=void 0;"center"===d?(p=.5*h.width,f=.5*h.height):(p=Fr(d[0],h.width),f=Fr(d[1],h.height)),l=!0,r.originX=-r.x+p+(i?0:h.x),r.originY=-r.y+f+(i?0:h.y)}}null!=n.rotation&&(r.rotation=n.rotation);var g=n.offset;g&&(r.x+=g[0],r.y+=g[1],l||(r.originX=-g[0],r.originY=-g[1]));var y=this._innerTextDefaultStyle||(this._innerTextDefaultStyle={});if(c){var v=y.overflowRect=y.overflowRect||new He(0,0,0,0);r.getLocalTransform(jr),Te(jr,jr),He.copy(v,h),v.applyTransform(jr)}else y.overflowRect=null;var m=void 0,x=void 0,_=void 0;(null==n.inside?"string"==typeof n.position&&n.position.indexOf("inside")>=0:n.inside)&&this.canBeInsideText()?(m=n.insideFill,x=n.insideStroke,null!=m&&"auto"!==m||(m=this.getInsideTextFill()),null!=x&&"auto"!==x||(x=this.getInsideTextStroke(m),_=!0)):(m=n.outsideFill,x=n.outsideStroke,null!=m&&"auto"!==m||(m=this.getOutsideFill()),null!=x&&"auto"!==x||(x=this.getOutsideStroke(m),_=!0)),(m=m||"#000")===y.fill&&x===y.stroke&&_===y.autoStroke&&o===y.align&&a===y.verticalAlign||(s=!0,y.fill=m,y.stroke=x,y.autoStroke=_,y.align=o,y.verticalAlign=a,e.setDefaultTextStyle(y)),e.__dirty|=1,s&&e.dirtyStyle(!0)}},t.prototype.canBeInsideText=function(){return!0},t.prototype.getInsideTextFill=function(){return"#fff"},t.prototype.getInsideTextStroke=function(t){return"#000"},t.prototype.getOutsideFill=function(){return this.__zr&&this.__zr.isDarkMode()?xr:mr},t.prototype.getOutsideStroke=function(t){var e=this.__zr&&this.__zr.getBackgroundColor(),n="string"==typeof e&&oi(e);n||(n=[255,255,255,1]);for(var i=n[3],r=this.__zr.isDarkMode(),o=0;o<3;o++)n[o]=n[o]*i+(r?0:255)*(1-i);return n[3]=1,fi(n,"rgba")},t.prototype.traverse=function(t,e){},t.prototype.attrKV=function(t,e){"textConfig"===t?this.setTextConfig(e):"textContent"===t?this.setTextContent(e):"clipPath"===t?this.setClipPath(e):"extra"===t?(this.extra=this.extra||{},A(this.extra,e)):this[t]=e},t.prototype.hide=function(){this.ignore=!0,this.markRedraw()},t.prototype.show=function(){this.ignore=!1,this.markRedraw()},t.prototype.attr=function(t,e){if("string"==typeof t)this.attrKV(t,e);else if(q(t))for(var n=F(t),i=0;i0},t.prototype.getState=function(t){return this.states[t]},t.prototype.ensureState=function(t){var e=this.states;return e[t]||(e[t]={}),e[t]},t.prototype.clearStates=function(t){this.useState(Hr,!1,t)},t.prototype.useState=function(t,e,n,i){var r=t===Hr;if(this.hasState()||!r){var o=this.currentStates,a=this.stateTransition;if(!(P(o,t)>=0)||!e&&1!==o.length){var s;if(this.stateProxy&&!r&&(s=this.stateProxy(t)),s||(s=this.states&&this.states[t]),s||r){r||this.saveCurrentToNormalState(s);var l=!!(s&&s.hoverLayer||i);l&&this._toggleHoverLayerFlag(!0),this._applyStateObj(t,s,this._normalState,e,!n&&!this.__inHover&&a&&a.duration>0,a);var u=this._textContent,c=this._textGuide;return u&&u.useState(t,e,n,l),c&&c.useState(t,e,n,l),r?(this.currentStates=[],this._normalState={}):e?this.currentStates.push(t):this.currentStates=[t],this._updateAnimationTargets(),this.markRedraw(),!l&&this.__inHover&&(this._toggleHoverLayerFlag(!1),this.__dirty&=-2),s}I("State "+t+" not exists.")}}},t.prototype.useStates=function(t,e,n){if(t.length){var i=[],r=this.currentStates,o=t.length,a=o===r.length;if(a)for(var s=0;s0,p);var f=this._textContent,g=this._textGuide;f&&f.useStates(t,e,h),g&&g.useStates(t,e,h),this._updateAnimationTargets(),this.currentStates=t.slice(),this.markRedraw(),!h&&this.__inHover&&(this._toggleHoverLayerFlag(!1),this.__dirty&=-2)}else this.clearStates()},t.prototype.isSilent=function(){for(var t=this;t;){if(t.silent)return!0;var e=t.__hostTarget;t=e?t.ignoreHostSilent?null:e:t.parent}return!1},t.prototype._updateAnimationTargets=function(){for(var t=0;t=0){var n=this.currentStates.slice();n.splice(e,1),this.useStates(n)}},t.prototype.replaceState=function(t,e,n){var i=this.currentStates.slice(),r=P(i,t),o=P(i,e)>=0;r>=0?o?i.splice(r,1):i[r]=e:n&&!o&&i.push(e),this.useStates(i)},t.prototype.toggleState=function(t,e){e?this.useState(t,!0):this.removeState(t)},t.prototype._mergeStates=function(t){for(var e,n={},i=0;i=0&&e.splice(n,1)})),this.animators.push(t),n&&n.animation.addAnimator(t),n&&n.wakeUp()},t.prototype.updateDuringAnimation=function(t){this.markRedraw()},t.prototype.stopAnimation=function(t,e){for(var n=this.animators,i=n.length,r=[],o=0;o0&&n.during&&o[0].during((function(t,e){n.during(e)}));for(var d=0;d0||r.force&&!a.length){var w,S=void 0,M=void 0,I=void 0;if(s){M={},d&&(S={});for(_=0;_=0&&(n.splice(i,0,t),this._doAdd(t))}return this},e.prototype.replace=function(t,e){var n=P(this._children,t);return n>=0&&this.replaceAt(e,n),this},e.prototype.replaceAt=function(t,e){var n=this._children,i=n[e];if(t&&t!==this&&t.parent!==this&&t!==i){n[e]=t,i.parent=null;var r=this.__zr;r&&i.removeSelfFromZr(r),this._doAdd(t)}return this},e.prototype._doAdd=function(t){t.parent&&t.parent.remove(t),t.parent=this;var e=this.__zr;e&&e!==t.__zr&&t.addSelfToZr(e),e&&e.refresh()},e.prototype.remove=function(t){var e=this.__zr,n=this._children,i=P(n,t);return i<0||(n.splice(i,1),t.parent=null,e&&t.removeSelfFromZr(e),e&&e.refresh()),this},e.prototype.removeAll=function(){for(var t=this._children,e=this.__zr,n=0;n0&&(this._stillFrameAccum++,this._stillFrameAccum>this._sleepAfterStill&&this.animation.stop())},t.prototype.setSleepAfterStill=function(t){this._sleepAfterStill=t},t.prototype.wakeUp=function(){this._disposed||(this.animation.start(),this._stillFrameAccum=0)},t.prototype.refreshHover=function(){this._needsRefreshHover=!0},t.prototype.refreshHoverImmediately=function(){this._disposed||(this._needsRefreshHover=!1,this.painter.refreshHover&&"canvas"===this.painter.getType()&&this.painter.refreshHover())},t.prototype.resize=function(t){this._disposed||(t=t||{},this.painter.resize(t.width,t.height),this.handler.resize())},t.prototype.clearAnimation=function(){this._disposed||this.animation.clear()},t.prototype.getWidth=function(){if(!this._disposed)return this.painter.getWidth()},t.prototype.getHeight=function(){if(!this._disposed)return this.painter.getHeight()},t.prototype.setCursorStyle=function(t){this._disposed||this.handler.setCursorStyle(t)},t.prototype.findHover=function(t,e){if(!this._disposed)return this.handler.findHover(t,e)},t.prototype.on=function(t,e,n){return this._disposed||this.handler.on(t,e,n),this},t.prototype.off=function(t,e){this._disposed||this.handler.off(t,e)},t.prototype.trigger=function(t,e){this._disposed||this.handler.trigger(t,e)},t.prototype.clear=function(){if(!this._disposed){for(var t=this.storage.getRoots(),e=0;e0){if(t<=r)return a;if(t>=o)return s}else{if(t>=r)return a;if(t<=o)return s}else{if(t===r)return a;if(t===o)return s}return(t-r)/l*u+a}var yo=function(t,e,n){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return vo(t,e,n)};function vo(t,e,n){return X(t)?(i=t,i.replace(/^\s+|\s+$/g,"")).match(/%$/)?parseFloat(t)/100*e+(n||0):parseFloat(t):null==t?NaN:+t;var i}function mo(t,e,n){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),n?t:+t}function xo(t){return t.sort((function(t,e){return t-e})),t}function _o(t){if(t=+t,isNaN(t))return 0;if(t>1e-14)for(var e=1,n=0;n<15;n++,e*=10)if(Math.round(t*e)/e===t)return n;return bo(t)}function bo(t){var e=t.toString().toLowerCase(),n=e.indexOf("e"),i=n>0?+e.slice(n+1):0,r=n>0?n:e.length,o=e.indexOf("."),a=o<0?0:r-1-o;return Math.max(0,a-i)}function wo(t,e){var n=Math.log,i=Math.LN10,r=Math.floor(n(t[1]-t[0])/i),o=Math.round(n(fo(e[1]-e[0]))/i),a=Math.min(Math.max(-r+o,0),20);return isFinite(a)?a:20}function So(t,e){var n=B(t,(function(t,e){return t+(isNaN(e)?0:e)}),0);if(0===n)return[];for(var i=Math.pow(10,e),r=E(t,(function(t){return(isNaN(t)?0:t)/n*i*100})),o=100*i,a=E(r,(function(t){return Math.floor(t)})),s=B(a,(function(t,e){return t+e}),0),l=E(r,(function(t,e){return t-a[e]}));su&&(u=l[h],c=h);++a[c],l[c]=0,++s}return E(a,(function(t){return t/i}))}function Mo(t,e){var n=Math.max(_o(t),_o(e)),i=t+e;return n>20?i:mo(i,n)}var Io=9007199254740991;function To(t){var e=2*Math.PI;return(t%e+e)%e}function Co(t){return t>-1e-4&&t=10&&e++,e}function Po(t,e){var n=Lo(t),i=Math.pow(10,n),r=t/i;return t=(e?r<1.5?1:r<2.5?2:r<4?3:r<7?5:10:r<1?1:r<2?2:r<3?3:r<5?5:10)*i,n>=-20?+t.toFixed(n<0?-n:0):t}function Oo(t,e){var n=(t.length-1)*e+1,i=Math.floor(n),r=+t[i-1],o=n-i;return o?r+o*(t[i]-r):r}function Ro(t){t.sort((function(t,e){return s(t,e,0)?-1:1}));for(var e=-1/0,n=1,i=0;i0?t.length:0,this.item=null,this.key=NaN,this},t.prototype.next=function(){return(this._step>0?this._idx=this._end)&&(this.item=this._list[this._idx],this.key=this._idx=this._idx+this._step,!0)},t}();function ma(t){t.option=t.parentModel=t.ecModel=null}var xa="___EC__COMPONENT__CONTAINER___",_a="___EC__EXTENDED_CLASS___";function ba(t){var e={main:"",sub:""};if(t){var n=t.split(".");e.main=n[0]||"",e.sub=n[1]||""}return e}function wa(t,e){t.$constructor=t,t.extend=function(t){var e,i,r=this;return Y(i=r)&&/^class\s/.test(Function.prototype.toString.call(i))?e=function(t){function e(){return t.apply(this,arguments)||this}return n(e,t),e}(r):(e=function(){(t.$constructor||r).apply(this,arguments)},O(e,this)),A(e.prototype,t),e[_a]=!0,e.extend=this.extend,e.superCall=Ia,e.superApply=Ta,e.superClass=r,e}}function Sa(t,e){t.extend=e.extend}var Ma=Math.round(10*Math.random());function Ia(t,e){for(var n=[],i=2;i=0||r&&P(r,s)<0)){var l=n.getShallow(s,e);null!=l&&(o[t[a][0]]=l)}}return o}}var Aa=Da([["fill","color"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["opacity"],["shadowColor"]]),ka=function(){function t(){}return t.prototype.getAreaStyle=function(t,e){return Aa(this,t,e)},t}(),La=new Xn(50);function Pa(t){if("string"==typeof t){var e=La.get(t);return e&&e.image}return t}function Oa(t,e,n,i,r){if(t){if("string"==typeof t){if(e&&e.__zrImageSrc===t||!n)return e;var o=La.get(t),a={hostEl:n,cb:i,cbPayload:r};return o?!Na(e=o.image)&&o.pending.push(a):((e=c.loadImage(t,Ra,Ra)).__zrImageSrc=t,La.put(t,e.__cachedImgObj={image:e,pending:[a]})),e}return t}return e}function Ra(){var t=this.__cachedImgObj;this.onload=this.onerror=this.__cachedImgObj=null;for(var e=0;e=s;u++)l-=s;var c=Nr(a,n);return c>l&&(n="",c=0),l=t-c,r.ellipsis=n,r.ellipsisWidth=c,r.contentWidth=l,r.containerWidth=t,r}function Va(t,e,n){var i=n.containerWidth,r=n.contentWidth,o=n.fontMeasureInfo;if(!i)return t.textLine="",void(t.isTruncated=!1);var a=Nr(o,e);if(a<=i)return t.textLine=e,void(t.isTruncated=!1);for(var s=0;;s++){if(a<=r||s>=n.maxIterations){e+=n.ellipsis;break}var l=0===s?Ga(e,r,o):a>0?Math.floor(e.length*r/a):0;a=Nr(o,e=e.substr(0,l))}""===e&&(e=n.placeholder),t.textLine=e,t.isTruncated=!0}function Ga(t,e,n){for(var i=0,r=0,o=t.length;r0&&f+i.accumWidth>i.width&&(o=e.split("\n"),h=!0),i.accumWidth=f}else{var g=Za(e,c,i.width,i.breakAll,i.accumWidth);i.accumWidth=g.accumWidth+p,a=g.linesWidths,o=g.lines}}o||(o=e.split("\n"));for(var y=Lr(c),v=0;v=32&&e<=591||e>=880&&e<=4351||e>=4608&&e<=5119||e>=7680&&e<=8303}(t)||!!Ya[t]}function Za(t,e,n,i,r){for(var o=[],a=[],s="",l="",u=0,c=0,h=Lr(e),d=0;dn:r+c+f>n)?c?(s||l)&&(g?(s||(s=l,l="",c=u=0),o.push(s),a.push(c-u),l+=p,s="",c=u+=f):(l&&(s+=l,l="",u=0),o.push(s),a.push(c),s=p,c=f)):g?(o.push(l),a.push(u),l=p,u=f):(o.push(p),a.push(f)):(c+=f,g?(l+=p,u+=f):(l&&(s+=l,l="",u=0),s+=p))}else l&&(s+=l,c+=u),o.push(s),a.push(c),s="",l="",u=0,c=0}return l&&(s+=l),s&&(o.push(s),a.push(c)),1===o.length&&(c+=r),{accumWidth:c,lines:o,linesWidths:a}}function ja(t,e,n,i,r,o){if(t.baseX=n,t.baseY=i,t.outerWidth=t.outerHeight=null,e){var a=2*e.width,s=2*e.height;He.set(qa,Br(n,a,r),Vr(i,s,o),a,s),He.intersect(e,qa,null,Ka);var l=Ka.outIntersectRect;t.outerWidth=l.width,t.outerHeight=l.height,t.baseX=Br(l.x,l.width,r,!0),t.baseY=Vr(l.y,l.height,o,!0)}}var qa=new He(0,0,0,0),Ka={outIntersectRect:{},clamp:!0};function $a(t){return null!=t?t+="":t=""}function Ja(t,e,n,i){var r=new He(Br(t.x||0,e,t.textAlign),Vr(t.y||0,n,t.textBaseline),e,n),o=null!=i?i:Qa(t)?t.lineWidth:0;return o>0&&(r.x-=o/2,r.y-=o/2,r.width+=o,r.height+=o),r}function Qa(t){var e=t.stroke;return null!=e&&"none"!==e&&t.lineWidth>0}var ts="__zr_style_"+Math.round(10*Math.random()),es={shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,shadowColor:"#000",opacity:1,blend:"source-over"},ns={style:{shadowBlur:!0,shadowOffsetX:!0,shadowOffsetY:!0,shadowColor:!0,opacity:!0}};es[ts]=!0;var is=["z","z2","invisible"],rs=["invisible"],os=function(t){function e(e){return t.call(this,e)||this}var i;return n(e,t),e.prototype._init=function(e){for(var n=F(e),i=0;i1e-4)return s[0]=t-n,s[1]=e-i,l[0]=t+n,void(l[1]=e+i);if(ps[0]=hs(r)*n+t,ps[1]=cs(r)*i+e,fs[0]=hs(o)*n+t,fs[1]=cs(o)*i+e,u(s,ps,fs),c(l,ps,fs),(r%=ds)<0&&(r+=ds),(o%=ds)<0&&(o+=ds),r>o&&!a?o+=ds:rr&&(gs[0]=hs(p)*n+t,gs[1]=cs(p)*i+e,u(s,gs,s),c(l,gs,l))}var Ss={M:1,L:2,C:3,Q:4,A:5,Z:6,R:7},Ms=[],Is=[],Ts=[],Cs=[],Ds=[],As=[],ks=Math.min,Ls=Math.max,Ps=Math.cos,Os=Math.sin,Rs=Math.abs,Ns=Math.PI,zs=2*Ns,Es="undefined"!=typeof Float32Array,Bs=[];function Vs(t){return Math.round(t/Ns*1e8)/1e8%2*Ns}function Gs(t,e){var n=Vs(t[0]);n<0&&(n+=zs);var i=n-t[0],r=t[1];r+=i,!e&&r-n>=zs?r=n+zs:e&&n-r>=zs?r=n-zs:!e&&n>r?r=n+(zs-Vs(n-r)):e&&n0&&(this._ux=Rs(n/vr/t)||0,this._uy=Rs(n/vr/e)||0)},t.prototype.setDPR=function(t){this.dpr=t},t.prototype.setContext=function(t){this._ctx=t},t.prototype.getContext=function(){return this._ctx},t.prototype.beginPath=function(){return this._ctx&&this._ctx.beginPath(),this.reset(),this},t.prototype.reset=function(){this._saveData&&(this._len=0),this._pathSegLen&&(this._pathSegLen=null,this._pathLen=0),this._version++},t.prototype.moveTo=function(t,e){return this._drawPendingPt(),this.addData(Ss.M,t,e),this._ctx&&this._ctx.moveTo(t,e),this._x0=t,this._y0=e,this._xi=t,this._yi=e,this},t.prototype.lineTo=function(t,e){var n=Rs(t-this._xi),i=Rs(e-this._yi),r=n>this._ux||i>this._uy;if(this.addData(Ss.L,t,e),this._ctx&&r&&this._ctx.lineTo(t,e),r)this._xi=t,this._yi=e,this._pendingPtDist=0;else{var o=n*n+i*i;o>this._pendingPtDist&&(this._pendingPtX=t,this._pendingPtY=e,this._pendingPtDist=o)}return this},t.prototype.bezierCurveTo=function(t,e,n,i,r,o){return this._drawPendingPt(),this.addData(Ss.C,t,e,n,i,r,o),this._ctx&&this._ctx.bezierCurveTo(t,e,n,i,r,o),this._xi=r,this._yi=o,this},t.prototype.quadraticCurveTo=function(t,e,n,i){return this._drawPendingPt(),this.addData(Ss.Q,t,e,n,i),this._ctx&&this._ctx.quadraticCurveTo(t,e,n,i),this._xi=n,this._yi=i,this},t.prototype.arc=function(t,e,n,i,r,o){this._drawPendingPt(),Bs[0]=i,Bs[1]=r,Gs(Bs,o),i=Bs[0];var a=(r=Bs[1])-i;return this.addData(Ss.A,t,e,n,n,i,a,0,o?0:1),this._ctx&&this._ctx.arc(t,e,n,i,r,o),this._xi=Ps(r)*n+t,this._yi=Os(r)*n+e,this},t.prototype.arcTo=function(t,e,n,i,r){return this._drawPendingPt(),this._ctx&&this._ctx.arcTo(t,e,n,i,r),this},t.prototype.rect=function(t,e,n,i){return this._drawPendingPt(),this._ctx&&this._ctx.rect(t,e,n,i),this.addData(Ss.R,t,e,n,i),this},t.prototype.closePath=function(){this._drawPendingPt(),this.addData(Ss.Z);var t=this._ctx,e=this._x0,n=this._y0;return t&&t.closePath(),this._xi=e,this._yi=n,this},t.prototype.fill=function(t){t&&t.fill(),this.toStatic()},t.prototype.stroke=function(t){t&&t.stroke(),this.toStatic()},t.prototype.len=function(){return this._len},t.prototype.setData=function(t){if(this._saveData){var e=t.length;this.data&&this.data.length===e||!Es||(this.data=new Float32Array(e));for(var n=0;n0&&o))for(var a=0;au.length&&(this._expandData(),u=this.data);for(var c=0;c0&&(this._ctx&&this._ctx.lineTo(this._pendingPtX,this._pendingPtY),this._pendingPtDist=0)},t.prototype._expandData=function(){if(!(this.data instanceof Array)){for(var t=[],e=0;e11&&(this.data=new Float32Array(t)))}},t.prototype.getBoundingRect=function(){Ts[0]=Ts[1]=Ds[0]=Ds[1]=Number.MAX_VALUE,Cs[0]=Cs[1]=As[0]=As[1]=-Number.MAX_VALUE;var t,e=this.data,n=0,i=0,r=0,o=0;for(t=0;tn||Rs(y)>i||h===e-1)&&(f=Math.sqrt(A*A+y*y),r=g,o=x);break;case Ss.C:var v=t[h++],m=t[h++],x=(g=t[h++],t[h++]),_=t[h++],b=t[h++];f=Rn(r,o,v,m,g,x,_,b,10),r=_,o=b;break;case Ss.Q:f=Gn(r,o,v=t[h++],m=t[h++],g=t[h++],x=t[h++],10),r=g,o=x;break;case Ss.A:var w=t[h++],S=t[h++],M=t[h++],I=t[h++],T=t[h++],C=t[h++],D=C+T;h+=1,p&&(a=Ps(T)*M+w,s=Os(T)*I+S),f=Ls(M,I)*ks(zs,Math.abs(C)),r=Ps(D)*M+w,o=Os(D)*I+S;break;case Ss.R:a=r=t[h++],s=o=t[h++],f=2*t[h++]+2*t[h++];break;case Ss.Z:var A=a-r;y=s-o;f=Math.sqrt(A*A+y*y),r=a,o=s}f>=0&&(l[c++]=f,u+=f)}return this._pathLen=u,u},t.prototype.rebuildPath=function(t,e){var n,i,r,o,a,s,l,u,c,h,d=this.data,p=this._ux,f=this._uy,g=this._len,y=e<1,v=0,m=0,x=0;if(!y||(this._pathSegLen||this._calculateLength(),l=this._pathSegLen,u=e*this._pathLen))t:for(var _=0;_0&&(t.lineTo(c,h),x=0),b){case Ss.M:n=r=d[_++],i=o=d[_++],t.moveTo(r,o);break;case Ss.L:a=d[_++],s=d[_++];var S=Rs(a-r),M=Rs(s-o);if(S>p||M>f){if(y){if(v+(j=l[m++])>u){var I=(u-v)/j;t.lineTo(r*(1-I)+a*I,o*(1-I)+s*I);break t}v+=j}t.lineTo(a,s),r=a,o=s,x=0}else{var T=S*S+M*M;T>x&&(c=a,h=s,x=T)}break;case Ss.C:var C=d[_++],D=d[_++],A=d[_++],k=d[_++],L=d[_++],P=d[_++];if(y){if(v+(j=l[m++])>u){Pn(r,C,A,L,I=(u-v)/j,Ms),Pn(o,D,k,P,I,Is),t.bezierCurveTo(Ms[1],Is[1],Ms[2],Is[2],Ms[3],Is[3]);break t}v+=j}t.bezierCurveTo(C,D,A,k,L,P),r=L,o=P;break;case Ss.Q:C=d[_++],D=d[_++],A=d[_++],k=d[_++];if(y){if(v+(j=l[m++])>u){Bn(r,C,A,I=(u-v)/j,Ms),Bn(o,D,k,I,Is),t.quadraticCurveTo(Ms[1],Is[1],Ms[2],Is[2]);break t}v+=j}t.quadraticCurveTo(C,D,A,k),r=A,o=k;break;case Ss.A:var O=d[_++],R=d[_++],N=d[_++],z=d[_++],E=d[_++],B=d[_++],V=d[_++],G=!d[_++],F=N>z?N:z,W=Rs(N-z)>.001,H=E+B,U=!1;if(y)v+(j=l[m++])>u&&(H=E+B*(u-v)/j,U=!0),v+=j;if(W&&t.ellipse?t.ellipse(O,R,N,z,V,E,H,G):t.arc(O,R,F,E,H,G),U)break t;w&&(n=Ps(E)*N+O,i=Os(E)*z+R),r=Ps(H)*N+O,o=Os(H)*z+R;break;case Ss.R:n=r=d[_],i=o=d[_+1],a=d[_++],s=d[_++];var Y=d[_++],X=d[_++];if(y){if(v+(j=l[m++])>u){var Z=u-v;t.moveTo(a,s),t.lineTo(a+ks(Z,Y),s),(Z-=Y)>0&&t.lineTo(a+Y,s+ks(Z,X)),(Z-=X)>0&&t.lineTo(a+Ls(Y-Z,0),s+X),(Z-=Y)>0&&t.lineTo(a,s+Ls(X-Z,0));break t}v+=j}t.rect(a,s,Y,X);break;case Ss.Z:if(y){var j;if(v+(j=l[m++])>u){I=(u-v)/j;t.lineTo(r*(1-I)+n*I,o*(1-I)+i*I);break t}v+=j}t.closePath(),r=n,o=i}}},t.prototype.clone=function(){var e=new t,n=this.data;return e.data=n.slice?n.slice():Array.prototype.slice.call(n),e._len=this._len,e},t.prototype.canSave=function(){return!!this._saveData},t.CMD=Ss,t.initDefaultProps=((e=t.prototype)._saveData=!0,e._ux=0,e._uy=0,e._pendingPtDist=0,void(e._version=0)),t}();function Ws(t,e,n,i,r,o,a){if(0===r)return!1;var s=r,l=0;if(a>e+s&&a>i+s||at+s&&o>n+s||oe+h&&c>i+h&&c>o+h&&c>s+h||ct+h&&u>n+h&&u>r+h&&u>a+h||ue+u&&l>i+u&&l>o+u||lt+u&&s>n+u&&s>r+u||sn||c+ur&&(r+=Zs);var d=Math.atan2(l,s);return d<0&&(d+=Zs),d>=i&&d<=r||d+Zs>=i&&d+Zs<=r}function qs(t,e,n,i,r,o){if(o>e&&o>i||or?s:0}var Ks=Fs.CMD,$s=2*Math.PI;var Js=[-1,-1,-1],Qs=[-1,-1];function tl(t,e,n,i,r,o,a,s,l,u){if(u>e&&u>i&&u>o&&u>s||u1&&(c=void 0,c=Qs[0],Qs[0]=Qs[1],Qs[1]=c),f=Dn(e,i,o,s,Qs[0]),p>1&&(g=Dn(e,i,o,s,Qs[1]))),2===p?ve&&s>i&&s>o||s=0&&c<=1&&(r[l++]=c);else{var u=a*a-4*o*s;if(Tn(u))(c=-a/(2*o))>=0&&c<=1&&(r[l++]=c);else if(u>0){var c,h=mn(u),d=(-a-h)/(2*o);(c=(-a+h)/(2*o))>=0&&c<=1&&(r[l++]=c),d>=0&&d<=1&&(r[l++]=d)}}return l}(e,i,o,s,Js);if(0===l)return 0;var u=En(e,i,o);if(u>=0&&u<=1){for(var c=0,h=Nn(e,i,o,u),d=0;dn||s<-n)return 0;var l=Math.sqrt(n*n-s*s);Js[0]=-l,Js[1]=l;var u=Math.abs(i-r);if(u<1e-4)return 0;if(u>=$s-1e-4){i=0,r=$s;var c=o?1:-1;return a>=Js[0]+t&&a<=Js[1]+t?c:0}if(i>r){var h=i;i=r,r=h}i<0&&(i+=$s,r+=$s);for(var d=0,p=0;p<2;p++){var f=Js[p];if(f+t>a){var g=Math.atan2(s,f);c=o?1:-1;g<0&&(g=$s+g),(g>=i&&g<=r||g+$s>=i&&g+$s<=r)&&(g>Math.PI/2&&g<1.5*Math.PI&&(c=-c),d+=c)}}return d}function il(t,e,n,i,r){for(var o,a,s,l,u=t.data,c=t.len(),h=0,d=0,p=0,f=0,g=0,y=0;y1&&(n||(h+=qs(d,p,f,g,i,r))),m&&(f=d=u[y],g=p=u[y+1]),v){case Ks.M:d=f=u[y++],p=g=u[y++];break;case Ks.L:if(n){if(Ws(d,p,u[y],u[y+1],e,i,r))return!0}else h+=qs(d,p,u[y],u[y+1],i,r)||0;d=u[y++],p=u[y++];break;case Ks.C:if(n){if(Hs(d,p,u[y++],u[y++],u[y++],u[y++],u[y],u[y+1],e,i,r))return!0}else h+=tl(d,p,u[y++],u[y++],u[y++],u[y++],u[y],u[y+1],i,r)||0;d=u[y++],p=u[y++];break;case Ks.Q:if(n){if(Us(d,p,u[y++],u[y++],u[y],u[y+1],e,i,r))return!0}else h+=el(d,p,u[y++],u[y++],u[y],u[y+1],i,r)||0;d=u[y++],p=u[y++];break;case Ks.A:var x=u[y++],_=u[y++],b=u[y++],w=u[y++],S=u[y++],M=u[y++];y+=1;var I=!!(1-u[y++]);o=Math.cos(S)*b+x,a=Math.sin(S)*w+_,m?(f=o,g=a):h+=qs(d,p,o,a,i,r);var T=(i-x)*w/b+x;if(n){if(js(x,_,w,S,S+M,I,e,T,r))return!0}else h+=nl(x,_,w,S,S+M,I,T,r);d=Math.cos(S+M)*b+x,p=Math.sin(S+M)*w+_;break;case Ks.R:if(f=d=u[y++],g=p=u[y++],o=f+u[y++],a=g+u[y++],n){if(Ws(f,g,o,g,e,i,r)||Ws(o,g,o,a,e,i,r)||Ws(o,a,f,a,e,i,r)||Ws(f,a,f,g,e,i,r))return!0}else h+=qs(o,g,o,a,i,r),h+=qs(f,a,f,g,i,r);break;case Ks.Z:if(n){if(Ws(d,p,f,g,e,i,r))return!0}else h+=qs(d,p,f,g,i,r);d=f,p=g}}return n||(s=p,l=g,Math.abs(s-l)<1e-4)||(h+=qs(d,p,f,g,i,r)||0),0!==h}var rl=k({fill:"#000",stroke:null,strokePercent:1,fillOpacity:1,strokeOpacity:1,lineDashOffset:0,lineWidth:1,lineCap:"butt",miterLimit:10,strokeNoScale:!1,strokeFirst:!1},es),ol={style:k({fill:!0,stroke:!0,strokePercent:!0,fillOpacity:!0,strokeOpacity:!0,lineDashOffset:!0,lineWidth:!0,miterLimit:!0},ns.style)},al=Ar.concat(["invisible","culling","z","z2","zlevel","parent"]),sl=function(t){function e(e){return t.call(this,e)||this}var i;return n(e,t),e.prototype.update=function(){var n=this;t.prototype.update.call(this);var i=this.style;if(i.decal){var r=this._decalEl=this._decalEl||new e;r.buildPath===e.prototype.buildPath&&(r.buildPath=function(t){n.buildPath(t,n.shape)}),r.silent=!0;var o=r.style;for(var a in i)o[a]!==i[a]&&(o[a]=i[a]);o.fill=i.fill?i.decal:null,o.decal=null,o.shadowColor=null,i.strokeFirst&&(o.stroke=null);for(var s=0;s.5?mr:e>.2?"#eee":xr}if(t)return xr}return mr},e.prototype.getInsideTextStroke=function(t){var e=this.style.fill;if(X(e)){var n=this.__zr;if(!(!n||!n.isDarkMode())===gi(t,0)<.4)return e}},e.prototype.buildPath=function(t,e,n){},e.prototype.pathUpdated=function(){this.__dirty&=-5},e.prototype.getUpdatedPathProxy=function(t){return!this.path&&this.createPathProxy(),this.path.beginPath(),this.buildPath(this.path,this.shape,t),this.path},e.prototype.createPathProxy=function(){this.path=new Fs(!1)},e.prototype.hasStroke=function(){var t=this.style,e=t.stroke;return!(null==e||"none"===e||!(t.lineWidth>0))},e.prototype.hasFill=function(){var t=this.style.fill;return null!=t&&"none"!==t},e.prototype.getBoundingRect=function(){var t=this._rect,e=this.style,n=!t;if(n){var i=!1;this.path||(i=!0,this.createPathProxy());var r=this.path;(i||4&this.__dirty)&&(r.beginPath(),this.buildPath(r,this.shape,!1),this.pathUpdated()),t=r.getBoundingRect()}if(this._rect=t,this.hasStroke()&&this.path&&this.path.len()>0){var o=this._rectStroke||(this._rectStroke=t.clone());if(this.__dirty||n){o.copy(t);var a=e.strokeNoScale?this.getLineScale():1,s=e.lineWidth;if(!this.hasFill()){var l=this.strokeContainThreshold;s=Math.max(s,null==l?4:l)}a>1e-10&&(o.width+=s/a,o.height+=s/a,o.x-=s/a/2,o.y-=s/a/2)}return o}return t},e.prototype.contain=function(t,e){var n=this.transformCoordToLocal(t,e),i=this.getBoundingRect(),r=this.style;if(t=n[0],e=n[1],i.contain(t,e)){var o=this.path;if(this.hasStroke()){var a=r.lineWidth,s=r.strokeNoScale?this.getLineScale():1;if(s>1e-10&&(this.hasFill()||(a=Math.max(a,this.strokeContainThreshold)),function(t,e,n,i){return il(t,e,!0,n,i)}(o,a/s,t,e)))return!0}if(this.hasFill())return function(t,e,n){return il(t,0,!1,e,n)}(o,t,e)}return!1},e.prototype.dirtyShape=function(){this.__dirty|=4,this._rect&&(this._rect=null),this._decalEl&&this._decalEl.dirtyShape(),this.markRedraw()},e.prototype.dirty=function(){this.dirtyStyle(),this.dirtyShape()},e.prototype.animateShape=function(t){return this.animate("shape",t)},e.prototype.updateDuringAnimation=function(t){"style"===t?this.dirtyStyle():"shape"===t?this.dirtyShape():this.markRedraw()},e.prototype.attrKV=function(e,n){"shape"===e?this.setShape(n):t.prototype.attrKV.call(this,e,n)},e.prototype.setShape=function(t,e){var n=this.shape;return n||(n=this.shape={}),"string"==typeof t?n[t]=e:A(n,t),this.dirtyShape(),this},e.prototype.shapeChanged=function(){return!!(4&this.__dirty)},e.prototype.createStyle=function(t){return mt(rl,t)},e.prototype._innerSaveToNormal=function(e){t.prototype._innerSaveToNormal.call(this,e);var n=this._normalState;e.shape&&!n.shape&&(n.shape=A({},this.shape))},e.prototype._applyStateObj=function(e,n,i,r,o,a){t.prototype._applyStateObj.call(this,e,n,i,r,o,a);var s,l=!(n&&r);if(n&&n.shape?o?r?s=n.shape:(s=A({},i.shape),A(s,n.shape)):(s=A({},r?this.shape:i.shape),A(s,n.shape)):l&&(s=i.shape),s)if(o){this.shape=A({},this.shape);for(var u={},c=F(s),h=0;hu&&(n*=u/(a=n+i),i*=u/a),r+o>u&&(r*=u/(a=r+o),o*=u/a),i+r>c&&(i*=c/(a=i+r),r*=c/a),n+o>c&&(n*=c/(a=n+o),o*=c/a),t.moveTo(s+n,l),t.lineTo(s+u-i,l),0!==i&&t.arc(s+u-i,l+i,i,-Math.PI/2,0),t.lineTo(s+u,l+c-r),0!==r&&t.arc(s+u-r,l+c-r,r,0,Math.PI/2),t.lineTo(s+o,l+c),0!==o&&t.arc(s+o,l+c-o,o,Math.PI/2,Math.PI),t.lineTo(s,l+n),0!==n&&t.arc(s+n,l+n,n,Math.PI,1.5*Math.PI)}(t,e):t.rect(n,i,r,o)},e.prototype.isZeroArea=function(){return!this.shape.width||!this.shape.height},e}(sl);xl.prototype.type="rect";var _l={fill:"#000"},bl={},wl={style:k({fill:!0,stroke:!0,fillOpacity:!0,strokeOpacity:!0,lineWidth:!0,fontSize:!0,lineHeight:!0,width:!0,height:!0,textShadowColor:!0,textShadowBlur:!0,textShadowOffsetX:!0,textShadowOffsetY:!0,backgroundColor:!0,padding:!0,borderColor:!0,borderWidth:!0,borderRadius:!0},ns.style)},Sl=function(t){function e(e){var n=t.call(this)||this;return n.type="text",n._children=[],n._defaultStyle=_l,n.attr(e),n}return n(e,t),e.prototype.childrenRef=function(){return this._children},e.prototype.update=function(){t.prototype.update.call(this),this.styleChanged()&&this._updateSubTexts();for(var e=0;ev&&p){var x=Math.floor(v/d);f=f||y.length>x,m=(y=y.slice(0,x)).length*d}if(r&&c&&null!=g)for(var _=Ba(g,u,e.ellipsis,{minChar:e.truncateMinChar,placeholder:e.placeholder}),b={},w=0;w0,T=0;Tg&&Ua(o,a.substring(g,y),e,f),Ua(o,d[2],e,f,d[1]),g=za.lastIndex}gh){var R=o.lines.length;D>0?(I.tokens=I.tokens.slice(0,D),S(I,C,T),o.lines=o.lines.slice(0,M+1)):o.lines=o.lines.slice(0,M),o.isTruncated=o.isTruncated||o.lines.length=0&&"right"===(C=x[T]).align;)this._placeToken(C,t,b,f,I,"right",y),w-=C.width,I-=C.width,T--;for(M+=(s-(M-p)-(g-I)-w)/2;S<=T;)C=x[S],this._placeToken(C,t,b,f,M+C.width/2,"center",y),M+=C.width,S++;f+=b}},e.prototype._placeToken=function(t,e,n,i,r,o,s){var l=e.rich[t.styleName]||{};l.text=t.text;var u=t.verticalAlign,c=i+n/2;"top"===u?c=i+t.height/2:"bottom"===u&&(c=i+n-t.height/2),!t.isLineHolder&&Nl(l)&&this._renderBackground(l,e,"right"===o?r-t.width:"center"===o?r-t.width/2:r,c-t.height/2,t.width,t.height);var h=!!l.backgroundColor,d=t.textPadding;d&&(r=Ol(r,o,d),c-=t.height/2-d[0]-t.innerHeight/2);var p=this._getOrCreateChild(ul),f=p.createStyle();p.useStyle(f);var g=this._defaultStyle,y=!1,v=0,m=!1,x=Pl("fill"in l?l.fill:"fill"in e?e.fill:(y=!0,g.fill)),_=Ll("stroke"in l?l.stroke:"stroke"in e?e.stroke:h||s||g.autoStroke&&!y?null:(v=2,m=!0,g.stroke)),b=l.textShadowBlur>0||e.textShadowBlur>0;f.text=t.text,f.x=r,f.y=c,b&&(f.shadowBlur=l.textShadowBlur||e.textShadowBlur||0,f.shadowColor=l.textShadowColor||e.textShadowColor||"transparent",f.shadowOffsetX=l.textShadowOffsetX||e.textShadowOffsetX||0,f.shadowOffsetY=l.textShadowOffsetY||e.textShadowOffsetY||0),f.textAlign=o,f.textBaseline="middle",f.font=t.font||a,f.opacity=ot(l.opacity,e.opacity,1),Dl(f,l),_&&(f.lineWidth=ot(l.lineWidth,e.lineWidth,v),f.lineDash=rt(l.lineDash,e.lineDash),f.lineDashOffset=e.lineDashOffset||0,f.stroke=_),x&&(f.fill=x),p.setBoundingRect(Ja(f,t.contentWidth,t.contentHeight,m?0:null))},e.prototype._renderBackground=function(t,e,n,i,r,o){var a,s,l,u=t.backgroundColor,c=t.borderWidth,h=t.borderColor,d=u&&u.image,p=u&&!d,f=t.borderRadius,g=this;if(p||t.lineHeight||c&&h){(a=this._getOrCreateChild(xl)).useStyle(a.createStyle()),a.style.fill=null;var y=a.shape;y.x=n,y.y=i,y.width=r,y.height=o,y.r=f,a.dirtyShape()}if(p)(l=a.style).fill=u||null,l.fillOpacity=rt(t.fillOpacity,1);else if(d){(s=this._getOrCreateChild(dl)).onload=function(){g.dirtyStyle()};var v=s.style;v.image=u.image,v.x=n,v.y=i,v.width=r,v.height=o}c&&h&&((l=a.style).lineWidth=c,l.stroke=h,l.strokeOpacity=rt(t.strokeOpacity,1),l.lineDash=t.borderDash,l.lineDashOffset=t.borderDashOffset||0,a.strokeContainThreshold=0,a.hasFill()&&a.hasStroke()&&(l.strokeFirst=!0,l.lineWidth*=2));var m=(a||s).style;m.shadowBlur=t.shadowBlur||0,m.shadowColor=t.shadowColor||"transparent",m.shadowOffsetX=t.shadowOffsetX||0,m.shadowOffsetY=t.shadowOffsetY||0,m.opacity=ot(t.opacity,e.opacity,1)},e.makeFont=function(t){var e="";return Al(t)&&(e=[t.fontStyle,t.fontWeight,Cl(t.fontSize),t.fontFamily||"sans-serif"].join(" ")),e&&ut(e)||t.textFont||t.font},e}(os),Ml={left:!0,right:1,center:1},Il={top:1,bottom:1,middle:1},Tl=["fontStyle","fontWeight","fontSize","fontFamily"];function Cl(t){return"string"!=typeof t||-1===t.indexOf("px")&&-1===t.indexOf("rem")&&-1===t.indexOf("em")?isNaN(+t)?"12px":t+"px":t}function Dl(t,e){for(var n=0;n=0,o=!1;if(t instanceof sl){var a=Gl(t),s=r&&a.selectFill||a.normalFill,l=r&&a.selectStroke||a.normalStroke;if($l(s)||$l(l)){var u=(i=i||{}).style||{};"inherit"===u.fill?(o=!0,i=A({},i),(u=A({},u)).fill=s):!$l(u.fill)&&$l(s)?(o=!0,i=A({},i),(u=A({},u)).fill=vi(s)):!$l(u.stroke)&&$l(l)&&(o||(i=A({},i),u=A({},u)),u.stroke=vi(l)),i.style=u}}if(i&&null==i.z2){o||(i=A({},i));var c=t.z2EmphasisLift;i.z2=t.z2+(null!=c?c:Ul)}return i}(this,0,e,n);if("blur"===t)return function(t,e,n){var i=P(t.currentStates,e)>=0,r=t.style.opacity,o=i?null:function(t,e,n,i){for(var r=t.style,o={},a=0;a0){var o={dataIndex:r,seriesIndex:t.seriesIndex};null!=i&&(o.dataType=i),e.push(o)}}))})),e}function Iu(t,e,n){Lu(t,!0),au(t,uu),Cu(t,e,n)}function Tu(t,e,n,i){i?function(t){Lu(t,!1)}(t):Iu(t,e,n)}function Cu(t,e,n){var i=zl(t);null!=e?(i.focus=e,i.blurScope=n):i.focus&&(i.focus=null)}var Du=["emphasis","blur","select"],Au={itemStyle:"getItemStyle",lineStyle:"getLineStyle",areaStyle:"getAreaStyle"};function ku(t,e,n,i){n=n||"itemStyle";for(var r=0;r1&&(a*=Gu(f),s*=Gu(f));var g=(r===o?-1:1)*Gu((a*a*(s*s)-a*a*(p*p)-s*s*(d*d))/(a*a*(p*p)+s*s*(d*d)))||0,y=g*a*p/s,v=g*-s*d/a,m=(t+n)/2+Wu(h)*y-Fu(h)*v,x=(e+i)/2+Fu(h)*y+Wu(h)*v,_=Xu([1,0],[(d-y)/a,(p-v)/s]),b=[(d-y)/a,(p-v)/s],w=[(-1*d-y)/a,(-1*p-v)/s],S=Xu(b,w);if(Yu(b,w)<=-1&&(S=Hu),Yu(b,w)>=1&&(S=0),S<0){var M=Math.round(S/Hu*1e6)/1e6;S=2*Hu+M%2*Hu}c.addData(u,m,x,a,s,_,S,h,o)}var ju=/([mlvhzcqtsa])([^mlvhzcqtsa]*)/gi,qu=/-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;var Ku=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.applyTransform=function(t){},e}(sl);function $u(t){return null!=t.setData}function Ju(t,e){var n=function(t){var e=new Fs;if(!t)return e;var n,i=0,r=0,o=i,a=r,s=Fs.CMD,l=t.match(ju);if(!l)return e;for(var u=0;uk*k+L*L&&(M=T,I=C),{cx:M,cy:I,x0:-c,y0:-h,x1:M*(r/b-1),y1:I*(r/b-1)}}function vc(t,e){var n,i=pc(e.r,0),r=pc(e.r0||0,0),o=i>0;if(o||r>0){if(o||(i=r,r=0),r>i){var a=i;i=r,r=a}var s=e.startAngle,l=e.endAngle;if(!isNaN(s)&&!isNaN(l)){var u=e.cx,c=e.cy,h=!!e.clockwise,d=hc(l-s),p=d>ac&&d%ac;if(p>gc&&(d=p),i>gc)if(d>ac-gc)t.moveTo(u+i*lc(s),c+i*sc(s)),t.arc(u,c,i,s,l,!h),r>gc&&(t.moveTo(u+r*lc(l),c+r*sc(l)),t.arc(u,c,r,l,s,h));else{var f=void 0,g=void 0,y=void 0,v=void 0,m=void 0,x=void 0,_=void 0,b=void 0,w=void 0,S=void 0,M=void 0,I=void 0,T=void 0,C=void 0,D=void 0,A=void 0,k=i*lc(s),L=i*sc(s),P=r*lc(l),O=r*sc(l),R=d>gc;if(R){var N=e.cornerRadius;N&&(n=function(t){var e;if(U(t)){var n=t.length;if(!n)return t;e=1===n?[t[0],t[0],0,0]:2===n?[t[0],t[0],t[1],t[1]]:3===n?t.concat(t[2]):t}else e=[t,t,t,t];return e}(N),f=n[0],g=n[1],y=n[2],v=n[3]);var z=hc(i-r)/2;if(m=fc(z,y),x=fc(z,v),_=fc(z,f),b=fc(z,g),M=w=pc(m,x),I=S=pc(_,b),(w>gc||S>gc)&&(T=i*lc(l),C=i*sc(l),D=r*lc(s),A=r*sc(s),dgc){var Y=fc(y,M),X=fc(v,M),Z=yc(D,A,k,L,i,Y,h),j=yc(T,C,P,O,i,X,h);t.moveTo(u+Z.cx+Z.x0,c+Z.cy+Z.y0),M0&&t.arc(u+Z.cx,c+Z.cy,Y,cc(Z.y0,Z.x0),cc(Z.y1,Z.x1),!h),t.arc(u,c,i,cc(Z.cy+Z.y1,Z.cx+Z.x1),cc(j.cy+j.y1,j.cx+j.x1),!h),X>0&&t.arc(u+j.cx,c+j.cy,X,cc(j.y1,j.x1),cc(j.y0,j.x0),!h))}else t.moveTo(u+k,c+L),t.arc(u,c,i,s,l,!h);else t.moveTo(u+k,c+L);if(r>gc&&R)if(I>gc){Y=fc(f,I),Z=yc(P,O,T,C,r,-(X=fc(g,I)),h),j=yc(k,L,D,A,r,-Y,h);t.lineTo(u+Z.cx+Z.x0,c+Z.cy+Z.y0),I0&&t.arc(u+Z.cx,c+Z.cy,X,cc(Z.y0,Z.x0),cc(Z.y1,Z.x1),!h),t.arc(u,c,r,cc(Z.cy+Z.y1,Z.cx+Z.x1),cc(j.cy+j.y1,j.cx+j.x1),h),Y>0&&t.arc(u+j.cx,c+j.cy,Y,cc(j.y1,j.x1),cc(j.y0,j.x0),!h))}else t.lineTo(u+P,c+O),t.arc(u,c,r,l,s,h);else t.lineTo(u+P,c+O)}else t.moveTo(u,c);t.closePath()}}}var mc=function(){this.cx=0,this.cy=0,this.r0=0,this.r=0,this.startAngle=0,this.endAngle=2*Math.PI,this.clockwise=!0,this.cornerRadius=0},xc=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.getDefaultShape=function(){return new mc},e.prototype.buildPath=function(t,e){vc(t,e)},e.prototype.isZeroArea=function(){return this.shape.startAngle===this.shape.endAngle||this.shape.r===this.shape.r0},e}(sl);xc.prototype.type="sector";var _c=function(){this.cx=0,this.cy=0,this.r=0,this.r0=0},bc=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.getDefaultShape=function(){return new _c},e.prototype.buildPath=function(t,e){var n=e.cx,i=e.cy,r=2*Math.PI;t.moveTo(n+e.r,i),t.arc(n,i,e.r,0,r,!1),t.moveTo(n+e.r0,i),t.arc(n,i,e.r0,0,r,!0)},e}(sl);function wc(t,e,n){var i=e.smooth,r=e.points;if(r&&r.length>=2){if(i){var o=function(t,e,n,i){var r,o,a,s,l=[],u=[],c=[],h=[];if(i){a=[1/0,1/0],s=[-1/0,-1/0];for(var d=0,p=t.length;dUc[1]){if(r=!1,Yc.negativeSize||n)return r;var s=Wc(Uc[0]-Hc[1]),l=Wc(Hc[0]-Uc[1]);Gc(s,l)>Zc.len()&&(s=l||!Yc.bidirectional)&&(Ae.scale(Xc,a,-l*i),Yc.useDir&&Yc.calcDirMTV()))}}return r},t.prototype._getProjMinMaxOnAxis=function(t,e,n){for(var i=this._axes[t],r=this._origin,o=e[0].dot(i)+r[t],a=o,s=o,l=1;l0){var h={duration:c.duration,delay:c.delay||0,easing:c.easing,done:o,force:!!o||!!a,setToFinal:!u,scope:t,during:a};l?e.animateFrom(n,h):e.animateTo(n,h)}else e.stopAnimation(),!l&&e.attr(n),a&&a(1),o&&o()}function th(t,e,n,i,r,o){Qc("update",t,e,n,i,r,o)}function eh(t,e,n,i,r,o){Qc("enter",t,e,n,i,r,o)}function nh(t){if(!t.__zr)return!0;for(var e=0;efo(o[1])?o[0]>0?"right":"left":o[1]>0?"bottom":"top"}function Ih(t){return!t.isGroup}function Th(t,e,n){if(t&&e){var i,r=(i={},t.traverse((function(t){Ih(t)&&t.anid&&(i[t.anid]=t)})),i);e.traverse((function(t){if(Ih(t)&&t.anid){var e=r[t.anid];if(e){var i=o(t);t.attr(o(e)),th(t,i,n,zl(t).dataIndex)}}}))}function o(t){var e={x:t.x,y:t.y,rotation:t.rotation};return function(t){return null!=t.shape}(t)&&(e.shape=T(t.shape)),e}}function Ch(t,e){return E(t,(function(t){var n=t[0];n=po(n,e.x),n=ho(n,e.x+e.width);var i=t[1];return i=po(i,e.y),[n,i=ho(i,e.y+e.height)]}))}function Dh(t,e){var n=po(t.x,e.x),i=ho(t.x+t.width,e.x+e.width),r=po(t.y,e.y),o=ho(t.y+t.height,e.y+e.height);if(i>=n&&o>=r)return{x:n,y:r,width:i-n,height:o-r}}function Ah(t,e,n){var i=A({rectHover:!0},e),r=i.style={strokeNoScale:!0};if(n=n||{x:-1,y:-1,width:2,height:2},t)return 0===t.indexOf("image://")?(r.image=t.slice(8),k(r,n),new dl(i)):gh(t.replace("path://",""),i,n,"center")}function kh(t,e,n,i,r){for(var o=0,a=r[r.length-1];o=-1e-6)return!1;var f=t-r,g=e-o,y=Ph(f,g,u,c)/p;if(y<0||y>1)return!1;var v=Ph(f,g,h,d)/p;return!(v<0||v>1)}function Ph(t,e,n,i){return t*i-n*e}function Oh(t,e,n,i,r){return null==e||(j(e)?Rh[0]=Rh[1]=Rh[2]=Rh[3]=e:(Rh[0]=e[0],Rh[1]=e[1],Rh[2]=e[2],Rh[3]=e[3]),i&&(Rh[0]=po(0,Rh[0]),Rh[1]=po(0,Rh[1]),Rh[2]=po(0,Rh[2]),Rh[3]=po(0,Rh[3])),n&&(Rh[0]=-Rh[0],Rh[1]=-Rh[1],Rh[2]=-Rh[2],Rh[3]=-Rh[3]),Nh(t,Rh,"x","width",3,1,r&&r[0]||0),Nh(t,Rh,"y","height",0,2,r&&r[1]||0)),t}var Rh=[0,0,0,0];function Nh(t,e,n,i,r,o,a){var s=e[o]+e[r],l=t[i];t[i]+=s,a=po(0,ho(a,l)),t[i]=0?-e[r]:e[o]>=0?l+e[o]:fo(s)>1e-8?(l-a)*e[r]/s:0):t[n]-=e[r]}function zh(t){var e=t.itemTooltipOption,n=t.componentModel,i=t.itemName,r=X(e)?{formatter:e}:e,o=n.mainType,a=n.componentIndex,s={componentType:o,name:i,$vars:["name"]};s[o+"Index"]=a;var l=t.formatterParamsExtra;l&&z(F(l),(function(t){_t(s,t)||(s[t]=l[t],s.$vars.push(t))}));var u=zl(t.el);u.componentMainType=o,u.componentIndex=a,u.tooltipConfig={name:i,option:k({content:i,encodeHTMLContent:!0,formatterParams:s},r)}}function Eh(t,e){var n;t.isGroup&&(n=e(t)),n||t.traverse(e)}function Bh(t,e){if(t)if(U(t))for(var n=0;ne&&(e=i),ie&&(n=e=0),{min:n,max:e}}function Yh(t,e,n){Xh(t,e,n,-1/0)}function Xh(t,e,n,i){if(t.ignoreModelZ)return i;var r=t.getTextContent(),o=t.getTextGuideLine();if(t.isGroup)for(var a=t.childrenRef(),s=0;s-1?Td:Dd;function Pd(t,e){t=t.toUpperCase(),kd[t]=new wd(e),Ad[t]=e}function Od(t){return kd[t]}Pd(Cd,{time:{month:["January","February","March","April","May","June","July","August","September","October","November","December"],monthAbbr:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayOfWeek:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayOfWeekAbbr:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},legend:{selector:{all:"All",inverse:"Inv"}},toolbox:{brush:{title:{rect:"Box Select",polygon:"Lasso Select",lineX:"Horizontally Select",lineY:"Vertically Select",keep:"Keep Selections",clear:"Clear Selections"}},dataView:{title:"Data View",lang:["Data View","Close","Refresh"]},dataZoom:{title:{zoom:"Zoom",back:"Zoom Reset"}},magicType:{title:{line:"Switch to Line Chart",bar:"Switch to Bar Chart",stack:"Stack",tiled:"Tile"}},restore:{title:"Restore"},saveAsImage:{title:"Save as Image",lang:["Right Click to Save Image"]}},series:{typeNames:{pie:"Pie chart",bar:"Bar chart",line:"Line chart",scatter:"Scatter plot",effectScatter:"Ripple scatter plot",radar:"Radar chart",tree:"Tree",treemap:"Treemap",boxplot:"Boxplot",candlestick:"Candlestick",k:"K line chart",heatmap:"Heat map",map:"Map",parallel:"Parallel coordinate map",lines:"Line graph",graph:"Relationship graph",sankey:"Sankey diagram",funnel:"Funnel chart",gauge:"Gauge",pictorialBar:"Pictorial bar",themeRiver:"Theme River Map",sunburst:"Sunburst",custom:"Custom chart",chart:"Chart"}},aria:{general:{withTitle:'This is a chart about "{title}"',withoutTitle:"This is a chart"},series:{single:{prefix:"",withName:" with type {seriesType} named {seriesName}.",withoutName:" with type {seriesType}."},multiple:{prefix:". It consists of {seriesCount} series count.",withName:" The {seriesId} series is a {seriesType} representing {seriesName}.",withoutName:" The {seriesId} series is a {seriesType}.",separator:{middle:"",end:""}}},data:{allData:"The data is as follows: ",partialData:"The first {displayCnt} items are: ",withName:"the data for {name} is {value}",withoutName:"{value}",separator:{middle:", ",end:". "}}}}),Pd(Td,{time:{month:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthAbbr:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayOfWeek:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayOfWeekAbbr:["日","一","二","三","四","五","六"]},legend:{selector:{all:"全选",inverse:"反选"}},toolbox:{brush:{title:{rect:"矩形选择",polygon:"圈选",lineX:"横向选择",lineY:"纵向选择",keep:"保持选择",clear:"清除选择"}},dataView:{title:"数据视图",lang:["数据视图","关闭","刷新"]},dataZoom:{title:{zoom:"区域缩放",back:"区域缩放还原"}},magicType:{title:{line:"切换为折线图",bar:"切换为柱状图",stack:"切换为堆叠",tiled:"切换为平铺"}},restore:{title:"还原"},saveAsImage:{title:"保存为图片",lang:["右键另存为图片"]}},series:{typeNames:{pie:"饼图",bar:"柱状图",line:"折线图",scatter:"散点图",effectScatter:"涟漪散点图",radar:"雷达图",tree:"树图",treemap:"矩形树图",boxplot:"箱型图",candlestick:"K线图",k:"K线图",heatmap:"热力图",map:"地图",parallel:"平行坐标图",lines:"线图",graph:"关系图",sankey:"桑基图",funnel:"漏斗图",gauge:"仪表盘图",pictorialBar:"象形柱图",themeRiver:"主题河流图",sunburst:"旭日图",custom:"自定义图表",chart:"图表"}},aria:{general:{withTitle:"这是一个关于“{title}”的图表。",withoutTitle:"这是一个图表,"},series:{single:{prefix:"",withName:"图表类型是{seriesType},表示{seriesName}。",withoutName:"图表类型是{seriesType}。"},multiple:{prefix:"它由{seriesCount}个图表系列组成。",withName:"第{seriesId}个系列是一个表示{seriesName}的{seriesType},",withoutName:"第{seriesId}个系列是一个{seriesType},",separator:{middle:";",end:"。"}}},data:{allData:"其数据是——",partialData:"其中,前{displayCnt}项是——",withName:"{name}的数据是{value}",withoutName:"{value}",separator:{middle:",",end:""}}}});var Rd=null;function Nd(){return Rd}var zd=1e3,Ed=6e4,Bd=36e5,Vd=864e5,Gd=31536e6,Fd={year:/({yyyy}|{yy})/,month:/({MMMM}|{MMM}|{MM}|{M})/,day:/({dd}|{d})/,hour:/({HH}|{H}|{hh}|{h})/,minute:/({mm}|{m})/,second:/({ss}|{s})/,millisecond:/({SSS}|{S})/},Wd={year:"{yyyy}",month:"{MMM}",day:"{d}",hour:"{HH}:{mm}",minute:"{HH}:{mm}",second:"{HH}:{mm}:{ss}",millisecond:"{HH}:{mm}:{ss} {SSS}"},Hd="{yyyy}-{MM}-{dd}",Ud={year:"{yyyy}",month:"{yyyy}-{MM}",day:Hd,hour:Hd+" "+Wd.hour,minute:Hd+" "+Wd.minute,second:Hd+" "+Wd.second,millisecond:"{yyyy}-{MM}-{dd} {HH}:{mm}:{ss} {SSS}"},Yd=["year","month","day","hour","minute","second","millisecond"],Xd=["year","half-year","quarter","month","week","half-week","day","half-day","quarter-day","hour","minute","second","millisecond"];function Zd(t){return X(t)||Y(t)?t:function(t){t=t||{};var e={},n=!0;return z(Yd,(function(e){n&&(n=null==t[e])})),z(Yd,(function(i,r){var o=t[i];e[i]={};for(var a=null,s=r;s>=0;s--){var l=Yd[s],u=q(o)&&!U(o)?o[l]:o,c=void 0;U(u)?a=(c=u.slice())[0]||"":X(u)?c=[a=u]:(null==a?a=Wd[i]:Fd[l].test(a)||(a=e[l][l][0]+" "+a),c=[a],n&&(c[1]="{primary|"+a+"}")),e[i][l]=c}})),e}(t)}function jd(t,e){return"0000".substr(0,e-(t+="").length)+t}function qd(t){switch(t){case"half-year":case"quarter":return"month";case"week":case"half-week":return"day";case"half-day":case"quarter-day":return"hour";default:return t}}function Kd(t){return t===qd(t)}function $d(t,e,n,i){var r=Ao(t),o=r[tp(n)](),a=r[ep(n)]()+1,s=Math.floor((a-1)/3)+1,l=r[np(n)](),u=r["get"+(n?"UTC":"")+"Day"](),c=r[ip(n)](),h=(c-1)%12+1,d=r[rp(n)](),p=r[op(n)](),f=r[ap(n)](),g=c>=12?"pm":"am",y=g.toUpperCase(),v=(i instanceof wd?i:Od(i||Ld)||kd[Dd]).getModel("time"),m=v.get("month"),x=v.get("monthAbbr"),_=v.get("dayOfWeek"),b=v.get("dayOfWeekAbbr");return(e||"").replace(/{a}/g,g+"").replace(/{A}/g,y+"").replace(/{yyyy}/g,o+"").replace(/{yy}/g,jd(o%100+"",2)).replace(/{Q}/g,s+"").replace(/{MMMM}/g,m[a-1]).replace(/{MMM}/g,x[a-1]).replace(/{MM}/g,jd(a,2)).replace(/{M}/g,a+"").replace(/{dd}/g,jd(l,2)).replace(/{d}/g,l+"").replace(/{eeee}/g,_[u]).replace(/{ee}/g,b[u]).replace(/{e}/g,u+"").replace(/{HH}/g,jd(c,2)).replace(/{H}/g,c+"").replace(/{hh}/g,jd(h+"",2)).replace(/{h}/g,h+"").replace(/{mm}/g,jd(d,2)).replace(/{m}/g,d+"").replace(/{ss}/g,jd(p,2)).replace(/{s}/g,p+"").replace(/{SSS}/g,jd(f,3)).replace(/{S}/g,f+"")}function Jd(t,e){var n=Ao(t),i=n[ep(e)]()+1,r=n[np(e)](),o=n[ip(e)](),a=n[rp(e)](),s=n[op(e)](),l=0===n[ap(e)](),u=l&&0===s,c=u&&0===a,h=c&&0===o,d=h&&1===r;return d&&1===i?"year":d?"month":h?"day":c?"hour":u?"minute":l?"second":"millisecond"}function Qd(t,e,n){switch(e){case"year":t[lp(n)](0);case"month":t[up(n)](1);case"day":t[cp(n)](0);case"hour":t[hp(n)](0);case"minute":t[dp(n)](0);case"second":t[pp(n)](0)}return t}function tp(t){return t?"getUTCFullYear":"getFullYear"}function ep(t){return t?"getUTCMonth":"getMonth"}function np(t){return t?"getUTCDate":"getDate"}function ip(t){return t?"getUTCHours":"getHours"}function rp(t){return t?"getUTCMinutes":"getMinutes"}function op(t){return t?"getUTCSeconds":"getSeconds"}function ap(t){return t?"getUTCMilliseconds":"getMilliseconds"}function sp(t){return t?"setUTCFullYear":"setFullYear"}function lp(t){return t?"setUTCMonth":"setMonth"}function up(t){return t?"setUTCDate":"setDate"}function cp(t){return t?"setUTCHours":"setHours"}function hp(t){return t?"setUTCMinutes":"setMinutes"}function dp(t){return t?"setUTCSeconds":"setSeconds"}function pp(t){return t?"setUTCMilliseconds":"setMilliseconds"}function fp(t){if(!zo(t))return X(t)?t:"-";var e=(t+"").split(".");return e[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(e.length>1?"."+e[1]:"")}function gp(t,e){return t=(t||"").toLowerCase().replace(/-(.)/g,(function(t,e){return e.toUpperCase()})),e&&t&&(t=t.charAt(0).toUpperCase()+t.slice(1)),t}var yp=st;function vp(t,e,n){function i(t){return t&&ut(t)?t:"-"}function r(t){return!(null==t||isNaN(t)||!isFinite(t))}var o="time"===e,a=t instanceof Date;if(o||a){var s=o?Ao(t):t;if(!isNaN(+s))return $d(s,"{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}",n);if(a)return"-"}if("ordinal"===e)return Z(t)?i(t):j(t)&&r(t)?t+"":"-";var l=No(t);return r(l)?fp(l):Z(t)?i(t):"boolean"==typeof t?t+"":"-"}var mp=["a","b","c","d","e","f","g"],xp=function(t,e){return"{"+t+(null==e?"":e)+"}"};function _p(t,e,n){U(e)||(e=[e]);var i=e.length;if(!i)return"";for(var r=e[0].$vars||[],o=0;o':'':{renderMode:o,content:"{"+(n.markerId||"markerX")+"|} ",style:"subItem"===r?{width:4,height:4,borderRadius:2,backgroundColor:i}:{width:10,height:10,borderRadius:5,backgroundColor:i}}:""}function wp(t,e){return e=e||"transparent",X(t)?t:q(t)&&t.colorStops&&(t.colorStops[0]||{}).color||e}function Sp(t,e){if("_blank"===e||"blank"===e){var n=window.open();n.opener=null,n.location.href=t}else window.open(t,e)}var Mp={},Ip={},Tp=function(){function t(){this._normalMasterList=[],this._nonSeriesBoxMasterList=[]}return t.prototype.create=function(t,e){function n(n,i){var r=[];return z(n,(function(n,i){var o=n.create(t,e);r=r.concat(o||[])})),r}this._nonSeriesBoxMasterList=n(Mp,!0),this._normalMasterList=n(Ip,!1)},t.prototype.update=function(t,e){z(this._normalMasterList,(function(n){n.update&&n.update(t,e)}))},t.prototype.getCoordinateSystems=function(){return this._normalMasterList.concat(this._nonSeriesBoxMasterList)},t.register=function(t,e){"matrix"!==t&&"calendar"!==t?Ip[t]=e:Mp[t]=e},t.get=function(t){return Ip[t]||Mp[t]},t}();var Cp=1,Dp=2;var Ap=yt();var kp=0,Lp=1,Pp=2;function Op(t,e){var n=t.getShallow("coordinateSystem"),i=t.getShallow("coordinateSystemUsage",!0),r=kp;if(n){var o="series"===t.mainType;null==i&&(i=o?"data":"box"),"data"===i?(r=Lp,o||(r=kp)):"box"===i&&(r=Pp,o||function(t){return!!Mp[t]}(n)||(r=kp))}return{coordSysType:n,kind:r}}function Rp(t){var e=t.targetModel,n=t.coordSysType,i=t.coordSysProvider,r=t.isDefaultDataCoordSys;t.allowNotFound;var o=Op(e),a=o.kind,s=o.coordSysType;if(r&&a!==Lp&&(a=Lp,s=n),a===kp||s!==n)return!1;var l=i(n,e);return!!l&&(a===Lp?e.coordinateSystem=l:e.boxCoordinateSystem=l,!0)}var Np=function(t,e){var n=e.getReferringComponents(t,ha).models[0];return n&&n.coordinateSystem},zp=z,Ep=["left","right","top","bottom","width","height"],Bp=[["width","left","right"],["height","top","bottom"]];function Vp(t,e,n,i,r){var o=0,a=0;null==i&&(i=1/0),null==r&&(r=1/0);var s=0;e.eachChild((function(l,u){var c,h,d=l.getBoundingRect(),p=e.childAt(u+1),f=p&&p.getBoundingRect();if("horizontal"===t){var g=d.width+(f?-f.x+d.x:0);(c=o+g)>i||l.newline?(o=0,c=g,a+=s+n,s=d.height):s=Math.max(s,d.height)}else{var y=d.height+(f?-f.y+d.y:0);(h=a+y)>r||l.newline?(o+=s+n,a=0,h=y,s=d.width):s=Math.max(s,d.width)}l.newline||(l.x=o,l.y=a,l.markRedraw(),"horizontal"===t?o=c+n:a=h+n)}))}var Gp=Vp;H(Vp,"vertical"),H(Vp,"horizontal");function Fp(t,e){return{left:t.getShallow("left",e),top:t.getShallow("top",e),right:t.getShallow("right",e),bottom:t.getShallow("bottom",e),width:t.getShallow("width",e),height:t.getShallow("height",e)}}function Wp(t,e){var n=function(t,e){var n,i,r=Xp(t,e,{enableLayoutOnlyByCenter:!0}),o=t.getBoxLayoutParams();if(r.type===Yp.point)i=r.refPoint,n=Hp(o,{width:e.getWidth(),height:e.getHeight()});else{var a=t.get("center"),s=U(a)?a:[a,a];n=Hp(o,r.refContainer),i=r.boxCoordFrom===Dp?r.refPoint:[yo(s[0],n.width)+n.x,yo(s[1],n.height)+n.y]}return{viewRect:n,center:i}}(t,e),i=n.viewRect,r=n.center,o=t.get("radius");U(o)||(o=[0,o]);var a=yo(i.width,e.getWidth()),s=yo(i.height,e.getHeight()),l=Math.min(a,s),u=yo(o[0],l/2),c=yo(o[1],l/2);return{cx:r[0],cy:r[1],r0:u,r:c,viewRect:i}}function Hp(t,e,n){n=yp(n||0);var i=e.width,r=e.height,o=yo(t.left,i),a=yo(t.top,r),s=yo(t.right,i),l=yo(t.bottom,r),u=yo(t.width,i),c=yo(t.height,r),h=n[2]+n[0],d=n[1]+n[3],p=t.aspect;switch(isNaN(u)&&(u=i-s-d-o),isNaN(c)&&(c=r-l-h-a),null!=p&&(isNaN(u)&&isNaN(c)&&(p>i/r?u=.8*i:c=.8*r),isNaN(u)&&(u=p*c),isNaN(c)&&(c=u/p)),isNaN(o)&&(o=i-s-u-d),isNaN(a)&&(a=r-l-c-h),t.left||t.right){case"center":o=i/2-u/2-n[3];break;case"right":o=i-u-d}switch(t.top||t.bottom){case"middle":case"center":a=r/2-c/2-n[0];break;case"bottom":a=r-c-h}o=o||0,a=a||0,isNaN(u)&&(u=i-d-o-(s||0)),isNaN(c)&&(c=r-h-a-(l||0));var f=new He((e.x||0)+o+n[3],(e.y||0)+a+n[0],u,c);return f.margin=n,f}function Up(t,e,n){var i=t.getShallow("preserveAspect",!0);if(!i)return e;var r=e.width/e.height;if(Math.abs(Math.atan(n)-Math.atan(r))<1e-9)return e;var o=t.getShallow("preserveAspectAlign",!0),a=t.getShallow("preserveAspectVerticalAlign",!0),s={width:e.width,height:e.height},l="cover"===i;return r>n&&!l||r=2)return o;for(var c=0;c=0;a--)o=C(o,n[a],!0);e.defaultOption=o}return e.defaultOption},e.prototype.getReferringComponents=function(t,e){var n=t+"Index",i=t+"Id";return pa(this.ecModel,t,{index:this.get(n,!0),id:this.get(i,!0)},e)},e.prototype.getBoxLayoutParams=function(){return Fp(this,!1)},e.prototype.getZLevelKey=function(){return""},e.prototype.setZLevel=function(t){this.option.zlevel=t},e.protoInitialize=((i=e.prototype).type="component",i.id="",i.name="",i.mainType="",i.subType="",void(i.componentIndex=0)),e}(wd);Sa(Qp,wd),Ca(Qp),function(t){var e={};t.registerSubTypeDefaulter=function(t,n){var i=ba(t);e[i.main]=n},t.determineSubType=function(n,i){var r=i.type;if(!r){var o=ba(n).main;t.hasSubTypes(n)&&e[o]&&(r=e[o](i))}return r}}(Qp),function(t,e){function n(t,e){return t[e]||(t[e]={predecessor:[],successor:[]}),t[e]}t.topologicalTravel=function(t,i,r,o){if(t.length){var a=function(t){var i={},r=[];return z(t,(function(o){var a=n(i,o),s=function(t,e){var n=[];return z(t,(function(t){P(e,t)>=0&&n.push(t)})),n}(a.originalDeps=e(o),t);a.entryCount=s.length,0===a.entryCount&&r.push(o),z(s,(function(t){P(a.predecessor,t)<0&&a.predecessor.push(t);var e=n(i,t);P(e.successor,t)<0&&e.successor.push(o)}))})),{graph:i,noEntryList:r}}(i),s=a.graph,l=a.noEntryList,u={};for(z(t,(function(t){u[t]=!0}));l.length;){var c=l.pop(),h=s[c],d=!!u[c];d&&(r.call(o,c,h.originalDeps.slice()),delete u[c]),z(h.successor,d?f:p)}z(u,(function(){var t="";throw new Error(t)}))}function p(t){s[t].entryCount--,0===s[t].entryCount&&l.push(t)}function f(t){u[t]=!0,p(t)}}}(Qp,(function(t){var e=[];z(Qp.getClassesByMainType(t),(function(t){e=e.concat(t.dependencies||t.prototype.dependencies||[])})),e=E(e,(function(t){return ba(t).main})),"dataset"!==t&&P(e,"dataset")<=0&&e.unshift("dataset");return e}));var tf={color:{},darkColor:{},size:{}},ef=tf.color={theme:["#5070dd","#b6d634","#505372","#ff994d","#0ca8df","#ffd10a","#fb628b","#785db0","#3fbe95"],neutral00:"#fff",neutral05:"#f4f7fd",neutral10:"#e8ebf0",neutral15:"#dbdee4",neutral20:"#cfd2d7",neutral25:"#c3c5cb",neutral30:"#b7b9be",neutral35:"#aaacb2",neutral40:"#9ea0a5",neutral45:"#929399",neutral50:"#86878c",neutral55:"#797b7f",neutral60:"#6d6e73",neutral65:"#616266",neutral70:"#54555a",neutral75:"#48494d",neutral80:"#3c3c41",neutral85:"#303034",neutral90:"#232328",neutral95:"#17171b",neutral99:"#000",accent05:"#eff1f9",accent10:"#e0e4f2",accent15:"#d0d6ec",accent20:"#c0c9e6",accent25:"#b1bbdf",accent30:"#a1aed9",accent35:"#91a0d3",accent40:"#8292cc",accent45:"#7285c6",accent50:"#6578ba",accent55:"#5c6da9",accent60:"#536298",accent65:"#4a5787",accent70:"#404c76",accent75:"#374165",accent80:"#2e3654",accent85:"#252b43",accent90:"#1b2032",accent95:"#121521",transparent:"rgba(0,0,0,0)",highlight:"rgba(255,231,130,0.8)"};for(var nf in A(ef,{primary:ef.neutral80,secondary:ef.neutral70,tertiary:ef.neutral60,quaternary:ef.neutral50,disabled:ef.neutral20,border:ef.neutral30,borderTint:ef.neutral20,borderShade:ef.neutral40,background:ef.neutral05,backgroundTint:"rgba(234,237,245,0.5)",backgroundTransparent:"rgba(255,255,255,0)",backgroundShade:ef.neutral10,shadow:"rgba(0,0,0,0.2)",shadowTint:"rgba(129,130,136,0.2)",axisLine:ef.neutral70,axisLineTint:ef.neutral40,axisTick:ef.neutral70,axisTickMinor:ef.neutral60,axisLabel:ef.neutral70,axisSplitLine:ef.neutral15,axisMinorSplitLine:ef.neutral05}),ef)if(ef.hasOwnProperty(nf)){var rf=ef[nf];"theme"===nf?tf.darkColor.theme=ef.theme.slice():"highlight"===nf?tf.darkColor.highlight="rgba(255,231,130,0.4)":0===nf.indexOf("accent")?tf.darkColor[nf]=di(rf,null,(function(t){return.5*t}),(function(t){return Math.min(1,1.3-t)})):tf.darkColor[nf]=di(rf,null,(function(t){return.9*t}),(function(t){return 1-Math.pow(t,1.5)}))}tf.size={xxs:2,xs:5,s:10,m:15,l:20,xl:30,xxl:40,xxxl:50};var of="";"undefined"!=typeof navigator&&(of=navigator.platform||"");var af="rgba(0, 0, 0, 0.2)",sf=tf.color.theme[0],lf=di(sf,null,null,.9),uf={darkMode:"auto",colorBy:"series",color:tf.color.theme,gradientColor:[lf,sf],aria:{decal:{decals:[{color:af,dashArrayX:[1,0],dashArrayY:[2,5],symbolSize:1,rotation:Math.PI/6},{color:af,symbol:"circle",dashArrayX:[[8,8],[0,8,8,0]],dashArrayY:[6,0],symbolSize:.8},{color:af,dashArrayX:[1,0],dashArrayY:[4,3],rotation:-Math.PI/4},{color:af,dashArrayX:[[6,6],[0,6,6,0]],dashArrayY:[6,0]},{color:af,dashArrayX:[[1,0],[1,6]],dashArrayY:[1,0,6,0],rotation:Math.PI/4},{color:af,symbol:"triangle",dashArrayX:[[9,9],[0,9,9,0]],dashArrayY:[7,2],symbolSize:.75}]}},textStyle:{fontFamily:of.match(/^Win/)?"Microsoft YaHei":"sans-serif",fontSize:12,fontStyle:"normal",fontWeight:"normal"},blendMode:null,stateAnimation:{duration:300,easing:"cubicOut"},animation:"auto",animationDuration:1e3,animationDurationUpdate:500,animationEasing:"cubicInOut",animationEasingUpdate:"cubicInOut",animationThreshold:2e3,progressiveThreshold:3e3,progressive:400,hoverLayerThreshold:3e3,useUTC:!1},cf=yt(["tooltip","label","itemName","itemId","itemGroupId","itemChildGroupId","seriesName"]),hf="original",df="arrayRows",pf="objectRows",ff="keyedColumns",gf="typedArray",yf="unknown",vf="column",mf="row",xf=1,_f=2,bf=3,wf=sa();function Sf(t,e,n){var i={},r=If(e);if(!r||!t)return i;var o,a,s=[],l=[],u=e.ecModel,c=wf(u).datasetMap,h=r.uid+"_"+n.seriesLayoutBy;z(t=t.slice(),(function(e,n){var r=q(e)?e:t[n]={name:e};"ordinal"===r.type&&null==o&&(o=n,a=f(r)),i[r.name]=[]}));var d=c.get(h)||c.set(h,{categoryWayDim:a,valueWayDim:0});function p(t,e,n){for(var i=0;ie)return t[i];return t[n-1]}(i,a):n;if((c=c||n)&&c.length){var h=c[l];return r&&(u[r]=h),s.paletteIdx=(l+1)%c.length,h}}var Ef="\0_ec_inner";var Bf=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.init=function(t,e,n,i,r,o){i=i||{},this.option=null,this._theme=new wd(i),this._locale=new wd(r),this._optionManager=o},e.prototype.setOption=function(t,e,n){var i=Ff(e);this._optionManager.setOption(t,n,i),this._resetOption(null,i)},e.prototype.resetOption=function(t,e){return this._resetOption(t,Ff(e))},e.prototype._resetOption=function(t,e){var n=!1,i=this._optionManager;if(!t||"recreate"===t){var r=i.mountOption("recreate"===t);0,this.option&&"recreate"!==t?(this.restoreData(),this._mergeOption(r,e)):Lf(this,r),n=!0}if("timeline"!==t&&"media"!==t||this.restoreData(),!t||"recreate"===t||"timeline"===t){var o=i.getTimelineOption(this);o&&(n=!0,this._mergeOption(o,e))}if(!t||"recreate"===t||"media"===t){var a=i.getMediaOption(this);a.length&&z(a,(function(t){n=!0,this._mergeOption(t,e)}),this)}return n},e.prototype.mergeOption=function(t){this._mergeOption(t,null)},e.prototype._mergeOption=function(t,e){var n=this.option,i=this._componentsMap,r=this._componentsCount,o=[],a=yt(),s=e&&e.replaceMergeMainTypeMap;wf(this).datasetMap=yt(),z(t,(function(t,e){null!=t&&(Qp.hasClass(e)?e&&(o.push(e),a.set(e,!0)):n[e]=null==n[e]?T(t):C(n[e],t,!0))})),s&&s.each((function(t,e){Qp.hasClass(e)&&!a.get(e)&&(o.push(e),a.set(e,!0))})),Qp.topologicalTravel(o,Qp.getAllClassMainTypes(),(function(e){var o=function(t,e,n){var i=Df.get(e);if(!i)return n;var r=i(t);return r?n.concat(r):n}(this,e,qo(t[e])),a=i.get(e),l=a?s&&s.get(e)?"replaceMerge":"normalMerge":"replaceAll",u=ta(a,o,l);(function(t,e,n){z(t,(function(t){var i=t.newOption;q(i)&&(t.keyInfo.mainType=e,t.keyInfo.subType=function(t,e,n,i){return e.type?e.type:n?n.subType:i.determineSubType(t,e)}(e,i,t.existing,n))}))})(u,e,Qp),n[e]=null,i.set(e,null),r.set(e,0);var c,h=[],d=[],p=0;z(u,(function(t,n){var i=t.existing,r=t.newOption;if(r){var o="series"===e,a=Qp.getClass(e,t.keyInfo.subType,!o);if(!a)return;if("tooltip"===e){if(c)return void 0;c=!0}if(i&&i.constructor===a)i.name=t.keyInfo.name,i.mergeOption(r,this),i.optionUpdated(r,!1);else{var s=A({componentIndex:n},t.keyInfo);A(i=new a(r,this,this,s),s),t.brandNew&&(i.__requireNewView=!0),i.init(r,this,this),i.optionUpdated(null,!0)}}else i&&(i.mergeOption({},this),i.optionUpdated({},!1));i?(h.push(i.option),d.push(i),p++):(h.push(void 0),d.push(void 0))}),this),n[e]=h,i.set(e,d),r.set(e,p),"series"===e&&Af(this)}),this),this._seriesIndices||Af(this)},e.prototype.getOption=function(){var t=T(this.option);return z(t,(function(e,n){if(Qp.hasClass(n)){for(var i=qo(e),r=i.length,o=!1,a=r-1;a>=0;a--)i[a]&&!oa(i[a])?o=!0:(i[a]=null,!o&&r--);i.length=r,t[n]=i}})),delete t[Ef],t},e.prototype.setTheme=function(t){this._theme=new wd(t),this._resetOption("recreate",null)},e.prototype.getTheme=function(){return this._theme},e.prototype.getLocaleModel=function(){return this._locale},e.prototype.setUpdatePayload=function(t){this._payload=t},e.prototype.getUpdatePayload=function(){return this._payload},e.prototype.getComponent=function(t,e){var n=this._componentsMap.get(t);if(n){var i=n[e||0];if(i)return i;if(null==e)for(var r=0;r=e:"max"===n?t<=e:t===e})(i[a],t,o)||(r=!1)}})),r}var Zf=z,jf=q,qf=["areaStyle","lineStyle","nodeStyle","linkStyle","chordStyle","label","labelLine"];function Kf(t){var e=t&&t.itemStyle;if(e)for(var n=0,i=qf.length;nu&&(u=p)}s[0]=l,s[1]=u}},i=function(){return this._data?this._data.length/this._dimSize:0};function r(t){for(var e=0;e=0&&(s=o.interpolatedValue[l])}return null!=s?s+"":""})):void 0},t.prototype.getRawValue=function(t,e){return Vg(this.getData(e),t)},t.prototype.formatTooltip=function(t,e,n){},t}();function Wg(t){var e,n;return q(t)?t.type&&(n=t):e=t,{text:e,frag:n}}function Hg(t){return new Ug(t)}var Ug=function(){function t(t){t=t||{},this._reset=t.reset,this._plan=t.plan,this._count=t.count,this._onDirty=t.onDirty,this._dirty=!0}return t.prototype.perform=function(t){var e,n=this._upstream,i=t&&t.skip;if(this._dirty&&n){var r=this.context;r.data=r.outputData=n.context.outputData}this.__pipeline&&(this.__pipeline.currentTask=this),this._plan&&!i&&(e=this._plan(this.context));var o,a=c(this._modBy),s=this._modDataCount||0,l=c(t&&t.modBy),u=t&&t.modDataCount||0;function c(t){return!(t>=1)&&(t=1),t}a===l&&s===u||(e="reset"),(this._dirty||"reset"===e)&&(this._dirty=!1,o=this._doReset(i)),this._modBy=l,this._modDataCount=u;var h=t&&t.step;if(this._dueEnd=n?n._outputDueEnd:this._count?this._count(this.context):1/0,this._progress){var d=this._dueIndex,p=Math.min(null!=h?this._dueIndex+h:1/0,this._dueEnd);if(!i&&(o||d1&&i>0?s:a}};return o;function a(){return e=t?null:oe},gte:function(t,e){return t>=e}},Kg=function(){function t(t,e){if(!j(e)){var n="";0,Yo(n)}this._opFn=qg[t],this._rvalFloat=No(e)}return t.prototype.evaluate=function(t){return j(t)?this._opFn(t,this._rvalFloat):this._opFn(No(t),this._rvalFloat)},t}(),$g=function(){function t(t,e){var n="desc"===t;this._resultLT=n?1:-1,null==e&&(e=n?"min":"max"),this._incomparable="min"===e?-1/0:1/0}return t.prototype.evaluate=function(t,e){var n=j(t)?t:No(t),i=j(e)?e:No(e),r=isNaN(n),o=isNaN(i);if(r&&(n=this._incomparable),o&&(i=this._incomparable),r&&o){var a=X(t),s=X(e);a&&(n=s?t:0),s&&(i=a?e:0)}return ni?-this._resultLT:0},t}(),Jg=function(){function t(t,e){this._rval=e,this._isEQ=t,this._rvalTypeof=typeof e,this._rvalFloat=No(e)}return t.prototype.evaluate=function(t){var e=t===this._rval;if(!e){var n=typeof t;n===this._rvalTypeof||"number"!==n&&"number"!==this._rvalTypeof||(e=No(t)===this._rvalFloat)}return this._isEQ?e:!e},t}();function Qg(t,e){return"eq"===t||"ne"===t?new Jg("eq"===t,e):_t(qg,t)?new Kg(t,e):null}var ty=function(){function t(){}return t.prototype.getRawData=function(){throw new Error("not supported")},t.prototype.getRawDataItem=function(t){throw new Error("not supported")},t.prototype.cloneRawData=function(){},t.prototype.getDimensionInfo=function(t){},t.prototype.cloneAllDimensionInfo=function(){},t.prototype.count=function(){},t.prototype.retrieveValue=function(t,e){},t.prototype.retrieveValueFromItem=function(t,e){},t.prototype.convertValue=function(t,e){return Xg(t,e)},t}();function ey(t){var e=t.sourceFormat;if(!sy(e)){var n="";0,Yo(n)}return t.data}function ny(t){var e=t.sourceFormat,n=t.data;if(!sy(e)){var i="";0,Yo(i)}if(e===df){for(var r=[],o=0,a=n.length;o65535?cy:hy}function yy(t,e,n,i,r){var o=fy[n||"float"];if(r){var a=t[e],s=a&&a.length;if(s!==i){for(var l=new o(i),u=0;ug[1]&&(g[1]=f)}return this._rawCount=this._count=s,{start:a,end:s}},t.prototype._initDataFromProvider=function(t,e,n){for(var i=this._provider,r=this._chunks,o=this._dimensions,a=o.length,s=this._rawExtent,l=E(o,(function(t){return t.property})),u=0;uy[1]&&(y[1]=g)}}!i.persistent&&i.clean&&i.clean(),this._rawCount=this._count=e,this._extent=[]},t.prototype.count=function(){return this._count},t.prototype.get=function(t,e){if(!(e>=0&&e=0&&e=this._rawCount||t<0)return-1;if(!this._indices)return t;var e=this._indices,n=e[t];if(null!=n&&nt))return o;r=o-1}}return-1},t.prototype.getIndices=function(){var t,e=this._indices;if(e){var n=e.constructor,i=this._count;if(n===Array){t=new n(i);for(var r=0;r=u&&x<=c||isNaN(x))&&(a[s++]=p),p++}d=!0}else if(2===r){f=h[i[0]];var y=h[i[1]],v=t[i[1]][0],m=t[i[1]][1];for(g=0;g=u&&x<=c||isNaN(x))&&(_>=v&&_<=m||isNaN(_))&&(a[s++]=p),p++}d=!0}}if(!d)if(1===r)for(g=0;g=u&&x<=c||isNaN(x))&&(a[s++]=b)}else for(g=0;gt[M][1])&&(w=!1)}w&&(a[s++]=e.getRawIndex(g))}return sy[1]&&(y[1]=g)}}}},t.prototype.lttbDownSample=function(t,e){var n,i,r,o=this.clone([t],!0),a=o._chunks[t],s=this.count(),l=0,u=Math.floor(1/e),c=this.getRawIndex(0),h=new(gy(this._rawCount))(Math.min(2*(Math.ceil(s/u)+2),s));h[l++]=c;for(var d=1;dn&&(n=i,r=I)}M>0&&M<_-x&&(h[l++]=Math.min(S,r),r=Math.max(S,r)),h[l++]=r,c=r}return h[l++]=this.getRawIndex(s-1),o._count=l,o._indices=h,o.getRawIndex=this._getRawIdx,o},t.prototype.minmaxDownSample=function(t,e){for(var n=this.clone([t],!0),i=n._chunks,r=Math.floor(1/e),o=i[t],a=this.count(),s=new(gy(this._rawCount))(2*Math.ceil(a/r)),l=0,u=0;ua&&(f=a-u);for(var g=0;gp&&(p=y,d=u+g)}var v=this.getRawIndex(c),m=this.getRawIndex(d);cu-p&&(s=u-p,a.length=s);for(var f=0;fc[1]&&(c[1]=y),h[d++]=v}return r._count=d,r._indices=h,r._updateGetRawIdx(),r},t.prototype.each=function(t,e){if(this._count)for(var n=t.length,i=this._chunks,r=0,o=this.count();ra&&(a=l)}return i=[o,a],this._extent[t]=i,i},t.prototype.getRawDataItem=function(t){var e=this.getRawIndex(t);if(this._provider.persistent)return this._provider.getItem(e);for(var n=[],i=this._chunks,r=0;r=0?this._indices[t]:-1},t.prototype._updateGetRawIdx=function(){this.getRawIndex=this._indices?this._getRawIdx:this._getRawIdxIdentity},t.internalField=function(){function t(t,e,n,i){return Xg(t[i],this._dimensions[i])}ly={arrayRows:t,objectRows:function(t,e,n,i){return Xg(t[e],this._dimensions[i])},keyedColumns:t,original:function(t,e,n,i){var r=t&&(null==t.value?t:t.value);return Xg(r instanceof Array?r[i]:r,this._dimensions[i])},typedArray:function(t,e,n,i){return t[i]}}}(),t}(),my=function(){function t(t){this._sourceList=[],this._storeList=[],this._upstreamSignList=[],this._versionSignBase=0,this._dirty=!0,this._sourceHost=t}return t.prototype.dirty=function(){this._setLocalSource([],[]),this._storeList=[],this._dirty=!0},t.prototype._setLocalSource=function(t,e){this._sourceList=t,this._upstreamSignList=e,this._versionSignBase++,this._versionSignBase>9e10&&(this._versionSignBase=0)},t.prototype._getVersionSign=function(){return this._sourceHost.uid+"_"+this._versionSignBase},t.prototype.prepareSource=function(){this._isDirty()&&(this._createSource(),this._dirty=!1)},t.prototype._createSource=function(){this._setLocalSource([],[]);var t,e,n=this._sourceHost,i=this._getUpstreamSourceManagers(),r=!!i.length;if(_y(n)){var o=n,a=void 0,s=void 0,l=void 0;if(r){var u=i[0];u.prepareSource(),a=(l=u.getSource()).data,s=l.sourceFormat,e=[u._getVersionSign()]}else s=$(a=o.get("data",!0))?gf:hf,e=[];var c=this._getSourceMetaRawOption()||{},h=l&&l.metaRawOption||{},d=rt(c.seriesLayoutBy,h.seriesLayoutBy)||null,p=rt(c.sourceHeader,h.sourceHeader),f=rt(c.dimensions,h.dimensions);t=d!==h.seriesLayoutBy||!!p!=!!h.sourceHeader||f?[bg(a,{seriesLayoutBy:d,sourceHeader:p,dimensions:f},s)]:[]}else{var g=n;if(r){var y=this._applyTransform(i);t=y.sourceList,e=y.upstreamSignList}else{t=[bg(g.get("source",!0),this._getSourceMetaRawOption(),null)],e=[]}}this._setLocalSource(t,e)},t.prototype._applyTransform=function(t){var e,n=this._sourceHost,i=n.get("transform",!0),r=n.get("fromTransformResult",!0);if(null!=r){var o="";1!==t.length&&by(o)}var a,s=[],l=[];return z(t,(function(t){t.prepareSource();var e=t.getSource(r||0),n="";null==r||e||by(n),s.push(e),l.push(t._getVersionSign())})),i?e=function(t,e,n){var i=qo(t),r=i.length,o="";r||Yo(o);for(var a=0,s=r;a1||n>0&&!t.noHeader;return z(t.blocks,(function(t){var n=Ay(t);n>=e&&(e=n+ +(i&&(!n||Cy(t)&&!t.noHeader)))})),e}return 0}function ky(t,e,n,i){var r,o=e.noHeader,a=(r=Ay(e),{html:My[r],richText:Iy[r]}),s=[],l=e.blocks||[];lt(!l||U(l)),l=l||[];var u=t.orderMode;if(e.sortBlocks&&u){l=l.slice();var c={valueAsc:"asc",valueDesc:"desc"};if(_t(c,u)){var h=new $g(c[u],null);l.sort((function(t,e){return h.evaluate(t.sortParam,e.sortParam)}))}else"seriesDesc"===u&&l.reverse()}z(l,(function(n,r){var o=e.valueFormatter,l=Dy(n)(o?A(A({},t),{valueFormatter:o}):t,n,r>0?a.html:0,i);null!=l&&s.push(l)}));var d="richText"===t.renderMode?s.join(a.richText):Oy(i,s.join(""),o?n:a.html);if(o)return d;var p=vp(e.header,"ordinal",t.useUTC),f=Sy(i,t.renderMode).nameStyle,g=wy(i);return"richText"===t.renderMode?Ry(t,p,f)+a.richText+d:Oy(i,'
'+oe(p)+"
"+d,n)}function Ly(t,e,n,i){var r=t.renderMode,o=e.noName,a=e.noValue,s=!e.markerType,l=e.name,u=t.useUTC,c=e.valueFormatter||t.valueFormatter||function(t){return E(t=U(t)?t:[t],(function(t,e){return vp(t,U(p)?p[e]:p,u)}))};if(!o||!a){var h=s?"":t.markupStyleCreator.makeTooltipMarker(e.markerType,e.markerColor||tf.color.secondary,r),d=o?"":vp(l,"ordinal",u),p=e.valueType,f=a?[]:c(e.value,e.dataIndex),g=!s||!o,y=!s&&o,v=Sy(i,r),m=v.nameStyle,x=v.valueStyle;return"richText"===r?(s?"":h)+(o?"":Ry(t,d,m))+(a?"":function(t,e,n,i,r){var o=[r],a=i?10:20;return n&&o.push({padding:[0,0,0,a],align:"right"}),t.markupStyleCreator.wrapRichTextStyle(U(e)?e.join(" "):e,o)}(t,f,g,y,x)):Oy(i,(s?"":h)+(o?"":function(t,e,n){return''+oe(t)+""}(d,!s,m))+(a?"":function(t,e,n,i){var r=n?"10px":"20px",o=e?"float:right;margin-left:"+r:"";return t=U(t)?t:[t],''+E(t,(function(t){return oe(t)})).join("  ")+""}(f,g,y,x)),n)}}function Py(t,e,n,i,r,o){if(t)return Dy(t)({useUTC:r,renderMode:n,orderMode:i,markupStyleCreator:e,valueFormatter:t.valueFormatter},t,0,o)}function Oy(t,e,n){return'
'+e+'
'}function Ry(t,e,n){return t.markupStyleCreator.wrapRichTextStyle(e,n)}function Ny(t,e){return wp(t.getData().getItemVisual(e,"style")[t.visualDrawType])}function zy(t,e){var n=t.get("padding");return null!=n?n:"richText"===e?[8,10]:10}var Ey=function(){function t(){this.richTextStyles={},this._nextStyleNameId=Eo()}return t.prototype._generateStyleName=function(){return"__EC_aUTo_"+this._nextStyleNameId++},t.prototype.makeTooltipMarker=function(t,e,n){var i="richText"===n?this._generateStyleName():null,r=bp({color:e,type:t,renderMode:n,markerId:i});return X(r)?r:(this.richTextStyles[i]=r.style,r.content)},t.prototype.wrapRichTextStyle=function(t,e){var n={};U(e)?z(e,(function(t){return A(n,t)})):A(n,e);var i=this._generateStyleName();return this.richTextStyles[i]=n,"{"+i+"|"+t+"}"},t}();function By(t){var e,n,i,r,o=t.series,a=t.dataIndex,s=t.multipleSeries,l=o.getData(),u=l.mapDimensionsAll("defaultedTooltip"),c=u.length,h=o.getRawValue(a),d=U(h),p=Ny(o,a);if(c>1||d&&!c){var f=function(t,e,n,i,r){var o=e.getData(),a=B(t,(function(t,e,n){var i=o.getDimensionInfo(n);return t||i&&!1!==i.tooltip&&null!=i.displayName}),!1),s=[],l=[],u=[];function c(t,e){var n=o.getDimensionInfo(e);n&&!1!==n.otherDims.tooltip&&(a?u.push(Ty("nameValue",{markerType:"subItem",markerColor:r,name:n.displayName,value:t,valueType:n.type})):(s.push(t),l.push(n.type)))}return i.length?z(i,(function(t){c(Vg(o,n,t),t)})):z(t,c),{inlineValues:s,inlineValueTypes:l,blocks:u}}(h,o,a,u,p);e=f.inlineValues,n=f.inlineValueTypes,i=f.blocks,r=f.inlineValues[0]}else if(c){var g=l.getDimensionInfo(u[0]);r=e=Vg(l,a,u[0]),n=g.type}else r=e=d?h[0]:h;var y=ra(o),v=y&&o.name||"",m=l.getName(a),x=s?v:m;return Ty("section",{header:v,noHeader:s||!y,sortParam:r,blocks:[Ty("nameValue",{markerType:"item",markerColor:p,name:x,noName:!ut(x),value:e,valueType:n,dataIndex:a})].concat(i||[])})}var Vy=sa();function Gy(t,e){return t.getName(e)||t.getId(e)}var Fy="__universalTransitionEnabled",Wy=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e._selectedDataIndicesMap={},e}var i;return n(e,t),e.prototype.init=function(t,e,n){this.seriesIndex=this.componentIndex,this.dataTask=Hg({count:Uy,reset:Yy}),this.dataTask.context={model:this},this.mergeDefaultAndTheme(t,n),(Vy(this).sourceManager=new my(this)).prepareSource();var i=this.getInitialData(t,n);Zy(i,this),this.dataTask.context.data=i,Vy(this).dataBeforeProcessed=i,Hy(this),this._initSelectedMapFromData(i)},e.prototype.mergeDefaultAndTheme=function(t,e){var n=jp(this),i=n?Kp(t):{},r=this.subType;Qp.hasClass(r)&&(r+="Series"),C(t,e.getTheme().get(this.subType)),C(t,this.getDefaultOption()),Ko(t,"label",["show"]),this.fillDataTextStyle(t.data),n&&qp(t,i,n)},e.prototype.mergeOption=function(t,e){t=C(this.option,t,!0),this.fillDataTextStyle(t.data);var n=jp(this);n&&qp(this.option,t,n);var i=Vy(this).sourceManager;i.dirty(),i.prepareSource();var r=this.getInitialData(t,e);Zy(r,this),this.dataTask.dirty(),this.dataTask.context.data=r,Vy(this).dataBeforeProcessed=r,Hy(this),this._initSelectedMapFromData(r)},e.prototype.fillDataTextStyle=function(t){if(t&&!$(t))for(var e=["show"],n=0;n=0&&c<0)&&(u=o,c=r,h=0),r===c&&(l[h++]=e))})),l.length=h,l},e.prototype.formatTooltip=function(t,e,n){return By({series:this,dataIndex:t,multipleSeries:e})},e.prototype.isAnimationEnabled=function(){var t=this.ecModel;if(r.node&&(!t||!t.ssr))return!1;var e=this.getShallow("animation");return e&&this.getData().count()>this.getShallow("animationThreshold")&&(e=!1),!!e},e.prototype.restoreData=function(){this.dataTask.dirty()},e.prototype.getColorFromPalette=function(t,e,n){var i=this.ecModel,r=Rf.prototype.getColorFromPalette.call(this,t,e,n);return r||(r=i.getColorFromPalette(t,e,n)),r},e.prototype.coordDimToDataDim=function(t){return this.getRawData().mapDimensionsAll(t)},e.prototype.getProgressive=function(){return this.get("progressive")},e.prototype.getProgressiveThreshold=function(){return this.get("progressiveThreshold")},e.prototype.select=function(t,e){this._innerSelect(this.getData(e),t)},e.prototype.unselect=function(t,e){var n=this.option.selectedMap;if(n){var i=this.option.selectedMode,r=this.getData(e);if("series"===i||"all"===n)return this.option.selectedMap={},void(this._selectedDataIndicesMap={});for(var o=0;o=0&&n.push(r)}return n},e.prototype.isSelected=function(t,e){var n=this.option.selectedMap;if(!n)return!1;var i=this.getData(e);return("all"===n||n[Gy(i,t)])&&!i.getItemModel(t).get(["select","disabled"])},e.prototype.isUniversalTransitionEnabled=function(){if(this[Fy])return!0;var t=this.option.universalTransition;return!!t&&(!0===t||t&&t.enabled)},e.prototype._innerSelect=function(t,e){var n,i,r=this.option,o=r.selectedMode,a=e.length;if(o&&a)if("series"===o)r.selectedMap="all";else if("multiple"===o){q(r.selectedMap)||(r.selectedMap={});for(var s=r.selectedMap,l=0;l0&&this._innerSelect(t,e)}},e.registerClass=function(t){return Qp.registerClass(t)},e.protoInitialize=((i=e.prototype).type="series.__base__",i.seriesIndex=0,i.ignoreStyleOnData=!1,i.hasSymbolVisual=!1,i.defaultSymbol="circle",i.visualStyleAccessPath="itemStyle",void(i.visualDrawType="fill")),e}(Qp);function Hy(t){var e=t.name;ra(t)||(t.name=function(t){var e=t.getRawData(),n=e.mapDimensionsAll("seriesName"),i=[];return z(n,(function(t){var n=e.getDimensionInfo(t);n.displayName&&i.push(n.displayName)})),i.join(" ")}(t)||e)}function Uy(t){return t.model.getRawData().count()}function Yy(t){var e=t.model;return e.setData(e.getRawData().cloneShallow()),Xy}function Xy(t,e){e.outputData&&t.end>e.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function Zy(t,e){z(vt(t.CHANGABLE_METHODS,t.DOWNSAMPLE_METHODS),(function(n){t.wrapMethod(n,H(jy,e))}))}function jy(t,e){var n=qy(t);return n&&n.setOutputEnd((e||this).count()),e}function qy(t){var e=(t.ecModel||{}).scheduler,n=e&&e.getPipeline(t.uid);if(n){var i=n.currentTask;if(i){var r=i.agentStubMap;r&&(i=r.get(t.uid))}return i}}R(Wy,Fg),R(Wy,Rf),Sa(Wy,Qp);var Ky=function(){function t(){this.group=new to,this.uid=Md("viewComponent")}return t.prototype.init=function(t,e){},t.prototype.render=function(t,e,n,i){},t.prototype.dispose=function(t,e){},t.prototype.updateView=function(t,e,n,i){},t.prototype.updateLayout=function(t,e,n,i){},t.prototype.updateVisual=function(t,e,n,i){},t.prototype.toggleBlurSeries=function(t,e,n){},t.prototype.eachRendered=function(t){var e=this.group;e&&e.traverse(t)},t}();function $y(){var t=sa();return function(e){var n=t(e),i=e.pipelineContext,r=!!n.large,o=!!n.progressiveRender,a=n.large=!(!i||!i.large),s=n.progressiveRender=!(!i||!i.progressiveRender);return!(r===a&&o===s)&&"reset"}}wa(Ky),Ca(Ky);var Jy=sa(),Qy=$y(),tv=function(){function t(){this.group=new to,this.uid=Md("viewChart"),this.renderTask=Hg({plan:iv,reset:rv}),this.renderTask.context={view:this}}return t.prototype.init=function(t,e){},t.prototype.render=function(t,e,n,i){0},t.prototype.highlight=function(t,e,n,i){var r=t.getData(i&&i.dataType);r&&nv(r,i,"emphasis")},t.prototype.downplay=function(t,e,n,i){var r=t.getData(i&&i.dataType);r&&nv(r,i,"normal")},t.prototype.remove=function(t,e){this.group.removeAll()},t.prototype.dispose=function(t,e){},t.prototype.updateView=function(t,e,n,i){this.render(t,e,n,i)},t.prototype.updateLayout=function(t,e,n,i){this.render(t,e,n,i)},t.prototype.updateVisual=function(t,e,n,i){this.render(t,e,n,i)},t.prototype.eachRendered=function(t){Bh(this.group,t)},t.markUpdateMethod=function(t,e){Jy(t).updateMethod=e},t.protoInitialize=void(t.prototype.type="chart"),t}();function ev(t,e,n){t&&Pu(t)&&("emphasis"===e?du:pu)(t,n)}function nv(t,e,n){var i=aa(t,e),r=e&&null!=e.highlightKey?function(t){var e=Vl[t];return null==e&&Bl<=32&&(e=Vl[t]=Bl++),e}(e.highlightKey):null;null!=i?z(qo(i),(function(e){ev(t.getItemGraphicEl(e),n,r)})):t.eachItemGraphicEl((function(t){ev(t,n,r)}))}function iv(t){return Qy(t.model)}function rv(t){var e=t.model,n=t.ecModel,i=t.api,r=t.payload,o=e.pipelineContext.progressiveRender,a=t.view,s=r&&Jy(r).updateMethod,l=o?"incrementalPrepareRender":s&&a[s]?s:"render";return"render"!==l&&a[l](e,n,i,r),ov[l]}wa(tv),Ca(tv);var ov={incrementalPrepareRender:{progress:function(t,e){e.view.incrementalRender(t,e.model,e.ecModel,e.api,e.payload)}},render:{forceFirstProgress:!0,progress:function(t,e){e.view.render(e.model,e.ecModel,e.api,e.payload)}}},av="\0__throttleOriginMethod",sv="\0__throttleRate",lv="\0__throttleType";function uv(t,e,n){var i,r,o,a,s,l=0,u=0,c=null;function h(){u=(new Date).getTime(),c=null,t.apply(o,a||[])}e=e||0;var d=function(){for(var t=[],d=0;d=0?h():c=setTimeout(h,-r),l=i};return d.clear=function(){c&&(clearTimeout(c),c=null)},d.debounceNextCall=function(t){s=t},d}function cv(t,e,n,i){var r=t[e];if(r){var o=r[av]||r,a=r[lv];if(r[sv]!==n||a!==i){if(null==n||!i)return t[e]=o;(r=t[e]=uv(o,n,"debounce"===i))[av]=o,r[lv]=i,r[sv]=n}return r}}function hv(t,e){var n=t[e];n&&n[av]&&(n.clear&&n.clear(),t[e]=n[av])}var dv=sa(),pv={itemStyle:Da(xd,!0),lineStyle:Da(yd,!0)},fv={lineStyle:"stroke",itemStyle:"fill"};function gv(t,e){var n=t.visualStyleMapper||pv[e];return n||(console.warn("Unknown style type '"+e+"'."),pv.itemStyle)}function yv(t,e){var n=t.visualDrawType||fv[e];return n||(console.warn("Unknown style type '"+e+"'."),"fill")}var vv={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var n=t.getData(),i=t.visualStyleAccessPath||"itemStyle",r=t.getModel(i),o=gv(t,i)(r),a=r.getShallow("decal");a&&(n.setVisual("decal",a),a.dirty=!0);var s=yv(t,i),l=o[s],u=Y(l)?l:null,c="auto"===o.fill||"auto"===o.stroke;if(!o[s]||u||c){var h=t.getColorFromPalette(t.name,null,e.getSeriesCount());o[s]||(o[s]=h,n.setVisual("colorFromPalette",!0)),o.fill="auto"===o.fill||Y(o.fill)?h:o.fill,o.stroke="auto"===o.stroke||Y(o.stroke)?h:o.stroke}if(n.setVisual("style",o),n.setVisual("drawType",s),!e.isSeriesFiltered(t)&&u)return n.setVisual("colorFromPalette",!1),{dataEach:function(e,n){var i=t.getDataParams(n),r=A({},o);r[s]=u(i),e.setItemVisual(n,"style",r)}}}},mv=new wd,xv={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){if(!t.ignoreStyleOnData&&!e.isSeriesFiltered(t)){var n=t.getData(),i=t.visualStyleAccessPath||"itemStyle",r=gv(t,i),o=n.getVisual("drawType");return{dataEach:n.hasItemOption?function(t,e){var n=t.getRawDataItem(e);if(n&&n[i]){mv.option=n[i];var a=r(mv);A(t.ensureUniqueItemVisual(e,"style"),a),mv.option.decal&&(t.setItemVisual(e,"decal",mv.option.decal),mv.option.decal.dirty=!0),o in a&&t.setItemVisual(e,"colorFromPalette",!1)}}:null}}}},_v={performRawSeries:!0,overallReset:function(t){var e=yt();t.eachSeries((function(t){var n=t.getColorBy();if(!t.isColorBySeries()){var i=t.type+"-"+n,r=e.get(i);r||(r={},e.set(i,r)),dv(t).scope=r}})),t.eachSeries((function(e){if(!e.isColorBySeries()&&!t.isSeriesFiltered(e)){var n=e.getRawData(),i={},r=e.getData(),o=dv(e).scope,a=e.visualStyleAccessPath||"itemStyle",s=yv(e,a);r.each((function(t){var e=r.getRawIndex(t);i[e]=t})),n.each((function(t){var a=i[t];if(r.getItemVisual(a,"colorFromPalette")){var l=r.ensureUniqueItemVisual(a,"style"),u=n.getName(t)||t+"",c=n.count();l[s]=e.getColorFromPalette(u,o,c)}}))}}))}},bv=Math.PI;var wv=function(){function t(t,e,n,i){this._stageTaskMap=yt(),this.ecInstance=t,this.api=e,n=this._dataProcessorHandlers=n.slice(),i=this._visualHandlers=i.slice(),this._allHandlers=n.concat(i)}return t.prototype.restoreData=function(t,e){t.restoreData(e),this._stageTaskMap.each((function(t){var e=t.overallTask;e&&e.dirty()}))},t.prototype.getPerformArgs=function(t,e){if(t.__pipeline){var n=this._pipelineMap.get(t.__pipeline.id),i=n.context,r=!e&&n.progressiveEnabled&&(!i||i.progressiveRender)&&t.__idxInPipeline>n.blockIndex?n.step:null,o=i&&i.modDataCount;return{step:r,modBy:null!=o?Math.ceil(o/r):null,modDataCount:o}}},t.prototype.getPipeline=function(t){return this._pipelineMap.get(t)},t.prototype.updateStreamModes=function(t,e){var n=this._pipelineMap.get(t.uid),i=t.getData().count(),r=n.progressiveEnabled&&e.incrementalPrepareRender&&i>=n.threshold,o=t.get("large")&&i>=t.get("largeThreshold"),a="mod"===t.get("progressiveChunkMode")?i:null;t.pipelineContext=n.context={progressiveRender:r,modDataCount:a,large:o}},t.prototype.restorePipelines=function(t){var e=this,n=e._pipelineMap=yt();t.eachSeries((function(t){var i=t.getProgressive(),r=t.uid;n.set(r,{id:r,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:i&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(i||700),count:0}),e._pipe(t,t.dataTask)}))},t.prototype.prepareStageTasks=function(){var t=this._stageTaskMap,e=this.api.getModel(),n=this.api;z(this._allHandlers,(function(i){var r=t.get(i.uid)||t.set(i.uid,{}),o="";lt(!(i.reset&&i.overallReset),o),i.reset&&this._createSeriesStageTask(i,r,e,n),i.overallReset&&this._createOverallStageTask(i,r,e,n)}),this)},t.prototype.prepareView=function(t,e,n,i){var r=t.renderTask,o=r.context;o.model=e,o.ecModel=n,o.api=i,r.__block=!t.incrementalPrepareRender,this._pipe(e,r)},t.prototype.performDataProcessorTasks=function(t,e){this._performStageTasks(this._dataProcessorHandlers,t,e,{block:!0})},t.prototype.performVisualTasks=function(t,e,n){this._performStageTasks(this._visualHandlers,t,e,n)},t.prototype._performStageTasks=function(t,e,n,i){i=i||{};var r=!1,o=this;function a(t,e){return t.setDirty&&(!t.dirtyMap||t.dirtyMap.get(e.__pipeline.id))}z(t,(function(t,s){if(!i.visualType||i.visualType===t.visualType){var l=o._stageTaskMap.get(t.uid),u=l.seriesTaskMap,c=l.overallTask;if(c){var h,d=c.agentStubMap;d.each((function(t){a(i,t)&&(t.dirty(),h=!0)})),h&&c.dirty(),o.updatePayload(c,n);var p=o.getPerformArgs(c,i.block);d.each((function(t){t.perform(p)})),c.perform(p)&&(r=!0)}else u&&u.each((function(s,l){a(i,s)&&s.dirty();var u=o.getPerformArgs(s,i.block);u.skip=!t.performRawSeries&&e.isSeriesFiltered(s.context.model),o.updatePayload(s,n),s.perform(u)&&(r=!0)}))}})),this.unfinished=r||this.unfinished},t.prototype.performSeriesTasks=function(t){var e;t.eachSeries((function(t){e=t.dataTask.perform()||e})),this.unfinished=e||this.unfinished},t.prototype.plan=function(){this._pipelineMap.each((function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)}))},t.prototype.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)},t.prototype._createSeriesStageTask=function(t,e,n,i){var r=this,o=e.seriesTaskMap,a=e.seriesTaskMap=yt(),s=t.seriesType,l=t.getTargetSeries;function u(e){var s=e.uid,l=a.set(s,o&&o.get(s)||Hg({plan:Cv,reset:Dv,count:Lv}));l.context={model:e,ecModel:n,api:i,useClearVisual:t.isVisual&&!t.isLayout,plan:t.plan,reset:t.reset,scheduler:r},r._pipe(e,l)}t.createOnAllSeries?n.eachRawSeries(u):s?n.eachRawSeriesByType(s,u):l&&l(n,i).each(u)},t.prototype._createOverallStageTask=function(t,e,n,i){var r=this,o=e.overallTask=e.overallTask||Hg({reset:Sv});o.context={ecModel:n,api:i,overallReset:t.overallReset,scheduler:r};var a=o.agentStubMap,s=o.agentStubMap=yt(),l=t.seriesType,u=t.getTargetSeries,c=!0,h=!1,d="";function p(t){var e=t.uid,n=s.set(e,a&&a.get(e)||(h=!0,Hg({reset:Mv,onDirty:Tv})));n.context={model:t,overallProgress:c},n.agent=o,n.__block=c,r._pipe(t,n)}lt(!t.createOnAllSeries,d),l?n.eachRawSeriesByType(l,p):u?u(n,i).each(p):(c=!1,z(n.getSeries(),p)),h&&o.dirty()},t.prototype._pipe=function(t,e){var n=t.uid,i=this._pipelineMap.get(n);!i.head&&(i.head=e),i.tail&&i.tail.pipe(e),i.tail=e,e.__idxInPipeline=i.count++,e.__pipeline=i},t.wrapStageHandler=function(t,e){return Y(t)&&(t={overallReset:t,seriesType:Pv(t)}),t.uid=Md("stageHandler"),e&&(t.visualType=e),t},t}();function Sv(t){t.overallReset(t.ecModel,t.api,t.payload)}function Mv(t){return t.overallProgress&&Iv}function Iv(){this.agent.dirty(),this.getDownstream().dirty()}function Tv(){this.agent&&this.agent.dirty()}function Cv(t){return t.plan?t.plan(t.model,t.ecModel,t.api,t.payload):null}function Dv(t){t.useClearVisual&&t.data.clearAllVisual();var e=t.resetDefines=qo(t.reset(t.model,t.ecModel,t.api,t.payload));return e.length>1?E(e,(function(t,e){return kv(e)})):Av}var Av=kv(0);function kv(t){return function(e,n){var i=n.data,r=n.resetDefines[t];if(r&&r.dataEach)for(var o=e.start;o0&&c===r.length-u.length){var h=r.slice(0,c);"data"!==h&&(e.mainType=h,e[u.toLowerCase()]=t,s=!0)}}a.hasOwnProperty(r)&&(n[r]=t,s=!0),s||(i[r]=t)}))}return{cptQuery:e,dataQuery:n,otherQuery:i}},t.prototype.filter=function(t,e){var n=this.eventInfo;if(!n)return!0;var i=n.targetEl,r=n.packedEvent,o=n.model,a=n.view;if(!o||!a)return!0;var s=e.cptQuery,l=e.dataQuery;return u(s,o,"mainType")&&u(s,o,"subType")&&u(s,o,"index","componentIndex")&&u(s,o,"name")&&u(s,o,"id")&&u(l,r,"name")&&u(l,r,"dataIndex")&&u(l,r,"dataType")&&(!a.filterForExposedEvent||a.filterForExposedEvent(t,e.otherQuery,i,r));function u(t,e,n,i){return null==t[n]||e[i||n]===t[n]}},t.prototype.afterTrigger=function(){this.eventInfo=null},t}(),Uv=["symbol","symbolSize","symbolRotate","symbolOffset"],Yv=Uv.concat(["symbolKeepAspect"]),Xv={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var n=t.getData();if(t.legendIcon&&n.setVisual("legendIcon",t.legendIcon),t.hasSymbolVisual){for(var i={},r={},o=!1,a=0;a=0&&fm(l)?l:.5,t.createRadialGradient(a,s,0,a,s,l)}(t,e,n):function(t,e,n){var i=null==e.x?0:e.x,r=null==e.x2?1:e.x2,o=null==e.y?0:e.y,a=null==e.y2?0:e.y2;return e.global||(i=i*n.width+n.x,r=r*n.width+n.x,o=o*n.height+n.y,a=a*n.height+n.y),i=fm(i)?i:0,r=fm(r)?r:1,o=fm(o)?o:0,a=fm(a)?a:0,t.createLinearGradient(i,o,r,a)}(t,e,n),r=e.colorStops,o=0;o0&&(e=i.lineDash,n=i.lineWidth,e&&"solid"!==e&&n>0?"dashed"===e?[4*n,2*n]:"dotted"===e?[n]:j(e)?[e]:U(e)?e:null:null),o=i.lineDashOffset;if(r){var a=i.strokeNoScale&&t.getLineScale?t.getLineScale():1;a&&1!==a&&(r=E(r,(function(t){return t/a})),o/=a)}return[r,o]}var xm=new Fs(!0);function _m(t){var e=t.stroke;return!(null==e||"none"===e||!(t.lineWidth>0))}function bm(t){return"string"==typeof t&&"none"!==t}function wm(t){var e=t.fill;return null!=e&&"none"!==e}function Sm(t,e){if(null!=e.fillOpacity&&1!==e.fillOpacity){var n=t.globalAlpha;t.globalAlpha=e.fillOpacity*e.opacity,t.fill(),t.globalAlpha=n}else t.fill()}function Mm(t,e){if(null!=e.strokeOpacity&&1!==e.strokeOpacity){var n=t.globalAlpha;t.globalAlpha=e.strokeOpacity*e.opacity,t.stroke(),t.globalAlpha=n}else t.stroke()}function Im(t,e,n){var i=Oa(e.image,e.__image,n);if(Na(i)){var r=t.createPattern(i,e.repeat||"repeat");if("function"==typeof DOMMatrix&&r&&r.setTransform){var o=new DOMMatrix;o.translateSelf(e.x||0,e.y||0),o.rotateSelf(0,0,(e.rotation||0)*wt),o.scaleSelf(e.scaleX||1,e.scaleY||1),r.setTransform(o)}return r}}var Tm=["shadowBlur","shadowOffsetX","shadowOffsetY"],Cm=[["lineCap","butt"],["lineJoin","miter"],["miterLimit",10]];function Dm(t,e,n,i,r){var o=!1;if(!i&&e===(n=n||{}))return!1;if(i||e.opacity!==n.opacity){Lm(t,r),o=!0;var a=Math.max(Math.min(e.opacity,1),0);t.globalAlpha=isNaN(a)?es.opacity:a}(i||e.blend!==n.blend)&&(o||(Lm(t,r),o=!0),t.globalCompositeOperation=e.blend||es.blend);for(var s=0;s0&&t.unfinished);t.unfinished||this._zr.flush()}}},e.prototype.getDom=function(){return this._dom},e.prototype.getId=function(){return this.id},e.prototype.getZr=function(){return this._zr},e.prototype.isSSR=function(){return this._ssr},e.prototype.setOption=function(t,e,n){if(!this[Km])if(this._disposed)kx(this.id);else{var i,r,o;if(q(e)&&(n=e.lazyUpdate,i=e.silent,r=e.replaceMerge,o=e.transition,e=e.notMerge),this[Km]=!0,Mx(this),!this._model||e){var a=new Yf(this._api),s=this._theme,l=this._model=new Bf;l.scheduler=this._scheduler,l.ssr=this._ssr,l.init(null,null,null,s,this._locale,a)}this._model.setOption(t,{replaceMerge:r},Nx);var u={seriesTransition:o,optionChanged:!0};if(n)this[Jm]={silent:i,updateParams:u},this[Km]=!1,this.getZr().wakeUp();else{try{ox(this),lx.update.call(this,null,u)}catch(t){throw this[Jm]=null,this[Km]=!1,t}this._ssr||this._zr.flush(),this[Jm]=null,this[Km]=!1,dx.call(this,i),px.call(this,i)}}},e.prototype.setTheme=function(t,e){if(!this[Km])if(this._disposed)kx(this.id);else{var n=this._model;if(n){var i=e&&e.silent,r=null;this[Jm]&&(null==i&&(i=this[Jm].silent),r=this[Jm].updateParams,this[Jm]=null),this[Km]=!0,Mx(this);try{this._updateTheme(t),n.setTheme(this._theme),ox(this),lx.update.call(this,{type:"setTheme"},r)}catch(t){throw this[Km]=!1,t}this[Km]=!1,dx.call(this,i),px.call(this,i)}}},e.prototype._updateTheme=function(t){X(t)&&(t=Ex[t]),t&&((t=T(t))&&dg(t,!0),this._theme=t)},e.prototype.getModel=function(){return this._model},e.prototype.getOption=function(){return this._model&&this._model.getOption()},e.prototype.getWidth=function(){return this._zr.getWidth()},e.prototype.getHeight=function(){return this._zr.getHeight()},e.prototype.getDevicePixelRatio=function(){return this._zr.painter.dpr||r.hasGlobalWindow&&window.devicePixelRatio||1},e.prototype.getRenderedCanvas=function(t){return this.renderToCanvas(t)},e.prototype.renderToCanvas=function(t){t=t||{};var e=this._zr.painter;return e.getRenderedCanvas({backgroundColor:t.backgroundColor||this._model.get("backgroundColor"),pixelRatio:t.pixelRatio||this.getDevicePixelRatio()})},e.prototype.renderToSVGString=function(t){t=t||{};var e=this._zr.painter;return e.renderToString({useViewBox:t.useViewBox})},e.prototype.getSvgDataURL=function(){var t=this._zr;return z(t.storage.getDisplayList(),(function(t){t.stopAnimation(null,!0)})),t.painter.toDataURL()},e.prototype.getDataURL=function(t){if(!this._disposed){var e=(t=t||{}).excludeComponents,n=this._model,i=[],r=this;z(e,(function(t){n.eachComponent({mainType:t},(function(t){var e=r._componentsMap[t.__viewId];e.group.ignore||(i.push(e),e.group.ignore=!0)}))}));var o="svg"===this._zr.painter.getType()?this.getSvgDataURL():this.renderToCanvas(t).toDataURL("image/"+(t&&t.type||"png"));return z(i,(function(t){t.group.ignore=!1})),o}kx(this.id)},e.prototype.getConnectedDataURL=function(t){if(!this._disposed){var e="svg"===t.type,n=this.group,i=Math.min,r=Math.max,o=1/0;if(Gx[n]){var a=o,s=o,l=-1/0,u=-1/0,h=[],d=t&&t.pixelRatio||this.getDevicePixelRatio();z(Vx,(function(o,c){if(o.group===n){var d=e?o.getZr().painter.getSvgDom().innerHTML:o.renderToCanvas(T(t)),p=o.getDom().getBoundingClientRect();a=i(p.left,a),s=i(p.top,s),l=r(p.right,l),u=r(p.bottom,u),h.push({dom:d,left:p.left,top:p.top})}}));var p=(l*=d)-(a*=d),f=(u*=d)-(s*=d),g=c.createCanvas(),y=oo(g,{renderer:e?"svg":"canvas"});if(y.resize({width:p,height:f}),e){var v="";return z(h,(function(t){var e=t.left-a,n=t.top-s;v+=''+t.dom+""})),y.painter.getSvgRoot().innerHTML=v,t.connectedBackgroundColor&&y.painter.setBackgroundColor(t.connectedBackgroundColor),y.refreshImmediately(),y.painter.toDataURL()}return t.connectedBackgroundColor&&y.add(new xl({shape:{x:0,y:0,width:p,height:f},style:{fill:t.connectedBackgroundColor}})),z(h,(function(t){var e=new dl({style:{x:t.left*d-a,y:t.top*d-s,image:t.dom}});y.add(e)})),y.refreshImmediately(),g.toDataURL("image/"+(t&&t.type||"png"))}return this.getDataURL(t)}kx(this.id)},e.prototype.convertToPixel=function(t,e,n){return ux(this,"convertToPixel",t,e,n)},e.prototype.convertToLayout=function(t,e,n){return ux(this,"convertToLayout",t,e,n)},e.prototype.convertFromPixel=function(t,e,n){return ux(this,"convertFromPixel",t,e,n)},e.prototype.containPixel=function(t,e){var n;if(!this._disposed)return z(ua(this._model,t),(function(t,i){i.indexOf("Models")>=0&&z(t,(function(t){var r=t.coordinateSystem;if(r&&r.containPoint)n=n||!!r.containPoint(e);else if("seriesModels"===i){var o=this._chartsMap[t.__viewId];o&&o.containPoint&&(n=n||o.containPoint(e,t))}else 0}),this)}),this),!!n;kx(this.id)},e.prototype.getVisual=function(t,e){var n=ua(this._model,t,{defaultMainType:"series"}),i=n.seriesModel;var r=i.getData(),o=n.hasOwnProperty("dataIndexInside")?n.dataIndexInside:n.hasOwnProperty("dataIndex")?r.indexOfRawIndex(n.dataIndex):null;return null!=o?jv(r,o,e):qv(r,e)},e.prototype.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},e.prototype.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]},e.prototype._initEvents=function(){var t=this;z(Ax,(function(e){var n=function(n){var i,r=t.getModel(),o=n.target,a="globalout"===e;if(a?i={}:o&&Qv(o,(function(t){var e=zl(t);if(e&&null!=e.dataIndex){var n=e.dataModel||r.getSeriesByIndex(e.seriesIndex);return i=n&&n.getDataParams(e.dataIndex,e.dataType,o)||{},!0}if(e.eventData)return i=A({},e.eventData),!0}),!0),i){var s=i.componentType,l=i.componentIndex;"markLine"!==s&&"markPoint"!==s&&"markArea"!==s||(s="series",l=i.seriesIndex);var u=s&&null!=l&&r.getComponent(s,l),c=u&&t["series"===u.mainType?"_chartsMap":"_componentsMap"][u.__viewId];0,i.event=n,i.type=e,t._$eventProcessor.eventInfo={targetEl:o,packedEvent:i,model:u,view:c},t.trigger(e,i)}};n.zrEventfulCallAtLast=!0,t._zr.on(e,n,t)}));var e=this._messageCenter;z(Ox,(function(n,i){e.on(i,(function(e){t.trigger(i,e)}))})),function(t,e,n){t.on("selectchanged",(function(t){var i=n.getModel();t.isFromClick?(Jv("map","selectchanged",e,i,t),Jv("pie","selectchanged",e,i,t)):"select"===t.fromAction?(Jv("map","selected",e,i,t),Jv("pie","selected",e,i,t)):"unselect"===t.fromAction&&(Jv("map","unselected",e,i,t),Jv("pie","unselected",e,i,t))}))}(e,this,this._api)},e.prototype.isDisposed=function(){return this._disposed},e.prototype.clear=function(){this._disposed?kx(this.id):this.setOption({series:[]},!0)},e.prototype.dispose=function(){if(this._disposed)kx(this.id);else{this._disposed=!0,this.getDom()&&fa(this.getDom(),Hx,"");var t=this,e=t._api,n=t._model;z(t._componentsViews,(function(t){t.dispose(n,e)})),z(t._chartsViews,(function(t){t.dispose(n,e)})),t._zr.dispose(),t._dom=t._model=t._chartsMap=t._componentsMap=t._chartsViews=t._componentsViews=t._scheduler=t._api=t._zr=t._throttledZrFlush=t._theme=t._coordSysMgr=t._messageCenter=null,delete Vx[t.id]}},e.prototype.resize=function(t){if(!this[Km])if(this._disposed)kx(this.id);else{this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var n=e.resetOption("media"),i=t&&t.silent;this[Jm]&&(null==i&&(i=this[Jm].silent),n=!0,this[Jm]=null),this[Km]=!0,Mx(this);try{n&&ox(this),lx.update.call(this,{type:"resize",animation:A({duration:0},t&&t.animation)})}catch(t){throw this[Km]=!1,t}this[Km]=!1,dx.call(this,i),px.call(this,i)}}},e.prototype.showLoading=function(t,e){if(this._disposed)kx(this.id);else if(q(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),Bx[t]){var n=Bx[t](this._api,e),i=this._zr;this._loadingFX=n,i.add(n)}},e.prototype.hideLoading=function(){this._disposed?kx(this.id):(this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null)},e.prototype.makeActionFromEvent=function(t){var e=A({},t);return e.type=Px[t.type],e},e.prototype.dispatchAction=function(t,e){if(this._disposed)kx(this.id);else if(q(e)||(e={silent:!!e}),Lx[t.type]&&this._model)if(this[Km])this._pendingActions.push(t);else{var n=e.silent;hx.call(this,t,n);var i=e.flush;i?this._zr.flush():!1!==i&&r.browser.weChat&&this._throttledZrFlush(),dx.call(this,n),px.call(this,n)}},e.prototype.updateLabelLayout=function(){Wm.trigger("series:layoutlabels",this._model,this._api,{updatedSeries:[]})},e.prototype.appendData=function(t){if(this._disposed)kx(this.id);else{var e=t.seriesIndex,n=this.getModel().getSeriesByIndex(e);0,n.appendData(t),this._scheduler.unfinished=!0,this.getZr().wakeUp()}},e.internalField=function(){function t(t){t.clearColorPalette(),t.eachSeries((function(t){t.clearColorPalette()}))}function e(t){for(var e=[],n=t.currentStates,i=0;i0?{duration:o,delay:i.get("delay"),easing:i.get("easing")}:null;n.eachRendered((function(t){if(t.states&&t.states.emphasis){if(nh(t))return;if(t instanceof sl&&function(t){var e=Gl(t);e.normalFill=t.style.fill,e.normalStroke=t.style.stroke;var n=t.states.select||{};e.selectFill=n.style&&n.style.fill||null,e.selectStroke=n.style&&n.style.stroke||null}(t),t.__dirty){var n=t.prevStates;n&&t.useStates(n)}if(r){t.stateTransition=a;var i=t.getTextContent(),o=t.getTextGuideLine();i&&(i.stateTransition=a),o&&(o.stateTransition=a)}t.__dirty&&e(t)}}))}ox=function(t){var e=t._scheduler;e.restorePipelines(t._model),e.prepareStageTasks(),ax(t,!0),ax(t,!1),e.plan()},ax=function(t,e){for(var n=t._model,i=t._scheduler,r=e?t._componentsViews:t._chartsViews,o=e?t._componentsMap:t._chartsMap,a=t._zr,s=t._api,l=0;le.get("hoverLayerThreshold")&&!r.node&&!r.worker&&e.eachSeries((function(e){if(!e.preventUsingHoverLayer){var n=t._chartsMap[e.__viewId];n.__alive&&n.eachRendered((function(t){t.states.emphasis&&(t.states.emphasis.hoverLayer=!0)}))}}))}(t,e),Wm.trigger("series:afterupdate",e,n,l)},bx=function(t){t[Qm]=!0,t.getZr().wakeUp()},Mx=function(t){t[$m]=(t[$m]+1)%1e3},Sx=function(t){t[Qm]&&(t.getZr().storage.traverse((function(t){nh(t)||e(t)})),t[Qm]=!1)},xx=function(t){return new(function(e){function i(){return null!==e&&e.apply(this,arguments)||this}return n(i,e),i.prototype.getCoordinateSystems=function(){return t._coordSysMgr.getCoordinateSystems()},i.prototype.getComponentByElement=function(e){for(;e;){var n=e.__ecComponentInfo;if(null!=n)return t._model.getComponent(n.mainType,n.index);e=e.parent}},i.prototype.enterEmphasis=function(e,n){du(e,n),bx(t)},i.prototype.leaveEmphasis=function(e,n){pu(e,n),bx(t)},i.prototype.enterBlur=function(e){fu(e),bx(t)},i.prototype.leaveBlur=function(e){gu(e),bx(t)},i.prototype.enterSelect=function(e){yu(e),bx(t)},i.prototype.leaveSelect=function(e){vu(e),bx(t)},i.prototype.getModel=function(){return t.getModel()},i.prototype.getViewOfComponentModel=function(e){return t.getViewOfComponentModel(e)},i.prototype.getViewOfSeriesModel=function(e){return t.getViewOfSeriesModel(e)},i.prototype.getMainProcessVersion=function(){return t[$m]},i}(Hf))(t)},_x=function(t){function e(t,e){for(var n=0;n=0)){i_.push(n);var o=wv.wrapStageHandler(n,r);o.__prio=e,o.__raw=n,t.push(o)}}function o_(t,e){Bx[t]=e}function a_(t,e,n){var i=Um("registerMap");i&&i(t,e,n)}var s_=function(t){var e=(t=T(t)).type,n="";e||Yo(n);var i=e.split(":");2!==i.length&&Yo(n);var r=!1;"echarts"===i[0]&&(e=i[1],r=!0),t.__isBuiltIn=r,oy.set(e,t)};function l_(t,e,n,i){return{eventContent:{selected:Mu(n),isFromClick:e.isFromClick||!1}}}n_(Zm,vv),n_(jm,xv),n_(jm,_v),n_(Zm,Xv),n_(jm,Zv),n_(7e3,(function(t,e){t.eachRawSeries((function(n){if(!t.isSeriesFiltered(n)){var i=n.getData();i.hasItemVisual()&&i.each((function(t){var n=i.getItemVisual(t,"decal");n&&(i.ensureUniqueItemVisual(t,"style").decal=Bm(n,e))}));var r=i.getVisual("decal");if(r)i.getVisual("style").decal=Bm(r,e)}}))})),jx(dg),qx(900,(function(t){var e=yt();t.eachSeries((function(t){var n=t.get("stack");if(n){var i=e.get(n)||e.set(n,[]),r=t.getData(),o={stackResultDimension:r.getCalculationInfo("stackResultDimension"),stackedOverDimension:r.getCalculationInfo("stackedOverDimension"),stackedDimension:r.getCalculationInfo("stackedDimension"),stackedByDimension:r.getCalculationInfo("stackedByDimension"),isStackedByIndex:r.getCalculationInfo("isStackedByIndex"),data:r,seriesModel:t};if(!o.stackedDimension||!o.isStackedByIndex&&!o.stackedByDimension)return;i.push(o)}})),e.each((function(t){0!==t.length&&("seriesDesc"===(t[0].seriesModel.get("stackOrder")||"seriesAsc")&&t.reverse(),z(t,(function(e,n){e.data.setCalculationInfo("stackedOnSeries",n>0?t[n-1].seriesModel:null)})),function(t){z(t,(function(e,n){var i=[],r=[NaN,NaN],o=[e.stackResultDimension,e.stackedOverDimension],a=e.data,s=e.isStackedByIndex,l=e.seriesModel.get("stackStrategy")||"samesign";a.modify(o,(function(o,u,c){var h,d,p=a.get(e.stackedDimension,c);if(isNaN(p))return r;s?d=a.getRawIndex(c):h=a.get(e.stackedByDimension,c);for(var f=NaN,g=n-1;g>=0;g--){var y=t[g];if(s||(d=y.data.rawIndexOf(y.stackedByDimension,h)),d>=0){var v=y.data.getByRawIndex(y.stackResultDimension,d);if("all"===l||"positive"===l&&v>0||"negative"===l&&v<0||"samesign"===l&&p>=0&&v>0||"samesign"===l&&p<=0&&v<0){p=Mo(p,v),f=v;break}}}return i[0]=p,i[1]=f,i}))}))}(t))}))})),o_("default",(function(t,e){k(e=e||{},{text:"loading",textColor:tf.color.primary,fontSize:12,fontWeight:"normal",fontStyle:"normal",fontFamily:"sans-serif",maskColor:"rgba(255,255,255,0.8)",showSpinner:!0,color:tf.color.theme[0],spinnerRadius:10,lineWidth:5,zlevel:0});var n=new to,i=new xl({style:{fill:e.maskColor},zlevel:e.zlevel,z:1e4});n.add(i);var r,o=new Sl({style:{text:e.text,fill:e.textColor,fontSize:e.fontSize,fontWeight:e.fontWeight,fontStyle:e.fontStyle,fontFamily:e.fontFamily},zlevel:e.zlevel,z:10001}),a=new xl({style:{fill:"none"},textContent:o,textConfig:{position:"right",distance:10},zlevel:e.zlevel,z:10001});return n.add(a),e.showSpinner&&((r=new Nc({shape:{startAngle:-bv/2,endAngle:-bv/2+.1,r:e.spinnerRadius},style:{stroke:e.color,lineCap:"round",lineWidth:e.lineWidth},zlevel:e.zlevel,z:10001})).animateShape(!0).when(1e3,{endAngle:3*bv/2}).start("circularInOut"),r.animateShape(!0).when(1e3,{startAngle:3*bv/2}).delay(300).start("circularInOut"),n.add(r)),n.resize=function(){var n=o.getBoundingRect().width,s=e.showSpinner?e.spinnerRadius:0,l=(t.getWidth()-2*s-(e.showSpinner&&n?10:0)-n)/2-(e.showSpinner&&n?0:5+n/2)+(e.showSpinner?0:n/2)+(n?0:s),u=t.getHeight()/2;e.showSpinner&&r.setShape({cx:l,cy:u}),a.setShape({x:l-s,y:u-s,width:2*s,height:2*s}),i.setShape({x:0,y:0,width:t.getWidth(),height:t.getHeight()})},n.resize(),n})),Qx({type:Yl,event:Yl,update:Yl},bt),Qx({type:Xl,event:Xl,update:Xl},bt),Qx({type:Zl,event:Kl,update:Zl,action:bt,refineEvent:l_,publishNonRefinedEvent:!0}),Qx({type:jl,event:Kl,update:jl,action:bt,refineEvent:l_,publishNonRefinedEvent:!0}),Qx({type:ql,event:Kl,update:ql,action:bt,refineEvent:l_,publishNonRefinedEvent:!0}),Zx("default",{}),Zx("dark",Wv);var u_=[],c_={registerPreprocessor:jx,registerProcessor:qx,registerPostInit:Kx,registerPostUpdate:$x,registerUpdateLifecycle:Jx,registerAction:Qx,registerCoordinateSystem:t_,registerLayout:e_,registerVisual:n_,registerTransform:s_,registerLoading:o_,registerMap:a_,registerImpl:function(t,e){Hm[t]=e},PRIORITY:qm,ComponentModel:Qp,ComponentView:Ky,SeriesModel:Wy,ChartView:tv,registerComponentModel:function(t){Qp.registerClass(t)},registerComponentView:function(t){Ky.registerClass(t)},registerSeriesModel:function(t){Wy.registerClass(t)},registerChartView:function(t){tv.registerClass(t)},registerCustomSeries:function(t,e){Xm(t,e)},registerSubTypeDefaulter:function(t,e){Qp.registerSubTypeDefaulter(t,e)},registerPainter:function(t,e){ao(t,e)}};function h_(t){U(t)?z(t,(function(t){h_(t)})):P(u_,t)>=0||(u_.push(t),Y(t)&&(t={install:t}),t.install(c_))}function d_(t){return null==t?0:t.length||1}function p_(t){return t}var f_=function(){function t(t,e,n,i,r,o){this._old=t,this._new=e,this._oldKeyGetter=n||p_,this._newKeyGetter=i||p_,this.context=r,this._diffModeMultiple="multiple"===o}return t.prototype.add=function(t){return this._add=t,this},t.prototype.update=function(t){return this._update=t,this},t.prototype.updateManyToOne=function(t){return this._updateManyToOne=t,this},t.prototype.updateOneToMany=function(t){return this._updateOneToMany=t,this},t.prototype.updateManyToMany=function(t){return this._updateManyToMany=t,this},t.prototype.remove=function(t){return this._remove=t,this},t.prototype.execute=function(){this[this._diffModeMultiple?"_executeMultiple":"_executeOneToOne"]()},t.prototype._executeOneToOne=function(){var t=this._old,e=this._new,n={},i=new Array(t.length),r=new Array(e.length);this._initIndexMap(t,null,i,"_oldKeyGetter"),this._initIndexMap(e,n,r,"_newKeyGetter");for(var o=0;o1){var u=s.shift();1===s.length&&(n[a]=s[0]),this._update&&this._update(u,o)}else 1===l?(n[a]=null,this._update&&this._update(s,o)):this._remove&&this._remove(o)}this._performRestAdd(r,n)},t.prototype._executeMultiple=function(){var t=this._old,e=this._new,n={},i={},r=[],o=[];this._initIndexMap(t,n,r,"_oldKeyGetter"),this._initIndexMap(e,i,o,"_newKeyGetter");for(var a=0;a1&&1===h)this._updateManyToOne&&this._updateManyToOne(u,l),i[s]=null;else if(1===c&&h>1)this._updateOneToMany&&this._updateOneToMany(u,l),i[s]=null;else if(1===c&&1===h)this._update&&this._update(u,l),i[s]=null;else if(c>1&&h>1)this._updateManyToMany&&this._updateManyToMany(u,l),i[s]=null;else if(c>1)for(var d=0;d1)for(var a=0;a30}var T_,C_,D_,A_,k_,L_,P_,O_=q,R_=E,N_="undefined"==typeof Int32Array?Array:Int32Array,z_=["hasItemOption","_nameList","_idList","_invertedIndicesMap","_dimSummary","userOutput","_rawData","_dimValueGetter","_nameDimIdx","_idDimIdx","_nameRepeatCount"],E_=["_approximateExtent"],B_=function(){function t(t,e){var n;this.type="list",this._dimOmitted=!1,this._nameList=[],this._idList=[],this._visual={},this._layout={},this._itemVisuals=[],this._itemLayouts=[],this._graphicEls=[],this._approximateExtent={},this._calculationInfo={},this.hasItemOption=!1,this.TRANSFERABLE_METHODS=["cloneShallow","downSample","minmaxDownSample","lttbDownSample","map"],this.CHANGABLE_METHODS=["filterSelf","selectRange"],this.DOWNSAMPLE_METHODS=["downSample","minmaxDownSample","lttbDownSample"];var i=!1;w_(t)?(n=t.dimensions,this._dimOmitted=t.isDimensionOmitted(),this._schema=t):(i=!0,n=t),n=n||["x","y"];for(var r={},o=[],a={},s=!1,l={},u=0;u=e)){var n=this._store.getProvider();this._updateOrdinalMeta();var i=this._nameList,r=this._idList;if(n.getSource().sourceFormat===hf&&!n.pure)for(var o=[],a=t;a0},t.prototype.ensureUniqueItemVisual=function(t,e){var n=this._itemVisuals,i=n[t];i||(i=n[t]={});var r=i[e];return null==r&&(U(r=this.getVisual(e))?r=r.slice():O_(r)&&(r=A({},r)),i[e]=r),r},t.prototype.setItemVisual=function(t,e,n){var i=this._itemVisuals[t]||{};this._itemVisuals[t]=i,O_(e)?A(i,e):i[e]=n},t.prototype.clearAllVisual=function(){this._visual={},this._itemVisuals=[]},t.prototype.setLayout=function(t,e){O_(t)?A(this._layout,t):this._layout[t]=e},t.prototype.getLayout=function(t){return this._layout[t]},t.prototype.getItemLayout=function(t){return this._itemLayouts[t]},t.prototype.setItemLayout=function(t,e,n){this._itemLayouts[t]=n?A(this._itemLayouts[t]||{},e):e},t.prototype.clearItemLayouts=function(){this._itemLayouts.length=0},t.prototype.setItemGraphicEl=function(t,e){var n=this.hostModel&&this.hostModel.seriesIndex;El(n,this.dataType,t,e),this._graphicEls[t]=e},t.prototype.getItemGraphicEl=function(t){return this._graphicEls[t]},t.prototype.eachItemGraphicEl=function(t,e){z(this._graphicEls,(function(n,i){n&&t&&t.call(e,n,i)}))},t.prototype.cloneShallow=function(e){return e||(e=new t(this._schema?this._schema:R_(this.dimensions,this._getDimInfo,this),this.hostModel)),k_(e,this),e._store=this._store,e},t.prototype.wrapMethod=function(t,e){var n=this[t];Y(n)&&(this.__wrappedMethods=this.__wrappedMethods||[],this.__wrappedMethods.push(t),this[t]=function(){var t=n.apply(this,arguments);return e.apply(this,[t].concat(at(arguments)))})},t.internalField=(T_=function(t){var e=t._invertedIndicesMap;z(e,(function(n,i){var r=t._dimInfos[i],o=r.ordinalMeta,a=t._store;if(o){n=e[i]=new N_(o.categories.length);for(var s=0;s1&&(s+="__ec__"+u),i[e]=s}})),t}();function V_(t,e){_g(t)||(t=wg(t));var n=(e=e||{}).coordDimensions||[],i=e.dimensionsDefine||t.dimensionsDefine||[],r=yt(),o=[],a=function(t,e,n,i){var r=Math.max(t.dimensionsDetectedCount||1,e.length,n.length,i||0);return z(e,(function(t){var e;q(t)&&(e=t.dimsDef)&&(r=Math.max(r,e.length))})),r}(t,n,i,e.dimensionsCount),s=e.canOmitUnusedDimensions&&I_(a),l=i===t.dimensionsDefine,u=l?M_(t):S_(i),c=e.encodeDefine;!c&&e.encodeDefaulter&&(c=e.encodeDefaulter(t,a));for(var h=yt(c),d=new dy(a),p=0;p0&&(i.name=r+(o-1)),o++,e.set(r,o)}}(o),new b_({source:t,dimensions:o,fullDimensionCount:a,dimensionOmitted:s})}function G_(t,e,n){if(n||e.hasKey(t)){for(var i=0;e.hasKey(t+i);)i++;t+=i}return e.set(t,!0),t}var F_=function(t){this.coordSysDims=[],this.axisMap=yt(),this.categoryAxisMap=yt(),this.coordSysName=t};var W_={cartesian2d:function(t,e,n,i){var r=t.getReferringComponents("xAxis",ha).models[0],o=t.getReferringComponents("yAxis",ha).models[0];e.coordSysDims=["x","y"],n.set("x",r),n.set("y",o),H_(r)&&(i.set("x",r),e.firstCategoryDimIndex=0),H_(o)&&(i.set("y",o),null==e.firstCategoryDimIndex&&(e.firstCategoryDimIndex=1))},singleAxis:function(t,e,n,i){var r=t.getReferringComponents("singleAxis",ha).models[0];e.coordSysDims=["single"],n.set("single",r),H_(r)&&(i.set("single",r),e.firstCategoryDimIndex=0)},polar:function(t,e,n,i){var r=t.getReferringComponents("polar",ha).models[0],o=r.findAxisModel("radiusAxis"),a=r.findAxisModel("angleAxis");e.coordSysDims=["radius","angle"],n.set("radius",o),n.set("angle",a),H_(o)&&(i.set("radius",o),e.firstCategoryDimIndex=0),H_(a)&&(i.set("angle",a),null==e.firstCategoryDimIndex&&(e.firstCategoryDimIndex=1))},geo:function(t,e,n,i){e.coordSysDims=["lng","lat"]},parallel:function(t,e,n,i){var r=t.ecModel,o=r.getComponent("parallel",t.get("parallelIndex")),a=e.coordSysDims=o.dimensions.slice();z(o.parallelAxisIndex,(function(t,o){var s=r.getComponent("parallelAxis",t),l=a[o];n.set(l,s),H_(s)&&(i.set(l,s),null==e.firstCategoryDimIndex&&(e.firstCategoryDimIndex=o))}))},matrix:function(t,e,n,i){var r=t.getReferringComponents("matrix",ha).models[0];e.coordSysDims=["x","y"];var o=r.getDimensionModel("x"),a=r.getDimensionModel("y");n.set("x",o),n.set("y",a),i.set("x",o),i.set("y",a)}};function H_(t){return"category"===t.get("type")}function U_(t,e,n){var i,r,o,a=(n=n||{}).byIndex,s=n.stackedCoordDimension;!function(t){return!w_(t.schema)}(e)?(r=e.schema,i=r.dimensions,o=e.store):i=e;var l,u,c,h,d=!(!t||!t.get("stack"));if(z(i,(function(t,e){X(t)&&(i[e]=t={name:t}),d&&!t.isExtraCoord&&(a||l||!t.ordinalMeta||(l=t),u||"ordinal"===t.type||"time"===t.type||s&&s!==t.coordDim||(u=t))})),!u||a||l||(a=!0),u){c="__\0ecstackresult_"+t.id,h="__\0ecstackedover_"+t.id,l&&(l.createInvertedIndices=!0);var p=u.coordDim,f=u.type,g=0;z(i,(function(t){t.coordDim===p&&g++}));var y={name:c,coordDim:p,coordDimIndex:g,type:f,isExtraCoord:!0,isCalculationCoord:!0,storeDimIndex:i.length},v={name:h,coordDim:h,coordDimIndex:g+1,type:f,isExtraCoord:!0,isCalculationCoord:!0,storeDimIndex:i.length+1};r?(o&&(y.storeDimIndex=o.ensureCalculationDimension(h,f),v.storeDimIndex=o.ensureCalculationDimension(c,f)),r.appendCalculationDimension(y),r.appendCalculationDimension(v)):(i.push(y),i.push(v))}return{stackedDimension:u&&u.name,stackedByDimension:l&&l.name,isStackedByIndex:a,stackedOverDimension:h,stackResultDimension:c}}function Y_(t,e){return!!e&&e===t.getCalculationInfo("stackedDimension")}function X_(t,e){return Y_(t,e)?t.getCalculationInfo("stackResultDimension"):e}function Z_(t,e,n){n=n||{};var i,r=e.getSourceManager(),o=!1;t?(o=!0,i=wg(t)):o=(i=r.getSource()).sourceFormat===hf;var a=function(t){var e=t.get("coordinateSystem"),n=new F_(e),i=W_[e];if(i)return i(t,n,n.axisMap,n.categoryAxisMap),n}(e),s=function(t,e){var n,i=t.get("coordinateSystem"),r=Tp.get(i);return e&&e.coordSysDims&&(n=E(e.coordSysDims,(function(t){var n={name:t},i=e.axisMap.get(t);if(i){var r=i.get("type");n.type=v_(r)}return n}))),n||(n=r&&(r.getDimensionsInfo?r.getDimensionsInfo():r.dimensions.slice())||["x","y"]),n}(e,a),l=n.useEncodeDefaulter,u=Y(l)?l:l?H(Sf,s,e):null,c=V_(i,{coordDimensions:s,generateCoord:n.generateCoord,encodeDefine:e.getEncode(),encodeDefaulter:u,canOmitUnusedDimensions:!o}),h=function(t,e,n){var i,r;return n&&z(t,(function(t,o){var a=t.coordDim,s=n.categoryAxisMap.get(a);s&&(null==i&&(i=o),t.ordinalMeta=s.getOrdinalMeta(),e&&(t.createInvertedIndices=!0)),null!=t.otherDims.itemName&&(r=!0)})),r||null==i||(t[i].otherDims.itemName=0),i}(c.dimensions,n.createInvertedIndices,a),d=o?null:r.getSharedDataStore(c),p=U_(e,{schema:c,store:d}),f=new B_(c,e);f.setCalculationInfo(p);var g=null!=h&&function(t){if(t.sourceFormat===hf){var e=function(t){var e=0;for(;er&&(a=o.interval=r);var s=o.intervalPrecision=$_(a);return function(t,e){!isFinite(t[0])&&(t[0]=e[0]),!isFinite(t[1])&&(t[1]=e[1]),J_(t,0,e),J_(t,1,e),t[0]>t[1]&&(t[0]=t[1])}(o.niceTickExtent=[mo(Math.ceil(t[0]/a)*a,s),mo(Math.floor(t[1]/a)*a,s)],t),o}function K_(t){var e=Math.pow(10,Lo(t)),n=t/e;return n?2===n?n=3:3===n?n=5:n*=2:n=1,mo(n*e)}function $_(t){return _o(t)+2}function J_(t,e,n){t[e]=Math.max(Math.min(t[e],n[1]),n[0])}function Q_(t,e){return t>=e[0]&&t<=e[1]}var tb=function(){function t(){this.normalize=eb,this.scale=nb}return t.prototype.updateMethods=function(t){t.hasBreaks()?(this.normalize=W(t.normalize,t),this.scale=W(t.scale,t)):(this.normalize=eb,this.scale=nb)},t}();function eb(t,e){return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])}function nb(t,e){return t*(e[1]-e[0])+e[0]}function ib(t,e,n){var i=Math.log(t);return[Math.log(n?e[0]:Math.max(0,e[0]))/i,Math.log(n?e[1]:Math.max(0,e[1]))/i]}var rb=function(){function t(t){this._calculator=new tb,this._setting=t||{},this._extent=[1/0,-1/0];var e=Nd();e&&(this._brkCtx=e.createScaleBreakContext(),this._brkCtx.update(this._extent))}return t.prototype.getSetting=function(t){return this._setting[t]},t.prototype._innerUnionExtent=function(t){var e=this._extent;this._innerSetExtent(t[0]e[1]?t[1]:e[1])},t.prototype.unionExtentFromData=function(t,e){this._innerUnionExtent(t.getApproximateExtent(e))},t.prototype.getExtent=function(){return this._extent.slice()},t.prototype.setExtent=function(t,e){this._innerSetExtent(t,e)},t.prototype._innerSetExtent=function(t,e){var n=this._extent;isNaN(t)||(n[0]=t),isNaN(e)||(n[1]=e),this._brkCtx&&this._brkCtx.update(n)},t.prototype.setBreaksFromOption=function(t){var e=Nd();e&&this._innerSetBreak(e.parseAxisBreakOption(t,W(this.parse,this)))},t.prototype._innerSetBreak=function(t){this._brkCtx&&(this._brkCtx.setBreaks(t),this._calculator.updateMethods(this._brkCtx),this._brkCtx.update(this._extent))},t.prototype._innerGetBreaks=function(){return this._brkCtx?this._brkCtx.breaks:[]},t.prototype.hasBreaks=function(){return!!this._brkCtx&&this._brkCtx.hasBreaks()},t.prototype._getExtentSpanWithBreaks=function(){return this._brkCtx&&this._brkCtx.hasBreaks()?this._brkCtx.getExtentSpan():this._extent[1]-this._extent[0]},t.prototype.isInExtentRange=function(t){return this._extent[0]<=t&&this._extent[1]>=t},t.prototype.isBlank=function(){return this._isBlank},t.prototype.setBlank=function(t){this._isBlank=t},t}();Ca(rb);var ob=0,ab=function(){function t(t){this.categories=t.categories||[],this._needCollect=t.needCollect,this._deduplication=t.deduplication,this.uid=++ob,this._onCollect=t.onCollect}return t.createByAxisModel=function(e){var n=e.option,i=n.data,r=i&&E(i,sb);return new t({categories:r,needCollect:!r,deduplication:!1!==n.dedplication})},t.prototype.getOrdinal=function(t){return this._getOrCreateMap().get(t)},t.prototype.parseAndCollect=function(t){var e,n=this._needCollect;if(!X(t)&&!n)return t;if(n&&!this._deduplication)return e=this.categories.length,this.categories[e]=t,this._onCollect&&this._onCollect(t,e),e;var i=this._getOrCreateMap();return null==(e=i.get(t))&&(n?(e=this.categories.length,this.categories[e]=t,i.set(t,e),this._onCollect&&this._onCollect(t,e)):e=NaN),e},t.prototype._getOrCreateMap=function(){return this._map||(this._map=yt(this.categories))},t}();function sb(t){return q(t)&&null!=t.value?t.value:t+""}var lb=function(t){function e(e){var n=t.call(this,e)||this;n.type="ordinal";var i=n.getSetting("ordinalMeta");return i||(i=new ab({})),U(i)&&(i=new ab({categories:E(i,(function(t){return q(t)?t.value:t}))})),n._ordinalMeta=i,n._extent=n.getSetting("extent")||[0,i.categories.length-1],n}return n(e,t),e.prototype.parse=function(t){return null==t?NaN:X(t)?this._ordinalMeta.getOrdinal(t):Math.round(t)},e.prototype.contain=function(t){return Q_(t,this._extent)&&t>=0&&t=0&&t=0&&t=t},e.prototype.getOrdinalMeta=function(){return this._ordinalMeta},e.prototype.calcNiceTicks=function(){},e.prototype.calcNiceExtent=function(){},e.type="ordinal",e}(rb);rb.registerClass(lb);var ub=mo,cb=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.type="interval",e._interval=0,e._intervalPrecision=2,e}return n(e,t),e.prototype.parse=function(t){return null==t||""===t?NaN:Number(t)},e.prototype.contain=function(t){return Q_(t,this._extent)},e.prototype.normalize=function(t){return this._calculator.normalize(t,this._extent)},e.prototype.scale=function(t){return this._calculator.scale(t,this._extent)},e.prototype.getInterval=function(){return this._interval},e.prototype.setInterval=function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=$_(t)},e.prototype.getTicks=function(t){t=t||{};var e=this._interval,n=this._extent,i=this._niceExtent,r=this._intervalPrecision,o=Nd(),a=[];if(!e)return a;if("only_break"===t.breakTicks&&o)return o.addBreaksToTicks(a,this._brkCtx.breaks,this._extent),a;n[0]=0&&(l=ub(l+u*e,r))}if(a.length>0&&l===a[a.length-1].value)break;if(a.length>1e4)return[]}var c=a.length?a[a.length-1].value:i[1];return n[1]>c&&(t.expandToNicedExtent?a.push({value:ub(c+e,r)}):a.push({value:n[1]})),o&&o.pruneTicksByBreak(t.pruneByBreak,a,this._brkCtx.breaks,(function(t){return t.value}),this._interval,this._extent),"none"!==t.breakTicks&&o&&o.addBreaksToTicks(a,this._brkCtx.breaks,this._extent),a},e.prototype.getMinorTicks=function(t){for(var e=this.getTicks({expandToNicedExtent:!0}),n=[],i=this.getExtent(),r=1;ri[0]&&h0&&(o=null===o?s:Math.min(o,s))}n[i]=o}}return n}(t),n=[];return z(t,(function(t){var i,r=t.coordinateSystem.getBaseAxis(),o=r.getExtent();if("category"===r.type)i=r.getBandWidth();else if("value"===r.type||"time"===r.type){var a=r.dim+"_"+r.index,s=e[a],l=Math.abs(o[1]-o[0]),u=r.scale.getExtent(),c=Math.abs(u[1]-u[0]);i=s?l/c*s:l}else{var h=t.getData();i=Math.abs(o[1]-o[0])/h.count()}var d=yo(t.get("barWidth"),i),p=yo(t.get("barMaxWidth"),i),f=yo(t.get("barMinWidth")||(Sb(t)?.5:1),i),g=t.get("barGap"),y=t.get("barCategoryGap"),v=t.get("defaultBarGap");n.push({bandWidth:i,barWidth:d,barMaxWidth:p,barMinWidth:f,barGap:g,barCategoryGap:y,defaultBarGap:v,axisKey:yb(r),stackId:gb(t)})})),xb(n)}function xb(t){var e={};z(t,(function(t,n){var i=t.axisKey,r=t.bandWidth,o=e[i]||{bandWidth:r,remainedWidth:r,autoWidthCount:0,categoryGap:null,gap:t.defaultBarGap||0,stacks:{}},a=o.stacks;e[i]=o;var s=t.stackId;a[s]||o.autoWidthCount++,a[s]=a[s]||{width:0,maxWidth:0};var l=t.barWidth;l&&!a[s].width&&(a[s].width=l,l=Math.min(o.remainedWidth,l),o.remainedWidth-=l);var u=t.barMaxWidth;u&&(a[s].maxWidth=u);var c=t.barMinWidth;c&&(a[s].minWidth=c);var h=t.barGap;null!=h&&(o.gap=h);var d=t.barCategoryGap;null!=d&&(o.categoryGap=d)}));var n={};return z(e,(function(t,e){n[e]={};var i=t.stacks,r=t.bandWidth,o=t.categoryGap;if(null==o){var a=F(i).length;o=Math.max(35-4*a,15)+"%"}var s=yo(o,r),l=yo(t.gap,1),u=t.remainedWidth,c=t.autoWidthCount,h=(u-s)/(c+(c-1)*l);h=Math.max(h,0),z(i,(function(t){var e=t.maxWidth,n=t.minWidth;if(t.width){i=t.width;e&&(i=Math.min(i,e)),n&&(i=Math.max(i,n)),t.width=i,u-=i+l*i,c--}else{var i=h;e&&ei&&(i=n),i!==h&&(t.width=i,u-=i+l*i,c--)}})),h=(u-s)/(c+(c-1)*l),h=Math.max(h,0);var d,p=0;z(i,(function(t,e){t.width||(t.width=h),d=t,p+=t.width*(1+l)})),d&&(p-=d.width*l);var f=-p/2;z(i,(function(t,i){n[e][i]=n[e][i]||{bandWidth:r,offset:f,width:t.width},f+=t.width*(1+l)}))})),n}function _b(t,e){var n=vb(t,e),i=mb(n);z(n,(function(t){var e=t.getData(),n=t.coordinateSystem.getBaseAxis(),r=gb(t),o=i[yb(n)][r],a=o.offset,s=o.width;e.setLayout({bandWidth:o.bandWidth,offset:a,size:s})}))}function bb(t){return{seriesType:t,plan:$y(),reset:function(t){if(wb(t)){var e=t.getData(),n=t.coordinateSystem,i=n.getBaseAxis(),r=n.getOtherAxis(i),o=e.getDimensionIndex(e.mapDimension(r.dim)),a=e.getDimensionIndex(e.mapDimension(i.dim)),s=t.get("showBackground",!0),l=e.mapDimension(r.dim),u=e.getCalculationInfo("stackResultDimension"),c=Y_(e,l)&&!!e.getCalculationInfo("stackedOnSeries"),h=r.isHorizontal(),d=function(t,e){var n=e.model.get("startValue");n||(n=0);return e.toGlobalCoord(e.dataToCoord("log"===e.type?n>0?n:1:n))}(0,r),p=Sb(t),f=t.get("barMinHeight")||0,g=u&&e.getDimensionIndex(u),y=e.getLayout("size"),v=e.getLayout("offset");return{progress:function(t,e){for(var i,r=t.count,l=p&&pb(3*r),u=p&&s&&pb(3*r),m=p&&pb(r),x=n.master.getRect(),_=h?x.width:x.height,b=e.getStore(),w=0;null!=(i=t.next());){var S=b.get(c?g:o,i),M=b.get(a,i),I=d,T=void 0;c&&(T=+S-b.get(o,i));var C=void 0,D=void 0,A=void 0,k=void 0;if(h){var L=n.dataToPoint([S,M]);if(c)I=n.dataToPoint([T,M])[0];C=I,D=L[1]+v,A=L[0]-I,k=y,Math.abs(A)a){0;break}if(p[s](p[r]()+t),d=p.getTime(),o){var f=o.calcNiceTickMultiple(d,h);f>0&&(p[s](p[r]()+f*t),d=p.getTime())}}c.push({value:d,notAdd:!0})}function c(t,r,o){var a=[],s=!r.length;if(!Tb(qd(t),i[0],i[1],n)){s&&(r=[{value:Pb(i[0],t,n)},{value:i[1]}]);for(var l=0;l=i[0]&&c<=i[1]&&u(d,c,h,p,f,g,a),"year"===t&&o.length>1&&0===l&&o.unshift({value:o[0].value-d})}}for(l=0;l=i[0]&&x<=i[1]&&p++)}var _=r/e;if(p>1.5*_&&f>_/1.5)break;if(h.push(v),p>_||t===s[g])break}d=[]}}var b=V(E(h,(function(t){return V(t,(function(t){return t.value>=i[0]&&t.value<=i[1]&&!t.notAdd}))})),(function(t){return t.length>0})),w=[],S=b.length-1;for(g=0;gn&&(this._approxInterval=n);var r=Ib.length,o=Math.min(function(t,e,n,i){for(;n>>1;t[r][1]16?16:t>7.5?7:t>3.5?4:t>1.5?2:1}function Db(t){return(t/=2592e6)>6?6:t>3?3:t>2?2:1}function Ab(t){return(t/=Bd)>12?12:t>6?6:t>3.5?4:t>2?2:1}function kb(t,e){return(t/=e?Ed:zd)>30?30:t>20?20:t>15?15:t>10?10:t>5?5:t>2?2:1}function Lb(t){return Po(t,!0)}function Pb(t,e,n){var i=Math.max(0,P(Yd,e)-1);return Qd(new Date(t),Yd[i],n).getTime()}rb.registerClass(Mb);var Ob=mo,Rb=Math.floor,Nb=Math.ceil,zb=Math.pow,Eb=Math.log,Bb=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.type="log",e.base=10,e._originalScale=new cb,e}return n(e,t),e.prototype.getTicks=function(e){e=e||{};var n=this._extent.slice(),i=this._originalScale.getExtent(),r=t.prototype.getTicks.call(this,e),o=this.base,a=this._originalScale._innerGetBreaks(),s=Nd();return E(r,(function(t){var e,r=t.value,l=null,u=zb(o,r);if(r===n[0]&&this._fixMin?l=i[0]:r===n[1]&&this._fixMax&&(l=i[1]),s){var c=s.getTicksLogTransformBreak(t,o,a,Vb);e=c.vBreak,null==l&&(l=c.brkRoundingCriterion)}return null!=l&&(u=Vb(u,l)),{value:u,break:e}}),this)},e.prototype._getNonTransBreaks=function(){return this._originalScale._innerGetBreaks()},e.prototype.setExtent=function(e,n){this._originalScale.setExtent(e,n);var i=ib(this.base,[e,n]);t.prototype.setExtent.call(this,i[0],i[1])},e.prototype.getExtent=function(){var e=this.base,n=t.prototype.getExtent.call(this);n[0]=zb(e,n[0]),n[1]=zb(e,n[1]);var i=this._originalScale.getExtent();return this._fixMin&&(n[0]=Vb(n[0],i[0])),this._fixMax&&(n[1]=Vb(n[1],i[1])),n},e.prototype.unionExtentFromData=function(t,e){this._originalScale.unionExtentFromData(t,e);var n=ib(this.base,t.getApproximateExtent(e),!0);this._innerUnionExtent(n)},e.prototype.calcNiceTicks=function(t){t=t||10;var e=this._extent.slice(),n=this._getExtentSpanWithBreaks();if(isFinite(n)&&!(n<=0)){var i=ko(n);for(t/n*i<=.5&&(i*=10);!isNaN(i)&&Math.abs(i)<1&&Math.abs(i)>0;)i*=10;var r=[Ob(Nb(e[0]/i)*i),Ob(Rb(e[1]/i)*i)];this._interval=i,this._intervalPrecision=$_(i),this._niceExtent=r}},e.prototype.calcNiceExtent=function(e){t.prototype.calcNiceExtent.call(this,e),this._fixMin=e.fixMin,this._fixMax=e.fixMax},e.prototype.contain=function(e){return e=Eb(e)/Eb(this.base),t.prototype.contain.call(this,e)},e.prototype.normalize=function(e){return e=Eb(e)/Eb(this.base),t.prototype.normalize.call(this,e)},e.prototype.scale=function(e){return e=t.prototype.scale.call(this,e),zb(this.base,e)},e.prototype.setBreaksFromOption=function(t){var e=Nd();if(e){var n=e.logarithmicParseBreaksFromOption(t,this.base,W(this.parse,this)),i=n.parsedOriginal,r=n.parsedLogged;this._originalScale._innerSetBreak(i),this._innerSetBreak(r)}},e.type="log",e}(cb);function Vb(t,e){return Ob(t,_o(e))}rb.registerClass(Bb);var Gb=function(){function t(t,e,n){this._prepareParams(t,e,n)}return t.prototype._prepareParams=function(t,e,n){n[1]0&&s>0&&!l&&(a=0),a<0&&s<0&&!u&&(s=0));var h=this._determinedMin,d=this._determinedMax;return null!=h&&(a=h,l=!0),null!=d&&(s=d,u=!0),{min:a,max:s,minFixed:l,maxFixed:u,isBlank:c}},t.prototype.modifyDataMinMax=function(t,e){this[Wb[t]]=e},t.prototype.setDeterminedMinMax=function(t,e){var n=Fb[t];this[n]=e},t.prototype.freeze=function(){this.frozen=!0},t}(),Fb={min:"_determinedMin",max:"_determinedMax"},Wb={min:"_dataMin",max:"_dataMax"};function Hb(t,e,n){var i=t.rawExtentInfo;return i||(i=new Gb(t,e,n),t.rawExtentInfo=i,i)}function Ub(t,e){return null==e?null:nt(e)?NaN:t.parse(e)}function Yb(t,e){var n=t.type,i=Hb(t,e,t.getExtent()).calculate();t.setBlank(i.isBlank);var r=i.min,o=i.max,a=e.ecModel;if(a&&"time"===n){var s=vb("bar",a),l=!1;if(z(s,(function(t){l=l||t.getBaseAxis()===e.axis})),l){var u=mb(s),c=function(t,e,n,i){var r=n.axis.getExtent(),o=Math.abs(r[1]-r[0]),a=function(t,e,n){if(t&&e){var i=t[yb(e)];return null!=i&&null!=n?i[gb(n)]:i}}(i,n.axis);if(void 0===a)return{min:t,max:e};var s=1/0;z(a,(function(t){s=Math.min(t.offset,s)}));var l=-1/0;z(a,(function(t){l=Math.max(t.offset+t.width,l)})),s=Math.abs(s),l=Math.abs(l);var u=s+l,c=e-t,h=c/(1-(s+l)/o)-c;return e+=h*(l/u),t-=h*(s/u),{min:t,max:e}}(r,o,e,u);r=c.min,o=c.max}}return{extent:[r,o],fixMin:i.minFixed,fixMax:i.maxFixed}}function Xb(t,e){var n=e,i=Yb(t,n),r=i.extent,o=n.get("splitNumber");t instanceof Bb&&(t.base=n.get("logBase"));var a=t.type,s=n.get("interval"),l="interval"===a||"time"===a;t.setBreaksFromOption(ew(n)),t.setExtent(r[0],r[1]),t.calcNiceExtent({splitNumber:o,fixMin:i.fixMin,fixMax:i.fixMax,minInterval:l?n.get("minInterval"):null,maxInterval:l?n.get("maxInterval"):null}),null!=s&&t.setInterval&&t.setInterval(s)}function Zb(t,e){if(e=e||t.get("type"))switch(e){case"category":return new lb({ordinalMeta:t.getOrdinalMeta?t.getOrdinalMeta():t.getCategories(),extent:[1/0,-1/0]});case"time":return new Mb({locale:t.ecModel.getLocaleModel(),useUTC:t.ecModel.get("useUTC")});default:return new(rb.getClass(e)||cb)}}function jb(t){var e=t.getLabelModel().get("formatter");if("time"===t.type){var n=Zd(e);return function(e,i){return t.scale.getFormattedLabel(e,i,n)}}if(X(e))return function(n){var i=t.scale.getLabel(n);return e.replace("{value}",null!=i?i:"")};if(Y(e)){if("category"===t.type)return function(n,i){return e(qb(t,n),n.value-t.scale.getExtent()[0],null)};var i=Nd();return function(n,r){var o=null;return i&&(o=i.makeAxisLabelFormatterParamBreak(o,n.break)),e(qb(t,n),r,o)}}return function(e){return t.scale.getLabel(e)}}function qb(t,e){return"category"===t.type?t.scale.getLabel(e):e.value}function Kb(t){var e=t.get("interval");return null==e?"auto":e}function $b(t){return"category"===t.type&&0===Kb(t.getLabelModel())}function Jb(t,e){var n={};return z(t.mapDimensionsAll(e),(function(e){n[X_(t,e)]=!0})),F(n)}function Qb(t){return"middle"===t||"center"===t}function tw(t){return t.getShallow("show")}function ew(t){var e,n=t.get("breaks",!0);if(null!=n)return Nd()?"x"!==(e=t.axis).dim&&"y"!==e.dim&&"z"!==e.dim&&"single"!==e.dim||"category"===e.type?void 0:n:void 0}var nw=function(){function t(){}return t.prototype.getNeedCrossZero=function(){return!this.option.scale},t.prototype.getCoordSysModel=function(){},t}();var iw={isDimensionStacked:Y_,enableDataStack:U_,getStackedDimension:X_};var rw=Object.freeze({__proto__:null,createList:function(t){return Z_(null,t)},getLayoutRect:Hp,dataStack:iw,createScale:function(t,e){var n=e;e instanceof wd||(n=new wd(e));var i=Zb(n);return i.setExtent(t[0],t[1]),Xb(i,n),i},mixinAxisModelCommonMethods:function(t){R(t,nw)},getECData:zl,createTextStyle:function(t,e){return Qh(t,null,null,"normal"!==(e=e||{}).state)},createDimensions:function(t,e){return V_(t,e).dimensions},createSymbol:hm,enableHoverEmphasis:Iu});function ow(t,e){return Math.abs(t-e)<1e-8}function aw(t,e,n){var i=0,r=t[0];if(!r)return!1;for(var o=1;on&&(t=r,n=a)}if(t)return function(t){for(var e=0,n=0,i=0,r=t.length,o=t[r-1][0],a=t[r-1][1],s=0;s>1^-(1&s),l=l>>1^-(1&l),r=s+=r,o=l+=o,i.push([s/n,l/n])}return i}function vw(t,e){return E(V((t=function(t){if(!t.UTF8Encoding)return t;var e=t,n=e.UTF8Scale;return null==n&&(n=1024),z(e.features,(function(t){var e=t.geometry,i=e.encodeOffsets,r=e.coordinates;if(i)switch(e.type){case"LineString":e.coordinates=yw(r,i,n);break;case"Polygon":case"MultiLineString":gw(r,i,n);break;case"MultiPolygon":z(r,(function(t,e){return gw(t,i[e],n)}))}})),e.UTF8Encoding=!1,e}(t)).features,(function(t){return t.geometry&&t.properties&&t.geometry.coordinates.length>0})),(function(t){var n=t.properties,i=t.geometry,r=[];switch(i.type){case"Polygon":var o=i.coordinates;r.push(new hw(o[0],o.slice(1)));break;case"MultiPolygon":z(i.coordinates,(function(t){t[0]&&r.push(new hw(t[0],t.slice(1)))}));break;case"LineString":r.push(new dw([i.coordinates]));break;case"MultiLineString":r.push(new dw(i.coordinates))}var a=new pw(n[e||"name"],r,n.cp);return a.properties=n,a}))}var mw=Object.freeze({__proto__:null,linearMap:go,round:mo,asc:xo,getPrecision:_o,getPrecisionSafe:bo,getPixelPrecision:wo,getPercentWithPrecision:function(t,e,n){return t[e]&&So(t,n)[e]||0},parsePercent:yo,MAX_SAFE_INTEGER:Io,remRadian:To,isRadianAroundZero:Co,parseDate:Ao,quantity:ko,quantityExponent:Lo,nice:Po,quantile:Oo,reformIntervals:Ro,isNumeric:zo,numericToNumber:No}),xw=Object.freeze({__proto__:null,parse:Ao,format:$d,roundTime:Qd}),_w=Object.freeze({__proto__:null,extendShape:ch,extendPath:dh,makePath:gh,makeImage:yh,mergePath:mh,resizePath:xh,createIcon:Ah,updateProps:th,initProps:eh,getTransform:wh,clipPointsByRect:Ch,clipRectByRect:Dh,registerShape:ph,getShapeClass:fh,Group:to,Image:dl,Text:Sl,Circle:nc,Ellipse:rc,Sector:xc,Ring:bc,Polygon:Mc,Polyline:Tc,Rect:xl,Line:Ac,BezierCurve:Oc,Arc:Nc,IncrementalDisplayable:Kc,CompoundPath:zc,LinearGradient:Bc,RadialGradient:Vc,BoundingRect:He}),bw=Object.freeze({__proto__:null,addCommas:fp,toCamelCase:gp,normalizeCssArray:yp,encodeHTML:oe,formatTpl:_p,getTooltipMarker:bp,formatTime:function(t,e,n){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var i=Ao(e),r=n?"getUTC":"get",o=i[r+"FullYear"](),a=i[r+"Month"]()+1,s=i[r+"Date"](),l=i[r+"Hours"](),u=i[r+"Minutes"](),c=i[r+"Seconds"](),h=i[r+"Milliseconds"]();return t=t.replace("MM",jd(a,2)).replace("M",a).replace("yyyy",o).replace("yy",jd(o%100+"",2)).replace("dd",jd(s,2)).replace("d",s).replace("hh",jd(l,2)).replace("h",l).replace("mm",jd(u,2)).replace("m",u).replace("ss",jd(c,2)).replace("s",c).replace("SSS",jd(h,3))},capitalFirst:function(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t},truncateText:function(t,e,n,i,r){var o={};return Ea(o,t,e,n,i,r),o.text},getTextRect:function(t,e,n,i,r,o,a,s){return new Sl({style:{text:t,font:e,align:n,verticalAlign:i,padding:r,rich:o,overflow:a?"truncate":null,lineHeight:s}}).getBoundingRect()}}),ww=Object.freeze({__proto__:null,map:E,each:z,indexOf:P,inherits:O,reduce:B,filter:V,bind:W,curry:H,isArray:U,isString:X,isObject:q,isFunction:Y,extend:A,defaults:k,clone:T,merge:C}),Sw=sa(),Mw=sa(),Iw=1,Tw=2;function Cw(t){return{out:{noPxChangeTryDetermine:[]},kind:t}}function Dw(t,e){var n=E(e,(function(e){return t.scale.parse(e)}));return"time"===t.type&&n.length>0&&(n.sort(),n.unshift(n[0]),n.push(n[n.length-1])),n}function Aw(t,e){var n=t.getLabelModel().get("customValues");if(n){var i=jb(t),r=t.scale.getExtent();return{labels:E(V(Dw(t,n),(function(t){return t>=r[0]&&t<=r[1]})),(function(e){var n={value:e};return{formattedLabel:i(n),rawLabel:t.scale.getLabel(n),tickValue:e,time:void 0,break:void 0}}))}}return"category"===t.type?function(t,e){var n=t.getLabelModel(),i=Lw(t,n,e);return!n.get("show")||t.scale.isBlank()?{labels:[]}:i}(t,e):function(t){var e=t.scale.getTicks(),n=jb(t);return{labels:E(e,(function(e,i){return{formattedLabel:n(e,i),rawLabel:t.scale.getLabel(e),tickValue:e.value,time:e.time,break:e.break}}))}}(t)}function kw(t,e,n){var i=t.getTickModel().get("customValues");if(i){var r=t.scale.getExtent();return{ticks:V(Dw(t,i),(function(t){return t>=r[0]&&t<=r[1]}))}}return"category"===t.type?function(t,e){var n,i,r=Pw(t),o=Kb(e),a=Nw(r,o);if(a)return a;e.get("show")&&!t.scale.isBlank()||(n=[]);if(Y(o))n=Gw(t,o,!0);else if("auto"===o){var s=Lw(t,t.getLabelModel(),Cw(Tw));i=s.labelCategoryInterval,n=E(s.labels,(function(t){return t.tickValue}))}else n=Vw(t,i=o,!0);return zw(r,o,{ticks:n,tickCategoryInterval:i})}(t,e):{ticks:E(t.scale.getTicks(n),(function(t){return t.value}))}}function Lw(t,e,n){var i,r,o=Ow(t),a=Kb(e),s=n.kind===Iw;if(!s){var l=Nw(o,a);if(l)return l}Y(a)?i=Gw(t,a):(r="auto"===a?function(t,e){if(e.kind===Iw){var n=t.calculateCategoryInterval(e);return e.out.noPxChangeTryDetermine.push((function(){return Mw(t).autoInterval=n,!0})),n}var i=Mw(t).autoInterval;return null!=i?i:Mw(t).autoInterval=t.calculateCategoryInterval(e)}(t,n):a,i=Vw(t,r));var u={labels:i,labelCategoryInterval:r};return s?n.out.noPxChangeTryDetermine.push((function(){return zw(o,a,u),!0})):zw(o,a,u),u}var Pw=Rw("axisTick"),Ow=Rw("axisLabel");function Rw(t){return function(e){return Mw(e)[t]||(Mw(e)[t]={list:[]})}}function Nw(t,e){for(var n=0;ne&&i.axisExtent0===r[0]&&i.axisExtent1===r[1])return o;i.lastTickCount=n,i.lastAutoInterval=e,i.axisExtent0=r[0],i.axisExtent1=r[1]}function Vw(t,e,n){var i=jb(t),r=t.scale,o=r.getExtent(),a=t.getLabelModel(),s=[],l=Math.max((e||0)+1,1),u=o[0],c=r.count();0!==u&&l>1&&c/l>2&&(u=Math.round(Math.ceil(u/l)*l));var h=$b(t),d=a.get("showMinLabel")||h,p=a.get("showMaxLabel")||h;d&&u!==o[0]&&g(o[0]);for(var f=u;f<=o[1];f+=l)g(f);function g(t){var e={value:t};s.push(n?t:{formattedLabel:i(e),rawLabel:r.getLabel(e),tickValue:t,time:void 0,break:void 0})}return p&&f-l!==o[1]&&g(o[1]),s}function Gw(t,e,n){var i=t.scale,r=jb(t),o=[];return z(i.getTicks(),(function(t){var a=i.getLabel(t),s=t.value;e(t.value,a)&&o.push(n?s:{formattedLabel:r(t),rawLabel:a,tickValue:s,time:void 0,break:void 0})})),o}var Fw=[0,1],Ww=function(){function t(t,e,n){this.onBand=!1,this.inverse=!1,this.dim=t,this.scale=e,this._extent=n||[0,0]}return t.prototype.contain=function(t){var e=this._extent,n=Math.min(e[0],e[1]),i=Math.max(e[0],e[1]);return t>=n&&t<=i},t.prototype.containData=function(t){return this.scale.contain(this.scale.parse(t))},t.prototype.getExtent=function(){return this._extent.slice()},t.prototype.getPixelPrecision=function(t){return wo(t||this.scale.getExtent(),this._extent)},t.prototype.setExtent=function(t,e){var n=this._extent;n[0]=t,n[1]=e},t.prototype.dataToCoord=function(t,e){var n=this._extent,i=this.scale;return t=i.normalize(i.parse(t)),this.onBand&&"ordinal"===i.type&&Hw(n=n.slice(),i.count()),go(t,Fw,n,e)},t.prototype.coordToData=function(t,e){var n=this._extent,i=this.scale;this.onBand&&"ordinal"===i.type&&Hw(n=n.slice(),i.count());var r=go(t,n,Fw,e);return this.scale.scale(r)},t.prototype.pointToData=function(t,e){},t.prototype.getTicksCoords=function(t){var e=(t=t||{}).tickModel||this.getTickModel(),n=E(kw(this,e,{breakTicks:t.breakTicks,pruneByBreak:t.pruneByBreak}).ticks,(function(t){return{coord:this.dataToCoord("ordinal"===this.scale.type?this.scale.getRawOrdinalNumber(t):t),tickValue:t}}),this);return function(t,e,n,i){var r=e.length;if(!t.onBand||n||!r)return;var o,a,s=t.getExtent();if(1===r)e[0].coord=s[0],e[0].onBand=!0,o=e[1]={coord:s[1],tickValue:e[0].tickValue,onBand:!0};else{var l=e[r-1].tickValue-e[0].tickValue,u=(e[r-1].coord-e[0].coord)/l;z(e,(function(t){t.coord-=u/2,t.onBand=!0}));var c=t.scale.getExtent();a=1+c[1]-e[r-1].tickValue,o={coord:e[r-1].coord+u*a,tickValue:c[1]+1,onBand:!0},e.push(o)}var h=s[0]>s[1];d(e[0].coord,s[0])&&(i?e[0].coord=s[0]:e.shift());i&&d(s[0],e[0].coord)&&e.unshift({coord:s[0],onBand:!0});d(s[1],o.coord)&&(i?o.coord=s[1]:e.pop());i&&d(o.coord,s[1])&&e.push({coord:s[1],onBand:!0});function d(t,e){return t=mo(t),e=mo(e),h?t>e:t0&&t<100||(t=5),E(this.scale.getMinorTicks(t),(function(t){return E(t,(function(t){return{coord:this.dataToCoord(t),tickValue:t}}),this)}),this)},t.prototype.getViewLabels=function(t){return Aw(this,t=t||Cw(Tw)).labels},t.prototype.getLabelModel=function(){return this.model.getModel("axisLabel")},t.prototype.getTickModel=function(){return this.model.getModel("axisTick")},t.prototype.getBandWidth=function(){var t=this._extent,e=this.scale.getExtent(),n=e[1]-e[0]+(this.onBand?1:0);0===n&&(n=1);var i=Math.abs(t[1]-t[0]);return Math.abs(i)/n},t.prototype.calculateCategoryInterval=function(t){return function(t,e){var n=e.kind,i=function(t){var e=t.getLabelModel();return{axisRotate:t.getRotate?t.getRotate():t.isHorizontal&&!t.isHorizontal()?90:0,labelRotate:e.get("rotate")||0,font:e.getFont()}}(t),r=jb(t),o=(i.axisRotate-i.labelRotate)/180*Math.PI,a=t.scale,s=a.getExtent(),l=a.count();if(s[1]-s[0]<1)return 0;var u=1;l>40&&(u=Math.max(1,Math.floor(l/40)));for(var c=s[0],h=t.dataToCoord(c+1)-t.dataToCoord(c),d=Math.abs(h*Math.cos(o)),p=Math.abs(h*Math.sin(o)),f=0,g=0;c<=s[1];c+=u){var y,v,m=Er(r({value:c}),i.font,"center","top");y=1.3*m.width,v=1.3*m.height,f=Math.max(f,y,7),g=Math.max(g,v,7)}var x=f/d,_=g/p;isNaN(x)&&(x=1/0),isNaN(_)&&(_=1/0);var b=Math.max(0,Math.floor(Math.min(x,_)));if(n===Iw)return e.out.noPxChangeTryDetermine.push(W(Ew,null,t,b,l)),b;var w=Bw(t,b,l);return null!=w?w:b}(this,t=t||Cw(Tw))},t}();function Hw(t,e){var n=(t[1]-t[0])/e/2;t[0]+=n,t[1]-=n}var Uw=2*Math.PI,Yw=Fs.CMD,Xw=["top","right","bottom","left"];function Zw(t,e,n,i,r){var o=n.width,a=n.height;switch(t){case"top":i.set(n.x+o/2,n.y-e),r.set(0,-1);break;case"bottom":i.set(n.x+o/2,n.y+a+e),r.set(0,1);break;case"left":i.set(n.x-e,n.y+a/2),r.set(-1,0);break;case"right":i.set(n.x+o+e,n.y+a/2),r.set(1,0)}}function jw(t,e,n,i,r,o,a,s,l){a-=t,s-=e;var u=Math.sqrt(a*a+s*s),c=(a/=u)*n+t,h=(s/=u)*n+e;if(Math.abs(i-r)%Uw<1e-4)return l[0]=c,l[1]=h,u-n;if(o){var d=i;i=Xs(r),r=Xs(d)}else i=Xs(i),r=Xs(r);i>r&&(r+=Uw);var p=Math.atan2(s,a);if(p<0&&(p+=Uw),p>=i&&p<=r||p+Uw>=i&&p+Uw<=r)return l[0]=c,l[1]=h,u-n;var f=n*Math.cos(i)+t,g=n*Math.sin(i)+e,y=n*Math.cos(r)+t,v=n*Math.sin(r)+e,m=(f-a)*(f-a)+(g-s)*(g-s),x=(y-a)*(y-a)+(v-s)*(v-s);return m0){e=e/180*Math.PI,tS.fromArray(t[0]),eS.fromArray(t[1]),nS.fromArray(t[2]),Ae.sub(iS,tS,eS),Ae.sub(rS,nS,eS);var n=iS.len(),i=rS.len();if(!(n<.001||i<.001)){iS.scale(1/n),rS.scale(1/i);var r=iS.dot(rS);if(Math.cos(e)1&&Ae.copy(sS,nS),sS.toArray(t[1])}}}}function uS(t,e,n){if(n<=180&&n>0){n=n/180*Math.PI,tS.fromArray(t[0]),eS.fromArray(t[1]),nS.fromArray(t[2]),Ae.sub(iS,eS,tS),Ae.sub(rS,nS,eS);var i=iS.len(),r=rS.len();if(!(i<.001||r<.001))if(iS.scale(1/i),rS.scale(1/r),iS.dot(e)=a)Ae.copy(sS,nS);else{sS.scaleAndAdd(rS,o/Math.tan(Math.PI/2-s));var l=nS.x!==eS.x?(sS.x-eS.x)/(nS.x-eS.x):(sS.y-eS.y)/(nS.y-eS.y);if(isNaN(l))return;l<0?Ae.copy(sS,eS):l>1&&Ae.copy(sS,nS)}sS.toArray(t[1])}}}function cS(t,e,n,i){var r="normal"===n,o=r?t:t.ensureState(n);o.ignore=e;var a=i.get("smooth");a&&!0===a&&(a=.3),o.shape=o.shape||{},a>0&&(o.shape.smooth=a);var s=i.getModel("lineStyle").getLineStyle();r?t.useStyle(s):o.style=s}function hS(t,e){var n=e.smooth,i=e.points;if(i)if(t.moveTo(i[0][0],i[0][1]),n>0&&i.length>=3){var r=Vt(i[0],i[1]),o=Vt(i[1],i[2]);if(!r||!o)return t.lineTo(i[1][0],i[1][1]),void t.lineTo(i[2][0],i[2][1]);var a=Math.min(r,o)*n,s=Wt([],i[1],i[0],a/r),l=Wt([],i[1],i[2],a/o),u=Wt([],s,l,.5);t.bezierCurveTo(s[0],s[1],s[0],s[1],u[0],u[1]),t.bezierCurveTo(l[0],l[1],l[0],l[1],i[2][0],i[2][1])}else for(var c=1;c0&&r&&b(-h/o,0,o);var g,y,v=t[0],m=t[o-1];function x(){g=v.rect[a]-n,y=i-m.rect[a]-m.rect[s]}function _(t,e,n){if(t<0){var i=Math.min(e,-t);if(i>0){b(i*n,0,o);var r=i+t;r<0&&w(-r*n,1)}else w(-t*n,1)}}function b(e,n,i){0!==e&&(c=!0);for(var r=n;r0)for(l=0;l0;l--){b(-(i[l-1]*h),l,o)}}}function S(t){var e=t<0?-1:1;t=Math.abs(t);for(var n=Math.ceil(t/(o-1)),i=0;i0?b(n,0,i+1):b(-n,o-i-1,o),(t-=n)<=0)return}return x(),g<0&&w(-g,.8),y<0&&w(y,.8),x(),_(g,y,1),_(y,g,-1),x(),g<0&&S(-g),y<0&&S(y),c}function MS(t){var e=[];function n(t){if(!t.ignore){var e=t.ensureState("emphasis");null==e.ignore&&(e.ignore=!1)}t.ignore=!0}t.sort((function(t,e){return(e.suggestIgnore?1:0)-(t.suggestIgnore?1:0)||e.priority-t.priority}));for(var i=0;i=0&&n.attr(p.oldLayoutSelect),P(u,"emphasis")>=0&&n.attr(p.oldLayoutEmphasis)),th(n,s,e,a)}else if(n.attr(s),!ad(n).valueAnimation){var c=rt(n.style.opacity,1);n.style.opacity=0,eh(n,{style:{opacity:c}},e,a)}if(p.oldLayout=s,n.states.select){var h=p.oldLayoutSelect={};PS(h,s,OS),PS(h,n.states.select,OS)}if(n.states.emphasis){var d=p.oldLayoutEmphasis={};PS(d,s,OS),PS(d,n.states.emphasis,OS)}ld(n,a,l,e,e)}if(i&&!i.ignore&&!i.invisible){r=(p=LS(i)).oldLayout;var p,f={points:i.shape.points};r?(i.attr({shape:r}),th(i,{shape:f},e)):(i.setShape(f),i.style.strokePercent=0,eh(i,{style:{strokePercent:1}},e)),p.oldLayout=f}},t}(),NS=sa();var zS=Math.sin,ES=Math.cos,BS=Math.PI,VS=2*Math.PI,GS=180/BS,FS=function(){function t(){}return t.prototype.reset=function(t){this._start=!0,this._d=[],this._str="",this._p=Math.pow(10,t||4)},t.prototype.moveTo=function(t,e){this._add("M",t,e)},t.prototype.lineTo=function(t,e){this._add("L",t,e)},t.prototype.bezierCurveTo=function(t,e,n,i,r,o){this._add("C",t,e,n,i,r,o)},t.prototype.quadraticCurveTo=function(t,e,n,i){this._add("Q",t,e,n,i)},t.prototype.arc=function(t,e,n,i,r,o){this.ellipse(t,e,n,n,0,i,r,o)},t.prototype.ellipse=function(t,e,n,i,r,o,a,s){var l=a-o,u=!s,c=Math.abs(l),h=wi(c-VS)||(u?l>=VS:-l>=VS),d=l>0?l%VS:l%VS+VS,p=!1;p=!!h||!wi(c)&&d>=BS==!!u;var f=t+n*ES(o),g=e+i*zS(o);this._start&&this._add("M",f,g);var y=Math.round(r*GS);if(h){var v=1/this._p,m=(u?1:-1)*(VS-v);this._add("A",n,i,y,1,+u,t+n*ES(o+m),e+i*zS(o+m)),v>.01&&this._add("A",n,i,y,0,+u,f,g)}else{var x=t+n*ES(a),_=e+i*zS(a);this._add("A",n,i,y,+p,+u,x,_)}},t.prototype.rect=function(t,e,n,i){this._add("M",t,e),this._add("l",n,0),this._add("l",0,i),this._add("l",-n,0),this._add("Z")},t.prototype.closePath=function(){this._d.length>0&&this._add("Z")},t.prototype._add=function(t,e,n,i,r,o,a,s,l){for(var u=[],c=this._p,h=1;h"}(r,o)+("style"!==r?oe(a):a||"")+(i?""+n+E(i,(function(e){return t(e)})).join(n)+n:"")+("")}(t)}function QS(t){return{zrId:t,shadowCache:{},patternCache:{},gradientCache:{},clipPathCache:{},defs:{},cssNodes:{},cssAnims:{},cssStyleCache:{},cssAnimIdx:0,shadowIdx:0,gradientIdx:0,patternIdx:0,clipPathIdx:0}}function tM(t,e,n,i){return $S("svg","root",{width:t,height:e,xmlns:ZS,"xmlns:xlink":jS,version:"1.1",baseProfile:"full",viewBox:!!i&&"0 0 "+t+" "+e},n)}var eM=0;function nM(){return eM++}var iM={cubicIn:"0.32,0,0.67,0",cubicOut:"0.33,1,0.68,1",cubicInOut:"0.65,0,0.35,1",quadraticIn:"0.11,0,0.5,0",quadraticOut:"0.5,1,0.89,1",quadraticInOut:"0.45,0,0.55,1",quarticIn:"0.5,0,0.75,0",quarticOut:"0.25,1,0.5,1",quarticInOut:"0.76,0,0.24,1",quinticIn:"0.64,0,0.78,0",quinticOut:"0.22,1,0.36,1",quinticInOut:"0.83,0,0.17,1",sinusoidalIn:"0.12,0,0.39,0",sinusoidalOut:"0.61,1,0.88,1",sinusoidalInOut:"0.37,0,0.63,1",exponentialIn:"0.7,0,0.84,0",exponentialOut:"0.16,1,0.3,1",exponentialInOut:"0.87,0,0.13,1",circularIn:"0.55,0,1,0.45",circularOut:"0,0.55,0.45,1",circularInOut:"0.85,0,0.15,1"},rM="transform-origin";function oM(t,e,n){var i=A({},t.shape);A(i,e),t.buildPath(n,i);var r=new FS;return r.reset(Pi(t)),n.rebuildPath(r,1),r.generateStr(),r.getStr()}function aM(t,e){var n=e.originX,i=e.originY;(n||i)&&(t[rM]=n+"px "+i+"px")}var sM={fill:"fill",opacity:"opacity",lineWidth:"stroke-width",lineDashOffset:"stroke-dashoffset"};function lM(t,e){var n=e.zrId+"-ani-"+e.cssAnimIdx++;return e.cssAnims[n]=t,n}function uM(t){return X(t)?iM[t]?"cubic-bezier("+iM[t]+")":Wn(t)?t:"":""}function cM(t,e,n,i){var r=t.animators,o=r.length,a=[];if(t instanceof zc){var s=function(t,e,n){var i,r,o=t.shape.paths,a={};if(z(o,(function(t){var e=QS(n.zrId);e.animation=!0,cM(t,{},e,!0);var o=e.cssAnims,s=e.cssNodes,l=F(o),u=l.length;if(u){var c=o[r=l[u-1]];for(var h in c){var d=c[h];a[h]=a[h]||{d:""},a[h].d+=d.d||""}for(var p in s){var f=s[p].animation;f.indexOf(r)>=0&&(i=f)}}})),i){e.d=!1;var s=lM(a,n);return i.replace(r,s)}}(t,e,n);if(s)a.push(s);else if(!o)return}else if(!o)return;for(var l={},u=0;u0})).length)return lM(c,n)+" "+r[0]+" both"}for(var y in l){(s=g(l[y]))&&a.push(s)}if(a.length){var v=n.zrId+"-cls-"+nM();n.cssNodes["."+v]={animation:a.join(",")},e.class=v}}function hM(t,e,n,i){var r=JSON.stringify(t),o=n.cssStyleCache[r];o||(o=n.zrId+"-cls-"+nM(),n.cssStyleCache[r]=o,n.cssNodes["."+o+(i?":hover":"")]=t),e.class=e.class?e.class+" "+o:o}var dM=Math.round;function pM(t){return t&&X(t.src)}function fM(t){return t&&Y(t.toDataURL)}function gM(t,e,n,i){XS((function(r,o){var a="fill"===r||"stroke"===r;a&&ki(o)?TM(e,t,r,i):a&&Ci(o)?CM(n,t,r,i):t[r]=o,a&&i.ssr&&"none"===o&&(t["pointer-events"]="visible")}),e,n,!1),function(t,e,n){var i=t.style;if(function(t){return t&&(t.shadowBlur||t.shadowOffsetX||t.shadowOffsetY)}(i)){var r=function(t){var e=t.style,n=t.getGlobalScale();return[e.shadowColor,(e.shadowBlur||0).toFixed(2),(e.shadowOffsetX||0).toFixed(2),(e.shadowOffsetY||0).toFixed(2),n[0],n[1]].join(",")}(t),o=n.shadowCache,a=o[r];if(!a){var s=t.getGlobalScale(),l=s[0],u=s[1];if(!l||!u)return;var c=i.shadowOffsetX||0,h=i.shadowOffsetY||0,d=i.shadowBlur,p=_i(i.shadowColor),f=p.opacity,g=p.color,y=d/2/l+" "+d/2/u;a=n.zrId+"-s"+n.shadowIdx++,n.defs[a]=$S("filter",a,{id:a,x:"-100%",y:"-100%",width:"300%",height:"300%"},[$S("feDropShadow","",{dx:c/l,dy:h/u,stdDeviation:y,"flood-color":g,"flood-opacity":f})]),o[r]=a}e.filter=Li(a)}}(n,t,i)}function yM(t,e){var n=so(e);n&&(n.each((function(e,n){null!=e&&(t[(qS+n).toLowerCase()]=e+"")})),e.isSilent()&&(t[qS+"silent"]="true"))}function vM(t){return wi(t[0]-1)&&wi(t[1])&&wi(t[2])&&wi(t[3]-1)}function mM(t,e,n){if(e&&(!function(t){return wi(t[4])&&wi(t[5])}(e)||!vM(e))){var i=n?10:1e4;t.transform=vM(e)?"translate("+dM(e[4]*i)/i+" "+dM(e[5]*i)/i+")":function(t){return"matrix("+Si(t[0])+","+Si(t[1])+","+Si(t[2])+","+Si(t[3])+","+Mi(t[4])+","+Mi(t[5])+")"}(e)}}function xM(t,e,n){for(var i=t.points,r=[],o=0;o=0&&a||o;s&&(r=vi(s))}var l=i.lineWidth;l&&(l/=!i.strokeNoScale&&t.transform?t.transform[0]:1);var u={cursor:"pointer"};r&&(u.fill=r),i.stroke&&(u.stroke=i.stroke),l&&(u["stroke-width"]=l),hM(u,e,n,!0)}}(t,o,e),$S(s,t.id+"",o)}function IM(t,e){return t instanceof sl?MM(t,e):t instanceof dl?function(t,e){var n=t.style,i=n.image;if(i&&!X(i)&&(pM(i)?i=i.src:fM(i)&&(i=i.toDataURL())),i){var r=n.x||0,o=n.y||0,a={href:i,width:n.width,height:n.height};return r&&(a.x=r),o&&(a.y=o),mM(a,t.transform),gM(a,n,t,e),yM(a,t),e.animation&&cM(t,a,e),$S("image",t.id+"",a)}}(t,e):t instanceof ul?function(t,e){var n=t.style,i=n.text;if(null!=i&&(i+=""),i&&!isNaN(n.x)&&!isNaN(n.y)){var r=n.font||a,s=n.x||0,l=function(t,e,n){return"top"===n?t+=e/2:"bottom"===n&&(t-=e/2),t}(n.y||0,Gr(r),n.textBaseline),u={"dominant-baseline":"central","text-anchor":Ii[n.textAlign]||n.textAlign};if(Al(n)){var c="",h=n.fontStyle,d=Cl(n.fontSize);if(!parseFloat(d))return;var p=n.fontFamily||o,f=n.fontWeight;c+="font-size:"+d+";font-family:"+p+";",h&&"normal"!==h&&(c+="font-style:"+h+";"),f&&"normal"!==f&&(c+="font-weight:"+f+";"),u.style=c}else u.style="font: "+r;return i.match(/\s/)&&(u["xml:space"]="preserve"),s&&(u.x=s),l&&(u.y=l),mM(u,t.transform),gM(u,n,t,e),yM(u,t),e.animation&&cM(t,u,e),$S("text",t.id+"",u,void 0,i)}}(t,e):void 0}function TM(t,e,n,i){var r,o=t[n],a={gradientUnits:o.global?"userSpaceOnUse":"objectBoundingBox"};if(Di(o))r="linearGradient",a.x1=o.x,a.y1=o.y,a.x2=o.x2,a.y2=o.y2;else{if(!Ai(o))return void 0;r="radialGradient",a.cx=rt(o.x,.5),a.cy=rt(o.y,.5),a.r=rt(o.r,.5)}for(var s=o.colorStops,l=[],u=0,c=s.length;ul?WM(t,null==n[h+1]?null:n[h+1].elm,n,s,h):HM(t,e,a,l))}(n,i,r):BM(r)?(BM(t.text)&&NM(n,""),WM(n,null,r,0,r.length-1)):BM(i)?HM(n,i,0,i.length-1):BM(t.text)&&NM(n,""):t.text!==e.text&&(BM(i)&&HM(n,i,0,i.length-1),NM(n,e.text)))}var XM=0,ZM=function(){function t(t,e,n){if(this.type="svg",this.refreshHover=jM("refreshHover"),this.configLayer=jM("configLayer"),this.storage=e,this._opts=n=A({},n),this.root=t,this._id="zr"+XM++,this._oldVNode=tM(n.width,n.height),t&&!n.ssr){var i=this._viewport=document.createElement("div");i.style.cssText="position:relative;overflow:hidden";var r=this._svgDom=this._oldVNode.elm=KS("svg");UM(null,this._oldVNode),i.appendChild(r),t.appendChild(i)}this.resize(n.width,n.height)}return t.prototype.getType=function(){return this.type},t.prototype.getViewportRoot=function(){return this._viewport},t.prototype.getViewportRootOffset=function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},t.prototype.getSvgDom=function(){return this._svgDom},t.prototype.refresh=function(){if(this.root){var t=this.renderToVNode({willUpdate:!0});t.attrs.style="position:absolute;left:0;top:0;user-select:none",function(t,e){if(GM(t,e))YM(t,e);else{var n=t.elm,i=OM(n);FM(e),null!==i&&(kM(i,e.elm,RM(n)),HM(i,[t],0,0))}}(this._oldVNode,t),this._oldVNode=t}},t.prototype.renderOneToVNode=function(t){return IM(t,QS(this._id))},t.prototype.renderToVNode=function(t){t=t||{};var e=this.storage.getDisplayList(!0),n=this._width,i=this._height,r=QS(this._id);r.animation=t.animation,r.willUpdate=t.willUpdate,r.compress=t.compress,r.emphasis=t.emphasis,r.ssr=this._opts.ssr;var o=[],a=this._bgVNode=function(t,e,n,i){var r;if(n&&"none"!==n)if(r=$S("rect","bg",{width:t,height:e,x:"0",y:"0"}),ki(n))TM({fill:n},r.attrs,"fill",i);else if(Ci(n))CM({style:{fill:n},dirty:bt,getBoundingRect:function(){return{width:t,height:e}}},r.attrs,"fill",i);else{var o=_i(n),a=o.color,s=o.opacity;r.attrs.fill=a,s<1&&(r.attrs["fill-opacity"]=s)}return r}(n,i,this._backgroundColor,r);a&&o.push(a);var s=t.compress?null:this._mainVNode=$S("g","main",{},[]);this._paintList(e,r,s?s.children:o),s&&o.push(s);var l=E(F(r.defs),(function(t){return r.defs[t]}));if(l.length&&o.push($S("defs","defs",{},l)),t.animation){var u=function(t,e,n){var i=(n=n||{}).newline?"\n":"",r=" {"+i,o=i+"}",a=E(F(t),(function(e){return e+r+E(F(t[e]),(function(n){return n+":"+t[e][n]+";"})).join(i)+o})).join(i),s=E(F(e),(function(t){return"@keyframes "+t+r+E(F(e[t]),(function(n){return n+r+E(F(e[t][n]),(function(i){var r=e[t][n][i];return"d"===i&&(r='path("'+r+'")'),i+":"+r+";"})).join(i)+o})).join(i)+o})).join(i);return a||s?[""].join(i):""}(r.cssNodes,r.cssAnims,{newline:!0});if(u){var c=$S("style","stl",{},[],u);o.push(c)}}return tM(n,i,o,t.useViewBox)},t.prototype.renderToString=function(t){return t=t||{},JS(this.renderToVNode({animation:rt(t.cssAnimation,!0),emphasis:rt(t.cssEmphasis,!0),willUpdate:!1,compress:!0,useViewBox:rt(t.useViewBox,!0)}),{newline:!0})},t.prototype.setBackgroundColor=function(t){this._backgroundColor=t},t.prototype.getSvgRoot=function(){return this._mainVNode&&this._mainVNode.elm},t.prototype._paintList=function(t,e,n){for(var i,r,o=t.length,a=[],s=0,l=0,u=0;u=0&&(!h||!r||h[f]!==r[f]);f--);for(var g=p-1;g>f;g--)i=a[--s-1];for(var y=f+1;y=a)}}for(var c=this.__startIndex;c15)break}n.prevElClipPaths&&u.restore()};if(d)if(0===d.length)s=l.__endIndex;else for(var _=p.dpr,b=0;b0&&t>i[0]){for(s=0;st);s++);a=n[i[s]]}if(i.splice(s+1,0,t),n[t]=e,!e.virtual)if(a){var l=a.dom;l.nextSibling?o.insertBefore(e.dom,l.nextSibling):o.appendChild(e.dom)}else o.firstChild?o.insertBefore(e.dom,o.firstChild):o.appendChild(e.dom);e.painter||(e.painter=this)}},t.prototype.eachLayer=function(t,e){for(var n=this._zlevelList,i=0;i0?QM:0),this._needsManuallyCompositing),u.__builtin__||I("ZLevel "+l+" has been used by unkown layer "+u.id),u!==o&&(u.__used=!0,u.__startIndex!==r&&(u.__dirty=!0),u.__startIndex=r,u.incremental?u.__drawIndex=-1:u.__drawIndex=r,e(r),o=u),1&s.__dirty&&!s.__inHover&&(u.__dirty=!0,u.incremental&&u.__drawIndex<0&&(u.__drawIndex=r))}e(r),this.eachBuiltinLayer((function(t,e){!t.__used&&t.getElementCount()>0&&(t.__dirty=!0,t.__startIndex=t.__endIndex=t.__drawIndex=0),t.__dirty&&t.__drawIndex<0&&(t.__drawIndex=t.__startIndex)}))},t.prototype.clear=function(){return this.eachBuiltinLayer(this._clearLayer),this},t.prototype._clearLayer=function(t){t.clear()},t.prototype.setBackgroundColor=function(t){this._backgroundColor=t,z(this._layers,(function(t){t.setUnpainted()}))},t.prototype.configLayer=function(t,e){if(e){var n=this._layerConfig;n[t]?C(n[t],e,!0):n[t]=e;for(var i=0;i-1&&(s.style.stroke=s.style.fill,s.style.fill=tf.color.neutral00,s.style.lineWidth=2),e},e.type="series.line",e.dependencies=["grid","polar"],e.defaultOption={z:3,coordinateSystem:"cartesian2d",legendHoverLink:!0,clip:!0,label:{position:"top"},endLabel:{show:!1,valueAnimation:!0,distance:8},lineStyle:{width:2,type:"solid"},emphasis:{scale:!0},step:!1,smooth:!1,smoothMonotone:null,symbol:"emptyCircle",symbolSize:6,symbolRotate:null,showSymbol:!0,showAllSymbol:"auto",connectNulls:!1,sampling:"none",animationEasing:"linear",progressive:0,hoverLayerThreshold:1/0,universalTransition:{divideShape:"clone"},triggerLineEvent:!1},e}(Wy);function nI(t,e){var n=t.mapDimensionsAll("defaultedLabel"),i=n.length;if(1===i){var r=Vg(t,e,n[0]);return null!=r?r+"":null}if(i){for(var o=[],a=0;a=0&&i.push(e[o])}return i.join(" ")}var rI=function(t){function e(e,n,i,r){var o=t.call(this)||this;return o.updateData(e,n,i,r),o}return n(e,t),e.prototype._createSymbol=function(t,e,n,i,r,o){this.removeAll();var a=hm(t,-1,-1,2,2,null,o);a.attr({z2:rt(r,100),culling:!0,scaleX:i[0]/2,scaleY:i[1]/2}),a.drift=oI,this._symbolType=t,this.add(a)},e.prototype.stopSymbolAnimation=function(t){this.childAt(0).stopAnimation(null,t)},e.prototype.getSymbolType=function(){return this._symbolType},e.prototype.getSymbolPath=function(){return this.childAt(0)},e.prototype.highlight=function(){du(this.childAt(0))},e.prototype.downplay=function(){pu(this.childAt(0))},e.prototype.setZ=function(t,e){var n=this.childAt(0);n.zlevel=t,n.z=e},e.prototype.setDraggable=function(t,e){var n=this.childAt(0);n.draggable=t,n.cursor=!e&&t?"move":n.cursor},e.prototype.updateData=function(t,n,i,r){this.silent=!1;var o=t.getItemVisual(n,"symbol")||"circle",a=t.hostModel,s=e.getSymbolSize(t,n),l=e.getSymbolZ2(t,n),u=o!==this._symbolType,c=r&&r.disableAnimation;if(u){var h=t.getItemVisual(n,"symbolKeepAspect");this._createSymbol(o,t,n,s,l,h)}else{(p=this.childAt(0)).silent=!1;var d={scaleX:s[0]/2,scaleY:s[1]/2};c?p.attr(d):th(p,d,a,n),ah(p)}if(this._updateCommon(t,n,s,i,r),u){var p=this.childAt(0);if(!c){d={scaleX:this._sizeX,scaleY:this._sizeY,style:{opacity:p.style.opacity}};p.scaleX=p.scaleY=0,p.style.opacity=0,eh(p,d,a,n)}}c&&this.childAt(0).stopAnimation("leave")},e.prototype._updateCommon=function(t,e,n,i,r){var o,a,s,l,u,c,h,d,p,f=this.childAt(0),g=t.hostModel;if(i&&(o=i.emphasisItemStyle,a=i.blurItemStyle,s=i.selectItemStyle,l=i.focus,u=i.blurScope,h=i.labelStatesModels,d=i.hoverScale,p=i.cursorStyle,c=i.emphasisDisabled),!i||t.hasItemOption){var y=i&&i.itemModel?i.itemModel:t.getItemModel(e),v=y.getModel("emphasis");o=v.getModel("itemStyle").getItemStyle(),s=y.getModel(["select","itemStyle"]).getItemStyle(),a=y.getModel(["blur","itemStyle"]).getItemStyle(),l=v.get("focus"),u=v.get("blurScope"),c=v.get("disabled"),h=Jh(y),d=v.getShallow("scale"),p=y.getShallow("cursor")}var m=t.getItemVisual(e,"symbolRotate");f.attr("rotation",(m||0)*Math.PI/180||0);var x=pm(t.getItemVisual(e,"symbolOffset"),n);x&&(f.x=x[0],f.y=x[1]),p&&f.attr("cursor",p);var _=t.getItemVisual(e,"style"),b=_.fill;if(f instanceof dl){var w=f.style;f.useStyle(A({image:w.image,x:w.x,y:w.y,width:w.width,height:w.height},_))}else f.__isEmptyBrush?f.useStyle(A({},_)):f.useStyle(_),f.style.decal=null,f.setColor(b,r&&r.symbolInnerColor),f.style.strokeNoScale=!0;var S=t.getItemVisual(e,"liftZ"),M=this._z2;null!=S?null==M&&(this._z2=f.z2,f.z2+=S):null!=M&&(f.z2=M,this._z2=null);var I=r&&r.useNameLabel;$h(f,h,{labelFetcher:g,labelDataIndex:e,defaultText:function(e){return I?t.getName(e):nI(t,e)},inheritColor:b,defaultOpacity:_.opacity}),this._sizeX=n[0]/2,this._sizeY=n[1]/2;var T=f.ensureState("emphasis");T.style=o,f.ensureState("select").style=s,f.ensureState("blur").style=a;var C=null==d||!0===d?Math.max(1.1,3/this._sizeY):isFinite(d)&&d>0?+d:1;T.scaleX=this._sizeX*C,T.scaleY=this._sizeY*C,this.setSymbolScale(1),Tu(this,l,u,c)},e.prototype.setSymbolScale=function(t){this.scaleX=this.scaleY=t},e.prototype.fadeOut=function(t,e,n){var i=this.childAt(0),r=zl(this).dataIndex,o=n&&n.animation;if(this.silent=i.silent=!0,n&&n.fadeLabel){var a=i.getTextContent();a&&ih(a,{style:{opacity:0}},e,{dataIndex:r,removeOpt:o,cb:function(){i.removeTextContent()}})}else i.removeTextContent();ih(i,{style:{opacity:0},scaleX:0,scaleY:0},e,{dataIndex:r,cb:t,removeOpt:o})},e.getSymbolSize=function(t,e){return dm(t.getItemVisual(e,"symbolSize"))},e.getSymbolZ2=function(t,e){return t.getItemVisual(e,"z2")},e}(to);function oI(t,e){this.parent.drift(t,e)}function aI(t,e,n,i){return e&&!isNaN(e[0])&&!isNaN(e[1])&&!(i.isIgnore&&i.isIgnore(n))&&!(i.clipShape&&!i.clipShape.contain(e[0],e[1]))&&"none"!==t.getItemVisual(n,"symbol")}function sI(t){return null==t||q(t)||(t={isIgnore:t}),t||{}}function lI(t){var e=t.hostModel,n=e.getModel("emphasis");return{emphasisItemStyle:n.getModel("itemStyle").getItemStyle(),blurItemStyle:e.getModel(["blur","itemStyle"]).getItemStyle(),selectItemStyle:e.getModel(["select","itemStyle"]).getItemStyle(),focus:n.get("focus"),blurScope:n.get("blurScope"),emphasisDisabled:n.get("disabled"),hoverScale:n.get("scale"),labelStatesModels:Jh(e),cursorStyle:e.get("cursor")}}var uI=function(){function t(t){this.group=new to,this._SymbolCtor=t||rI}return t.prototype.updateData=function(t,e){this._progressiveEls=null,e=sI(e);var n=this.group,i=t.hostModel,r=this._data,o=this._SymbolCtor,a=e.disableAnimation,s=lI(t),l={disableAnimation:a},u=e.getSymbolPoint||function(e){return t.getItemLayout(e)};r||n.removeAll(),t.diff(r).add((function(i){var r=u(i);if(aI(t,r,i,e)){var a=new o(t,i,s,l);a.setPosition(r),t.setItemGraphicEl(i,a),n.add(a)}})).update((function(c,h){var d=r.getItemGraphicEl(h),p=u(c);if(aI(t,p,c,e)){var f=t.getItemVisual(c,"symbol")||"circle",g=d&&d.getSymbolType&&d.getSymbolType();if(!d||g&&g!==f)n.remove(d),(d=new o(t,c,s,l)).setPosition(p);else{d.updateData(t,c,s,l);var y={x:p[0],y:p[1]};a?d.attr(y):th(d,y,i)}n.add(d),t.setItemGraphicEl(c,d)}else n.remove(d)})).remove((function(t){var e=r.getItemGraphicEl(t);e&&e.fadeOut((function(){n.remove(e)}),i)})).execute(),this._getSymbolPoint=u,this._data=t},t.prototype.updateLayout=function(){var t=this,e=this._data;e&&e.eachItemGraphicEl((function(e,n){var i=t._getSymbolPoint(n);e.setPosition(i),e.markRedraw()}))},t.prototype.incrementalPrepareUpdate=function(t){this._seriesScope=lI(t),this._data=null,this.group.removeAll()},t.prototype.incrementalUpdate=function(t,e,n){function i(t){t.isGroup||(t.incremental=!0,t.ensureState("emphasis").hoverLayer=!0)}this._progressiveEls=[],n=sI(n);for(var r=t.start;r0?n=i[0]:i[1]<0&&(n=i[1]);return n}(r,n),a=i.dim,s=r.dim,l=e.mapDimension(s),u=e.mapDimension(a),c="x"===s||"radius"===s?1:0,h=E(t.dimensions,(function(t){return e.mapDimension(t)})),d=!1,p=e.getCalculationInfo("stackResultDimension");return Y_(e,h[0])&&(d=!0,h[0]=p),Y_(e,h[1])&&(d=!0,h[1]=p),{dataDimsForPoint:h,valueStart:o,valueAxisDim:s,baseAxisDim:a,stacked:!!d,valueDim:l,baseDim:u,baseDataOffset:c,stackedOverDimension:e.getCalculationInfo("stackedOverDimension")}}function hI(t,e,n,i){var r=NaN;t.stacked&&(r=n.get(n.getCalculationInfo("stackedOverDimension"),i)),isNaN(r)&&(r=t.valueStart);var o=t.baseDataOffset,a=[];return a[o]=n.get(t.baseDim,i),a[1-o]=r,e.dataToPoint(a)}var dI=Math.min,pI=Math.max;function fI(t,e){return isNaN(t)||isNaN(e)}function gI(t,e,n,i,r,o,a,s,l){for(var u,c,h,d,p,f,g=n,y=0;y=r||g<0)break;if(fI(v,m)){if(l){g+=o;continue}break}if(g===n)t[o>0?"moveTo":"lineTo"](v,m),h=v,d=m;else{var x=v-u,_=m-c;if(x*x+_*_<.5){g+=o;continue}if(a>0){for(var b=g+o,w=e[2*b],S=e[2*b+1];w===v&&S===m&&y=i||fI(w,S))p=v,f=m;else{T=w-u,C=S-c;var k=v-u,L=w-v,P=m-c,O=S-m,R=void 0,N=void 0;if("x"===s){var z=T>0?1:-1;p=v-z*(R=Math.abs(k))*a,f=m,D=v+z*(N=Math.abs(L))*a,A=m}else if("y"===s){var E=C>0?1:-1;p=v,f=m-E*(R=Math.abs(P))*a,D=v,A=m+E*(N=Math.abs(O))*a}else R=Math.sqrt(k*k+P*P),p=v-T*a*(1-(I=(N=Math.sqrt(L*L+O*O))/(N+R))),f=m-C*a*(1-I),A=m+C*a*I,D=dI(D=v+T*a*I,pI(w,v)),A=dI(A,pI(S,m)),D=pI(D,dI(w,v)),f=m-(C=(A=pI(A,dI(S,m)))-m)*R/N,p=dI(p=v-(T=D-v)*R/N,pI(u,v)),f=dI(f,pI(c,m)),D=v+(T=v-(p=pI(p,dI(u,v))))*N/R,A=m+(C=m-(f=pI(f,dI(c,m))))*N/R}t.bezierCurveTo(h,d,p,f,v,m),h=D,d=A}else t.lineTo(v,m)}u=v,c=m,g+=o}return y}var yI=function(){this.smooth=0,this.smoothConstraint=!0},vI=function(t){function e(e){var n=t.call(this,e)||this;return n.type="ec-polyline",n}return n(e,t),e.prototype.getDefaultStyle=function(){return{stroke:tf.color.neutral99,fill:null}},e.prototype.getDefaultShape=function(){return new yI},e.prototype.buildPath=function(t,e){var n=e.points,i=0,r=n.length/2;if(e.connectNulls){for(;r>0&&fI(n[2*r-2],n[2*r-1]);r--);for(;i=0){var y=a?(c-i)*g+i:(u-n)*g+n;return a?[t,y]:[y,t]}n=u,i=c;break;case o.C:u=r[l++],c=r[l++],h=r[l++],d=r[l++],p=r[l++],f=r[l++];var v=a?kn(n,u,h,p,t,s):kn(i,c,d,f,t,s);if(v>0)for(var m=0;m=0){y=a?Dn(i,c,d,f,x):Dn(n,u,h,p,x);return a?[t,y]:[y,t]}}n=p,i=f}}},e}(sl),mI=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e}(yI),xI=function(t){function e(e){var n=t.call(this,e)||this;return n.type="ec-polygon",n}return n(e,t),e.prototype.getDefaultShape=function(){return new mI},e.prototype.buildPath=function(t,e){var n=e.points,i=e.stackedOnPoints,r=0,o=n.length/2,a=e.smoothMonotone;if(e.connectNulls){for(;o>0&&fI(n[2*o-2],n[2*o-1]);o--);for(;r=0;a--){var s=t.getDimensionInfo(i[a].dimension);if("x"===(r=s&&s.coordDim)||"y"===r){o=i[a];break}}if(o){var l=e.getAxis(r),u=E(o.stops,(function(t){return{coord:l.toGlobalCoord(l.dataToCoord(t.value)),color:t.color}})),c=u.length,h=o.outerColors.slice();c&&u[0].coord>u[c-1].coord&&(u.reverse(),h.reverse());var d=function(t,e){var n,i,r=[],o=t.length;function a(t,e,n){var i=t.coord;return{coord:n,color:ci((n-i)/(e.coord-i),[t.color,e.color])}}for(var s=0;se){i?r.push(a(i,l,e)):n&&r.push(a(n,l,0),a(n,l,e));break}n&&(r.push(a(n,l,0)),n=null),r.push(l),i=l}}return r}(u,"x"===r?n.getWidth():n.getHeight()),p=d.length;if(!p&&c)return u[0].coord<0?h[1]?h[1]:u[c-1].color:h[0]?h[0]:u[0].color;var f=d[0].coord-10,g=d[p-1].coord+10,y=g-f;if(y<.001)return"transparent";z(d,(function(t){t.offset=(t.coord-f)/y})),d.push({offset:p?d[p-1].offset:.5,color:h[1]||"transparent"}),d.unshift({offset:p?d[0].offset:.5,color:h[0]||"transparent"});var v=new Bc(0,0,0,0,d,!0);return v[r]=f,v[r+"2"]=g,v}}}function kI(t,e,n){var i=t.get("showAllSymbol"),r="auto"===i;if(!i||r){var o=n.getAxesByScale("ordinal")[0];if(o&&(!r||!function(t,e){var n=t.getExtent(),i=Math.abs(n[1]-n[0])/t.scale.count();isNaN(i)&&(i=0);for(var r=e.count(),o=Math.max(1,Math.round(r/5)),a=0;ai)return!1;return!0}(o,e))){var a=e.mapDimension(o.dim),s={};return z(o.getViewLabels(),(function(t){var e=o.scale.getRawOrdinalNumber(t.tickValue);s[e]=1})),function(t){return!s.hasOwnProperty(e.get(a,t))}}}}function LI(t,e){return[t[2*e],t[2*e+1]]}function PI(t){if(t.get(["endLabel","show"]))return!0;for(var e=0;e0&&"bolder"===t.get(["emphasis","lineStyle","width"]))&&(d.getState("emphasis").style.lineWidth=+d.style.lineWidth+1);zl(d).seriesIndex=t.seriesIndex,Tu(d,A,L,P);var O=CI(t.get("smooth")),R=t.get("smoothMonotone");if(d.setShape({smooth:O,smoothMonotone:R,connectNulls:b}),p){var N=o.getCalculationInfo("stackedOnSeries"),z=0;p.useStyle(k(s.getAreaStyle(),{fill:T,opacity:.7,lineJoin:"bevel",decal:o.getVisual("style").decal})),N&&(z=CI(N.get("smooth"))),p.setShape({smooth:O,stackedOnSmooth:z,smoothMonotone:R,connectNulls:b}),ku(p,t,"areaStyle"),zl(p).seriesIndex=t.seriesIndex,Tu(p,A,L,P)}var E=this._changePolyState;o.eachItemGraphicEl((function(t){t&&(t.onHoverStateChange=E)})),this._polyline.onHoverStateChange=E,this._data=o,this._coordSys=i,this._stackedOnPoints=x,this._points=l,this._step=I,this._valueOrigin=v,t.get("triggerLineEvent")&&(this.packEventData(t,d),p&&this.packEventData(t,p))},e.prototype.packEventData=function(t,e){zl(e).eventData={componentType:"series",componentSubType:"line",componentIndex:t.componentIndex,seriesIndex:t.seriesIndex,seriesName:t.name,seriesType:"line"}},e.prototype.highlight=function(t,e,n,i){var r=t.getData(),o=aa(r,i);if(this._changePolyState("emphasis"),!(o instanceof Array)&&null!=o&&o>=0){var a=r.getLayout("points"),s=r.getItemGraphicEl(o);if(!s){var l=a[2*o],u=a[2*o+1];if(isNaN(l)||isNaN(u))return;if(this._clipShapeForSymbol&&!this._clipShapeForSymbol.contain(l,u))return;var c=t.get("zlevel")||0,h=t.get("z")||0;(s=new rI(r,o)).x=l,s.y=u,s.setZ(c,h);var d=s.getSymbolPath().getTextContent();d&&(d.zlevel=c,d.z=h,d.z2=this._polyline.z2+1),s.__temp=!0,r.setItemGraphicEl(o,s),s.stopSymbolAnimation(!0),this.group.add(s)}s.highlight()}else tv.prototype.highlight.call(this,t,e,n,i)},e.prototype.downplay=function(t,e,n,i){var r=t.getData(),o=aa(r,i);if(this._changePolyState("normal"),null!=o&&o>=0){var a=r.getItemGraphicEl(o);a&&(a.__temp?(r.setItemGraphicEl(o,null),this.group.remove(a)):a.downplay())}else tv.prototype.downplay.call(this,t,e,n,i)},e.prototype._changePolyState=function(t){var e=this._polygon;su(this._polyline,t),e&&su(e,t)},e.prototype._newPolyline=function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new vI({shape:{points:t},segmentIgnoreThreshold:2,z2:10}),this._lineGroup.add(e),this._polyline=e,e},e.prototype._newPolygon=function(t,e){var n=this._polygon;return n&&this._lineGroup.remove(n),n=new xI({shape:{points:t,stackedOnPoints:e},segmentIgnoreThreshold:2}),this._lineGroup.add(n),this._polygon=n,n},e.prototype._initSymbolLabelAnimation=function(t,e,n){var i,r,o=e.getBaseAxis(),a=o.inverse;"cartesian2d"===e.type?(i=o.isHorizontal(),r=!1):"polar"===e.type&&(i="angle"===o.dim,r=!0);var s=t.hostModel,l=s.get("animationDuration");Y(l)&&(l=l(null));var u=s.get("animationDelay")||0,c=Y(u)?u(null):u;t.eachItemGraphicEl((function(t,o){var s=t;if(s){var h=[t.x,t.y],d=void 0,p=void 0,f=void 0;if(n)if(r){var g=n,y=e.pointToCoord(h);i?(d=g.startAngle,p=g.endAngle,f=-y[1]/180*Math.PI):(d=g.r0,p=g.r,f=y[0])}else{var v=n;i?(d=v.x,p=v.x+v.width,f=t.x):(d=v.y+v.height,p=v.y,f=t.y)}var m=p===d?0:(f-d)/(p-d);a&&(m=1-m);var x=Y(u)?u(o):l*m+c,_=s.getSymbolPath(),b=_.getTextContent();s.attr({scaleX:0,scaleY:0}),s.animateTo({scaleX:1,scaleY:1},{duration:200,setToFinal:!0,delay:x}),b&&b.animateFrom({style:{opacity:0}},{duration:300,delay:x}),_.disableLabelAnimation=!0}}))},e.prototype._initOrUpdateEndLabel=function(t,e,n){var i=t.getModel("endLabel");if(PI(t)){var r=t.getData(),o=this._polyline,a=r.getLayout("points");if(!a)return o.removeTextContent(),void(this._endLabel=null);var s=this._endLabel;s||((s=this._endLabel=new Sl({z2:200})).ignoreClip=!0,o.setTextContent(this._endLabel),o.disableLabelAnimation=!0);var l=function(t){for(var e,n,i=t.length/2;i>0&&(e=t[2*i-2],n=t[2*i-1],isNaN(e)||isNaN(n));i--);return i-1}(a);l>=0&&($h(o,Jh(t,"endLabel"),{inheritColor:n,labelFetcher:t,labelDataIndex:l,defaultText:function(t,e,n){return null!=n?iI(r,n):nI(r,t)},enableTextSetter:!0},function(t,e){var n=e.getBaseAxis(),i=n.isHorizontal(),r=n.inverse,o=i?r?"right":"left":"center",a=i?"middle":r?"top":"bottom";return{normal:{align:t.get("align")||o,verticalAlign:t.get("verticalAlign")||a}}}(i,e)),o.textConfig.position=null)}else this._endLabel&&(this._polyline.removeTextContent(),this._endLabel=null)},e.prototype._endLabelOnDuring=function(t,e,n,i,r,o,a){var s=this._endLabel,l=this._polyline;if(s){t<1&&null==i.originalX&&(i.originalX=s.x,i.originalY=s.y);var u=n.getLayout("points"),c=n.hostModel,h=c.get("connectNulls"),d=o.get("precision"),p=o.get("distance")||0,f=a.getBaseAxis(),g=f.isHorizontal(),y=f.inverse,v=e.shape,m=y?g?v.x:v.y+v.height:g?v.x+v.width:v.y,x=(g?p:0)*(y?-1:1),_=(g?0:-p)*(y?-1:1),b=g?"x":"y",w=function(t,e,n){for(var i,r,o=t.length/2,a="x"===n?0:1,s=0,l=-1,u=0;u=e||i>=e&&r<=e){l=u;break}s=u,i=r}else i=r;return{range:[s,l],t:(e-i)/(r-i)}}(u,m,b),S=w.range,M=S[1]-S[0],I=void 0;if(M>=1){if(M>1&&!h){var T=LI(u,S[0]);s.attr({x:T[0]+x,y:T[1]+_}),r&&(I=c.getRawValue(S[0]))}else{(T=l.getPointOn(m,b))&&s.attr({x:T[0]+x,y:T[1]+_});var C=c.getRawValue(S[0]),D=c.getRawValue(S[1]);r&&(I=ya(n,d,C,D,w.t))}i.lastFrameIndex=S[0]}else{var A=1===t||i.lastFrameIndex>0?S[0]:0;T=LI(u,A);r&&(I=c.getRawValue(A)),s.attr({x:T[0]+x,y:T[1]+_})}if(r){var k=ad(s);"function"==typeof k.setLabelText&&k.setLabelText(I)}}},e.prototype._doUpdateAnimation=function(t,e,n,i,r,o,a){var s=this._polyline,l=this._polygon,u=t.hostModel,c=function(t,e,n,i,r,o,a,s){for(var l=function(t,e){var n=[];return e.diff(t).add((function(t){n.push({cmd:"+",idx:t})})).update((function(t,e){n.push({cmd:"=",idx:e,idx1:t})})).remove((function(t){n.push({cmd:"-",idx:t})})).execute(),n}(t,e),u=[],c=[],h=[],d=[],p=[],f=[],g=[],y=cI(r,e,a),v=t.getLayout("points")||[],m=e.getLayout("points")||[],x=0;x3e3||l&&TI(d,f)>3e3)return s.stopAnimation(),s.setShape({points:p}),void(l&&(l.stopAnimation(),l.setShape({points:p,stackedOnPoints:f})));s.shape.__points=c.current,s.shape.points=h;var g={shape:{points:p}};c.current!==h&&(g.shape.__points=c.next),s.stopAnimation(),th(s,g,u),l&&(l.setShape({points:h,stackedOnPoints:d}),l.stopAnimation(),th(l,{shape:{stackedOnPoints:f}},u),s.shape.points!==l.shape.points&&(l.shape.points=s.shape.points));for(var y=[],v=c.status,m=0;me&&(e=t[n]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,n=0;n10&&"cartesian2d"===o.type&&r){var s=o.getBaseAxis(),l=o.getOtherAxis(s),u=s.getExtent(),c=n.getDevicePixelRatio(),h=Math.abs(u[1]-u[0])*(c||1),d=Math.round(a/h);if(isFinite(d)&&d>1){"lttb"===r?t.setData(i.lttbDownSample(i.mapDimension(l.dim),1/d)):"minmax"===r&&t.setData(i.minmaxDownSample(i.mapDimension(l.dim),1/d));var p=void 0;X(r)?p=zI[r]:Y(r)&&(p=r),p&&t.setData(i.downSample(i.mapDimension(l.dim),1/d,p,EI))}}}}}var VI=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.getInitialData=function(t,e){return Z_(null,this,{useEncodeDefaulter:!0})},e.prototype.getMarkerPosition=function(t,e,n){var i=this.coordinateSystem;if(i&&i.clampData){var r=i.clampData(t),o=i.dataToPoint(r);if(n)z(i.getAxes(),(function(t,n){if("category"===t.type&&null!=e){var i=t.getTicksCoords(),a=t.getTickModel().get("alignWithLabel"),s=r[n],l="x1"===e[n]||"y1"===e[n];if(l&&!a&&(s+=1),i.length<2)return;if(2===i.length)return void(o[n]=t.toGlobalCoord(t.getExtent()[l?1:0]));for(var u=void 0,c=void 0,h=1,d=0;ds){c=(p+u)/2;break}1===d&&(h=f-i[0].tickValue)}null==c&&(u?u&&(c=i[i.length-1].coord):c=i[0].coord),o[n]=t.toGlobalCoord(c)}}));else{var a=this.getData(),s=a.getLayout("offset"),l=a.getLayout("size"),u=i.getBaseAxis().isHorizontal()?0:1;o[u]+=s+l/2}return o}return[NaN,NaN]},e.type="series.__base_bar__",e.defaultOption={z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,barMinHeight:0,barMinAngle:0,large:!1,largeThreshold:400,progressive:3e3,progressiveChunkMode:"mod",defaultBarGap:"10%"},e}(Wy);Wy.registerClass(VI);var GI=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.getInitialData=function(){return Z_(null,this,{useEncodeDefaulter:!0,createInvertedIndices:!!this.get("realtimeSort",!0)||null})},e.prototype.getProgressive=function(){return!!this.get("large")&&this.get("progressive")},e.prototype.getProgressiveThreshold=function(){var t=this.get("progressiveThreshold"),e=this.get("largeThreshold");return e>t&&(t=e),t},e.prototype.brushSelector=function(t,e,n){return n.rect(e.getItemLayout(t))},e.type="series.bar",e.dependencies=["grid","polar"],e.defaultOption=Id(VI.defaultOption,{clip:!0,roundCap:!1,showBackground:!1,backgroundStyle:{color:"rgba(180, 180, 180, 0.2)",borderColor:null,borderWidth:0,borderType:"solid",borderRadius:0,shadowBlur:0,shadowColor:null,shadowOffsetX:0,shadowOffsetY:0,opacity:1},select:{itemStyle:{borderColor:tf.color.primary,borderWidth:2}},realtimeSort:!1}),e}(VI),FI=function(){this.cx=0,this.cy=0,this.r0=0,this.r=0,this.startAngle=0,this.endAngle=2*Math.PI,this.clockwise=!0},WI=function(t){function e(e){var n=t.call(this,e)||this;return n.type="sausage",n}return n(e,t),e.prototype.getDefaultShape=function(){return new FI},e.prototype.buildPath=function(t,e){var n=e.cx,i=e.cy,r=Math.max(e.r0||0,0),o=Math.max(e.r,0),a=.5*(o-r),s=r+a,l=e.startAngle,u=e.endAngle,c=e.clockwise,h=2*Math.PI,d=c?u-lo)return!0;o=u}return!1},e.prototype._isOrderDifferentInView=function(t,e){for(var n=e.scale,i=n.getExtent(),r=Math.max(0,i[0]),o=Math.min(i[1],n.getOrdinalMeta().categories.length-1);r<=o;++r)if(t.ordinalNumbers[r]!==n.getRawOrdinalNumber(r))return!0},e.prototype._updateSortWithinSameData=function(t,e,n,i){if(this._isOrderChangedWithinSameData(t,e,n)){var r=this._dataSort(t,n,e);this._isOrderDifferentInView(r,n)&&(this._removeOnRenderedListener(i),i.dispatchAction({type:"changeAxisOrder",componentType:n.dim+"Axis",axisId:n.index,sortInfo:r}))}},e.prototype._dispatchInitSort=function(t,e,n){var i=e.baseAxis,r=this._dataSort(t,i,(function(n){return t.get(t.mapDimension(e.otherAxis.dim),n)}));n.dispatchAction({type:"changeAxisOrder",componentType:i.dim+"Axis",isInitSort:!0,axisId:i.index,sortInfo:r})},e.prototype.remove=function(t,e){this._clear(this._model),this._removeOnRenderedListener(e)},e.prototype.dispose=function(t,e){this._removeOnRenderedListener(e)},e.prototype._removeOnRenderedListener=function(t){this._onRendered&&(t.getZr().off("rendered",this._onRendered),this._onRendered=null)},e.prototype._clear=function(t){var e=this.group,n=this._data;t&&t.isAnimationEnabled()&&n&&!this._isLargeDraw?(this._removeBackground(),this._backgroundEls=[],n.eachItemGraphicEl((function(e){oh(e,t,zl(e).dataIndex)}))):e.removeAll(),this._data=null,this._isFirstFrame=!0},e.prototype._removeBackground=function(){this.group.remove(this._backgroundGroup),this._backgroundGroup=null},e.type="bar",e}(tv),qI={cartesian2d:function(t,e){var n=e.width<0?-1:1,i=e.height<0?-1:1;n<0&&(e.x+=e.width,e.width=-e.width),i<0&&(e.y+=e.height,e.height=-e.height);var r=t.x+t.width,o=t.y+t.height,a=XI(e.x,t.x),s=ZI(e.x+e.width,r),l=XI(e.y,t.y),u=ZI(e.y+e.height,o),c=sr?s:a,e.y=h&&l>o?u:l,e.width=c?0:s-a,e.height=h?0:u-l,n<0&&(e.x+=e.width,e.width=-e.width),i<0&&(e.y+=e.height,e.height=-e.height),c||h},polar:function(t,e){var n=e.r0<=e.r?1:-1;if(n<0){var i=e.r;e.r=e.r0,e.r0=i}var r=ZI(e.r,t.r),o=XI(e.r0,t.r0);e.r=r,e.r0=o;var a=r-o<0;if(n<0){i=e.r;e.r=e.r0,e.r0=i}return a}},KI={cartesian2d:function(t,e,n,i,r,o,a,s,l){var u=new xl({shape:A({},i),z2:1});(u.__dataIndex=n,u.name="item",o)&&(u.shape[r?"height":"width"]=0);return u},polar:function(t,e,n,i,r,o,a,s,l){var u=!r&&l?WI:xc,c=new u({shape:i,z2:1});c.name="item";var h,d,p=iT(r);if(c.calculateTextPosition=(h=p,d=({isRoundCap:u===WI}||{}).isRoundCap,function(t,e,n){var i=e.position;if(!i||i instanceof Array)return Wr(t,e,n);var r=h(i),o=null!=e.distance?e.distance:5,a=this.shape,s=a.cx,l=a.cy,u=a.r,c=a.r0,p=(u+c)/2,f=a.startAngle,g=a.endAngle,y=(f+g)/2,v=d?Math.abs(u-c)/2:0,m=Math.cos,x=Math.sin,_=s+u*m(f),b=l+u*x(f),w="left",S="top";switch(r){case"startArc":_=s+(c-o)*m(y),b=l+(c-o)*x(y),w="center",S="top";break;case"insideStartArc":_=s+(c+o)*m(y),b=l+(c+o)*x(y),w="center",S="bottom";break;case"startAngle":_=s+p*m(f)+HI(f,o+v,!1),b=l+p*x(f)+UI(f,o+v,!1),w="right",S="middle";break;case"insideStartAngle":_=s+p*m(f)+HI(f,-o+v,!1),b=l+p*x(f)+UI(f,-o+v,!1),w="left",S="middle";break;case"middle":_=s+p*m(y),b=l+p*x(y),w="center",S="middle";break;case"endArc":_=s+(u+o)*m(y),b=l+(u+o)*x(y),w="center",S="bottom";break;case"insideEndArc":_=s+(u-o)*m(y),b=l+(u-o)*x(y),w="center",S="top";break;case"endAngle":_=s+p*m(g)+HI(g,o+v,!0),b=l+p*x(g)+UI(g,o+v,!0),w="left",S="middle";break;case"insideEndAngle":_=s+p*m(g)+HI(g,-o+v,!0),b=l+p*x(g)+UI(g,-o+v,!0),w="right",S="middle";break;default:return Wr(t,e,n)}return(t=t||{}).x=_,t.y=b,t.align=w,t.verticalAlign=S,t}),o){var f=r?"r":"endAngle",g={};c.shape[f]=r?i.r0:i.startAngle,g[f]=i[f],(s?th:eh)(c,{shape:g},o)}return c}};function $I(t,e,n,i,r,o,a,s){var l,u;o?(u={x:i.x,width:i.width},l={y:i.y,height:i.height}):(u={y:i.y,height:i.height},l={x:i.x,width:i.width}),s||(a?th:eh)(n,{shape:l},e,r,null),(a?th:eh)(n,{shape:u},e?t.baseAxis.model:null,r)}function JI(t,e){for(var n=0;n0?1:-1,a=i.height>0?1:-1;return{x:i.x+o*r/2,y:i.y+a*r/2,width:i.width-o*r,height:i.height-a*r}},polar:function(t,e,n){var i=t.getItemLayout(e);return{cx:i.cx,cy:i.cy,r0:i.r0,r:i.r,startAngle:i.startAngle,endAngle:i.endAngle,clockwise:i.clockwise}}};function iT(t){return function(t){var e=t?"Arc":"Angle";return function(t){switch(t){case"start":case"insideStart":case"end":case"insideEnd":return t+e;default:return t}}}(t)}function rT(t,e,n,i,r,o,a,s){var l=e.getItemVisual(n,"style");if(s){if(!o.get("roundCap")){var u=t.shape;A(u,YI(i.getModel("itemStyle"),u,!0)),t.setShape(u)}}else{var c=i.get(["itemStyle","borderRadius"])||0;t.setShape("r",c)}t.useStyle(l);var h=i.getShallow("cursor");h&&t.attr("cursor",h);var d=s?a?r.r>=r.r0?"endArc":"startArc":r.endAngle>=r.startAngle?"endAngle":"startAngle":a?r.height>=0?"bottom":"top":r.width>=0?"right":"left",p=Jh(i);$h(t,p,{labelFetcher:o,labelDataIndex:n,defaultText:nI(o.getData(),n),inheritColor:l.fill,defaultOpacity:l.opacity,defaultOutsidePosition:d});var f=t.getTextContent();if(s&&f){var g=i.get(["label","position"]);t.textConfig.inside="middle"===g||null,function(t,e,n,i){if(j(i))t.setTextConfig({rotation:i});else if(U(e))t.setTextConfig({rotation:0});else{var r,o=t.shape,a=o.clockwise?o.startAngle:o.endAngle,s=o.clockwise?o.endAngle:o.startAngle,l=(a+s)/2,u=n(e);switch(u){case"startArc":case"insideStartArc":case"middle":case"insideEndArc":case"endArc":r=l;break;case"startAngle":case"insideStartAngle":r=a;break;case"endAngle":case"insideEndAngle":r=s;break;default:return void t.setTextConfig({rotation:0})}var c=1.5*Math.PI-r;"middle"===u&&c>Math.PI/2&&c<1.5*Math.PI&&(c-=Math.PI),t.setTextConfig({rotation:c})}}(t,"outside"===g?d:g,iT(a),i.get(["label","rotate"]))}sd(f,p,o.getRawValue(n),(function(t){return iI(e,t)}));var y=i.getModel(["emphasis"]);Tu(t,y.get("focus"),y.get("blurScope"),y.get("disabled")),ku(t,i),function(t){return null!=t.startAngle&&null!=t.endAngle&&t.startAngle===t.endAngle}(r)&&(t.style.fill="none",t.style.stroke="none",z(t.states,(function(t){t.style&&(t.style.fill=t.style.stroke="none")})))}var oT=function(){},aT=function(t){function e(e){var n=t.call(this,e)||this;return n.type="largeBar",n}return n(e,t),e.prototype.getDefaultShape=function(){return new oT},e.prototype.buildPath=function(t,e){for(var n=e.points,i=this.baseDimIdx,r=1-this.baseDimIdx,o=[],a=[],s=this.barWidth,l=0;l=s[0]&&e<=s[0]+l[0]&&n>=s[1]&&n<=s[1]+l[1])return a[c]}return-1}(this,t.offsetX,t.offsetY);zl(this).dataIndex=e>=0?e:null}),30,!1);function uT(t,e,n){if(SI(n,"cartesian2d")){var i=e,r=n.getArea();return{x:t?i.x:r.x,y:t?r.y:i.y,width:t?i.width:r.width,height:t?r.height:i.height}}var o=e;return{cx:(r=n.getArea()).cx,cy:r.cy,r0:t?r.r0:o.r0,r:t?r.r:o.r,startAngle:t?o.startAngle:0,endAngle:t?o.endAngle:2*Math.PI}}var cT=2*Math.PI,hT=Math.PI/180;function dT(t,e,n){e.eachSeriesByType(t,(function(t){var e=t.getData(),i=e.mapDimension("value"),r=Wp(t,n),o=r.cx,a=r.cy,s=r.r,l=r.r0,u=r.viewRect,c=-t.get("startAngle")*hT,h=t.get("endAngle"),d=t.get("padAngle")*hT;h="auto"===h?c-cT:-h*hT;var p=t.get("minAngle")*hT+d,f=0;e.each(i,(function(t){!isNaN(t)&&f++}));var g=e.getSum(i),y=Math.PI/(g||f)*2,v=t.get("clockwise"),m=t.get("roseType"),x=t.get("stillShowZeroSum"),_=e.getDataExtent(i);_[0]=0;var b=v?1:-1,w=[c,h],S=b*d/2;Gs(w,!v),c=w[0],h=w[1];var M=pT(t);M.startAngle=c,M.endAngle=h,M.clockwise=v,M.cx=o,M.cy=a,M.r=s,M.r0=l;var I=Math.abs(h-c),T=I,C=0,D=c;if(e.setLayout({viewRect:u,r:s}),e.each(i,(function(t,n){var i;if(isNaN(t))e.setItemLayout(n,{angle:NaN,startAngle:NaN,endAngle:NaN,clockwise:v,cx:o,cy:a,r0:l,r:m?NaN:s});else{(i="area"!==m?0===g&&x?y:t*y:I/f)i?c=u=D+b*i/2:(u=D+S,c=r-S),e.setItemLayout(n,{angle:i,startAngle:u,endAngle:c,clockwise:v,cx:o,cy:a,r0:l,r:m?go(t,_,[l,s]):s}),D=r}})),Tn?a:o,c=Math.abs(l.label.y-n);if(c>=u.maxY){var h=l.label.x-e-l.len2*r,d=i+l.len,f=Math.abs(h)t.unconstrainedWidth?null:d:null;i.setStyle("width",p)}mT(o,i)}}}function mT(t,e){_T.rect=t,mS(_T,e,xT)}var xT={minMarginForce:[null,0,null,0],marginDefault:[1,0,1,0]},_T={};function bT(t){return"center"===t.position}function wT(t){var e,n,i=t.getData(),r=[],o=!1,a=(t.get("minShowLabelAngle")||0)*gT,s=i.getLayout("viewRect"),l=i.getLayout("r"),u=s.width,c=s.x,h=s.y,d=s.height;function p(t){t.ignore=!0}i.each((function(t){var s=i.getItemGraphicEl(t),h=s.shape,f=s.getTextContent(),g=s.getTextGuideLine(),y=i.getItemModel(t),v=y.getModel("label"),m=v.get("position")||y.get(["emphasis","label","position"]),x=v.get("distanceToLabelLine"),_=v.get("alignTo"),b=yo(v.get("edgeDistance"),u),w=v.get("bleedMargin");null==w&&(w=Math.min(u,d)>200?10:2);var S=y.getModel("labelLine"),M=S.get("length");M=yo(M,u);var I=S.get("length2");if(I=yo(I,u),Math.abs(h.endAngle-h.startAngle)0?"right":"left":L>0?"left":"right"}var G=Math.PI,F=0,W=v.get("rotate");if(j(W))F=W*(G/180);else if("center"===m)F=0;else if("radial"===W||!0===W){F=L<0?-k+G:-k}else if("tangential"===W&&"outside"!==m&&"outer"!==m){var H=Math.atan2(L,P);H<0&&(H=2*G+H),P>0&&(H=G+H),F=H-G}if(o=!!F,f.x=T,f.y=C,f.rotation=F,f.setStyle({verticalAlign:"middle"}),O){f.setStyle({align:A});var U=f.states.select;U&&(U.x+=f.x,U.y+=f.y)}else{var Y=new He(0,0,0,0);mT(Y,f),r.push({label:f,labelLine:g,position:m,len:M,len2:I,minTurnAngle:S.get("minTurnAngle"),maxSurfaceAngle:S.get("maxSurfaceAngle"),surfaceNormal:new Ae(L,P),linePoints:D,textAlign:A,labelDistance:x,labelAlignTo:_,edgeDistance:b,bleedMargin:w,rect:Y,unconstrainedWidth:Y.width,labelStyleWidth:f.style.width})}s.setTextConfig({inside:O})}})),!o&&t.get("avoidLabelOverlap")&&function(t,e,n,i,r,o,a,s){for(var l=[],u=[],c=Number.MAX_VALUE,h=-Number.MAX_VALUE,d=0;d0){for(var l=o.getItemLayout(0),u=1;isNaN(l&&l.startAngle)&&u=n.r0}},e.type="pie",e}(tv);function IT(t,e,n){e=U(e)&&{coordDimensions:e}||A({encodeDefine:t.getEncode()},e);var i=t.getSource(),r=V_(i,e).dimensions,o=new B_(r,t);return o.initData(i,n),o}var TT,CT=function(){function t(t,e){this._getDataWithEncodedVisual=t,this._getRawData=e}return t.prototype.getAllNames=function(){var t=this._getRawData();return t.mapArray(t.getName)},t.prototype.containName=function(t){return this._getRawData().indexOfName(t)>=0},t.prototype.indexOfName=function(t){return this._getDataWithEncodedVisual().indexOfName(t)},t.prototype.getItemVisual=function(t,e){return this._getDataWithEncodedVisual().getItemVisual(t,e)},t}(),DT=sa(),AT=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.init=function(e){t.prototype.init.apply(this,arguments),this.legendVisualProvider=new CT(W(this.getData,this),W(this.getRawData,this)),this._defaultLabelLine(e)},e.prototype.mergeOption=function(){t.prototype.mergeOption.apply(this,arguments)},e.prototype.getInitialData=function(){return IT(this,{coordDimensions:["value"],encodeDefaulter:H(Mf,this)})},e.prototype.getDataParams=function(e){var n=this.getData(),i=DT(n),r=i.seats;if(!r){var o=[];n.each(n.mapDimension("value"),(function(t){o.push(t)})),r=i.seats=So(o,n.hostModel.get("percentPrecision"))}var a=t.prototype.getDataParams.call(this,e);return a.percent=r[e]||0,a.$vars.push("percent"),a},e.prototype._defaultLabelLine=function(t){Ko(t,"labelLine",["show"]);var e=t.labelLine,n=t.emphasis.labelLine;e.show=e.show&&t.label.show,n.show=n.show&&t.emphasis.label.show},e.type="series.pie",e.defaultOption={z:2,legendHoverLink:!0,colorBy:"data",center:["50%","50%"],radius:[0,"50%"],clockwise:!0,startAngle:90,endAngle:"auto",padAngle:0,minAngle:0,minShowLabelAngle:0,selectedOffset:10,percentPrecision:2,stillShowZeroSum:!0,coordinateSystemUsage:"box",left:0,top:0,right:0,bottom:0,width:null,height:null,label:{rotate:0,show:!0,overflow:"truncate",position:"outer",alignTo:"none",edgeDistance:"25%",distanceToLabelLine:5},labelLine:{show:!0,length:15,length2:30,smooth:!1,minTurnAngle:90,maxSurfaceAngle:90,lineStyle:{width:1,type:"solid"}},itemStyle:{borderWidth:1,borderJoin:"round"},showEmptyCircle:!0,emptyCircleStyle:{color:"lightgray",opacity:1},labelLayout:{hideOverlap:!0},emphasis:{scale:!0,scaleSize:5},avoidLabelOverlap:!0,animationType:"expansion",animationDuration:1e3,animationTypeUpdate:"transition",animationEasingUpdate:"cubicInOut",animationDurationUpdate:500,animationEasing:"cubicInOut"},e}(Wy);TT={fullType:AT.type,getCoord2:function(t){return t.getShallow("center")}},Ap.set(TT.fullType,{getCoord2:void 0}).getCoord2=TT.getCoord2;var kT=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.hasSymbolVisual=!0,n}return n(e,t),e.prototype.getInitialData=function(t,e){return Z_(null,this,{useEncodeDefaulter:!0})},e.prototype.getProgressive=function(){var t=this.option.progressive;return null==t?this.option.large?5e3:this.get("progressive"):t},e.prototype.getProgressiveThreshold=function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?1e4:this.get("progressiveThreshold"):t},e.prototype.brushSelector=function(t,e,n){return n.point(e.getItemLayout(t))},e.prototype.getZLevelKey=function(){return this.getData().count()>this.getProgressiveThreshold()?this.id:""},e.type="series.scatter",e.dependencies=["grid","polar","geo","singleAxis","calendar","matrix"],e.defaultOption={coordinateSystem:"cartesian2d",z:2,legendHoverLink:!0,symbolSize:10,large:!1,largeThreshold:2e3,itemStyle:{opacity:.8},emphasis:{scale:!0},clip:!0,select:{itemStyle:{borderColor:tf.color.primary}},universalTransition:{divideShape:"clone"}},e}(Wy),LT=function(){},PT=function(t){function e(e){var n=t.call(this,e)||this;return n._off=0,n.hoverDataIdx=-1,n}return n(e,t),e.prototype.getDefaultShape=function(){return new LT},e.prototype.reset=function(){this.notClear=!1,this._off=0},e.prototype.buildPath=function(t,e){var n,i=e.points,r=e.size,o=this.symbolProxy,a=o.shape,s=t.getContext?t.getContext():t,l=s&&r[0]<4,u=this.softClipShape;if(l)this._ctx=s;else{for(this._ctx=null,n=this._off;n=0;s--){var l=2*s,u=i[l]-o/2,c=i[l+1]-a/2;if(t>=u&&e>=c&&t<=u+o&&e<=c+a)return s}return-1},e.prototype.contain=function(t,e){var n=this.transformCoordToLocal(t,e),i=this.getBoundingRect();return t=n[0],e=n[1],i.contain(t,e)?(this.hoverDataIdx=this.findDataIndex(t,e))>=0:(this.hoverDataIdx=-1,!1)},e.prototype.getBoundingRect=function(){var t=this._rect;if(!t){for(var e=this.shape,n=e.points,i=e.size,r=i[0],o=i[1],a=1/0,s=1/0,l=-1/0,u=-1/0,c=0;c=0&&(l.dataIndex=n+(t.startIndex||0))}))},t.prototype.remove=function(){this._clear()},t.prototype._clear=function(){this._newAdded=[],this.group.removeAll()},t}(),RT=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData();this._updateSymbolDraw(i,t).updateData(i,{clipShape:this._getClipShape(t)}),this._finished=!0},e.prototype.incrementalPrepareRender=function(t,e,n){var i=t.getData();this._updateSymbolDraw(i,t).incrementalPrepareUpdate(i),this._finished=!1},e.prototype.incrementalRender=function(t,e,n){this._symbolDraw.incrementalUpdate(t,e.getData(),{clipShape:this._getClipShape(e)}),this._finished=t.end===e.getData().count()},e.prototype.updateTransform=function(t,e,n){var i=t.getData();if(this.group.dirty(),!this._finished||i.count()>1e4)return{update:!0};var r=NI("").reset(t,e,n);r.progress&&r.progress({start:0,end:i.count(),count:i.count()},i),this._symbolDraw.updateLayout(i)},e.prototype.eachRendered=function(t){this._symbolDraw&&this._symbolDraw.eachRendered(t)},e.prototype._getClipShape=function(t){if(t.get("clip",!0)){var e=t.coordinateSystem;return e&&e.getArea&&e.getArea(.1)}},e.prototype._updateSymbolDraw=function(t,e){var n=this._symbolDraw,i=e.pipelineContext.large;return n&&i===this._isLargeDraw||(n&&n.remove(),n=this._symbolDraw=i?new OT:new uI,this._isLargeDraw=i,this.group.removeAll()),this.group.add(n.group),n},e.prototype.remove=function(t,e){this._symbolDraw&&this._symbolDraw.remove(!0),this._symbolDraw=null},e.prototype.dispose=function(){},e.type="scatter",e}(tv),NT={left:0,right:0,top:0,bottom:0},zT=["25%","25%"],ET=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.mergeDefaultAndTheme=function(e,n){var i=Kp(e.outerBounds);t.prototype.mergeDefaultAndTheme.apply(this,arguments),i&&e.outerBounds&&qp(e.outerBounds,i)},e.prototype.mergeOption=function(e,n){t.prototype.mergeOption.apply(this,arguments),this.option.outerBounds&&e.outerBounds&&qp(this.option.outerBounds,e.outerBounds)},e.type="grid",e.dependencies=["xAxis","yAxis"],e.layoutMode="box",e.defaultOption={show:!1,z:0,left:"15%",top:65,right:"10%",bottom:80,containLabel:!1,outerBoundsMode:"auto",outerBounds:NT,outerBoundsContain:"all",outerBoundsClampWidth:zT[0],outerBoundsClampHeight:zT[1],backgroundColor:tf.color.transparent,borderWidth:1,borderColor:tf.color.neutral30},e}(Qp),BT=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.getCoordSysModel=function(){return this.getReferringComponents("grid",ha).models[0]},e.type="cartesian2dAxis",e}(Qp);R(BT,nw);var VT={show:!0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:tf.color.axisLine,width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15],breakLine:!0},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12,color:tf.color.axisLabel,textMargin:[0,3]},splitLine:{show:!0,showMinLine:!0,showMaxLine:!0,lineStyle:{color:tf.color.axisSplitLine,width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:[tf.color.backgroundTint,tf.color.backgroundTransparent]}},breakArea:{show:!0,itemStyle:{color:tf.color.neutral00,borderColor:tf.color.border,borderWidth:1,borderType:[3,3],opacity:.6},zigzagAmplitude:4,zigzagMinSpan:4,zigzagMaxSpan:20,zigzagZ:100,expandOnClick:!0},breakLabelLayout:{moveOverlap:"auto"}},GT=C({boundaryGap:!0,deduplication:null,jitter:0,jitterOverlap:!0,jitterMargin:2,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto",show:"auto"},axisLabel:{interval:"auto"}},VT),FT=C({boundaryGap:[0,0],axisLine:{show:"auto"},axisTick:{show:"auto"},splitNumber:5,minorTick:{show:!1,splitNumber:5,length:3,lineStyle:{}},minorSplitLine:{show:!1,lineStyle:{color:tf.color.axisMinorSplitLine,width:1}}},VT),WT={category:GT,value:FT,time:C({splitNumber:6,axisLabel:{showMinLabel:!1,showMaxLabel:!1,rich:{primary:{fontWeight:"bold"}}},splitLine:{show:!1}},FT),log:k({logBase:10},FT)},HT={value:1,category:1,time:1,log:1},UT=null;function YT(){return UT}function XT(t,e,i,r){z(HT,(function(o,a){var s=C(C({},WT[a],!0),r,!0),l=function(t){function i(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e+"Axis."+a,n}return n(i,t),i.prototype.mergeDefaultAndTheme=function(t,e){var n=jp(this),i=n?Kp(t):{};C(t,e.getTheme().get(a+"Axis")),C(t,this.getDefaultOption()),t.type=ZT(t),n&&qp(t,i,n)},i.prototype.optionUpdated=function(){"category"===this.option.type&&(this.__ordinalMeta=ab.createByAxisModel(this))},i.prototype.getCategories=function(t){var e=this.option;if("category"===e.type)return t?e.data:this.__ordinalMeta.categories},i.prototype.getOrdinalMeta=function(){return this.__ordinalMeta},i.prototype.updateAxisBreaks=function(t){var e=YT();return e?e.updateModelAxisBreak(this,t):{breaks:[]}},i.type=e+"Axis."+a,i.defaultOption=s,i}(i);t.registerComponentModel(l)})),t.registerSubTypeDefaulter(e+"Axis",ZT)}function ZT(t){return t.type||(t.data?"category":"value")}var jT=function(){function t(t){this.type="cartesian",this._dimList=[],this._axes={},this.name=t||""}return t.prototype.getAxis=function(t){return this._axes[t]},t.prototype.getAxes=function(){return E(this._dimList,(function(t){return this._axes[t]}),this)},t.prototype.getAxesByScale=function(t){return t=t.toLowerCase(),V(this.getAxes(),(function(e){return e.scale.type===t}))},t.prototype.addAxis=function(t){var e=t.dim;this._axes[e]=t,this._dimList.push(e)},t}(),qT=["x","y"];function KT(t){return("interval"===t.type||"time"===t.type)&&!t.hasBreaks()}var $T=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.type="cartesian2d",e.dimensions=qT,e}return n(e,t),e.prototype.calcAffineTransform=function(){this._transform=this._invTransform=null;var t=this.getAxis("x").scale,e=this.getAxis("y").scale;if(KT(t)&&KT(e)){var n=t.getExtent(),i=e.getExtent(),r=this.dataToPoint([n[0],i[0]]),o=this.dataToPoint([n[1],i[1]]),a=n[1]-n[0],s=i[1]-i[0];if(a&&s){var l=(o[0]-r[0])/a,u=(o[1]-r[1])/s,c=r[0]-n[0]*l,h=r[1]-i[0]*u,d=this._transform=[l,0,0,u,c,h];this._invTransform=Te([],d)}}},e.prototype.getBaseAxis=function(){return this.getAxesByScale("ordinal")[0]||this.getAxesByScale("time")[0]||this.getAxis("x")},e.prototype.containPoint=function(t){var e=this.getAxis("x"),n=this.getAxis("y");return e.contain(e.toLocalCoord(t[0]))&&n.contain(n.toLocalCoord(t[1]))},e.prototype.containData=function(t){return this.getAxis("x").containData(t[0])&&this.getAxis("y").containData(t[1])},e.prototype.containZone=function(t,e){var n=this.dataToPoint(t),i=this.dataToPoint(e),r=this.getArea(),o=new He(n[0],n[1],i[0]-n[0],i[1]-n[1]);return r.intersect(o)},e.prototype.dataToPoint=function(t,e,n){n=n||[];var i=t[0],r=t[1];if(this._transform&&null!=i&&isFinite(i)&&null!=r&&isFinite(r))return Ht(n,t,this._transform);var o=this.getAxis("x"),a=this.getAxis("y");return n[0]=o.toGlobalCoord(o.dataToCoord(i,e)),n[1]=a.toGlobalCoord(a.dataToCoord(r,e)),n},e.prototype.clampData=function(t,e){var n=this.getAxis("x").scale,i=this.getAxis("y").scale,r=n.getExtent(),o=i.getExtent(),a=n.parse(t[0]),s=i.parse(t[1]);return(e=e||[])[0]=Math.min(Math.max(Math.min(r[0],r[1]),a),Math.max(r[0],r[1])),e[1]=Math.min(Math.max(Math.min(o[0],o[1]),s),Math.max(o[0],o[1])),e},e.prototype.pointToData=function(t,e,n){if(n=n||[],this._invTransform)return Ht(n,t,this._invTransform);var i=this.getAxis("x"),r=this.getAxis("y");return n[0]=i.coordToData(i.toLocalCoord(t[0]),e),n[1]=r.coordToData(r.toLocalCoord(t[1]),e),n},e.prototype.getOtherAxis=function(t){return this.getAxis("x"===t.dim?"y":"x")},e.prototype.getArea=function(t){t=t||0;var e=this.getAxis("x").getGlobalExtent(),n=this.getAxis("y").getGlobalExtent(),i=Math.min(e[0],e[1])-t,r=Math.min(n[0],n[1])-t,o=Math.max(e[0],e[1])-i+t,a=Math.max(n[0],n[1])-r+t;return new He(i,r,o,a)},e}(jT),JT=function(t){function e(e,n,i,r,o){var a=t.call(this,e,n,i)||this;return a.index=0,a.type=r||"value",a.position=o||"bottom",a}return n(e,t),e.prototype.isHorizontal=function(){var t=this.position;return"top"===t||"bottom"===t},e.prototype.getGlobalExtent=function(t){var e=this.getExtent();return e[0]=this.toGlobalCoord(e[0]),e[1]=this.toGlobalCoord(e[1]),t&&e[0]>e[1]&&e.reverse(),e},e.prototype.pointToData=function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},e.prototype.setCategorySortInfo=function(t){if("category"!==this.type)return!1;this.model.option.categorySortInfo=t,this.scale.setSortInfo(t)},e}(Ww),QT="expandAxisBreak",tC="collapseAxisBreak",eC="toggleAxisBreak",nC="axisbreakchanged",iC={type:QT,event:nC,update:"update",refineEvent:aC},rC={type:tC,event:nC,update:"update",refineEvent:aC},oC={type:eC,event:nC,update:"update",refineEvent:aC};function aC(t,e,n,i){var r=[];return z(t,(function(t){r=r.concat(t.eventBreaks)})),{eventContent:{breaks:r}}}var sC=Math.PI,lC=[[1,2,1,2],[5,3,5,3],[8,3,8,3]],uC=[[0,1,0,1],[0,3,0,3],[0,3,0,3]],cC=sa(),hC=sa(),dC=function(){function t(t){this.recordMap={},this.resolveAxisNameOverlap=t}return t.prototype.ensureRecord=function(t){var e=t.axis.dim,n=t.componentIndex,i=this.recordMap,r=i[e]||(i[e]=[]);return r[n]||(r[n]={ready:{}})},t}();var pC=[1,0,0,1,0,0],fC=new He(0,0,0,0),gC=function(t,e,n,i,r,o){if(Qb(t.nameLocation)){var a=o.stOccupiedRect;a&&yC(function(t,e,n){return t.transform=Wh(t.transform,n),t.localRect=Fh(t.localRect,e),t.rect=Fh(t.rect,e),n&&t.rect.applyTransform(n),t.axisAligned=Vh(n),t.obb=void 0,(t.label=t.label||{}).ignore=!1,t}({},a,o.transGroup.transform),i,r)}else vC(o.labelInfoList,o.dirVec,i,r)};function yC(t,e,n){var i=new Ae;IS(t,e,i,{direction:Math.atan2(n.y,n.x),bidirectional:!1,touchThreshold:.05})&&_S(e,i)}function vC(t,e,n,i){for(var r=Ae.dot(i,e)>=0,o=0,a=t.length;o0?"top":"bottom",i="center"):Co(o-sC)?(r=n>0?"bottom":"top",i="center"):(r="middle",i=o>0&&o0?"right":"left":n>0?"left":"right"),{rotation:o,textAlign:i,textVerticalAlign:r}},t.makeAxisEventDataBase=function(t){var e={componentType:t.mainType,componentIndex:t.componentIndex};return e[t.mainType+"Index"]=t.componentIndex,e},t.isLabelSilent=function(t){var e=t.get("tooltip");return t.get("silent")||!(t.get("triggerEvent")||e&&e.show)},t}(),xC=["axisLine","axisTickLabelEstimate","axisTickLabelDetermine","axisName"],_C={axisLine:function(t,e,n,i,r,o,a){var s=i.get(["axisLine","show"]);if("auto"===s&&(s=!0,null!=t.raw.axisLineAutoShow&&(s=!!t.raw.axisLineAutoShow)),s){var l=i.axis.getExtent(),u=o.transform,c=[l[0],0],h=[l[1],0],d=c[0]>h[0];u&&(Ht(c,c,u),Ht(h,h,u));var p=A({lineCap:"round"},i.getModel(["axisLine","lineStyle"]).getLineStyle()),f={strokeContainThreshold:t.raw.strokeContainThreshold||5,silent:!0,z2:1,style:p};if(i.get(["axisLine","breakLine"])&&i.axis.scale.hasBreaks())YT().buildAxisBreakLine(i,r,o,f);else{var g=new Ac(A({shape:{x1:c[0],y1:c[1],x2:h[0],y2:h[1]}},f));_h(g.shape,g.style.lineWidth),g.anid="line",r.add(g)}var y=i.get(["axisLine","symbol"]);if(null!=y){var v=i.get(["axisLine","symbolSize"]);X(y)&&(y=[y,y]),(X(v)||j(v))&&(v=[v,v]);var m=pm(i.get(["axisLine","symbolOffset"])||0,v),x=v[0],_=v[1];z([{rotate:t.rotation+Math.PI/2,offset:m[0],r:0},{rotate:t.rotation-Math.PI/2,offset:m[1],r:Math.sqrt((c[0]-h[0])*(c[0]-h[0])+(c[1]-h[1])*(c[1]-h[1]))}],(function(e,n){if("none"!==y[n]&&null!=y[n]){var i=hm(y[n],-x/2,-_/2,x,_,p.stroke,!0),o=e.r+e.offset,a=d?h:c;i.attr({rotation:e.rotate,x:a[0]+o*Math.cos(t.rotation),y:a[1]-o*Math.sin(t.rotation),silent:!0,z2:11}),r.add(i)}}))}}},axisTickLabelEstimate:function(t,e,n,i,r,o,a,s){MC(e,r,s)&&bC(t,e,n,i,r,o,a,Iw)},axisTickLabelDetermine:function(t,e,n,i,r,o,a,s){MC(e,r,s)&&bC(t,e,n,i,r,o,a,Tw);var l=function(t,e,n,i){var r=i.axis,o=i.getModel("axisTick"),a=o.get("show");"auto"===a&&(a=!0,null!=t.raw.axisTickAutoShow&&(a=!!t.raw.axisTickAutoShow));if(!a||r.scale.isBlank())return[];for(var s=o.getModel("lineStyle"),l=t.tickDirection*o.get("length"),u=SC(r.getTicksCoords(),n.transform,l,k(s.getLineStyle(),{stroke:i.get(["axisLine","lineStyle","color"])}),"ticks"),c=0;ci[1],l="start"===e&&!s||"start"!==e&&s;Co(a-sC/2)?(o=l?"bottom":"top",r="center"):Co(a-1.5*sC)?(o=l?"top":"bottom",r="center"):(o="middle",r=a<1.5*sC&&a>sC/2?l?"left":"right":l?"right":"left");return{rotation:a,textAlign:r,textVerticalAlign:o}}(t.rotation,c,b||0,f),null!=(_=t.raw.axisNameAvailableWidth)&&(_=Math.abs(_/Math.sin(x.rotation)),!isFinite(_)&&(_=null)));var w=d.getFont(),S=i.get("nameTruncate",!0)||{},M=S.ellipsis,I=it(t.raw.nameTruncateMaxWidth,S.maxWidth,_),T=s.nameMarginLevel||0,C=new Sl({x:y.x,y:y.y,rotation:x.rotation,silent:mC.isLabelSilent(i),style:Qh(d,{text:u,font:w,overflow:"truncate",width:I,ellipsis:M,fill:d.getTextColor()||i.get(["axisLine","lineStyle","color"]),align:d.get("align")||x.textAlign,verticalAlign:d.get("verticalAlign")||x.textVerticalAlign}),z2:1});if(zh({el:C,componentModel:i,itemName:u}),C.__fullText=u,C.anid="name",i.get("triggerEvent")){var D=mC.makeAxisEventDataBase(i);D.targetType="axisName",D.name=u,zl(C).eventData=D}o.add(C),C.updateTransform(),e.nameEl=C;var A=l.nameLayout=vS({label:C,priority:C.z2,defaultAttr:{ignore:C.ignore},marginDefault:Qb(c)?lC[T]:uC[T]});if(l.nameLocation=c,r.add(C),C.decomposeTransform(),t.shouldNameMoveOverlap&&A){var k=n.ensureRecord(i);0,n.resolveAxisNameOverlap(t,n,i,A,v,k)}}}};function bC(t,e,n,i,r,o,a,s){IC(e)||function(t,e,n,i,r,o){var a=r.axis,s=it(t.raw.axisLabelShow,r.get(["axisLabel","show"])),l=new to;n.add(l);var u=Cw(i);if(!s||a.scale.isBlank())return void TC(e,[],l,u);var c=r.getModel("axisLabel"),h=a.getViewLabels(u),d=(it(t.raw.labelRotate,c.get("rotate"))||0)*sC/180,p=mC.innerTextLayout(t.rotation,d,t.labelDirection),f=r.getCategories&&r.getCategories(!0),g=[],y=r.get("triggerEvent"),v=1/0,m=-1/0;z(h,(function(t,e){var n,i="ordinal"===a.scale.type?a.scale.getRawOrdinalNumber(t.tickValue):t.tickValue,s=t.formattedLabel,u=t.rawLabel,d=c;if(f&&f[i]){var x=f[i];q(x)&&x.textStyle&&(d=new wd(x.textStyle,c,r.ecModel))}var _=d.getTextColor()||r.get(["axisLine","lineStyle","color"]),b=d.getShallow("align",!0)||p.textAlign,w=rt(d.getShallow("alignMinLabel",!0),b),S=rt(d.getShallow("alignMaxLabel",!0),b),M=d.getShallow("verticalAlign",!0)||d.getShallow("baseline",!0)||p.textVerticalAlign,I=rt(d.getShallow("verticalAlignMinLabel",!0),M),T=rt(d.getShallow("verticalAlignMaxLabel",!0),M),C=10+((null===(n=t.time)||void 0===n?void 0:n.level)||0);v=Math.min(v,C),m=Math.max(m,C);var D=new Sl({x:0,y:0,rotation:0,silent:mC.isLabelSilent(r),z2:C,style:Qh(d,{text:s,align:0===e?w:e===h.length-1?S:b,verticalAlign:0===e?I:e===h.length-1?T:M,fill:Y(_)?_("category"===a.type?u:"value"===a.type?i+"":i,e):_})});D.anid="label_"+i;var A=cC(D);if(A.break=t.break,A.tickValue=i,A.layoutRotation=p.rotation,zh({el:D,componentModel:r,itemName:s,formatterParamsExtra:{isTruncated:function(){return D.isTruncated},value:u,tickIndex:e}}),y){var k=mC.makeAxisEventDataBase(r);k.targetType="axisLabel",k.value=u,k.tickIndex=e,t.break&&(k.break={start:t.break.parsedBreak.vmin,end:t.break.parsedBreak.vmax}),"category"===a.type&&(k.dataIndex=i),zl(D).eventData=k,t.break&&function(t,e,n,i){n.on("click",(function(n){var r={type:QT,breaks:[{start:i.parsedBreak.breakOption.start,end:i.parsedBreak.breakOption.end}]};r[t.axis.dim+"AxisIndex"]=t.componentIndex,e.dispatchAction(r)}))}(r,o,D,t.break)}g.push(D),l.add(D)}));var x=E(g,(function(t){return{label:t,priority:cC(t).break?t.z2+(m-v+1):t.z2,defaultAttr:{ignore:t.ignore}}}));TC(e,x,l,u)}(t,e,r,s,i,a);var l=e.labelLayoutList;!function(t,e,n,i){var r=e.get(["axisLabel","margin"]);z(n,(function(n,o){var a=vS(n);if(a){var s=a.label,l=cC(s);a.suggestIgnore=s.ignore,s.ignore=!1,kr(CC,DC),CC.x=e.axis.dataToCoord(l.tickValue),CC.y=t.labelOffset+t.labelDirection*r,CC.rotation=l.layoutRotation,i.add(CC),CC.updateTransform(),i.remove(CC),CC.decomposeTransform(),kr(s,CC),s.markRedraw(),gS(a,!0),vS(a)}}))}(t,i,l,o),function(t,e,n){var i=Nd();if(!i)return;var r=i.retrieveAxisBreakPairs(n,(function(t){return t&&cC(t.label).break}),!0),o=t.get(["breakLabelLayout","moveOverlap"],!0);!0!==o&&"auto"!==o||z(r,(function(i){YT().adjustBreakLabelPair(t.axis.inverse,e,[vS(n[i[0]]),vS(n[i[1]])])}))}(i,t.rotation,l);var u=t.optionHideOverlap;!function(t,e,n){if($b(t.axis))return;function i(t,i,r){var o=vS(e[i]),a=vS(e[r]);if(o&&a)if(!1===t||o.suggestIgnore)wC(o.label);else if(a.suggestIgnore)wC(a.label);else{var s=.1;if(!n){var l=[0,0,0,0];o=bS({marginForce:l},o),a=bS({marginForce:l},a)}IS(o,a,null,{touchThreshold:s})&&wC(t?a.label:o.label)}}var r=t.get(["axisLabel","showMinLabel"]),o=t.get(["axisLabel","showMaxLabel"]),a=e.length;i(r,0,1),i(o,a-1,a-2)}(i,l,u),u&&MS(V(l,(function(t){return t&&!t.label.ignore}))),function(t,e,n,i){var r,o=n.axis,a=e.ensureRecord(n),s=[],l=AC(t.axisName)&&Qb(t.nameLocation);z(i,(function(t){var e=vS(t);if(e&&!e.label.ignore){s.push(e);var n=a.transGroup;l&&(n.transform?Te(pC,n.transform):_e(pC),e.transform&&we(pC,pC,e.transform),He.copy(fC,e.localRect),fC.applyTransform(pC),r?r.union(fC):He.copy(r=new He(0,0,0,0),fC))}}));var u=Math.abs(a.dirVec.x)>.1?"x":"y",c=a.transGroup[u];if(s.sort((function(t,e){return Math.abs(t.label[u]-c)-Math.abs(e.label[u]-c)})),l&&r){var h=o.getExtent(),d=Math.min(h[0],h[1]),p=Math.max(h[0],h[1])-d;r.union(new He(d,0,p,1))}a.stOccupiedRect=r,a.labelInfoList=s}(t,n,i,l)}function wC(t){t&&(t.ignore=!0)}function SC(t,e,n,i,r){for(var o=[],a=[],s=[],l=0;lu[0]&&isFinite(f)&&isFinite(u[0]);)p=K_(p),f=u[1]-p*a;else{t.getTicks().length-1>a&&(p=K_(p));var y=p*a;(f=mo((g=Math.ceil(u[1]/p)*p)-y))<0&&u[0]>=0?(f=0,g=mo(y)):g>0&&u[1]<=0&&(g=0,f=-mo(y))}var v=(r[0].value-o[0].value)/s,m=(r[a].value-o[a].value)/s;i.setExtent.call(t,f+p*v,g+p*m),i.setInterval.call(t,p),(v||m)&&i.setNiceExtent.call(t,f+p,g-p)}var OC,RC=[[3,1],[0,2]],NC=function(){function t(t,e,n){this.type="grid",this._coordsMap={},this._coordsList=[],this._axesMap={},this._axesList=[],this.axisPointerEnabled=!0,this.dimensions=qT,this._initCartesian(t,e,n),this.model=t}return t.prototype.getRect=function(){return this._rect},t.prototype.update=function(t,e){var n=this._axesMap;function i(t){var e,n=F(t),i=n.length;if(i){for(var r=[],o=i-1;o>=0;o--){var a=t[+n[o]],s=a.model,l=a.scale;j_(l)&&s.get("alignTicks")&&null==s.get("interval")?r.push(a):(Xb(l,s),j_(l)&&(e=a))}r.length&&(e||Xb((e=r.pop()).scale,e.model),z(r,(function(t){PC(t.scale,t.model,e.scale)})))}}this._updateScale(t,this.model),i(n.x),i(n.y);var r={};z(n.x,(function(t){EC(n,"y",t,r)})),z(n.y,(function(t){EC(n,"x",t,r)})),this.resize(this.model,e)},t.prototype.resize=function(t,e,n){var i=Xp(t,e),r=this._rect=Hp(t.getBoxLayoutParams(),i.refContainer),o=this._axesMap,a=this._coordsList,s=t.get("containLabel");if(VC(o,r),!n){var l=function(t,e,n,i,r){var o=new dC(HC);return z(n,(function(n){return z(n,(function(n){if(tw(n.model)){var a=!i;n.axisBuilder=function(t,e,n,i,r,o){for(var a=kC(t,n),s=!1,l=!1,u=0;u0&&i>0||n<0&&i<0)}(t)}function VC(t,e){z(t.x,(function(t){return GC(t,e.x,e.width)})),z(t.y,(function(t){return GC(t,e.y,e.height)}))}function GC(t,e,n){var i=[0,n],r=t.inverse?1:0;t.setExtent(i[r],i[1-r]),function(t,e){var n=t.getExtent(),i=n[0]+n[1];t.toGlobalCoord="x"===t.dim?function(t){return t+e}:function(t){return i-t+e},t.toLocalCoord="x"===t.dim?function(t){return t-e}:function(t){return i-t+e}}(t,e)}function FC(t,e,n,i,r,o,a){WC(i,r,Iw,e,!1,a);var s=[0,0,0,0];u(0),u(1),c(i,0,NaN),c(i,1,NaN);var l=null==G(s,(function(t){return t>0}));return Oh(i,s,!0,!0,n),VC(r,i),l;function u(t){z(r[lh[t]],(function(e){if(tw(e.model)){var n=o.ensureRecord(e.model),i=n.labelInfoList;if(i)for(var r=0;r0&&!nt(e)&&e>1e-4&&(t/=e),t}}function WC(t,e,n,i,r,o){var a=n===Tw;z(e,(function(e){return z(e,(function(e){tw(e.model)&&(!function(t,e,n){var i=kC(e,n);t.updateCfg(i)}(e.axisBuilder,t,e.model),e.axisBuilder.build(a?{axisTickLabelDetermine:!0}:{axisTickLabelEstimate:!0},{noPxChange:r}))}))}));var s={x:0,y:0};function l(e){s[lh[1-e]]=t[uh[e]]<=.5*o.refContainer[uh[e]]?0:1-e==1?2:1}l(0),l(1),z(e,(function(t,e){return z(t,(function(t){tw(t.model)&&(("all"===i||a)&&t.axisBuilder.build({axisName:!0},{nameMarginLevel:s[e]}),a&&t.axisBuilder.build({axisLine:!0}))}))}))}var HC=function(t,e,n,i,r,o){var a="x"===n.axis.dim?"y":"x";gC(t,0,0,i,r,o),Qb(t.nameLocation)||z(e.recordMap[a],(function(t){t&&t.labelInfoList&&t.dirVec&&vC(t.labelInfoList,t.dirVec,i,r)}))};function UC(t,e){var n={axesInfo:{},seriesInvolved:!1,coordSysAxesInfo:{},coordSysMap:{}};return function(t,e,n){var i=e.getComponent("tooltip"),r=e.getComponent("axisPointer"),o=r.get("link",!0)||[],a=[];z(n.getCoordinateSystems(),(function(n){if(n.axisPointerEnabled){var s=qC(n.model),l=t.coordSysAxesInfo[s]={};t.coordSysMap[s]=n;var u=n.model.getModel("tooltip",i);if(z(n.getAxes(),H(p,!1,null)),n.getTooltipAxes&&i&&u.get("show")){var c="axis"===u.get("trigger"),h="cross"===u.get(["axisPointer","type"]),d=n.getTooltipAxes(u.get(["axisPointer","axis"]));(c||h)&&z(d.baseAxes,H(p,!h||"cross",c)),h&&z(d.otherAxes,H(p,"cross",!1))}}function p(i,s,c){var h=c.model.getModel("axisPointer",r),d=h.get("show");if(d&&("auto"!==d||i||jC(h))){null==s&&(s=h.get("triggerTooltip")),h=i?function(t,e,n,i,r,o){var a=e.getModel("axisPointer"),s={};z(["type","snap","lineStyle","shadowStyle","label","animation","animationDurationUpdate","animationEasingUpdate","z"],(function(t){s[t]=T(a.get(t))})),s.snap="category"!==t.type&&!!o,"cross"===a.get("type")&&(s.type="line");var l=s.label||(s.label={});if(null==l.show&&(l.show=!1),"cross"===r){var u=a.get(["label","show"]);if(l.show=null==u||u,!o){var c=s.lineStyle=a.get("crossStyle");c&&k(l,c.textStyle)}}return t.model.getModel("axisPointer",new wd(s,n,i))}(c,u,r,e,i,s):h;var p=h.get("snap"),f=h.get("triggerEmphasis"),g=qC(c.model),y=s||p||"category"===c.type,v=t.axesInfo[g]={key:g,axis:c,coordSys:n,axisPointerModel:h,triggerTooltip:s,triggerEmphasis:f,involveSeries:y,snap:p,useHandle:jC(h),seriesModels:[],linkGroup:null};l[g]=v,t.seriesInvolved=t.seriesInvolved||y;var m=function(t,e){for(var n=e.model,i=e.dim,r=0;r=0||t===e}function XC(t){var e=ZC(t);if(e){var n=e.axisPointerModel,i=e.axis.scale,r=n.option,o=n.get("status"),a=n.get("value");null!=a&&(a=i.parse(a));var s=jC(n);null==o&&(r.status=s?"show":"hide");var l=i.getExtent().slice();l[0]>l[1]&&l.reverse(),(null==a||a>l[1])&&(a=l[1]),a0?s?hD(n,a,u,i):function(t,e,n,i,r,o){var a=uD(t);a.items||(a.items=[]);var s=a.items,l=dD(s,e,n,i,r,o,1),u=dD(s,e,n,i,r,o,-1),c=Math.abs(l-n)r/2||h&&d>h/2-i)return hD(n,r,h,i);return s.push({fixedCoord:e,floatCoord:c,r:i}),c}(t,e,n,i,a,l):n}function hD(t,e,n,i){if(null===n)return t+(Math.random()-.5)*e;var r=n-2*i,o=Math.min(Math.max(0,e),r);return t+(Math.random()-.5)*o}function dD(t,e,n,i,r,o,a){for(var s=n,l=0;lr/2)return Number.MAX_VALUE;if(1===a&&f>s||-1===a&&f0;return a&&s}(t,n);if(i){var r=t.getData();r.each((function(t){var e=n.dim,i=n.orient,o="horizontal"===i&&"category"!==n.type||"vertical"===i&&"category"===n.type,a=r.getItemLayout(t),s=r.getItemVisual(t,"symbolSize"),l=s instanceof Array?(s[1]+s[0])/2:s;if("y"===e||"single"===e&&o){var u=cD(n,a[0],a[1],l/2);r.setItemLayout(t,[a[0],u])}else if("x"===e||"single"===e&&!o){u=cD(n,a[1],a[0],l/2);r.setItemLayout(t,[u,a[1]])}}))}}}))}function fD(t){t.eachSeriesByType("radar",(function(t){var e=t.getData(),n=[],i=t.coordinateSystem;if(i){var r=i.getIndicatorAxes();z(r,(function(t,o){e.each(e.mapDimension(r[o].dim),(function(t,e){n[e]=n[e]||[];var r=i.dataToPoint(t,o);n[e][o]=gD(r)?r:yD(i)}))})),e.each((function(t){var r=G(n[t],(function(t){return gD(t)}))||yD(i);n[t].push(r.slice()),e.setItemLayout(t,n[t])}))}}))}function gD(t){return!isNaN(t[0])&&!isNaN(t[1])}function yD(t){return[t.cx,t.cy]}function vD(t){var e=t.polar;if(e){U(e)||(e=[e]);var n=[];z(e,(function(e,i){e.indicator?(e.type&&!e.shape&&(e.shape=e.type),t.radar=t.radar||[],U(t.radar)||(t.radar=[t.radar]),t.radar.push(e)):n.push(e)})),t.polar=n}z(t.series,(function(t){t&&"radar"===t.type&&t.polarIndex&&(t.radarIndex=t.polarIndex)}))}var mD=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.coordinateSystem,r=this.group,o=t.getData(),a=this._data;function s(t,e){var n=t.getItemVisual(e,"symbol")||"circle";if("none"!==n){var i=dm(t.getItemVisual(e,"symbolSize")),r=hm(n,-1,-1,2,2),o=t.getItemVisual(e,"symbolRotate")||0;return r.attr({style:{strokeNoScale:!0},z2:100,scaleX:i[0]/2,scaleY:i[1]/2,rotation:o*Math.PI/180||0}),r}}function l(e,n,i,r,o,a){i.removeAll();for(var l=0;l0&&!h.min?h.min=0:null!=h.min&&h.min<0&&!h.max&&(h.max=0);var d=a;null!=h.color&&(d=k({color:h.color},a));var p=C(T(h),{boundaryGap:t,splitNumber:e,scale:n,axisLine:i,axisTick:r,axisLabel:o,name:h.text,showName:s,nameLocation:"end",nameGap:u,nameTextStyle:d,triggerEvent:c},!1);if(X(l)){var f=p.name;p.name=l.replace("{value}",null!=f?f:"")}else Y(l)&&(p.name=l(p.name,p));var g=new wd(p,null,this.ecModel);return R(g,nw.prototype),g.mainType="radar",g.componentIndex=this.componentIndex,g}),this);this._indicatorModels=h},e.prototype.getIndicatorModels=function(){return this._indicatorModels},e.type="radar",e.defaultOption={z:0,center:["50%","50%"],radius:"50%",startAngle:90,axisName:{show:!0,color:tf.color.axisLabel},boundaryGap:[0,0],splitNumber:5,axisNameGap:15,scale:!1,shape:"polygon",axisLine:C({lineStyle:{color:tf.color.neutral20}},_D.axisLine),axisLabel:bD(_D.axisLabel,!1),axisTick:bD(_D.axisTick,!1),splitLine:bD(_D.splitLine,!0),splitArea:bD(_D.splitArea,!0),indicator:[]},e}(Qp),SD=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){this.group.removeAll(),this._buildAxes(t,n),this._buildSplitLineAndArea(t)},e.prototype._buildAxes=function(t,e){var n=t.coordinateSystem;z(E(n.getIndicatorAxes(),(function(t){var i=t.model.get("showName")?t.name:"";return new mC(t.model,e,{axisName:i,position:[n.cx,n.cy],rotation:t.angle,labelDirection:-1,tickDirection:-1,nameDirection:1})})),(function(t){t.build(),this.group.add(t.group)}),this)},e.prototype._buildSplitLineAndArea=function(t){var e=t.coordinateSystem,n=e.getIndicatorAxes();if(n.length){var i=t.get("shape"),r=t.getModel("splitLine"),o=t.getModel("splitArea"),a=r.getModel("lineStyle"),s=o.getModel("areaStyle"),l=r.get("show"),u=o.get("show"),c=a.get("color"),h=s.get("color"),d=U(c)?c:[c],p=U(h)?h:[h],f=[],g=[];if("circle"===i)for(var y=n[0].getTicksCoords(),v=e.cx,m=e.cy,x=0;x3?1.4:r>1?1.2:1.1,l=i>0?s:1/s;this._checkTriggerMoveZoom(this,"zoom","zoomOnMouseWheel",t,{scale:l,originX:o,originY:a,isAvailableBehavior:null})}if(n){var u=Math.abs(i),c=(i>0?1:-1)*(u>3?.4:u>1?.15:.05);this._checkTriggerMoveZoom(this,"scrollMove","moveOnMouseWheel",t,{scrollDelta:c,originX:o,originY:a,isAvailableBehavior:null})}}}},e.prototype._pinchHandler=function(t){if(!DD(this._zr,"globalPan")&&!PD(t)){var e=t.pinchScale>1?1.1:1/1.1;this._checkTriggerMoveZoom(this,"zoom",null,t,{scale:e,originX:t.pinchX,originY:t.pinchY,isAvailableBehavior:null})}},e.prototype._checkTriggerMoveZoom=function(t,e,n,i,r){t._checkPointer(i,r.originX,r.originY)&&(fe(i.event),i.__ecRoamConsumed=!0,VD(t,e,n,i,r))},e}(qt);function PD(t){return t.__ecRoamConsumed}var OD,RD=sa();function ND(t){var e=RD(t);return e.roam=e.roam||{},e.uniform=e.uniform||{},e}function zD(t,e,n,i){for(var r=ND(t).roam,o=r[e]=r[e]||[],a=0;a=4&&(l={x:parseFloat(h[0]||0),y:parseFloat(h[1]||0),width:parseFloat(h[2]),height:parseFloat(h[3])})}if(l&&null!=a&&null!=s&&(u=fA(l,{x:0,y:0,width:a,height:s}),!e.ignoreViewBox)){var d=i;(i=new to).add(d),d.scaleX=d.scaleY=u.scale,d.x=u.x,d.y=u.y}return e.ignoreRootClip||null==a||null==s||i.setClipPath(new xl({shape:{x:0,y:0,width:a,height:s}})),{root:i,width:a,height:s,viewBoxRect:l,viewBoxTransform:u,named:r}},t.prototype._parseNode=function(t,e,n,i,r,o){var a,s=t.nodeName.toLowerCase(),l=i;if("defs"===s&&(r=!0),"text"===s&&(o=!0),"defs"===s||"switch"===s)a=e;else{if(!r){var u=OD[s];if(u&&_t(OD,s)){a=u.call(this,t,e);var c=t.getAttribute("name");if(c){var h={name:c,namedFrom:null,svgNodeTagLower:s,el:a};n.push(h),"g"===s&&(l=h)}else i&&n.push({name:i.name,namedFrom:i,svgNodeTagLower:s,el:a});e.add(a)}}var d=tA[s];if(d&&_t(tA,s)){var p=d.call(this,t),f=t.getAttribute("id");f&&(this._defs[f]=p)}}if(a&&a.isGroup)for(var g=t.firstChild;g;)1===g.nodeType?this._parseNode(g,a,n,l,r,o):3===g.nodeType&&o&&this._parseText(g,a),g=g.nextSibling},t.prototype._parseText=function(t,e){var n=new ul({style:{text:t.textContent},silent:!0,x:this._textX||0,y:this._textY||0});iA(e,n),oA(t,n,this._defsUsePending,!1,!1),function(t,e){var n=e.__selfStyle;if(n){var i=n.textBaseline,r=i;i&&"auto"!==i?"baseline"===i?r="alphabetic":"before-edge"===i||"text-before-edge"===i?r="top":"after-edge"===i||"text-after-edge"===i?r="bottom":"central"!==i&&"mathematical"!==i||(r="middle"):r="alphabetic",t.style.textBaseline=r}var o=e.__inheritedStyle;if(o){var a=o.textAlign,s=a;a&&("middle"===a&&(s="center"),t.style.textAlign=s)}}(n,e);var i=n.style,r=i.fontSize;r&&r<9&&(i.fontSize=9,n.scaleX*=r/9,n.scaleY*=r/9);var o=(i.fontSize||i.fontFamily)&&[i.fontStyle,i.fontWeight,(i.fontSize||12)+"px",i.fontFamily||"sans-serif"].join(" ");i.font=o;var a=n.getBoundingRect();return this._textX+=a.width,e.add(n),n},t.internalField=void(OD={g:function(t,e){var n=new to;return iA(e,n),oA(t,n,this._defsUsePending,!1,!1),n},rect:function(t,e){var n=new xl;return iA(e,n),oA(t,n,this._defsUsePending,!1,!1),n.setShape({x:parseFloat(t.getAttribute("x")||"0"),y:parseFloat(t.getAttribute("y")||"0"),width:parseFloat(t.getAttribute("width")||"0"),height:parseFloat(t.getAttribute("height")||"0")}),n.silent=!0,n},circle:function(t,e){var n=new nc;return iA(e,n),oA(t,n,this._defsUsePending,!1,!1),n.setShape({cx:parseFloat(t.getAttribute("cx")||"0"),cy:parseFloat(t.getAttribute("cy")||"0"),r:parseFloat(t.getAttribute("r")||"0")}),n.silent=!0,n},line:function(t,e){var n=new Ac;return iA(e,n),oA(t,n,this._defsUsePending,!1,!1),n.setShape({x1:parseFloat(t.getAttribute("x1")||"0"),y1:parseFloat(t.getAttribute("y1")||"0"),x2:parseFloat(t.getAttribute("x2")||"0"),y2:parseFloat(t.getAttribute("y2")||"0")}),n.silent=!0,n},ellipse:function(t,e){var n=new rc;return iA(e,n),oA(t,n,this._defsUsePending,!1,!1),n.setShape({cx:parseFloat(t.getAttribute("cx")||"0"),cy:parseFloat(t.getAttribute("cy")||"0"),rx:parseFloat(t.getAttribute("rx")||"0"),ry:parseFloat(t.getAttribute("ry")||"0")}),n.silent=!0,n},polygon:function(t,e){var n,i=t.getAttribute("points");i&&(n=rA(i));var r=new Mc({shape:{points:n||[]},silent:!0});return iA(e,r),oA(t,r,this._defsUsePending,!1,!1),r},polyline:function(t,e){var n,i=t.getAttribute("points");i&&(n=rA(i));var r=new Tc({shape:{points:n||[]},silent:!0});return iA(e,r),oA(t,r,this._defsUsePending,!1,!1),r},image:function(t,e){var n=new dl;return iA(e,n),oA(t,n,this._defsUsePending,!1,!1),n.setStyle({image:t.getAttribute("xlink:href")||t.getAttribute("href"),x:+t.getAttribute("x"),y:+t.getAttribute("y"),width:+t.getAttribute("width"),height:+t.getAttribute("height")}),n.silent=!0,n},text:function(t,e){var n=t.getAttribute("x")||"0",i=t.getAttribute("y")||"0",r=t.getAttribute("dx")||"0",o=t.getAttribute("dy")||"0";this._textX=parseFloat(n)+parseFloat(r),this._textY=parseFloat(i)+parseFloat(o);var a=new to;return iA(e,a),oA(t,a,this._defsUsePending,!1,!0),a},tspan:function(t,e){var n=t.getAttribute("x"),i=t.getAttribute("y");null!=n&&(this._textX=parseFloat(n)),null!=i&&(this._textY=parseFloat(i));var r=t.getAttribute("dx")||"0",o=t.getAttribute("dy")||"0",a=new to;return iA(e,a),oA(t,a,this._defsUsePending,!1,!0),this._textX+=parseFloat(r),this._textY+=parseFloat(o),a},path:function(t,e){var n=Qu(t.getAttribute("d")||"");return iA(e,n),oA(t,n,this._defsUsePending,!1,!1),n.silent=!0,n}}),t}(),tA={lineargradient:function(t){var e=parseInt(t.getAttribute("x1")||"0",10),n=parseInt(t.getAttribute("y1")||"0",10),i=parseInt(t.getAttribute("x2")||"10",10),r=parseInt(t.getAttribute("y2")||"0",10),o=new Bc(e,n,i,r);return eA(t,o),nA(t,o),o},radialgradient:function(t){var e=parseInt(t.getAttribute("cx")||"0",10),n=parseInt(t.getAttribute("cy")||"0",10),i=parseInt(t.getAttribute("r")||"0",10),r=new Vc(e,n,i);return eA(t,r),nA(t,r),r}};function eA(t,e){"userSpaceOnUse"===t.getAttribute("gradientUnits")&&(e.global=!0)}function nA(t,e){for(var n=t.firstChild;n;){if(1===n.nodeType&&"stop"===n.nodeName.toLocaleLowerCase()){var i=n.getAttribute("offset"),r=void 0;r=i&&i.indexOf("%")>0?parseInt(i,10)/100:i?parseFloat(i):0;var o={};pA(n,o,o);var a=o.stopColor||n.getAttribute("stop-color")||"#000000",s=o.stopOpacity||n.getAttribute("stop-opacity");if(s){var l=oi(a);l&&l[3]&&(l[3]*=$n(s),a=fi(l,"rgba"))}e.colorStops.push({offset:r,color:a})}n=n.nextSibling}}function iA(t,e){t&&t.__inheritedStyle&&(e.__inheritedStyle||(e.__inheritedStyle={}),k(e.__inheritedStyle,t.__inheritedStyle))}function rA(t){for(var e=uA(t),n=[],i=0;i0;o-=2){var a=i[o],s=i[o-1],l=uA(a);switch(r=r||[1,0,0,1,0,0],s){case"translate":Se(r,r,[parseFloat(l[0]),parseFloat(l[1]||"0")]);break;case"scale":Ie(r,r,[parseFloat(l[0]),parseFloat(l[1]||l[0])]);break;case"rotate":Me(r,r,-parseFloat(l[0])*hA,[parseFloat(l[1]||"0"),parseFloat(l[2]||"0")]);break;case"skewX":we(r,[1,0,Math.tan(parseFloat(l[0])*hA),1,0,0],r);break;case"skewY":we(r,[1,Math.tan(parseFloat(l[0])*hA),0,1,0,0],r);break;case"matrix":r[0]=parseFloat(l[0]),r[1]=parseFloat(l[1]),r[2]=parseFloat(l[2]),r[3]=parseFloat(l[3]),r[4]=parseFloat(l[4]),r[5]=parseFloat(l[5])}}e.setLocalTransform(r)}}(t,e),pA(t,a,s),i||function(t,e,n){for(var i=0;i0,y={api:n,geo:l,mapOrGeoModel:t,data:a,isVisualEncodedByVisualMap:g,isGeo:o,transformInfoRaw:d};"geoJSON"===l.resourceType?this._buildGeoJSON(y):"geoSVG"===l.resourceType&&this._buildSVG(y),this._updateController(t,s,e,n),this._updateMapSelectHandler(t,u,n,i)},t.prototype._buildGeoJSON=function(t){var e=this._regionsGroupByName=yt(),n=yt(),i=this._regionsGroup,r=t.transformInfoRaw,o=t.mapOrGeoModel,a=t.data,s=t.geo.projection,l=s&&s.stream;function u(t,e){return e&&(t=e(t)),t&&[t[0]*r.scaleX+r.x,t[1]*r.scaleY+r.y]}function c(t){for(var e=[],n=!l&&s&&s.project,i=0;i=0)&&(d=r);var p=a?{normal:{align:"center",verticalAlign:"middle"}}:null;$h(e,Jh(i),{labelFetcher:d,labelDataIndex:h,defaultText:n},p);var f=e.getTextContent();if(f&&(NA(f).ignore=f.ignore,e.textConfig&&a)){var g=e.getBoundingRect().clone();e.textConfig.layoutRect=g,e.textConfig.position=[(a[0]-g.x)/g.width*100+"%",(a[1]-g.y)/g.height*100+"%"]}e.disableLabelAnimation=!0}else e.removeTextContent(),e.removeTextConfig(),e.disableLabelAnimation=null}function FA(t,e,n,i,r,o){t.data?t.data.setItemGraphicEl(o,e):zl(e).eventData={componentType:"geo",componentIndex:r.componentIndex,geoIndex:r.componentIndex,name:n,region:i&&i.option||{}}}function WA(t,e,n,i,r){t.data||zh({el:e,componentModel:r,itemName:n,itemTooltipOption:i.get("tooltip")})}function HA(t,e,n,i,r){e.highDownSilentOnTouch=!!r.get("selectedMode");var o=i.getModel("emphasis"),a=o.get("focus");return Tu(e,a,o.get("blurScope"),o.get("disabled")),t.isGeo&&function(t,e,n){var i=zl(t);i.componentMainType=e.mainType,i.componentIndex=e.componentIndex,i.componentHighDownName=n}(e,r,n),a}function UA(t,e,n){var i,r=[];function o(){i=[]}function a(){i.length&&(r.push(i),i=[])}var s=e({polygonStart:o,polygonEnd:a,lineStart:o,lineEnd:a,point:function(t,e){isFinite(t)&&isFinite(e)&&i.push([t,e])},sphere:function(){}});return!n&&s.polygonStart(),z(t,(function(t){s.lineStart();for(var e=0;e-1&&(n.style.stroke=n.style.fill,n.style.fill=tf.color.neutral00,n.style.lineWidth=2),n},e.type="series.map",e.dependencies=["geo"],e.layoutMode="box",e.defaultOption={z:2,coordinateSystem:"geo",map:"",left:"center",top:"center",aspectScale:null,showLegendSymbol:!0,boundingCoords:null,center:null,zoom:1,scaleLimit:null,selectedMode:!0,label:{show:!1,color:tf.color.tertiary},itemStyle:{borderWidth:.5,borderColor:tf.color.border,areaColor:tf.color.background},emphasis:{label:{show:!0,color:tf.color.primary},itemStyle:{areaColor:tf.color.highlight}},select:{label:{show:!0,color:tf.color.primary},itemStyle:{color:tf.color.highlight}},nameProperty:"name"},e}(Wy);function ZA(t){var e={};t.eachSeriesByType("map",(function(t){var n=t.getHostGeoModel(),i=n?"o"+n.id:"i"+t.getMapType();(e[i]=e[i]||[]).push(t)})),z(e,(function(t,e){for(var n,i,r,o=(n=E(t,(function(t){return t.getData()})),i=t[0].get("mapValueCalculation"),r={},z(n,(function(t){t.each(t.mapDimension("value"),(function(e,n){var i="ec-"+t.getName(n);r[i]=r[i]||[],isNaN(e)||r[i].push(e)}))})),n[0].map(n[0].mapDimension("value"),(function(t,e){for(var o="ec-"+n[0].getName(e),a=0,s=1/0,l=-1/0,u=r[o].length,c=0;c1?(p.width=d,p.height=d/m):(p.height=d,p.width=d*m),p.y=h[1]-p.height/2,p.x=h[0]-p.width/2;else{var _=t.getBoxLayoutParams();_.aspect=m,p=Up(t,p=Hp(_,v),m)}this.setViewRect(p.x,p.y,p.width,p.height),this.setCenter(t.get("center")),this.setZoom(t.get("zoom"))}R(tk,KA);var ik=function(){function t(){this.dimensions=QA}return t.prototype.create=function(t,e){var n=[];function i(t){return{nameProperty:t.get("nameProperty"),aspectScale:t.get("aspectScale"),projection:t.get("projection")}}t.eachComponent("geo",(function(r,o){var a=r.get("map"),s=new tk(a+o,a,A({nameMap:r.get("nameMap"),api:e,ecModel:t},i(r)));s.zoomLimit=r.get("scaleLimit"),n.push(s),r.coordinateSystem=s,s.model=r,s.resize=nk,s.resize(r,e)})),t.eachSeries((function(t){Rp({targetModel:t,coordSysType:"geo",coordSysProvider:function(){var e="map"===t.subType?t.getHostGeoModel():t.getReferringComponents("geo",ha).models[0];return e&&e.coordinateSystem},allowNotFound:!0})}));var r={};return t.eachSeriesByType("map",(function(t){if(!t.getHostGeoModel()){var e=t.getMapType();r[e]=r[e]||[],r[e].push(t)}})),z(r,(function(r,o){var a=E(r,(function(t){return t.get("nameMap")})),s=new tk(o,o,A({nameMap:D(a),api:e,ecModel:t},i(r[0])));s.zoomLimit=it.apply(null,E(r,(function(t){return t.get("scaleLimit")}))),n.push(s),s.resize=nk,s.resize(r[0],e),z(r,(function(t){t.coordinateSystem=s,function(t,e){z(e.get("geoCoord"),(function(e,n){t.addGeoCoord(n,e)}))}(s,t)}))})),n},t.prototype.getFilledRegions=function(t,e,n,i){for(var r=(t||[]).slice(),o=yt(),a=0;a=0;){var o=e[n];o.hierNode.prelim+=i,o.hierNode.modifier+=i,r+=o.hierNode.change,i+=o.hierNode.shift+r}}(t);var o=(n[0].hierNode.prelim+n[n.length-1].hierNode.prelim)/2;r?(t.hierNode.prelim=r.hierNode.prelim+e(t,r),t.hierNode.modifier=t.hierNode.prelim-o):t.hierNode.prelim=o}else r&&(t.hierNode.prelim=r.hierNode.prelim+e(t,r));t.parentNode.hierNode.defaultAncestor=function(t,e,n,i){if(e){for(var r=t,o=t,a=o.parentNode.children[0],s=e,l=r.hierNode.modifier,u=o.hierNode.modifier,c=a.hierNode.modifier,h=s.hierNode.modifier;s=pk(s),o=fk(o),s&&o;){r=pk(r),a=fk(a),r.hierNode.ancestor=t;var d=s.hierNode.prelim+h-o.hierNode.prelim-u+i(s,o);d>0&&(yk(gk(s,t,n),t,d),u+=d,l+=d),h+=s.hierNode.modifier,u+=o.hierNode.modifier,l+=r.hierNode.modifier,c+=a.hierNode.modifier}s&&!pk(r)&&(r.hierNode.thread=s,r.hierNode.modifier+=h-l),o&&!fk(a)&&(a.hierNode.thread=o,a.hierNode.modifier+=u-c,n=t)}return n}(t,r,t.parentNode.hierNode.defaultAncestor||i[0],e)}function ck(t){var e=t.hierNode.prelim+t.parentNode.hierNode.modifier;t.setLayout({x:e},!0),t.hierNode.modifier+=t.parentNode.hierNode.modifier}function hk(t){return arguments.length?t:vk}function dk(t,e){return t-=Math.PI/2,{x:e*Math.cos(t),y:e*Math.sin(t)}}function pk(t){var e=t.children;return e.length&&t.isExpand?e[e.length-1]:t.hierNode.thread}function fk(t){var e=t.children;return e.length&&t.isExpand?e[0]:t.hierNode.thread}function gk(t,e,n){return t.hierNode.ancestor.parentNode===e.parentNode?t.hierNode.ancestor:n}function yk(t,e,n){var i=n/(e.hierNode.i-t.hierNode.i);e.hierNode.change-=i,e.hierNode.shift+=n,e.hierNode.modifier+=n,e.hierNode.prelim+=n,t.hierNode.change+=i}function vk(t,e){return t.parentNode===e.parentNode?1:2}var mk=function(){this.parentPoint=[],this.childPoints=[]},xk=function(t){function e(e){return t.call(this,e)||this}return n(e,t),e.prototype.getDefaultStyle=function(){return{stroke:tf.color.neutral99,fill:null}},e.prototype.getDefaultShape=function(){return new mk},e.prototype.buildPath=function(t,e){var n=e.childPoints,i=n.length,r=e.parentPoint,o=n[0],a=n[i-1];if(1===i)return t.moveTo(r[0],r[1]),void t.lineTo(o[0],o[1]);var s=e.orient,l="TB"===s||"BT"===s?0:1,u=1-l,c=yo(e.forkPosition,1),h=[];h[l]=r[l],h[u]=r[u]+(a[u]-r[u])*c,t.moveTo(r[0],r[1]),t.lineTo(h[0],h[1]),t.moveTo(o[0],o[1]),h[l]=o[l],t.lineTo(h[0],h[1]),h[l]=a[l],t.lineTo(h[0],h[1]),t.lineTo(a[0],a[1]);for(var d=1;dm.x)||(_-=Math.PI);var S=b?"left":"right",M=s.getModel("label"),I=M.get("rotate"),T=I*(Math.PI/180),C=y.getTextContent();C&&(y.setTextConfig({position:M.get("position")||S,rotation:null==I?-_:T,origin:"center"}),C.setStyle("verticalAlign","middle"))}var D=s.get(["emphasis","focus"]),A="relative"===D?vt(a.getAncestorsIndices(),a.getDescendantIndices()):"ancestor"===D?a.getAncestorsIndices():"descendant"===D?a.getDescendantIndices():null;A&&(zl(n).focus=A),function(t,e,n,i,r,o,a,s){var l=e.getModel(),u=t.get("edgeShape"),c=t.get("layout"),h=t.getOrient(),d=t.get(["lineStyle","curveness"]),p=t.get("edgeForkPosition"),f=l.getModel("lineStyle").getLineStyle(),g=i.__edge;if("curve"===u)e.parentNode&&e.parentNode!==n&&(g||(g=i.__edge=new Oc({shape:Tk(c,h,d,r,r)})),th(g,{shape:Tk(c,h,d,o,a)},t));else if("polyline"===u)if("orthogonal"===c){if(e!==n&&e.children&&0!==e.children.length&&!0===e.isExpand){for(var y=e.children,v=[],m=0;me&&(e=i.height)}this.height=e+1},t.prototype.getNodeById=function(t){if(this.getId()===t)return this;for(var e=0,n=this.children,i=n.length;e=0&&this.hostTree.data.setItemLayout(this.dataIndex,t,e)},t.prototype.getLayout=function(){return this.hostTree.data.getItemLayout(this.dataIndex)},t.prototype.getModel=function(t){if(!(this.dataIndex<0))return this.hostTree.data.getItemModel(this.dataIndex).getModel(t)},t.prototype.getLevelModel=function(){return(this.hostTree.levelModels||[])[this.depth]},t.prototype.setVisual=function(t,e){this.dataIndex>=0&&this.hostTree.data.setItemVisual(this.dataIndex,t,e)},t.prototype.getVisual=function(t){return this.hostTree.data.getItemVisual(this.dataIndex,t)},t.prototype.getRawIndex=function(){return this.hostTree.data.getRawIndex(this.dataIndex)},t.prototype.getId=function(){return this.hostTree.data.getId(this.dataIndex)},t.prototype.getChildIndex=function(){if(this.parentNode){for(var t=this.parentNode.children,e=0;e=0){var i=n.getData().tree.root,r=t.targetNode;if(X(r)&&(r=i.getNodeById(r)),r&&i.contains(r))return{node:r};var o=t.targetNodeId;if(null!=o&&(r=i.getNodeById(o)))return{node:r}}}function Vk(t){for(var e=[];t;)(t=t.parentNode)&&e.push(t);return e.reverse()}function Gk(t,e){return P(Vk(t),e)>=0}function Fk(t,e){for(var n=[];t;){var i=t.dataIndex;n.push({name:t.name,dataIndex:i,value:e.getRawValue(i)}),t=t.parentNode}return n.reverse(),n}var Wk=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.hasSymbolVisual=!0,e.ignoreStyleOnData=!0,e}return n(e,t),e.prototype.getInitialData=function(t){var e={name:t.name,children:t.data},n=t.leaves||{},i=new wd(n,this,this.ecModel),r=Ek.createTree(e,this,(function(t){t.wrapMethod("getItemModel",(function(t,e){var n=r.getNodeByDataIndex(e);return n&&n.children.length&&n.isExpand||(t.parentModel=i),t}))}));var o=0;r.eachNode("preorder",(function(t){t.depth>o&&(o=t.depth)}));var a=t.expandAndCollapse&&t.initialTreeDepth>=0?t.initialTreeDepth:o;return r.root.eachNode("preorder",(function(t){var e=t.hostTree.data.getRawDataItem(t.dataIndex);t.isExpand=e&&null!=e.collapsed?!e.collapsed:t.depth<=a})),r.data},e.prototype.getOrient=function(){var t=this.get("orient");return"horizontal"===t?t="LR":"vertical"===t&&(t="TB"),t},e.prototype.setZoom=function(t){this.option.zoom=t},e.prototype.setCenter=function(t){this.option.center=t},e.prototype.formatTooltip=function(t,e,n){for(var i=this.getData().tree,r=i.root.children[0],o=i.getNodeByDataIndex(t),a=o.getValue(),s=o.name;o&&o!==r;)s=o.parentNode.name+"."+s,o=o.parentNode;return Ty("nameValue",{name:s,value:a,noValue:isNaN(a)||null==a})},e.prototype.getDataParams=function(e){var n=t.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(e);return n.treeAncestors=Fk(i,this),n.collapsed=!i.isExpand,n},e.type="series.tree",e.layoutMode="box",e.defaultOption={z:2,coordinateSystemUsage:"box",left:"12%",top:"12%",right:"12%",bottom:"12%",layout:"orthogonal",edgeShape:"curve",edgeForkPosition:"50%",roam:!1,roamTrigger:"global",nodeScaleRatio:.4,center:null,zoom:1,orient:"LR",symbol:"emptyCircle",symbolSize:7,expandAndCollapse:!0,initialTreeDepth:2,lineStyle:{color:tf.color.borderTint,width:1.5,curveness:.5},itemStyle:{color:"lightsteelblue",borderWidth:1.5},label:{show:!0},animationEasing:"linear",animationDuration:700,animationDurationUpdate:500},e}(Wy);function Hk(t,e){for(var n,i=[t];n=i.pop();)if(e(n),n.isExpand){var r=n.children;if(r.length)for(var o=r.length-1;o>=0;o--)i.push(r[o])}}function Uk(t,e){t.eachSeriesByType("tree",(function(t){!function(t,e){var n=Xp(t,e).refContainer,i=Hp(t.getBoxLayoutParams(),n);t.layoutInfo=i;var r=t.get("layout"),o=0,a=0,s=null;"radial"===r?(o=2*Math.PI,a=Math.min(i.height,i.width)/2,s=hk((function(t,e){return(t.parentNode===e.parentNode?1:2)/t.depth}))):(o=i.width,a=i.height,s=hk());var l=t.getData().tree.root,u=l.children[0];if(u){!function(t){var e=t;e.hierNode={defaultAncestor:null,ancestor:e,prelim:0,modifier:0,change:0,shift:0,i:0,thread:null};for(var n,i,r=[e];n=r.pop();)if(i=n.children,n.isExpand&&i.length)for(var o=i.length-1;o>=0;o--){var a=i[o];a.hierNode={defaultAncestor:null,ancestor:a,prelim:0,modifier:0,change:0,shift:0,i:o,thread:null},r.push(a)}}(l),function(t,e,n){for(var i,r=[t],o=[];i=r.pop();)if(o.push(i),i.isExpand){var a=i.children;if(a.length)for(var s=0;sh.getLayout().x&&(h=t),t.depth>d.depth&&(d=t)}));var p=c===h?1:s(c,h)/2,f=p-c.getLayout().x,g=0,y=0,v=0,m=0;if("radial"===r)g=o/(h.getLayout().x+p+f),y=a/(d.depth-1||1),Hk(u,(function(t){v=(t.getLayout().x+f)*g,m=(t.depth-1)*y;var e=dk(v,m);t.setLayout({x:e.x,y:e.y,rawX:v,rawY:m},!0)}));else{var x=t.getOrient();"RL"===x||"LR"===x?(y=a/(h.getLayout().x+p+f),g=o/(d.depth-1||1),Hk(u,(function(t){m=(t.getLayout().x+f)*y,v="LR"===x?(t.depth-1)*g:o-(t.depth-1)*g,t.setLayout({x:v,y:m},!0)}))):"TB"!==x&&"BT"!==x||(g=o/(h.getLayout().x+p+f),y=a/(d.depth-1||1),Hk(u,(function(t){v=(t.getLayout().x+f)*g,m="TB"===x?(t.depth-1)*y:a-(t.depth-1)*y,t.setLayout({x:v,y:m},!0)})))}}}(t,e)}))}function Yk(t){t.eachSeriesByType("tree",(function(t){var e=t.getData();e.tree.eachNode((function(t){var n=t.getModel().getModel("itemStyle").getItemStyle();A(e.ensureUniqueItemVisual(t.dataIndex,"style"),n)}))}))}var Xk=["treemapZoomToNode","treemapRender","treemapMove"];function Zk(t){var e=t.getData().tree,n={};e.eachNode((function(e){for(var i=e;i&&i.depth>1;)i=i.parentNode;var r=Nf(t.ecModel,i.name||i.dataIndex+"",n);e.setVisual("decal",r)}))}var jk=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.preventUsingHoverLayer=!0,n}return n(e,t),e.prototype.getInitialData=function(t,e){var n={name:t.name,children:t.data};qk(n);var i=t.levels||[],r=this.designatedVisualItemStyle={},o=new wd({itemStyle:r},this,e);i=t.levels=function(t,e){var n,i,r=qo(e.get("color")),o=qo(e.get(["aria","decal","decals"]));if(!r)return;t=t||[],z(t,(function(t){var e=new wd(t),r=e.get("color"),o=e.get("decal");(e.get(["itemStyle","color"])||r&&"none"!==r)&&(n=!0),(e.get(["itemStyle","decal"])||o&&"none"!==o)&&(i=!0)}));var a=t[0]||(t[0]={});n||(a.color=r.slice());!i&&o&&(a.decal=o.slice());return t}(i,e);var a=E(i||[],(function(t){return new wd(t,o,e)}),this),s=Ek.createTree(n,this,(function(t){t.wrapMethod("getItemModel",(function(t,e){var n=s.getNodeByDataIndex(e),i=n?a[n.depth]:null;return t.parentModel=i||o,t}))}));return s.data},e.prototype.optionUpdated=function(){this.resetViewRoot()},e.prototype.formatTooltip=function(t,e,n){var i=this.getData(),r=this.getRawValue(t);return Ty("nameValue",{name:i.getName(t),value:r})},e.prototype.getDataParams=function(e){var n=t.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(e);return n.treeAncestors=Fk(i,this),n.treePathInfo=n.treeAncestors,n},e.prototype.setLayoutInfo=function(t){this.layoutInfo=this.layoutInfo||{},A(this.layoutInfo,t)},e.prototype.mapIdToIndex=function(t){var e=this._idIndexMap;e||(e=this._idIndexMap=yt(),this._idIndexMapCount=0);var n=e.get(t);return null==n&&e.set(t,n=this._idIndexMapCount++),n},e.prototype.getViewRoot=function(){return this._viewRoot},e.prototype.resetViewRoot=function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)},e.prototype.enableAriaDecal=function(){Zk(this)},e.type="series.treemap",e.layoutMode="box",e.defaultOption={progressive:0,coordinateSystemUsage:"box",left:tf.size.l,top:tf.size.xxxl,right:tf.size.l,bottom:tf.size.xxxl,sort:!0,clipWindow:"origin",squareRatio:.5*(1+Math.sqrt(5)),leafDepth:null,drillDownIcon:"▶",zoomToNodeRatio:.1024,scaleLimit:{max:5,min:.2},roam:!0,roamTrigger:"global",nodeClick:"zoomToNode",animation:!0,animationDurationUpdate:900,animationEasing:"quinticInOut",breadcrumb:{show:!0,height:22,left:"center",bottom:tf.size.m,emptyItemWidth:25,itemStyle:{color:tf.color.backgroundShade,textStyle:{color:tf.color.secondary}},emphasis:{itemStyle:{color:tf.color.background}}},label:{show:!0,distance:0,padding:5,position:"inside",color:tf.color.neutral00,overflow:"truncate"},upperLabel:{show:!1,position:[0,"50%"],height:20,overflow:"truncate",verticalAlign:"middle"},itemStyle:{color:null,colorAlpha:null,colorSaturation:null,borderWidth:0,gapWidth:0,borderColor:tf.color.neutral00,borderColorSaturation:null},emphasis:{upperLabel:{show:!0,position:[0,"50%"],overflow:"truncate",verticalAlign:"middle"}},visualDimension:0,visualMin:null,visualMax:null,color:[],colorAlpha:null,colorSaturation:null,colorMappingBy:"index",visibleMin:10,childrenVisibleMin:null,levels:[]},e}(Wy);function qk(t){var e=0;z(t.children,(function(t){qk(t);var n=t.value;U(n)&&(n=n[0]),e+=n}));var n=t.value;U(n)&&(n=n[0]),(null==n||isNaN(n))&&(n=e),n<0&&(n=0),U(t.value)?t.value[0]=n:t.value=n}var Kk=function(){function t(t){this.group=new to,t.add(this.group)}return t.prototype.render=function(t,e,n,i){var r=t.getModel("breadcrumb"),o=this.group;if(o.removeAll(),r.get("show")&&n){var a=r.getModel("itemStyle"),s=r.getModel("emphasis"),l=a.getModel("textStyle"),u=s.getModel(["itemStyle","textStyle"]),c=Xp(t,e).refContainer,h={left:r.get("left"),right:r.get("right"),top:r.get("top"),bottom:r.get("bottom")},d={emptyItemWidth:r.get("emptyItemWidth"),totalWidth:0,renderList:[]},p=Hp(h,c);this._prepare(n,d,l),this._renderContent(t,d,p,a,s,l,u,i),Zp(o,h,c)}},t.prototype._prepare=function(t,e,n){for(var i=t;i;i=i.parentNode){var r=ia(i.getModel().get("name"),""),o=n.getTextRect(r),a=Math.max(o.width+16,e.emptyItemWidth);e.totalWidth+=a+8,e.renderList.push({node:i,text:r,width:a})}},t.prototype._renderContent=function(t,e,n,i,r,o,a,s){for(var l=0,u=e.emptyItemWidth,c=t.get(["breadcrumb","height"]),h=e.totalWidth,d=e.renderList,p=r.getModel("itemStyle").getItemStyle(),f=d.length-1;f>=0;f--){var g=d[f],y=g.node,v=g.width,m=g.text;h>n.width&&(h-=v-u,v=u,m=null);var x=new Mc({shape:{points:$k(l,0,v,c,f===d.length-1,0===f)},style:k(i.getItemStyle(),{lineJoin:"bevel"}),textContent:new Sl({style:Qh(o,{text:m})}),textConfig:{position:"inside"},z2:1e5,onclick:H(s,y)});x.disableLabelAnimation=!0,x.getTextContent().ensureState("emphasis").style=Qh(a,{text:m}),x.ensureState("emphasis").style=p,Tu(x,r.get("focus"),r.get("blurScope"),r.get("disabled")),this.group.add(x),Jk(x,t,y),l+=v+8}},t.prototype.remove=function(){this.group.removeAll()},t}();function $k(t,e,n,i,r,o){var a=[[r?t:t-5,e],[t+n,e],[t+n,e+i],[r?t:t-5,e+i]];return!o&&a.splice(2,0,[t+n+5,e+i/2]),!r&&a.push([t,e+i/2]),a}function Jk(t,e,n){zl(t).eventData={componentType:"series",componentSubType:"treemap",componentIndex:e.componentIndex,seriesIndex:e.seriesIndex,seriesName:e.name,seriesType:"treemap",selfType:"breadcrumb",nodeData:{dataIndex:n&&n.dataIndex,name:n&&n.name},treePathInfo:n&&Fk(n,e)}}var Qk=function(){function t(){this._storage=[],this._elExistsMap={}}return t.prototype.add=function(t,e,n,i,r){return!this._elExistsMap[t.id]&&(this._elExistsMap[t.id]=!0,this._storage.push({el:t,target:e,duration:n,delay:i,easing:r}),!0)},t.prototype.finished=function(t){return this._finishedCallback=t,this},t.prototype.start=function(){for(var t=this,e=this._storage.length,n=function(){--e<=0&&(t._storage.length=0,t._elExistsMap={},t._finishedCallback&&t._finishedCallback())},i=0,r=this._storage.length;i3||Math.abs(t.dy)>3)){var e=this.seriesModel.getData().tree.root;if(!e)return;var n=e.getLayout();if(!n)return;this.api.dispatchAction({type:"treemapMove",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:n.x+t.dx,y:n.y+t.dy,width:n.width,height:n.height}})}},e.prototype._onZoom=function(t){var e=t.originX,n=t.originY,i=t.scale;if("animating"!==this._state){var r=this.seriesModel.getData().tree.root;if(!r)return;var o=r.getLayout();if(!o)return;var a,s=new He(o.x,o.y,o.width,o.height),l=this._controllerHost;a=l.zoomLimit;var u=l.zoom=l.zoom||1;if(u*=i,a){var c=a.min||0,h=a.max||1/0;u=Math.max(Math.min(h,u),c)}var d=u/l.zoom;l.zoom=u;var p=this.seriesModel.layoutInfo,f=[1,0,0,1,0,0];Se(f,f,[-(e-=p.x),-(n-=p.y)]),Ie(f,f,[d,d]),Se(f,f,[e,n]),s.applyTransform(f),this.api.dispatchAction({type:"treemapRender",from:this.uid,seriesId:this.seriesModel.id,rootRect:{x:s.x,y:s.y,width:s.width,height:s.height}})}},e.prototype._initEvents=function(t){var e=this;t.on("click",(function(t){if("ready"===e._state){var n=e.seriesModel.get("nodeClick",!0);if(n){var i=e.findTarget(t.offsetX,t.offsetY);if(i){var r=i.node;if(r.getLayout().isLeafRoot)e._rootToNode(i);else if("zoomToNode"===n)e._zoomToNode(i);else if("link"===n){var o=r.hostTree.data.getItemModel(r.dataIndex),a=o.get("link",!0),s=o.get("target",!0)||"blank";a&&Sp(a,s)}}}}}),this)},e.prototype._renderBreadcrumb=function(t,e,n){var i=this;n||(n=null!=t.get("leafDepth",!0)?{node:t.getViewRoot()}:this.findTarget(e.getWidth()/2,e.getHeight()/2))||(n={node:t.getData().tree.root}),(this._breadcrumb||(this._breadcrumb=new Kk(this.group))).render(t,e,n.node,(function(e){"animating"!==i._state&&(Gk(t.getViewRoot(),e)?i._rootToNode({node:e}):i._zoomToNode({node:e}))}))},e.prototype.remove=function(){this._clearController(),this._containerGroup&&this._containerGroup.removeAll(),this._storage={nodeGroup:[],background:[],content:[]},this._state="ready",this._breadcrumb&&this._breadcrumb.remove()},e.prototype.dispose=function(){this._clearController()},e.prototype._zoomToNode=function(t){this.api.dispatchAction({type:"treemapZoomToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},e.prototype._rootToNode=function(t){this.api.dispatchAction({type:"treemapRootToNode",from:this.uid,seriesId:this.seriesModel.id,targetNode:t.node})},e.prototype.findTarget=function(t,e){var n;return this.seriesModel.getViewRoot().eachNode({attr:"viewChildren",order:"preorder"},(function(i){var r=this._storage.background[i.getRawIndex()];if(r){var o=r.transformCoordToLocal(t,e),a=r.shape;if(!(a.x<=o[0]&&o[0]<=a.x+a.width&&a.y<=o[1]&&o[1]<=a.y+a.height))return!1;n={node:i,offsetX:o[0],offsetY:o[1]}}}),this),n},e.type="treemap",e}(tv);var lL=z,uL=q,cL=-1,hL=function(){function t(e){var n=e.mappingMethod,i=e.type,r=this.option=T(e);this.type=i,this.mappingMethod=n,this._normalizeData=bL[n];var o=t.visualHandlers[i];this.applyVisual=o.applyVisual,this.getColorMapper=o.getColorMapper,this._normalizedToVisual=o._normalizedToVisual[n],"piecewise"===n?(dL(r),function(t){var e=t.pieceList;t.hasSpecialVisual=!1,z(e,(function(e,n){e.originIndex=n,null!=e.visual&&(t.hasSpecialVisual=!0)}))}(r)):"category"===n?r.categories?function(t){var e=t.categories,n=t.categoryMap={},i=t.visual;if(lL(e,(function(t,e){n[t]=e})),!U(i)){var r=[];q(i)?lL(i,(function(t,e){var i=n[e];r[null!=i?i:cL]=t})):r[-1]=i,i=_L(t,r)}for(var o=e.length-1;o>=0;o--)null==i[o]&&(delete n[e[o]],e.pop())}(r):dL(r,!0):(lt("linear"!==n||r.dataExtent),dL(r))}return t.prototype.mapValueToVisual=function(t){var e=this._normalizeData(t);return this._normalizedToVisual(e,t)},t.prototype.getNormalizer=function(){return W(this._normalizeData,this)},t.listVisualTypes=function(){return F(t.visualHandlers)},t.isValidType=function(e){return t.visualHandlers.hasOwnProperty(e)},t.eachVisual=function(t,e,n){q(t)?z(t,e,n):e.call(n,t)},t.mapVisual=function(e,n,i){var r,o=U(e)?[]:q(e)?{}:(r=!0,null);return t.eachVisual(e,(function(t,e){var a=n.call(i,t,e);r?o=a:o[e]=a})),o},t.retrieveVisuals=function(e){var n,i={};return e&&lL(t.visualHandlers,(function(t,r){e.hasOwnProperty(r)&&(i[r]=e[r],n=!0)})),n?i:null},t.prepareVisualTypes=function(t){if(U(t))t=t.slice();else{if(!uL(t))return[];var e=[];lL(t,(function(t,n){e.push(n)})),t=e}return t.sort((function(t,e){return"color"===e&&"color"!==t&&0===t.indexOf("color")?1:-1})),t},t.dependsOn=function(t,e){return"color"===e?!(!t||0!==t.indexOf(e)):t===e},t.findPieceIndex=function(t,e,n){for(var i,r=1/0,o=0,a=e.length;ou[1]&&(u[1]=l);var c=e.get("colorMappingBy"),h={type:a.name,dataExtent:u,visual:a.range};"color"!==h.type||"index"!==c&&"id"!==c?h.mappingMethod="linear":(h.mappingMethod="category",h.loop=!0);var d=new hL(h);return SL(d).drColorMappingBy=c,d}(0,r,o,0,u,p);z(p,(function(t,e){if(t.depth>=n.length||t===n[t.depth]){var o=function(t,e,n,i,r,o){var a=A({},e);if(r){var s=r.type,l="color"===s&&SL(r).drColorMappingBy,u="index"===l?i:"id"===l?o.mapIdToIndex(n.getId()):n.getValue(t.get("visualDimension"));a[s]=r.mapValueToVisual(u)}return a}(r,u,t,e,f,i);IL(t,o,n,i)}}))}else s=TL(u),c.fill=s}}function TL(t){var e=CL(t,"color");if(e){var n=CL(t,"colorAlpha"),i=CL(t,"colorSaturation");return i&&(e=di(e,null,null,i)),n&&(e=pi(e,n)),e}}function CL(t,e){var n=t[e];if(null!=n&&"none"!==n)return n}function DL(t,e){var n=t.get(e);return U(n)&&n.length?{name:e,range:n}:null}var AL=Math.max,kL=Math.min,LL=it,PL=z,OL=["itemStyle","borderWidth"],RL=["itemStyle","gapWidth"],NL=["upperLabel","show"],zL=["upperLabel","height"],EL={seriesType:"treemap",reset:function(t,e,n,i){var r=t.option,o=Xp(t,n).refContainer,a=Hp(t.getBoxLayoutParams(),o),s=r.size||[],l=yo(LL(a.width,s[0]),o.width),u=yo(LL(a.height,s[1]),o.height),c=i&&i.type,h=Bk(i,["treemapZoomToNode","treemapRootToNode"],t),d="treemapRender"===c||"treemapMove"===c?i.rootRect:null,p=t.getViewRoot(),f=Vk(p);if("treemapMove"!==c){var g="treemapZoomToNode"===c?function(t,e,n,i,r){var o,a=(e||{}).node,s=[i,r];if(!a||a===n)return s;var l=i*r,u=l*t.option.zoomToNodeRatio;for(;o=a.parentNode;){for(var c=0,h=o.children,d=0,p=h.length;dIo&&(u=Io),a=o}ua[1]&&(a[1]=e)}))):a=[NaN,NaN];return{sum:i,dataExtent:a}}(e,a,s);if(0===u.sum)return t.viewChildren=[];if(u.sum=function(t,e,n,i,r){if(!i)return n;for(var o=t.get("visibleMin"),a=r.length,s=a,l=a-1;l>=0;l--){var u=r["asc"===i?a-l-1:l].getValue();u/n*ei&&(i=a));var l=t.area*t.area,u=e*e*n;return l?AL(u*i/l,l/(u*r)):1/0}function GL(t,e,n,i,r){var o=e===n.width?0:1,a=1-o,s=["x","y"],l=["width","height"],u=n[s[o]],c=e?t.area/e:0;(r||c>n[l[a]])&&(c=n[l[a]]);for(var h=0,d=t.length;hi&&(i=e);var o=i%2?i+2:i+3;r=[];for(var a=0;a0&&(m[0]=-m[0],m[1]=-m[1]);var _=v[0]<0?-1:1;if("start"!==i.__position&&"end"!==i.__position){var b=-Math.atan2(v[1],v[0]);u[0].8?"left":c[0]<-.8?"right":"center",d=c[1]>.8?"top":c[1]<-.8?"bottom":"middle";break;case"start":i.x=-c[0]*f+l[0],i.y=-c[1]*g+l[1],h=c[0]>.8?"right":c[0]<-.8?"left":"center",d=c[1]>.8?"bottom":c[1]<-.8?"top":"middle";break;case"insideStartTop":case"insideStart":case"insideStartBottom":i.x=f*_+l[0],i.y=l[1]+w,h=v[0]<0?"right":"left",i.originX=-f*_,i.originY=-w;break;case"insideMiddleTop":case"insideMiddle":case"insideMiddleBottom":case"middle":i.x=x[0],i.y=x[1]+w,h="center",i.originY=-w;break;case"insideEndTop":case"insideEnd":case"insideEndBottom":i.x=-f*_+u[0],i.y=u[1]+w,h=v[0]>=0?"right":"left",i.originX=f*_,i.originY=-w}i.scaleX=i.scaleY=r,i.setStyle({verticalAlign:i.__verticalAlign||d,align:i.__align||h})}}}function S(t,e){var n=t.__specifiedRotation;if(null==n){var i=a.tangentAt(e);t.attr("rotation",(1===e?-1:1)*Math.PI/2-Math.atan2(i[1],i[0]))}else t.attr("rotation",n)}},e}(to),IP=function(){function t(t){this.group=new to,this._LineCtor=t||MP}return t.prototype.updateData=function(t){var e=this;this._progressiveEls=null;var n=this,i=n.group,r=n._lineData;n._lineData=t,r||i.removeAll();var o=TP(t);t.diff(r).add((function(n){e._doAdd(t,n,o)})).update((function(n,i){e._doUpdate(r,t,i,n,o)})).remove((function(t){i.remove(r.getItemGraphicEl(t))})).execute()},t.prototype.updateLayout=function(){var t=this._lineData;t&&t.eachItemGraphicEl((function(e,n){e.updateLayout(t,n)}),this)},t.prototype.incrementalPrepareUpdate=function(t){this._seriesScope=TP(t),this._lineData=null,this.group.removeAll()},t.prototype.incrementalUpdate=function(t,e){function n(t){t.isGroup||function(t){return t.animators&&t.animators.length>0}(t)||(t.incremental=!0,t.ensureState("emphasis").hoverLayer=!0)}this._progressiveEls=[];for(var i=t.start;i=0?i+=u:i-=u:f>=0?i-=u:i+=u}return i}function zP(t,e){var n=[],i=Bn,r=[[],[],[]],o=[[],[]],a=[];e/=2,t.eachEdge((function(t,s){var l=t.getLayout(),u=t.getVisual("fromSymbol"),c=t.getVisual("toSymbol");l.__original||(l.__original=[Ct(l[0]),Ct(l[1])],l[2]&&l.__original.push(Ct(l[2])));var h=l.__original;if(null!=l[2]){if(Tt(r[0],h[0]),Tt(r[1],h[2]),Tt(r[2],h[1]),u&&"none"!==u){var d=rP(t.node1),p=NP(r,h[0],d*e);i(r[0][0],r[1][0],r[2][0],p,n),r[0][0]=n[3],r[1][0]=n[4],i(r[0][1],r[1][1],r[2][1],p,n),r[0][1]=n[3],r[1][1]=n[4]}if(c&&"none"!==c){d=rP(t.node2),p=NP(r,h[1],d*e);i(r[0][0],r[1][0],r[2][0],p,n),r[1][0]=n[1],r[2][0]=n[2],i(r[0][1],r[1][1],r[2][1],p,n),r[1][1]=n[1],r[2][1]=n[2]}Tt(l[0],r[0]),Tt(l[1],r[2]),Tt(l[2],r[1])}else{if(Tt(o[0],h[0]),Tt(o[1],h[1]),Lt(a,o[1],o[0]),Et(a,a),u&&"none"!==u){d=rP(t.node1);kt(o[0],o[0],a,d*e)}if(c&&"none"!==c){d=rP(t.node2);kt(o[1],o[1],a,-d*e)}Tt(l[0],o[0]),Tt(l[1],o[1])}}))}var EP=sa();function BP(t,e){t&&(EP(t).bridge=e)}function VP(t){return"view"===t.type}var GP=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(t,e){var n=new uI,i=new IP,r=this.group,o=new to;this._controller=new LD(e.getZr()),this._controllerHost={target:o},o.add(n.group),o.add(i.group),r.add(o),this._symbolDraw=n,this._lineDraw=i,this._mainGroup=o,this._firstRender=!0},e.prototype.render=function(t,e,n){var i=this,r=t.coordinateSystem,o=!1;this._model=t,this._api=n,this._active=!0;var a=this._getThumbnailInfo();a&&a.bridge.reset(n);var s=this._symbolDraw,l=this._lineDraw;if(VP(r)){var u={x:r.x,y:r.y,scaleX:r.scaleX,scaleY:r.scaleY};this._firstRender?this._mainGroup.attr(u):th(this._mainGroup,u,t)}zP(t.getGraph(),iP(t));var c=t.getData();s.updateData(c);var h=t.getEdgeData();l.updateData(h),this._updateNodeAndLinkScale(),this._updateController(null,t,n),clearTimeout(this._layoutTimeout);var d=t.forceLayout,p=t.get(["force","layoutAnimation"]);d&&(o=!0,this._startForceLayoutIteration(d,n,p));var f=t.get("layout");c.graph.eachNode((function(e){var r=e.dataIndex,o=e.getGraphicEl(),a=e.getModel();if(o){o.off("drag").off("dragend");var s=a.get("draggable");s&&o.on("drag",(function(a){switch(f){case"force":d.warmUp(),!i._layouting&&i._startForceLayoutIteration(d,n,p),d.setFixed(r),c.setItemLayout(r,[o.x,o.y]);break;case"circular":c.setItemLayout(r,[o.x,o.y]),e.setLayout({fixed:!0},!0),sP(t,"symbolSize",e,[a.offsetX,a.offsetY]),i.updateLayout(t);break;default:c.setItemLayout(r,[o.x,o.y]),eP(t.getGraph(),t),i.updateLayout(t)}})).on("dragend",(function(){d&&d.setUnfixed(r)})),o.setDraggable(s,!!a.get("cursor")),"adjacency"===a.get(["emphasis","focus"])&&(zl(o).focus=e.getAdjacentDataIndices())}})),c.graph.eachEdge((function(t){var e=t.getGraphicEl(),n=t.getModel().get(["emphasis","focus"]);e&&"adjacency"===n&&(zl(e).focus={edge:[t.dataIndex],node:[t.node1.dataIndex,t.node2.dataIndex]})}));var g="circular"===t.get("layout")&&t.get(["circular","rotateLabel"]),y=c.getLayout("cx"),v=c.getLayout("cy");c.graph.eachNode((function(t){uP(t,g,y,v)})),this._firstRender=!1,o||this._renderThumbnail(t,n,this._symbolDraw,this._lineDraw)},e.prototype.dispose=function(){this.remove(),this._controller&&this._controller.dispose(),this._controllerHost=null},e.prototype._startForceLayoutIteration=function(t,e,n){var i=this,r=!1;!function o(){t.step((function(t){i.updateLayout(i._model),!t&&r||(r=!0,i._renderThumbnail(i._model,e,i._symbolDraw,i._lineDraw)),(i._layouting=!t)&&(n?i._layoutTimeout=setTimeout(o,16):o())}))}()},e.prototype._updateController=function(t,e,n){var i=this._controller,r=this._controllerHost,o=e.coordinateSystem;VP(o)?(i.enable(e.get("roam"),{api:n,zInfo:{component:e},triggerInfo:{roamTrigger:e.get("roamTrigger"),isInSelf:function(t,e,n){return o.containPoint([e,n])},isInClip:function(e,n,i){return!t||t.contain(n,i)}}}),r.zoomLimit=e.get("scaleLimit"),r.zoom=o.getZoom(),i.off("pan").off("zoom").on("pan",(function(t){n.dispatchAction({seriesId:e.id,type:"graphRoam",dx:t.dx,dy:t.dy})})).on("zoom",(function(t){n.dispatchAction({seriesId:e.id,type:"graphRoam",zoom:t.scale,originX:t.originX,originY:t.originY})}))):i.disable()},e.prototype.updateViewOnPan=function(t,e,n){this._active&&(FD(this._controllerHost,n.dx,n.dy),this._updateThumbnailWindow())},e.prototype.updateViewOnZoom=function(t,e,n){this._active&&(WD(this._controllerHost,n.zoom,n.originX,n.originY),this._updateNodeAndLinkScale(),zP(t.getGraph(),iP(t)),this._lineDraw.updateLayout(),e.updateLabelLayout(),this._updateThumbnailWindow())},e.prototype._updateNodeAndLinkScale=function(){var t=this._model,e=t.getData(),n=iP(t);e.eachItemGraphicEl((function(t,e){t&&t.setSymbolScale(n)}))},e.prototype.updateLayout=function(t){this._active&&(zP(t.getGraph(),iP(t)),this._symbolDraw.updateLayout(),this._lineDraw.updateLayout())},e.prototype.remove=function(){this._active=!1,clearTimeout(this._layoutTimeout),this._layouting=!1,this._layoutTimeout=null,this._symbolDraw&&this._symbolDraw.remove(),this._lineDraw&&this._lineDraw.remove(),this._controller&&this._controller.disable()},e.prototype._getThumbnailInfo=function(){var t=this._model,e=t.coordinateSystem;if("view"===e.type){var n=function(t){if(t)return EP(t).bridge}(t);if(n)return{bridge:n,coordSys:e}}},e.prototype._updateThumbnailWindow=function(){var t=this._getThumbnailInfo();t&&t.bridge.updateWindow(t.coordSys.transform,this._api)},e.prototype._renderThumbnail=function(t,e,n,i){var r=this._getThumbnailInfo();if(r){var o=new to,a=n.group.children(),s=i.group.children(),l=new to,u=new to;o.add(u),o.add(l);for(var c=0;c=0&&t.call(e,n[r],r)},t.prototype.eachEdge=function(t,e){for(var n=this.edges,i=n.length,r=0;r=0&&n[r].node1.dataIndex>=0&&n[r].node2.dataIndex>=0&&t.call(e,n[r],r)},t.prototype.breadthFirstTraverse=function(t,e,n,i){if(e instanceof HP||(e=this._nodesMap[FP(e)]),e){for(var r="out"===n?"outEdges":"in"===n?"inEdges":"edges",o=0;o=0&&n.node2.dataIndex>=0}));for(r=0,o=i.length;r=0&&!t.hasKey(p)&&(t.set(p,!0),o.push(d.node1))}for(s=0;s=0&&!t.hasKey(m)&&(t.set(m,!0),a.push(v.node2))}}}return{edge:t.keys(),node:e.keys()}},t}(),UP=function(){function t(t,e,n){this.dataIndex=-1,this.node1=t,this.node2=e,this.dataIndex=null==n?-1:n}return t.prototype.getModel=function(t){if(!(this.dataIndex<0))return this.hostGraph.edgeData.getItemModel(this.dataIndex).getModel(t)},t.prototype.getAdjacentDataIndices=function(){return{edge:[this.dataIndex],node:[this.node1.dataIndex,this.node2.dataIndex]}},t.prototype.getTrajectoryDataIndices=function(){var t=yt(),e=yt();t.set(this.dataIndex,!0);for(var n=[this.node1],i=[this.node2],r=0;r=0&&!t.hasKey(u)&&(t.set(u,!0),n.push(l.node1))}for(r=0;r=0&&!t.hasKey(d)&&(t.set(d,!0),i.push(h.node2))}return{edge:t.keys(),node:e.keys()}},t}();function YP(t,e){return{getValue:function(n){var i=this[t][e];return i.getStore().get(i.getDimensionIndex(n||"value"),this.dataIndex)},setVisual:function(n,i){this.dataIndex>=0&&this[t][e].setItemVisual(this.dataIndex,n,i)},getVisual:function(n){return this[t][e].getItemVisual(this.dataIndex,n)},setLayout:function(n,i){this.dataIndex>=0&&this[t][e].setItemLayout(this.dataIndex,n,i)},getLayout:function(){return this[t][e].getItemLayout(this.dataIndex)},getGraphicEl:function(){return this[t][e].getItemGraphicEl(this.dataIndex)},getRawIndex:function(){return this[t][e].getRawIndex(this.dataIndex)}}}function XP(t,e,n,i,r){for(var o=new WP(i),a=0;a "+d)),u++)}var p,f=n.get("coordinateSystem");if("cartesian2d"===f||"polar"===f||"matrix"===f)p=Z_(t,n);else{var g=Tp.get(f),y=g&&g.dimensions||[];P(y,"value")<0&&y.concat(["value"]);var v=V_(t,{coordDimensions:y,encodeDefine:n.getEncode()}).dimensions;(p=new B_(v,n)).initData(t)}var m=new B_(["value"],n);return m.initData(l,s),r&&r(p,m),Dk({mainData:p,struct:o,structAttr:"graph",datas:{node:p,edge:m},datasAttr:{node:"data",edge:"edgeData"}}),o.update(),o}R(HP,YP("hostGraph","data")),R(UP,YP("hostGraph","edgeData"));var ZP=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.hasSymbolVisual=!0,n}return n(e,t),e.prototype.init=function(e){t.prototype.init.apply(this,arguments);var n=this;function i(){return n._categoriesData}this.legendVisualProvider=new CT(i,i),this.fillDataTextStyle(e.edges||e.links),this._updateCategoriesData()},e.prototype.mergeOption=function(e){t.prototype.mergeOption.apply(this,arguments),this.fillDataTextStyle(e.edges||e.links),this._updateCategoriesData()},e.prototype.mergeDefaultAndTheme=function(e){t.prototype.mergeDefaultAndTheme.apply(this,arguments),Ko(e,"edgeLabel",["show"])},e.prototype.getInitialData=function(t,e){var n,i=t.edges||t.links||[],r=t.data||t.nodes||[],o=this;if(r&&i){jL(n=this)&&(n.__curvenessList=[],n.__edgeMap={},qL(n));var a=XP(r,i,this,!0,(function(t,e){t.wrapMethod("getItemModel",(function(t){var e=o._categoriesModels[t.getShallow("category")];return e&&(e.parentModel=t.parentModel,t.parentModel=e),t}));var n=wd.prototype.getModel;function i(t,e){var i=n.call(this,t,e);return i.resolveParentPath=r,i}function r(t){if(t&&("label"===t[0]||"label"===t[1])){var e=t.slice();return"label"===t[0]?e[0]="edgeLabel":"label"===t[1]&&(e[1]="edgeLabel"),e}return t}e.wrapMethod("getItemModel",(function(t){return t.resolveParentPath=r,t.getModel=i,t}))}));return z(a.edges,(function(t){!function(t,e,n,i){if(jL(n)){var r=KL(t,e,n),o=n.__edgeMap,a=o[$L(r)];o[r]&&!a?o[r].isForward=!0:a&&o[r]&&(a.isForward=!0,o[r].isForward=!1),o[r]=o[r]||[],o[r].push(i)}}(t.node1,t.node2,this,t.dataIndex)}),this),a.data}},e.prototype.getGraph=function(){return this.getData().graph},e.prototype.getEdgeData=function(){return this.getGraph().edgeData},e.prototype.getCategoriesData=function(){return this._categoriesData},e.prototype.formatTooltip=function(t,e,n){if("edge"===n){var i=this.getData(),r=this.getDataParams(t,n),o=i.graph.getEdgeByIndex(t),a=i.getName(o.node1.dataIndex),s=i.getName(o.node2.dataIndex),l=[];return null!=a&&l.push(a),null!=s&&l.push(s),Ty("nameValue",{name:l.join(" > "),value:r.value,noValue:null==r.value})}return By({series:this,dataIndex:t,multipleSeries:e})},e.prototype._updateCategoriesData=function(){var t=E(this.option.categories||[],(function(t){return null!=t.value?t:A({value:0},t)})),e=new B_(["value"],this);e.initData(t),this._categoriesData=e,this._categoriesModels=e.mapArray((function(t){return e.getItemModel(t)}))},e.prototype.setZoom=function(t){this.option.zoom=t},e.prototype.setCenter=function(t){this.option.center=t},e.prototype.isAnimationEnabled=function(){return t.prototype.isAnimationEnabled.call(this)&&!("force"===this.get("layout")&&this.get(["force","layoutAnimation"]))},e.type="series.graph",e.dependencies=["grid","polar","geo","singleAxis","calendar"],e.defaultOption={z:2,coordinateSystem:"view",legendHoverLink:!0,layout:null,circular:{rotateLabel:!1},force:{initLayout:null,repulsion:[0,50],gravity:.1,friction:.6,edgeLength:30,layoutAnimation:!0},left:"center",top:"center",symbol:"circle",symbolSize:10,edgeSymbol:["none","none"],edgeSymbolSize:10,edgeLabel:{position:"middle",distance:5},draggable:!1,roam:!1,center:null,zoom:1,nodeScaleRatio:.6,label:{show:!1,formatter:"{b}"},itemStyle:{},lineStyle:{color:tf.color.neutral50,width:1,opacity:.5},emphasis:{scale:!0,label:{show:!0}},select:{itemStyle:{borderColor:tf.color.primary}}},e}(Wy);var jP=function(t){function e(e,n,i){var r=t.call(this)||this;zl(r).dataType="node",r.z2=2;var o=new Sl;return r.setTextContent(o),r.updateData(e,n,i,!0),r}return n(e,t),e.prototype.updateData=function(t,e,n,i){var r=this,o=t.graph.getNodeByIndex(e),a=t.hostModel,s=o.getModel(),l=s.getModel("emphasis"),u=t.getItemLayout(e),c=A(YI(s.getModel("itemStyle"),u,!0),u),h=this;if(isNaN(c.startAngle))h.setShape(c);else{i?h.setShape(c):th(h,{shape:c},a,e);var d=A(YI(s.getModel("itemStyle"),u,!0),u);r.setShape(d),r.useStyle(t.getItemVisual(e,"style")),ku(r,s),this._updateLabel(a,s,o),t.setItemGraphicEl(e,h),ku(h,s,"itemStyle");var p=l.get("focus");Tu(this,"adjacency"===p?o.getAdjacentDataIndices():p,l.get("blurScope"),l.get("disabled"))}},e.prototype._updateLabel=function(t,e,n){var i=this.getTextContent(),r=n.getLayout(),o=(r.startAngle+r.endAngle)/2,a=Math.cos(o),s=Math.sin(o),l=e.getModel("label");i.ignore=!l.get("show");var u=Jh(e),c=n.getVisual("style");$h(i,u,{labelFetcher:{getFormattedLabel:function(n,i,r,o,a,s){return t.getFormattedLabel(n,i,"node",o,ot(a,u.normal&&u.normal.get("formatter"),e.get("name")),s)}},labelDataIndex:n.dataIndex,defaultText:n.dataIndex+"",inheritColor:c.fill,defaultOpacity:c.opacity,defaultOutsidePosition:"startArc"});var h,d=l.get("position")||"outside",p=l.get("distance")||0;h="outside"===d?r.r+p:(r.r+r.r0)/2,this.textConfig={inside:"outside"!==d};var f="outside"!==d?l.get("align")||"center":a>0?"left":"right",g="outside"!==d?l.get("verticalAlign")||"middle":s>0?"top":"bottom";i.attr({x:a*h+r.cx,y:s*h+r.cy,rotation:0,style:{align:f,verticalAlign:g}})},e}(xc),qP=function(t){function e(e,n,i,r){var o=t.call(this)||this;return zl(o).dataType="edge",o.updateData(e,n,i,r,!0),o}return n(e,t),e.prototype.buildPath=function(t,e){t.moveTo(e.s1[0],e.s1[1]);var n=.7,i=e.clockwise;t.arc(e.cx,e.cy,e.r,e.sStartAngle,e.sEndAngle,!i),t.bezierCurveTo((e.cx-e.s2[0])*n+e.s2[0],(e.cy-e.s2[1])*n+e.s2[1],(e.cx-e.t1[0])*n+e.t1[0],(e.cy-e.t1[1])*n+e.t1[1],e.t1[0],e.t1[1]),t.arc(e.cx,e.cy,e.r,e.tStartAngle,e.tEndAngle,!i),t.bezierCurveTo((e.cx-e.t2[0])*n+e.t2[0],(e.cy-e.t2[1])*n+e.t2[1],(e.cx-e.s1[0])*n+e.s1[0],(e.cy-e.s1[1])*n+e.s1[1],e.s1[0],e.s1[1]),t.closePath()},e.prototype.updateData=function(t,e,n,i,r){var o=t.hostModel,a=e.graph.getEdgeByIndex(n),s=a.getLayout(),l=a.node1.getModel(),u=e.getItemModel(a.dataIndex),c=u.getModel("lineStyle"),h=u.getModel("emphasis"),d=h.get("focus"),p=A(YI(l.getModel("itemStyle"),s,!0),s),f=this;isNaN(p.sStartAngle)||isNaN(p.tStartAngle)?f.setShape(p):(r?(f.setShape(p),KP(f,a,t,c)):(ah(f),KP(f,a,t,c),th(f,{shape:p},o,n)),Tu(this,"adjacency"===d?a.getAdjacentDataIndices():d,h.get("blurScope"),h.get("disabled")),ku(f,u,"lineStyle"),e.setItemGraphicEl(a.dataIndex,f))},e}(sl);function KP(t,e,n,i){var r=e.node1,o=e.node2,a=t.style;switch(t.setStyle(i.getLineStyle()),i.get("color")){case"source":a.fill=n.getItemVisual(r.dataIndex,"style").fill,a.decal=r.getVisual("style").decal;break;case"target":a.fill=n.getItemVisual(o.dataIndex,"style").fill,a.decal=o.getVisual("style").decal;break;case"gradient":var s=n.getItemVisual(r.dataIndex,"style").fill,l=n.getItemVisual(o.dataIndex,"style").fill;if(X(s)&&X(l)){var u=t.shape,c=(u.s1[0]+u.s2[0])/2,h=(u.s1[1]+u.s2[1])/2,d=(u.t1[0]+u.t2[0])/2,p=(u.t1[1]+u.t2[1])/2;a.fill=new Bc(c,h,d,p,[{offset:0,color:s},{offset:1,color:l}],!0)}}}var $P=Math.PI/180,JP=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(t,e){},e.prototype.render=function(t,e,n){var i=t.getData(),r=this._data,o=this.group,a=-t.get("startAngle")*$P;if(i.diff(r).add((function(t){if(i.getItemLayout(t)){var e=new jP(i,t,a);zl(e).dataIndex=t,o.add(e)}})).update((function(e,n){var s=r.getItemGraphicEl(n);i.getItemLayout(e)?(s?s.updateData(i,e,a):s=new jP(i,e,a),o.add(s)):s&&oh(s,t,n)})).remove((function(e){var n=r.getItemGraphicEl(e);n&&oh(n,t,e)})).execute(),!r){var s=t.get("center");this.group.scaleX=.01,this.group.scaleY=.01,this.group.originX=yo(s[0],n.getWidth()),this.group.originY=yo(s[1],n.getHeight()),eh(this.group,{scaleX:1,scaleY:1},t)}this._data=i,this.renderEdges(t,a)},e.prototype.renderEdges=function(t,e){var n=t.getData(),i=t.getEdgeData(),r=this._edgeData,o=this.group;i.diff(r).add((function(t){var r=new qP(n,i,t,e);zl(r).dataIndex=t,o.add(r)})).update((function(t,a){var s=r.getItemGraphicEl(a);s.updateData(n,i,t,e),o.add(s)})).remove((function(e){var n=r.getItemGraphicEl(e);n&&oh(n,t,e)})).execute(),this._edgeData=i},e.prototype.dispose=function(){},e.type="chord",e}(tv),QP=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(e){t.prototype.init.apply(this,arguments),this.fillDataTextStyle(e.edges||e.links),this.legendVisualProvider=new CT(W(this.getData,this),W(this.getRawData,this))},e.prototype.mergeOption=function(e){t.prototype.mergeOption.apply(this,arguments),this.fillDataTextStyle(e.edges||e.links)},e.prototype.getInitialData=function(t,e){var n=t.edges||t.links||[],i=t.data||t.nodes||[];if(i&&n)return XP(i,n,this,!0,(function(t,e){var n=wd.prototype.getModel;function i(t,e){var i=n.call(this,t,e);return i.resolveParentPath=r,i}function r(t){if(t&&("label"===t[0]||"label"===t[1])){var e=t.slice();return"label"===t[0]?e[0]="edgeLabel":"label"===t[1]&&(e[1]="edgeLabel"),e}return t}e.wrapMethod("getItemModel",(function(t){return t.resolveParentPath=r,t.getModel=i,t}))})).data},e.prototype.getGraph=function(){return this.getData().graph},e.prototype.getEdgeData=function(){return this.getGraph().edgeData},e.prototype.formatTooltip=function(t,e,n){var i=this.getDataParams(t,n);if("edge"===n){var r=this.getData(),o=r.graph.getEdgeByIndex(t),a=r.getName(o.node1.dataIndex),s=r.getName(o.node2.dataIndex),l=[];return null!=a&&l.push(a),null!=s&&l.push(s),Ty("nameValue",{name:l.join(" > "),value:i.value,noValue:null==i.value})}return Ty("nameValue",{name:i.name,value:i.value,noValue:null==i.value})},e.prototype.getDataParams=function(e,n){var i=t.prototype.getDataParams.call(this,e,n);if("node"===n){var r=this.getData(),o=this.getGraph().getNodeByIndex(e);if(null==i.name&&(i.name=r.getName(e)),null==i.value){var a=o.getLayout().value;i.value=a}}return i},e.type="series.chord",e.defaultOption={z:2,coordinateSystem:"none",legendHoverLink:!0,colorBy:"data",left:0,top:0,right:0,bottom:0,width:null,height:null,center:["50%","50%"],radius:["70%","80%"],clockwise:!0,startAngle:90,endAngle:"auto",minAngle:0,padAngle:3,itemStyle:{borderRadius:[0,0,5,5]},lineStyle:{width:0,color:"source",opacity:.2},label:{show:!0,position:"outside",distance:5},emphasis:{focus:"adjacency",lineStyle:{opacity:.5}}},e}(Wy),tO=Math.PI/180;function eO(t,e){t.eachSeriesByType("chord",(function(t){!function(t,e){var n=t.getData(),i=n.graph,r=t.getEdgeData();if(!r.count())return;var o=Wp(t,e),a=o.cx,s=o.cy,l=o.r,u=o.r0,c=Math.max((t.get("padAngle")||0)*tO,0),h=Math.max((t.get("minAngle")||0)*tO,0),d=-t.get("startAngle")*tO,p=d+2*Math.PI,f=t.get("clockwise"),g=f?1:-1,y=[d,p];Gs(y,!f);var v=y[0],m=y[1]-v,x=0===n.getSum("value")&&0===r.getSum("value"),_=[],b=0;i.eachEdge((function(t){var e=x?1:t.getValue("value");x&&(e>0||h)&&(b+=2);var n=t.node1.dataIndex,i=t.node2.dataIndex;_[n]=(_[n]||0)+e,_[i]=(_[i]||0)+e}));var w=0;if(i.eachNode((function(t){var e=t.getValue("value");isNaN(e)||(_[t.dataIndex]=Math.max(e,_[t.dataIndex]||0)),!x&&(_[t.dataIndex]>0||h)&&b++,w+=_[t.dataIndex]||0})),0===b||0===w)return;c*b>=Math.abs(m)&&(c=Math.max(0,(Math.abs(m)-h*b)/b));(c+h)*b>=Math.abs(m)&&(h=(Math.abs(m)-c*b)/b);var S=(m-c*b*g)/w,M=0,I=0,T=0;i.eachNode((function(t){var e=_[t.dataIndex]||0,n=S*(w?e:1)*g;Math.abs(n)I){var D=M/I;i.eachNode((function(t){var e=t.getLayout().angle;Math.abs(e)>=h?t.setLayout({angle:e*D,ratio:D},!0):t.setLayout({angle:h,ratio:0===h?1:e/h},!0)}))}else i.eachNode((function(t){if(!C){var e=t.getLayout().angle;e-Math.min(e/T,1)*Mh&&h>0){var n=C?1:Math.min(e/T,1),i=e-h,r=Math.min(i,Math.min(A,M*n));A-=r,t.setLayout({angle:e-r,ratio:(e-r)/e},!0)}else h>0&&t.setLayout({angle:h,ratio:0===e?1:h/e},!0)}}));var k=v,L=[];i.eachNode((function(t){var e=Math.max(t.getLayout().angle,h);t.setLayout({cx:a,cy:s,r0:u,r:l,startAngle:k,endAngle:k+e*g,clockwise:f},!0),L[t.dataIndex]=k,k+=(e+c)*g})),i.eachEdge((function(t){var e=x?1:t.getValue("value"),n=S*(w?e:1)*g,i=t.node1.dataIndex,r=L[i]||0,o=r+Math.abs((t.node1.getLayout().ratio||1)*n)*g,l=[a+u*Math.cos(r),s+u*Math.sin(r)],c=[a+u*Math.cos(o),s+u*Math.sin(o)],h=t.node2.dataIndex,d=L[h]||0,p=d+Math.abs((t.node2.getLayout().ratio||1)*n)*g,y=[a+u*Math.cos(d),s+u*Math.sin(d)],v=[a+u*Math.cos(p),s+u*Math.sin(p)];t.setLayout({s1:l,s2:c,sStartAngle:r,sEndAngle:o,t1:y,t2:v,tStartAngle:d,tEndAngle:p,cx:a,cy:s,r:u,value:e,clockwise:f}),L[i]=o,L[h]=p}))}(t,e)}))}var nO=function(){this.angle=0,this.width=10,this.r=10,this.x=0,this.y=0},iO=function(t){function e(e){var n=t.call(this,e)||this;return n.type="pointer",n}return n(e,t),e.prototype.getDefaultShape=function(){return new nO},e.prototype.buildPath=function(t,e){var n=Math.cos,i=Math.sin,r=e.r,o=e.width,a=e.angle,s=e.x-n(a)*o*(o>=r/3?1:2),l=e.y-i(a)*o*(o>=r/3?1:2);a=e.angle-Math.PI/2,t.moveTo(s,l),t.lineTo(e.x+n(a)*o,e.y+i(a)*o),t.lineTo(e.x+n(e.angle)*r,e.y+i(e.angle)*r),t.lineTo(e.x-n(a)*o,e.y-i(a)*o),t.lineTo(s,l)},e}(sl);function rO(t,e){var n=null==t?"":t+"";return e&&(X(e)?n=e.replace("{value}",n):Y(e)&&(n=e(t))),n}var oO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){this.group.removeAll();var i=t.get(["axisLine","lineStyle","color"]),r=function(t,e){var n=t.get("center"),i=e.getWidth(),r=e.getHeight(),o=Math.min(i,r);return{cx:yo(n[0],e.getWidth()),cy:yo(n[1],e.getHeight()),r:yo(t.get("radius"),o/2)}}(t,n);this._renderMain(t,e,n,i,r),this._data=t.getData()},e.prototype.dispose=function(){},e.prototype._renderMain=function(t,e,n,i,r){var o=this.group,a=t.get("clockwise"),s=-t.get("startAngle")/180*Math.PI,l=-t.get("endAngle")/180*Math.PI,u=t.getModel("axisLine"),c=u.get("roundCap")?WI:xc,h=u.get("show"),d=u.getModel("lineStyle"),p=d.get("width"),f=[s,l];Gs(f,!a);for(var g=(l=f[1])-(s=f[0]),y=s,v=[],m=0;h&&m=t&&(0===e?0:i[e-1][0])Math.PI/2&&(B+=Math.PI):"tangential"===E?B=-M-Math.PI/2:j(E)&&(B=E*Math.PI/180),0===B?h.add(new Sl({style:Qh(x,{text:O,x:N,y:z,verticalAlign:c<-.8?"top":c>.8?"bottom":"middle",align:u<-.4?"left":u>.4?"right":"center"},{inheritColor:R}),silent:!0})):h.add(new Sl({style:Qh(x,{text:O,x:N,y:z,verticalAlign:"middle",align:"center"},{inheritColor:R}),silent:!0,originX:N,originY:z,rotation:B}))}if(m.get("show")&&k!==_){P=(P=m.get("distance"))?P+l:l;for(var V=0;V<=b;V++){u=Math.cos(M),c=Math.sin(M);var G=new Ac({shape:{x1:u*(f-P)+d,y1:c*(f-P)+p,x2:u*(f-S-P)+d,y2:c*(f-S-P)+p},silent:!0,style:D});"auto"===D.stroke&&G.setStyle({stroke:i((k+V/b)/_)}),h.add(G),M+=T}M-=T}else M+=I}},e.prototype._renderPointer=function(t,e,n,i,r,o,a,s,l){var u=this.group,c=this._data,h=this._progressEls,d=[],p=t.get(["pointer","show"]),f=t.getModel("progress"),g=f.get("show"),y=t.getData(),v=y.mapDimension("value"),m=+t.get("min"),x=+t.get("max"),_=[m,x],b=[o,a];function w(e,n){var i,o=y.getItemModel(e).getModel("pointer"),a=yo(o.get("width"),r.r),s=yo(o.get("length"),r.r),l=t.get(["pointer","icon"]),u=o.get("offsetCenter"),c=yo(u[0],r.r),h=yo(u[1],r.r),d=o.get("keepAspect");return(i=l?hm(l,c-a/2,h-s,a,s,null,d):new iO({shape:{angle:-Math.PI/2,width:a,r:s,x:c,y:h}})).rotation=-(n+Math.PI/2),i.x=r.cx,i.y=r.cy,i}function S(t,e){var n=f.get("roundCap")?WI:xc,i=f.get("overlap"),a=i?f.get("width"):l/y.count(),u=i?r.r-a:r.r-(t+1)*a,c=i?r.r:r.r-t*a,h=new n({shape:{startAngle:o,endAngle:e,cx:r.cx,cy:r.cy,clockwise:s,r0:u,r:c}});return i&&(h.z2=go(y.get(v,t),[m,x],[100,0],!0)),h}(g||p)&&(y.diff(c).add((function(e){var n=y.get(v,e);if(p){var i=w(e,o);eh(i,{rotation:-((isNaN(+n)?b[0]:go(n,_,b,!0))+Math.PI/2)},t),u.add(i),y.setItemGraphicEl(e,i)}if(g){var r=S(e,o),a=f.get("clip");eh(r,{shape:{endAngle:go(n,_,b,a)}},t),u.add(r),El(t.seriesIndex,y.dataType,e,r),d[e]=r}})).update((function(e,n){var i=y.get(v,e);if(p){var r=c.getItemGraphicEl(n),a=r?r.rotation:o,s=w(e,a);s.rotation=a,th(s,{rotation:-((isNaN(+i)?b[0]:go(i,_,b,!0))+Math.PI/2)},t),u.add(s),y.setItemGraphicEl(e,s)}if(g){var l=h[n],m=S(e,l?l.shape.endAngle:o),x=f.get("clip");th(m,{shape:{endAngle:go(i,_,b,x)}},t),u.add(m),El(t.seriesIndex,y.dataType,e,m),d[e]=m}})).execute(),y.each((function(t){var e=y.getItemModel(t),n=e.getModel("emphasis"),r=n.get("focus"),o=n.get("blurScope"),a=n.get("disabled");if(p){var s=y.getItemGraphicEl(t),l=y.getItemVisual(t,"style"),u=l.fill;if(s instanceof dl){var c=s.style;s.useStyle(A({image:c.image,x:c.x,y:c.y,width:c.width,height:c.height},l))}else s.useStyle(l),"pointer"!==s.type&&s.setColor(u);s.setStyle(e.getModel(["pointer","itemStyle"]).getItemStyle()),"auto"===s.style.fill&&s.setStyle("fill",i(go(y.get(v,t),_,[0,1],!0))),s.z2EmphasisLift=0,ku(s,e),Tu(s,r,o,a)}if(g){var h=d[t];h.useStyle(y.getItemVisual(t,"style")),h.setStyle(e.getModel(["progress","itemStyle"]).getItemStyle()),h.z2EmphasisLift=0,ku(h,e),Tu(h,r,o,a)}})),this._progressEls=d)},e.prototype._renderAnchor=function(t,e){var n=t.getModel("anchor");if(n.get("show")){var i=n.get("size"),r=n.get("icon"),o=n.get("offsetCenter"),a=n.get("keepAspect"),s=hm(r,e.cx-i/2+yo(o[0],e.r),e.cy-i/2+yo(o[1],e.r),i,i,null,a);s.z2=n.get("showAbove")?1:0,s.setStyle(n.getModel("itemStyle").getItemStyle()),this.group.add(s)}},e.prototype._renderTitleAndDetail=function(t,e,n,i,r){var o=this,a=t.getData(),s=a.mapDimension("value"),l=+t.get("min"),u=+t.get("max"),c=new to,h=[],d=[],p=t.isAnimationEnabled(),f=t.get(["pointer","showAbove"]);a.diff(this._data).add((function(t){h[t]=new Sl({silent:!0}),d[t]=new Sl({silent:!0})})).update((function(t,e){h[t]=o._titleEls[e],d[t]=o._detailEls[e]})).execute(),a.each((function(e){var n=a.getItemModel(e),o=a.get(s,e),g=new to,y=i(go(o,[l,u],[0,1],!0)),v=n.getModel("title");if(v.get("show")){var m=v.get("offsetCenter"),x=r.cx+yo(m[0],r.r),_=r.cy+yo(m[1],r.r);(D=h[e]).attr({z2:f?0:2,style:Qh(v,{x:x,y:_,text:a.getName(e),align:"center",verticalAlign:"middle"},{inheritColor:y})}),g.add(D)}var b=n.getModel("detail");if(b.get("show")){var w=b.get("offsetCenter"),S=r.cx+yo(w[0],r.r),M=r.cy+yo(w[1],r.r),I=yo(b.get("width"),r.r),T=yo(b.get("height"),r.r),C=t.get(["progress","show"])?a.getItemVisual(e,"style").fill:y,D=d[e],A=b.get("formatter");D.attr({z2:f?0:2,style:Qh(b,{x:S,y:M,text:rO(o,A),width:isNaN(I)?null:I,height:isNaN(T)?null:T,align:"center",verticalAlign:"middle"},{inheritColor:C})}),sd(D,{normal:b},o,(function(t){return rO(t,A)})),p&&ld(D,e,a,t,{getFormattedLabel:function(t,e,n,i,r,a){return rO(a?a.interpolatedValue:o,A)}}),g.add(D)}c.add(g)})),this.group.add(c),this._titleEls=h,this._detailEls=d},e.type="gauge",e}(tv),aO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.visualStyleAccessPath="itemStyle",n}return n(e,t),e.prototype.getInitialData=function(t,e){return IT(this,["value"])},e.type="series.gauge",e.defaultOption={z:2,colorBy:"data",center:["50%","50%"],legendHoverLink:!0,radius:"75%",startAngle:225,endAngle:-45,clockwise:!0,min:0,max:100,splitNumber:10,axisLine:{show:!0,roundCap:!1,lineStyle:{color:[[1,tf.color.neutral10]],width:10}},progress:{show:!1,overlap:!0,width:10,roundCap:!1,clip:!0},splitLine:{show:!0,length:10,distance:10,lineStyle:{color:tf.color.axisTick,width:3,type:"solid"}},axisTick:{show:!0,splitNumber:5,length:6,distance:10,lineStyle:{color:tf.color.axisTickMinor,width:1,type:"solid"}},axisLabel:{show:!0,distance:15,color:tf.color.axisLabel,fontSize:12,rotate:0},pointer:{icon:null,offsetCenter:[0,0],show:!0,showAbove:!0,length:"60%",width:6,keepAspect:!1},anchor:{show:!1,showAbove:!1,size:6,icon:"circle",offsetCenter:[0,0],keepAspect:!1,itemStyle:{color:tf.color.neutral00,borderWidth:0,borderColor:tf.color.theme[0]}},title:{show:!0,offsetCenter:[0,"20%"],color:tf.color.secondary,fontSize:16,valueAnimation:!1},detail:{show:!0,backgroundColor:tf.color.transparent,borderWidth:0,borderColor:tf.color.neutral40,width:100,height:null,padding:[5,10],offsetCenter:[0,"40%"],color:tf.color.primary,fontSize:30,fontWeight:"bold",lineHeight:30,valueAnimation:!1}},e}(Wy);var sO=["itemStyle","opacity"],lO=function(t){function e(e,n){var i=t.call(this)||this,r=i,o=new Tc,a=new Sl;return r.setTextContent(a),i.setTextGuideLine(o),i.updateData(e,n,!0),i}return n(e,t),e.prototype.updateData=function(t,e,n){var i=this,r=t.hostModel,o=t.getItemModel(e),a=t.getItemLayout(e),s=o.getModel("emphasis"),l=o.get(sO);l=null==l?1:l,n||ah(i),i.useStyle(t.getItemVisual(e,"style")),i.style.lineJoin="round",n?(i.setShape({points:a.points}),i.style.opacity=0,eh(i,{style:{opacity:l}},r,e)):th(i,{style:{opacity:l},shape:{points:a.points}},r,e),ku(i,o),this._updateLabel(t,e),Tu(this,s.get("focus"),s.get("blurScope"),s.get("disabled"))},e.prototype._updateLabel=function(t,e){var n=this,i=this.getTextGuideLine(),r=n.getTextContent(),o=t.hostModel,a=t.getItemModel(e),s=t.getItemLayout(e).label,l=t.getItemVisual(e,"style"),u=l.fill;$h(r,Jh(a),{labelFetcher:t.hostModel,labelDataIndex:e,defaultOpacity:l.opacity,defaultText:t.getName(e)},{normal:{align:s.textAlign,verticalAlign:s.verticalAlign}});var c="inherit"===a.getModel("label").get("color")?u:null;n.setTextConfig({local:!0,inside:!!s.inside,insideStroke:c,outsideFill:c});var h=s.linePoints;i.setShape({points:h}),n.textGuideLineConfig={anchor:h?new Ae(h[0][0],h[0][1]):null},th(r,{style:{x:s.x,y:s.y}},o,e),r.attr({rotation:s.rotation,originX:s.x,originY:s.y,z2:10}),dS(n,pS(a),{stroke:u})},e}(Mc),uO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.ignoreLabelLineUpdate=!0,n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData(),r=this._data,o=this.group;i.diff(r).add((function(t){var e=new lO(i,t);i.setItemGraphicEl(t,e),o.add(e)})).update((function(t,e){var n=r.getItemGraphicEl(e);n.updateData(i,t),o.add(n),i.setItemGraphicEl(t,n)})).remove((function(e){oh(r.getItemGraphicEl(e),t,e)})).execute(),this._data=i},e.prototype.remove=function(){this.group.removeAll(),this._data=null},e.prototype.dispose=function(){},e.type="funnel",e}(tv),cO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(e){t.prototype.init.apply(this,arguments),this.legendVisualProvider=new CT(W(this.getData,this),W(this.getRawData,this)),this._defaultLabelLine(e)},e.prototype.getInitialData=function(t,e){return IT(this,{coordDimensions:["value"],encodeDefaulter:H(Mf,this)})},e.prototype._defaultLabelLine=function(t){Ko(t,"labelLine",["show"]);var e=t.labelLine,n=t.emphasis.labelLine;e.show=e.show&&t.label.show,n.show=n.show&&t.emphasis.label.show},e.prototype.getDataParams=function(e){var n=this.getData(),i=t.prototype.getDataParams.call(this,e),r=n.mapDimension("value"),o=n.getSum(r);return i.percent=o?+(n.get(r,e)/o*100).toFixed(2):0,i.$vars.push("percent"),i},e.type="series.funnel",e.defaultOption={coordinateSystemUsage:"box",z:2,legendHoverLink:!0,colorBy:"data",left:80,top:60,right:80,bottom:65,minSize:"0%",maxSize:"100%",sort:"descending",orient:"vertical",gap:0,funnelAlign:"center",label:{show:!0,position:"outer"},labelLine:{show:!0,length:20,lineStyle:{width:1}},itemStyle:{borderColor:tf.color.neutral00,borderWidth:1},emphasis:{label:{show:!0}},select:{itemStyle:{borderColor:tf.color.primary}}},e}(Wy);function hO(t,e){t.eachSeriesByType("funnel",(function(t){var n=t.getData(),i=n.mapDimension("value"),r=t.get("sort"),o=Xp(t,e),a=Hp(t.getBoxLayoutParams(),o.refContainer),s=t.get("orient"),l=a.width,u=a.height,c=function(t,e){for(var n=t.mapDimension("value"),i=t.mapArray(n,(function(t){return t})),r=[],o="ascending"===e,a=0,s=t.count();a5)return;var i=this._model.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]);"none"!==i.behavior&&this._dispatchExpand({axisExpandWindow:i.axisExpandWindow})}this._mouseDownPoint=null},mousemove:function(t){if(!this._mouseDownPoint&&MO(this,"mousemove")){var e=this._model,n=e.coordinateSystem.getSlidedAxisExpandWindow([t.offsetX,t.offsetY]),i=n.behavior;"jump"===i&&this._throttledDispatchExpand.debounceNextCall(e.get("axisExpandDebounce")),this._throttledDispatchExpand("none"===i?null:{axisExpandWindow:n.axisExpandWindow,animation:"jump"===i?null:{duration:0}})}}};function MO(t,e){var n=t._model;return n.get("axisExpandable")&&n.get("axisExpandTriggerOn")===e}var IO=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(){t.prototype.init.apply(this,arguments),this.mergeOption({})},e.prototype.mergeOption=function(t){var e=this.option;t&&C(e,t,!0),this._initDimensions()},e.prototype.contains=function(t,e){var n=t.get("parallelIndex");return null!=n&&e.getComponent("parallel",n)===this},e.prototype.setAxisExpand=function(t){z(["axisExpandable","axisExpandCenter","axisExpandCount","axisExpandWidth","axisExpandWindow"],(function(e){t.hasOwnProperty(e)&&(this.option[e]=t[e])}),this)},e.prototype._initDimensions=function(){var t=this.dimensions=[],e=this.parallelAxisIndex=[];z(V(this.ecModel.queryComponents({mainType:"parallelAxis"}),(function(t){return(t.get("parallelIndex")||0)===this.componentIndex}),this),(function(n){t.push("dim"+n.get("dim")),e.push(n.componentIndex)}))},e.type="parallel",e.dependencies=["parallelAxis"],e.layoutMode="box",e.defaultOption={z:0,left:80,top:60,right:80,bottom:60,layout:"horizontal",axisExpandable:!1,axisExpandCenter:null,axisExpandCount:0,axisExpandWidth:50,axisExpandRate:17,axisExpandDebounce:50,axisExpandSlideTriggerArea:[-.15,.05,.4],axisExpandTriggerOn:"click",parallelAxisDefault:null},e}(Qp),TO=function(t){function e(e,n,i,r,o){var a=t.call(this,e,n,i)||this;return a.type=r||"value",a.axisIndex=o,a}return n(e,t),e.prototype.isHorizontal=function(){return"horizontal"!==this.coordinateSystem.getModel().get("layout")},e}(Ww);function CO(t,e,n,i,r,o){t=t||0;var a=n[1]-n[0];if(null!=r&&(r=AO(r,[0,a])),null!=o&&(o=Math.max(o,null!=r?r:0)),"all"===i){var s=Math.abs(e[1]-e[0]);s=AO(s,[0,a]),r=o=AO(s,[r,o]),i=0}e[0]=AO(e[0],n),e[1]=AO(e[1],n);var l=DO(e,i);e[i]+=t;var u,c=r||0,h=n.slice();return l.sign<0?h[0]+=c:h[1]-=c,e[i]=AO(e[i],h),u=DO(e,i),null!=r&&(u.sign!==l.sign||u.spano&&(e[1-i]=e[i]+u.sign*o),e}function DO(t,e){var n=t[e]-t[1-e];return{span:Math.abs(n),sign:n>0?-1:n<0?1:e?-1:1}}function AO(t,e){return Math.min(null!=e[1]?e[1]:1/0,Math.max(null!=e[0]?e[0]:-1/0,t))}var kO=z,LO=Math.min,PO=Math.max,OO=Math.floor,RO=Math.ceil,NO=mo,zO=Math.PI,EO=function(){function t(t,e,n){this.type="parallel",this._axesMap=yt(),this._axesLayout={},this.dimensions=t.dimensions,this._model=t,this._init(t,e,n)}return t.prototype._init=function(t,e,n){var i=t.dimensions,r=t.parallelAxisIndex;kO(i,(function(t,n){var i=r[n],o=e.getComponent("parallelAxis",i),a=this._axesMap.set(t,new TO(t,Zb(o),[0,0],o.get("type"),i)),s="category"===a.type;a.onBand=s&&o.get("boundaryGap"),a.inverse=o.get("inverse"),o.axis=a,a.model=o,a.coordinateSystem=o.coordinateSystem=this}),this)},t.prototype.update=function(t,e){this._updateAxesFromSeries(this._model,t)},t.prototype.containPoint=function(t){var e=this._makeLayoutInfo(),n=e.axisBase,i=e.layoutBase,r=e.pixelDimIndex,o=t[1-r],a=t[r];return o>=n&&o<=n+e.axisLength&&a>=i&&a<=i+e.layoutLength},t.prototype.getModel=function(){return this._model},t.prototype._updateAxesFromSeries=function(t,e){e.eachSeries((function(n){if(t.contains(n,e)){var i=n.getData();kO(this.dimensions,(function(t){var e=this._axesMap.get(t);e.scale.unionExtentFromData(i,i.mapDimension(t)),Xb(e.scale,e.model)}),this)}}),this)},t.prototype.resize=function(t,e){var n=Xp(t,e).refContainer;this._rect=Hp(t.getBoxLayoutParams(),n),this._layoutAxes()},t.prototype.getRect=function(){return this._rect},t.prototype._makeLayoutInfo=function(){var t,e=this._model,n=this._rect,i=["x","y"],r=["width","height"],o=e.get("layout"),a="horizontal"===o?0:1,s=n[r[a]],l=[0,s],u=this.dimensions.length,c=BO(e.get("axisExpandWidth"),l),h=BO(e.get("axisExpandCount")||0,[0,u]),d=e.get("axisExpandable")&&u>3&&u>h&&h>1&&c>0&&s>0,p=e.get("axisExpandWindow");p?(t=BO(p[1]-p[0],l),p[1]=p[0]+t):(t=BO(c*(h-1),l),(p=[c*(e.get("axisExpandCenter")||OO(u/2))-t/2])[1]=p[0]+t);var f=(s-t)/(u-h);f<3&&(f=0);var g=[OO(NO(p[0]/c,1))+1,RO(NO(p[1]/c,1))-1],y=f/c*p[0];return{layout:o,pixelDimIndex:a,layoutBase:n[i[a]],layoutLength:s,axisBase:n[i[1-a]],axisLength:n[r[1-a]],axisExpandable:d,axisExpandWidth:c,axisCollapseWidth:f,axisExpandWindow:p,axisCount:u,winInnerIndices:g,axisExpandWindow0Pos:y}},t.prototype._layoutAxes=function(){var t=this._rect,e=this._axesMap,n=this.dimensions,i=this._makeLayoutInfo(),r=i.layout;e.each((function(t){var e=[0,i.axisLength],n=t.inverse?1:0;t.setExtent(e[n],e[1-n])})),kO(n,(function(e,n){var o=(i.axisExpandable?GO:VO)(n,i),a={horizontal:{x:o.position,y:i.axisLength},vertical:{x:0,y:o.position}},s={horizontal:zO/2,vertical:0},l=[a[r].x+t.x,a[r].y+t.y],u=s[r],c=[1,0,0,1,0,0];Me(c,c,u),Se(c,c,l),this._axesLayout[e]={position:l,rotation:u,transform:c,axisNameAvailableWidth:o.axisNameAvailableWidth,axisLabelShow:o.axisLabelShow,nameTruncateMaxWidth:o.nameTruncateMaxWidth,tickDirection:1,labelDirection:1}}),this)},t.prototype.getAxis=function(t){return this._axesMap.get(t)},t.prototype.dataToPoint=function(t,e){return this.axisCoordToPoint(this._axesMap.get(e).dataToCoord(t),e)},t.prototype.eachActiveState=function(t,e,n,i){null==n&&(n=0),null==i&&(i=t.count());var r=this._axesMap,o=this.dimensions,a=[],s=[];z(o,(function(e){a.push(t.mapDimension(e)),s.push(r.get(e).model)}));for(var l=this.hasAxisBrushed(),u=n;ur*(1-c[0])?(l="jump",a=s-r*(1-c[2])):(a=s-r*c[1])>=0&&(a=s-r*(1-c[1]))<=0&&(a=0),(a*=e.axisExpandWidth/u)?CO(a,i,o,"all"):l="none";else{var d=i[1]-i[0];(i=[PO(0,o[1]*s/d-d/2)])[1]=LO(o[1],i[0]+d),i[0]=i[1]-d}return{axisExpandWindow:i,behavior:l}},t}();function BO(t,e){return LO(PO(t,e[0]),e[1])}function VO(t,e){var n=e.layoutLength/(e.axisCount-1);return{position:n*t,axisNameAvailableWidth:n,axisLabelShow:!0}}function GO(t,e){var n,i,r=e.layoutLength,o=e.axisExpandWidth,a=e.axisCount,s=e.axisCollapseWidth,l=e.winInnerIndices,u=s,c=!1;return t=0;n--)xo(e[n])},e.prototype.getActiveState=function(t){var e=this.activeIntervals;if(!e.length)return"normal";if(null==t||isNaN(+t))return"inactive";if(1===e.length){var n=e[0];if(n[0]<=t&&t<=n[1])return"active"}else for(var i=0,r=e.length;i6}(t)||o){if(a&&!o){"single"===s.brushMode&&sR(t);var l=T(s);l.brushType=MR(l.brushType,a),l.panelId=a===HO?null:a.panelId,o=t._creatingCover=QO(t,l),t._covers.push(o)}if(o){var u=CR[MR(t._brushType,a)];o.__brushOption.range=u.getCreatingRange(_R(t,o,t._track)),i&&(tR(t,o),u.updateCommon(t,o)),eR(t,o),r={isEnd:i}}}else i&&"single"===s.brushMode&&s.removeOnClick&&oR(t,e,n)&&sR(t)&&(r={isEnd:i,removeOnClick:!0});return r}function MR(t,e){return"auto"===t?e.defaultBrushType:t}var IR={mousedown:function(t){if(this._dragging)TR(this,t);else if(!t.target||!t.target.draggable){bR(t);var e=this.group.transformCoordToLocal(t.offsetX,t.offsetY);this._creatingCover=null,(this._creatingPanel=oR(this,t,e))&&(this._dragging=!0,this._track=[e.slice()])}},mousemove:function(t){var e=t.offsetX,n=t.offsetY,i=this.group.transformCoordToLocal(e,n);if(function(t,e,n){if(t._brushType&&!function(t,e,n){var i=t._zr;return e<0||e>i.getWidth()||n<0||n>i.getHeight()}(t,e.offsetX,e.offsetY)){var i=t._zr,r=t._covers,o=oR(t,e,n);if(!t._dragging)for(var a=0;a=0&&(o[r[a].depth]=new wd(r[a],this,e));var s=XP(i,n,this,!0,(function(t,e){t.wrapMethod("getItemModel",(function(t,e){var n=t.parentModel,i=n.getData().getItemLayout(e);if(i){var r=i.depth,o=n.levelModels[r];o&&(t.parentModel=o)}return t})),e.wrapMethod("getItemModel",(function(t,e){var n=t.parentModel,i=n.getGraph().getEdgeByIndex(e).node1.getLayout();if(i){var r=i.depth,o=n.levelModels[r];o&&(t.parentModel=o)}return t}))}));return s.data},e.prototype.setNodePosition=function(t,e){var n=(this.option.data||this.option.nodes)[t];n.localX=e[0],n.localY=e[1]},e.prototype.setCenter=function(t){this.option.center=t},e.prototype.setZoom=function(t){this.option.zoom=t},e.prototype.getGraph=function(){return this.getData().graph},e.prototype.getEdgeData=function(){return this.getGraph().edgeData},e.prototype.formatTooltip=function(t,e,n){function i(t){return isNaN(t)||null==t}if("edge"===n){var r=this.getDataParams(t,n),o=r.data,a=r.value;return Ty("nameValue",{name:o.source+" -- "+o.target,value:a,noValue:i(a)})}var s=this.getGraph().getNodeByIndex(t).getLayout().value,l=this.getDataParams(t,n).data.name;return Ty("nameValue",{name:null!=l?l+"":null,value:s,noValue:i(s)})},e.prototype.optionUpdated=function(){},e.prototype.getDataParams=function(e,n){var i=t.prototype.getDataParams.call(this,e,n);if(null==i.value&&"node"===n){var r=this.getGraph().getNodeByIndex(e).getLayout().value;i.value=r}return i},e.type="series.sankey",e.layoutMode="box",e.defaultOption={z:2,coordinateSystemUsage:"box",left:"5%",top:"5%",right:"20%",bottom:"5%",orient:"horizontal",nodeWidth:20,nodeGap:8,draggable:!0,layoutIterations:32,roam:!1,roamTrigger:"global",center:null,zoom:1,label:{show:!0,position:"right",fontSize:12},edgeLabel:{show:!1,fontSize:12},levels:[],nodeAlign:"justify",lineStyle:{color:tf.color.neutral50,opacity:.2,curveness:.5},emphasis:{label:{show:!0},lineStyle:{opacity:.5}},select:{itemStyle:{borderColor:tf.color.primary}},animationEasing:"linear",animationDuration:1e3},e}(Wy);function WR(t,e){t.eachSeriesByType("sankey",(function(t){var n=t.get("nodeWidth"),i=t.get("nodeGap"),r=Xp(t,e).refContainer,o=Hp(t.getBoxLayoutParams(),r);t.layoutInfo=o;var a=o.width,s=o.height,l=t.getGraph(),u=l.nodes,c=l.edges;!function(t){z(t,(function(t){var e=JR(t.outEdges,$R),n=JR(t.inEdges,$R),i=t.getValue()||0,r=Math.max(e,n,i);t.setLayout({value:r},!0)}))}(u),function(t,e,n,i,r,o,a,s,l){(function(t,e,n,i,r,o,a){for(var s=[],l=[],u=[],c=[],h=0,d=0;d=0;v&&y.depth>p&&(p=y.depth),g.setLayout({depth:v?y.depth:h},!0),"vertical"===o?g.setLayout({dy:n},!0):g.setLayout({dx:n},!0);for(var m=0;mh-1?p:h-1;a&&"left"!==a&&function(t,e,n,i){if("right"===e){for(var r=[],o=t,a=0;o.length;){for(var s=0;s0;o--)YR(s,l*=.99,a),UR(s,r,n,i,a),QR(s,l,a),UR(s,r,n,i,a)}(t,e,o,r,i,a,s),function(t,e){var n="vertical"===e?"x":"y";z(t,(function(t){t.outEdges.sort((function(t,e){return t.node2.getLayout()[n]-e.node2.getLayout()[n]})),t.inEdges.sort((function(t,e){return t.node1.getLayout()[n]-e.node1.getLayout()[n]}))})),z(t,(function(t){var e=0,n=0;z(t.outEdges,(function(t){t.setLayout({sy:e},!0),e+=t.getLayout().dy})),z(t.inEdges,(function(t){t.setLayout({ty:n},!0),n+=t.getLayout().dy}))}))}(t,s)}(u,c,n,i,a,s,0!==V(u,(function(t){return 0===t.getLayout().value})).length?0:t.get("layoutIterations"),t.get("orient"),t.get("nodeAlign"))}))}function HR(t){var e=t.hostGraph.data.getRawDataItem(t.dataIndex);return null!=e.depth&&e.depth>=0}function UR(t,e,n,i,r){var o="vertical"===r?"x":"y";z(t,(function(t){var a,s,l;t.sort((function(t,e){return t.getLayout()[o]-e.getLayout()[o]}));for(var u=0,c=t.length,h="vertical"===r?"dx":"dy",d=0;d0&&(a=s.getLayout()[o]+l,"vertical"===r?s.setLayout({x:a},!0):s.setLayout({y:a},!0)),u=s.getLayout()[o]+s.getLayout()[h]+e;if((l=u-e-("vertical"===r?i:n))>0){a=s.getLayout()[o]-l,"vertical"===r?s.setLayout({x:a},!0):s.setLayout({y:a},!0),u=a;for(d=c-2;d>=0;--d)(l=(s=t[d]).getLayout()[o]+s.getLayout()[h]+e-u)>0&&(a=s.getLayout()[o]-l,"vertical"===r?s.setLayout({x:a},!0):s.setLayout({y:a},!0)),u=s.getLayout()[o]}}))}function YR(t,e,n){z(t.slice().reverse(),(function(t){z(t,(function(t){if(t.outEdges.length){var i=JR(t.outEdges,XR,n)/JR(t.outEdges,$R);if(isNaN(i)){var r=t.outEdges.length;i=r?JR(t.outEdges,ZR,n)/r:0}if("vertical"===n){var o=t.getLayout().x+(i-KR(t,n))*e;t.setLayout({x:o},!0)}else{var a=t.getLayout().y+(i-KR(t,n))*e;t.setLayout({y:a},!0)}}}))}))}function XR(t,e){return KR(t.node2,e)*t.getValue()}function ZR(t,e){return KR(t.node2,e)}function jR(t,e){return KR(t.node1,e)*t.getValue()}function qR(t,e){return KR(t.node1,e)}function KR(t,e){return"vertical"===e?t.getLayout().x+t.getLayout().dx/2:t.getLayout().y+t.getLayout().dy/2}function $R(t){return t.getValue()}function JR(t,e,n){for(var i=0,r=t.length,o=-1;++oo&&(o=e)})),z(n,(function(e){var n=new hL({type:"color",mappingMethod:"linear",dataExtent:[r,o],visual:t.get("color")}).mapValueToVisual(e.getLayout().value),i=e.getModel().get(["itemStyle","color"]);null!=i?(e.setVisual("color",i),e.setVisual("style",{fill:i})):(e.setVisual("color",n),e.setVisual("style",{fill:n}))}))}i.length&&z(i,(function(t){var e=t.getModel().get("lineStyle");t.setVisual("style",e)}))}))}var eN=function(){function t(){}return t.prototype._hasEncodeRule=function(t){var e=this.getEncode();return e&&null!=e.get(t)},t.prototype.getInitialData=function(t,e){var n,i,r=e.getComponent("xAxis",this.get("xAxisIndex")),o=e.getComponent("yAxis",this.get("yAxisIndex")),a=r.get("type"),s=o.get("type");"category"===a?(t.layout="horizontal",n=r.getOrdinalMeta(),i=!this._hasEncodeRule("x")):"category"===s?(t.layout="vertical",n=o.getOrdinalMeta(),i=!this._hasEncodeRule("y")):t.layout=t.layout||"horizontal";var l=["x","y"],u="horizontal"===t.layout?0:1,c=this._baseAxisDim=l[u],h=l[1-u],d=[r,o],p=d[u].get("type"),f=d[1-u].get("type"),g=t.data;if(g&&i){var y=[];z(g,(function(t,e){var n;U(t)?(n=t.slice(),t.unshift(e)):U(t.value)?((n=A({},t)).value=n.value.slice(),t.value.unshift(e)):n=t,y.push(n)})),t.data=y}var v=this.defaultValueDimensions,m=[{name:c,type:v_(p),ordinalMeta:n,otherDims:{tooltip:!1,itemName:0},dimsDef:["base"]},{name:h,type:v_(f),dimsDef:v.slice()}];return IT(this,{coordDimensions:m,dimensionsCount:v.length+1,encodeDefaulter:H(Sf,m,this)})},t.prototype.getBaseAxis=function(){var t=this._baseAxisDim;return this.ecModel.getComponent(t+"Axis",this.get(t+"AxisIndex")).axis},t}(),nN=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.defaultValueDimensions=[{name:"min",defaultTooltip:!0},{name:"Q1",defaultTooltip:!0},{name:"median",defaultTooltip:!0},{name:"Q3",defaultTooltip:!0},{name:"max",defaultTooltip:!0}],n.visualDrawType="stroke",n}return n(e,t),e.type="series.boxplot",e.dependencies=["xAxis","yAxis","grid"],e.defaultOption={z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,layout:null,boxWidth:[7,50],itemStyle:{color:tf.color.neutral00,borderWidth:1},emphasis:{scale:!0,itemStyle:{borderWidth:2,shadowBlur:5,shadowOffsetX:1,shadowOffsetY:1,shadowColor:tf.color.shadow}},animationDuration:800},e}(Wy);R(nN,eN,!0);var iN=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData(),r=this.group,o=this._data;this._data||r.removeAll();var a="horizontal"===t.get("layout")?1:0;i.diff(o).add((function(t){if(i.hasValue(t)){var e=aN(i.getItemLayout(t),i,t,a,!0);i.setItemGraphicEl(t,e),r.add(e)}})).update((function(t,e){var n=o.getItemGraphicEl(e);if(i.hasValue(t)){var s=i.getItemLayout(t);n?(ah(n),sN(s,n,i,t)):n=aN(s,i,t,a),r.add(n),i.setItemGraphicEl(t,n)}else r.remove(n)})).remove((function(t){var e=o.getItemGraphicEl(t);e&&r.remove(e)})).execute(),this._data=i},e.prototype.remove=function(t){var e=this.group,n=this._data;this._data=null,n&&n.eachItemGraphicEl((function(t){t&&e.remove(t)}))},e.type="boxplot",e}(tv),rN=function(){},oN=function(t){function e(e){var n=t.call(this,e)||this;return n.type="boxplotBoxPath",n}return n(e,t),e.prototype.getDefaultShape=function(){return new rN},e.prototype.buildPath=function(t,e){var n=e.points,i=0;for(t.moveTo(n[i][0],n[i][1]),i++;i<4;i++)t.lineTo(n[i][0],n[i][1]);for(t.closePath();ig){var _=[v,x];i.push(_)}}}return{boxData:n,outliers:i}}(e.getRawData(),t.config);return[{dimensions:["ItemName","Low","Q1","Q2","Q3","High"],data:i.boxData},{data:i.outliers}]}};var dN=["itemStyle","borderColor"],pN=["itemStyle","borderColor0"],fN=["itemStyle","borderColorDoji"],gN=["itemStyle","color"],yN=["itemStyle","color0"];function vN(t,e){return e.get(t>0?gN:yN)}function mN(t,e){return e.get(0===t?fN:t>0?dN:pN)}var xN={seriesType:"candlestick",plan:$y(),performRawSeries:!0,reset:function(t,e){if(!e.isSeriesFiltered(t))return!t.pipelineContext.large&&{progress:function(t,e){for(var n;null!=(n=t.next());){var i=e.getItemModel(n),r=e.getItemLayout(n).sign,o=i.getItemStyle();o.fill=vN(r,i),o.stroke=mN(r,i)||o.fill,A(e.ensureUniqueItemVisual(n,"style"),o)}}}}},_N=["color","borderColor"],bN=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){this.group.removeClipPath(),this._progressiveEls=null,this._updateDrawMode(t),this._isLargeDraw?this._renderLarge(t):this._renderNormal(t)},e.prototype.incrementalPrepareRender=function(t,e,n){this._clear(),this._updateDrawMode(t)},e.prototype.incrementalRender=function(t,e,n,i){this._progressiveEls=[],this._isLargeDraw?this._incrementalRenderLarge(t,e):this._incrementalRenderNormal(t,e)},e.prototype.eachRendered=function(t){Bh(this._progressiveEls||this.group,t)},e.prototype._updateDrawMode=function(t){var e=t.pipelineContext.large;null!=this._isLargeDraw&&e===this._isLargeDraw||(this._isLargeDraw=e,this._clear())},e.prototype._renderNormal=function(t){var e=t.getData(),n=this._data,i=this.group,r=e.getLayout("isSimpleBox"),o=t.get("clip",!0),a=t.coordinateSystem,s=a.getArea&&a.getArea();this._data||i.removeAll(),e.diff(n).add((function(n){if(e.hasValue(n)){var a=e.getItemLayout(n);if(o&&IN(s,a))return;var l=MN(a,n,!0);eh(l,{shape:{points:a.ends}},t,n),TN(l,e,n,r),i.add(l),e.setItemGraphicEl(n,l)}})).update((function(a,l){var u=n.getItemGraphicEl(l);if(e.hasValue(a)){var c=e.getItemLayout(a);o&&IN(s,c)?i.remove(u):(u?(th(u,{shape:{points:c.ends}},t,a),ah(u)):u=MN(c),TN(u,e,a,r),i.add(u),e.setItemGraphicEl(a,u))}else i.remove(u)})).remove((function(t){var e=n.getItemGraphicEl(t);e&&i.remove(e)})).execute(),this._data=e},e.prototype._renderLarge=function(t){this._clear(),kN(t,this.group);var e=t.get("clip",!0)?wI(t.coordinateSystem,!1,t):null;e?this.group.setClipPath(e):this.group.removeClipPath()},e.prototype._incrementalRenderNormal=function(t,e){for(var n,i=e.getData(),r=i.getLayout("isSimpleBox");null!=(n=t.next());){var o=MN(i.getItemLayout(n));TN(o,i,n,r),o.incremental=!0,this.group.add(o),this._progressiveEls.push(o)}},e.prototype._incrementalRenderLarge=function(t,e){kN(e,this.group,this._progressiveEls,!0)},e.prototype.remove=function(t){this._clear()},e.prototype._clear=function(){this.group.removeAll(),this._data=null},e.type="candlestick",e}(tv),wN=function(){},SN=function(t){function e(e){var n=t.call(this,e)||this;return n.type="normalCandlestickBox",n}return n(e,t),e.prototype.getDefaultShape=function(){return new wN},e.prototype.buildPath=function(t,e){var n=e.points;this.__simpleBox?(t.moveTo(n[4][0],n[4][1]),t.lineTo(n[6][0],n[6][1])):(t.moveTo(n[0][0],n[0][1]),t.lineTo(n[1][0],n[1][1]),t.lineTo(n[2][0],n[2][1]),t.lineTo(n[3][0],n[3][1]),t.closePath(),t.moveTo(n[4][0],n[4][1]),t.lineTo(n[5][0],n[5][1]),t.moveTo(n[6][0],n[6][1]),t.lineTo(n[7][0],n[7][1]))},e}(sl);function MN(t,e,n){var i=t.ends;return new SN({shape:{points:n?CN(i,t):i},z2:100})}function IN(t,e){for(var n=!0,i=0;ip?x[1]:m[1],ends:w,brushRect:T(f,g,h)})}function M(t,n){var i=[];return i[0]=n,i[1]=t,isNaN(n)||isNaN(t)?[NaN,NaN]:e.dataToPoint(i)}function I(t,e,n){var r=e.slice(),o=e.slice();r[0]=bh(r[0]+i/2,1,!1),o[0]=bh(o[0]-i/2,1,!0),n?t.push(r,o):t.push(o,r)}function T(t,e,n){var r=M(t,n),o=M(e,n);return r[0]-=i/2,o[0]-=i/2,{x:r[0],y:r[1],width:i,height:o[1]-r[1]}}function C(t){return t[0]=bh(t[0],1),t}}}}};function NN(t,e,n,i,r,o){return n>i?-1:n0?t.get(r,e-1)<=i?1:-1:1}function zN(t,e){var n=e.rippleEffectColor||e.color;t.eachChild((function(t){t.attr({z:e.z,zlevel:e.zlevel,style:{stroke:"stroke"===e.brushType?n:null,fill:"fill"===e.brushType?n:null}})}))}var EN=function(t){function e(e,n){var i=t.call(this)||this,r=new rI(e,n),o=new to;return i.add(r),i.add(o),i.updateData(e,n),i}return n(e,t),e.prototype.stopEffectAnimation=function(){this.childAt(1).removeAll()},e.prototype.startEffectAnimation=function(t){for(var e=t.symbolType,n=t.color,i=t.rippleNumber,r=this.childAt(1),o=0;o0&&(o=this._getLineLength(i)/l*1e3),o!==this._period||a!==this._loop||s!==this._roundTrip){i.stopAnimation();var c=void 0;c=Y(u)?u(n):u,i.__t>0&&(c=-o*i.__t),this._animateSymbol(i,o,c,a,s)}this._period=o,this._loop=a,this._roundTrip=s}},e.prototype._animateSymbol=function(t,e,n,i,r){if(e>0){t.__t=0;var o=this,a=t.animate("",i).when(r?2*e:e,{__t:r?2:1}).delay(n).during((function(){o._updateSymbolPosition(t)}));i||a.done((function(){o.remove(t)})),a.start()}},e.prototype._getLineLength=function(t){return Vt(t.__p1,t.__cp1)+Vt(t.__cp1,t.__p2)},e.prototype._updateAnimationPoints=function(t,e){t.__p1=e[0],t.__p2=e[1],t.__cp1=e[2]||[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]},e.prototype.updateData=function(t,e,n){this.childAt(0).updateData(t,e,n),this._updateEffectSymbol(t,e)},e.prototype._updateSymbolPosition=function(t){var e=t.__p1,n=t.__p2,i=t.__cp1,r=t.__t<1?t.__t:2-t.__t,o=[t.x,t.y],a=o.slice(),s=Nn,l=zn;o[0]=s(e[0],i[0],n[0],r),o[1]=s(e[1],i[1],n[1],r);var u=t.__t<1?l(e[0],i[0],n[0],r):l(n[0],i[0],e[0],1-r),c=t.__t<1?l(e[1],i[1],n[1],r):l(n[1],i[1],e[1],1-r);t.rotation=-Math.atan2(c,u)-Math.PI/2,"line"!==this._symbolType&&"rect"!==this._symbolType&&"roundRect"!==this._symbolType||(void 0!==t.__lastT&&t.__lastT=0&&!(i[o]<=e);o--);o=Math.min(o,r-2)}else{for(o=a;oe);o++);o=Math.min(o-1,r-2)}var s=(e-i[o])/(i[o+1]-i[o]),l=n[o],u=n[o+1];t.x=l[0]*(1-s)+s*u[0],t.y=l[1]*(1-s)+s*u[1];var c=t.__t<1?u[0]-l[0]:l[0]-u[0],h=t.__t<1?u[1]-l[1]:l[1]-u[1];t.rotation=-Math.atan2(h,c)-Math.PI/2,this._lastFrame=o,this._lastFramePercent=e,t.ignore=!1}},e}(GN),HN=function(){this.polyline=!1,this.curveness=0,this.segs=[]},UN=function(t){function e(e){var n=t.call(this,e)||this;return n._off=0,n.hoverDataIdx=-1,n}return n(e,t),e.prototype.reset=function(){this.notClear=!1,this._off=0},e.prototype.getDefaultStyle=function(){return{stroke:tf.color.neutral99,fill:null}},e.prototype.getDefaultShape=function(){return new HN},e.prototype.buildPath=function(t,e){var n,i=e.segs,r=e.curveness;if(e.polyline)for(n=this._off;n0){t.moveTo(i[n++],i[n++]);for(var a=1;a0){var h=(s+u)/2-(l-c)*r,d=(l+c)/2-(u-s)*r;t.quadraticCurveTo(h,d,u,c)}else t.lineTo(u,c)}this.incremental&&(this._off=n,this.notClear=!0)},e.prototype.findDataIndex=function(t,e){var n=this.shape,i=n.segs,r=n.curveness,o=this.style.lineWidth;if(n.polyline)for(var a=0,s=0;s0)for(var u=i[s++],c=i[s++],h=1;h0){if(Us(u,c,(u+d)/2-(c-p)*r,(c+p)/2-(d-u)*r,d,p,o,t,e))return a}else if(Ws(u,c,d,p,o,t,e))return a;a++}return-1},e.prototype.contain=function(t,e){var n=this.transformCoordToLocal(t,e),i=this.getBoundingRect();return t=n[0],e=n[1],i.contain(t,e)?(this.hoverDataIdx=this.findDataIndex(t,e))>=0:(this.hoverDataIdx=-1,!1)},e.prototype.getBoundingRect=function(){var t=this._rect;if(!t){for(var e=this.shape.segs,n=1/0,i=1/0,r=-1/0,o=-1/0,a=0;a0&&(o.dataIndex=n+t.__startIndex)}))},t.prototype._clear=function(){this._newAdded=[],this.group.removeAll()},t}(),XN={seriesType:"lines",plan:$y(),reset:function(t){var e=t.coordinateSystem;if(e){var n=t.get("polyline"),i=t.pipelineContext.large;return{progress:function(r,o){var a=[];if(i){var s=void 0,l=r.end-r.start;if(n){for(var u=0,c=r.start;c0&&(l||s.configLayer(o,{motionBlur:!0,lastFrameAlpha:Math.max(Math.min(a/10+.9,1),0)})),r.updateData(i);var u=t.get("clip",!0)&&wI(t.coordinateSystem,!1,t);u?this.group.setClipPath(u):this.group.removeClipPath(),this._lastZlevel=o,this._finished=!0},e.prototype.incrementalPrepareRender=function(t,e,n){var i=t.getData();this._updateLineDraw(i,t).incrementalPrepareUpdate(i),this._clearLayer(n),this._finished=!1},e.prototype.incrementalRender=function(t,e,n){this._lineDraw.incrementalUpdate(t,e.getData()),this._finished=t.end===e.getData().count()},e.prototype.eachRendered=function(t){this._lineDraw&&this._lineDraw.eachRendered(t)},e.prototype.updateTransform=function(t,e,n){var i=t.getData(),r=t.pipelineContext;if(!this._finished||r.large||r.progressiveRender)return{update:!0};var o=XN.reset(t,e,n);o.progress&&o.progress({start:0,end:i.count(),count:i.count()},i),this._lineDraw.updateLayout(),this._clearLayer(n)},e.prototype._updateLineDraw=function(t,e){var n=this._lineDraw,i=this._showEffect(e),r=!!e.get("polyline"),o=e.pipelineContext.large;return n&&i===this._hasEffet&&r===this._isPolyline&&o===this._isLargeDraw||(n&&n.remove(),n=this._lineDraw=o?new YN:new IP(r?i?WN:FN:i?GN:MP),this._hasEffet=i,this._isPolyline=r,this._isLargeDraw=o),this.group.add(n.group),n},e.prototype._showEffect=function(t){return!!t.get(["effect","show"])},e.prototype._clearLayer=function(t){var e=t.getZr();"svg"===e.painter.getType()||null==this._lastZlevel||e.painter.getLayer(this._lastZlevel).clear(!0)},e.prototype.remove=function(t,e){this._lineDraw&&this._lineDraw.remove(),this._lineDraw=null,this._clearLayer(e)},e.prototype.dispose=function(t,e){this.remove(t,e)},e.type="lines",e}(tv),jN="undefined"==typeof Uint32Array?Array:Uint32Array,qN="undefined"==typeof Float64Array?Array:Float64Array;function KN(t){var e=t.data;e&&e[0]&&e[0][0]&&e[0][0].coord&&(t.data=E(e,(function(t){var e={coords:[t[0].coord,t[1].coord]};return t[0].name&&(e.fromName=t[0].name),t[1].name&&(e.toName=t[1].name),D([e,t[0],t[1]])})))}var $N=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.visualStyleAccessPath="lineStyle",n.visualDrawType="stroke",n}return n(e,t),e.prototype.init=function(e){e.data=e.data||[],KN(e);var n=this._processFlatCoordsArray(e.data);this._flatCoords=n.flatCoords,this._flatCoordsOffset=n.flatCoordsOffset,n.flatCoords&&(e.data=new Float32Array(n.count)),t.prototype.init.apply(this,arguments)},e.prototype.mergeOption=function(e){if(KN(e),e.data){var n=this._processFlatCoordsArray(e.data);this._flatCoords=n.flatCoords,this._flatCoordsOffset=n.flatCoordsOffset,n.flatCoords&&(e.data=new Float32Array(n.count))}t.prototype.mergeOption.apply(this,arguments)},e.prototype.appendData=function(t){var e=this._processFlatCoordsArray(t.data);e.flatCoords&&(this._flatCoords?(this._flatCoords=vt(this._flatCoords,e.flatCoords),this._flatCoordsOffset=vt(this._flatCoordsOffset,e.flatCoordsOffset)):(this._flatCoords=e.flatCoords,this._flatCoordsOffset=e.flatCoordsOffset),t.data=new Float32Array(e.count)),this.getRawData().appendData(t.data)},e.prototype._getCoordsFromItemModel=function(t){var e=this.getData().getItemModel(t),n=e.option instanceof Array?e.option:e.getShallow("coords");return n},e.prototype.getLineCoordsCount=function(t){return this._flatCoordsOffset?this._flatCoordsOffset[2*t+1]:this._getCoordsFromItemModel(t).length},e.prototype.getLineCoords=function(t,e){if(this._flatCoordsOffset){for(var n=this._flatCoordsOffset[2*t],i=this._flatCoordsOffset[2*t+1],r=0;r ")})},e.prototype.preventIncremental=function(){return!!this.get(["effect","show"])},e.prototype.getProgressive=function(){var t=this.option.progressive;return null==t?this.option.large?1e4:this.get("progressive"):t},e.prototype.getProgressiveThreshold=function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?2e4:this.get("progressiveThreshold"):t},e.prototype.getZLevelKey=function(){var t=this.getModel("effect"),e=t.get("trailLength");return this.getData().count()>this.getProgressiveThreshold()?this.id:t.get("show")&&e>0?e+"":""},e.type="series.lines",e.dependencies=["grid","polar","geo","calendar"],e.defaultOption={coordinateSystem:"geo",z:2,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,symbol:["none","none"],symbolSize:[10,10],geoIndex:0,effect:{show:!1,period:4,constantSpeed:0,symbol:"circle",symbolSize:3,loop:!0,trailLength:.2},large:!1,largeThreshold:2e3,polyline:!1,clip:!0,label:{show:!1,position:"end"},lineStyle:{opacity:.5}},e}(Wy);function JN(t){return t instanceof Array||(t=[t,t]),t}var QN={seriesType:"lines",reset:function(t){var e=JN(t.get("symbol")),n=JN(t.get("symbolSize")),i=t.getData();return i.setVisual("fromSymbol",e&&e[0]),i.setVisual("toSymbol",e&&e[1]),i.setVisual("fromSymbolSize",n&&n[0]),i.setVisual("toSymbolSize",n&&n[1]),{dataEach:i.hasItemOption?function(t,e){var n=t.getItemModel(e),i=JN(n.getShallow("symbol",!0)),r=JN(n.getShallow("symbolSize",!0));i[0]&&t.setItemVisual(e,"fromSymbol",i[0]),i[1]&&t.setItemVisual(e,"toSymbol",i[1]),r[0]&&t.setItemVisual(e,"fromSymbolSize",r[0]),r[1]&&t.setItemVisual(e,"toSymbolSize",r[1])}:null}}};var tz=function(){function t(){this.blurSize=30,this.pointSize=20,this.maxOpacity=1,this.minOpacity=0,this._gradientPixels={inRange:null,outOfRange:null};var t=c.createCanvas();this.canvas=t}return t.prototype.update=function(t,e,n,i,r,o){var a=this._getBrush(),s=this._getGradient(r,"inRange"),l=this._getGradient(r,"outOfRange"),u=this.pointSize+this.blurSize,c=this.canvas,h=c.getContext("2d"),d=t.length;c.width=e,c.height=n;for(var p=0;p0){var I=o(v)?s:l;v>0&&(v=v*S+w),x[_++]=I[M],x[_++]=I[M+1],x[_++]=I[M+2],x[_++]=I[M+3]*v*256}else _+=4}return h.putImageData(m,0,0),c},t.prototype._getBrush=function(){var t=this._brushCanvas||(this._brushCanvas=c.createCanvas()),e=this.pointSize+this.blurSize,n=2*e;t.width=n,t.height=n;var i=t.getContext("2d");return i.clearRect(0,0,n,n),i.shadowOffsetX=n,i.shadowBlur=this.blurSize,i.shadowColor=tf.color.neutral99,i.beginPath(),i.arc(-e,e,this.pointSize,0,2*Math.PI,!0),i.closePath(),i.fill(),t},t.prototype._getGradient=function(t,e){for(var n=this._gradientPixels,i=n[e]||(n[e]=new Uint8ClampedArray(1024)),r=[0,0,0,0],o=0,a=0;a<256;a++)t[e](a/255,!0,r),i[o++]=r[0],i[o++]=r[1],i[o++]=r[2],i[o++]=r[3];return i},t}();function ez(t){var e=t.dimensions;return"lng"===e[0]&&"lat"===e[1]}var nz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i;e.eachComponent("visualMap",(function(e){e.eachTargetSeries((function(n){n===t&&(i=e)}))})),this._progressiveEls=null,this.group.removeAll();var r=t.coordinateSystem;"cartesian2d"===r.type||"calendar"===r.type||"matrix"===r.type?this._renderOnGridLike(t,n,0,t.getData().count()):ez(r)&&this._renderOnGeo(r,t,i,n)},e.prototype.incrementalPrepareRender=function(t,e,n){this.group.removeAll()},e.prototype.incrementalRender=function(t,e,n,i){var r=e.coordinateSystem;r&&(ez(r)?this.render(e,n,i):(this._progressiveEls=[],this._renderOnGridLike(e,i,t.start,t.end,!0)))},e.prototype.eachRendered=function(t){Bh(this._progressiveEls||this.group,t)},e.prototype._renderOnGridLike=function(t,e,n,i,r){var o,a,s,l,u=t.coordinateSystem,c=SI(u,"cartesian2d"),h=SI(u,"matrix");if(c){var d=u.getAxis("x"),p=u.getAxis("y");0,o=d.getBandWidth()+.5,a=p.getBandWidth()+.5,s=d.scale.getExtent(),l=p.scale.getExtent()}for(var f=this.group,g=t.getData(),y=t.getModel(["emphasis","itemStyle"]).getItemStyle(),v=t.getModel(["blur","itemStyle"]).getItemStyle(),m=t.getModel(["select","itemStyle"]).getItemStyle(),x=t.get(["itemStyle","borderRadius"]),_=Jh(t),b=t.getModel("emphasis"),w=b.get("focus"),S=b.get("blurScope"),M=b.get("disabled"),I=c||h?[g.mapDimension("x"),g.mapDimension("y"),g.mapDimension("value")]:[g.mapDimension("time"),g.mapDimension("value")],T=n;Ts[1]||kl[1])continue;var L=u.dataToPoint([A,k]);C=new xl({shape:{x:L[0]-o/2,y:L[1]-a/2,width:o,height:a},style:D})}else if(h){if(nt((P=u.dataToLayout([g.get(I[0],T),g.get(I[1],T)]).rect).x))continue;C=new xl({z2:1,shape:P,style:D})}else{if(isNaN(g.get(I[1],T)))continue;var P,O=u.dataToLayout([g.get(I[0],T)]);if(nt((P=O.contentRect||O.rect).x)||nt(P.y))continue;C=new xl({z2:1,shape:P,style:D})}if(g.hasItemOption){var R=g.getItemModel(T),N=R.getModel("emphasis");y=N.getModel("itemStyle").getItemStyle(),v=R.getModel(["blur","itemStyle"]).getItemStyle(),m=R.getModel(["select","itemStyle"]).getItemStyle(),x=R.get(["itemStyle","borderRadius"]),w=N.get("focus"),S=N.get("blurScope"),M=N.get("disabled"),_=Jh(R)}C.shape.r=x;var z=t.getRawValue(T),E="-";z&&null!=z[2]&&(E=z[2]+""),$h(C,_,{labelFetcher:t,labelDataIndex:T,defaultOpacity:D.opacity,defaultText:E}),C.ensureState("emphasis").style=y,C.ensureState("blur").style=v,C.ensureState("select").style=m,Tu(C,w,S,M),C.incremental=r,r&&(C.states.emphasis.hoverLayer=!0),f.add(C),g.setItemGraphicEl(T,C),this._progressiveEls&&this._progressiveEls.push(C)}},e.prototype._renderOnGeo=function(t,e,n,i){var r=n.targetVisuals.inRange,o=n.targetVisuals.outOfRange,a=e.getData(),s=this._hmLayer||this._hmLayer||new tz;s.blurSize=e.get("blurSize"),s.pointSize=e.get("pointSize"),s.minOpacity=e.get("minOpacity"),s.maxOpacity=e.get("maxOpacity");var l=t.getViewRect().clone(),u=t.getRoamTransform();l.applyTransform(u);var c=Math.max(l.x,0),h=Math.max(l.y,0),d=Math.min(l.width+l.x,i.getWidth()),p=Math.min(l.height+l.y,i.getHeight()),f=d-c,g=p-h,y=[a.mapDimension("lng"),a.mapDimension("lat"),a.mapDimension("value")],v=a.mapArray(y,(function(e,n,i){var r=t.dataToPoint([e,n]);return r[0]-=c,r[1]-=h,r.push(i),r})),m=n.getExtent(),x="visualMap.continuous"===n.type?function(t,e){var n=t[1]-t[0];return e=[(e[0]-t[0])/n,(e[1]-t[0])/n],function(t){return t>=e[0]&&t<=e[1]}}(m,n.option.range):function(t,e,n){var i=t[1]-t[0],r=(e=E(e,(function(e){return{interval:[(e.interval[0]-t[0])/i,(e.interval[1]-t[0])/i]}}))).length,o=0;return function(t){var i;for(i=o;i=0;i--){var a;if((a=e[i].interval)[0]<=t&&t<=a[1]){o=i;break}}return i>=0&&i=0?1:-1:o>0?1:-1}(n,o,r,i,h),function(t,e,n,i,r,o,a,s,l,u){var c,h=l.valueDim,d=l.categoryDim,p=Math.abs(n[d.wh]),f=t.getItemVisual(e,"symbolSize");c=U(f)?f.slice():null==f?["100%","100%"]:[f,f];c[d.index]=yo(c[d.index],p),c[h.index]=yo(c[h.index],i?p:Math.abs(o)),u.symbolSize=c;var g=u.symbolScale=[c[0]/s,c[1]/s];g[h.index]*=(l.isHorizontal?-1:1)*a}(t,e,r,o,0,h.boundingLength,h.pxSign,u,i,h),function(t,e,n,i,r){var o=t.get(rz)||0;o&&(az.attr({scaleX:e[0],scaleY:e[1],rotation:n}),az.updateTransform(),o/=az.getLineScale(),o*=e[i.valueDim.index]);r.valueLineWidth=o||0}(n,h.symbolScale,l,i,h);var d=h.symbolSize,p=pm(n.get("symbolOffset"),d);return function(t,e,n,i,r,o,a,s,l,u,c,h){var d=c.categoryDim,p=c.valueDim,f=h.pxSign,g=Math.max(e[p.index]+s,0),y=g;if(i){var v=Math.abs(l),m=it(t.get("symbolMargin"),"15%")+"",x=!1;m.lastIndexOf("!")===m.length-1&&(x=!0,m=m.slice(0,m.length-1));var _=yo(m,e[p.index]),b=Math.max(g+2*_,0),w=x?0:2*_,S=zo(i),M=S?i:Mz((v+w)/b);b=g+2*(_=(v-M*g)/2/(x?M:Math.max(M-1,1))),w=x?0:2*_,S||"fixed"===i||(M=u?Mz((Math.abs(u)+w)/b):0),y=M*b-w,h.repeatTimes=M,h.symbolMargin=_}var I=f*(y/2),T=h.pathPosition=[];T[d.index]=n[d.wh]/2,T[p.index]="start"===a?I:"end"===a?l-I:l/2,o&&(T[0]+=o[0],T[1]+=o[1]);var C=h.bundlePosition=[];C[d.index]=n[d.xy],C[p.index]=n[p.xy];var D=h.barRectShape=A({},n);D[p.wh]=f*Math.max(Math.abs(n[p.wh]),Math.abs(T[p.index]+I)),D[d.wh]=n[d.wh];var k=h.clipShape={};k[d.xy]=-n[d.xy],k[d.wh]=c.ecSize[d.wh],k[p.xy]=0,k[p.wh]=n[p.wh]}(n,d,r,o,0,p,s,h.valueLineWidth,h.boundingLength,h.repeatCutLength,i,h),h}function uz(t,e){return t.toGlobalCoord(t.dataToCoord(t.scale.parse(e)))}function cz(t){var e=t.symbolPatternSize,n=hm(t.symbolType,-e/2,-e/2,e,e);return n.attr({culling:!0}),"image"!==n.type&&n.setStyle({strokeNoScale:!0}),n}function hz(t,e,n,i){var r=t.__pictorialBundle,o=n.symbolSize,a=n.valueLineWidth,s=n.pathPosition,l=e.valueDim,u=n.repeatTimes||0,c=0,h=o[e.valueDim.index]+a+2*n.symbolMargin;for(bz(t,(function(t){t.__pictorialAnimationIndex=c,t.__pictorialRepeatTimes=u,c0:i<0)&&(r=u-1-t),e[l.index]=h*(r-u/2+.5)+s[l.index],{x:e[0],y:e[1],scaleX:n.symbolScale[0],scaleY:n.symbolScale[1],rotation:n.rotation}}}function dz(t,e,n,i){var r=t.__pictorialBundle,o=t.__pictorialMainPath;o?wz(o,null,{x:n.pathPosition[0],y:n.pathPosition[1],scaleX:n.symbolScale[0],scaleY:n.symbolScale[1],rotation:n.rotation},n,i):(o=t.__pictorialMainPath=cz(n),r.add(o),wz(o,{x:n.pathPosition[0],y:n.pathPosition[1],scaleX:0,scaleY:0,rotation:n.rotation},{scaleX:n.symbolScale[0],scaleY:n.symbolScale[1]},n,i))}function pz(t,e,n){var i=A({},e.barRectShape),r=t.__pictorialBarRect;r?wz(r,null,{shape:i},e,n):((r=t.__pictorialBarRect=new xl({z2:2,shape:i,silent:!0,style:{stroke:"transparent",fill:"transparent",lineWidth:0}})).disableMorphing=!0,t.add(r))}function fz(t,e,n,i){if(n.symbolClip){var r=t.__pictorialClipPath,o=A({},n.clipShape),a=e.valueDim,s=n.animationModel,l=n.dataIndex;if(r)th(r,{shape:o},s,l);else{o[a.wh]=0,r=new xl({shape:o}),t.__pictorialBundle.setClipPath(r),t.__pictorialClipPath=r;var u={};u[a.wh]=n.clipShape[a.wh],Zh[i?"updateProps":"initProps"](r,{shape:u},s,l)}}}function gz(t,e){var n=t.getItemModel(e);return n.getAnimationDelayParams=yz,n.isAnimationEnabled=vz,n}function yz(t){return{index:t.__pictorialAnimationIndex,count:t.__pictorialRepeatTimes}}function vz(){return this.parentModel.isAnimationEnabled()&&!!this.getShallow("animation")}function mz(t,e,n,i){var r=new to,o=new to;return r.add(o),r.__pictorialBundle=o,o.x=n.bundlePosition[0],o.y=n.bundlePosition[1],n.symbolRepeat?hz(r,e,n):dz(r,0,n),pz(r,n,i),fz(r,e,n,i),r.__pictorialShapeStr=_z(t,n),r.__pictorialSymbolMeta=n,r}function xz(t,e,n,i){var r=i.__pictorialBarRect;r&&r.removeTextContent();var o=[];bz(i,(function(t){o.push(t)})),i.__pictorialMainPath&&o.push(i.__pictorialMainPath),i.__pictorialClipPath&&(n=null),z(o,(function(t){ih(t,{scaleX:0,scaleY:0},n,e,(function(){i.parent&&i.parent.remove(i)}))})),t.setItemGraphicEl(e,null)}function _z(t,e){return[t.getItemVisual(e.dataIndex,"symbol")||"none",!!e.symbolRepeat,!!e.symbolClip].join(":")}function bz(t,e,n){z(t.__pictorialBundle.children(),(function(i){i!==t.__pictorialBarRect&&e.call(n,i)}))}function wz(t,e,n,i,r,o){e&&t.attr(e),i.symbolClip&&!r?n&&t.attr(n):n&&Zh[r?"updateProps":"initProps"](t,n,i.animationModel,i.dataIndex,o)}function Sz(t,e,n){var i=n.dataIndex,r=n.itemModel,o=r.getModel("emphasis"),a=o.getModel("itemStyle").getItemStyle(),s=r.getModel(["blur","itemStyle"]).getItemStyle(),l=r.getModel(["select","itemStyle"]).getItemStyle(),u=r.getShallow("cursor"),c=o.get("focus"),h=o.get("blurScope"),d=o.get("scale");bz(t,(function(t){if(t instanceof dl){var e=t.style;t.useStyle(A({image:e.image,x:e.x,y:e.y,width:e.width,height:e.height},n.style))}else t.useStyle(n.style);var i=t.ensureState("emphasis");i.style=a,d&&(i.scaleX=1.1*t.scaleX,i.scaleY=1.1*t.scaleY),t.ensureState("blur").style=s,t.ensureState("select").style=l,u&&(t.cursor=u),t.z2=n.z2}));var p=e.valueDim.posDesc[+(n.boundingLength>0)],f=t.__pictorialBarRect;f.ignoreClip=!0,$h(f,Jh(r),{labelFetcher:e.seriesModel,labelDataIndex:i,defaultText:nI(e.seriesModel.getData(),i),inheritColor:n.style.fill,defaultOpacity:n.style.opacity,defaultOutsidePosition:p}),Tu(t,c,h,o.get("disabled"))}function Mz(t){var e=Math.round(t);return Math.abs(t-e)<1e-4?e:Math.ceil(t)}var Iz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.hasSymbolVisual=!0,n.defaultSymbol="roundRect",n}return n(e,t),e.prototype.getInitialData=function(e){return e.stack=null,t.prototype.getInitialData.apply(this,arguments)},e.type="series.pictorialBar",e.dependencies=["grid"],e.defaultOption=Id(VI.defaultOption,{symbol:"circle",symbolSize:null,symbolRotate:null,symbolPosition:null,symbolOffset:null,symbolMargin:null,symbolRepeat:!1,symbolRepeatDirection:"end",symbolClip:!1,symbolBoundingData:null,symbolPatternSize:400,barGap:"-100%",clip:!1,progressive:0,emphasis:{scale:!1},select:{itemStyle:{borderColor:tf.color.primary}}}),e}(VI);var Tz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._layers=[],n}return n(e,t),e.prototype.render=function(t,e,n){var i=t.getData(),r=this,o=this.group,a=t.getLayerSeries(),s=i.getLayout("layoutInfo"),l=s.rect,u=s.boundaryGap;function c(t){return t.name}o.x=0,o.y=l.y+u[0];var h=new f_(this._layersSeries||[],a,c,c),d=[];function p(e,n,s){var l=r._layers;if("remove"!==e){for(var u,c,h=[],p=[],f=a[n].indices,g=0;go&&(o=s),i.push(s)}for(var u=0;uo&&(o=h)}return{y0:r,max:o}}(l),c=u.y0,h=n/u.max,d=o.length,p=o[0].indices.length,f=0;fI&&!Co(C-I)&&C0?(r.virtualPiece?r.virtualPiece.updateData(!1,i,t,e,n):(r.virtualPiece=new kz(i,t,e,n),l.add(r.virtualPiece)),o.piece.off("click"),r.virtualPiece.on("click",(function(t){r._rootToNode(o.parentNode)}))):r.virtualPiece&&(l.remove(r.virtualPiece),r.virtualPiece=null)}(a,s),this._initEvents(),this._oldChildren=c},e.prototype._initEvents=function(){var t=this;this.group.off("click"),this.group.on("click",(function(e){var n=!1;t.seriesModel.getViewRoot().eachNode((function(i){if(!n&&i.piece&&i.piece===e.target){var r=i.getModel().get("nodeClick");if("rootToNode"===r)t._rootToNode(i);else if("link"===r){var o=i.getModel(),a=o.get("link");if(a)Sp(a,o.get("target",!0)||"_blank")}n=!0}}))}))},e.prototype._rootToNode=function(t){t!==this.seriesModel.getViewRoot()&&this.api.dispatchAction({type:Lz,from:this.uid,seriesId:this.seriesModel.id,targetNode:t})},e.prototype.containPoint=function(t,e){var n=e.getData().getItemLayout(0);if(n){var i=t[0]-n.cx,r=t[1]-n.cy,o=Math.sqrt(i*i+r*r);return o<=n.r&&o>=n.r0}},e.type="sunburst",e}(tv),Rz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.ignoreStyleOnData=!0,n}return n(e,t),e.prototype.getInitialData=function(t,e){var n={name:t.name,children:t.data};Nz(n);var i=this._levelModels=E(t.levels||[],(function(t){return new wd(t,this,e)}),this),r=Ek.createTree(n,this,(function(t){t.wrapMethod("getItemModel",(function(t,e){var n=r.getNodeByDataIndex(e),o=i[n.depth];return o&&(t.parentModel=o),t}))}));return r.data},e.prototype.optionUpdated=function(){this.resetViewRoot()},e.prototype.getDataParams=function(e){var n=t.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(e);return n.treePathInfo=Fk(i,this),n},e.prototype.getLevelModel=function(t){return this._levelModels&&this._levelModels[t.depth]},e.prototype.getViewRoot=function(){return this._viewRoot},e.prototype.resetViewRoot=function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)},e.prototype.enableAriaDecal=function(){Zk(this)},e.type="series.sunburst",e.defaultOption={z:2,center:["50%","50%"],radius:[0,"75%"],clockwise:!0,startAngle:90,minAngle:0,stillShowZeroSum:!0,nodeClick:"rootToNode",renderLabelForZeroData:!1,label:{rotate:"radial",show:!0,opacity:1,align:"center",position:"inside",distance:5,silent:!0},itemStyle:{borderWidth:1,borderColor:"white",borderType:"solid",shadowBlur:0,shadowColor:"rgba(0, 0, 0, 0.2)",shadowOffsetX:0,shadowOffsetY:0,opacity:1},emphasis:{focus:"descendant"},blur:{itemStyle:{opacity:.2},label:{opacity:.1}},animationType:"expansion",animationDuration:1e3,animationDurationUpdate:500,data:[],sort:"desc"},e}(Wy);function Nz(t){var e=0;z(t.children,(function(t){Nz(t);var n=t.value;U(n)&&(n=n[0]),e+=n}));var n=t.value;U(n)&&(n=n[0]),(null==n||isNaN(n))&&(n=e),n<0&&(n=0),U(t.value)?t.value[0]=n:t.value=n}var zz=Math.PI/180;function Ez(t,e,n){e.eachSeriesByType(t,(function(t){var e=t.get("center"),i=t.get("radius");U(i)||(i=[0,i]),U(e)||(e=[e,e]);var r=n.getWidth(),o=n.getHeight(),a=Math.min(r,o),s=yo(e[0],r),l=yo(e[1],o),u=yo(i[0],a/2),c=yo(i[1],a/2),h=-t.get("startAngle")*zz,d=t.get("minAngle")*zz,p=t.getData().tree.root,f=t.getViewRoot(),g=f.depth,y=t.get("sort");null!=y&&Bz(f,y);var v=0;z(f.children,(function(t){!isNaN(t.getValue())&&v++}));var m=f.getValue(),x=Math.PI/(m||v)*2,_=f.depth>0,b=f.height-(_?-1:1),w=(c-u)/(b||1),S=t.get("clockwise"),M=t.get("stillShowZeroSum"),I=S?1:-1,T=function(e,n){if(e){var i=n;if(e!==p){var r=e.getValue(),o=0===m&&M?x:r*x;o1;)r=r.parentNode;var o=n.getColorFromPalette(r.name||r.dataIndex+"",e);return t.depth>1&&X(o)&&(o=si(o,(t.depth-1)/(i-1)*.5)),o}(r,t,i.root.height)),A(n.ensureUniqueItemVisual(r.dataIndex,"style"),o)}))}))}var Gz={color:"fill",borderColor:"stroke"},Fz={symbol:1,symbolSize:1,symbolKeepAspect:1,legendIcon:1,visualMeta:1,liftZ:1,decal:1},Wz=sa(),Hz=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.optionUpdated=function(){this.currentZLevel=this.get("zlevel",!0),this.currentZ=this.get("z",!0)},e.prototype.getInitialData=function(t,e){return Z_(null,this)},e.prototype.getDataParams=function(e,n,i){var r=t.prototype.getDataParams.call(this,e,n);return i&&(r.info=Wz(i).info),r},e.type="series.custom",e.dependencies=["grid","polar","geo","singleAxis","calendar","matrix"],e.defaultOption={coordinateSystem:"cartesian2d",z:2,legendHoverLink:!0,clip:!1},e}(Wy);function Uz(t,e){return e=e||[0,0],E(["x","y"],(function(n,i){var r=this.getAxis(n),o=e[i],a=t[i]/2;return"category"===r.type?r.getBandWidth():Math.abs(r.dataToCoord(o-a)-r.dataToCoord(o+a))}),this)}function Yz(t,e){return e=e||[0,0],E([0,1],(function(n){var i=e[n],r=t[n]/2,o=[],a=[];return o[n]=i-r,a[n]=i+r,o[1-n]=a[1-n]=e[1-n],Math.abs(this.dataToPoint(o)[n]-this.dataToPoint(a)[n])}),this)}function Xz(t,e){var n=this.getAxis(),i=e instanceof Array?e[0]:e,r=(t instanceof Array?t[0]:t)/2;return"category"===n.type?n.getBandWidth():Math.abs(n.dataToCoord(i-r)-n.dataToCoord(i+r))}function Zz(t,e){return e=e||[0,0],E(["Radius","Angle"],(function(n,i){var r=this["get"+n+"Axis"](),o=e[i],a=t[i]/2,s="category"===r.type?r.getBandWidth():Math.abs(r.dataToCoord(o-a)-r.dataToCoord(o+a));return"Angle"===n&&(s=s*Math.PI/180),s}),this)}function jz(t,e,n,i){return t&&(t.legacy||!1!==t.legacy&&!n&&!i&&"tspan"!==e&&("text"===e||_t(t,"text")))}function qz(t,e,n){var i,r,o,a=t;if("text"===e)o=a;else{o={},_t(a,"text")&&(o.text=a.text),_t(a,"rich")&&(o.rich=a.rich),_t(a,"textFill")&&(o.fill=a.textFill),_t(a,"textStroke")&&(o.stroke=a.textStroke),_t(a,"fontFamily")&&(o.fontFamily=a.fontFamily),_t(a,"fontSize")&&(o.fontSize=a.fontSize),_t(a,"fontStyle")&&(o.fontStyle=a.fontStyle),_t(a,"fontWeight")&&(o.fontWeight=a.fontWeight),r={type:"text",style:o,silent:!0},i={};var s=_t(a,"textPosition");n?i.position=s?a.textPosition:"inside":s&&(i.position=a.textPosition),_t(a,"textPosition")&&(i.position=a.textPosition),_t(a,"textOffset")&&(i.offset=a.textOffset),_t(a,"textRotation")&&(i.rotation=a.textRotation),_t(a,"textDistance")&&(i.distance=a.textDistance)}return Kz(o,t),z(o.rich,(function(t){Kz(t,t)})),{textConfig:i,textContent:r}}function Kz(t,e){e&&(e.font=e.textFont||e.font,_t(e,"textStrokeWidth")&&(t.lineWidth=e.textStrokeWidth),_t(e,"textAlign")&&(t.align=e.textAlign),_t(e,"textVerticalAlign")&&(t.verticalAlign=e.textVerticalAlign),_t(e,"textLineHeight")&&(t.lineHeight=e.textLineHeight),_t(e,"textWidth")&&(t.width=e.textWidth),_t(e,"textHeight")&&(t.height=e.textHeight),_t(e,"textBackgroundColor")&&(t.backgroundColor=e.textBackgroundColor),_t(e,"textPadding")&&(t.padding=e.textPadding),_t(e,"textBorderColor")&&(t.borderColor=e.textBorderColor),_t(e,"textBorderWidth")&&(t.borderWidth=e.textBorderWidth),_t(e,"textBorderRadius")&&(t.borderRadius=e.textBorderRadius),_t(e,"textBoxShadowColor")&&(t.shadowColor=e.textBoxShadowColor),_t(e,"textBoxShadowBlur")&&(t.shadowBlur=e.textBoxShadowBlur),_t(e,"textBoxShadowOffsetX")&&(t.shadowOffsetX=e.textBoxShadowOffsetX),_t(e,"textBoxShadowOffsetY")&&(t.shadowOffsetY=e.textBoxShadowOffsetY))}function $z(t,e,n){var i=t;i.textPosition=i.textPosition||n.position||"inside",null!=n.offset&&(i.textOffset=n.offset),null!=n.rotation&&(i.textRotation=n.rotation),null!=n.distance&&(i.textDistance=n.distance);var r=i.textPosition.indexOf("inside")>=0,o=t.fill||tf.color.neutral99;Jz(i,e);var a=null==i.textFill;return r?a&&(i.textFill=n.insideFill||tf.color.neutral00,!i.textStroke&&n.insideStroke&&(i.textStroke=n.insideStroke),!i.textStroke&&(i.textStroke=o),null==i.textStrokeWidth&&(i.textStrokeWidth=2)):(a&&(i.textFill=t.fill||n.outsideFill||tf.color.neutral00),!i.textStroke&&n.outsideStroke&&(i.textStroke=n.outsideStroke)),i.text=e.text,i.rich=e.rich,z(e.rich,(function(t){Jz(t,t)})),i}function Jz(t,e){e&&(_t(e,"fill")&&(t.textFill=e.fill),_t(e,"stroke")&&(t.textStroke=e.fill),_t(e,"lineWidth")&&(t.textStrokeWidth=e.lineWidth),_t(e,"font")&&(t.font=e.font),_t(e,"fontStyle")&&(t.fontStyle=e.fontStyle),_t(e,"fontWeight")&&(t.fontWeight=e.fontWeight),_t(e,"fontSize")&&(t.fontSize=e.fontSize),_t(e,"fontFamily")&&(t.fontFamily=e.fontFamily),_t(e,"align")&&(t.textAlign=e.align),_t(e,"verticalAlign")&&(t.textVerticalAlign=e.verticalAlign),_t(e,"lineHeight")&&(t.textLineHeight=e.lineHeight),_t(e,"width")&&(t.textWidth=e.width),_t(e,"height")&&(t.textHeight=e.height),_t(e,"backgroundColor")&&(t.textBackgroundColor=e.backgroundColor),_t(e,"padding")&&(t.textPadding=e.padding),_t(e,"borderColor")&&(t.textBorderColor=e.borderColor),_t(e,"borderWidth")&&(t.textBorderWidth=e.borderWidth),_t(e,"borderRadius")&&(t.textBorderRadius=e.borderRadius),_t(e,"shadowColor")&&(t.textBoxShadowColor=e.shadowColor),_t(e,"shadowBlur")&&(t.textBoxShadowBlur=e.shadowBlur),_t(e,"shadowOffsetX")&&(t.textBoxShadowOffsetX=e.shadowOffsetX),_t(e,"shadowOffsetY")&&(t.textBoxShadowOffsetY=e.shadowOffsetY),_t(e,"textShadowColor")&&(t.textShadowColor=e.textShadowColor),_t(e,"textShadowBlur")&&(t.textShadowBlur=e.textShadowBlur),_t(e,"textShadowOffsetX")&&(t.textShadowOffsetX=e.textShadowOffsetX),_t(e,"textShadowOffsetY")&&(t.textShadowOffsetY=e.textShadowOffsetY))}var Qz={position:["x","y"],scale:["scaleX","scaleY"],origin:["originX","originY"]},tE=F(Qz),eE=(B(Ar,(function(t,e){return t[e]=1,t}),{}),Ar.join(", "),["","style","shape","extra"]),nE=sa();function iE(t,e,n,i,r){var o=t+"Animation",a=Jc(t,i,r)||{},s=nE(e).userDuring;return a.duration>0&&(a.during=s?W(cE,{el:e,userDuring:s}):null,a.setToFinal=!0,a.scope=t),A(a,n[o]),a}function rE(t,e,n,i){var r=(i=i||{}).dataIndex,o=i.isInit,a=i.clearStyle,s=n.isAnimationEnabled(),l=nE(t),u=e.style;l.userDuring=e.during;var c={},h={};if(function(t,e,n){for(var i=0;i=0)){var h=t.getAnimationStyleProps(),d=h?h.style:null;if(d){!r&&(r=i.style={});var p=F(n);for(u=0;u0&&t.animateFrom(g,y)}else!function(t,e,n,i,r){if(r){var o=iE("update",t,e,i,n);o.duration>0&&t.animateFrom(r,o)}}(t,e,r||0,n,c);oE(t,e),u?t.dirty():t.markRedraw()}function oE(t,e){for(var n=nE(t).leaveToProps,i=0;i=0){!o&&(o=i[t]={});var d=F(a);for(c=0;ci[1]&&i.reverse(),{coordSys:{type:"polar",cx:t.cx,cy:t.cy,r:i[1],r0:i[0]},api:{coord:function(i){var r=e.dataToRadius(i[0]),o=n.dataToAngle(i[1]),a=t.coordToPoint([r,o]);return a.push(r,o*Math.PI/180),a},size:W(Zz,t)}}},calendar:function(t){var e=t.getRect(),n=t.getRangeInfo();return{coordSys:{type:"calendar",x:e.x,y:e.y,width:e.width,height:e.height,cellWidth:t.getCellWidth(),cellHeight:t.getCellHeight(),rangeInfo:{start:n.start,end:n.end,weeks:n.weeks,dayCount:n.allDay}},api:{coord:function(e,n){return t.dataToPoint(e,n)},layout:function(e,n){return t.dataToLayout(e,n)}}}},matrix:function(t){var e=t.getRect();return{coordSys:{type:"matrix",x:e.x,y:e.y,width:e.width,height:e.height},api:{coord:function(e,n){return t.dataToPoint(e,n)},layout:function(e,n){return t.dataToLayout(e,n)}}}}};function DE(t){return t instanceof sl}function AE(t){return t instanceof os}var kE=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n,i){this._progressiveEls=null;var r=this._data,o=t.getData(),a=this.group,s=NE(t,o,e,n);r||a.removeAll(),o.diff(r).add((function(e){EE(n,null,e,s(e,i),t,a,o)})).remove((function(e){var n=r.getItemGraphicEl(e);n&&aE(n,Wz(n).option,t)})).update((function(e,l){var u=r.getItemGraphicEl(l);EE(n,u,e,s(e,i),t,a,o)})).execute();var l=t.get("clip",!0)?wI(t.coordinateSystem,!1,t):null;l?a.setClipPath(l):a.removeClipPath(),this._data=o},e.prototype.incrementalPrepareRender=function(t,e,n){this.group.removeAll(),this._data=null},e.prototype.incrementalRender=function(t,e,n,i,r){var o=e.getData(),a=NE(e,o,n,i),s=this._progressiveEls=[];function l(t){t.isGroup||(t.incremental=!0,t.ensureState("emphasis").hoverLayer=!0)}for(var u=t.start;u=0?e.getStore().get(r,n):void 0}var o=e.get(i.name,n),a=i&&i.ordinalMeta;return a?a.categories[o]:o},styleEmphasis:function(n,i){0;null==i&&(i=l);var r=x(i,mE).getItemStyle(),o=_(i,mE),a=Qh(o,null,null,!0,!0);a.text=o.getShallow("show")?ot(t.getFormattedLabel(i,mE),t.getFormattedLabel(i,xE),nI(e,i)):null;var s=td(o,null,!0);return w(n,r),r=$z(r,a,s),n&&b(r,n),r.legacy=!0,r},visual:function(t,n){if(null==n&&(n=l),_t(Gz,t)){var i=e.getItemVisual(n,"style");return i?i[Gz[t]]:null}if(_t(Fz,t))return e.getItemVisual(n,t)},barLayout:function(t){if("cartesian2d"===a.type){return function(t){var e=[],n=t.axis,i="axis0";if("category"===n.type){for(var r=n.getBandWidth(),o=0;o=h;f--){var g=e.childAt(f);HE(e,g,r)}}(t,h,n,i,r),a>=0?o.replaceAt(h,a):o.add(h),h}function VE(t,e,n){var i,r=Wz(t),o=e.type,a=e.shape,s=e.style;return n.isUniversalTransitionEnabled()||null!=o&&o!==r.customGraphicType||"path"===o&&((i=a)&&(_t(i,"pathData")||_t(i,"d")))&&ZE(a)!==r.customPathData||"image"===o&&_t(s,"image")&&s.image!==r.customImagePath}function GE(t,e,n){var i=e?FE(t,e):t,r=e?WE(t,i,mE):t.style,o=t.type,a=i?i.textConfig:null,s=t.textContent,l=s?e?FE(s,e):s:null;if(r&&(n.isLegacy||jz(r,o,!!a,!!l))){n.isLegacy=!0;var u=qz(r,o,!e);!a&&u.textConfig&&(a=u.textConfig),!l&&u.textContent&&(l=u.textContent)}if(!e&&l){var c=l;!c.type&&(c.type="text")}var h=e?n[e]:n.normal;h.cfg=a,h.conOpt=l}function FE(t,e){return e?t?t[e]:null:t}function WE(t,e,n){var i=e&&e.style;return null==i&&n===mE&&t&&(i=t.styleEmphasis),i}function HE(t,e,n){e&&aE(e,Wz(t).option,n)}function UE(t,e){var n=t&&t.name;return null!=n?n:"e\0\0"+e}function YE(t,e){var n=this.context,i=null!=t?n.newChildren[t]:null,r=null!=e?n.oldChildren[e]:null;BE(n.api,r,n.dataIndex,i,n.seriesModel,n.group)}function XE(t){var e=this.context,n=e.oldChildren[t];n&&aE(n,Wz(n).option,e.seriesModel)}function ZE(t){return t&&(t.pathData||t.d)}var jE=sa(),qE=T,KE=W,$E=function(){function t(){this._dragging=!1,this.animationThreshold=15}return t.prototype.render=function(t,e,n,i){var r=e.get("value"),o=e.get("status");if(this._axisModel=t,this._axisPointerModel=e,this._api=n,i||this._lastValue!==r||this._lastStatus!==o){this._lastValue=r,this._lastStatus=o;var a=this._group,s=this._handle;if(!o||"hide"===o)return a&&a.hide(),void(s&&s.hide());a&&a.show(),s&&s.show();var l={};this.makeElOption(l,r,t,e,n);var u=l.graphicKey;u!==this._lastGraphicKey&&this.clear(n),this._lastGraphicKey=u;var c=this._moveAnimation=this.determineAnimation(t,e);if(a){var h=H(JE,e,c);this.updatePointerEl(a,l,h),this.updateLabelEl(a,l,h,e)}else a=this._group=new to,this.createPointerEl(a,l,t,e),this.createLabelEl(a,l,t,e),n.getZr().add(a);nB(a,e,!0),this._renderHandle(r)}},t.prototype.remove=function(t){this.clear(t)},t.prototype.dispose=function(t){this.clear(t)},t.prototype.determineAnimation=function(t,e){var n=e.get("animation"),i=t.axis,r="category"===i.type,o=e.get("snap");if(!o&&!r)return!1;if("auto"===n||null==n){var a=this.animationThreshold;if(r&&i.getBandWidth()>a)return!0;if(o){var s=ZC(t).seriesDataCount,l=i.getExtent();return Math.abs(l[0]-l[1])/s>a}return!1}return!0===n},t.prototype.makeElOption=function(t,e,n,i,r){},t.prototype.createPointerEl=function(t,e,n,i){var r=e.pointer;if(r){var o=jE(t).pointerEl=new Zh[r.type](qE(e.pointer));t.add(o)}},t.prototype.createLabelEl=function(t,e,n,i){if(e.label){var r=jE(t).labelEl=new Sl(qE(e.label));t.add(r),tB(r,i)}},t.prototype.updatePointerEl=function(t,e,n){var i=jE(t).pointerEl;i&&e.pointer&&(i.setStyle(e.pointer.style),n(i,{shape:e.pointer.shape}))},t.prototype.updateLabelEl=function(t,e,n,i){var r=jE(t).labelEl;r&&(r.setStyle(e.label.style),n(r,{x:e.label.x,y:e.label.y}),tB(r,i))},t.prototype._renderHandle=function(t){if(!this._dragging&&this.updateHandleTransform){var e,n=this._axisPointerModel,i=this._api.getZr(),r=this._handle,o=n.getModel("handle"),a=n.get("status");if(!o.get("show")||!a||"hide"===a)return r&&i.remove(r),void(this._handle=null);this._handle||(e=!0,r=this._handle=Ah(o.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){fe(t.event)},onmousedown:KE(this._onHandleDragMove,this,0,0),drift:KE(this._onHandleDragMove,this),ondragend:KE(this._onHandleDragEnd,this)}),i.add(r)),nB(r,n,!1),r.setStyle(o.getItemStyle(null,["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"]));var s=o.get("size");U(s)||(s=[s,s]),r.scaleX=s[0]/2,r.scaleY=s[1]/2,cv(this,"_doDispatchAxisPointer",o.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,e)}},t.prototype._moveHandleToValue=function(t,e){JE(this._axisPointerModel,!e&&this._moveAnimation,this._handle,eB(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},t.prototype._onHandleDragMove=function(t,e){var n=this._handle;if(n){this._dragging=!0;var i=this.updateHandleTransform(eB(n),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=i,n.stopAnimation(),n.attr(eB(i)),jE(n).lastProp=null,this._doDispatchAxisPointer()}},t.prototype._doDispatchAxisPointer=function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},t.prototype._onHandleDragEnd=function(){if(this._dragging=!1,this._handle){var t=this._axisPointerModel.get("value");this._moveHandleToValue(t),this._api.dispatchAction({type:"hideTip"})}},t.prototype.clear=function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),n=this._group,i=this._handle;e&&n&&(this._lastGraphicKey=null,n&&e.remove(n),i&&e.remove(i),this._group=null,this._handle=null,this._payloadInfo=null),hv(this,"_doDispatchAxisPointer")},t.prototype.doClear=function(){},t.prototype.buildLabel=function(t,e,n){return{x:t[n=n||0],y:t[1-n],width:e[n],height:e[1-n]}},t}();function JE(t,e,n,i){QE(jE(n).lastProp,i)||(jE(n).lastProp=i,e?th(n,i,t):(n.stopAnimation(),n.attr(i)))}function QE(t,e){if(q(t)&&q(e)){var n=!0;return z(e,(function(e,i){n=n&&QE(t[i],e)})),!!n}return t===e}function tB(t,e){t[e.get(["label","show"])?"show":"hide"]()}function eB(t){return{x:t.x||0,y:t.y||0,rotation:t.rotation||0}}function nB(t,e,n){var i=e.get("z"),r=e.get("zlevel");t&&t.traverse((function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=r&&(t.zlevel=r),t.silent=n)}))}function iB(t){var e,n=t.get("type"),i=t.getModel(n+"Style");return"line"===n?(e=i.getLineStyle()).fill=null:"shadow"===n&&((e=i.getAreaStyle()).stroke=null),e}function rB(t,e,n,i,r){var o=oB(n.get("value"),e.axis,e.ecModel,n.get("seriesDataIndices"),{precision:n.get(["label","precision"]),formatter:n.get(["label","formatter"])}),a=n.getModel("label"),s=yp(a.get("padding")||0),l=a.getFont(),u=Er(o,l),c=r.position,h=u.width+s[1]+s[3],d=u.height+s[0]+s[2],p=r.align;"right"===p&&(c[0]-=h),"center"===p&&(c[0]-=h/2);var f=r.verticalAlign;"bottom"===f&&(c[1]-=d),"middle"===f&&(c[1]-=d/2),function(t,e,n,i){var r=i.getWidth(),o=i.getHeight();t[0]=Math.min(t[0]+e,r)-e,t[1]=Math.min(t[1]+n,o)-n,t[0]=Math.max(t[0],0),t[1]=Math.max(t[1],0)}(c,h,d,i);var g=a.get("backgroundColor");g&&"auto"!==g||(g=e.get(["axisLine","lineStyle","color"])),t.label={x:c[0],y:c[1],style:Qh(a,{text:o,font:l,fill:a.getTextColor(),padding:s,backgroundColor:g}),z2:10}}function oB(t,e,n,i,r){t=e.scale.parse(t);var o=e.scale.getLabel({value:t},{precision:r.precision}),a=r.formatter;if(a){var s={value:qb(e,{value:t}),axisDimension:e.dim,axisIndex:e.index,seriesData:[]};z(i,(function(t){var e=n.getSeriesByIndex(t.seriesIndex),i=t.dataIndexInside,r=e&&e.getDataParams(i);r&&s.seriesData.push(r)})),X(a)?o=a.replace("{value}",o):Y(a)&&(o=a(s))}return o}function aB(t,e,n){var i=[1,0,0,1,0,0];return Me(i,i,n.rotation),Se(i,i,n.position),Sh([t.dataToCoord(e),(n.labelOffset||0)+(n.labelDirection||1)*(n.labelMargin||0)],i)}function sB(t,e,n,i,r,o){var a=mC.innerTextLayout(n.rotation,0,n.labelDirection);n.labelMargin=r.get(["label","margin"]),rB(e,i,r,o,{position:aB(i.axis,t,n),align:a.textAlign,verticalAlign:a.textVerticalAlign})}function lB(t,e,n){return{x1:t[n=n||0],y1:t[1-n],x2:e[n],y2:e[1-n]}}function uB(t,e,n){return{x:t[n=n||0],y:t[1-n],width:e[n],height:e[1-n]}}function cB(t,e,n,i,r,o){return{cx:t,cy:e,r0:n,r:i,startAngle:r,endAngle:o,clockwise:!0}}var hB=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.makeElOption=function(t,e,n,i,r){var o=n.axis,a=o.grid,s=i.get("type"),l=dB(a,o).getOtherAxis(o).getGlobalExtent(),u=o.toGlobalCoord(o.dataToCoord(e,!0));if(s&&"none"!==s){var c=iB(i),h=pB[s](o,u,l);h.style=c,t.graphicKey=h.type,t.pointer=h}sB(e,t,kC(a.getRect(),n),n,i,r)},e.prototype.getHandleTransform=function(t,e,n){var i=kC(e.axis.grid.getRect(),e,{labelInside:!1});i.labelMargin=n.get(["handle","margin"]);var r=aB(e.axis,t,i);return{x:r[0],y:r[1],rotation:i.rotation+(i.labelDirection<0?Math.PI:0)}},e.prototype.updateHandleTransform=function(t,e,n,i){var r=n.axis,o=r.grid,a=r.getGlobalExtent(!0),s=dB(o,r).getOtherAxis(r).getGlobalExtent(),l="x"===r.dim?0:1,u=[t.x,t.y];u[l]+=e[l],u[l]=Math.min(a[1],u[l]),u[l]=Math.max(a[0],u[l]);var c=(s[1]+s[0])/2,h=[c,c];h[l]=u[l];return{x:u[0],y:u[1],rotation:t.rotation,cursorPoint:h,tooltipOption:[{verticalAlign:"middle"},{align:"center"}][l]}},e}($E);function dB(t,e){var n={};return n[e.dim+"AxisIndex"]=e.index,t.getCartesian(n)}var pB={line:function(t,e,n){return{type:"Line",subPixelOptimize:!0,shape:lB([e,n[0]],[e,n[1]],fB(t))}},shadow:function(t,e,n){var i=Math.max(1,t.getBandWidth()),r=n[1]-n[0];return{type:"Rect",shape:uB([e-i/2,n[0]],[i,r],fB(t))}}};function fB(t){return"x"===t.dim?0:1}var gB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="axisPointer",e.defaultOption={show:"auto",z:50,type:"line",snap:!1,triggerTooltip:!0,triggerEmphasis:!0,value:null,status:null,link:[],animation:null,animationDurationUpdate:200,lineStyle:{color:tf.color.border,width:1,type:"dashed"},shadowStyle:{color:tf.color.shadowTint},label:{show:!0,formatter:null,precision:"auto",margin:3,color:tf.color.neutral00,padding:[5,7,5,7],backgroundColor:tf.color.accent60,borderColor:null,borderWidth:0,borderRadius:3},handle:{show:!1,icon:"M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z",size:45,margin:50,color:tf.color.accent40,throttle:40}},e}(Qp),yB=sa(),vB=z;function mB(t,e,n){if(!r.node){var i=e.getZr();yB(i).records||(yB(i).records={}),function(t,e){if(yB(t).initialized)return;function n(n,i){t.on(n,(function(n){var r=function(t){var e={showTip:[],hideTip:[]},n=function(i){var r=e[i.type];r?r.push(i):(i.dispatchAction=n,t.dispatchAction(i))};return{dispatchAction:n,pendings:e}}(e);vB(yB(t).records,(function(t){t&&i(t,n,r.dispatchAction)})),function(t,e){var n,i=t.showTip.length,r=t.hideTip.length;i?n=t.showTip[i-1]:r&&(n=t.hideTip[r-1]);n&&(n.dispatchAction=null,e.dispatchAction(n))}(r.pendings,e)}))}yB(t).initialized=!0,n("click",H(_B,"click")),n("mousemove",H(_B,"mousemove")),n("globalout",xB)}(i,e),(yB(i).records[t]||(yB(i).records[t]={})).handler=n}}function xB(t,e,n){t.handler("leave",null,n)}function _B(t,e,n,i){e.handler(t,n,i)}function bB(t,e){if(!r.node){var n=e.getZr();(yB(n).records||{})[t]&&(yB(n).records[t]=null)}}var wB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=e.getComponent("tooltip"),r=t.get("triggerOn")||i&&i.get("triggerOn")||"mousemove|click";mB("axisPointer",n,(function(t,e,n){"none"!==r&&("leave"===t||r.indexOf(t)>=0)&&n({type:"updateAxisPointer",currTrigger:t,x:e&&e.offsetX,y:e&&e.offsetY})}))},e.prototype.remove=function(t,e){bB("axisPointer",e)},e.prototype.dispose=function(t,e){bB("axisPointer",e)},e.type="axisPointer",e}(Ky);function SB(t,e){var n,i=[],r=t.seriesIndex;if(null==r||!(n=e.getSeriesByIndex(r)))return{point:[]};var o=n.getData(),a=aa(o,t);if(null==a||a<0||U(a))return{point:[]};var s=o.getItemGraphicEl(a),l=n.coordinateSystem;if(n.getTooltipPosition)i=n.getTooltipPosition(a)||[];else if(l&&l.dataToPoint)if(t.isStacked){var u=l.getBaseAxis(),c=l.getOtherAxis(u).dim,h=u.dim,d="x"===c||"radius"===c?1:0,p=o.mapDimension(h),f=[];f[d]=o.get(p,a),f[1-d]=o.get(o.getCalculationInfo("stackResultDimension"),a),i=l.dataToPoint(f)||[]}else i=l.dataToPoint(o.getValues(E(l.dimensions,(function(t){return o.mapDimension(t)})),a))||[];else if(s){var g=s.getBoundingRect().clone();g.applyTransform(s.transform),i=[g.x+g.width/2,g.y+g.height/2]}return{point:i,el:s}}var MB=sa();function IB(t,e,n){var i=t.currTrigger,r=[t.x,t.y],o=t,a=t.dispatchAction||W(n.dispatchAction,n),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){kB(r)&&(r=SB({seriesIndex:o.seriesIndex,dataIndex:o.dataIndex},e).point);var l=kB(r),u=o.axesInfo,c=s.axesInfo,h="leave"===i||kB(r),d={},p={},f={list:[],map:{}},g={showPointer:H(CB,p),showTooltip:H(DB,f)};z(s.coordSysMap,(function(t,e){var n=l||t.containPoint(r);z(s.coordSysAxesInfo[e],(function(t,e){var i=t.axis,o=function(t,e){for(var n=0;n<(t||[]).length;n++){var i=t[n];if(e.axis.dim===i.axisDim&&e.axis.model.componentIndex===i.axisIndex)return i}}(u,t);if(!h&&n&&(!u||o)){var a=o&&o.value;null!=a||l||(a=i.pointToData(r)),null!=a&&TB(t,a,g,!1,d)}}))}));var y={};return z(c,(function(t,e){var n=t.linkGroup;n&&!p[e]&&z(n.axesInfo,(function(e,i){var r=p[i];if(e!==t&&r){var o=r.value;n.mapper&&(o=t.axis.scale.parse(n.mapper(o,AB(e),AB(t)))),y[t.key]=o}}))})),z(y,(function(t,e){TB(c[e],t,g,!0,d)})),function(t,e,n){var i=n.axesInfo=[];z(e,(function(e,n){var r=e.axisPointerModel.option,o=t[n];o?(!e.useHandle&&(r.status="show"),r.value=o.value,r.seriesDataIndices=(o.payloadBatch||[]).slice()):!e.useHandle&&(r.status="hide"),"show"===r.status&&i.push({axisDim:e.axis.dim,axisIndex:e.axis.model.componentIndex,value:r.value})}))}(p,c,d),function(t,e,n,i){if(kB(e)||!t.list.length)return void i({type:"hideTip"});var r=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};i({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:n.tooltipOption,position:n.position,dataIndexInside:r.dataIndexInside,dataIndex:r.dataIndex,seriesIndex:r.seriesIndex,dataByCoordSys:t.list})}(f,r,t,a),function(t,e,n){var i=n.getZr(),r="axisPointerLastHighlights",o=MB(i)[r]||{},a=MB(i)[r]={};z(t,(function(t,e){var n=t.axisPointerModel.option;"show"===n.status&&t.triggerEmphasis&&z(n.seriesDataIndices,(function(t){var e=t.seriesIndex+" | "+t.dataIndex;a[e]=t}))}));var s=[],l=[];z(o,(function(t,e){!a[e]&&l.push(t)})),z(a,(function(t,e){!o[e]&&s.push(t)})),l.length&&n.dispatchAction({type:"downplay",escapeConnect:!0,notBlur:!0,batch:l}),s.length&&n.dispatchAction({type:"highlight",escapeConnect:!0,notBlur:!0,batch:s})}(c,0,n),d}}function TB(t,e,n,i,r){var o=t.axis;if(!o.scale.isBlank()&&o.containData(e))if(t.involveSeries){var a=function(t,e){var n=e.axis,i=n.dim,r=t,o=[],a=Number.MAX_VALUE,s=-1;return z(e.seriesModels,(function(e,l){var u,c,h=e.getData().mapDimensionsAll(i);if(e.getAxisTooltipData){var d=e.getAxisTooltipData(h,t,n);c=d.dataIndices,u=d.nestestValue}else{if(!(c=e.indicesOfNearest(i,h[0],t,"category"===n.type?.5:null)).length)return;u=e.getData().get(h[0],c[0])}if(null!=u&&isFinite(u)){var p=t-u,f=Math.abs(p);f<=a&&((f=0&&s<0)&&(a=f,s=p,r=u,o.length=0),z(c,(function(t){o.push({seriesIndex:e.seriesIndex,dataIndexInside:t,dataIndex:e.getData().getRawIndex(t)})})))}})),{payloadBatch:o,snapToValue:r}}(e,t),s=a.payloadBatch,l=a.snapToValue;s[0]&&null==r.seriesIndex&&A(r,s[0]),!i&&t.snap&&o.containData(l)&&null!=l&&(e=l),n.showPointer(t,e,s),n.showTooltip(t,a,l)}else n.showPointer(t,e)}function CB(t,e,n,i){t[e.key]={value:n,payloadBatch:i}}function DB(t,e,n,i){var r=n.payloadBatch,o=e.axis,a=o.model,s=e.axisPointerModel;if(e.triggerTooltip&&r.length){var l=e.coordSys.model,u=qC(l),c=t.map[u];c||(c=t.map[u]={coordSysId:l.id,coordSysIndex:l.componentIndex,coordSysType:l.type,coordSysMainType:l.mainType,dataByAxis:[]},t.list.push(c)),c.dataByAxis.push({axisDim:o.dim,axisIndex:a.componentIndex,axisType:a.type,axisId:a.id,value:i,valueLabelOpt:{precision:s.get(["label","precision"]),formatter:s.get(["label","formatter"])},seriesDataIndices:r.slice()})}}function AB(t){var e=t.axis.model,n={},i=n.axisDim=t.axis.dim;return n.axisIndex=n[i+"AxisIndex"]=e.componentIndex,n.axisName=n[i+"AxisName"]=e.name,n.axisId=n[i+"AxisId"]=e.id,n}function kB(t){return!t||null==t[0]||isNaN(t[0])||null==t[1]||isNaN(t[1])}function LB(t){$C.registerAxisPointerClass("CartesianAxisPointer",hB),t.registerComponentModel(gB),t.registerComponentView(wB),t.registerPreprocessor((function(t){if(t){(!t.axisPointer||0===t.axisPointer.length)&&(t.axisPointer={});var e=t.axisPointer.link;e&&!U(e)&&(t.axisPointer.link=[e])}})),t.registerProcessor(t.PRIORITY.PROCESSOR.STATISTIC,(function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=UC(t,e)})),t.registerAction({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},IB)}var PB=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.makeElOption=function(t,e,n,i,r){var o=n.axis;"angle"===o.dim&&(this.animationThreshold=Math.PI/18);var a=o.polar,s=a.getOtherAxis(o).getExtent(),l=o.dataToCoord(e),u=i.get("type");if(u&&"none"!==u){var c=iB(i),h=OB[u](o,a,l,s);h.style=c,t.graphicKey=h.type,t.pointer=h}var d=function(t,e,n,i,r){var o=e.axis,a=o.dataToCoord(t),s=i.getAngleAxis().getExtent()[0];s=s/180*Math.PI;var l,u,c,h=i.getRadiusAxis().getExtent();if("radius"===o.dim){var d=[1,0,0,1,0,0];Me(d,d,s),Se(d,d,[i.cx,i.cy]),l=Sh([a,-r],d);var p=e.getModel("axisLabel").get("rotate")||0,f=mC.innerTextLayout(s,p*Math.PI/180,-1);u=f.textAlign,c=f.textVerticalAlign}else{var g=h[1];l=i.coordToPoint([g+r,a]);var y=i.cx,v=i.cy;u=Math.abs(l[0]-y)/g<.3?"center":l[0]>y?"left":"right",c=Math.abs(l[1]-v)/g<.3?"middle":l[1]>v?"top":"bottom"}return{position:l,align:u,verticalAlign:c}}(e,n,0,a,i.get(["label","margin"]));rB(t,n,i,r,d)},e}($E);var OB={line:function(t,e,n,i){return"angle"===t.dim?{type:"Line",shape:lB(e.coordToPoint([i[0],n]),e.coordToPoint([i[1],n]))}:{type:"Circle",shape:{cx:e.cx,cy:e.cy,r:n}}},shadow:function(t,e,n,i){var r=Math.max(1,t.getBandWidth()),o=Math.PI/180;return"angle"===t.dim?{type:"Sector",shape:cB(e.cx,e.cy,i[0],i[1],(-n-r/2)*o,(r/2-n)*o)}:{type:"Sector",shape:cB(e.cx,e.cy,n-r/2,n+r/2,0,2*Math.PI)}}},RB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.findAxisModel=function(t){var e;return this.ecModel.eachComponent(t,(function(t){t.getCoordSysModel()===this&&(e=t)}),this),e},e.type="polar",e.dependencies=["radiusAxis","angleAxis"],e.defaultOption={z:0,center:["50%","50%"],radius:"80%"},e}(Qp),NB=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.getCoordSysModel=function(){return this.getReferringComponents("polar",ha).models[0]},e.type="polarAxis",e}(Qp);R(NB,nw);var zB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="angleAxis",e}(NB),EB=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="radiusAxis",e}(NB),BB=function(t){function e(e,n){return t.call(this,"radius",e,n)||this}return n(e,t),e.prototype.pointToData=function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},e}(Ww);BB.prototype.dataToRadius=Ww.prototype.dataToCoord,BB.prototype.radiusToData=Ww.prototype.coordToData;var VB=sa(),GB=function(t){function e(e,n){return t.call(this,"angle",e,n||[0,360])||this}return n(e,t),e.prototype.pointToData=function(t,e){return this.polar.pointToData(t,e)["radius"===this.dim?0:1]},e.prototype.calculateCategoryInterval=function(){var t=this,e=t.getLabelModel(),n=t.scale,i=n.getExtent(),r=n.count();if(i[1]-i[0]<1)return 0;var o=i[0],a=t.dataToCoord(o+1)-t.dataToCoord(o),s=Math.abs(a),l=Er(null==o?"":o+"",e.getFont(),"center","top"),u=Math.max(l.height,7)/s;isNaN(u)&&(u=1/0);var c=Math.max(0,Math.floor(u)),h=VB(t.model),d=h.lastAutoInterval,p=h.lastTickCount;return null!=d&&null!=p&&Math.abs(d-c)<=1&&Math.abs(p-r)<=1&&d>c?c=d:(h.lastTickCount=r,h.lastAutoInterval=c),c},e}(Ww);GB.prototype.dataToAngle=Ww.prototype.dataToCoord,GB.prototype.angleToData=Ww.prototype.coordToData;var FB=["radius","angle"],WB=function(){function t(t){this.dimensions=FB,this.type="polar",this.cx=0,this.cy=0,this._radiusAxis=new BB,this._angleAxis=new GB,this.axisPointerEnabled=!0,this.name=t||"",this._radiusAxis.polar=this._angleAxis.polar=this}return t.prototype.containPoint=function(t){var e=this.pointToCoord(t);return this._radiusAxis.contain(e[0])&&this._angleAxis.contain(e[1])},t.prototype.containData=function(t){return this._radiusAxis.containData(t[0])&&this._angleAxis.containData(t[1])},t.prototype.getAxis=function(t){return this["_"+t+"Axis"]},t.prototype.getAxes=function(){return[this._radiusAxis,this._angleAxis]},t.prototype.getAxesByScale=function(t){var e=[],n=this._angleAxis,i=this._radiusAxis;return n.scale.type===t&&e.push(n),i.scale.type===t&&e.push(i),e},t.prototype.getAngleAxis=function(){return this._angleAxis},t.prototype.getRadiusAxis=function(){return this._radiusAxis},t.prototype.getOtherAxis=function(t){var e=this._angleAxis;return t===e?this._radiusAxis:e},t.prototype.getBaseAxis=function(){return this.getAxesByScale("ordinal")[0]||this.getAxesByScale("time")[0]||this.getAngleAxis()},t.prototype.getTooltipAxes=function(t){var e=null!=t&&"auto"!==t?this.getAxis(t):this.getBaseAxis();return{baseAxes:[e],otherAxes:[this.getOtherAxis(e)]}},t.prototype.dataToPoint=function(t,e,n){return this.coordToPoint([this._radiusAxis.dataToRadius(t[0],e),this._angleAxis.dataToAngle(t[1],e)],n)},t.prototype.pointToData=function(t,e,n){n=n||[];var i=this.pointToCoord(t);return n[0]=this._radiusAxis.radiusToData(i[0],e),n[1]=this._angleAxis.angleToData(i[1],e),n},t.prototype.pointToCoord=function(t){var e=t[0]-this.cx,n=t[1]-this.cy,i=this.getAngleAxis(),r=i.getExtent(),o=Math.min(r[0],r[1]),a=Math.max(r[0],r[1]);i.inverse?o=a-360:a=o+360;var s=Math.sqrt(e*e+n*n);e/=s,n/=s;for(var l=Math.atan2(-n,e)/Math.PI*180,u=la;)l+=360*u;return[s,l]},t.prototype.coordToPoint=function(t,e){e=e||[];var n=t[0],i=t[1]/180*Math.PI;return e[0]=Math.cos(i)*n+this.cx,e[1]=-Math.sin(i)*n+this.cy,e},t.prototype.getArea=function(){var t=this.getAngleAxis(),e=this.getRadiusAxis().getExtent().slice();e[0]>e[1]&&e.reverse();var n=t.getExtent(),i=Math.PI/180,r=1e-4;return{cx:this.cx,cy:this.cy,r0:e[0],r:e[1],startAngle:-n[0]*i,endAngle:-n[1]*i,clockwise:t.inverse,contain:function(t,e){var n=t-this.cx,i=e-this.cy,o=n*n+i*i,a=this.r,s=this.r0;return a!==s&&o-r<=a*a&&o+r>=s*s},x:this.cx-e[1],y:this.cy-e[1],width:2*e[1],height:2*e[1]}},t.prototype.convertToPixel=function(t,e,n){return HB(e)===this?this.dataToPoint(n):null},t.prototype.convertFromPixel=function(t,e,n){return HB(e)===this?this.pointToData(n):null},t}();function HB(t){var e=t.seriesModel,n=t.polarModel;return n&&n.coordinateSystem||e&&e.coordinateSystem}function UB(t,e){var n=this,i=n.getAngleAxis(),r=n.getRadiusAxis();if(i.scale.setExtent(1/0,-1/0),r.scale.setExtent(1/0,-1/0),t.eachSeries((function(t){if(t.coordinateSystem===n){var e=t.getData();z(Jb(e,"radius"),(function(t){r.scale.unionExtentFromData(e,t)})),z(Jb(e,"angle"),(function(t){i.scale.unionExtentFromData(e,t)}))}})),Xb(i.scale,i.model),Xb(r.scale,r.model),"category"===i.type&&!i.onBand){var o=i.getExtent(),a=360/i.scale.count();i.inverse?o[1]+=a:o[1]-=a,i.setExtent(o[0],o[1])}}function YB(t,e){var n;if(t.type=e.get("type"),t.scale=Zb(e),t.onBand=e.get("boundaryGap")&&"category"===t.type,t.inverse=e.get("inverse"),function(t){return"angleAxis"===t.mainType}(e)){t.inverse=t.inverse!==e.get("clockwise");var i=e.get("startAngle"),r=null!==(n=e.get("endAngle"))&&void 0!==n?n:i+(t.inverse?-360:360);t.setExtent(i,r)}e.axis=t,t.model=e}var XB={dimensions:FB,create:function(t,e){var n=[];return t.eachComponent("polar",(function(t,i){var r=new WB(i+"");r.update=UB;var o=r.getRadiusAxis(),a=r.getAngleAxis(),s=t.findAxisModel("radiusAxis"),l=t.findAxisModel("angleAxis");YB(o,s),YB(a,l),function(t,e,n){var i=e.get("center"),r=Xp(e,n).refContainer;t.cx=yo(i[0],r.width)+r.x,t.cy=yo(i[1],r.height)+r.y;var o=t.getRadiusAxis(),a=Math.min(r.width,r.height)/2,s=e.get("radius");null==s?s=[0,"100%"]:U(s)||(s=[0,s]);var l=[yo(s[0],a),yo(s[1],a)];o.inverse?o.setExtent(l[1],l[0]):o.setExtent(l[0],l[1])}(r,t,e),n.push(r),t.coordinateSystem=r,r.model=t})),t.eachSeries((function(t){if("polar"===t.get("coordinateSystem")){var e=t.getReferringComponents("polar",ha).models[0];0,t.coordinateSystem=e.coordinateSystem}})),n}},ZB=["axisLine","axisLabel","axisTick","minorTick","splitLine","minorSplitLine","splitArea"];function jB(t,e,n){e[1]>e[0]&&(e=e.slice().reverse());var i=t.coordToPoint([e[0],n]),r=t.coordToPoint([e[1],n]);return{x1:i[0],y1:i[1],x2:r[0],y2:r[1]}}function qB(t){return t.getRadiusAxis().inverse?0:1}function KB(t){var e=t[0],n=t[t.length-1];e&&n&&Math.abs(Math.abs(e.coord-n.coord)-360)<1e-4&&t.pop()}var $B=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.axisPointerClass="PolarAxisPointer",n}return n(e,t),e.prototype.render=function(t,e){if(this.group.removeAll(),t.get("show")){var n=t.axis,i=n.polar,r=i.getRadiusAxis().getExtent(),o=n.getTicksCoords({breakTicks:"none"}),a=n.getMinorTicksCoords(),s=E(n.getViewLabels(),(function(t){t=T(t);var e=n.scale,i="ordinal"===e.type?e.getRawOrdinalNumber(t.tickValue):t.tickValue;return t.coord=n.dataToCoord(i),t}));KB(s),KB(o),z(ZB,(function(e){!t.get([e,"show"])||n.scale.isBlank()&&"axisLine"!==e||JB[e](this.group,t,i,o,a,r,s)}),this)}},e.type="angleAxis",e}($C),JB={axisLine:function(t,e,n,i,r,o){var a,s=e.getModel(["axisLine","lineStyle"]),l=n.getAngleAxis(),u=Math.PI/180,c=l.getExtent(),h=qB(n),d=h?0:1,p=360===Math.abs(c[1]-c[0])?"Circle":"Arc";(a=0===o[d]?new Zh[p]({shape:{cx:n.cx,cy:n.cy,r:o[h],startAngle:-c[0]*u,endAngle:-c[1]*u,clockwise:l.inverse},style:s.getLineStyle(),z2:1,silent:!0}):new bc({shape:{cx:n.cx,cy:n.cy,r:o[h],r0:o[d]},style:s.getLineStyle(),z2:1,silent:!0})).style.fill=null,t.add(a)},axisTick:function(t,e,n,i,r,o){var a=e.getModel("axisTick"),s=(a.get("inside")?-1:1)*a.get("length"),l=o[qB(n)],u=E(i,(function(t){return new Ac({shape:jB(n,[l,l+s],t.coord)})}));t.add(mh(u,{style:k(a.getModel("lineStyle").getLineStyle(),{stroke:e.get(["axisLine","lineStyle","color"])})}))},minorTick:function(t,e,n,i,r,o){if(r.length){for(var a=e.getModel("axisTick"),s=e.getModel("minorTick"),l=(a.get("inside")?-1:1)*s.get("length"),u=o[qB(n)],c=[],h=0;hf?"left":"right",v=Math.abs(p[1]-g)/d<.3?"middle":p[1]>g?"top":"bottom";if(s&&s[h]){var m=s[h];q(m)&&m.textStyle&&(a=new wd(m.textStyle,l,l.ecModel))}var x=new Sl({silent:mC.isLabelSilent(e),style:Qh(a,{x:p[0],y:p[1],fill:a.getTextColor()||e.get(["axisLine","lineStyle","color"]),text:i.formattedLabel,align:y,verticalAlign:v})});if(t.add(x),zh({el:x,componentModel:e,itemName:i.formattedLabel,formatterParamsExtra:{isTruncated:function(){return x.isTruncated},value:i.rawLabel,tickIndex:r}}),c){var _=mC.makeAxisEventDataBase(e);_.targetType="axisLabel",_.value=i.rawLabel,zl(x).eventData=_}}),this)},splitLine:function(t,e,n,i,r,o){var a=e.getModel("splitLine").getModel("lineStyle"),s=a.get("color"),l=0;s=s instanceof Array?s:[s];for(var u=[],c=0;c=0?"p":"n",C=b;m&&(i[s][I]||(i[s][I]={p:b,n:b}),C=i[s][I][T]);var D=void 0,A=void 0,k=void 0,L=void 0;if("radius"===h.dim){var P=h.dataToCoord(M)-b,O=o.dataToCoord(I);Math.abs(P)=L})}}}))}var oV={startAngle:90,clockwise:!0,splitNumber:12,axisLabel:{rotate:0}},aV={splitNumber:5},sV=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="polar",e}(Ky);function lV(t,e){e=e||{};var n=t.coordinateSystem,i=t.axis,r={},o=i.position,a=i.orient,s=n.getRect(),l=[s.x,s.x+s.width,s.y,s.y+s.height],u={horizontal:{top:l[2],bottom:l[3]},vertical:{left:l[0],right:l[1]}};r.position=["vertical"===a?u.vertical[o]:l[0],"horizontal"===a?u.horizontal[o]:l[3]];r.rotation=Math.PI/2*{horizontal:0,vertical:1}[a];r.labelDirection=r.tickDirection=r.nameDirection={top:-1,bottom:1,right:1,left:-1}[o],t.get(["axisTick","inside"])&&(r.tickDirection=-r.tickDirection),it(e.labelInside,t.get(["axisLabel","inside"]))&&(r.labelDirection=-r.labelDirection);var c=t.get(["axisLabel","rotate"]);return r.labelRotate="top"===o?-c:c,r.z2=1,r}var uV=["splitArea","splitLine","breakArea"],cV=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.axisPointerClass="SingleAxisPointer",n}return n(e,t),e.prototype.render=function(e,n,i,r){var o=this.group;o.removeAll();var a=this._axisGroup;this._axisGroup=new to;var s=lV(e),l=new mC(e,i,s);l.build(),o.add(this._axisGroup),o.add(l.group),z(uV,(function(t){e.get([t,"show"])&&hV[t](this,this.group,this._axisGroup,e,i)}),this),Th(a,this._axisGroup,e),t.prototype.render.call(this,e,n,i,r)},e.prototype.remove=function(){tD(this)},e.type="singleAxis",e}($C),hV={splitLine:function(t,e,n,i,r){var o=i.axis;if(!o.scale.isBlank()){var a=i.getModel("splitLine"),s=a.getModel("lineStyle"),l=s.get("color");l=l instanceof Array?l:[l];for(var u=s.get("width"),c=i.coordinateSystem.getRect(),h=o.isHorizontal(),d=[],p=0,f=o.getTicksCoords({tickModel:a,breakTicks:"none",pruneByBreak:"preserve_extent_bound"}),g=[],y=[],v=0;v=e.y&&t[1]<=e.y+e.height:n.contain(n.toLocalCoord(t[1]))&&t[0]>=e.y&&t[0]<=e.y+e.height},t.prototype.pointToData=function(t,e,n){n=n||[];var i=this.getAxis();return n[0]=i.coordToData(i.toLocalCoord(t["horizontal"===i.orient?0:1])),n},t.prototype.dataToPoint=function(t,e,n){var i=this.getAxis(),r=this.getRect();n=n||[];var o="horizontal"===i.orient?0:1;return t instanceof Array&&(t=t[0]),n[o]=i.toGlobalCoord(i.dataToCoord(+t)),n[1-o]=0===o?r.y+r.height/2:r.x+r.width/2,n},t.prototype.convertToPixel=function(t,e,n){return yV(e)===this?this.dataToPoint(n):null},t.prototype.convertFromPixel=function(t,e,n){return yV(e)===this?this.pointToData(n):null},t}();function yV(t){var e=t.seriesModel,n=t.singleAxisModel;return n&&n.coordinateSystem||e&&e.coordinateSystem}var vV={create:function(t,e){var n=[];return t.eachComponent("singleAxis",(function(i,r){var o=new gV(i,t,e);o.name="single_"+r,o.resize(i,e),i.coordinateSystem=o,n.push(o)})),t.eachSeries((function(t){if("singleAxis"===t.get("coordinateSystem")){var e=t.getReferringComponents("singleAxis",ha).models[0];t.coordinateSystem=e&&e.coordinateSystem}})),n},dimensions:fV},mV=["x","y"],xV=["width","height"],_V=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.makeElOption=function(t,e,n,i,r){var o=n.axis,a=o.coordinateSystem,s=SV(a,1-wV(o)),l=a.dataToPoint(e)[0],u=i.get("type");if(u&&"none"!==u){var c=iB(i),h=bV[u](o,l,s);h.style=c,t.graphicKey=h.type,t.pointer=h}sB(e,t,lV(n),n,i,r)},e.prototype.getHandleTransform=function(t,e,n){var i=lV(e,{labelInside:!1});i.labelMargin=n.get(["handle","margin"]);var r=aB(e.axis,t,i);return{x:r[0],y:r[1],rotation:i.rotation+(i.labelDirection<0?Math.PI:0)}},e.prototype.updateHandleTransform=function(t,e,n,i){var r=n.axis,o=r.coordinateSystem,a=wV(r),s=SV(o,a),l=[t.x,t.y];l[a]+=e[a],l[a]=Math.min(s[1],l[a]),l[a]=Math.max(s[0],l[a]);var u=SV(o,1-a),c=(u[1]+u[0])/2,h=[c,c];return h[a]=l[a],{x:l[0],y:l[1],rotation:t.rotation,cursorPoint:h,tooltipOption:{verticalAlign:"middle"}}},e}($E),bV={line:function(t,e,n){return{type:"Line",subPixelOptimize:!0,shape:lB([e,n[0]],[e,n[1]],wV(t))}},shadow:function(t,e,n){var i=t.getBandWidth(),r=n[1]-n[0];return{type:"Rect",shape:uB([e-i/2,n[0]],[i,r],wV(t))}}};function wV(t){return t.isHorizontal()?0:1}function SV(t,e){var n=t.getRect();return[n[mV[e]],n[mV[e]]+n[xV[e]]]}var MV=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="single",e}(Ky);var IV=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(e,n,i){var r=Kp(e);t.prototype.init.apply(this,arguments),TV(e,r)},e.prototype.mergeOption=function(e){t.prototype.mergeOption.apply(this,arguments),TV(this.option,e)},e.prototype.getCellSize=function(){return this.option.cellSize},e.type="calendar",e.layoutMode="box",e.defaultOption={z:2,left:80,top:60,cellSize:20,orient:"horizontal",splitLine:{show:!0,lineStyle:{color:tf.color.axisLine,width:1,type:"solid"}},itemStyle:{color:tf.color.neutral00,borderWidth:1,borderColor:tf.color.neutral10},dayLabel:{show:!0,firstDay:0,position:"start",margin:tf.size.s,color:tf.color.secondary},monthLabel:{show:!0,position:"start",margin:tf.size.s,align:"center",formatter:null,color:tf.color.secondary},yearLabel:{show:!0,position:null,margin:tf.size.xl,formatter:null,color:tf.color.quaternary,fontFamily:"sans-serif",fontWeight:"bolder",fontSize:20}},e}(Qp);function TV(t,e){var n,i=t.cellSize;1===(n=U(i)?i:t.cellSize=[i,i]).length&&(n[1]=n[0]);var r=E([0,1],(function(t){return function(t,e){return null!=t[Bp[e][0]]||null!=t[Bp[e][1]]&&null!=t[Bp[e][2]]}(e,t)&&(n[t]="auto"),null!=n[t]&&"auto"!==n[t]}));qp(t,e,{type:"box",ignoreSize:r})}var CV=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){var i=this.group;i.removeAll();var r=t.coordinateSystem,o=r.getRangeInfo(),a=r.getOrient(),s=e.getLocaleModel();this._renderDayRect(t,o,i),this._renderLines(t,o,a,i),this._renderYearText(t,o,a,i),this._renderMonthText(t,s,a,i),this._renderWeekText(t,s,o,a,i)},e.prototype._renderDayRect=function(t,e,n){for(var i=t.coordinateSystem,r=t.getModel("itemStyle").getItemStyle(),o=i.getCellWidth(),a=i.getCellHeight(),s=e.start.time;s<=e.end.time;s=i.getNextNDay(s,1).time){var l=i.dataToCalendarLayout([s],!1).tl,u=new xl({shape:{x:l[0],y:l[1],width:o,height:a},cursor:"default",style:r});n.add(u)}},e.prototype._renderLines=function(t,e,n,i){var r=this,o=t.coordinateSystem,a=t.getModel(["splitLine","lineStyle"]).getLineStyle(),s=t.get(["splitLine","show"]),l=a.lineWidth;this._tlpoints=[],this._blpoints=[],this._firstDayOfMonth=[],this._firstDayPoints=[];for(var u=e.start,c=0;u.time<=e.end.time;c++){d(u.formatedDate),0===c&&(u=o.getDateInfo(e.start.y+"-"+e.start.m));var h=u.date;h.setMonth(h.getMonth()+1),u=o.getDateInfo(h)}function d(e){r._firstDayOfMonth.push(o.getDateInfo(e)),r._firstDayPoints.push(o.dataToCalendarLayout([e],!1).tl);var l=r._getLinePointsOfOneWeek(t,e,n);r._tlpoints.push(l[0]),r._blpoints.push(l[l.length-1]),s&&r._drawSplitline(l,a,i)}d(o.getNextNDay(e.end.time,1).formatedDate),s&&this._drawSplitline(r._getEdgesPoints(r._tlpoints,l,n),a,i),s&&this._drawSplitline(r._getEdgesPoints(r._blpoints,l,n),a,i)},e.prototype._getEdgesPoints=function(t,e,n){var i=[t[0].slice(),t[t.length-1].slice()],r="horizontal"===n?0:1;return i[0][r]=i[0][r]-e/2,i[1][r]=i[1][r]+e/2,i},e.prototype._drawSplitline=function(t,e,n){var i=new Tc({z2:20,shape:{points:t},style:e});n.add(i)},e.prototype._getLinePointsOfOneWeek=function(t,e,n){for(var i=t.coordinateSystem,r=i.getDateInfo(e),o=[],a=0;a<7;a++){var s=i.getNextNDay(r.time,a),l=i.dataToCalendarLayout([s.time],!1);o[2*s.day]=l.tl,o[2*s.day+1]=l["horizontal"===n?"bl":"tr"]}return o},e.prototype._formatterLabel=function(t,e){return X(t)&&t?(n=t,z(e,(function(t,e){n=n.replace("{"+e+"}",i?oe(t):t)})),n):Y(t)?t(e):e.nameMap;var n,i},e.prototype._yearTextPositionControl=function(t,e,n,i,r){var o=e[0],a=e[1],s=["center","bottom"];"bottom"===i?(a+=r,s=["center","top"]):"left"===i?o-=r:"right"===i?(o+=r,s=["center","top"]):a-=r;var l=0;return"left"!==i&&"right"!==i||(l=Math.PI/2),{rotation:l,x:o,y:a,style:{align:s[0],verticalAlign:s[1]}}},e.prototype._renderYearText=function(t,e,n,i){var r=t.getModel("yearLabel");if(r.get("show")){var o=r.get("margin"),a=r.get("position");a||(a="horizontal"!==n?"top":"left");var s=[this._tlpoints[this._tlpoints.length-1],this._blpoints[0]],l=(s[0][0]+s[1][0])/2,u=(s[0][1]+s[1][1])/2,c="horizontal"===n?0:1,h={top:[l,s[c][1]],bottom:[l,s[1-c][1]],left:[s[1-c][0],u],right:[s[c][0],u]},d=e.start.y;+e.end.y>+e.start.y&&(d=d+"-"+e.end.y);var p=r.get("formatter"),f={start:e.start.y,end:e.end.y,nameMap:d},g=this._formatterLabel(p,f),y=new Sl({z2:30,style:Qh(r,{text:g}),silent:r.get("silent")});y.attr(this._yearTextPositionControl(y,h[a],n,a,o)),i.add(y)}},e.prototype._monthTextPositionControl=function(t,e,n,i,r){var o="left",a="top",s=t[0],l=t[1];return"horizontal"===n?(l+=r,e&&(o="center"),"start"===i&&(a="bottom")):(s+=r,e&&(a="middle"),"start"===i&&(o="right")),{x:s,y:l,align:o,verticalAlign:a}},e.prototype._renderMonthText=function(t,e,n,i){var r=t.getModel("monthLabel");if(r.get("show")){var o=r.get("nameMap"),a=r.get("margin"),s=r.get("position"),l=r.get("align"),u=[this._tlpoints,this._blpoints];o&&!X(o)||(o&&(e=Od(o)||e),o=e.get(["time","monthAbbr"])||[]);var c="start"===s?0:1,h="horizontal"===n?0:1;a="start"===s?-a:a;for(var d="center"===l,p=r.get("silent"),f=0;f=r.start.time&&i.timea.end.time&&t.reverse(),t},t.prototype._getRangeInfo=function(t){var e,n=[this.getDateInfo(t[0]),this.getDateInfo(t[1])];n[0].time>n[1].time&&(e=!0,n.reverse());var i=Math.floor(n[1].time/DV)-Math.floor(n[0].time/DV)+1,r=new Date(n[0].time),o=r.getDate(),a=n[1].date.getDate();r.setDate(o+i-1);var s=r.getDate();if(s!==a)for(var l=r.getTime()-n[1].time>0?1:-1;(s=r.getDate())!==a&&(r.getTime()-n[1].time)*l>0;)i-=l,r.setDate(s-l);var u=Math.floor((i+n[0].day+6)/7),c=e?1-u:u-1;return e&&n.reverse(),{range:[n[0].formatedDate,n[1].formatedDate],start:n[0],end:n[1],allDay:i,weeks:u,nthWeek:c,fweek:n[0].day,lweek:n[1].day}},t.prototype._getDateByWeeksAndDay=function(t,e,n){var i=this._getRangeInfo(n);if(t>i.weeks||0===t&&ei.lweek)return null;var r=7*(t-1)-i.fweek+e,o=new Date(i.start.time);return o.setDate(+i.start.d+r),this.getDateInfo(o)},t.create=function(e,n){var i=[];return e.eachComponent("calendar",(function(r){var o=new t(r,e,n);i.push(o),r.coordinateSystem=o})),e.eachComponent((function(t,e){Rp({targetModel:e,coordSysType:"calendar",coordSysProvider:Np})})),i},t.dimensions=["time","value"],t}();function kV(t){var e=t.calendarModel,n=t.seriesModel;return e?e.coordinateSystem:n?n.coordinateSystem:null}var LV=1,PV=2,OV=3,RV={none:0,all:1,body:2,corner:3};function NV(t,e,n){var i=e[lh[n]].getCell(t);return!i&&j(t)&&t<0&&(i=e[lh[1-n]].getUnitLayoutInfo(n,Math.round(t))),i}function zV(t){var e=t||[];return e[0]=e[0]||[],e[1]=e[1]||[],e[0][0]=e[0][1]=e[1][0]=e[1][1]=NaN,e}function EV(t,e,n,i,r){BV(t[0],e,r,n,i,0),BV(t[1],e,r,n,i,1)}function BV(t,e,n,i,r,o){t[0]=1/0,t[1]=-1/0;var a=i[o],s=U(a)?a:[a],l=s.length,u=!!n;if(l>=1?(VV(t,e,s,u,r,o,0),l>1&&VV(t,e,s,u,r,o,l-1)):t[0]=t[1]=NaN,u){var c=-r[lh[1-o]].getLocatorCount(o),h=r[lh[o]].getLocatorCount(o)-1;n===RV.body?c=po(0,c):n===RV.corner&&(h=ho(-1,h)),h=e[0]&&t[0]<=e[1]}function YV(t,e){t.id.set(e[0][0],e[1][0]),t.span.set(e[0][1]-t.id.x+1,e[1][1]-t.id.y+1)}function XV(t,e,n,i){var r=NV(e[i][0],n,i),o=NV(e[i][1],n,i);t[lh[i]]=t[uh[i]]=NaN,r&&o&&(t[lh[i]]=r.xy,t[uh[i]]=o.xy+o.wh-r.xy)}function ZV(t,e,n,i){return t[lh[e]]=n,t[lh[1-e]]=i,t}var jV=function(){function t(t,e){this._cells=[],this._levels=[],this.dim=t,this.dimIdx="x"===t?0:1,this._model=e,this._uniqueValueGen=function(t){var e=t.toUpperCase(),n=new RegExp("^"+e+"([0-9]+)$"),i=0;function r(t){var e;null!=t&&(e=t.match(n))&&(i=po(i,+e[1]+1))}function o(){return""+e+i++}function a(t,e){for(var n=yt(),i=0;i=1,x=n[lh[i]],_=o.getLocatorCount(i)-1,b=new va;for(a.resetLayoutIterator(b,i);b.next();)w(b.item);for(o.resetLayoutIterator(b,i);b.next();)w(b.item);function w(t){nt(t.wh)&&(t.wh=v),t.xy=x,t.id[lh[i]]!==_||m||(t.wh=n[lh[i]]+n[uh[i]]-t.xy),x+=t.wh}}function _G(t,e){for(var n=e[lh[t]].resetCellIterator();n.next();){var i=n.item;wG(i.rect,t,i.id,i.span,e),wG(i.rect,1-t,i.id,i.span,e),i.type===OV&&(i.xy=i.rect[lh[t]],i.wh=i.rect[uh[t]])}}function bG(t,e){t.travelExistingCells((function(t){var n=t.span;if(n){var i=t.spanRect,r=t.id;wG(i,0,r,n,e),wG(i,1,r,n,e)}}))}function wG(t,e,n,i,r){t[uh[e]]=0;var o=n[lh[e]]<0?r[lh[1-e]]:r[lh[e]],a=o.getUnitLayoutInfo(e,n[lh[e]]);if(t[lh[e]]=a.xy,t[uh[e]]=a.wh,i[lh[e]]>1){var s=o.getUnitLayoutInfo(e,n[lh[e]]+i[lh[e]]-1);t[uh[e]]=s.xy+s.wh-a.xy}}function SG(t,e){return Math.max(Math.min(t,rt(e,1/0)),0)}function MG(t){var e=t.matrixModel,n=t.seriesModel;return e?e.coordinateSystem:n?n.coordinateSystem:null}var IG={inBody:1,inCorner:2,outside:3},TG={x:null,y:null,point:[]};function CG(t,e,n,i,r){var o=n[lh[e]],a=n[lh[1-e]],s=o.getUnitLayoutInfo(e,o.getLocatorCount(e)-1),l=o.getUnitLayoutInfo(e,0),u=a.getUnitLayoutInfo(e,-a.getLocatorCount(e)),c=a.shouldShow()?a.getUnitLayoutInfo(e,-1):null,h=t.point[e]=i[e];if(l||c)if(r!==RV.body)if(r!==RV.corner){var d=l?l.xy:c?c.xy+c.wh:NaN,p=u?u.xy:d,f=s?s.xy+s.wh:d;if(hf){if(!r)return void(t[lh[e]]=IG.outside);h=f}t.point[e]=h,t[lh[e]]=d<=h&&h<=f?IG.inBody:p<=h&&h<=d?IG.inCorner:IG.outside}else c?(t[lh[e]]=IG.inCorner,h=ho(c.xy+c.wh,po(u.xy,h)),t.point[e]=h):t[lh[e]]=IG.outside;else l?(t[lh[e]]=IG.inBody,h=ho(s.xy+s.wh,po(l.xy,h)),t.point[e]=h):t[lh[e]]=IG.outside;else t[lh[e]]=IG.outside}function DG(t,e,n,i){var r=1-n;if(t[lh[n]]!==IG.outside)for(i[lh[n]].resetCellIterator(mG);mG.next();){var o=mG.item;if(kG(t.point[n],o.rect,n)&&kG(t.point[r],o.rect,r))return e[n]=o.ordinal,void(e[r]=o.id[lh[r]])}}function AG(t,e,n,i){var r,o;if(t[lh[n]]!==IG.outside)for((t[lh[n]]===IG.inCorner?i[lh[1-n]]:i[lh[n]]).resetLayoutIterator(vG,n);vG.next();)if(r=t.point[n],(o=vG.item).xy<=r&&r<=o.xy+o.wh)return void(e[n]=vG.item.id[lh[n]])}function kG(t,e,n){return e[lh[n]]<=t&&t<=e[lh[n]]+e[uh[n]]}function LG(t,e){var n;return z(e,(function(e){null!=t[e]&&"auto"!==t[e]&&(n=!0)})),n}var PG=["transition","enterFrom","leaveTo"],OG=PG.concat(["enterAnimation","updateAnimation","leaveAnimation"]);function RG(t,e,n){if(n&&(!t[n]&&e[n]&&(t[n]={}),t=t[n],e=e[n]),t&&e)for(var i=n?PG:OG,r=0;r=0;l--){var d,p,f;if(f=null!=(p=ia((d=n[l]).id,null))?r.get(p):null){var g=f.parent,y=(h=EG(g),{}),v=Zp(f,d,g===i?{width:o,height:a}:{width:h.width,height:h.height},null,{hv:d.hv,boundingMode:d.bounding},y);if(!EG(f).isNew&&v){for(var m=d.transition,x={},_=0;_=0)?x[b]=w:f[b]=w}th(f,x,t,0)}else f.attr(y)}}},e.prototype._clear=function(){var t=this,e=this._elMap;e.each((function(n){FG(n,EG(n).option,e,t._lastGraphicModel)})),this._elMap=yt()},e.prototype.dispose=function(){this._clear()},e.type="graphic",e}(Ky);function VG(t){var e=_t(zG,t)?zG[t]:fh(t);var n=new e({});return EG(n).type=t,n}function GG(t,e,n,i){var r=VG(n);return e.add(r),i.set(t,r),EG(r).id=t,EG(r).isNew=!0,r}function FG(t,e,n,i){t&&t.parent&&("group"===t.type&&t.traverse((function(t){FG(t,e,n,i)})),aE(t,e,i),n.removeKey(EG(t).id))}function WG(t,e,n,i){t.isGroup||z([["cursor",os.prototype.cursor],["zlevel",i||0],["z",n||0],["z2",0]],(function(n){var i=n[0];_t(e,i)?t[i]=rt(e[i],n[1]):null==t[i]&&(t[i]=n[1])})),z(F(e),(function(n){if(0===n.indexOf("on")){var i=e[n];t[n]=Y(i)?i:null}})),_t(e,"draggable")&&(t.draggable=e.draggable),null!=e.name&&(t.name=e.name),null!=e.id&&(t.id=e.id)}var HG=["x","y","radius","angle","single"],UG=["cartesian2d","polar","singleAxis"];function YG(t){return t+"Axis"}function XG(t,e){var n,i=yt(),r=[],o=yt();t.eachComponent({mainType:"dataZoom",query:e},(function(t){o.get(t.uid)||s(t)}));do{n=!1,t.eachComponent("dataZoom",a)}while(n);function a(t){!o.get(t.uid)&&function(t){var e=!1;return t.eachTargetAxis((function(t,n){var r=i.get(t);r&&r[n]&&(e=!0)})),e}(t)&&(s(t),n=!0)}function s(t){o.set(t.uid,!0),r.push(t),t.eachTargetAxis((function(t,e){(i.get(t)||i.set(t,[]))[e]=!0}))}return r}function ZG(t){var e=t.ecModel,n={infoList:[],infoMap:yt()};return t.eachTargetAxis((function(t,i){var r=e.getComponent(YG(t),i);if(r){var o=r.getCoordSysModel();if(o){var a=o.uid,s=n.infoMap.get(a);s||(s={model:o,axisModels:[]},n.infoList.push(s),n.infoMap.set(a,s)),s.axisModels.push(r)}}})),n}var jG=function(){function t(){this.indexList=[],this.indexMap=[]}return t.prototype.add=function(t){this.indexMap[t]||(this.indexList.push(t),this.indexMap[t]=!0)},t}(),qG=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._autoThrottle=!0,n._noTarget=!0,n._rangePropMode=["percent","percent"],n}return n(e,t),e.prototype.init=function(t,e,n){var i=KG(t);this.settledOption=i,this.mergeDefaultAndTheme(t,n),this._doInit(i)},e.prototype.mergeOption=function(t){var e=KG(t);C(this.option,t,!0),C(this.settledOption,e,!0),this._doInit(e)},e.prototype._doInit=function(t){var e=this.option;this._setDefaultThrottle(t),this._updateRangeUse(t);var n=this.settledOption;z([["start","startValue"],["end","endValue"]],(function(t,i){"value"===this._rangePropMode[i]&&(e[t[0]]=n[t[0]]=null)}),this),this._resetTarget()},e.prototype._resetTarget=function(){var t=this.get("orient",!0),e=this._targetAxisInfoMap=yt();this._fillSpecifiedTargetAxis(e)?this._orient=t||this._makeAutoOrientByTargetAxis():(this._orient=t||"horizontal",this._fillAutoTargetAxisByOrient(e,this._orient)),this._noTarget=!0,e.each((function(t){t.indexList.length&&(this._noTarget=!1)}),this)},e.prototype._fillSpecifiedTargetAxis=function(t){var e=!1;return z(HG,(function(n){var i=this.getReferringComponents(YG(n),da);if(i.specified){e=!0;var r=new jG;z(i.models,(function(t){r.add(t.componentIndex)})),t.set(n,r)}}),this),e},e.prototype._fillAutoTargetAxisByOrient=function(t,e){var n=this.ecModel,i=!0;if(i){var r="vertical"===e?"y":"x";o(n.findComponents({mainType:r+"Axis"}),r)}i&&o(n.findComponents({mainType:"singleAxis",filter:function(t){return t.get("orient",!0)===e}}),"single");function o(e,n){var r=e[0];if(r){var o=new jG;if(o.add(r.componentIndex),t.set(n,o),i=!1,"x"===n||"y"===n){var a=r.getReferringComponents("grid",ha).models[0];a&&z(e,(function(t){r.componentIndex!==t.componentIndex&&a===t.getReferringComponents("grid",ha).models[0]&&o.add(t.componentIndex)}))}}}i&&z(HG,(function(e){if(i){var r=n.findComponents({mainType:YG(e),filter:function(t){return"category"===t.get("type",!0)}});if(r[0]){var o=new jG;o.add(r[0].componentIndex),t.set(e,o),i=!1}}}),this)},e.prototype._makeAutoOrientByTargetAxis=function(){var t;return this.eachTargetAxis((function(e){!t&&(t=e)}),this),"y"===t?"vertical":"horizontal"},e.prototype._setDefaultThrottle=function(t){if(t.hasOwnProperty("throttle")&&(this._autoThrottle=!1),this._autoThrottle){var e=this.ecModel.option;this.option.throttle=e.animation&&e.animationDurationUpdate>0?100:20}},e.prototype._updateRangeUse=function(t){var e=this._rangePropMode,n=this.get("rangeMode");z([["start","startValue"],["end","endValue"]],(function(i,r){var o=null!=t[i[0]],a=null!=t[i[1]];o&&!a?e[r]="percent":!o&&a?e[r]="value":n?e[r]=n[r]:o&&(e[r]="percent")}))},e.prototype.noTarget=function(){return this._noTarget},e.prototype.getFirstTargetAxisModel=function(){var t;return this.eachTargetAxis((function(e,n){null==t&&(t=this.ecModel.getComponent(YG(e),n))}),this),t},e.prototype.eachTargetAxis=function(t,e){this._targetAxisInfoMap.each((function(n,i){z(n.indexList,(function(n){t.call(e,i,n)}))}))},e.prototype.getAxisProxy=function(t,e){var n=this.getAxisModel(t,e);if(n)return n.__dzAxisProxy},e.prototype.getAxisModel=function(t,e){var n=this._targetAxisInfoMap.get(t);if(n&&n.indexMap[e])return this.ecModel.getComponent(YG(t),e)},e.prototype.setRawRange=function(t){var e=this.option,n=this.settledOption;z([["start","startValue"],["end","endValue"]],(function(i){null==t[i[0]]&&null==t[i[1]]||(e[i[0]]=n[i[0]]=t[i[0]],e[i[1]]=n[i[1]]=t[i[1]])}),this),this._updateRangeUse(t)},e.prototype.setCalculatedRange=function(t){var e=this.option;z(["start","startValue","end","endValue"],(function(n){e[n]=t[n]}))},e.prototype.getPercentRange=function(){var t=this.findRepresentativeAxisProxy();if(t)return t.getDataPercentWindow()},e.prototype.getValueRange=function(t,e){if(null!=t||null!=e)return this.getAxisProxy(t,e).getDataValueWindow();var n=this.findRepresentativeAxisProxy();return n?n.getDataValueWindow():void 0},e.prototype.findRepresentativeAxisProxy=function(t){if(t)return t.__dzAxisProxy;for(var e,n=this._targetAxisInfoMap.keys(),i=0;i=0}(e)){var n=YG(this._dimName),i=e.getReferringComponents(n,ha).models[0];i&&this._axisIndex===i.componentIndex&&t.push(e)}}),this),t},t.prototype.getAxisModel=function(){return this.ecModel.getComponent(this._dimName+"Axis",this._axisIndex)},t.prototype.getMinMaxSpan=function(){return T(this._minMaxSpan)},t.prototype.calculateDataWindow=function(t){var e,n=this._dataExtent,i=this.getAxisModel().axis.scale,r=this._dataZoomModel.getRangePropMode(),o=[0,100],a=[],s=[];tF(["start","end"],(function(l,u){var c=t[l],h=t[l+"Value"];"percent"===r[u]?(null==c&&(c=o[u]),h=i.parse(go(c,o,n))):(e=!0,c=go(h=null==h?n[u]:i.parse(h),n,o)),s[u]=null==h||isNaN(h)?n[u]:h,a[u]=null==c||isNaN(c)?o[u]:c})),eF(s),eF(a);var l=this._minMaxSpan;function u(t,e,n,r,o){var a=o?"Span":"ValueSpan";CO(0,t,n,"all",l["min"+a],l["max"+a]);for(var s=0;s<2;s++)e[s]=go(t[s],n,r,!0),o&&(e[s]=i.parse(e[s]))}return e?u(s,a,n,o,!1):u(a,s,o,n,!0),{valueWindow:s,percentWindow:a}},t.prototype.reset=function(t){if(t===this._dataZoomModel){var e=this.getTargetSeriesModels();this._dataExtent=function(t,e,n){var i=[1/0,-1/0];tF(n,(function(t){!function(t,e,n){e&&z(Jb(e,n),(function(n){var i=e.getApproximateExtent(n);i[0]t[1]&&(t[1]=i[1])}))}(i,t.getData(),e)}));var r=t.getAxisModel(),o=Hb(r.axis.scale,r,i).calculate();return[o.min,o.max]}(this,this._dimName,e),this._updateMinMaxSpan();var n=this.calculateDataWindow(t.settledOption);this._valueWindow=n.valueWindow,this._percentWindow=n.percentWindow,this._setAxisModel()}},t.prototype.filterData=function(t,e){if(t===this._dataZoomModel){var n=this._dimName,i=this.getTargetSeriesModels(),r=t.get("filterMode"),o=this._valueWindow;"none"!==r&&tF(i,(function(t){var e=t.getData(),i=e.mapDimensionsAll(n);if(i.length){if("weakFilter"===r){var a=e.getStore(),s=E(i,(function(t){return e.getDimensionIndex(t)}),e);e.filterSelf((function(t){for(var e,n,r,l=0;lo[1];if(c&&!h&&!d)return!0;c&&(r=!0),h&&(e=!0),d&&(n=!0)}return r&&e&&n}))}else tF(i,(function(n){if("empty"===r)t.setData(e=e.map(n,(function(t){return function(t){return t>=o[0]&&t<=o[1]}(t)?t:NaN})));else{var i={};i[n]=o,e.selectRange(i)}}));tF(i,(function(t){e.setApproximateExtent(o,t)}))}}))}},t.prototype._updateMinMaxSpan=function(){var t=this._minMaxSpan={},e=this._dataZoomModel,n=this._dataExtent;tF(["min","max"],(function(i){var r=e.get(i+"Span"),o=e.get(i+"ValueSpan");null!=o&&(o=this.getAxisModel().axis.scale.parse(o)),null!=o?r=go(n[0]+o,n,[0,100],!0):null!=r&&(o=go(r,[0,100],n,!0)-n[0]),t[i+"Span"]=r,t[i+"ValueSpan"]=o}),this)},t.prototype._setAxisModel=function(){var t=this.getAxisModel(),e=this._percentWindow,n=this._valueWindow;if(e){var i=wo(n,[0,500]);i=Math.min(i,20);var r=t.axis.scale.rawExtentInfo;0!==e[0]&&r.setDeterminedMinMax("min",+n[0].toFixed(i)),100!==e[1]&&r.setDeterminedMinMax("max",+n[1].toFixed(i)),r.freeze()}},t}();var iF={getTargetSeries:function(t){function e(e){t.eachComponent("dataZoom",(function(n){n.eachTargetAxis((function(i,r){var o=t.getComponent(YG(i),r);e(i,r,o,n)}))}))}e((function(t,e,n,i){n.__dzAxisProxy=null}));var n=[];e((function(e,i,r,o){r.__dzAxisProxy||(r.__dzAxisProxy=new nF(e,i,o,t),n.push(r.__dzAxisProxy))}));var i=yt();return z(n,(function(t){z(t.getTargetSeriesModels(),(function(t){i.set(t.uid,t)}))})),i},overallReset:function(t,e){t.eachComponent("dataZoom",(function(t){t.eachTargetAxis((function(e,n){t.getAxisProxy(e,n).reset(t)})),t.eachTargetAxis((function(n,i){t.getAxisProxy(n,i).filterData(t,e)}))})),t.eachComponent("dataZoom",(function(t){var e=t.findRepresentativeAxisProxy();if(e){var n=e.getDataPercentWindow(),i=e.getDataValueWindow();t.setCalculatedRange({start:n[0],end:n[1],startValue:i[0],endValue:i[1]})}}))}};var rF=!1;function oF(t){rF||(rF=!0,t.registerProcessor(t.PRIORITY.PROCESSOR.FILTER,iF),function(t){t.registerAction("dataZoom",(function(t,e){z(XG(e,t),(function(e){e.setRawRange({start:t.start,end:t.end,startValue:t.startValue,endValue:t.endValue})}))}))}(t),t.registerSubTypeDefaulter("dataZoom",(function(){return"slider"})))}function aF(t){t.registerComponentModel($G),t.registerComponentView(QG),oF(t)}var sF=function(){},lF={};function uF(t,e){lF[t]=e}function cF(t){return lF[t]}var hF=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.optionUpdated=function(){t.prototype.optionUpdated.apply(this,arguments);var e=this.ecModel;z(this.option.feature,(function(t,n){var i=cF(n);i&&(i.getDefaultOption&&(i.defaultOption=i.getDefaultOption(e)),C(t,i.defaultOption))}))},e.type="toolbox",e.layoutMode={type:"box",ignoreSize:!0},e.defaultOption={show:!0,z:6,orient:"horizontal",left:"right",top:"top",backgroundColor:"transparent",borderColor:tf.color.border,borderRadius:0,borderWidth:0,padding:tf.size.m,itemSize:15,itemGap:tf.size.s,showTitle:!0,iconStyle:{borderColor:tf.color.accent50,color:"none"},emphasis:{iconStyle:{borderColor:tf.color.accent50}},tooltip:{show:!1,position:"bottom"}},e}(Qp);function dF(t,e){var n=yp(e.get("padding")),i=e.getItemStyle(["color","opacity"]);return i.fill=e.get("backgroundColor"),new xl({shape:{x:t.x-n[3],y:t.y-n[0],width:t.width+n[1]+n[3],height:t.height+n[0]+n[2],r:e.get("borderRadius")},style:i,silent:!0,z2:-1})}var pF=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.render=function(t,e,n,i){var r=this.group;if(r.removeAll(),t.get("show")){var o=+t.get("itemSize"),a="vertical"===t.get("orient"),s=t.get("feature")||{},l=this._features||(this._features={}),u=[];z(s,(function(t,e){u.push(e)})),new f_(this._featureNames||[],u).add(f).update(f).remove(H(f,null)).execute(),this._featureNames=u;var c=Xp(t,n).refContainer,h=t.getBoxLayoutParams(),d=t.get("padding"),p=Hp(h,c,d);Gp(t.get("orient"),r,t.get("itemGap"),p.width,p.height),Zp(r,h,c,d),r.add(dF(r.getBoundingRect(),t)),a||r.eachChild((function(t){var e=t.__title,i=t.ensureState("emphasis"),a=i.textConfig||(i.textConfig={}),s=t.getTextContent(),l=s&&s.ensureState("emphasis");if(l&&!Y(l)&&e){var u=l.style||(l.style={}),c=Er(e,Sl.makeFont(u)),h=t.x+r.x,d=!1;t.y+r.y+o+c.height>n.getHeight()&&(a.position="top",d=!0);var p=d?-5-c.height:o+10;h+c.width/2>n.getWidth()?(a.position=["100%",p],u.align="right"):h-c.width/2<0&&(a.position=[0,p],u.align="left")}}))}function f(c,h){var d,p=u[c],f=u[h],g=s[p],y=new wd(g,t,t.ecModel);if(i&&null!=i.newTitle&&i.featureName===p&&(g.title=i.newTitle),p&&!f){if(function(t){return 0===t.indexOf("my")}(p))d={onclick:y.option.onclick,featureName:p};else{var v=cF(p);if(!v)return;d=new v}l[p]=d}else if(!(d=l[f]))return;d.uid=Md("toolbox-feature"),d.model=y,d.ecModel=e,d.api=n;var m=d instanceof sF;p||!f?!y.get("show")||m&&d.unusable?m&&d.remove&&d.remove(e,n):(!function(i,s,l){var u,c,h=i.getModel("iconStyle"),d=i.getModel(["emphasis","iconStyle"]),p=s instanceof sF&&s.getIcons?s.getIcons():i.get("icon"),f=i.get("title")||{};X(p)?(u={})[l]=p:u=p;X(f)?(c={})[l]=f:c=f;var g=i.iconPaths={};z(u,(function(l,u){var p=Ah(l,{},{x:-o/2,y:-o/2,width:o,height:o});p.setStyle(h.getItemStyle()),p.ensureState("emphasis").style=d.getItemStyle();var f=new Sl({style:{text:c[u],align:d.get("textAlign"),borderRadius:d.get("textBorderRadius"),padding:d.get("textPadding"),fill:null,font:od({fontStyle:d.get("textFontStyle"),fontFamily:d.get("textFontFamily"),fontSize:d.get("textFontSize"),fontWeight:d.get("textFontWeight")},e)},ignore:!0});p.setTextContent(f),zh({el:p,componentModel:t,itemName:u,formatterParamsExtra:{title:c[u]}}),p.__title=c[u],p.on("mouseover",(function(){var e=d.getItemStyle(),i=a?null==t.get("right")&&"right"!==t.get("left")?"right":"left":null==t.get("bottom")&&"bottom"!==t.get("top")?"bottom":"top";f.setStyle({fill:d.get("textFill")||e.fill||e.stroke||tf.color.neutral99,backgroundColor:d.get("textBackgroundColor")}),p.setTextConfig({position:d.get("textPosition")||i}),f.ignore=!t.get("showTitle"),n.enterEmphasis(this)})).on("mouseout",(function(){"emphasis"!==i.get(["iconStatus",u])&&n.leaveEmphasis(this),f.hide()})),("emphasis"===i.get(["iconStatus",u])?du:pu)(p),r.add(p),p.on("click",W(s.onclick,s,e,n,u)),g[u]=p}))}(y,d,p),y.setIconStatus=function(t,e){var n=this.option,i=this.iconPaths;n.iconStatus=n.iconStatus||{},n.iconStatus[t]=e,i[t]&&("emphasis"===e?du:pu)(i[t])},d instanceof sF&&d.render&&d.render(y,e,n,i)):m&&d.dispose&&d.dispose(e,n)}},e.prototype.updateView=function(t,e,n,i){z(this._features,(function(t){t instanceof sF&&t.updateView&&t.updateView(t.model,e,n,i)}))},e.prototype.remove=function(t,e){z(this._features,(function(n){n instanceof sF&&n.remove&&n.remove(t,e)})),this.group.removeAll()},e.prototype.dispose=function(t,e){z(this._features,(function(n){n instanceof sF&&n.dispose&&n.dispose(t,e)}))},e.type="toolbox",e}(Ky);var fF=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.onclick=function(t,e){var n=this.model,i=n.get("name")||t.get("title.0.text")||"echarts",o="svg"===e.getZr().painter.getType(),a=o?"svg":n.get("type",!0)||"png",s=e.getConnectedDataURL({type:a,backgroundColor:n.get("backgroundColor",!0)||t.get("backgroundColor")||tf.color.neutral00,connectedBackgroundColor:n.get("connectedBackgroundColor"),excludeComponents:n.get("excludeComponents"),pixelRatio:n.get("pixelRatio")}),l=r.browser;if("function"!=typeof MouseEvent||!l.newEdge&&(l.ie||l.edge))if(window.navigator.msSaveOrOpenBlob||o){var u=s.split(","),c=u[0].indexOf("base64")>-1,h=o?decodeURIComponent(u[1]):u[1];c&&(h=window.atob(h));var d=i+"."+a;if(window.navigator.msSaveOrOpenBlob){for(var p=h.length,f=new Uint8Array(p);p--;)f[p]=h.charCodeAt(p);var g=new Blob([f]);window.navigator.msSaveOrOpenBlob(g,d)}else{var y=document.createElement("iframe");document.body.appendChild(y);var v=y.contentWindow,m=v.document;m.open("image/svg+xml","replace"),m.write(h),m.close(),v.focus(),m.execCommand("SaveAs",!0,d),document.body.removeChild(y)}}else{var x=n.get("lang"),_='',b=window.open();b.document.write(_),b.document.title=i}else{var w=document.createElement("a");w.download=i+"."+a,w.target="_blank",w.href=s;var S=new MouseEvent("click",{view:document.defaultView,bubbles:!0,cancelable:!1});w.dispatchEvent(S)}},e.getDefaultOption=function(t){return{show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:t.getLocaleModel().get(["toolbox","saveAsImage","title"]),type:"png",connectedBackgroundColor:tf.color.neutral00,name:"",excludeComponents:["toolbox"],lang:t.getLocaleModel().get(["toolbox","saveAsImage","lang"])}},e}(sF),gF="__ec_magicType_stack__",yF=[["line","bar"],["stack"]],vF=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.getIcons=function(){var t=this.model,e=t.get("icon"),n={};return z(t.get("type"),(function(t){e[t]&&(n[t]=e[t])})),n},e.getDefaultOption=function(t){return{show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z"},title:t.getLocaleModel().get(["toolbox","magicType","title"]),option:{},seriesIndex:{}}},e.prototype.onclick=function(t,e,n){var i=this.model,r=i.get(["seriesIndex",n]);if(mF[n]){var o,a={series:[]};z(yF,(function(t){P(t,n)>=0&&z(t,(function(t){i.setIconStatus(t,"normal")}))})),i.setIconStatus(n,"emphasis"),t.eachComponent({mainType:"series",query:null==r?null:{seriesIndex:r}},(function(t){var e=t.subType,r=t.id,o=mF[n](e,r,t,i);o&&(k(o,t.option),a.series.push(o));var s=t.coordinateSystem;if(s&&"cartesian2d"===s.type&&("line"===n||"bar"===n)){var l=s.getAxesByScale("ordinal")[0];if(l){var u=l.dim+"Axis",c=t.getReferringComponents(u,ha).models[0].componentIndex;a[u]=a[u]||[];for(var h=0;h<=c;h++)a[u][c]=a[u][c]||{};a[u][c].boundaryGap="bar"===n}}}));var s=n;"stack"===n&&(o=C({stack:i.option.title.tiled,tiled:i.option.title.stack},i.option.title),"emphasis"!==i.get(["iconStatus",n])&&(s="tiled")),e.dispatchAction({type:"changeMagicType",currentType:s,newOption:a,newTitle:o,featureName:"magicType"})}},e}(sF),mF={line:function(t,e,n,i){if("bar"===t)return C({id:e,type:"line",data:n.get("data"),stack:n.get("stack"),markPoint:n.get("markPoint"),markLine:n.get("markLine")},i.get(["option","line"])||{},!0)},bar:function(t,e,n,i){if("line"===t)return C({id:e,type:"bar",data:n.get("data"),stack:n.get("stack"),markPoint:n.get("markPoint"),markLine:n.get("markLine")},i.get(["option","bar"])||{},!0)},stack:function(t,e,n,i){var r=n.get("stack")===gF;if("line"===t||"bar"===t)return i.setIconStatus("stack",r?"normal":"emphasis"),C({id:e,stack:r?"":gF},i.get(["option","stack"])||{},!0)}};Qx({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},(function(t,e){e.mergeOption(t.newOption)}));var xF=new Array(60).join("-"),_F="\t";function bF(t){return t.replace(/^\s\s*/,"").replace(/\s\s*$/,"")}var wF=new RegExp("[\t]+","g");function SF(t,e){var n=t.split(new RegExp("\n*"+xF+"\n*","g")),i={series:[]};return z(n,(function(t,n){if(function(t){if(t.slice(0,t.indexOf("\n")).indexOf(_F)>=0)return!0}(t)){var r=function(t){for(var e=t.split(/\n+/g),n=[],i=E(bF(e.shift()).split(wF),(function(t){return{name:t,data:[]}})),r=0;r=0)&&t(r,i._targetInfoList)}))}return t.prototype.setOutputRanges=function(t,e){return this.matchOutputRanges(t,e,(function(t,e,n){if((t.coordRanges||(t.coordRanges=[])).push(e),!t.coordRange){t.coordRange=e;var i=EF[t.brushType](0,n,e);t.__rangeOffset={offset:VF[t.brushType](i.values,t.range,[1,1]),xyMinMax:i.xyMinMax}}})),t},t.prototype.matchOutputRanges=function(t,e,n){z(t,(function(t){var i=this.findTargetInfo(t,e);i&&!0!==i&&z(i.coordSyses,(function(i){var r=EF[t.brushType](1,i,t.range,!0);n(t,r.values,i,e)}))}),this)},t.prototype.setInputRanges=function(t,e){z(t,(function(t){var n,i,r,o,a,s=this.findTargetInfo(t,e);if(t.range=t.range||[],s&&!0!==s){t.panelId=s.panelId;var l=EF[t.brushType](0,s.coordSys,t.coordRange),u=t.__rangeOffset;t.range=u?VF[t.brushType](l.values,u.offset,(n=l.xyMinMax,i=u.xyMinMax,r=FF(n),o=FF(i),a=[r[0]/o[0],r[1]/o[1]],isNaN(a[0])&&(a[0]=1),isNaN(a[1])&&(a[1]=1),a)):l.values}}),this)},t.prototype.makePanelOpts=function(t,e){return E(this._targetInfoList,(function(n){var i=n.getPanelRect();return{panelId:n.panelId,defaultBrushType:e?e(n):null,clipPath:AR(i),isTargetByCursor:LR(i,t,n.coordSysModel),getLinearBrushOtherExtent:kR(i)}}))},t.prototype.controlSeries=function(t,e,n){var i=this.findTargetInfo(t,n);return!0===i||i&&P(i.coordSyses,e.coordinateSystem)>=0},t.prototype.findTargetInfo=function(t,e){for(var n=this._targetInfoList,i=OF(e,t),r=0;rt[1]&&t.reverse(),t}function OF(t,e){return ua(t,e,{includeMainTypes:kF})}var RF={grid:function(t,e){var n=t.xAxisModels,i=t.yAxisModels,r=t.gridModels,o=yt(),a={},s={};(n||i||r)&&(z(n,(function(t){var e=t.axis.grid.model;o.set(e.id,e),a[e.id]=!0})),z(i,(function(t){var e=t.axis.grid.model;o.set(e.id,e),s[e.id]=!0})),z(r,(function(t){o.set(t.id,t),a[t.id]=!0,s[t.id]=!0})),o.each((function(t){var r=t.coordinateSystem,o=[];z(r.getCartesians(),(function(t,e){(P(n,t.getAxis("x").model)>=0||P(i,t.getAxis("y").model)>=0)&&o.push(t)})),e.push({panelId:"grid--"+t.id,gridModel:t,coordSysModel:t,coordSys:o[0],coordSyses:o,getPanelRect:zF.grid,xAxisDeclared:a[t.id],yAxisDeclared:s[t.id]})})))},geo:function(t,e){z(t.geoModels,(function(t){var n=t.coordinateSystem;e.push({panelId:"geo--"+t.id,geoModel:t,coordSysModel:t,coordSys:n,coordSyses:[n],getPanelRect:zF.geo})}))}},NF=[function(t,e){var n=t.xAxisModel,i=t.yAxisModel,r=t.gridModel;return!r&&n&&(r=n.axis.grid.model),!r&&i&&(r=i.axis.grid.model),r&&r===e.gridModel},function(t,e){var n=t.geoModel;return n&&n===e.geoModel}],zF={grid:function(){return this.coordSys.master.getRect().clone()},geo:function(){var t=this.coordSys,e=t.getBoundingRect().clone();return e.applyTransform(wh(t)),e}},EF={lineX:H(BF,0),lineY:H(BF,1),rect:function(t,e,n,i){var r=t?e.pointToData([n[0][0],n[1][0]],i):e.dataToPoint([n[0][0],n[1][0]],i),o=t?e.pointToData([n[0][1],n[1][1]],i):e.dataToPoint([n[0][1],n[1][1]],i),a=[PF([r[0],o[0]]),PF([r[1],o[1]])];return{values:a,xyMinMax:a}},polygon:function(t,e,n,i){var r=[[1/0,-1/0],[1/0,-1/0]];return{values:E(n,(function(n){var o=t?e.pointToData(n,i):e.dataToPoint(n,i);return r[0][0]=Math.min(r[0][0],o[0]),r[1][0]=Math.min(r[1][0],o[1]),r[0][1]=Math.max(r[0][1],o[0]),r[1][1]=Math.max(r[1][1],o[1]),o})),xyMinMax:r}}};function BF(t,e,n,i){var r=n.getAxis(["x","y"][t]),o=PF(E([0,1],(function(t){return e?r.coordToData(r.toLocalCoord(i[t]),!0):r.toGlobalCoord(r.dataToCoord(i[t]))}))),a=[];return a[t]=o,a[1-t]=[NaN,NaN],{values:o,xyMinMax:a}}var VF={lineX:H(GF,0),lineY:H(GF,1),rect:function(t,e,n){return[[t[0][0]-n[0]*e[0][0],t[0][1]-n[0]*e[0][1]],[t[1][0]-n[1]*e[1][0],t[1][1]-n[1]*e[1][1]]]},polygon:function(t,e,n){return E(t,(function(t,i){return[t[0]-n[0]*e[i][0],t[1]-n[1]*e[i][1]]}))}};function GF(t,e,n,i){return[e[0]-i[t]*n[0],e[1]-i[t]*n[1]]}function FF(t){return t?[t[0][1]-t[0][0],t[1][1]-t[1][0]]:[NaN,NaN]}var WF,HF,UF=z,YF=jo+"toolbox-dataZoom_",XF=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.render=function(t,e,n,i){this._brushController||(this._brushController=new JO(n.getZr()),this._brushController.on("brush",W(this._onBrush,this)).mount()),function(t,e,n,i,r){var o=n._isZoomActive;i&&"takeGlobalCursor"===i.type&&(o="dataZoomSelect"===i.key&&i.dataZoomSelectActive);n._isZoomActive=o,t.setIconStatus("zoom",o?"emphasis":"normal");var a=new LF(jF(t),e,{include:["grid"]}),s=a.makePanelOpts(r,(function(t){return t.xAxisDeclared&&!t.yAxisDeclared?"lineX":!t.xAxisDeclared&&t.yAxisDeclared?"lineY":"rect"}));n._brushController.setPanels(s).enableBrush(!(!o||!s.length)&&{brushType:"auto",brushStyle:t.getModel("brushStyle").getItemStyle()})}(t,e,this,i,n),function(t,e){t.setIconStatus("back",function(t){return DF(t).length}(e)>1?"emphasis":"normal")}(t,e)},e.prototype.onclick=function(t,e,n){ZF[n].call(this)},e.prototype.remove=function(t,e){this._brushController&&this._brushController.unmount()},e.prototype.dispose=function(t,e){this._brushController&&this._brushController.dispose()},e.prototype._onBrush=function(t){var e=t.areas;if(t.isEnd&&e.length){var n={},i=this.ecModel;this._brushController.updateCovers([]),new LF(jF(this.model),i,{include:["grid"]}).matchOutputRanges(e,i,(function(t,e,n){if("cartesian2d"===n.type){var i=t.brushType;"rect"===i?(r("x",n,e[0]),r("y",n,e[1])):r({lineX:"x",lineY:"y"}[i],n,e)}})),function(t,e){var n=DF(t);TF(e,(function(e,i){for(var r=n.length-1;r>=0&&!n[r][i];r--);if(r<0){var o=t.queryComponents({mainType:"dataZoom",subType:"select",id:i})[0];if(o){var a=o.getPercentRange();n[0][i]={dataZoomId:i,start:a[0],end:a[1]}}}})),n.push(e)}(i,n),this._dispatchZoomAction(n)}function r(t,e,r){var o=e.getAxis(t),a=o.model,s=function(t,e,n){var i;return n.eachComponent({mainType:"dataZoom",subType:"select"},(function(n){n.getAxisModel(t,e.componentIndex)&&(i=n)})),i}(t,a,i),l=s.findRepresentativeAxisProxy(a).getMinMaxSpan();null==l.minValueSpan&&null==l.maxValueSpan||(r=CO(0,r.slice(),o.scale.getExtent(),0,l.minValueSpan,l.maxValueSpan)),s&&(n[s.id]={dataZoomId:s.id,startValue:r[0],endValue:r[1]})}},e.prototype._dispatchZoomAction=function(t){var e=[];UF(t,(function(t,n){e.push(T(t))})),e.length&&this.api.dispatchAction({type:"dataZoom",from:this.uid,batch:e})},e.getDefaultOption=function(t){return{show:!0,filterMode:"filter",icon:{zoom:"M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1",back:"M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26"},title:t.getLocaleModel().get(["toolbox","dataZoom","title"]),brushStyle:{borderWidth:0,color:tf.color.backgroundTint}}},e}(sF),ZF={zoom:function(){var t=!this._isZoomActive;this.api.dispatchAction({type:"takeGlobalCursor",key:"dataZoomSelect",dataZoomSelectActive:t})},back:function(){this._dispatchZoomAction(function(t){var e=DF(t),n=e[e.length-1];e.length>1&&e.pop();var i={};return TF(n,(function(t,n){for(var r=e.length-1;r>=0;r--)if(t=e[r][n]){i[n]=t;break}})),i}(this.ecModel))}};function jF(t){var e={xAxisIndex:t.get("xAxisIndex",!0),yAxisIndex:t.get("yAxisIndex",!0),xAxisId:t.get("xAxisId",!0),yAxisId:t.get("yAxisId",!0)};return null==e.xAxisIndex&&null==e.xAxisId&&(e.xAxisIndex="all"),null==e.yAxisIndex&&null==e.yAxisId&&(e.yAxisIndex="all"),e}WF="dataZoom",HF=function(t){var e=t.getComponent("toolbox",0),n=["feature","dataZoom"];if(e&&null!=e.get(n)){var i=e.getModel(n),r=[],o=ua(t,jF(i));return UF(o.xAxisModels,(function(t){return a(t,"xAxis","xAxisIndex")})),UF(o.yAxisModels,(function(t){return a(t,"yAxis","yAxisIndex")})),r}function a(t,e,n){var o=t.componentIndex,a={type:"select",$fromToolbox:!0,filterMode:i.get("filterMode",!0)||"filter",id:YF+e+o};a[n]=o,r.push(a)}},lt(null==Df.get(WF)&&HF),Df.set(WF,HF);var qF=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="tooltip",e.dependencies=["axisPointer"],e.defaultOption={z:60,show:!0,showContent:!0,trigger:"item",triggerOn:"mousemove|click",alwaysShowContent:!1,renderMode:"auto",confine:null,showDelay:0,hideDelay:100,transitionDuration:.4,displayTransition:!0,enterable:!1,backgroundColor:tf.color.neutral00,shadowBlur:10,shadowColor:"rgba(0, 0, 0, .2)",shadowOffsetX:1,shadowOffsetY:2,borderRadius:4,borderWidth:1,defaultBorderColor:tf.color.border,padding:null,extraCssText:"",axisPointer:{type:"line",axis:"auto",animation:"auto",animationDurationUpdate:200,animationEasingUpdate:"exponentialOut",crossStyle:{color:tf.color.borderShade,width:1,type:"dashed",textStyle:{}}},textStyle:{color:tf.color.tertiary,fontSize:14}},e}(Qp);function KF(t){var e=t.get("confine");return null!=e?!!e:"richText"===t.get("renderMode")}function $F(t){if(r.domSupported)for(var e=document.documentElement.style,n=0,i=t.length;n0&&o.push(function(t,e,n){var i="cubic-bezier(0.23,1,0.32,1)",o="",a="";return n&&(a="opacity"+(o=" "+t/2+"s "+i)+",visibility"+o),e||(o=" "+t+"s "+i,a+=(a.length?",":"")+(r.transformSupported?""+eW+o:",left"+o+",top"+o)),tW+":"+a}(a,n,i)),s&&o.push("background-color:"+s),z(["width","color","radius"],(function(e){var n="border-"+e,i=gp(n),r=t.get(i);null!=r&&o.push(n+":"+r+("color"===e?"":"px"))})),o.push(function(t){var e=[],n=t.get("fontSize"),i=t.getTextColor();i&&e.push("color:"+i),e.push("font:"+t.getFont());var r=rt(t.get("lineHeight"),Math.round(3*n/2));n&&e.push("line-height:"+r+"px");var o=t.get("textShadowColor"),a=t.get("textShadowBlur")||0,s=t.get("textShadowOffsetX")||0,l=t.get("textShadowOffsetY")||0;return o&&a&&e.push("text-shadow:"+s+"px "+l+"px "+a+"px "+o),z(["decoration","align"],(function(n){var i=t.get(n);i&&e.push("text-"+n+":"+i)})),e.join(";")}(d)),null!=p&&o.push("padding:"+yp(p).join("px ")+"px"),o.join(";")+";"}function oW(t,e,n,i,r){var o=e&&e.painter;if(n){var a=o&&o.getViewportRoot();a&&function(t,e,n,i,r){ee(te,e,i,r,!0)&&ee(t,n,te[0],te[1])}(t,a,n,i,r)}else{t[0]=i,t[1]=r;var s=o&&o.getViewportRootOffset();s&&(t[0]+=s.offsetLeft,t[1]+=s.offsetTop)}t[2]=t[0]/e.getWidth(),t[3]=t[1]/e.getHeight()}var aW=function(){function t(t,e){if(this._show=!1,this._styleCoord=[0,0,0,0],this._enterable=!0,this._alwaysShowContent=!1,this._firstShow=!0,this._longHide=!0,r.wxa)return null;var n=document.createElement("div");n.domBelongToZr=!0,this.el=n;var i=this._zr=t.getZr(),o=e.appendTo,a=o&&(X(o)?document.querySelector(o):J(o)?o:Y(o)&&o(t.getDom()));oW(this._styleCoord,i,a,t.getWidth()/2,t.getHeight()/2),(a||t.getDom()).appendChild(n),this._api=t,this._container=a;var s=this;n.onmouseenter=function(){s._enterable&&(clearTimeout(s._hideTimeout),s._show=!0),s._inContent=!0},n.onmousemove=function(t){if(t=t||window.event,!s._enterable){var e=i.handler;de(i.painter.getViewportRoot(),t,!0),e.dispatch("mousemove",t)}},n.onmouseleave=function(){s._inContent=!1,s._enterable&&s._show&&s.hideLater(s._hideDelay)}}return t.prototype.update=function(t){if(!this._container){var e=this._api.getDom(),n=(o="position",(a=(r=e).currentStyle||document.defaultView&&document.defaultView.getComputedStyle(r))?o?a[o]:a:null),i=e.style;"absolute"!==i.position&&"absolute"!==n&&(i.position="relative")}var r,o,a,s=t.get("alwaysShowContent");s&&this._moveIfResized(),this._alwaysShowContent=s,this._enableDisplayTransition=t.get("displayTransition")&&t.get("transitionDuration")>0,this.el.className=t.get("className")||""},t.prototype.show=function(t,e){clearTimeout(this._hideTimeout),clearTimeout(this._longHideTimeout);var n=this.el,i=n.style,r=this._styleCoord;n.innerHTML?i.cssText=nW+rW(t,!this._firstShow,this._longHide,this._enableDisplayTransition)+iW(r[0],r[1],!0)+"border-color:"+wp(e)+";"+(t.get("extraCssText")||"")+";pointer-events:"+(this._enterable?"auto":"none"):i.display="none",this._show=!0,this._firstShow=!1,this._longHide=!1},t.prototype.setContent=function(t,e,n,i,r){var o=this.el;if(null!=t){var a="";if(X(r)&&"item"===n.get("trigger")&&!KF(n)&&(a=function(t,e,n){if(!X(n)||"inside"===n)return"";var i=t.get("backgroundColor"),r=t.get("borderWidth");e=wp(e);var o,a,s="left"===(o=n)?"right":"right"===o?"left":"top"===o?"bottom":"top",l=Math.max(1.5*Math.round(r),6),u="",c=eW+":";P(["left","right"],s)>-1?(u+="top:50%",c+="translateY(-50%) rotate("+(a="left"===s?-225:-45)+"deg)"):(u+="left:50%",c+="translateX(-50%) rotate("+(a="top"===s?225:45)+"deg)");var h=a*Math.PI/180,d=l+r,p=d*Math.abs(Math.cos(h))+d*Math.abs(Math.sin(h)),f=e+" solid "+r+"px;";return'
'}(n,i,r)),X(t))o.innerHTML=t+a;else if(t){o.innerHTML="",U(t)||(t=[t]);for(var s=0;s=0?this._tryShow(n,i):"leave"===e&&this._hide(i))}),this))},e.prototype._keepShow=function(){var t=this._tooltipModel,e=this._ecModel,n=this._api,i=t.get("triggerOn");if(null!=this._lastX&&null!=this._lastY&&"none"!==i&&"click"!==i){var r=this;clearTimeout(this._refreshUpdateTimeout),this._refreshUpdateTimeout=setTimeout((function(){!n.isDisposed()&&r.manuallyShowTip(t,e,n,{x:r._lastX,y:r._lastY,dataByCoordSys:r._lastDataByCoordSys})}))}},e.prototype.manuallyShowTip=function(t,e,n,i){if(i.from!==this.uid&&!r.node&&n.getDom()){var o=fW(i,n);this._ticket="";var a=i.dataByCoordSys,s=function(t,e,n){var i=ca(t).queryOptionMap,r=i.keys()[0];if(!r||"series"===r)return;var o=pa(e,r,i.get(r),{useDefault:!1,enableAll:!1,enableNone:!1}),a=o.models[0];if(!a)return;var s,l=n.getViewOfComponentModel(a);if(l.group.traverse((function(e){var n=zl(e).tooltipConfig;if(n&&n.name===t.name)return s=e,!0})),s)return{componentMainType:r,componentIndex:a.componentIndex,el:s}}(i,e,n);if(s){var l=s.el.getBoundingRect().clone();l.applyTransform(s.el.transform),this._tryShow({offsetX:l.x+l.width/2,offsetY:l.y+l.height/2,target:s.el,position:i.position,positionDefault:"bottom"},o)}else if(i.tooltip&&null!=i.x&&null!=i.y){var u=hW;u.x=i.x,u.y=i.y,u.update(),zl(u).tooltipConfig={name:null,option:i.tooltip},this._tryShow({offsetX:i.x,offsetY:i.y,target:u},o)}else if(a)this._tryShow({offsetX:i.x,offsetY:i.y,position:i.position,dataByCoordSys:a,tooltipOption:i.tooltipOption},o);else if(null!=i.seriesIndex){if(this._manuallyAxisShowTip(t,e,n,i))return;var c=SB(i,e),h=c.point[0],d=c.point[1];null!=h&&null!=d&&this._tryShow({offsetX:h,offsetY:d,target:c.el,position:i.position,positionDefault:"bottom"},o)}else null!=i.x&&null!=i.y&&(n.dispatchAction({type:"updateAxisPointer",x:i.x,y:i.y}),this._tryShow({offsetX:i.x,offsetY:i.y,position:i.position,target:n.getZr().findHover(i.x,i.y).target},o))}},e.prototype.manuallyHideTip=function(t,e,n,i){var r=this._tooltipContent;this._tooltipModel&&r.hideLater(this._tooltipModel.get("hideDelay")),this._lastX=this._lastY=this._lastDataByCoordSys=null,i.from!==this.uid&&this._hide(fW(i,n))},e.prototype._manuallyAxisShowTip=function(t,e,n,i){var r=i.seriesIndex,o=i.dataIndex,a=e.getComponent("axisPointer").coordSysAxesInfo;if(null!=r&&null!=o&&null!=a){var s=e.getSeriesByIndex(r);if(s)if("axis"===pW([s.getData().getItemModel(o),s,(s.coordinateSystem||{}).model],this._tooltipModel).get("trigger"))return n.dispatchAction({type:"updateAxisPointer",seriesIndex:r,dataIndex:o,position:i.position}),!0}},e.prototype._tryShow=function(t,e){var n=t.target;if(this._tooltipModel){this._lastX=t.offsetX,this._lastY=t.offsetY;var i=t.dataByCoordSys;if(i&&i.length)this._showAxisTooltip(i,t);else if(n){var r,o;if("legend"===zl(n).ssrType)return;this._lastDataByCoordSys=null,Qv(n,(function(t){if(t.tooltipDisabled)return r=o=null,!0;r||o||(null!=zl(t).dataIndex?r=t:null!=zl(t).tooltipConfig&&(o=t))}),!0),r?this._showSeriesItemTooltip(t,r,e):o?this._showComponentItemTooltip(t,o,e):this._hide(e)}else this._lastDataByCoordSys=null,this._hide(e)}},e.prototype._showOrMove=function(t,e){var n=t.get("showDelay");e=W(e,this),clearTimeout(this._showTimout),n>0?this._showTimout=setTimeout(e,n):e()},e.prototype._showAxisTooltip=function(t,e){var n=this._ecModel,i=this._tooltipModel,r=[e.offsetX,e.offsetY],o=pW([e.tooltipOption],i),a=this._renderMode,s=[],l=Ty("section",{blocks:[],noHeader:!0}),u=[],c=new Ey;z(t,(function(t){z(t.dataByAxis,(function(t){var e=n.getComponent(t.axisDim+"Axis",t.axisIndex),r=t.value;if(e&&null!=r){var o=oB(r,e.axis,n,t.seriesDataIndices,t.valueLabelOpt),h=Ty("section",{header:o,noHeader:!ut(o),sortBlocks:!0,blocks:[]});l.blocks.push(h),z(t.seriesDataIndices,(function(l){var d=n.getSeriesByIndex(l.seriesIndex),p=l.dataIndexInside,f=d.getDataParams(p);if(!(f.dataIndex<0)){f.axisDim=t.axisDim,f.axisIndex=t.axisIndex,f.axisType=t.axisType,f.axisId=t.axisId,f.axisValue=qb(e.axis,{value:r}),f.axisValueLabel=o,f.marker=c.makeTooltipMarker("item",wp(f.color),a);var g=Wg(d.formatTooltip(p,!0,null)),y=g.frag;if(y){var v=pW([d],i).get("valueFormatter");h.blocks.push(v?A({valueFormatter:v},y):y)}g.text&&u.push(g.text),s.push(f)}}))}}))})),l.blocks.reverse(),u.reverse();var h=e.position,d=o.get("order"),p=Py(l,c,a,d,n.get("useUTC"),o.get("textStyle"));p&&u.unshift(p);var f="richText"===a?"\n\n":"
",g=u.join(f);this._showOrMove(o,(function(){this._updateContentNotChangedOnAxis(t,s)?this._updatePosition(o,h,r[0],r[1],this._tooltipContent,s):this._showTooltipContent(o,g,s,Math.random()+"",r[0],r[1],h,null,c)}))},e.prototype._showSeriesItemTooltip=function(t,e,n){var i=this._ecModel,r=zl(e),o=r.seriesIndex,a=i.getSeriesByIndex(o),s=r.dataModel||a,l=r.dataIndex,u=r.dataType,c=s.getData(u),h=this._renderMode,d=t.positionDefault,p=pW([c.getItemModel(l),s,a&&(a.coordinateSystem||{}).model],this._tooltipModel,d?{position:d}:null),f=p.get("trigger");if(null==f||"item"===f){var g=s.getDataParams(l,u),y=new Ey;g.marker=y.makeTooltipMarker("item",wp(g.color),h);var v=Wg(s.formatTooltip(l,!1,u)),m=p.get("order"),x=p.get("valueFormatter"),_=v.frag,b=_?Py(x?A({valueFormatter:x},_):_,y,h,m,i.get("useUTC"),p.get("textStyle")):v.text,w="item_"+s.name+"_"+l;this._showOrMove(p,(function(){this._showTooltipContent(p,b,g,w,t.offsetX,t.offsetY,t.position,t.target,y)})),n({type:"showTip",dataIndexInside:l,dataIndex:c.getRawIndex(l),seriesIndex:o,from:this.uid})}},e.prototype._showComponentItemTooltip=function(t,e,n){var i="html"===this._renderMode,r=zl(e),o=r.tooltipConfig.option||{},a=o.encodeHTMLContent;if(X(o)){o={content:o,formatter:o},a=!0}a&&i&&o.content&&((o=T(o)).content=oe(o.content));var s=[o],l=this._ecModel.getComponent(r.componentMainType,r.componentIndex);l&&s.push(l),s.push({formatter:o.content});var u=t.positionDefault,c=pW(s,this._tooltipModel,u?{position:u}:null),h=c.get("content"),d=Math.random()+"",p=new Ey;this._showOrMove(c,(function(){var n=T(c.get("formatterParams")||{});this._showTooltipContent(c,h,n,d,t.offsetX,t.offsetY,t.position,e,p)})),n({type:"showTip",from:this.uid})},e.prototype._showTooltipContent=function(t,e,n,i,r,o,a,s,l){if(this._ticket="",t.get("showContent")&&t.get("show")){var u=this._tooltipContent;u.setEnterable(t.get("enterable"));var c=t.get("formatter");a=a||t.get("position");var h=e,d=this._getNearestPoint([r,o],n,t.get("trigger"),t.get("borderColor"),t.get("defaultBorderColor",!0)).color;if(c)if(X(c)){var p=t.ecModel.get("useUTC"),f=U(n)?n[0]:n;h=c,f&&f.axisType&&f.axisType.indexOf("time")>=0&&(h=$d(f.axisValue,h,p)),h=_p(h,n,!0)}else if(Y(c)){var g=W((function(e,i){e===this._ticket&&(u.setContent(i,l,t,d,a),this._updatePosition(t,a,r,o,u,n,s))}),this);this._ticket=i,h=c(n,i,g)}else h=c;u.setContent(h,l,t,d,a),u.show(t,d),this._updatePosition(t,a,r,o,u,n,s)}},e.prototype._getNearestPoint=function(t,e,n,i,r){return"axis"===n||U(e)?{color:i||r}:U(e)?void 0:{color:i||e.color||e.borderColor}},e.prototype._updatePosition=function(t,e,n,i,r,o,a){var s=this._api.getWidth(),l=this._api.getHeight();e=e||t.get("position");var u=r.getSize(),c=t.get("align"),h=t.get("verticalAlign"),d=a&&a.getBoundingRect().clone();if(a&&d.applyTransform(a.transform),Y(e)&&(e=e([n,i],o,r.el,d,{viewSize:[s,l],contentSize:u.slice()})),U(e))n=yo(e[0],s),i=yo(e[1],l);else if(q(e)){var p=e;p.width=u[0],p.height=u[1];var f=Hp(p,{width:s,height:l});n=f.x,i=f.y,c=null,h=null}else if(X(e)&&a){var g=function(t,e,n,i){var r=n[0],o=n[1],a=Math.ceil(Math.SQRT2*i)+8,s=0,l=0,u=e.width,c=e.height;switch(t){case"inside":s=e.x+u/2-r/2,l=e.y+c/2-o/2;break;case"top":s=e.x+u/2-r/2,l=e.y-o-a;break;case"bottom":s=e.x+u/2-r/2,l=e.y+c+a;break;case"left":s=e.x-r-a,l=e.y+c/2-o/2;break;case"right":s=e.x+u+a,l=e.y+c/2-o/2}return[s,l]}(e,d,u,t.get("borderWidth"));n=g[0],i=g[1]}else{g=function(t,e,n,i,r,o,a){var s=n.getSize(),l=s[0],u=s[1];null!=o&&(t+l+o+2>i?t-=l+o:t+=o);null!=a&&(e+u+a>r?e-=u+a:e+=a);return[t,e]}(n,i,r,s,l,c?null:20,h?null:20);n=g[0],i=g[1]}if(c&&(n-=gW(c)?u[0]/2:"right"===c?u[0]:0),h&&(i-=gW(h)?u[1]/2:"bottom"===h?u[1]:0),KF(t)){g=function(t,e,n,i,r){var o=n.getSize(),a=o[0],s=o[1];return t=Math.min(t+a,i)-a,e=Math.min(e+s,r)-s,t=Math.max(t,0),e=Math.max(e,0),[t,e]}(n,i,r,s,l);n=g[0],i=g[1]}r.moveTo(n,i)},e.prototype._updateContentNotChangedOnAxis=function(t,e){var n=this._lastDataByCoordSys,i=this._cbParamsList,r=!!n&&n.length===t.length;return r&&z(n,(function(n,o){var a=n.dataByAxis||[],s=(t[o]||{}).dataByAxis||[];(r=r&&a.length===s.length)&&z(a,(function(t,n){var o=s[n]||{},a=t.seriesDataIndices||[],l=o.seriesDataIndices||[];(r=r&&t.value===o.value&&t.axisType===o.axisType&&t.axisId===o.axisId&&a.length===l.length)&&z(a,(function(t,e){var n=l[e];r=r&&t.seriesIndex===n.seriesIndex&&t.dataIndex===n.dataIndex})),i&&z(t.seriesDataIndices,(function(t){var n=t.seriesIndex,o=e[n],a=i[n];o&&a&&a.data!==o.data&&(r=!1)}))}))})),this._lastDataByCoordSys=t,this._cbParamsList=e,!!r},e.prototype._hide=function(t){this._lastDataByCoordSys=null,t({type:"hideTip",from:this.uid})},e.prototype.dispose=function(t,e){!r.node&&e.getDom()&&(hv(this,"_updatePosition"),this._tooltipContent.dispose(),bB("itemTooltip",e))},e.type="tooltip",e}(Ky);function pW(t,e,n){var i,r=e.ecModel;n?(i=new wd(n,r,r),i=new wd(e.option,i,r)):i=e;for(var o=t.length-1;o>=0;o--){var a=t[o];a&&(a instanceof wd&&(a=a.get("tooltip",!0)),X(a)&&(a={formatter:a}),a&&(i=new wd(a,i,r)))}return i}function fW(t,e){return t.dispatchAction||W(e.dispatchAction,e)}function gW(t){return"center"===t||"middle"===t}var yW=["rect","polygon","keep","clear"];function vW(t,e){var n=qo(t?t.brush:[]);if(n.length){var i=[];z(n,(function(t){var e=t.hasOwnProperty("toolbox")?t.toolbox:[];e instanceof Array&&(i=i.concat(e))}));var r=t&&t.toolbox;U(r)&&(r=r[0]),r||(r={feature:{}},t.toolbox=[r]);var o=r.feature||(r.feature={}),a=o.brush||(o.brush={}),s=a.type||(a.type=[]);s.push.apply(s,i),function(t){var e={};z(t,(function(t){e[t]=1})),t.length=0,z(e,(function(e,n){t.push(n)}))}(s),e&&!s.length&&s.push.apply(s,yW)}}var mW=z;function xW(t){if(t)for(var e in t)if(t.hasOwnProperty(e))return!0}function _W(t,e,n){var i={};return mW(e,(function(e){var r,o=i[e]=((r=function(){}).prototype.__hidden=r.prototype,new r);mW(t[e],(function(t,i){if(hL.isValidType(i)){var r={type:i,visual:t};n&&n(r,e),o[i]=new hL(r),"opacity"===i&&((r=T(r)).type="colorAlpha",o.__hidden.__alphaForOpacity=new hL(r))}}))})),i}function bW(t,e,n){var i;z(n,(function(t){e.hasOwnProperty(t)&&xW(e[t])&&(i=!0)})),i&&z(n,(function(n){e.hasOwnProperty(n)&&xW(e[n])?t[n]=T(e[n]):delete t[n]}))}var wW={lineX:SW(0),lineY:SW(1),rect:{point:function(t,e,n){return t&&n.boundingRect.contain(t[0],t[1])},rect:function(t,e,n){return t&&n.boundingRect.intersect(t)}},polygon:{point:function(t,e,n){return t&&n.boundingRect.contain(t[0],t[1])&&aw(n.range,t[0],t[1])},rect:function(t,e,n){var i=n.range;if(!t||i.length<=1)return!1;var r=t.x,o=t.y,a=t.width,s=t.height,l=i[0];return!!(aw(i,r,o)||aw(i,r+a,o)||aw(i,r,o+s)||aw(i,r+a,o+s)||He.create(t).contain(l[0],l[1])||kh(r,o,r+a,o,i)||kh(r,o,r,o+s,i)||kh(r+a,o,r+a,o+s,i)||kh(r,o+s,r+a,o+s,i))||void 0}}};function SW(t){var e=["x","y"],n=["width","height"];return{point:function(e,n,i){if(e){var r=i.range;return MW(e[t],r)}},rect:function(i,r,o){if(i){var a=o.range,s=[i[e[t]],i[e[t]]+i[n[t]]];return s[1]e[0][1]&&(e[0][1]=o[0]),o[1]e[1][1]&&(e[1][1]=o[1])}return e&&OW(e)}};function OW(t){return new He(t[0][0],t[1][0],t[0][1]-t[0][0],t[1][1]-t[1][0])}var RW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(t,e){this.ecModel=t,this.api=e,this.model,(this._brushController=new JO(e.getZr())).on("brush",W(this._onBrush,this)).mount()},e.prototype.render=function(t,e,n,i){this.model=t,this._updateController(t,e,n,i)},e.prototype.updateTransform=function(t,e,n,i){DW(e),this._updateController(t,e,n,i)},e.prototype.updateVisual=function(t,e,n,i){this.updateTransform(t,e,n,i)},e.prototype.updateView=function(t,e,n,i){this._updateController(t,e,n,i)},e.prototype._updateController=function(t,e,n,i){(!i||i.$from!==t.id)&&this._brushController.setPanels(t.brushTargetManager.makePanelOpts(n)).enableBrush(t.brushOption).updateCovers(t.areas.slice())},e.prototype.dispose=function(){this._brushController.dispose()},e.prototype._onBrush=function(t){var e=this.model.id,n=this.model.brushTargetManager.setOutputRanges(t.areas,this.ecModel);(!t.isEnd||t.removeOnClick)&&this.api.dispatchAction({type:"brush",brushId:e,areas:T(n),$from:e}),t.isEnd&&this.api.dispatchAction({type:"brushEnd",brushId:e,areas:T(n),$from:e})},e.type="brush",e}(Ky),NW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.areas=[],n.brushOption={},n}return n(e,t),e.prototype.optionUpdated=function(t,e){var n=this.option;!e&&bW(n,t,["inBrush","outOfBrush"]);var i=n.inBrush=n.inBrush||{};n.outOfBrush=n.outOfBrush||{color:this.option.defaultOutOfBrushColor},i.hasOwnProperty("liftZ")||(i.liftZ=5)},e.prototype.setAreas=function(t){t&&(this.areas=E(t,(function(t){return zW(this.option,t)}),this))},e.prototype.setBrushOption=function(t){this.brushOption=zW(this.option,t),this.brushType=this.brushOption.brushType},e.type="brush",e.dependencies=["geo","grid","xAxis","yAxis","parallel","series"],e.defaultOption={seriesIndex:"all",brushType:"rect",brushMode:"single",transformable:!0,brushStyle:{borderWidth:1,color:tf.color.backgroundTint,borderColor:tf.color.borderTint},throttleType:"fixRate",throttleDelay:0,removeOnClick:!0,z:1e4,defaultOutOfBrushColor:tf.color.disabled},e}(Qp);function zW(t,e){return C({brushType:t.brushType,brushMode:t.brushMode,transformable:t.transformable,brushStyle:new wd(t.brushStyle).getItemStyle(),removeOnClick:t.removeOnClick,z:t.z},e,!0)}var EW=["rect","polygon","lineX","lineY","keep","clear"],BW=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return n(e,t),e.prototype.render=function(t,e,n){var i,r,o;e.eachComponent({mainType:"brush"},(function(t){i=t.brushType,r=t.brushOption.brushMode||"single",o=o||!!t.areas.length})),this._brushType=i,this._brushMode=r,z(t.get("type",!0),(function(e){t.setIconStatus(e,("keep"===e?"multiple"===r:"clear"===e?o:e===i)?"emphasis":"normal")}))},e.prototype.updateView=function(t,e,n){this.render(t,e,n)},e.prototype.getIcons=function(){var t=this.model,e=t.get("icon",!0),n={};return z(t.get("type",!0),(function(t){e[t]&&(n[t]=e[t])})),n},e.prototype.onclick=function(t,e,n){var i=this._brushType,r=this._brushMode;"clear"===n?(e.dispatchAction({type:"axisAreaSelect",intervals:[]}),e.dispatchAction({type:"brush",command:"clear",areas:[]})):e.dispatchAction({type:"takeGlobalCursor",key:"brush",brushOption:{brushType:"keep"===n?i:i!==n&&n,brushMode:"keep"===n?"multiple"===r?"single":"multiple":r}})},e.getDefaultOption=function(t){return{show:!0,type:EW.slice(),icon:{rect:"M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13",polygon:"M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2",lineX:"M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4",lineY:"M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4",keep:"M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z",clear:"M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2"},title:t.getLocaleModel().get(["toolbox","brush","title"])}},e}(sF);var VW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.layoutMode={type:"box",ignoreSize:!0},n}return n(e,t),e.type="title",e.defaultOption={z:6,show:!0,text:"",target:"blank",subtext:"",subtarget:"blank",left:"center",top:tf.size.m,backgroundColor:tf.color.transparent,borderColor:tf.color.primary,borderWidth:0,padding:5,itemGap:10,textStyle:{fontSize:18,fontWeight:"bold",color:tf.color.primary},subtextStyle:{fontSize:12,color:tf.color.quaternary}},e}(Qp),GW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){if(this.group.removeAll(),t.get("show")){var i=this.group,r=t.getModel("textStyle"),o=t.getModel("subtextStyle"),a=t.get("textAlign"),s=rt(t.get("textBaseline"),t.get("textVerticalAlign")),l=new Sl({style:Qh(r,{text:t.get("text"),fill:r.getTextColor()},{disableBox:!0}),z2:10}),u=l.getBoundingRect(),c=t.get("subtext"),h=new Sl({style:Qh(o,{text:c,fill:o.getTextColor(),y:u.height+t.get("itemGap"),verticalAlign:"top"},{disableBox:!0}),z2:10}),d=t.get("link"),p=t.get("sublink"),f=t.get("triggerEvent",!0);l.silent=!d&&!f,h.silent=!p&&!f,d&&l.on("click",(function(){Sp(d,"_"+t.get("target"))})),p&&h.on("click",(function(){Sp(p,"_"+t.get("subtarget"))})),zl(l).eventData=zl(h).eventData=f?{componentType:"title",componentIndex:t.componentIndex}:null,i.add(l),c&&i.add(h);var g=i.getBoundingRect(),y=t.getBoxLayoutParams();y.width=g.width,y.height=g.height;var v=Hp(y,Xp(t,n).refContainer,t.get("padding"));a||("middle"===(a=t.get("left")||t.get("right"))&&(a="center"),"right"===a?v.x+=v.width:"center"===a&&(v.x+=v.width/2)),s||("center"===(s=t.get("top")||t.get("bottom"))&&(s="middle"),"bottom"===s?v.y+=v.height:"middle"===s&&(v.y+=v.height/2),s=s||"top"),i.x=v.x,i.y=v.y,i.markRedraw();var m={align:a,verticalAlign:s};l.setStyle(m),h.setStyle(m),g=i.getBoundingRect();var x=v.margin,_=t.getItemStyle(["color","opacity"]);_.fill=t.get("backgroundColor");var b=new xl({shape:{x:g.x-x[3],y:g.y-x[0],width:g.width+x[1]+x[3],height:g.height+x[0]+x[2],r:t.get("borderRadius")},style:_,subPixelOptimize:!0,silent:!0});i.add(b)}},e.type="title",e}(Ky);var FW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.layoutMode="box",n}return n(e,t),e.prototype.init=function(t,e,n){this.mergeDefaultAndTheme(t,n),this._initData()},e.prototype.mergeOption=function(e){t.prototype.mergeOption.apply(this,arguments),this._initData()},e.prototype.setCurrentIndex=function(t){null==t&&(t=this.option.currentIndex);var e=this._data.count();this.option.loop?t=(t%e+e)%e:(t>=e&&(t=e-1),t<0&&(t=0)),this.option.currentIndex=t},e.prototype.getCurrentIndex=function(){return this.option.currentIndex},e.prototype.isIndexMax=function(){return this.getCurrentIndex()>=this._data.count()-1},e.prototype.setPlayState=function(t){this.option.autoPlay=!!t},e.prototype.getPlayState=function(){return!!this.option.autoPlay},e.prototype._initData=function(){var t,e=this.option,n=e.data||[],i=e.axisType,r=this._names=[];"category"===i?(t=[],z(n,(function(e,n){var i,o=ia(Jo(e),"");q(e)?(i=T(e)).value=n:i=n,t.push(i),r.push(o)}))):t=n;var o={category:"ordinal",time:"time",value:"number"}[i]||"number";(this._data=new B_([{name:"value",type:o}],this)).initData(t,r)},e.prototype.getData=function(){return this._data},e.prototype.getCategories=function(){if("category"===this.get("axisType"))return this._names.slice()},e.type="timeline",e.defaultOption={z:4,show:!0,axisType:"time",realtime:!0,left:"20%",top:null,right:"20%",bottom:0,width:null,height:40,padding:tf.size.m,controlPosition:"left",autoPlay:!1,rewind:!1,loop:!0,playInterval:2e3,currentIndex:0,itemStyle:{},label:{color:tf.color.secondary},data:[]},e}(Qp),WW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="timeline.slider",e.defaultOption=Id(FW.defaultOption,{backgroundColor:"rgba(0,0,0,0)",borderColor:tf.color.border,borderWidth:0,orient:"horizontal",inverse:!1,tooltip:{trigger:"item"},symbol:"circle",symbolSize:12,lineStyle:{show:!0,width:2,color:tf.color.accent10},label:{position:"auto",show:!0,interval:"auto",rotate:0,color:tf.color.tertiary},itemStyle:{color:tf.color.accent20,borderWidth:0},checkpointStyle:{symbol:"circle",symbolSize:15,color:tf.color.accent50,borderColor:tf.color.accent50,borderWidth:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,shadowColor:"rgba(0, 0, 0, 0)",animation:!0,animationDuration:300,animationEasing:"quinticInOut"},controlStyle:{show:!0,showPlayBtn:!0,showPrevBtn:!0,showNextBtn:!0,itemSize:24,itemGap:12,position:"left",playIcon:"path://M15 0C23.2843 0 30 6.71573 30 15C30 23.2843 23.2843 30 15 30C6.71573 30 0 23.2843 0 15C0 6.71573 6.71573 0 15 0ZM15 3C8.37258 3 3 8.37258 3 15C3 21.6274 8.37258 27 15 27C21.6274 27 27 21.6274 27 15C27 8.37258 21.6274 3 15 3ZM11.5 10.6699C11.5 9.90014 12.3333 9.41887 13 9.80371L20.5 14.1338C21.1667 14.5187 21.1667 15.4813 20.5 15.8662L13 20.1963C12.3333 20.5811 11.5 20.0999 11.5 19.3301V10.6699Z",stopIcon:"path://M15 0C23.2843 0 30 6.71573 30 15C30 23.2843 23.2843 30 15 30C6.71573 30 0 23.2843 0 15C0 6.71573 6.71573 0 15 0ZM15 3C8.37258 3 3 8.37258 3 15C3 21.6274 8.37258 27 15 27C21.6274 27 27 21.6274 27 15C27 8.37258 21.6274 3 15 3ZM11.5 10C12.3284 10 13 10.6716 13 11.5V18.5C13 19.3284 12.3284 20 11.5 20C10.6716 20 10 19.3284 10 18.5V11.5C10 10.6716 10.6716 10 11.5 10ZM18.5 10C19.3284 10 20 10.6716 20 11.5V18.5C20 19.3284 19.3284 20 18.5 20C17.6716 20 17 19.3284 17 18.5V11.5C17 10.6716 17.6716 10 18.5 10Z",nextIcon:"path://M0.838834 18.7383C0.253048 18.1525 0.253048 17.2028 0.838834 16.617L7.55635 9.89949L0.838834 3.18198C0.253048 2.59619 0.253048 1.64645 0.838834 1.06066C1.42462 0.474874 2.37437 0.474874 2.96015 1.06066L10.7383 8.83883L10.8412 8.95277C11.2897 9.50267 11.2897 10.2963 10.8412 10.8462L10.7383 10.9602L2.96015 18.7383C2.37437 19.3241 1.42462 19.3241 0.838834 18.7383Z",prevIcon:"path://M10.9602 1.06066C11.5459 1.64645 11.5459 2.59619 10.9602 3.18198L4.24264 9.89949L10.9602 16.617C11.5459 17.2028 11.5459 18.1525 10.9602 18.7383C10.3744 19.3241 9.42462 19.3241 8.83883 18.7383L1.06066 10.9602L0.957771 10.8462C0.509245 10.2963 0.509245 9.50267 0.957771 8.95277L1.06066 8.83883L8.83883 1.06066C9.42462 0.474874 10.3744 0.474874 10.9602 1.06066Z",prevBtnSize:18,nextBtnSize:18,color:tf.color.accent50,borderColor:tf.color.accent50,borderWidth:0},emphasis:{label:{show:!0,color:tf.color.accent60},itemStyle:{color:tf.color.accent60,borderColor:tf.color.accent60},controlStyle:{color:tf.color.accent70,borderColor:tf.color.accent70}},progress:{lineStyle:{color:tf.color.accent30},itemStyle:{color:tf.color.accent40}},data:[]}),e}(FW);R(WW,Fg.prototype);var HW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="timeline",e}(Ky),UW=function(t){function e(e,n,i,r){var o=t.call(this,e,n,i)||this;return o.type=r||"value",o}return n(e,t),e.prototype.getLabelModel=function(){return this.model.getModel("label")},e.prototype.isHorizontal=function(){return"horizontal"===this.model.get("orient")},e}(Ww),YW=Math.PI,XW=sa(),ZW=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(t,e){this.api=e},e.prototype.render=function(t,e,n){if(this.model=t,this.api=n,this.ecModel=e,this.group.removeAll(),t.get("show",!0)){var i=this._layout(t,n),r=this._createGroup("_mainGroup"),o=this._createGroup("_labelGroup"),a=this._axis=this._createAxis(i,t);t.formatTooltip=function(t){return Ty("nameValue",{noName:!0,value:a.scale.getLabel({value:t})})},z(["AxisLine","AxisTick","Control","CurrentPointer"],(function(e){this["_render"+e](i,r,a,t)}),this),this._renderAxisLabel(i,o,a,t),this._position(i,t)}this._doPlayStop(),this._updateTicksStatus()},e.prototype.remove=function(){this._clearTimer(),this.group.removeAll()},e.prototype.dispose=function(){this._clearTimer()},e.prototype._layout=function(t,e){var n,i,r,o,a=t.get(["label","position"]),s=t.get("orient"),l=function(t,e){return Hp(t.getBoxLayoutParams(),Xp(t,e).refContainer,t.get("padding"))}(t,e),u={horizontal:"center",vertical:(n=null==a||"auto"===a?"horizontal"===s?l.y+l.height/2=0||"+"===n?"left":"right"},c={horizontal:n>=0||"+"===n?"top":"bottom",vertical:"middle"},h={horizontal:0,vertical:YW/2},d="vertical"===s?l.height:l.width,p=t.getModel("controlStyle"),f=p.get("show",!0),g=f?p.get("itemSize"):0,y=f?p.get("itemGap"):0,v=g+y,m=t.get(["label","rotate"])||0;m=m*YW/180;var x=p.get("position",!0),_=f&&p.get("showPlayBtn",!0),b=f&&p.get("showPrevBtn",!0),w=f&&p.get("showNextBtn",!0),S=0,M=d;"left"===x||"bottom"===x?(_&&(i=[0,0],S+=v),b&&(r=[S,0],S+=v),w&&(o=[M-g,0],M-=v)):(_&&(i=[M-g,0],M-=v),b&&(r=[0,0],S+=v),w&&(o=[M-g,0],M-=v));var I=[S,M];return t.get("inverse")&&I.reverse(),{viewRect:l,mainLength:d,orient:s,rotation:h[s],labelRotation:m,labelPosOpt:n,labelAlign:t.get(["label","align"])||u[s],labelBaseline:t.get(["label","verticalAlign"])||t.get(["label","baseline"])||c[s],playPosition:i,prevBtnPosition:r,nextBtnPosition:o,axisExtent:I,controlSize:g,controlGap:y}},e.prototype._position=function(t,e){var n=this._mainGroup,i=this._labelGroup,r=t.viewRect;if("vertical"===t.orient){var o=[1,0,0,1,0,0],a=r.x,s=r.y+r.height;Se(o,o,[-a,-s]),Me(o,o,-YW/2),Se(o,o,[a,s]),(r=r.clone()).applyTransform(o)}var l=y(r),u=y(n.getBoundingRect()),c=y(i.getBoundingRect()),h=[n.x,n.y],d=[i.x,i.y];d[0]=h[0]=l[0][0];var p,f=t.labelPosOpt;null==f||X(f)?(v(h,u,l,1,p="+"===f?0:1),v(d,c,l,1,1-p)):(v(h,u,l,1,p=f>=0?0:1),d[1]=h[1]+f);function g(t){t.originX=l[0][0]-t.x,t.originY=l[1][0]-t.y}function y(t){return[[t.x,t.x+t.width],[t.y,t.y+t.height]]}function v(t,e,n,i,r){t[i]+=n[i][r]-e[i][r]}n.setPosition(h),i.setPosition(d),n.rotation=i.rotation=t.rotation,g(n),g(i)},e.prototype._createAxis=function(t,e){var n=e.getData(),i=e.get("axisType"),r=function(t,e){if(e=e||t.get("type"),e)switch(e){case"category":return new lb({ordinalMeta:t.getCategories(),extent:[1/0,-1/0]});case"time":return new Mb({locale:t.ecModel.getLocaleModel(),useUTC:t.ecModel.get("useUTC")});default:return new cb}}(e,i);r.getTicks=function(){return n.mapArray(["value"],(function(t){return{value:t}}))};var o=n.getDataExtent("value");r.setExtent(o[0],o[1]),r.calcNiceTicks();var a=new UW("value",r,t.axisExtent,i);return a.model=e,a},e.prototype._createGroup=function(t){var e=this[t]=new to;return this.group.add(e),e},e.prototype._renderAxisLine=function(t,e,n,i){var r=n.getExtent();if(i.get(["lineStyle","show"])){var o=new Ac({shape:{x1:r[0],y1:0,x2:r[1],y2:0},style:A({lineCap:"round"},i.getModel("lineStyle").getLineStyle()),silent:!0,z2:1});e.add(o);var a=this._progressLine=new Ac({shape:{x1:r[0],x2:this._currentPointer?this._currentPointer.x:r[0],y1:0,y2:0},style:k({lineCap:"round",lineWidth:o.style.lineWidth},i.getModel(["progress","lineStyle"]).getLineStyle()),silent:!0,z2:1});e.add(a)}},e.prototype._renderAxisTick=function(t,e,n,i){var r=this,o=i.getData(),a=n.scale.getTicks();this._tickSymbols=[],z(a,(function(t){var a=n.dataToCoord(t.value),s=o.getItemModel(t.value),l=s.getModel("itemStyle"),u=s.getModel(["emphasis","itemStyle"]),c=s.getModel(["progress","itemStyle"]),h={x:a,y:0,onclick:W(r._changeTimeline,r,t.value)},d=jW(s,l,e,h);d.ensureState("emphasis").style=u.getItemStyle(),d.ensureState("progress").style=c.getItemStyle(),Iu(d);var p=zl(d);s.get("tooltip")?(p.dataIndex=t.value,p.dataModel=i):p.dataIndex=p.dataModel=null,r._tickSymbols.push(d)}))},e.prototype._renderAxisLabel=function(t,e,n,i){var r=this;if(n.getLabelModel().get("show")){var o=i.getData(),a=n.getViewLabels();this._tickLabels=[],z(a,(function(i){var a=i.tickValue,s=o.getItemModel(a),l=s.getModel("label"),u=s.getModel(["emphasis","label"]),c=s.getModel(["progress","label"]),h=n.dataToCoord(i.tickValue),d=new Sl({x:h,y:0,rotation:t.labelRotation-t.rotation,onclick:W(r._changeTimeline,r,a),silent:!1,style:Qh(l,{text:i.formattedLabel,align:t.labelAlign,verticalAlign:t.labelBaseline})});d.ensureState("emphasis").style=Qh(u),d.ensureState("progress").style=Qh(c),e.add(d),Iu(d),XW(d).dataIndex=a,r._tickLabels.push(d)}))}},e.prototype._renderControl=function(t,e,n,i){var r=t.controlSize,o=t.rotation,a=i.getModel("controlStyle").getItemStyle(),s=i.getModel(["emphasis","controlStyle"]).getItemStyle(),l=i.getPlayState(),u=i.get("inverse",!0);function c(t,n,l,u){if(t){var c=Fr(rt(i.get(["controlStyle",n+"BtnSize"]),r),r),h=function(t,e,n,i){var r=i.style,o=Ah(t.get(["controlStyle",e]),i||{},new He(n[0],n[1],n[2],n[3]));r&&o.setStyle(r);return o}(i,n+"Icon",[0,-c/2,c,c],{x:t[0],y:t[1],originX:r/2,originY:0,rotation:u?-o:0,rectHover:!0,style:a,onclick:l});h.ensureState("emphasis").style=s,e.add(h),Iu(h)}}c(t.nextBtnPosition,"next",W(this._changeTimeline,this,u?"-":"+")),c(t.prevBtnPosition,"prev",W(this._changeTimeline,this,u?"+":"-")),c(t.playPosition,l?"stop":"play",W(this._handlePlayClick,this,!l),!0)},e.prototype._renderCurrentPointer=function(t,e,n,i){var r=i.getData(),o=i.getCurrentIndex(),a=r.getItemModel(o).getModel("checkpointStyle"),s=this,l={onCreate:function(t){t.draggable=!0,t.drift=W(s._handlePointerDrag,s),t.ondragend=W(s._handlePointerDragend,s),qW(t,s._progressLine,o,n,i,!0)},onUpdate:function(t){qW(t,s._progressLine,o,n,i)}};this._currentPointer=jW(a,a,this._mainGroup,{},this._currentPointer,l)},e.prototype._handlePlayClick=function(t){this._clearTimer(),this.api.dispatchAction({type:"timelinePlayChange",playState:t,from:this.uid})},e.prototype._handlePointerDrag=function(t,e,n){this._clearTimer(),this._pointerChangeTimeline([n.offsetX,n.offsetY])},e.prototype._handlePointerDragend=function(t){this._pointerChangeTimeline([t.offsetX,t.offsetY],!0)},e.prototype._pointerChangeTimeline=function(t,e){var n=this._toAxisCoord(t)[0],i=xo(this._axis.getExtent().slice());n>i[1]&&(n=i[1]),n=0&&(s[a]=+s[a].toFixed(d)),[s,h]}var aH={min:H(oH,"min"),max:H(oH,"max"),average:H(oH,"average"),median:H(oH,"median")};function sH(t,e){if(e){var n=t.getData(),i=t.coordinateSystem,r=i&&i.dimensions;if(!function(t){return!isNaN(parseFloat(t.x))&&!isNaN(parseFloat(t.y))}(e)&&!U(e.coord)&&U(r)){var o=lH(e,n,i,t);if((e=T(e)).type&&aH[e.type]&&o.baseAxis&&o.valueAxis){var a=P(r,o.baseAxis.dim),s=P(r,o.valueAxis.dim),l=aH[e.type](n,o.valueAxis.dim,o.baseDataDim,o.valueDataDim,a,s);e.coord=l[0],e.value=l[1]}else e.coord=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis]}if(null!=e.coord&&U(r))for(var u=e.coord,c=0;c<2;c++)aH[u[c]]&&(u[c]=hH(n,n.mapDimension(r[c]),u[c]));else{e.coord=[];var h=t.getBaseAxis();if(h&&e.type&&aH[e.type]){var d=i.getOtherAxis(h);d&&(e.value=hH(n,n.mapDimension(d.dim),e.type))}}return e}}function lH(t,e,n,i){var r={};return null!=t.valueIndex||null!=t.valueDim?(r.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,r.valueAxis=n.getAxis(function(t,e){var n=t.getData().getDimensionInfo(e);return n&&n.coordDim}(i,r.valueDataDim)),r.baseAxis=n.getOtherAxis(r.valueAxis),r.baseDataDim=e.mapDimension(r.baseAxis.dim)):(r.baseAxis=i.getBaseAxis(),r.valueAxis=n.getOtherAxis(r.baseAxis),r.baseDataDim=e.mapDimension(r.baseAxis.dim),r.valueDataDim=e.mapDimension(r.valueAxis.dim)),r}function uH(t,e){return!(t&&t.containData&&e.coord&&!rH(e))||t.containData(e.coord)}function cH(t,e){return t?function(t,n,i,r){return Xg(r<2?t.coord&&t.coord[r]:t.value,e[r])}:function(t,n,i,r){return Xg(t.value,e[r])}}function hH(t,e,n){if("average"===n){var i=0,r=0;return t.each(e,(function(t,e){isNaN(t)||(i+=t,r++)})),i/r}return"median"===n?t.getMedian(e):t.getDataExtent(e)["max"===n?1:0]}var dH=sa(),pH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.init=function(){this.markerGroupMap=yt()},e.prototype.render=function(t,e,n){var i=this,r=this.markerGroupMap;r.each((function(t){dH(t).keep=!1})),e.eachSeries((function(t){var r=nH.getMarkerModelFromSeries(t,i.type);r&&i.renderSeries(t,r,e,n)})),r.each((function(t){!dH(t).keep&&i.group.remove(t.group)})),function(t,e,n){t.eachSeries((function(t){var i=nH.getMarkerModelFromSeries(t,n),r=e.get(t.id);if(i&&r&&r.group){var o=Hh(i),a=o.z,s=o.zlevel;Yh(r.group,a,s)}}))}(e,r,this.type)},e.prototype.markKeep=function(t){dH(t).keep=!0},e.prototype.toggleBlurSeries=function(t,e){var n=this;z(t,(function(t){var i=nH.getMarkerModelFromSeries(t,n.type);i&&i.getData().eachItemGraphicEl((function(t){t&&(e?fu(t):gu(t))}))}))},e.type="marker",e}(Ky);function fH(t,e,n){var i=e.coordinateSystem,r=n.getWidth(),o=n.getHeight(),a=i&&i.getArea&&i.getArea();t.each((function(n){var s,l=t.getItemModel(n),u="coordinate"===l.get("relativeTo"),c=u?a?a.width:0:r,h=u?a?a.height:0:o,d=u&&a?a.x:0,p=u&&a?a.y:0,f=yo(l.get("x"),c)+d,g=yo(l.get("y"),h)+p;if(isNaN(f)||isNaN(g)){if(e.getMarkerPosition)s=e.getMarkerPosition(t.getValues(t.dimensions,n));else if(i){var y=t.get(i.dimensions[0],n),v=t.get(i.dimensions[1],n);s=i.dataToPoint([y,v])}}else s=[f,g];isNaN(f)||(s[0]=f),isNaN(g)||(s[1]=g),t.setItemLayout(n,s)}))}var gH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.updateTransform=function(t,e,n){e.eachSeries((function(t){var e=nH.getMarkerModelFromSeries(t,"markPoint");e&&(fH(e.getData(),t,n),this.markerGroupMap.get(t.id).updateLayout())}),this)},e.prototype.renderSeries=function(t,e,n,i){var r=t.coordinateSystem,o=t.id,a=t.getData(),s=this.markerGroupMap,l=s.get(o)||s.set(o,new uI),u=function(t,e,n){var i;i=t?E(t&&t.dimensions,(function(t){return A(A({},e.getData().getDimensionInfo(e.getData().mapDimension(t))||{}),{name:t,ordinalMeta:null})})):[{name:"value",type:"float"}];var r=new B_(i,n),o=E(n.get("data"),H(sH,e));t&&(o=V(o,H(uH,t)));var a=cH(!!t,i);return r.initData(o,null,a),r}(r,t,e);e.setData(u),fH(e.getData(),t,i),u.each((function(t){var n=u.getItemModel(t),i=n.getShallow("symbol"),r=n.getShallow("symbolSize"),o=n.getShallow("symbolRotate"),s=n.getShallow("symbolOffset"),l=n.getShallow("symbolKeepAspect");if(Y(i)||Y(r)||Y(o)||Y(s)){var c=e.getRawValue(t),h=e.getDataParams(t);Y(i)&&(i=i(c,h)),Y(r)&&(r=r(c,h)),Y(o)&&(o=o(c,h)),Y(s)&&(s=s(c,h))}var d=n.getModel("itemStyle").getItemStyle(),p=n.get("z2"),f=qv(a,"color");d.fill||(d.fill=f),u.setItemVisual(t,{z2:rt(p,0),symbol:i,symbolSize:r,symbolRotate:o,symbolOffset:s,symbolKeepAspect:l,style:d})})),l.updateData(u),this.group.add(l.group),u.eachItemGraphicEl((function(t){t.traverse((function(t){zl(t).dataModel=e}))})),this.markKeep(l),l.group.silent=e.get("silent")||t.get("silent")},e.type="markPoint",e}(pH);var yH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.createMarkerModelFromSeries=function(t,n,i){return new e(t,n,i)},e.type="markLine",e.defaultOption={z:5,symbol:["circle","arrow"],symbolSize:[8,16],symbolOffset:0,precision:2,tooltip:{trigger:"item"},label:{show:!0,position:"end",distance:5},lineStyle:{type:"dashed"},emphasis:{label:{show:!0},lineStyle:{width:3}},animationEasing:"linear"},e}(nH),vH=sa(),mH=function(t,e,n,i){var r,o=t.getData();if(U(i))r=i;else{var a=i.type;if("min"===a||"max"===a||"average"===a||"median"===a||null!=i.xAxis||null!=i.yAxis){var s=void 0,l=void 0;if(null!=i.yAxis||null!=i.xAxis)s=e.getAxis(null!=i.yAxis?"y":"x"),l=it(i.yAxis,i.xAxis);else{var u=lH(i,o,e,t);s=u.valueAxis,l=hH(o,X_(o,u.valueDataDim),a)}var c="x"===s.dim?0:1,h=1-c,d=T(i),p={coord:[]};d.type=null,d.coord=[],d.coord[h]=-1/0,p.coord[h]=1/0;var f=n.get("precision");f>=0&&j(l)&&(l=+l.toFixed(Math.min(f,20))),d.coord[c]=p.coord[c]=l,r=[d,p,{type:a,valueIndex:i.valueIndex,value:l}]}else r=[]}var g=[sH(t,r[0]),sH(t,r[1]),A({},r[2])];return g[2].type=g[2].type||null,C(g[2],g[0]),C(g[2],g[1]),g};function xH(t){return!isNaN(t)&&!isFinite(t)}function _H(t,e,n,i){var r=1-t,o=i.dimensions[t];return xH(e[r])&&xH(n[r])&&e[t]===n[t]&&i.getAxis(o).containData(e[t])}function bH(t,e){if("cartesian2d"===t.type){var n=e[0].coord,i=e[1].coord;if(n&&i&&(_H(1,n,i,t)||_H(0,n,i,t)))return!0}return uH(t,e[0])&&uH(t,e[1])}function wH(t,e,n,i,r){var o,a=i.coordinateSystem,s=t.getItemModel(e),l=yo(s.get("x"),r.getWidth()),u=yo(s.get("y"),r.getHeight());if(isNaN(l)||isNaN(u)){if(i.getMarkerPosition)o=i.getMarkerPosition(t.getValues(t.dimensions,e));else{var c=a.dimensions,h=t.get(c[0],e),d=t.get(c[1],e);o=a.dataToPoint([h,d])}if(SI(a,"cartesian2d")){var p=a.getAxis("x"),f=a.getAxis("y");c=a.dimensions;xH(t.get(c[0],e))?o[0]=p.toGlobalCoord(p.getExtent()[n?0:1]):xH(t.get(c[1],e))&&(o[1]=f.toGlobalCoord(f.getExtent()[n?0:1]))}isNaN(l)||(o[0]=l),isNaN(u)||(o[1]=u)}else o=[l,u];t.setItemLayout(e,o)}var SH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.updateTransform=function(t,e,n){e.eachSeries((function(t){var e=nH.getMarkerModelFromSeries(t,"markLine");if(e){var i=e.getData(),r=vH(e).from,o=vH(e).to;r.each((function(e){wH(r,e,!0,t,n),wH(o,e,!1,t,n)})),i.each((function(t){i.setItemLayout(t,[r.getItemLayout(t),o.getItemLayout(t)])})),this.markerGroupMap.get(t.id).updateLayout()}}),this)},e.prototype.renderSeries=function(t,e,n,i){var r=t.coordinateSystem,o=t.id,a=t.getData(),s=this.markerGroupMap,l=s.get(o)||s.set(o,new IP);this.group.add(l.group);var u=function(t,e,n){var i;i=t?E(t&&t.dimensions,(function(t){return A(A({},e.getData().getDimensionInfo(e.getData().mapDimension(t))||{}),{name:t,ordinalMeta:null})})):[{name:"value",type:"float"}];var r=new B_(i,n),o=new B_(i,n),a=new B_([],n),s=E(n.get("data"),H(mH,e,t,n));t&&(s=V(s,H(bH,t)));var l=cH(!!t,i);return r.initData(E(s,(function(t){return t[0]})),null,l),o.initData(E(s,(function(t){return t[1]})),null,l),a.initData(E(s,(function(t){return t[2]}))),a.hasItemOption=!0,{from:r,to:o,line:a}}(r,t,e),c=u.from,h=u.to,d=u.line;vH(e).from=c,vH(e).to=h,e.setData(d);var p=e.get("symbol"),f=e.get("symbolSize"),g=e.get("symbolRotate"),y=e.get("symbolOffset");function v(e,n,r){var o=e.getItemModel(n);wH(e,n,r,t,i);var s=o.getModel("itemStyle").getItemStyle();null==s.fill&&(s.fill=qv(a,"color")),e.setItemVisual(n,{symbolKeepAspect:o.get("symbolKeepAspect"),symbolOffset:rt(o.get("symbolOffset",!0),y[r?0:1]),symbolRotate:rt(o.get("symbolRotate",!0),g[r?0:1]),symbolSize:rt(o.get("symbolSize"),f[r?0:1]),symbol:rt(o.get("symbol",!0),p[r?0:1]),style:s})}U(p)||(p=[p,p]),U(f)||(f=[f,f]),U(g)||(g=[g,g]),U(y)||(y=[y,y]),u.from.each((function(t){v(c,t,!0),v(h,t,!1)})),d.each((function(t){var e=d.getItemModel(t),n=e.getModel("lineStyle").getLineStyle();d.setItemLayout(t,[c.getItemLayout(t),h.getItemLayout(t)]);var i=e.get("z2");null==n.stroke&&(n.stroke=c.getItemVisual(t,"style").fill),d.setItemVisual(t,{z2:rt(i,0),fromSymbolKeepAspect:c.getItemVisual(t,"symbolKeepAspect"),fromSymbolOffset:c.getItemVisual(t,"symbolOffset"),fromSymbolRotate:c.getItemVisual(t,"symbolRotate"),fromSymbolSize:c.getItemVisual(t,"symbolSize"),fromSymbol:c.getItemVisual(t,"symbol"),toSymbolKeepAspect:h.getItemVisual(t,"symbolKeepAspect"),toSymbolOffset:h.getItemVisual(t,"symbolOffset"),toSymbolRotate:h.getItemVisual(t,"symbolRotate"),toSymbolSize:h.getItemVisual(t,"symbolSize"),toSymbol:h.getItemVisual(t,"symbol"),style:n})})),l.updateData(d),u.line.eachItemGraphicEl((function(t){zl(t).dataModel=e,t.traverse((function(t){zl(t).dataModel=e}))})),this.markKeep(l),l.group.silent=e.get("silent")||t.get("silent")},e.type="markLine",e}(pH);var MH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.createMarkerModelFromSeries=function(t,n,i){return new e(t,n,i)},e.type="markArea",e.defaultOption={z:1,tooltip:{trigger:"item"},animation:!1,label:{show:!0,position:"top"},itemStyle:{borderWidth:0},emphasis:{label:{show:!0,position:"top"}}},e}(nH),IH=sa(),TH=function(t,e,n,i){var r=i[0],o=i[1];if(r&&o){var a=sH(t,r),s=sH(t,o),l=a.coord,u=s.coord;l[0]=it(l[0],-1/0),l[1]=it(l[1],-1/0),u[0]=it(u[0],1/0),u[1]=it(u[1],1/0);var c=D([{},a,s]);return c.coord=[a.coord,s.coord],c.x0=a.x,c.y0=a.y,c.x1=s.x,c.y1=s.y,c}};function CH(t){return!isNaN(t)&&!isFinite(t)}function DH(t,e,n,i){var r=1-t;return CH(e[r])&&CH(n[r])}function AH(t,e){var n=e.coord[0],i=e.coord[1],r={coord:n,x:e.x0,y:e.y0},o={coord:i,x:e.x1,y:e.y1};return SI(t,"cartesian2d")?!(!n||!i||!DH(1,n,i)&&!DH(0,n,i))||function(t,e,n){return!(t&&t.containZone&&e.coord&&n.coord&&!rH(e)&&!rH(n))||t.containZone(e.coord,n.coord)}(t,r,o):uH(t,r)||uH(t,o)}function kH(t,e,n,i,r){var o,a=i.coordinateSystem,s=t.getItemModel(e),l=yo(s.get(n[0]),r.getWidth()),u=yo(s.get(n[1]),r.getHeight());if(isNaN(l)||isNaN(u)){if(i.getMarkerPosition){var c=t.getValues(["x0","y0"],e),h=t.getValues(["x1","y1"],e),d=a.clampData(c),p=a.clampData(h),f=[];"x0"===n[0]?f[0]=d[0]>p[0]?h[0]:c[0]:f[0]=d[0]>p[0]?c[0]:h[0],"y0"===n[1]?f[1]=d[1]>p[1]?h[1]:c[1]:f[1]=d[1]>p[1]?c[1]:h[1],o=i.getMarkerPosition(f,n,!0)}else{var g=[m=t.get(n[0],e),x=t.get(n[1],e)];a.clampData&&a.clampData(g,g),o=a.dataToPoint(g,!0)}if(SI(a,"cartesian2d")){var y=a.getAxis("x"),v=a.getAxis("y"),m=t.get(n[0],e),x=t.get(n[1],e);CH(m)?o[0]=y.toGlobalCoord(y.getExtent()["x0"===n[0]?0:1]):CH(x)&&(o[1]=v.toGlobalCoord(v.getExtent()["y0"===n[1]?0:1]))}isNaN(l)||(o[0]=l),isNaN(u)||(o[1]=u)}else o=[l,u];return o}var LH=[["x0","y0"],["x1","y0"],["x1","y1"],["x0","y1"]],PH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.updateTransform=function(t,e,n){e.eachSeries((function(t){var e=nH.getMarkerModelFromSeries(t,"markArea");if(e){var i=e.getData();i.each((function(e){var r=E(LH,(function(r){return kH(i,e,r,t,n)}));i.setItemLayout(e,r),i.getItemGraphicEl(e).setShape("points",r)}))}}),this)},e.prototype.renderSeries=function(t,e,n,i){var r=t.coordinateSystem,o=t.id,a=t.getData(),s=this.markerGroupMap,l=s.get(o)||s.set(o,{group:new to});this.group.add(l.group),this.markKeep(l);var u=function(t,e,n){var i,r,o=["x0","y0","x1","y1"];if(t){var a=E(t&&t.dimensions,(function(t){var n=e.getData();return A(A({},n.getDimensionInfo(n.mapDimension(t))||{}),{name:t,ordinalMeta:null})}));r=E(o,(function(t,e){return{name:t,type:a[e%2].type}})),i=new B_(r,n)}else i=new B_(r=[{name:"value",type:"float"}],n);var s=E(n.get("data"),H(TH,e,t,n));t&&(s=V(s,H(AH,t)));var l=t?function(t,e,n,i){return Xg(t.coord[Math.floor(i/2)][i%2],r[i])}:function(t,e,n,i){return Xg(t.value,r[i])};return i.initData(s,null,l),i.hasItemOption=!0,i}(r,t,e);e.setData(u),u.each((function(e){var n=E(LH,(function(n){return kH(u,e,n,t,i)})),o=r.getAxis("x").scale,s=r.getAxis("y").scale,l=o.getExtent(),c=s.getExtent(),h=[o.parse(u.get("x0",e)),o.parse(u.get("x1",e))],d=[s.parse(u.get("y0",e)),s.parse(u.get("y1",e))];xo(h),xo(d);var p=!!(l[0]>h[1]||l[1]d[1]||c[1]=0},e.prototype.getOrient=function(){return"vertical"===this.get("orient")?{index:1,name:"vertical"}:{index:0,name:"horizontal"}},e.type="legend.plain",e.dependencies=["series"],e.defaultOption={z:4,show:!0,orient:"horizontal",left:"center",bottom:tf.size.m,align:"auto",backgroundColor:tf.color.transparent,borderColor:tf.color.border,borderRadius:0,borderWidth:0,padding:5,itemGap:8,itemWidth:25,itemHeight:14,symbolRotate:"inherit",symbolKeepAspect:!0,inactiveColor:tf.color.disabled,inactiveBorderColor:tf.color.disabled,inactiveBorderWidth:"auto",itemStyle:{color:"inherit",opacity:"inherit",borderColor:"inherit",borderWidth:"auto",borderCap:"inherit",borderJoin:"inherit",borderDashOffset:"inherit",borderMiterLimit:"inherit"},lineStyle:{width:"auto",color:"inherit",inactiveColor:tf.color.disabled,inactiveWidth:2,opacity:"inherit",type:"inherit",cap:"inherit",join:"inherit",dashOffset:"inherit",miterLimit:"inherit"},textStyle:{color:tf.color.secondary},selectedMode:!0,selector:!1,selectorLabel:{show:!0,borderRadius:10,padding:[3,5,3,5],fontSize:12,fontFamily:"sans-serif",color:tf.color.tertiary,borderWidth:1,borderColor:tf.color.border},emphasis:{selectorLabel:{show:!0,color:tf.color.quaternary}},selectorPosition:"auto",selectorItemGap:7,selectorButtonGap:10,tooltip:{show:!1},triggerEvent:!1},e}(Qp),RH=H,NH=z,zH=to,EH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.newlineDisabled=!1,n}return n(e,t),e.prototype.init=function(){this.group.add(this._contentGroup=new zH),this.group.add(this._selectorGroup=new zH),this._isFirstRender=!0},e.prototype.getContentGroup=function(){return this._contentGroup},e.prototype.getSelectorGroup=function(){return this._selectorGroup},e.prototype.render=function(t,e,n){var i=this._isFirstRender;if(this._isFirstRender=!1,this.resetInner(),t.get("show",!0)){var r=t.get("align"),o=t.get("orient");r&&"auto"!==r||(r="right"===t.get("left")&&"vertical"===o?"right":"left");var a=t.get("selector",!0),s=t.get("selectorPosition",!0);!a||s&&"auto"!==s||(s="horizontal"===o?"end":"start"),this.renderInner(r,t,e,n,a,o,s);var l=Xp(t,n).refContainer,u=t.getBoxLayoutParams(),c=t.get("padding"),h=Hp(u,l,c),d=this.layoutInner(t,r,h,i,a,s),p=Hp(k({width:d.width,height:d.height},u),l,c);this.group.x=p.x-d.x,this.group.y=p.y-d.y,this.group.markRedraw(),this.group.add(this._backgroundEl=dF(d,t))}},e.prototype.resetInner=function(){this.getContentGroup().removeAll(),this._backgroundEl&&this.group.remove(this._backgroundEl),this.getSelectorGroup().removeAll()},e.prototype.renderInner=function(t,e,n,i,r,o,a){var s=this.getContentGroup(),l=yt(),u=e.get("selectedMode"),c=e.get("triggerEvent"),h=[];n.eachRawSeries((function(t){!t.get("legendHoverLink")&&h.push(t.id)})),NH(e.getData(),(function(r,o){var a=this,d=r.get("name");if(!this.newlineDisabled&&(""===d||"\n"===d)){var p=new zH;return p.newline=!0,void s.add(p)}var f=n.getSeriesByName(d)[0];if(!l.get(d)){if(f){var g=f.getData(),y=g.getVisual("legendLineStyle")||{},v=g.getVisual("legendIcon"),m=g.getVisual("style"),x=this._createItem(f,d,o,r,e,t,y,m,v,u,i);x.on("click",RH(BH,d,null,i,h)).on("mouseover",RH(GH,f.name,null,i,h)).on("mouseout",RH(FH,f.name,null,i,h)),n.ssr&&x.eachChild((function(t){var e=zl(t);e.seriesIndex=f.seriesIndex,e.dataIndex=o,e.ssrType="legend"})),c&&x.eachChild((function(t){a.packEventData(t,e,f,o,d)})),l.set(d,!0)}else n.eachRawSeries((function(a){var s=this;if(!l.get(d)&&a.legendVisualProvider){var p=a.legendVisualProvider;if(!p.containName(d))return;var f=p.indexOfName(d),g=p.getItemVisual(f,"style"),y=p.getItemVisual(f,"legendIcon"),v=oi(g.fill);v&&0===v[3]&&(v[3]=.2,g=A(A({},g),{fill:fi(v,"rgba")}));var m=this._createItem(a,d,o,r,e,t,{},g,y,u,i);m.on("click",RH(BH,null,d,i,h)).on("mouseover",RH(GH,null,d,i,h)).on("mouseout",RH(FH,null,d,i,h)),n.ssr&&m.eachChild((function(t){var e=zl(t);e.seriesIndex=a.seriesIndex,e.dataIndex=o,e.ssrType="legend"})),c&&m.eachChild((function(t){s.packEventData(t,e,a,o,d)})),l.set(d,!0)}}),this);0}}),this),r&&this._createSelector(r,e,i,o,a)},e.prototype.packEventData=function(t,e,n,i,r){var o={componentType:"legend",componentIndex:e.componentIndex,dataIndex:i,value:r,seriesIndex:n.seriesIndex};zl(t).eventData=o},e.prototype._createSelector=function(t,e,n,i,r){var o=this.getSelectorGroup();NH(t,(function(t){var i=t.type,r=new Sl({style:{x:0,y:0,align:"center",verticalAlign:"middle"},onclick:function(){n.dispatchAction({type:"all"===i?"legendAllSelect":"legendInverseSelect",legendId:e.id})}});o.add(r),$h(r,{normal:e.getModel("selectorLabel"),emphasis:e.getModel(["emphasis","selectorLabel"])},{defaultText:t.title}),Iu(r)}))},e.prototype._createItem=function(t,e,n,i,r,o,a,s,l,u,c){var h=t.visualDrawType,d=r.get("itemWidth"),p=r.get("itemHeight"),f=r.isSelected(e),g=i.get("symbolRotate"),y=i.get("symbolKeepAspect"),v=i.get("icon"),m=function(t,e,n,i,r,o,a){function s(t,e){"auto"===t.lineWidth&&(t.lineWidth=e.lineWidth>0?2:0),NH(t,(function(n,i){"inherit"===t[i]&&(t[i]=e[i])}))}var l=e.getModel("itemStyle"),u=l.getItemStyle(),c=0===t.lastIndexOf("empty",0)?"fill":"stroke",h=l.getShallow("decal");u.decal=h&&"inherit"!==h?Bm(h,a):i.decal,"inherit"===u.fill&&(u.fill=i[r]);"inherit"===u.stroke&&(u.stroke=i[c]);"inherit"===u.opacity&&(u.opacity=("fill"===r?i:n).opacity);s(u,i);var d=e.getModel("lineStyle"),p=d.getLineStyle();if(s(p,n),"auto"===u.fill&&(u.fill=i.fill),"auto"===u.stroke&&(u.stroke=i.fill),"auto"===p.stroke&&(p.stroke=i.fill),!o){var f=e.get("inactiveBorderWidth"),g=u[c];u.lineWidth="auto"===f?i.lineWidth>0&&g?2:0:u.lineWidth,u.fill=e.get("inactiveColor"),u.stroke=e.get("inactiveBorderColor"),p.stroke=d.get("inactiveColor"),p.lineWidth=d.get("inactiveWidth")}return{itemStyle:u,lineStyle:p}}(l=v||l||"roundRect",i,a,s,h,f,c),x=new zH,_=i.getModel("textStyle");if(!Y(t.getLegendIcon)||v&&"inherit"!==v){var b="inherit"===v&&t.getData().getVisual("symbol")?"inherit"===g?t.getData().getVisual("symbolRotate"):g:0;x.add(function(t){var e=t.icon||"roundRect",n=hm(e,0,0,t.itemWidth,t.itemHeight,t.itemStyle.fill,t.symbolKeepAspect);n.setStyle(t.itemStyle),n.rotation=(t.iconRotate||0)*Math.PI/180,n.setOrigin([t.itemWidth/2,t.itemHeight/2]),e.indexOf("empty")>-1&&(n.style.stroke=n.style.fill,n.style.fill=tf.color.neutral00,n.style.lineWidth=2);return n}({itemWidth:d,itemHeight:p,icon:l,iconRotate:b,itemStyle:m.itemStyle,lineStyle:m.lineStyle,symbolKeepAspect:y}))}else x.add(t.getLegendIcon({itemWidth:d,itemHeight:p,icon:l,iconRotate:g,itemStyle:m.itemStyle,lineStyle:m.lineStyle,symbolKeepAspect:y}));var w="left"===o?d+5:-5,S=o,M=r.get("formatter"),I=e;X(M)&&M?I=M.replace("{name}",null!=e?e:""):Y(M)&&(I=M(e));var T=f?_.getTextColor():i.get("inactiveColor");x.add(new Sl({style:Qh(_,{text:I,x:w,y:p/2,fill:T,align:S,verticalAlign:"middle"},{inheritColor:T})}));var C=new xl({shape:x.getBoundingRect(),style:{fill:"transparent"}}),D=i.getModel("tooltip");return D.get("show")&&zh({el:C,componentModel:r,itemName:e,itemTooltipOption:D.option}),x.add(C),x.eachChild((function(t){t.silent=!0})),C.silent=!u,this.getContentGroup().add(x),Iu(x),x.__legendDataIndex=n,x},e.prototype.layoutInner=function(t,e,n,i,r,o){var a=this.getContentGroup(),s=this.getSelectorGroup();Gp(t.get("orient"),a,t.get("itemGap"),n.width,n.height);var l=a.getBoundingRect(),u=[-l.x,-l.y];if(s.markRedraw(),a.markRedraw(),r){Gp("horizontal",s,t.get("selectorItemGap",!0));var c=s.getBoundingRect(),h=[-c.x,-c.y],d=t.get("selectorButtonGap",!0),p=t.getOrient().index,f=0===p?"width":"height",g=0===p?"height":"width",y=0===p?"y":"x";"end"===o?h[p]+=l[f]+d:u[p]+=c[f]+d,h[1-p]+=l[g]/2-c[g]/2,s.x=h[0],s.y=h[1],a.x=u[0],a.y=u[1];var v={x:0,y:0};return v[f]=l[f]+d+c[f],v[g]=Math.max(l[g],c[g]),v[y]=Math.min(0,c[y]+h[1-p]),v}return a.x=u[0],a.y=u[1],this.group.getBoundingRect()},e.prototype.remove=function(){this.getContentGroup().removeAll(),this._isFirstRender=!0},e.type="legend.plain",e}(Ky);function BH(t,e,n,i){FH(t,e,n,i),n.dispatchAction({type:"legendToggleSelect",name:null!=t?t:e}),GH(t,e,n,i)}function VH(t){for(var e,n=t.getZr().storage.getDisplayList(),i=0,r=n.length;in[r],f=[-h.x,-h.y];e||(f[i]=l[s]);var g=[0,0],y=[-d.x,-d.y],v=rt(t.get("pageButtonGap",!0),t.get("itemGap",!0));p&&("end"===t.get("pageButtonPosition",!0)?y[i]+=n[r]-d[r]:g[i]+=d[r]+v);y[1-i]+=h[o]/2-d[o]/2,l.setPosition(f),u.setPosition(g),c.setPosition(y);var m={x:0,y:0};if(m[r]=p?n[r]:h[r],m[o]=Math.max(h[o],d[o]),m[a]=Math.min(0,d[a]+y[1-i]),u.__rectSize=n[r],p){var x={x:0,y:0};x[r]=Math.max(n[r]-d[r]-v,0),x[o]=m[o],u.setClipPath(new xl({shape:x})),u.__rectSize=x[r]}else c.eachChild((function(t){t.attr({invisible:!0,silent:!0})}));var _=this._getPageInfo(t);return null!=_.pageIndex&&th(l,{x:_.contentPosition[0],y:_.contentPosition[1]},p?t:null),this._updatePageInfoView(t,_),m},e.prototype._pageGo=function(t,e,n){var i=this._getPageInfo(e)[t];null!=i&&n.dispatchAction({type:"legendScroll",scrollDataIndex:i,legendId:e.id})},e.prototype._updatePageInfoView=function(t,e){var n=this._controllerGroup;z(["pagePrev","pageNext"],(function(i){var r=null!=e[i+"DataIndex"],o=n.childOfName(i);o&&(o.setStyle("fill",r?t.get("pageIconColor",!0):t.get("pageIconInactiveColor",!0)),o.cursor=r?"pointer":"default")}));var i=n.childOfName("pageText"),r=t.get("pageFormatter"),o=e.pageIndex,a=null!=o?o+1:0,s=e.pageCount;i&&r&&i.setStyle("text",X(r)?r.replace("{current}",null==a?"":a+"").replace("{total}",null==s?"":s+""):r({current:a,total:s}))},e.prototype._getPageInfo=function(t){var e=t.get("scrollDataIndex",!0),n=this.getContentGroup(),i=this._containerGroup.__rectSize,r=t.getOrient().index,o=qH[r],a=KH[r],s=this._findTargetItemIndex(e),l=n.children(),u=l[s],c=l.length,h=c?1:0,d={contentPosition:[n.x,n.y],pageCount:h,pageIndex:h-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!u)return d;var p=m(u);d.contentPosition[r]=-p.s;for(var f=s+1,g=p,y=p,v=null;f<=c;++f)(!(v=m(l[f]))&&y.e>g.s+i||v&&!x(v,g.s))&&(g=y.i>g.i?y:v)&&(null==d.pageNextDataIndex&&(d.pageNextDataIndex=g.i),++d.pageCount),y=v;for(f=s-1,g=p,y=p,v=null;f>=-1;--f)(v=m(l[f]))&&x(y,v.s)||!(g.i=e&&t.s<=e+i}},e.prototype._findTargetItemIndex=function(t){return this._showController?(this.getContentGroup().eachChild((function(i,r){var o=i.__legendDataIndex;null==n&&null!=o&&(n=r),o===t&&(e=r)})),null!=e?e:n):0;var e,n},e.type="legend.scroll",e}(EH);function JH(t){h_(YH),t.registerComponentModel(XH),t.registerComponentView($H),function(t){t.registerAction("legendScroll","legendscroll",(function(t,e){var n=t.scrollDataIndex;null!=n&&e.eachComponent({mainType:"legend",subType:"scroll",query:t},(function(t){t.setScrollDataIndex(n)}))}))}(t)}var QH=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="dataZoom.inside",e.defaultOption=Id(qG.defaultOption,{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}),e}(qG),tU=sa();function eU(t,e,n){tU(t).coordSysRecordMap.each((function(t){var i=t.dataZoomInfoMap.get(e.uid);i&&(i.getRange=n)}))}function nU(t,e){if(e){t.removeKey(e.model.uid);var n=e.controller;n&&n.dispose()}}function iU(t,e){t.isDisposed()||t.dispatchAction({type:"dataZoom",animation:{easing:"cubicOut",duration:100},batch:e})}function rU(t,e,n,i){return t.coordinateSystem.containPoint([n,i])}function oU(t){t.registerProcessor(t.PRIORITY.PROCESSOR.FILTER,(function(t,e){var n=tU(e),i=n.coordSysRecordMap||(n.coordSysRecordMap=yt());i.each((function(t){t.dataZoomInfoMap=null})),t.eachComponent({mainType:"dataZoom",subType:"inside"},(function(t){z(ZG(t).infoList,(function(n){var r=n.model.uid,o=i.get(r)||i.set(r,function(t,e){var n={model:e,containsPoint:H(rU,e),dispatchAction:H(iU,t),dataZoomInfoMap:null,controller:null},i=n.controller=new LD(t.getZr());return z(["pan","zoom","scrollMove"],(function(t){i.on(t,(function(e){var i=[];n.dataZoomInfoMap.each((function(r){if(e.isAvailableBehavior(r.model.option)){var o=(r.getRange||{})[t],a=o&&o(r.dzReferCoordSysInfo,n.model.mainType,n.controller,e);!r.model.get("disabled",!0)&&a&&i.push({dataZoomId:r.model.id,start:a[0],end:a[1]})}})),i.length&&n.dispatchAction(i)}))})),n}(e,n.model));(o.dataZoomInfoMap||(o.dataZoomInfoMap=yt())).set(t.uid,{dzReferCoordSysInfo:n,model:t,getRange:null})}))})),i.each((function(t){var n,r=t.controller,o=t.dataZoomInfoMap;if(o){var a=o.keys()[0];null!=a&&(n=o.get(a))}if(n){var s=function(t,e,n){var i,r="type_",o={type_true:2,type_move:1,type_false:0,type_undefined:-1},a=!0;return t.each((function(t){var e=t.model,n=!e.get("disabled",!0)&&(!e.get("zoomLock",!0)||"move");o[r+n]>o[r+i]&&(i=n),a=a&&e.get("preventDefaultMouseMove",!0)})),{controlType:i,opt:{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!0,preventDefaultMouseMove:!!a,api:n,zInfo:{component:e.model},triggerInfo:{roamTrigger:null,isInSelf:e.containsPoint}}}}(o,t,e);r.enable(s.controlType,s.opt),cv(t,"dispatchAction",n.model.get("throttle",!0),"fixRate")}else nU(i,t)}))}))}var aU=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.type="dataZoom.inside",e}return n(e,t),e.prototype.render=function(e,n,i){t.prototype.render.apply(this,arguments),e.noTarget()?this._clear():(this.range=e.getPercentRange(),eU(i,e,{pan:W(sU.pan,this),zoom:W(sU.zoom,this),scrollMove:W(sU.scrollMove,this)}))},e.prototype.dispose=function(){this._clear(),t.prototype.dispose.apply(this,arguments)},e.prototype._clear=function(){!function(t,e){for(var n=tU(t).coordSysRecordMap,i=n.keys(),r=0;r0?s.pixelStart+s.pixelLength-s.pixel:s.pixel-s.pixelStart)/s.pixelLength*(o[1]-o[0])+o[0],u=Math.max(1/i.scale,0);o[0]=(o[0]-l)*u+l,o[1]=(o[1]-l)*u+l;var c=this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();return CO(0,o,[0,100],0,c.minSpan,c.maxSpan),this.range=o,r[0]!==o[0]||r[1]!==o[1]?o:void 0}},pan:lU((function(t,e,n,i,r,o){var a=uU[i]([o.oldX,o.oldY],[o.newX,o.newY],e,r,n);return a.signal*(t[1]-t[0])*a.pixel/a.pixelLength})),scrollMove:lU((function(t,e,n,i,r,o){return uU[i]([0,0],[o.scrollDelta,o.scrollDelta],e,r,n).signal*(t[1]-t[0])*o.scrollDelta}))};function lU(t){return function(e,n,i,r){var o=this.range,a=o.slice(),s=e.axisModels[0];if(s)return CO(t(a,s,e,n,i,r),a,[0,100],"all"),this.range=a,o[0]!==a[0]||o[1]!==a[1]?a:void 0}}var uU={grid:function(t,e,n,i,r){var o=n.axis,a={},s=r.model.coordinateSystem.getRect();return t=t||[0,0],"x"===o.dim?(a.pixel=e[0]-t[0],a.pixelLength=s.width,a.pixelStart=s.x,a.signal=o.inverse?1:-1):(a.pixel=e[1]-t[1],a.pixelLength=s.height,a.pixelStart=s.y,a.signal=o.inverse?-1:1),a},polar:function(t,e,n,i,r){var o=n.axis,a={},s=r.model.coordinateSystem,l=s.getRadiusAxis().getExtent(),u=s.getAngleAxis().getExtent();return t=t?s.pointToCoord(t):[0,0],e=s.pointToCoord(e),"radiusAxis"===n.mainType?(a.pixel=e[0]-t[0],a.pixelLength=l[1]-l[0],a.pixelStart=l[0],a.signal=o.inverse?1:-1):(a.pixel=e[1]-t[1],a.pixelLength=u[1]-u[0],a.pixelStart=u[0],a.signal=o.inverse?-1:1),a},singleAxis:function(t,e,n,i,r){var o=n.axis,a=r.model.coordinateSystem.getRect(),s={};return t=t||[0,0],"horizontal"===o.orient?(s.pixel=e[0]-t[0],s.pixelLength=a.width,s.pixelStart=a.x,s.signal=o.inverse?1:-1):(s.pixel=e[1]-t[1],s.pixelLength=a.height,s.pixelStart=a.y,s.signal=o.inverse?-1:1),s}};function cU(t){oF(t),t.registerComponentModel(QH),t.registerComponentView(aU),oU(t)}var hU=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.type="dataZoom.slider",e.layoutMode="box",e.defaultOption=Id(qG.defaultOption,{show:!0,right:"ph",top:"ph",width:"ph",height:"ph",left:null,bottom:null,borderColor:tf.color.accent10,borderRadius:0,backgroundColor:tf.color.transparent,dataBackground:{lineStyle:{color:tf.color.accent30,width:.5},areaStyle:{color:tf.color.accent20,opacity:.2}},selectedDataBackground:{lineStyle:{color:tf.color.accent40,width:.5},areaStyle:{color:tf.color.accent20,opacity:.3}},fillerColor:"rgba(135,175,274,0.2)",handleIcon:"path://M-9.35,34.56V42m0-40V9.5m-2,0h4a2,2,0,0,1,2,2v21a2,2,0,0,1-2,2h-4a2,2,0,0,1-2-2v-21A2,2,0,0,1-11.35,9.5Z",handleSize:"100%",handleStyle:{color:tf.color.neutral00,borderColor:tf.color.accent20},moveHandleSize:7,moveHandleIcon:"path://M-320.9-50L-320.9-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-348-41-339-50-320.9-50z M-212.3-50L-212.3-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-239.4-41-230.4-50-212.3-50z M-103.7-50L-103.7-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-130.9-41-121.8-50-103.7-50z",moveHandleStyle:{color:tf.color.accent40,opacity:.5},showDetail:!0,showDataShadow:"auto",realtime:!0,zoomLock:!1,textStyle:{color:tf.color.tertiary},brushSelect:!0,brushStyle:{color:tf.color.accent30,opacity:.3},emphasis:{handleLabel:{show:!0},handleStyle:{borderColor:tf.color.accent40},moveHandleStyle:{opacity:.8}},defaultLocationEdgeGap:15}),e}(qG),dU=xl,pU="horizontal",fU="vertical",gU=["line","bar","candlestick","scatter"],yU={easing:"cubicOut",duration:100,delay:0},vU=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._displayables={},n}return n(e,t),e.prototype.init=function(t,e){this.api=e,this._onBrush=W(this._onBrush,this),this._onBrushEnd=W(this._onBrushEnd,this)},e.prototype.render=function(e,n,i,r){if(t.prototype.render.apply(this,arguments),cv(this,"_dispatchZoomAction",e.get("throttle"),"fixRate"),this._orient=e.getOrient(),!1!==e.get("show")){if(e.noTarget())return this._clear(),void this.group.removeAll();r&&"dataZoom"===r.type&&r.from===this.uid||this._buildView(),this._updateView()}else this.group.removeAll()},e.prototype.dispose=function(){this._clear(),t.prototype.dispose.apply(this,arguments)},e.prototype._clear=function(){hv(this,"_dispatchZoomAction");var t=this.api.getZr();t.off("mousemove",this._onBrush),t.off("mouseup",this._onBrushEnd)},e.prototype._buildView=function(){var t=this.group;t.removeAll(),this._brushing=!1,this._displayables.brushRect=null,this._resetLocation(),this._resetInterval();var e=this._displayables.sliderGroup=new to;this._renderBackground(),this._renderHandle(),this._renderDataShadow(),t.add(e),this._positionGroup()},e.prototype._resetLocation=function(){var t=this.dataZoomModel,e=this.api,n=t.get("brushSelect")?7:0,i=Xp(t,e).refContainer,r=this._findCoordRect(),o=t.get("defaultLocationEdgeGap",!0)||0,a=this._orient===pU?{right:i.width-r.x-r.width,top:i.height-30-o-n,width:r.width,height:30}:{right:o,top:r.y,width:30,height:r.height},s=Kp(t.option);z(["right","top","width","height"],(function(t){"ph"===s[t]&&(s[t]=a[t])}));var l=Hp(s,i);this._location={x:l.x,y:l.y},this._size=[l.width,l.height],this._orient===fU&&this._size.reverse()},e.prototype._positionGroup=function(){var t=this.group,e=this._location,n=this._orient,i=this.dataZoomModel.getFirstTargetAxisModel(),r=i&&i.get("inverse"),o=this._displayables.sliderGroup,a=(this._dataShadowInfo||{}).otherAxisInverse;o.attr(n!==pU||r?n===pU&&r?{scaleY:a?1:-1,scaleX:-1}:n!==fU||r?{scaleY:a?-1:1,scaleX:-1,rotation:Math.PI/2}:{scaleY:a?-1:1,scaleX:1,rotation:Math.PI/2}:{scaleY:a?1:-1,scaleX:1});var s=t.getBoundingRect([o]);t.x=e.x-s.x,t.y=e.y-s.y,t.markRedraw()},e.prototype._getViewExtent=function(){return[0,this._size[0]]},e.prototype._renderBackground=function(){var t=this.dataZoomModel,e=this._size,n=this._displayables.sliderGroup,i=t.get("brushSelect");n.add(new dU({silent:!0,shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:t.get("backgroundColor")},z2:-40}));var r=new dU({shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:"transparent"},z2:0,onclick:W(this._onClickPanel,this)}),o=this.api.getZr();i?(r.on("mousedown",this._onBrushStart,this),r.cursor="crosshair",o.on("mousemove",this._onBrush),o.on("mouseup",this._onBrushEnd)):(o.off("mousemove",this._onBrush),o.off("mouseup",this._onBrushEnd)),n.add(r)},e.prototype._renderDataShadow=function(){var t=this._dataShadowInfo=this._prepareDataShadowInfo();if(this._displayables.dataShadowSegs=[],t){var e=this._size,n=this._shadowSize||[],i=t.series,r=i.getRawData(),o=i.getShadowDim&&i.getShadowDim(),a=o&&r.getDimensionInfo(o)?i.getShadowDim():t.otherDim;if(null!=a){var s=this._shadowPolygonPts,l=this._shadowPolylinePts;if(r!==this._shadowData||a!==this._shadowDim||e[0]!==n[0]||e[1]!==n[1]){var u=r.getDataExtent(t.thisDim),c=r.getDataExtent(a),h=.3*(c[1]-c[0]);c=[c[0]-h,c[1]+h];var d,p=[0,e[1]],f=[0,e[0]],g=[[e[0],0],[0,0]],y=[],v=f[1]/Math.max(1,r.count()-1),m=e[0]/(u[1]-u[0]),x="time"===t.thisAxis.type,_=-v,b=Math.round(r.count()/e[0]);r.each([t.thisDim,a],(function(t,e,n){if(b>0&&n%b)x||(_+=v);else{_=x?(+t-u[0])*m:_+v;var i=null==e||isNaN(e)||""===e,r=i?0:go(e,c,p,!0);i&&!d&&n?(g.push([g[g.length-1][0],0]),y.push([y[y.length-1][0],0])):!i&&d&&(g.push([_,0]),y.push([_,0])),i||(g.push([_,r]),y.push([_,r])),d=i}})),s=this._shadowPolygonPts=g,l=this._shadowPolylinePts=y}this._shadowData=r,this._shadowDim=a,this._shadowSize=[e[0],e[1]];for(var w=this.dataZoomModel,S=0;S<3;S++){var M=I(1===S);this._displayables.sliderGroup.add(M),this._displayables.dataShadowSegs.push(M)}}}function I(t){var e=w.getModel(t?"selectedDataBackground":"dataBackground"),n=new to,i=new Mc({shape:{points:s},segmentIgnoreThreshold:1,style:e.getModel("areaStyle").getAreaStyle(),silent:!0,z2:-20}),r=new Tc({shape:{points:l},segmentIgnoreThreshold:1,style:e.getModel("lineStyle").getLineStyle(),silent:!0,z2:-19});return n.add(i),n.add(r),n}},e.prototype._prepareDataShadowInfo=function(){var t=this.dataZoomModel,e=t.get("showDataShadow");if(!1!==e){var n,i=this.ecModel;return t.eachTargetAxis((function(r,o){z(t.getAxisProxy(r,o).getTargetSeriesModels(),(function(t){if(!(n||!0!==e&&P(gU,t.get("type"))<0)){var a,s=i.getComponent(YG(r),o).axis,l=function(t){var e={x:"y",y:"x",radius:"angle",angle:"radius"};return e[t]}(r),u=t.coordinateSystem;null!=l&&u.getOtherAxis&&(a=u.getOtherAxis(s).inverse),l=t.getData().mapDimension(l);var c=t.getData().mapDimension(r);n={thisAxis:s,series:t,thisDim:c,otherDim:l,otherAxisInverse:a}}}),this)}),this),n}},e.prototype._renderHandle=function(){var t=this.group,e=this._displayables,n=e.handles=[null,null],i=e.handleLabels=[null,null],r=this._displayables.sliderGroup,o=this._size,a=this.dataZoomModel,s=this.api,l=a.get("borderRadius")||0,u=a.get("brushSelect"),c=e.filler=new dU({silent:u,style:{fill:a.get("fillerColor")},textConfig:{position:"inside"}});r.add(c),r.add(new dU({silent:!0,subPixelOptimize:!0,shape:{x:0,y:0,width:o[0],height:o[1],r:l},style:{stroke:a.get("dataBackgroundColor")||a.get("borderColor"),lineWidth:1,fill:tf.color.transparent}})),z([0,1],(function(e){var o=a.get("handleIcon");!lm[o]&&o.indexOf("path://")<0&&o.indexOf("image://")<0&&(o="path://"+o);var s,l=hm(o,-1,0,2,2,null,!0);l.attr({cursor:(s=this._orient,"vertical"===s?"ns-resize":"ew-resize"),draggable:!0,drift:W(this._onDragMove,this,e),ondragend:W(this._onDragEnd,this),onmouseover:W(this._showDataInfo,this,!0),onmouseout:W(this._showDataInfo,this,!1),z2:5});var u=l.getBoundingRect(),c=a.get("handleSize");this._handleHeight=yo(c,this._size[1]),this._handleWidth=u.width/u.height*this._handleHeight,l.setStyle(a.getModel("handleStyle").getItemStyle()),l.style.strokeNoScale=!0,l.rectHover=!0,l.ensureState("emphasis").style=a.getModel(["emphasis","handleStyle"]).getItemStyle(),Iu(l);var h=a.get("handleColor");null!=h&&(l.style.fill=h),r.add(n[e]=l);var d=a.getModel("textStyle"),p=(a.get("handleLabel")||{}).show||!1;t.add(i[e]=new Sl({silent:!0,invisible:!p,style:Qh(d,{x:0,y:0,text:"",verticalAlign:"middle",align:"center",fill:d.getTextColor(),font:d.getFont()}),z2:10}))}),this);var h=c;if(u){var d=yo(a.get("moveHandleSize"),o[1]),p=e.moveHandle=new xl({style:a.getModel("moveHandleStyle").getItemStyle(),silent:!0,shape:{r:[0,0,2,2],y:o[1]-.5,height:d}}),f=.8*d,g=e.moveHandleIcon=hm(a.get("moveHandleIcon"),-f/2,-f/2,f,f,tf.color.neutral00,!0);g.silent=!0,g.y=o[1]+d/2-.5,p.ensureState("emphasis").style=a.getModel(["emphasis","moveHandleStyle"]).getItemStyle();var y=Math.min(o[1]/2,Math.max(d,10));(h=e.moveZone=new xl({invisible:!0,shape:{y:o[1]-y,height:d+y}})).on("mouseover",(function(){s.enterEmphasis(p)})).on("mouseout",(function(){s.leaveEmphasis(p)})),r.add(p),r.add(g),r.add(h)}h.attr({draggable:!0,cursor:"default",drift:W(this._onDragMove,this,"all"),ondragstart:W(this._showDataInfo,this,!0),ondragend:W(this._onDragEnd,this),onmouseover:W(this._showDataInfo,this,!0),onmouseout:W(this._showDataInfo,this,!1)})},e.prototype._resetInterval=function(){var t=this._range=this.dataZoomModel.getPercentRange(),e=this._getViewExtent();this._handleEnds=[go(t[0],[0,100],e,!0),go(t[1],[0,100],e,!0)]},e.prototype._updateInterval=function(t,e){var n=this.dataZoomModel,i=this._handleEnds,r=this._getViewExtent(),o=n.findRepresentativeAxisProxy().getMinMaxSpan(),a=[0,100];CO(e,i,r,n.get("zoomLock")?"all":t,null!=o.minSpan?go(o.minSpan,a,r,!0):null,null!=o.maxSpan?go(o.maxSpan,a,r,!0):null);var s=this._range,l=this._range=xo([go(i[0],r,a,!0),go(i[1],r,a,!0)]);return!s||s[0]!==l[0]||s[1]!==l[1]},e.prototype._updateView=function(t){var e=this._displayables,n=this._handleEnds,i=xo(n.slice()),r=this._size;z([0,1],(function(t){var i=e.handles[t],o=this._handleHeight;i.attr({scaleX:o/2,scaleY:o/2,x:n[t]+(t?-1:1),y:r[1]/2-o/2})}),this),e.filler.setShape({x:i[0],y:0,width:i[1]-i[0],height:r[1]});var o={x:i[0],width:i[1]-i[0]};e.moveHandle&&(e.moveHandle.setShape(o),e.moveZone.setShape(o),e.moveZone.getBoundingRect(),e.moveHandleIcon&&e.moveHandleIcon.attr("x",o.x+o.width/2));for(var a=e.dataShadowSegs,s=[0,i[0],i[1],r[0]],l=0;le[0]||n[1]<0||n[1]>e[1])){var i=this._handleEnds,r=(i[0]+i[1])/2,o=this._updateInterval("all",n[0]-r);this._updateView(),o&&this._dispatchZoomAction(!1)}},e.prototype._onBrushStart=function(t){var e=t.offsetX,n=t.offsetY;this._brushStart=new Ae(e,n),this._brushing=!0,this._brushStartTime=+new Date},e.prototype._onBrushEnd=function(t){if(this._brushing){var e=this._displayables.brushRect;if(this._brushing=!1,e){e.attr("ignore",!0);var n=e.shape;if(!(+new Date-this._brushStartTime<200&&Math.abs(n.width)<5)){var i=this._getViewExtent(),r=[0,100],o=this._handleEnds=[n.x,n.x+n.width],a=this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();CO(0,o,i,0,null!=a.minSpan?go(a.minSpan,r,i,!0):null,null!=a.maxSpan?go(a.maxSpan,r,i,!0):null),this._range=xo([go(o[0],i,r,!0),go(o[1],i,r,!0)]),this._updateView(),this._dispatchZoomAction(!1)}}}},e.prototype._onBrush=function(t){this._brushing&&(fe(t.event),this._updateBrushRect(t.offsetX,t.offsetY))},e.prototype._updateBrushRect=function(t,e){var n=this._displayables,i=this.dataZoomModel,r=n.brushRect;r||(r=n.brushRect=new dU({silent:!0,style:i.getModel("brushStyle").getItemStyle()}),n.sliderGroup.add(r)),r.attr("ignore",!1);var o=this._brushStart,a=this._displayables.sliderGroup,s=a.transformCoordToLocal(t,e),l=a.transformCoordToLocal(o.x,o.y),u=this._size;s[0]=Math.max(Math.min(u[0],s[0]),0),r.setShape({x:l[0],y:0,width:s[0]-l[0],height:u[1]})},e.prototype._dispatchZoomAction=function(t){var e=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,animation:t?yU:null,start:e[0],end:e[1]})},e.prototype._findCoordRect=function(){var t,e=ZG(this.dataZoomModel).infoList;if(!t&&e.length){var n=e[0].model.coordinateSystem;t=n.getRect&&n.getRect()}if(!t){var i=this.api.getWidth(),r=this.api.getHeight();t={x:.2*i,y:.2*r,width:.6*i,height:.6*r}}return t},e.type="dataZoom.slider",e}(JG);function mU(t){t.registerComponentModel(hU),t.registerComponentView(vU),oF(t)}var xU=function(t,e,n){var i=T((_U[t]||{})[e]);return n&&U(i)?i[i.length-1]:i},_U={color:{active:["#006edd","#e0ffff"],inactive:[tf.color.transparent]},colorHue:{active:[0,360],inactive:[0,0]},colorSaturation:{active:[.3,1],inactive:[0,0]},colorLightness:{active:[.9,.5],inactive:[0,0]},colorAlpha:{active:[.3,1],inactive:[0,0]},opacity:{active:[.3,1],inactive:[0,0]},symbol:{active:["circle","roundRect","diamond"],inactive:["none"]},symbolSize:{active:[10,50],inactive:[0,0]}},bU=hL.mapVisual,wU=hL.eachVisual,SU=U,MU=z,IU=xo,TU=go,CU=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.stateList=["inRange","outOfRange"],n.replacableOptionKeys=["inRange","outOfRange","target","controller","color"],n.layoutMode={type:"box",ignoreSize:!0},n.dataBound=[-1/0,1/0],n.targetVisuals={},n.controllerVisuals={},n}return n(e,t),e.prototype.init=function(t,e,n){this.mergeDefaultAndTheme(t,n)},e.prototype.optionUpdated=function(t,e){var n=this.option;!e&&bW(n,t,this.replacableOptionKeys),this.textStyleModel=this.getModel("textStyle"),this.resetItemSize(),this.completeVisualOption()},e.prototype.resetVisual=function(t){var e=this.stateList;t=W(t,this),this.controllerVisuals=_W(this.option.controller,e,t),this.targetVisuals=_W(this.option.target,e,t)},e.prototype.getItemSymbol=function(){return null},e.prototype.getTargetSeriesIndices=function(){var t=this.option.seriesId,e=this.option.seriesIndex;return null==e&&null==t&&(e="all"),E(pa(this.ecModel,"series",{index:e,id:t},{useDefault:!1,enableAll:!0,enableNone:!1}).models,(function(t){return t.componentIndex}))},e.prototype.eachTargetSeries=function(t,e){z(this.getTargetSeriesIndices(),(function(n){var i=this.ecModel.getSeriesByIndex(n);i&&t.call(e,i)}),this)},e.prototype.isTargetSeries=function(t){var e=!1;return this.eachTargetSeries((function(n){n===t&&(e=!0)})),e},e.prototype.formatValueText=function(t,e,n){var i,r=this.option,o=r.precision,a=this.dataBound,s=r.formatter;n=n||["<",">"],U(t)&&(t=t.slice(),i=!0);var l=e?t:i?[u(t[0]),u(t[1])]:u(t);return X(s)?s.replace("{value}",i?l[0]:l).replace("{value2}",i?l[1]:l):Y(s)?i?s(t[0],t[1]):s(t):i?t[0]===a[0]?n[0]+" "+l[1]:t[1]===a[1]?n[1]+" "+l[0]:l[0]+" - "+l[1]:l;function u(t){return t===a[0]?"min":t===a[1]?"max":(+t).toFixed(Math.min(o,20))}},e.prototype.resetExtent=function(){var t=this.option,e=IU([t.min,t.max]);this._dataExtent=e},e.prototype.getDataDimensionIndex=function(t){var e=this.option.dimension;if(null!=e)return t.getDimensionIndex(e);for(var n=t.dimensions,i=n.length-1;i>=0;i--){var r=n[i],o=t.getDimensionInfo(r);if(!o.isCalculationCoord)return o.storeDimIndex}},e.prototype.getExtent=function(){return this._dataExtent.slice()},e.prototype.completeVisualOption=function(){var t=this.ecModel,e=this.option,n={inRange:e.inRange,outOfRange:e.outOfRange},i=e.target||(e.target={}),r=e.controller||(e.controller={});C(i,n),C(r,n);var o=this.isCategory();function a(n){SU(e.color)&&!n.inRange&&(n.inRange={color:e.color.slice().reverse()}),n.inRange=n.inRange||{color:t.get("gradientColor")}}a.call(this,i),a.call(this,r),function(t,e,n){var i=t[e],r=t[n];i&&!r&&(r=t[n]={},MU(i,(function(t,e){if(hL.isValidType(e)){var n=xU(e,"inactive",o);null!=n&&(r[e]=n,"color"!==e||r.hasOwnProperty("opacity")||r.hasOwnProperty("colorAlpha")||(r.opacity=[0,0]))}})))}.call(this,i,"inRange","outOfRange"),function(t){var e=(t.inRange||{}).symbol||(t.outOfRange||{}).symbol,n=(t.inRange||{}).symbolSize||(t.outOfRange||{}).symbolSize,i=this.get("inactiveColor"),r=this.getItemSymbol()||"roundRect";MU(this.stateList,(function(a){var s=this.itemSize,l=t[a];l||(l=t[a]={color:o?i:[i]}),null==l.symbol&&(l.symbol=e&&T(e)||(o?r:[r])),null==l.symbolSize&&(l.symbolSize=n&&T(n)||(o?s[0]:[s[0],s[0]])),l.symbol=bU(l.symbol,(function(t){return"none"===t?r:t}));var u=l.symbolSize;if(null!=u){var c=-1/0;wU(u,(function(t){t>c&&(c=t)})),l.symbolSize=bU(u,(function(t){return TU(t,[0,c],[0,s[0]],!0)}))}}),this)}.call(this,r)},e.prototype.resetItemSize=function(){this.itemSize=[parseFloat(this.get("itemWidth")),parseFloat(this.get("itemHeight"))]},e.prototype.isCategory=function(){return!!this.option.categories},e.prototype.setSelected=function(t){},e.prototype.getSelected=function(){return null},e.prototype.getValueState=function(t){return null},e.prototype.getVisualMeta=function(t){return null},e.type="visualMap",e.dependencies=["series"],e.defaultOption={show:!0,z:4,min:0,max:200,left:0,right:null,top:null,bottom:0,itemWidth:null,itemHeight:null,inverse:!1,orient:"vertical",backgroundColor:tf.color.transparent,borderColor:tf.color.borderTint,contentColor:tf.color.theme[0],inactiveColor:tf.color.disabled,borderWidth:0,padding:tf.size.m,textGap:10,precision:0,textStyle:{color:tf.color.secondary}},e}(Qp),DU=[20,140],AU=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.optionUpdated=function(e,n){t.prototype.optionUpdated.apply(this,arguments),this.resetExtent(),this.resetVisual((function(t){t.mappingMethod="linear",t.dataExtent=this.getExtent()})),this._resetRange()},e.prototype.resetItemSize=function(){t.prototype.resetItemSize.apply(this,arguments);var e=this.itemSize;(null==e[0]||isNaN(e[0]))&&(e[0]=DU[0]),(null==e[1]||isNaN(e[1]))&&(e[1]=DU[1])},e.prototype._resetRange=function(){var t=this.getExtent(),e=this.option.range;!e||e.auto?(t.auto=1,this.option.range=t):U(e)&&(e[0]>e[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},e.prototype.completeVisualOption=function(){t.prototype.completeVisualOption.apply(this,arguments),z(this.stateList,(function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=e[1]/3)}),this)},e.prototype.setSelected=function(t){this.option.range=t.slice(),this._resetRange()},e.prototype.getSelected=function(){var t=this.getExtent(),e=xo((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]=n[1]||t<=e[1])?"inRange":"outOfRange"},e.prototype.findTargetDataIndices=function(t){var e=[];return this.eachTargetSeries((function(n){var i=[],r=n.getData();r.each(this.getDataDimensionIndex(r),(function(e,n){t[0]<=e&&e<=t[1]&&i.push(n)}),this),e.push({seriesId:n.id,dataIndex:i})}),this),e},e.prototype.getVisualMeta=function(t){var e=kU(this,"outOfRange",this.getExtent()),n=kU(this,"inRange",this.option.range.slice()),i=[];function r(e,n){i.push({value:e,color:t(e,n)})}for(var o=0,a=0,s=n.length,l=e.length;at[1])break;n.push({color:this.getControllerVisual(o,"color",e),offset:r/100})}return n.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),n},e.prototype._createBarPoints=function(t,e){var n=this.visualMapModel.itemSize;return[[n[0]-e[0],t[0]],[n[0],t[0]],[n[0],t[1]],[n[0]-e[1],t[1]]]},e.prototype._createBarGroup=function(t){var e=this._orient,n=this.visualMapModel.get("inverse");return new to("horizontal"!==e||n?"horizontal"===e&&n?{scaleX:"bottom"===t?-1:1,rotation:-Math.PI/2}:"vertical"!==e||n?{scaleX:"left"===t?1:-1}:{scaleX:"left"===t?1:-1,scaleY:-1}:{scaleX:"bottom"===t?1:-1,rotation:Math.PI/2})},e.prototype._updateHandle=function(t,e){if(this._useHandle){var n=this._shapes,i=this.visualMapModel,r=n.handleThumbs,o=n.handleLabels,a=i.itemSize,s=i.getExtent(),l=this._applyTransform("left",n.mainGroup);zU([0,1],(function(u){var c=r[u];c.setStyle("fill",e.handlesColor[u]),c.y=t[u];var h=NU(t[u],[0,a[1]],s,!0),d=this.getControllerVisual(h,"symbolSize");c.scaleX=c.scaleY=d/a[0],c.x=a[0]-d/2;var p=Sh(n.handleLabelPoints[u],wh(c,this.group));if("horizontal"===this._orient){var f="left"===l||"top"===l?(a[0]-d)/2:(a[0]-d)/-2;p[1]+=f}o[u].setStyle({x:p[0],y:p[1],text:i.formatValueText(this._dataInterval[u]),verticalAlign:"middle",align:"vertical"===this._orient?this._applyTransform("left",n.mainGroup):"center"})}),this)}},e.prototype._showIndicator=function(t,e,n,i){var r=this.visualMapModel,o=r.getExtent(),a=r.itemSize,s=[0,a[1]],l=this._shapes,u=l.indicator;if(u){u.attr("invisible",!1);var c=this.getControllerVisual(t,"color",{convertOpacityToAlpha:!0}),h=this.getControllerVisual(t,"symbolSize"),d=NU(t,o,s,!0),p=a[0]-h/2,f={x:u.x,y:u.y};u.y=d,u.x=p;var g=Sh(l.indicatorLabelPoint,wh(u,this.group)),y=l.indicatorLabel;y.attr("invisible",!1);var v=this._applyTransform("left",l.mainGroup),m="horizontal"===this._orient;y.setStyle({text:(n||"")+r.formatValueText(e),verticalAlign:m?v:"middle",align:m?"center":v});var x={x:p,y:d,style:{fill:c}},_={style:{x:g[0],y:g[1]}};if(r.ecModel.isAnimationEnabled()&&!this._firstShowIndicator){var b={duration:100,easing:"cubicInOut",additive:!0};u.x=f.x,u.y=f.y,u.animateTo(x,b),y.animateTo(_,b)}else u.attr(x),y.attr(_);this._firstShowIndicator=!1;var w=this._shapes.handleLabels;if(w)for(var S=0;Sr[1]&&(u[1]=1/0),e&&(u[0]===-1/0?this._showIndicator(l,u[1],"< ",a):u[1]===1/0?this._showIndicator(l,u[0],"> ",a):this._showIndicator(l,l,"≈ ",a));var c=this._hoverLinkDataIndices,h=[];(e||FU(n))&&(h=this._hoverLinkDataIndices=n.findTargetDataIndices(u));var d=function(t,e){var n={},i={};return r(t||[],n),r(e||[],i,n),[o(n),o(i)];function r(t,e,n){for(var i=0,r=t.length;i=0&&(r.dimension=o,i.push(r))}})),t.getData().setVisual("visualMeta",i)}}];function XU(t,e,n,i){for(var r=e.targetVisuals[i],o=hL.prepareVisualTypes(r),a={color:qv(t.getData(),"color")},s=0,l=o.length;s0:t.splitNumber>0)&&!t.calculable?"piecewise":"continuous"})),t.registerAction(HU,UU),z(YU,(function(e){t.registerVisual(t.PRIORITY.VISUAL.COMPONENT,e)})),t.registerPreprocessor(jU))}function JU(t){t.registerComponentModel(AU),t.registerComponentView(VU),$U(t)}var QU=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n._pieceList=[],n}return n(e,t),e.prototype.optionUpdated=function(e,n){t.prototype.optionUpdated.apply(this,arguments),this.resetExtent();var i=this._mode=this._determineMode();this._pieceList=[],tY[this._mode].call(this,this._pieceList),this._resetSelected(e,n);var r=this.option.categories;this.resetVisual((function(t,e){"categories"===i?(t.mappingMethod="category",t.categories=T(r)):(t.dataExtent=this.getExtent(),t.mappingMethod="piecewise",t.pieceList=E(this._pieceList,(function(t){return t=T(t),"inRange"!==e&&(t.visual=null),t})))}))},e.prototype.completeVisualOption=function(){var e=this.option,n={},i=hL.listVisualTypes(),r=this.isCategory();function o(t,e,n){return t&&t[e]&&t[e].hasOwnProperty(n)}z(e.pieces,(function(t){z(i,(function(e){t.hasOwnProperty(e)&&(n[e]=1)}))})),z(n,(function(t,n){var i=!1;z(this.stateList,(function(t){i=i||o(e,t,n)||o(e.target,t,n)}),this),!i&&z(this.stateList,(function(t){(e[t]||(e[t]={}))[n]=xU(n,"inRange"===t?"active":"inactive",r)}))}),this),t.prototype.completeVisualOption.apply(this,arguments)},e.prototype._resetSelected=function(t,e){var n=this.option,i=this._pieceList,r=(e?n:t).selected||{};if(n.selected=r,z(i,(function(t,e){var n=this.getSelectedMapKey(t);r.hasOwnProperty(n)||(r[n]=!0)}),this),"single"===n.selectedMode){var o=!1;z(i,(function(t,e){var n=this.getSelectedMapKey(t);r[n]&&(o?r[n]=!1:o=!0)}),this)}},e.prototype.getItemSymbol=function(){return this.get("itemSymbol")},e.prototype.getSelectedMapKey=function(t){return"categories"===this._mode?t.value+"":t.index+""},e.prototype.getPieceList=function(){return this._pieceList},e.prototype._determineMode=function(){var t=this.option;return t.pieces&&t.pieces.length>0?"pieces":this.option.categories?"categories":"splitNumber"},e.prototype.setSelected=function(t){this.option.selected=T(t)},e.prototype.getValueState=function(t){var e=hL.findPieceIndex(t,this._pieceList);return null!=e&&this.option.selected[this.getSelectedMapKey(this._pieceList[e])]?"inRange":"outOfRange"},e.prototype.findTargetDataIndices=function(t){var e=[],n=this._pieceList;return this.eachTargetSeries((function(i){var r=[],o=i.getData();o.each(this.getDataDimensionIndex(o),(function(e,i){hL.findPieceIndex(e,n)===t&&r.push(i)}),this),e.push({seriesId:i.id,dataIndex:r})}),this),e},e.prototype.getRepresentValue=function(t){var e;if(this.isCategory())e=t.value;else if(null!=t.value)e=t.value;else{var n=t.interval||[];e=n[0]===-1/0&&n[1]===1/0?0:(n[0]+n[1])/2}return e},e.prototype.getVisualMeta=function(t){if(!this.isCategory()){var e=[],n=["",""],i=this,r=this._pieceList.slice();if(r.length){var o=r[0].interval[0];o!==-1/0&&r.unshift({interval:[-1/0,o]}),(o=r[r.length-1].interval[1])!==1/0&&r.push({interval:[o,1/0]})}else r.push({interval:[-1/0,1/0]});var a=-1/0;return z(r,(function(t){var e=t.interval;e&&(e[0]>a&&s([a,e[0]],"outOfRange"),s(e.slice()),a=e[1])}),this),{stops:e,outerColors:n}}function s(r,o){var a=i.getRepresentValue({interval:r});o||(o=i.getValueState(a));var s=t(a,o);r[0]===-1/0?n[0]=s:r[1]===1/0?n[1]=s:e.push({value:r[0],color:s},{value:r[1],color:s})}},e.type="visualMap.piecewise",e.defaultOption=Id(CU.defaultOption,{selected:null,minOpen:!1,maxOpen:!1,align:"auto",itemWidth:20,itemHeight:14,itemSymbol:"roundRect",pieces:null,categories:null,splitNumber:5,selectedMode:"multiple",itemGap:10,hoverLink:!0}),e}(CU),tY={splitNumber:function(t){var e=this.option,n=Math.min(e.precision,20),i=this.getExtent(),r=e.splitNumber;r=Math.max(parseInt(r,10),1),e.splitNumber=r;for(var o=(i[1]-i[0])/r;+o.toFixed(n)!==o&&n<5;)n++;e.precision=n,o=+o.toFixed(n),e.minOpen&&t.push({interval:[-1/0,i[0]],close:[0,0]});for(var a=0,s=i[0];a","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,n)}),this)}};function eY(t,e){var n=t.inverse;("vertical"===t.orient?!n:n)&&e.reverse()}var nY=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.doRender=function(){var t=this.group;t.removeAll();var e=this.visualMapModel,n=e.get("textGap"),i=e.textStyleModel,r=this._getItemAlign(),o=e.itemSize,a=this._getViewData(),s=a.endsText,l=it(e.get("showLabel",!0),!s),u=!e.get("selectedMode");s&&this._renderEndsText(t,s[0],o,l,r),z(a.viewPieceList,(function(a){var s=a.piece,c=new to;c.onclick=W(this._onItemClick,this,s),this._enableHoverLink(c,a.indexInModelPieceList);var h=e.getRepresentValue(s);if(this._createItemSymbol(c,h,[0,0,o[0],o[1]],u),l){var d=this.visualMapModel.getValueState(h),p=i.get("align")||r;c.add(new Sl({style:Qh(i,{x:"right"===p?-n:o[0]+n,y:o[1]/2,text:s.text,verticalAlign:i.get("verticalAlign")||"middle",align:p,opacity:rt(i.get("opacity"),"outOfRange"===d?.5:1)}),silent:u}))}t.add(c)}),this),s&&this._renderEndsText(t,s[1],o,l,r),Gp(e.get("orient"),t,e.get("itemGap")),this.renderBackground(t),this.positionGroup(t)},e.prototype._enableHoverLink=function(t,e){var n=this;t.on("mouseover",(function(){return i("highlight")})).on("mouseout",(function(){return i("downplay")}));var i=function(t){var i=n.visualMapModel;i.option.hoverLink&&n.api.dispatchAction({type:t,batch:RU(i.findTargetDataIndices(e),i)})}},e.prototype._getItemAlign=function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return OU(t,this.api,t.itemSize);var n=e.align;return n&&"auto"!==n||(n="left"),n},e.prototype._renderEndsText=function(t,e,n,i,r){if(e){var o=new to,a=this.visualMapModel.textStyleModel;o.add(new Sl({style:Qh(a,{x:i?"right"===r?n[0]:0:n[0]/2,y:n[1]/2,verticalAlign:"middle",align:i?r:"center",text:e})})),t.add(o)}},e.prototype._getViewData=function(){var t=this.visualMapModel,e=E(t.getPieceList(),(function(t,e){return{piece:t,indexInModelPieceList:e}})),n=t.get("text"),i=t.get("orient"),r=t.get("inverse");return("horizontal"===i?r:!r)?e.reverse():n&&(n=n.slice().reverse()),{viewPieceList:e,endsText:n}},e.prototype._createItemSymbol=function(t,e,n,i){var r=hm(this.getControllerVisual(e,"symbol"),n[0],n[1],n[2],n[3],this.getControllerVisual(e,"color"));r.silent=i,t.add(r)},e.prototype._onItemClick=function(t){var e=this.visualMapModel,n=e.option,i=n.selectedMode;if(i){var r=T(n.selected),o=e.getSelectedMapKey(t);"single"===i||!0===i?(r[o]=!0,z(r,(function(t,e){r[e]=e===o}))):r[o]=!r[o],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:r})}},e.type="visualMap.piecewise",e}(LU);function iY(t){t.registerComponentModel(QU),t.registerComponentView(nY),$U(t)}var rY=function(){function t(t){this._thumbnailModel=t}return t.prototype.reset=function(t){this._renderVersion=t.getMainProcessVersion()},t.prototype.renderContent=function(t){var e=t.api.getViewOfComponentModel(this._thumbnailModel);e&&(t.group.silent=!0,e.renderContent({group:t.group,targetTrans:t.targetTrans,z2Range:Uh(t.group),roamType:t.roamType,viewportRect:t.viewportRect,renderVersion:this._renderVersion}))},t.prototype.updateWindow=function(t,e){var n=e.getViewOfComponentModel(this._thumbnailModel);n&&n.updateWindow({targetTrans:t,renderVersion:this._renderVersion})},t}(),oY=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n.preventAutoZ=!0,n}return n(e,t),e.prototype.optionUpdated=function(t,e){this._updateBridge()},e.prototype._updateBridge=function(){var t=this._birdge=this._birdge||new rY(this);(this._target=null,this.ecModel.eachSeries((function(t){BP(t,null)})),this.shouldShow())&&BP(this.getTarget().baseMapProvider,t)},e.prototype.shouldShow=function(){return this.getShallow("show",!0)},e.prototype.getBridge=function(){return this._birdge},e.prototype.getTarget=function(){if(this._target)return this._target;var t=this.getReferringComponents("series",{useDefault:!1,enableAll:!1,enableNone:!1}).models[0];return t?"graph"!==t.subType&&(t=null):t=this.ecModel.queryComponents({mainType:"series",subType:"graph"})[0],this._target={baseMapProvider:t},this._target},e.type="thumbnail",e.layoutMode="box",e.dependencies=["series","geo"],e.defaultOption={show:!0,right:1,bottom:1,height:"25%",width:"25%",itemStyle:{borderColor:tf.color.border,borderWidth:2},windowStyle:{borderWidth:1,color:tf.color.neutral30,borderColor:tf.color.neutral40,opacity:.3},z:10},e}(Qp),aY=function(t){function e(){var n=null!==t&&t.apply(this,arguments)||this;return n.type=e.type,n}return n(e,t),e.prototype.render=function(t,e,n){if(this._api=n,this._model=t,this._coordSys||(this._coordSys=new KA),this._isEnabled()){this._renderVersion=n.getMainProcessVersion();var i=this.group;i.removeAll();var r=t.getModel("itemStyle"),o=r.getItemStyle();null==o.fill&&(o.fill=e.get("backgroundColor")||tf.color.neutral00);var a=Xp(t,n).refContainer,s=Hp(Fp(t,!0),a),l=o.lineWidth||0,u=this._contentRect=Oh(s.clone(),l/2,!0,!0),c=new to;i.add(c),c.setClipPath(new xl({shape:u.plain()}));var h=this._targetGroup=new to;c.add(h);var d=s.plain();d.r=r.getShallow("borderRadius",!0),i.add(this._bgRect=new xl({style:o,shape:d,silent:!1,cursor:"grab"}));var p=t.getModel("windowStyle"),f=p.getShallow("borderRadius",!0);c.add(this._windowRect=new xl({shape:{x:0,y:0,width:0,height:0,r:f},style:p.getItemStyle(),silent:!1,cursor:"grab"})),this._dealRenderContent(),this._dealUpdateWindow(),lY(t,this)}else this._clear()},e.prototype.renderContent=function(t){this._bridgeRendered=t,this._isEnabled()&&(this._dealRenderContent(),this._dealUpdateWindow(),lY(this._model,this))},e.prototype._dealRenderContent=function(){var t=this._bridgeRendered;if(t&&t.renderVersion===this._renderVersion){var e=this._targetGroup,n=this._coordSys,i=this._contentRect;if(e.removeAll(),t){var r=t.group,o=r.getBoundingRect();e.add(r),this._bgRect.z2=t.z2Range.min-10,n.setBoundingRect(o.x,o.y,o.width,o.height);var a=Hp({left:"center",top:"center",aspect:o.width/o.height},i);n.setViewRect(a.x,a.y,a.width,a.height),r.attr(n.getTransformInfo().raw),this._windowRect.z2=t.z2Range.max+10,this._resetRoamController(t.roamType)}}},e.prototype.updateWindow=function(t){var e=this._bridgeRendered;e&&e.renderVersion===t.renderVersion&&(e.targetTrans=t.targetTrans),this._isEnabled()&&this._dealUpdateWindow()},e.prototype._dealUpdateWindow=function(){var t=this._bridgeRendered;if(t&&t.renderVersion===this._renderVersion){var e=Te([],t.targetTrans),n=we([],this._coordSys.transform,e);this._transThisToTarget=Te([],n);var i=t.viewportRect;(i=i?i.clone():new He(0,0,this._api.getWidth(),this._api.getHeight())).applyTransform(n);var r=this._windowRect,o=r.shape.r;r.setShape(k({r:o},i))}},e.prototype._resetRoamController=function(t){var e=this,n=this._api,i=this._roamController;i||(i=this._roamController=new LD(n.getZr())),t&&this._isEnabled()?(i.enable(t,{api:n,zInfo:{component:this._model},triggerInfo:{roamTrigger:null,isInSelf:function(t,n,i){return e._contentRect.contain(n,i)}}}),i.off("pan").off("zoom").on("pan",W(this._onPan,this)).on("zoom",W(this._onZoom,this))):i.disable()},e.prototype._onPan=function(t){var e=this._transThisToTarget;if(this._isEnabled()&&e){var n=Ht([],[t.oldX,t.oldY],e),i=Ht([],[t.oldX-t.dx,t.oldY-t.dy],e);this._api.dispatchAction(sY(this._model.getTarget().baseMapProvider,{dx:i[0]-n[0],dy:i[1]-n[1]}))}},e.prototype._onZoom=function(t){var e=this._transThisToTarget;if(this._isEnabled()&&e){var n=Ht([],[t.originX,t.originY],e);this._api.dispatchAction(sY(this._model.getTarget().baseMapProvider,{zoom:1/t.scale,originX:n[0],originY:n[1]}))}},e.prototype._isEnabled=function(){var t=this._model;return!(!t||!t.shouldShow())&&!!t.getTarget().baseMapProvider},e.prototype._clear=function(){this.group.removeAll(),this._bridgeRendered=null,this._roamController&&this._roamController.disable()},e.prototype.remove=function(){this._clear()},e.prototype.dispose=function(){this._clear()},e.type="thumbnail",e}(Ky);function sY(t,e){var n={type:"series"===t.mainType?t.subType+"Roam":t.mainType+"Roam"};return n[t.mainType+"Id"]=t.id,A(n,e),n}function lY(t,e){var n=Hh(t);Yh(e.group,n.z,n.zlevel)}var uY={label:{enabled:!0},decal:{show:!1}},cY=sa(),hY={};function dY(t,e){var n=t.getModel("aria");if(n.get("enabled")){var i=T(uY);C(i.label,t.getLocaleModel().get("aria"),!1),C(n.option,i,!1),function(){if(n.getModel("decal").get("show")){var e=yt();t.eachSeries((function(t){if(!t.isColorBySeries()){var n=e.get(t.type);n||(n={},e.set(t.type,n)),cY(t).scope=n}})),t.eachRawSeries((function(e){if(!t.isSeriesFiltered(e))if(Y(e.enableAriaDecal))e.enableAriaDecal();else{var n=e.getData();if(e.isColorBySeries()){var i=Nf(e.ecModel,e.name,hY,t.getSeriesCount()),r=n.getVisual("decal");n.setVisual("decal",u(r,i))}else{var o=e.getRawData(),a={},s=cY(e).scope;n.each((function(t){var e=n.getRawIndex(t);a[e]=t}));var l=o.count();o.each((function(t){var i=a[t],r=o.getName(t)||t+"",c=Nf(e.ecModel,r,s,l),h=n.getItemVisual(i,"decal");n.setItemVisual(i,"decal",u(h,c))}))}}function u(t,e){var n=t?A(A({},e),t):e;return n.dirty=!0,n}}))}}(),function(){var i=e.getZr().dom;if(!i)return;var o=t.getLocaleModel().get("aria"),a=n.getModel("label");if(a.option=k(a.option,o),!a.get("enabled"))return;if(i.setAttribute("role","img"),a.get("description"))return void i.setAttribute("aria-label",a.get("description"));var s,l=t.getSeriesCount(),u=a.get(["data","maxCount"])||10,c=a.get(["series","maxCount"])||10,h=Math.min(l,c);if(l<1)return;var d=function(){var e=t.get("title");e&&e.length&&(e=e[0]);return e&&e.text}();s=d?r(a.get(["general","withTitle"]),{title:d}):a.get(["general","withoutTitle"]);var p=[];s+=r(l>1?a.get(["series","multiple","prefix"]):a.get(["series","single","prefix"]),{seriesCount:l}),t.eachSeries((function(e,n){if(n1?a.get(["series","multiple",o]):a.get(["series","single",o]),{seriesId:e.seriesIndex,seriesName:e.get("name"),seriesType:(_=e.subType,b=t.getLocaleModel().get(["series","typeNames"]),b[_]||b.chart)});var s=e.getData();if(s.count()>u)i+=r(a.get(["data","partialData"]),{displayCnt:u});else i+=a.get(["data","allData"]);for(var c=a.get(["data","separator","middle"]),d=a.get(["data","separator","end"]),f=a.get(["data","excludeDimensionId"]),g=[],y=0;y":"gt",">=":"gte","=":"eq","!=":"ne","<>":"ne"},gY=function(){function t(t){if(null==(this._condVal=X(t)?new RegExp(t):et(t)?t:null)){var e="";0,Yo(e)}}return t.prototype.evaluate=function(t){var e=typeof t;return X(e)?this._condVal.test(t):!!j(e)&&this._condVal.test(t+"")},t}(),yY=function(){function t(){}return t.prototype.evaluate=function(){return this.value},t}(),vY=function(){function t(){}return t.prototype.evaluate=function(){for(var t=this.children,e=0;e2&&l.push(e),e=[t,n]}function f(t,n,i,r){kY(t,i)&&kY(n,r)||e.push(t,n,i,r,i,r)}function g(t,n,i,r,o,a){var s=Math.abs(n-t),l=4*Math.tan(s/4)/3,u=nM:C2&&l.push(e),l}function PY(t,e,n,i,r,o,a,s,l,u){if(kY(t,n)&&kY(e,i)&&kY(r,a)&&kY(o,s))l.push(a,s);else{var c=2/u,h=c*c,d=a-t,p=s-e,f=Math.sqrt(d*d+p*p);d/=f,p/=f;var g=n-t,y=i-e,v=r-a,m=o-s,x=g*g+y*y,_=v*v+m*m;if(x=0&&_-w*w=0)l.push(a,s);else{var S=[],M=[];Pn(t,n,r,a,.5,S),Pn(e,i,o,s,.5,M),PY(S[0],M[0],S[1],M[1],S[2],M[2],S[3],M[3],l,u),PY(S[4],M[4],S[5],M[5],S[6],M[6],S[7],M[7],l,u)}}}}function OY(t,e,n){var i=t[e],r=t[1-e],o=Math.abs(i/r),a=Math.ceil(Math.sqrt(o*n)),s=Math.floor(n/a);0===s&&(s=1,a=n);for(var l=[],u=0;u0)for(u=0;uMath.abs(u),h=OY([l,u],c?0:1,e),d=(c?s:u)/h.length,p=0;p1?null:new Ae(p*l+t,p*u+e)}function EY(t,e,n){var i=new Ae;Ae.sub(i,n,e),i.normalize();var r=new Ae;return Ae.sub(r,t,e),r.dot(i)}function BY(t,e){var n=t[t.length-1];n&&n[0]===e[0]&&n[1]===e[1]||t.push(e)}function VY(t){var e=t.points,n=[],i=[];ys(e,n,i);var r=new He(n[0],n[1],i[0]-n[0],i[1]-n[1]),o=r.width,a=r.height,s=r.x,l=r.y,u=new Ae,c=new Ae;return o>a?(u.x=c.x=s+o/2,u.y=l,c.y=l+a):(u.y=c.y=l+a/2,u.x=s,c.x=s+o),function(t,e,n){for(var i=t.length,r=[],o=0;or,a=OY([i,r],o?0:1,e),s=o?"width":"height",l=o?"height":"width",u=o?"x":"y",c=o?"y":"x",h=t[s]/a.length,d=0;d0)for(var b=i/n,w=-i/2;w<=i/2;w+=b){var S=Math.sin(w),M=Math.cos(w),I=0;for(x=0;x0;l/=2){var u=0,c=0;(t&l)>0&&(u=1),(e&l)>0&&(c=1),s+=l*l*(3*u^c),0===c&&(1===u&&(t=l-1-t,e=l-1-e),a=t,t=e,e=a)}return s}function nX(t){var e=1/0,n=1/0,i=-1/0,r=-1/0,o=E(t,(function(t){var o=t.getBoundingRect(),a=t.getComputedTransform(),s=o.x+o.width/2+(a?a[4]:0),l=o.y+o.height/2+(a?a[5]:0);return e=Math.min(s,e),n=Math.min(l,n),i=Math.max(s,i),r=Math.max(l,r),[s,l]}));return E(o,(function(o,a){return{cp:o,z:eX(o[0],o[1],e,n,i,r),path:t[a]}})).sort((function(t,e){return t.z-e.z})).map((function(t){return t.path}))}function iX(t){return WY(t.path,t.count)}function rX(t){return U(t[0])}function oX(t,e){for(var n=[],i=t.length,r=0;r=0;r--)if(!n[r].many.length){var l=n[s].many;if(l.length<=1){if(!s)return n;s=0}o=l.length;var u=Math.ceil(o/2);n[r].many=l.slice(u,o),n[s].many=l.slice(0,u),s++}return n}var aX={clone:function(t){for(var e=[],n=1-Math.pow(1-t.path.style.opacity,1/t.count),i=0;i0){var s,l,u=i.getModel("universalTransition").get("delay"),c=Object.assign({setToFinal:!0},a);rX(t)&&(s=t,l=e),rX(e)&&(s=e,l=t);for(var h=s?s===t:t.length>e.length,d=s?oX(l,s):oX(h?e:t,[h?t:e]),p=0,f=0;f1e4))for(var r=n.getIndices(),o=0;o0&&i.group.traverse((function(t){t instanceof sl&&!t.animators.length&&t.animateFrom({style:{opacity:0}},r)}))}))}function vX(t){var e=t.getModel("universalTransition").get("seriesKey");return e||t.id}function mX(t){return U(t)?t.sort().join(","):t}function xX(t){if(t.hostModel)return t.hostModel.getModel("universalTransition").get("divideShape")}function _X(t,e){for(var n=0;no.vmin?e+=o.vmin-n+(t-o.vmin)/(o.vmax-o.vmin)*o.gapReal:e+=t-n,n=o.vmax,i=!1;break}e+=o.vmin-n+o.gapReal,n=o.vmax}return i&&(e+=t-n),e},t.prototype.unelapse=function(t){for(var e=SX,n=MX,i=!0,r=0,o=0;os?a.vmin+(t-s)/(l-s)*(a.vmax-a.vmin):n+t-e,n=a.vmax,i=!1;break}e=l,n=a.vmax}return i&&(r=n+t-e),r},t}();function wX(){return new bX}var SX=0,MX=0;function IX(t,e,n,i,r,o){"no"!==t&&z(n,(function(n){var a=CX(n,o);if(a)for(var s=e.length-1;s>=0;s--){var l=e[s],u=i(l),c=3*r/4;u>a.vmin-c&&ue[0]&&n=0&&t<.99999})(s)||(s=0),r.gapParsed.type="tpPrct",r.gapParsed.val=s,o=!0}}if(!o){var l=e(t.gap);(!isFinite(l)||l<0)&&(l=0),r.gapParsed.type="tpAbs",r.gapParsed.val=l}}if(r.vmin===r.vmax&&(r.gapParsed.type="tpAbs",r.gapParsed.val=0),n&&n.noNegative&&z(["vmin","vmax"],(function(t){r[t]<0&&(r[t]=0)})),r.vmin>r.vmax){var u=r.vmax;r.vmax=r.vmin,r.vmin=u}i.push(r)}})),i.sort((function(t,e){return t.vmin-e.vmin}));var r=-1/0;return z(i,(function(t,e){r>t.vmin&&(i[e]=null),r=t.vmax})),{breaks:i.filter((function(t){return!!t}))}}function AX(t,e){return kX(e)===kX(t)}function kX(t){return t.start+"_\0_"+t.end}function LX(t,e,n){var i=[];z(t,(function(t,n){var r=e(t);r&&"vmin"===r.type&&i.push([n])})),z(t,(function(n,r){var o=e(n);if(o&&"vmax"===o.type){var a=G(i,(function(n){return AX(e(t[n[0]]).parsedBreak.breakOption,o.parsedBreak.breakOption)}));a&&a.push(r)}}));var r=[];return z(i,(function(e){2===e.length&&r.push(n?e:[t[e[0]],t[e[1]]])})),r}function PX(t,e,n,i){var r,o;if(t.break){var a=t.break.parsedBreak,s=G(n,(function(e){return AX(e.breakOption,t.break.parsedBreak.breakOption)})),l=i(Math.pow(e,a.vmin),s.vmin),u=i(Math.pow(e,a.vmax),s.vmax),c={type:a.gapParsed.type,val:"tpAbs"===a.gapParsed.type?mo(Math.pow(e,a.vmin+a.gapParsed.val))-l:a.gapParsed.val};r={type:t.break.type,parsedBreak:{breakOption:a.breakOption,vmin:l,vmax:u,gapParsed:c,gapReal:a.gapReal}},o=s[t.break.type]}return{brkRoundingCriterion:o,vBreak:r}}function OX(t,e,n){var i={noNegative:!0},r=DX(t,n,i),o=DX(t,n,i),a=Math.log(e);return o.breaks=E(o.breaks,(function(t){var e=Math.log(t.vmin)/a;return{vmin:e,vmax:Math.log(t.vmax)/a,gapParsed:{type:t.gapParsed.type,val:"tpAbs"===t.gapParsed.type?Math.log(t.vmin+t.gapParsed.val)/a-e:t.gapParsed.val},gapReal:t.gapReal,breakOption:t.breakOption}})),{parsedOriginal:r,parsedLogged:o}}var RX={vmin:"start",vmax:"end"};function NX(t,e){return e&&((t=t||{}).break={type:RX[e.type],start:e.parsedBreak.vmin,end:e.parsedBreak.vmax}),t}function zX(){var t;t={createScaleBreakContext:wX,pruneTicksByBreak:IX,addBreaksToTicks:TX,parseAxisBreakOption:DX,identifyAxisBreak:AX,serializeAxisBreakIdentifier:kX,retrieveAxisBreakPairs:LX,getTicksLogTransformBreak:PX,logarithmicParseBreaksFromOption:OX,makeAxisLabelFormatterParamBreak:NX},Rd||(Rd=t)}var EX=sa();function BX(t,e,n,i,r){var o=n.axis;if(!o.scale.isBlank()&&Nd()){var a=Nd().retrieveAxisBreakPairs(o.scale.getTicks({breakTicks:"only_break"}),(function(t){return t.break}),!1);if(a.length){var s=n.getModel("breakArea"),l=s.get("zigzagAmplitude"),u=s.get("zigzagMinSpan"),c=s.get("zigzagMaxSpan");u=Math.max(2,u||0),c=Math.max(u,c||0);var h=s.get("expandOnClick"),d=s.get("zigzagZ"),p=s.getModel("itemStyle").getItemStyle(),f=p.stroke,g=p.lineWidth,y=p.lineDash,v=p.fill,m=new to({ignoreModelZ:!0}),x=o.isHorizontal(),_=EX(e).visualList||(EX(e).visualList=[]);z(_,(function(t){return t.shouldRemove=!0}));for(var b=function(t){var e=a[t][0].break.parsedBreak,s=[];s[0]=o.toGlobalCoord(o.dataToCoord(e.vmin,!0)),s[1]=o.toGlobalCoord(o.dataToCoord(e.vmax,!0)),s[1]=x;C&&(M=x);var D=[],A=[];D[h]=n,A[h]=r,T||C||(D[h]+=S?-l:l,A[h]-=S?l:-l),D[m]=M,A[m]=M,b.push(D),w.push(A);var k=void 0;if(I=0;e--)t[e].shouldRemove&&t.splice(e,1)}(_)}}}function VX(t,e,n,i){var r=t.axis,o=n.transform;lt(i.style);var a=r.getExtent();r.inverse&&(a=a.slice()).reverse();var s=E(Nd().retrieveAxisBreakPairs(r.scale.getTicks({breakTicks:"only_break"}),(function(t){return t.break}),!1),(function(t){var e=t[0].break.parsedBreak,n=[r.dataToCoord(e.vmin,!0),r.dataToCoord(e.vmax,!0)];return n[0]>n[1]&&n.reverse(),{coordPair:n,brkId:Nd().serializeAxisBreakIdentifier(e.breakOption)}}));s.sort((function(t,e){return t.coordPair[0]-e.coordPair[0]}));for(var l=a[0],u=null,c=0;c=0?s[0].width:s[1].width)+u.x)/2-l.x,h=Math.min(c,c-u.x),d=Math.max(c,c-u.x);a=(c-(d<0?d:h>0?h:0))/u.x}var p=new Ae,f=new Ae;Ae.scale(p,i,-a),Ae.scale(f,i,1-a),_S(n[0],p),_S(n[1],f)}}function g(t){var e=n[0].localRect,i=new Ae(e[uh[t]]*o[0][0],e[uh[t]]*o[0][1]);return Math.abs(i.y)<1e-5}}function FX(t,e){var n={breaks:[]};return z(e.breaks,(function(i){if(i){var r=G(t.get("breaks",!0),(function(t){return Nd().identifyAxisBreak(t,i)}));if(r){var o=e.type,a={isExpanded:!!r.isExpanded};r.isExpanded=o===QT||o!==tC&&(o===eC?!r.isExpanded:r.isExpanded),n.breaks.push({start:r.start,end:r.end,isExpanded:!!r.isExpanded,old:a})}}})),n}function WX(){var t;t={adjustBreakLabelPair:GX,buildAxisBreakLine:VX,rectCoordBuildBreakAxis:BX,updateModelAxisBreak:FX},UT||(UT=t)}function HX(t,e){z(t,(function(t){if(!t.model.get(["axisLabel","inside"])){var n=function(t){var e,n,i=t.model,r=t.scale;if(!i.get(["axisLabel","show"])||r.isBlank())return;var o=r.getExtent();n=r instanceof lb?r.count():(e=r.getTicks()).length;var a,s=t.getLabelModel(),l=jb(t),u=1;n>40&&(u=Math.ceil(n/40));for(var c=0;c=0&&r.push({dataGroupId:e.oldDataGroupIds[n],data:e.oldData[n],divide:xX(e.oldData[n]),groupIdDim:t.dimension})})),z(qo(t.to),(function(t){var i=_X(n.updatedSeries,t);if(i>=0){var r=n.updatedSeries[i].getData();o.push({dataGroupId:e.oldDataGroupIds[i],data:r,divide:xX(r),groupIdDim:t.dimension})}})),r.length>0&&o.length>0&&yX(r,o,i)}(t,i,n,e)}));else{var o=function(t,e){var n=yt(),i=yt(),r=yt();return z(t.oldSeries,(function(e,n){var o=t.oldDataGroupIds[n],a=t.oldData[n],s=vX(e),l=mX(s);i.set(l,{dataGroupId:o,data:a}),U(s)&&z(s,(function(t){r.set(t,{key:l,dataGroupId:o,data:a})}))})),z(e.updatedSeries,(function(t){if(t.isUniversalTransitionEnabled()&&t.isAnimationEnabled()){var e=t.get("dataGroupId"),o=t.getData(),a=vX(t),s=mX(a),l=i.get(s);if(l)n.set(s,{oldSeries:[{dataGroupId:l.dataGroupId,divide:xX(l.data),data:l.data}],newSeries:[{dataGroupId:e,divide:xX(o),data:o}]});else if(U(a)){var u=[];z(a,(function(t){var e=i.get(t);e.data&&u.push({dataGroupId:e.dataGroupId,divide:xX(e.data),data:e.data})})),u.length&&n.set(s,{oldSeries:u,newSeries:[{dataGroupId:e,data:o,divide:xX(o)}]})}else{var c=r.get(a);if(c){var h=n.get(c.key);h||(h={oldSeries:[{dataGroupId:c.dataGroupId,data:c.data,divide:xX(c.data)}],newSeries:[]},n.set(c.key,h)),h.newSeries.push({dataGroupId:e,data:o,divide:xX(o)})}}}})),n}(i,n);z(o.keys(),(function(t){var n=o.get(t);yX(n.oldSeries,n.newSeries,e)}))}z(n.updatedSeries,(function(t){t[Fy]&&(t[Fy]=!1)}))}for(var a=t.getSeries(),s=i.oldSeries=[],l=i.oldDataGroupIds=[],u=i.oldData=[],c=0;c\s*\{[\s\S]*\}\s*$/.test(v) || + // 箭头函数 - 简写形式 + /^\s*\([^)]*\)\s*=>\s*[^{\s][\s\S]*$/.test(v) || + // 单参数箭头函数 - 无括号 + /^\s*[a-zA-Z0-9_$]+\s*=>\s*[^{\s][\s\S]*$/.test(v) || + // 单参数箭头函数 - 带花括号 + /^\s*[a-zA-Z0-9_$]+\s*=>\s*\{[\s\S]*\}\s*$/.test(v); + + + if(typeof v === 'string' && isFunctionStr){ + v = eval('('+v+')') + } + + return v; + }); + + return obj; +} + + +function chart_setOption(optionStr) { + chart_setSize() + // 基于准备好的dom,初始化echarts实例 + let chart = getchart(); + if (!optionStr) return; + try { + + let option = decodeJSON(optionStr) + + chart.setOption(option) + } catch (error) { + alert(error) + } +} + +function chart_call(funName, optionStr, eventsid) { + + chart_setSize() + let filterevents = ["click"] + // 基于准备好的dom,初始化echarts实例 + let chart = getchart(); + + if (filterevents.includes(funName)) { + + chart['on'](funName, function(params) { + delete params.event + window.parent.postMessage({ + action: funName, + eventId: eventsid, + data: JSON.stringify(params), + iframeId: iframeId + }, '*'); + + uni.postMessage({ + data: { + action: funName, + eventId: eventsid, + data: JSON.stringify(params) + } + }) + + }) + } else { + + try { + let option = JSON.parse(optionStr) + chart[funName](option) + } catch (e) { + chart[funName]() + } + } + + + +} \ No newline at end of file diff --git a/hybrid/html/js/highlight.min.js b/hybrid/html/js/highlight.min.js new file mode 100644 index 0000000..382ebcd --- /dev/null +++ b/hybrid/html/js/highlight.min.js @@ -0,0 +1,1004 @@ +/*! + Highlight.js v11.10.0 (git: 366a8bd012) + (c) 2006-2024 Josh Goebel and other contributors + License: BSD-3-Clause + */ +var hljs=function(){"use strict";function e(t){ +return t instanceof Map?t.clear=t.delete=t.set=()=>{ +throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{ +const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i) +})),t}class t{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function n(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope +;class o{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{ +if(e.startsWith("language:"))return e.replace("language:","language-") +;if(e.includes(".")){const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)} +closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}const r=(e={})=>{const t={children:[]} +;return Object.assign(t,e),t};class a{constructor(){ +this.rootNode=r(),this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t=r({scope:e}) +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e} +addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){ +this.closeNode()}__addSublanguage(e,t){const n=e.root +;t&&(n.scope="language:"+t),this.add(n)}toHTML(){ +return new o(this,this.options).value()}finalize(){ +return this.closeAllNodes(),!0}}function l(e){ +return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")} +function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")} +function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"} +function p(e){return RegExp(e.toString()+"|").exec("").length-1} +const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break} +s+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0], +"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)} +const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={ +begin:"\\\\[\\s\\S]",relevance:0},v={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[O]},k={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t, +contains:[]},n);s.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const o=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return s.contains.push({begin:h(/[ ]+/,"(",o,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s +},S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var j=Object.freeze({ +__proto__:null,APOS_STRING_MODE:v,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{ +scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N, +C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number", +begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E, +MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0}, +NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w, +PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},QUOTE_STRING_MODE:k,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/, +end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]}, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function A(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=A,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function L(e,t){ +Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function P(e,t){ +void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={ +relevance:0,contains:[Object.assign(n,{endsParent:!0})] +},e.relevance=0,delete n.beforeMatch +},H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword" +;function $(e,t,n=C){const i=Object.create(null) +;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,$(e[n],t,n))})),i;function s(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){ +return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{ +console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{ +z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0) +},K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],o={},r={} +;for(let e=1;e<=t.length;e++)r[e+i]=s[e],o[e+i]=!0,i+=p(t[e-1]) +;e[n]=r,e[n]._emit=o,e[n]._multi=!0}function Z(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +K +;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"), +K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +K +;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"), +K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){ +function t(t,n){ +return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) +}class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=i(e.classNameAliases||{}),function n(o,r){const a=o +;if(o.isCompiled)return a +;[I,B,Z,D].forEach((e=>e(o,r))),e.compilerExtensions.forEach((e=>e(o,r))), +o.__beforeBegin=null,[T,L,P].forEach((e=>e(o,r))),o.isCompiled=!0;let c=null +;return"object"==typeof o.keywords&&o.keywords.$pattern&&(o.keywords=Object.assign({},o.keywords), +c=o.keywords.$pattern, +delete o.keywords.$pattern),c=c||/\w+/,o.keywords&&(o.keywords=$(o.keywords,e.case_insensitive)), +a.keywordPatternRe=t(c,!0), +r&&(o.begin||(o.begin=/\B|\b/),a.beginRe=t(a.begin),o.end||o.endsWithParent||(o.end=/\B|\b/), +o.end&&(a.endRe=t(a.end)), +a.terminatorEnd=l(a.end)||"",o.endsWithParent&&r.terminatorEnd&&(a.terminatorEnd+=(o.end?"|":"")+r.terminatorEnd)), +o.illegal&&(a.illegalRe=t(o.illegal)), +o.contains||(o.contains=[]),o.contains=[].concat(...o.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{ +starts:e.starts?i(e.starts):null +}):Object.isFrozen(e)?i(e):e))("self"===e?o:e)))),o.contains.forEach((e=>{n(e,a) +})),o.starts&&n(o.starts,r),a.matcher=(e=>{const t=new s +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){ +return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{ +constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} +const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{ +const i=Object.create(null),s=Object.create(null),o=[];let r=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ +disableAutodetect:!0,name:"Plain text",contains:[]};let p={ +ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:c};function b(e){ +return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s="" +;"object"==typeof t?(i=e, +n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."), +G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +s=e,i=t),void 0===n&&(n=!0);const o={code:i,language:s};N("before:highlight",o) +;const r=o.result?o.result:E(o.language,o.code,n) +;return r.code=o.code,N("after:highlight",r),r}function E(e,n,s,o){ +const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R) +;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n="" +;for(;t;){n+=R.substring(e,t.index) +;const s=_.case_insensitive?t[0].toLowerCase():t[0],o=(i=s,N.keywords[i]);if(o){ +const[e,i]=o +;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(j+=i),e.startsWith("_"))n+=t[0];else{ +const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0] +;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i +;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{ +if(""===R)return;let e=null;if("string"==typeof N.subLanguage){ +if(!i[N.subLanguage])return void M.addText(R) +;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top +}else e=x(R,N.subLanguage.length?N.subLanguage:null) +;N.relevance>0&&(j+=e.relevance),M.__addSublanguage(e._emitter,e.language) +})():l(),R=""}function u(e,t){ +""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1 +;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue} +const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}} +function h(e,t){ +return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{ +value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e) +;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return f(e.parent,n,i)}function b(e){ +return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){ +const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const o=N +;N.endScope&&N.endScope._wrap?(g(), +u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(), +d(N.endScope,e)):o.skip?R+=t:(o.returnEnd||o.excludeEnd||(R+=t), +g(),o.excludeEnd&&(R=t));do{ +N.scope&&M.closeNode(),N.skip||N.subLanguage||(j+=N.relevance),N=N.parent +}while(N!==s.parent);return s.starts&&h(s.starts,e),o.returnEnd?0:t.length} +let w={};function y(i,o){const a=o&&o[0];if(R+=i,null==a)return g(),0 +;if("begin"===w.type&&"end"===o.type&&w.index===o.index&&""===a){ +if(R+=n.slice(o.index,o.index+1),!r){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=w.rule,t}return 1} +if(w=o,"begin"===o.type)return(e=>{ +const n=e[0],i=e.rule,s=new t(i),o=[i.__beforeBegin,i["on:begin"]] +;for(const t of o)if(t&&(t(e,s),s.isMatchIgnored))return b(n) +;return i.skip?R+=n:(i.excludeBegin&&(R+=n), +g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(o) +;if("illegal"===o.type&&!s){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') +;throw e.mode=N,e}if("end"===o.type){const e=m(o);if(e!==ee)return e} +if("illegal"===o.type&&""===a)return 1 +;if(I>1e5&&I>3*o.index)throw Error("potential infinite loop, way more iterations than matches") +;return R+=a,a.length}const _=O(e) +;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const v=V(_);let k="",N=o||v;const S={},M=new p.__emitter(p);(()=>{const e=[] +;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>M.openNode(e)))})();let R="",j=0,A=0,I=0,T=!1;try{ +if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){ +I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=A +;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(A,e.index),e) +;A=e.index+t}y(n.substring(A))}return M.finalize(),k=M.toHTML(),{language:e, +value:k,relevance:j,illegal:!1,_emitter:M,_top:N}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n), +illegal:!0,relevance:0,_illegalBy:{message:t.message,index:A, +context:n.slice(A-100,A+100),mode:t.mode,resultSoFar:k},_emitter:M};if(r)return{ +language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N} +;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{ +const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)} +;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(k).map((t=>E(t,e,!1))) +;s.unshift(n);const o=s.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 +;if(O(t.language).supersetOf===e.language)return-1}return 0})),[r,a]=o,c=r +;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1]) +;return t||(X(a.replace("{}",n[1])), +X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return +;if(N("before:highlightElement",{el:e,language:n +}),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e) +;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), +console.warn("The element with unescaped HTML:"), +console.warn(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML) +;t=e;const i=t.textContent,o=n?m(i,{language:n,ignoreIllegals:!0}):x(i) +;e.innerHTML=o.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,o.language),e.result={language:o.language,re:o.relevance, +relevance:o.relevance},o.secondBest&&(e.secondBest={ +language:o.secondBest.language,relevance:o.secondBest.relevance +}),N("after:highlightElement",{el:e,result:o,text:i})}let y=!1;function _(){ +"loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0 +}function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]} +function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +s[e.toLowerCase()]=t}))}function k(e){const t=O(e) +;return t&&!t.disableAutodetect}function N(e,t){const n=e;o.forEach((e=>{ +e[n]&&e[n](t)}))} +"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ +y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_, +highlightElement:w, +highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"), +G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)}, +initHighlighting:()=>{ +_(),G("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +_(),G("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){ +if(W("Language definition for '{}' could not be registered.".replace("{}",e)), +!r)throw t;W(t),s=l} +s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&v(s.aliases,{ +languageName:e})},unregisterLanguage:e=>{delete i[e] +;for(const t of Object.keys(s))s[t]===e&&delete s[t]}, +listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v, +autoDetection:k,inherit:Q,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),o.push(e)}, +removePlugin:e=>{const t=o.indexOf(e);-1!==t&&o.splice(t,1)}}),n.debugMode=()=>{ +r=!1},n.safeMode=()=>{r=!0},n.versionString="11.10.0",n.regex={concat:h, +lookahead:g,either:f,optional:d,anyNumberOfTimes:u} +;for(const t in j)"object"==typeof j[t]&&e(j[t]);return Object.assign(n,j),n +},ne=te({});return ne.newInstance=()=>te({}),ne}() +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `c` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const n=e.regex,t=e.COMMENT("//","$",{ +contains:[{begin:/\\\n/}] +}),a="decltype\\(auto\\)",s="[a-zA-Z_]\\w*::",i="("+a+"|"+n.optional(s)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",r={ +className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{ +match:/\batomic_[a-z]{3,6}\b/}]},l={className:"string",variants:[{ +begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef elifdef elifndef include" +},contains:[{begin:/\\\n/,relevance:0},e.inherit(l,{className:"string"}),{ +className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},d={ +className:"title",begin:n.optional(s)+e.IDENT_RE,relevance:0 +},_=n.optional(s)+e.IDENT_RE+"\\s*\\(",u={ +keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","typeof","typeof_unqual","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"], +type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_BitInt","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal96","_Decimal128","_Decimal64x","_Decimal128x","_Float16","_Float32","_Float64","_Float128","_Float32x","_Float64x","_Float128x","const","static","constexpr","complex","bool","imaginary"], +literal:"true false NULL", +built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" +},g=[c,r,t,e.C_BLOCK_COMMENT_MODE,o,l],m={variants:[{begin:/=/,end:/;/},{ +begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], +keywords:u,contains:g.concat([{begin:/\(/,end:/\)/,keywords:u, +contains:g.concat(["self"]),relevance:0}]),relevance:0},p={ +begin:"("+i+"[\\*&\\s]+)+"+_,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, +keywords:u,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:a,keywords:u,relevance:0},{ +begin:_,returnBegin:!0,contains:[e.inherit(d,{className:"title.function"})], +relevance:0},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/, +keywords:u,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,l,o,r,{begin:/\(/, +end:/\)/,keywords:u,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,l,o,r] +}]},r,t,e.C_BLOCK_COMMENT_MODE,c]};return{name:"C",aliases:["h"],keywords:u, +disableAutodetect:!0,illegal:"=]/,contains:[{ +beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:c, +strings:l,keywords:u}}}})();hljs.registerLanguage("c",e)})();/*! `cpp` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const t=e.regex,a=e.COMMENT("//","$",{ +contains:[{begin:/\\\n/}] +}),n="decltype\\(auto\\)",r="[a-zA-Z_]\\w*::",i="(?!struct)("+n+"|"+t.optional(r)+"[a-zA-Z_]\\w*"+t.optional("<[^<>]+>")+")",s={ +className:"type",begin:"\\b[a-z\\d_]*_t\\b"},c={className:"string",variants:[{ +begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={ +className:"number",variants:[{ +begin:"[+-]?(?:(?:[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?|\\.[0-9](?:'?[0-9])*)(?:[Ee][+-]?[0-9](?:'?[0-9])*)?|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*|0[Xx](?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)[Pp][+-]?[0-9](?:'?[0-9])*)(?:[Ff](?:16|32|64|128)?|(BF|bf)16|[Ll]|)" +},{ +begin:"[+-]?\\b(?:0[Bb][01](?:'?[01])*|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*|0(?:'?[0-7])*|[1-9](?:'?[0-9])*)(?:[Uu](?:LL?|ll?)|[Uu][Zz]?|(?:LL?|ll?)[Uu]?|[Zz][Uu]|)" +}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},e.inherit(c,{className:"string"}),{ +className:"string",begin:/<.*?>/},a,e.C_BLOCK_COMMENT_MODE]},u={ +className:"title",begin:t.optional(r)+e.IDENT_RE,relevance:0 +},d=t.optional(r)+e.IDENT_RE+"\\s*\\(",p={ +type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"], +keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"], +literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"], +_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"] +},_={className:"function.dispatch",relevance:0,keywords:{ +_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"] +}, +begin:t.concat(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!switch)/,/(?!while)/,e.IDENT_RE,t.lookahead(/(<[^<>]+>|)\s*\(/)) +},m=[_,l,s,a,e.C_BLOCK_COMMENT_MODE,o,c],f={variants:[{begin:/=/,end:/;/},{ +begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], +keywords:p,contains:m.concat([{begin:/\(/,end:/\)/,keywords:p, +contains:m.concat(["self"]),relevance:0}]),relevance:0},g={className:"function", +begin:"("+i+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, +keywords:p,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:n,keywords:p,relevance:0},{ +begin:d,returnBegin:!0,contains:[u],relevance:0},{begin:/::/,relevance:0},{ +begin:/:/,endsWithParent:!0,contains:[c,o]},{relevance:0,match:/,/},{ +className:"params",begin:/\(/,end:/\)/,keywords:p,relevance:0, +contains:[a,e.C_BLOCK_COMMENT_MODE,c,o,s,{begin:/\(/,end:/\)/,keywords:p, +relevance:0,contains:["self",a,e.C_BLOCK_COMMENT_MODE,c,o,s]}] +},s,a,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C++", +aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:p,illegal:"",keywords:p,contains:["self",s]},{begin:e.IDENT_RE+"::",keywords:p},{ +match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/], +className:{1:"keyword",3:"title.class"}}])}}})();hljs.registerLanguage("cpp",e) +})();/*! `css` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],r=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),t=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),i=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),o=["accent-color","align-content","align-items","align-self","alignment-baseline","all","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-end-end-radius","border-end-start-radius","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","cx","cy","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","content-visibility","counter-increment","counter-reset","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","empty-cells","enable-background","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flow","flood-color","flood-opacity","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-synthesis","font-variant","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inline-size","inset","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","kerning","justify-content","justify-items","justify-self","left","letter-spacing","lighting-color","line-break","line-height","list-style","list-style-image","list-style-position","list-style-type","marker","marker-end","marker-mid","marker-start","mask","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","pause","pause-after","pause-before","perspective","perspective-origin","pointer-events","position","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","scale","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","speak","speak-as","src","tab-size","table-layout","text-anchor","text-align","text-align-all","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-transform","text-underline-offset","text-underline-position","top","transform","transform-box","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","vector-effect","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index"].sort().reverse() +;return n=>{const a=n.regex,l=(e=>({IMPORTANT:{scope:"meta",begin:"!important"}, +BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number", +begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{ +className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{ +scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ +scope:"number", +begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/} +}))(n),s=[n.APOS_STRING_MODE,n.QUOTE_STRING_MODE];return{name:"CSS", +case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"}, +classNameAliases:{keyframePosition:"selector-tag"},contains:[l.BLOCK_COMMENT,{ +begin:/-(webkit|moz|ms|o)-(?=[a-z])/},l.CSS_NUMBER_MODE,{ +className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{ +className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0 +},l.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{ +begin:":("+t.join("|")+")"},{begin:":(:)?("+i.join("|")+")"}]},l.CSS_VARIABLE,{ +className:"attribute",begin:"\\b("+o.join("|")+")\\b"},{begin:/:/,end:/[;}{]/, +contains:[l.BLOCK_COMMENT,l.HEXCOLOR,l.IMPORTANT,l.CSS_NUMBER_MODE,...s,{ +begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri" +},contains:[...s,{className:"string",begin:/[^)]/,endsWithParent:!0, +excludeEnd:!0}]},l.FUNCTION_DISPATCH]},{begin:a.lookahead(/@/),end:"[{;]", +relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/ +},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{ +$pattern:/[a-z-]+/,keyword:"and or not only",attribute:r.join(" ")},contains:[{ +begin:/[a-z-]+(?=:)/,className:"attribute"},...s,l.CSS_NUMBER_MODE]}]},{ +className:"selector-tag",begin:"\\b("+e.join("|")+")\\b"}]}}})() +;hljs.registerLanguage("css",e)})();/*! `go` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const a={ +keyword:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","switch","type","var"], +type:["bool","byte","complex64","complex128","error","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"], +literal:["true","false","iota","nil"], +built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"] +};return{name:"Go",aliases:["golang"],keywords:a,illegal:"{var e=(()=>{"use strict";return e=>{const n="HTTP/([32]|1\\.[01])",a={ +className:"attribute", +begin:e.regex.concat("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{ +contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$", +relevance:0}}]}},s=[a,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0} +}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{ +begin:"^(?="+n+" \\d{3})",end:/$/,contains:[{className:"meta",begin:n},{ +className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/, +contains:s}},{begin:"(?=^[A-Z]+ (.*?) "+n+"$)",end:/$/,contains:[{ +className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{ +className:"meta",begin:n},{className:"keyword",begin:"[A-Z]+"}],starts:{ +end:/\b\B/,illegal:/\S/,contains:s}},e.inherit(a,{relevance:0})]}}})() +;hljs.registerLanguage("http",e)})();/*! `ini` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const n=e.regex,a={className:"number", +relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{begin:e.NUMBER_RE}] +},s=e.COMMENT();s.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];const i={ +className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)\}/ +}]},t={className:"literal",begin:/\bon|off|true|false|yes|no\b/},r={ +className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:"'''", +end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"' +},{begin:"'",end:"'"}]},l={begin:/\[/,end:/\]/,contains:[s,t,i,r,a,"self"], +relevance:0},c=n.either(/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/);return{ +name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/, +contains:[s,{className:"section",begin:/\[+/,end:/\]+/},{ +begin:n.concat(c,"(\\s*\\.\\s*",c,")*",n.lookahead(/\s*=\s*[^#\s]/)), +className:"attr",starts:{end:/$/,contains:[s,l,t,i,r,a]}}]}}})() +;hljs.registerLanguage("ini",e)})();/*! `java` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;var e="[0-9](_*[0-9])*",a=`\\.(${e})`,n="[0-9a-fA-F](_*[0-9a-fA-F])*",s={ +className:"number",variants:[{ +begin:`(\\b(${e})((${a})|\\.)?|(${a}))[eE][+-]?(${e})[fFdD]?\\b`},{ +begin:`\\b(${e})((${a})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${a})[fFdD]?\\b` +},{begin:`\\b(${e})[fFdD]\\b`},{ +begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?(${e})[fFdD]?\\b`},{ +begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};function t(e,a,n){return-1===n?"":e.replace(a,(s=>t(e,a,n-1)))} +return e=>{ +const a=e.regex,n="[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*",i=n+t("(?:<"+n+"~~~(?:\\s*,\\s*"+n+"~~~)*>)?",/~~~/g,2),r={ +keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","switch","continue","throws","protected","public","private","module","requires","exports","do","sealed","yield","permits","goto"], +literal:["false","true","null"], +type:["char","boolean","long","float","int","byte","short","double"], +built_in:["super","this"]},l={className:"meta",begin:"@"+n,contains:[{ +begin:/\(/,end:/\)/,contains:["self"]}]},c={className:"params",begin:/\(/, +end:/\)/,keywords:r,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0} +;return{name:"Java",aliases:["jsp"],keywords:r,illegal:/<\/|#/, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/, +relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{ +begin:/import java\.[a-z]+\./,keywords:"import",relevance:2 +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{begin:/"""/,end:/"""/, +className:"string",contains:[e.BACKSLASH_ESCAPE] +},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{ +match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,n],className:{ +1:"keyword",3:"title.class"}},{match:/non-sealed/,scope:"keyword"},{ +begin:[a.concat(/(?!else)/,n),/\s+/,n,/\s+/,/=(?!=)/],className:{1:"type", +3:"variable",5:"operator"}},{begin:[/record/,/\s+/,n],className:{1:"keyword", +3:"title.class"},contains:[c,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ +beginKeywords:"new throw return else",relevance:0},{ +begin:["(?:"+i+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{ +2:"title.function"},keywords:r,contains:[{className:"params",begin:/\(/, +end:/\)/,keywords:r,relevance:0, +contains:[l,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,s,e.C_BLOCK_COMMENT_MODE] +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},s,l]}}})() +;hljs.registerLanguage("java",e)})();/*! `javascript` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(r,t,s) +;return o=>{const l=o.regex,b=e,d={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,t=e.input[a] +;if("<"===t||","===t)return void n.ignoreMatch();let s +;">"===t&&(((e,{after:n})=>{const a="e+"\\s*\\(")), +l.concat("(?!",T.join("|"),")")),b,l.lookahead(/\s*\(/)), +className:"title.function",relevance:0};var T;const C={ +begin:l.concat(/\./,l.lookahead(l.concat(b,/(?![0-9A-Za-z$_(])/))),end:b, +excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},M={ +match:[/get|set/,/\s+/,b,/(?=\()/],className:{1:"keyword",3:"title.function"}, +contains:[{begin:/\(\)/},R] +},B="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+o.UNDERSCORE_IDENT_RE+")\\s*=>",$={ +match:[/const|var|let/,/\s+/,b,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)], +keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]} +;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ +PARAMS_CONTAINS:w,CLASS_REFERENCE:k},illegal:/#(?![$_A-z])/, +contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ +label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,h,N,_,f,p,{match:/\$\d+/},A,k,{ +className:"attr",begin:b+l.lookahead(":"),relevance:0},$,{ +begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[p,o.REGEXP_MODE,{ +className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/, +excludeBegin:!0,excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0 +},{match:/\s+/,relevance:0},{variants:[{begin:"<>",end:""},{ +match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:d.begin, +"on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ +begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},I,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:b, +className:"title.function"})]},{match:/\.\.\./,relevance:0},C,{match:"\\$"+b, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[R]},x,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, +className:"variable.constant"},O,M,{match:/\$[(.]/}]}}})() +;hljs.registerLanguage("javascript",e)})();/*! `json` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=["true","false","null"],s={ +scope:"literal",beginKeywords:a.join(" ")};return{name:"JSON",aliases:["jsonc"], +keywords:{literal:a},contains:[{className:"attr", +begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},{match:/[{}[\],:]/, +className:"punctuation",relevance:0 +},e.QUOTE_STRING_MODE,s,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE], +illegal:"\\S"}}})();hljs.registerLanguage("json",e)})();/*! `less` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],t=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),r=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),i=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),o=["accent-color","align-content","align-items","align-self","alignment-baseline","all","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-end-end-radius","border-end-start-radius","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","cx","cy","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","content-visibility","counter-increment","counter-reset","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","empty-cells","enable-background","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flow","flood-color","flood-opacity","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-synthesis","font-variant","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inline-size","inset","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","kerning","justify-content","justify-items","justify-self","left","letter-spacing","lighting-color","line-break","line-height","list-style","list-style-image","list-style-position","list-style-type","marker","marker-end","marker-mid","marker-start","mask","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","pause","pause-after","pause-before","perspective","perspective-origin","pointer-events","position","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","scale","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","speak","speak-as","src","tab-size","table-layout","text-anchor","text-align","text-align-all","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-transform","text-underline-offset","text-underline-position","top","transform","transform-box","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","vector-effect","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index"].sort().reverse(),n=r.concat(i).sort().reverse() +;return a=>{const l=(e=>({IMPORTANT:{scope:"meta",begin:"!important"}, +BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number", +begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{ +className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{ +scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ +scope:"number", +begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/} +}))(a),s=n,d="[\\w-]+",c="("+d+"|@\\{"+d+"\\})",g=[],b=[],m=e=>({ +className:"string",begin:"~?"+e+".*?"+e}),p=(e,t,r)=>({className:e,begin:t, +relevance:r}),f={$pattern:/[a-z-]+/,keyword:"and or not only", +attribute:t.join(" ")},u={begin:"\\(",end:"\\)",contains:b,keywords:f, +relevance:0} +;b.push(a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,m("'"),m('"'),l.CSS_NUMBER_MODE,{ +begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]", +excludeEnd:!0} +},l.HEXCOLOR,u,p("variable","@@?"+d,10),p("variable","@\\{"+d+"\\}"),p("built_in","~?`[^`]*?`"),{ +className:"attribute",begin:d+"\\s*:",end:":",returnBegin:!0,excludeEnd:!0 +},l.IMPORTANT,{beginKeywords:"and not"},l.FUNCTION_DISPATCH);const h=b.concat({ +begin:/\{/,end:/\}/,contains:g}),k={beginKeywords:"when",endsWithParent:!0, +contains:[{beginKeywords:"and not"}].concat(b)},v={begin:c+"\\s*:", +returnBegin:!0,end:/[;}]/,relevance:0,contains:[{begin:/-(webkit|moz|ms|o)-/ +},l.CSS_VARIABLE,{className:"attribute",begin:"\\b("+o.join("|")+")\\b", +end:/(?=:)/,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:b}}] +},y={className:"keyword", +begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b", +starts:{end:"[;{}]",keywords:f,returnEnd:!0,contains:b,relevance:0}},w={ +className:"variable",variants:[{begin:"@"+d+"\\s*:",relevance:15},{begin:"@"+d +}],starts:{end:"[;}]",returnEnd:!0,contains:h}},x={variants:[{ +begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:c,end:/\{/}],returnBegin:!0, +returnEnd:!0,illegal:"[<='$\"]",relevance:0, +contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,k,p("keyword","all\\b"),p("variable","@\\{"+d+"\\}"),{ +begin:"\\b("+e.join("|")+")\\b",className:"selector-tag" +},l.CSS_NUMBER_MODE,p("selector-tag",c,0),p("selector-id","#"+c),p("selector-class","\\."+c,0),p("selector-tag","&",0),l.ATTRIBUTE_SELECTOR_MODE,{ +className:"selector-pseudo",begin:":("+r.join("|")+")"},{ +className:"selector-pseudo",begin:":(:)?("+i.join("|")+")"},{begin:/\(/, +end:/\)/,relevance:0,contains:h},{begin:"!important"},l.FUNCTION_DISPATCH]},_={ +begin:d+":(:)?"+`(${s.join("|")})`,returnBegin:!0,contains:[x]} +;return g.push(a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,y,w,_,v,x,k,l.FUNCTION_DISPATCH), +{name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:g}}})() +;hljs.registerLanguage("less",e)})();/*! `nginx` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const n=e.regex,a={ +className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{\w+\}/},{ +begin:n.concat(/[$@]/,e.UNDERSCORE_IDENT_RE)}]},s={endsWithParent:!0,keywords:{ +$pattern:/[a-z_]{2,}|\/dev\/poll/, +literal:["on","off","yes","no","true","false","none","blocked","debug","info","notice","warn","error","crit","select","break","last","permanent","redirect","kqueue","rtsig","epoll","poll","/dev/poll"] +},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string", +contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/ +}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[a] +},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:"\\s\\^", +end:"\\s|\\{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|\\{|;",returnEnd:!0},{ +begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number", +begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{ +className:"number",begin:"\\b\\d+[kKmMgGdshdwy]?\\b",relevance:0},a]};return{ +name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{ +beginKeywords:"upstream location",end:/;|\{/,contains:s.contains,keywords:{ +section:"upstream location"}},{className:"section", +begin:n.concat(e.UNDERSCORE_IDENT_RE+n.lookahead(/\s+\{/)),relevance:0},{ +begin:n.lookahead(e.UNDERSCORE_IDENT_RE+"\\s"),end:";|\\{",contains:[{ +className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:s}],relevance:0}], +illegal:"[^\\s\\}\\{]"}}})();hljs.registerLanguage("nginx",e)})();/*! `php` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const t=e.regex,a=/(?![A-Za-z0-9])(?![$])/,r=t.concat(/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/,a),n=t.concat(/(\\?[A-Z][a-z0-9_\x7f-\xff]+|\\?[A-Z]+(?=[A-Z][a-z0-9_\x7f-\xff])){1,}/,a),o={ +scope:"variable",match:"\\$+"+r},c={scope:"subst",variants:[{begin:/\$\w+/},{ +begin:/\{\$/,end:/\}/}]},i=e.inherit(e.APOS_STRING_MODE,{illegal:null +}),s="[ \t\n]",l={scope:"string",variants:[e.inherit(e.QUOTE_STRING_MODE,{ +illegal:null,contains:e.QUOTE_STRING_MODE.contains.concat(c)}),i,{ +begin:/<<<[ \t]*(?:(\w+)|"(\w+)")\n/,end:/[ \t]*(\w+)\b/, +contains:e.QUOTE_STRING_MODE.contains.concat(c),"on:begin":(e,t)=>{ +t.data._beginMatch=e[1]||e[2]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}},e.END_SAME_AS_BEGIN({ +begin:/<<<[ \t]*'(\w+)'\n/,end:/[ \t]*(\w+)\b/})]},d={scope:"number",variants:[{ +begin:"\\b0[bB][01]+(?:_[01]+)*\\b"},{begin:"\\b0[oO][0-7]+(?:_[0-7]+)*\\b"},{ +begin:"\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b"},{ +begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?" +}],relevance:0 +},_=["false","null","true"],p=["__CLASS__","__DIR__","__FILE__","__FUNCTION__","__COMPILER_HALT_OFFSET__","__LINE__","__METHOD__","__NAMESPACE__","__TRAIT__","die","echo","exit","include","include_once","print","require","require_once","array","abstract","and","as","binary","bool","boolean","break","callable","case","catch","class","clone","const","continue","declare","default","do","double","else","elseif","empty","enddeclare","endfor","endforeach","endif","endswitch","endwhile","enum","eval","extends","final","finally","float","for","foreach","from","global","goto","if","implements","instanceof","insteadof","int","integer","interface","isset","iterable","list","match|0","mixed","new","never","object","or","private","protected","public","readonly","real","return","string","switch","throw","trait","try","unset","use","var","void","while","xor","yield"],b=["Error|0","AppendIterator","ArgumentCountError","ArithmeticError","ArrayIterator","ArrayObject","AssertionError","BadFunctionCallException","BadMethodCallException","CachingIterator","CallbackFilterIterator","CompileError","Countable","DirectoryIterator","DivisionByZeroError","DomainException","EmptyIterator","ErrorException","Exception","FilesystemIterator","FilterIterator","GlobIterator","InfiniteIterator","InvalidArgumentException","IteratorIterator","LengthException","LimitIterator","LogicException","MultipleIterator","NoRewindIterator","OutOfBoundsException","OutOfRangeException","OuterIterator","OverflowException","ParentIterator","ParseError","RangeException","RecursiveArrayIterator","RecursiveCachingIterator","RecursiveCallbackFilterIterator","RecursiveDirectoryIterator","RecursiveFilterIterator","RecursiveIterator","RecursiveIteratorIterator","RecursiveRegexIterator","RecursiveTreeIterator","RegexIterator","RuntimeException","SeekableIterator","SplDoublyLinkedList","SplFileInfo","SplFileObject","SplFixedArray","SplHeap","SplMaxHeap","SplMinHeap","SplObjectStorage","SplObserver","SplPriorityQueue","SplQueue","SplStack","SplSubject","SplTempFileObject","TypeError","UnderflowException","UnexpectedValueException","UnhandledMatchError","ArrayAccess","BackedEnum","Closure","Fiber","Generator","Iterator","IteratorAggregate","Serializable","Stringable","Throwable","Traversable","UnitEnum","WeakReference","WeakMap","Directory","__PHP_Incomplete_Class","parent","php_user_filter","self","static","stdClass"],E={ +keyword:p,literal:(e=>{const t=[];return e.forEach((e=>{ +t.push(e),e.toLowerCase()===e?t.push(e.toUpperCase()):t.push(e.toLowerCase()) +})),t})(_),built_in:b},u=e=>e.map((e=>e.replace(/\|\d+$/,""))),g={variants:[{ +match:[/new/,t.concat(s,"+"),t.concat("(?!",u(b).join("\\b|"),"\\b)"),n],scope:{ +1:"keyword",4:"title.class"}}]},h=t.concat(r,"\\b(?!\\()"),m={variants:[{ +match:[t.concat(/::/,t.lookahead(/(?!class\b)/)),h],scope:{2:"variable.constant" +}},{match:[/::/,/class/],scope:{2:"variable.language"}},{ +match:[n,t.concat(/::/,t.lookahead(/(?!class\b)/)),h],scope:{1:"title.class", +3:"variable.constant"}},{match:[n,t.concat("::",t.lookahead(/(?!class\b)/))], +scope:{1:"title.class"}},{match:[n,/::/,/class/],scope:{1:"title.class", +3:"variable.language"}}]},I={scope:"attr", +match:t.concat(r,t.lookahead(":"),t.lookahead(/(?!::)/))},f={relevance:0, +begin:/\(/,end:/\)/,keywords:E,contains:[I,o,m,e.C_BLOCK_COMMENT_MODE,l,d,g] +},O={relevance:0, +match:[/\b/,t.concat("(?!fn\\b|function\\b|",u(p).join("\\b|"),"|",u(b).join("\\b|"),"\\b)"),r,t.concat(s,"*"),t.lookahead(/(?=\()/)], +scope:{3:"title.function.invoke"},contains:[f]};f.contains.push(O) +;const v=[I,m,e.C_BLOCK_COMMENT_MODE,l,d,g];return{case_insensitive:!1, +keywords:E,contains:[{begin:t.concat(/#\[\s*/,n),beginScope:"meta",end:/]/, +endScope:"meta",keywords:{literal:_,keyword:["new","array"]},contains:[{ +begin:/\[/,end:/]/,keywords:{literal:_,keyword:["new","array"]}, +contains:["self",...v]},...v,{scope:"meta",match:n}] +},e.HASH_COMMENT_MODE,e.COMMENT("//","$"),e.COMMENT("/\\*","\\*/",{contains:[{ +scope:"doctag",match:"@[A-Za-z]+"}]}),{match:/__halt_compiler\(\);/, +keywords:"__halt_compiler",starts:{scope:"comment",end:e.MATCH_NOTHING_RE, +contains:[{match:/\?>/,scope:"meta",endsParent:!0}]}},{scope:"meta",variants:[{ +begin:/<\?php/,relevance:10},{begin:/<\?=/},{begin:/<\?/,relevance:.1},{ +begin:/\?>/}]},{scope:"variable.language",match:/\$this\b/},o,O,m,{ +match:[/const/,/\s/,r],scope:{1:"keyword",3:"variable.constant"}},g,{ +scope:"function",relevance:0,beginKeywords:"fn function",end:/[;{]/, +excludeEnd:!0,illegal:"[$%\\[]",contains:[{beginKeywords:"use" +},e.UNDERSCORE_TITLE_MODE,{begin:"=>",endsParent:!0},{scope:"params", +begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:E, +contains:["self",o,m,e.C_BLOCK_COMMENT_MODE,l,d]}]},{scope:"class",variants:[{ +beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"class interface trait", +illegal:/[:($"]/}],relevance:0,end:/\{/,excludeEnd:!0,contains:[{ +beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{ +beginKeywords:"namespace",relevance:0,end:";",illegal:/[.']/, +contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{scope:"title.class"})]},{ +beginKeywords:"use",relevance:0,end:";",contains:[{ +match:/\b(as|const|function)\b/,scope:"keyword"},e.UNDERSCORE_TITLE_MODE]},l,d]} +}})();hljs.registerLanguage("php",e)})();/*! `python` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,s=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],t={ +$pattern:/[A-Za-z]\w+|__\w+__/,keyword:s, +built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"], +literal:["__debug__","Ellipsis","False","None","NotImplemented","True"], +type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"] +},i={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/, +end:/\}/,keywords:t,illegal:/#/},l={begin:/\{\{/,relevance:0},o={ +className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,i],relevance:10},{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, +contains:[e.BACKSLASH_ESCAPE,i],relevance:10},{ +begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,i,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, +end:/"""/,contains:[e.BACKSLASH_ESCAPE,i,l,r]},{begin:/([uU]|[rR])'/,end:/'/, +relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ +begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, +end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, +contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] +},b="[0-9](_?[0-9])*",c=`(\\b(${b}))?\\.(${b})|\\b(${b})\\.`,d="\\b|"+s.join("|"),g={ +className:"number",relevance:0,variants:[{ +begin:`(\\b(${b})|(${c}))[eE][+-]?(${b})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{ +begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{ +begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})` +},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${b})[jJ](?=${d})` +}]},p={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:t, +contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={ +className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/, +end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t, +contains:["self",i,g,o,e.HASH_COMMENT_MODE]}]};return r.contains=[o,g,i],{ +name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:t, +illegal:/(<\/|\?)|=>/,contains:[i,g,{scope:"variable.language",match:/\bself\b/ +},{beginKeywords:"if",relevance:0},{match:/\bor\b/,scope:"keyword" +},o,p,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,a],scope:{1:"keyword", +3:"title.function"},contains:[m]},{variants:[{ +match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{match:[/\bclass/,/\s+/,a]}], +scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{ +className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[g,m,o]}]}}})() +;hljs.registerLanguage("python",e)})();/*! `rust` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const t=e.regex,n=/(r#)?/,a=t.concat(n,e.UNDERSCORE_IDENT_RE),i=t.concat(n,e.IDENT_RE),r={ +className:"title.function.invoke",relevance:0, +begin:t.concat(/\b/,/(?!let|for|while|if|else|match\b)/,i,t.lookahead(/\s*\(/)) +},s="([ui](8|16|32|64|128|size)|f(32|64))?",l=["drop ","Copy","Send","Sized","Sync","Drop","Fn","FnMut","FnOnce","ToOwned","Clone","Debug","PartialEq","PartialOrd","Eq","Ord","AsRef","AsMut","Into","From","Default","Iterator","Extend","IntoIterator","DoubleEndedIterator","ExactSizeIterator","SliceConcatExt","ToString","assert!","assert_eq!","bitflags!","bytes!","cfg!","col!","concat!","concat_idents!","debug_assert!","debug_assert_eq!","env!","eprintln!","panic!","file!","format!","format_args!","include_bytes!","include_str!","line!","local_data_key!","module_path!","option_env!","print!","println!","select!","stringify!","try!","unimplemented!","unreachable!","vec!","write!","writeln!","macro_rules!","assert_ne!","debug_assert_ne!"],o=["i8","i16","i32","i64","i128","isize","u8","u16","u32","u64","u128","usize","f32","f64","str","char","bool","Box","Option","Result","String","Vec"] +;return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",type:o, +keyword:["abstract","as","async","await","become","box","break","const","continue","crate","do","dyn","else","enum","extern","false","final","fn","for","if","impl","in","let","loop","macro","match","mod","move","mut","override","priv","pub","ref","return","self","Self","static","struct","super","trait","true","try","type","typeof","union","unsafe","unsized","use","virtual","where","while","yield"], +literal:["true","false","Some","None","Ok","Err"],built_in:l},illegal:""},r]}}})() +;hljs.registerLanguage("rust",e)})();/*! `scss` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],r=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),t=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),i=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),o=["accent-color","align-content","align-items","align-self","alignment-baseline","all","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-end-end-radius","border-end-start-radius","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","cx","cy","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","content-visibility","counter-increment","counter-reset","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","empty-cells","enable-background","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flow","flood-color","flood-opacity","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-synthesis","font-variant","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inline-size","inset","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","kerning","justify-content","justify-items","justify-self","left","letter-spacing","lighting-color","line-break","line-height","list-style","list-style-image","list-style-position","list-style-type","marker","marker-end","marker-mid","marker-start","mask","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","pause","pause-after","pause-before","perspective","perspective-origin","pointer-events","position","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","scale","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","speak","speak-as","src","tab-size","table-layout","text-anchor","text-align","text-align-all","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-transform","text-underline-offset","text-underline-position","top","transform","transform-box","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","vector-effect","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index"].sort().reverse() +;return n=>{const a=(e=>({IMPORTANT:{scope:"meta",begin:"!important"}, +BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number", +begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{ +className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{ +scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ +scope:"number", +begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/} +}))(n),l=i,s=t,d="@[a-z-]+",c={className:"variable", +begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b",relevance:0};return{name:"SCSS", +case_insensitive:!0,illegal:"[=/|']", +contains:[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE,a.CSS_NUMBER_MODE,{ +className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{ +className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0 +},a.ATTRIBUTE_SELECTOR_MODE,{className:"selector-tag", +begin:"\\b("+e.join("|")+")\\b",relevance:0},{className:"selector-pseudo", +begin:":("+s.join("|")+")"},{className:"selector-pseudo", +begin:":(:)?("+l.join("|")+")"},c,{begin:/\(/,end:/\)/, +contains:[a.CSS_NUMBER_MODE]},a.CSS_VARIABLE,{className:"attribute", +begin:"\\b("+o.join("|")+")\\b"},{ +begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b" +},{begin:/:/,end:/[;}{]/,relevance:0, +contains:[a.BLOCK_COMMENT,c,a.HEXCOLOR,a.CSS_NUMBER_MODE,n.QUOTE_STRING_MODE,n.APOS_STRING_MODE,a.IMPORTANT,a.FUNCTION_DISPATCH] +},{begin:"@(page|font-face)",keywords:{$pattern:d,keyword:"@page @font-face"}},{ +begin:"@",end:"[{;]",returnBegin:!0,keywords:{$pattern:/[a-z-]+/, +keyword:"and or not only",attribute:r.join(" ")},contains:[{begin:d, +className:"keyword"},{begin:/[a-z-]+(?=:)/,className:"attribute" +},c,n.QUOTE_STRING_MODE,n.APOS_STRING_MODE,a.HEXCOLOR,a.CSS_NUMBER_MODE] +},a.FUNCTION_DISPATCH]}}})();hljs.registerLanguage("scss",e)})();/*! `swift` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(e){return t("(?=",e,")")} +function t(...n){return n.map((n=>e(n))).join("")}function a(...n){const t=(e=>{ +const n=e[e.length-1] +;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} +})(n);return"("+(t.capture?"":"?:")+n.map((n=>e(n))).join("|")+")"} +const i=e=>t(/\b/,e,/\w$/.test(e)?/\b/:/\B/),s=["Protocol","Type"].map(i),c=["init","self"].map(i),u=["Any","Self"],o=["actor","any","associatedtype","async","await",/as\?/,/as!/,"as","borrowing","break","case","catch","class","consume","consuming","continue","convenience","copy","default","defer","deinit","didSet","distributed","do","dynamic","each","else","enum","extension","fallthrough",/fileprivate\(set\)/,"fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout",/internal\(set\)/,"internal","in","is","isolated","nonisolated","lazy","let","macro","mutating","nonmutating",/open\(set\)/,"open","operator","optional","override","package","postfix","precedencegroup","prefix",/private\(set\)/,"private","protocol",/public\(set\)/,"public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","switch","throws","throw",/try\?/,/try!/,"try","typealias",/unowned\(safe\)/,/unowned\(unsafe\)/,"unowned","var","weak","where","while","willSet"],r=["false","nil","true"],l=["assignment","associativity","higherThan","left","lowerThan","none","right"],m=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warning"],p=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"],d=a(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/),F=a(d,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),b=t(d,F,"*"),h=a(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFEFE\uFF00-\uFFFD]/),f=a(h,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),w=t(h,f,"*"),g=t(/[A-Z]/,f,"*"),y=["attached","autoclosure",t(/convention\(/,a("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","freestanding","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",t(/objc\(/,w,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","resultBuilder","Sendable","testable","UIApplicationMain","unchecked","unknown","usableFromInline","warn_unqualified_access"],v=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"] +;return e=>{const d={match:/\s+/,relevance:0},h=e.COMMENT("/\\*","\\*/",{ +contains:["self"]}),E=[e.C_LINE_COMMENT_MODE,h],A={match:[/\./,a(...s,...c)], +className:{2:"keyword"}},C={match:t(/\./,a(...o)),relevance:0 +},k=o.filter((e=>"string"==typeof e)).concat(["_|0"]),N={variants:[{ +className:"keyword", +match:a(...o.filter((e=>"string"!=typeof e)).concat(u).map(i),...c)}]},S={ +$pattern:a(/\b\w+/,/#\w+/),keyword:k.concat(m),literal:r},B=[A,C,N],D=[{ +match:t(/\./,a(...p)),relevance:0},{className:"built_in", +match:t(/\b/,a(...p),/(?=\()/)}],_={match:/->/,relevance:0},M=[_,{ +className:"operator",relevance:0,variants:[{match:b},{match:`\\.(\\.|${F})+`}] +}],x="([0-9]_*)+",L="([0-9a-fA-F]_*)+",$={className:"number",relevance:0, +variants:[{match:`\\b(${x})(\\.(${x}))?([eE][+-]?(${x}))?\\b`},{ +match:`\\b0x(${L})(\\.(${L}))?([pP][+-]?(${x}))?\\b`},{match:/\b0o([0-7]_*)+\b/ +},{match:/\b0b([01]_*)+\b/}]},I=(e="")=>({className:"subst",variants:[{ +match:t(/\\/,e,/[0\\tnr"']/)},{match:t(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}] +}),O=(e="")=>({className:"subst",match:t(/\\/,e,/[\t ]*(?:[\r\n]|\r\n)/) +}),P=(e="")=>({className:"subst",label:"interpol",begin:t(/\\/,e,/\(/),end:/\)/ +}),j=(e="")=>({begin:t(e,/"""/),end:t(/"""/,e),contains:[I(e),O(e),P(e)] +}),K=(e="")=>({begin:t(e,/"/),end:t(/"/,e),contains:[I(e),P(e)]}),T={ +className:"string", +variants:[j(),j("#"),j("##"),j("###"),K(),K("#"),K("##"),K("###")] +},q=[e.BACKSLASH_ESCAPE,{begin:/\[/,end:/\]/,relevance:0, +contains:[e.BACKSLASH_ESCAPE]}],U={begin:/\/[^\s](?=[^/\n]*\/)/,end:/\//, +contains:q},z=e=>{const n=t(e,/\//),a=t(/\//,e);return{begin:n,end:a, +contains:[...q,{scope:"comment",begin:`#(?!.*${a})`,end:/$/}]}},V={ +scope:"regexp",variants:[z("###"),z("##"),z("#"),U]},W={match:t(/`/,w,/`/) +},Z=[W,{className:"variable",match:/\$\d+/},{className:"variable", +match:`\\$${f}+`}],G=[{match:/(@|#(un)?)available/,scope:"keyword",starts:{ +contains:[{begin:/\(/,end:/\)/,keywords:v,contains:[...M,$,T]}]}},{ +scope:"keyword",match:t(/@/,a(...y),n(a(/\(/,/\s+/)))},{scope:"meta", +match:t(/@/,w)}],H={match:n(/\b[A-Z]/),relevance:0,contains:[{className:"type", +match:t(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,f,"+") +},{className:"type",match:g,relevance:0},{match:/[?!]+/,relevance:0},{ +match:/\.\.\./,relevance:0},{match:t(/\s+&\s+/,n(g)),relevance:0}]},R={ +begin://,keywords:S,contains:[...E,...B,...G,_,H]};H.contains.push(R) +;const X={begin:/\(/,end:/\)/,relevance:0,keywords:S,contains:["self",{ +match:t(w,/\s*:/),keywords:"_|0",relevance:0 +},...E,V,...B,...D,...M,$,T,...Z,...G,H]},J={begin://, +keywords:"repeat each",contains:[...E,H]},Q={begin:/\(/,end:/\)/,keywords:S, +contains:[{begin:a(n(t(w,/\s*:/)),n(t(w,/\s+/,w,/\s*:/))),end:/:/,relevance:0, +contains:[{className:"keyword",match:/\b_\b/},{className:"params",match:w}] +},...E,...B,...M,$,T,...G,H,X],endsParent:!0,illegal:/["']/},Y={ +match:[/(func|macro)/,/\s+/,a(W.match,w,b)],className:{1:"keyword", +3:"title.function"},contains:[J,Q,d],illegal:[/\[/,/%/]},ee={ +match:[/\b(?:subscript|init[?!]?)/,/\s*(?=[<(])/],className:{1:"keyword"}, +contains:[J,Q,d],illegal:/\[|%/},ne={match:[/operator/,/\s+/,b],className:{ +1:"keyword",3:"title"}},te={begin:[/precedencegroup/,/\s+/,g],className:{ +1:"keyword",3:"title"},contains:[H],keywords:[...l,...r],end:/}/},ae={ +begin:[/(struct|protocol|class|extension|enum|actor)/,/\s+/,w,/\s*/], +beginScope:{1:"keyword",3:"title.class"},keywords:S,contains:[J,...B,{begin:/:/, +end:/\{/,keywords:S,contains:[{scope:"title.class.inherited",match:g},...B], +relevance:0}]};for(const e of T.variants){ +const n=e.contains.find((e=>"interpol"===e.label));n.keywords=S +;const t=[...B,...D,...M,$,T,...Z];n.contains=[...t,{begin:/\(/,end:/\)/, +contains:["self",...t]}]}return{name:"Swift",keywords:S, +contains:[...E,Y,ee,ae,ne,te,{beginKeywords:"import",end:/$/,contains:[...E], +relevance:0},V,...B,...D,...M,$,T,...Z,...G,H,X]}}})() +;hljs.registerLanguage("swift",e)})();/*! `typescript` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(r,t,s) +;function o(o){const l=o.regex,d=e,b={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,t=e.input[a] +;if("<"===t||","===t)return void n.ignoreMatch();let s +;">"===t&&(((e,{after:n})=>{const a="e+"\\s*\\(")), +l.concat("(?!",C.join("|"),")")),d,l.lookahead(/\s*\(/)), +className:"title.function",relevance:0};var C;const T={ +begin:l.concat(/\./,l.lookahead(l.concat(d,/(?![0-9A-Za-z$_(])/))),end:d, +excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},M={ +match:[/get|set/,/\s+/,d,/(?=\()/],className:{1:"keyword",3:"title.function"}, +contains:[{begin:/\(\)/},R] +},B="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+o.UNDERSCORE_IDENT_RE+")\\s*=>",$={ +match:[/const|var|let/,/\s+/,d,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)], +keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]} +;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ +PARAMS_CONTAINS:w,CLASS_REFERENCE:x},illegal:/#(?![$_A-z])/, +contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ +label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,p,N,f,_,h,{match:/\$\d+/},A,x,{ +className:"attr",begin:d+l.lookahead(":"),relevance:0},$,{ +begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[h,o.REGEXP_MODE,{ +className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/, +excludeBegin:!0,excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0 +},{match:/\s+/,relevance:0},{variants:[{begin:"<>",end:""},{ +match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:b.begin, +"on:begin":b.isTrulyOpeningTag,end:b.end}],subLanguage:"xml",contains:[{ +begin:b.begin,end:b.end,skip:!0,contains:["self"]}]}]},O,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:d, +className:"title.function"})]},{match:/\.\.\./,relevance:0},T,{match:"\\$"+d, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[R]},I,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, +className:"variable.constant"},k,M,{match:/\$[(.]/}]}}return t=>{ +const s=o(t),r=e,l=["any","void","number","boolean","string","object","never","symbol","bigint","unknown"],d={ +begin:[/namespace/,/\s+/,t.IDENT_RE],beginScope:{1:"keyword",3:"title.class"} +},b={beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:{ +keyword:"interface extends",built_in:l},contains:[s.exports.CLASS_REFERENCE] +},g={$pattern:e, +keyword:n.concat(["type","interface","public","private","protected","implements","declare","abstract","readonly","enum","override","satisfies"]), +literal:a,built_in:i.concat(l),"variable.language":c},u={className:"meta", +begin:"@"+r},m=(e,n,a)=>{const t=e.contains.findIndex((e=>e.label===n)) +;if(-1===t)throw Error("can not find mode to replace");e.contains.splice(t,1,a)} +;Object.assign(s.keywords,g),s.exports.PARAMS_CONTAINS.push(u) +;const E=s.contains.find((e=>"attr"===e.className)) +;return s.exports.PARAMS_CONTAINS.push([s.exports.CLASS_REFERENCE,E]), +s.contains=s.contains.concat([u,d,b]), +m(s,"shebang",t.SHEBANG()),m(s,"use_strict",{className:"meta",relevance:10, +begin:/^\s*['"]use strict['"]/ +}),s.contains.find((e=>"func.def"===e.label)).relevance=0,Object.assign(s,{ +name:"TypeScript",aliases:["ts","tsx","mts","cts"]}),s}})() +;hljs.registerLanguage("typescript",e)})();/*! `xml` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const a=e.regex,n=a.concat(/[\p{L}_]/u,a.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),s={ +className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},t={begin:/\s/, +contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] +},i=e.inherit(t,{begin:/\(/,end:/\)/}),c=e.inherit(e.APOS_STRING_MODE,{ +className:"string"}),l=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),r={ +endsWithParent:!0,illegal:/`]+/}]}]}]};return{ +name:"HTML, XML", +aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], +case_insensitive:!0,unicodeRegex:!0,contains:[{className:"meta",begin://,relevance:10,contains:[t,l,c,i,{begin:/\[/,end:/\]/,contains:[{ +className:"meta",begin://,contains:[t,i,l,c]}]}] +},e.COMMENT(//,{relevance:10}),{begin://, +relevance:10},s,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/, +relevance:10,contains:[l]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"style"},contains:[r],starts:{ +end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"script"},contains:[r],starts:{ +end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ +className:"tag",begin:/<>|<\/>/},{className:"tag", +begin:a.concat(//,/>/,/\s/)))), +end:/\/?>/,contains:[{className:"name",begin:n,relevance:0,starts:r}]},{ +className:"tag",begin:a.concat(/<\//,a.lookahead(a.concat(n,/>/))),contains:[{ +className:"name",begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}} +})();hljs.registerLanguage("xml",e)})(); \ No newline at end of file diff --git a/hybrid/html/js/katex.js b/hybrid/html/js/katex.js new file mode 100644 index 0000000..4759411 --- /dev/null +++ b/hybrid/html/js/katex.js @@ -0,0 +1,19092 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["katex"] = factory(); + else + root["katex"] = factory(); +})((typeof self !== 'undefined' ? self : this), function() { +return /******/ (function() { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ !function() { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = function(exports, definition) { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ }(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ !function() { +/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } +/******/ }(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; + +// EXPORTS +__webpack_require__.d(__webpack_exports__, { + "default": function() { return /* binding */ katex_webpack; } +}); + +;// CONCATENATED MODULE: ./src/ParseError.js + + +/** + * This is the ParseError class, which is the main error thrown by KaTeX + * functions when something has gone wrong. This is used to distinguish internal + * errors from errors in the expression that the user provided. + * + * If possible, a caller should provide a Token or ParseNode with information + * about where in the source string the problem occurred. + */ +class ParseError { + // Error start position based on passed-in Token or ParseNode. + // Length of affected text based on passed-in Token or ParseNode. + // The underlying error message without any context added. + constructor(message, // The error message + token // An object providing position information + ) { + this.name = void 0; + this.position = void 0; + this.length = void 0; + this.rawMessage = void 0; + let error = "KaTeX parse error: " + message; + let start; + let end; + const loc = token && token.loc; + + if (loc && loc.start <= loc.end) { + // If we have the input and a position, make the error a bit fancier + // Get the input + const input = loc.lexer.input; // Prepend some information + + start = loc.start; + end = loc.end; + + if (start === input.length) { + error += " at end of input: "; + } else { + error += " at position " + (start + 1) + ": "; + } // Underline token in question using combining underscores + + + const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error + + let left; + + if (start > 15) { + left = "…" + input.slice(start - 15, start); + } else { + left = input.slice(0, start); + } + + let right; + + if (end + 15 < input.length) { + right = input.slice(end, end + 15) + "…"; + } else { + right = input.slice(end); + } + + error += left + underlined + right; + } // Some hackery to make ParseError a prototype of Error + // See http://stackoverflow.com/a/8460753 + // $FlowFixMe + + + const self = new Error(error); + self.name = "ParseError"; // $FlowFixMe + + self.__proto__ = ParseError.prototype; + self.position = start; + + if (start != null && end != null) { + self.length = end - start; + } + + self.rawMessage = message; + return self; + } + +} // $FlowFixMe More hackery + + +ParseError.prototype.__proto__ = Error.prototype; +/* harmony default export */ var src_ParseError = (ParseError); +;// CONCATENATED MODULE: ./src/utils.js +/** + * This file contains a list of utility functions which are useful in other + * files. + */ + +/** + * Return whether an element is contained in a list + */ +const contains = function (list, elem) { + return list.indexOf(elem) !== -1; +}; +/** + * Provide a default value if a setting is undefined + * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022. + */ + + +const deflt = function (setting, defaultIfUndefined) { + return setting === undefined ? defaultIfUndefined : setting; +}; // hyphenate and escape adapted from Facebook's React under Apache 2 license + + +const uppercase = /([A-Z])/g; + +const hyphenate = function (str) { + return str.replace(uppercase, "-$1").toLowerCase(); +}; + +const ESCAPE_LOOKUP = { + "&": "&", + ">": ">", + "<": "<", + "\"": """, + "'": "'" +}; +const ESCAPE_REGEX = /[&><"']/g; +/** + * Escapes text to prevent scripting attacks. + */ + +function utils_escape(text) { + return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]); +} +/** + * Sometimes we want to pull out the innermost element of a group. In most + * cases, this will just be the group itself, but when ordgroups and colors have + * a single element, we want to pull that out. + */ + + +const getBaseElem = function (group) { + if (group.type === "ordgroup") { + if (group.body.length === 1) { + return getBaseElem(group.body[0]); + } else { + return group; + } + } else if (group.type === "color") { + if (group.body.length === 1) { + return getBaseElem(group.body[0]); + } else { + return group; + } + } else if (group.type === "font") { + return getBaseElem(group.body); + } else { + return group; + } +}; +/** + * TeXbook algorithms often reference "character boxes", which are simply groups + * with a single character in them. To decide if something is a character box, + * we find its innermost group, and see if it is a single character. + */ + + +const isCharacterBox = function (group) { + const baseElem = getBaseElem(group); // These are all they types of groups which hold single characters + + return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom"; +}; + +const assert = function (value) { + if (!value) { + throw new Error('Expected non-null, but got ' + String(value)); + } + + return value; +}; +/** + * Return the protocol of a URL, or "_relative" if the URL does not specify a + * protocol (and thus is relative), or `null` if URL has invalid protocol + * (so should be outright rejected). + */ + +const protocolFromUrl = function (url) { + // Check for possible leading protocol. + // https://url.spec.whatwg.org/#url-parsing strips leading whitespace + // (U+20) or C0 control (U+00-U+1F) characters. + // eslint-disable-next-line no-control-regex + const protocol = /^[\x00-\x20]*([^\\/#?]*?)(:|�*58|�*3a|&colon)/i.exec(url); + + if (!protocol) { + return "_relative"; + } // Reject weird colons + + + if (protocol[2] !== ":") { + return null; + } // Reject invalid characters in scheme according to + // https://datatracker.ietf.org/doc/html/rfc3986#section-3.1 + + + if (!/^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(protocol[1])) { + return null; + } // Lowercase the protocol + + + return protocol[1].toLowerCase(); +}; +/* harmony default export */ var utils = ({ + contains, + deflt, + escape: utils_escape, + hyphenate, + getBaseElem, + isCharacterBox, + protocolFromUrl +}); +;// CONCATENATED MODULE: ./src/Settings.js +/* eslint no-console:0 */ + +/** + * This is a module for storing settings passed into KaTeX. It correctly handles + * default settings. + */ + + + +// TODO: automatically generate documentation +// TODO: check all properties on Settings exist +// TODO: check the type of a property on Settings matches +const SETTINGS_SCHEMA = { + displayMode: { + type: "boolean", + description: "Render math in display mode, which puts the math in " + "display style (so \\int and \\sum are large, for example), and " + "centers the math on the page on its own line.", + cli: "-d, --display-mode" + }, + output: { + type: { + enum: ["htmlAndMathml", "html", "mathml"] + }, + description: "Determines the markup language of the output.", + cli: "-F, --format " + }, + leqno: { + type: "boolean", + description: "Render display math in leqno style (left-justified tags)." + }, + fleqn: { + type: "boolean", + description: "Render display math flush left." + }, + throwOnError: { + type: "boolean", + default: true, + cli: "-t, --no-throw-on-error", + cliDescription: "Render errors (in the color given by --error-color) ins" + "tead of throwing a ParseError exception when encountering an error." + }, + errorColor: { + type: "string", + default: "#cc0000", + cli: "-c, --error-color ", + cliDescription: "A color string given in the format 'rgb' or 'rrggbb' " + "(no #). This option determines the color of errors rendered by the " + "-t option.", + cliProcessor: color => "#" + color + }, + macros: { + type: "object", + cli: "-m, --macro ", + cliDescription: "Define custom macro of the form '\\foo:expansion' (use " + "multiple -m arguments for multiple macros).", + cliDefault: [], + cliProcessor: (def, defs) => { + defs.push(def); + return defs; + } + }, + minRuleThickness: { + type: "number", + description: "Specifies a minimum thickness, in ems, for fraction lines," + " `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, " + "`\\hdashline`, `\\underline`, `\\overline`, and the borders of " + "`\\fbox`, `\\boxed`, and `\\fcolorbox`.", + processor: t => Math.max(0, t), + cli: "--min-rule-thickness ", + cliProcessor: parseFloat + }, + colorIsTextColor: { + type: "boolean", + description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, " + "instead of LaTeX's one-argument \\color mode change.", + cli: "-b, --color-is-text-color" + }, + strict: { + type: [{ + enum: ["warn", "ignore", "error"] + }, "boolean", "function"], + description: "Turn on strict / LaTeX faithfulness mode, which throws an " + "error if the input uses features that are not supported by LaTeX.", + cli: "-S, --strict", + cliDefault: false + }, + trust: { + type: ["boolean", "function"], + description: "Trust the input, enabling all HTML features such as \\url.", + cli: "-T, --trust" + }, + maxSize: { + type: "number", + default: Infinity, + description: "If non-zero, all user-specified sizes, e.g. in " + "\\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, " + "elements and spaces can be arbitrarily large", + processor: s => Math.max(0, s), + cli: "-s, --max-size ", + cliProcessor: parseInt + }, + maxExpand: { + type: "number", + default: 1000, + description: "Limit the number of macro expansions to the specified " + "number, to prevent e.g. infinite macro loops. If set to Infinity, " + "the macro expander will try to fully expand as in LaTeX.", + processor: n => Math.max(0, n), + cli: "-e, --max-expand ", + cliProcessor: n => n === "Infinity" ? Infinity : parseInt(n) + }, + globalGroup: { + type: "boolean", + cli: false + } +}; + +function getDefaultValue(schema) { + if (schema.default) { + return schema.default; + } + + const type = schema.type; + const defaultType = Array.isArray(type) ? type[0] : type; + + if (typeof defaultType !== 'string') { + return defaultType.enum[0]; + } + + switch (defaultType) { + case 'boolean': + return false; + + case 'string': + return ''; + + case 'number': + return 0; + + case 'object': + return {}; + } +} +/** + * The main Settings object + * + * The current options stored are: + * - displayMode: Whether the expression should be typeset as inline math + * (false, the default), meaning that the math starts in + * \textstyle and is placed in an inline-block); or as display + * math (true), meaning that the math starts in \displaystyle + * and is placed in a block with vertical margin. + */ + + +class Settings { + constructor(options) { + this.displayMode = void 0; + this.output = void 0; + this.leqno = void 0; + this.fleqn = void 0; + this.throwOnError = void 0; + this.errorColor = void 0; + this.macros = void 0; + this.minRuleThickness = void 0; + this.colorIsTextColor = void 0; + this.strict = void 0; + this.trust = void 0; + this.maxSize = void 0; + this.maxExpand = void 0; + this.globalGroup = void 0; + // allow null options + options = options || {}; + + for (const prop in SETTINGS_SCHEMA) { + if (SETTINGS_SCHEMA.hasOwnProperty(prop)) { + // $FlowFixMe + const schema = SETTINGS_SCHEMA[prop]; // TODO: validate options + // $FlowFixMe + + this[prop] = options[prop] !== undefined ? schema.processor ? schema.processor(options[prop]) : options[prop] : getDefaultValue(schema); + } + } + } + /** + * Report nonstrict (non-LaTeX-compatible) input. + * Can safely not be called if `this.strict` is false in JavaScript. + */ + + + reportNonstrict(errorCode, errorMsg, token) { + let strict = this.strict; + + if (typeof strict === "function") { + // Allow return value of strict function to be boolean or string + // (or null/undefined, meaning no further processing). + strict = strict(errorCode, errorMsg, token); + } + + if (!strict || strict === "ignore") { + return; + } else if (strict === true || strict === "error") { + throw new src_ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + (errorMsg + " [" + errorCode + "]"), token); + } else if (strict === "warn") { + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]")); + } else { + // won't happen in type-safe code + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]")); + } + } + /** + * Check whether to apply strict (LaTeX-adhering) behavior for unusual + * input (like `\\`). Unlike `nonstrict`, will not throw an error; + * instead, "error" translates to a return value of `true`, while "ignore" + * translates to a return value of `false`. May still print a warning: + * "warn" prints a warning and returns `false`. + * This is for the second category of `errorCode`s listed in the README. + */ + + + useStrictBehavior(errorCode, errorMsg, token) { + let strict = this.strict; + + if (typeof strict === "function") { + // Allow return value of strict function to be boolean or string + // (or null/undefined, meaning no further processing). + // But catch any exceptions thrown by function, treating them + // like "error". + try { + strict = strict(errorCode, errorMsg, token); + } catch (error) { + strict = "error"; + } + } + + if (!strict || strict === "ignore") { + return false; + } else if (strict === true || strict === "error") { + return true; + } else if (strict === "warn") { + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]")); + return false; + } else { + // won't happen in type-safe code + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]")); + return false; + } + } + /** + * Check whether to test potentially dangerous input, and return + * `true` (trusted) or `false` (untrusted). The sole argument `context` + * should be an object with `command` field specifying the relevant LaTeX + * command (as a string starting with `\`), and any other arguments, etc. + * If `context` has a `url` field, a `protocol` field will automatically + * get added by this function (changing the specified object). + */ + + + isTrusted(context) { + if (context.url && !context.protocol) { + const protocol = utils.protocolFromUrl(context.url); + + if (protocol == null) { + return false; + } + + context.protocol = protocol; + } + + const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; + return Boolean(trust); + } + +} +;// CONCATENATED MODULE: ./src/Style.js +/** + * This file contains information and classes for the various kinds of styles + * used in TeX. It provides a generic `Style` class, which holds information + * about a specific style. It then provides instances of all the different kinds + * of styles possible, and provides functions to move between them and get + * information about them. + */ + +/** + * The main style class. Contains a unique id for the style, a size (which is + * the same for cramped and uncramped version of a style), and a cramped flag. + */ +class Style { + constructor(id, size, cramped) { + this.id = void 0; + this.size = void 0; + this.cramped = void 0; + this.id = id; + this.size = size; + this.cramped = cramped; + } + /** + * Get the style of a superscript given a base in the current style. + */ + + + sup() { + return styles[sup[this.id]]; + } + /** + * Get the style of a subscript given a base in the current style. + */ + + + sub() { + return styles[sub[this.id]]; + } + /** + * Get the style of a fraction numerator given the fraction in the current + * style. + */ + + + fracNum() { + return styles[fracNum[this.id]]; + } + /** + * Get the style of a fraction denominator given the fraction in the current + * style. + */ + + + fracDen() { + return styles[fracDen[this.id]]; + } + /** + * Get the cramped version of a style (in particular, cramping a cramped style + * doesn't change the style). + */ + + + cramp() { + return styles[cramp[this.id]]; + } + /** + * Get a text or display version of this style. + */ + + + text() { + return styles[Style_text[this.id]]; + } + /** + * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle) + */ + + + isTight() { + return this.size >= 2; + } + +} // Export an interface for type checking, but don't expose the implementation. +// This way, no more styles can be generated. + + +// IDs of the different styles +const D = 0; +const Dc = 1; +const T = 2; +const Tc = 3; +const S = 4; +const Sc = 5; +const SS = 6; +const SSc = 7; // Instances of the different styles + +const styles = [new Style(D, 0, false), new Style(Dc, 0, true), new Style(T, 1, false), new Style(Tc, 1, true), new Style(S, 2, false), new Style(Sc, 2, true), new Style(SS, 3, false), new Style(SSc, 3, true)]; // Lookup tables for switching from one style to another + +const sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; +const sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; +const fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; +const fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; +const cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; +const Style_text = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles. + +/* harmony default export */ var src_Style = ({ + DISPLAY: styles[D], + TEXT: styles[T], + SCRIPT: styles[S], + SCRIPTSCRIPT: styles[SS] +}); +;// CONCATENATED MODULE: ./src/unicodeScripts.js +/* + * This file defines the Unicode scripts and script families that we + * support. To add new scripts or families, just add a new entry to the + * scriptData array below. Adding scripts to the scriptData array allows + * characters from that script to appear in \text{} environments. + */ + +/** + * Each script or script family has a name and an array of blocks. + * Each block is an array of two numbers which specify the start and + * end points (inclusive) of a block of Unicode codepoints. + */ + +/** + * Unicode block data for the families of scripts we support in \text{}. + * Scripts only need to appear here if they do not have font metrics. + */ +const scriptData = [{ + // Latin characters beyond the Latin-1 characters we have metrics for. + // Needed for Czech, Hungarian and Turkish text, for example. + name: 'latin', + blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B + [0x0300, 0x036f] // Combining Diacritical marks + ] +}, { + // The Cyrillic script used by Russian and related languages. + // A Cyrillic subset used to be supported as explicitly defined + // symbols in symbols.js + name: 'cyrillic', + blocks: [[0x0400, 0x04ff]] +}, { + // Armenian + name: 'armenian', + blocks: [[0x0530, 0x058F]] +}, { + // The Brahmic scripts of South and Southeast Asia + // Devanagari (0900–097F) + // Bengali (0980–09FF) + // Gurmukhi (0A00–0A7F) + // Gujarati (0A80–0AFF) + // Oriya (0B00–0B7F) + // Tamil (0B80–0BFF) + // Telugu (0C00–0C7F) + // Kannada (0C80–0CFF) + // Malayalam (0D00–0D7F) + // Sinhala (0D80–0DFF) + // Thai (0E00–0E7F) + // Lao (0E80–0EFF) + // Tibetan (0F00–0FFF) + // Myanmar (1000–109F) + name: 'brahmic', + blocks: [[0x0900, 0x109F]] +}, { + name: 'georgian', + blocks: [[0x10A0, 0x10ff]] +}, { + // Chinese and Japanese. + // The "k" in cjk is for Korean, but we've separated Korean out + name: "cjk", + blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana + [0x4E00, 0x9FAF], // CJK ideograms + [0xFF00, 0xFF60] // Fullwidth punctuation + // TODO: add halfwidth Katakana and Romanji glyphs + ] +}, { + // Korean + name: 'hangul', + blocks: [[0xAC00, 0xD7AF]] +}]; +/** + * Given a codepoint, return the name of the script or script family + * it is from, or null if it is not part of a known block + */ + +function scriptFromCodepoint(codepoint) { + for (let i = 0; i < scriptData.length; i++) { + const script = scriptData[i]; + + for (let i = 0; i < script.blocks.length; i++) { + const block = script.blocks[i]; + + if (codepoint >= block[0] && codepoint <= block[1]) { + return script.name; + } + } + } + + return null; +} +/** + * A flattened version of all the supported blocks in a single array. + * This is an optimization to make supportedCodepoint() fast. + */ + +const allBlocks = []; +scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b))); +/** + * Given a codepoint, return true if it falls within one of the + * scripts or script families defined above and false otherwise. + * + * Micro benchmarks shows that this is faster than + * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() + * in Firefox, Chrome and Node. + */ + +function supportedCodepoint(codepoint) { + for (let i = 0; i < allBlocks.length; i += 2) { + if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { + return true; + } + } + + return false; +} +;// CONCATENATED MODULE: ./src/svgGeometry.js +/** + * This file provides support to domTree.js and delimiter.js. + * It's a storehouse of path geometry for SVG images. + */ +// In all paths below, the viewBox-to-em scale is 1000:1. +const hLinePad = 80; // padding above a sqrt vinculum. Prevents image cropping. +// The vinculum of a \sqrt can be made thicker by a KaTeX rendering option. +// Think of variable extraVinculum as two detours in the SVG path. +// The detour begins at the lower left of the area labeled extraVinculum below. +// The detour proceeds one extraVinculum distance up and slightly to the right, +// displacing the radiused corner between surd and vinculum. The radius is +// traversed as usual, then the detour resumes. It goes right, to the end of +// the very long vinculum, then down one extraVinculum distance, +// after which it resumes regular path geometry for the radical. + +/* vinculum + / + /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraVinculum + / █████████████████████←0.04em (40 unit) std vinculum thickness + / / + / / + / /\ + / / surd +*/ + +const sqrtMain = function (extraVinculum, hLinePad) { + // sqrtMain path geometry is from glyph U221A in the font KaTeX Main + return "M95," + (622 + extraVinculum + hLinePad) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + extraVinculum / 2.075 + " -" + extraVinculum + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + extraVinculum) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +const sqrtSize1 = function (extraVinculum, hLinePad) { + // size1 is from glyph U221A in the font KaTeX_Size1-Regular + return "M263," + (601 + extraVinculum + hLinePad) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + extraVinculum / 2.084 + " -" + extraVinculum + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + extraVinculum) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +const sqrtSize2 = function (extraVinculum, hLinePad) { + // size2 is from glyph U221A in the font KaTeX_Size2-Regular + return "M983 " + (10 + extraVinculum + hLinePad) + "\nl" + extraVinculum / 3.13 + " -" + extraVinculum + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + extraVinculum) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +const sqrtSize3 = function (extraVinculum, hLinePad) { + // size3 is from glyph U221A in the font KaTeX_Size3-Regular + return "M424," + (2398 + extraVinculum + hLinePad) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + extraVinculum / 4.223 + " -" + extraVinculum + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + extraVinculum) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + extraVinculum) + " " + hLinePad + "\nh400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +const sqrtSize4 = function (extraVinculum, hLinePad) { + // size4 is from glyph U221A in the font KaTeX_Size4-Regular + return "M473," + (2713 + extraVinculum + hLinePad) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + extraVinculum / 5.298 + " -" + extraVinculum + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + extraVinculum) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "H1017.7z"; +}; + +const phasePath = function (y) { + const x = y / 2; // x coordinate at top of angle + + return "M400000 " + y + " H0 L" + x + " 0 l65 45 L145 " + (y - 80) + " H400000z"; +}; + +const sqrtTall = function (extraVinculum, hLinePad, viewBoxHeight) { + // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular + // One path edge has a variable length. It runs vertically from the vinculum + // to a point near (14 units) the bottom of the surd. The vinculum + // is normally 40 units thick. So the length of the line in question is: + const vertSegment = viewBoxHeight - 54 - hLinePad - extraVinculum; + return "M702 " + (extraVinculum + hLinePad) + "H400000" + (40 + extraVinculum) + "\nH742v" + vertSegment + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + hLinePad + "H400000v" + (40 + extraVinculum) + "H742z"; +}; + +const sqrtPath = function (size, extraVinculum, viewBoxHeight) { + extraVinculum = 1000 * extraVinculum; // Convert from document ems to viewBox. + + let path = ""; + + switch (size) { + case "sqrtMain": + path = sqrtMain(extraVinculum, hLinePad); + break; + + case "sqrtSize1": + path = sqrtSize1(extraVinculum, hLinePad); + break; + + case "sqrtSize2": + path = sqrtSize2(extraVinculum, hLinePad); + break; + + case "sqrtSize3": + path = sqrtSize3(extraVinculum, hLinePad); + break; + + case "sqrtSize4": + path = sqrtSize4(extraVinculum, hLinePad); + break; + + case "sqrtTall": + path = sqrtTall(extraVinculum, hLinePad, viewBoxHeight); + } + + return path; +}; +const innerPath = function (name, height) { + // The inner part of stretchy tall delimiters + switch (name) { + case "\u239c": + return "M291 0 H417 V" + height + " H291z M291 0 H417 V" + height + " H291z"; + + case "\u2223": + return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z"; + + case "\u2225": + return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z" + ("M367 0 H410 V" + height + " H367z M367 0 H410 V" + height + " H367z"); + + case "\u239f": + return "M457 0 H583 V" + height + " H457z M457 0 H583 V" + height + " H457z"; + + case "\u23a2": + return "M319 0 H403 V" + height + " H319z M319 0 H403 V" + height + " H319z"; + + case "\u23a5": + return "M263 0 H347 V" + height + " H263z M263 0 H347 V" + height + " H263z"; + + case "\u23aa": + return "M384 0 H504 V" + height + " H384z M384 0 H504 V" + height + " H384z"; + + case "\u23d0": + return "M312 0 H355 V" + height + " H312z M312 0 H355 V" + height + " H312z"; + + case "\u2016": + return "M257 0 H300 V" + height + " H257z M257 0 H300 V" + height + " H257z" + ("M478 0 H521 V" + height + " H478z M478 0 H521 V" + height + " H478z"); + + default: + return ""; + } +}; +const path = { + // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main + doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z", + // doublerightarrow is from glyph U+21D2 in font KaTeX Main + doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z", + // leftarrow is from glyph U+2190 in font KaTeX Main + leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z", + // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular + leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z", + leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z", + // overgroup is from the MnSymbol package (public domain) + leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z", + leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z", + // Harpoons are from glyph U+21BD in font KaTeX Main + leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z", + leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z", + leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z", + leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z", + // hook is from glyph U+21A9 in font KaTeX Main + lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z", + leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z", + leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z", + // tofrom is from glyph U+21C4 in font KaTeX AMS Regular + leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z", + longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z", + midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z", + midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z", + oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z", + oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z", + oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z", + oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z", + rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z", + rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z", + rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z", + rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z", + rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z", + rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z", + rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z", + rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z", + rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z", + righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z", + rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z", + rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z", + // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular + twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z", + twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z", + // tilde1 is a modified version of a glyph from the MnSymbol package + tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z", + // ditto tilde2, tilde3, & tilde4 + tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z", + tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z", + tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z", + // vec is from glyph U+20D7 in font KaTeX Main + vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z", + // widehat1 is a modified version of a glyph from the MnSymbol package + widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z", + // ditto widehat2, widehat3, & widehat4 + widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", + widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", + widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", + // widecheck paths are all inverted versions of widehat + widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z", + widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", + widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", + widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", + // The next ten paths support reaction arrows from the mhchem package. + // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX + // baraboveleftarrow is mostly from glyph U+2190 in font KaTeX Main + baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z", + // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main + rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z", + // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end. + // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em + baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z", + rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z", + shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z", + shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z" +}; +const tallDelim = function (label, midHeight) { + switch (label) { + case "lbrack": + return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v" + midHeight + " v1759 h84z"; + + case "rbrack": + return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v" + midHeight + " v1759 h84z"; + + case "vert": + return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z"; + + case "doublevert": + return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z\nM367 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v" + midHeight + " v585 h43z"; + + case "lfloor": + return "M319 602 V0 H403 V602 v" + midHeight + " v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z"; + + case "rfloor": + return "M319 602 V0 H403 V602 v" + midHeight + " v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z"; + + case "lceil": + return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v602 h84z\nM403 1759 V0 H319 V1759 v" + midHeight + " v602 h84z"; + + case "rceil": + return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v602 h84z\nM347 1759 V0 h-84 V1759 v" + midHeight + " v602 h84z"; + + case "lparen": + return "M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0," + (midHeight + 84) + "c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-" + (midHeight + 92) + "c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"; + + case "rparen": + return "M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0," + (midHeight + 9) + "\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-" + (midHeight + 144) + "c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"; + + default: + // We should not ever get here. + throw new Error("Unknown stretchy delimiter."); + } +}; +;// CONCATENATED MODULE: ./src/tree.js + + +/** + * This node represents a document fragment, which contains elements, but when + * placed into the DOM doesn't have any representation itself. It only contains + * children and doesn't have any DOM node properties. + */ +class DocumentFragment { + // HtmlDomNode + // Never used; needed for satisfying interface. + constructor(children) { + this.children = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.maxFontSize = void 0; + this.style = void 0; + this.children = children; + this.classes = []; + this.height = 0; + this.depth = 0; + this.maxFontSize = 0; + this.style = {}; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + /** Convert the fragment into a node. */ + + + toNode() { + const frag = document.createDocumentFragment(); + + for (let i = 0; i < this.children.length; i++) { + frag.appendChild(this.children[i].toNode()); + } + + return frag; + } + /** Convert the fragment into HTML markup. */ + + + toMarkup() { + let markup = ""; // Simply concatenate the markup for the children together. + + for (let i = 0; i < this.children.length; i++) { + markup += this.children[i].toMarkup(); + } + + return markup; + } + /** + * Converts the math node into a string, similar to innerText. Applies to + * MathDomNode's only. + */ + + + toText() { + // To avoid this, we would subclass documentFragment separately for + // MathML, but polyfills for subclassing is expensive per PR 1469. + // $FlowFixMe: Only works for ChildType = MathDomNode. + const toText = child => child.toText(); + + return this.children.map(toText).join(""); + } + +} +;// CONCATENATED MODULE: ./src/fontMetricsData.js +// This file is GENERATED by buildMetrics.sh. DO NOT MODIFY. +/* harmony default export */ var fontMetricsData = ({ + "AMS-Regular": { + "32": [0, 0, 0, 0, 0.25], + "65": [0, 0.68889, 0, 0, 0.72222], + "66": [0, 0.68889, 0, 0, 0.66667], + "67": [0, 0.68889, 0, 0, 0.72222], + "68": [0, 0.68889, 0, 0, 0.72222], + "69": [0, 0.68889, 0, 0, 0.66667], + "70": [0, 0.68889, 0, 0, 0.61111], + "71": [0, 0.68889, 0, 0, 0.77778], + "72": [0, 0.68889, 0, 0, 0.77778], + "73": [0, 0.68889, 0, 0, 0.38889], + "74": [0.16667, 0.68889, 0, 0, 0.5], + "75": [0, 0.68889, 0, 0, 0.77778], + "76": [0, 0.68889, 0, 0, 0.66667], + "77": [0, 0.68889, 0, 0, 0.94445], + "78": [0, 0.68889, 0, 0, 0.72222], + "79": [0.16667, 0.68889, 0, 0, 0.77778], + "80": [0, 0.68889, 0, 0, 0.61111], + "81": [0.16667, 0.68889, 0, 0, 0.77778], + "82": [0, 0.68889, 0, 0, 0.72222], + "83": [0, 0.68889, 0, 0, 0.55556], + "84": [0, 0.68889, 0, 0, 0.66667], + "85": [0, 0.68889, 0, 0, 0.72222], + "86": [0, 0.68889, 0, 0, 0.72222], + "87": [0, 0.68889, 0, 0, 1.0], + "88": [0, 0.68889, 0, 0, 0.72222], + "89": [0, 0.68889, 0, 0, 0.72222], + "90": [0, 0.68889, 0, 0, 0.66667], + "107": [0, 0.68889, 0, 0, 0.55556], + "160": [0, 0, 0, 0, 0.25], + "165": [0, 0.675, 0.025, 0, 0.75], + "174": [0.15559, 0.69224, 0, 0, 0.94666], + "240": [0, 0.68889, 0, 0, 0.55556], + "295": [0, 0.68889, 0, 0, 0.54028], + "710": [0, 0.825, 0, 0, 2.33334], + "732": [0, 0.9, 0, 0, 2.33334], + "770": [0, 0.825, 0, 0, 2.33334], + "771": [0, 0.9, 0, 0, 2.33334], + "989": [0.08167, 0.58167, 0, 0, 0.77778], + "1008": [0, 0.43056, 0.04028, 0, 0.66667], + "8245": [0, 0.54986, 0, 0, 0.275], + "8463": [0, 0.68889, 0, 0, 0.54028], + "8487": [0, 0.68889, 0, 0, 0.72222], + "8498": [0, 0.68889, 0, 0, 0.55556], + "8502": [0, 0.68889, 0, 0, 0.66667], + "8503": [0, 0.68889, 0, 0, 0.44445], + "8504": [0, 0.68889, 0, 0, 0.66667], + "8513": [0, 0.68889, 0, 0, 0.63889], + "8592": [-0.03598, 0.46402, 0, 0, 0.5], + "8594": [-0.03598, 0.46402, 0, 0, 0.5], + "8602": [-0.13313, 0.36687, 0, 0, 1.0], + "8603": [-0.13313, 0.36687, 0, 0, 1.0], + "8606": [0.01354, 0.52239, 0, 0, 1.0], + "8608": [0.01354, 0.52239, 0, 0, 1.0], + "8610": [0.01354, 0.52239, 0, 0, 1.11111], + "8611": [0.01354, 0.52239, 0, 0, 1.11111], + "8619": [0, 0.54986, 0, 0, 1.0], + "8620": [0, 0.54986, 0, 0, 1.0], + "8621": [-0.13313, 0.37788, 0, 0, 1.38889], + "8622": [-0.13313, 0.36687, 0, 0, 1.0], + "8624": [0, 0.69224, 0, 0, 0.5], + "8625": [0, 0.69224, 0, 0, 0.5], + "8630": [0, 0.43056, 0, 0, 1.0], + "8631": [0, 0.43056, 0, 0, 1.0], + "8634": [0.08198, 0.58198, 0, 0, 0.77778], + "8635": [0.08198, 0.58198, 0, 0, 0.77778], + "8638": [0.19444, 0.69224, 0, 0, 0.41667], + "8639": [0.19444, 0.69224, 0, 0, 0.41667], + "8642": [0.19444, 0.69224, 0, 0, 0.41667], + "8643": [0.19444, 0.69224, 0, 0, 0.41667], + "8644": [0.1808, 0.675, 0, 0, 1.0], + "8646": [0.1808, 0.675, 0, 0, 1.0], + "8647": [0.1808, 0.675, 0, 0, 1.0], + "8648": [0.19444, 0.69224, 0, 0, 0.83334], + "8649": [0.1808, 0.675, 0, 0, 1.0], + "8650": [0.19444, 0.69224, 0, 0, 0.83334], + "8651": [0.01354, 0.52239, 0, 0, 1.0], + "8652": [0.01354, 0.52239, 0, 0, 1.0], + "8653": [-0.13313, 0.36687, 0, 0, 1.0], + "8654": [-0.13313, 0.36687, 0, 0, 1.0], + "8655": [-0.13313, 0.36687, 0, 0, 1.0], + "8666": [0.13667, 0.63667, 0, 0, 1.0], + "8667": [0.13667, 0.63667, 0, 0, 1.0], + "8669": [-0.13313, 0.37788, 0, 0, 1.0], + "8672": [-0.064, 0.437, 0, 0, 1.334], + "8674": [-0.064, 0.437, 0, 0, 1.334], + "8705": [0, 0.825, 0, 0, 0.5], + "8708": [0, 0.68889, 0, 0, 0.55556], + "8709": [0.08167, 0.58167, 0, 0, 0.77778], + "8717": [0, 0.43056, 0, 0, 0.42917], + "8722": [-0.03598, 0.46402, 0, 0, 0.5], + "8724": [0.08198, 0.69224, 0, 0, 0.77778], + "8726": [0.08167, 0.58167, 0, 0, 0.77778], + "8733": [0, 0.69224, 0, 0, 0.77778], + "8736": [0, 0.69224, 0, 0, 0.72222], + "8737": [0, 0.69224, 0, 0, 0.72222], + "8738": [0.03517, 0.52239, 0, 0, 0.72222], + "8739": [0.08167, 0.58167, 0, 0, 0.22222], + "8740": [0.25142, 0.74111, 0, 0, 0.27778], + "8741": [0.08167, 0.58167, 0, 0, 0.38889], + "8742": [0.25142, 0.74111, 0, 0, 0.5], + "8756": [0, 0.69224, 0, 0, 0.66667], + "8757": [0, 0.69224, 0, 0, 0.66667], + "8764": [-0.13313, 0.36687, 0, 0, 0.77778], + "8765": [-0.13313, 0.37788, 0, 0, 0.77778], + "8769": [-0.13313, 0.36687, 0, 0, 0.77778], + "8770": [-0.03625, 0.46375, 0, 0, 0.77778], + "8774": [0.30274, 0.79383, 0, 0, 0.77778], + "8776": [-0.01688, 0.48312, 0, 0, 0.77778], + "8778": [0.08167, 0.58167, 0, 0, 0.77778], + "8782": [0.06062, 0.54986, 0, 0, 0.77778], + "8783": [0.06062, 0.54986, 0, 0, 0.77778], + "8785": [0.08198, 0.58198, 0, 0, 0.77778], + "8786": [0.08198, 0.58198, 0, 0, 0.77778], + "8787": [0.08198, 0.58198, 0, 0, 0.77778], + "8790": [0, 0.69224, 0, 0, 0.77778], + "8791": [0.22958, 0.72958, 0, 0, 0.77778], + "8796": [0.08198, 0.91667, 0, 0, 0.77778], + "8806": [0.25583, 0.75583, 0, 0, 0.77778], + "8807": [0.25583, 0.75583, 0, 0, 0.77778], + "8808": [0.25142, 0.75726, 0, 0, 0.77778], + "8809": [0.25142, 0.75726, 0, 0, 0.77778], + "8812": [0.25583, 0.75583, 0, 0, 0.5], + "8814": [0.20576, 0.70576, 0, 0, 0.77778], + "8815": [0.20576, 0.70576, 0, 0, 0.77778], + "8816": [0.30274, 0.79383, 0, 0, 0.77778], + "8817": [0.30274, 0.79383, 0, 0, 0.77778], + "8818": [0.22958, 0.72958, 0, 0, 0.77778], + "8819": [0.22958, 0.72958, 0, 0, 0.77778], + "8822": [0.1808, 0.675, 0, 0, 0.77778], + "8823": [0.1808, 0.675, 0, 0, 0.77778], + "8828": [0.13667, 0.63667, 0, 0, 0.77778], + "8829": [0.13667, 0.63667, 0, 0, 0.77778], + "8830": [0.22958, 0.72958, 0, 0, 0.77778], + "8831": [0.22958, 0.72958, 0, 0, 0.77778], + "8832": [0.20576, 0.70576, 0, 0, 0.77778], + "8833": [0.20576, 0.70576, 0, 0, 0.77778], + "8840": [0.30274, 0.79383, 0, 0, 0.77778], + "8841": [0.30274, 0.79383, 0, 0, 0.77778], + "8842": [0.13597, 0.63597, 0, 0, 0.77778], + "8843": [0.13597, 0.63597, 0, 0, 0.77778], + "8847": [0.03517, 0.54986, 0, 0, 0.77778], + "8848": [0.03517, 0.54986, 0, 0, 0.77778], + "8858": [0.08198, 0.58198, 0, 0, 0.77778], + "8859": [0.08198, 0.58198, 0, 0, 0.77778], + "8861": [0.08198, 0.58198, 0, 0, 0.77778], + "8862": [0, 0.675, 0, 0, 0.77778], + "8863": [0, 0.675, 0, 0, 0.77778], + "8864": [0, 0.675, 0, 0, 0.77778], + "8865": [0, 0.675, 0, 0, 0.77778], + "8872": [0, 0.69224, 0, 0, 0.61111], + "8873": [0, 0.69224, 0, 0, 0.72222], + "8874": [0, 0.69224, 0, 0, 0.88889], + "8876": [0, 0.68889, 0, 0, 0.61111], + "8877": [0, 0.68889, 0, 0, 0.61111], + "8878": [0, 0.68889, 0, 0, 0.72222], + "8879": [0, 0.68889, 0, 0, 0.72222], + "8882": [0.03517, 0.54986, 0, 0, 0.77778], + "8883": [0.03517, 0.54986, 0, 0, 0.77778], + "8884": [0.13667, 0.63667, 0, 0, 0.77778], + "8885": [0.13667, 0.63667, 0, 0, 0.77778], + "8888": [0, 0.54986, 0, 0, 1.11111], + "8890": [0.19444, 0.43056, 0, 0, 0.55556], + "8891": [0.19444, 0.69224, 0, 0, 0.61111], + "8892": [0.19444, 0.69224, 0, 0, 0.61111], + "8901": [0, 0.54986, 0, 0, 0.27778], + "8903": [0.08167, 0.58167, 0, 0, 0.77778], + "8905": [0.08167, 0.58167, 0, 0, 0.77778], + "8906": [0.08167, 0.58167, 0, 0, 0.77778], + "8907": [0, 0.69224, 0, 0, 0.77778], + "8908": [0, 0.69224, 0, 0, 0.77778], + "8909": [-0.03598, 0.46402, 0, 0, 0.77778], + "8910": [0, 0.54986, 0, 0, 0.76042], + "8911": [0, 0.54986, 0, 0, 0.76042], + "8912": [0.03517, 0.54986, 0, 0, 0.77778], + "8913": [0.03517, 0.54986, 0, 0, 0.77778], + "8914": [0, 0.54986, 0, 0, 0.66667], + "8915": [0, 0.54986, 0, 0, 0.66667], + "8916": [0, 0.69224, 0, 0, 0.66667], + "8918": [0.0391, 0.5391, 0, 0, 0.77778], + "8919": [0.0391, 0.5391, 0, 0, 0.77778], + "8920": [0.03517, 0.54986, 0, 0, 1.33334], + "8921": [0.03517, 0.54986, 0, 0, 1.33334], + "8922": [0.38569, 0.88569, 0, 0, 0.77778], + "8923": [0.38569, 0.88569, 0, 0, 0.77778], + "8926": [0.13667, 0.63667, 0, 0, 0.77778], + "8927": [0.13667, 0.63667, 0, 0, 0.77778], + "8928": [0.30274, 0.79383, 0, 0, 0.77778], + "8929": [0.30274, 0.79383, 0, 0, 0.77778], + "8934": [0.23222, 0.74111, 0, 0, 0.77778], + "8935": [0.23222, 0.74111, 0, 0, 0.77778], + "8936": [0.23222, 0.74111, 0, 0, 0.77778], + "8937": [0.23222, 0.74111, 0, 0, 0.77778], + "8938": [0.20576, 0.70576, 0, 0, 0.77778], + "8939": [0.20576, 0.70576, 0, 0, 0.77778], + "8940": [0.30274, 0.79383, 0, 0, 0.77778], + "8941": [0.30274, 0.79383, 0, 0, 0.77778], + "8994": [0.19444, 0.69224, 0, 0, 0.77778], + "8995": [0.19444, 0.69224, 0, 0, 0.77778], + "9416": [0.15559, 0.69224, 0, 0, 0.90222], + "9484": [0, 0.69224, 0, 0, 0.5], + "9488": [0, 0.69224, 0, 0, 0.5], + "9492": [0, 0.37788, 0, 0, 0.5], + "9496": [0, 0.37788, 0, 0, 0.5], + "9585": [0.19444, 0.68889, 0, 0, 0.88889], + "9586": [0.19444, 0.74111, 0, 0, 0.88889], + "9632": [0, 0.675, 0, 0, 0.77778], + "9633": [0, 0.675, 0, 0, 0.77778], + "9650": [0, 0.54986, 0, 0, 0.72222], + "9651": [0, 0.54986, 0, 0, 0.72222], + "9654": [0.03517, 0.54986, 0, 0, 0.77778], + "9660": [0, 0.54986, 0, 0, 0.72222], + "9661": [0, 0.54986, 0, 0, 0.72222], + "9664": [0.03517, 0.54986, 0, 0, 0.77778], + "9674": [0.11111, 0.69224, 0, 0, 0.66667], + "9733": [0.19444, 0.69224, 0, 0, 0.94445], + "10003": [0, 0.69224, 0, 0, 0.83334], + "10016": [0, 0.69224, 0, 0, 0.83334], + "10731": [0.11111, 0.69224, 0, 0, 0.66667], + "10846": [0.19444, 0.75583, 0, 0, 0.61111], + "10877": [0.13667, 0.63667, 0, 0, 0.77778], + "10878": [0.13667, 0.63667, 0, 0, 0.77778], + "10885": [0.25583, 0.75583, 0, 0, 0.77778], + "10886": [0.25583, 0.75583, 0, 0, 0.77778], + "10887": [0.13597, 0.63597, 0, 0, 0.77778], + "10888": [0.13597, 0.63597, 0, 0, 0.77778], + "10889": [0.26167, 0.75726, 0, 0, 0.77778], + "10890": [0.26167, 0.75726, 0, 0, 0.77778], + "10891": [0.48256, 0.98256, 0, 0, 0.77778], + "10892": [0.48256, 0.98256, 0, 0, 0.77778], + "10901": [0.13667, 0.63667, 0, 0, 0.77778], + "10902": [0.13667, 0.63667, 0, 0, 0.77778], + "10933": [0.25142, 0.75726, 0, 0, 0.77778], + "10934": [0.25142, 0.75726, 0, 0, 0.77778], + "10935": [0.26167, 0.75726, 0, 0, 0.77778], + "10936": [0.26167, 0.75726, 0, 0, 0.77778], + "10937": [0.26167, 0.75726, 0, 0, 0.77778], + "10938": [0.26167, 0.75726, 0, 0, 0.77778], + "10949": [0.25583, 0.75583, 0, 0, 0.77778], + "10950": [0.25583, 0.75583, 0, 0, 0.77778], + "10955": [0.28481, 0.79383, 0, 0, 0.77778], + "10956": [0.28481, 0.79383, 0, 0, 0.77778], + "57350": [0.08167, 0.58167, 0, 0, 0.22222], + "57351": [0.08167, 0.58167, 0, 0, 0.38889], + "57352": [0.08167, 0.58167, 0, 0, 0.77778], + "57353": [0, 0.43056, 0.04028, 0, 0.66667], + "57356": [0.25142, 0.75726, 0, 0, 0.77778], + "57357": [0.25142, 0.75726, 0, 0, 0.77778], + "57358": [0.41951, 0.91951, 0, 0, 0.77778], + "57359": [0.30274, 0.79383, 0, 0, 0.77778], + "57360": [0.30274, 0.79383, 0, 0, 0.77778], + "57361": [0.41951, 0.91951, 0, 0, 0.77778], + "57366": [0.25142, 0.75726, 0, 0, 0.77778], + "57367": [0.25142, 0.75726, 0, 0, 0.77778], + "57368": [0.25142, 0.75726, 0, 0, 0.77778], + "57369": [0.25142, 0.75726, 0, 0, 0.77778], + "57370": [0.13597, 0.63597, 0, 0, 0.77778], + "57371": [0.13597, 0.63597, 0, 0, 0.77778] + }, + "Caligraphic-Regular": { + "32": [0, 0, 0, 0, 0.25], + "65": [0, 0.68333, 0, 0.19445, 0.79847], + "66": [0, 0.68333, 0.03041, 0.13889, 0.65681], + "67": [0, 0.68333, 0.05834, 0.13889, 0.52653], + "68": [0, 0.68333, 0.02778, 0.08334, 0.77139], + "69": [0, 0.68333, 0.08944, 0.11111, 0.52778], + "70": [0, 0.68333, 0.09931, 0.11111, 0.71875], + "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487], + "72": [0, 0.68333, 0.00965, 0.11111, 0.84452], + "73": [0, 0.68333, 0.07382, 0, 0.54452], + "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778], + "75": [0, 0.68333, 0.01445, 0.05556, 0.76195], + "76": [0, 0.68333, 0, 0.13889, 0.68972], + "77": [0, 0.68333, 0, 0.13889, 1.2009], + "78": [0, 0.68333, 0.14736, 0.08334, 0.82049], + "79": [0, 0.68333, 0.02778, 0.11111, 0.79611], + "80": [0, 0.68333, 0.08222, 0.08334, 0.69556], + "81": [0.09722, 0.68333, 0, 0.11111, 0.81667], + "82": [0, 0.68333, 0, 0.08334, 0.8475], + "83": [0, 0.68333, 0.075, 0.13889, 0.60556], + "84": [0, 0.68333, 0.25417, 0, 0.54464], + "85": [0, 0.68333, 0.09931, 0.08334, 0.62583], + "86": [0, 0.68333, 0.08222, 0, 0.61278], + "87": [0, 0.68333, 0.08222, 0.08334, 0.98778], + "88": [0, 0.68333, 0.14643, 0.13889, 0.7133], + "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834], + "90": [0, 0.68333, 0.07944, 0.13889, 0.72473], + "160": [0, 0, 0, 0, 0.25] + }, + "Fraktur-Regular": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69141, 0, 0, 0.29574], + "34": [0, 0.69141, 0, 0, 0.21471], + "38": [0, 0.69141, 0, 0, 0.73786], + "39": [0, 0.69141, 0, 0, 0.21201], + "40": [0.24982, 0.74947, 0, 0, 0.38865], + "41": [0.24982, 0.74947, 0, 0, 0.38865], + "42": [0, 0.62119, 0, 0, 0.27764], + "43": [0.08319, 0.58283, 0, 0, 0.75623], + "44": [0, 0.10803, 0, 0, 0.27764], + "45": [0.08319, 0.58283, 0, 0, 0.75623], + "46": [0, 0.10803, 0, 0, 0.27764], + "47": [0.24982, 0.74947, 0, 0, 0.50181], + "48": [0, 0.47534, 0, 0, 0.50181], + "49": [0, 0.47534, 0, 0, 0.50181], + "50": [0, 0.47534, 0, 0, 0.50181], + "51": [0.18906, 0.47534, 0, 0, 0.50181], + "52": [0.18906, 0.47534, 0, 0, 0.50181], + "53": [0.18906, 0.47534, 0, 0, 0.50181], + "54": [0, 0.69141, 0, 0, 0.50181], + "55": [0.18906, 0.47534, 0, 0, 0.50181], + "56": [0, 0.69141, 0, 0, 0.50181], + "57": [0.18906, 0.47534, 0, 0, 0.50181], + "58": [0, 0.47534, 0, 0, 0.21606], + "59": [0.12604, 0.47534, 0, 0, 0.21606], + "61": [-0.13099, 0.36866, 0, 0, 0.75623], + "63": [0, 0.69141, 0, 0, 0.36245], + "65": [0, 0.69141, 0, 0, 0.7176], + "66": [0, 0.69141, 0, 0, 0.88397], + "67": [0, 0.69141, 0, 0, 0.61254], + "68": [0, 0.69141, 0, 0, 0.83158], + "69": [0, 0.69141, 0, 0, 0.66278], + "70": [0.12604, 0.69141, 0, 0, 0.61119], + "71": [0, 0.69141, 0, 0, 0.78539], + "72": [0.06302, 0.69141, 0, 0, 0.7203], + "73": [0, 0.69141, 0, 0, 0.55448], + "74": [0.12604, 0.69141, 0, 0, 0.55231], + "75": [0, 0.69141, 0, 0, 0.66845], + "76": [0, 0.69141, 0, 0, 0.66602], + "77": [0, 0.69141, 0, 0, 1.04953], + "78": [0, 0.69141, 0, 0, 0.83212], + "79": [0, 0.69141, 0, 0, 0.82699], + "80": [0.18906, 0.69141, 0, 0, 0.82753], + "81": [0.03781, 0.69141, 0, 0, 0.82699], + "82": [0, 0.69141, 0, 0, 0.82807], + "83": [0, 0.69141, 0, 0, 0.82861], + "84": [0, 0.69141, 0, 0, 0.66899], + "85": [0, 0.69141, 0, 0, 0.64576], + "86": [0, 0.69141, 0, 0, 0.83131], + "87": [0, 0.69141, 0, 0, 1.04602], + "88": [0, 0.69141, 0, 0, 0.71922], + "89": [0.18906, 0.69141, 0, 0, 0.83293], + "90": [0.12604, 0.69141, 0, 0, 0.60201], + "91": [0.24982, 0.74947, 0, 0, 0.27764], + "93": [0.24982, 0.74947, 0, 0, 0.27764], + "94": [0, 0.69141, 0, 0, 0.49965], + "97": [0, 0.47534, 0, 0, 0.50046], + "98": [0, 0.69141, 0, 0, 0.51315], + "99": [0, 0.47534, 0, 0, 0.38946], + "100": [0, 0.62119, 0, 0, 0.49857], + "101": [0, 0.47534, 0, 0, 0.40053], + "102": [0.18906, 0.69141, 0, 0, 0.32626], + "103": [0.18906, 0.47534, 0, 0, 0.5037], + "104": [0.18906, 0.69141, 0, 0, 0.52126], + "105": [0, 0.69141, 0, 0, 0.27899], + "106": [0, 0.69141, 0, 0, 0.28088], + "107": [0, 0.69141, 0, 0, 0.38946], + "108": [0, 0.69141, 0, 0, 0.27953], + "109": [0, 0.47534, 0, 0, 0.76676], + "110": [0, 0.47534, 0, 0, 0.52666], + "111": [0, 0.47534, 0, 0, 0.48885], + "112": [0.18906, 0.52396, 0, 0, 0.50046], + "113": [0.18906, 0.47534, 0, 0, 0.48912], + "114": [0, 0.47534, 0, 0, 0.38919], + "115": [0, 0.47534, 0, 0, 0.44266], + "116": [0, 0.62119, 0, 0, 0.33301], + "117": [0, 0.47534, 0, 0, 0.5172], + "118": [0, 0.52396, 0, 0, 0.5118], + "119": [0, 0.52396, 0, 0, 0.77351], + "120": [0.18906, 0.47534, 0, 0, 0.38865], + "121": [0.18906, 0.47534, 0, 0, 0.49884], + "122": [0.18906, 0.47534, 0, 0, 0.39054], + "160": [0, 0, 0, 0, 0.25], + "8216": [0, 0.69141, 0, 0, 0.21471], + "8217": [0, 0.69141, 0, 0, 0.21471], + "58112": [0, 0.62119, 0, 0, 0.49749], + "58113": [0, 0.62119, 0, 0, 0.4983], + "58114": [0.18906, 0.69141, 0, 0, 0.33328], + "58115": [0.18906, 0.69141, 0, 0, 0.32923], + "58116": [0.18906, 0.47534, 0, 0, 0.50343], + "58117": [0, 0.69141, 0, 0, 0.33301], + "58118": [0, 0.62119, 0, 0, 0.33409], + "58119": [0, 0.47534, 0, 0, 0.50073] + }, + "Main-Bold": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.35], + "34": [0, 0.69444, 0, 0, 0.60278], + "35": [0.19444, 0.69444, 0, 0, 0.95833], + "36": [0.05556, 0.75, 0, 0, 0.575], + "37": [0.05556, 0.75, 0, 0, 0.95833], + "38": [0, 0.69444, 0, 0, 0.89444], + "39": [0, 0.69444, 0, 0, 0.31944], + "40": [0.25, 0.75, 0, 0, 0.44722], + "41": [0.25, 0.75, 0, 0, 0.44722], + "42": [0, 0.75, 0, 0, 0.575], + "43": [0.13333, 0.63333, 0, 0, 0.89444], + "44": [0.19444, 0.15556, 0, 0, 0.31944], + "45": [0, 0.44444, 0, 0, 0.38333], + "46": [0, 0.15556, 0, 0, 0.31944], + "47": [0.25, 0.75, 0, 0, 0.575], + "48": [0, 0.64444, 0, 0, 0.575], + "49": [0, 0.64444, 0, 0, 0.575], + "50": [0, 0.64444, 0, 0, 0.575], + "51": [0, 0.64444, 0, 0, 0.575], + "52": [0, 0.64444, 0, 0, 0.575], + "53": [0, 0.64444, 0, 0, 0.575], + "54": [0, 0.64444, 0, 0, 0.575], + "55": [0, 0.64444, 0, 0, 0.575], + "56": [0, 0.64444, 0, 0, 0.575], + "57": [0, 0.64444, 0, 0, 0.575], + "58": [0, 0.44444, 0, 0, 0.31944], + "59": [0.19444, 0.44444, 0, 0, 0.31944], + "60": [0.08556, 0.58556, 0, 0, 0.89444], + "61": [-0.10889, 0.39111, 0, 0, 0.89444], + "62": [0.08556, 0.58556, 0, 0, 0.89444], + "63": [0, 0.69444, 0, 0, 0.54305], + "64": [0, 0.69444, 0, 0, 0.89444], + "65": [0, 0.68611, 0, 0, 0.86944], + "66": [0, 0.68611, 0, 0, 0.81805], + "67": [0, 0.68611, 0, 0, 0.83055], + "68": [0, 0.68611, 0, 0, 0.88194], + "69": [0, 0.68611, 0, 0, 0.75555], + "70": [0, 0.68611, 0, 0, 0.72361], + "71": [0, 0.68611, 0, 0, 0.90416], + "72": [0, 0.68611, 0, 0, 0.9], + "73": [0, 0.68611, 0, 0, 0.43611], + "74": [0, 0.68611, 0, 0, 0.59444], + "75": [0, 0.68611, 0, 0, 0.90138], + "76": [0, 0.68611, 0, 0, 0.69166], + "77": [0, 0.68611, 0, 0, 1.09166], + "78": [0, 0.68611, 0, 0, 0.9], + "79": [0, 0.68611, 0, 0, 0.86388], + "80": [0, 0.68611, 0, 0, 0.78611], + "81": [0.19444, 0.68611, 0, 0, 0.86388], + "82": [0, 0.68611, 0, 0, 0.8625], + "83": [0, 0.68611, 0, 0, 0.63889], + "84": [0, 0.68611, 0, 0, 0.8], + "85": [0, 0.68611, 0, 0, 0.88472], + "86": [0, 0.68611, 0.01597, 0, 0.86944], + "87": [0, 0.68611, 0.01597, 0, 1.18888], + "88": [0, 0.68611, 0, 0, 0.86944], + "89": [0, 0.68611, 0.02875, 0, 0.86944], + "90": [0, 0.68611, 0, 0, 0.70277], + "91": [0.25, 0.75, 0, 0, 0.31944], + "92": [0.25, 0.75, 0, 0, 0.575], + "93": [0.25, 0.75, 0, 0, 0.31944], + "94": [0, 0.69444, 0, 0, 0.575], + "95": [0.31, 0.13444, 0.03194, 0, 0.575], + "97": [0, 0.44444, 0, 0, 0.55902], + "98": [0, 0.69444, 0, 0, 0.63889], + "99": [0, 0.44444, 0, 0, 0.51111], + "100": [0, 0.69444, 0, 0, 0.63889], + "101": [0, 0.44444, 0, 0, 0.52708], + "102": [0, 0.69444, 0.10903, 0, 0.35139], + "103": [0.19444, 0.44444, 0.01597, 0, 0.575], + "104": [0, 0.69444, 0, 0, 0.63889], + "105": [0, 0.69444, 0, 0, 0.31944], + "106": [0.19444, 0.69444, 0, 0, 0.35139], + "107": [0, 0.69444, 0, 0, 0.60694], + "108": [0, 0.69444, 0, 0, 0.31944], + "109": [0, 0.44444, 0, 0, 0.95833], + "110": [0, 0.44444, 0, 0, 0.63889], + "111": [0, 0.44444, 0, 0, 0.575], + "112": [0.19444, 0.44444, 0, 0, 0.63889], + "113": [0.19444, 0.44444, 0, 0, 0.60694], + "114": [0, 0.44444, 0, 0, 0.47361], + "115": [0, 0.44444, 0, 0, 0.45361], + "116": [0, 0.63492, 0, 0, 0.44722], + "117": [0, 0.44444, 0, 0, 0.63889], + "118": [0, 0.44444, 0.01597, 0, 0.60694], + "119": [0, 0.44444, 0.01597, 0, 0.83055], + "120": [0, 0.44444, 0, 0, 0.60694], + "121": [0.19444, 0.44444, 0.01597, 0, 0.60694], + "122": [0, 0.44444, 0, 0, 0.51111], + "123": [0.25, 0.75, 0, 0, 0.575], + "124": [0.25, 0.75, 0, 0, 0.31944], + "125": [0.25, 0.75, 0, 0, 0.575], + "126": [0.35, 0.34444, 0, 0, 0.575], + "160": [0, 0, 0, 0, 0.25], + "163": [0, 0.69444, 0, 0, 0.86853], + "168": [0, 0.69444, 0, 0, 0.575], + "172": [0, 0.44444, 0, 0, 0.76666], + "176": [0, 0.69444, 0, 0, 0.86944], + "177": [0.13333, 0.63333, 0, 0, 0.89444], + "184": [0.17014, 0, 0, 0, 0.51111], + "198": [0, 0.68611, 0, 0, 1.04166], + "215": [0.13333, 0.63333, 0, 0, 0.89444], + "216": [0.04861, 0.73472, 0, 0, 0.89444], + "223": [0, 0.69444, 0, 0, 0.59722], + "230": [0, 0.44444, 0, 0, 0.83055], + "247": [0.13333, 0.63333, 0, 0, 0.89444], + "248": [0.09722, 0.54167, 0, 0, 0.575], + "305": [0, 0.44444, 0, 0, 0.31944], + "338": [0, 0.68611, 0, 0, 1.16944], + "339": [0, 0.44444, 0, 0, 0.89444], + "567": [0.19444, 0.44444, 0, 0, 0.35139], + "710": [0, 0.69444, 0, 0, 0.575], + "711": [0, 0.63194, 0, 0, 0.575], + "713": [0, 0.59611, 0, 0, 0.575], + "714": [0, 0.69444, 0, 0, 0.575], + "715": [0, 0.69444, 0, 0, 0.575], + "728": [0, 0.69444, 0, 0, 0.575], + "729": [0, 0.69444, 0, 0, 0.31944], + "730": [0, 0.69444, 0, 0, 0.86944], + "732": [0, 0.69444, 0, 0, 0.575], + "733": [0, 0.69444, 0, 0, 0.575], + "915": [0, 0.68611, 0, 0, 0.69166], + "916": [0, 0.68611, 0, 0, 0.95833], + "920": [0, 0.68611, 0, 0, 0.89444], + "923": [0, 0.68611, 0, 0, 0.80555], + "926": [0, 0.68611, 0, 0, 0.76666], + "928": [0, 0.68611, 0, 0, 0.9], + "931": [0, 0.68611, 0, 0, 0.83055], + "933": [0, 0.68611, 0, 0, 0.89444], + "934": [0, 0.68611, 0, 0, 0.83055], + "936": [0, 0.68611, 0, 0, 0.89444], + "937": [0, 0.68611, 0, 0, 0.83055], + "8211": [0, 0.44444, 0.03194, 0, 0.575], + "8212": [0, 0.44444, 0.03194, 0, 1.14999], + "8216": [0, 0.69444, 0, 0, 0.31944], + "8217": [0, 0.69444, 0, 0, 0.31944], + "8220": [0, 0.69444, 0, 0, 0.60278], + "8221": [0, 0.69444, 0, 0, 0.60278], + "8224": [0.19444, 0.69444, 0, 0, 0.51111], + "8225": [0.19444, 0.69444, 0, 0, 0.51111], + "8242": [0, 0.55556, 0, 0, 0.34444], + "8407": [0, 0.72444, 0.15486, 0, 0.575], + "8463": [0, 0.69444, 0, 0, 0.66759], + "8465": [0, 0.69444, 0, 0, 0.83055], + "8467": [0, 0.69444, 0, 0, 0.47361], + "8472": [0.19444, 0.44444, 0, 0, 0.74027], + "8476": [0, 0.69444, 0, 0, 0.83055], + "8501": [0, 0.69444, 0, 0, 0.70277], + "8592": [-0.10889, 0.39111, 0, 0, 1.14999], + "8593": [0.19444, 0.69444, 0, 0, 0.575], + "8594": [-0.10889, 0.39111, 0, 0, 1.14999], + "8595": [0.19444, 0.69444, 0, 0, 0.575], + "8596": [-0.10889, 0.39111, 0, 0, 1.14999], + "8597": [0.25, 0.75, 0, 0, 0.575], + "8598": [0.19444, 0.69444, 0, 0, 1.14999], + "8599": [0.19444, 0.69444, 0, 0, 1.14999], + "8600": [0.19444, 0.69444, 0, 0, 1.14999], + "8601": [0.19444, 0.69444, 0, 0, 1.14999], + "8636": [-0.10889, 0.39111, 0, 0, 1.14999], + "8637": [-0.10889, 0.39111, 0, 0, 1.14999], + "8640": [-0.10889, 0.39111, 0, 0, 1.14999], + "8641": [-0.10889, 0.39111, 0, 0, 1.14999], + "8656": [-0.10889, 0.39111, 0, 0, 1.14999], + "8657": [0.19444, 0.69444, 0, 0, 0.70277], + "8658": [-0.10889, 0.39111, 0, 0, 1.14999], + "8659": [0.19444, 0.69444, 0, 0, 0.70277], + "8660": [-0.10889, 0.39111, 0, 0, 1.14999], + "8661": [0.25, 0.75, 0, 0, 0.70277], + "8704": [0, 0.69444, 0, 0, 0.63889], + "8706": [0, 0.69444, 0.06389, 0, 0.62847], + "8707": [0, 0.69444, 0, 0, 0.63889], + "8709": [0.05556, 0.75, 0, 0, 0.575], + "8711": [0, 0.68611, 0, 0, 0.95833], + "8712": [0.08556, 0.58556, 0, 0, 0.76666], + "8715": [0.08556, 0.58556, 0, 0, 0.76666], + "8722": [0.13333, 0.63333, 0, 0, 0.89444], + "8723": [0.13333, 0.63333, 0, 0, 0.89444], + "8725": [0.25, 0.75, 0, 0, 0.575], + "8726": [0.25, 0.75, 0, 0, 0.575], + "8727": [-0.02778, 0.47222, 0, 0, 0.575], + "8728": [-0.02639, 0.47361, 0, 0, 0.575], + "8729": [-0.02639, 0.47361, 0, 0, 0.575], + "8730": [0.18, 0.82, 0, 0, 0.95833], + "8733": [0, 0.44444, 0, 0, 0.89444], + "8734": [0, 0.44444, 0, 0, 1.14999], + "8736": [0, 0.69224, 0, 0, 0.72222], + "8739": [0.25, 0.75, 0, 0, 0.31944], + "8741": [0.25, 0.75, 0, 0, 0.575], + "8743": [0, 0.55556, 0, 0, 0.76666], + "8744": [0, 0.55556, 0, 0, 0.76666], + "8745": [0, 0.55556, 0, 0, 0.76666], + "8746": [0, 0.55556, 0, 0, 0.76666], + "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875], + "8764": [-0.10889, 0.39111, 0, 0, 0.89444], + "8768": [0.19444, 0.69444, 0, 0, 0.31944], + "8771": [0.00222, 0.50222, 0, 0, 0.89444], + "8773": [0.027, 0.638, 0, 0, 0.894], + "8776": [0.02444, 0.52444, 0, 0, 0.89444], + "8781": [0.00222, 0.50222, 0, 0, 0.89444], + "8801": [0.00222, 0.50222, 0, 0, 0.89444], + "8804": [0.19667, 0.69667, 0, 0, 0.89444], + "8805": [0.19667, 0.69667, 0, 0, 0.89444], + "8810": [0.08556, 0.58556, 0, 0, 1.14999], + "8811": [0.08556, 0.58556, 0, 0, 1.14999], + "8826": [0.08556, 0.58556, 0, 0, 0.89444], + "8827": [0.08556, 0.58556, 0, 0, 0.89444], + "8834": [0.08556, 0.58556, 0, 0, 0.89444], + "8835": [0.08556, 0.58556, 0, 0, 0.89444], + "8838": [0.19667, 0.69667, 0, 0, 0.89444], + "8839": [0.19667, 0.69667, 0, 0, 0.89444], + "8846": [0, 0.55556, 0, 0, 0.76666], + "8849": [0.19667, 0.69667, 0, 0, 0.89444], + "8850": [0.19667, 0.69667, 0, 0, 0.89444], + "8851": [0, 0.55556, 0, 0, 0.76666], + "8852": [0, 0.55556, 0, 0, 0.76666], + "8853": [0.13333, 0.63333, 0, 0, 0.89444], + "8854": [0.13333, 0.63333, 0, 0, 0.89444], + "8855": [0.13333, 0.63333, 0, 0, 0.89444], + "8856": [0.13333, 0.63333, 0, 0, 0.89444], + "8857": [0.13333, 0.63333, 0, 0, 0.89444], + "8866": [0, 0.69444, 0, 0, 0.70277], + "8867": [0, 0.69444, 0, 0, 0.70277], + "8868": [0, 0.69444, 0, 0, 0.89444], + "8869": [0, 0.69444, 0, 0, 0.89444], + "8900": [-0.02639, 0.47361, 0, 0, 0.575], + "8901": [-0.02639, 0.47361, 0, 0, 0.31944], + "8902": [-0.02778, 0.47222, 0, 0, 0.575], + "8968": [0.25, 0.75, 0, 0, 0.51111], + "8969": [0.25, 0.75, 0, 0, 0.51111], + "8970": [0.25, 0.75, 0, 0, 0.51111], + "8971": [0.25, 0.75, 0, 0, 0.51111], + "8994": [-0.13889, 0.36111, 0, 0, 1.14999], + "8995": [-0.13889, 0.36111, 0, 0, 1.14999], + "9651": [0.19444, 0.69444, 0, 0, 1.02222], + "9657": [-0.02778, 0.47222, 0, 0, 0.575], + "9661": [0.19444, 0.69444, 0, 0, 1.02222], + "9667": [-0.02778, 0.47222, 0, 0, 0.575], + "9711": [0.19444, 0.69444, 0, 0, 1.14999], + "9824": [0.12963, 0.69444, 0, 0, 0.89444], + "9825": [0.12963, 0.69444, 0, 0, 0.89444], + "9826": [0.12963, 0.69444, 0, 0, 0.89444], + "9827": [0.12963, 0.69444, 0, 0, 0.89444], + "9837": [0, 0.75, 0, 0, 0.44722], + "9838": [0.19444, 0.69444, 0, 0, 0.44722], + "9839": [0.19444, 0.69444, 0, 0, 0.44722], + "10216": [0.25, 0.75, 0, 0, 0.44722], + "10217": [0.25, 0.75, 0, 0, 0.44722], + "10815": [0, 0.68611, 0, 0, 0.9], + "10927": [0.19667, 0.69667, 0, 0, 0.89444], + "10928": [0.19667, 0.69667, 0, 0, 0.89444], + "57376": [0.19444, 0.69444, 0, 0, 0] + }, + "Main-BoldItalic": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0.11417, 0, 0.38611], + "34": [0, 0.69444, 0.07939, 0, 0.62055], + "35": [0.19444, 0.69444, 0.06833, 0, 0.94444], + "37": [0.05556, 0.75, 0.12861, 0, 0.94444], + "38": [0, 0.69444, 0.08528, 0, 0.88555], + "39": [0, 0.69444, 0.12945, 0, 0.35555], + "40": [0.25, 0.75, 0.15806, 0, 0.47333], + "41": [0.25, 0.75, 0.03306, 0, 0.47333], + "42": [0, 0.75, 0.14333, 0, 0.59111], + "43": [0.10333, 0.60333, 0.03306, 0, 0.88555], + "44": [0.19444, 0.14722, 0, 0, 0.35555], + "45": [0, 0.44444, 0.02611, 0, 0.41444], + "46": [0, 0.14722, 0, 0, 0.35555], + "47": [0.25, 0.75, 0.15806, 0, 0.59111], + "48": [0, 0.64444, 0.13167, 0, 0.59111], + "49": [0, 0.64444, 0.13167, 0, 0.59111], + "50": [0, 0.64444, 0.13167, 0, 0.59111], + "51": [0, 0.64444, 0.13167, 0, 0.59111], + "52": [0.19444, 0.64444, 0.13167, 0, 0.59111], + "53": [0, 0.64444, 0.13167, 0, 0.59111], + "54": [0, 0.64444, 0.13167, 0, 0.59111], + "55": [0.19444, 0.64444, 0.13167, 0, 0.59111], + "56": [0, 0.64444, 0.13167, 0, 0.59111], + "57": [0, 0.64444, 0.13167, 0, 0.59111], + "58": [0, 0.44444, 0.06695, 0, 0.35555], + "59": [0.19444, 0.44444, 0.06695, 0, 0.35555], + "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555], + "63": [0, 0.69444, 0.11472, 0, 0.59111], + "64": [0, 0.69444, 0.09208, 0, 0.88555], + "65": [0, 0.68611, 0, 0, 0.86555], + "66": [0, 0.68611, 0.0992, 0, 0.81666], + "67": [0, 0.68611, 0.14208, 0, 0.82666], + "68": [0, 0.68611, 0.09062, 0, 0.87555], + "69": [0, 0.68611, 0.11431, 0, 0.75666], + "70": [0, 0.68611, 0.12903, 0, 0.72722], + "71": [0, 0.68611, 0.07347, 0, 0.89527], + "72": [0, 0.68611, 0.17208, 0, 0.8961], + "73": [0, 0.68611, 0.15681, 0, 0.47166], + "74": [0, 0.68611, 0.145, 0, 0.61055], + "75": [0, 0.68611, 0.14208, 0, 0.89499], + "76": [0, 0.68611, 0, 0, 0.69777], + "77": [0, 0.68611, 0.17208, 0, 1.07277], + "78": [0, 0.68611, 0.17208, 0, 0.8961], + "79": [0, 0.68611, 0.09062, 0, 0.85499], + "80": [0, 0.68611, 0.0992, 0, 0.78721], + "81": [0.19444, 0.68611, 0.09062, 0, 0.85499], + "82": [0, 0.68611, 0.02559, 0, 0.85944], + "83": [0, 0.68611, 0.11264, 0, 0.64999], + "84": [0, 0.68611, 0.12903, 0, 0.7961], + "85": [0, 0.68611, 0.17208, 0, 0.88083], + "86": [0, 0.68611, 0.18625, 0, 0.86555], + "87": [0, 0.68611, 0.18625, 0, 1.15999], + "88": [0, 0.68611, 0.15681, 0, 0.86555], + "89": [0, 0.68611, 0.19803, 0, 0.86555], + "90": [0, 0.68611, 0.14208, 0, 0.70888], + "91": [0.25, 0.75, 0.1875, 0, 0.35611], + "93": [0.25, 0.75, 0.09972, 0, 0.35611], + "94": [0, 0.69444, 0.06709, 0, 0.59111], + "95": [0.31, 0.13444, 0.09811, 0, 0.59111], + "97": [0, 0.44444, 0.09426, 0, 0.59111], + "98": [0, 0.69444, 0.07861, 0, 0.53222], + "99": [0, 0.44444, 0.05222, 0, 0.53222], + "100": [0, 0.69444, 0.10861, 0, 0.59111], + "101": [0, 0.44444, 0.085, 0, 0.53222], + "102": [0.19444, 0.69444, 0.21778, 0, 0.4], + "103": [0.19444, 0.44444, 0.105, 0, 0.53222], + "104": [0, 0.69444, 0.09426, 0, 0.59111], + "105": [0, 0.69326, 0.11387, 0, 0.35555], + "106": [0.19444, 0.69326, 0.1672, 0, 0.35555], + "107": [0, 0.69444, 0.11111, 0, 0.53222], + "108": [0, 0.69444, 0.10861, 0, 0.29666], + "109": [0, 0.44444, 0.09426, 0, 0.94444], + "110": [0, 0.44444, 0.09426, 0, 0.64999], + "111": [0, 0.44444, 0.07861, 0, 0.59111], + "112": [0.19444, 0.44444, 0.07861, 0, 0.59111], + "113": [0.19444, 0.44444, 0.105, 0, 0.53222], + "114": [0, 0.44444, 0.11111, 0, 0.50167], + "115": [0, 0.44444, 0.08167, 0, 0.48694], + "116": [0, 0.63492, 0.09639, 0, 0.385], + "117": [0, 0.44444, 0.09426, 0, 0.62055], + "118": [0, 0.44444, 0.11111, 0, 0.53222], + "119": [0, 0.44444, 0.11111, 0, 0.76777], + "120": [0, 0.44444, 0.12583, 0, 0.56055], + "121": [0.19444, 0.44444, 0.105, 0, 0.56166], + "122": [0, 0.44444, 0.13889, 0, 0.49055], + "126": [0.35, 0.34444, 0.11472, 0, 0.59111], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.69444, 0.11473, 0, 0.59111], + "176": [0, 0.69444, 0, 0, 0.94888], + "184": [0.17014, 0, 0, 0, 0.53222], + "198": [0, 0.68611, 0.11431, 0, 1.02277], + "216": [0.04861, 0.73472, 0.09062, 0, 0.88555], + "223": [0.19444, 0.69444, 0.09736, 0, 0.665], + "230": [0, 0.44444, 0.085, 0, 0.82666], + "248": [0.09722, 0.54167, 0.09458, 0, 0.59111], + "305": [0, 0.44444, 0.09426, 0, 0.35555], + "338": [0, 0.68611, 0.11431, 0, 1.14054], + "339": [0, 0.44444, 0.085, 0, 0.82666], + "567": [0.19444, 0.44444, 0.04611, 0, 0.385], + "710": [0, 0.69444, 0.06709, 0, 0.59111], + "711": [0, 0.63194, 0.08271, 0, 0.59111], + "713": [0, 0.59444, 0.10444, 0, 0.59111], + "714": [0, 0.69444, 0.08528, 0, 0.59111], + "715": [0, 0.69444, 0, 0, 0.59111], + "728": [0, 0.69444, 0.10333, 0, 0.59111], + "729": [0, 0.69444, 0.12945, 0, 0.35555], + "730": [0, 0.69444, 0, 0, 0.94888], + "732": [0, 0.69444, 0.11472, 0, 0.59111], + "733": [0, 0.69444, 0.11472, 0, 0.59111], + "915": [0, 0.68611, 0.12903, 0, 0.69777], + "916": [0, 0.68611, 0, 0, 0.94444], + "920": [0, 0.68611, 0.09062, 0, 0.88555], + "923": [0, 0.68611, 0, 0, 0.80666], + "926": [0, 0.68611, 0.15092, 0, 0.76777], + "928": [0, 0.68611, 0.17208, 0, 0.8961], + "931": [0, 0.68611, 0.11431, 0, 0.82666], + "933": [0, 0.68611, 0.10778, 0, 0.88555], + "934": [0, 0.68611, 0.05632, 0, 0.82666], + "936": [0, 0.68611, 0.10778, 0, 0.88555], + "937": [0, 0.68611, 0.0992, 0, 0.82666], + "8211": [0, 0.44444, 0.09811, 0, 0.59111], + "8212": [0, 0.44444, 0.09811, 0, 1.18221], + "8216": [0, 0.69444, 0.12945, 0, 0.35555], + "8217": [0, 0.69444, 0.12945, 0, 0.35555], + "8220": [0, 0.69444, 0.16772, 0, 0.62055], + "8221": [0, 0.69444, 0.07939, 0, 0.62055] + }, + "Main-Italic": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0.12417, 0, 0.30667], + "34": [0, 0.69444, 0.06961, 0, 0.51444], + "35": [0.19444, 0.69444, 0.06616, 0, 0.81777], + "37": [0.05556, 0.75, 0.13639, 0, 0.81777], + "38": [0, 0.69444, 0.09694, 0, 0.76666], + "39": [0, 0.69444, 0.12417, 0, 0.30667], + "40": [0.25, 0.75, 0.16194, 0, 0.40889], + "41": [0.25, 0.75, 0.03694, 0, 0.40889], + "42": [0, 0.75, 0.14917, 0, 0.51111], + "43": [0.05667, 0.56167, 0.03694, 0, 0.76666], + "44": [0.19444, 0.10556, 0, 0, 0.30667], + "45": [0, 0.43056, 0.02826, 0, 0.35778], + "46": [0, 0.10556, 0, 0, 0.30667], + "47": [0.25, 0.75, 0.16194, 0, 0.51111], + "48": [0, 0.64444, 0.13556, 0, 0.51111], + "49": [0, 0.64444, 0.13556, 0, 0.51111], + "50": [0, 0.64444, 0.13556, 0, 0.51111], + "51": [0, 0.64444, 0.13556, 0, 0.51111], + "52": [0.19444, 0.64444, 0.13556, 0, 0.51111], + "53": [0, 0.64444, 0.13556, 0, 0.51111], + "54": [0, 0.64444, 0.13556, 0, 0.51111], + "55": [0.19444, 0.64444, 0.13556, 0, 0.51111], + "56": [0, 0.64444, 0.13556, 0, 0.51111], + "57": [0, 0.64444, 0.13556, 0, 0.51111], + "58": [0, 0.43056, 0.0582, 0, 0.30667], + "59": [0.19444, 0.43056, 0.0582, 0, 0.30667], + "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666], + "63": [0, 0.69444, 0.1225, 0, 0.51111], + "64": [0, 0.69444, 0.09597, 0, 0.76666], + "65": [0, 0.68333, 0, 0, 0.74333], + "66": [0, 0.68333, 0.10257, 0, 0.70389], + "67": [0, 0.68333, 0.14528, 0, 0.71555], + "68": [0, 0.68333, 0.09403, 0, 0.755], + "69": [0, 0.68333, 0.12028, 0, 0.67833], + "70": [0, 0.68333, 0.13305, 0, 0.65277], + "71": [0, 0.68333, 0.08722, 0, 0.77361], + "72": [0, 0.68333, 0.16389, 0, 0.74333], + "73": [0, 0.68333, 0.15806, 0, 0.38555], + "74": [0, 0.68333, 0.14028, 0, 0.525], + "75": [0, 0.68333, 0.14528, 0, 0.76888], + "76": [0, 0.68333, 0, 0, 0.62722], + "77": [0, 0.68333, 0.16389, 0, 0.89666], + "78": [0, 0.68333, 0.16389, 0, 0.74333], + "79": [0, 0.68333, 0.09403, 0, 0.76666], + "80": [0, 0.68333, 0.10257, 0, 0.67833], + "81": [0.19444, 0.68333, 0.09403, 0, 0.76666], + "82": [0, 0.68333, 0.03868, 0, 0.72944], + "83": [0, 0.68333, 0.11972, 0, 0.56222], + "84": [0, 0.68333, 0.13305, 0, 0.71555], + "85": [0, 0.68333, 0.16389, 0, 0.74333], + "86": [0, 0.68333, 0.18361, 0, 0.74333], + "87": [0, 0.68333, 0.18361, 0, 0.99888], + "88": [0, 0.68333, 0.15806, 0, 0.74333], + "89": [0, 0.68333, 0.19383, 0, 0.74333], + "90": [0, 0.68333, 0.14528, 0, 0.61333], + "91": [0.25, 0.75, 0.1875, 0, 0.30667], + "93": [0.25, 0.75, 0.10528, 0, 0.30667], + "94": [0, 0.69444, 0.06646, 0, 0.51111], + "95": [0.31, 0.12056, 0.09208, 0, 0.51111], + "97": [0, 0.43056, 0.07671, 0, 0.51111], + "98": [0, 0.69444, 0.06312, 0, 0.46], + "99": [0, 0.43056, 0.05653, 0, 0.46], + "100": [0, 0.69444, 0.10333, 0, 0.51111], + "101": [0, 0.43056, 0.07514, 0, 0.46], + "102": [0.19444, 0.69444, 0.21194, 0, 0.30667], + "103": [0.19444, 0.43056, 0.08847, 0, 0.46], + "104": [0, 0.69444, 0.07671, 0, 0.51111], + "105": [0, 0.65536, 0.1019, 0, 0.30667], + "106": [0.19444, 0.65536, 0.14467, 0, 0.30667], + "107": [0, 0.69444, 0.10764, 0, 0.46], + "108": [0, 0.69444, 0.10333, 0, 0.25555], + "109": [0, 0.43056, 0.07671, 0, 0.81777], + "110": [0, 0.43056, 0.07671, 0, 0.56222], + "111": [0, 0.43056, 0.06312, 0, 0.51111], + "112": [0.19444, 0.43056, 0.06312, 0, 0.51111], + "113": [0.19444, 0.43056, 0.08847, 0, 0.46], + "114": [0, 0.43056, 0.10764, 0, 0.42166], + "115": [0, 0.43056, 0.08208, 0, 0.40889], + "116": [0, 0.61508, 0.09486, 0, 0.33222], + "117": [0, 0.43056, 0.07671, 0, 0.53666], + "118": [0, 0.43056, 0.10764, 0, 0.46], + "119": [0, 0.43056, 0.10764, 0, 0.66444], + "120": [0, 0.43056, 0.12042, 0, 0.46389], + "121": [0.19444, 0.43056, 0.08847, 0, 0.48555], + "122": [0, 0.43056, 0.12292, 0, 0.40889], + "126": [0.35, 0.31786, 0.11585, 0, 0.51111], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.66786, 0.10474, 0, 0.51111], + "176": [0, 0.69444, 0, 0, 0.83129], + "184": [0.17014, 0, 0, 0, 0.46], + "198": [0, 0.68333, 0.12028, 0, 0.88277], + "216": [0.04861, 0.73194, 0.09403, 0, 0.76666], + "223": [0.19444, 0.69444, 0.10514, 0, 0.53666], + "230": [0, 0.43056, 0.07514, 0, 0.71555], + "248": [0.09722, 0.52778, 0.09194, 0, 0.51111], + "338": [0, 0.68333, 0.12028, 0, 0.98499], + "339": [0, 0.43056, 0.07514, 0, 0.71555], + "710": [0, 0.69444, 0.06646, 0, 0.51111], + "711": [0, 0.62847, 0.08295, 0, 0.51111], + "713": [0, 0.56167, 0.10333, 0, 0.51111], + "714": [0, 0.69444, 0.09694, 0, 0.51111], + "715": [0, 0.69444, 0, 0, 0.51111], + "728": [0, 0.69444, 0.10806, 0, 0.51111], + "729": [0, 0.66786, 0.11752, 0, 0.30667], + "730": [0, 0.69444, 0, 0, 0.83129], + "732": [0, 0.66786, 0.11585, 0, 0.51111], + "733": [0, 0.69444, 0.1225, 0, 0.51111], + "915": [0, 0.68333, 0.13305, 0, 0.62722], + "916": [0, 0.68333, 0, 0, 0.81777], + "920": [0, 0.68333, 0.09403, 0, 0.76666], + "923": [0, 0.68333, 0, 0, 0.69222], + "926": [0, 0.68333, 0.15294, 0, 0.66444], + "928": [0, 0.68333, 0.16389, 0, 0.74333], + "931": [0, 0.68333, 0.12028, 0, 0.71555], + "933": [0, 0.68333, 0.11111, 0, 0.76666], + "934": [0, 0.68333, 0.05986, 0, 0.71555], + "936": [0, 0.68333, 0.11111, 0, 0.76666], + "937": [0, 0.68333, 0.10257, 0, 0.71555], + "8211": [0, 0.43056, 0.09208, 0, 0.51111], + "8212": [0, 0.43056, 0.09208, 0, 1.02222], + "8216": [0, 0.69444, 0.12417, 0, 0.30667], + "8217": [0, 0.69444, 0.12417, 0, 0.30667], + "8220": [0, 0.69444, 0.1685, 0, 0.51444], + "8221": [0, 0.69444, 0.06961, 0, 0.51444], + "8463": [0, 0.68889, 0, 0, 0.54028] + }, + "Main-Regular": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.27778], + "34": [0, 0.69444, 0, 0, 0.5], + "35": [0.19444, 0.69444, 0, 0, 0.83334], + "36": [0.05556, 0.75, 0, 0, 0.5], + "37": [0.05556, 0.75, 0, 0, 0.83334], + "38": [0, 0.69444, 0, 0, 0.77778], + "39": [0, 0.69444, 0, 0, 0.27778], + "40": [0.25, 0.75, 0, 0, 0.38889], + "41": [0.25, 0.75, 0, 0, 0.38889], + "42": [0, 0.75, 0, 0, 0.5], + "43": [0.08333, 0.58333, 0, 0, 0.77778], + "44": [0.19444, 0.10556, 0, 0, 0.27778], + "45": [0, 0.43056, 0, 0, 0.33333], + "46": [0, 0.10556, 0, 0, 0.27778], + "47": [0.25, 0.75, 0, 0, 0.5], + "48": [0, 0.64444, 0, 0, 0.5], + "49": [0, 0.64444, 0, 0, 0.5], + "50": [0, 0.64444, 0, 0, 0.5], + "51": [0, 0.64444, 0, 0, 0.5], + "52": [0, 0.64444, 0, 0, 0.5], + "53": [0, 0.64444, 0, 0, 0.5], + "54": [0, 0.64444, 0, 0, 0.5], + "55": [0, 0.64444, 0, 0, 0.5], + "56": [0, 0.64444, 0, 0, 0.5], + "57": [0, 0.64444, 0, 0, 0.5], + "58": [0, 0.43056, 0, 0, 0.27778], + "59": [0.19444, 0.43056, 0, 0, 0.27778], + "60": [0.0391, 0.5391, 0, 0, 0.77778], + "61": [-0.13313, 0.36687, 0, 0, 0.77778], + "62": [0.0391, 0.5391, 0, 0, 0.77778], + "63": [0, 0.69444, 0, 0, 0.47222], + "64": [0, 0.69444, 0, 0, 0.77778], + "65": [0, 0.68333, 0, 0, 0.75], + "66": [0, 0.68333, 0, 0, 0.70834], + "67": [0, 0.68333, 0, 0, 0.72222], + "68": [0, 0.68333, 0, 0, 0.76389], + "69": [0, 0.68333, 0, 0, 0.68056], + "70": [0, 0.68333, 0, 0, 0.65278], + "71": [0, 0.68333, 0, 0, 0.78472], + "72": [0, 0.68333, 0, 0, 0.75], + "73": [0, 0.68333, 0, 0, 0.36111], + "74": [0, 0.68333, 0, 0, 0.51389], + "75": [0, 0.68333, 0, 0, 0.77778], + "76": [0, 0.68333, 0, 0, 0.625], + "77": [0, 0.68333, 0, 0, 0.91667], + "78": [0, 0.68333, 0, 0, 0.75], + "79": [0, 0.68333, 0, 0, 0.77778], + "80": [0, 0.68333, 0, 0, 0.68056], + "81": [0.19444, 0.68333, 0, 0, 0.77778], + "82": [0, 0.68333, 0, 0, 0.73611], + "83": [0, 0.68333, 0, 0, 0.55556], + "84": [0, 0.68333, 0, 0, 0.72222], + "85": [0, 0.68333, 0, 0, 0.75], + "86": [0, 0.68333, 0.01389, 0, 0.75], + "87": [0, 0.68333, 0.01389, 0, 1.02778], + "88": [0, 0.68333, 0, 0, 0.75], + "89": [0, 0.68333, 0.025, 0, 0.75], + "90": [0, 0.68333, 0, 0, 0.61111], + "91": [0.25, 0.75, 0, 0, 0.27778], + "92": [0.25, 0.75, 0, 0, 0.5], + "93": [0.25, 0.75, 0, 0, 0.27778], + "94": [0, 0.69444, 0, 0, 0.5], + "95": [0.31, 0.12056, 0.02778, 0, 0.5], + "97": [0, 0.43056, 0, 0, 0.5], + "98": [0, 0.69444, 0, 0, 0.55556], + "99": [0, 0.43056, 0, 0, 0.44445], + "100": [0, 0.69444, 0, 0, 0.55556], + "101": [0, 0.43056, 0, 0, 0.44445], + "102": [0, 0.69444, 0.07778, 0, 0.30556], + "103": [0.19444, 0.43056, 0.01389, 0, 0.5], + "104": [0, 0.69444, 0, 0, 0.55556], + "105": [0, 0.66786, 0, 0, 0.27778], + "106": [0.19444, 0.66786, 0, 0, 0.30556], + "107": [0, 0.69444, 0, 0, 0.52778], + "108": [0, 0.69444, 0, 0, 0.27778], + "109": [0, 0.43056, 0, 0, 0.83334], + "110": [0, 0.43056, 0, 0, 0.55556], + "111": [0, 0.43056, 0, 0, 0.5], + "112": [0.19444, 0.43056, 0, 0, 0.55556], + "113": [0.19444, 0.43056, 0, 0, 0.52778], + "114": [0, 0.43056, 0, 0, 0.39167], + "115": [0, 0.43056, 0, 0, 0.39445], + "116": [0, 0.61508, 0, 0, 0.38889], + "117": [0, 0.43056, 0, 0, 0.55556], + "118": [0, 0.43056, 0.01389, 0, 0.52778], + "119": [0, 0.43056, 0.01389, 0, 0.72222], + "120": [0, 0.43056, 0, 0, 0.52778], + "121": [0.19444, 0.43056, 0.01389, 0, 0.52778], + "122": [0, 0.43056, 0, 0, 0.44445], + "123": [0.25, 0.75, 0, 0, 0.5], + "124": [0.25, 0.75, 0, 0, 0.27778], + "125": [0.25, 0.75, 0, 0, 0.5], + "126": [0.35, 0.31786, 0, 0, 0.5], + "160": [0, 0, 0, 0, 0.25], + "163": [0, 0.69444, 0, 0, 0.76909], + "167": [0.19444, 0.69444, 0, 0, 0.44445], + "168": [0, 0.66786, 0, 0, 0.5], + "172": [0, 0.43056, 0, 0, 0.66667], + "176": [0, 0.69444, 0, 0, 0.75], + "177": [0.08333, 0.58333, 0, 0, 0.77778], + "182": [0.19444, 0.69444, 0, 0, 0.61111], + "184": [0.17014, 0, 0, 0, 0.44445], + "198": [0, 0.68333, 0, 0, 0.90278], + "215": [0.08333, 0.58333, 0, 0, 0.77778], + "216": [0.04861, 0.73194, 0, 0, 0.77778], + "223": [0, 0.69444, 0, 0, 0.5], + "230": [0, 0.43056, 0, 0, 0.72222], + "247": [0.08333, 0.58333, 0, 0, 0.77778], + "248": [0.09722, 0.52778, 0, 0, 0.5], + "305": [0, 0.43056, 0, 0, 0.27778], + "338": [0, 0.68333, 0, 0, 1.01389], + "339": [0, 0.43056, 0, 0, 0.77778], + "567": [0.19444, 0.43056, 0, 0, 0.30556], + "710": [0, 0.69444, 0, 0, 0.5], + "711": [0, 0.62847, 0, 0, 0.5], + "713": [0, 0.56778, 0, 0, 0.5], + "714": [0, 0.69444, 0, 0, 0.5], + "715": [0, 0.69444, 0, 0, 0.5], + "728": [0, 0.69444, 0, 0, 0.5], + "729": [0, 0.66786, 0, 0, 0.27778], + "730": [0, 0.69444, 0, 0, 0.75], + "732": [0, 0.66786, 0, 0, 0.5], + "733": [0, 0.69444, 0, 0, 0.5], + "915": [0, 0.68333, 0, 0, 0.625], + "916": [0, 0.68333, 0, 0, 0.83334], + "920": [0, 0.68333, 0, 0, 0.77778], + "923": [0, 0.68333, 0, 0, 0.69445], + "926": [0, 0.68333, 0, 0, 0.66667], + "928": [0, 0.68333, 0, 0, 0.75], + "931": [0, 0.68333, 0, 0, 0.72222], + "933": [0, 0.68333, 0, 0, 0.77778], + "934": [0, 0.68333, 0, 0, 0.72222], + "936": [0, 0.68333, 0, 0, 0.77778], + "937": [0, 0.68333, 0, 0, 0.72222], + "8211": [0, 0.43056, 0.02778, 0, 0.5], + "8212": [0, 0.43056, 0.02778, 0, 1.0], + "8216": [0, 0.69444, 0, 0, 0.27778], + "8217": [0, 0.69444, 0, 0, 0.27778], + "8220": [0, 0.69444, 0, 0, 0.5], + "8221": [0, 0.69444, 0, 0, 0.5], + "8224": [0.19444, 0.69444, 0, 0, 0.44445], + "8225": [0.19444, 0.69444, 0, 0, 0.44445], + "8230": [0, 0.123, 0, 0, 1.172], + "8242": [0, 0.55556, 0, 0, 0.275], + "8407": [0, 0.71444, 0.15382, 0, 0.5], + "8463": [0, 0.68889, 0, 0, 0.54028], + "8465": [0, 0.69444, 0, 0, 0.72222], + "8467": [0, 0.69444, 0, 0.11111, 0.41667], + "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646], + "8476": [0, 0.69444, 0, 0, 0.72222], + "8501": [0, 0.69444, 0, 0, 0.61111], + "8592": [-0.13313, 0.36687, 0, 0, 1.0], + "8593": [0.19444, 0.69444, 0, 0, 0.5], + "8594": [-0.13313, 0.36687, 0, 0, 1.0], + "8595": [0.19444, 0.69444, 0, 0, 0.5], + "8596": [-0.13313, 0.36687, 0, 0, 1.0], + "8597": [0.25, 0.75, 0, 0, 0.5], + "8598": [0.19444, 0.69444, 0, 0, 1.0], + "8599": [0.19444, 0.69444, 0, 0, 1.0], + "8600": [0.19444, 0.69444, 0, 0, 1.0], + "8601": [0.19444, 0.69444, 0, 0, 1.0], + "8614": [0.011, 0.511, 0, 0, 1.0], + "8617": [0.011, 0.511, 0, 0, 1.126], + "8618": [0.011, 0.511, 0, 0, 1.126], + "8636": [-0.13313, 0.36687, 0, 0, 1.0], + "8637": [-0.13313, 0.36687, 0, 0, 1.0], + "8640": [-0.13313, 0.36687, 0, 0, 1.0], + "8641": [-0.13313, 0.36687, 0, 0, 1.0], + "8652": [0.011, 0.671, 0, 0, 1.0], + "8656": [-0.13313, 0.36687, 0, 0, 1.0], + "8657": [0.19444, 0.69444, 0, 0, 0.61111], + "8658": [-0.13313, 0.36687, 0, 0, 1.0], + "8659": [0.19444, 0.69444, 0, 0, 0.61111], + "8660": [-0.13313, 0.36687, 0, 0, 1.0], + "8661": [0.25, 0.75, 0, 0, 0.61111], + "8704": [0, 0.69444, 0, 0, 0.55556], + "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309], + "8707": [0, 0.69444, 0, 0, 0.55556], + "8709": [0.05556, 0.75, 0, 0, 0.5], + "8711": [0, 0.68333, 0, 0, 0.83334], + "8712": [0.0391, 0.5391, 0, 0, 0.66667], + "8715": [0.0391, 0.5391, 0, 0, 0.66667], + "8722": [0.08333, 0.58333, 0, 0, 0.77778], + "8723": [0.08333, 0.58333, 0, 0, 0.77778], + "8725": [0.25, 0.75, 0, 0, 0.5], + "8726": [0.25, 0.75, 0, 0, 0.5], + "8727": [-0.03472, 0.46528, 0, 0, 0.5], + "8728": [-0.05555, 0.44445, 0, 0, 0.5], + "8729": [-0.05555, 0.44445, 0, 0, 0.5], + "8730": [0.2, 0.8, 0, 0, 0.83334], + "8733": [0, 0.43056, 0, 0, 0.77778], + "8734": [0, 0.43056, 0, 0, 1.0], + "8736": [0, 0.69224, 0, 0, 0.72222], + "8739": [0.25, 0.75, 0, 0, 0.27778], + "8741": [0.25, 0.75, 0, 0, 0.5], + "8743": [0, 0.55556, 0, 0, 0.66667], + "8744": [0, 0.55556, 0, 0, 0.66667], + "8745": [0, 0.55556, 0, 0, 0.66667], + "8746": [0, 0.55556, 0, 0, 0.66667], + "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667], + "8764": [-0.13313, 0.36687, 0, 0, 0.77778], + "8768": [0.19444, 0.69444, 0, 0, 0.27778], + "8771": [-0.03625, 0.46375, 0, 0, 0.77778], + "8773": [-0.022, 0.589, 0, 0, 0.778], + "8776": [-0.01688, 0.48312, 0, 0, 0.77778], + "8781": [-0.03625, 0.46375, 0, 0, 0.77778], + "8784": [-0.133, 0.673, 0, 0, 0.778], + "8801": [-0.03625, 0.46375, 0, 0, 0.77778], + "8804": [0.13597, 0.63597, 0, 0, 0.77778], + "8805": [0.13597, 0.63597, 0, 0, 0.77778], + "8810": [0.0391, 0.5391, 0, 0, 1.0], + "8811": [0.0391, 0.5391, 0, 0, 1.0], + "8826": [0.0391, 0.5391, 0, 0, 0.77778], + "8827": [0.0391, 0.5391, 0, 0, 0.77778], + "8834": [0.0391, 0.5391, 0, 0, 0.77778], + "8835": [0.0391, 0.5391, 0, 0, 0.77778], + "8838": [0.13597, 0.63597, 0, 0, 0.77778], + "8839": [0.13597, 0.63597, 0, 0, 0.77778], + "8846": [0, 0.55556, 0, 0, 0.66667], + "8849": [0.13597, 0.63597, 0, 0, 0.77778], + "8850": [0.13597, 0.63597, 0, 0, 0.77778], + "8851": [0, 0.55556, 0, 0, 0.66667], + "8852": [0, 0.55556, 0, 0, 0.66667], + "8853": [0.08333, 0.58333, 0, 0, 0.77778], + "8854": [0.08333, 0.58333, 0, 0, 0.77778], + "8855": [0.08333, 0.58333, 0, 0, 0.77778], + "8856": [0.08333, 0.58333, 0, 0, 0.77778], + "8857": [0.08333, 0.58333, 0, 0, 0.77778], + "8866": [0, 0.69444, 0, 0, 0.61111], + "8867": [0, 0.69444, 0, 0, 0.61111], + "8868": [0, 0.69444, 0, 0, 0.77778], + "8869": [0, 0.69444, 0, 0, 0.77778], + "8872": [0.249, 0.75, 0, 0, 0.867], + "8900": [-0.05555, 0.44445, 0, 0, 0.5], + "8901": [-0.05555, 0.44445, 0, 0, 0.27778], + "8902": [-0.03472, 0.46528, 0, 0, 0.5], + "8904": [0.005, 0.505, 0, 0, 0.9], + "8942": [0.03, 0.903, 0, 0, 0.278], + "8943": [-0.19, 0.313, 0, 0, 1.172], + "8945": [-0.1, 0.823, 0, 0, 1.282], + "8968": [0.25, 0.75, 0, 0, 0.44445], + "8969": [0.25, 0.75, 0, 0, 0.44445], + "8970": [0.25, 0.75, 0, 0, 0.44445], + "8971": [0.25, 0.75, 0, 0, 0.44445], + "8994": [-0.14236, 0.35764, 0, 0, 1.0], + "8995": [-0.14236, 0.35764, 0, 0, 1.0], + "9136": [0.244, 0.744, 0, 0, 0.412], + "9137": [0.244, 0.745, 0, 0, 0.412], + "9651": [0.19444, 0.69444, 0, 0, 0.88889], + "9657": [-0.03472, 0.46528, 0, 0, 0.5], + "9661": [0.19444, 0.69444, 0, 0, 0.88889], + "9667": [-0.03472, 0.46528, 0, 0, 0.5], + "9711": [0.19444, 0.69444, 0, 0, 1.0], + "9824": [0.12963, 0.69444, 0, 0, 0.77778], + "9825": [0.12963, 0.69444, 0, 0, 0.77778], + "9826": [0.12963, 0.69444, 0, 0, 0.77778], + "9827": [0.12963, 0.69444, 0, 0, 0.77778], + "9837": [0, 0.75, 0, 0, 0.38889], + "9838": [0.19444, 0.69444, 0, 0, 0.38889], + "9839": [0.19444, 0.69444, 0, 0, 0.38889], + "10216": [0.25, 0.75, 0, 0, 0.38889], + "10217": [0.25, 0.75, 0, 0, 0.38889], + "10222": [0.244, 0.744, 0, 0, 0.412], + "10223": [0.244, 0.745, 0, 0, 0.412], + "10229": [0.011, 0.511, 0, 0, 1.609], + "10230": [0.011, 0.511, 0, 0, 1.638], + "10231": [0.011, 0.511, 0, 0, 1.859], + "10232": [0.024, 0.525, 0, 0, 1.609], + "10233": [0.024, 0.525, 0, 0, 1.638], + "10234": [0.024, 0.525, 0, 0, 1.858], + "10236": [0.011, 0.511, 0, 0, 1.638], + "10815": [0, 0.68333, 0, 0, 0.75], + "10927": [0.13597, 0.63597, 0, 0, 0.77778], + "10928": [0.13597, 0.63597, 0, 0, 0.77778], + "57376": [0.19444, 0.69444, 0, 0, 0] + }, + "Math-BoldItalic": { + "32": [0, 0, 0, 0, 0.25], + "48": [0, 0.44444, 0, 0, 0.575], + "49": [0, 0.44444, 0, 0, 0.575], + "50": [0, 0.44444, 0, 0, 0.575], + "51": [0.19444, 0.44444, 0, 0, 0.575], + "52": [0.19444, 0.44444, 0, 0, 0.575], + "53": [0.19444, 0.44444, 0, 0, 0.575], + "54": [0, 0.64444, 0, 0, 0.575], + "55": [0.19444, 0.44444, 0, 0, 0.575], + "56": [0, 0.64444, 0, 0, 0.575], + "57": [0.19444, 0.44444, 0, 0, 0.575], + "65": [0, 0.68611, 0, 0, 0.86944], + "66": [0, 0.68611, 0.04835, 0, 0.8664], + "67": [0, 0.68611, 0.06979, 0, 0.81694], + "68": [0, 0.68611, 0.03194, 0, 0.93812], + "69": [0, 0.68611, 0.05451, 0, 0.81007], + "70": [0, 0.68611, 0.15972, 0, 0.68889], + "71": [0, 0.68611, 0, 0, 0.88673], + "72": [0, 0.68611, 0.08229, 0, 0.98229], + "73": [0, 0.68611, 0.07778, 0, 0.51111], + "74": [0, 0.68611, 0.10069, 0, 0.63125], + "75": [0, 0.68611, 0.06979, 0, 0.97118], + "76": [0, 0.68611, 0, 0, 0.75555], + "77": [0, 0.68611, 0.11424, 0, 1.14201], + "78": [0, 0.68611, 0.11424, 0, 0.95034], + "79": [0, 0.68611, 0.03194, 0, 0.83666], + "80": [0, 0.68611, 0.15972, 0, 0.72309], + "81": [0.19444, 0.68611, 0, 0, 0.86861], + "82": [0, 0.68611, 0.00421, 0, 0.87235], + "83": [0, 0.68611, 0.05382, 0, 0.69271], + "84": [0, 0.68611, 0.15972, 0, 0.63663], + "85": [0, 0.68611, 0.11424, 0, 0.80027], + "86": [0, 0.68611, 0.25555, 0, 0.67778], + "87": [0, 0.68611, 0.15972, 0, 1.09305], + "88": [0, 0.68611, 0.07778, 0, 0.94722], + "89": [0, 0.68611, 0.25555, 0, 0.67458], + "90": [0, 0.68611, 0.06979, 0, 0.77257], + "97": [0, 0.44444, 0, 0, 0.63287], + "98": [0, 0.69444, 0, 0, 0.52083], + "99": [0, 0.44444, 0, 0, 0.51342], + "100": [0, 0.69444, 0, 0, 0.60972], + "101": [0, 0.44444, 0, 0, 0.55361], + "102": [0.19444, 0.69444, 0.11042, 0, 0.56806], + "103": [0.19444, 0.44444, 0.03704, 0, 0.5449], + "104": [0, 0.69444, 0, 0, 0.66759], + "105": [0, 0.69326, 0, 0, 0.4048], + "106": [0.19444, 0.69326, 0.0622, 0, 0.47083], + "107": [0, 0.69444, 0.01852, 0, 0.6037], + "108": [0, 0.69444, 0.0088, 0, 0.34815], + "109": [0, 0.44444, 0, 0, 1.0324], + "110": [0, 0.44444, 0, 0, 0.71296], + "111": [0, 0.44444, 0, 0, 0.58472], + "112": [0.19444, 0.44444, 0, 0, 0.60092], + "113": [0.19444, 0.44444, 0.03704, 0, 0.54213], + "114": [0, 0.44444, 0.03194, 0, 0.5287], + "115": [0, 0.44444, 0, 0, 0.53125], + "116": [0, 0.63492, 0, 0, 0.41528], + "117": [0, 0.44444, 0, 0, 0.68102], + "118": [0, 0.44444, 0.03704, 0, 0.56666], + "119": [0, 0.44444, 0.02778, 0, 0.83148], + "120": [0, 0.44444, 0, 0, 0.65903], + "121": [0.19444, 0.44444, 0.03704, 0, 0.59028], + "122": [0, 0.44444, 0.04213, 0, 0.55509], + "160": [0, 0, 0, 0, 0.25], + "915": [0, 0.68611, 0.15972, 0, 0.65694], + "916": [0, 0.68611, 0, 0, 0.95833], + "920": [0, 0.68611, 0.03194, 0, 0.86722], + "923": [0, 0.68611, 0, 0, 0.80555], + "926": [0, 0.68611, 0.07458, 0, 0.84125], + "928": [0, 0.68611, 0.08229, 0, 0.98229], + "931": [0, 0.68611, 0.05451, 0, 0.88507], + "933": [0, 0.68611, 0.15972, 0, 0.67083], + "934": [0, 0.68611, 0, 0, 0.76666], + "936": [0, 0.68611, 0.11653, 0, 0.71402], + "937": [0, 0.68611, 0.04835, 0, 0.8789], + "945": [0, 0.44444, 0, 0, 0.76064], + "946": [0.19444, 0.69444, 0.03403, 0, 0.65972], + "947": [0.19444, 0.44444, 0.06389, 0, 0.59003], + "948": [0, 0.69444, 0.03819, 0, 0.52222], + "949": [0, 0.44444, 0, 0, 0.52882], + "950": [0.19444, 0.69444, 0.06215, 0, 0.50833], + "951": [0.19444, 0.44444, 0.03704, 0, 0.6], + "952": [0, 0.69444, 0.03194, 0, 0.5618], + "953": [0, 0.44444, 0, 0, 0.41204], + "954": [0, 0.44444, 0, 0, 0.66759], + "955": [0, 0.69444, 0, 0, 0.67083], + "956": [0.19444, 0.44444, 0, 0, 0.70787], + "957": [0, 0.44444, 0.06898, 0, 0.57685], + "958": [0.19444, 0.69444, 0.03021, 0, 0.50833], + "959": [0, 0.44444, 0, 0, 0.58472], + "960": [0, 0.44444, 0.03704, 0, 0.68241], + "961": [0.19444, 0.44444, 0, 0, 0.6118], + "962": [0.09722, 0.44444, 0.07917, 0, 0.42361], + "963": [0, 0.44444, 0.03704, 0, 0.68588], + "964": [0, 0.44444, 0.13472, 0, 0.52083], + "965": [0, 0.44444, 0.03704, 0, 0.63055], + "966": [0.19444, 0.44444, 0, 0, 0.74722], + "967": [0.19444, 0.44444, 0, 0, 0.71805], + "968": [0.19444, 0.69444, 0.03704, 0, 0.75833], + "969": [0, 0.44444, 0.03704, 0, 0.71782], + "977": [0, 0.69444, 0, 0, 0.69155], + "981": [0.19444, 0.69444, 0, 0, 0.7125], + "982": [0, 0.44444, 0.03194, 0, 0.975], + "1009": [0.19444, 0.44444, 0, 0, 0.6118], + "1013": [0, 0.44444, 0, 0, 0.48333], + "57649": [0, 0.44444, 0, 0, 0.39352], + "57911": [0.19444, 0.44444, 0, 0, 0.43889] + }, + "Math-Italic": { + "32": [0, 0, 0, 0, 0.25], + "48": [0, 0.43056, 0, 0, 0.5], + "49": [0, 0.43056, 0, 0, 0.5], + "50": [0, 0.43056, 0, 0, 0.5], + "51": [0.19444, 0.43056, 0, 0, 0.5], + "52": [0.19444, 0.43056, 0, 0, 0.5], + "53": [0.19444, 0.43056, 0, 0, 0.5], + "54": [0, 0.64444, 0, 0, 0.5], + "55": [0.19444, 0.43056, 0, 0, 0.5], + "56": [0, 0.64444, 0, 0, 0.5], + "57": [0.19444, 0.43056, 0, 0, 0.5], + "65": [0, 0.68333, 0, 0.13889, 0.75], + "66": [0, 0.68333, 0.05017, 0.08334, 0.75851], + "67": [0, 0.68333, 0.07153, 0.08334, 0.71472], + "68": [0, 0.68333, 0.02778, 0.05556, 0.82792], + "69": [0, 0.68333, 0.05764, 0.08334, 0.7382], + "70": [0, 0.68333, 0.13889, 0.08334, 0.64306], + "71": [0, 0.68333, 0, 0.08334, 0.78625], + "72": [0, 0.68333, 0.08125, 0.05556, 0.83125], + "73": [0, 0.68333, 0.07847, 0.11111, 0.43958], + "74": [0, 0.68333, 0.09618, 0.16667, 0.55451], + "75": [0, 0.68333, 0.07153, 0.05556, 0.84931], + "76": [0, 0.68333, 0, 0.02778, 0.68056], + "77": [0, 0.68333, 0.10903, 0.08334, 0.97014], + "78": [0, 0.68333, 0.10903, 0.08334, 0.80347], + "79": [0, 0.68333, 0.02778, 0.08334, 0.76278], + "80": [0, 0.68333, 0.13889, 0.08334, 0.64201], + "81": [0.19444, 0.68333, 0, 0.08334, 0.79056], + "82": [0, 0.68333, 0.00773, 0.08334, 0.75929], + "83": [0, 0.68333, 0.05764, 0.08334, 0.6132], + "84": [0, 0.68333, 0.13889, 0.08334, 0.58438], + "85": [0, 0.68333, 0.10903, 0.02778, 0.68278], + "86": [0, 0.68333, 0.22222, 0, 0.58333], + "87": [0, 0.68333, 0.13889, 0, 0.94445], + "88": [0, 0.68333, 0.07847, 0.08334, 0.82847], + "89": [0, 0.68333, 0.22222, 0, 0.58056], + "90": [0, 0.68333, 0.07153, 0.08334, 0.68264], + "97": [0, 0.43056, 0, 0, 0.52859], + "98": [0, 0.69444, 0, 0, 0.42917], + "99": [0, 0.43056, 0, 0.05556, 0.43276], + "100": [0, 0.69444, 0, 0.16667, 0.52049], + "101": [0, 0.43056, 0, 0.05556, 0.46563], + "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959], + "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697], + "104": [0, 0.69444, 0, 0, 0.57616], + "105": [0, 0.65952, 0, 0, 0.34451], + "106": [0.19444, 0.65952, 0.05724, 0, 0.41181], + "107": [0, 0.69444, 0.03148, 0, 0.5206], + "108": [0, 0.69444, 0.01968, 0.08334, 0.29838], + "109": [0, 0.43056, 0, 0, 0.87801], + "110": [0, 0.43056, 0, 0, 0.60023], + "111": [0, 0.43056, 0, 0.05556, 0.48472], + "112": [0.19444, 0.43056, 0, 0.08334, 0.50313], + "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641], + "114": [0, 0.43056, 0.02778, 0.05556, 0.45116], + "115": [0, 0.43056, 0, 0.05556, 0.46875], + "116": [0, 0.61508, 0, 0.08334, 0.36111], + "117": [0, 0.43056, 0, 0.02778, 0.57246], + "118": [0, 0.43056, 0.03588, 0.02778, 0.48472], + "119": [0, 0.43056, 0.02691, 0.08334, 0.71592], + "120": [0, 0.43056, 0, 0.02778, 0.57153], + "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028], + "122": [0, 0.43056, 0.04398, 0.05556, 0.46505], + "160": [0, 0, 0, 0, 0.25], + "915": [0, 0.68333, 0.13889, 0.08334, 0.61528], + "916": [0, 0.68333, 0, 0.16667, 0.83334], + "920": [0, 0.68333, 0.02778, 0.08334, 0.76278], + "923": [0, 0.68333, 0, 0.16667, 0.69445], + "926": [0, 0.68333, 0.07569, 0.08334, 0.74236], + "928": [0, 0.68333, 0.08125, 0.05556, 0.83125], + "931": [0, 0.68333, 0.05764, 0.08334, 0.77986], + "933": [0, 0.68333, 0.13889, 0.05556, 0.58333], + "934": [0, 0.68333, 0, 0.08334, 0.66667], + "936": [0, 0.68333, 0.11, 0.05556, 0.61222], + "937": [0, 0.68333, 0.05017, 0.08334, 0.7724], + "945": [0, 0.43056, 0.0037, 0.02778, 0.6397], + "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563], + "947": [0.19444, 0.43056, 0.05556, 0, 0.51773], + "948": [0, 0.69444, 0.03785, 0.05556, 0.44444], + "949": [0, 0.43056, 0, 0.08334, 0.46632], + "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375], + "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653], + "952": [0, 0.69444, 0.02778, 0.08334, 0.46944], + "953": [0, 0.43056, 0, 0.05556, 0.35394], + "954": [0, 0.43056, 0, 0, 0.57616], + "955": [0, 0.69444, 0, 0, 0.58334], + "956": [0.19444, 0.43056, 0, 0.02778, 0.60255], + "957": [0, 0.43056, 0.06366, 0.02778, 0.49398], + "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375], + "959": [0, 0.43056, 0, 0.05556, 0.48472], + "960": [0, 0.43056, 0.03588, 0, 0.57003], + "961": [0.19444, 0.43056, 0, 0.08334, 0.51702], + "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285], + "963": [0, 0.43056, 0.03588, 0, 0.57141], + "964": [0, 0.43056, 0.1132, 0.02778, 0.43715], + "965": [0, 0.43056, 0.03588, 0.02778, 0.54028], + "966": [0.19444, 0.43056, 0, 0.08334, 0.65417], + "967": [0.19444, 0.43056, 0, 0.05556, 0.62569], + "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139], + "969": [0, 0.43056, 0.03588, 0, 0.62245], + "977": [0, 0.69444, 0, 0.08334, 0.59144], + "981": [0.19444, 0.69444, 0, 0.08334, 0.59583], + "982": [0, 0.43056, 0.02778, 0, 0.82813], + "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702], + "1013": [0, 0.43056, 0, 0.05556, 0.4059], + "57649": [0, 0.43056, 0, 0.02778, 0.32246], + "57911": [0.19444, 0.43056, 0, 0.08334, 0.38403] + }, + "SansSerif-Bold": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.36667], + "34": [0, 0.69444, 0, 0, 0.55834], + "35": [0.19444, 0.69444, 0, 0, 0.91667], + "36": [0.05556, 0.75, 0, 0, 0.55], + "37": [0.05556, 0.75, 0, 0, 1.02912], + "38": [0, 0.69444, 0, 0, 0.83056], + "39": [0, 0.69444, 0, 0, 0.30556], + "40": [0.25, 0.75, 0, 0, 0.42778], + "41": [0.25, 0.75, 0, 0, 0.42778], + "42": [0, 0.75, 0, 0, 0.55], + "43": [0.11667, 0.61667, 0, 0, 0.85556], + "44": [0.10556, 0.13056, 0, 0, 0.30556], + "45": [0, 0.45833, 0, 0, 0.36667], + "46": [0, 0.13056, 0, 0, 0.30556], + "47": [0.25, 0.75, 0, 0, 0.55], + "48": [0, 0.69444, 0, 0, 0.55], + "49": [0, 0.69444, 0, 0, 0.55], + "50": [0, 0.69444, 0, 0, 0.55], + "51": [0, 0.69444, 0, 0, 0.55], + "52": [0, 0.69444, 0, 0, 0.55], + "53": [0, 0.69444, 0, 0, 0.55], + "54": [0, 0.69444, 0, 0, 0.55], + "55": [0, 0.69444, 0, 0, 0.55], + "56": [0, 0.69444, 0, 0, 0.55], + "57": [0, 0.69444, 0, 0, 0.55], + "58": [0, 0.45833, 0, 0, 0.30556], + "59": [0.10556, 0.45833, 0, 0, 0.30556], + "61": [-0.09375, 0.40625, 0, 0, 0.85556], + "63": [0, 0.69444, 0, 0, 0.51945], + "64": [0, 0.69444, 0, 0, 0.73334], + "65": [0, 0.69444, 0, 0, 0.73334], + "66": [0, 0.69444, 0, 0, 0.73334], + "67": [0, 0.69444, 0, 0, 0.70278], + "68": [0, 0.69444, 0, 0, 0.79445], + "69": [0, 0.69444, 0, 0, 0.64167], + "70": [0, 0.69444, 0, 0, 0.61111], + "71": [0, 0.69444, 0, 0, 0.73334], + "72": [0, 0.69444, 0, 0, 0.79445], + "73": [0, 0.69444, 0, 0, 0.33056], + "74": [0, 0.69444, 0, 0, 0.51945], + "75": [0, 0.69444, 0, 0, 0.76389], + "76": [0, 0.69444, 0, 0, 0.58056], + "77": [0, 0.69444, 0, 0, 0.97778], + "78": [0, 0.69444, 0, 0, 0.79445], + "79": [0, 0.69444, 0, 0, 0.79445], + "80": [0, 0.69444, 0, 0, 0.70278], + "81": [0.10556, 0.69444, 0, 0, 0.79445], + "82": [0, 0.69444, 0, 0, 0.70278], + "83": [0, 0.69444, 0, 0, 0.61111], + "84": [0, 0.69444, 0, 0, 0.73334], + "85": [0, 0.69444, 0, 0, 0.76389], + "86": [0, 0.69444, 0.01528, 0, 0.73334], + "87": [0, 0.69444, 0.01528, 0, 1.03889], + "88": [0, 0.69444, 0, 0, 0.73334], + "89": [0, 0.69444, 0.0275, 0, 0.73334], + "90": [0, 0.69444, 0, 0, 0.67223], + "91": [0.25, 0.75, 0, 0, 0.34306], + "93": [0.25, 0.75, 0, 0, 0.34306], + "94": [0, 0.69444, 0, 0, 0.55], + "95": [0.35, 0.10833, 0.03056, 0, 0.55], + "97": [0, 0.45833, 0, 0, 0.525], + "98": [0, 0.69444, 0, 0, 0.56111], + "99": [0, 0.45833, 0, 0, 0.48889], + "100": [0, 0.69444, 0, 0, 0.56111], + "101": [0, 0.45833, 0, 0, 0.51111], + "102": [0, 0.69444, 0.07639, 0, 0.33611], + "103": [0.19444, 0.45833, 0.01528, 0, 0.55], + "104": [0, 0.69444, 0, 0, 0.56111], + "105": [0, 0.69444, 0, 0, 0.25556], + "106": [0.19444, 0.69444, 0, 0, 0.28611], + "107": [0, 0.69444, 0, 0, 0.53056], + "108": [0, 0.69444, 0, 0, 0.25556], + "109": [0, 0.45833, 0, 0, 0.86667], + "110": [0, 0.45833, 0, 0, 0.56111], + "111": [0, 0.45833, 0, 0, 0.55], + "112": [0.19444, 0.45833, 0, 0, 0.56111], + "113": [0.19444, 0.45833, 0, 0, 0.56111], + "114": [0, 0.45833, 0.01528, 0, 0.37222], + "115": [0, 0.45833, 0, 0, 0.42167], + "116": [0, 0.58929, 0, 0, 0.40417], + "117": [0, 0.45833, 0, 0, 0.56111], + "118": [0, 0.45833, 0.01528, 0, 0.5], + "119": [0, 0.45833, 0.01528, 0, 0.74445], + "120": [0, 0.45833, 0, 0, 0.5], + "121": [0.19444, 0.45833, 0.01528, 0, 0.5], + "122": [0, 0.45833, 0, 0, 0.47639], + "126": [0.35, 0.34444, 0, 0, 0.55], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.69444, 0, 0, 0.55], + "176": [0, 0.69444, 0, 0, 0.73334], + "180": [0, 0.69444, 0, 0, 0.55], + "184": [0.17014, 0, 0, 0, 0.48889], + "305": [0, 0.45833, 0, 0, 0.25556], + "567": [0.19444, 0.45833, 0, 0, 0.28611], + "710": [0, 0.69444, 0, 0, 0.55], + "711": [0, 0.63542, 0, 0, 0.55], + "713": [0, 0.63778, 0, 0, 0.55], + "728": [0, 0.69444, 0, 0, 0.55], + "729": [0, 0.69444, 0, 0, 0.30556], + "730": [0, 0.69444, 0, 0, 0.73334], + "732": [0, 0.69444, 0, 0, 0.55], + "733": [0, 0.69444, 0, 0, 0.55], + "915": [0, 0.69444, 0, 0, 0.58056], + "916": [0, 0.69444, 0, 0, 0.91667], + "920": [0, 0.69444, 0, 0, 0.85556], + "923": [0, 0.69444, 0, 0, 0.67223], + "926": [0, 0.69444, 0, 0, 0.73334], + "928": [0, 0.69444, 0, 0, 0.79445], + "931": [0, 0.69444, 0, 0, 0.79445], + "933": [0, 0.69444, 0, 0, 0.85556], + "934": [0, 0.69444, 0, 0, 0.79445], + "936": [0, 0.69444, 0, 0, 0.85556], + "937": [0, 0.69444, 0, 0, 0.79445], + "8211": [0, 0.45833, 0.03056, 0, 0.55], + "8212": [0, 0.45833, 0.03056, 0, 1.10001], + "8216": [0, 0.69444, 0, 0, 0.30556], + "8217": [0, 0.69444, 0, 0, 0.30556], + "8220": [0, 0.69444, 0, 0, 0.55834], + "8221": [0, 0.69444, 0, 0, 0.55834] + }, + "SansSerif-Italic": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0.05733, 0, 0.31945], + "34": [0, 0.69444, 0.00316, 0, 0.5], + "35": [0.19444, 0.69444, 0.05087, 0, 0.83334], + "36": [0.05556, 0.75, 0.11156, 0, 0.5], + "37": [0.05556, 0.75, 0.03126, 0, 0.83334], + "38": [0, 0.69444, 0.03058, 0, 0.75834], + "39": [0, 0.69444, 0.07816, 0, 0.27778], + "40": [0.25, 0.75, 0.13164, 0, 0.38889], + "41": [0.25, 0.75, 0.02536, 0, 0.38889], + "42": [0, 0.75, 0.11775, 0, 0.5], + "43": [0.08333, 0.58333, 0.02536, 0, 0.77778], + "44": [0.125, 0.08333, 0, 0, 0.27778], + "45": [0, 0.44444, 0.01946, 0, 0.33333], + "46": [0, 0.08333, 0, 0, 0.27778], + "47": [0.25, 0.75, 0.13164, 0, 0.5], + "48": [0, 0.65556, 0.11156, 0, 0.5], + "49": [0, 0.65556, 0.11156, 0, 0.5], + "50": [0, 0.65556, 0.11156, 0, 0.5], + "51": [0, 0.65556, 0.11156, 0, 0.5], + "52": [0, 0.65556, 0.11156, 0, 0.5], + "53": [0, 0.65556, 0.11156, 0, 0.5], + "54": [0, 0.65556, 0.11156, 0, 0.5], + "55": [0, 0.65556, 0.11156, 0, 0.5], + "56": [0, 0.65556, 0.11156, 0, 0.5], + "57": [0, 0.65556, 0.11156, 0, 0.5], + "58": [0, 0.44444, 0.02502, 0, 0.27778], + "59": [0.125, 0.44444, 0.02502, 0, 0.27778], + "61": [-0.13, 0.37, 0.05087, 0, 0.77778], + "63": [0, 0.69444, 0.11809, 0, 0.47222], + "64": [0, 0.69444, 0.07555, 0, 0.66667], + "65": [0, 0.69444, 0, 0, 0.66667], + "66": [0, 0.69444, 0.08293, 0, 0.66667], + "67": [0, 0.69444, 0.11983, 0, 0.63889], + "68": [0, 0.69444, 0.07555, 0, 0.72223], + "69": [0, 0.69444, 0.11983, 0, 0.59722], + "70": [0, 0.69444, 0.13372, 0, 0.56945], + "71": [0, 0.69444, 0.11983, 0, 0.66667], + "72": [0, 0.69444, 0.08094, 0, 0.70834], + "73": [0, 0.69444, 0.13372, 0, 0.27778], + "74": [0, 0.69444, 0.08094, 0, 0.47222], + "75": [0, 0.69444, 0.11983, 0, 0.69445], + "76": [0, 0.69444, 0, 0, 0.54167], + "77": [0, 0.69444, 0.08094, 0, 0.875], + "78": [0, 0.69444, 0.08094, 0, 0.70834], + "79": [0, 0.69444, 0.07555, 0, 0.73611], + "80": [0, 0.69444, 0.08293, 0, 0.63889], + "81": [0.125, 0.69444, 0.07555, 0, 0.73611], + "82": [0, 0.69444, 0.08293, 0, 0.64584], + "83": [0, 0.69444, 0.09205, 0, 0.55556], + "84": [0, 0.69444, 0.13372, 0, 0.68056], + "85": [0, 0.69444, 0.08094, 0, 0.6875], + "86": [0, 0.69444, 0.1615, 0, 0.66667], + "87": [0, 0.69444, 0.1615, 0, 0.94445], + "88": [0, 0.69444, 0.13372, 0, 0.66667], + "89": [0, 0.69444, 0.17261, 0, 0.66667], + "90": [0, 0.69444, 0.11983, 0, 0.61111], + "91": [0.25, 0.75, 0.15942, 0, 0.28889], + "93": [0.25, 0.75, 0.08719, 0, 0.28889], + "94": [0, 0.69444, 0.0799, 0, 0.5], + "95": [0.35, 0.09444, 0.08616, 0, 0.5], + "97": [0, 0.44444, 0.00981, 0, 0.48056], + "98": [0, 0.69444, 0.03057, 0, 0.51667], + "99": [0, 0.44444, 0.08336, 0, 0.44445], + "100": [0, 0.69444, 0.09483, 0, 0.51667], + "101": [0, 0.44444, 0.06778, 0, 0.44445], + "102": [0, 0.69444, 0.21705, 0, 0.30556], + "103": [0.19444, 0.44444, 0.10836, 0, 0.5], + "104": [0, 0.69444, 0.01778, 0, 0.51667], + "105": [0, 0.67937, 0.09718, 0, 0.23889], + "106": [0.19444, 0.67937, 0.09162, 0, 0.26667], + "107": [0, 0.69444, 0.08336, 0, 0.48889], + "108": [0, 0.69444, 0.09483, 0, 0.23889], + "109": [0, 0.44444, 0.01778, 0, 0.79445], + "110": [0, 0.44444, 0.01778, 0, 0.51667], + "111": [0, 0.44444, 0.06613, 0, 0.5], + "112": [0.19444, 0.44444, 0.0389, 0, 0.51667], + "113": [0.19444, 0.44444, 0.04169, 0, 0.51667], + "114": [0, 0.44444, 0.10836, 0, 0.34167], + "115": [0, 0.44444, 0.0778, 0, 0.38333], + "116": [0, 0.57143, 0.07225, 0, 0.36111], + "117": [0, 0.44444, 0.04169, 0, 0.51667], + "118": [0, 0.44444, 0.10836, 0, 0.46111], + "119": [0, 0.44444, 0.10836, 0, 0.68334], + "120": [0, 0.44444, 0.09169, 0, 0.46111], + "121": [0.19444, 0.44444, 0.10836, 0, 0.46111], + "122": [0, 0.44444, 0.08752, 0, 0.43472], + "126": [0.35, 0.32659, 0.08826, 0, 0.5], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.67937, 0.06385, 0, 0.5], + "176": [0, 0.69444, 0, 0, 0.73752], + "184": [0.17014, 0, 0, 0, 0.44445], + "305": [0, 0.44444, 0.04169, 0, 0.23889], + "567": [0.19444, 0.44444, 0.04169, 0, 0.26667], + "710": [0, 0.69444, 0.0799, 0, 0.5], + "711": [0, 0.63194, 0.08432, 0, 0.5], + "713": [0, 0.60889, 0.08776, 0, 0.5], + "714": [0, 0.69444, 0.09205, 0, 0.5], + "715": [0, 0.69444, 0, 0, 0.5], + "728": [0, 0.69444, 0.09483, 0, 0.5], + "729": [0, 0.67937, 0.07774, 0, 0.27778], + "730": [0, 0.69444, 0, 0, 0.73752], + "732": [0, 0.67659, 0.08826, 0, 0.5], + "733": [0, 0.69444, 0.09205, 0, 0.5], + "915": [0, 0.69444, 0.13372, 0, 0.54167], + "916": [0, 0.69444, 0, 0, 0.83334], + "920": [0, 0.69444, 0.07555, 0, 0.77778], + "923": [0, 0.69444, 0, 0, 0.61111], + "926": [0, 0.69444, 0.12816, 0, 0.66667], + "928": [0, 0.69444, 0.08094, 0, 0.70834], + "931": [0, 0.69444, 0.11983, 0, 0.72222], + "933": [0, 0.69444, 0.09031, 0, 0.77778], + "934": [0, 0.69444, 0.04603, 0, 0.72222], + "936": [0, 0.69444, 0.09031, 0, 0.77778], + "937": [0, 0.69444, 0.08293, 0, 0.72222], + "8211": [0, 0.44444, 0.08616, 0, 0.5], + "8212": [0, 0.44444, 0.08616, 0, 1.0], + "8216": [0, 0.69444, 0.07816, 0, 0.27778], + "8217": [0, 0.69444, 0.07816, 0, 0.27778], + "8220": [0, 0.69444, 0.14205, 0, 0.5], + "8221": [0, 0.69444, 0.00316, 0, 0.5] + }, + "SansSerif-Regular": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.31945], + "34": [0, 0.69444, 0, 0, 0.5], + "35": [0.19444, 0.69444, 0, 0, 0.83334], + "36": [0.05556, 0.75, 0, 0, 0.5], + "37": [0.05556, 0.75, 0, 0, 0.83334], + "38": [0, 0.69444, 0, 0, 0.75834], + "39": [0, 0.69444, 0, 0, 0.27778], + "40": [0.25, 0.75, 0, 0, 0.38889], + "41": [0.25, 0.75, 0, 0, 0.38889], + "42": [0, 0.75, 0, 0, 0.5], + "43": [0.08333, 0.58333, 0, 0, 0.77778], + "44": [0.125, 0.08333, 0, 0, 0.27778], + "45": [0, 0.44444, 0, 0, 0.33333], + "46": [0, 0.08333, 0, 0, 0.27778], + "47": [0.25, 0.75, 0, 0, 0.5], + "48": [0, 0.65556, 0, 0, 0.5], + "49": [0, 0.65556, 0, 0, 0.5], + "50": [0, 0.65556, 0, 0, 0.5], + "51": [0, 0.65556, 0, 0, 0.5], + "52": [0, 0.65556, 0, 0, 0.5], + "53": [0, 0.65556, 0, 0, 0.5], + "54": [0, 0.65556, 0, 0, 0.5], + "55": [0, 0.65556, 0, 0, 0.5], + "56": [0, 0.65556, 0, 0, 0.5], + "57": [0, 0.65556, 0, 0, 0.5], + "58": [0, 0.44444, 0, 0, 0.27778], + "59": [0.125, 0.44444, 0, 0, 0.27778], + "61": [-0.13, 0.37, 0, 0, 0.77778], + "63": [0, 0.69444, 0, 0, 0.47222], + "64": [0, 0.69444, 0, 0, 0.66667], + "65": [0, 0.69444, 0, 0, 0.66667], + "66": [0, 0.69444, 0, 0, 0.66667], + "67": [0, 0.69444, 0, 0, 0.63889], + "68": [0, 0.69444, 0, 0, 0.72223], + "69": [0, 0.69444, 0, 0, 0.59722], + "70": [0, 0.69444, 0, 0, 0.56945], + "71": [0, 0.69444, 0, 0, 0.66667], + "72": [0, 0.69444, 0, 0, 0.70834], + "73": [0, 0.69444, 0, 0, 0.27778], + "74": [0, 0.69444, 0, 0, 0.47222], + "75": [0, 0.69444, 0, 0, 0.69445], + "76": [0, 0.69444, 0, 0, 0.54167], + "77": [0, 0.69444, 0, 0, 0.875], + "78": [0, 0.69444, 0, 0, 0.70834], + "79": [0, 0.69444, 0, 0, 0.73611], + "80": [0, 0.69444, 0, 0, 0.63889], + "81": [0.125, 0.69444, 0, 0, 0.73611], + "82": [0, 0.69444, 0, 0, 0.64584], + "83": [0, 0.69444, 0, 0, 0.55556], + "84": [0, 0.69444, 0, 0, 0.68056], + "85": [0, 0.69444, 0, 0, 0.6875], + "86": [0, 0.69444, 0.01389, 0, 0.66667], + "87": [0, 0.69444, 0.01389, 0, 0.94445], + "88": [0, 0.69444, 0, 0, 0.66667], + "89": [0, 0.69444, 0.025, 0, 0.66667], + "90": [0, 0.69444, 0, 0, 0.61111], + "91": [0.25, 0.75, 0, 0, 0.28889], + "93": [0.25, 0.75, 0, 0, 0.28889], + "94": [0, 0.69444, 0, 0, 0.5], + "95": [0.35, 0.09444, 0.02778, 0, 0.5], + "97": [0, 0.44444, 0, 0, 0.48056], + "98": [0, 0.69444, 0, 0, 0.51667], + "99": [0, 0.44444, 0, 0, 0.44445], + "100": [0, 0.69444, 0, 0, 0.51667], + "101": [0, 0.44444, 0, 0, 0.44445], + "102": [0, 0.69444, 0.06944, 0, 0.30556], + "103": [0.19444, 0.44444, 0.01389, 0, 0.5], + "104": [0, 0.69444, 0, 0, 0.51667], + "105": [0, 0.67937, 0, 0, 0.23889], + "106": [0.19444, 0.67937, 0, 0, 0.26667], + "107": [0, 0.69444, 0, 0, 0.48889], + "108": [0, 0.69444, 0, 0, 0.23889], + "109": [0, 0.44444, 0, 0, 0.79445], + "110": [0, 0.44444, 0, 0, 0.51667], + "111": [0, 0.44444, 0, 0, 0.5], + "112": [0.19444, 0.44444, 0, 0, 0.51667], + "113": [0.19444, 0.44444, 0, 0, 0.51667], + "114": [0, 0.44444, 0.01389, 0, 0.34167], + "115": [0, 0.44444, 0, 0, 0.38333], + "116": [0, 0.57143, 0, 0, 0.36111], + "117": [0, 0.44444, 0, 0, 0.51667], + "118": [0, 0.44444, 0.01389, 0, 0.46111], + "119": [0, 0.44444, 0.01389, 0, 0.68334], + "120": [0, 0.44444, 0, 0, 0.46111], + "121": [0.19444, 0.44444, 0.01389, 0, 0.46111], + "122": [0, 0.44444, 0, 0, 0.43472], + "126": [0.35, 0.32659, 0, 0, 0.5], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.67937, 0, 0, 0.5], + "176": [0, 0.69444, 0, 0, 0.66667], + "184": [0.17014, 0, 0, 0, 0.44445], + "305": [0, 0.44444, 0, 0, 0.23889], + "567": [0.19444, 0.44444, 0, 0, 0.26667], + "710": [0, 0.69444, 0, 0, 0.5], + "711": [0, 0.63194, 0, 0, 0.5], + "713": [0, 0.60889, 0, 0, 0.5], + "714": [0, 0.69444, 0, 0, 0.5], + "715": [0, 0.69444, 0, 0, 0.5], + "728": [0, 0.69444, 0, 0, 0.5], + "729": [0, 0.67937, 0, 0, 0.27778], + "730": [0, 0.69444, 0, 0, 0.66667], + "732": [0, 0.67659, 0, 0, 0.5], + "733": [0, 0.69444, 0, 0, 0.5], + "915": [0, 0.69444, 0, 0, 0.54167], + "916": [0, 0.69444, 0, 0, 0.83334], + "920": [0, 0.69444, 0, 0, 0.77778], + "923": [0, 0.69444, 0, 0, 0.61111], + "926": [0, 0.69444, 0, 0, 0.66667], + "928": [0, 0.69444, 0, 0, 0.70834], + "931": [0, 0.69444, 0, 0, 0.72222], + "933": [0, 0.69444, 0, 0, 0.77778], + "934": [0, 0.69444, 0, 0, 0.72222], + "936": [0, 0.69444, 0, 0, 0.77778], + "937": [0, 0.69444, 0, 0, 0.72222], + "8211": [0, 0.44444, 0.02778, 0, 0.5], + "8212": [0, 0.44444, 0.02778, 0, 1.0], + "8216": [0, 0.69444, 0, 0, 0.27778], + "8217": [0, 0.69444, 0, 0, 0.27778], + "8220": [0, 0.69444, 0, 0, 0.5], + "8221": [0, 0.69444, 0, 0, 0.5] + }, + "Script-Regular": { + "32": [0, 0, 0, 0, 0.25], + "65": [0, 0.7, 0.22925, 0, 0.80253], + "66": [0, 0.7, 0.04087, 0, 0.90757], + "67": [0, 0.7, 0.1689, 0, 0.66619], + "68": [0, 0.7, 0.09371, 0, 0.77443], + "69": [0, 0.7, 0.18583, 0, 0.56162], + "70": [0, 0.7, 0.13634, 0, 0.89544], + "71": [0, 0.7, 0.17322, 0, 0.60961], + "72": [0, 0.7, 0.29694, 0, 0.96919], + "73": [0, 0.7, 0.19189, 0, 0.80907], + "74": [0.27778, 0.7, 0.19189, 0, 1.05159], + "75": [0, 0.7, 0.31259, 0, 0.91364], + "76": [0, 0.7, 0.19189, 0, 0.87373], + "77": [0, 0.7, 0.15981, 0, 1.08031], + "78": [0, 0.7, 0.3525, 0, 0.9015], + "79": [0, 0.7, 0.08078, 0, 0.73787], + "80": [0, 0.7, 0.08078, 0, 1.01262], + "81": [0, 0.7, 0.03305, 0, 0.88282], + "82": [0, 0.7, 0.06259, 0, 0.85], + "83": [0, 0.7, 0.19189, 0, 0.86767], + "84": [0, 0.7, 0.29087, 0, 0.74697], + "85": [0, 0.7, 0.25815, 0, 0.79996], + "86": [0, 0.7, 0.27523, 0, 0.62204], + "87": [0, 0.7, 0.27523, 0, 0.80532], + "88": [0, 0.7, 0.26006, 0, 0.94445], + "89": [0, 0.7, 0.2939, 0, 0.70961], + "90": [0, 0.7, 0.24037, 0, 0.8212], + "160": [0, 0, 0, 0, 0.25] + }, + "Size1-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [0.35001, 0.85, 0, 0, 0.45834], + "41": [0.35001, 0.85, 0, 0, 0.45834], + "47": [0.35001, 0.85, 0, 0, 0.57778], + "91": [0.35001, 0.85, 0, 0, 0.41667], + "92": [0.35001, 0.85, 0, 0, 0.57778], + "93": [0.35001, 0.85, 0, 0, 0.41667], + "123": [0.35001, 0.85, 0, 0, 0.58334], + "125": [0.35001, 0.85, 0, 0, 0.58334], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.72222, 0, 0, 0.55556], + "732": [0, 0.72222, 0, 0, 0.55556], + "770": [0, 0.72222, 0, 0, 0.55556], + "771": [0, 0.72222, 0, 0, 0.55556], + "8214": [-0.00099, 0.601, 0, 0, 0.77778], + "8593": [1e-05, 0.6, 0, 0, 0.66667], + "8595": [1e-05, 0.6, 0, 0, 0.66667], + "8657": [1e-05, 0.6, 0, 0, 0.77778], + "8659": [1e-05, 0.6, 0, 0, 0.77778], + "8719": [0.25001, 0.75, 0, 0, 0.94445], + "8720": [0.25001, 0.75, 0, 0, 0.94445], + "8721": [0.25001, 0.75, 0, 0, 1.05556], + "8730": [0.35001, 0.85, 0, 0, 1.0], + "8739": [-0.00599, 0.606, 0, 0, 0.33333], + "8741": [-0.00599, 0.606, 0, 0, 0.55556], + "8747": [0.30612, 0.805, 0.19445, 0, 0.47222], + "8748": [0.306, 0.805, 0.19445, 0, 0.47222], + "8749": [0.306, 0.805, 0.19445, 0, 0.47222], + "8750": [0.30612, 0.805, 0.19445, 0, 0.47222], + "8896": [0.25001, 0.75, 0, 0, 0.83334], + "8897": [0.25001, 0.75, 0, 0, 0.83334], + "8898": [0.25001, 0.75, 0, 0, 0.83334], + "8899": [0.25001, 0.75, 0, 0, 0.83334], + "8968": [0.35001, 0.85, 0, 0, 0.47222], + "8969": [0.35001, 0.85, 0, 0, 0.47222], + "8970": [0.35001, 0.85, 0, 0, 0.47222], + "8971": [0.35001, 0.85, 0, 0, 0.47222], + "9168": [-0.00099, 0.601, 0, 0, 0.66667], + "10216": [0.35001, 0.85, 0, 0, 0.47222], + "10217": [0.35001, 0.85, 0, 0, 0.47222], + "10752": [0.25001, 0.75, 0, 0, 1.11111], + "10753": [0.25001, 0.75, 0, 0, 1.11111], + "10754": [0.25001, 0.75, 0, 0, 1.11111], + "10756": [0.25001, 0.75, 0, 0, 0.83334], + "10758": [0.25001, 0.75, 0, 0, 0.83334] + }, + "Size2-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [0.65002, 1.15, 0, 0, 0.59722], + "41": [0.65002, 1.15, 0, 0, 0.59722], + "47": [0.65002, 1.15, 0, 0, 0.81111], + "91": [0.65002, 1.15, 0, 0, 0.47222], + "92": [0.65002, 1.15, 0, 0, 0.81111], + "93": [0.65002, 1.15, 0, 0, 0.47222], + "123": [0.65002, 1.15, 0, 0, 0.66667], + "125": [0.65002, 1.15, 0, 0, 0.66667], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.75, 0, 0, 1.0], + "732": [0, 0.75, 0, 0, 1.0], + "770": [0, 0.75, 0, 0, 1.0], + "771": [0, 0.75, 0, 0, 1.0], + "8719": [0.55001, 1.05, 0, 0, 1.27778], + "8720": [0.55001, 1.05, 0, 0, 1.27778], + "8721": [0.55001, 1.05, 0, 0, 1.44445], + "8730": [0.65002, 1.15, 0, 0, 1.0], + "8747": [0.86225, 1.36, 0.44445, 0, 0.55556], + "8748": [0.862, 1.36, 0.44445, 0, 0.55556], + "8749": [0.862, 1.36, 0.44445, 0, 0.55556], + "8750": [0.86225, 1.36, 0.44445, 0, 0.55556], + "8896": [0.55001, 1.05, 0, 0, 1.11111], + "8897": [0.55001, 1.05, 0, 0, 1.11111], + "8898": [0.55001, 1.05, 0, 0, 1.11111], + "8899": [0.55001, 1.05, 0, 0, 1.11111], + "8968": [0.65002, 1.15, 0, 0, 0.52778], + "8969": [0.65002, 1.15, 0, 0, 0.52778], + "8970": [0.65002, 1.15, 0, 0, 0.52778], + "8971": [0.65002, 1.15, 0, 0, 0.52778], + "10216": [0.65002, 1.15, 0, 0, 0.61111], + "10217": [0.65002, 1.15, 0, 0, 0.61111], + "10752": [0.55001, 1.05, 0, 0, 1.51112], + "10753": [0.55001, 1.05, 0, 0, 1.51112], + "10754": [0.55001, 1.05, 0, 0, 1.51112], + "10756": [0.55001, 1.05, 0, 0, 1.11111], + "10758": [0.55001, 1.05, 0, 0, 1.11111] + }, + "Size3-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [0.95003, 1.45, 0, 0, 0.73611], + "41": [0.95003, 1.45, 0, 0, 0.73611], + "47": [0.95003, 1.45, 0, 0, 1.04445], + "91": [0.95003, 1.45, 0, 0, 0.52778], + "92": [0.95003, 1.45, 0, 0, 1.04445], + "93": [0.95003, 1.45, 0, 0, 0.52778], + "123": [0.95003, 1.45, 0, 0, 0.75], + "125": [0.95003, 1.45, 0, 0, 0.75], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.75, 0, 0, 1.44445], + "732": [0, 0.75, 0, 0, 1.44445], + "770": [0, 0.75, 0, 0, 1.44445], + "771": [0, 0.75, 0, 0, 1.44445], + "8730": [0.95003, 1.45, 0, 0, 1.0], + "8968": [0.95003, 1.45, 0, 0, 0.58334], + "8969": [0.95003, 1.45, 0, 0, 0.58334], + "8970": [0.95003, 1.45, 0, 0, 0.58334], + "8971": [0.95003, 1.45, 0, 0, 0.58334], + "10216": [0.95003, 1.45, 0, 0, 0.75], + "10217": [0.95003, 1.45, 0, 0, 0.75] + }, + "Size4-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [1.25003, 1.75, 0, 0, 0.79167], + "41": [1.25003, 1.75, 0, 0, 0.79167], + "47": [1.25003, 1.75, 0, 0, 1.27778], + "91": [1.25003, 1.75, 0, 0, 0.58334], + "92": [1.25003, 1.75, 0, 0, 1.27778], + "93": [1.25003, 1.75, 0, 0, 0.58334], + "123": [1.25003, 1.75, 0, 0, 0.80556], + "125": [1.25003, 1.75, 0, 0, 0.80556], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.825, 0, 0, 1.8889], + "732": [0, 0.825, 0, 0, 1.8889], + "770": [0, 0.825, 0, 0, 1.8889], + "771": [0, 0.825, 0, 0, 1.8889], + "8730": [1.25003, 1.75, 0, 0, 1.0], + "8968": [1.25003, 1.75, 0, 0, 0.63889], + "8969": [1.25003, 1.75, 0, 0, 0.63889], + "8970": [1.25003, 1.75, 0, 0, 0.63889], + "8971": [1.25003, 1.75, 0, 0, 0.63889], + "9115": [0.64502, 1.155, 0, 0, 0.875], + "9116": [1e-05, 0.6, 0, 0, 0.875], + "9117": [0.64502, 1.155, 0, 0, 0.875], + "9118": [0.64502, 1.155, 0, 0, 0.875], + "9119": [1e-05, 0.6, 0, 0, 0.875], + "9120": [0.64502, 1.155, 0, 0, 0.875], + "9121": [0.64502, 1.155, 0, 0, 0.66667], + "9122": [-0.00099, 0.601, 0, 0, 0.66667], + "9123": [0.64502, 1.155, 0, 0, 0.66667], + "9124": [0.64502, 1.155, 0, 0, 0.66667], + "9125": [-0.00099, 0.601, 0, 0, 0.66667], + "9126": [0.64502, 1.155, 0, 0, 0.66667], + "9127": [1e-05, 0.9, 0, 0, 0.88889], + "9128": [0.65002, 1.15, 0, 0, 0.88889], + "9129": [0.90001, 0, 0, 0, 0.88889], + "9130": [0, 0.3, 0, 0, 0.88889], + "9131": [1e-05, 0.9, 0, 0, 0.88889], + "9132": [0.65002, 1.15, 0, 0, 0.88889], + "9133": [0.90001, 0, 0, 0, 0.88889], + "9143": [0.88502, 0.915, 0, 0, 1.05556], + "10216": [1.25003, 1.75, 0, 0, 0.80556], + "10217": [1.25003, 1.75, 0, 0, 0.80556], + "57344": [-0.00499, 0.605, 0, 0, 1.05556], + "57345": [-0.00499, 0.605, 0, 0, 1.05556], + "57680": [0, 0.12, 0, 0, 0.45], + "57681": [0, 0.12, 0, 0, 0.45], + "57682": [0, 0.12, 0, 0, 0.45], + "57683": [0, 0.12, 0, 0, 0.45] + }, + "Typewriter-Regular": { + "32": [0, 0, 0, 0, 0.525], + "33": [0, 0.61111, 0, 0, 0.525], + "34": [0, 0.61111, 0, 0, 0.525], + "35": [0, 0.61111, 0, 0, 0.525], + "36": [0.08333, 0.69444, 0, 0, 0.525], + "37": [0.08333, 0.69444, 0, 0, 0.525], + "38": [0, 0.61111, 0, 0, 0.525], + "39": [0, 0.61111, 0, 0, 0.525], + "40": [0.08333, 0.69444, 0, 0, 0.525], + "41": [0.08333, 0.69444, 0, 0, 0.525], + "42": [0, 0.52083, 0, 0, 0.525], + "43": [-0.08056, 0.53055, 0, 0, 0.525], + "44": [0.13889, 0.125, 0, 0, 0.525], + "45": [-0.08056, 0.53055, 0, 0, 0.525], + "46": [0, 0.125, 0, 0, 0.525], + "47": [0.08333, 0.69444, 0, 0, 0.525], + "48": [0, 0.61111, 0, 0, 0.525], + "49": [0, 0.61111, 0, 0, 0.525], + "50": [0, 0.61111, 0, 0, 0.525], + "51": [0, 0.61111, 0, 0, 0.525], + "52": [0, 0.61111, 0, 0, 0.525], + "53": [0, 0.61111, 0, 0, 0.525], + "54": [0, 0.61111, 0, 0, 0.525], + "55": [0, 0.61111, 0, 0, 0.525], + "56": [0, 0.61111, 0, 0, 0.525], + "57": [0, 0.61111, 0, 0, 0.525], + "58": [0, 0.43056, 0, 0, 0.525], + "59": [0.13889, 0.43056, 0, 0, 0.525], + "60": [-0.05556, 0.55556, 0, 0, 0.525], + "61": [-0.19549, 0.41562, 0, 0, 0.525], + "62": [-0.05556, 0.55556, 0, 0, 0.525], + "63": [0, 0.61111, 0, 0, 0.525], + "64": [0, 0.61111, 0, 0, 0.525], + "65": [0, 0.61111, 0, 0, 0.525], + "66": [0, 0.61111, 0, 0, 0.525], + "67": [0, 0.61111, 0, 0, 0.525], + "68": [0, 0.61111, 0, 0, 0.525], + "69": [0, 0.61111, 0, 0, 0.525], + "70": [0, 0.61111, 0, 0, 0.525], + "71": [0, 0.61111, 0, 0, 0.525], + "72": [0, 0.61111, 0, 0, 0.525], + "73": [0, 0.61111, 0, 0, 0.525], + "74": [0, 0.61111, 0, 0, 0.525], + "75": [0, 0.61111, 0, 0, 0.525], + "76": [0, 0.61111, 0, 0, 0.525], + "77": [0, 0.61111, 0, 0, 0.525], + "78": [0, 0.61111, 0, 0, 0.525], + "79": [0, 0.61111, 0, 0, 0.525], + "80": [0, 0.61111, 0, 0, 0.525], + "81": [0.13889, 0.61111, 0, 0, 0.525], + "82": [0, 0.61111, 0, 0, 0.525], + "83": [0, 0.61111, 0, 0, 0.525], + "84": [0, 0.61111, 0, 0, 0.525], + "85": [0, 0.61111, 0, 0, 0.525], + "86": [0, 0.61111, 0, 0, 0.525], + "87": [0, 0.61111, 0, 0, 0.525], + "88": [0, 0.61111, 0, 0, 0.525], + "89": [0, 0.61111, 0, 0, 0.525], + "90": [0, 0.61111, 0, 0, 0.525], + "91": [0.08333, 0.69444, 0, 0, 0.525], + "92": [0.08333, 0.69444, 0, 0, 0.525], + "93": [0.08333, 0.69444, 0, 0, 0.525], + "94": [0, 0.61111, 0, 0, 0.525], + "95": [0.09514, 0, 0, 0, 0.525], + "96": [0, 0.61111, 0, 0, 0.525], + "97": [0, 0.43056, 0, 0, 0.525], + "98": [0, 0.61111, 0, 0, 0.525], + "99": [0, 0.43056, 0, 0, 0.525], + "100": [0, 0.61111, 0, 0, 0.525], + "101": [0, 0.43056, 0, 0, 0.525], + "102": [0, 0.61111, 0, 0, 0.525], + "103": [0.22222, 0.43056, 0, 0, 0.525], + "104": [0, 0.61111, 0, 0, 0.525], + "105": [0, 0.61111, 0, 0, 0.525], + "106": [0.22222, 0.61111, 0, 0, 0.525], + "107": [0, 0.61111, 0, 0, 0.525], + "108": [0, 0.61111, 0, 0, 0.525], + "109": [0, 0.43056, 0, 0, 0.525], + "110": [0, 0.43056, 0, 0, 0.525], + "111": [0, 0.43056, 0, 0, 0.525], + "112": [0.22222, 0.43056, 0, 0, 0.525], + "113": [0.22222, 0.43056, 0, 0, 0.525], + "114": [0, 0.43056, 0, 0, 0.525], + "115": [0, 0.43056, 0, 0, 0.525], + "116": [0, 0.55358, 0, 0, 0.525], + "117": [0, 0.43056, 0, 0, 0.525], + "118": [0, 0.43056, 0, 0, 0.525], + "119": [0, 0.43056, 0, 0, 0.525], + "120": [0, 0.43056, 0, 0, 0.525], + "121": [0.22222, 0.43056, 0, 0, 0.525], + "122": [0, 0.43056, 0, 0, 0.525], + "123": [0.08333, 0.69444, 0, 0, 0.525], + "124": [0.08333, 0.69444, 0, 0, 0.525], + "125": [0.08333, 0.69444, 0, 0, 0.525], + "126": [0, 0.61111, 0, 0, 0.525], + "127": [0, 0.61111, 0, 0, 0.525], + "160": [0, 0, 0, 0, 0.525], + "176": [0, 0.61111, 0, 0, 0.525], + "184": [0.19445, 0, 0, 0, 0.525], + "305": [0, 0.43056, 0, 0, 0.525], + "567": [0.22222, 0.43056, 0, 0, 0.525], + "711": [0, 0.56597, 0, 0, 0.525], + "713": [0, 0.56555, 0, 0, 0.525], + "714": [0, 0.61111, 0, 0, 0.525], + "715": [0, 0.61111, 0, 0, 0.525], + "728": [0, 0.61111, 0, 0, 0.525], + "730": [0, 0.61111, 0, 0, 0.525], + "770": [0, 0.61111, 0, 0, 0.525], + "771": [0, 0.61111, 0, 0, 0.525], + "776": [0, 0.61111, 0, 0, 0.525], + "915": [0, 0.61111, 0, 0, 0.525], + "916": [0, 0.61111, 0, 0, 0.525], + "920": [0, 0.61111, 0, 0, 0.525], + "923": [0, 0.61111, 0, 0, 0.525], + "926": [0, 0.61111, 0, 0, 0.525], + "928": [0, 0.61111, 0, 0, 0.525], + "931": [0, 0.61111, 0, 0, 0.525], + "933": [0, 0.61111, 0, 0, 0.525], + "934": [0, 0.61111, 0, 0, 0.525], + "936": [0, 0.61111, 0, 0, 0.525], + "937": [0, 0.61111, 0, 0, 0.525], + "8216": [0, 0.61111, 0, 0, 0.525], + "8217": [0, 0.61111, 0, 0, 0.525], + "8242": [0, 0.61111, 0, 0, 0.525], + "9251": [0.11111, 0.21944, 0, 0, 0.525] + } +}); +;// CONCATENATED MODULE: ./src/fontMetrics.js + + +/** + * This file contains metrics regarding fonts and individual symbols. The sigma + * and xi variables, as well as the metricMap map contain data extracted from + * TeX, TeX font metrics, and the TTF files. These data are then exposed via the + * `metrics` variable and the getCharacterMetrics function. + */ +// In TeX, there are actually three sets of dimensions, one for each of +// textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4: +// 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt). These are +// provided in the arrays below, in that order. +// +// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respectively. +// This was determined by running the following script: +// +// latex -interaction=nonstopmode \ +// '\documentclass{article}\usepackage{amsmath}\begin{document}' \ +// '$a$ \expandafter\show\the\textfont2' \ +// '\expandafter\show\the\scriptfont2' \ +// '\expandafter\show\the\scriptscriptfont2' \ +// '\stop' +// +// The metrics themselves were retrieved using the following commands: +// +// tftopl cmsy10 +// tftopl cmsy7 +// tftopl cmsy5 +// +// The output of each of these commands is quite lengthy. The only part we +// care about is the FONTDIMEN section. Each value is measured in EMs. +const sigmasAndXis = { + slant: [0.250, 0.250, 0.250], + // sigma1 + space: [0.000, 0.000, 0.000], + // sigma2 + stretch: [0.000, 0.000, 0.000], + // sigma3 + shrink: [0.000, 0.000, 0.000], + // sigma4 + xHeight: [0.431, 0.431, 0.431], + // sigma5 + quad: [1.000, 1.171, 1.472], + // sigma6 + extraSpace: [0.000, 0.000, 0.000], + // sigma7 + num1: [0.677, 0.732, 0.925], + // sigma8 + num2: [0.394, 0.384, 0.387], + // sigma9 + num3: [0.444, 0.471, 0.504], + // sigma10 + denom1: [0.686, 0.752, 1.025], + // sigma11 + denom2: [0.345, 0.344, 0.532], + // sigma12 + sup1: [0.413, 0.503, 0.504], + // sigma13 + sup2: [0.363, 0.431, 0.404], + // sigma14 + sup3: [0.289, 0.286, 0.294], + // sigma15 + sub1: [0.150, 0.143, 0.200], + // sigma16 + sub2: [0.247, 0.286, 0.400], + // sigma17 + supDrop: [0.386, 0.353, 0.494], + // sigma18 + subDrop: [0.050, 0.071, 0.100], + // sigma19 + delim1: [2.390, 1.700, 1.980], + // sigma20 + delim2: [1.010, 1.157, 1.420], + // sigma21 + axisHeight: [0.250, 0.250, 0.250], + // sigma22 + // These font metrics are extracted from TeX by using tftopl on cmex10.tfm; + // they correspond to the font parameters of the extension fonts (family 3). + // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to + // match cmex7, we'd use cmex7.tfm values for script and scriptscript + // values. + defaultRuleThickness: [0.04, 0.049, 0.049], + // xi8; cmex7: 0.049 + bigOpSpacing1: [0.111, 0.111, 0.111], + // xi9 + bigOpSpacing2: [0.166, 0.166, 0.166], + // xi10 + bigOpSpacing3: [0.2, 0.2, 0.2], + // xi11 + bigOpSpacing4: [0.6, 0.611, 0.611], + // xi12; cmex7: 0.611 + bigOpSpacing5: [0.1, 0.143, 0.143], + // xi13; cmex7: 0.143 + // The \sqrt rule width is taken from the height of the surd character. + // Since we use the same font at all sizes, this thickness doesn't scale. + sqrtRuleThickness: [0.04, 0.04, 0.04], + // This value determines how large a pt is, for metrics which are defined + // in terms of pts. + // This value is also used in katex.scss; if you change it make sure the + // values match. + ptPerEm: [10.0, 10.0, 10.0], + // The space between adjacent `|` columns in an array definition. From + // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm. + doubleRuleSep: [0.2, 0.2, 0.2], + // The width of separator lines in {array} environments. From + // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm. + arrayRuleWidth: [0.04, 0.04, 0.04], + // Two values from LaTeX source2e: + fboxsep: [0.3, 0.3, 0.3], + // 3 pt / ptPerEm + fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm + +}; // This map contains a mapping from font name and character code to character +// metrics, including height, depth, italic correction, and skew (kern from the +// character to the corresponding \skewchar) +// This map is generated via `make metrics`. It should not be changed manually. + + // These are very rough approximations. We default to Times New Roman which +// should have Latin-1 and Cyrillic characters, but may not depending on the +// operating system. The metrics do not account for extra height from the +// accents. In the case of Cyrillic characters which have both ascenders and +// descenders we prefer approximations with ascenders, primarily to prevent +// the fraction bar or root line from intersecting the glyph. +// TODO(kevinb) allow union of multiple glyph metrics for better accuracy. + +const extraCharacterMap = { + // Latin-1 + 'Å': 'A', + 'Ð': 'D', + 'Þ': 'o', + 'å': 'a', + 'ð': 'd', + 'þ': 'o', + // Cyrillic + 'А': 'A', + 'Б': 'B', + 'В': 'B', + 'Г': 'F', + 'Д': 'A', + 'Е': 'E', + 'Ж': 'K', + 'З': '3', + 'И': 'N', + 'Й': 'N', + 'К': 'K', + 'Л': 'N', + 'М': 'M', + 'Н': 'H', + 'О': 'O', + 'П': 'N', + 'Р': 'P', + 'С': 'C', + 'Т': 'T', + 'У': 'y', + 'Ф': 'O', + 'Х': 'X', + 'Ц': 'U', + 'Ч': 'h', + 'Ш': 'W', + 'Щ': 'W', + 'Ъ': 'B', + 'Ы': 'X', + 'Ь': 'B', + 'Э': '3', + 'Ю': 'X', + 'Я': 'R', + 'а': 'a', + 'б': 'b', + 'в': 'a', + 'г': 'r', + 'д': 'y', + 'е': 'e', + 'ж': 'm', + 'з': 'e', + 'и': 'n', + 'й': 'n', + 'к': 'n', + 'л': 'n', + 'м': 'm', + 'н': 'n', + 'о': 'o', + 'п': 'n', + 'р': 'p', + 'с': 'c', + 'т': 'o', + 'у': 'y', + 'ф': 'b', + 'х': 'x', + 'ц': 'n', + 'ч': 'n', + 'ш': 'w', + 'щ': 'w', + 'ъ': 'a', + 'ы': 'm', + 'ь': 'a', + 'э': 'e', + 'ю': 'm', + 'я': 'r' +}; + +/** + * This function adds new font metrics to default metricMap + * It can also override existing metrics + */ +function setFontMetrics(fontName, metrics) { + fontMetricsData[fontName] = metrics; +} +/** + * This function is a convenience function for looking up information in the + * metricMap table. It takes a character as a string, and a font. + * + * Note: the `width` property may be undefined if fontMetricsData.js wasn't + * built using `Make extended_metrics`. + */ + +function getCharacterMetrics(character, font, mode) { + if (!fontMetricsData[font]) { + throw new Error("Font metrics not found for font: " + font + "."); + } + + let ch = character.charCodeAt(0); + let metrics = fontMetricsData[font][ch]; + + if (!metrics && character[0] in extraCharacterMap) { + ch = extraCharacterMap[character[0]].charCodeAt(0); + metrics = fontMetricsData[font][ch]; + } + + if (!metrics && mode === 'text') { + // We don't typically have font metrics for Asian scripts. + // But since we support them in text mode, we need to return + // some sort of metrics. + // So if the character is in a script we support but we + // don't have metrics for it, just use the metrics for + // the Latin capital letter M. This is close enough because + // we (currently) only care about the height of the glyph + // not its width. + if (supportedCodepoint(ch)) { + metrics = fontMetricsData[font][77]; // 77 is the charcode for 'M' + } + } + + if (metrics) { + return { + depth: metrics[0], + height: metrics[1], + italic: metrics[2], + skew: metrics[3], + width: metrics[4] + }; + } +} +const fontMetricsBySizeIndex = {}; +/** + * Get the font metrics for a given size. + */ + +function getGlobalMetrics(size) { + let sizeIndex; + + if (size >= 5) { + sizeIndex = 0; + } else if (size >= 3) { + sizeIndex = 1; + } else { + sizeIndex = 2; + } + + if (!fontMetricsBySizeIndex[sizeIndex]) { + const metrics = fontMetricsBySizeIndex[sizeIndex] = { + cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18 + }; + + for (const key in sigmasAndXis) { + if (sigmasAndXis.hasOwnProperty(key)) { + metrics[key] = sigmasAndXis[key][sizeIndex]; + } + } + } + + return fontMetricsBySizeIndex[sizeIndex]; +} +;// CONCATENATED MODULE: ./src/Options.js +/** + * This file contains information about the options that the Parser carries + * around with it while parsing. Data is held in an `Options` object, and when + * recursing, a new `Options` object can be created with the `.with*` and + * `.reset` functions. + */ + +const sizeStyleMap = [// Each element contains [textsize, scriptsize, scriptscriptsize]. +// The size mappings are taken from TeX with \normalsize=10pt. +[1, 1, 1], // size1: [5, 5, 5] \tiny +[2, 1, 1], // size2: [6, 5, 5] +[3, 1, 1], // size3: [7, 5, 5] \scriptsize +[4, 2, 1], // size4: [8, 6, 5] \footnotesize +[5, 2, 1], // size5: [9, 6, 5] \small +[6, 3, 1], // size6: [10, 7, 5] \normalsize +[7, 4, 2], // size7: [12, 8, 6] \large +[8, 6, 3], // size8: [14.4, 10, 7] \Large +[9, 7, 6], // size9: [17.28, 12, 10] \LARGE +[10, 8, 7], // size10: [20.74, 14.4, 12] \huge +[11, 10, 9] // size11: [24.88, 20.74, 17.28] \HUGE +]; +const sizeMultipliers = [// fontMetrics.js:getGlobalMetrics also uses size indexes, so if +// you change size indexes, change that function. +0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488]; + +const sizeAtStyle = function (size, style) { + return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1]; +}; // In these types, "" (empty string) means "no change". + + +/** + * This is the main options class. It contains the current style, size, color, + * and font. + * + * Options objects should not be modified. To create a new Options with + * different properties, call a `.having*` method. + */ +class Options { + // A font family applies to a group of fonts (i.e. SansSerif), while a font + // represents a specific font (i.e. SansSerif Bold). + // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm + + /** + * The base size index. + */ + constructor(data) { + this.style = void 0; + this.color = void 0; + this.size = void 0; + this.textSize = void 0; + this.phantom = void 0; + this.font = void 0; + this.fontFamily = void 0; + this.fontWeight = void 0; + this.fontShape = void 0; + this.sizeMultiplier = void 0; + this.maxSize = void 0; + this.minRuleThickness = void 0; + this._fontMetrics = void 0; + this.style = data.style; + this.color = data.color; + this.size = data.size || Options.BASESIZE; + this.textSize = data.textSize || this.size; + this.phantom = !!data.phantom; + this.font = data.font || ""; + this.fontFamily = data.fontFamily || ""; + this.fontWeight = data.fontWeight || ''; + this.fontShape = data.fontShape || ''; + this.sizeMultiplier = sizeMultipliers[this.size - 1]; + this.maxSize = data.maxSize; + this.minRuleThickness = data.minRuleThickness; + this._fontMetrics = undefined; + } + /** + * Returns a new options object with the same properties as "this". Properties + * from "extension" will be copied to the new options object. + */ + + + extend(extension) { + const data = { + style: this.style, + size: this.size, + textSize: this.textSize, + color: this.color, + phantom: this.phantom, + font: this.font, + fontFamily: this.fontFamily, + fontWeight: this.fontWeight, + fontShape: this.fontShape, + maxSize: this.maxSize, + minRuleThickness: this.minRuleThickness + }; + + for (const key in extension) { + if (extension.hasOwnProperty(key)) { + data[key] = extension[key]; + } + } + + return new Options(data); + } + /** + * Return an options object with the given style. If `this.style === style`, + * returns `this`. + */ + + + havingStyle(style) { + if (this.style === style) { + return this; + } else { + return this.extend({ + style: style, + size: sizeAtStyle(this.textSize, style) + }); + } + } + /** + * Return an options object with a cramped version of the current style. If + * the current style is cramped, returns `this`. + */ + + + havingCrampedStyle() { + return this.havingStyle(this.style.cramp()); + } + /** + * Return an options object with the given size and in at least `\textstyle`. + * Returns `this` if appropriate. + */ + + + havingSize(size) { + if (this.size === size && this.textSize === size) { + return this; + } else { + return this.extend({ + style: this.style.text(), + size: size, + textSize: size, + sizeMultiplier: sizeMultipliers[size - 1] + }); + } + } + /** + * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted, + * changes to at least `\textstyle`. + */ + + + havingBaseStyle(style) { + style = style || this.style.text(); + const wantSize = sizeAtStyle(Options.BASESIZE, style); + + if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) { + return this; + } else { + return this.extend({ + style: style, + size: wantSize + }); + } + } + /** + * Remove the effect of sizing changes such as \Huge. + * Keep the effect of the current style, such as \scriptstyle. + */ + + + havingBaseSizing() { + let size; + + switch (this.style.id) { + case 4: + case 5: + size = 3; // normalsize in scriptstyle + + break; + + case 6: + case 7: + size = 1; // normalsize in scriptscriptstyle + + break; + + default: + size = 6; + // normalsize in textstyle or displaystyle + } + + return this.extend({ + style: this.style.text(), + size: size + }); + } + /** + * Create a new options object with the given color. + */ + + + withColor(color) { + return this.extend({ + color: color + }); + } + /** + * Create a new options object with "phantom" set to true. + */ + + + withPhantom() { + return this.extend({ + phantom: true + }); + } + /** + * Creates a new options object with the given math font or old text font. + * @type {[type]} + */ + + + withFont(font) { + return this.extend({ + font + }); + } + /** + * Create a new options objects with the given fontFamily. + */ + + + withTextFontFamily(fontFamily) { + return this.extend({ + fontFamily, + font: "" + }); + } + /** + * Creates a new options object with the given font weight + */ + + + withTextFontWeight(fontWeight) { + return this.extend({ + fontWeight, + font: "" + }); + } + /** + * Creates a new options object with the given font weight + */ + + + withTextFontShape(fontShape) { + return this.extend({ + fontShape, + font: "" + }); + } + /** + * Return the CSS sizing classes required to switch from enclosing options + * `oldOptions` to `this`. Returns an array of classes. + */ + + + sizingClasses(oldOptions) { + if (oldOptions.size !== this.size) { + return ["sizing", "reset-size" + oldOptions.size, "size" + this.size]; + } else { + return []; + } + } + /** + * Return the CSS sizing classes required to switch to the base size. Like + * `this.havingSize(BASESIZE).sizingClasses(this)`. + */ + + + baseSizingClasses() { + if (this.size !== Options.BASESIZE) { + return ["sizing", "reset-size" + this.size, "size" + Options.BASESIZE]; + } else { + return []; + } + } + /** + * Return the font metrics for this size. + */ + + + fontMetrics() { + if (!this._fontMetrics) { + this._fontMetrics = getGlobalMetrics(this.size); + } + + return this._fontMetrics; + } + /** + * Gets the CSS color of the current options object + */ + + + getColor() { + if (this.phantom) { + return "transparent"; + } else { + return this.color; + } + } + +} + +Options.BASESIZE = 6; +/* harmony default export */ var src_Options = (Options); +;// CONCATENATED MODULE: ./src/units.js +/** + * This file does conversion between units. In particular, it provides + * calculateSize to convert other units into ems. + */ + + // This table gives the number of TeX pts in one of each *absolute* TeX unit. +// Thus, multiplying a length by this number converts the length from units +// into pts. Dividing the result by ptPerEm gives the number of ems +// *assuming* a font size of ptPerEm (normal size, normal style). + +const ptPerUnit = { + // https://en.wikibooks.org/wiki/LaTeX/Lengths and + // https://tex.stackexchange.com/a/8263 + "pt": 1, + // TeX point + "mm": 7227 / 2540, + // millimeter + "cm": 7227 / 254, + // centimeter + "in": 72.27, + // inch + "bp": 803 / 800, + // big (PostScript) points + "pc": 12, + // pica + "dd": 1238 / 1157, + // didot + "cc": 14856 / 1157, + // cicero (12 didot) + "nd": 685 / 642, + // new didot + "nc": 1370 / 107, + // new cicero (12 new didot) + "sp": 1 / 65536, + // scaled point (TeX's internal smallest unit) + // https://tex.stackexchange.com/a/41371 + "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX + +}; // Dictionary of relative units, for fast validity testing. + +const relativeUnit = { + "ex": true, + "em": true, + "mu": true +}; + +/** + * Determine whether the specified unit (either a string defining the unit + * or a "size" parse node containing a unit field) is valid. + */ +const validUnit = function (unit) { + if (typeof unit !== "string") { + unit = unit.unit; + } + + return unit in ptPerUnit || unit in relativeUnit || unit === "ex"; +}; +/* + * Convert a "size" parse node (with numeric "number" and string "unit" fields, + * as parsed by functions.js argType "size") into a CSS em value for the + * current style/scale. `options` gives the current options. + */ + +const calculateSize = function (sizeValue, options) { + let scale; + + if (sizeValue.unit in ptPerUnit) { + // Absolute units + scale = ptPerUnit[sizeValue.unit] // Convert unit to pt + / options.fontMetrics().ptPerEm // Convert pt to CSS em + / options.sizeMultiplier; // Unscale to make absolute units + } else if (sizeValue.unit === "mu") { + // `mu` units scale with scriptstyle/scriptscriptstyle. + scale = options.fontMetrics().cssEmPerMu; + } else { + // Other relative units always refer to the *textstyle* font + // in the current size. + let unitOptions; + + if (options.style.isTight()) { + // isTight() means current style is script/scriptscript. + unitOptions = options.havingStyle(options.style.text()); + } else { + unitOptions = options; + } // TODO: In TeX these units are relative to the quad of the current + // *text* font, e.g. cmr10. KaTeX instead uses values from the + // comparably-sized *Computer Modern symbol* font. At 10pt, these + // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641; + // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$. + // TeX \showlists shows a kern of 1.13889 * fontsize; + // KaTeX shows a kern of 1.171 * fontsize. + + + if (sizeValue.unit === "ex") { + scale = unitOptions.fontMetrics().xHeight; + } else if (sizeValue.unit === "em") { + scale = unitOptions.fontMetrics().quad; + } else { + throw new src_ParseError("Invalid unit: '" + sizeValue.unit + "'"); + } + + if (unitOptions !== options) { + scale *= unitOptions.sizeMultiplier / options.sizeMultiplier; + } + } + + return Math.min(sizeValue.number * scale, options.maxSize); +}; +/** + * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. See + * https://github.com/KaTeX/KaTeX/pull/2460. + */ + +const makeEm = function (n) { + return +n.toFixed(4) + "em"; +}; +;// CONCATENATED MODULE: ./src/domTree.js +/** + * These objects store the data about the DOM nodes we create, as well as some + * extra data. They can then be transformed into real DOM nodes with the + * `toNode` function or HTML markup using `toMarkup`. They are useful for both + * storing extra properties on the nodes, as well as providing a way to easily + * work with the DOM. + * + * Similar functions for working with MathML nodes exist in mathMLTree.js. + * + * TODO: refactor `span` and `anchor` into common superclass when + * target environments support class inheritance + */ + + + + + + + +/** + * Create an HTML className based on a list of classes. In addition to joining + * with spaces, we also remove empty classes. + */ +const createClass = function (classes) { + return classes.filter(cls => cls).join(" "); +}; + +const initNode = function (classes, options, style) { + this.classes = classes || []; + this.attributes = {}; + this.height = 0; + this.depth = 0; + this.maxFontSize = 0; + this.style = style || {}; + + if (options) { + if (options.style.isTight()) { + this.classes.push("mtight"); + } + + const color = options.getColor(); + + if (color) { + this.style.color = color; + } + } +}; +/** + * Convert into an HTML node + */ + + +const toNode = function (tagName) { + const node = document.createElement(tagName); // Apply the class + + node.className = createClass(this.classes); // Apply inline styles + + for (const style in this.style) { + if (this.style.hasOwnProperty(style)) { + // $FlowFixMe Flow doesn't seem to understand span.style's type. + node.style[style] = this.style[style]; + } + } // Apply attributes + + + for (const attr in this.attributes) { + if (this.attributes.hasOwnProperty(attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } // Append the children, also as HTML nodes + + + for (let i = 0; i < this.children.length; i++) { + node.appendChild(this.children[i].toNode()); + } + + return node; +}; +/** + * https://w3c.github.io/html-reference/syntax.html#syntax-attributes + * + * > Attribute Names must consist of one or more characters + * other than the space characters, U+0000 NULL, + * '"', "'", ">", "/", "=", the control characters, + * and any characters that are not defined by Unicode. + */ + + +const invalidAttributeNameRegex = /[\s"'>/=\x00-\x1f]/; +/** + * Convert into an HTML markup string + */ + +const toMarkup = function (tagName) { + let markup = "<" + tagName; // Add the class + + if (this.classes.length) { + markup += " class=\"" + utils.escape(createClass(this.classes)) + "\""; + } + + let styles = ""; // Add the styles, after hyphenation + + for (const style in this.style) { + if (this.style.hasOwnProperty(style)) { + styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; + } + } + + if (styles) { + markup += " style=\"" + utils.escape(styles) + "\""; + } // Add the attributes + + + for (const attr in this.attributes) { + if (this.attributes.hasOwnProperty(attr)) { + if (invalidAttributeNameRegex.test(attr)) { + throw new src_ParseError("Invalid attribute name '" + attr + "'"); + } + + markup += " " + attr + "=\"" + utils.escape(this.attributes[attr]) + "\""; + } + } + + markup += ">"; // Add the markup of the children, also as markup + + for (let i = 0; i < this.children.length; i++) { + markup += this.children[i].toMarkup(); + } + + markup += ""; + return markup; +}; // Making the type below exact with all optional fields doesn't work due to +// - https://github.com/facebook/flow/issues/4582 +// - https://github.com/facebook/flow/issues/5688 +// However, since *all* fields are optional, $Shape<> works as suggested in 5688 +// above. +// This type does not include all CSS properties. Additional properties should +// be added as needed. + + +/** + * This node represents a span node, with a className, a list of children, and + * an inline style. It also contains information about its height, depth, and + * maxFontSize. + * + * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan + * otherwise. This typesafety is important when HTML builders access a span's + * children. + */ +class Span { + constructor(classes, children, options, style) { + this.children = void 0; + this.attributes = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.width = void 0; + this.maxFontSize = void 0; + this.style = void 0; + initNode.call(this, classes, options, style); + this.children = children || []; + } + /** + * Sets an arbitrary attribute on the span. Warning: use this wisely. Not + * all browsers support attributes the same, and having too many custom + * attributes is probably bad. + */ + + + setAttribute(attribute, value) { + this.attributes[attribute] = value; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + + toNode() { + return toNode.call(this, "span"); + } + + toMarkup() { + return toMarkup.call(this, "span"); + } + +} +/** + * This node represents an anchor () element with a hyperlink. See `span` + * for further details. + */ + +class Anchor { + constructor(href, classes, children, options) { + this.children = void 0; + this.attributes = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.maxFontSize = void 0; + this.style = void 0; + initNode.call(this, classes, options); + this.children = children || []; + this.setAttribute('href', href); + } + + setAttribute(attribute, value) { + this.attributes[attribute] = value; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + + toNode() { + return toNode.call(this, "a"); + } + + toMarkup() { + return toMarkup.call(this, "a"); + } + +} +/** + * This node represents an image embed () element. + */ + +class Img { + constructor(src, alt, style) { + this.src = void 0; + this.alt = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.maxFontSize = void 0; + this.style = void 0; + this.alt = alt; + this.src = src; + this.classes = ["mord"]; + this.style = style; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + + toNode() { + const node = document.createElement("img"); + node.src = this.src; + node.alt = this.alt; + node.className = "mord"; // Apply inline styles + + for (const style in this.style) { + if (this.style.hasOwnProperty(style)) { + // $FlowFixMe + node.style[style] = this.style[style]; + } + } + + return node; + } + + toMarkup() { + let markup = "\"" 0) { + span = document.createElement("span"); + span.style.marginRight = makeEm(this.italic); + } + + if (this.classes.length > 0) { + span = span || document.createElement("span"); + span.className = createClass(this.classes); + } + + for (const style in this.style) { + if (this.style.hasOwnProperty(style)) { + span = span || document.createElement("span"); // $FlowFixMe Flow doesn't seem to understand span.style's type. + + span.style[style] = this.style[style]; + } + } + + if (span) { + span.appendChild(node); + return span; + } else { + return node; + } + } + /** + * Creates markup for a symbol node. + */ + + + toMarkup() { + // TODO(alpert): More duplication than I'd like from + // span.prototype.toMarkup and symbolNode.prototype.toNode... + let needsSpan = false; + let markup = " 0) { + styles += "margin-right:" + this.italic + "em;"; + } + + for (const style in this.style) { + if (this.style.hasOwnProperty(style)) { + styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; + } + } + + if (styles) { + needsSpan = true; + markup += " style=\"" + utils.escape(styles) + "\""; + } + + const escaped = utils.escape(this.text); + + if (needsSpan) { + markup += ">"; + markup += escaped; + markup += ""; + return markup; + } else { + return escaped; + } + } + +} +/** + * SVG nodes are used to render stretchy wide elements. + */ + +class SvgNode { + constructor(children, attributes) { + this.children = void 0; + this.attributes = void 0; + this.children = children || []; + this.attributes = attributes || {}; + } + + toNode() { + const svgNS = "http://www.w3.org/2000/svg"; + const node = document.createElementNS(svgNS, "svg"); // Apply attributes + + for (const attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } + + for (let i = 0; i < this.children.length; i++) { + node.appendChild(this.children[i].toNode()); + } + + return node; + } + + toMarkup() { + let markup = ""; + } else { + return ""; + } + } + +} +class LineNode { + constructor(attributes) { + this.attributes = void 0; + this.attributes = attributes || {}; + } + + toNode() { + const svgNS = "http://www.w3.org/2000/svg"; + const node = document.createElementNS(svgNS, "line"); // Apply attributes + + for (const attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } + + return node; + } + + toMarkup() { + let markup = " but got " + String(group) + "."); + } +} +;// CONCATENATED MODULE: ./src/symbols.js +/** + * This file holds a list of all no-argument functions and single-character + * symbols (like 'a' or ';'). + * + * For each of the symbols, there are three properties they can have: + * - font (required): the font to be used for this symbol. Either "main" (the + normal font), or "ams" (the ams fonts). + * - group (required): the ParseNode group type the symbol should have (i.e. + "textord", "mathord", etc). + See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types + * - replace: the character that this symbol or function should be + * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi + * character in the main font). + * + * The outermost map in the table indicates what mode the symbols should be + * accepted in (e.g. "math" or "text"). + */ +// Some of these have a "-token" suffix since these are also used as `ParseNode` +// types for raw text tokens, and we want to avoid conflicts with higher-level +// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by +// looking up the `symbols` map. +const ATOMS = { + "bin": 1, + "close": 1, + "inner": 1, + "open": 1, + "punct": 1, + "rel": 1 +}; +const NON_ATOMS = { + "accent-token": 1, + "mathord": 1, + "op-token": 1, + "spacing": 1, + "textord": 1 +}; +const symbols = { + "math": {}, + "text": {} +}; +/* harmony default export */ var src_symbols = (symbols); +/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ + +function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) { + symbols[mode][name] = { + font, + group, + replace + }; + + if (acceptUnicodeChar && replace) { + symbols[mode][replace] = symbols[mode][name]; + } +} // Some abbreviations for commonly used strings. +// This helps minify the code, and also spotting typos using jshint. +// modes: + +const math = "math"; +const symbols_text = "text"; // fonts: + +const main = "main"; +const ams = "ams"; // groups: + +const accent = "accent-token"; +const bin = "bin"; +const symbols_close = "close"; +const inner = "inner"; +const mathord = "mathord"; +const op = "op-token"; +const symbols_open = "open"; +const punct = "punct"; +const rel = "rel"; +const spacing = "spacing"; +const textord = "textord"; // Now comes the symbol table +// Relation Symbols + +defineSymbol(math, main, rel, "\u2261", "\\equiv", true); +defineSymbol(math, main, rel, "\u227a", "\\prec", true); +defineSymbol(math, main, rel, "\u227b", "\\succ", true); +defineSymbol(math, main, rel, "\u223c", "\\sim", true); +defineSymbol(math, main, rel, "\u22a5", "\\perp"); +defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true); +defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true); +defineSymbol(math, main, rel, "\u2243", "\\simeq", true); +defineSymbol(math, main, rel, "\u2223", "\\mid", true); +defineSymbol(math, main, rel, "\u226a", "\\ll", true); +defineSymbol(math, main, rel, "\u226b", "\\gg", true); +defineSymbol(math, main, rel, "\u224d", "\\asymp", true); +defineSymbol(math, main, rel, "\u2225", "\\parallel"); +defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true); +defineSymbol(math, main, rel, "\u2323", "\\smile", true); +defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true); +defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true); +defineSymbol(math, main, rel, "\u2250", "\\doteq", true); +defineSymbol(math, main, rel, "\u2322", "\\frown", true); +defineSymbol(math, main, rel, "\u220b", "\\ni", true); +defineSymbol(math, main, rel, "\u221d", "\\propto", true); +defineSymbol(math, main, rel, "\u22a2", "\\vdash", true); +defineSymbol(math, main, rel, "\u22a3", "\\dashv", true); +defineSymbol(math, main, rel, "\u220b", "\\owns"); // Punctuation + +defineSymbol(math, main, punct, "\u002e", "\\ldotp"); +defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); // Misc Symbols + +defineSymbol(math, main, textord, "\u0023", "\\#"); +defineSymbol(symbols_text, main, textord, "\u0023", "\\#"); +defineSymbol(math, main, textord, "\u0026", "\\&"); +defineSymbol(symbols_text, main, textord, "\u0026", "\\&"); +defineSymbol(math, main, textord, "\u2135", "\\aleph", true); +defineSymbol(math, main, textord, "\u2200", "\\forall", true); +defineSymbol(math, main, textord, "\u210f", "\\hbar", true); +defineSymbol(math, main, textord, "\u2203", "\\exists", true); +defineSymbol(math, main, textord, "\u2207", "\\nabla", true); +defineSymbol(math, main, textord, "\u266d", "\\flat", true); +defineSymbol(math, main, textord, "\u2113", "\\ell", true); +defineSymbol(math, main, textord, "\u266e", "\\natural", true); +defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true); +defineSymbol(math, main, textord, "\u2118", "\\wp", true); +defineSymbol(math, main, textord, "\u266f", "\\sharp", true); +defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true); +defineSymbol(math, main, textord, "\u211c", "\\Re", true); +defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true); +defineSymbol(math, main, textord, "\u2111", "\\Im", true); +defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true); +defineSymbol(math, main, textord, "\u00a7", "\\S", true); +defineSymbol(symbols_text, main, textord, "\u00a7", "\\S"); +defineSymbol(math, main, textord, "\u00b6", "\\P", true); +defineSymbol(symbols_text, main, textord, "\u00b6", "\\P"); // Math and Text + +defineSymbol(math, main, textord, "\u2020", "\\dag"); +defineSymbol(symbols_text, main, textord, "\u2020", "\\dag"); +defineSymbol(symbols_text, main, textord, "\u2020", "\\textdagger"); +defineSymbol(math, main, textord, "\u2021", "\\ddag"); +defineSymbol(symbols_text, main, textord, "\u2021", "\\ddag"); +defineSymbol(symbols_text, main, textord, "\u2021", "\\textdaggerdbl"); // Large Delimiters + +defineSymbol(math, main, symbols_close, "\u23b1", "\\rmoustache", true); +defineSymbol(math, main, symbols_open, "\u23b0", "\\lmoustache", true); +defineSymbol(math, main, symbols_close, "\u27ef", "\\rgroup", true); +defineSymbol(math, main, symbols_open, "\u27ee", "\\lgroup", true); // Binary Operators + +defineSymbol(math, main, bin, "\u2213", "\\mp", true); +defineSymbol(math, main, bin, "\u2296", "\\ominus", true); +defineSymbol(math, main, bin, "\u228e", "\\uplus", true); +defineSymbol(math, main, bin, "\u2293", "\\sqcap", true); +defineSymbol(math, main, bin, "\u2217", "\\ast"); +defineSymbol(math, main, bin, "\u2294", "\\sqcup", true); +defineSymbol(math, main, bin, "\u25ef", "\\bigcirc", true); +defineSymbol(math, main, bin, "\u2219", "\\bullet", true); +defineSymbol(math, main, bin, "\u2021", "\\ddagger"); +defineSymbol(math, main, bin, "\u2240", "\\wr", true); +defineSymbol(math, main, bin, "\u2a3f", "\\amalg"); +defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath +// Arrow Symbols + +defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true); +defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true); +defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true); +defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true); +defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true); +defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true); +defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true); +defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true); +defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true); +defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true); +defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true); +defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true); +defineSymbol(math, main, rel, "\u2197", "\\nearrow", true); +defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true); +defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true); +defineSymbol(math, main, rel, "\u2198", "\\searrow", true); +defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true); +defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true); +defineSymbol(math, main, rel, "\u2199", "\\swarrow", true); +defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true); +defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true); +defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true); +defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true); // AMS Negated Binary Relations + +defineSymbol(math, ams, rel, "\u226e", "\\nless", true); // Symbol names preceded by "@" each have a corresponding macro. + +defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant"); +defineSymbol(math, ams, rel, "\ue011", "\\@nleqq"); +defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true); +defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true); +defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq"); +defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true); +defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true); +defineSymbol(math, ams, rel, "\u2280", "\\nprec", true); // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true); +defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true); +defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true); +defineSymbol(math, ams, rel, "\u2241", "\\nsim", true); +defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid"); +defineSymbol(math, ams, rel, "\u2224", "\\nmid", true); +defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true); +defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true); +defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft"); +defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true); +defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true); +defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq"); +defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true); +defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq"); +defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true); +defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant"); +defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq"); +defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true); +defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true); +defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq"); +defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true); +defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true); +defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true); // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true); +defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true); +defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true); // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u2246", "\\ncong", true); +defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel"); +defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true); +defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true); +defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright"); +defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true); +defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq"); +defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true); +defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq"); +defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true); +defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq"); +defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true); +defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true); +defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true); +defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq"); +defineSymbol(math, ams, bin, "\u22b4", "\\unlhd"); +defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); // AMS Negated Arrows + +defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true); +defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true); +defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true); +defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true); +defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true); +defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true); // AMS Misc + +defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle"); +defineSymbol(math, ams, textord, "\u210f", "\\hslash"); +defineSymbol(math, ams, textord, "\u25bd", "\\triangledown"); +defineSymbol(math, ams, textord, "\u25ca", "\\lozenge"); +defineSymbol(math, ams, textord, "\u24c8", "\\circledS"); +defineSymbol(math, ams, textord, "\u00ae", "\\circledR"); +defineSymbol(symbols_text, ams, textord, "\u00ae", "\\circledR"); +defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true); +defineSymbol(math, ams, textord, "\u2204", "\\nexists"); +defineSymbol(math, ams, textord, "\u2127", "\\mho"); +defineSymbol(math, ams, textord, "\u2132", "\\Finv", true); +defineSymbol(math, ams, textord, "\u2141", "\\Game", true); +defineSymbol(math, ams, textord, "\u2035", "\\backprime"); +defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle"); +defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown"); +defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare"); +defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge"); +defineSymbol(math, ams, textord, "\u2605", "\\bigstar"); +defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true); +defineSymbol(math, ams, textord, "\u2201", "\\complement", true); // unicode-math maps U+F0 to \matheth. We map to AMS function \eth + +defineSymbol(math, ams, textord, "\u00f0", "\\eth", true); +defineSymbol(symbols_text, main, textord, "\u00f0", "\u00f0"); +defineSymbol(math, ams, textord, "\u2571", "\\diagup"); +defineSymbol(math, ams, textord, "\u2572", "\\diagdown"); +defineSymbol(math, ams, textord, "\u25a1", "\\square"); +defineSymbol(math, ams, textord, "\u25a1", "\\Box"); +defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen + +defineSymbol(math, ams, textord, "\u00a5", "\\yen", true); +defineSymbol(symbols_text, ams, textord, "\u00a5", "\\yen", true); +defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true); +defineSymbol(symbols_text, ams, textord, "\u2713", "\\checkmark"); // AMS Hebrew + +defineSymbol(math, ams, textord, "\u2136", "\\beth", true); +defineSymbol(math, ams, textord, "\u2138", "\\daleth", true); +defineSymbol(math, ams, textord, "\u2137", "\\gimel", true); // AMS Greek + +defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true); +defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); // AMS Delimiters + +defineSymbol(math, ams, symbols_open, "\u250c", "\\@ulcorner", true); +defineSymbol(math, ams, symbols_close, "\u2510", "\\@urcorner", true); +defineSymbol(math, ams, symbols_open, "\u2514", "\\@llcorner", true); +defineSymbol(math, ams, symbols_close, "\u2518", "\\@lrcorner", true); // AMS Binary Relations + +defineSymbol(math, ams, rel, "\u2266", "\\leqq", true); +defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true); +defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true); +defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true); +defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true); +defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true); +defineSymbol(math, ams, bin, "\u22d6", "\\lessdot"); +defineSymbol(math, ams, rel, "\u22d8", "\\lll", true); +defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true); +defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true); +defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true); +defineSymbol(math, ams, rel, "\u2251", "\\doteqdot"); +defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true); +defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true); +defineSymbol(math, ams, rel, "\u223d", "\\backsim", true); +defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true); +defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true); +defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true); +defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true); +defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true); +defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true); +defineSymbol(math, ams, rel, "\u227e", "\\precsim", true); +defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true); +defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft"); +defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq"); +defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true); +defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true); +defineSymbol(math, ams, rel, "\u2323", "\\smallsmile"); +defineSymbol(math, ams, rel, "\u2322", "\\smallfrown"); +defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true); +defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true); +defineSymbol(math, ams, rel, "\u2267", "\\geqq", true); +defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true); +defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true); +defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true); +defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true); +defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot"); +defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true); +defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true); +defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true); +defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true); +defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true); +defineSymbol(math, ams, rel, "\u2257", "\\circeq", true); +defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true); +defineSymbol(math, ams, rel, "\u223c", "\\thicksim"); +defineSymbol(math, ams, rel, "\u2248", "\\thickapprox"); +defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true); +defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true); +defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true); +defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true); +defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true); +defineSymbol(math, ams, rel, "\u227f", "\\succsim", true); +defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true); +defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright"); +defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq"); +defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true); +defineSymbol(math, ams, rel, "\u2223", "\\shortmid"); +defineSymbol(math, ams, rel, "\u2225", "\\shortparallel"); +defineSymbol(math, ams, rel, "\u226c", "\\between", true); +defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true); +defineSymbol(math, ams, rel, "\u221d", "\\varpropto"); +defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); // unicode-math says that \therefore is a mathord atom. +// We kept the amssymb atom type, which is rel. + +defineSymbol(math, ams, rel, "\u2234", "\\therefore", true); +defineSymbol(math, ams, rel, "\u220d", "\\backepsilon"); +defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); // unicode-math says that \because is a mathord atom. +// We kept the amssymb atom type, which is rel. + +defineSymbol(math, ams, rel, "\u2235", "\\because", true); +defineSymbol(math, ams, rel, "\u22d8", "\\llless"); +defineSymbol(math, ams, rel, "\u22d9", "\\gggtr"); +defineSymbol(math, ams, bin, "\u22b2", "\\lhd"); +defineSymbol(math, ams, bin, "\u22b3", "\\rhd"); +defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true); +defineSymbol(math, main, rel, "\u22c8", "\\Join"); +defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true); // AMS Binary Operators + +defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true); +defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus"); +defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true); +defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true); +defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true); +defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true); +defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true); +defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true); +defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true); +defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true); +defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true); +defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true); +defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true); +defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true); +defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true); +defineSymbol(math, ams, bin, "\u229b", "\\circledast", true); +defineSymbol(math, ams, bin, "\u22c5", "\\centerdot"); +defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true); +defineSymbol(math, ams, bin, "\u22d2", "\\doublecap"); +defineSymbol(math, ams, bin, "\u22d3", "\\doublecup"); +defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true); // AMS Arrows +// Note: unicode-math maps \u21e2 to their own function \rightdasharrow. +// We'll map it to AMS function \dashrightarrow. It produces the same atom. + +defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true); // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true); +defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true); +defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true); +defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true); +defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true); +defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true); +defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true); +defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true); +defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true); // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true); +defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true); +defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true); +defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true); +defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true); +defineSymbol(math, main, rel, "\u22b6", "\\origof", true); // not in font + +defineSymbol(math, main, rel, "\u22b7", "\\imageof", true); // not in font + +defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true); +defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true); +defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true); +defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true); +defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true); +defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true); +defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true); +defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true); // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true); +defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true); +defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true); +defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true); +defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true); +defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true); +defineSymbol(math, ams, rel, "\u21dd", "\\leadsto"); +defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true); +defineSymbol(math, ams, rel, "\u21be", "\\restriction"); +defineSymbol(math, main, textord, "\u2018", "`"); +defineSymbol(math, main, textord, "$", "\\$"); +defineSymbol(symbols_text, main, textord, "$", "\\$"); +defineSymbol(symbols_text, main, textord, "$", "\\textdollar"); +defineSymbol(math, main, textord, "%", "\\%"); +defineSymbol(symbols_text, main, textord, "%", "\\%"); +defineSymbol(math, main, textord, "_", "\\_"); +defineSymbol(symbols_text, main, textord, "_", "\\_"); +defineSymbol(symbols_text, main, textord, "_", "\\textunderscore"); +defineSymbol(math, main, textord, "\u2220", "\\angle", true); +defineSymbol(math, main, textord, "\u221e", "\\infty", true); +defineSymbol(math, main, textord, "\u2032", "\\prime"); +defineSymbol(math, main, textord, "\u25b3", "\\triangle"); +defineSymbol(math, main, textord, "\u0393", "\\Gamma", true); +defineSymbol(math, main, textord, "\u0394", "\\Delta", true); +defineSymbol(math, main, textord, "\u0398", "\\Theta", true); +defineSymbol(math, main, textord, "\u039b", "\\Lambda", true); +defineSymbol(math, main, textord, "\u039e", "\\Xi", true); +defineSymbol(math, main, textord, "\u03a0", "\\Pi", true); +defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true); +defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true); +defineSymbol(math, main, textord, "\u03a6", "\\Phi", true); +defineSymbol(math, main, textord, "\u03a8", "\\Psi", true); +defineSymbol(math, main, textord, "\u03a9", "\\Omega", true); +defineSymbol(math, main, textord, "A", "\u0391"); +defineSymbol(math, main, textord, "B", "\u0392"); +defineSymbol(math, main, textord, "E", "\u0395"); +defineSymbol(math, main, textord, "Z", "\u0396"); +defineSymbol(math, main, textord, "H", "\u0397"); +defineSymbol(math, main, textord, "I", "\u0399"); +defineSymbol(math, main, textord, "K", "\u039A"); +defineSymbol(math, main, textord, "M", "\u039C"); +defineSymbol(math, main, textord, "N", "\u039D"); +defineSymbol(math, main, textord, "O", "\u039F"); +defineSymbol(math, main, textord, "P", "\u03A1"); +defineSymbol(math, main, textord, "T", "\u03A4"); +defineSymbol(math, main, textord, "X", "\u03A7"); +defineSymbol(math, main, textord, "\u00ac", "\\neg", true); +defineSymbol(math, main, textord, "\u00ac", "\\lnot"); +defineSymbol(math, main, textord, "\u22a4", "\\top"); +defineSymbol(math, main, textord, "\u22a5", "\\bot"); +defineSymbol(math, main, textord, "\u2205", "\\emptyset"); +defineSymbol(math, ams, textord, "\u2205", "\\varnothing"); +defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true); +defineSymbol(math, main, mathord, "\u03b2", "\\beta", true); +defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true); +defineSymbol(math, main, mathord, "\u03b4", "\\delta", true); +defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true); +defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true); +defineSymbol(math, main, mathord, "\u03b7", "\\eta", true); +defineSymbol(math, main, mathord, "\u03b8", "\\theta", true); +defineSymbol(math, main, mathord, "\u03b9", "\\iota", true); +defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true); +defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true); +defineSymbol(math, main, mathord, "\u03bc", "\\mu", true); +defineSymbol(math, main, mathord, "\u03bd", "\\nu", true); +defineSymbol(math, main, mathord, "\u03be", "\\xi", true); +defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true); +defineSymbol(math, main, mathord, "\u03c0", "\\pi", true); +defineSymbol(math, main, mathord, "\u03c1", "\\rho", true); +defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true); +defineSymbol(math, main, mathord, "\u03c4", "\\tau", true); +defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true); +defineSymbol(math, main, mathord, "\u03d5", "\\phi", true); +defineSymbol(math, main, mathord, "\u03c7", "\\chi", true); +defineSymbol(math, main, mathord, "\u03c8", "\\psi", true); +defineSymbol(math, main, mathord, "\u03c9", "\\omega", true); +defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true); +defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true); +defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true); +defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true); +defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true); +defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true); +defineSymbol(math, main, bin, "\u2217", "*", true); +defineSymbol(math, main, bin, "+", "+"); +defineSymbol(math, main, bin, "\u2212", "-", true); +defineSymbol(math, main, bin, "\u22c5", "\\cdot", true); +defineSymbol(math, main, bin, "\u2218", "\\circ", true); +defineSymbol(math, main, bin, "\u00f7", "\\div", true); +defineSymbol(math, main, bin, "\u00b1", "\\pm", true); +defineSymbol(math, main, bin, "\u00d7", "\\times", true); +defineSymbol(math, main, bin, "\u2229", "\\cap", true); +defineSymbol(math, main, bin, "\u222a", "\\cup", true); +defineSymbol(math, main, bin, "\u2216", "\\setminus", true); +defineSymbol(math, main, bin, "\u2227", "\\land"); +defineSymbol(math, main, bin, "\u2228", "\\lor"); +defineSymbol(math, main, bin, "\u2227", "\\wedge", true); +defineSymbol(math, main, bin, "\u2228", "\\vee", true); +defineSymbol(math, main, textord, "\u221a", "\\surd"); +defineSymbol(math, main, symbols_open, "\u27e8", "\\langle", true); +defineSymbol(math, main, symbols_open, "\u2223", "\\lvert"); +defineSymbol(math, main, symbols_open, "\u2225", "\\lVert"); +defineSymbol(math, main, symbols_close, "?", "?"); +defineSymbol(math, main, symbols_close, "!", "!"); +defineSymbol(math, main, symbols_close, "\u27e9", "\\rangle", true); +defineSymbol(math, main, symbols_close, "\u2223", "\\rvert"); +defineSymbol(math, main, symbols_close, "\u2225", "\\rVert"); +defineSymbol(math, main, rel, "=", "="); +defineSymbol(math, main, rel, ":", ":"); +defineSymbol(math, main, rel, "\u2248", "\\approx", true); +defineSymbol(math, main, rel, "\u2245", "\\cong", true); +defineSymbol(math, main, rel, "\u2265", "\\ge"); +defineSymbol(math, main, rel, "\u2265", "\\geq", true); +defineSymbol(math, main, rel, "\u2190", "\\gets"); +defineSymbol(math, main, rel, ">", "\\gt", true); +defineSymbol(math, main, rel, "\u2208", "\\in", true); +defineSymbol(math, main, rel, "\ue020", "\\@not"); +defineSymbol(math, main, rel, "\u2282", "\\subset", true); +defineSymbol(math, main, rel, "\u2283", "\\supset", true); +defineSymbol(math, main, rel, "\u2286", "\\subseteq", true); +defineSymbol(math, main, rel, "\u2287", "\\supseteq", true); +defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true); +defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true); +defineSymbol(math, main, rel, "\u22a8", "\\models"); +defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true); +defineSymbol(math, main, rel, "\u2264", "\\le"); +defineSymbol(math, main, rel, "\u2264", "\\leq", true); +defineSymbol(math, main, rel, "<", "\\lt", true); +defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true); +defineSymbol(math, main, rel, "\u2192", "\\to"); +defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true); +defineSymbol(math, ams, rel, "\u2270", "\\nleq", true); +defineSymbol(math, main, spacing, "\u00a0", "\\ "); +defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% + +defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace"); +defineSymbol(symbols_text, main, spacing, "\u00a0", "\\ "); +defineSymbol(symbols_text, main, spacing, "\u00a0", " "); +defineSymbol(symbols_text, main, spacing, "\u00a0", "\\space"); +defineSymbol(symbols_text, main, spacing, "\u00a0", "\\nobreakspace"); +defineSymbol(math, main, spacing, null, "\\nobreak"); +defineSymbol(math, main, spacing, null, "\\allowbreak"); +defineSymbol(math, main, punct, ",", ","); +defineSymbol(math, main, punct, ";", ";"); +defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true); +defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true); +defineSymbol(math, main, bin, "\u2299", "\\odot", true); +defineSymbol(math, main, bin, "\u2295", "\\oplus", true); +defineSymbol(math, main, bin, "\u2297", "\\otimes", true); +defineSymbol(math, main, textord, "\u2202", "\\partial", true); +defineSymbol(math, main, bin, "\u2298", "\\oslash", true); +defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true); +defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true); +defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup"); +defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown"); +defineSymbol(math, main, bin, "\u2020", "\\dagger"); +defineSymbol(math, main, bin, "\u22c4", "\\diamond"); +defineSymbol(math, main, bin, "\u22c6", "\\star"); +defineSymbol(math, main, bin, "\u25c3", "\\triangleleft"); +defineSymbol(math, main, bin, "\u25b9", "\\triangleright"); +defineSymbol(math, main, symbols_open, "{", "\\{"); +defineSymbol(symbols_text, main, textord, "{", "\\{"); +defineSymbol(symbols_text, main, textord, "{", "\\textbraceleft"); +defineSymbol(math, main, symbols_close, "}", "\\}"); +defineSymbol(symbols_text, main, textord, "}", "\\}"); +defineSymbol(symbols_text, main, textord, "}", "\\textbraceright"); +defineSymbol(math, main, symbols_open, "{", "\\lbrace"); +defineSymbol(math, main, symbols_close, "}", "\\rbrace"); +defineSymbol(math, main, symbols_open, "[", "\\lbrack", true); +defineSymbol(symbols_text, main, textord, "[", "\\lbrack", true); +defineSymbol(math, main, symbols_close, "]", "\\rbrack", true); +defineSymbol(symbols_text, main, textord, "]", "\\rbrack", true); +defineSymbol(math, main, symbols_open, "(", "\\lparen", true); +defineSymbol(math, main, symbols_close, ")", "\\rparen", true); +defineSymbol(symbols_text, main, textord, "<", "\\textless", true); // in T1 fontenc + +defineSymbol(symbols_text, main, textord, ">", "\\textgreater", true); // in T1 fontenc + +defineSymbol(math, main, symbols_open, "\u230a", "\\lfloor", true); +defineSymbol(math, main, symbols_close, "\u230b", "\\rfloor", true); +defineSymbol(math, main, symbols_open, "\u2308", "\\lceil", true); +defineSymbol(math, main, symbols_close, "\u2309", "\\rceil", true); +defineSymbol(math, main, textord, "\\", "\\backslash"); +defineSymbol(math, main, textord, "\u2223", "|"); +defineSymbol(math, main, textord, "\u2223", "\\vert"); +defineSymbol(symbols_text, main, textord, "|", "\\textbar", true); // in T1 fontenc + +defineSymbol(math, main, textord, "\u2225", "\\|"); +defineSymbol(math, main, textord, "\u2225", "\\Vert"); +defineSymbol(symbols_text, main, textord, "\u2225", "\\textbardbl"); +defineSymbol(symbols_text, main, textord, "~", "\\textasciitilde"); +defineSymbol(symbols_text, main, textord, "\\", "\\textbackslash"); +defineSymbol(symbols_text, main, textord, "^", "\\textasciicircum"); +defineSymbol(math, main, rel, "\u2191", "\\uparrow", true); +defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true); +defineSymbol(math, main, rel, "\u2193", "\\downarrow", true); +defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true); +defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true); +defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true); +defineSymbol(math, main, op, "\u2210", "\\coprod"); +defineSymbol(math, main, op, "\u22c1", "\\bigvee"); +defineSymbol(math, main, op, "\u22c0", "\\bigwedge"); +defineSymbol(math, main, op, "\u2a04", "\\biguplus"); +defineSymbol(math, main, op, "\u22c2", "\\bigcap"); +defineSymbol(math, main, op, "\u22c3", "\\bigcup"); +defineSymbol(math, main, op, "\u222b", "\\int"); +defineSymbol(math, main, op, "\u222b", "\\intop"); +defineSymbol(math, main, op, "\u222c", "\\iint"); +defineSymbol(math, main, op, "\u222d", "\\iiint"); +defineSymbol(math, main, op, "\u220f", "\\prod"); +defineSymbol(math, main, op, "\u2211", "\\sum"); +defineSymbol(math, main, op, "\u2a02", "\\bigotimes"); +defineSymbol(math, main, op, "\u2a01", "\\bigoplus"); +defineSymbol(math, main, op, "\u2a00", "\\bigodot"); +defineSymbol(math, main, op, "\u222e", "\\oint"); +defineSymbol(math, main, op, "\u222f", "\\oiint"); +defineSymbol(math, main, op, "\u2230", "\\oiiint"); +defineSymbol(math, main, op, "\u2a06", "\\bigsqcup"); +defineSymbol(math, main, op, "\u222b", "\\smallint"); +defineSymbol(symbols_text, main, inner, "\u2026", "\\textellipsis"); +defineSymbol(math, main, inner, "\u2026", "\\mathellipsis"); +defineSymbol(symbols_text, main, inner, "\u2026", "\\ldots", true); +defineSymbol(math, main, inner, "\u2026", "\\ldots", true); +defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true); +defineSymbol(math, main, inner, "\u22f1", "\\ddots", true); // \vdots is a macro that uses one of these two symbols (with made-up names): + +defineSymbol(math, main, textord, "\u22ee", "\\varvdots"); +defineSymbol(symbols_text, main, textord, "\u22ee", "\\varvdots"); +defineSymbol(math, main, accent, "\u02ca", "\\acute"); +defineSymbol(math, main, accent, "\u02cb", "\\grave"); +defineSymbol(math, main, accent, "\u00a8", "\\ddot"); +defineSymbol(math, main, accent, "\u007e", "\\tilde"); +defineSymbol(math, main, accent, "\u02c9", "\\bar"); +defineSymbol(math, main, accent, "\u02d8", "\\breve"); +defineSymbol(math, main, accent, "\u02c7", "\\check"); +defineSymbol(math, main, accent, "\u005e", "\\hat"); +defineSymbol(math, main, accent, "\u20d7", "\\vec"); +defineSymbol(math, main, accent, "\u02d9", "\\dot"); +defineSymbol(math, main, accent, "\u02da", "\\mathring"); // \imath and \jmath should be invariant to \mathrm, \mathbf, etc., so use PUA + +defineSymbol(math, main, mathord, "\ue131", "\\@imath"); +defineSymbol(math, main, mathord, "\ue237", "\\@jmath"); +defineSymbol(math, main, textord, "\u0131", "\u0131"); +defineSymbol(math, main, textord, "\u0237", "\u0237"); +defineSymbol(symbols_text, main, textord, "\u0131", "\\i", true); +defineSymbol(symbols_text, main, textord, "\u0237", "\\j", true); +defineSymbol(symbols_text, main, textord, "\u00df", "\\ss", true); +defineSymbol(symbols_text, main, textord, "\u00e6", "\\ae", true); +defineSymbol(symbols_text, main, textord, "\u0153", "\\oe", true); +defineSymbol(symbols_text, main, textord, "\u00f8", "\\o", true); +defineSymbol(symbols_text, main, textord, "\u00c6", "\\AE", true); +defineSymbol(symbols_text, main, textord, "\u0152", "\\OE", true); +defineSymbol(symbols_text, main, textord, "\u00d8", "\\O", true); +defineSymbol(symbols_text, main, accent, "\u02ca", "\\'"); // acute + +defineSymbol(symbols_text, main, accent, "\u02cb", "\\`"); // grave + +defineSymbol(symbols_text, main, accent, "\u02c6", "\\^"); // circumflex + +defineSymbol(symbols_text, main, accent, "\u02dc", "\\~"); // tilde + +defineSymbol(symbols_text, main, accent, "\u02c9", "\\="); // macron + +defineSymbol(symbols_text, main, accent, "\u02d8", "\\u"); // breve + +defineSymbol(symbols_text, main, accent, "\u02d9", "\\."); // dot above + +defineSymbol(symbols_text, main, accent, "\u00b8", "\\c"); // cedilla + +defineSymbol(symbols_text, main, accent, "\u02da", "\\r"); // ring above + +defineSymbol(symbols_text, main, accent, "\u02c7", "\\v"); // caron + +defineSymbol(symbols_text, main, accent, "\u00a8", '\\"'); // diaeresis + +defineSymbol(symbols_text, main, accent, "\u02dd", "\\H"); // double acute + +defineSymbol(symbols_text, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph +// These ligatures are detected and created in Parser.js's `formLigatures`. + +const ligatures = { + "--": true, + "---": true, + "``": true, + "''": true +}; +defineSymbol(symbols_text, main, textord, "\u2013", "--", true); +defineSymbol(symbols_text, main, textord, "\u2013", "\\textendash"); +defineSymbol(symbols_text, main, textord, "\u2014", "---", true); +defineSymbol(symbols_text, main, textord, "\u2014", "\\textemdash"); +defineSymbol(symbols_text, main, textord, "\u2018", "`", true); +defineSymbol(symbols_text, main, textord, "\u2018", "\\textquoteleft"); +defineSymbol(symbols_text, main, textord, "\u2019", "'", true); +defineSymbol(symbols_text, main, textord, "\u2019", "\\textquoteright"); +defineSymbol(symbols_text, main, textord, "\u201c", "``", true); +defineSymbol(symbols_text, main, textord, "\u201c", "\\textquotedblleft"); +defineSymbol(symbols_text, main, textord, "\u201d", "''", true); +defineSymbol(symbols_text, main, textord, "\u201d", "\\textquotedblright"); // \degree from gensymb package + +defineSymbol(math, main, textord, "\u00b0", "\\degree", true); +defineSymbol(symbols_text, main, textord, "\u00b0", "\\degree"); // \textdegree from inputenc package + +defineSymbol(symbols_text, main, textord, "\u00b0", "\\textdegree", true); // TODO: In LaTeX, \pounds can generate a different character in text and math +// mode, but among our fonts, only Main-Regular defines this character "163". + +defineSymbol(math, main, textord, "\u00a3", "\\pounds"); +defineSymbol(math, main, textord, "\u00a3", "\\mathsterling", true); +defineSymbol(symbols_text, main, textord, "\u00a3", "\\pounds"); +defineSymbol(symbols_text, main, textord, "\u00a3", "\\textsterling", true); +defineSymbol(math, ams, textord, "\u2720", "\\maltese"); +defineSymbol(symbols_text, ams, textord, "\u2720", "\\maltese"); // There are lots of symbols which are the same, so we add them in afterwards. +// All of these are textords in math mode + +const mathTextSymbols = "0123456789/@.\""; + +for (let i = 0; i < mathTextSymbols.length; i++) { + const ch = mathTextSymbols.charAt(i); + defineSymbol(math, main, textord, ch, ch); +} // All of these are textords in text mode + + +const textSymbols = "0123456789!@*()-=+\";:?/.,"; + +for (let i = 0; i < textSymbols.length; i++) { + const ch = textSymbols.charAt(i); + defineSymbol(symbols_text, main, textord, ch, ch); +} // All of these are textords in text mode, and mathords in math mode + + +const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +for (let i = 0; i < letters.length; i++) { + const ch = letters.charAt(i); + defineSymbol(math, main, mathord, ch, ch); + defineSymbol(symbols_text, main, textord, ch, ch); +} // Blackboard bold and script letters in Unicode range + + +defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold + +defineSymbol(symbols_text, ams, textord, "C", "\u2102"); +defineSymbol(math, ams, textord, "H", "\u210D"); +defineSymbol(symbols_text, ams, textord, "H", "\u210D"); +defineSymbol(math, ams, textord, "N", "\u2115"); +defineSymbol(symbols_text, ams, textord, "N", "\u2115"); +defineSymbol(math, ams, textord, "P", "\u2119"); +defineSymbol(symbols_text, ams, textord, "P", "\u2119"); +defineSymbol(math, ams, textord, "Q", "\u211A"); +defineSymbol(symbols_text, ams, textord, "Q", "\u211A"); +defineSymbol(math, ams, textord, "R", "\u211D"); +defineSymbol(symbols_text, ams, textord, "R", "\u211D"); +defineSymbol(math, ams, textord, "Z", "\u2124"); +defineSymbol(symbols_text, ams, textord, "Z", "\u2124"); +defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant + +defineSymbol(symbols_text, main, mathord, "h", "\u210E"); // The next loop loads wide (surrogate pair) characters. +// We support some letters in the Unicode range U+1D400 to U+1D7FF, +// Mathematical Alphanumeric Symbols. +// Some editors do not deal well with wide characters. So don't write the +// string into this file. Instead, create the string from the surrogate pair. + +let wideChar = ""; + +for (let i = 0; i < letters.length; i++) { + const ch = letters.charAt(i); // The hex numbers in the next line are a surrogate pair. + // 0xD835 is the high surrogate for all letters in the range we support. + // 0xDC00 is the low surrogate for bold A. + + wideChar = String.fromCharCode(0xD835, 0xDC00 + i); // A-Z a-z bold + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDC34 + i); // A-Z a-z italic + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDC68 + i); // A-Z a-z bold italic + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDD04 + i); // A-Z a-z Fraktur + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDD6C + i); // A-Z a-z bold Fraktur + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDDA0 + i); // A-Z a-z sans-serif + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDDD4 + i); // A-Z a-z sans bold + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDE08 + i); // A-Z a-z sans italic + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDE70 + i); // A-Z a-z monospace + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + + if (i < 26) { + // KaTeX fonts have only capital letters for blackboard bold and script. + // See exception for k below. + wideChar = String.fromCharCode(0xD835, 0xDD38 + i); // A-Z double struck + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDC9C + i); // A-Z script + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + } // TODO: Add bold script when it is supported by a KaTeX font. + +} // "k" is the only double struck lower case letter in the KaTeX fonts. + + +wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck + +defineSymbol(math, main, mathord, "k", wideChar); +defineSymbol(symbols_text, main, textord, "k", wideChar); // Next, some wide character numerals + +for (let i = 0; i < 10; i++) { + const ch = i.toString(); + wideChar = String.fromCharCode(0xD835, 0xDFCE + i); // 0-9 bold + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDFE2 + i); // 0-9 sans serif + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDFEC + i); // 0-9 bold sans + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDFF6 + i); // 0-9 monospace + + defineSymbol(math, main, mathord, ch, wideChar); + defineSymbol(symbols_text, main, textord, ch, wideChar); +} // We add these Latin-1 letters as symbols for backwards-compatibility, +// but they are not actually in the font, nor are they supported by the +// Unicode accent mechanism, so they fall back to Times font and look ugly. +// TODO(edemaine): Fix this. + + +const extraLatin = "\u00d0\u00de\u00fe"; + +for (let i = 0; i < extraLatin.length; i++) { + const ch = extraLatin.charAt(i); + defineSymbol(math, main, mathord, ch, ch); + defineSymbol(symbols_text, main, textord, ch, ch); +} +;// CONCATENATED MODULE: ./src/wide-character.js +/** + * This file provides support for Unicode range U+1D400 to U+1D7FF, + * Mathematical Alphanumeric Symbols. + * + * Function wideCharacterFont takes a wide character as input and returns + * the font information necessary to render it properly. + */ + +/** + * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf + * That document sorts characters into groups by font type, say bold or italic. + * + * In the arrays below, each subarray consists three elements: + * * The CSS class of that group when in math mode. + * * The CSS class of that group when in text mode. + * * The font name, so that KaTeX can get font metrics. + */ + +const wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"], // A-Z bold upright +["mathbf", "textbf", "Main-Bold"], // a-z bold upright +["mathnormal", "textit", "Math-Italic"], // A-Z italic +["mathnormal", "textit", "Math-Italic"], // a-z italic +["boldsymbol", "boldsymbol", "Main-BoldItalic"], // A-Z bold italic +["boldsymbol", "boldsymbol", "Main-BoldItalic"], // a-z bold italic +// Map fancy A-Z letters to script, not calligraphic. +// This aligns with unicode-math and math fonts (except Cambria Math). +["mathscr", "textscr", "Script-Regular"], // A-Z script +["", "", ""], // a-z script. No font +["", "", ""], // A-Z bold script. No font +["", "", ""], // a-z bold script. No font +["mathfrak", "textfrak", "Fraktur-Regular"], // A-Z Fraktur +["mathfrak", "textfrak", "Fraktur-Regular"], // a-z Fraktur +["mathbb", "textbb", "AMS-Regular"], // A-Z double-struck +["mathbb", "textbb", "AMS-Regular"], // k double-struck +// Note that we are using a bold font, but font metrics for regular Fraktur. +["mathboldfrak", "textboldfrak", "Fraktur-Regular"], // A-Z bold Fraktur +["mathboldfrak", "textboldfrak", "Fraktur-Regular"], // a-z bold Fraktur +["mathsf", "textsf", "SansSerif-Regular"], // A-Z sans-serif +["mathsf", "textsf", "SansSerif-Regular"], // a-z sans-serif +["mathboldsf", "textboldsf", "SansSerif-Bold"], // A-Z bold sans-serif +["mathboldsf", "textboldsf", "SansSerif-Bold"], // a-z bold sans-serif +["mathitsf", "textitsf", "SansSerif-Italic"], // A-Z italic sans-serif +["mathitsf", "textitsf", "SansSerif-Italic"], // a-z italic sans-serif +["", "", ""], // A-Z bold italic sans. No font +["", "", ""], // a-z bold italic sans. No font +["mathtt", "texttt", "Typewriter-Regular"], // A-Z monospace +["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace +]; +const wideNumeralData = [["mathbf", "textbf", "Main-Bold"], // 0-9 bold +["", "", ""], // 0-9 double-struck. No KaTeX font. +["mathsf", "textsf", "SansSerif-Regular"], // 0-9 sans-serif +["mathboldsf", "textboldsf", "SansSerif-Bold"], // 0-9 bold sans-serif +["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace +]; +const wideCharacterFont = function (wideChar, mode) { + // IE doesn't support codePointAt(). So work with the surrogate pair. + const H = wideChar.charCodeAt(0); // high surrogate + + const L = wideChar.charCodeAt(1); // low surrogate + + const codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000; + const j = mode === "math" ? 0 : 1; // column index for CSS class. + + if (0x1D400 <= codePoint && codePoint < 0x1D6A4) { + // wideLatinLetterData contains exactly 26 chars on each row. + // So we can calculate the relevant row. No traverse necessary. + const i = Math.floor((codePoint - 0x1D400) / 26); + return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]]; + } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) { + // Numerals, ten per row. + const i = Math.floor((codePoint - 0x1D7CE) / 10); + return [wideNumeralData[i][2], wideNumeralData[i][j]]; + } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) { + // dotless i or j + return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]]; + } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) { + // Greek letters. Not supported, yet. + return ["", ""]; + } else { + // We don't support any wide characters outside 1D400–1D7FF. + throw new src_ParseError("Unsupported character: " + wideChar); + } +}; +;// CONCATENATED MODULE: ./src/buildCommon.js +/* eslint no-console:0 */ + +/** + * This module contains general functions that can be used for building + * different kinds of domTree nodes in a consistent manner. + */ + + + + + + + +/** + * Looks up the given symbol in fontMetrics, after applying any symbol + * replacements defined in symbol.js + */ +const lookupSymbol = function (value, // TODO(#963): Use a union type for this. +fontName, mode) { + // Replace the value with its replaced value from symbol.js + if (src_symbols[mode][value] && src_symbols[mode][value].replace) { + value = src_symbols[mode][value].replace; + } + + return { + value: value, + metrics: getCharacterMetrics(value, fontName, mode) + }; +}; +/** + * Makes a symbolNode after translation via the list of symbols in symbols.js. + * Correctly pulls out metrics for the character, and optionally takes a list of + * classes to be attached to the node. + * + * TODO: make argument order closer to makeSpan + * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which + * should if present come first in `classes`. + * TODO(#953): Make `options` mandatory and always pass it in. + */ + + +const makeSymbol = function (value, fontName, mode, options, classes) { + const lookup = lookupSymbol(value, fontName, mode); + const metrics = lookup.metrics; + value = lookup.value; + let symbolNode; + + if (metrics) { + let italic = metrics.italic; + + if (mode === "text" || options && options.font === "mathit") { + italic = 0; + } + + symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes); + } else { + // TODO(emily): Figure out a good way to only print this in development + typeof console !== "undefined" && console.warn("No character metrics " + ("for '" + value + "' in style '" + fontName + "' and mode '" + mode + "'")); + symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes); + } + + if (options) { + symbolNode.maxFontSize = options.sizeMultiplier; + + if (options.style.isTight()) { + symbolNode.classes.push("mtight"); + } + + const color = options.getColor(); + + if (color) { + symbolNode.style.color = color; + } + } + + return symbolNode; +}; +/** + * Makes a symbol in Main-Regular or AMS-Regular. + * Used for rel, bin, open, close, inner, and punct. + */ + + +const mathsym = function (value, mode, options, classes) { + if (classes === void 0) { + classes = []; + } + + // Decide what font to render the symbol in by its entry in the symbols + // table. + // Have a special case for when the value = \ because the \ is used as a + // textord in unsupported command errors but cannot be parsed as a regular + // text ordinal and is therefore not present as a symbol in the symbols + // table for text, as well as a special case for boldsymbol because it + // can be used for bold + and - + if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) { + return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"])); + } else if (value === "\\" || src_symbols[mode][value].font === "main") { + return makeSymbol(value, "Main-Regular", mode, options, classes); + } else { + return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"])); + } +}; +/** + * Determines which of the two font names (Main-Bold and Math-BoldItalic) and + * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol", + * depending on the symbol. Use this function instead of fontMap for font + * "boldsymbol". + */ + + +const boldsymbol = function (value, mode, options, classes, type) { + if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) { + return { + fontName: "Math-BoldItalic", + fontClass: "boldsymbol" + }; + } else { + // Some glyphs do not exist in Math-BoldItalic so we need to use + // Main-Bold instead. + return { + fontName: "Main-Bold", + fontClass: "mathbf" + }; + } +}; +/** + * Makes either a mathord or textord in the correct font and color. + */ + + +const makeOrd = function (group, options, type) { + const mode = group.mode; + const text = group.text; + const classes = ["mord"]; // Math mode or Old font (i.e. \rm) + + const isFont = mode === "math" || mode === "text" && options.font; + const fontOrFamily = isFont ? options.font : options.fontFamily; + let wideFontName = ""; + let wideFontClass = ""; + + if (text.charCodeAt(0) === 0xD835) { + [wideFontName, wideFontClass] = wideCharacterFont(text, mode); + } + + if (wideFontName.length > 0) { + // surrogate pairs get special treatment + return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass)); + } else if (fontOrFamily) { + let fontName; + let fontClasses; + + if (fontOrFamily === "boldsymbol") { + const fontData = boldsymbol(text, mode, options, classes, type); + fontName = fontData.fontName; + fontClasses = [fontData.fontClass]; + } else if (isFont) { + fontName = fontMap[fontOrFamily].fontName; + fontClasses = [fontOrFamily]; + } else { + fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape); + fontClasses = [fontOrFamily, options.fontWeight, options.fontShape]; + } + + if (lookupSymbol(text, fontName, mode).metrics) { + return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses)); + } else if (ligatures.hasOwnProperty(text) && fontName.slice(0, 10) === "Typewriter") { + // Deconstruct ligatures in monospace fonts (\texttt, \tt). + const parts = []; + + for (let i = 0; i < text.length; i++) { + parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses))); + } + + return makeFragment(parts); + } + } // Makes a symbol in the default font for mathords and textords. + + + if (type === "mathord") { + return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"])); + } else if (type === "textord") { + const font = src_symbols[mode][text] && src_symbols[mode][text].font; + + if (font === "ams") { + const fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape); + return makeSymbol(text, fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape)); + } else if (font === "main" || !font) { + const fontName = retrieveTextFontName("textrm", options.fontWeight, options.fontShape); + return makeSymbol(text, fontName, mode, options, classes.concat(options.fontWeight, options.fontShape)); + } else { + // fonts added by plugins + const fontName = retrieveTextFontName(font, options.fontWeight, options.fontShape); // We add font name as a css class + + return makeSymbol(text, fontName, mode, options, classes.concat(fontName, options.fontWeight, options.fontShape)); + } + } else { + throw new Error("unexpected type: " + type + " in makeOrd"); + } +}; +/** + * Returns true if subsequent symbolNodes have the same classes, skew, maxFont, + * and styles. + */ + + +const canCombine = (prev, next) => { + if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize) { + return false; + } // If prev and next both are just "mbin"s or "mord"s we don't combine them + // so that the proper spacing can be preserved. + + + if (prev.classes.length === 1) { + const cls = prev.classes[0]; + + if (cls === "mbin" || cls === "mord") { + return false; + } + } + + for (const style in prev.style) { + if (prev.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) { + return false; + } + } + + for (const style in next.style) { + if (next.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) { + return false; + } + } + + return true; +}; +/** + * Combine consecutive domTree.symbolNodes into a single symbolNode. + * Note: this function mutates the argument. + */ + + +const tryCombineChars = chars => { + for (let i = 0; i < chars.length - 1; i++) { + const prev = chars[i]; + const next = chars[i + 1]; + + if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) { + prev.text += next.text; + prev.height = Math.max(prev.height, next.height); + prev.depth = Math.max(prev.depth, next.depth); // Use the last character's italic correction since we use + // it to add padding to the right of the span created from + // the combined characters. + + prev.italic = next.italic; + chars.splice(i + 1, 1); + i--; + } + } + + return chars; +}; +/** + * Calculate the height, depth, and maxFontSize of an element based on its + * children. + */ + + +const sizeElementFromChildren = function (elem) { + let height = 0; + let depth = 0; + let maxFontSize = 0; + + for (let i = 0; i < elem.children.length; i++) { + const child = elem.children[i]; + + if (child.height > height) { + height = child.height; + } + + if (child.depth > depth) { + depth = child.depth; + } + + if (child.maxFontSize > maxFontSize) { + maxFontSize = child.maxFontSize; + } + } + + elem.height = height; + elem.depth = depth; + elem.maxFontSize = maxFontSize; +}; +/** + * Makes a span with the given list of classes, list of children, and options. + * + * TODO(#953): Ensure that `options` is always provided (currently some call + * sites don't pass it) and make the type below mandatory. + * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which + * should if present come first in `classes`. + */ + + +const makeSpan = function (classes, children, options, style) { + const span = new Span(classes, children, options, style); + sizeElementFromChildren(span); + return span; +}; // SVG one is simpler -- doesn't require height, depth, max-font setting. +// This is also a separate method for typesafety. + + +const makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style); + +const makeLineSpan = function (className, options, thickness) { + const line = makeSpan([className], [], options); + line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness); + line.style.borderBottomWidth = makeEm(line.height); + line.maxFontSize = 1.0; + return line; +}; +/** + * Makes an anchor with the given href, list of classes, list of children, + * and options. + */ + + +const makeAnchor = function (href, classes, children, options) { + const anchor = new Anchor(href, classes, children, options); + sizeElementFromChildren(anchor); + return anchor; +}; +/** + * Makes a document fragment with the given list of children. + */ + + +const makeFragment = function (children) { + const fragment = new DocumentFragment(children); + sizeElementFromChildren(fragment); + return fragment; +}; +/** + * Wraps group in a span if it's a document fragment, allowing to apply classes + * and styles + */ + + +const wrapFragment = function (group, options) { + if (group instanceof DocumentFragment) { + return makeSpan([], [group], options); + } + + return group; +}; // These are exact object types to catch typos in the names of the optional fields. + + +// Computes the updated `children` list and the overall depth. +// +// This helper function for makeVList makes it easier to enforce type safety by +// allowing early exits (returns) in the logic. +const getVListChildrenAndDepth = function (params) { + if (params.positionType === "individualShift") { + const oldChildren = params.children; + const children = [oldChildren[0]]; // Add in kerns to the list of params.children to get each element to be + // shifted to the correct specified shift + + const depth = -oldChildren[0].shift - oldChildren[0].elem.depth; + let currPos = depth; + + for (let i = 1; i < oldChildren.length; i++) { + const diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth; + const size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth); + currPos = currPos + diff; + children.push({ + type: "kern", + size + }); + children.push(oldChildren[i]); + } + + return { + children, + depth + }; + } + + let depth; + + if (params.positionType === "top") { + // We always start at the bottom, so calculate the bottom by adding up + // all the sizes + let bottom = params.positionData; + + for (let i = 0; i < params.children.length; i++) { + const child = params.children[i]; + bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth; + } + + depth = bottom; + } else if (params.positionType === "bottom") { + depth = -params.positionData; + } else { + const firstChild = params.children[0]; + + if (firstChild.type !== "elem") { + throw new Error('First child must have type "elem".'); + } + + if (params.positionType === "shift") { + depth = -firstChild.elem.depth - params.positionData; + } else if (params.positionType === "firstBaseline") { + depth = -firstChild.elem.depth; + } else { + throw new Error("Invalid positionType " + params.positionType + "."); + } + } + + return { + children: params.children, + depth + }; +}; +/** + * Makes a vertical list by stacking elements and kerns on top of each other. + * Allows for many different ways of specifying the positioning method. + * + * See VListParam documentation above. + */ + + +const makeVList = function (params, options) { + const { + children, + depth + } = getVListChildrenAndDepth(params); // Create a strut that is taller than any list item. The strut is added to + // each item, where it will determine the item's baseline. Since it has + // `overflow:hidden`, the strut's top edge will sit on the item's line box's + // top edge and the strut's bottom edge will sit on the item's baseline, + // with no additional line-height spacing. This allows the item baseline to + // be positioned precisely without worrying about font ascent and + // line-height. + + let pstrutSize = 0; + + for (let i = 0; i < children.length; i++) { + const child = children[i]; + + if (child.type === "elem") { + const elem = child.elem; + pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height); + } + } + + pstrutSize += 2; + const pstrut = makeSpan(["pstrut"], []); + pstrut.style.height = makeEm(pstrutSize); // Create a new list of actual children at the correct offsets + + const realChildren = []; + let minPos = depth; + let maxPos = depth; + let currPos = depth; + + for (let i = 0; i < children.length; i++) { + const child = children[i]; + + if (child.type === "kern") { + currPos += child.size; + } else { + const elem = child.elem; + const classes = child.wrapperClasses || []; + const style = child.wrapperStyle || {}; + const childWrap = makeSpan(classes, [pstrut, elem], undefined, style); + childWrap.style.top = makeEm(-pstrutSize - currPos - elem.depth); + + if (child.marginLeft) { + childWrap.style.marginLeft = child.marginLeft; + } + + if (child.marginRight) { + childWrap.style.marginRight = child.marginRight; + } + + realChildren.push(childWrap); + currPos += elem.height + elem.depth; + } + + minPos = Math.min(minPos, currPos); + maxPos = Math.max(maxPos, currPos); + } // The vlist contents go in a table-cell with `vertical-align:bottom`. + // This cell's bottom edge will determine the containing table's baseline + // without overly expanding the containing line-box. + + + const vlist = makeSpan(["vlist"], realChildren); + vlist.style.height = makeEm(maxPos); // A second row is used if necessary to represent the vlist's depth. + + let rows; + + if (minPos < 0) { + // We will define depth in an empty span with display: table-cell. + // It should render with the height that we define. But Chrome, in + // contenteditable mode only, treats that span as if it contains some + // text content. And that min-height over-rides our desired height. + // So we put another empty span inside the depth strut span. + const emptySpan = makeSpan([], []); + const depthStrut = makeSpan(["vlist"], [emptySpan]); + depthStrut.style.height = makeEm(-minPos); // Safari wants the first row to have inline content; otherwise it + // puts the bottom of the *second* row on the baseline. + + const topStrut = makeSpan(["vlist-s"], [new SymbolNode("\u200b")]); + rows = [makeSpan(["vlist-r"], [vlist, topStrut]), makeSpan(["vlist-r"], [depthStrut])]; + } else { + rows = [makeSpan(["vlist-r"], [vlist])]; + } + + const vtable = makeSpan(["vlist-t"], rows); + + if (rows.length === 2) { + vtable.classes.push("vlist-t2"); + } + + vtable.height = maxPos; + vtable.depth = -minPos; + return vtable; +}; // Glue is a concept from TeX which is a flexible space between elements in +// either a vertical or horizontal list. In KaTeX, at least for now, it's +// static space between elements in a horizontal layout. + + +const makeGlue = (measurement, options) => { + // Make an empty span for the space + const rule = makeSpan(["mspace"], [], options); + const size = calculateSize(measurement, options); + rule.style.marginRight = makeEm(size); + return rule; +}; // Takes font options, and returns the appropriate fontLookup name + + +const retrieveTextFontName = function (fontFamily, fontWeight, fontShape) { + let baseFontName = ""; + + switch (fontFamily) { + case "amsrm": + baseFontName = "AMS"; + break; + + case "textrm": + baseFontName = "Main"; + break; + + case "textsf": + baseFontName = "SansSerif"; + break; + + case "texttt": + baseFontName = "Typewriter"; + break; + + default: + baseFontName = fontFamily; + // use fonts added by a plugin + } + + let fontStylesName; + + if (fontWeight === "textbf" && fontShape === "textit") { + fontStylesName = "BoldItalic"; + } else if (fontWeight === "textbf") { + fontStylesName = "Bold"; + } else if (fontWeight === "textit") { + fontStylesName = "Italic"; + } else { + fontStylesName = "Regular"; + } + + return baseFontName + "-" + fontStylesName; +}; +/** + * Maps TeX font commands to objects containing: + * - variant: string used for "mathvariant" attribute in buildMathML.js + * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics + */ +// A map between tex font commands an MathML mathvariant attribute values + + +const fontMap = { + // styles + "mathbf": { + variant: "bold", + fontName: "Main-Bold" + }, + "mathrm": { + variant: "normal", + fontName: "Main-Regular" + }, + "textit": { + variant: "italic", + fontName: "Main-Italic" + }, + "mathit": { + variant: "italic", + fontName: "Main-Italic" + }, + "mathnormal": { + variant: "italic", + fontName: "Math-Italic" + }, + "mathsfit": { + variant: "sans-serif-italic", + fontName: "SansSerif-Italic" + }, + // "boldsymbol" is missing because they require the use of multiple fonts: + // Math-BoldItalic and Main-Bold. This is handled by a special case in + // makeOrd which ends up calling boldsymbol. + // families + "mathbb": { + variant: "double-struck", + fontName: "AMS-Regular" + }, + "mathcal": { + variant: "script", + fontName: "Caligraphic-Regular" + }, + "mathfrak": { + variant: "fraktur", + fontName: "Fraktur-Regular" + }, + "mathscr": { + variant: "script", + fontName: "Script-Regular" + }, + "mathsf": { + variant: "sans-serif", + fontName: "SansSerif-Regular" + }, + "mathtt": { + variant: "monospace", + fontName: "Typewriter-Regular" + } +}; +const svgData = { + // path, width, height + vec: ["vec", 0.471, 0.714], + // values from the font glyph + oiintSize1: ["oiintSize1", 0.957, 0.499], + // oval to overlay the integrand + oiintSize2: ["oiintSize2", 1.472, 0.659], + oiiintSize1: ["oiiintSize1", 1.304, 0.499], + oiiintSize2: ["oiiintSize2", 1.98, 0.659] +}; + +const staticSvg = function (value, options) { + // Create a span with inline SVG for the element. + const [pathName, width, height] = svgData[value]; + const path = new PathNode(pathName); + const svgNode = new SvgNode([path], { + "width": makeEm(width), + "height": makeEm(height), + // Override CSS rule `.katex svg { width: 100% }` + "style": "width:" + makeEm(width), + "viewBox": "0 0 " + 1000 * width + " " + 1000 * height, + "preserveAspectRatio": "xMinYMin" + }); + const span = makeSvgSpan(["overlay"], [svgNode], options); + span.height = height; + span.style.height = makeEm(height); + span.style.width = makeEm(width); + return span; +}; + +/* harmony default export */ var buildCommon = ({ + fontMap, + makeSymbol, + mathsym, + makeSpan, + makeSvgSpan, + makeLineSpan, + makeAnchor, + makeFragment, + wrapFragment, + makeVList, + makeOrd, + makeGlue, + staticSvg, + svgData, + tryCombineChars +}); +;// CONCATENATED MODULE: ./src/spacingData.js +/** + * Describes spaces between different classes of atoms. + */ +const thinspace = { + number: 3, + unit: "mu" +}; +const mediumspace = { + number: 4, + unit: "mu" +}; +const thickspace = { + number: 5, + unit: "mu" +}; // Making the type below exact with all optional fields doesn't work due to +// - https://github.com/facebook/flow/issues/4582 +// - https://github.com/facebook/flow/issues/5688 +// However, since *all* fields are optional, $Shape<> works as suggested in 5688 +// above. + +// Spacing relationships for display and text styles +const spacings = { + mord: { + mop: thinspace, + mbin: mediumspace, + mrel: thickspace, + minner: thinspace + }, + mop: { + mord: thinspace, + mop: thinspace, + mrel: thickspace, + minner: thinspace + }, + mbin: { + mord: mediumspace, + mop: mediumspace, + mopen: mediumspace, + minner: mediumspace + }, + mrel: { + mord: thickspace, + mop: thickspace, + mopen: thickspace, + minner: thickspace + }, + mopen: {}, + mclose: { + mop: thinspace, + mbin: mediumspace, + mrel: thickspace, + minner: thinspace + }, + mpunct: { + mord: thinspace, + mop: thinspace, + mrel: thickspace, + mopen: thinspace, + mclose: thinspace, + mpunct: thinspace, + minner: thinspace + }, + minner: { + mord: thinspace, + mop: thinspace, + mbin: mediumspace, + mrel: thickspace, + mopen: thinspace, + mpunct: thinspace, + minner: thinspace + } +}; // Spacing relationships for script and scriptscript styles + +const tightSpacings = { + mord: { + mop: thinspace + }, + mop: { + mord: thinspace, + mop: thinspace + }, + mbin: {}, + mrel: {}, + mopen: {}, + mclose: { + mop: thinspace + }, + mpunct: {}, + minner: { + mop: thinspace + } +}; +;// CONCATENATED MODULE: ./src/defineFunction.js +/** Context provided to function handlers for error messages. */ +// Note: reverse the order of the return type union will cause a flow error. +// See https://github.com/facebook/flow/issues/3663. +// More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types) +// whose presence impacts super/subscripting. In this case, ParseNode<"supsub"> +// delegates its HTML building to the HtmlBuilder corresponding to these nodes. + +/** + * Final function spec for use at parse time. + * This is almost identical to `FunctionPropSpec`, except it + * 1. includes the function handler, and + * 2. requires all arguments except argTypes. + * It is generated by `defineFunction()` below. + */ + +/** + * All registered functions. + * `functions.js` just exports this same dictionary again and makes it public. + * `Parser.js` requires this dictionary. + */ +const _functions = {}; +/** + * All HTML builders. Should be only used in the `define*` and the `build*ML` + * functions. + */ + +const _htmlGroupBuilders = {}; +/** + * All MathML builders. Should be only used in the `define*` and the `build*ML` + * functions. + */ + +const _mathmlGroupBuilders = {}; +function defineFunction(_ref) { + let { + type, + names, + props, + handler, + htmlBuilder, + mathmlBuilder + } = _ref; + // Set default values of functions + const data = { + type, + numArgs: props.numArgs, + argTypes: props.argTypes, + allowedInArgument: !!props.allowedInArgument, + allowedInText: !!props.allowedInText, + allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, + numOptionalArgs: props.numOptionalArgs || 0, + infix: !!props.infix, + primitive: !!props.primitive, + handler: handler + }; + + for (let i = 0; i < names.length; ++i) { + _functions[names[i]] = data; + } + + if (type) { + if (htmlBuilder) { + _htmlGroupBuilders[type] = htmlBuilder; + } + + if (mathmlBuilder) { + _mathmlGroupBuilders[type] = mathmlBuilder; + } + } +} +/** + * Use this to register only the HTML and MathML builders for a function (e.g. + * if the function's ParseNode is generated in Parser.js rather than via a + * stand-alone handler provided to `defineFunction`). + */ + +function defineFunctionBuilders(_ref2) { + let { + type, + htmlBuilder, + mathmlBuilder + } = _ref2; + defineFunction({ + type, + names: [], + props: { + numArgs: 0 + }, + + handler() { + throw new Error('Should never be called.'); + }, + + htmlBuilder, + mathmlBuilder + }); +} +const normalizeArgument = function (arg) { + return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg; +}; // Since the corresponding buildHTML/buildMathML function expects a +// list of elements, we normalize for different kinds of arguments + +const ordargument = function (arg) { + return arg.type === "ordgroup" ? arg.body : [arg]; +}; +;// CONCATENATED MODULE: ./src/buildHTML.js +/** + * This file does the main work of building a domTree structure from a parse + * tree. The entry point is the `buildHTML` function, which takes a parse tree. + * Then, the buildExpression, buildGroup, and various groupBuilders functions + * are called, to produce a final HTML tree. + */ + + + + + + + + + +const buildHTML_makeSpan = buildCommon.makeSpan; // Binary atoms (first class `mbin`) change into ordinary atoms (`mord`) +// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6, +// and the text before Rule 19. + +const binLeftCanceller = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"]; +const binRightCanceller = ["rightmost", "mrel", "mclose", "mpunct"]; +const styleMap = { + "display": src_Style.DISPLAY, + "text": src_Style.TEXT, + "script": src_Style.SCRIPT, + "scriptscript": src_Style.SCRIPTSCRIPT +}; +const DomEnum = { + mord: "mord", + mop: "mop", + mbin: "mbin", + mrel: "mrel", + mopen: "mopen", + mclose: "mclose", + mpunct: "mpunct", + minner: "minner" +}; + +/** + * Take a list of nodes, build them in order, and return a list of the built + * nodes. documentFragments are flattened into their contents, so the + * returned list contains no fragments. `isRealGroup` is true if `expression` + * is a real group (no atoms will be added on either side), as opposed to + * a partial group (e.g. one created by \color). `surrounding` is an array + * consisting type of nodes that will be added to the left and right. + */ +const buildExpression = function (expression, options, isRealGroup, surrounding) { + if (surrounding === void 0) { + surrounding = [null, null]; + } + + // Parse expressions into `groups`. + const groups = []; + + for (let i = 0; i < expression.length; i++) { + const output = buildGroup(expression[i], options); + + if (output instanceof DocumentFragment) { + const children = output.children; + groups.push(...children); + } else { + groups.push(output); + } + } // Combine consecutive domTree.symbolNodes into a single symbolNode. + + + buildCommon.tryCombineChars(groups); // If `expression` is a partial group, let the parent handle spacings + // to avoid processing groups multiple times. + + if (!isRealGroup) { + return groups; + } + + let glueOptions = options; + + if (expression.length === 1) { + const node = expression[0]; + + if (node.type === "sizing") { + glueOptions = options.havingSize(node.size); + } else if (node.type === "styling") { + glueOptions = options.havingStyle(styleMap[node.style]); + } + } // Dummy spans for determining spacings between surrounding atoms. + // If `expression` has no atoms on the left or right, class "leftmost" + // or "rightmost", respectively, is used to indicate it. + + + const dummyPrev = buildHTML_makeSpan([surrounding[0] || "leftmost"], [], options); + const dummyNext = buildHTML_makeSpan([surrounding[1] || "rightmost"], [], options); // TODO: These code assumes that a node's math class is the first element + // of its `classes` array. A later cleanup should ensure this, for + // instance by changing the signature of `makeSpan`. + // Before determining what spaces to insert, perform bin cancellation. + // Binary operators change to ordinary symbols in some contexts. + + const isRoot = isRealGroup === "root"; + traverseNonSpaceNodes(groups, (node, prev) => { + const prevType = prev.classes[0]; + const type = node.classes[0]; + + if (prevType === "mbin" && utils.contains(binRightCanceller, type)) { + prev.classes[0] = "mord"; + } else if (type === "mbin" && utils.contains(binLeftCanceller, prevType)) { + node.classes[0] = "mord"; + } + }, { + node: dummyPrev + }, dummyNext, isRoot); + traverseNonSpaceNodes(groups, (node, prev) => { + const prevType = getTypeOfDomTree(prev); + const type = getTypeOfDomTree(node); // 'mtight' indicates that the node is script or scriptscript style. + + const space = prevType && type ? node.hasClass("mtight") ? tightSpacings[prevType][type] : spacings[prevType][type] : null; + + if (space) { + // Insert glue (spacing) after the `prev`. + return buildCommon.makeGlue(space, glueOptions); + } + }, { + node: dummyPrev + }, dummyNext, isRoot); + return groups; +}; // Depth-first traverse non-space `nodes`, calling `callback` with the current and +// previous node as arguments, optionally returning a node to insert after the +// previous node. `prev` is an object with the previous node and `insertAfter` +// function to insert after it. `next` is a node that will be added to the right. +// Used for bin cancellation and inserting spacings. + +const traverseNonSpaceNodes = function (nodes, callback, prev, next, isRoot) { + if (next) { + // temporarily append the right node, if exists + nodes.push(next); + } + + let i = 0; + + for (; i < nodes.length; i++) { + const node = nodes[i]; + const partialGroup = checkPartialGroup(node); + + if (partialGroup) { + // Recursive DFS + // $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array + traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot); + continue; + } // Ignore explicit spaces (e.g., \;, \,) when determining what implicit + // spacing should go between atoms of different classes + + + const nonspace = !node.hasClass("mspace"); + + if (nonspace) { + const result = callback(node, prev.node); + + if (result) { + if (prev.insertAfter) { + prev.insertAfter(result); + } else { + // insert at front + nodes.unshift(result); + i++; + } + } + } + + if (nonspace) { + prev.node = node; + } else if (isRoot && node.hasClass("newline")) { + prev.node = buildHTML_makeSpan(["leftmost"]); // treat like beginning of line + } + + prev.insertAfter = (index => n => { + nodes.splice(index + 1, 0, n); + i++; + })(i); + } + + if (next) { + nodes.pop(); + } +}; // Check if given node is a partial group, i.e., does not affect spacing around. + + +const checkPartialGroup = function (node) { + if (node instanceof DocumentFragment || node instanceof Anchor || node instanceof Span && node.hasClass("enclosing")) { + return node; + } + + return null; +}; // Return the outermost node of a domTree. + + +const getOutermostNode = function (node, side) { + const partialGroup = checkPartialGroup(node); + + if (partialGroup) { + const children = partialGroup.children; + + if (children.length) { + if (side === "right") { + return getOutermostNode(children[children.length - 1], "right"); + } else if (side === "left") { + return getOutermostNode(children[0], "left"); + } + } + } + + return node; +}; // Return math atom class (mclass) of a domTree. +// If `side` is given, it will get the type of the outermost node at given side. + + +const getTypeOfDomTree = function (node, side) { + if (!node) { + return null; + } + + if (side) { + node = getOutermostNode(node, side); + } // This makes a lot of assumptions as to where the type of atom + // appears. We should do a better job of enforcing this. + + + return DomEnum[node.classes[0]] || null; +}; +const makeNullDelimiter = function (options, classes) { + const moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses()); + return buildHTML_makeSpan(classes.concat(moreClasses)); +}; +/** + * buildGroup is the function that takes a group and calls the correct groupType + * function for it. It also handles the interaction of size and style changes + * between parents and children. + */ + +const buildGroup = function (group, options, baseOptions) { + if (!group) { + return buildHTML_makeSpan(); + } + + if (_htmlGroupBuilders[group.type]) { + // Call the groupBuilders function + // $FlowFixMe + let groupNode = _htmlGroupBuilders[group.type](group, options); // If the size changed between the parent and the current group, account + // for that size difference. + + if (baseOptions && options.size !== baseOptions.size) { + groupNode = buildHTML_makeSpan(options.sizingClasses(baseOptions), [groupNode], options); + const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; + groupNode.height *= multiplier; + groupNode.depth *= multiplier; + } + + return groupNode; + } else { + throw new src_ParseError("Got group of unknown type: '" + group.type + "'"); + } +}; +/** + * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`) + * into an unbreakable HTML node of class .base, with proper struts to + * guarantee correct vertical extent. `buildHTML` calls this repeatedly to + * make up the entire expression as a sequence of unbreakable units. + */ + +function buildHTMLUnbreakable(children, options) { + // Compute height and depth of this chunk. + const body = buildHTML_makeSpan(["base"], children, options); // Add strut, which ensures that the top of the HTML element falls at + // the height of the expression, and the bottom of the HTML element + // falls at the depth of the expression. + + const strut = buildHTML_makeSpan(["strut"]); + strut.style.height = makeEm(body.height + body.depth); + + if (body.depth) { + strut.style.verticalAlign = makeEm(-body.depth); + } + + body.children.unshift(strut); + return body; +} +/** + * Take an entire parse tree, and build it into an appropriate set of HTML + * nodes. + */ + + +function buildHTML(tree, options) { + // Strip off outer tag wrapper for processing below. + let tag = null; + + if (tree.length === 1 && tree[0].type === "tag") { + tag = tree[0].tag; + tree = tree[0].body; + } // Build the expression contained in the tree + + + const expression = buildExpression(tree, options, "root"); + let eqnNum; + + if (expression.length === 2 && expression[1].hasClass("tag")) { + // An environment with automatic equation numbers, e.g. {gather}. + eqnNum = expression.pop(); + } + + const children = []; // Create one base node for each chunk between potential line breaks. + // The TeXBook [p.173] says "A formula will be broken only after a + // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary + // operation symbol like $+$ or $-$ or $\times$, where the relation or + // binary operation is on the ``outer level'' of the formula (i.e., not + // enclosed in {...} and not part of an \over construction)." + + let parts = []; + + for (let i = 0; i < expression.length; i++) { + parts.push(expression[i]); + + if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) { + // Put any post-operator glue on same line as operator. + // Watch for \nobreak along the way, and stop at \newline. + let nobreak = false; + + while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("newline")) { + i++; + parts.push(expression[i]); + + if (expression[i].hasClass("nobreak")) { + nobreak = true; + } + } // Don't allow break if \nobreak among the post-operator glue. + + + if (!nobreak) { + children.push(buildHTMLUnbreakable(parts, options)); + parts = []; + } + } else if (expression[i].hasClass("newline")) { + // Write the line except the newline + parts.pop(); + + if (parts.length > 0) { + children.push(buildHTMLUnbreakable(parts, options)); + parts = []; + } // Put the newline at the top level + + + children.push(expression[i]); + } + } + + if (parts.length > 0) { + children.push(buildHTMLUnbreakable(parts, options)); + } // Now, if there was a tag, build it too and append it as a final child. + + + let tagChild; + + if (tag) { + tagChild = buildHTMLUnbreakable(buildExpression(tag, options, true)); + tagChild.classes = ["tag"]; + children.push(tagChild); + } else if (eqnNum) { + children.push(eqnNum); + } + + const htmlNode = buildHTML_makeSpan(["katex-html"], children); + htmlNode.setAttribute("aria-hidden", "true"); // Adjust the strut of the tag to be the maximum height of all children + // (the height of the enclosing htmlNode) for proper vertical alignment. + + if (tagChild) { + const strut = tagChild.children[0]; + strut.style.height = makeEm(htmlNode.height + htmlNode.depth); + + if (htmlNode.depth) { + strut.style.verticalAlign = makeEm(-htmlNode.depth); + } + } + + return htmlNode; +} +;// CONCATENATED MODULE: ./src/mathMLTree.js +/** + * These objects store data about MathML nodes. This is the MathML equivalent + * of the types in domTree.js. Since MathML handles its own rendering, and + * since we're mainly using MathML to improve accessibility, we don't manage + * any of the styling state that the plain DOM nodes do. + * + * The `toNode` and `toMarkup` functions work similarly to how they do in + * domTree.js, creating namespaced DOM nodes and HTML text markup respectively. + */ + + + + +function newDocumentFragment(children) { + return new DocumentFragment(children); +} +/** + * This node represents a general purpose MathML node of any type. The + * constructor requires the type of node to create (for example, `"mo"` or + * `"mspace"`, corresponding to `` and `` tags). + */ + +class MathNode { + constructor(type, children, classes) { + this.type = void 0; + this.attributes = void 0; + this.children = void 0; + this.classes = void 0; + this.type = type; + this.attributes = {}; + this.children = children || []; + this.classes = classes || []; + } + /** + * Sets an attribute on a MathML node. MathML depends on attributes to convey a + * semantic content, so this is used heavily. + */ + + + setAttribute(name, value) { + this.attributes[name] = value; + } + /** + * Gets an attribute on a MathML node. + */ + + + getAttribute(name) { + return this.attributes[name]; + } + /** + * Converts the math node into a MathML-namespaced DOM element. + */ + + + toNode() { + const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); + + for (const attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } + + if (this.classes.length > 0) { + node.className = createClass(this.classes); + } + + for (let i = 0; i < this.children.length; i++) { + // Combine multiple TextNodes into one TextNode, to prevent + // screen readers from reading each as a separate word [#3995] + if (this.children[i] instanceof TextNode && this.children[i + 1] instanceof TextNode) { + let text = this.children[i].toText() + this.children[++i].toText(); + + while (this.children[i + 1] instanceof TextNode) { + text += this.children[++i].toText(); + } + + node.appendChild(new TextNode(text).toNode()); + } else { + node.appendChild(this.children[i].toNode()); + } + } + + return node; + } + /** + * Converts the math node into an HTML markup string. + */ + + + toMarkup() { + let markup = "<" + this.type; // Add the attributes + + for (const attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + markup += " " + attr + "=\""; + markup += utils.escape(this.attributes[attr]); + markup += "\""; + } + } + + if (this.classes.length > 0) { + markup += " class =\"" + utils.escape(createClass(this.classes)) + "\""; + } + + markup += ">"; + + for (let i = 0; i < this.children.length; i++) { + markup += this.children[i].toMarkup(); + } + + markup += ""; + return markup; + } + /** + * Converts the math node into a string, similar to innerText, but escaped. + */ + + + toText() { + return this.children.map(child => child.toText()).join(""); + } + +} +/** + * This node represents a piece of text. + */ + +class TextNode { + constructor(text) { + this.text = void 0; + this.text = text; + } + /** + * Converts the text node into a DOM text node. + */ + + + toNode() { + return document.createTextNode(this.text); + } + /** + * Converts the text node into escaped HTML markup + * (representing the text itself). + */ + + + toMarkup() { + return utils.escape(this.toText()); + } + /** + * Converts the text node into a string + * (representing the text itself). + */ + + + toText() { + return this.text; + } + +} +/** + * This node represents a space, but may render as or as text, + * depending on the width. + */ + +class SpaceNode { + /** + * Create a Space node with width given in CSS ems. + */ + constructor(width) { + this.width = void 0; + this.character = void 0; + this.width = width; // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html + // for a table of space-like characters. We use Unicode + // representations instead of &LongNames; as it's not clear how to + // make the latter via document.createTextNode. + + if (width >= 0.05555 && width <= 0.05556) { + this.character = "\u200a"; //   + } else if (width >= 0.1666 && width <= 0.1667) { + this.character = "\u2009"; //   + } else if (width >= 0.2222 && width <= 0.2223) { + this.character = "\u2005"; //   + } else if (width >= 0.2777 && width <= 0.2778) { + this.character = "\u2005\u200a"; //    + } else if (width >= -0.05556 && width <= -0.05555) { + this.character = "\u200a\u2063"; // ​ + } else if (width >= -0.1667 && width <= -0.1666) { + this.character = "\u2009\u2063"; // ​ + } else if (width >= -0.2223 && width <= -0.2222) { + this.character = "\u205f\u2063"; // ​ + } else if (width >= -0.2778 && width <= -0.2777) { + this.character = "\u2005\u2063"; // ​ + } else { + this.character = null; + } + } + /** + * Converts the math node into a MathML-namespaced DOM element. + */ + + + toNode() { + if (this.character) { + return document.createTextNode(this.character); + } else { + const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace"); + node.setAttribute("width", makeEm(this.width)); + return node; + } + } + /** + * Converts the math node into an HTML markup string. + */ + + + toMarkup() { + if (this.character) { + return "" + this.character + ""; + } else { + return ""; + } + } + /** + * Converts the math node into a string, similar to innerText. + */ + + + toText() { + if (this.character) { + return this.character; + } else { + return " "; + } + } + +} + +/* harmony default export */ var mathMLTree = ({ + MathNode, + TextNode, + SpaceNode, + newDocumentFragment +}); +;// CONCATENATED MODULE: ./src/buildMathML.js +/** + * This file converts a parse tree into a corresponding MathML tree. The main + * entry point is the `buildMathML` function, which takes a parse tree from the + * parser. + */ + + + + + + + + + +/** + * Takes a symbol and converts it into a MathML text node after performing + * optional replacement from symbols.js. + */ +const makeText = function (text, mode, options) { + if (src_symbols[mode][text] && src_symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(ligatures.hasOwnProperty(text) && options && (options.fontFamily && options.fontFamily.slice(4, 6) === "tt" || options.font && options.font.slice(4, 6) === "tt"))) { + text = src_symbols[mode][text].replace; + } + + return new mathMLTree.TextNode(text); +}; +/** + * Wrap the given array of nodes in an node if needed, i.e., + * unless the array has length 1. Always returns a single node. + */ + +const makeRow = function (body) { + if (body.length === 1) { + return body[0]; + } else { + return new mathMLTree.MathNode("mrow", body); + } +}; +/** + * Returns the math variant as a string or null if none is required. + */ + +const getVariant = function (group, options) { + // Handle \text... font specifiers as best we can. + // MathML has a limited list of allowable mathvariant specifiers; see + // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt + if (options.fontFamily === "texttt") { + return "monospace"; + } else if (options.fontFamily === "textsf") { + if (options.fontShape === "textit" && options.fontWeight === "textbf") { + return "sans-serif-bold-italic"; + } else if (options.fontShape === "textit") { + return "sans-serif-italic"; + } else if (options.fontWeight === "textbf") { + return "bold-sans-serif"; + } else { + return "sans-serif"; + } + } else if (options.fontShape === "textit" && options.fontWeight === "textbf") { + return "bold-italic"; + } else if (options.fontShape === "textit") { + return "italic"; + } else if (options.fontWeight === "textbf") { + return "bold"; + } + + const font = options.font; + + if (!font || font === "mathnormal") { + return null; + } + + const mode = group.mode; + + if (font === "mathit") { + return "italic"; + } else if (font === "boldsymbol") { + return group.type === "textord" ? "bold" : "bold-italic"; + } else if (font === "mathbf") { + return "bold"; + } else if (font === "mathbb") { + return "double-struck"; + } else if (font === "mathsfit") { + return "sans-serif-italic"; + } else if (font === "mathfrak") { + return "fraktur"; + } else if (font === "mathscr" || font === "mathcal") { + // MathML makes no distinction between script and calligraphic + return "script"; + } else if (font === "mathsf") { + return "sans-serif"; + } else if (font === "mathtt") { + return "monospace"; + } + + let text = group.text; + + if (utils.contains(["\\imath", "\\jmath"], text)) { + return null; + } + + if (src_symbols[mode][text] && src_symbols[mode][text].replace) { + text = src_symbols[mode][text].replace; + } + + const fontName = buildCommon.fontMap[font].fontName; + + if (getCharacterMetrics(text, fontName, mode)) { + return buildCommon.fontMap[font].variant; + } + + return null; +}; +/** + * Check for . which is how a dot renders in MathML, + * or , + * which is how a braced comma {,} renders in MathML + */ + +function isNumberPunctuation(group) { + if (!group) { + return false; + } + + if (group.type === 'mi' && group.children.length === 1) { + const child = group.children[0]; + return child instanceof TextNode && child.text === '.'; + } else if (group.type === 'mo' && group.children.length === 1 && group.getAttribute('separator') === 'true' && group.getAttribute('lspace') === '0em' && group.getAttribute('rspace') === '0em') { + const child = group.children[0]; + return child instanceof TextNode && child.text === ','; + } else { + return false; + } +} +/** + * Takes a list of nodes, builds them, and returns a list of the generated + * MathML nodes. Also combine consecutive outputs into a single + * tag. + */ + + +const buildMathML_buildExpression = function (expression, options, isOrdgroup) { + if (expression.length === 1) { + const group = buildMathML_buildGroup(expression[0], options); + + if (isOrdgroup && group instanceof MathNode && group.type === "mo") { + // When TeX writers want to suppress spacing on an operator, + // they often put the operator by itself inside braces. + group.setAttribute("lspace", "0em"); + group.setAttribute("rspace", "0em"); + } + + return [group]; + } + + const groups = []; + let lastGroup; + + for (let i = 0; i < expression.length; i++) { + const group = buildMathML_buildGroup(expression[i], options); + + if (group instanceof MathNode && lastGroup instanceof MathNode) { + // Concatenate adjacent s + if (group.type === 'mtext' && lastGroup.type === 'mtext' && group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) { + lastGroup.children.push(...group.children); + continue; // Concatenate adjacent s + } else if (group.type === 'mn' && lastGroup.type === 'mn') { + lastGroup.children.push(...group.children); + continue; // Concatenate ... followed by . + } else if (isNumberPunctuation(group) && lastGroup.type === 'mn') { + lastGroup.children.push(...group.children); + continue; // Concatenate . followed by ... + } else if (group.type === 'mn' && isNumberPunctuation(lastGroup)) { + group.children = [...lastGroup.children, ...group.children]; + groups.pop(); // Put preceding ... or . inside base of + // ...base......exponent... (or ) + } else if ((group.type === 'msup' || group.type === 'msub') && group.children.length >= 1 && (lastGroup.type === 'mn' || isNumberPunctuation(lastGroup))) { + const base = group.children[0]; + + if (base instanceof MathNode && base.type === 'mn') { + base.children = [...lastGroup.children, ...base.children]; + groups.pop(); + } // \not + + } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) { + const lastChild = lastGroup.children[0]; + + if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (group.type === 'mo' || group.type === 'mi' || group.type === 'mn')) { + const child = group.children[0]; + + if (child instanceof TextNode && child.text.length > 0) { + // Overlay with combining character long solidus + child.text = child.text.slice(0, 1) + "\u0338" + child.text.slice(1); + groups.pop(); + } + } + } + } + + groups.push(group); + lastGroup = group; + } + + return groups; +}; +/** + * Equivalent to buildExpression, but wraps the elements in an + * if there's more than one. Returns a single node instead of an array. + */ + +const buildExpressionRow = function (expression, options, isOrdgroup) { + return makeRow(buildMathML_buildExpression(expression, options, isOrdgroup)); +}; +/** + * Takes a group from the parser and calls the appropriate groupBuilders function + * on it to produce a MathML node. + */ + +const buildMathML_buildGroup = function (group, options) { + if (!group) { + return new mathMLTree.MathNode("mrow"); + } + + if (_mathmlGroupBuilders[group.type]) { + // Call the groupBuilders function + // $FlowFixMe + const result = _mathmlGroupBuilders[group.type](group, options); // $FlowFixMe + + return result; + } else { + throw new src_ParseError("Got group of unknown type: '" + group.type + "'"); + } +}; +/** + * Takes a full parse tree and settings and builds a MathML representation of + * it. In particular, we put the elements from building the parse tree into a + * tag so we can also include that TeX source as an annotation. + * + * Note that we actually return a domTree element with a `` inside it so + * we can do appropriate styling. + */ + +function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly) { + const expression = buildMathML_buildExpression(tree, options); // TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes + // and add spacing nodes. This is necessary only adjacent to math operators + // like \sin or \lim or to subsup elements that contain math operators. + // MathML takes care of the other spacing issues. + // Wrap up the expression in an mrow so it is presented in the semantics + // tag correctly, unless it's a single or . + + let wrapper; + + if (expression.length === 1 && expression[0] instanceof MathNode && utils.contains(["mrow", "mtable"], expression[0].type)) { + wrapper = expression[0]; + } else { + wrapper = new mathMLTree.MathNode("mrow", expression); + } // Build a TeX annotation of the source + + + const annotation = new mathMLTree.MathNode("annotation", [new mathMLTree.TextNode(texExpression)]); + annotation.setAttribute("encoding", "application/x-tex"); + const semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); + const math = new mathMLTree.MathNode("math", [semantics]); + math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); + + if (isDisplayMode) { + math.setAttribute("display", "block"); + } // You can't style nodes, so we wrap the node in a span. + // NOTE: The span class is not typed to have nodes as children, and + // we don't want to make the children type more generic since the children + // of span are expected to have more fields in `buildHtml` contexts. + + + const wrapperClass = forMathmlOnly ? "katex" : "katex-mathml"; // $FlowFixMe + + return buildCommon.makeSpan([wrapperClass], [math]); +} +;// CONCATENATED MODULE: ./src/buildTree.js + + + + + + + +const optionsFromSettings = function (settings) { + return new src_Options({ + style: settings.displayMode ? src_Style.DISPLAY : src_Style.TEXT, + maxSize: settings.maxSize, + minRuleThickness: settings.minRuleThickness + }); +}; + +const displayWrap = function (node, settings) { + if (settings.displayMode) { + const classes = ["katex-display"]; + + if (settings.leqno) { + classes.push("leqno"); + } + + if (settings.fleqn) { + classes.push("fleqn"); + } + + node = buildCommon.makeSpan(classes, [node]); + } + + return node; +}; + +const buildTree = function (tree, expression, settings) { + const options = optionsFromSettings(settings); + let katexNode; + + if (settings.output === "mathml") { + return buildMathML(tree, expression, options, settings.displayMode, true); + } else if (settings.output === "html") { + const htmlNode = buildHTML(tree, options); + katexNode = buildCommon.makeSpan(["katex"], [htmlNode]); + } else { + const mathMLNode = buildMathML(tree, expression, options, settings.displayMode, false); + const htmlNode = buildHTML(tree, options); + katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, htmlNode]); + } + + return displayWrap(katexNode, settings); +}; +const buildHTMLTree = function (tree, expression, settings) { + const options = optionsFromSettings(settings); + const htmlNode = buildHTML(tree, options); + const katexNode = buildCommon.makeSpan(["katex"], [htmlNode]); + return displayWrap(katexNode, settings); +}; +/* harmony default export */ var src_buildTree = ((/* unused pure expression or super */ null && (buildTree))); +;// CONCATENATED MODULE: ./src/stretchy.js +/** + * This file provides support to buildMathML.js and buildHTML.js + * for stretchy wide elements rendered from SVG files + * and other CSS trickery. + */ + + + + + +const stretchyCodePoint = { + widehat: "^", + widecheck: "ˇ", + widetilde: "~", + utilde: "~", + overleftarrow: "\u2190", + underleftarrow: "\u2190", + xleftarrow: "\u2190", + overrightarrow: "\u2192", + underrightarrow: "\u2192", + xrightarrow: "\u2192", + underbrace: "\u23df", + overbrace: "\u23de", + overgroup: "\u23e0", + undergroup: "\u23e1", + overleftrightarrow: "\u2194", + underleftrightarrow: "\u2194", + xleftrightarrow: "\u2194", + Overrightarrow: "\u21d2", + xRightarrow: "\u21d2", + overleftharpoon: "\u21bc", + xleftharpoonup: "\u21bc", + overrightharpoon: "\u21c0", + xrightharpoonup: "\u21c0", + xLeftarrow: "\u21d0", + xLeftrightarrow: "\u21d4", + xhookleftarrow: "\u21a9", + xhookrightarrow: "\u21aa", + xmapsto: "\u21a6", + xrightharpoondown: "\u21c1", + xleftharpoondown: "\u21bd", + xrightleftharpoons: "\u21cc", + xleftrightharpoons: "\u21cb", + xtwoheadleftarrow: "\u219e", + xtwoheadrightarrow: "\u21a0", + xlongequal: "=", + xtofrom: "\u21c4", + xrightleftarrows: "\u21c4", + xrightequilibrium: "\u21cc", + // Not a perfect match. + xleftequilibrium: "\u21cb", + // None better available. + "\\cdrightarrow": "\u2192", + "\\cdleftarrow": "\u2190", + "\\cdlongequal": "=" +}; + +const mathMLnode = function (label) { + const node = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(stretchyCodePoint[label.replace(/^\\/, '')])]); + node.setAttribute("stretchy", "true"); + return node; +}; // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts. +// Copyright (c) 2009-2010, Design Science, Inc. () +// Copyright (c) 2014-2017 Khan Academy () +// Licensed under the SIL Open Font License, Version 1.1. +// See \nhttp://scripts.sil.org/OFL +// Very Long SVGs +// Many of the KaTeX stretchy wide elements use a long SVG image and an +// overflow: hidden tactic to achieve a stretchy image while avoiding +// distortion of arrowheads or brace corners. +// The SVG typically contains a very long (400 em) arrow. +// The SVG is in a container span that has overflow: hidden, so the span +// acts like a window that exposes only part of the SVG. +// The SVG always has a longer, thinner aspect ratio than the container span. +// After the SVG fills 100% of the height of the container span, +// there is a long arrow shaft left over. That left-over shaft is not shown. +// Instead, it is sliced off because the span's CSS has overflow: hidden. +// Thus, the reader sees an arrow that matches the subject matter width +// without distortion. +// Some functions, such as \cancel, need to vary their aspect ratio. These +// functions do not get the overflow SVG treatment. +// Second Brush Stroke +// Low resolution monitors struggle to display images in fine detail. +// So browsers apply anti-aliasing. A long straight arrow shaft therefore +// will sometimes appear as if it has a blurred edge. +// To mitigate this, these SVG files contain a second "brush-stroke" on the +// arrow shafts. That is, a second long thin rectangular SVG path has been +// written directly on top of each arrow shaft. This reinforcement causes +// some of the screen pixels to display as black instead of the anti-aliased +// gray pixel that a single path would generate. So we get arrow shafts +// whose edges appear to be sharper. +// In the katexImagesData object just below, the dimensions all +// correspond to path geometry inside the relevant SVG. +// For example, \overrightarrow uses the same arrowhead as glyph U+2192 +// from the KaTeX Main font. The scaling factor is 1000. +// That is, inside the font, that arrowhead is 522 units tall, which +// corresponds to 0.522 em inside the document. + + +const katexImagesData = { + // path(s), minWidth, height, align + overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], + overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], + underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], + underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], + xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"], + "\\cdrightarrow": [["rightarrow"], 3.0, 522, "xMaxYMin"], + // CD minwwidth2.5pc + xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"], + "\\cdleftarrow": [["leftarrow"], 3.0, 522, "xMinYMin"], + Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"], + xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"], + xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"], + overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"], + xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"], + xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"], + overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"], + xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"], + xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"], + xlongequal: [["longequal"], 0.888, 334, "xMinYMin"], + "\\cdlongequal": [["longequal"], 3.0, 334, "xMinYMin"], + xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"], + xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"], + overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], + overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548], + underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548], + underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], + xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522], + xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560], + xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716], + xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716], + xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522], + xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522], + overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], + underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], + overgroup: [["leftgroup", "rightgroup"], 0.888, 342], + undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342], + xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522], + xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528], + // The next three arrows are from the mhchem package. + // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the + // document as \xrightarrow or \xrightleftharpoons. Those have + // min-length = 1.75em, so we set min-length on these next three to match. + xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901], + xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716], + xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716] +}; + +const groupLength = function (arg) { + if (arg.type === "ordgroup") { + return arg.body.length; + } else { + return 1; + } +}; + +const svgSpan = function (group, options) { + // Create a span with inline SVG for the element. + function buildSvgSpan_() { + let viewBoxWidth = 400000; // default + + const label = group.label.slice(1); + + if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) { + // Each type in the `if` statement corresponds to one of the ParseNode + // types below. This narrowing is required to access `grp.base`. + // $FlowFixMe + const grp = group; // There are four SVG images available for each function. + // Choose a taller image when there are more characters. + + const numChars = groupLength(grp.base); + let viewBoxHeight; + let pathName; + let height; + + if (numChars > 5) { + if (label === "widehat" || label === "widecheck") { + viewBoxHeight = 420; + viewBoxWidth = 2364; + height = 0.42; + pathName = label + "4"; + } else { + viewBoxHeight = 312; + viewBoxWidth = 2340; + height = 0.34; + pathName = "tilde4"; + } + } else { + const imgIndex = [1, 1, 2, 2, 3, 3][numChars]; + + if (label === "widehat" || label === "widecheck") { + viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex]; + viewBoxHeight = [0, 239, 300, 360, 420][imgIndex]; + height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex]; + pathName = label + imgIndex; + } else { + viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex]; + viewBoxHeight = [0, 260, 286, 306, 312][imgIndex]; + height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex]; + pathName = "tilde" + imgIndex; + } + } + + const path = new PathNode(pathName); + const svgNode = new SvgNode([path], { + "width": "100%", + "height": makeEm(height), + "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight, + "preserveAspectRatio": "none" + }); + return { + span: buildCommon.makeSvgSpan([], [svgNode], options), + minWidth: 0, + height + }; + } else { + const spans = []; + const data = katexImagesData[label]; + const [paths, minWidth, viewBoxHeight] = data; + const height = viewBoxHeight / 1000; + const numSvgChildren = paths.length; + let widthClasses; + let aligns; + + if (numSvgChildren === 1) { + // $FlowFixMe: All these cases must be of the 4-tuple type. + const align1 = data[3]; + widthClasses = ["hide-tail"]; + aligns = [align1]; + } else if (numSvgChildren === 2) { + widthClasses = ["halfarrow-left", "halfarrow-right"]; + aligns = ["xMinYMin", "xMaxYMin"]; + } else if (numSvgChildren === 3) { + widthClasses = ["brace-left", "brace-center", "brace-right"]; + aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"]; + } else { + throw new Error("Correct katexImagesData or update code here to support\n " + numSvgChildren + " children."); + } + + for (let i = 0; i < numSvgChildren; i++) { + const path = new PathNode(paths[i]); + const svgNode = new SvgNode([path], { + "width": "400em", + "height": makeEm(height), + "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight, + "preserveAspectRatio": aligns[i] + " slice" + }); + const span = buildCommon.makeSvgSpan([widthClasses[i]], [svgNode], options); + + if (numSvgChildren === 1) { + return { + span, + minWidth, + height + }; + } else { + span.style.height = makeEm(height); + spans.push(span); + } + } + + return { + span: buildCommon.makeSpan(["stretchy"], spans, options), + minWidth, + height + }; + } + } // buildSvgSpan_() + + + const { + span, + minWidth, + height + } = buildSvgSpan_(); // Note that we are returning span.depth = 0. + // Any adjustments relative to the baseline must be done in buildHTML. + + span.height = height; + span.style.height = makeEm(height); + + if (minWidth > 0) { + span.style.minWidth = makeEm(minWidth); + } + + return span; +}; + +const encloseSpan = function (inner, label, topPad, bottomPad, options) { + // Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl + let img; + const totalHeight = inner.height + inner.depth + topPad + bottomPad; + + if (/fbox|color|angl/.test(label)) { + img = buildCommon.makeSpan(["stretchy", label], [], options); + + if (label === "fbox") { + const color = options.color && options.getColor(); + + if (color) { + img.style.borderColor = color; + } + } + } else { + // \cancel, \bcancel, or \xcancel + // Since \cancel's SVG is inline and it omits the viewBox attribute, + // its stroke-width will not vary with span area. + const lines = []; + + if (/^[bx]cancel$/.test(label)) { + lines.push(new LineNode({ + "x1": "0", + "y1": "0", + "x2": "100%", + "y2": "100%", + "stroke-width": "0.046em" + })); + } + + if (/^x?cancel$/.test(label)) { + lines.push(new LineNode({ + "x1": "0", + "y1": "100%", + "x2": "100%", + "y2": "0", + "stroke-width": "0.046em" + })); + } + + const svgNode = new SvgNode(lines, { + "width": "100%", + "height": makeEm(totalHeight) + }); + img = buildCommon.makeSvgSpan([], [svgNode], options); + } + + img.height = totalHeight; + img.style.height = makeEm(totalHeight); + return img; +}; + +/* harmony default export */ var stretchy = ({ + encloseSpan, + mathMLnode, + svgSpan +}); +;// CONCATENATED MODULE: ./src/parseNode.js + + +/** + * Asserts that the node is of the given type and returns it with stricter + * typing. Throws if the node's type does not match. + */ +function assertNodeType(node, type) { + if (!node || node.type !== type) { + throw new Error("Expected node of type " + type + ", but got " + (node ? "node of type " + node.type : String(node))); + } // $FlowFixMe, >=0.125 + + + return node; +} +/** + * Returns the node more strictly typed iff it is of the given type. Otherwise, + * returns null. + */ + +function assertSymbolNodeType(node) { + const typedNode = checkSymbolNodeType(node); + + if (!typedNode) { + throw new Error("Expected node of symbol group type, but got " + (node ? "node of type " + node.type : String(node))); + } + + return typedNode; +} +/** + * Returns the node more strictly typed iff it is of the given type. Otherwise, + * returns null. + */ + +function checkSymbolNodeType(node) { + if (node && (node.type === "atom" || NON_ATOMS.hasOwnProperty(node.type))) { + // $FlowFixMe + return node; + } + + return null; +} +;// CONCATENATED MODULE: ./src/functions/accent.js + + + + + + + + + + +// NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but +// also "supsub" since an accent can affect super/subscripting. +const htmlBuilder = (grp, options) => { + // Accents are handled in the TeXbook pg. 443, rule 12. + let base; + let group; + let supSubGroup; + + if (grp && grp.type === "supsub") { + // If our base is a character box, and we have superscripts and + // subscripts, the supsub will defer to us. In particular, we want + // to attach the superscripts and subscripts to the inner body (so + // that the position of the superscripts and subscripts won't be + // affected by the height of the accent). We accomplish this by + // sticking the base of the accent into the base of the supsub, and + // rendering that, while keeping track of where the accent is. + // The real accent group is the base of the supsub group + group = assertNodeType(grp.base, "accent"); // The character box is the base of the accent group + + base = group.base; // Stick the character box into the base of the supsub group + + grp.base = base; // Rerender the supsub group with its new base, and store that + // result. + + supSubGroup = assertSpan(buildGroup(grp, options)); // reset original base + + grp.base = group; + } else { + group = assertNodeType(grp, "accent"); + base = group.base; + } // Build the base group + + + const body = buildGroup(base, options.havingCrampedStyle()); // Does the accent need to shift for the skew of a character? + + const mustShift = group.isShifty && utils.isCharacterBox(base); // Calculate the skew of the accent. This is based on the line "If the + // nucleus is not a single character, let s = 0; otherwise set s to the + // kern amount for the nucleus followed by the \skewchar of its font." + // Note that our skew metrics are just the kern between each character + // and the skewchar. + + let skew = 0; + + if (mustShift) { + // If the base is a character box, then we want the skew of the + // innermost character. To do that, we find the innermost character: + const baseChar = utils.getBaseElem(base); // Then, we render its group to get the symbol inside it + + const baseGroup = buildGroup(baseChar, options.havingCrampedStyle()); // Finally, we pull the skew off of the symbol. + + skew = assertSymbolDomNode(baseGroup).skew; // Note that we now throw away baseGroup, because the layers we + // removed with getBaseElem might contain things like \color which + // we can't get rid of. + // TODO(emily): Find a better way to get the skew + } + + const accentBelow = group.label === "\\c"; // calculate the amount of space between the body and the accent + + let clearance = accentBelow ? body.height + body.depth : Math.min(body.height, options.fontMetrics().xHeight); // Build the accent + + let accentBody; + + if (!group.isStretchy) { + let accent; + let width; + + if (group.label === "\\vec") { + // Before version 0.9, \vec used the combining font glyph U+20D7. + // But browsers, especially Safari, are not consistent in how they + // render combining characters when not preceded by a character. + // So now we use an SVG. + // If Safari reforms, we should consider reverting to the glyph. + accent = buildCommon.staticSvg("vec", options); + width = buildCommon.svgData.vec[1]; + } else { + accent = buildCommon.makeOrd({ + mode: group.mode, + text: group.label + }, options, "textord"); + accent = assertSymbolDomNode(accent); // Remove the italic correction of the accent, because it only serves to + // shift the accent over to a place we don't want. + + accent.italic = 0; + width = accent.width; + + if (accentBelow) { + clearance += accent.depth; + } + } + + accentBody = buildCommon.makeSpan(["accent-body"], [accent]); // "Full" accents expand the width of the resulting symbol to be + // at least the width of the accent, and overlap directly onto the + // character without any vertical offset. + + const accentFull = group.label === "\\textcircled"; + + if (accentFull) { + accentBody.classes.push('accent-full'); + clearance = body.height; + } // Shift the accent over by the skew. + + + let left = skew; // CSS defines `.katex .accent .accent-body:not(.accent-full) { width: 0 }` + // so that the accent doesn't contribute to the bounding box. + // We need to shift the character by its width (effectively half + // its width) to compensate. + + if (!accentFull) { + left -= width / 2; + } + + accentBody.style.left = makeEm(left); // \textcircled uses the \bigcirc glyph, so it needs some + // vertical adjustment to match LaTeX. + + if (group.label === "\\textcircled") { + accentBody.style.top = ".2em"; + } + + accentBody = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: body + }, { + type: "kern", + size: -clearance + }, { + type: "elem", + elem: accentBody + }] + }, options); + } else { + accentBody = stretchy.svgSpan(group, options); + accentBody = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: body + }, { + type: "elem", + elem: accentBody, + wrapperClasses: ["svg-align"], + wrapperStyle: skew > 0 ? { + width: "calc(100% - " + makeEm(2 * skew) + ")", + marginLeft: makeEm(2 * skew) + } : undefined + }] + }, options); + } + + const accentWrap = buildCommon.makeSpan(["mord", "accent"], [accentBody], options); + + if (supSubGroup) { + // Here, we replace the "base" child of the supsub with our newly + // generated accent. + supSubGroup.children[0] = accentWrap; // Since we don't rerun the height calculation after replacing the + // accent, we manually recalculate height. + + supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height); // Accents should always be ords, even when their innards are not. + + supSubGroup.classes[0] = "mord"; + return supSubGroup; + } else { + return accentWrap; + } +}; + +const mathmlBuilder = (group, options) => { + const accentNode = group.isStretchy ? stretchy.mathMLnode(group.label) : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); + const node = new mathMLTree.MathNode("mover", [buildMathML_buildGroup(group.base, options), accentNode]); + node.setAttribute("accent", "true"); + return node; +}; + +const NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => "\\" + accent).join("|")); // Accents + +defineFunction({ + type: "accent", + names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"], + props: { + numArgs: 1 + }, + handler: (context, args) => { + const base = normalizeArgument(args[0]); + const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); + const isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck"; + return { + type: "accent", + mode: context.parser.mode, + label: context.funcName, + isStretchy: isStretchy, + isShifty: isShifty, + base: base + }; + }, + htmlBuilder, + mathmlBuilder +}); // Text-mode accents + +defineFunction({ + type: "accent", + names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\c", "\\r", "\\H", "\\v", "\\textcircled"], + props: { + numArgs: 1, + allowedInText: true, + allowedInMath: true, + // unless in strict mode + argTypes: ["primitive"] + }, + handler: (context, args) => { + const base = args[0]; + let mode = context.parser.mode; + + if (mode === "math") { + context.parser.settings.reportNonstrict("mathVsTextAccents", "LaTeX's accent " + context.funcName + " works only in text mode"); + mode = "text"; + } + + return { + type: "accent", + mode: mode, + label: context.funcName, + isStretchy: false, + isShifty: true, + base: base + }; + }, + htmlBuilder, + mathmlBuilder +}); +;// CONCATENATED MODULE: ./src/functions/accentunder.js +// Horizontal overlap functions + + + + + + +defineFunction({ + type: "accentUnder", + names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"], + props: { + numArgs: 1 + }, + handler: (_ref, args) => { + let { + parser, + funcName + } = _ref; + const base = args[0]; + return { + type: "accentUnder", + mode: parser.mode, + label: funcName, + base: base + }; + }, + htmlBuilder: (group, options) => { + // Treat under accents much like underlines. + const innerGroup = buildGroup(group.base, options); + const accentBody = stretchy.svgSpan(group, options); + const kern = group.label === "\\utilde" ? 0.12 : 0; // Generate the vlist, with the appropriate kerns + + const vlist = buildCommon.makeVList({ + positionType: "top", + positionData: innerGroup.height, + children: [{ + type: "elem", + elem: accentBody, + wrapperClasses: ["svg-align"] + }, { + type: "kern", + size: kern + }, { + type: "elem", + elem: innerGroup + }] + }, options); + return buildCommon.makeSpan(["mord", "accentunder"], [vlist], options); + }, + mathmlBuilder: (group, options) => { + const accentNode = stretchy.mathMLnode(group.label); + const node = new mathMLTree.MathNode("munder", [buildMathML_buildGroup(group.base, options), accentNode]); + node.setAttribute("accentunder", "true"); + return node; + } +}); +;// CONCATENATED MODULE: ./src/functions/arrow.js + + + + + + + +// Helper function +const paddedNode = group => { + const node = new mathMLTree.MathNode("mpadded", group ? [group] : []); + node.setAttribute("width", "+0.6em"); + node.setAttribute("lspace", "0.3em"); + return node; +}; // Stretchy arrows with an optional argument + + +defineFunction({ + type: "xArrow", + names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom", // The next 3 functions are here to support the mhchem extension. + // Direct use of these functions is discouraged and may break someday. + "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", // The next 3 functions are here only to support the {CD} environment. + "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"], + props: { + numArgs: 1, + numOptionalArgs: 1 + }, + + handler(_ref, args, optArgs) { + let { + parser, + funcName + } = _ref; + return { + type: "xArrow", + mode: parser.mode, + label: funcName, + body: args[0], + below: optArgs[0] + }; + }, + + // Flow is unable to correctly infer the type of `group`, even though it's + // unambiguously determined from the passed-in `type` above. + htmlBuilder(group, options) { + const style = options.style; // Build the argument groups in the appropriate style. + // Ref: amsmath.dtx: \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}% + // Some groups can return document fragments. Handle those by wrapping + // them in a span. + + let newOptions = options.havingStyle(style.sup()); + const upperGroup = buildCommon.wrapFragment(buildGroup(group.body, newOptions, options), options); + const arrowPrefix = group.label.slice(0, 2) === "\\x" ? "x" : "cd"; + upperGroup.classes.push(arrowPrefix + "-arrow-pad"); + let lowerGroup; + + if (group.below) { + // Build the lower group + newOptions = options.havingStyle(style.sub()); + lowerGroup = buildCommon.wrapFragment(buildGroup(group.below, newOptions, options), options); + lowerGroup.classes.push(arrowPrefix + "-arrow-pad"); + } + + const arrowBody = stretchy.svgSpan(group, options); // Re shift: Note that stretchy.svgSpan returned arrowBody.depth = 0. + // The point we want on the math axis is at 0.5 * arrowBody.height. + + const arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height; // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi + + let upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu + + if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") { + upperShift -= upperGroup.depth; // shift up if depth encroaches + } // Generate the vlist + + + let vlist; + + if (lowerGroup) { + const lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111; + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: upperGroup, + shift: upperShift + }, { + type: "elem", + elem: arrowBody, + shift: arrowShift + }, { + type: "elem", + elem: lowerGroup, + shift: lowerShift + }] + }, options); + } else { + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: upperGroup, + shift: upperShift + }, { + type: "elem", + elem: arrowBody, + shift: arrowShift + }] + }, options); + } // $FlowFixMe: Replace this with passing "svg-align" into makeVList. + + + vlist.children[0].children[0].children[1].classes.push("svg-align"); + return buildCommon.makeSpan(["mrel", "x-arrow"], [vlist], options); + }, + + mathmlBuilder(group, options) { + const arrowNode = stretchy.mathMLnode(group.label); + arrowNode.setAttribute("minsize", group.label.charAt(0) === "x" ? "1.75em" : "3.0em"); + let node; + + if (group.body) { + const upperNode = paddedNode(buildMathML_buildGroup(group.body, options)); + + if (group.below) { + const lowerNode = paddedNode(buildMathML_buildGroup(group.below, options)); + node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); + } else { + node = new mathMLTree.MathNode("mover", [arrowNode, upperNode]); + } + } else if (group.below) { + const lowerNode = paddedNode(buildMathML_buildGroup(group.below, options)); + node = new mathMLTree.MathNode("munder", [arrowNode, lowerNode]); + } else { + // This should never happen. + // Parser.js throws an error if there is no argument. + node = paddedNode(); + node = new mathMLTree.MathNode("mover", [arrowNode, node]); + } + + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/mclass.js + + + + + + +const mclass_makeSpan = buildCommon.makeSpan; + +function mclass_htmlBuilder(group, options) { + const elements = buildExpression(group.body, options, true); + return mclass_makeSpan([group.mclass], elements, options); +} + +function mclass_mathmlBuilder(group, options) { + let node; + const inner = buildMathML_buildExpression(group.body, options); + + if (group.mclass === "minner") { + node = new mathMLTree.MathNode("mpadded", inner); + } else if (group.mclass === "mord") { + if (group.isCharacterBox) { + node = inner[0]; + node.type = "mi"; + } else { + node = new mathMLTree.MathNode("mi", inner); + } + } else { + if (group.isCharacterBox) { + node = inner[0]; + node.type = "mo"; + } else { + node = new mathMLTree.MathNode("mo", inner); + } // Set spacing based on what is the most likely adjacent atom type. + // See TeXbook p170. + + + if (group.mclass === "mbin") { + node.attributes.lspace = "0.22em"; // medium space + + node.attributes.rspace = "0.22em"; + } else if (group.mclass === "mpunct") { + node.attributes.lspace = "0em"; + node.attributes.rspace = "0.17em"; // thinspace + } else if (group.mclass === "mopen" || group.mclass === "mclose") { + node.attributes.lspace = "0em"; + node.attributes.rspace = "0em"; + } else if (group.mclass === "minner") { + node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option + + node.attributes.width = "+0.1111em"; + } // MathML default space is 5/18 em, so needs no action. + // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo + + } + + return node; +} // Math class commands except \mathop + + +defineFunction({ + type: "mclass", + names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"], + props: { + numArgs: 1, + primitive: true + }, + + handler(_ref, args) { + let { + parser, + funcName + } = _ref; + const body = args[0]; + return { + type: "mclass", + mode: parser.mode, + mclass: "m" + funcName.slice(5), + // TODO(kevinb): don't prefix with 'm' + body: ordargument(body), + isCharacterBox: utils.isCharacterBox(body) + }; + }, + + htmlBuilder: mclass_htmlBuilder, + mathmlBuilder: mclass_mathmlBuilder +}); +const binrelClass = arg => { + // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. + // (by rendering separately and with {}s before and after, and measuring + // the change in spacing). We'll do roughly the same by detecting the + // atom type directly. + const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; + + if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { + return "m" + atom.family; + } else { + return "mord"; + } +}; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. +// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. + +defineFunction({ + type: "mclass", + names: ["\\@binrel"], + props: { + numArgs: 2 + }, + + handler(_ref2, args) { + let { + parser + } = _ref2; + return { + type: "mclass", + mode: parser.mode, + mclass: binrelClass(args[0]), + body: ordargument(args[1]), + isCharacterBox: utils.isCharacterBox(args[1]) + }; + } + +}); // Build a relation or stacked op by placing one symbol on top of another + +defineFunction({ + type: "mclass", + names: ["\\stackrel", "\\overset", "\\underset"], + props: { + numArgs: 2 + }, + + handler(_ref3, args) { + let { + parser, + funcName + } = _ref3; + const baseArg = args[1]; + const shiftedArg = args[0]; + let mclass; + + if (funcName !== "\\stackrel") { + // LaTeX applies \binrel spacing to \overset and \underset. + mclass = binrelClass(baseArg); + } else { + mclass = "mrel"; // for \stackrel + } + + const baseOp = { + type: "op", + mode: baseArg.mode, + limits: true, + alwaysHandleSupSub: true, + parentIsSupSub: false, + symbol: false, + suppressBaseShift: funcName !== "\\stackrel", + body: ordargument(baseArg) + }; + const supsub = { + type: "supsub", + mode: shiftedArg.mode, + base: baseOp, + sup: funcName === "\\underset" ? null : shiftedArg, + sub: funcName === "\\underset" ? shiftedArg : null + }; + return { + type: "mclass", + mode: parser.mode, + mclass, + body: [supsub], + isCharacterBox: utils.isCharacterBox(supsub) + }; + }, + + htmlBuilder: mclass_htmlBuilder, + mathmlBuilder: mclass_mathmlBuilder +}); +;// CONCATENATED MODULE: ./src/functions/pmb.js + + + + + + +// \pmb is a simulation of bold font. +// The version of \pmb in ambsy.sty works by typesetting three copies +// with small offsets. We use CSS text-shadow. +// It's a hack. Not as good as a real bold font. Better than nothing. +defineFunction({ + type: "pmb", + names: ["\\pmb"], + props: { + numArgs: 1, + allowedInText: true + }, + + handler(_ref, args) { + let { + parser + } = _ref; + return { + type: "pmb", + mode: parser.mode, + mclass: binrelClass(args[0]), + body: ordargument(args[0]) + }; + }, + + htmlBuilder(group, options) { + const elements = buildExpression(group.body, options, true); + const node = buildCommon.makeSpan([group.mclass], elements, options); + node.style.textShadow = "0.02em 0.01em 0.04px"; + return node; + }, + + mathmlBuilder(group, style) { + const inner = buildMathML_buildExpression(group.body, style); // Wrap with an element. + + const node = new mathMLTree.MathNode("mstyle", inner); + node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"); + return node; + } + +}); +;// CONCATENATED MODULE: ./src/environments/cd.js + + + + + + + + +const cdArrowFunctionName = { + ">": "\\\\cdrightarrow", + "<": "\\\\cdleftarrow", + "=": "\\\\cdlongequal", + "A": "\\uparrow", + "V": "\\downarrow", + "|": "\\Vert", + ".": "no arrow" +}; + +const newCell = () => { + // Create an empty cell, to be filled below with parse nodes. + // The parseTree from this module must be constructed like the + // one created by parseArray(), so an empty CD cell must + // be a ParseNode<"styling">. And CD is always displaystyle. + // So these values are fixed and flow can do implicit typing. + return { + type: "styling", + body: [], + mode: "math", + style: "display" + }; +}; + +const isStartOfArrow = node => { + return node.type === "textord" && node.text === "@"; +}; + +const isLabelEnd = (node, endChar) => { + return (node.type === "mathord" || node.type === "atom") && node.text === endChar; +}; + +function cdArrow(arrowChar, labels, parser) { + // Return a parse tree of an arrow and its labels. + // This acts in a way similar to a macro expansion. + const funcName = cdArrowFunctionName[arrowChar]; + + switch (funcName) { + case "\\\\cdrightarrow": + case "\\\\cdleftarrow": + return parser.callFunction(funcName, [labels[0]], [labels[1]]); + + case "\\uparrow": + case "\\downarrow": + { + const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); + const bareArrow = { + type: "atom", + text: funcName, + mode: "math", + family: "rel" + }; + const sizedArrow = parser.callFunction("\\Big", [bareArrow], []); + const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); + const arrowGroup = { + type: "ordgroup", + mode: "math", + body: [leftLabel, sizedArrow, rightLabel] + }; + return parser.callFunction("\\\\cdparent", [arrowGroup], []); + } + + case "\\\\cdlongequal": + return parser.callFunction("\\\\cdlongequal", [], []); + + case "\\Vert": + { + const arrow = { + type: "textord", + text: "\\Vert", + mode: "math" + }; + return parser.callFunction("\\Big", [arrow], []); + } + + default: + return { + type: "textord", + text: " ", + mode: "math" + }; + } +} + +function parseCD(parser) { + // Get the array's parse nodes with \\ temporarily mapped to \cr. + const parsedRows = []; + parser.gullet.beginGroup(); + parser.gullet.macros.set("\\cr", "\\\\\\relax"); + parser.gullet.beginGroup(); + + while (true) { + // eslint-disable-line no-constant-condition + // Get the parse nodes for the next row. + parsedRows.push(parser.parseExpression(false, "\\\\")); + parser.gullet.endGroup(); + parser.gullet.beginGroup(); + const next = parser.fetch().text; + + if (next === "&" || next === "\\\\") { + parser.consume(); + } else if (next === "\\end") { + if (parsedRows[parsedRows.length - 1].length === 0) { + parsedRows.pop(); // final row ended in \\ + } + + break; + } else { + throw new src_ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); + } + } + + let row = []; + const body = [row]; // Loop thru the parse nodes. Collect them into cells and arrows. + + for (let i = 0; i < parsedRows.length; i++) { + // Start a new row. + const rowNodes = parsedRows[i]; // Create the first cell. + + let cell = newCell(); + + for (let j = 0; j < rowNodes.length; j++) { + if (!isStartOfArrow(rowNodes[j])) { + // If a parseNode is not an arrow, it goes into a cell. + cell.body.push(rowNodes[j]); + } else { + // Parse node j is an "@", the start of an arrow. + // Before starting on the arrow, push the cell into `row`. + row.push(cell); // Now collect parseNodes into an arrow. + // The character after "@" defines the arrow type. + + j += 1; + const arrowChar = assertSymbolNodeType(rowNodes[j]).text; // Create two empty label nodes. We may or may not use them. + + const labels = new Array(2); + labels[0] = { + type: "ordgroup", + mode: "math", + body: [] + }; + labels[1] = { + type: "ordgroup", + mode: "math", + body: [] + }; // Process the arrow. + + if ("=|.".indexOf(arrowChar) > -1) {// Three "arrows", ``@=`, `@|`, and `@.`, do not take labels. + // Do nothing here. + } else if ("<>AV".indexOf(arrowChar) > -1) { + // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take + // two optional labels. E.g. the right-point arrow syntax is + // really: @>{optional label}>{optional label}> + // Collect parseNodes into labels. + for (let labelNum = 0; labelNum < 2; labelNum++) { + let inLabel = true; + + for (let k = j + 1; k < rowNodes.length; k++) { + if (isLabelEnd(rowNodes[k], arrowChar)) { + inLabel = false; + j = k; + break; + } + + if (isStartOfArrow(rowNodes[k])) { + throw new src_ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[k]); + } + + labels[labelNum].body.push(rowNodes[k]); + } + + if (inLabel) { + // isLabelEnd never returned a true. + throw new src_ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[j]); + } + } + } else { + throw new src_ParseError("Expected one of \"<>AV=|.\" after @", rowNodes[j]); + } // Now join the arrow to its labels. + + + const arrow = cdArrow(arrowChar, labels, parser); // Wrap the arrow in ParseNode<"styling">. + // This is done to match parseArray() behavior. + + const wrappedArrow = { + type: "styling", + body: [arrow], + mode: "math", + style: "display" // CD is always displaystyle. + + }; + row.push(wrappedArrow); // In CD's syntax, cells are implicit. That is, everything that + // is not an arrow gets collected into a cell. So create an empty + // cell now. It will collect upcoming parseNodes. + + cell = newCell(); + } + } + + if (i % 2 === 0) { + // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell + // The last cell is not yet pushed into `row`, so: + row.push(cell); + } else { + // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow + // Remove the empty cell that was placed at the beginning of `row`. + row.shift(); + } + + row = []; + body.push(row); + } // End row group + + + parser.gullet.endGroup(); // End array group defining \\ + + parser.gullet.endGroup(); // define column separation. + + const cols = new Array(body[0].length).fill({ + type: "align", + align: "c", + pregap: 0.25, + // CD package sets \enskip between columns. + postgap: 0.25 // So pre and post each get half an \enskip, i.e. 0.25em. + + }); + return { + type: "array", + mode: "math", + body, + arraystretch: 1, + addJot: true, + rowGaps: [null], + cols, + colSeparationType: "CD", + hLinesBeforeRow: new Array(body.length + 1).fill([]) + }; +} // The functions below are not available for general use. +// They are here only for internal use by the {CD} environment in placing labels +// next to vertical arrows. +// We don't need any such functions for horizontal arrows because we can reuse +// the functionality that already exists for extensible arrows. + +defineFunction({ + type: "cdlabel", + names: ["\\\\cdleft", "\\\\cdright"], + props: { + numArgs: 1 + }, + + handler(_ref, args) { + let { + parser, + funcName + } = _ref; + return { + type: "cdlabel", + mode: parser.mode, + side: funcName.slice(4), + label: args[0] + }; + }, + + htmlBuilder(group, options) { + const newOptions = options.havingStyle(options.style.sup()); + const label = buildCommon.wrapFragment(buildGroup(group.label, newOptions, options), options); + label.classes.push("cd-label-" + group.side); + label.style.bottom = makeEm(0.8 - label.depth); // Zero out label height & depth, so vertical align of arrow is set + // by the arrow height, not by the label. + + label.height = 0; + label.depth = 0; + return label; + }, + + mathmlBuilder(group, options) { + let label = new mathMLTree.MathNode("mrow", [buildMathML_buildGroup(group.label, options)]); + label = new mathMLTree.MathNode("mpadded", [label]); + label.setAttribute("width", "0"); + + if (group.side === "left") { + label.setAttribute("lspace", "-1width"); + } // We have to guess at vertical alignment. We know the arrow is 1.8em tall, + // But we don't know the height or depth of the label. + + + label.setAttribute("voffset", "0.7em"); + label = new mathMLTree.MathNode("mstyle", [label]); + label.setAttribute("displaystyle", "false"); + label.setAttribute("scriptlevel", "1"); + return label; + } + +}); +defineFunction({ + type: "cdlabelparent", + names: ["\\\\cdparent"], + props: { + numArgs: 1 + }, + + handler(_ref2, args) { + let { + parser + } = _ref2; + return { + type: "cdlabelparent", + mode: parser.mode, + fragment: args[0] + }; + }, + + htmlBuilder(group, options) { + // Wrap the vertical arrow and its labels. + // The parent gets position: relative. The child gets position: absolute. + // So CSS can locate the label correctly. + const parent = buildCommon.wrapFragment(buildGroup(group.fragment, options), options); + parent.classes.push("cd-vert-arrow"); + return parent; + }, + + mathmlBuilder(group, options) { + return new mathMLTree.MathNode("mrow", [buildMathML_buildGroup(group.fragment, options)]); + } + +}); +;// CONCATENATED MODULE: ./src/functions/char.js + + + // \@char is an internal function that takes a grouped decimal argument like +// {123} and converts into symbol with code 123. It is used by the *macro* +// \char defined in macros.js. + +defineFunction({ + type: "textord", + names: ["\\@char"], + props: { + numArgs: 1, + allowedInText: true + }, + + handler(_ref, args) { + let { + parser + } = _ref; + const arg = assertNodeType(args[0], "ordgroup"); + const group = arg.body; + let number = ""; + + for (let i = 0; i < group.length; i++) { + const node = assertNodeType(group[i], "textord"); + number += node.text; + } + + let code = parseInt(number); + let text; + + if (isNaN(code)) { + throw new src_ParseError("\\@char has non-numeric argument " + number); // If we drop IE support, the following code could be replaced with + // text = String.fromCodePoint(code) + } else if (code < 0 || code >= 0x10ffff) { + throw new src_ParseError("\\@char with invalid code point " + number); + } else if (code <= 0xffff) { + text = String.fromCharCode(code); + } else { + // Astral code point; split into surrogate halves + code -= 0x10000; + text = String.fromCharCode((code >> 10) + 0xd800, (code & 0x3ff) + 0xdc00); + } + + return { + type: "textord", + mode: parser.mode, + text: text + }; + } + +}); +;// CONCATENATED MODULE: ./src/functions/color.js + + + + + + + +const color_htmlBuilder = (group, options) => { + const elements = buildExpression(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains. + // To accomplish this, we wrap the results in a fragment, so the inner + // elements will be able to directly interact with their neighbors. For + // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3` + + return buildCommon.makeFragment(elements); +}; + +const color_mathmlBuilder = (group, options) => { + const inner = buildMathML_buildExpression(group.body, options.withColor(group.color)); + const node = new mathMLTree.MathNode("mstyle", inner); + node.setAttribute("mathcolor", group.color); + return node; +}; + +defineFunction({ + type: "color", + names: ["\\textcolor"], + props: { + numArgs: 2, + allowedInText: true, + argTypes: ["color", "original"] + }, + + handler(_ref, args) { + let { + parser + } = _ref; + const color = assertNodeType(args[0], "color-token").color; + const body = args[1]; + return { + type: "color", + mode: parser.mode, + color, + body: ordargument(body) + }; + }, + + htmlBuilder: color_htmlBuilder, + mathmlBuilder: color_mathmlBuilder +}); +defineFunction({ + type: "color", + names: ["\\color"], + props: { + numArgs: 1, + allowedInText: true, + argTypes: ["color"] + }, + + handler(_ref2, args) { + let { + parser, + breakOnTokenText + } = _ref2; + const color = assertNodeType(args[0], "color-token").color; // Set macro \current@color in current namespace to store the current + // color, mimicking the behavior of color.sty. + // This is currently used just to correctly color a \right + // that follows a \color command. + + parser.gullet.macros.set("\\current@color", color); // Parse out the implicit body that should be colored. + + const body = parser.parseExpression(true, breakOnTokenText); + return { + type: "color", + mode: parser.mode, + color, + body + }; + }, + + htmlBuilder: color_htmlBuilder, + mathmlBuilder: color_mathmlBuilder +}); +;// CONCATENATED MODULE: ./src/functions/cr.js +// Row breaks within tabular environments, and line breaks at top level + + + + + // \DeclareRobustCommand\\{...\@xnewline} + +defineFunction({ + type: "cr", + names: ["\\\\"], + props: { + numArgs: 0, + numOptionalArgs: 0, + allowedInText: true + }, + + handler(_ref, args, optArgs) { + let { + parser + } = _ref; + const size = parser.gullet.future().text === "[" ? parser.parseSizeGroup(true) : null; + const newLine = !parser.settings.displayMode || !parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode"); + return { + type: "cr", + mode: parser.mode, + newLine, + size: size && assertNodeType(size, "size").value + }; + }, + + // The following builders are called only at the top level, + // not within tabular/array environments. + htmlBuilder(group, options) { + const span = buildCommon.makeSpan(["mspace"], [], options); + + if (group.newLine) { + span.classes.push("newline"); + + if (group.size) { + span.style.marginTop = makeEm(calculateSize(group.size, options)); + } + } + + return span; + }, + + mathmlBuilder(group, options) { + const node = new mathMLTree.MathNode("mspace"); + + if (group.newLine) { + node.setAttribute("linebreak", "newline"); + + if (group.size) { + node.setAttribute("height", makeEm(calculateSize(group.size, options))); + } + } + + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/def.js + + + +const globalMap = { + "\\global": "\\global", + "\\long": "\\\\globallong", + "\\\\globallong": "\\\\globallong", + "\\def": "\\gdef", + "\\gdef": "\\gdef", + "\\edef": "\\xdef", + "\\xdef": "\\xdef", + "\\let": "\\\\globallet", + "\\futurelet": "\\\\globalfuture" +}; + +const checkControlSequence = tok => { + const name = tok.text; + + if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { + throw new src_ParseError("Expected a control sequence", tok); + } + + return name; +}; + +const getRHS = parser => { + let tok = parser.gullet.popToken(); + + if (tok.text === "=") { + // consume optional equals + tok = parser.gullet.popToken(); + + if (tok.text === " ") { + // consume one optional space + tok = parser.gullet.popToken(); + } + } + + return tok; +}; + +const letCommand = (parser, name, tok, global) => { + let macro = parser.gullet.macros.get(tok.text); + + if (macro == null) { + // don't expand it later even if a macro with the same name is defined + // e.g., \let\foo=\frac \def\frac{\relax} \frac12 + tok.noexpand = true; + macro = { + tokens: [tok], + numArgs: 0, + // reproduce the same behavior in expansion + unexpandable: !parser.gullet.isExpandable(tok.text) + }; + } + + parser.gullet.macros.set(name, macro, global); +}; // -> | +// -> |\global +// -> | +// -> \global|\long|\outer + + +defineFunction({ + type: "internal", + names: ["\\global", "\\long", "\\\\globallong" // can’t be entered directly + ], + props: { + numArgs: 0, + allowedInText: true + }, + + handler(_ref) { + let { + parser, + funcName + } = _ref; + parser.consumeSpaces(); + const token = parser.fetch(); + + if (globalMap[token.text]) { + // KaTeX doesn't have \par, so ignore \long + if (funcName === "\\global" || funcName === "\\\\globallong") { + token.text = globalMap[token.text]; + } + + return assertNodeType(parser.parseFunction(), "internal"); + } + + throw new src_ParseError("Invalid token after macro prefix", token); + } + +}); // Basic support for macro definitions: \def, \gdef, \edef, \xdef +// -> +// -> \def|\gdef|\edef|\xdef +// -> + +defineFunction({ + type: "internal", + names: ["\\def", "\\gdef", "\\edef", "\\xdef"], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref2) { + let { + parser, + funcName + } = _ref2; + let tok = parser.gullet.popToken(); + const name = tok.text; + + if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { + throw new src_ParseError("Expected a control sequence", tok); + } + + let numArgs = 0; + let insert; + const delimiters = [[]]; // contains no braces + + while (parser.gullet.future().text !== "{") { + tok = parser.gullet.popToken(); + + if (tok.text === "#") { + // If the very last character of the is #, so that + // this # is immediately followed by {, TeX will behave as if the { + // had been inserted at the right end of both the parameter text + // and the replacement text. + if (parser.gullet.future().text === "{") { + insert = parser.gullet.future(); + delimiters[numArgs].push("{"); + break; + } // A parameter, the first appearance of # must be followed by 1, + // the next by 2, and so on; up to nine #’s are allowed + + + tok = parser.gullet.popToken(); + + if (!/^[1-9]$/.test(tok.text)) { + throw new src_ParseError("Invalid argument number \"" + tok.text + "\""); + } + + if (parseInt(tok.text) !== numArgs + 1) { + throw new src_ParseError("Argument number \"" + tok.text + "\" out of order"); + } + + numArgs++; + delimiters.push([]); + } else if (tok.text === "EOF") { + throw new src_ParseError("Expected a macro definition"); + } else { + delimiters[numArgs].push(tok.text); + } + } // replacement text, enclosed in '{' and '}' and properly nested + + + let { + tokens + } = parser.gullet.consumeArg(); + + if (insert) { + tokens.unshift(insert); + } + + if (funcName === "\\edef" || funcName === "\\xdef") { + tokens = parser.gullet.expandTokens(tokens); + tokens.reverse(); // to fit in with stack order + } // Final arg is the expansion of the macro + + + parser.gullet.macros.set(name, { + tokens, + numArgs, + delimiters + }, funcName === globalMap[funcName]); + return { + type: "internal", + mode: parser.mode + }; + } + +}); // -> +// -> \futurelet +// | \let +// -> |= + +defineFunction({ + type: "internal", + names: ["\\let", "\\\\globallet" // can’t be entered directly + ], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref3) { + let { + parser, + funcName + } = _ref3; + const name = checkControlSequence(parser.gullet.popToken()); + parser.gullet.consumeSpaces(); + const tok = getRHS(parser); + letCommand(parser, name, tok, funcName === "\\\\globallet"); + return { + type: "internal", + mode: parser.mode + }; + } + +}); // ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf + +defineFunction({ + type: "internal", + names: ["\\futurelet", "\\\\globalfuture" // can’t be entered directly + ], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref4) { + let { + parser, + funcName + } = _ref4; + const name = checkControlSequence(parser.gullet.popToken()); + const middle = parser.gullet.popToken(); + const tok = parser.gullet.popToken(); + letCommand(parser, name, tok, funcName === "\\\\globalfuture"); + parser.gullet.pushToken(tok); + parser.gullet.pushToken(middle); + return { + type: "internal", + mode: parser.mode + }; + } + +}); +;// CONCATENATED MODULE: ./src/delimiter.js +/** + * This file deals with creating delimiters of various sizes. The TeXbook + * discusses these routines on page 441-442, in the "Another subroutine sets box + * x to a specified variable delimiter" paragraph. + * + * There are three main routines here. `makeSmallDelim` makes a delimiter in the + * normal font, but in either text, script, or scriptscript style. + * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1, + * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of + * smaller pieces that are stacked on top of one another. + * + * The functions take a parameter `center`, which determines if the delimiter + * should be centered around the axis. + * + * Then, there are three exposed functions. `sizedDelim` makes a delimiter in + * one of the given sizes. This is used for things like `\bigl`. + * `customSizedDelim` makes a delimiter with a given total height+depth. It is + * called in places like `\sqrt`. `leftRightDelim` makes an appropriate + * delimiter which surrounds an expression of a given height an depth. It is + * used in `\left` and `\right`. + */ + + + + + + + + + + + +/** + * Get the metrics for a given symbol and font, after transformation (i.e. + * after following replacement from symbols.js) + */ +const getMetrics = function (symbol, font, mode) { + const replace = src_symbols.math[symbol] && src_symbols.math[symbol].replace; + const metrics = getCharacterMetrics(replace || symbol, font, mode); + + if (!metrics) { + throw new Error("Unsupported symbol " + symbol + " and font size " + font + "."); + } + + return metrics; +}; +/** + * Puts a delimiter span in a given style, and adds appropriate height, depth, + * and maxFontSizes. + */ + + +const styleWrap = function (delim, toStyle, options, classes) { + const newOptions = options.havingBaseStyle(toStyle); + const span = buildCommon.makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options); + const delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier; + span.height *= delimSizeMultiplier; + span.depth *= delimSizeMultiplier; + span.maxFontSize = newOptions.sizeMultiplier; + return span; +}; + +const centerSpan = function (span, options, style) { + const newOptions = options.havingBaseStyle(style); + const shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight; + span.classes.push("delimcenter"); + span.style.top = makeEm(shift); + span.height -= shift; + span.depth += shift; +}; +/** + * Makes a small delimiter. This is a delimiter that comes in the Main-Regular + * font, but is restyled to either be in textstyle, scriptstyle, or + * scriptscriptstyle. + */ + + +const makeSmallDelim = function (delim, style, center, options, mode, classes) { + const text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options); + const span = styleWrap(text, style, options, classes); + + if (center) { + centerSpan(span, options, style); + } + + return span; +}; +/** + * Builds a symbol in the given font size (note size is an integer) + */ + + +const mathrmSize = function (value, size, mode, options) { + return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode, options); +}; +/** + * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2, + * Size3, or Size4 fonts. It is always rendered in textstyle. + */ + + +const makeLargeDelim = function (delim, size, center, options, mode, classes) { + const inner = mathrmSize(delim, size, mode, options); + const span = styleWrap(buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options), src_Style.TEXT, options, classes); + + if (center) { + centerSpan(span, options, src_Style.TEXT); + } + + return span; +}; +/** + * Make a span from a font glyph with the given offset and in the given font. + * This is used in makeStackedDelim to make the stacking pieces for the delimiter. + */ + + +const makeGlyphSpan = function (symbol, font, mode) { + let sizeClass; // Apply the correct CSS class to choose the right font. + + if (font === "Size1-Regular") { + sizeClass = "delim-size1"; + } else + /* if (font === "Size4-Regular") */ + { + sizeClass = "delim-size4"; + } + + const corner = buildCommon.makeSpan(["delimsizinginner", sizeClass], [buildCommon.makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); // Since this will be passed into `makeVList` in the end, wrap the element + // in the appropriate tag that VList uses. + + return { + type: "elem", + elem: corner + }; +}; + +const makeInner = function (ch, height, options) { + // Create a span with inline SVG for the inner part of a tall stacked delimiter. + const width = fontMetricsData['Size4-Regular'][ch.charCodeAt(0)] ? fontMetricsData['Size4-Regular'][ch.charCodeAt(0)][4] : fontMetricsData['Size1-Regular'][ch.charCodeAt(0)][4]; + const path = new PathNode("inner", innerPath(ch, Math.round(1000 * height))); + const svgNode = new SvgNode([path], { + "width": makeEm(width), + "height": makeEm(height), + // Override CSS rule `.katex svg { width: 100% }` + "style": "width:" + makeEm(width), + "viewBox": "0 0 " + 1000 * width + " " + Math.round(1000 * height), + "preserveAspectRatio": "xMinYMin" + }); + const span = buildCommon.makeSvgSpan([], [svgNode], options); + span.height = height; + span.style.height = makeEm(height); + span.style.width = makeEm(width); + return { + type: "elem", + elem: span + }; +}; // Helpers for makeStackedDelim + + +const lapInEms = 0.008; +const lap = { + type: "kern", + size: -1 * lapInEms +}; +const verts = ["|", "\\lvert", "\\rvert", "\\vert"]; +const doubleVerts = ["\\|", "\\lVert", "\\rVert", "\\Vert"]; +/** + * Make a stacked delimiter out of a given delimiter, with the total height at + * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook. + */ + +const makeStackedDelim = function (delim, heightTotal, center, options, mode, classes) { + // There are four parts, the top, an optional middle, a repeated part, and a + // bottom. + let top; + let middle; + let repeat; + let bottom; + let svgLabel = ""; + let viewBoxWidth = 0; + top = repeat = bottom = delim; + middle = null; // Also keep track of what font the delimiters are in + + let font = "Size1-Regular"; // We set the parts and font based on the symbol. Note that we use + // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the + // repeats of the arrows + + if (delim === "\\uparrow") { + repeat = bottom = "\u23d0"; + } else if (delim === "\\Uparrow") { + repeat = bottom = "\u2016"; + } else if (delim === "\\downarrow") { + top = repeat = "\u23d0"; + } else if (delim === "\\Downarrow") { + top = repeat = "\u2016"; + } else if (delim === "\\updownarrow") { + top = "\\uparrow"; + repeat = "\u23d0"; + bottom = "\\downarrow"; + } else if (delim === "\\Updownarrow") { + top = "\\Uparrow"; + repeat = "\u2016"; + bottom = "\\Downarrow"; + } else if (utils.contains(verts, delim)) { + repeat = "\u2223"; + svgLabel = "vert"; + viewBoxWidth = 333; + } else if (utils.contains(doubleVerts, delim)) { + repeat = "\u2225"; + svgLabel = "doublevert"; + viewBoxWidth = 556; + } else if (delim === "[" || delim === "\\lbrack") { + top = "\u23a1"; + repeat = "\u23a2"; + bottom = "\u23a3"; + font = "Size4-Regular"; + svgLabel = "lbrack"; + viewBoxWidth = 667; + } else if (delim === "]" || delim === "\\rbrack") { + top = "\u23a4"; + repeat = "\u23a5"; + bottom = "\u23a6"; + font = "Size4-Regular"; + svgLabel = "rbrack"; + viewBoxWidth = 667; + } else if (delim === "\\lfloor" || delim === "\u230a") { + repeat = top = "\u23a2"; + bottom = "\u23a3"; + font = "Size4-Regular"; + svgLabel = "lfloor"; + viewBoxWidth = 667; + } else if (delim === "\\lceil" || delim === "\u2308") { + top = "\u23a1"; + repeat = bottom = "\u23a2"; + font = "Size4-Regular"; + svgLabel = "lceil"; + viewBoxWidth = 667; + } else if (delim === "\\rfloor" || delim === "\u230b") { + repeat = top = "\u23a5"; + bottom = "\u23a6"; + font = "Size4-Regular"; + svgLabel = "rfloor"; + viewBoxWidth = 667; + } else if (delim === "\\rceil" || delim === "\u2309") { + top = "\u23a4"; + repeat = bottom = "\u23a5"; + font = "Size4-Regular"; + svgLabel = "rceil"; + viewBoxWidth = 667; + } else if (delim === "(" || delim === "\\lparen") { + top = "\u239b"; + repeat = "\u239c"; + bottom = "\u239d"; + font = "Size4-Regular"; + svgLabel = "lparen"; + viewBoxWidth = 875; + } else if (delim === ")" || delim === "\\rparen") { + top = "\u239e"; + repeat = "\u239f"; + bottom = "\u23a0"; + font = "Size4-Regular"; + svgLabel = "rparen"; + viewBoxWidth = 875; + } else if (delim === "\\{" || delim === "\\lbrace") { + top = "\u23a7"; + middle = "\u23a8"; + bottom = "\u23a9"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\}" || delim === "\\rbrace") { + top = "\u23ab"; + middle = "\u23ac"; + bottom = "\u23ad"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\lgroup" || delim === "\u27ee") { + top = "\u23a7"; + bottom = "\u23a9"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\rgroup" || delim === "\u27ef") { + top = "\u23ab"; + bottom = "\u23ad"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\lmoustache" || delim === "\u23b0") { + top = "\u23a7"; + bottom = "\u23ad"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\rmoustache" || delim === "\u23b1") { + top = "\u23ab"; + bottom = "\u23a9"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } // Get the metrics of the four sections + + + const topMetrics = getMetrics(top, font, mode); + const topHeightTotal = topMetrics.height + topMetrics.depth; + const repeatMetrics = getMetrics(repeat, font, mode); + const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; + const bottomMetrics = getMetrics(bottom, font, mode); + const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; + let middleHeightTotal = 0; + let middleFactor = 1; + + if (middle !== null) { + const middleMetrics = getMetrics(middle, font, mode); + middleHeightTotal = middleMetrics.height + middleMetrics.depth; + middleFactor = 2; // repeat symmetrically above and below middle + } // Calculate the minimal height that the delimiter can have. + // It is at least the size of the top, bottom, and optional middle combined. + + + const minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; // Compute the number of copies of the repeat symbol we will need + + const repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal))); // Compute the total height of the delimiter including all the symbols + + const realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // The center of the delimiter is placed at the center of the axis. Note + // that in this context, "center" means that the delimiter should be + // centered around the axis in the current style, while normally it is + // centered around the axis in textstyle. + + let axisHeight = options.fontMetrics().axisHeight; + + if (center) { + axisHeight *= options.sizeMultiplier; + } // Calculate the depth + + + const depth = realHeightTotal / 2 - axisHeight; // Now, we start building the pieces that will go into the vlist + // Keep a list of the pieces of the stacked delimiter + + const stack = []; + + if (svgLabel.length > 0) { + // Instead of stacking glyphs, create a single SVG. + // This evades browser problems with imprecise positioning of spans. + const midHeight = realHeightTotal - topHeightTotal - bottomHeightTotal; + const viewBoxHeight = Math.round(realHeightTotal * 1000); + const pathStr = tallDelim(svgLabel, Math.round(midHeight * 1000)); + const path = new PathNode(svgLabel, pathStr); + const width = (viewBoxWidth / 1000).toFixed(3) + "em"; + const height = (viewBoxHeight / 1000).toFixed(3) + "em"; + const svg = new SvgNode([path], { + "width": width, + "height": height, + "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight + }); + const wrapper = buildCommon.makeSvgSpan([], [svg], options); + wrapper.height = viewBoxHeight / 1000; + wrapper.style.width = width; + wrapper.style.height = height; + stack.push({ + type: "elem", + elem: wrapper + }); + } else { + // Stack glyphs + // Start by adding the bottom symbol + stack.push(makeGlyphSpan(bottom, font, mode)); + stack.push(lap); // overlap + + if (middle === null) { + // The middle section will be an SVG. Make it an extra 0.016em tall. + // We'll overlap by 0.008em at top and bottom. + const innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms; + stack.push(makeInner(repeat, innerHeight, options)); + } else { + // When there is a middle bit, we need the middle part and two repeated + // sections + const innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms; + stack.push(makeInner(repeat, innerHeight, options)); // Now insert the middle of the brace. + + stack.push(lap); + stack.push(makeGlyphSpan(middle, font, mode)); + stack.push(lap); + stack.push(makeInner(repeat, innerHeight, options)); + } // Add the top symbol + + + stack.push(lap); + stack.push(makeGlyphSpan(top, font, mode)); + } // Finally, build the vlist + + + const newOptions = options.havingBaseStyle(src_Style.TEXT); + const inner = buildCommon.makeVList({ + positionType: "bottom", + positionData: depth, + children: stack + }, newOptions); + return styleWrap(buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions), src_Style.TEXT, options, classes); +}; // All surds have 0.08em padding above the vinculum inside the SVG. +// That keeps browser span height rounding error from pinching the line. + + +const vbPad = 80; // padding above the surd, measured inside the viewBox. + +const emPad = 0.08; // padding, in ems, measured in the document. + +const sqrtSvg = function (sqrtName, height, viewBoxHeight, extraVinculum, options) { + const path = sqrtPath(sqrtName, extraVinculum, viewBoxHeight); + const pathNode = new PathNode(sqrtName, path); + const svg = new SvgNode([pathNode], { + // Note: 1000:1 ratio of viewBox to document em width. + "width": "400em", + "height": makeEm(height), + "viewBox": "0 0 400000 " + viewBoxHeight, + "preserveAspectRatio": "xMinYMin slice" + }); + return buildCommon.makeSvgSpan(["hide-tail"], [svg], options); +}; +/** + * Make a sqrt image of the given height, + */ + + +const makeSqrtImage = function (height, options) { + // Define a newOptions that removes the effect of size changes such as \Huge. + // We don't pick different a height surd for \Huge. For it, we scale up. + const newOptions = options.havingBaseSizing(); // Pick the desired surd glyph from a sequence of surds. + + const delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions); + let sizeMultiplier = newOptions.sizeMultiplier; // default + // The standard sqrt SVGs each have a 0.04em thick vinculum. + // If Settings.minRuleThickness is larger than that, we add extraVinculum. + + const extraVinculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness); // Create a span containing an SVG image of a sqrt symbol. + + let span; + let spanHeight = 0; + let texHeight = 0; + let viewBoxHeight = 0; + let advanceWidth; // We create viewBoxes with 80 units of "padding" above each surd. + // Then browser rounding error on the parent span height will not + // encroach on the ink of the vinculum. But that padding is not + // included in the TeX-like `height` used for calculation of + // vertical alignment. So texHeight = span.height < span.style.height. + + if (delim.type === "small") { + // Get an SVG that is derived from glyph U+221A in font KaTeX-Main. + // 1000 unit normal glyph height. + viewBoxHeight = 1000 + 1000 * extraVinculum + vbPad; + + if (height < 1.0) { + sizeMultiplier = 1.0; // mimic a \textfont radical + } else if (height < 1.4) { + sizeMultiplier = 0.7; // mimic a \scriptfont radical + } + + spanHeight = (1.0 + extraVinculum + emPad) / sizeMultiplier; + texHeight = (1.00 + extraVinculum) / sizeMultiplier; + span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraVinculum, options); + span.style.minWidth = "0.853em"; + advanceWidth = 0.833 / sizeMultiplier; // from the font. + } else if (delim.type === "large") { + // These SVGs come from fonts: KaTeX_Size1, _Size2, etc. + viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size]; + texHeight = (sizeToMaxHeight[delim.size] + extraVinculum) / sizeMultiplier; + spanHeight = (sizeToMaxHeight[delim.size] + extraVinculum + emPad) / sizeMultiplier; + span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraVinculum, options); + span.style.minWidth = "1.02em"; + advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font. + } else { + // Tall sqrt. In TeX, this would be stacked using multiple glyphs. + // We'll use a single SVG to accomplish the same thing. + spanHeight = height + extraVinculum + emPad; + texHeight = height + extraVinculum; + viewBoxHeight = Math.floor(1000 * height + extraVinculum) + vbPad; + span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraVinculum, options); + span.style.minWidth = "0.742em"; + advanceWidth = 1.056; + } + + span.height = texHeight; + span.style.height = makeEm(spanHeight); + return { + span, + advanceWidth, + // Calculate the actual line width. + // This actually should depend on the chosen font -- e.g. \boldmath + // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and + // have thicker rules. + ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraVinculum) * sizeMultiplier + }; +}; // There are three kinds of delimiters, delimiters that stack when they become +// too large + + +const stackLargeDelimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]; // delimiters that always stack + +const stackAlwaysDelimiters = ["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"]; // and delimiters that never stack + +const stackNeverDelimiters = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]; // Metrics of the different sizes. Found by looking at TeX's output of +// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ +// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. + +const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; +/** + * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4. + */ + +const makeSizedDelim = function (delim, size, options, mode, classes) { + // < and > turn into \langle and \rangle in delimiters + if (delim === "<" || delim === "\\lt" || delim === "\u27e8") { + delim = "\\langle"; + } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") { + delim = "\\rangle"; + } // Sized delimiters are never centered. + + + if (utils.contains(stackLargeDelimiters, delim) || utils.contains(stackNeverDelimiters, delim)) { + return makeLargeDelim(delim, size, false, options, mode, classes); + } else if (utils.contains(stackAlwaysDelimiters, delim)) { + return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes); + } else { + throw new src_ParseError("Illegal delimiter: '" + delim + "'"); + } +}; +/** + * There are three different sequences of delimiter sizes that the delimiters + * follow depending on the kind of delimiter. This is used when creating custom + * sized delimiters to decide whether to create a small, large, or stacked + * delimiter. + * + * In real TeX, these sequences aren't explicitly defined, but are instead + * defined inside the font metrics. Since there are only three sequences that + * are possible for the delimiters that TeX defines, it is easier to just encode + * them explicitly here. + */ + + +// Delimiters that never stack try small delimiters and large delimiters only +const stackNeverDelimiterSequence = [{ + type: "small", + style: src_Style.SCRIPTSCRIPT +}, { + type: "small", + style: src_Style.SCRIPT +}, { + type: "small", + style: src_Style.TEXT +}, { + type: "large", + size: 1 +}, { + type: "large", + size: 2 +}, { + type: "large", + size: 3 +}, { + type: "large", + size: 4 +}]; // Delimiters that always stack try the small delimiters first, then stack + +const stackAlwaysDelimiterSequence = [{ + type: "small", + style: src_Style.SCRIPTSCRIPT +}, { + type: "small", + style: src_Style.SCRIPT +}, { + type: "small", + style: src_Style.TEXT +}, { + type: "stack" +}]; // Delimiters that stack when large try the small and then large delimiters, and +// stack afterwards + +const stackLargeDelimiterSequence = [{ + type: "small", + style: src_Style.SCRIPTSCRIPT +}, { + type: "small", + style: src_Style.SCRIPT +}, { + type: "small", + style: src_Style.TEXT +}, { + type: "large", + size: 1 +}, { + type: "large", + size: 2 +}, { + type: "large", + size: 3 +}, { + type: "large", + size: 4 +}, { + type: "stack" +}]; +/** + * Get the font used in a delimiter based on what kind of delimiter it is. + * TODO(#963) Use more specific font family return type once that is introduced. + */ + +const delimTypeToFont = function (type) { + if (type.type === "small") { + return "Main-Regular"; + } else if (type.type === "large") { + return "Size" + type.size + "-Regular"; + } else if (type.type === "stack") { + return "Size4-Regular"; + } else { + throw new Error("Add support for delim type '" + type.type + "' here."); + } +}; +/** + * Traverse a sequence of types of delimiters to decide what kind of delimiter + * should be used to create a delimiter of the given height+depth. + */ + + +const traverseSequence = function (delim, height, sequence, options) { + // Here, we choose the index we should start at in the sequences. In smaller + // sizes (which correspond to larger numbers in style.size) we start earlier + // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts + // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2 + const start = Math.min(2, 3 - options.style.size); + + for (let i = start; i < sequence.length; i++) { + if (sequence[i].type === "stack") { + // This is always the last delimiter, so we just break the loop now. + break; + } + + const metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math"); + let heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we + // account for the style change size. + + if (sequence[i].type === "small") { + const newOptions = options.havingBaseStyle(sequence[i].style); + heightDepth *= newOptions.sizeMultiplier; + } // Check if the delimiter at this size works for the given height. + + + if (heightDepth > height) { + return sequence[i]; + } + } // If we reached the end of the sequence, return the last sequence element. + + + return sequence[sequence.length - 1]; +}; +/** + * Make a delimiter of a given height+depth, with optional centering. Here, we + * traverse the sequences, and create a delimiter that the sequence tells us to. + */ + + +const makeCustomSizedDelim = function (delim, height, center, options, mode, classes) { + if (delim === "<" || delim === "\\lt" || delim === "\u27e8") { + delim = "\\langle"; + } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") { + delim = "\\rangle"; + } // Decide what sequence to use + + + let sequence; + + if (utils.contains(stackNeverDelimiters, delim)) { + sequence = stackNeverDelimiterSequence; + } else if (utils.contains(stackLargeDelimiters, delim)) { + sequence = stackLargeDelimiterSequence; + } else { + sequence = stackAlwaysDelimiterSequence; + } // Look through the sequence + + + const delimType = traverseSequence(delim, height, sequence, options); // Get the delimiter from font glyphs. + // Depending on the sequence element we decided on, call the + // appropriate function. + + if (delimType.type === "small") { + return makeSmallDelim(delim, delimType.style, center, options, mode, classes); + } else if (delimType.type === "large") { + return makeLargeDelim(delim, delimType.size, center, options, mode, classes); + } else + /* if (delimType.type === "stack") */ + { + return makeStackedDelim(delim, height, center, options, mode, classes); + } +}; +/** + * Make a delimiter for use with `\left` and `\right`, given a height and depth + * of an expression that the delimiters surround. + */ + + +const makeLeftRightDelim = function (delim, height, depth, options, mode, classes) { + // We always center \left/\right delimiters, so the axis is always shifted + const axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right + + const delimiterFactor = 901; + const delimiterExtend = 5.0 / options.fontMetrics().ptPerEm; + const maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight); + const totalHeight = Math.max( // In real TeX, calculations are done using integral values which are + // 65536 per pt, or 655360 per em. So, the division here truncates in + // TeX but doesn't here, producing different results. If we wanted to + // exactly match TeX's calculation, we could do + // Math.floor(655360 * maxDistFromAxis / 500) * + // delimiterFactor / 655360 + // (To see the difference, compare + // x^{x^{\left(\rule{0.1em}{0.68em}\right)}} + // in TeX and KaTeX) + maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend); // Finally, we defer to `makeCustomSizedDelim` with our calculated total + // height + + return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes); +}; + +/* harmony default export */ var delimiter = ({ + sqrtImage: makeSqrtImage, + sizedDelim: makeSizedDelim, + sizeToMaxHeight: sizeToMaxHeight, + customSizedDelim: makeCustomSizedDelim, + leftRightDelim: makeLeftRightDelim +}); +;// CONCATENATED MODULE: ./src/functions/delimsizing.js + + + + + + + + + + +// Extra data needed for the delimiter handler down below +const delimiterSizes = { + "\\bigl": { + mclass: "mopen", + size: 1 + }, + "\\Bigl": { + mclass: "mopen", + size: 2 + }, + "\\biggl": { + mclass: "mopen", + size: 3 + }, + "\\Biggl": { + mclass: "mopen", + size: 4 + }, + "\\bigr": { + mclass: "mclose", + size: 1 + }, + "\\Bigr": { + mclass: "mclose", + size: 2 + }, + "\\biggr": { + mclass: "mclose", + size: 3 + }, + "\\Biggr": { + mclass: "mclose", + size: 4 + }, + "\\bigm": { + mclass: "mrel", + size: 1 + }, + "\\Bigm": { + mclass: "mrel", + size: 2 + }, + "\\biggm": { + mclass: "mrel", + size: 3 + }, + "\\Biggm": { + mclass: "mrel", + size: 4 + }, + "\\big": { + mclass: "mord", + size: 1 + }, + "\\Big": { + mclass: "mord", + size: 2 + }, + "\\bigg": { + mclass: "mord", + size: 3 + }, + "\\Bigg": { + mclass: "mord", + size: 4 + } +}; +const delimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."]; + +// Delimiter functions +function checkDelimiter(delim, context) { + const symDelim = checkSymbolNodeType(delim); + + if (symDelim && utils.contains(delimiters, symDelim.text)) { + return symDelim; + } else if (symDelim) { + throw new src_ParseError("Invalid delimiter '" + symDelim.text + "' after '" + context.funcName + "'", delim); + } else { + throw new src_ParseError("Invalid delimiter type '" + delim.type + "'", delim); + } +} + +defineFunction({ + type: "delimsizing", + names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"], + props: { + numArgs: 1, + argTypes: ["primitive"] + }, + handler: (context, args) => { + const delim = checkDelimiter(args[0], context); + return { + type: "delimsizing", + mode: context.parser.mode, + size: delimiterSizes[context.funcName].size, + mclass: delimiterSizes[context.funcName].mclass, + delim: delim.text + }; + }, + htmlBuilder: (group, options) => { + if (group.delim === ".") { + // Empty delimiters still count as elements, even though they don't + // show anything. + return buildCommon.makeSpan([group.mclass]); + } // Use delimiter.sizedDelim to generate the delimiter. + + + return delimiter.sizedDelim(group.delim, group.size, options, group.mode, [group.mclass]); + }, + mathmlBuilder: group => { + const children = []; + + if (group.delim !== ".") { + children.push(makeText(group.delim, group.mode)); + } + + const node = new mathMLTree.MathNode("mo", children); + + if (group.mclass === "mopen" || group.mclass === "mclose") { + // Only some of the delimsizing functions act as fences, and they + // return "mopen" or "mclose" mclass. + node.setAttribute("fence", "true"); + } else { + // Explicitly disable fencing if it's not a fence, to override the + // defaults. + node.setAttribute("fence", "false"); + } + + node.setAttribute("stretchy", "true"); + const size = makeEm(delimiter.sizeToMaxHeight[group.size]); + node.setAttribute("minsize", size); + node.setAttribute("maxsize", size); + return node; + } +}); + +function assertParsed(group) { + if (!group.body) { + throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); + } +} + +defineFunction({ + type: "leftright-right", + names: ["\\right"], + props: { + numArgs: 1, + primitive: true + }, + handler: (context, args) => { + // \left case below triggers parsing of \right in + // `const right = parser.parseFunction();` + // uses this return value. + const color = context.parser.gullet.macros.get("\\current@color"); + + if (color && typeof color !== "string") { + throw new src_ParseError("\\current@color set to non-string in \\right"); + } + + return { + type: "leftright-right", + mode: context.parser.mode, + delim: checkDelimiter(args[0], context).text, + color // undefined if not set via \color + + }; + } +}); +defineFunction({ + type: "leftright", + names: ["\\left"], + props: { + numArgs: 1, + primitive: true + }, + handler: (context, args) => { + const delim = checkDelimiter(args[0], context); + const parser = context.parser; // Parse out the implicit body + + ++parser.leftrightDepth; // parseExpression stops before '\\right' + + const body = parser.parseExpression(false); + --parser.leftrightDepth; // Check the next token + + parser.expect("\\right", false); + const right = assertNodeType(parser.parseFunction(), "leftright-right"); + return { + type: "leftright", + mode: parser.mode, + body, + left: delim.text, + right: right.delim, + rightColor: right.color + }; + }, + htmlBuilder: (group, options) => { + assertParsed(group); // Build the inner expression + + const inner = buildExpression(group.body, options, true, ["mopen", "mclose"]); + let innerHeight = 0; + let innerDepth = 0; + let hadMiddle = false; // Calculate its height and depth + + for (let i = 0; i < inner.length; i++) { + // Property `isMiddle` not defined on `span`. See comment in + // "middle"'s htmlBuilder. + // $FlowFixMe + if (inner[i].isMiddle) { + hadMiddle = true; + } else { + innerHeight = Math.max(inner[i].height, innerHeight); + innerDepth = Math.max(inner[i].depth, innerDepth); + } + } // The size of delimiters is the same, regardless of what style we are + // in. Thus, to correctly calculate the size of delimiter we need around + // a group, we scale down the inner size based on the size. + + + innerHeight *= options.sizeMultiplier; + innerDepth *= options.sizeMultiplier; + let leftDelim; + + if (group.left === ".") { + // Empty delimiters in \left and \right make null delimiter spaces. + leftDelim = makeNullDelimiter(options, ["mopen"]); + } else { + // Otherwise, use leftRightDelim to generate the correct sized + // delimiter. + leftDelim = delimiter.leftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]); + } // Add it to the beginning of the expression + + + inner.unshift(leftDelim); // Handle middle delimiters + + if (hadMiddle) { + for (let i = 1; i < inner.length; i++) { + const middleDelim = inner[i]; // Property `isMiddle` not defined on `span`. See comment in + // "middle"'s htmlBuilder. + // $FlowFixMe + + const isMiddle = middleDelim.isMiddle; + + if (isMiddle) { + // Apply the options that were active when \middle was called + inner[i] = delimiter.leftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []); + } + } + } + + let rightDelim; // Same for the right delimiter, but using color specified by \color + + if (group.right === ".") { + rightDelim = makeNullDelimiter(options, ["mclose"]); + } else { + const colorOptions = group.rightColor ? options.withColor(group.rightColor) : options; + rightDelim = delimiter.leftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]); + } // Add it to the end of the expression. + + + inner.push(rightDelim); + return buildCommon.makeSpan(["minner"], inner, options); + }, + mathmlBuilder: (group, options) => { + assertParsed(group); + const inner = buildMathML_buildExpression(group.body, options); + + if (group.left !== ".") { + const leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); + leftNode.setAttribute("fence", "true"); + inner.unshift(leftNode); + } + + if (group.right !== ".") { + const rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); + rightNode.setAttribute("fence", "true"); + + if (group.rightColor) { + rightNode.setAttribute("mathcolor", group.rightColor); + } + + inner.push(rightNode); + } + + return makeRow(inner); + } +}); +defineFunction({ + type: "middle", + names: ["\\middle"], + props: { + numArgs: 1, + primitive: true + }, + handler: (context, args) => { + const delim = checkDelimiter(args[0], context); + + if (!context.parser.leftrightDepth) { + throw new src_ParseError("\\middle without preceding \\left", delim); + } + + return { + type: "middle", + mode: context.parser.mode, + delim: delim.text + }; + }, + htmlBuilder: (group, options) => { + let middleDelim; + + if (group.delim === ".") { + middleDelim = makeNullDelimiter(options, []); + } else { + middleDelim = delimiter.sizedDelim(group.delim, 1, options, group.mode, []); + const isMiddle = { + delim: group.delim, + options + }; // Property `isMiddle` not defined on `span`. It is only used in + // this file above. + // TODO: Fix this violation of the `span` type and possibly rename + // things since `isMiddle` sounds like a boolean, but is a struct. + // $FlowFixMe + + middleDelim.isMiddle = isMiddle; + } + + return middleDelim; + }, + mathmlBuilder: (group, options) => { + // A Firefox \middle will stretch a character vertically only if it + // is in the fence part of the operator dictionary at: + // https://www.w3.org/TR/MathML3/appendixc.html. + // So we need to avoid U+2223 and use plain "|" instead. + const textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode); + const middleNode = new mathMLTree.MathNode("mo", [textNode]); + middleNode.setAttribute("fence", "true"); // MathML gives 5/18em spacing to each element. + // \middle should get delimiter spacing instead. + + middleNode.setAttribute("lspace", "0.05em"); + middleNode.setAttribute("rspace", "0.05em"); + return middleNode; + } +}); +;// CONCATENATED MODULE: ./src/functions/enclose.js + + + + + + + + + + + + +const enclose_htmlBuilder = (group, options) => { + // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase + // Some groups can return document fragments. Handle those by wrapping + // them in a span. + const inner = buildCommon.wrapFragment(buildGroup(group.body, options), options); + const label = group.label.slice(1); + let scale = options.sizeMultiplier; + let img; + let imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different + // depending on whether the subject is wider than it is tall, or vice versa. + // We don't know the width of a group, so as a proxy, we test if + // the subject is a single character. This captures most of the + // subjects that should get the "tall" treatment. + + const isSingleChar = utils.isCharacterBox(group.body); + + if (label === "sout") { + img = buildCommon.makeSpan(["stretchy", "sout"]); + img.height = options.fontMetrics().defaultRuleThickness / scale; + imgShift = -0.5 * options.fontMetrics().xHeight; + } else if (label === "phase") { + // Set a couple of dimensions from the steinmetz package. + const lineWeight = calculateSize({ + number: 0.6, + unit: "pt" + }, options); + const clearance = calculateSize({ + number: 0.35, + unit: "ex" + }, options); // Prevent size changes like \Huge from affecting line thickness + + const newOptions = options.havingBaseSizing(); + scale = scale / newOptions.sizeMultiplier; + const angleHeight = inner.height + inner.depth + lineWeight + clearance; // Reserve a left pad for the angle. + + inner.style.paddingLeft = makeEm(angleHeight / 2 + lineWeight); // Create an SVG + + const viewBoxHeight = Math.floor(1000 * angleHeight * scale); + const path = phasePath(viewBoxHeight); + const svgNode = new SvgNode([new PathNode("phase", path)], { + "width": "400em", + "height": makeEm(viewBoxHeight / 1000), + "viewBox": "0 0 400000 " + viewBoxHeight, + "preserveAspectRatio": "xMinYMin slice" + }); // Wrap it in a span with overflow: hidden. + + img = buildCommon.makeSvgSpan(["hide-tail"], [svgNode], options); + img.style.height = makeEm(angleHeight); + imgShift = inner.depth + lineWeight + clearance; + } else { + // Add horizontal padding + if (/cancel/.test(label)) { + if (!isSingleChar) { + inner.classes.push("cancel-pad"); + } + } else if (label === "angl") { + inner.classes.push("anglpad"); + } else { + inner.classes.push("boxpad"); + } // Add vertical padding + + + let topPad = 0; + let bottomPad = 0; + let ruleThickness = 0; // ref: cancel package: \advance\totalheight2\p@ % "+2" + + if (/box/.test(label)) { + ruleThickness = Math.max(options.fontMetrics().fboxrule, // default + options.minRuleThickness // User override. + ); + topPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness); + bottomPad = topPad; + } else if (label === "angl") { + ruleThickness = Math.max(options.fontMetrics().defaultRuleThickness, options.minRuleThickness); + topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself. + + bottomPad = Math.max(0, 0.25 - inner.depth); + } else { + topPad = isSingleChar ? 0.2 : 0; + bottomPad = topPad; + } + + img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options); + + if (/fbox|boxed|fcolorbox/.test(label)) { + img.style.borderStyle = "solid"; + img.style.borderWidth = makeEm(ruleThickness); + } else if (label === "angl" && ruleThickness !== 0.049) { + img.style.borderTopWidth = makeEm(ruleThickness); + img.style.borderRightWidth = makeEm(ruleThickness); + } + + imgShift = inner.depth + bottomPad; + + if (group.backgroundColor) { + img.style.backgroundColor = group.backgroundColor; + + if (group.borderColor) { + img.style.borderColor = group.borderColor; + } + } + } + + let vlist; + + if (group.backgroundColor) { + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [// Put the color background behind inner; + { + type: "elem", + elem: img, + shift: imgShift + }, { + type: "elem", + elem: inner, + shift: 0 + }] + }, options); + } else { + const classes = /cancel|phase/.test(label) ? ["svg-align"] : []; + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [// Write the \cancel stroke on top of inner. + { + type: "elem", + elem: inner, + shift: 0 + }, { + type: "elem", + elem: img, + shift: imgShift, + wrapperClasses: classes + }] + }, options); + } + + if (/cancel/.test(label)) { + // The cancel package documentation says that cancel lines add their height + // to the expression, but tests show that isn't how it actually works. + vlist.height = inner.height; + vlist.depth = inner.depth; + } + + if (/cancel/.test(label) && !isSingleChar) { + // cancel does not create horiz space for its line extension. + return buildCommon.makeSpan(["mord", "cancel-lap"], [vlist], options); + } else { + return buildCommon.makeSpan(["mord"], [vlist], options); + } +}; + +const enclose_mathmlBuilder = (group, options) => { + let fboxsep = 0; + const node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildMathML_buildGroup(group.body, options)]); + + switch (group.label) { + case "\\cancel": + node.setAttribute("notation", "updiagonalstrike"); + break; + + case "\\bcancel": + node.setAttribute("notation", "downdiagonalstrike"); + break; + + case "\\phase": + node.setAttribute("notation", "phasorangle"); + break; + + case "\\sout": + node.setAttribute("notation", "horizontalstrike"); + break; + + case "\\fbox": + node.setAttribute("notation", "box"); + break; + + case "\\angl": + node.setAttribute("notation", "actuarial"); + break; + + case "\\fcolorbox": + case "\\colorbox": + // doesn't have a good notation option. So use + // instead. Set some attributes that come included with . + fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm; + node.setAttribute("width", "+" + 2 * fboxsep + "pt"); + node.setAttribute("height", "+" + 2 * fboxsep + "pt"); + node.setAttribute("lspace", fboxsep + "pt"); // + + node.setAttribute("voffset", fboxsep + "pt"); + + if (group.label === "\\fcolorbox") { + const thk = Math.max(options.fontMetrics().fboxrule, // default + options.minRuleThickness // user override + ); + node.setAttribute("style", "border: " + thk + "em solid " + String(group.borderColor)); + } + + break; + + case "\\xcancel": + node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); + break; + } + + if (group.backgroundColor) { + node.setAttribute("mathbackground", group.backgroundColor); + } + + return node; +}; + +defineFunction({ + type: "enclose", + names: ["\\colorbox"], + props: { + numArgs: 2, + allowedInText: true, + argTypes: ["color", "text"] + }, + + handler(_ref, args, optArgs) { + let { + parser, + funcName + } = _ref; + const color = assertNodeType(args[0], "color-token").color; + const body = args[1]; + return { + type: "enclose", + mode: parser.mode, + label: funcName, + backgroundColor: color, + body + }; + }, + + htmlBuilder: enclose_htmlBuilder, + mathmlBuilder: enclose_mathmlBuilder +}); +defineFunction({ + type: "enclose", + names: ["\\fcolorbox"], + props: { + numArgs: 3, + allowedInText: true, + argTypes: ["color", "color", "text"] + }, + + handler(_ref2, args, optArgs) { + let { + parser, + funcName + } = _ref2; + const borderColor = assertNodeType(args[0], "color-token").color; + const backgroundColor = assertNodeType(args[1], "color-token").color; + const body = args[2]; + return { + type: "enclose", + mode: parser.mode, + label: funcName, + backgroundColor, + borderColor, + body + }; + }, + + htmlBuilder: enclose_htmlBuilder, + mathmlBuilder: enclose_mathmlBuilder +}); +defineFunction({ + type: "enclose", + names: ["\\fbox"], + props: { + numArgs: 1, + argTypes: ["hbox"], + allowedInText: true + }, + + handler(_ref3, args) { + let { + parser + } = _ref3; + return { + type: "enclose", + mode: parser.mode, + label: "\\fbox", + body: args[0] + }; + } + +}); +defineFunction({ + type: "enclose", + names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"], + props: { + numArgs: 1 + }, + + handler(_ref4, args) { + let { + parser, + funcName + } = _ref4; + const body = args[0]; + return { + type: "enclose", + mode: parser.mode, + label: funcName, + body + }; + }, + + htmlBuilder: enclose_htmlBuilder, + mathmlBuilder: enclose_mathmlBuilder +}); +defineFunction({ + type: "enclose", + names: ["\\angl"], + props: { + numArgs: 1, + argTypes: ["hbox"], + allowedInText: false + }, + + handler(_ref5, args) { + let { + parser + } = _ref5; + return { + type: "enclose", + mode: parser.mode, + label: "\\angl", + body: args[0] + }; + } + +}); +;// CONCATENATED MODULE: ./src/defineEnvironment.js + + +/** + * All registered environments. + * `environments.js` exports this same dictionary again and makes it public. + * `Parser.js` requires this dictionary via `environments.js`. + */ +const _environments = {}; +function defineEnvironment(_ref) { + let { + type, + names, + props, + handler, + htmlBuilder, + mathmlBuilder + } = _ref; + // Set default values of environments. + const data = { + type, + numArgs: props.numArgs || 0, + allowedInText: false, + numOptionalArgs: 0, + handler + }; + + for (let i = 0; i < names.length; ++i) { + // TODO: The value type of _environments should be a type union of all + // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is + // an existential type. + _environments[names[i]] = data; + } + + if (htmlBuilder) { + _htmlGroupBuilders[type] = htmlBuilder; + } + + if (mathmlBuilder) { + _mathmlGroupBuilders[type] = mathmlBuilder; + } +} +;// CONCATENATED MODULE: ./src/defineMacro.js + + +/** + * All registered global/built-in macros. + * `macros.js` exports this same dictionary again and makes it public. + * `Parser.js` requires this dictionary via `macros.js`. + */ +const _macros = {}; // This function might one day accept an additional argument and do more things. + +function defineMacro(name, body) { + _macros[name] = body; +} +;// CONCATENATED MODULE: ./src/SourceLocation.js +/** + * Lexing or parsing positional information for error reporting. + * This object is immutable. + */ +class SourceLocation { + // The + prefix indicates that these fields aren't writeable + // Lexer holding the input string. + // Start offset, zero-based inclusive. + // End offset, zero-based exclusive. + constructor(lexer, start, end) { + this.lexer = void 0; + this.start = void 0; + this.end = void 0; + this.lexer = lexer; + this.start = start; + this.end = end; + } + /** + * Merges two `SourceLocation`s from location providers, given they are + * provided in order of appearance. + * - Returns the first one's location if only the first is provided. + * - Returns a merged range of the first and the last if both are provided + * and their lexers match. + * - Otherwise, returns null. + */ + + + static range(first, second) { + if (!second) { + return first && first.loc; + } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { + return null; + } else { + return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); + } + } + +} +;// CONCATENATED MODULE: ./src/Token.js + +/** + * Interface required to break circular dependency between Token, Lexer, and + * ParseError. + */ + +/** + * The resulting token returned from `lex`. + * + * It consists of the token text plus some position information. + * The position information is essentially a range in an input string, + * but instead of referencing the bare input string, we refer to the lexer. + * That way it is possible to attach extra metadata to the input string, + * like for example a file name or similar. + * + * The position information is optional, so it is OK to construct synthetic + * tokens if appropriate. Not providing available position information may + * lead to degraded error reporting, though. + */ +class Token { + // don't expand the token + // used in \noexpand + constructor(text, // the text of this token + loc) { + this.text = void 0; + this.loc = void 0; + this.noexpand = void 0; + this.treatAsRelax = void 0; + this.text = text; + this.loc = loc; + } + /** + * Given a pair of tokens (this and endToken), compute a `Token` encompassing + * the whole input range enclosed by these two. + */ + + + range(endToken, // last token of the range, inclusive + text // the text of the newly constructed token + ) { + return new Token(text, SourceLocation.range(this, endToken)); + } + +} +;// CONCATENATED MODULE: ./src/environments/array.js + + + + + + + + + + + + + + + + +// Helper functions +function getHLines(parser) { + // Return an array. The array length = number of hlines. + // Each element in the array tells if the line is dashed. + const hlineInfo = []; + parser.consumeSpaces(); + let nxt = parser.fetch().text; + + if (nxt === "\\relax") { + // \relax is an artifact of the \cr macro below + parser.consume(); + parser.consumeSpaces(); + nxt = parser.fetch().text; + } + + while (nxt === "\\hline" || nxt === "\\hdashline") { + parser.consume(); + hlineInfo.push(nxt === "\\hdashline"); + parser.consumeSpaces(); + nxt = parser.fetch().text; + } + + return hlineInfo; +} + +const validateAmsEnvironmentContext = context => { + const settings = context.parser.settings; + + if (!settings.displayMode) { + throw new src_ParseError("{" + context.envName + "} can be used only in" + " display mode."); + } +}; // autoTag (an argument to parseArray) can be one of three values: +// * undefined: Regular (not-top-level) array; no tags on each row +// * true: Automatic equation numbering, overridable by \tag +// * false: Tags allowed on each row, but no automatic numbering +// This function *doesn't* work with the "split" environment name. + + +function getAutoTag(name) { + if (name.indexOf("ed") === -1) { + return name.indexOf("*") === -1; + } // return undefined; + +} +/** + * Parse the body of the environment, with rows delimited by \\ and + * columns delimited by &, and create a nested list in row-major order + * with one group per cell. If given an optional argument style + * ("text", "display", etc.), then each cell is cast into that style. + */ + + +function parseArray(parser, _ref, style) { + let { + hskipBeforeAndAfter, + addJot, + cols, + arraystretch, + colSeparationType, + autoTag, + singleRow, + emptySingleRow, + maxNumCols, + leqno + } = _ref; + parser.gullet.beginGroup(); + + if (!singleRow) { + // \cr is equivalent to \\ without the optional size argument (see below) + // TODO: provide helpful error when \cr is used outside array environment + parser.gullet.macros.set("\\cr", "\\\\\\relax"); + } // Get current arraystretch if it's not set by the environment + + + if (!arraystretch) { + const stretch = parser.gullet.expandMacroAsText("\\arraystretch"); + + if (stretch == null) { + // Default \arraystretch from lttab.dtx + arraystretch = 1; + } else { + arraystretch = parseFloat(stretch); + + if (!arraystretch || arraystretch < 0) { + throw new src_ParseError("Invalid \\arraystretch: " + stretch); + } + } + } // Start group for first cell + + + parser.gullet.beginGroup(); + let row = []; + const body = [row]; + const rowGaps = []; + const hLinesBeforeRow = []; + const tags = autoTag != null ? [] : undefined; // amsmath uses \global\@eqnswtrue and \global\@eqnswfalse to represent + // whether this row should have an equation number. Simulate this with + // a \@eqnsw macro set to 1 or 0. + + function beginRow() { + if (autoTag) { + parser.gullet.macros.set("\\@eqnsw", "1", true); + } + } + + function endRow() { + if (tags) { + if (parser.gullet.macros.get("\\df@tag")) { + tags.push(parser.subparse([new Token("\\df@tag")])); + parser.gullet.macros.set("\\df@tag", undefined, true); + } else { + tags.push(Boolean(autoTag) && parser.gullet.macros.get("\\@eqnsw") === "1"); + } + } + } + + beginRow(); // Test for \hline at the top of the array. + + hLinesBeforeRow.push(getHLines(parser)); + + while (true) { + // eslint-disable-line no-constant-condition + // Parse each cell in its own group (namespace) + let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); + parser.gullet.endGroup(); + parser.gullet.beginGroup(); + cell = { + type: "ordgroup", + mode: parser.mode, + body: cell + }; + + if (style) { + cell = { + type: "styling", + mode: parser.mode, + style, + body: [cell] + }; + } + + row.push(cell); + const next = parser.fetch().text; + + if (next === "&") { + if (maxNumCols && row.length === maxNumCols) { + if (singleRow || colSeparationType) { + // {equation} or {split} + throw new src_ParseError("Too many tab characters: &", parser.nextToken); + } else { + // {array} environment + parser.settings.reportNonstrict("textEnv", "Too few columns " + "specified in the {array} column argument."); + } + } + + parser.consume(); + } else if (next === "\\end") { + endRow(); // Arrays terminate newlines with `\crcr` which consumes a `\cr` if + // the last line is empty. However, AMS environments keep the + // empty row if it's the only one. + // NOTE: Currently, `cell` is the last item added into `row`. + + if (row.length === 1 && cell.type === "styling" && cell.body[0].body.length === 0 && (body.length > 1 || !emptySingleRow)) { + body.pop(); + } + + if (hLinesBeforeRow.length < body.length + 1) { + hLinesBeforeRow.push([]); + } + + break; + } else if (next === "\\\\") { + parser.consume(); + let size; // \def\Let@{\let\\\math@cr} + // \def\math@cr{...\math@cr@} + // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} + // \def\math@cr@@[#1]{...\math@cr@@@...} + // \def\math@cr@@@{\cr} + + if (parser.gullet.future().text !== " ") { + size = parser.parseSizeGroup(true); + } + + rowGaps.push(size ? size.value : null); + endRow(); // check for \hline(s) following the row separator + + hLinesBeforeRow.push(getHLines(parser)); + row = []; + body.push(row); + beginRow(); + } else { + throw new src_ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); + } + } // End cell group + + + parser.gullet.endGroup(); // End array group defining \cr + + parser.gullet.endGroup(); + return { + type: "array", + mode: parser.mode, + addJot, + arraystretch, + body, + cols, + rowGaps, + hskipBeforeAndAfter, + hLinesBeforeRow, + colSeparationType, + tags, + leqno + }; +} // Decides on a style for cells in an array according to whether the given +// environment name starts with the letter 'd'. + + +function dCellStyle(envName) { + if (envName.slice(0, 1) === "d") { + return "display"; + } else { + return "text"; + } +} + +const array_htmlBuilder = function (group, options) { + let r; + let c; + const nr = group.body.length; + const hLinesBeforeRow = group.hLinesBeforeRow; + let nc = 0; + let body = new Array(nr); + const hlines = []; + const ruleThickness = Math.max( // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em. + options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override. + ); // Horizontal spacing + + const pt = 1 / options.fontMetrics().ptPerEm; + let arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls + + if (group.colSeparationType && group.colSeparationType === "small") { + // We're in a {smallmatrix}. Default column space is \thickspace, + // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}. + // But that needs adjustment because LaTeX applies \scriptstyle to the + // entire array, including the colspace, but this function applies + // \scriptstyle only inside each element. + const localMultiplier = options.havingStyle(src_Style.SCRIPT).sizeMultiplier; + arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier); + } // Vertical spacing + + + const baselineskip = group.colSeparationType === "CD" ? calculateSize({ + number: 3, + unit: "ex" + }, options) : 12 * pt; // see size10.clo + // Default \jot from ltmath.dtx + // TODO(edemaine): allow overriding \jot via \setlength (#687) + + const jot = 3 * pt; + const arrayskip = group.arraystretch * baselineskip; + const arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and + + const arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx + + let totalHeight = 0; // Set a position for \hline(s) at the top of the array, if any. + + function setHLinePos(hlinesInGap) { + for (let i = 0; i < hlinesInGap.length; ++i) { + if (i > 0) { + totalHeight += 0.25; + } + + hlines.push({ + pos: totalHeight, + isDashed: hlinesInGap[i] + }); + } + } + + setHLinePos(hLinesBeforeRow[0]); + + for (r = 0; r < group.body.length; ++r) { + const inrow = group.body[r]; + let height = arstrutHeight; // \@array adds an \@arstrut + + let depth = arstrutDepth; // to each tow (via the template) + + if (nc < inrow.length) { + nc = inrow.length; + } + + const outrow = new Array(inrow.length); + + for (c = 0; c < inrow.length; ++c) { + const elt = buildGroup(inrow[c], options); + + if (depth < elt.depth) { + depth = elt.depth; + } + + if (height < elt.height) { + height = elt.height; + } + + outrow[c] = elt; + } + + const rowGap = group.rowGaps[r]; + let gap = 0; + + if (rowGap) { + gap = calculateSize(rowGap, options); + + if (gap > 0) { + // \@argarraycr + gap += arstrutDepth; + + if (depth < gap) { + depth = gap; // \@xargarraycr + } + + gap = 0; + } + } // In AMS multiline environments such as aligned and gathered, rows + // correspond to lines that have additional \jot added to the + // \baselineskip via \openup. + + + if (group.addJot) { + depth += jot; + } + + outrow.height = height; + outrow.depth = depth; + totalHeight += height; + outrow.pos = totalHeight; + totalHeight += depth + gap; // \@yargarraycr + + body[r] = outrow; // Set a position for \hline(s), if any. + + setHLinePos(hLinesBeforeRow[r + 1]); + } + + const offset = totalHeight / 2 + options.fontMetrics().axisHeight; + const colDescriptions = group.cols || []; + const cols = []; + let colSep; + let colDescrNum; + const tagSpans = []; + + if (group.tags && group.tags.some(tag => tag)) { + // An environment with manual tags and/or automatic equation numbers. + // Create node(s), the latter of which trigger CSS counter increment. + for (r = 0; r < nr; ++r) { + const rw = body[r]; + const shift = rw.pos - offset; + const tag = group.tags[r]; + let tagSpan; + + if (tag === true) { + // automatic numbering + tagSpan = buildCommon.makeSpan(["eqn-num"], [], options); + } else if (tag === false) { + // \nonumber/\notag or starred environment + tagSpan = buildCommon.makeSpan([], [], options); + } else { + // manual \tag + tagSpan = buildCommon.makeSpan([], buildExpression(tag, options, true), options); + } + + tagSpan.depth = rw.depth; + tagSpan.height = rw.height; + tagSpans.push({ + type: "elem", + elem: tagSpan, + shift + }); + } + } + + for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column + // descriptions, so trailing separators don't get lost. + c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) { + let colDescr = colDescriptions[colDescrNum] || {}; + let firstSeparator = true; + + while (colDescr.type === "separator") { + // If there is more than one separator in a row, add a space + // between them. + if (!firstSeparator) { + colSep = buildCommon.makeSpan(["arraycolsep"], []); + colSep.style.width = makeEm(options.fontMetrics().doubleRuleSep); + cols.push(colSep); + } + + if (colDescr.separator === "|" || colDescr.separator === ":") { + const lineType = colDescr.separator === "|" ? "solid" : "dashed"; + const separator = buildCommon.makeSpan(["vertical-separator"], [], options); + separator.style.height = makeEm(totalHeight); + separator.style.borderRightWidth = makeEm(ruleThickness); + separator.style.borderRightStyle = lineType; + separator.style.margin = "0 " + makeEm(-ruleThickness / 2); + const shift = totalHeight - offset; + + if (shift) { + separator.style.verticalAlign = makeEm(-shift); + } + + cols.push(separator); + } else { + throw new src_ParseError("Invalid separator type: " + colDescr.separator); + } + + colDescrNum++; + colDescr = colDescriptions[colDescrNum] || {}; + firstSeparator = false; + } + + if (c >= nc) { + continue; + } + + let sepwidth; + + if (c > 0 || group.hskipBeforeAndAfter) { + sepwidth = utils.deflt(colDescr.pregap, arraycolsep); + + if (sepwidth !== 0) { + colSep = buildCommon.makeSpan(["arraycolsep"], []); + colSep.style.width = makeEm(sepwidth); + cols.push(colSep); + } + } + + let col = []; + + for (r = 0; r < nr; ++r) { + const row = body[r]; + const elem = row[c]; + + if (!elem) { + continue; + } + + const shift = row.pos - offset; + elem.depth = row.depth; + elem.height = row.height; + col.push({ + type: "elem", + elem: elem, + shift: shift + }); + } + + col = buildCommon.makeVList({ + positionType: "individualShift", + children: col + }, options); + col = buildCommon.makeSpan(["col-align-" + (colDescr.align || "c")], [col]); + cols.push(col); + + if (c < nc - 1 || group.hskipBeforeAndAfter) { + sepwidth = utils.deflt(colDescr.postgap, arraycolsep); + + if (sepwidth !== 0) { + colSep = buildCommon.makeSpan(["arraycolsep"], []); + colSep.style.width = makeEm(sepwidth); + cols.push(colSep); + } + } + } + + body = buildCommon.makeSpan(["mtable"], cols); // Add \hline(s), if any. + + if (hlines.length > 0) { + const line = buildCommon.makeLineSpan("hline", options, ruleThickness); + const dashes = buildCommon.makeLineSpan("hdashline", options, ruleThickness); + const vListElems = [{ + type: "elem", + elem: body, + shift: 0 + }]; + + while (hlines.length > 0) { + const hline = hlines.pop(); + const lineShift = hline.pos - offset; + + if (hline.isDashed) { + vListElems.push({ + type: "elem", + elem: dashes, + shift: lineShift + }); + } else { + vListElems.push({ + type: "elem", + elem: line, + shift: lineShift + }); + } + } + + body = buildCommon.makeVList({ + positionType: "individualShift", + children: vListElems + }, options); + } + + if (tagSpans.length === 0) { + return buildCommon.makeSpan(["mord"], [body], options); + } else { + let eqnNumCol = buildCommon.makeVList({ + positionType: "individualShift", + children: tagSpans + }, options); + eqnNumCol = buildCommon.makeSpan(["tag"], [eqnNumCol], options); + return buildCommon.makeFragment([body, eqnNumCol]); + } +}; + +const alignMap = { + c: "center ", + l: "left ", + r: "right " +}; + +const array_mathmlBuilder = function (group, options) { + const tbl = []; + const glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]); + const tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]); + + for (let i = 0; i < group.body.length; i++) { + const rw = group.body[i]; + const row = []; + + for (let j = 0; j < rw.length; j++) { + row.push(new mathMLTree.MathNode("mtd", [buildMathML_buildGroup(rw[j], options)])); + } + + if (group.tags && group.tags[i]) { + row.unshift(glue); + row.push(glue); + + if (group.leqno) { + row.unshift(tag); + } else { + row.push(tag); + } + } + + tbl.push(new mathMLTree.MathNode("mtr", row)); + } + + let table = new mathMLTree.MathNode("mtable", tbl); // Set column alignment, row spacing, column spacing, and + // array lines by setting attributes on the table element. + // Set the row spacing. In MathML, we specify a gap distance. + // We do not use rowGap[] because MathML automatically increases + // cell height with the height/depth of the element content. + // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. + // We simulate this by adding (arraystretch - 1)em to the gap. This + // does a reasonable job of adjusting arrays containing 1 em tall content. + // The 0.16 and 0.09 values are found empirically. They produce an array + // similar to LaTeX and in which content does not interfere with \hlines. + + const gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray} + : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); + table.setAttribute("rowspacing", makeEm(gap)); // MathML table lines go only between cells. + // To place a line on an edge we'll use , if necessary. + + let menclose = ""; + let align = ""; + + if (group.cols && group.cols.length > 0) { + // Find column alignment, column spacing, and vertical lines. + const cols = group.cols; + let columnLines = ""; + let prevTypeWasAlign = false; + let iStart = 0; + let iEnd = cols.length; + + if (cols[0].type === "separator") { + menclose += "top "; + iStart = 1; + } + + if (cols[cols.length - 1].type === "separator") { + menclose += "bottom "; + iEnd -= 1; + } + + for (let i = iStart; i < iEnd; i++) { + if (cols[i].type === "align") { + align += alignMap[cols[i].align]; + + if (prevTypeWasAlign) { + columnLines += "none "; + } + + prevTypeWasAlign = true; + } else if (cols[i].type === "separator") { + // MathML accepts only single lines between cells. + // So we read only the first of consecutive separators. + if (prevTypeWasAlign) { + columnLines += cols[i].separator === "|" ? "solid " : "dashed "; + prevTypeWasAlign = false; + } + } + } + + table.setAttribute("columnalign", align.trim()); + + if (/[sd]/.test(columnLines)) { + table.setAttribute("columnlines", columnLines.trim()); + } + } // Set column spacing. + + + if (group.colSeparationType === "align") { + const cols = group.cols || []; + let spacing = ""; + + for (let i = 1; i < cols.length; i++) { + spacing += i % 2 ? "0em " : "1em "; + } + + table.setAttribute("columnspacing", spacing.trim()); + } else if (group.colSeparationType === "alignat" || group.colSeparationType === "gather") { + table.setAttribute("columnspacing", "0em"); + } else if (group.colSeparationType === "small") { + table.setAttribute("columnspacing", "0.2778em"); + } else if (group.colSeparationType === "CD") { + table.setAttribute("columnspacing", "0.5em"); + } else { + table.setAttribute("columnspacing", "1em"); + } // Address \hline and \hdashline + + + let rowLines = ""; + const hlines = group.hLinesBeforeRow; + menclose += hlines[0].length > 0 ? "left " : ""; + menclose += hlines[hlines.length - 1].length > 0 ? "right " : ""; + + for (let i = 1; i < hlines.length - 1; i++) { + rowLines += hlines[i].length === 0 ? "none " // MathML accepts only a single line between rows. Read one element. + : hlines[i][0] ? "dashed " : "solid "; + } + + if (/[sd]/.test(rowLines)) { + table.setAttribute("rowlines", rowLines.trim()); + } + + if (menclose !== "") { + table = new mathMLTree.MathNode("menclose", [table]); + table.setAttribute("notation", menclose.trim()); + } + + if (group.arraystretch && group.arraystretch < 1) { + // A small array. Wrap in scriptstyle so row gap is not too large. + table = new mathMLTree.MathNode("mstyle", [table]); + table.setAttribute("scriptlevel", "1"); + } + + return table; +}; // Convenience function for align, align*, aligned, alignat, alignat*, alignedat. + + +const alignedHandler = function (context, args) { + if (context.envName.indexOf("ed") === -1) { + validateAmsEnvironmentContext(context); + } + + const cols = []; + const separationType = context.envName.indexOf("at") > -1 ? "alignat" : "align"; + const isSplit = context.envName === "split"; + const res = parseArray(context.parser, { + cols, + addJot: true, + autoTag: isSplit ? undefined : getAutoTag(context.envName), + emptySingleRow: true, + colSeparationType: separationType, + maxNumCols: isSplit ? 2 : undefined, + leqno: context.parser.settings.leqno + }, "display"); // Determining number of columns. + // 1. If the first argument is given, we use it as a number of columns, + // and makes sure that each row doesn't exceed that number. + // 2. Otherwise, just count number of columns = maximum number + // of cells in each row ("aligned" mode -- isAligned will be true). + // + // At the same time, prepend empty group {} at beginning of every second + // cell in each row (starting with second cell) so that operators become + // binary. This behavior is implemented in amsmath's \start@aligned. + + let numMaths; + let numCols = 0; + const emptyGroup = { + type: "ordgroup", + mode: context.mode, + body: [] + }; + + if (args[0] && args[0].type === "ordgroup") { + let arg0 = ""; + + for (let i = 0; i < args[0].body.length; i++) { + const textord = assertNodeType(args[0].body[i], "textord"); + arg0 += textord.text; + } + + numMaths = Number(arg0); + numCols = numMaths * 2; + } + + const isAligned = !numCols; + res.body.forEach(function (row) { + for (let i = 1; i < row.length; i += 2) { + // Modify ordgroup node within styling node + const styling = assertNodeType(row[i], "styling"); + const ordgroup = assertNodeType(styling.body[0], "ordgroup"); + ordgroup.body.unshift(emptyGroup); + } + + if (!isAligned) { + // Case 1 + const curMaths = row.length / 2; + + if (numMaths < curMaths) { + throw new src_ParseError("Too many math in a row: " + ("expected " + numMaths + ", but got " + curMaths), row[0]); + } + } else if (numCols < row.length) { + // Case 2 + numCols = row.length; + } + }); // Adjusting alignment. + // In aligned mode, we add one \qquad between columns; + // otherwise we add nothing. + + for (let i = 0; i < numCols; ++i) { + let align = "r"; + let pregap = 0; + + if (i % 2 === 1) { + align = "l"; + } else if (i > 0 && isAligned) { + // "aligned" mode. + pregap = 1; // add one \quad + } + + cols[i] = { + type: "align", + align: align, + pregap: pregap, + postgap: 0 + }; + } + + res.colSeparationType = isAligned ? "align" : "alignat"; + return res; +}; // Arrays are part of LaTeX, defined in lttab.dtx so its documentation +// is part of the source2e.pdf file of LaTeX2e source documentation. +// {darray} is an {array} environment where cells are set in \displaystyle, +// as defined in nccmath.sty. + + +defineEnvironment({ + type: "array", + names: ["array", "darray"], + props: { + numArgs: 1 + }, + + handler(context, args) { + // Since no types are specified above, the two possibilities are + // - The argument is wrapped in {} or [], in which case Parser's + // parseGroup() returns an "ordgroup" wrapping some symbol node. + // - The argument is a bare symbol node. + const symNode = checkSymbolNodeType(args[0]); + const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; + const cols = colalign.map(function (nde) { + const node = assertSymbolNodeType(nde); + const ca = node.text; + + if ("lcr".indexOf(ca) !== -1) { + return { + type: "align", + align: ca + }; + } else if (ca === "|") { + return { + type: "separator", + separator: "|" + }; + } else if (ca === ":") { + return { + type: "separator", + separator: ":" + }; + } + + throw new src_ParseError("Unknown column alignment: " + ca, nde); + }); + const res = { + cols, + hskipBeforeAndAfter: true, + // \@preamble in lttab.dtx + maxNumCols: cols.length + }; + return parseArray(context.parser, res, dCellStyle(context.envName)); + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); // The matrix environments of amsmath builds on the array environment +// of LaTeX, which is discussed above. +// The mathtools package adds starred versions of the same environments. +// These have an optional argument to choose left|center|right justification. + +defineEnvironment({ + type: "array", + names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"], + props: { + numArgs: 0 + }, + + handler(context) { + const delimiters = { + "matrix": null, + "pmatrix": ["(", ")"], + "bmatrix": ["[", "]"], + "Bmatrix": ["\\{", "\\}"], + "vmatrix": ["|", "|"], + "Vmatrix": ["\\Vert", "\\Vert"] + }[context.envName.replace("*", "")]; // \hskip -\arraycolsep in amsmath + + let colAlign = "c"; + const payload = { + hskipBeforeAndAfter: false, + cols: [{ + type: "align", + align: colAlign + }] + }; + + if (context.envName.charAt(context.envName.length - 1) === "*") { + // It's one of the mathtools starred functions. + // Parse the optional alignment argument. + const parser = context.parser; + parser.consumeSpaces(); + + if (parser.fetch().text === "[") { + parser.consume(); + parser.consumeSpaces(); + colAlign = parser.fetch().text; + + if ("lcr".indexOf(colAlign) === -1) { + throw new src_ParseError("Expected l or c or r", parser.nextToken); + } + + parser.consume(); + parser.consumeSpaces(); + parser.expect("]"); + parser.consume(); + payload.cols = [{ + type: "align", + align: colAlign + }]; + } + } + + const res = parseArray(context.parser, payload, dCellStyle(context.envName)); // Populate cols with the correct number of column alignment specs. + + const numCols = Math.max(0, ...res.body.map(row => row.length)); + res.cols = new Array(numCols).fill({ + type: "align", + align: colAlign + }); + return delimiters ? { + type: "leftright", + mode: context.mode, + body: [res], + left: delimiters[0], + right: delimiters[1], + rightColor: undefined // \right uninfluenced by \color in array + + } : res; + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); +defineEnvironment({ + type: "array", + names: ["smallmatrix"], + props: { + numArgs: 0 + }, + + handler(context) { + const payload = { + arraystretch: 0.5 + }; + const res = parseArray(context.parser, payload, "script"); + res.colSeparationType = "small"; + return res; + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); +defineEnvironment({ + type: "array", + names: ["subarray"], + props: { + numArgs: 1 + }, + + handler(context, args) { + // Parsing of {subarray} is similar to {array} + const symNode = checkSymbolNodeType(args[0]); + const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; + const cols = colalign.map(function (nde) { + const node = assertSymbolNodeType(nde); + const ca = node.text; // {subarray} only recognizes "l" & "c" + + if ("lc".indexOf(ca) !== -1) { + return { + type: "align", + align: ca + }; + } + + throw new src_ParseError("Unknown column alignment: " + ca, nde); + }); + + if (cols.length > 1) { + throw new src_ParseError("{subarray} can contain only one column"); + } + + let res = { + cols, + hskipBeforeAndAfter: false, + arraystretch: 0.5 + }; + res = parseArray(context.parser, res, "script"); + + if (res.body.length > 0 && res.body[0].length > 1) { + throw new src_ParseError("{subarray} can contain only one column"); + } + + return res; + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); // A cases environment (in amsmath.sty) is almost equivalent to +// \def\arraystretch{1.2}% +// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. +// {dcases} is a {cases} environment where cells are set in \displaystyle, +// as defined in mathtools.sty. +// {rcases} is another mathtools environment. It's brace is on the right side. + +defineEnvironment({ + type: "array", + names: ["cases", "dcases", "rcases", "drcases"], + props: { + numArgs: 0 + }, + + handler(context) { + const payload = { + arraystretch: 1.2, + cols: [{ + type: "align", + align: "l", + pregap: 0, + // TODO(kevinb) get the current style. + // For now we use the metrics for TEXT style which is what we were + // doing before. Before attempting to get the current style we + // should look at TeX's behavior especially for \over and matrices. + postgap: 1.0 + /* 1em quad */ + + }, { + type: "align", + align: "l", + pregap: 0, + postgap: 0 + }] + }; + const res = parseArray(context.parser, payload, dCellStyle(context.envName)); + return { + type: "leftright", + mode: context.mode, + body: [res], + left: context.envName.indexOf("r") > -1 ? "." : "\\{", + right: context.envName.indexOf("r") > -1 ? "\\}" : ".", + rightColor: undefined + }; + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); // In the align environment, one uses ampersands, &, to specify number of +// columns in each row, and to locate spacing between each column. +// align gets automatic numbering. align* and aligned do not. +// The alignedat environment can be used in math mode. +// Note that we assume \nomallineskiplimit to be zero, +// so that \strut@ is the same as \strut. + +defineEnvironment({ + type: "array", + names: ["align", "align*", "aligned", "split"], + props: { + numArgs: 0 + }, + handler: alignedHandler, + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); // A gathered environment is like an array environment with one centered +// column, but where rows are considered lines so get \jot line spacing +// and contents are set in \displaystyle. + +defineEnvironment({ + type: "array", + names: ["gathered", "gather", "gather*"], + props: { + numArgs: 0 + }, + + handler(context) { + if (utils.contains(["gather", "gather*"], context.envName)) { + validateAmsEnvironmentContext(context); + } + + const res = { + cols: [{ + type: "align", + align: "c" + }], + addJot: true, + colSeparationType: "gather", + autoTag: getAutoTag(context.envName), + emptySingleRow: true, + leqno: context.parser.settings.leqno + }; + return parseArray(context.parser, res, "display"); + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); // alignat environment is like an align environment, but one must explicitly +// specify maximum number of columns in each row, and can adjust spacing between +// each columns. + +defineEnvironment({ + type: "array", + names: ["alignat", "alignat*", "alignedat"], + props: { + numArgs: 1 + }, + handler: alignedHandler, + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); +defineEnvironment({ + type: "array", + names: ["equation", "equation*"], + props: { + numArgs: 0 + }, + + handler(context) { + validateAmsEnvironmentContext(context); + const res = { + autoTag: getAutoTag(context.envName), + emptySingleRow: true, + singleRow: true, + maxNumCols: 1, + leqno: context.parser.settings.leqno + }; + return parseArray(context.parser, res, "display"); + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); +defineEnvironment({ + type: "array", + names: ["CD"], + props: { + numArgs: 0 + }, + + handler(context) { + validateAmsEnvironmentContext(context); + return parseCD(context.parser); + }, + + htmlBuilder: array_htmlBuilder, + mathmlBuilder: array_mathmlBuilder +}); +defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}"); +defineMacro("\\notag", "\\nonumber"); // Catch \hline outside array environment + +defineFunction({ + type: "text", + // Doesn't matter what this is. + names: ["\\hline", "\\hdashline"], + props: { + numArgs: 0, + allowedInText: true, + allowedInMath: true + }, + + handler(context, args) { + throw new src_ParseError(context.funcName + " valid only within array environment"); + } + +}); +;// CONCATENATED MODULE: ./src/environments.js + +const environments = _environments; +/* harmony default export */ var src_environments = (environments); // All environment definitions should be imported below + + +;// CONCATENATED MODULE: ./src/functions/environment.js + + + + // Environment delimiters. HTML/MathML rendering is defined in the corresponding +// defineEnvironment definitions. + +defineFunction({ + type: "environment", + names: ["\\begin", "\\end"], + props: { + numArgs: 1, + argTypes: ["text"] + }, + + handler(_ref, args) { + let { + parser, + funcName + } = _ref; + const nameGroup = args[0]; + + if (nameGroup.type !== "ordgroup") { + throw new src_ParseError("Invalid environment name", nameGroup); + } + + let envName = ""; + + for (let i = 0; i < nameGroup.body.length; ++i) { + envName += assertNodeType(nameGroup.body[i], "textord").text; + } + + if (funcName === "\\begin") { + // begin...end is similar to left...right + if (!src_environments.hasOwnProperty(envName)) { + throw new src_ParseError("No such environment: " + envName, nameGroup); + } // Build the environment object. Arguments and other information will + // be made available to the begin and end methods using properties. + + + const env = src_environments[envName]; + const { + args, + optArgs + } = parser.parseArguments("\\begin{" + envName + "}", env); + const context = { + mode: parser.mode, + envName, + parser + }; + const result = env.handler(context, args, optArgs); + parser.expect("\\end", false); + const endNameToken = parser.nextToken; + const end = assertNodeType(parser.parseFunction(), "environment"); + + if (end.name !== envName) { + throw new src_ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken); + } // $FlowFixMe, "environment" handler returns an environment ParseNode + + + return result; + } + + return { + type: "environment", + mode: parser.mode, + name: envName, + nameGroup + }; + } + +}); +;// CONCATENATED MODULE: ./src/functions/font.js +// TODO(kevinb): implement \\sl and \\sc + + + + + + +const font_htmlBuilder = (group, options) => { + const font = group.font; + const newOptions = options.withFont(font); + return buildGroup(group.body, newOptions); +}; + +const font_mathmlBuilder = (group, options) => { + const font = group.font; + const newOptions = options.withFont(font); + return buildMathML_buildGroup(group.body, newOptions); +}; + +const fontAliases = { + "\\Bbb": "\\mathbb", + "\\bold": "\\mathbf", + "\\frak": "\\mathfrak", + "\\bm": "\\boldsymbol" +}; +defineFunction({ + type: "font", + names: [// styles, except \boldsymbol defined below + "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", "\\mathsfit", // families + "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", // aliases, except \bm defined below + "\\Bbb", "\\bold", "\\frak"], + props: { + numArgs: 1, + allowedInArgument: true + }, + handler: (_ref, args) => { + let { + parser, + funcName + } = _ref; + const body = normalizeArgument(args[0]); + let func = funcName; + + if (func in fontAliases) { + func = fontAliases[func]; + } + + return { + type: "font", + mode: parser.mode, + font: func.slice(1), + body + }; + }, + htmlBuilder: font_htmlBuilder, + mathmlBuilder: font_mathmlBuilder +}); +defineFunction({ + type: "mclass", + names: ["\\boldsymbol", "\\bm"], + props: { + numArgs: 1 + }, + handler: (_ref2, args) => { + let { + parser + } = _ref2; + const body = args[0]; + const isCharacterBox = utils.isCharacterBox(body); // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the + // argument's bin|rel|ord status + + return { + type: "mclass", + mode: parser.mode, + mclass: binrelClass(body), + body: [{ + type: "font", + mode: parser.mode, + font: "boldsymbol", + body + }], + isCharacterBox: isCharacterBox + }; + } +}); // Old font changing functions + +defineFunction({ + type: "font", + names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], + props: { + numArgs: 0, + allowedInText: true + }, + handler: (_ref3, args) => { + let { + parser, + funcName, + breakOnTokenText + } = _ref3; + const { + mode + } = parser; + const body = parser.parseExpression(true, breakOnTokenText); + const style = "math" + funcName.slice(1); + return { + type: "font", + mode: mode, + font: style, + body: { + type: "ordgroup", + mode: parser.mode, + body + } + }; + }, + htmlBuilder: font_htmlBuilder, + mathmlBuilder: font_mathmlBuilder +}); +;// CONCATENATED MODULE: ./src/functions/genfrac.js + + + + + + + + + + + +const adjustStyle = (size, originalStyle) => { + // Figure out what style this fraction should be in based on the + // function used + let style = originalStyle; + + if (size === "display") { + // Get display style as a default. + // If incoming style is sub/sup, use style.text() to get correct size. + style = style.id >= src_Style.SCRIPT.id ? style.text() : src_Style.DISPLAY; + } else if (size === "text" && style.size === src_Style.DISPLAY.size) { + // We're in a \tfrac but incoming style is displaystyle, so: + style = src_Style.TEXT; + } else if (size === "script") { + style = src_Style.SCRIPT; + } else if (size === "scriptscript") { + style = src_Style.SCRIPTSCRIPT; + } + + return style; +}; + +const genfrac_htmlBuilder = (group, options) => { + // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e). + const style = adjustStyle(group.size, options.style); + const nstyle = style.fracNum(); + const dstyle = style.fracDen(); + let newOptions; + newOptions = options.havingStyle(nstyle); + const numerm = buildGroup(group.numer, newOptions, options); + + if (group.continued) { + // \cfrac inserts a \strut into the numerator. + // Get \strut dimensions from TeXbook page 353. + const hStrut = 8.5 / options.fontMetrics().ptPerEm; + const dStrut = 3.5 / options.fontMetrics().ptPerEm; + numerm.height = numerm.height < hStrut ? hStrut : numerm.height; + numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth; + } + + newOptions = options.havingStyle(dstyle); + const denomm = buildGroup(group.denom, newOptions, options); + let rule; + let ruleWidth; + let ruleSpacing; + + if (group.hasBarLine) { + if (group.barSize) { + ruleWidth = calculateSize(group.barSize, options); + rule = buildCommon.makeLineSpan("frac-line", options, ruleWidth); + } else { + rule = buildCommon.makeLineSpan("frac-line", options); + } + + ruleWidth = rule.height; + ruleSpacing = rule.height; + } else { + rule = null; + ruleWidth = 0; + ruleSpacing = options.fontMetrics().defaultRuleThickness; + } // Rule 15b + + + let numShift; + let clearance; + let denomShift; + + if (style.size === src_Style.DISPLAY.size || group.size === "display") { + numShift = options.fontMetrics().num1; + + if (ruleWidth > 0) { + clearance = 3 * ruleSpacing; + } else { + clearance = 7 * ruleSpacing; + } + + denomShift = options.fontMetrics().denom1; + } else { + if (ruleWidth > 0) { + numShift = options.fontMetrics().num2; + clearance = ruleSpacing; + } else { + numShift = options.fontMetrics().num3; + clearance = 3 * ruleSpacing; + } + + denomShift = options.fontMetrics().denom2; + } + + let frac; + + if (!rule) { + // Rule 15c + const candidateClearance = numShift - numerm.depth - (denomm.height - denomShift); + + if (candidateClearance < clearance) { + numShift += 0.5 * (clearance - candidateClearance); + denomShift += 0.5 * (clearance - candidateClearance); + } + + frac = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: denomm, + shift: denomShift + }, { + type: "elem", + elem: numerm, + shift: -numShift + }] + }, options); + } else { + // Rule 15d + const axisHeight = options.fontMetrics().axisHeight; + + if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) { + numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth)); + } + + if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) { + denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift)); + } + + const midShift = -(axisHeight - 0.5 * ruleWidth); + frac = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: denomm, + shift: denomShift + }, { + type: "elem", + elem: rule, + shift: midShift + }, { + type: "elem", + elem: numerm, + shift: -numShift + }] + }, options); + } // Since we manually change the style sometimes (with \dfrac or \tfrac), + // account for the possible size change here. + + + newOptions = options.havingStyle(style); + frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier; + frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier; // Rule 15e + + let delimSize; + + if (style.size === src_Style.DISPLAY.size) { + delimSize = options.fontMetrics().delim1; + } else if (style.size === src_Style.SCRIPTSCRIPT.size) { + delimSize = options.havingStyle(src_Style.SCRIPT).fontMetrics().delim2; + } else { + delimSize = options.fontMetrics().delim2; + } + + let leftDelim; + let rightDelim; + + if (group.leftDelim == null) { + leftDelim = makeNullDelimiter(options, ["mopen"]); + } else { + leftDelim = delimiter.customSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]); + } + + if (group.continued) { + rightDelim = buildCommon.makeSpan([]); // zero width for \cfrac + } else if (group.rightDelim == null) { + rightDelim = makeNullDelimiter(options, ["mclose"]); + } else { + rightDelim = delimiter.customSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]); + } + + return buildCommon.makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, buildCommon.makeSpan(["mfrac"], [frac]), rightDelim], options); +}; + +const genfrac_mathmlBuilder = (group, options) => { + let node = new mathMLTree.MathNode("mfrac", [buildMathML_buildGroup(group.numer, options), buildMathML_buildGroup(group.denom, options)]); + + if (!group.hasBarLine) { + node.setAttribute("linethickness", "0px"); + } else if (group.barSize) { + const ruleWidth = calculateSize(group.barSize, options); + node.setAttribute("linethickness", makeEm(ruleWidth)); + } + + const style = adjustStyle(group.size, options.style); + + if (style.size !== options.style.size) { + node = new mathMLTree.MathNode("mstyle", [node]); + const isDisplay = style.size === src_Style.DISPLAY.size ? "true" : "false"; + node.setAttribute("displaystyle", isDisplay); + node.setAttribute("scriptlevel", "0"); + } + + if (group.leftDelim != null || group.rightDelim != null) { + const withDelims = []; + + if (group.leftDelim != null) { + const leftOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.leftDelim.replace("\\", ""))]); + leftOp.setAttribute("fence", "true"); + withDelims.push(leftOp); + } + + withDelims.push(node); + + if (group.rightDelim != null) { + const rightOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.rightDelim.replace("\\", ""))]); + rightOp.setAttribute("fence", "true"); + withDelims.push(rightOp); + } + + return makeRow(withDelims); + } + + return node; +}; + +defineFunction({ + type: "genfrac", + names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", // can’t be entered directly + "\\\\bracefrac", "\\\\brackfrac" // ditto + ], + props: { + numArgs: 2, + allowedInArgument: true + }, + handler: (_ref, args) => { + let { + parser, + funcName + } = _ref; + const numer = args[0]; + const denom = args[1]; + let hasBarLine; + let leftDelim = null; + let rightDelim = null; + let size = "auto"; + + switch (funcName) { + case "\\dfrac": + case "\\frac": + case "\\tfrac": + hasBarLine = true; + break; + + case "\\\\atopfrac": + hasBarLine = false; + break; + + case "\\dbinom": + case "\\binom": + case "\\tbinom": + hasBarLine = false; + leftDelim = "("; + rightDelim = ")"; + break; + + case "\\\\bracefrac": + hasBarLine = false; + leftDelim = "\\{"; + rightDelim = "\\}"; + break; + + case "\\\\brackfrac": + hasBarLine = false; + leftDelim = "["; + rightDelim = "]"; + break; + + default: + throw new Error("Unrecognized genfrac command"); + } + + switch (funcName) { + case "\\dfrac": + case "\\dbinom": + size = "display"; + break; + + case "\\tfrac": + case "\\tbinom": + size = "text"; + break; + } + + return { + type: "genfrac", + mode: parser.mode, + continued: false, + numer, + denom, + hasBarLine, + leftDelim, + rightDelim, + size, + barSize: null + }; + }, + htmlBuilder: genfrac_htmlBuilder, + mathmlBuilder: genfrac_mathmlBuilder +}); +defineFunction({ + type: "genfrac", + names: ["\\cfrac"], + props: { + numArgs: 2 + }, + handler: (_ref2, args) => { + let { + parser, + funcName + } = _ref2; + const numer = args[0]; + const denom = args[1]; + return { + type: "genfrac", + mode: parser.mode, + continued: true, + numer, + denom, + hasBarLine: true, + leftDelim: null, + rightDelim: null, + size: "display", + barSize: null + }; + } +}); // Infix generalized fractions -- these are not rendered directly, but replaced +// immediately by one of the variants above. + +defineFunction({ + type: "infix", + names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], + props: { + numArgs: 0, + infix: true + }, + + handler(_ref3) { + let { + parser, + funcName, + token + } = _ref3; + let replaceWith; + + switch (funcName) { + case "\\over": + replaceWith = "\\frac"; + break; + + case "\\choose": + replaceWith = "\\binom"; + break; + + case "\\atop": + replaceWith = "\\\\atopfrac"; + break; + + case "\\brace": + replaceWith = "\\\\bracefrac"; + break; + + case "\\brack": + replaceWith = "\\\\brackfrac"; + break; + + default: + throw new Error("Unrecognized infix genfrac command"); + } + + return { + type: "infix", + mode: parser.mode, + replaceWith, + token + }; + } + +}); +const stylArray = ["display", "text", "script", "scriptscript"]; + +const delimFromValue = function (delimString) { + let delim = null; + + if (delimString.length > 0) { + delim = delimString; + delim = delim === "." ? null : delim; + } + + return delim; +}; + +defineFunction({ + type: "genfrac", + names: ["\\genfrac"], + props: { + numArgs: 6, + allowedInArgument: true, + argTypes: ["math", "math", "size", "text", "math", "math"] + }, + + handler(_ref4, args) { + let { + parser + } = _ref4; + const numer = args[4]; + const denom = args[5]; // Look into the parse nodes to get the desired delimiters. + + const leftNode = normalizeArgument(args[0]); + const leftDelim = leftNode.type === "atom" && leftNode.family === "open" ? delimFromValue(leftNode.text) : null; + const rightNode = normalizeArgument(args[1]); + const rightDelim = rightNode.type === "atom" && rightNode.family === "close" ? delimFromValue(rightNode.text) : null; + const barNode = assertNodeType(args[2], "size"); + let hasBarLine; + let barSize = null; + + if (barNode.isBlank) { + // \genfrac acts differently than \above. + // \genfrac treats an empty size group as a signal to use a + // standard bar size. \above would see size = 0 and omit the bar. + hasBarLine = true; + } else { + barSize = barNode.value; + hasBarLine = barSize.number > 0; + } // Find out if we want displaystyle, textstyle, etc. + + + let size = "auto"; + let styl = args[3]; + + if (styl.type === "ordgroup") { + if (styl.body.length > 0) { + const textOrd = assertNodeType(styl.body[0], "textord"); + size = stylArray[Number(textOrd.text)]; + } + } else { + styl = assertNodeType(styl, "textord"); + size = stylArray[Number(styl.text)]; + } + + return { + type: "genfrac", + mode: parser.mode, + numer, + denom, + continued: false, + hasBarLine, + barSize, + leftDelim, + rightDelim, + size + }; + }, + + htmlBuilder: genfrac_htmlBuilder, + mathmlBuilder: genfrac_mathmlBuilder +}); // \above is an infix fraction that also defines a fraction bar size. + +defineFunction({ + type: "infix", + names: ["\\above"], + props: { + numArgs: 1, + argTypes: ["size"], + infix: true + }, + + handler(_ref5, args) { + let { + parser, + funcName, + token + } = _ref5; + return { + type: "infix", + mode: parser.mode, + replaceWith: "\\\\abovefrac", + size: assertNodeType(args[0], "size").value, + token + }; + } + +}); +defineFunction({ + type: "genfrac", + names: ["\\\\abovefrac"], + props: { + numArgs: 3, + argTypes: ["math", "size", "math"] + }, + handler: (_ref6, args) => { + let { + parser, + funcName + } = _ref6; + const numer = args[0]; + const barSize = assert(assertNodeType(args[1], "infix").size); + const denom = args[2]; + const hasBarLine = barSize.number > 0; + return { + type: "genfrac", + mode: parser.mode, + numer, + denom, + continued: false, + hasBarLine, + barSize, + leftDelim: null, + rightDelim: null, + size: "auto" + }; + }, + htmlBuilder: genfrac_htmlBuilder, + mathmlBuilder: genfrac_mathmlBuilder +}); +;// CONCATENATED MODULE: ./src/functions/horizBrace.js + + + + + + + + +// NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but +// also "supsub" since an over/underbrace can affect super/subscripting. +const horizBrace_htmlBuilder = (grp, options) => { + const style = options.style; // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node. + + let supSubGroup; + let group; + + if (grp.type === "supsub") { + // Ref: LaTeX source2e: }}}}\limits} + // i.e. LaTeX treats the brace similar to an op and passes it + // with \limits, so we need to assign supsub style. + supSubGroup = grp.sup ? buildGroup(grp.sup, options.havingStyle(style.sup()), options) : buildGroup(grp.sub, options.havingStyle(style.sub()), options); + group = assertNodeType(grp.base, "horizBrace"); + } else { + group = assertNodeType(grp, "horizBrace"); + } // Build the base group + + + const body = buildGroup(group.base, options.havingBaseStyle(src_Style.DISPLAY)); // Create the stretchy element + + const braceBody = stretchy.svgSpan(group, options); // Generate the vlist, with the appropriate kerns ┏━━━━━━━━┓ + // This first vlist contains the content and the brace: equation + + let vlist; + + if (group.isOver) { + vlist = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: body + }, { + type: "kern", + size: 0.1 + }, { + type: "elem", + elem: braceBody + }] + }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList. + + vlist.children[0].children[0].children[1].classes.push("svg-align"); + } else { + vlist = buildCommon.makeVList({ + positionType: "bottom", + positionData: body.depth + 0.1 + braceBody.height, + children: [{ + type: "elem", + elem: braceBody + }, { + type: "kern", + size: 0.1 + }, { + type: "elem", + elem: body + }] + }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList. + + vlist.children[0].children[0].children[0].classes.push("svg-align"); + } + + if (supSubGroup) { + // To write the supsub, wrap the first vlist in another vlist: + // They can't all go in the same vlist, because the note might be + // wider than the equation. We want the equation to control the + // brace width. + // note long note long note + // ┏━━━━━━━━┓ or ┏━━━┓ not ┏━━━━━━━━━┓ + // equation eqn eqn + const vSpan = buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options); + + if (group.isOver) { + vlist = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: vSpan + }, { + type: "kern", + size: 0.2 + }, { + type: "elem", + elem: supSubGroup + }] + }, options); + } else { + vlist = buildCommon.makeVList({ + positionType: "bottom", + positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth, + children: [{ + type: "elem", + elem: supSubGroup + }, { + type: "kern", + size: 0.2 + }, { + type: "elem", + elem: vSpan + }] + }, options); + } + } + + return buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options); +}; + +const horizBrace_mathmlBuilder = (group, options) => { + const accentNode = stretchy.mathMLnode(group.label); + return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [buildMathML_buildGroup(group.base, options), accentNode]); +}; // Horizontal stretchy braces + + +defineFunction({ + type: "horizBrace", + names: ["\\overbrace", "\\underbrace"], + props: { + numArgs: 1 + }, + + handler(_ref, args) { + let { + parser, + funcName + } = _ref; + return { + type: "horizBrace", + mode: parser.mode, + label: funcName, + isOver: /^\\over/.test(funcName), + base: args[0] + }; + }, + + htmlBuilder: horizBrace_htmlBuilder, + mathmlBuilder: horizBrace_mathmlBuilder +}); +;// CONCATENATED MODULE: ./src/functions/href.js + + + + + + +defineFunction({ + type: "href", + names: ["\\href"], + props: { + numArgs: 2, + argTypes: ["url", "original"], + allowedInText: true + }, + handler: (_ref, args) => { + let { + parser + } = _ref; + const body = args[1]; + const href = assertNodeType(args[0], "url").url; + + if (!parser.settings.isTrusted({ + command: "\\href", + url: href + })) { + return parser.formatUnsupportedCmd("\\href"); + } + + return { + type: "href", + mode: parser.mode, + href, + body: ordargument(body) + }; + }, + htmlBuilder: (group, options) => { + const elements = buildExpression(group.body, options, false); + return buildCommon.makeAnchor(group.href, [], elements, options); + }, + mathmlBuilder: (group, options) => { + let math = buildExpressionRow(group.body, options); + + if (!(math instanceof MathNode)) { + math = new MathNode("mrow", [math]); + } + + math.setAttribute("href", group.href); + return math; + } +}); +defineFunction({ + type: "href", + names: ["\\url"], + props: { + numArgs: 1, + argTypes: ["url"], + allowedInText: true + }, + handler: (_ref2, args) => { + let { + parser + } = _ref2; + const href = assertNodeType(args[0], "url").url; + + if (!parser.settings.isTrusted({ + command: "\\url", + url: href + })) { + return parser.formatUnsupportedCmd("\\url"); + } + + const chars = []; + + for (let i = 0; i < href.length; i++) { + let c = href[i]; + + if (c === "~") { + c = "\\textasciitilde"; + } + + chars.push({ + type: "textord", + mode: "text", + text: c + }); + } + + const body = { + type: "text", + mode: parser.mode, + font: "\\texttt", + body: chars + }; + return { + type: "href", + mode: parser.mode, + href, + body: ordargument(body) + }; + } +}); +;// CONCATENATED MODULE: ./src/functions/hbox.js + + + + + // \hbox is provided for compatibility with LaTeX \vcenter. +// In LaTeX, \vcenter can act only on a box, as in +// \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}} +// This function by itself doesn't do anything but prevent a soft line break. + +defineFunction({ + type: "hbox", + names: ["\\hbox"], + props: { + numArgs: 1, + argTypes: ["text"], + allowedInText: true, + primitive: true + }, + + handler(_ref, args) { + let { + parser + } = _ref; + return { + type: "hbox", + mode: parser.mode, + body: ordargument(args[0]) + }; + }, + + htmlBuilder(group, options) { + const elements = buildExpression(group.body, options, false); + return buildCommon.makeFragment(elements); + }, + + mathmlBuilder(group, options) { + return new mathMLTree.MathNode("mrow", buildMathML_buildExpression(group.body, options)); + } + +}); +;// CONCATENATED MODULE: ./src/functions/html.js + + + + + + +defineFunction({ + type: "html", + names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"], + props: { + numArgs: 2, + argTypes: ["raw", "original"], + allowedInText: true + }, + handler: (_ref, args) => { + let { + parser, + funcName, + token + } = _ref; + const value = assertNodeType(args[0], "raw").string; + const body = args[1]; + + if (parser.settings.strict) { + parser.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode"); + } + + let trustContext; + const attributes = {}; + + switch (funcName) { + case "\\htmlClass": + attributes.class = value; + trustContext = { + command: "\\htmlClass", + class: value + }; + break; + + case "\\htmlId": + attributes.id = value; + trustContext = { + command: "\\htmlId", + id: value + }; + break; + + case "\\htmlStyle": + attributes.style = value; + trustContext = { + command: "\\htmlStyle", + style: value + }; + break; + + case "\\htmlData": + { + const data = value.split(","); + + for (let i = 0; i < data.length; i++) { + const keyVal = data[i].split("="); + + if (keyVal.length !== 2) { + throw new src_ParseError("Error parsing key-value for \\htmlData"); + } + + attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); + } + + trustContext = { + command: "\\htmlData", + attributes + }; + break; + } + + default: + throw new Error("Unrecognized html command"); + } + + if (!parser.settings.isTrusted(trustContext)) { + return parser.formatUnsupportedCmd(funcName); + } + + return { + type: "html", + mode: parser.mode, + attributes, + body: ordargument(body) + }; + }, + htmlBuilder: (group, options) => { + const elements = buildExpression(group.body, options, false); + const classes = ["enclosing"]; + + if (group.attributes.class) { + classes.push(...group.attributes.class.trim().split(/\s+/)); + } + + const span = buildCommon.makeSpan(classes, elements, options); + + for (const attr in group.attributes) { + if (attr !== "class" && group.attributes.hasOwnProperty(attr)) { + span.setAttribute(attr, group.attributes[attr]); + } + } + + return span; + }, + mathmlBuilder: (group, options) => { + return buildExpressionRow(group.body, options); + } +}); +;// CONCATENATED MODULE: ./src/functions/htmlmathml.js + + + + +defineFunction({ + type: "htmlmathml", + names: ["\\html@mathml"], + props: { + numArgs: 2, + allowedInText: true + }, + handler: (_ref, args) => { + let { + parser + } = _ref; + return { + type: "htmlmathml", + mode: parser.mode, + html: ordargument(args[0]), + mathml: ordargument(args[1]) + }; + }, + htmlBuilder: (group, options) => { + const elements = buildExpression(group.html, options, false); + return buildCommon.makeFragment(elements); + }, + mathmlBuilder: (group, options) => { + return buildExpressionRow(group.mathml, options); + } +}); +;// CONCATENATED MODULE: ./src/functions/includegraphics.js + + + + + + + +const sizeData = function (str) { + if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { + // str is a number with no unit specified. + // default unit is bp, per graphix package. + return { + number: +str, + unit: "bp" + }; + } else { + const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); + + if (!match) { + throw new src_ParseError("Invalid size: '" + str + "' in \\includegraphics"); + } + + const data = { + number: +(match[1] + match[2]), + // sign + magnitude, cast to number + unit: match[3] + }; + + if (!validUnit(data)) { + throw new src_ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); + } + + return data; + } +}; + +defineFunction({ + type: "includegraphics", + names: ["\\includegraphics"], + props: { + numArgs: 1, + numOptionalArgs: 1, + argTypes: ["raw", "url"], + allowedInText: false + }, + handler: (_ref, args, optArgs) => { + let { + parser + } = _ref; + let width = { + number: 0, + unit: "em" + }; + let height = { + number: 0.9, + unit: "em" + }; // sorta character sized. + + let totalheight = { + number: 0, + unit: "em" + }; + let alt = ""; + + if (optArgs[0]) { + const attributeStr = assertNodeType(optArgs[0], "raw").string; // Parser.js does not parse key/value pairs. We get a string. + + const attributes = attributeStr.split(","); + + for (let i = 0; i < attributes.length; i++) { + const keyVal = attributes[i].split("="); + + if (keyVal.length === 2) { + const str = keyVal[1].trim(); + + switch (keyVal[0].trim()) { + case "alt": + alt = str; + break; + + case "width": + width = sizeData(str); + break; + + case "height": + height = sizeData(str); + break; + + case "totalheight": + totalheight = sizeData(str); + break; + + default: + throw new src_ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics."); + } + } + } + } + + const src = assertNodeType(args[0], "url").url; + + if (alt === "") { + // No alt given. Use the file name. Strip away the path. + alt = src; + alt = alt.replace(/^.*[\\/]/, ''); + alt = alt.substring(0, alt.lastIndexOf('.')); + } + + if (!parser.settings.isTrusted({ + command: "\\includegraphics", + url: src + })) { + return parser.formatUnsupportedCmd("\\includegraphics"); + } + + return { + type: "includegraphics", + mode: parser.mode, + alt: alt, + width: width, + height: height, + totalheight: totalheight, + src: src + }; + }, + htmlBuilder: (group, options) => { + const height = calculateSize(group.height, options); + let depth = 0; + + if (group.totalheight.number > 0) { + depth = calculateSize(group.totalheight, options) - height; + } + + let width = 0; + + if (group.width.number > 0) { + width = calculateSize(group.width, options); + } + + const style = { + height: makeEm(height + depth) + }; + + if (width > 0) { + style.width = makeEm(width); + } + + if (depth > 0) { + style.verticalAlign = makeEm(-depth); + } + + const node = new Img(group.src, group.alt, style); + node.height = height; + node.depth = depth; + return node; + }, + mathmlBuilder: (group, options) => { + const node = new mathMLTree.MathNode("mglyph", []); + node.setAttribute("alt", group.alt); + const height = calculateSize(group.height, options); + let depth = 0; + + if (group.totalheight.number > 0) { + depth = calculateSize(group.totalheight, options) - height; + node.setAttribute("valign", makeEm(-depth)); + } + + node.setAttribute("height", makeEm(height + depth)); + + if (group.width.number > 0) { + const width = calculateSize(group.width, options); + node.setAttribute("width", makeEm(width)); + } + + node.setAttribute("src", group.src); + return node; + } +}); +;// CONCATENATED MODULE: ./src/functions/kern.js +// Horizontal spacing commands + + + + + // TODO: \hskip and \mskip should support plus and minus in lengths + +defineFunction({ + type: "kern", + names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], + props: { + numArgs: 1, + argTypes: ["size"], + primitive: true, + allowedInText: true + }, + + handler(_ref, args) { + let { + parser, + funcName + } = _ref; + const size = assertNodeType(args[0], "size"); + + if (parser.settings.strict) { + const mathFunction = funcName[1] === 'm'; // \mkern, \mskip + + const muUnit = size.value.unit === 'mu'; + + if (mathFunction) { + if (!muUnit) { + parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " supports only mu units, " + ("not " + size.value.unit + " units")); + } + + if (parser.mode !== "math") { + parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " works only in math mode"); + } + } else { + // !mathFunction + if (muUnit) { + parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " doesn't support mu units"); + } + } + } + + return { + type: "kern", + mode: parser.mode, + dimension: size.value + }; + }, + + htmlBuilder(group, options) { + return buildCommon.makeGlue(group.dimension, options); + }, + + mathmlBuilder(group, options) { + const dimension = calculateSize(group.dimension, options); + return new mathMLTree.SpaceNode(dimension); + } + +}); +;// CONCATENATED MODULE: ./src/functions/lap.js +// Horizontal overlap functions + + + + + + +defineFunction({ + type: "lap", + names: ["\\mathllap", "\\mathrlap", "\\mathclap"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref, args) => { + let { + parser, + funcName + } = _ref; + const body = args[0]; + return { + type: "lap", + mode: parser.mode, + alignment: funcName.slice(5), + body + }; + }, + htmlBuilder: (group, options) => { + // mathllap, mathrlap, mathclap + let inner; + + if (group.alignment === "clap") { + // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/ + inner = buildCommon.makeSpan([], [buildGroup(group.body, options)]); // wrap, since CSS will center a .clap > .inner > span + + inner = buildCommon.makeSpan(["inner"], [inner], options); + } else { + inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options)]); + } + + const fix = buildCommon.makeSpan(["fix"], []); + let node = buildCommon.makeSpan([group.alignment], [inner, fix], options); // At this point, we have correctly set horizontal alignment of the + // two items involved in the lap. + // Next, use a strut to set the height of the HTML bounding box. + // Otherwise, a tall argument may be misplaced. + // This code resolved issue #1153 + + const strut = buildCommon.makeSpan(["strut"]); + strut.style.height = makeEm(node.height + node.depth); + + if (node.depth) { + strut.style.verticalAlign = makeEm(-node.depth); + } + + node.children.unshift(strut); // Next, prevent vertical misplacement when next to something tall. + // This code resolves issue #1234 + + node = buildCommon.makeSpan(["thinbox"], [node], options); + return buildCommon.makeSpan(["mord", "vbox"], [node], options); + }, + mathmlBuilder: (group, options) => { + // mathllap, mathrlap, mathclap + const node = new mathMLTree.MathNode("mpadded", [buildMathML_buildGroup(group.body, options)]); + + if (group.alignment !== "rlap") { + const offset = group.alignment === "llap" ? "-1" : "-0.5"; + node.setAttribute("lspace", offset + "width"); + } + + node.setAttribute("width", "0px"); + return node; + } +}); +;// CONCATENATED MODULE: ./src/functions/math.js + + // Switching from text mode back to math mode + +defineFunction({ + type: "styling", + names: ["\\(", "$"], + props: { + numArgs: 0, + allowedInText: true, + allowedInMath: false + }, + + handler(_ref, args) { + let { + funcName, + parser + } = _ref; + const outerMode = parser.mode; + parser.switchMode("math"); + const close = funcName === "\\(" ? "\\)" : "$"; + const body = parser.parseExpression(false, close); + parser.expect(close); + parser.switchMode(outerMode); + return { + type: "styling", + mode: parser.mode, + style: "text", + body + }; + } + +}); // Check for extra closing math delimiters + +defineFunction({ + type: "text", + // Doesn't matter what this is. + names: ["\\)", "\\]"], + props: { + numArgs: 0, + allowedInText: true, + allowedInMath: false + }, + + handler(context, args) { + throw new src_ParseError("Mismatched " + context.funcName); + } + +}); +;// CONCATENATED MODULE: ./src/functions/mathchoice.js + + + + + + +const chooseMathStyle = (group, options) => { + switch (options.style.size) { + case src_Style.DISPLAY.size: + return group.display; + + case src_Style.TEXT.size: + return group.text; + + case src_Style.SCRIPT.size: + return group.script; + + case src_Style.SCRIPTSCRIPT.size: + return group.scriptscript; + + default: + return group.text; + } +}; + +defineFunction({ + type: "mathchoice", + names: ["\\mathchoice"], + props: { + numArgs: 4, + primitive: true + }, + handler: (_ref, args) => { + let { + parser + } = _ref; + return { + type: "mathchoice", + mode: parser.mode, + display: ordargument(args[0]), + text: ordargument(args[1]), + script: ordargument(args[2]), + scriptscript: ordargument(args[3]) + }; + }, + htmlBuilder: (group, options) => { + const body = chooseMathStyle(group, options); + const elements = buildExpression(body, options, false); + return buildCommon.makeFragment(elements); + }, + mathmlBuilder: (group, options) => { + const body = chooseMathStyle(group, options); + return buildExpressionRow(body, options); + } +}); +;// CONCATENATED MODULE: ./src/functions/utils/assembleSupSub.js + + + + // For an operator with limits, assemble the base, sup, and sub into a span. + +const assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => { + base = buildCommon.makeSpan([], [base]); + const subIsSingleCharacter = subGroup && utils.isCharacterBox(subGroup); + let sub; + let sup; // We manually have to handle the superscripts and subscripts. This, + // aside from the kern calculations, is copied from supsub. + + if (supGroup) { + const elem = buildGroup(supGroup, options.havingStyle(style.sup()), options); + sup = { + elem, + kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth) + }; + } + + if (subGroup) { + const elem = buildGroup(subGroup, options.havingStyle(style.sub()), options); + sub = { + elem, + kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - elem.height) + }; + } // Build the final group as a vlist of the possible subscript, base, + // and possible superscript. + + + let finalGroup; + + if (sup && sub) { + const bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift; + finalGroup = buildCommon.makeVList({ + positionType: "bottom", + positionData: bottom, + children: [{ + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }, { + type: "elem", + elem: sub.elem, + marginLeft: makeEm(-slant) + }, { + type: "kern", + size: sub.kern + }, { + type: "elem", + elem: base + }, { + type: "kern", + size: sup.kern + }, { + type: "elem", + elem: sup.elem, + marginLeft: makeEm(slant) + }, { + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }] + }, options); + } else if (sub) { + const top = base.height - baseShift; // Shift the limits by the slant of the symbol. Note + // that we are supposed to shift the limits by 1/2 of the slant, + // but since we are centering the limits adding a full slant of + // margin will shift by 1/2 that. + + finalGroup = buildCommon.makeVList({ + positionType: "top", + positionData: top, + children: [{ + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }, { + type: "elem", + elem: sub.elem, + marginLeft: makeEm(-slant) + }, { + type: "kern", + size: sub.kern + }, { + type: "elem", + elem: base + }] + }, options); + } else if (sup) { + const bottom = base.depth + baseShift; + finalGroup = buildCommon.makeVList({ + positionType: "bottom", + positionData: bottom, + children: [{ + type: "elem", + elem: base + }, { + type: "kern", + size: sup.kern + }, { + type: "elem", + elem: sup.elem, + marginLeft: makeEm(slant) + }, { + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }] + }, options); + } else { + // This case probably shouldn't occur (this would mean the + // supsub was sending us a group with no superscript or + // subscript) but be safe. + return base; + } + + const parts = [finalGroup]; + + if (sub && slant !== 0 && !subIsSingleCharacter) { + // A negative margin-left was applied to the lower limit. + // Avoid an overlap by placing a spacer on the left on the group. + const spacer = buildCommon.makeSpan(["mspace"], [], options); + spacer.style.marginRight = makeEm(slant); + parts.unshift(spacer); + } + + return buildCommon.makeSpan(["mop", "op-limits"], parts, options); +}; +;// CONCATENATED MODULE: ./src/functions/op.js +// Limits, symbols + + + + + + + + + + + +// Most operators have a large successor symbol, but these don't. +const noSuccessor = ["\\smallint"]; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also +// "supsub" since some of them (like \int) can affect super/subscripting. + +const op_htmlBuilder = (grp, options) => { + // Operators are handled in the TeXbook pg. 443-444, rule 13(a). + let supGroup; + let subGroup; + let hasLimits = false; + let group; + + if (grp.type === "supsub") { + // If we have limits, supsub will pass us its group to handle. Pull + // out the superscript and subscript and set the group to the op in + // its base. + supGroup = grp.sup; + subGroup = grp.sub; + group = assertNodeType(grp.base, "op"); + hasLimits = true; + } else { + group = assertNodeType(grp, "op"); + } + + const style = options.style; + let large = false; + + if (style.size === src_Style.DISPLAY.size && group.symbol && !utils.contains(noSuccessor, group.name)) { + // Most symbol operators get larger in displaystyle (rule 13) + large = true; + } + + let base; + + if (group.symbol) { + // If this is a symbol, create the symbol. + const fontName = large ? "Size2-Regular" : "Size1-Regular"; + let stash = ""; + + if (group.name === "\\oiint" || group.name === "\\oiiint") { + // No font glyphs yet, so use a glyph w/o the oval. + // TODO: When font glyphs are available, delete this code. + stash = group.name.slice(1); + group.name = stash === "oiint" ? "\\iint" : "\\iiint"; + } + + base = buildCommon.makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]); + + if (stash.length > 0) { + // We're in \oiint or \oiiint. Overlay the oval. + // TODO: When font glyphs are available, delete this code. + const italic = base.italic; + const oval = buildCommon.staticSvg(stash + "Size" + (large ? "2" : "1"), options); + base = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: base, + shift: 0 + }, { + type: "elem", + elem: oval, + shift: large ? 0.08 : 0 + }] + }, options); + group.name = "\\" + stash; + base.classes.unshift("mop"); // $FlowFixMe + + base.italic = italic; + } + } else if (group.body) { + // If this is a list, compose that list. + const inner = buildExpression(group.body, options, true); + + if (inner.length === 1 && inner[0] instanceof SymbolNode) { + base = inner[0]; + base.classes[0] = "mop"; // replace old mclass + } else { + base = buildCommon.makeSpan(["mop"], inner, options); + } + } else { + // Otherwise, this is a text operator. Build the text from the + // operator's name. + const output = []; + + for (let i = 1; i < group.name.length; i++) { + output.push(buildCommon.mathsym(group.name[i], group.mode, options)); + } + + base = buildCommon.makeSpan(["mop"], output, options); + } // If content of op is a single symbol, shift it vertically. + + + let baseShift = 0; + let slant = 0; + + if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) { + // We suppress the shift of the base of \overset and \underset. Otherwise, + // shift the symbol so its center lies on the axis (rule 13). It + // appears that our fonts have the centers of the symbols already + // almost on the axis, so these numbers are very small. Note we + // don't actually apply this here, but instead it is used either in + // the vlist creation or separately when there are no limits. + baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight; // The slant of the symbol is just its italic correction. + // $FlowFixMe + + slant = base.italic; + } + + if (hasLimits) { + return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift); + } else { + if (baseShift) { + base.style.position = "relative"; + base.style.top = makeEm(baseShift); + } + + return base; + } +}; + +const op_mathmlBuilder = (group, options) => { + let node; + + if (group.symbol) { + // This is a symbol. Just add the symbol. + node = new MathNode("mo", [makeText(group.name, group.mode)]); + + if (utils.contains(noSuccessor, group.name)) { + node.setAttribute("largeop", "false"); + } + } else if (group.body) { + // This is an operator with children. Add them. + node = new MathNode("mo", buildMathML_buildExpression(group.body, options)); + } else { + // This is a text operator. Add all of the characters from the + // operator's name. + node = new MathNode("mi", [new TextNode(group.name.slice(1))]); // Append an . + // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 + + const operator = new MathNode("mo", [makeText("\u2061", "text")]); + + if (group.parentIsSupSub) { + node = new MathNode("mrow", [node, operator]); + } else { + node = newDocumentFragment([node, operator]); + } + } + + return node; +}; + +const singleCharBigOps = { + "\u220F": "\\prod", + "\u2210": "\\coprod", + "\u2211": "\\sum", + "\u22c0": "\\bigwedge", + "\u22c1": "\\bigvee", + "\u22c2": "\\bigcap", + "\u22c3": "\\bigcup", + "\u2a00": "\\bigodot", + "\u2a01": "\\bigoplus", + "\u2a02": "\\bigotimes", + "\u2a04": "\\biguplus", + "\u2a06": "\\bigsqcup" +}; +defineFunction({ + type: "op", + names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220F", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"], + props: { + numArgs: 0 + }, + handler: (_ref, args) => { + let { + parser, + funcName + } = _ref; + let fName = funcName; + + if (fName.length === 1) { + fName = singleCharBigOps[fName]; + } + + return { + type: "op", + mode: parser.mode, + limits: true, + parentIsSupSub: false, + symbol: true, + name: fName + }; + }, + htmlBuilder: op_htmlBuilder, + mathmlBuilder: op_mathmlBuilder +}); // Note: calling defineFunction with a type that's already been defined only +// works because the same htmlBuilder and mathmlBuilder are being used. + +defineFunction({ + type: "op", + names: ["\\mathop"], + props: { + numArgs: 1, + primitive: true + }, + handler: (_ref2, args) => { + let { + parser + } = _ref2; + const body = args[0]; + return { + type: "op", + mode: parser.mode, + limits: false, + parentIsSupSub: false, + symbol: false, + body: ordargument(body) + }; + }, + htmlBuilder: op_htmlBuilder, + mathmlBuilder: op_mathmlBuilder +}); // There are 2 flags for operators; whether they produce limits in +// displaystyle, and whether they are symbols and should grow in +// displaystyle. These four groups cover the four possible choices. + +const singleCharIntegrals = { + "\u222b": "\\int", + "\u222c": "\\iint", + "\u222d": "\\iiint", + "\u222e": "\\oint", + "\u222f": "\\oiint", + "\u2230": "\\oiiint" +}; // No limits, not symbols + +defineFunction({ + type: "op", + names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"], + props: { + numArgs: 0 + }, + + handler(_ref3) { + let { + parser, + funcName + } = _ref3; + return { + type: "op", + mode: parser.mode, + limits: false, + parentIsSupSub: false, + symbol: false, + name: funcName + }; + }, + + htmlBuilder: op_htmlBuilder, + mathmlBuilder: op_mathmlBuilder +}); // Limits, not symbols + +defineFunction({ + type: "op", + names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], + props: { + numArgs: 0 + }, + + handler(_ref4) { + let { + parser, + funcName + } = _ref4; + return { + type: "op", + mode: parser.mode, + limits: true, + parentIsSupSub: false, + symbol: false, + name: funcName + }; + }, + + htmlBuilder: op_htmlBuilder, + mathmlBuilder: op_mathmlBuilder +}); // No limits, symbols + +defineFunction({ + type: "op", + names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"], + props: { + numArgs: 0 + }, + + handler(_ref5) { + let { + parser, + funcName + } = _ref5; + let fName = funcName; + + if (fName.length === 1) { + fName = singleCharIntegrals[fName]; + } + + return { + type: "op", + mode: parser.mode, + limits: false, + parentIsSupSub: false, + symbol: true, + name: fName + }; + }, + + htmlBuilder: op_htmlBuilder, + mathmlBuilder: op_mathmlBuilder +}); +;// CONCATENATED MODULE: ./src/functions/operatorname.js + + + + + + + + + +// NOTE: Unlike most `htmlBuilder`s, this one handles not only +// "operatorname", but also "supsub" since \operatorname* can +// affect super/subscripting. +const operatorname_htmlBuilder = (grp, options) => { + // Operators are handled in the TeXbook pg. 443-444, rule 13(a). + let supGroup; + let subGroup; + let hasLimits = false; + let group; + + if (grp.type === "supsub") { + // If we have limits, supsub will pass us its group to handle. Pull + // out the superscript and subscript and set the group to the op in + // its base. + supGroup = grp.sup; + subGroup = grp.sub; + group = assertNodeType(grp.base, "operatorname"); + hasLimits = true; + } else { + group = assertNodeType(grp, "operatorname"); + } + + let base; + + if (group.body.length > 0) { + const body = group.body.map(child => { + // $FlowFixMe: Check if the node has a string `text` property. + const childText = child.text; + + if (typeof childText === "string") { + return { + type: "textord", + mode: child.mode, + text: childText + }; + } else { + return child; + } + }); // Consolidate function names into symbol characters. + + const expression = buildExpression(body, options.withFont("mathrm"), true); + + for (let i = 0; i < expression.length; i++) { + const child = expression[i]; + + if (child instanceof SymbolNode) { + // Per amsopn package, + // change minus to hyphen and \ast to asterisk + child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); + } + } + + base = buildCommon.makeSpan(["mop"], expression, options); + } else { + base = buildCommon.makeSpan(["mop"], [], options); + } + + if (hasLimits) { + return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0); + } else { + return base; + } +}; + +const operatorname_mathmlBuilder = (group, options) => { + // The steps taken here are similar to the html version. + let expression = buildMathML_buildExpression(group.body, options.withFont("mathrm")); // Is expression a string or has it something like a fraction? + + let isAllString = true; // default + + for (let i = 0; i < expression.length; i++) { + const node = expression[i]; + + if (node instanceof mathMLTree.SpaceNode) {// Do nothing + } else if (node instanceof mathMLTree.MathNode) { + switch (node.type) { + case "mi": + case "mn": + case "ms": + case "mspace": + case "mtext": + break; + // Do nothing yet. + + case "mo": + { + const child = node.children[0]; + + if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { + child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); + } else { + isAllString = false; + } + + break; + } + + default: + isAllString = false; + } + } else { + isAllString = false; + } + } + + if (isAllString) { + // Write a single TextNode instead of multiple nested tags. + const word = expression.map(node => node.toText()).join(""); + expression = [new mathMLTree.TextNode(word)]; + } + + const identifier = new mathMLTree.MathNode("mi", expression); + identifier.setAttribute("mathvariant", "normal"); // \u2061 is the same as ⁡ + // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp + + const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); + + if (group.parentIsSupSub) { + return new mathMLTree.MathNode("mrow", [identifier, operator]); + } else { + return mathMLTree.newDocumentFragment([identifier, operator]); + } +}; // \operatorname +// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ + + +defineFunction({ + type: "operatorname", + names: ["\\operatorname@", "\\operatornamewithlimits"], + props: { + numArgs: 1 + }, + handler: (_ref, args) => { + let { + parser, + funcName + } = _ref; + const body = args[0]; + return { + type: "operatorname", + mode: parser.mode, + body: ordargument(body), + alwaysHandleSupSub: funcName === "\\operatornamewithlimits", + limits: false, + parentIsSupSub: false + }; + }, + htmlBuilder: operatorname_htmlBuilder, + mathmlBuilder: operatorname_mathmlBuilder +}); +defineMacro("\\operatorname", "\\@ifstar\\operatornamewithlimits\\operatorname@"); +;// CONCATENATED MODULE: ./src/functions/ordgroup.js + + + + +defineFunctionBuilders({ + type: "ordgroup", + + htmlBuilder(group, options) { + if (group.semisimple) { + return buildCommon.makeFragment(buildExpression(group.body, options, false)); + } + + return buildCommon.makeSpan(["mord"], buildExpression(group.body, options, true), options); + }, + + mathmlBuilder(group, options) { + return buildExpressionRow(group.body, options, true); + } + +}); +;// CONCATENATED MODULE: ./src/functions/overline.js + + + + + +defineFunction({ + type: "overline", + names: ["\\overline"], + props: { + numArgs: 1 + }, + + handler(_ref, args) { + let { + parser + } = _ref; + const body = args[0]; + return { + type: "overline", + mode: parser.mode, + body + }; + }, + + htmlBuilder(group, options) { + // Overlines are handled in the TeXbook pg 443, Rule 9. + // Build the inner group in the cramped style. + const innerGroup = buildGroup(group.body, options.havingCrampedStyle()); // Create the line above the body + + const line = buildCommon.makeLineSpan("overline-line", options); // Generate the vlist, with the appropriate kerns + + const defaultRuleThickness = options.fontMetrics().defaultRuleThickness; + const vlist = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: innerGroup + }, { + type: "kern", + size: 3 * defaultRuleThickness + }, { + type: "elem", + elem: line + }, { + type: "kern", + size: defaultRuleThickness + }] + }, options); + return buildCommon.makeSpan(["mord", "overline"], [vlist], options); + }, + + mathmlBuilder(group, options) { + const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]); + operator.setAttribute("stretchy", "true"); + const node = new mathMLTree.MathNode("mover", [buildMathML_buildGroup(group.body, options), operator]); + node.setAttribute("accent", "true"); + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/phantom.js + + + + + +defineFunction({ + type: "phantom", + names: ["\\phantom"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref, args) => { + let { + parser + } = _ref; + const body = args[0]; + return { + type: "phantom", + mode: parser.mode, + body: ordargument(body) + }; + }, + htmlBuilder: (group, options) => { + const elements = buildExpression(group.body, options.withPhantom(), false); // \phantom isn't supposed to affect the elements it contains. + // See "color" for more details. + + return buildCommon.makeFragment(elements); + }, + mathmlBuilder: (group, options) => { + const inner = buildMathML_buildExpression(group.body, options); + return new mathMLTree.MathNode("mphantom", inner); + } +}); +defineFunction({ + type: "hphantom", + names: ["\\hphantom"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref2, args) => { + let { + parser + } = _ref2; + const body = args[0]; + return { + type: "hphantom", + mode: parser.mode, + body + }; + }, + htmlBuilder: (group, options) => { + let node = buildCommon.makeSpan([], [buildGroup(group.body, options.withPhantom())]); + node.height = 0; + node.depth = 0; + + if (node.children) { + for (let i = 0; i < node.children.length; i++) { + node.children[i].height = 0; + node.children[i].depth = 0; + } + } // See smash for comment re: use of makeVList + + + node = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: node + }] + }, options); // For spacing, TeX treats \smash as a math group (same spacing as ord). + + return buildCommon.makeSpan(["mord"], [node], options); + }, + mathmlBuilder: (group, options) => { + const inner = buildMathML_buildExpression(ordargument(group.body), options); + const phantom = new mathMLTree.MathNode("mphantom", inner); + const node = new mathMLTree.MathNode("mpadded", [phantom]); + node.setAttribute("height", "0px"); + node.setAttribute("depth", "0px"); + return node; + } +}); +defineFunction({ + type: "vphantom", + names: ["\\vphantom"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref3, args) => { + let { + parser + } = _ref3; + const body = args[0]; + return { + type: "vphantom", + mode: parser.mode, + body + }; + }, + htmlBuilder: (group, options) => { + const inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options.withPhantom())]); + const fix = buildCommon.makeSpan(["fix"], []); + return buildCommon.makeSpan(["mord", "rlap"], [inner, fix], options); + }, + mathmlBuilder: (group, options) => { + const inner = buildMathML_buildExpression(ordargument(group.body), options); + const phantom = new mathMLTree.MathNode("mphantom", inner); + const node = new mathMLTree.MathNode("mpadded", [phantom]); + node.setAttribute("width", "0px"); + return node; + } +}); +;// CONCATENATED MODULE: ./src/functions/raisebox.js + + + + + + + // Box manipulation + +defineFunction({ + type: "raisebox", + names: ["\\raisebox"], + props: { + numArgs: 2, + argTypes: ["size", "hbox"], + allowedInText: true + }, + + handler(_ref, args) { + let { + parser + } = _ref; + const amount = assertNodeType(args[0], "size").value; + const body = args[1]; + return { + type: "raisebox", + mode: parser.mode, + dy: amount, + body + }; + }, + + htmlBuilder(group, options) { + const body = buildGroup(group.body, options); + const dy = calculateSize(group.dy, options); + return buildCommon.makeVList({ + positionType: "shift", + positionData: -dy, + children: [{ + type: "elem", + elem: body + }] + }, options); + }, + + mathmlBuilder(group, options) { + const node = new mathMLTree.MathNode("mpadded", [buildMathML_buildGroup(group.body, options)]); + const dy = group.dy.number + group.dy.unit; + node.setAttribute("voffset", dy); + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/relax.js + +defineFunction({ + type: "internal", + names: ["\\relax"], + props: { + numArgs: 0, + allowedInText: true, + allowedInArgument: true + }, + + handler(_ref) { + let { + parser + } = _ref; + return { + type: "internal", + mode: parser.mode + }; + } + +}); +;// CONCATENATED MODULE: ./src/functions/rule.js + + + + + +defineFunction({ + type: "rule", + names: ["\\rule"], + props: { + numArgs: 2, + numOptionalArgs: 1, + allowedInText: true, + allowedInMath: true, + argTypes: ["size", "size", "size"] + }, + + handler(_ref, args, optArgs) { + let { + parser + } = _ref; + const shift = optArgs[0]; + const width = assertNodeType(args[0], "size"); + const height = assertNodeType(args[1], "size"); + return { + type: "rule", + mode: parser.mode, + shift: shift && assertNodeType(shift, "size").value, + width: width.value, + height: height.value + }; + }, + + htmlBuilder(group, options) { + // Make an empty span for the rule + const rule = buildCommon.makeSpan(["mord", "rule"], [], options); // Calculate the shift, width, and height of the rule, and account for units + + const width = calculateSize(group.width, options); + const height = calculateSize(group.height, options); + const shift = group.shift ? calculateSize(group.shift, options) : 0; // Style the rule to the right size + + rule.style.borderRightWidth = makeEm(width); + rule.style.borderTopWidth = makeEm(height); + rule.style.bottom = makeEm(shift); // Record the height and width + + rule.width = width; + rule.height = height + shift; + rule.depth = -shift; // Font size is the number large enough that the browser will + // reserve at least `absHeight` space above the baseline. + // The 1.125 factor was empirically determined + + rule.maxFontSize = height * 1.125 * options.sizeMultiplier; + return rule; + }, + + mathmlBuilder(group, options) { + const width = calculateSize(group.width, options); + const height = calculateSize(group.height, options); + const shift = group.shift ? calculateSize(group.shift, options) : 0; + const color = options.color && options.getColor() || "black"; + const rule = new mathMLTree.MathNode("mspace"); + rule.setAttribute("mathbackground", color); + rule.setAttribute("width", makeEm(width)); + rule.setAttribute("height", makeEm(height)); + const wrapper = new mathMLTree.MathNode("mpadded", [rule]); + + if (shift >= 0) { + wrapper.setAttribute("height", makeEm(shift)); + } else { + wrapper.setAttribute("height", makeEm(shift)); + wrapper.setAttribute("depth", makeEm(-shift)); + } + + wrapper.setAttribute("voffset", makeEm(shift)); + return wrapper; + } + +}); +;// CONCATENATED MODULE: ./src/functions/sizing.js + + + + + + +function sizingGroup(value, options, baseOptions) { + const inner = buildExpression(value, options, false); + const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize + // manually. Handle nested size changes. + + for (let i = 0; i < inner.length; i++) { + const pos = inner[i].classes.indexOf("sizing"); + + if (pos < 0) { + Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions)); + } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) { + // This is a nested size change: e.g., inner[i] is the "b" in + // `\Huge a \small b`. Override the old size (the `reset-` class) + // but not the new size. + inner[i].classes[pos + 1] = "reset-size" + baseOptions.size; + } + + inner[i].height *= multiplier; + inner[i].depth *= multiplier; + } + + return buildCommon.makeFragment(inner); +} +const sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"]; +const sizing_htmlBuilder = (group, options) => { + // Handle sizing operators like \Huge. Real TeX doesn't actually allow + // these functions inside of math expressions, so we do some special + // handling. + const newOptions = options.havingSize(group.size); + return sizingGroup(group.body, newOptions, options); +}; +defineFunction({ + type: "sizing", + names: sizeFuncs, + props: { + numArgs: 0, + allowedInText: true + }, + handler: (_ref, args) => { + let { + breakOnTokenText, + funcName, + parser + } = _ref; + const body = parser.parseExpression(false, breakOnTokenText); + return { + type: "sizing", + mode: parser.mode, + // Figure out what size to use based on the list of functions above + size: sizeFuncs.indexOf(funcName) + 1, + body + }; + }, + htmlBuilder: sizing_htmlBuilder, + mathmlBuilder: (group, options) => { + const newOptions = options.havingSize(group.size); + const inner = buildMathML_buildExpression(group.body, newOptions); + const node = new mathMLTree.MathNode("mstyle", inner); // TODO(emily): This doesn't produce the correct size for nested size + // changes, because we don't keep state of what style we're currently + // in, so we can't reset the size to normal before changing it. Now + // that we're passing an options parameter we should be able to fix + // this. + + node.setAttribute("mathsize", makeEm(newOptions.sizeMultiplier)); + return node; + } +}); +;// CONCATENATED MODULE: ./src/functions/smash.js +// smash, with optional [tb], as in AMS + + + + + + +defineFunction({ + type: "smash", + names: ["\\smash"], + props: { + numArgs: 1, + numOptionalArgs: 1, + allowedInText: true + }, + handler: (_ref, args, optArgs) => { + let { + parser + } = _ref; + let smashHeight = false; + let smashDepth = false; + const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); + + if (tbArg) { + // Optional [tb] argument is engaged. + // ref: amsmath: \renewcommand{\smash}[1][tb]{% + // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% + let letter = ""; + + for (let i = 0; i < tbArg.body.length; ++i) { + const node = tbArg.body[i]; // $FlowFixMe: Not every node type has a `text` property. + + letter = node.text; + + if (letter === "t") { + smashHeight = true; + } else if (letter === "b") { + smashDepth = true; + } else { + smashHeight = false; + smashDepth = false; + break; + } + } + } else { + smashHeight = true; + smashDepth = true; + } + + const body = args[0]; + return { + type: "smash", + mode: parser.mode, + body, + smashHeight, + smashDepth + }; + }, + htmlBuilder: (group, options) => { + const node = buildCommon.makeSpan([], [buildGroup(group.body, options)]); + + if (!group.smashHeight && !group.smashDepth) { + return node; + } + + if (group.smashHeight) { + node.height = 0; // In order to influence makeVList, we have to reset the children. + + if (node.children) { + for (let i = 0; i < node.children.length; i++) { + node.children[i].height = 0; + } + } + } + + if (group.smashDepth) { + node.depth = 0; + + if (node.children) { + for (let i = 0; i < node.children.length; i++) { + node.children[i].depth = 0; + } + } + } // At this point, we've reset the TeX-like height and depth values. + // But the span still has an HTML line height. + // makeVList applies "display: table-cell", which prevents the browser + // from acting on that line height. So we'll call makeVList now. + + + const smashedNode = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: node + }] + }, options); // For spacing, TeX treats \hphantom as a math group (same spacing as ord). + + return buildCommon.makeSpan(["mord"], [smashedNode], options); + }, + mathmlBuilder: (group, options) => { + const node = new mathMLTree.MathNode("mpadded", [buildMathML_buildGroup(group.body, options)]); + + if (group.smashHeight) { + node.setAttribute("height", "0px"); + } + + if (group.smashDepth) { + node.setAttribute("depth", "0px"); + } + + return node; + } +}); +;// CONCATENATED MODULE: ./src/functions/sqrt.js + + + + + + + + +defineFunction({ + type: "sqrt", + names: ["\\sqrt"], + props: { + numArgs: 1, + numOptionalArgs: 1 + }, + + handler(_ref, args, optArgs) { + let { + parser + } = _ref; + const index = optArgs[0]; + const body = args[0]; + return { + type: "sqrt", + mode: parser.mode, + body, + index + }; + }, + + htmlBuilder(group, options) { + // Square roots are handled in the TeXbook pg. 443, Rule 11. + // First, we do the same steps as in overline to build the inner group + // and line + let inner = buildGroup(group.body, options.havingCrampedStyle()); + + if (inner.height === 0) { + // Render a small surd. + inner.height = options.fontMetrics().xHeight; + } // Some groups can return document fragments. Handle those by wrapping + // them in a span. + + + inner = buildCommon.wrapFragment(inner, options); // Calculate the minimum size for the \surd delimiter + + const metrics = options.fontMetrics(); + const theta = metrics.defaultRuleThickness; + let phi = theta; + + if (options.style.id < src_Style.TEXT.id) { + phi = options.fontMetrics().xHeight; + } // Calculate the clearance between the body and line + + + let lineClearance = theta + phi / 4; + const minDelimiterHeight = inner.height + inner.depth + lineClearance + theta; // Create a sqrt SVG of the required minimum size + + const { + span: img, + ruleWidth, + advanceWidth + } = delimiter.sqrtImage(minDelimiterHeight, options); + const delimDepth = img.height - ruleWidth; // Adjust the clearance based on the delimiter size + + if (delimDepth > inner.height + inner.depth + lineClearance) { + lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2; + } // Shift the sqrt image + + + const imgShift = img.height - inner.height - lineClearance - ruleWidth; + inner.style.paddingLeft = makeEm(advanceWidth); // Overlay the image and the argument. + + const body = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: inner, + wrapperClasses: ["svg-align"] + }, { + type: "kern", + size: -(inner.height + imgShift) + }, { + type: "elem", + elem: img + }, { + type: "kern", + size: ruleWidth + }] + }, options); + + if (!group.index) { + return buildCommon.makeSpan(["mord", "sqrt"], [body], options); + } else { + // Handle the optional root index + // The index is always in scriptscript style + const newOptions = options.havingStyle(src_Style.SCRIPTSCRIPT); + const rootm = buildGroup(group.index, newOptions, options); // The amount the index is shifted by. This is taken from the TeX + // source, in the definition of `\r@@t`. + + const toShift = 0.6 * (body.height - body.depth); // Build a VList with the superscript shifted up correctly + + const rootVList = buildCommon.makeVList({ + positionType: "shift", + positionData: -toShift, + children: [{ + type: "elem", + elem: rootm + }] + }, options); // Add a class surrounding it so we can add on the appropriate + // kerning + + const rootVListWrap = buildCommon.makeSpan(["root"], [rootVList]); + return buildCommon.makeSpan(["mord", "sqrt"], [rootVListWrap, body], options); + } + }, + + mathmlBuilder(group, options) { + const { + body, + index + } = group; + return index ? new mathMLTree.MathNode("mroot", [buildMathML_buildGroup(body, options), buildMathML_buildGroup(index, options)]) : new mathMLTree.MathNode("msqrt", [buildMathML_buildGroup(body, options)]); + } + +}); +;// CONCATENATED MODULE: ./src/functions/styling.js + + + + + +const styling_styleMap = { + "display": src_Style.DISPLAY, + "text": src_Style.TEXT, + "script": src_Style.SCRIPT, + "scriptscript": src_Style.SCRIPTSCRIPT +}; +defineFunction({ + type: "styling", + names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref, args) { + let { + breakOnTokenText, + funcName, + parser + } = _ref; + // parse out the implicit body + const body = parser.parseExpression(true, breakOnTokenText); // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g. + // here and in buildHTML and de-dupe the enumeration of all the styles). + // $FlowFixMe: The names above exactly match the styles. + + const style = funcName.slice(1, funcName.length - 5); + return { + type: "styling", + mode: parser.mode, + // Figure out what style to use by pulling out the style from + // the function name + style, + body + }; + }, + + htmlBuilder(group, options) { + // Style changes are handled in the TeXbook on pg. 442, Rule 3. + const newStyle = styling_styleMap[group.style]; + const newOptions = options.havingStyle(newStyle).withFont(''); + return sizingGroup(group.body, newOptions, options); + }, + + mathmlBuilder(group, options) { + // Figure out what style we're changing to. + const newStyle = styling_styleMap[group.style]; + const newOptions = options.havingStyle(newStyle); + const inner = buildMathML_buildExpression(group.body, newOptions); + const node = new mathMLTree.MathNode("mstyle", inner); + const styleAttributes = { + "display": ["0", "true"], + "text": ["0", "false"], + "script": ["1", "false"], + "scriptscript": ["2", "false"] + }; + const attr = styleAttributes[group.style]; + node.setAttribute("scriptlevel", attr[0]); + node.setAttribute("displaystyle", attr[1]); + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/supsub.js + + + + + + + + + + + + + + +/** + * Sometimes, groups perform special rules when they have superscripts or + * subscripts attached to them. This function lets the `supsub` group know that + * Sometimes, groups perform special rules when they have superscripts or + * its inner element should handle the superscripts and subscripts instead of + * handling them itself. + */ +const htmlBuilderDelegate = function (group, options) { + const base = group.base; + + if (!base) { + return null; + } else if (base.type === "op") { + // Operators handle supsubs differently when they have limits + // (e.g. `\displaystyle\sum_2^3`) + const delegate = base.limits && (options.style.size === src_Style.DISPLAY.size || base.alwaysHandleSupSub); + return delegate ? op_htmlBuilder : null; + } else if (base.type === "operatorname") { + const delegate = base.alwaysHandleSupSub && (options.style.size === src_Style.DISPLAY.size || base.limits); + return delegate ? operatorname_htmlBuilder : null; + } else if (base.type === "accent") { + return utils.isCharacterBox(base.base) ? htmlBuilder : null; + } else if (base.type === "horizBrace") { + const isSup = !group.sub; + return isSup === base.isOver ? horizBrace_htmlBuilder : null; + } else { + return null; + } +}; // Super scripts and subscripts, whose precise placement can depend on other +// functions that precede them. + + +defineFunctionBuilders({ + type: "supsub", + + htmlBuilder(group, options) { + // Superscript and subscripts are handled in the TeXbook on page + // 445-446, rules 18(a-f). + // Here is where we defer to the inner group if it should handle + // superscripts and subscripts itself. + const builderDelegate = htmlBuilderDelegate(group, options); + + if (builderDelegate) { + return builderDelegate(group, options); + } + + const { + base: valueBase, + sup: valueSup, + sub: valueSub + } = group; + const base = buildGroup(valueBase, options); + let supm; + let subm; + const metrics = options.fontMetrics(); // Rule 18a + + let supShift = 0; + let subShift = 0; + const isCharacterBox = valueBase && utils.isCharacterBox(valueBase); + + if (valueSup) { + const newOptions = options.havingStyle(options.style.sup()); + supm = buildGroup(valueSup, newOptions, options); + + if (!isCharacterBox) { + supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier; + } + } + + if (valueSub) { + const newOptions = options.havingStyle(options.style.sub()); + subm = buildGroup(valueSub, newOptions, options); + + if (!isCharacterBox) { + subShift = base.depth + newOptions.fontMetrics().subDrop * newOptions.sizeMultiplier / options.sizeMultiplier; + } + } // Rule 18c + + + let minSupShift; + + if (options.style === src_Style.DISPLAY) { + minSupShift = metrics.sup1; + } else if (options.style.cramped) { + minSupShift = metrics.sup3; + } else { + minSupShift = metrics.sup2; + } // scriptspace is a font-size-independent size, so scale it + // appropriately for use as the marginRight. + + + const multiplier = options.sizeMultiplier; + const marginRight = makeEm(0.5 / metrics.ptPerEm / multiplier); + let marginLeft = null; + + if (subm) { + // Subscripts shouldn't be shifted by the base's italic correction. + // Account for that by shifting the subscript back the appropriate + // amount. Note we only do this when the base is a single symbol. + const isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint"); + + if (base instanceof SymbolNode || isOiint) { + // $FlowFixMe + marginLeft = makeEm(-base.italic); + } + } + + let supsub; + + if (supm && subm) { + supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight); + subShift = Math.max(subShift, metrics.sub2); + const ruleWidth = metrics.defaultRuleThickness; // Rule 18e + + const maxWidth = 4 * ruleWidth; + + if (supShift - supm.depth - (subm.height - subShift) < maxWidth) { + subShift = maxWidth - (supShift - supm.depth) + subm.height; + const psi = 0.8 * metrics.xHeight - (supShift - supm.depth); + + if (psi > 0) { + supShift += psi; + subShift -= psi; + } + } + + const vlistElem = [{ + type: "elem", + elem: subm, + shift: subShift, + marginRight, + marginLeft + }, { + type: "elem", + elem: supm, + shift: -supShift, + marginRight + }]; + supsub = buildCommon.makeVList({ + positionType: "individualShift", + children: vlistElem + }, options); + } else if (subm) { + // Rule 18b + subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight); + const vlistElem = [{ + type: "elem", + elem: subm, + marginLeft, + marginRight + }]; + supsub = buildCommon.makeVList({ + positionType: "shift", + positionData: subShift, + children: vlistElem + }, options); + } else if (supm) { + // Rule 18c, d + supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight); + supsub = buildCommon.makeVList({ + positionType: "shift", + positionData: -supShift, + children: [{ + type: "elem", + elem: supm, + marginRight + }] + }, options); + } else { + throw new Error("supsub must have either sup or sub."); + } // Wrap the supsub vlist in a span.msupsub to reset text-align. + + + const mclass = getTypeOfDomTree(base, "right") || "mord"; + return buildCommon.makeSpan([mclass], [base, buildCommon.makeSpan(["msupsub"], [supsub])], options); + }, + + mathmlBuilder(group, options) { + // Is the inner group a relevant horizontal brace? + let isBrace = false; + let isOver; + let isSup; + + if (group.base && group.base.type === "horizBrace") { + isSup = !!group.sup; + + if (isSup === group.base.isOver) { + isBrace = true; + isOver = group.base.isOver; + } + } + + if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) { + group.base.parentIsSupSub = true; + } + + const children = [buildMathML_buildGroup(group.base, options)]; + + if (group.sub) { + children.push(buildMathML_buildGroup(group.sub, options)); + } + + if (group.sup) { + children.push(buildMathML_buildGroup(group.sup, options)); + } + + let nodeType; + + if (isBrace) { + nodeType = isOver ? "mover" : "munder"; + } else if (!group.sub) { + const base = group.base; + + if (base && base.type === "op" && base.limits && (options.style === src_Style.DISPLAY || base.alwaysHandleSupSub)) { + nodeType = "mover"; + } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === src_Style.DISPLAY)) { + nodeType = "mover"; + } else { + nodeType = "msup"; + } + } else if (!group.sup) { + const base = group.base; + + if (base && base.type === "op" && base.limits && (options.style === src_Style.DISPLAY || base.alwaysHandleSupSub)) { + nodeType = "munder"; + } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === src_Style.DISPLAY)) { + nodeType = "munder"; + } else { + nodeType = "msub"; + } + } else { + const base = group.base; + + if (base && base.type === "op" && base.limits && options.style === src_Style.DISPLAY) { + nodeType = "munderover"; + } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (options.style === src_Style.DISPLAY || base.limits)) { + nodeType = "munderover"; + } else { + nodeType = "msubsup"; + } + } + + return new mathMLTree.MathNode(nodeType, children); + } + +}); +;// CONCATENATED MODULE: ./src/functions/symbolsOp.js + + + + // Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js. + +defineFunctionBuilders({ + type: "atom", + + htmlBuilder(group, options) { + return buildCommon.mathsym(group.text, group.mode, options, ["m" + group.family]); + }, + + mathmlBuilder(group, options) { + const node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); + + if (group.family === "bin") { + const variant = getVariant(group, options); + + if (variant === "bold-italic") { + node.setAttribute("mathvariant", variant); + } + } else if (group.family === "punct") { + node.setAttribute("separator", "true"); + } else if (group.family === "open" || group.family === "close") { + // Delims built here should not stretch vertically. + // See delimsizing.js for stretchy delims. + node.setAttribute("stretchy", "false"); + } + + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/symbolsOrd.js + + + + +// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in +// src/symbols.js. +const defaultVariant = { + "mi": "italic", + "mn": "normal", + "mtext": "normal" +}; +defineFunctionBuilders({ + type: "mathord", + + htmlBuilder(group, options) { + return buildCommon.makeOrd(group, options, "mathord"); + }, + + mathmlBuilder(group, options) { + const node = new mathMLTree.MathNode("mi", [makeText(group.text, group.mode, options)]); + const variant = getVariant(group, options) || "italic"; + + if (variant !== defaultVariant[node.type]) { + node.setAttribute("mathvariant", variant); + } + + return node; + } + +}); +defineFunctionBuilders({ + type: "textord", + + htmlBuilder(group, options) { + return buildCommon.makeOrd(group, options, "textord"); + }, + + mathmlBuilder(group, options) { + const text = makeText(group.text, group.mode, options); + const variant = getVariant(group, options) || "normal"; + let node; + + if (group.mode === 'text') { + node = new mathMLTree.MathNode("mtext", [text]); + } else if (/[0-9]/.test(group.text)) { + node = new mathMLTree.MathNode("mn", [text]); + } else if (group.text === "\\prime") { + node = new mathMLTree.MathNode("mo", [text]); + } else { + node = new mathMLTree.MathNode("mi", [text]); + } + + if (variant !== defaultVariant[node.type]) { + node.setAttribute("mathvariant", variant); + } + + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/symbolsSpacing.js + + + + // A map of CSS-based spacing functions to their CSS class. + +const cssSpace = { + "\\nobreak": "nobreak", + "\\allowbreak": "allowbreak" +}; // A lookup table to determine whether a spacing function/symbol should be +// treated like a regular space character. If a symbol or command is a key +// in this table, then it should be a regular space character. Furthermore, +// the associated value may have a `className` specifying an extra CSS class +// to add to the created `span`. + +const regularSpace = { + " ": {}, + "\\ ": {}, + "~": { + className: "nobreak" + }, + "\\space": {}, + "\\nobreakspace": { + className: "nobreak" + } +}; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in +// src/symbols.js. + +defineFunctionBuilders({ + type: "spacing", + + htmlBuilder(group, options) { + if (regularSpace.hasOwnProperty(group.text)) { + const className = regularSpace[group.text].className || ""; // Spaces are generated by adding an actual space. Each of these + // things has an entry in the symbols table, so these will be turned + // into appropriate outputs. + + if (group.mode === "text") { + const ord = buildCommon.makeOrd(group, options, "textord"); + ord.classes.push(className); + return ord; + } else { + return buildCommon.makeSpan(["mspace", className], [buildCommon.mathsym(group.text, group.mode, options)], options); + } + } else if (cssSpace.hasOwnProperty(group.text)) { + // Spaces based on just a CSS class. + return buildCommon.makeSpan(["mspace", cssSpace[group.text]], [], options); + } else { + throw new src_ParseError("Unknown type of space \"" + group.text + "\""); + } + }, + + mathmlBuilder(group, options) { + let node; + + if (regularSpace.hasOwnProperty(group.text)) { + node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); + } else if (cssSpace.hasOwnProperty(group.text)) { + // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored + return new mathMLTree.MathNode("mspace"); + } else { + throw new src_ParseError("Unknown type of space \"" + group.text + "\""); + } + + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/tag.js + + + + +const pad = () => { + const padNode = new mathMLTree.MathNode("mtd", []); + padNode.setAttribute("width", "50%"); + return padNode; +}; + +defineFunctionBuilders({ + type: "tag", + + mathmlBuilder(group, options) { + const table = new mathMLTree.MathNode("mtable", [new mathMLTree.MathNode("mtr", [pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.body, options)]), pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.tag, options)])])]); + table.setAttribute("width", "100%"); + return table; // TODO: Left-aligned tags. + // Currently, the group and options passed here do not contain + // enough info to set tag alignment. `leqno` is in Settings but it is + // not passed to Options. On the HTML side, leqno is + // set by a CSS class applied in buildTree.js. That would have worked + // in MathML if browsers supported . Since they don't, we + // need to rewrite the way this function is called. + } + +}); +;// CONCATENATED MODULE: ./src/functions/text.js + + + + // Non-mathy text, possibly in a font + +const textFontFamilies = { + "\\text": undefined, + "\\textrm": "textrm", + "\\textsf": "textsf", + "\\texttt": "texttt", + "\\textnormal": "textrm" +}; +const textFontWeights = { + "\\textbf": "textbf", + "\\textmd": "textmd" +}; +const textFontShapes = { + "\\textit": "textit", + "\\textup": "textup" +}; + +const optionsWithFont = (group, options) => { + const font = group.font; // Checks if the argument is a font family or a font style. + + if (!font) { + return options; + } else if (textFontFamilies[font]) { + return options.withTextFontFamily(textFontFamilies[font]); + } else if (textFontWeights[font]) { + return options.withTextFontWeight(textFontWeights[font]); + } else if (font === "\\emph") { + return options.fontShape === "textit" ? options.withTextFontShape("textup") : options.withTextFontShape("textit"); + } + + return options.withTextFontShape(textFontShapes[font]); +}; + +defineFunction({ + type: "text", + names: [// Font families + "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", // Font weights + "\\textbf", "\\textmd", // Font Shapes + "\\textit", "\\textup", "\\emph"], + props: { + numArgs: 1, + argTypes: ["text"], + allowedInArgument: true, + allowedInText: true + }, + + handler(_ref, args) { + let { + parser, + funcName + } = _ref; + const body = args[0]; + return { + type: "text", + mode: parser.mode, + body: ordargument(body), + font: funcName + }; + }, + + htmlBuilder(group, options) { + const newOptions = optionsWithFont(group, options); + const inner = buildExpression(group.body, newOptions, true); + return buildCommon.makeSpan(["mord", "text"], inner, newOptions); + }, + + mathmlBuilder(group, options) { + const newOptions = optionsWithFont(group, options); + return buildExpressionRow(group.body, newOptions); + } + +}); +;// CONCATENATED MODULE: ./src/functions/underline.js + + + + + +defineFunction({ + type: "underline", + names: ["\\underline"], + props: { + numArgs: 1, + allowedInText: true + }, + + handler(_ref, args) { + let { + parser + } = _ref; + return { + type: "underline", + mode: parser.mode, + body: args[0] + }; + }, + + htmlBuilder(group, options) { + // Underlines are handled in the TeXbook pg 443, Rule 10. + // Build the inner group. + const innerGroup = buildGroup(group.body, options); // Create the line to go below the body + + const line = buildCommon.makeLineSpan("underline-line", options); // Generate the vlist, with the appropriate kerns + + const defaultRuleThickness = options.fontMetrics().defaultRuleThickness; + const vlist = buildCommon.makeVList({ + positionType: "top", + positionData: innerGroup.height, + children: [{ + type: "kern", + size: defaultRuleThickness + }, { + type: "elem", + elem: line + }, { + type: "kern", + size: 3 * defaultRuleThickness + }, { + type: "elem", + elem: innerGroup + }] + }, options); + return buildCommon.makeSpan(["mord", "underline"], [vlist], options); + }, + + mathmlBuilder(group, options) { + const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]); + operator.setAttribute("stretchy", "true"); + const node = new mathMLTree.MathNode("munder", [buildMathML_buildGroup(group.body, options), operator]); + node.setAttribute("accentunder", "true"); + return node; + } + +}); +;// CONCATENATED MODULE: ./src/functions/vcenter.js + + + + + // \vcenter: Vertically center the argument group on the math axis. + +defineFunction({ + type: "vcenter", + names: ["\\vcenter"], + props: { + numArgs: 1, + argTypes: ["original"], + // In LaTeX, \vcenter can act only on a box. + allowedInText: false + }, + + handler(_ref, args) { + let { + parser + } = _ref; + return { + type: "vcenter", + mode: parser.mode, + body: args[0] + }; + }, + + htmlBuilder(group, options) { + const body = buildGroup(group.body, options); + const axisHeight = options.fontMetrics().axisHeight; + const dy = 0.5 * (body.height - axisHeight - (body.depth + axisHeight)); + return buildCommon.makeVList({ + positionType: "shift", + positionData: dy, + children: [{ + type: "elem", + elem: body + }] + }, options); + }, + + mathmlBuilder(group, options) { + // There is no way to do this in MathML. + // Write a class as a breadcrumb in case some post-processor wants + // to perform a vcenter adjustment. + return new mathMLTree.MathNode("mpadded", [buildMathML_buildGroup(group.body, options)], ["vcenter"]); + } + +}); +;// CONCATENATED MODULE: ./src/functions/verb.js + + + + +defineFunction({ + type: "verb", + names: ["\\verb"], + props: { + numArgs: 0, + allowedInText: true + }, + + handler(context, args, optArgs) { + // \verb and \verb* are dealt with directly in Parser.js. + // If we end up here, it's because of a failure to match the two delimiters + // in the regex in Lexer.js. LaTeX raises the following error when \verb is + // terminated by end of line (or file). + throw new src_ParseError("\\verb ended by end of line instead of matching delimiter"); + }, + + htmlBuilder(group, options) { + const text = makeVerb(group); + const body = []; // \verb enters text mode and therefore is sized like \textstyle + + const newOptions = options.havingStyle(options.style.text()); + + for (let i = 0; i < text.length; i++) { + let c = text[i]; + + if (c === '~') { + c = '\\textasciitilde'; + } + + body.push(buildCommon.makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"])); + } + + return buildCommon.makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), buildCommon.tryCombineChars(body), newOptions); + }, + + mathmlBuilder(group, options) { + const text = new mathMLTree.TextNode(makeVerb(group)); + const node = new mathMLTree.MathNode("mtext", [text]); + node.setAttribute("mathvariant", "monospace"); + return node; + } + +}); +/** + * Converts verb group into body string. + * + * \verb* replaces each space with an open box \u2423 + * \verb replaces each space with a no-break space \xA0 + */ + +const makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0'); +;// CONCATENATED MODULE: ./src/functions.js +/** Include this to ensure that all functions are defined. */ + +const functions = _functions; +/* harmony default export */ var src_functions = (functions); // TODO(kevinb): have functions return an object and call defineFunction with +// that object in this file instead of relying on side-effects. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +;// CONCATENATED MODULE: ./src/Lexer.js +/** + * The Lexer class handles tokenizing the input in various ways. Since our + * parser expects us to be able to backtrack, the lexer allows lexing from any + * given starting point. + * + * Its main exposed function is the `lex` function, which takes a position to + * lex from and a type of token to lex. It defers to the appropriate `_innerLex` + * function. + * + * The various `_innerLex` functions perform the actual lexing of different + * kinds. + */ + + + + +/* The following tokenRegex + * - matches typical whitespace (but not NBSP etc.) using its first group + * - does not match any control character \x00-\x1f except whitespace + * - does not match a bare backslash + * - matches any ASCII character except those just mentioned + * - does not match the BMP private use area \uE000-\uF8FF + * - does not match bare surrogate code units + * - matches any BMP character except for those just described + * - matches any valid Unicode surrogate pair + * - matches a backslash followed by one or more whitespace characters + * - matches a backslash followed by one or more letters then whitespace + * - matches a backslash followed by any BMP character + * Capturing groups: + * [1] regular whitespace + * [2] backslash followed by whitespace + * [3] anything else, which may include: + * [4] left character of \verb* + * [5] left character of \verb + * [6] backslash followed by word, excluding any trailing whitespace + * Just because the Lexer matches something doesn't mean it's valid input: + * If there is no matching function or symbol definition, the Parser will + * still reject the input. + */ +const spaceRegexString = "[ \r\n\t]"; +const controlWordRegexString = "\\\\[a-zA-Z@]+"; +const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; +const controlWordWhitespaceRegexString = "(" + controlWordRegexString + ")" + spaceRegexString + "*"; +const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; +const combiningDiacriticalMarkString = "[\u0300-\u036f]"; +const combiningDiacriticalMarksEndRegex = new RegExp(combiningDiacriticalMarkString + "+$"); +const tokenRegexString = "(" + spaceRegexString + "+)|" + ( // whitespace +controlSpaceRegexString + "|") + // \whitespace +"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + ( // single codepoint +combiningDiacriticalMarkString + "*") + // ...plus accents +"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + ( // surrogate pair +combiningDiacriticalMarkString + "*") + // ...plus accents +"|\\\\verb\\*([^]).*?\\4" + // \verb* +"|\\\\verb([^*a-zA-Z]).*?\\5" + ( // \verb unstarred +"|" + controlWordWhitespaceRegexString) + ( // \macroName + spaces +"|" + controlSymbolRegexString + ")"); // \\, \', etc. + +/** Main Lexer class */ + +class Lexer { + // Category codes. The lexer only supports comment characters (14) for now. + // MacroExpander additionally distinguishes active (13). + constructor(input, settings) { + this.input = void 0; + this.settings = void 0; + this.tokenRegex = void 0; + this.catcodes = void 0; + // Separate accents from characters + this.input = input; + this.settings = settings; + this.tokenRegex = new RegExp(tokenRegexString, 'g'); + this.catcodes = { + "%": 14, + // comment character + "~": 13 // active character + + }; + } + + setCatcode(char, code) { + this.catcodes[char] = code; + } + /** + * This function lexes a single token. + */ + + + lex() { + const input = this.input; + const pos = this.tokenRegex.lastIndex; + + if (pos === input.length) { + return new Token("EOF", new SourceLocation(this, pos, pos)); + } + + const match = this.tokenRegex.exec(input); + + if (match === null || match.index !== pos) { + throw new src_ParseError("Unexpected character: '" + input[pos] + "'", new Token(input[pos], new SourceLocation(this, pos, pos + 1))); + } + + const text = match[6] || match[3] || (match[2] ? "\\ " : " "); + + if (this.catcodes[text] === 14) { + // comment character + const nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex); + + if (nlIndex === -1) { + this.tokenRegex.lastIndex = input.length; // EOF + + this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)"); + } else { + this.tokenRegex.lastIndex = nlIndex + 1; + } + + return this.lex(); + } + + return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); + } + +} +;// CONCATENATED MODULE: ./src/Namespace.js +/** + * A `Namespace` refers to a space of nameable things like macros or lengths, + * which can be `set` either globally or local to a nested group, using an + * undo stack similar to how TeX implements this functionality. + * Performance-wise, `get` and local `set` take constant time, while global + * `set` takes time proportional to the depth of group nesting. + */ + +class Namespace { + /** + * Both arguments are optional. The first argument is an object of + * built-in mappings which never change. The second argument is an object + * of initial (global-level) mappings, which will constantly change + * according to any global/top-level `set`s done. + */ + constructor(builtins, globalMacros) { + if (builtins === void 0) { + builtins = {}; + } + + if (globalMacros === void 0) { + globalMacros = {}; + } + + this.current = void 0; + this.builtins = void 0; + this.undefStack = void 0; + this.current = globalMacros; + this.builtins = builtins; + this.undefStack = []; + } + /** + * Start a new nested group, affecting future local `set`s. + */ + + + beginGroup() { + this.undefStack.push({}); + } + /** + * End current nested group, restoring values before the group began. + */ + + + endGroup() { + if (this.undefStack.length === 0) { + throw new src_ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug"); + } + + const undefs = this.undefStack.pop(); + + for (const undef in undefs) { + if (undefs.hasOwnProperty(undef)) { + if (undefs[undef] == null) { + delete this.current[undef]; + } else { + this.current[undef] = undefs[undef]; + } + } + } + } + /** + * Ends all currently nested groups (if any), restoring values before the + * groups began. Useful in case of an error in the middle of parsing. + */ + + + endGroups() { + while (this.undefStack.length > 0) { + this.endGroup(); + } + } + /** + * Detect whether `name` has a definition. Equivalent to + * `get(name) != null`. + */ + + + has(name) { + return this.current.hasOwnProperty(name) || this.builtins.hasOwnProperty(name); + } + /** + * Get the current value of a name, or `undefined` if there is no value. + * + * Note: Do not use `if (namespace.get(...))` to detect whether a macro + * is defined, as the definition may be the empty string which evaluates + * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or + * `if (namespace.has(...))`. + */ + + + get(name) { + if (this.current.hasOwnProperty(name)) { + return this.current[name]; + } else { + return this.builtins[name]; + } + } + /** + * Set the current value of a name, and optionally set it globally too. + * Local set() sets the current value and (when appropriate) adds an undo + * operation to the undo stack. Global set() may change the undo + * operation at every level, so takes time linear in their number. + * A value of undefined means to delete existing definitions. + */ + + + set(name, value, global) { + if (global === void 0) { + global = false; + } + + if (global) { + // Global set is equivalent to setting in all groups. Simulate this + // by destroying any undos currently scheduled for this name, + // and adding an undo with the *new* value (in case it later gets + // locally reset within this environment). + for (let i = 0; i < this.undefStack.length; i++) { + delete this.undefStack[i][name]; + } + + if (this.undefStack.length > 0) { + this.undefStack[this.undefStack.length - 1][name] = value; + } + } else { + // Undo this set at end of this group (possibly to `undefined`), + // unless an undo is already in place, in which case that older + // value is the correct one. + const top = this.undefStack[this.undefStack.length - 1]; + + if (top && !top.hasOwnProperty(name)) { + top[name] = this.current[name]; + } + } + + if (value == null) { + delete this.current[name]; + } else { + this.current[name] = value; + } + } + +} +;// CONCATENATED MODULE: ./src/macros.js +/** + * Predefined macros for KaTeX. + * This can be used to define some commands in terms of others. + */ +// Export global macros object from defineMacro + +const macros = _macros; +/* harmony default export */ var src_macros = (macros); + + + + + + ////////////////////////////////////////////////////////////////////// +// macro tools + +defineMacro("\\noexpand", function (context) { + // The expansion is the token itself; but that token is interpreted + // as if its meaning were ‘\relax’ if it is a control sequence that + // would ordinarily be expanded by TeX’s expansion rules. + const t = context.popToken(); + + if (context.isExpandable(t.text)) { + t.noexpand = true; + t.treatAsRelax = true; + } + + return { + tokens: [t], + numArgs: 0 + }; +}); +defineMacro("\\expandafter", function (context) { + // TeX first reads the token that comes immediately after \expandafter, + // without expanding it; let’s call this token t. Then TeX reads the + // token that comes after t (and possibly more tokens, if that token + // has an argument), replacing it by its expansion. Finally TeX puts + // t back in front of that expansion. + const t = context.popToken(); + context.expandOnce(true); // expand only an expandable token + + return { + tokens: [t], + numArgs: 0 + }; +}); // LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 +// TeX source: \long\def\@firstoftwo#1#2{#1} + +defineMacro("\\@firstoftwo", function (context) { + const args = context.consumeArgs(2); + return { + tokens: args[0], + numArgs: 0 + }; +}); // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 +// TeX source: \long\def\@secondoftwo#1#2{#2} + +defineMacro("\\@secondoftwo", function (context) { + const args = context.consumeArgs(2); + return { + tokens: args[1], + numArgs: 0 + }; +}); // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) +// symbol that isn't a space, consuming any spaces but not consuming the +// first nonspace character. If that nonspace character matches #1, then +// the macro expands to #2; otherwise, it expands to #3. + +defineMacro("\\@ifnextchar", function (context) { + const args = context.consumeArgs(3); // symbol, if, else + + context.consumeSpaces(); + const nextToken = context.future(); + + if (args[0].length === 1 && args[0][0].text === nextToken.text) { + return { + tokens: args[1], + numArgs: 0 + }; + } else { + return { + tokens: args[2], + numArgs: 0 + }; + } +}); // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. +// If it is `*`, then it consumes the symbol, and the macro expands to #1; +// otherwise, the macro expands to #2 (without consuming the symbol). +// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} + +defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode + +defineMacro("\\TextOrMath", function (context) { + const args = context.consumeArgs(2); + + if (context.mode === 'text') { + return { + tokens: args[0], + numArgs: 0 + }; + } else { + return { + tokens: args[1], + numArgs: 0 + }; + } +}); // Lookup table for parsing numbers in base 8 through 16 + +const digitToNumber = { + "0": 0, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7, + "8": 8, + "9": 9, + "a": 10, + "A": 10, + "b": 11, + "B": 11, + "c": 12, + "C": 12, + "d": 13, + "D": 13, + "e": 14, + "E": 14, + "f": 15, + "F": 15 +}; // TeX \char makes a literal character (catcode 12) using the following forms: +// (see The TeXBook, p. 43) +// \char123 -- decimal +// \char'123 -- octal +// \char"123 -- hex +// \char`x -- character that can be written (i.e. isn't active) +// \char`\x -- character that cannot be written (e.g. %) +// These all refer to characters from the font, so we turn them into special +// calls to a function \@char dealt with in the Parser. + +defineMacro("\\char", function (context) { + let token = context.popToken(); + let base; + let number = ''; + + if (token.text === "'") { + base = 8; + token = context.popToken(); + } else if (token.text === '"') { + base = 16; + token = context.popToken(); + } else if (token.text === "`") { + token = context.popToken(); + + if (token.text[0] === "\\") { + number = token.text.charCodeAt(1); + } else if (token.text === "EOF") { + throw new src_ParseError("\\char` missing argument"); + } else { + number = token.text.charCodeAt(0); + } + } else { + base = 10; + } + + if (base) { + // Parse a number in the given base, starting with first `token`. + number = digitToNumber[token.text]; + + if (number == null || number >= base) { + throw new src_ParseError("Invalid base-" + base + " digit " + token.text); + } + + let digit; + + while ((digit = digitToNumber[context.future().text]) != null && digit < base) { + number *= base; + number += digit; + context.popToken(); + } + } + + return "\\@char{" + number + "}"; +}); // \newcommand{\macro}[args]{definition} +// \renewcommand{\macro}[args]{definition} +// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition} + +const newcommand = (context, existsOK, nonexistsOK, skipIfExists) => { + let arg = context.consumeArg().tokens; + + if (arg.length !== 1) { + throw new src_ParseError("\\newcommand's first argument must be a macro name"); + } + + const name = arg[0].text; + const exists = context.isDefined(name); + + if (exists && !existsOK) { + throw new src_ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand")); + } + + if (!exists && !nonexistsOK) { + throw new src_ParseError("\\renewcommand{" + name + "} when command " + name + " " + "does not yet exist; use \\newcommand"); + } + + let numArgs = 0; + arg = context.consumeArg().tokens; + + if (arg.length === 1 && arg[0].text === "[") { + let argText = ''; + let token = context.expandNextToken(); + + while (token.text !== "]" && token.text !== "EOF") { + // TODO: Should properly expand arg, e.g., ignore {}s + argText += token.text; + token = context.expandNextToken(); + } + + if (!argText.match(/^\s*[0-9]+\s*$/)) { + throw new src_ParseError("Invalid number of arguments: " + argText); + } + + numArgs = parseInt(argText); + arg = context.consumeArg().tokens; + } + + if (!(exists && skipIfExists)) { + // Final arg is the expansion of the macro + context.macros.set(name, { + tokens: arg, + numArgs + }); + } + + return ''; +}; + +defineMacro("\\newcommand", context => newcommand(context, false, true, false)); +defineMacro("\\renewcommand", context => newcommand(context, true, false, false)); +defineMacro("\\providecommand", context => newcommand(context, true, true, true)); // terminal (console) tools + +defineMacro("\\message", context => { + const arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console + + console.log(arg.reverse().map(token => token.text).join("")); + return ''; +}); +defineMacro("\\errmessage", context => { + const arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console + + console.error(arg.reverse().map(token => token.text).join("")); + return ''; +}); +defineMacro("\\show", context => { + const tok = context.popToken(); + const name = tok.text; // eslint-disable-next-line no-console + + console.log(tok, context.macros.get(name), src_functions[name], src_symbols.math[name], src_symbols.text[name]); + return ''; +}); ////////////////////////////////////////////////////////////////////// +// Grouping +// \let\bgroup={ \let\egroup=} + +defineMacro("\\bgroup", "{"); +defineMacro("\\egroup", "}"); // Symbols from latex.ltx: +// \def~{\nobreakspace{}} +// \def\lq{`} +// \def\rq{'} +// \def \aa {\r a} +// \def \AA {\r A} + +defineMacro("~", "\\nobreakspace"); +defineMacro("\\lq", "`"); +defineMacro("\\rq", "'"); +defineMacro("\\aa", "\\r a"); +defineMacro("\\AA", "\\r A"); // Copyright (C) and registered (R) symbols. Use raw symbol in MathML. +// \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}} +// \DeclareTextCommandDefault{\textregistered}{\textcircled{% +// \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}} +// \DeclareRobustCommand{\copyright}{% +// \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi} + +defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}"); +defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}"); +defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}"); // Characters omitted from Unicode range 1D400–1D7FF + +defineMacro("\u212C", "\\mathscr{B}"); // script + +defineMacro("\u2130", "\\mathscr{E}"); +defineMacro("\u2131", "\\mathscr{F}"); +defineMacro("\u210B", "\\mathscr{H}"); +defineMacro("\u2110", "\\mathscr{I}"); +defineMacro("\u2112", "\\mathscr{L}"); +defineMacro("\u2133", "\\mathscr{M}"); +defineMacro("\u211B", "\\mathscr{R}"); +defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur + +defineMacro("\u210C", "\\mathfrak{H}"); +defineMacro("\u2128", "\\mathfrak{Z}"); // Define \Bbbk with a macro that works in both HTML and MathML. + +defineMacro("\\Bbbk", "\\Bbb{k}"); // Unicode middle dot +// The KaTeX fonts do not contain U+00B7. Instead, \cdotp displays +// the dot at U+22C5 and gives it punct spacing. + +defineMacro("\u00b7", "\\cdotp"); // \llap and \rlap render their contents in text mode + +defineMacro("\\llap", "\\mathllap{\\textrm{#1}}"); +defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}"); +defineMacro("\\clap", "\\mathclap{\\textrm{#1}}"); // \mathstrut from the TeXbook, p 360 + +defineMacro("\\mathstrut", "\\vphantom{(}"); // \underbar from TeXbook p 353 + +defineMacro("\\underbar", "\\underline{\\text{#1}}"); // \not is defined by base/fontmath.ltx via +// \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36} +// It's thus treated like a \mathrel, but defined by a symbol that has zero +// width but extends to the right. We use \rlap to get that spacing. +// For MathML we write U+0338 here. buildMathML.js will then do the overlay. + +defineMacro("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'); // Negated symbols from base/fontmath.ltx: +// \def\neq{\not=} \let\ne=\neq +// \DeclareRobustCommand +// \notin{\mathrel{\m@th\mathpalette\c@ncel\in}} +// \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}} + +defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}"); +defineMacro("\\ne", "\\neq"); +defineMacro("\u2260", "\\neq"); +defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}"); +defineMacro("\u2209", "\\notin"); // Unicode stacked relations + +defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}"); +defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}"); +defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}"); +defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}"); +defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}"); +defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}"); +defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}"); // Misc Unicode + +defineMacro("\u27C2", "\\perp"); +defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}"); +defineMacro("\u220C", "\\notni"); +defineMacro("\u231C", "\\ulcorner"); +defineMacro("\u231D", "\\urcorner"); +defineMacro("\u231E", "\\llcorner"); +defineMacro("\u231F", "\\lrcorner"); +defineMacro("\u00A9", "\\copyright"); +defineMacro("\u00AE", "\\textregistered"); +defineMacro("\uFE0F", "\\textregistered"); // The KaTeX fonts have corners at codepoints that don't match Unicode. +// For MathML purposes, use the Unicode code point. + +defineMacro("\\ulcorner", "\\html@mathml{\\@ulcorner}{\\mathop{\\char\"231c}}"); +defineMacro("\\urcorner", "\\html@mathml{\\@urcorner}{\\mathop{\\char\"231d}}"); +defineMacro("\\llcorner", "\\html@mathml{\\@llcorner}{\\mathop{\\char\"231e}}"); +defineMacro("\\lrcorner", "\\html@mathml{\\@lrcorner}{\\mathop{\\char\"231f}}"); ////////////////////////////////////////////////////////////////////// +// LaTeX_2ε +// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ +// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} +// We'll call \varvdots, which gets a glyph from symbols.js. +// The zero-width rule gets us an equivalent to the vertical 6pt kern. + +defineMacro("\\vdots", "{\\varvdots\\rule{0pt}{15pt}}"); +defineMacro("\u22ee", "\\vdots"); ////////////////////////////////////////////////////////////////////// +// amsmath.sty +// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf +// Italic Greek capital letters. AMS defines these with \DeclareMathSymbol, +// but they are equivalent to \mathit{\Letter}. + +defineMacro("\\varGamma", "\\mathit{\\Gamma}"); +defineMacro("\\varDelta", "\\mathit{\\Delta}"); +defineMacro("\\varTheta", "\\mathit{\\Theta}"); +defineMacro("\\varLambda", "\\mathit{\\Lambda}"); +defineMacro("\\varXi", "\\mathit{\\Xi}"); +defineMacro("\\varPi", "\\mathit{\\Pi}"); +defineMacro("\\varSigma", "\\mathit{\\Sigma}"); +defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}"); +defineMacro("\\varPhi", "\\mathit{\\Phi}"); +defineMacro("\\varPsi", "\\mathit{\\Psi}"); +defineMacro("\\varOmega", "\\mathit{\\Omega}"); //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} + +defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); // \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript +// \mkern-\thinmuskip{:}\mskip6muplus1mu\relax} + +defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"); // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} + +defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); // \def\iff{\DOTSB\;\Longleftrightarrow\;} +// \def\implies{\DOTSB\;\Longrightarrow\;} +// \def\impliedby{\DOTSB\;\Longleftarrow\;} + +defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); +defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); +defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); // \def\dddot#1{{\mathop{#1}\limits^{\vbox to-1.4\ex@{\kern-\tw@\ex@ +// \hbox{\normalfont ...}\vss}}}} +// We use \overset which avoids the vertical shift of \mathop. + +defineMacro("\\dddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ...}}{#1}}"); +defineMacro("\\ddddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ....}}{#1}}"); // AMSMath's automatic \dots, based on \mdots@@ macro. + +const dotsByToken = { + ',': '\\dotsc', + '\\not': '\\dotsb', + // \keybin@ checks for the following: + '+': '\\dotsb', + '=': '\\dotsb', + '<': '\\dotsb', + '>': '\\dotsb', + '-': '\\dotsb', + '*': '\\dotsb', + ':': '\\dotsb', + // Symbols whose definition starts with \DOTSB: + '\\DOTSB': '\\dotsb', + '\\coprod': '\\dotsb', + '\\bigvee': '\\dotsb', + '\\bigwedge': '\\dotsb', + '\\biguplus': '\\dotsb', + '\\bigcap': '\\dotsb', + '\\bigcup': '\\dotsb', + '\\prod': '\\dotsb', + '\\sum': '\\dotsb', + '\\bigotimes': '\\dotsb', + '\\bigoplus': '\\dotsb', + '\\bigodot': '\\dotsb', + '\\bigsqcup': '\\dotsb', + '\\And': '\\dotsb', + '\\longrightarrow': '\\dotsb', + '\\Longrightarrow': '\\dotsb', + '\\longleftarrow': '\\dotsb', + '\\Longleftarrow': '\\dotsb', + '\\longleftrightarrow': '\\dotsb', + '\\Longleftrightarrow': '\\dotsb', + '\\mapsto': '\\dotsb', + '\\longmapsto': '\\dotsb', + '\\hookrightarrow': '\\dotsb', + '\\doteq': '\\dotsb', + // Symbols whose definition starts with \mathbin: + '\\mathbin': '\\dotsb', + // Symbols whose definition starts with \mathrel: + '\\mathrel': '\\dotsb', + '\\relbar': '\\dotsb', + '\\Relbar': '\\dotsb', + '\\xrightarrow': '\\dotsb', + '\\xleftarrow': '\\dotsb', + // Symbols whose definition starts with \DOTSI: + '\\DOTSI': '\\dotsi', + '\\int': '\\dotsi', + '\\oint': '\\dotsi', + '\\iint': '\\dotsi', + '\\iiint': '\\dotsi', + '\\iiiint': '\\dotsi', + '\\idotsint': '\\dotsi', + // Symbols whose definition starts with \DOTSX: + '\\DOTSX': '\\dotsx' +}; +defineMacro("\\dots", function (context) { + // TODO: If used in text mode, should expand to \textellipsis. + // However, in KaTeX, \textellipsis and \ldots behave the same + // (in text mode), and it's unlikely we'd see any of the math commands + // that affect the behavior of \dots when in text mode. So fine for now + // (until we support \ifmmode ... \else ... \fi). + let thedots = '\\dotso'; + const next = context.expandAfterFuture().text; + + if (next in dotsByToken) { + thedots = dotsByToken[next]; + } else if (next.slice(0, 4) === '\\not') { + thedots = '\\dotsb'; + } else if (next in src_symbols.math) { + if (utils.contains(['bin', 'rel'], src_symbols.math[next].group)) { + thedots = '\\dotsb'; + } + } + + return thedots; +}); +const spaceAfterDots = { + // \rightdelim@ checks for the following: + ')': true, + ']': true, + '\\rbrack': true, + '\\}': true, + '\\rbrace': true, + '\\rangle': true, + '\\rceil': true, + '\\rfloor': true, + '\\rgroup': true, + '\\rmoustache': true, + '\\right': true, + '\\bigr': true, + '\\biggr': true, + '\\Bigr': true, + '\\Biggr': true, + // \extra@ also tests for the following: + '$': true, + // \extrap@ checks for the following: + ';': true, + '.': true, + ',': true +}; +defineMacro("\\dotso", function (context) { + const next = context.future().text; + + if (next in spaceAfterDots) { + return "\\ldots\\,"; + } else { + return "\\ldots"; + } +}); +defineMacro("\\dotsc", function (context) { + const next = context.future().text; // \dotsc uses \extra@ but not \extrap@, instead specially checking for + // ';' and '.', but doesn't check for ','. + + if (next in spaceAfterDots && next !== ',') { + return "\\ldots\\,"; + } else { + return "\\ldots"; + } +}); +defineMacro("\\cdots", function (context) { + const next = context.future().text; + + if (next in spaceAfterDots) { + return "\\@cdots\\,"; + } else { + return "\\@cdots"; + } +}); +defineMacro("\\dotsb", "\\cdots"); +defineMacro("\\dotsm", "\\cdots"); +defineMacro("\\dotsi", "\\!\\cdots"); // amsmath doesn't actually define \dotsx, but \dots followed by a macro +// starting with \DOTSX implies \dotso, and then \extra@ detects this case +// and forces the added `\,`. + +defineMacro("\\dotsx", "\\ldots\\,"); // \let\DOTSI\relax +// \let\DOTSB\relax +// \let\DOTSX\relax + +defineMacro("\\DOTSI", "\\relax"); +defineMacro("\\DOTSB", "\\relax"); +defineMacro("\\DOTSX", "\\relax"); // Spacing, based on amsmath.sty's override of LaTeX defaults +// \DeclareRobustCommand{\tmspace}[3]{% +// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} + +defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} +// TODO: math mode should use \thinmuskip + +defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); // \let\thinspace\, + +defineMacro("\\thinspace", "\\,"); // \def\>{\mskip\medmuskip} +// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} +// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu + +defineMacro("\\>", "\\mskip{4mu}"); +defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); // \let\medspace\: + +defineMacro("\\medspace", "\\:"); // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} +// TODO: math mode should use \thickmuskip = 5mu plus 5mu + +defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); // \let\thickspace\; + +defineMacro("\\thickspace", "\\;"); // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} +// TODO: math mode should use \thinmuskip + +defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); // \let\negthinspace\! + +defineMacro("\\negthinspace", "\\!"); // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} +// TODO: math mode should use \medmuskip + +defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} +// TODO: math mode should use \thickmuskip + +defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); // \def\enspace{\kern.5em } + +defineMacro("\\enspace", "\\kern.5em "); // \def\enskip{\hskip.5em\relax} + +defineMacro("\\enskip", "\\hskip.5em\\relax"); // \def\quad{\hskip1em\relax} + +defineMacro("\\quad", "\\hskip1em\\relax"); // \def\qquad{\hskip2em\relax} + +defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag + +defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); +defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); +defineMacro("\\tag@literal", context => { + if (context.macros.get("\\df@tag")) { + throw new src_ParseError("Multiple \\tag"); + } + + return "\\gdef\\df@tag{\\text{#1}}"; +}); // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin +// {\operator@font mod}\penalty900 +// \mkern5mu\nonscript\mskip-\medmuskip} +// \newcommand{\pod}[1]{\allowbreak +// \if@display\mkern18mu\else\mkern8mu\fi(#1)} +// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} +// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu +// \else\mkern12mu\fi{\operator@font mod}\,\,#1} +// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu + +defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"); +defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"); +defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); +defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); ////////////////////////////////////////////////////////////////////// +// LaTeX source2e +// \expandafter\let\expandafter\@normalcr +// \csname\expandafter\@gobble\string\\ \endcsname +// \DeclareRobustCommand\newline{\@normalcr\relax} + +defineMacro("\\newline", "\\\\\\relax"); // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} +// TODO: Doesn't normally work in math mode because \@ fails. KaTeX doesn't +// support \@ yet, so that's omitted, and we add \text so that the result +// doesn't look funny in math mode. + +defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}"); // \DeclareRobustCommand{\LaTeX}{L\kern-.36em% +// {\sbox\z@ T% +// \vbox to\ht\z@{\hbox{\check@mathfonts +// \fontsize\sf@size\z@ +// \math@fontsfalse\selectfont +// A}% +// \vss}% +// }% +// \kern-.15em% +// \TeX} +// This code aligns the top of the A with the T (from the perspective of TeX's +// boxes, though visually the A appears to extend above slightly). +// We compute the corresponding \raisebox when A is rendered in \normalsize +// \scriptstyle, which has a scale factor of 0.7 (see Options.js). + +const latexRaiseA = makeEm(fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1]); +defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + ("L\\kern-.36em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{LaTeX}}"); // New KaTeX logo based on tweaking LaTeX logo + +defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + ("K\\kern-.17em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{KaTeX}}"); // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} +// \def\@hspace#1{\hskip #1\relax} +// \def\@hspacer#1{\vrule \@width\z@\nobreak +// \hskip #1\hskip \z@skip} + +defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); +defineMacro("\\@hspace", "\\hskip #1\\relax"); +defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); ////////////////////////////////////////////////////////////////////// +// mathtools.sty +//\providecommand\ordinarycolon{:} + +defineMacro("\\ordinarycolon", ":"); //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}} +//TODO(edemaine): Not yet centered. Fix via \raisebox or #726 + +defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"); // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon} + +defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}"); // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=} + +defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔ +// \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=} + +defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}"); // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} + +defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}"); // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} + +defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}"); // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon} + +defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕ +// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} + +defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}"); // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon} + +defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}"); // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} + +defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}"); // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} + +defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}"); // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} + +defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}"); // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} + +defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}"); // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} + +defineMacro("\\Colonsim", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"2237\\char\"223c}}"); // Some Unicode characters are implemented with macros to mathtools functions. + +defineMacro("\u2237", "\\dblcolon"); // :: + +defineMacro("\u2239", "\\eqcolon"); // -: + +defineMacro("\u2254", "\\coloneqq"); // := + +defineMacro("\u2255", "\\eqqcolon"); // =: + +defineMacro("\u2A74", "\\Coloneqq"); // ::= +////////////////////////////////////////////////////////////////////// +// colonequals.sty +// Alternate names for mathtools's macros: + +defineMacro("\\ratio", "\\vcentcolon"); +defineMacro("\\coloncolon", "\\dblcolon"); +defineMacro("\\colonequals", "\\coloneqq"); +defineMacro("\\coloncolonequals", "\\Coloneqq"); +defineMacro("\\equalscolon", "\\eqqcolon"); +defineMacro("\\equalscoloncolon", "\\Eqqcolon"); +defineMacro("\\colonminus", "\\coloneq"); +defineMacro("\\coloncolonminus", "\\Coloneq"); +defineMacro("\\minuscolon", "\\eqcolon"); +defineMacro("\\minuscoloncolon", "\\Eqcolon"); // \colonapprox name is same in mathtools and colonequals. + +defineMacro("\\coloncolonapprox", "\\Colonapprox"); // \colonsim name is same in mathtools and colonequals. + +defineMacro("\\coloncolonsim", "\\Colonsim"); // Additional macros, implemented by analogy with mathtools definitions: + +defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"); +defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"); +defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"); +defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"); // Present in newtxmath, pxfonts and txfonts + +defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}"); +defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); +defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); ////////////////////////////////////////////////////////////////////// +// From amsopn.sty + +defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); +defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); +defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}"); +defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}"); +defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}"); +defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"); ////////////////////////////////////////////////////////////////////// +// MathML alternates for KaTeX glyphs in the Unicode private area + +defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}"); +defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}"); +defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}"); +defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}"); +defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}"); +defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}"); +defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}"); +defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}"); +defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}"); +defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}"); +defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}"); +defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}"); +defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}"); +defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}"); +defineMacro("\\imath", "\\html@mathml{\\@imath}{\u0131}"); +defineMacro("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"); ////////////////////////////////////////////////////////////////////// +// stmaryrd and semantic +// The stmaryrd and semantic packages render the next four items by calling a +// glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros. + +defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}"); +defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}"); +defineMacro("\u27e6", "\\llbracket"); // blackboard bold [ + +defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ] + +defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}"); +defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}"); +defineMacro("\u2983", "\\lBrace"); // blackboard bold { + +defineMacro("\u2984", "\\rBrace"); // blackboard bold } +// TODO: Create variable sized versions of the last two items. I believe that +// will require new font glyphs. +// The stmaryrd function `\minuso` provides a "Plimsoll" symbol that +// superimposes the characters \circ and \mathminus. Used in chemistry. + +defineMacro("\\minuso", "\\mathbin{\\html@mathml{" + "{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}" + "{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}" + "{\\char`⦵}}"); +defineMacro("⦵", "\\minuso"); ////////////////////////////////////////////////////////////////////// +// texvc.sty +// The texvc package contains macros available in mediawiki pages. +// We omit the functions deprecated at +// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax +// We also omit texvc's \O, which conflicts with \text{\O} + +defineMacro("\\darr", "\\downarrow"); +defineMacro("\\dArr", "\\Downarrow"); +defineMacro("\\Darr", "\\Downarrow"); +defineMacro("\\lang", "\\langle"); +defineMacro("\\rang", "\\rangle"); +defineMacro("\\uarr", "\\uparrow"); +defineMacro("\\uArr", "\\Uparrow"); +defineMacro("\\Uarr", "\\Uparrow"); +defineMacro("\\N", "\\mathbb{N}"); +defineMacro("\\R", "\\mathbb{R}"); +defineMacro("\\Z", "\\mathbb{Z}"); +defineMacro("\\alef", "\\aleph"); +defineMacro("\\alefsym", "\\aleph"); +defineMacro("\\Alpha", "\\mathrm{A}"); +defineMacro("\\Beta", "\\mathrm{B}"); +defineMacro("\\bull", "\\bullet"); +defineMacro("\\Chi", "\\mathrm{X}"); +defineMacro("\\clubs", "\\clubsuit"); +defineMacro("\\cnums", "\\mathbb{C}"); +defineMacro("\\Complex", "\\mathbb{C}"); +defineMacro("\\Dagger", "\\ddagger"); +defineMacro("\\diamonds", "\\diamondsuit"); +defineMacro("\\empty", "\\emptyset"); +defineMacro("\\Epsilon", "\\mathrm{E}"); +defineMacro("\\Eta", "\\mathrm{H}"); +defineMacro("\\exist", "\\exists"); +defineMacro("\\harr", "\\leftrightarrow"); +defineMacro("\\hArr", "\\Leftrightarrow"); +defineMacro("\\Harr", "\\Leftrightarrow"); +defineMacro("\\hearts", "\\heartsuit"); +defineMacro("\\image", "\\Im"); +defineMacro("\\infin", "\\infty"); +defineMacro("\\Iota", "\\mathrm{I}"); +defineMacro("\\isin", "\\in"); +defineMacro("\\Kappa", "\\mathrm{K}"); +defineMacro("\\larr", "\\leftarrow"); +defineMacro("\\lArr", "\\Leftarrow"); +defineMacro("\\Larr", "\\Leftarrow"); +defineMacro("\\lrarr", "\\leftrightarrow"); +defineMacro("\\lrArr", "\\Leftrightarrow"); +defineMacro("\\Lrarr", "\\Leftrightarrow"); +defineMacro("\\Mu", "\\mathrm{M}"); +defineMacro("\\natnums", "\\mathbb{N}"); +defineMacro("\\Nu", "\\mathrm{N}"); +defineMacro("\\Omicron", "\\mathrm{O}"); +defineMacro("\\plusmn", "\\pm"); +defineMacro("\\rarr", "\\rightarrow"); +defineMacro("\\rArr", "\\Rightarrow"); +defineMacro("\\Rarr", "\\Rightarrow"); +defineMacro("\\real", "\\Re"); +defineMacro("\\reals", "\\mathbb{R}"); +defineMacro("\\Reals", "\\mathbb{R}"); +defineMacro("\\Rho", "\\mathrm{P}"); +defineMacro("\\sdot", "\\cdot"); +defineMacro("\\sect", "\\S"); +defineMacro("\\spades", "\\spadesuit"); +defineMacro("\\sub", "\\subset"); +defineMacro("\\sube", "\\subseteq"); +defineMacro("\\supe", "\\supseteq"); +defineMacro("\\Tau", "\\mathrm{T}"); +defineMacro("\\thetasym", "\\vartheta"); // TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}"); + +defineMacro("\\weierp", "\\wp"); +defineMacro("\\Zeta", "\\mathrm{Z}"); ////////////////////////////////////////////////////////////////////// +// statmath.sty +// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf + +defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); +defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); +defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"); ////////////////////////////////////////////////////////////////////// +// braket.sty +// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf + +defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); +defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); +defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); +defineMacro("\\Bra", "\\left\\langle#1\\right|"); +defineMacro("\\Ket", "\\left|#1\\right\\rangle"); + +const braketHelper = one => context => { + const left = context.consumeArg().tokens; + const middle = context.consumeArg().tokens; + const middleDouble = context.consumeArg().tokens; + const right = context.consumeArg().tokens; + const oldMiddle = context.macros.get("|"); + const oldMiddleDouble = context.macros.get("\\|"); + context.macros.beginGroup(); + + const midMacro = double => context => { + if (one) { + // Only modify the first instance of | or \| + context.macros.set("|", oldMiddle); + + if (middleDouble.length) { + context.macros.set("\\|", oldMiddleDouble); + } + } + + let doubled = double; + + if (!double && middleDouble.length) { + // Mimic \@ifnextchar + const nextToken = context.future(); + + if (nextToken.text === "|") { + context.popToken(); + doubled = true; + } + } + + return { + tokens: doubled ? middleDouble : middle, + numArgs: 0 + }; + }; + + context.macros.set("|", midMacro(false)); + + if (middleDouble.length) { + context.macros.set("\\|", midMacro(true)); + } + + const arg = context.consumeArg().tokens; + const expanded = context.expandTokens([...right, ...arg, ...left // reversed + ]); + context.macros.endGroup(); + return { + tokens: expanded.reverse(), + numArgs: 0 + }; +}; + +defineMacro("\\bra@ket", braketHelper(false)); +defineMacro("\\bra@set", braketHelper(true)); +defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); +defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); +defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); // has no support for special || or \| +////////////////////////////////////////////////////////////////////// +// actuarialangle.dtx + +defineMacro("\\angln", "{\\angl n}"); // Custom Khan Academy colors, should be moved to an optional package + +defineMacro("\\blue", "\\textcolor{##6495ed}{#1}"); +defineMacro("\\orange", "\\textcolor{##ffa500}{#1}"); +defineMacro("\\pink", "\\textcolor{##ff00af}{#1}"); +defineMacro("\\red", "\\textcolor{##df0030}{#1}"); +defineMacro("\\green", "\\textcolor{##28ae7b}{#1}"); +defineMacro("\\gray", "\\textcolor{gray}{#1}"); +defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}"); +defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}"); +defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}"); +defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}"); +defineMacro("\\blueD", "\\textcolor{##11accd}{#1}"); +defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}"); +defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}"); +defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}"); +defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}"); +defineMacro("\\tealD", "\\textcolor{##01a995}{#1}"); +defineMacro("\\tealE", "\\textcolor{##208170}{#1}"); +defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}"); +defineMacro("\\greenB", "\\textcolor{##8af281}{#1}"); +defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}"); +defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}"); +defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}"); +defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}"); +defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}"); +defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}"); +defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}"); +defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}"); +defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}"); +defineMacro("\\redB", "\\textcolor{##ff8482}{#1}"); +defineMacro("\\redC", "\\textcolor{##f9685d}{#1}"); +defineMacro("\\redD", "\\textcolor{##e84d39}{#1}"); +defineMacro("\\redE", "\\textcolor{##bc2612}{#1}"); +defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}"); +defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}"); +defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}"); +defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}"); +defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}"); +defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}"); +defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}"); +defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}"); +defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}"); +defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}"); +defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}"); +defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}"); +defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}"); +defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}"); +defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}"); +defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}"); +defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}"); +defineMacro("\\grayE", "\\textcolor{##babec2}{#1}"); +defineMacro("\\grayF", "\\textcolor{##888d93}{#1}"); +defineMacro("\\grayG", "\\textcolor{##626569}{#1}"); +defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}"); +defineMacro("\\grayI", "\\textcolor{##21242c}{#1}"); +defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}"); +defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}"); +;// CONCATENATED MODULE: ./src/MacroExpander.js +/** + * This file contains the “gullet” where macros are expanded + * until only non-macro tokens remain. + */ + + + + + + + +// List of commands that act like macros but aren't defined as a macro, +// function, or symbol. Used in `isDefined`. +const implicitCommands = { + "^": true, + // Parser.js + "_": true, + // Parser.js + "\\limits": true, + // Parser.js + "\\nolimits": true // Parser.js + +}; +class MacroExpander { + constructor(input, settings, mode) { + this.settings = void 0; + this.expansionCount = void 0; + this.lexer = void 0; + this.macros = void 0; + this.stack = void 0; + this.mode = void 0; + this.settings = settings; + this.expansionCount = 0; + this.feed(input); // Make new global namespace + + this.macros = new Namespace(src_macros, settings.macros); + this.mode = mode; + this.stack = []; // contains tokens in REVERSE order + } + /** + * Feed a new input string to the same MacroExpander + * (with existing macros etc.). + */ + + + feed(input) { + this.lexer = new Lexer(input, this.settings); + } + /** + * Switches between "text" and "math" modes. + */ + + + switchMode(newMode) { + this.mode = newMode; + } + /** + * Start a new group nesting within all namespaces. + */ + + + beginGroup() { + this.macros.beginGroup(); + } + /** + * End current group nesting within all namespaces. + */ + + + endGroup() { + this.macros.endGroup(); + } + /** + * Ends all currently nested groups (if any), restoring values before the + * groups began. Useful in case of an error in the middle of parsing. + */ + + + endGroups() { + this.macros.endGroups(); + } + /** + * Returns the topmost token on the stack, without expanding it. + * Similar in behavior to TeX's `\futurelet`. + */ + + + future() { + if (this.stack.length === 0) { + this.pushToken(this.lexer.lex()); + } + + return this.stack[this.stack.length - 1]; + } + /** + * Remove and return the next unexpanded token. + */ + + + popToken() { + this.future(); // ensure non-empty stack + + return this.stack.pop(); + } + /** + * Add a given token to the token stack. In particular, this get be used + * to put back a token returned from one of the other methods. + */ + + + pushToken(token) { + this.stack.push(token); + } + /** + * Append an array of tokens to the token stack. + */ + + + pushTokens(tokens) { + this.stack.push(...tokens); + } + /** + * Find an macro argument without expanding tokens and append the array of + * tokens to the token stack. Uses Token as a container for the result. + */ + + + scanArgument(isOptional) { + let start; + let end; + let tokens; + + if (isOptional) { + this.consumeSpaces(); // \@ifnextchar gobbles any space following it + + if (this.future().text !== "[") { + return null; + } + + start = this.popToken(); // don't include [ in tokens + + ({ + tokens, + end + } = this.consumeArg(["]"])); + } else { + ({ + tokens, + start, + end + } = this.consumeArg()); + } // indicate the end of an argument + + + this.pushToken(new Token("EOF", end.loc)); + this.pushTokens(tokens); + return start.range(end, ""); + } + /** + * Consume all following space tokens, without expansion. + */ + + + consumeSpaces() { + for (;;) { + const token = this.future(); + + if (token.text === " ") { + this.stack.pop(); + } else { + break; + } + } + } + /** + * Consume an argument from the token stream, and return the resulting array + * of tokens and start/end token. + */ + + + consumeArg(delims) { + // The argument for a delimited parameter is the shortest (possibly + // empty) sequence of tokens with properly nested {...} groups that is + // followed ... by this particular list of non-parameter tokens. + // The argument for an undelimited parameter is the next nonblank + // token, unless that token is ‘{’, when the argument will be the + // entire {...} group that follows. + const tokens = []; + const isDelimited = delims && delims.length > 0; + + if (!isDelimited) { + // Ignore spaces between arguments. As the TeXbook says: + // "After you have said ‘\def\row#1#2{...}’, you are allowed to + // put spaces between the arguments (e.g., ‘\row x n’), because + // TeX doesn’t use single spaces as undelimited arguments." + this.consumeSpaces(); + } + + const start = this.future(); + let tok; + let depth = 0; + let match = 0; + + do { + tok = this.popToken(); + tokens.push(tok); + + if (tok.text === "{") { + ++depth; + } else if (tok.text === "}") { + --depth; + + if (depth === -1) { + throw new src_ParseError("Extra }", tok); + } + } else if (tok.text === "EOF") { + throw new src_ParseError("Unexpected end of input in a macro argument" + ", expected '" + (delims && isDelimited ? delims[match] : "}") + "'", tok); + } + + if (delims && isDelimited) { + if ((depth === 0 || depth === 1 && delims[match] === "{") && tok.text === delims[match]) { + ++match; + + if (match === delims.length) { + // don't include delims in tokens + tokens.splice(-match, match); + break; + } + } else { + match = 0; + } + } + } while (depth !== 0 || isDelimited); // If the argument found ... has the form ‘{}’, + // ... the outermost braces enclosing the argument are removed + + + if (start.text === "{" && tokens[tokens.length - 1].text === "}") { + tokens.pop(); + tokens.shift(); + } + + tokens.reverse(); // to fit in with stack order + + return { + tokens, + start, + end: tok + }; + } + /** + * Consume the specified number of (delimited) arguments from the token + * stream and return the resulting array of arguments. + */ + + + consumeArgs(numArgs, delimiters) { + if (delimiters) { + if (delimiters.length !== numArgs + 1) { + throw new src_ParseError("The length of delimiters doesn't match the number of args!"); + } + + const delims = delimiters[0]; + + for (let i = 0; i < delims.length; i++) { + const tok = this.popToken(); + + if (delims[i] !== tok.text) { + throw new src_ParseError("Use of the macro doesn't match its definition", tok); + } + } + } + + const args = []; + + for (let i = 0; i < numArgs; i++) { + args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens); + } + + return args; + } + /** + * Increment `expansionCount` by the specified amount. + * Throw an error if it exceeds `maxExpand`. + */ + + + countExpansion(amount) { + this.expansionCount += amount; + + if (this.expansionCount > this.settings.maxExpand) { + throw new src_ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting"); + } + } + /** + * Expand the next token only once if possible. + * + * If the token is expanded, the resulting tokens will be pushed onto + * the stack in reverse order, and the number of such tokens will be + * returned. This number might be zero or positive. + * + * If not, the return value is `false`, and the next token remains at the + * top of the stack. + * + * In either case, the next token will be on the top of the stack, + * or the stack will be empty (in case of empty expansion + * and no other tokens). + * + * Used to implement `expandAfterFuture` and `expandNextToken`. + * + * If expandableOnly, only expandable tokens are expanded and + * an undefined control sequence results in an error. + */ + + + expandOnce(expandableOnly) { + const topToken = this.popToken(); + const name = topToken.text; + const expansion = !topToken.noexpand ? this._getExpansion(name) : null; + + if (expansion == null || expandableOnly && expansion.unexpandable) { + if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { + throw new src_ParseError("Undefined control sequence: " + name); + } + + this.pushToken(topToken); + return false; + } + + this.countExpansion(1); + let tokens = expansion.tokens; + const args = this.consumeArgs(expansion.numArgs, expansion.delimiters); + + if (expansion.numArgs) { + // paste arguments in place of the placeholders + tokens = tokens.slice(); // make a shallow copy + + for (let i = tokens.length - 1; i >= 0; --i) { + let tok = tokens[i]; + + if (tok.text === "#") { + if (i === 0) { + throw new src_ParseError("Incomplete placeholder at end of macro body", tok); + } + + tok = tokens[--i]; // next token on stack + + if (tok.text === "#") { + // ## → # + tokens.splice(i + 1, 1); // drop first # + } else if (/^[1-9]$/.test(tok.text)) { + // replace the placeholder with the indicated argument + tokens.splice(i, 2, ...args[+tok.text - 1]); + } else { + throw new src_ParseError("Not a valid argument number", tok); + } + } + } + } // Concatenate expansion onto top of stack. + + + this.pushTokens(tokens); + return tokens.length; + } + /** + * Expand the next token only once (if possible), and return the resulting + * top token on the stack (without removing anything from the stack). + * Similar in behavior to TeX's `\expandafter\futurelet`. + * Equivalent to expandOnce() followed by future(). + */ + + + expandAfterFuture() { + this.expandOnce(); + return this.future(); + } + /** + * Recursively expand first token, then return first non-expandable token. + */ + + + expandNextToken() { + for (;;) { + if (this.expandOnce() === false) { + // fully expanded + const token = this.stack.pop(); // the token after \noexpand is interpreted as if its meaning + // were ‘\relax’ + + if (token.treatAsRelax) { + token.text = "\\relax"; + } + + return token; + } + } // Flow unable to figure out that this pathway is impossible. + // https://github.com/facebook/flow/issues/4808 + + + throw new Error(); // eslint-disable-line no-unreachable + } + /** + * Fully expand the given macro name and return the resulting list of + * tokens, or return `undefined` if no such macro is defined. + */ + + + expandMacro(name) { + return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; + } + /** + * Fully expand the given token stream and return the resulting list of + * tokens. Note that the input tokens are in reverse order, but the + * output tokens are in forward order. + */ + + + expandTokens(tokens) { + const output = []; + const oldStackLength = this.stack.length; + this.pushTokens(tokens); + + while (this.stack.length > oldStackLength) { + // Expand only expandable tokens + if (this.expandOnce(true) === false) { + // fully expanded + const token = this.stack.pop(); + + if (token.treatAsRelax) { + // the expansion of \noexpand is the token itself + token.noexpand = false; + token.treatAsRelax = false; + } + + output.push(token); + } + } // Count all of these tokens as additional expansions, to prevent + // exponential blowup from linearly many \edef's. + + + this.countExpansion(output.length); + return output; + } + /** + * Fully expand the given macro name and return the result as a string, + * or return `undefined` if no such macro is defined. + */ + + + expandMacroAsText(name) { + const tokens = this.expandMacro(name); + + if (tokens) { + return tokens.map(token => token.text).join(""); + } else { + return tokens; + } + } + /** + * Returns the expanded macro as a reversed array of tokens and a macro + * argument count. Or returns `null` if no such macro. + */ + + + _getExpansion(name) { + const definition = this.macros.get(name); + + if (definition == null) { + // mainly checking for undefined here + return definition; + } // If a single character has an associated catcode other than 13 + // (active character), then don't expand it. + + + if (name.length === 1) { + const catcode = this.lexer.catcodes[name]; + + if (catcode != null && catcode !== 13) { + return; + } + } + + const expansion = typeof definition === "function" ? definition(this) : definition; + + if (typeof expansion === "string") { + let numArgs = 0; + + if (expansion.indexOf("#") !== -1) { + const stripped = expansion.replace(/##/g, ""); + + while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { + ++numArgs; + } + } + + const bodyLexer = new Lexer(expansion, this.settings); + const tokens = []; + let tok = bodyLexer.lex(); + + while (tok.text !== "EOF") { + tokens.push(tok); + tok = bodyLexer.lex(); + } + + tokens.reverse(); // to fit in with stack using push and pop + + const expanded = { + tokens, + numArgs + }; + return expanded; + } + + return expansion; + } + /** + * Determine whether a command is currently "defined" (has some + * functionality), meaning that it's a macro (in the current group), + * a function, a symbol, or one of the special commands listed in + * `implicitCommands`. + */ + + + isDefined(name) { + return this.macros.has(name) || src_functions.hasOwnProperty(name) || src_symbols.math.hasOwnProperty(name) || src_symbols.text.hasOwnProperty(name) || implicitCommands.hasOwnProperty(name); + } + /** + * Determine whether a command is expandable. + */ + + + isExpandable(name) { + const macro = this.macros.get(name); + return macro != null ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable : src_functions.hasOwnProperty(name) && !src_functions[name].primitive; + } + +} +;// CONCATENATED MODULE: ./src/unicodeSupOrSub.js +// Helpers for Parser.js handling of Unicode (sub|super)script characters. +const unicodeSubRegEx = /^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/; +const uSubsAndSups = Object.freeze({ + '₊': '+', + '₋': '-', + '₌': '=', + '₍': '(', + '₎': ')', + '₀': '0', + '₁': '1', + '₂': '2', + '₃': '3', + '₄': '4', + '₅': '5', + '₆': '6', + '₇': '7', + '₈': '8', + '₉': '9', + '\u2090': 'a', + '\u2091': 'e', + '\u2095': 'h', + '\u1D62': 'i', + '\u2C7C': 'j', + '\u2096': 'k', + '\u2097': 'l', + '\u2098': 'm', + '\u2099': 'n', + '\u2092': 'o', + '\u209A': 'p', + '\u1D63': 'r', + '\u209B': 's', + '\u209C': 't', + '\u1D64': 'u', + '\u1D65': 'v', + '\u2093': 'x', + '\u1D66': 'β', + '\u1D67': 'γ', + '\u1D68': 'ρ', + '\u1D69': '\u03d5', + '\u1D6A': 'χ', + '⁺': '+', + '⁻': '-', + '⁼': '=', + '⁽': '(', + '⁾': ')', + '⁰': '0', + '¹': '1', + '²': '2', + '³': '3', + '⁴': '4', + '⁵': '5', + '⁶': '6', + '⁷': '7', + '⁸': '8', + '⁹': '9', + '\u1D2C': 'A', + '\u1D2E': 'B', + '\u1D30': 'D', + '\u1D31': 'E', + '\u1D33': 'G', + '\u1D34': 'H', + '\u1D35': 'I', + '\u1D36': 'J', + '\u1D37': 'K', + '\u1D38': 'L', + '\u1D39': 'M', + '\u1D3A': 'N', + '\u1D3C': 'O', + '\u1D3E': 'P', + '\u1D3F': 'R', + '\u1D40': 'T', + '\u1D41': 'U', + '\u2C7D': 'V', + '\u1D42': 'W', + '\u1D43': 'a', + '\u1D47': 'b', + '\u1D9C': 'c', + '\u1D48': 'd', + '\u1D49': 'e', + '\u1DA0': 'f', + '\u1D4D': 'g', + '\u02B0': 'h', + '\u2071': 'i', + '\u02B2': 'j', + '\u1D4F': 'k', + '\u02E1': 'l', + '\u1D50': 'm', + '\u207F': 'n', + '\u1D52': 'o', + '\u1D56': 'p', + '\u02B3': 'r', + '\u02E2': 's', + '\u1D57': 't', + '\u1D58': 'u', + '\u1D5B': 'v', + '\u02B7': 'w', + '\u02E3': 'x', + '\u02B8': 'y', + '\u1DBB': 'z', + '\u1D5D': 'β', + '\u1D5E': 'γ', + '\u1D5F': 'δ', + '\u1D60': '\u03d5', + '\u1D61': 'χ', + '\u1DBF': 'θ' +}); +;// CONCATENATED MODULE: ./src/Parser.js +/* eslint no-constant-condition:0 */ + + + + + + + + + + + // Pre-evaluate both modules as unicodeSymbols require String.normalize() + +const unicodeAccents = { + "́": { + "text": "\\'", + "math": "\\acute" + }, + "̀": { + "text": "\\`", + "math": "\\grave" + }, + "̈": { + "text": "\\\"", + "math": "\\ddot" + }, + "̃": { + "text": "\\~", + "math": "\\tilde" + }, + "̄": { + "text": "\\=", + "math": "\\bar" + }, + "̆": { + "text": "\\u", + "math": "\\breve" + }, + "̌": { + "text": "\\v", + "math": "\\check" + }, + "̂": { + "text": "\\^", + "math": "\\hat" + }, + "̇": { + "text": "\\.", + "math": "\\dot" + }, + "̊": { + "text": "\\r", + "math": "\\mathring" + }, + "̋": { + "text": "\\H" + }, + "̧": { + "text": "\\c" + } +}; +const unicodeSymbols = { + "á": "á", + "à": "à", + "ä": "ä", + "ǟ": "ǟ", + "ã": "ã", + "ā": "ā", + "ă": "ă", + "ắ": "ắ", + "ằ": "ằ", + "ẵ": "ẵ", + "ǎ": "ǎ", + "â": "â", + "ấ": "ấ", + "ầ": "ầ", + "ẫ": "ẫ", + "ȧ": "ȧ", + "ǡ": "ǡ", + "å": "å", + "ǻ": "ǻ", + "ḃ": "ḃ", + "ć": "ć", + "ḉ": "ḉ", + "č": "č", + "ĉ": "ĉ", + "ċ": "ċ", + "ç": "ç", + "ď": "ď", + "ḋ": "ḋ", + "ḑ": "ḑ", + "é": "é", + "è": "è", + "ë": "ë", + "ẽ": "ẽ", + "ē": "ē", + "ḗ": "ḗ", + "ḕ": "ḕ", + "ĕ": "ĕ", + "ḝ": "ḝ", + "ě": "ě", + "ê": "ê", + "ế": "ế", + "ề": "ề", + "ễ": "ễ", + "ė": "ė", + "ȩ": "ȩ", + "ḟ": "ḟ", + "ǵ": "ǵ", + "ḡ": "ḡ", + "ğ": "ğ", + "ǧ": "ǧ", + "ĝ": "ĝ", + "ġ": "ġ", + "ģ": "ģ", + "ḧ": "ḧ", + "ȟ": "ȟ", + "ĥ": "ĥ", + "ḣ": "ḣ", + "ḩ": "ḩ", + "í": "í", + "ì": "ì", + "ï": "ï", + "ḯ": "ḯ", + "ĩ": "ĩ", + "ī": "ī", + "ĭ": "ĭ", + "ǐ": "ǐ", + "î": "î", + "ǰ": "ǰ", + "ĵ": "ĵ", + "ḱ": "ḱ", + "ǩ": "ǩ", + "ķ": "ķ", + "ĺ": "ĺ", + "ľ": "ľ", + "ļ": "ļ", + "ḿ": "ḿ", + "ṁ": "ṁ", + "ń": "ń", + "ǹ": "ǹ", + "ñ": "ñ", + "ň": "ň", + "ṅ": "ṅ", + "ņ": "ņ", + "ó": "ó", + "ò": "ò", + "ö": "ö", + "ȫ": "ȫ", + "õ": "õ", + "ṍ": "ṍ", + "ṏ": "ṏ", + "ȭ": "ȭ", + "ō": "ō", + "ṓ": "ṓ", + "ṑ": "ṑ", + "ŏ": "ŏ", + "ǒ": "ǒ", + "ô": "ô", + "ố": "ố", + "ồ": "ồ", + "ỗ": "ỗ", + "ȯ": "ȯ", + "ȱ": "ȱ", + "ő": "ő", + "ṕ": "ṕ", + "ṗ": "ṗ", + "ŕ": "ŕ", + "ř": "ř", + "ṙ": "ṙ", + "ŗ": "ŗ", + "ś": "ś", + "ṥ": "ṥ", + "š": "š", + "ṧ": "ṧ", + "ŝ": "ŝ", + "ṡ": "ṡ", + "ş": "ş", + "ẗ": "ẗ", + "ť": "ť", + "ṫ": "ṫ", + "ţ": "ţ", + "ú": "ú", + "ù": "ù", + "ü": "ü", + "ǘ": "ǘ", + "ǜ": "ǜ", + "ǖ": "ǖ", + "ǚ": "ǚ", + "ũ": "ũ", + "ṹ": "ṹ", + "ū": "ū", + "ṻ": "ṻ", + "ŭ": "ŭ", + "ǔ": "ǔ", + "û": "û", + "ů": "ů", + "ű": "ű", + "ṽ": "ṽ", + "ẃ": "ẃ", + "ẁ": "ẁ", + "ẅ": "ẅ", + "ŵ": "ŵ", + "ẇ": "ẇ", + "ẘ": "ẘ", + "ẍ": "ẍ", + "ẋ": "ẋ", + "ý": "ý", + "ỳ": "ỳ", + "ÿ": "ÿ", + "ỹ": "ỹ", + "ȳ": "ȳ", + "ŷ": "ŷ", + "ẏ": "ẏ", + "ẙ": "ẙ", + "ź": "ź", + "ž": "ž", + "ẑ": "ẑ", + "ż": "ż", + "Á": "Á", + "À": "À", + "Ä": "Ä", + "Ǟ": "Ǟ", + "Ã": "Ã", + "Ā": "Ā", + "Ă": "Ă", + "Ắ": "Ắ", + "Ằ": "Ằ", + "Ẵ": "Ẵ", + "Ǎ": "Ǎ", + "Â": "Â", + "Ấ": "Ấ", + "Ầ": "Ầ", + "Ẫ": "Ẫ", + "Ȧ": "Ȧ", + "Ǡ": "Ǡ", + "Å": "Å", + "Ǻ": "Ǻ", + "Ḃ": "Ḃ", + "Ć": "Ć", + "Ḉ": "Ḉ", + "Č": "Č", + "Ĉ": "Ĉ", + "Ċ": "Ċ", + "Ç": "Ç", + "Ď": "Ď", + "Ḋ": "Ḋ", + "Ḑ": "Ḑ", + "É": "É", + "È": "È", + "Ë": "Ë", + "Ẽ": "Ẽ", + "Ē": "Ē", + "Ḗ": "Ḗ", + "Ḕ": "Ḕ", + "Ĕ": "Ĕ", + "Ḝ": "Ḝ", + "Ě": "Ě", + "Ê": "Ê", + "Ế": "Ế", + "Ề": "Ề", + "Ễ": "Ễ", + "Ė": "Ė", + "Ȩ": "Ȩ", + "Ḟ": "Ḟ", + "Ǵ": "Ǵ", + "Ḡ": "Ḡ", + "Ğ": "Ğ", + "Ǧ": "Ǧ", + "Ĝ": "Ĝ", + "Ġ": "Ġ", + "Ģ": "Ģ", + "Ḧ": "Ḧ", + "Ȟ": "Ȟ", + "Ĥ": "Ĥ", + "Ḣ": "Ḣ", + "Ḩ": "Ḩ", + "Í": "Í", + "Ì": "Ì", + "Ï": "Ï", + "Ḯ": "Ḯ", + "Ĩ": "Ĩ", + "Ī": "Ī", + "Ĭ": "Ĭ", + "Ǐ": "Ǐ", + "Î": "Î", + "İ": "İ", + "Ĵ": "Ĵ", + "Ḱ": "Ḱ", + "Ǩ": "Ǩ", + "Ķ": "Ķ", + "Ĺ": "Ĺ", + "Ľ": "Ľ", + "Ļ": "Ļ", + "Ḿ": "Ḿ", + "Ṁ": "Ṁ", + "Ń": "Ń", + "Ǹ": "Ǹ", + "Ñ": "Ñ", + "Ň": "Ň", + "Ṅ": "Ṅ", + "Ņ": "Ņ", + "Ó": "Ó", + "Ò": "Ò", + "Ö": "Ö", + "Ȫ": "Ȫ", + "Õ": "Õ", + "Ṍ": "Ṍ", + "Ṏ": "Ṏ", + "Ȭ": "Ȭ", + "Ō": "Ō", + "Ṓ": "Ṓ", + "Ṑ": "Ṑ", + "Ŏ": "Ŏ", + "Ǒ": "Ǒ", + "Ô": "Ô", + "Ố": "Ố", + "Ồ": "Ồ", + "Ỗ": "Ỗ", + "Ȯ": "Ȯ", + "Ȱ": "Ȱ", + "Ő": "Ő", + "Ṕ": "Ṕ", + "Ṗ": "Ṗ", + "Ŕ": "Ŕ", + "Ř": "Ř", + "Ṙ": "Ṙ", + "Ŗ": "Ŗ", + "Ś": "Ś", + "Ṥ": "Ṥ", + "Š": "Š", + "Ṧ": "Ṧ", + "Ŝ": "Ŝ", + "Ṡ": "Ṡ", + "Ş": "Ş", + "Ť": "Ť", + "Ṫ": "Ṫ", + "Ţ": "Ţ", + "Ú": "Ú", + "Ù": "Ù", + "Ü": "Ü", + "Ǘ": "Ǘ", + "Ǜ": "Ǜ", + "Ǖ": "Ǖ", + "Ǚ": "Ǚ", + "Ũ": "Ũ", + "Ṹ": "Ṹ", + "Ū": "Ū", + "Ṻ": "Ṻ", + "Ŭ": "Ŭ", + "Ǔ": "Ǔ", + "Û": "Û", + "Ů": "Ů", + "Ű": "Ű", + "Ṽ": "Ṽ", + "Ẃ": "Ẃ", + "Ẁ": "Ẁ", + "Ẅ": "Ẅ", + "Ŵ": "Ŵ", + "Ẇ": "Ẇ", + "Ẍ": "Ẍ", + "Ẋ": "Ẋ", + "Ý": "Ý", + "Ỳ": "Ỳ", + "Ÿ": "Ÿ", + "Ỹ": "Ỹ", + "Ȳ": "Ȳ", + "Ŷ": "Ŷ", + "Ẏ": "Ẏ", + "Ź": "Ź", + "Ž": "Ž", + "Ẑ": "Ẑ", + "Ż": "Ż", + "ά": "ά", + "ὰ": "ὰ", + "ᾱ": "ᾱ", + "ᾰ": "ᾰ", + "έ": "έ", + "ὲ": "ὲ", + "ή": "ή", + "ὴ": "ὴ", + "ί": "ί", + "ὶ": "ὶ", + "ϊ": "ϊ", + "ΐ": "ΐ", + "ῒ": "ῒ", + "ῑ": "ῑ", + "ῐ": "ῐ", + "ό": "ό", + "ὸ": "ὸ", + "ύ": "ύ", + "ὺ": "ὺ", + "ϋ": "ϋ", + "ΰ": "ΰ", + "ῢ": "ῢ", + "ῡ": "ῡ", + "ῠ": "ῠ", + "ώ": "ώ", + "ὼ": "ὼ", + "Ύ": "Ύ", + "Ὺ": "Ὺ", + "Ϋ": "Ϋ", + "Ῡ": "Ῡ", + "Ῠ": "Ῠ", + "Ώ": "Ώ", + "Ὼ": "Ὼ" +}; + +/** + * This file contains the parser used to parse out a TeX expression from the + * input. Since TeX isn't context-free, standard parsers don't work particularly + * well. + * + * The strategy of this parser is as such: + * + * The main functions (the `.parse...` ones) take a position in the current + * parse string to parse tokens from. The lexer (found in Lexer.js, stored at + * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When + * individual tokens are needed at a position, the lexer is called to pull out a + * token, which is then used. + * + * The parser has a property called "mode" indicating the mode that + * the parser is currently in. Currently it has to be one of "math" or + * "text", which denotes whether the current environment is a math-y + * one or a text-y one (e.g. inside \text). Currently, this serves to + * limit the functions which can be used in text mode. + * + * The main functions then return an object which contains the useful data that + * was parsed at its given point, and a new position at the end of the parsed + * data. The main functions can call each other and continue the parsing by + * using the returned position as a new starting point. + * + * There are also extra `.handle...` functions, which pull out some reused + * functionality into self-contained functions. + * + * The functions return ParseNodes. + */ +class Parser { + constructor(input, settings) { + this.mode = void 0; + this.gullet = void 0; + this.settings = void 0; + this.leftrightDepth = void 0; + this.nextToken = void 0; + // Start in math mode + this.mode = "math"; // Create a new macro expander (gullet) and (indirectly via that) also a + // new lexer (mouth) for this parser (stomach, in the language of TeX) + + this.gullet = new MacroExpander(input, settings, this.mode); // Store the settings for use in parsing + + this.settings = settings; // Count leftright depth (for \middle errors) + + this.leftrightDepth = 0; + } + /** + * Checks a result to make sure it has the right type, and throws an + * appropriate error otherwise. + */ + + + expect(text, consume) { + if (consume === void 0) { + consume = true; + } + + if (this.fetch().text !== text) { + throw new src_ParseError("Expected '" + text + "', got '" + this.fetch().text + "'", this.fetch()); + } + + if (consume) { + this.consume(); + } + } + /** + * Discards the current lookahead token, considering it consumed. + */ + + + consume() { + this.nextToken = null; + } + /** + * Return the current lookahead token, or if there isn't one (at the + * beginning, or if the previous lookahead token was consume()d), + * fetch the next token as the new lookahead token and return it. + */ + + + fetch() { + if (this.nextToken == null) { + this.nextToken = this.gullet.expandNextToken(); + } + + return this.nextToken; + } + /** + * Switches between "text" and "math" modes. + */ + + + switchMode(newMode) { + this.mode = newMode; + this.gullet.switchMode(newMode); + } + /** + * Main parsing function, which parses an entire input. + */ + + + parse() { + if (!this.settings.globalGroup) { + // Create a group namespace for the math expression. + // (LaTeX creates a new group for every $...$, $$...$$, \[...\].) + this.gullet.beginGroup(); + } // Use old \color behavior (same as LaTeX's \textcolor) if requested. + // We do this within the group for the math expression, so it doesn't + // pollute settings.macros. + + + if (this.settings.colorIsTextColor) { + this.gullet.macros.set("\\color", "\\textcolor"); + } + + try { + // Try to parse the input + const parse = this.parseExpression(false); // If we succeeded, make sure there's an EOF at the end + + this.expect("EOF"); // End the group namespace for the expression + + if (!this.settings.globalGroup) { + this.gullet.endGroup(); + } + + return parse; // Close any leftover groups in case of a parse error. + } finally { + this.gullet.endGroups(); + } + } + /** + * Fully parse a separate sequence of tokens as a separate job. + * Tokens should be specified in reverse order, as in a MacroDefinition. + */ + + + subparse(tokens) { + // Save the next token from the current job. + const oldToken = this.nextToken; + this.consume(); // Run the new job, terminating it with an excess '}' + + this.gullet.pushToken(new Token("}")); + this.gullet.pushTokens(tokens); + const parse = this.parseExpression(false); + this.expect("}"); // Restore the next token from the current job. + + this.nextToken = oldToken; + return parse; + } + + /** + * Parses an "expression", which is a list of atoms. + * + * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This + * happens when functions have higher precedence han infix + * nodes in implicit parses. + * + * `breakOnTokenText`: The text of the token that the expression should end + * with, or `null` if something else should end the + * expression. + */ + parseExpression(breakOnInfix, breakOnTokenText) { + const body = []; // Keep adding atoms to the body until we can't parse any more atoms (either + // we reached the end, a }, or a \right) + + while (true) { + // Ignore spaces in math mode + if (this.mode === "math") { + this.consumeSpaces(); + } + + const lex = this.fetch(); + + if (Parser.endOfExpression.indexOf(lex.text) !== -1) { + break; + } + + if (breakOnTokenText && lex.text === breakOnTokenText) { + break; + } + + if (breakOnInfix && src_functions[lex.text] && src_functions[lex.text].infix) { + break; + } + + const atom = this.parseAtom(breakOnTokenText); + + if (!atom) { + break; + } else if (atom.type === "internal") { + // Internal nodes do not appear in parse tree + continue; + } + + body.push(atom); + } + + if (this.mode === "text") { + this.formLigatures(body); + } + + return this.handleInfixNodes(body); + } + /** + * Rewrites infix operators such as \over with corresponding commands such + * as \frac. + * + * There can only be one infix operator per group. If there's more than one + * then the expression is ambiguous. This can be resolved by adding {}. + */ + + + handleInfixNodes(body) { + let overIndex = -1; + let funcName; + + for (let i = 0; i < body.length; i++) { + if (body[i].type === "infix") { + if (overIndex !== -1) { + throw new src_ParseError("only one infix operator per group", body[i].token); + } + + overIndex = i; + funcName = body[i].replaceWith; + } + } + + if (overIndex !== -1 && funcName) { + let numerNode; + let denomNode; + const numerBody = body.slice(0, overIndex); + const denomBody = body.slice(overIndex + 1); + + if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { + numerNode = numerBody[0]; + } else { + numerNode = { + type: "ordgroup", + mode: this.mode, + body: numerBody + }; + } + + if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { + denomNode = denomBody[0]; + } else { + denomNode = { + type: "ordgroup", + mode: this.mode, + body: denomBody + }; + } + + let node; + + if (funcName === "\\\\abovefrac") { + node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); + } else { + node = this.callFunction(funcName, [numerNode, denomNode], []); + } + + return [node]; + } else { + return body; + } + } + /** + * Handle a subscript or superscript with nice errors. + */ + + + handleSupSubscript(name // For error reporting. + ) { + const symbolToken = this.fetch(); + const symbol = symbolToken.text; + this.consume(); + this.consumeSpaces(); // ignore spaces before sup/subscript argument + // Skip over allowed internal nodes such as \relax + + let group; + + do { + var _group; + + group = this.parseGroup(name); + } while (((_group = group) == null ? void 0 : _group.type) === "internal"); + + if (!group) { + throw new src_ParseError("Expected group after '" + symbol + "'", symbolToken); + } + + return group; + } + /** + * Converts the textual input of an unsupported command into a text node + * contained within a color node whose color is determined by errorColor + */ + + + formatUnsupportedCmd(text) { + const textordArray = []; + + for (let i = 0; i < text.length; i++) { + textordArray.push({ + type: "textord", + mode: "text", + text: text[i] + }); + } + + const textNode = { + type: "text", + mode: this.mode, + body: textordArray + }; + const colorNode = { + type: "color", + mode: this.mode, + color: this.settings.errorColor, + body: [textNode] + }; + return colorNode; + } + /** + * Parses a group with optional super/subscripts. + */ + + + parseAtom(breakOnTokenText) { + // The body of an atom is an implicit group, so that things like + // \left(x\right)^2 work correctly. + const base = this.parseGroup("atom", breakOnTokenText); // Internal nodes (e.g. \relax) cannot support super/subscripts. + // Instead we will pick up super/subscripts with blank base next round. + + if ((base == null ? void 0 : base.type) === "internal") { + return base; + } // In text mode, we don't have superscripts or subscripts + + + if (this.mode === "text") { + return base; + } // Note that base may be empty (i.e. null) at this point. + + + let superscript; + let subscript; + + while (true) { + // Guaranteed in math mode, so eat any spaces first. + this.consumeSpaces(); // Lex the first token + + const lex = this.fetch(); + + if (lex.text === "\\limits" || lex.text === "\\nolimits") { + // We got a limit control + if (base && base.type === "op") { + const limits = lex.text === "\\limits"; + base.limits = limits; + base.alwaysHandleSupSub = true; + } else if (base && base.type === "operatorname") { + if (base.alwaysHandleSupSub) { + base.limits = lex.text === "\\limits"; + } + } else { + throw new src_ParseError("Limit controls must follow a math operator", lex); + } + + this.consume(); + } else if (lex.text === "^") { + // We got a superscript start + if (superscript) { + throw new src_ParseError("Double superscript", lex); + } + + superscript = this.handleSupSubscript("superscript"); + } else if (lex.text === "_") { + // We got a subscript start + if (subscript) { + throw new src_ParseError("Double subscript", lex); + } + + subscript = this.handleSupSubscript("subscript"); + } else if (lex.text === "'") { + // We got a prime + if (superscript) { + throw new src_ParseError("Double superscript", lex); + } + + const prime = { + type: "textord", + mode: this.mode, + text: "\\prime" + }; // Many primes can be grouped together, so we handle this here + + const primes = [prime]; + this.consume(); // Keep lexing tokens until we get something that's not a prime + + while (this.fetch().text === "'") { + // For each one, add another prime to the list + primes.push(prime); + this.consume(); + } // If there's a superscript following the primes, combine that + // superscript in with the primes. + + + if (this.fetch().text === "^") { + primes.push(this.handleSupSubscript("superscript")); + } // Put everything into an ordgroup as the superscript + + + superscript = { + type: "ordgroup", + mode: this.mode, + body: primes + }; + } else if (uSubsAndSups[lex.text]) { + // A Unicode subscript or superscript character. + // We treat these similarly to the unicode-math package. + // So we render a string of Unicode (sub|super)scripts the + // same as a (sub|super)script of regular characters. + const isSub = unicodeSubRegEx.test(lex.text); + const subsupTokens = []; + subsupTokens.push(new Token(uSubsAndSups[lex.text])); + this.consume(); // Continue fetching tokens to fill out the string. + + while (true) { + const token = this.fetch().text; + + if (!uSubsAndSups[token]) { + break; + } + + if (unicodeSubRegEx.test(token) !== isSub) { + break; + } + + subsupTokens.unshift(new Token(uSubsAndSups[token])); + this.consume(); + } // Now create a (sub|super)script. + + + const body = this.subparse(subsupTokens); + + if (isSub) { + subscript = { + type: "ordgroup", + mode: "math", + body + }; + } else { + superscript = { + type: "ordgroup", + mode: "math", + body + }; + } + } else { + // If it wasn't ^, _, or ', stop parsing super/subscripts + break; + } + } // Base must be set if superscript or subscript are set per logic above, + // but need to check here for type check to pass. + + + if (superscript || subscript) { + // If we got either a superscript or subscript, create a supsub + return { + type: "supsub", + mode: this.mode, + base: base, + sup: superscript, + sub: subscript + }; + } else { + // Otherwise return the original body + return base; + } + } + /** + * Parses an entire function, including its base and all of its arguments. + */ + + + parseFunction(breakOnTokenText, name // For determining its context + ) { + const token = this.fetch(); + const func = token.text; + const funcData = src_functions[func]; + + if (!funcData) { + return null; + } + + this.consume(); // consume command token + + if (name && name !== "atom" && !funcData.allowedInArgument) { + throw new src_ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token); + } else if (this.mode === "text" && !funcData.allowedInText) { + throw new src_ParseError("Can't use function '" + func + "' in text mode", token); + } else if (this.mode === "math" && funcData.allowedInMath === false) { + throw new src_ParseError("Can't use function '" + func + "' in math mode", token); + } + + const { + args, + optArgs + } = this.parseArguments(func, funcData); + return this.callFunction(func, args, optArgs, token, breakOnTokenText); + } + /** + * Call a function handler with a suitable context and arguments. + */ + + + callFunction(name, args, optArgs, token, breakOnTokenText) { + const context = { + funcName: name, + parser: this, + token, + breakOnTokenText + }; + const func = src_functions[name]; + + if (func && func.handler) { + return func.handler(context, args, optArgs); + } else { + throw new src_ParseError("No function handler for " + name); + } + } + /** + * Parses the arguments of a function or environment + */ + + + parseArguments(func, // Should look like "\name" or "\begin{name}". + funcData) { + const totalArgs = funcData.numArgs + funcData.numOptionalArgs; + + if (totalArgs === 0) { + return { + args: [], + optArgs: [] + }; + } + + const args = []; + const optArgs = []; + + for (let i = 0; i < totalArgs; i++) { + let argType = funcData.argTypes && funcData.argTypes[i]; + const isOptional = i < funcData.numOptionalArgs; + + if (funcData.primitive && argType == null || // \sqrt expands into primitive if optional argument doesn't exist + funcData.type === "sqrt" && i === 1 && optArgs[0] == null) { + argType = "primitive"; + } + + const arg = this.parseGroupOfType("argument to '" + func + "'", argType, isOptional); + + if (isOptional) { + optArgs.push(arg); + } else if (arg != null) { + args.push(arg); + } else { + // should be unreachable + throw new src_ParseError("Null argument, please report this as a bug"); + } + } + + return { + args, + optArgs + }; + } + /** + * Parses a group when the mode is changing. + */ + + + parseGroupOfType(name, type, optional) { + switch (type) { + case "color": + return this.parseColorGroup(optional); + + case "size": + return this.parseSizeGroup(optional); + + case "url": + return this.parseUrlGroup(optional); + + case "math": + case "text": + return this.parseArgumentGroup(optional, type); + + case "hbox": + { + // hbox argument type wraps the argument in the equivalent of + // \hbox, which is like \text but switching to \textstyle size. + const group = this.parseArgumentGroup(optional, "text"); + return group != null ? { + type: "styling", + mode: group.mode, + body: [group], + style: "text" // simulate \textstyle + + } : null; + } + + case "raw": + { + const token = this.parseStringGroup("raw", optional); + return token != null ? { + type: "raw", + mode: "text", + string: token.text + } : null; + } + + case "primitive": + { + if (optional) { + throw new src_ParseError("A primitive argument cannot be optional"); + } + + const group = this.parseGroup(name); + + if (group == null) { + throw new src_ParseError("Expected group as " + name, this.fetch()); + } + + return group; + } + + case "original": + case null: + case undefined: + return this.parseArgumentGroup(optional); + + default: + throw new src_ParseError("Unknown group type as " + name, this.fetch()); + } + } + /** + * Discard any space tokens, fetching the next non-space token. + */ + + + consumeSpaces() { + while (this.fetch().text === " ") { + this.consume(); + } + } + /** + * Parses a group, essentially returning the string formed by the + * brace-enclosed tokens plus some position information. + */ + + + parseStringGroup(modeName, // Used to describe the mode in error messages. + optional) { + const argToken = this.gullet.scanArgument(optional); + + if (argToken == null) { + return null; + } + + let str = ""; + let nextToken; + + while ((nextToken = this.fetch()).text !== "EOF") { + str += nextToken.text; + this.consume(); + } + + this.consume(); // consume the end of the argument + + argToken.text = str; + return argToken; + } + /** + * Parses a regex-delimited group: the largest sequence of tokens + * whose concatenated strings match `regex`. Returns the string + * formed by the tokens plus some position information. + */ + + + parseRegexGroup(regex, modeName // Used to describe the mode in error messages. + ) { + const firstToken = this.fetch(); + let lastToken = firstToken; + let str = ""; + let nextToken; + + while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { + lastToken = nextToken; + str += lastToken.text; + this.consume(); + } + + if (str === "") { + throw new src_ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); + } + + return firstToken.range(lastToken, str); + } + /** + * Parses a color description. + */ + + + parseColorGroup(optional) { + const res = this.parseStringGroup("color", optional); + + if (res == null) { + return null; + } + + const match = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(res.text); + + if (!match) { + throw new src_ParseError("Invalid color: '" + res.text + "'", res); + } + + let color = match[0]; + + if (/^[0-9a-f]{6}$/i.test(color)) { + // We allow a 6-digit HTML color spec without a leading "#". + // This follows the xcolor package's HTML color model. + // Predefined color names are all missed by this RegEx pattern. + color = "#" + color; + } + + return { + type: "color-token", + mode: this.mode, + color + }; + } + /** + * Parses a size specification, consisting of magnitude and unit. + */ + + + parseSizeGroup(optional) { + let res; + let isBlank = false; // don't expand before parseStringGroup + + this.gullet.consumeSpaces(); + + if (!optional && this.gullet.future().text !== "{") { + res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); + } else { + res = this.parseStringGroup("size", optional); + } + + if (!res) { + return null; + } + + if (!optional && res.text.length === 0) { + // Because we've tested for what is !optional, this block won't + // affect \kern, \hspace, etc. It will capture the mandatory arguments + // to \genfrac and \above. + res.text = "0pt"; // Enable \above{} + + isBlank = true; // This is here specifically for \genfrac + } + + const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); + + if (!match) { + throw new src_ParseError("Invalid size: '" + res.text + "'", res); + } + + const data = { + number: +(match[1] + match[2]), + // sign + magnitude, cast to number + unit: match[3] + }; + + if (!validUnit(data)) { + throw new src_ParseError("Invalid unit: '" + data.unit + "'", res); + } + + return { + type: "size", + mode: this.mode, + value: data, + isBlank + }; + } + /** + * Parses an URL, checking escaped letters and allowed protocols, + * and setting the catcode of % as an active character (as in \hyperref). + */ + + + parseUrlGroup(optional) { + this.gullet.lexer.setCatcode("%", 13); // active character + + this.gullet.lexer.setCatcode("~", 12); // other character + + const res = this.parseStringGroup("url", optional); + this.gullet.lexer.setCatcode("%", 14); // comment character + + this.gullet.lexer.setCatcode("~", 13); // active character + + if (res == null) { + return null; + } // hyperref package allows backslashes alone in href, but doesn't + // generate valid links in such cases; we interpret this as + // "undefined" behaviour, and keep them as-is. Some browser will + // replace backslashes with forward slashes. + + + const url = res.text.replace(/\\([#$%&~_^{}])/g, '$1'); + return { + type: "url", + mode: this.mode, + url + }; + } + /** + * Parses an argument with the mode specified. + */ + + + parseArgumentGroup(optional, mode) { + const argToken = this.gullet.scanArgument(optional); + + if (argToken == null) { + return null; + } + + const outerMode = this.mode; + + if (mode) { + // Switch to specified mode + this.switchMode(mode); + } + + this.gullet.beginGroup(); + const expression = this.parseExpression(false, "EOF"); // TODO: find an alternative way to denote the end + + this.expect("EOF"); // expect the end of the argument + + this.gullet.endGroup(); + const result = { + type: "ordgroup", + mode: this.mode, + loc: argToken.loc, + body: expression + }; + + if (mode) { + // Switch mode back + this.switchMode(outerMode); + } + + return result; + } + /** + * Parses an ordinary group, which is either a single nucleus (like "x") + * or an expression in braces (like "{x+y}") or an implicit group, a group + * that starts at the current position, and ends right before a higher explicit + * group ends, or at EOF. + */ + + + parseGroup(name, // For error reporting. + breakOnTokenText) { + const firstToken = this.fetch(); + const text = firstToken.text; + let result; // Try to parse an open brace or \begingroup + + if (text === "{" || text === "\\begingroup") { + this.consume(); + const groupEnd = text === "{" ? "}" : "\\endgroup"; + this.gullet.beginGroup(); // If we get a brace, parse an expression + + const expression = this.parseExpression(false, groupEnd); + const lastToken = this.fetch(); + this.expect(groupEnd); // Check that we got a matching closing brace + + this.gullet.endGroup(); + result = { + type: "ordgroup", + mode: this.mode, + loc: SourceLocation.range(firstToken, lastToken), + body: expression, + // A group formed by \begingroup...\endgroup is a semi-simple group + // which doesn't affect spacing in math mode, i.e., is transparent. + // https://tex.stackexchange.com/questions/1930/when-should-one- + // use-begingroup-instead-of-bgroup + semisimple: text === "\\begingroup" || undefined + }; + } else { + // If there exists a function with this name, parse the function. + // Otherwise, just return a nucleus + result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); + + if (result == null && text[0] === "\\" && !implicitCommands.hasOwnProperty(text)) { + if (this.settings.throwOnError) { + throw new src_ParseError("Undefined control sequence: " + text, firstToken); + } + + result = this.formatUnsupportedCmd(text); + this.consume(); + } + } + + return result; + } + /** + * Form ligature-like combinations of characters for text mode. + * This includes inputs like "--", "---", "``" and "''". + * The result will simply replace multiple textord nodes with a single + * character in each value by a single textord node having multiple + * characters in its value. The representation is still ASCII source. + * The group will be modified in place. + */ + + + formLigatures(group) { + let n = group.length - 1; + + for (let i = 0; i < n; ++i) { + const a = group[i]; // $FlowFixMe: Not every node type has a `text` property. + + const v = a.text; + + if (v === "-" && group[i + 1].text === "-") { + if (i + 1 < n && group[i + 2].text === "-") { + group.splice(i, 3, { + type: "textord", + mode: "text", + loc: SourceLocation.range(a, group[i + 2]), + text: "---" + }); + n -= 2; + } else { + group.splice(i, 2, { + type: "textord", + mode: "text", + loc: SourceLocation.range(a, group[i + 1]), + text: "--" + }); + n -= 1; + } + } + + if ((v === "'" || v === "`") && group[i + 1].text === v) { + group.splice(i, 2, { + type: "textord", + mode: "text", + loc: SourceLocation.range(a, group[i + 1]), + text: v + v + }); + n -= 1; + } + } + } + /** + * Parse a single symbol out of the string. Here, we handle single character + * symbols and special functions like \verb. + */ + + + parseSymbol() { + const nucleus = this.fetch(); + let text = nucleus.text; + + if (/^\\verb[^a-zA-Z]/.test(text)) { + this.consume(); + let arg = text.slice(5); + const star = arg.charAt(0) === "*"; + + if (star) { + arg = arg.slice(1); + } // Lexer's tokenRegex is constructed to always have matching + // first/last characters. + + + if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { + throw new src_ParseError("\\verb assertion failed --\n please report what input caused this bug"); + } + + arg = arg.slice(1, -1); // remove first and last char + + return { + type: "verb", + mode: "text", + body: arg, + star + }; + } // At this point, we should have a symbol, possibly with accents. + // First expand any accented base symbol according to unicodeSymbols. + + + if (unicodeSymbols.hasOwnProperty(text[0]) && !src_symbols[this.mode][text[0]]) { + // This behavior is not strict (XeTeX-compatible) in math mode. + if (this.settings.strict && this.mode === "math") { + this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus); + } + + text = unicodeSymbols[text[0]] + text.slice(1); + } // Strip off any combining characters + + + const match = combiningDiacriticalMarksEndRegex.exec(text); + + if (match) { + text = text.substring(0, match.index); + + if (text === 'i') { + text = '\u0131'; // dotless i, in math and text mode + } else if (text === 'j') { + text = '\u0237'; // dotless j, in math and text mode + } + } // Recognize base symbol + + + let symbol; + + if (src_symbols[this.mode][text]) { + if (this.settings.strict && this.mode === 'math' && extraLatin.indexOf(text) >= 0) { + this.settings.reportNonstrict("unicodeTextInMathMode", "Latin-1/Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus); + } + + const group = src_symbols[this.mode][text].group; + const loc = SourceLocation.range(nucleus); + let s; + + if (ATOMS.hasOwnProperty(group)) { + // $FlowFixMe + const family = group; + s = { + type: "atom", + mode: this.mode, + family, + loc, + text + }; + } else { + // $FlowFixMe + s = { + type: group, + mode: this.mode, + loc, + text + }; + } // $FlowFixMe + + + symbol = s; + } else if (text.charCodeAt(0) >= 0x80) { + // no symbol for e.g. ^ + if (this.settings.strict) { + if (!supportedCodepoint(text.charCodeAt(0))) { + this.settings.reportNonstrict("unknownSymbol", "Unrecognized Unicode character \"" + text[0] + "\"" + (" (" + text.charCodeAt(0) + ")"), nucleus); + } else if (this.mode === "math") { + this.settings.reportNonstrict("unicodeTextInMathMode", "Unicode text character \"" + text[0] + "\" used in math mode", nucleus); + } + } // All nonmathematical Unicode characters are rendered as if they + // are in text mode (wrapped in \text) because that's what it + // takes to render them in LaTeX. Setting `mode: this.mode` is + // another natural choice (the user requested math mode), but + // this makes it more difficult for getCharacterMetrics() to + // distinguish Unicode characters without metrics and those for + // which we want to simulate the letter M. + + + symbol = { + type: "textord", + mode: "text", + loc: SourceLocation.range(nucleus), + text + }; + } else { + return null; // EOF, ^, _, {, }, etc. + } + + this.consume(); // Transform combining characters into accents + + if (match) { + for (let i = 0; i < match[0].length; i++) { + const accent = match[0][i]; + + if (!unicodeAccents[accent]) { + throw new src_ParseError("Unknown accent ' " + accent + "'", nucleus); + } + + const command = unicodeAccents[accent][this.mode] || unicodeAccents[accent].text; + + if (!command) { + throw new src_ParseError("Accent " + accent + " unsupported in " + this.mode + " mode", nucleus); + } + + symbol = { + type: "accent", + mode: this.mode, + loc: SourceLocation.range(nucleus), + label: command, + isStretchy: false, + isShifty: true, + // $FlowFixMe + base: symbol + }; + } + } // $FlowFixMe + + + return symbol; + } + +} +Parser.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"]; +;// CONCATENATED MODULE: ./src/parseTree.js +/** + * Provides a single function for parsing an expression using a Parser + * TODO(emily): Remove this + */ + + + + +/** + * Parses an expression using a Parser, then returns the parsed result. + */ +const parseTree = function (toParse, settings) { + if (!(typeof toParse === 'string' || toParse instanceof String)) { + throw new TypeError('KaTeX can only parse string typed expression'); + } + + const parser = new Parser(toParse, settings); // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors + + delete parser.gullet.macros.current["\\df@tag"]; + let tree = parser.parse(); // Prevent a color definition from persisting between calls to katex.render(). + + delete parser.gullet.macros.current["\\current@color"]; + delete parser.gullet.macros.current["\\color"]; // If the input used \tag, it will set the \df@tag macro to the tag. + // In this case, we separately parse the tag and wrap the tree. + + if (parser.gullet.macros.get("\\df@tag")) { + if (!settings.displayMode) { + throw new src_ParseError("\\tag works only in display equations"); + } + + tree = [{ + type: "tag", + mode: "text", + body: tree, + tag: parser.subparse([new Token("\\df@tag")]) + }]; + } + + return tree; +}; + +/* harmony default export */ var src_parseTree = (parseTree); +;// CONCATENATED MODULE: ./katex.js +/* eslint no-console:0 */ + +/** + * This is the main entry point for KaTeX. Here, we expose functions for + * rendering expressions either to DOM nodes or to markup strings. + * + * We also expose the ParseError class to check if errors thrown from KaTeX are + * errors in the expression, or errors in javascript handling. + */ + + + + + + + + + + + +/** + * Parse and build an expression, and place that expression in the DOM node + * given. + */ +let render = function (expression, baseNode, options) { + baseNode.textContent = ""; + const node = renderToDomTree(expression, options).toNode(); + baseNode.appendChild(node); +}; // KaTeX's styles don't work properly in quirks mode. Print out an error, and +// disable rendering. + + +if (typeof document !== "undefined") { + if (document.compatMode !== "CSS1Compat") { + typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype."); + + render = function () { + throw new src_ParseError("KaTeX doesn't work in quirks mode."); + }; + } +} +/** + * Parse and build an expression, and return the markup for that. + */ + + +const renderToString = function (expression, options) { + const markup = renderToDomTree(expression, options).toMarkup(); + return markup; +}; +/** + * Parse an expression and return the parse tree. + */ + + +const generateParseTree = function (expression, options) { + const settings = new Settings(options); + return src_parseTree(expression, settings); +}; +/** + * If the given error is a KaTeX ParseError and options.throwOnError is false, + * renders the invalid LaTeX as a span with hover title giving the KaTeX + * error message. Otherwise, simply throws the error. + */ + + +const renderError = function (error, expression, options) { + if (options.throwOnError || !(error instanceof src_ParseError)) { + throw error; + } + + const node = buildCommon.makeSpan(["katex-error"], [new SymbolNode(expression)]); + node.setAttribute("title", error.toString()); + node.setAttribute("style", "color:" + options.errorColor); + return node; +}; +/** + * Generates and returns the katex build tree. This is used for advanced + * use cases (like rendering to custom output). + */ + + +const renderToDomTree = function (expression, options) { + const settings = new Settings(options); + + try { + const tree = src_parseTree(expression, settings); + return buildTree(tree, expression, settings); + } catch (error) { + return renderError(error, expression, settings); + } +}; +/** + * Generates and returns the katex build tree, with just HTML (no MathML). + * This is used for advanced use cases (like rendering to custom output). + */ + + +const renderToHTMLTree = function (expression, options) { + const settings = new Settings(options); + + try { + const tree = src_parseTree(expression, settings); + return buildHTMLTree(tree, expression, settings); + } catch (error) { + return renderError(error, expression, settings); + } +}; + +const version = "0.16.22"; +const __domTree = { + Span: Span, + Anchor: Anchor, + SymbolNode: SymbolNode, + SvgNode: SvgNode, + PathNode: PathNode, + LineNode: LineNode +}; // ESM exports + + // CJS exports and ESM default export + +/* harmony default export */ var katex = ({ + /** + * Current KaTeX version + */ + version, + + /** + * Renders the given LaTeX into an HTML+MathML combination, and adds + * it as a child to the specified DOM node. + */ + render, + + /** + * Renders the given LaTeX into an HTML+MathML combination string, + * for sending to the client. + */ + renderToString, + + /** + * KaTeX error, usually during parsing. + */ + ParseError: src_ParseError, + + /** + * The schema of Settings + */ + SETTINGS_SCHEMA: SETTINGS_SCHEMA, + + /** + * Parses the given LaTeX into KaTeX's internal parse tree structure, + * without rendering to HTML or MathML. + * + * NOTE: This method is not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __parse: generateParseTree, + + /** + * Renders the given LaTeX into an HTML+MathML internal DOM tree + * representation, without flattening that representation to a string. + * + * NOTE: This method is not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __renderToDomTree: renderToDomTree, + + /** + * Renders the given LaTeX into an HTML internal DOM tree representation, + * without MathML and without flattening that representation to a string. + * + * NOTE: This method is not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __renderToHTMLTree: renderToHTMLTree, + + /** + * extends internal font metrics object with a new object + * each key in the new object represents a font name + */ + __setFontMetrics: setFontMetrics, + + /** + * adds a new symbol to builtin symbols table + */ + __defineSymbol: defineSymbol, + + /** + * adds a new function to builtin function list, + * which directly produce parse tree elements + * and have their own html/mathml builders + */ + __defineFunction: defineFunction, + + /** + * adds a new macro to builtin macro list + */ + __defineMacro: defineMacro, + + /** + * Expose the dom tree node types, which can be useful for type checking nodes. + * + * NOTE: These methods are not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __domTree +}); +;// CONCATENATED MODULE: ./katex.webpack.js +/** + * This is the webpack entry point for KaTeX. As ECMAScript, flow[1] and jest[2] + * doesn't support CSS modules natively, a separate entry point is used and + * it is not flowtyped. + * + * [1] https://gist.github.com/lambdahands/d19e0da96285b749f0ef + * [2] https://facebook.github.io/jest/docs/en/webpack.html + */ + + +/* harmony default export */ var katex_webpack = (katex); +__webpack_exports__ = __webpack_exports__["default"]; +/******/ return __webpack_exports__; +/******/ })() +; +}); \ No newline at end of file diff --git a/hybrid/html/js/marked-highlight.js b/hybrid/html/js/marked-highlight.js new file mode 100644 index 0000000..5b04488 --- /dev/null +++ b/hybrid/html/js/marked-highlight.js @@ -0,0 +1,103 @@ + + function markedHighlight(options) { + if (typeof options === 'function') { + options = { + highlight: options, + }; + } + + if (!options || typeof options.highlight !== 'function') { + throw new Error('Must provide highlight function'); + } + + if (typeof options.langPrefix !== 'string') { + options.langPrefix = 'language-'; + } + + if (typeof options.emptyLangClass !== 'string') { + options.emptyLangClass = ''; + } + + return { + async: !!options.async, + walkTokens(token) { + if (token.type !== 'code') { + return; + } + + const lang = getLang(token.lang); + + if (options.async) { + return Promise.resolve(options.highlight(token.text, lang, token.lang || '')).then( + updateToken(token)); + } + + const code = options.highlight(token.text, lang, token.lang || ''); + if (code instanceof Promise) { + throw new Error( + 'markedHighlight is not set to async but the highlight function is async. Set the async option to true on markedHighlight to await the async highlight function.' + ); + } + updateToken(token)(code); + }, + useNewRenderer: true, + renderer: { + code(code, infoString, escaped) { + // istanbul ignore next + if (typeof code === 'object') { + escaped = code.escaped; + infoString = code.lang; + code = code.text; + } + const lang = getLang(infoString); + const classValue = lang ? options.langPrefix + escape(lang) : options.emptyLangClass; + const classAttr = classValue ? + ` class="${classValue}"` : + ''; + code = code.replace(/\n$/, ''); + return `
${escaped ? code : escape(code, true)}\n
`; + }, + }, + }; + } + + function getLang(lang) { + return (lang || '').match(/\S*/)[0]; + } + + function updateToken(token) { + return (code) => { + if (typeof code === 'string' && code !== token.text) { + token.escaped = true; + token.text = code; + } + }; + } + + // copied from marked helpers + const escapeTest = /[&<>"']/; + const escapeReplace = new RegExp(escapeTest.source, 'g'); + const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/; + const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, 'g'); + const escapeReplacements = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + }; + const getEscapeReplacement = (ch) => escapeReplacements[ch]; + + function escape(html, encode) { + if (encode) { + if (escapeTest.test(html)) { + return html.replace(escapeReplace, getEscapeReplacement); + } + } else { + if (escapeTestNoEncode.test(html)) { + return html.replace(escapeReplaceNoEncode, getEscapeReplacement); + } + } + + return html; + } diff --git a/hybrid/html/js/marked-katex-extension.js b/hybrid/html/js/marked-katex-extension.js new file mode 100644 index 0000000..bdc9928 --- /dev/null +++ b/hybrid/html/js/marked-katex-extension.js @@ -0,0 +1,88 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('katex')) : + typeof define === 'function' && define.amd ? define(['katex'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.markedKatex = factory(global.katex)); +})(this, (function (katex) { 'use strict'; + + const inlineRule = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n\$]))\1(?=[\s?!\.,:?!。,:]|$)/; + const inlineRuleNonStandard = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n\$]))\1/; // Non-standard, even if there are no spaces before and after $ or $$, try to parse + + const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/; + + function index(options = {}) { + return { + extensions: [ + inlineKatex(options, createRenderer(options, false)), + blockKatex(options, createRenderer(options, true)), + ], + }; + } + + function createRenderer(options, newlineAfter) { + return (token) => katex.renderToString(token.text, { ...options, displayMode: token.displayMode }) + (newlineAfter ? '\n' : ''); + } + + function inlineKatex(options, renderer) { + const nonStandard = options && options.nonStandard; + const ruleReg = nonStandard ? inlineRuleNonStandard : inlineRule; + return { + name: 'inlineKatex', + level: 'inline', + start(src) { + let index; + let indexSrc = src; + + while (indexSrc) { + index = indexSrc.indexOf('$'); + if (index === -1) { + return; + } + const f = nonStandard ? index > -1 : index === 0 || indexSrc.charAt(index - 1) === ' '; + if (f) { + const possibleKatex = indexSrc.substring(index); + + if (possibleKatex.match(ruleReg)) { + return index; + } + } + + indexSrc = indexSrc.substring(index + 1).replace(/^\$+/, ''); + } + }, + tokenizer(src, tokens) { + const match = src.match(ruleReg); + if (match) { + return { + type: 'inlineKatex', + raw: match[0], + text: match[2].trim(), + displayMode: match[1].length === 2, + }; + } + }, + renderer, + }; + } + + function blockKatex(options, renderer) { + return { + name: 'blockKatex', + level: 'block', + tokenizer(src, tokens) { + const match = src.match(blockRule); + if (match) { + return { + type: 'blockKatex', + raw: match[0], + text: match[2].trim(), + displayMode: match[1].length === 2, + }; + } + }, + renderer, + }; + } + + return index; + +})); diff --git a/hybrid/html/js/marked-tables.js b/hybrid/html/js/marked-tables.js new file mode 100644 index 0000000..be41636 --- /dev/null +++ b/hybrid/html/js/marked-tables.js @@ -0,0 +1,242 @@ + + function extendedTables({ + interruptPatterns = [], + skipEmptyRows = true + } = {}) { + return { + extensions: [{ + name: 'spanTable', + level: 'block', // Is this a block-level or inline-level tokenizer? + start(src) { + return src.match(/\n *([^\n ].*\|.*)\n/m)?.index; + }, // Hint to Marked.js to stop and check for a match + tokenizer(src, tokens) { + // const regex = this.tokenizer.rules.block.table; + let regexString = '^ *([^\\n ].*\\|.*\\n(?: *[^\\s].*\\n)*?)' // Header + + + ' {0,3}(?:\\| *)?(:?-+(?: *(?:100|[1-9][0-9]?%) *-+)?:? *(?:\\| *:?-+(?: *(?:100|[1-9][0-9]?%) *-+)?:? *)*)(?:\\| *)?' // Align + + + '(?:\\n((?:(?! *\\n| {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})' // Cells + + + '(?:\\n+|$)| {0,3}#{1,6}(?:\\s|$)| {0,3}>| {4}[^\\n]| {0,3}(?:`{3,}' + + '(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n| {0,3}(?:[*+-]|1[.)]) |' + + '<\\/?(?:address|article|aside|base|basefont|blockquote|body' + + '|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt' + + '|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]' + + '|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem' + + '|meta|nav|noframes|ol|optgroup|option|p|param|section|source' + + '|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)' + + '(?: +|\\n|\\/?>)|<(?:script|pre|style|textarea|!--)endRegex).*(?:\\n|$))*)\\n*|$)'; // Cells + + regexString = regexString.replace('endRegex', interruptPatterns.map(str => + `|(?:${str})`).join('')); + const widthRegex = / *(?:100|[1-9][0-9]?%) */g; + const regex = new RegExp(regexString); + const cap = regex.exec(src); + + if (cap) { + const item = { + type: 'spanTable', + header: cap[1].replace(/\n$/, '').split('\n'), + align: cap[2].replace(widthRegex, '').replace(/^ *|\| *$/g, '').split( + / *\| */), + rows: cap[3]?.trim() ? cap[3].replace(/\n[ \t]*$/, '').split('\n') : [], + width: cap[2].replace(/:/g, '').replace(/-+| /g, '').split('|') + }; + + // Get first header row to determine how many columns + item.header[0] = splitCells(item.header[0]); + + const colCount = item.header[0].reduce((length, header) => { + return length + header.colspan; + }, 0); + + if (colCount === item.align.length) { + item.raw = cap[0]; + + let i, j, k, row; + + // Get alignment row (:---:) + let l = item.align.length; + + for (i = 0; i < l; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + // Get any remaining header rows + l = item.header.length; + for (i = 1; i < l; i++) { + item.header[i] = splitCells(item.header[i], colCount, item.header[i - + 1], skipEmptyRows); + } + + // Get main table cells + l = item.rows.length; + for (i = 0; i < l; i++) { + item.rows[i] = splitCells(item.rows[i], colCount, item.rows[i - 1], + skipEmptyRows); + } + + // header child tokens + l = item.header.length; + for (j = 0; j < l; j++) { + row = item.header[j]; + for (k = 0; k < row.length; k++) { + row[k].tokens = []; + this.lexer.inline(row[k].text, row[k].tokens); + } + } + + // cell child tokens + l = item.rows.length; + for (j = 0; j < l; j++) { + row = item.rows[j]; + for (k = 0; k < row.length; k++) { + row[k].tokens = []; + this.lexer.inline(row[k].text, row[k].tokens); + } + } + return item; + } + } + }, + renderer(token) { + + let i, j, row, cell, col, text; + let output = ''; + output += ''; + for (i = 0; i < token.header.length; i++) { + row = token.header[i]; + let col = 0; + output += ''; + for (j = 0; j < row.length; j++) { + cell = row[j]; + text = this.parser.parseInline(cell.tokens); + output += getTableCell(text, cell, 'th', token.align[col], token.width[ + col]); + col += cell.colspan; + } + output += ''; + } + output += ''; + if (token.rows.length) { + output += ''; + for (i = 0; i < token.rows.length; i++) { + row = token.rows[i]; + col = 0; + if (!row[0].emptyRow) { + output += ''; + for (j = 0; j < row.length; j++) { + cell = row[j]; + text = this.parser.parseInline(cell.tokens); + output += getTableCell(text, cell, 'td', token.align[col], token + .width[col]); + col += cell.colspan; + } + output += ''; + } + } + output += ''; + } + output += '
'; + return output; + } + }] + }; + } + + const getTableCell = (text, cell, type, align, width) => { + if (!cell.rowspan) { + return ''; + } + const tag = `<${type}` + + `${cell.colspan > 1 ? ` colspan=${cell.colspan}` : ''}` + + `${cell.rowspan > 1 ? ` rowspan=${cell.rowspan}` : ''}` + + `${align ? ` align=${align}` : ''}` + + `${width ? ` width=${width}` : ''}>`; + return `${tag + text}\n`; + }; + + const splitCells = (tableRow, count, prevRow = [], skipEmptyRows) => { + const cells = [...tableRow.trim().matchAll(/(?:[^|\\]|\\.?)+(?:\|+|$)/g)].map((x) => x[0]); + + // Remove first/last cell in a row if whitespace only and no leading/trailing pipe + if (!cells[0]?.trim()) { + cells.shift(); + } + if (!cells[cells.length - 1]?.trim()) { + cells.pop(); + } + + let numCols = 0; + let i, j, trimmedCell, prevCell, prevCols; + + for (i = 0; i < cells.length; i++) { + trimmedCell = cells[i].split(/\|+$/)[0]; + cells[i] = { + rowspan: 1, + colspan: Math.max(cells[i].length - trimmedCell.length, 1), + text: trimmedCell.trim().replace(/\\\|/g, '|') + // display escaped pipes as normal character + }; + + // Handle Rowspan + if (trimmedCell.slice(-1) === '^' && prevRow.length) { + // Find matching cell in previous row + prevCols = 0; + for (j = 0; j < prevRow.length; j++) { + prevCell = prevRow[j]; + if ((prevCols === numCols) && (prevCell.colspan === cells[i].colspan)) { + // merge into matching cell in previous row (the "target") + cells[i].rowSpanTarget = prevCell.rowSpanTarget ?? prevCell; + cells[i].rowSpanTarget.text += ` ${cells[i].text.slice(0, -1)}`; + cells[i].rowSpanTarget.rowspan += 1; + cells[i].rowspan = 0; + break; + } + prevCols += prevCell.colspan; + if (prevCols > numCols) { + break; + } + } + } + + numCols += cells[i].colspan; + } + + // If all cells have been merged, flag as an empty row + if (cells.length > 0 && skipEmptyRows && cells.length === cells.filter((cell) => { + return cell.rowspan === 0; + }).length) { + cells[0].emptyRow = true; + for (i = 0; i < cells.length; i++) { + cells[i].rowSpanTarget.rowspan -= 1; + } + } + + // Force main cell rows to match header column count + if (numCols > count) { + cells.splice(count); + } else { + while (numCols < count) { + cells.push({ + rowspan: 1, + colspan: 1, + text: '' + }); + numCols += 1; + } + } + return cells; + }; + + + diff --git a/hybrid/html/js/marked.min.js b/hybrid/html/js/marked.min.js new file mode 100644 index 0000000..da0baed --- /dev/null +++ b/hybrid/html/js/marked.min.js @@ -0,0 +1,21 @@ +/** + * marked v15.0.7 - a markdown parser + * Copyright (c) 2011-2025, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ +if (!Array.prototype.at) { + Object.defineProperty(Array.prototype, 'at', { + value: function (index) { + // 处理负索引 + if (index < 0) { + index = this.length + index; + } + // 返回指定索引的元素,如果索引越界则返回undefined + return this[index]; + }, + writable: true, + configurable: true + }); +} + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,(function(e){"use strict";function t(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}function n(t){e.defaults=t}e.defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};const s={exec:()=>null};function r(e,t=""){let n="string"==typeof e?e:e.source;const s={replace:(e,t)=>{let r="string"==typeof t?t:t.source;return r=r.replace(i.caret,"$1"),n=n.replace(e,r),s},getRegex:()=>new RegExp(n,t)};return s}const i={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] /,listReplaceTask:/^\[[ xX]\] +/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:e=>new RegExp(`^( {0,3}${e})((?:[\t ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),hrRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}#`),htmlBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}<(?:[a-z].*>|!--)`,"i")},l=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,o=/(?:[*+-]|\d{1,9}[.)])/,a=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,c=r(a).replace(/bull/g,o).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),h=r(a).replace(/bull/g,o).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),p=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,u=/(?!\s*\])(?:\\.|[^\[\]\\])+/,g=r(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",u).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),k=r(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,o).getRegex(),d="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",f=/|$))/,x=r("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$))","i").replace("comment",f).replace("tag",d).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),b=r(p).replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",d).getRegex(),w={blockquote:r(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",b).getRegex(),code:/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,def:g,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:l,html:x,lheading:c,list:k,newline:/^(?:[ \t]*(?:\n|$))+/,paragraph:b,table:s,text:/^[^\n]+/},m=r("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3}\t)[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",d).getRegex(),y={...w,lheading:h,table:m,paragraph:r(p).replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",m).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",d).getRegex()},$={...w,html:r("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",f).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:s,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:r(p).replace("hr",l).replace("heading"," *#{1,6} *[^\n]").replace("lheading",c).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},R=/^( {2,}|\\)\n(?!\s*$)/,S=/[\p{P}\p{S}]/u,T=/[\s\p{P}\p{S}]/u,z=/[^\s\p{P}\p{S}]/u,A=r(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,T).getRegex(),_=/(?!~)[\p{P}\p{S}]/u,P=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,I=r(P,"u").replace(/punct/g,S).getRegex(),L=r(P,"u").replace(/punct/g,_).getRegex(),B="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",C=r(B,"gu").replace(/notPunctSpace/g,z).replace(/punctSpace/g,T).replace(/punct/g,S).getRegex(),q=r(B,"gu").replace(/notPunctSpace/g,/(?:[^\s\p{P}\p{S}]|~)/u).replace(/punctSpace/g,/(?!~)[\s\p{P}\p{S}]/u).replace(/punct/g,_).getRegex(),E=r("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,z).replace(/punctSpace/g,T).replace(/punct/g,S).getRegex(),Z=r(/\\(punct)/,"gu").replace(/punct/g,S).getRegex(),v=r(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),D=r(f).replace("(?:--\x3e|$)","--\x3e").getRegex(),M=r("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",D).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),O=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Q=r(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",O).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),j=r(/^!?\[(label)\]\[(ref)\]/).replace("label",O).replace("ref",u).getRegex(),N=r(/^!?\[(ref)\](?:\[\])?/).replace("ref",u).getRegex(),G={_backpedal:s,anyPunctuation:Z,autolink:v,blockSkip:/\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g,br:R,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:s,emStrongLDelim:I,emStrongRDelimAst:C,emStrongRDelimUnd:E,escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,link:Q,nolink:N,punctuation:A,reflink:j,reflinkSearch:r("reflink|nolink(?!\\()","g").replace("reflink",j).replace("nolink",N).getRegex(),tag:M,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},V=e=>K[e];function W(e,t){if(t){if(i.escapeTest.test(e))return e.replace(i.escapeReplace,V)}else if(i.escapeTestNoEncode.test(e))return e.replace(i.escapeReplaceNoEncode,V);return e}function Y(e){try{e=encodeURI(e).replace(i.percentDecode,"%")}catch{return null}return e}function ee(e,t){const n=e.replace(i.findPipe,((e,t,n)=>{let s=!1,r=t;for(;--r>=0&&"\\"===n[r];)s=!s;return s?"|":" |"})).split(i.splitPipe);let s=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?e:te(e,"\n")}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n=function(e,t,n){const s=e.match(n.other.indentCodeCompensation);if(null===s)return t;const r=s[1];return t.split("\n").map((e=>{const t=e.match(n.other.beginningSpace);if(null===t)return e;const[s]=t;return s.length>=r.length?e.slice(r.length):e})).join("\n")}(e,t[3]||"",this.rules);return{type:"code",raw:e,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:n}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].trim();if(this.rules.other.endingHash.test(e)){const t=te(e,"#");this.options.pedantic?e=t.trim():t&&!this.rules.other.endingSpaceChar.test(t)||(e=t.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:e,tokens:this.lexer.inline(e)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:te(t[0],"\n")}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){let e=te(t[0],"\n").split("\n"),n="",s="";const r=[];for(;e.length>0;){let t=!1;const i=[];let l;for(l=0;l1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");const i=this.rules.other.listItemRegex(n);let l=!1;for(;e;){let n=!1,s="",o="";if(!(t=i.exec(e)))break;if(this.rules.block.hr.test(e))break;s=t[0],e=e.substring(s.length);let a=t[2].split("\n",1)[0].replace(this.rules.other.listReplaceTabs,(e=>" ".repeat(3*e.length))),c=e.split("\n",1)[0],h=!a.trim(),p=0;if(this.options.pedantic?(p=2,o=a.trimStart()):h?p=t[1].length+1:(p=t[2].search(this.rules.other.nonSpaceChar),p=p>4?1:p,o=a.slice(p),p+=t[1].length),h&&this.rules.other.blankLine.test(c)&&(s+=c+"\n",e=e.substring(c.length+1),n=!0),!n){const t=this.rules.other.nextBulletRegex(p),n=this.rules.other.hrRegex(p),r=this.rules.other.fencesBeginRegex(p),i=this.rules.other.headingBeginRegex(p),l=this.rules.other.htmlBeginRegex(p);for(;e;){const u=e.split("\n",1)[0];let g;if(c=u,this.options.pedantic?(c=c.replace(this.rules.other.listReplaceNesting," "),g=c):g=c.replace(this.rules.other.tabCharGlobal," "),r.test(c))break;if(i.test(c))break;if(l.test(c))break;if(t.test(c))break;if(n.test(c))break;if(g.search(this.rules.other.nonSpaceChar)>=p||!c.trim())o+="\n"+g.slice(p);else{if(h)break;if(a.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4)break;if(r.test(a))break;if(i.test(a))break;if(n.test(a))break;o+="\n"+c}h||c.trim()||(h=!0),s+=u+"\n",e=e.substring(u.length+1),a=g.slice(p)}}r.loose||(l?r.loose=!0:this.rules.other.doubleBlankLine.test(s)&&(l=!0));let u,g=null;this.options.gfm&&(g=this.rules.other.listIsTask.exec(o),g&&(u="[ ] "!==g[0],o=o.replace(this.rules.other.listReplaceTask,""))),r.items.push({type:"list_item",raw:s,task:!!g,checked:u,loose:!1,text:o,tokens:[]}),r.raw+=s}const o=r.items.at(-1);if(!o)return;o.raw=o.raw.trimEnd(),o.text=o.text.trimEnd(),r.raw=r.raw.trimEnd();for(let e=0;e"space"===e.type)),n=t.length>0&&t.some((e=>this.rules.other.anyLine.test(e.raw)));r.loose=n}if(r.loose)for(let e=0;e({text:e,tokens:this.lexer.inline(e),header:!1,align:i.align[t]}))));return i}}lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:"="===t[2].charAt(0)?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e="\n"===t[1].charAt(t[1].length-1)?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:e,tokens:this.lexer.inline(e)}}}text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(e)){if(!this.rules.other.endAngleBracket.test(e))return;const t=te(e.slice(0,-1),"\\");if((e.length-t.length)%2==0)return}else{const e=function(e,t){if(-1===e.indexOf(t[1]))return-1;let n=0;for(let s=0;s-1){const n=(0===t[0].indexOf("!")?5:4)+t[1].length+e;t[2]=t[2].substring(0,e),t[0]=t[0].substring(0,n).trim(),t[3]=""}}let n=t[2],s="";if(this.options.pedantic){const e=this.rules.other.pedanticHrefTitle.exec(n);e&&(n=e[1],s=e[3])}else s=t[3]?t[3].slice(1,-1):"";return n=n.trim(),this.rules.other.startAngleBracket.test(n)&&(n=this.options.pedantic&&!this.rules.other.endAngleBracket.test(e)?n.slice(1):n.slice(1,-1)),ne(t,{href:n?n.replace(this.rules.inline.anyPunctuation,"$1"):n,title:s?s.replace(this.rules.inline.anyPunctuation,"$1"):s},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){const e=t[(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," ").toLowerCase()];if(!e){const e=n[0].charAt(0);return{type:"text",raw:e,text:e}}return ne(n,e,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s)return;if(s[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){const n=[...s[0]].length-1;let r,i,l=n,o=0;const a="*"===s[0][0]?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(a.lastIndex=0,t=t.slice(-1*e.length+n);null!=(s=a.exec(t));){if(r=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!r)continue;if(i=[...r].length,s[3]||s[4]){l+=i;continue}if((s[5]||s[6])&&n%3&&!((n+i)%3)){o+=i;continue}if(l-=i,l>0)continue;i=Math.min(i,i+l+o);const t=[...s[0]][0].length,a=e.slice(0,n+s.index+t+i);if(Math.min(n,i)%2){const e=a.slice(1,-1);return{type:"em",raw:a,text:e,tokens:this.lexer.inlineTokens(e)}}const c=a.slice(2,-2);return{type:"strong",raw:a,text:c,tokens:this.lexer.inlineTokens(c)}}}}codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].replace(this.rules.other.newLineCharGlobal," ");const n=this.rules.other.nonSpaceChar.test(e),s=this.rules.other.startingSpaceChar.test(e)&&this.rules.other.endingSpaceChar.test(e);return n&&s&&(e=e.substring(1,e.length-1)),{type:"codespan",raw:t[0],text:e}}}br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){const t=this.rules.inline.autolink.exec(e);if(t){let e,n;return"@"===t[2]?(e=t[1],n="mailto:"+e):(e=t[1],n=e),{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let e,n;if("@"===t[2])e=t[0],n="mailto:"+e;else{let s;do{s=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??""}while(s!==t[0]);e=t[0],n="www."===t[1]?"http://"+t[0]:t[0]}return{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}inlineText(e){const t=this.rules.inline.text.exec(e);if(t){const e=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:e}}}}class re{tokens;options;state;tokenizer;inlineQueue;constructor(t){this.tokens=[],this.tokens.links=Object.create(null),this.options=t||e.defaults,this.options.tokenizer=this.options.tokenizer||new se,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};const n={other:i,block:U.normal,inline:J.normal};this.options.pedantic?(n.block=U.pedantic,n.inline=J.pedantic):this.options.gfm&&(n.block=U.gfm,this.options.breaks?n.inline=J.breaks:n.inline=J.gfm),this.tokenizer.rules=n}static get rules(){return{block:U,inline:J}}static lex(e,t){return new re(t).lex(e)}static lexInline(e,t){return new re(t).inlineTokens(e)}lex(e){e=e.replace(i.carriageReturn,"\n"),this.blockTokens(e,this.tokens);for(let e=0;e!!(s=n.call({lexer:this},e,t))&&(e=e.substring(s.raw.length),t.push(s),!0))))continue;if(s=this.tokenizer.space(e)){e=e.substring(s.raw.length);const n=t.at(-1);1===s.raw.length&&void 0!==n?n.raw+="\n":t.push(s);continue}if(s=this.tokenizer.code(e)){e=e.substring(s.raw.length);const n=t.at(-1);"paragraph"===n?.type||"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.text,this.inlineQueue.at(-1).src=n.text):t.push(s);continue}if(s=this.tokenizer.fences(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.heading(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.hr(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.blockquote(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.list(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.html(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.def(e)){e=e.substring(s.raw.length);const n=t.at(-1);"paragraph"===n?.type||"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.raw,this.inlineQueue.at(-1).src=n.text):this.tokens.links[s.tag]||(this.tokens.links[s.tag]={href:s.href,title:s.title});continue}if(s=this.tokenizer.table(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.lheading(e)){e=e.substring(s.raw.length),t.push(s);continue}let r=e;if(this.options.extensions?.startBlock){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startBlock.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(this.state.top&&(s=this.tokenizer.paragraph(r))){const i=t.at(-1);n&&"paragraph"===i?.type?(i.raw+="\n"+s.raw,i.text+="\n"+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=i.text):t.push(s),n=r.length!==e.length,e=e.substring(s.raw.length)}else if(s=this.tokenizer.text(e)){e=e.substring(s.raw.length);const n=t.at(-1);"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=n.text):t.push(s)}else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,s=null;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(s=this.tokenizer.rules.inline.reflinkSearch.exec(n));)e.includes(s[0].slice(s[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(s=this.tokenizer.rules.inline.blockSkip.exec(n));)n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(s=this.tokenizer.rules.inline.anyPunctuation.exec(n));)n=n.slice(0,s.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let r=!1,i="";for(;e;){let s;if(r||(i=""),r=!1,this.options.extensions?.inline?.some((n=>!!(s=n.call({lexer:this},e,t))&&(e=e.substring(s.raw.length),t.push(s),!0))))continue;if(s=this.tokenizer.escape(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.tag(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.link(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(s.raw.length);const n=t.at(-1);"text"===s.type&&"text"===n?.type?(n.raw+=s.raw,n.text+=s.text):t.push(s);continue}if(s=this.tokenizer.emStrong(e,n,i)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.codespan(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.br(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.del(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.autolink(e)){e=e.substring(s.raw.length),t.push(s);continue}if(!this.state.inLink&&(s=this.tokenizer.url(e))){e=e.substring(s.raw.length),t.push(s);continue}let l=e;if(this.options.extensions?.startInline){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startInline.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(l=e.substring(0,t+1))}if(s=this.tokenizer.inlineText(l)){e=e.substring(s.raw.length),"_"!==s.raw.slice(-1)&&(i=s.raw.slice(-1)),r=!0;const n=t.at(-1);"text"===n?.type?(n.raw+=s.raw,n.text+=s.text):t.push(s)}else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return t}}class ie{options;parser;constructor(t){this.options=t||e.defaults}space(e){return""}code({text:e,lang:t,escaped:n}){const s=(t||"").match(i.notSpaceStart)?.[0],r=e.replace(i.endingNewline,"")+"\n";return s?'
'+(n?r:W(r,!0))+"
\n":"
"+(n?r:W(r,!0))+"
\n"}blockquote({tokens:e}){return`
\n${this.parser.parse(e)}
\n`}html({text:e}){return e}heading({tokens:e,depth:t}){return`${this.parser.parseInline(e)}\n`}hr(e){return"
\n"}list(e){const t=e.ordered,n=e.start;let s="";for(let t=0;t\n"+s+"\n"}listitem(e){let t="";if(e.task){const n=this.checkbox({checked:!!e.checked});e.loose?"paragraph"===e.tokens[0]?.type?(e.tokens[0].text=n+" "+e.tokens[0].text,e.tokens[0].tokens&&e.tokens[0].tokens.length>0&&"text"===e.tokens[0].tokens[0].type&&(e.tokens[0].tokens[0].text=n+" "+W(e.tokens[0].tokens[0].text),e.tokens[0].tokens[0].escaped=!0)):e.tokens.unshift({type:"text",raw:n+" ",text:n+" ",escaped:!0}):t+=n+" "}return t+=this.parser.parse(e.tokens,!!e.loose),`
  • ${t}
  • \n`}checkbox({checked:e}){return"'}paragraph({tokens:e}){return`

    ${this.parser.parseInline(e)}

    \n`}table(e){let t="",n="";for(let t=0;t${s}`),"\n\n"+t+"\n"+s+"
    \n"}tablerow({text:e}){return`\n${e}\n`}tablecell(e){const t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`\n`}strong({tokens:e}){return`${this.parser.parseInline(e)}`}em({tokens:e}){return`${this.parser.parseInline(e)}`}codespan({text:e}){return`${W(e,!0)}`}br(e){return"
    "}del({tokens:e}){return`${this.parser.parseInline(e)}`}link({href:e,title:t,tokens:n}){const s=this.parser.parseInline(n),r=Y(e);if(null===r)return s;let i='
    ",i}image({href:e,title:t,text:n}){const s=Y(e);if(null===s)return W(n);let r=`${n}{const r=e[s].flat(1/0);n=n.concat(this.walkTokens(r,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let s=e.renderer.apply(this,t);return!1===s&&(s=n.apply(this,t)),s}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new ie(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if(["options","parser"].includes(n))continue;const s=n,r=e.renderer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new se(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const s=n,r=e.tokenizer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new ae;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if(["options","block"].includes(n))continue;const s=n,r=e.hooks[s],i=t[s];ae.passThroughHooks.has(n)?t[s]=e=>{if(this.defaults.async)return Promise.resolve(r.call(t,e)).then((e=>i.call(t,e)));const n=r.call(t,e);return i.call(t,n)}:t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,s=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(s.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return re.lex(e,t??this.defaults)}parser(e,t){return oe.parse(e,t??this.defaults)}parseMarkdown(e){return(t,n)=>{const s={...n},r={...this.defaults,...s},i=this.onError(!!r.silent,!!r.async);if(!0===this.defaults.async&&!1===s.async)return i(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(null==t)return i(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof t)return i(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(t)+", string expected"));r.hooks&&(r.hooks.options=r,r.hooks.block=e);const l=r.hooks?r.hooks.provideLexer():e?re.lex:re.lexInline,o=r.hooks?r.hooks.provideParser():e?oe.parse:oe.parseInline;if(r.async)return Promise.resolve(r.hooks?r.hooks.preprocess(t):t).then((e=>l(e,r))).then((e=>r.hooks?r.hooks.processAllTokens(e):e)).then((e=>r.walkTokens?Promise.all(this.walkTokens(e,r.walkTokens)).then((()=>e)):e)).then((e=>o(e,r))).then((e=>r.hooks?r.hooks.postprocess(e):e)).catch(i);try{r.hooks&&(t=r.hooks.preprocess(t));let e=l(t,r);r.hooks&&(e=r.hooks.processAllTokens(e)),r.walkTokens&&this.walkTokens(e,r.walkTokens);let n=o(e,r);return r.hooks&&(n=r.hooks.postprocess(n)),n}catch(e){return i(e)}}}onError(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="

    An error occurred:

    "+W(n.message+"",!0)+"
    ";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}}const he=new ce;function pe(e,t){return he.parse(e,t)}pe.options=pe.setOptions=function(e){return he.setOptions(e),pe.defaults=he.defaults,n(pe.defaults),pe},pe.getDefaults=t,pe.defaults=e.defaults,pe.use=function(...e){return he.use(...e),pe.defaults=he.defaults,n(pe.defaults),pe},pe.walkTokens=function(e,t){return he.walkTokens(e,t)},pe.parseInline=he.parseInline,pe.Parser=oe,pe.parser=oe.parse,pe.Renderer=ie,pe.TextRenderer=le,pe.Lexer=re,pe.lexer=re.lex,pe.Tokenizer=se,pe.Hooks=ae,pe.parse=pe;const ue=pe.options,ge=pe.setOptions,ke=pe.use,de=pe.walkTokens,fe=pe.parseInline,xe=pe,be=oe.parse,we=re.lex;e.Hooks=ae,e.Lexer=re,e.Marked=ce,e.Parser=oe,e.Renderer=ie,e.TextRenderer=le,e.Tokenizer=se,e.getDefaults=t,e.lexer=we,e.marked=pe,e.options=ue,e.parse=xe,e.parseInline=fe,e.parser=be,e.setOptions=ge,e.use=ke,e.walkTokens=de})); diff --git a/hybrid/html/js/quill.js b/hybrid/html/js/quill.js new file mode 100644 index 0000000..aeddaa1 --- /dev/null +++ b/hybrid/html/js/quill.js @@ -0,0 +1,3 @@ +/*! For license information please see quill.js.LICENSE.txt */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Quill=e():t.Quill=e()}(self,(function(){return function(){var t={9698:function(t,e,n){"use strict";n.d(e,{Ay:function(){return c},Ji:function(){return d},mG:function(){return h},zo:function(){return u}});var r=n(6003),i=n(5232),s=n.n(i),o=n(3036),l=n(4850),a=n(5508);class c extends r.BlockBlot{cache={};delta(){return null==this.cache.delta&&(this.cache.delta=h(this)),this.cache.delta}deleteAt(t,e){super.deleteAt(t,e),this.cache={}}formatAt(t,e,n,i){e<=0||(this.scroll.query(n,r.Scope.BLOCK)?t+e===this.length()&&this.format(n,i):super.formatAt(t,Math.min(e,this.length()-t-1),n,i),this.cache={})}insertAt(t,e,n){if(null!=n)return super.insertAt(t,e,n),void(this.cache={});if(0===e.length)return;const r=e.split("\n"),i=r.shift();i.length>0&&(t(s=s.split(t,!0),s.insertAt(0,e),e.length)),t+i.length)}insertBefore(t,e){const{head:n}=this.children;super.insertBefore(t,e),n instanceof o.A&&n.remove(),this.cache={}}length(){return null==this.cache.length&&(this.cache.length=super.length()+1),this.cache.length}moveChildren(t,e){super.moveChildren(t,e),this.cache={}}optimize(t){super.optimize(t),this.cache={}}path(t){return super.path(t,!0)}removeChild(t){super.removeChild(t),this.cache={}}split(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(e&&(0===t||t>=this.length()-1)){const e=this.clone();return 0===t?(this.parent.insertBefore(e,this),this):(this.parent.insertBefore(e,this.next),e)}const n=super.split(t,e);return this.cache={},n}}c.blotName="block",c.tagName="P",c.defaultChild=o.A,c.allowedChildren=[o.A,l.A,r.EmbedBlot,a.A];class u extends r.EmbedBlot{attach(){super.attach(),this.attributes=new r.AttributorStore(this.domNode)}delta(){return(new(s())).insert(this.value(),{...this.formats(),...this.attributes.values()})}format(t,e){const n=this.scroll.query(t,r.Scope.BLOCK_ATTRIBUTE);null!=n&&this.attributes.attribute(n,e)}formatAt(t,e,n,r){this.format(n,r)}insertAt(t,e,n){if(null!=n)return void super.insertAt(t,e,n);const r=e.split("\n"),i=r.pop(),s=r.map((t=>{const e=this.scroll.create(c.blotName);return e.insertAt(0,t),e})),o=this.split(t);s.forEach((t=>{this.parent.insertBefore(t,o)})),i&&this.parent.insertBefore(this.scroll.create("text",i),o)}}function h(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return t.descendants(r.LeafBlot).reduce(((t,n)=>0===n.length()?t:t.insert(n.value(),d(n,{},e))),new(s())).insert("\n",d(t))}function d(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];return null==t?e:("formats"in t&&"function"==typeof t.formats&&(e={...e,...t.formats()},n&&delete e["code-token"]),null==t.parent||"scroll"===t.parent.statics.blotName||t.parent.statics.scope!==t.statics.scope?e:d(t.parent,e,n))}u.scope=r.Scope.BLOCK_BLOT},3036:function(t,e,n){"use strict";var r=n(6003);class i extends r.EmbedBlot{static value(){}optimize(){(this.prev||this.next)&&this.remove()}length(){return 0}value(){return""}}i.blotName="break",i.tagName="BR",e.A=i},580:function(t,e,n){"use strict";var r=n(6003);class i extends r.ContainerBlot{}e.A=i},4541:function(t,e,n){"use strict";var r=n(6003),i=n(5508);class s extends r.EmbedBlot{static blotName="cursor";static className="ql-cursor";static tagName="span";static CONTENTS="\ufeff";static value(){}constructor(t,e,n){super(t,e),this.selection=n,this.textNode=document.createTextNode(s.CONTENTS),this.domNode.appendChild(this.textNode),this.savedLength=0}detach(){null!=this.parent&&this.parent.removeChild(this)}format(t,e){if(0!==this.savedLength)return void super.format(t,e);let n=this,i=0;for(;null!=n&&n.statics.scope!==r.Scope.BLOCK_BLOT;)i+=n.offset(n.parent),n=n.parent;null!=n&&(this.savedLength=s.CONTENTS.length,n.optimize(),n.formatAt(i,s.CONTENTS.length,t,e),this.savedLength=0)}index(t,e){return t===this.textNode?0:super.index(t,e)}length(){return this.savedLength}position(){return[this.textNode,this.textNode.data.length]}remove(){super.remove(),this.parent=null}restore(){if(this.selection.composing||null==this.parent)return null;const t=this.selection.getNativeRange();for(;null!=this.domNode.lastChild&&this.domNode.lastChild!==this.textNode;)this.domNode.parentNode.insertBefore(this.domNode.lastChild,this.domNode);const e=this.prev instanceof i.A?this.prev:null,n=e?e.length():0,r=this.next instanceof i.A?this.next:null,o=r?r.text:"",{textNode:l}=this,a=l.data.split(s.CONTENTS).join("");let c;if(l.data=s.CONTENTS,e)c=e,(a||r)&&(e.insertAt(e.length(),a+o),r&&r.remove());else if(r)c=r,r.insertAt(0,a);else{const t=document.createTextNode(a);c=this.scroll.create(t),this.parent.insertBefore(c,this)}if(this.remove(),t){const i=(t,i)=>e&&t===e.domNode?i:t===l?n+i-1:r&&t===r.domNode?n+a.length+i:null,s=i(t.start.node,t.start.offset),o=i(t.end.node,t.end.offset);if(null!==s&&null!==o)return{startNode:c.domNode,startOffset:s,endNode:c.domNode,endOffset:o}}return null}update(t,e){if(t.some((t=>"characterData"===t.type&&t.target===this.textNode))){const t=this.restore();t&&(e.range=t)}}optimize(t){super.optimize(t);let{parent:e}=this;for(;e;){if("A"===e.domNode.tagName){this.savedLength=s.CONTENTS.length,e.isolate(this.offset(e),this.length()).unwrap(),this.savedLength=0;break}e=e.parent}}value(){return""}}e.A=s},746:function(t,e,n){"use strict";var r=n(6003),i=n(5508);const s="\ufeff";class o extends r.EmbedBlot{constructor(t,e){super(t,e),this.contentNode=document.createElement("span"),this.contentNode.setAttribute("contenteditable","false"),Array.from(this.domNode.childNodes).forEach((t=>{this.contentNode.appendChild(t)})),this.leftGuard=document.createTextNode(s),this.rightGuard=document.createTextNode(s),this.domNode.appendChild(this.leftGuard),this.domNode.appendChild(this.contentNode),this.domNode.appendChild(this.rightGuard)}index(t,e){return t===this.leftGuard?0:t===this.rightGuard?1:super.index(t,e)}restore(t){let e,n=null;const r=t.data.split(s).join("");if(t===this.leftGuard)if(this.prev instanceof i.A){const t=this.prev.length();this.prev.insertAt(t,r),n={startNode:this.prev.domNode,startOffset:t+r.length}}else e=document.createTextNode(r),this.parent.insertBefore(this.scroll.create(e),this),n={startNode:e,startOffset:r.length};else t===this.rightGuard&&(this.next instanceof i.A?(this.next.insertAt(0,r),n={startNode:this.next.domNode,startOffset:r.length}):(e=document.createTextNode(r),this.parent.insertBefore(this.scroll.create(e),this.next),n={startNode:e,startOffset:r.length}));return t.data=s,n}update(t,e){t.forEach((t=>{if("characterData"===t.type&&(t.target===this.leftGuard||t.target===this.rightGuard)){const n=this.restore(t.target);n&&(e.range=n)}}))}}e.A=o},4850:function(t,e,n){"use strict";var r=n(6003),i=n(3036),s=n(5508);class o extends r.InlineBlot{static allowedChildren=[o,i.A,r.EmbedBlot,s.A];static order=["cursor","inline","link","underline","strike","italic","bold","script","code"];static compare(t,e){const n=o.order.indexOf(t),r=o.order.indexOf(e);return n>=0||r>=0?n-r:t===e?0:t0){const t=this.parent.isolate(this.offset(),this.length());this.moveChildren(t),t.wrap(this)}}}e.A=o},5508:function(t,e,n){"use strict";n.d(e,{A:function(){return i},X:function(){return o}});var r=n(6003);class i extends r.TextBlot{}const s={"&":"&","<":"<",">":">",'"':""","'":"'"};function o(t){return t.replace(/[&<>"']/g,(t=>s[t]))}},3729:function(t,e,n){"use strict";n.d(e,{default:function(){return R}});var r=n(6142),i=n(9698),s=n(3036),o=n(580),l=n(4541),a=n(746),c=n(4850),u=n(6003),h=n(5232),d=n.n(h),f=n(5374);function p(t){return t instanceof i.Ay||t instanceof i.zo}function g(t){return"function"==typeof t.updateContent}class m extends u.ScrollBlot{static blotName="scroll";static className="ql-editor";static tagName="DIV";static defaultChild=i.Ay;static allowedChildren=[i.Ay,i.zo,o.A];constructor(t,e,n){let{emitter:r}=n;super(t,e),this.emitter=r,this.batch=!1,this.optimize(),this.enable(),this.domNode.addEventListener("dragstart",(t=>this.handleDragStart(t)))}batchStart(){Array.isArray(this.batch)||(this.batch=[])}batchEnd(){if(!this.batch)return;const t=this.batch;this.batch=!1,this.update(t)}emitMount(t){this.emitter.emit(f.A.events.SCROLL_BLOT_MOUNT,t)}emitUnmount(t){this.emitter.emit(f.A.events.SCROLL_BLOT_UNMOUNT,t)}emitEmbedUpdate(t,e){this.emitter.emit(f.A.events.SCROLL_EMBED_UPDATE,t,e)}deleteAt(t,e){const[n,r]=this.line(t),[o]=this.line(t+e);if(super.deleteAt(t,e),null!=o&&n!==o&&r>0){if(n instanceof i.zo||o instanceof i.zo)return void this.optimize();const t=o.children.head instanceof s.A?null:o.children.head;n.moveChildren(o,t),n.remove()}this.optimize()}enable(){let t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.domNode.setAttribute("contenteditable",t?"true":"false")}formatAt(t,e,n,r){super.formatAt(t,e,n,r),this.optimize()}insertAt(t,e,n){if(t>=this.length())if(null==n||null==this.scroll.query(e,u.Scope.BLOCK)){const t=this.scroll.create(this.statics.defaultChild.blotName);this.appendChild(t),null==n&&e.endsWith("\n")?t.insertAt(0,e.slice(0,-1),n):t.insertAt(0,e,n)}else{const t=this.scroll.create(e,n);this.appendChild(t)}else super.insertAt(t,e,n);this.optimize()}insertBefore(t,e){if(t.statics.scope===u.Scope.INLINE_BLOT){const n=this.scroll.create(this.statics.defaultChild.blotName);n.appendChild(t),super.insertBefore(n,e)}else super.insertBefore(t,e)}insertContents(t,e){const n=this.deltaToRenderBlocks(e.concat((new(d())).insert("\n"))),r=n.pop();if(null==r)return;this.batchStart();const s=n.shift();if(s){const e="block"===s.type&&(0===s.delta.length()||!this.descendant(i.zo,t)[0]&&t{this.formatAt(o-1,1,t,a[t])})),t=o}let[o,l]=this.children.find(t);n.length&&(o&&(o=o.split(l),l=0),n.forEach((t=>{if("block"===t.type)b(this.createBlock(t.attributes,o||void 0),0,t.delta);else{const e=this.create(t.key,t.value);this.insertBefore(e,o||void 0),Object.keys(t.attributes).forEach((n=>{e.format(n,t.attributes[n])}))}}))),"block"===r.type&&r.delta.length()&&b(this,o?o.offset(o.scroll)+l:this.length(),r.delta),this.batchEnd(),this.optimize()}isEnabled(){return"true"===this.domNode.getAttribute("contenteditable")}leaf(t){const e=this.path(t).pop();if(!e)return[null,-1];const[n,r]=e;return n instanceof u.LeafBlot?[n,r]:[null,-1]}line(t){return t===this.length()?this.line(t-1):this.descendant(p,t)}lines(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Number.MAX_VALUE;const n=(t,e,r)=>{let i=[],s=r;return t.children.forEachAt(e,r,((t,e,r)=>{p(t)?i.push(t):t instanceof u.ContainerBlot&&(i=i.concat(n(t,e,s))),s-=r})),i};return n(this,t,e)}optimize(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};this.batch||(super.optimize(t,e),t.length>0&&this.emitter.emit(f.A.events.SCROLL_OPTIMIZE,t,e))}path(t){return super.path(t).slice(1)}remove(){}update(t){if(this.batch)return void(Array.isArray(t)&&(this.batch=this.batch.concat(t)));let e=f.A.sources.USER;"string"==typeof t&&(e=t),Array.isArray(t)||(t=this.observer.takeRecords()),(t=t.filter((t=>{let{target:e}=t;const n=this.find(e,!0);return n&&!g(n)}))).length>0&&this.emitter.emit(f.A.events.SCROLL_BEFORE_UPDATE,e,t),super.update(t.concat([])),t.length>0&&this.emitter.emit(f.A.events.SCROLL_UPDATE,e,t)}updateEmbedAt(t,e,n){const[r]=this.descendant((t=>t instanceof i.zo),t);r&&r.statics.blotName===e&&g(r)&&r.updateContent(n)}handleDragStart(t){t.preventDefault()}deltaToRenderBlocks(t){const e=[];let n=new(d());return t.forEach((t=>{const r=t?.insert;if(r)if("string"==typeof r){const i=r.split("\n");i.slice(0,-1).forEach((r=>{n.insert(r,t.attributes),e.push({type:"block",delta:n,attributes:t.attributes??{}}),n=new(d())}));const s=i[i.length-1];s&&n.insert(s,t.attributes)}else{const i=Object.keys(r)[0];if(!i)return;this.query(i,u.Scope.INLINE)?n.push(t):(n.length()&&e.push({type:"block",delta:n,attributes:{}}),n=new(d()),e.push({type:"blockEmbed",key:i,value:r[i],attributes:t.attributes??{}}))}})),n.length()&&e.push({type:"block",delta:n,attributes:{}}),e}createBlock(t,e){let n;const r={};Object.entries(t).forEach((t=>{let[e,i]=t;null!=this.query(e,u.Scope.BLOCK&u.Scope.BLOT)?n=e:r[e]=i}));const i=this.create(n||this.statics.defaultChild.blotName,n?t[n]:void 0);this.insertBefore(i,e||void 0);const s=i.length();return Object.entries(r).forEach((t=>{let[e,n]=t;i.formatAt(0,s,e,n)})),i}}function b(t,e,n){n.reduce(((e,n)=>{const r=h.Op.length(n);let s=n.attributes||{};if(null!=n.insert)if("string"==typeof n.insert){const r=n.insert;t.insertAt(e,r);const[o]=t.descendant(u.LeafBlot,e),l=(0,i.Ji)(o);s=h.AttributeMap.diff(l,s)||{}}else if("object"==typeof n.insert){const r=Object.keys(n.insert)[0];if(null==r)return e;if(t.insertAt(e,r,n.insert[r]),null!=t.scroll.query(r,u.Scope.INLINE)){const[n]=t.descendant(u.LeafBlot,e),r=(0,i.Ji)(n);s=h.AttributeMap.diff(r,s)||{}}}return Object.keys(s).forEach((n=>{t.formatAt(e,r,n,s[n])})),e+r}),e)}var y=m,v=n(5508),A=n(584),x=n(4266);class N extends x.A{static DEFAULTS={delay:1e3,maxStack:100,userOnly:!1};lastRecorded=0;ignoreChange=!1;stack={undo:[],redo:[]};currentRange=null;constructor(t,e){super(t,e),this.quill.on(r.Ay.events.EDITOR_CHANGE,((t,e,n,i)=>{t===r.Ay.events.SELECTION_CHANGE?e&&i!==r.Ay.sources.SILENT&&(this.currentRange=e):t===r.Ay.events.TEXT_CHANGE&&(this.ignoreChange||(this.options.userOnly&&i!==r.Ay.sources.USER?this.transform(e):this.record(e,n)),this.currentRange=w(this.currentRange,e))})),this.quill.keyboard.addBinding({key:"z",shortKey:!0},this.undo.bind(this)),this.quill.keyboard.addBinding({key:["z","Z"],shortKey:!0,shiftKey:!0},this.redo.bind(this)),/Win/i.test(navigator.platform)&&this.quill.keyboard.addBinding({key:"y",shortKey:!0},this.redo.bind(this)),this.quill.root.addEventListener("beforeinput",(t=>{"historyUndo"===t.inputType?(this.undo(),t.preventDefault()):"historyRedo"===t.inputType&&(this.redo(),t.preventDefault())}))}change(t,e){if(0===this.stack[t].length)return;const n=this.stack[t].pop();if(!n)return;const i=this.quill.getContents(),s=n.delta.invert(i);this.stack[e].push({delta:s,range:w(n.range,s)}),this.lastRecorded=0,this.ignoreChange=!0,this.quill.updateContents(n.delta,r.Ay.sources.USER),this.ignoreChange=!1,this.restoreSelection(n)}clear(){this.stack={undo:[],redo:[]}}cutoff(){this.lastRecorded=0}record(t,e){if(0===t.ops.length)return;this.stack.redo=[];let n=t.invert(e),r=this.currentRange;const i=Date.now();if(this.lastRecorded+this.options.delay>i&&this.stack.undo.length>0){const t=this.stack.undo.pop();t&&(n=n.compose(t.delta),r=t.range)}else this.lastRecorded=i;0!==n.length()&&(this.stack.undo.push({delta:n,range:r}),this.stack.undo.length>this.options.maxStack&&this.stack.undo.shift())}redo(){this.change("redo","undo")}transform(t){E(this.stack.undo,t),E(this.stack.redo,t)}undo(){this.change("undo","redo")}restoreSelection(t){if(t.range)this.quill.setSelection(t.range,r.Ay.sources.USER);else{const e=function(t,e){const n=e.reduce(((t,e)=>t+(e.delete||0)),0);let r=e.length()-n;return function(t,e){const n=e.ops[e.ops.length-1];return null!=n&&(null!=n.insert?"string"==typeof n.insert&&n.insert.endsWith("\n"):null!=n.attributes&&Object.keys(n.attributes).some((e=>null!=t.query(e,u.Scope.BLOCK))))}(t,e)&&(r-=1),r}(this.quill.scroll,t.delta);this.quill.setSelection(e,r.Ay.sources.USER)}}}function E(t,e){let n=e;for(let e=t.length-1;e>=0;e-=1){const r=t[e];t[e]={delta:n.transform(r.delta,!0),range:r.range&&w(r.range,n)},n=r.delta.transform(n),0===t[e].delta.length()&&t.splice(e,1)}}function w(t,e){if(!t)return t;const n=e.transformPosition(t.index);return{index:n,length:e.transformPosition(t.index+t.length)-n}}var q=n(8123);class k extends x.A{constructor(t,e){super(t,e),t.root.addEventListener("drop",(e=>{e.preventDefault();let n=null;if(document.caretRangeFromPoint)n=document.caretRangeFromPoint(e.clientX,e.clientY);else if(document.caretPositionFromPoint){const t=document.caretPositionFromPoint(e.clientX,e.clientY);n=document.createRange(),n.setStart(t.offsetNode,t.offset),n.setEnd(t.offsetNode,t.offset)}const r=n&&t.selection.normalizeNative(n);if(r){const n=t.selection.normalizedToRange(r);e.dataTransfer?.files&&this.upload(n,e.dataTransfer.files)}}))}upload(t,e){const n=[];Array.from(e).forEach((t=>{t&&this.options.mimetypes?.includes(t.type)&&n.push(t)})),n.length>0&&this.options.handler.call(this,t,n)}}k.DEFAULTS={mimetypes:["image/png","image/jpeg"],handler(t,e){if(!this.quill.scroll.query("image"))return;const n=e.map((t=>new Promise((e=>{const n=new FileReader;n.onload=()=>{e(n.result)},n.readAsDataURL(t)}))));Promise.all(n).then((e=>{const n=e.reduce(((t,e)=>t.insert({image:e})),(new(d())).retain(t.index).delete(t.length));this.quill.updateContents(n,f.A.sources.USER),this.quill.setSelection(t.index+e.length,f.A.sources.SILENT)}))}};var _=k;const L=["insertText","insertReplacementText"];class S extends x.A{constructor(t,e){super(t,e),t.root.addEventListener("beforeinput",(t=>{this.handleBeforeInput(t)})),/Android/i.test(navigator.userAgent)||t.on(r.Ay.events.COMPOSITION_BEFORE_START,(()=>{this.handleCompositionStart()}))}deleteRange(t){(0,q.Xo)({range:t,quill:this.quill})}replaceText(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(0===t.length)return!1;if(e){const n=this.quill.getFormat(t.index,1);this.deleteRange(t),this.quill.updateContents((new(d())).retain(t.index).insert(e,n),r.Ay.sources.USER)}else this.deleteRange(t);return this.quill.setSelection(t.index+e.length,0,r.Ay.sources.SILENT),!0}handleBeforeInput(t){if(this.quill.composition.isComposing||t.defaultPrevented||!L.includes(t.inputType))return;const e=t.getTargetRanges?t.getTargetRanges()[0]:null;if(!e||!0===e.collapsed)return;const n=function(t){return"string"==typeof t.data?t.data:t.dataTransfer?.types.includes("text/plain")?t.dataTransfer.getData("text/plain"):null}(t);if(null==n)return;const r=this.quill.selection.normalizeNative(e),i=r?this.quill.selection.normalizedToRange(r):null;i&&this.replaceText(i,n)&&t.preventDefault()}handleCompositionStart(){const t=this.quill.getSelection();t&&this.replaceText(t)}}var O=S;const T=/Mac/i.test(navigator.platform);class j extends x.A{isListening=!1;selectionChangeDeadline=0;constructor(t,e){super(t,e),this.handleArrowKeys(),this.handleNavigationShortcuts()}handleArrowKeys(){this.quill.keyboard.addBinding({key:["ArrowLeft","ArrowRight"],offset:0,shiftKey:null,handler(t,e){let{line:n,event:i}=e;if(!(n instanceof u.ParentBlot&&n.uiNode))return!0;const s="rtl"===getComputedStyle(n.domNode).direction;return!!(s&&"ArrowRight"!==i.key||!s&&"ArrowLeft"!==i.key)||(this.quill.setSelection(t.index-1,t.length+(i.shiftKey?1:0),r.Ay.sources.USER),!1)}})}handleNavigationShortcuts(){this.quill.root.addEventListener("keydown",(t=>{!t.defaultPrevented&&(t=>"ArrowLeft"===t.key||"ArrowRight"===t.key||"ArrowUp"===t.key||"ArrowDown"===t.key||"Home"===t.key||!(!T||"a"!==t.key||!0!==t.ctrlKey))(t)&&this.ensureListeningToSelectionChange()}))}ensureListeningToSelectionChange(){this.selectionChangeDeadline=Date.now()+100,this.isListening||(this.isListening=!0,document.addEventListener("selectionchange",(()=>{this.isListening=!1,Date.now()<=this.selectionChangeDeadline&&this.handleSelectionChange()}),{once:!0}))}handleSelectionChange(){const t=document.getSelection();if(!t)return;const e=t.getRangeAt(0);if(!0!==e.collapsed||0!==e.startOffset)return;const n=this.quill.scroll.find(e.startContainer);if(!(n instanceof u.ParentBlot&&n.uiNode))return;const r=document.createRange();r.setStartAfter(n.uiNode),r.setEndAfter(n.uiNode),t.removeAllRanges(),t.addRange(r)}}var C=j;r.Ay.register({"blots/block":i.Ay,"blots/block/embed":i.zo,"blots/break":s.A,"blots/container":o.A,"blots/cursor":l.A,"blots/embed":a.A,"blots/inline":c.A,"blots/scroll":y,"blots/text":v.A,"modules/clipboard":A.Ay,"modules/history":N,"modules/keyboard":q.Ay,"modules/uploader":_,"modules/input":O,"modules/uiNode":C});var R=r.Ay},5374:function(t,e,n){"use strict";n.d(e,{A:function(){return o}});var r=n(8920),i=n(7356);const s=(0,n(6078).A)("quill:events");["selectionchange","mousedown","mouseup","click"].forEach((t=>{document.addEventListener(t,(function(){for(var t=arguments.length,e=new Array(t),n=0;n{const n=i.A.get(t);n&&n.emitter&&n.emitter.handleDOM(...e)}))}))}));var o=class extends r{static events={EDITOR_CHANGE:"editor-change",SCROLL_BEFORE_UPDATE:"scroll-before-update",SCROLL_BLOT_MOUNT:"scroll-blot-mount",SCROLL_BLOT_UNMOUNT:"scroll-blot-unmount",SCROLL_OPTIMIZE:"scroll-optimize",SCROLL_UPDATE:"scroll-update",SCROLL_EMBED_UPDATE:"scroll-embed-update",SELECTION_CHANGE:"selection-change",TEXT_CHANGE:"text-change",COMPOSITION_BEFORE_START:"composition-before-start",COMPOSITION_START:"composition-start",COMPOSITION_BEFORE_END:"composition-before-end",COMPOSITION_END:"composition-end"};static sources={API:"api",SILENT:"silent",USER:"user"};constructor(){super(),this.domListeners={},this.on("error",s.error)}emit(){for(var t=arguments.length,e=new Array(t),n=0;n1?e-1:0),r=1;r{let{node:r,handler:i}=e;(t.target===r||r.contains(t.target))&&i(t,...n)}))}listenDOM(t,e,n){this.domListeners[t]||(this.domListeners[t]=[]),this.domListeners[t].push({node:e,handler:n})}}},7356:function(t,e){"use strict";e.A=new WeakMap},6078:function(t,e){"use strict";const n=["error","warn","log","info"];let r="warn";function i(t){if(r&&n.indexOf(t)<=n.indexOf(r)){for(var e=arguments.length,i=new Array(e>1?e-1:0),s=1;s(e[n]=i.bind(console,n,t),e)),{})}s.level=t=>{r=t},i.level=s.level,e.A=s},4266:function(t,e){"use strict";e.A=class{static DEFAULTS={};constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};this.quill=t,this.options=e}}},6142:function(t,e,n){"use strict";n.d(e,{Ay:function(){return I}});var r=n(8347),i=n(6003),s=n(5232),o=n.n(s),l=n(3707),a=n(5123),c=n(9698),u=n(3036),h=n(4541),d=n(5508),f=n(8298);const p=/^[ -~]*$/;function g(t,e,n){if(0===t.length){const[t]=y(n.pop());return e<=0?``:`${g([],e-1,n)}`}const[{child:r,offset:i,length:s,indent:o,type:l},...a]=t,[c,u]=y(l);if(o>e)return n.push(l),o===e+1?`<${c}>${m(r,i,s)}${g(a,o,n)}`:`<${c}>
  • ${g(t,e+1,n)}`;const h=n[n.length-1];if(o===e&&l===h)return`
  • ${m(r,i,s)}${g(a,o,n)}`;const[d]=y(n.pop());return`${g(t,e-1,n)}`}function m(t,e,n){let r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if("html"in t&&"function"==typeof t.html)return t.html(e,n);if(t instanceof d.A)return(0,d.X)(t.value().slice(e,e+n)).replaceAll(" "," ");if(t instanceof i.ParentBlot){if("list-container"===t.statics.blotName){const r=[];return t.children.forEachAt(e,n,((t,e,n)=>{const i="formats"in t&&"function"==typeof t.formats?t.formats():{};r.push({child:t,offset:e,length:n,indent:i.indent||0,type:i.list})})),g(r,-1,[])}const i=[];if(t.children.forEachAt(e,n,((t,e,n)=>{i.push(m(t,e,n))})),r||"list"===t.statics.blotName)return i.join("");const{outerHTML:s,innerHTML:o}=t.domNode,[l,a]=s.split(`>${o}<`);return"${i.join("")}<${a}`:`${l}>${i.join("")}<${a}`}return t.domNode instanceof Element?t.domNode.outerHTML:""}function b(t,e){return Object.keys(e).reduce(((n,r)=>{if(null==t[r])return n;const i=e[r];return i===t[r]?n[r]=i:Array.isArray(i)?i.indexOf(t[r])<0?n[r]=i.concat([t[r]]):n[r]=i:n[r]=[i,t[r]],n}),{})}function y(t){const e="ordered"===t?"ol":"ul";switch(t){case"checked":return[e,' data-list="checked"'];case"unchecked":return[e,' data-list="unchecked"'];default:return[e,""]}}function v(t){return t.reduce(((t,e)=>{if("string"==typeof e.insert){const n=e.insert.replace(/\r\n/g,"\n").replace(/\r/g,"\n");return t.insert(n,e.attributes)}return t.push(e)}),new(o()))}function A(t,e){let{index:n,length:r}=t;return new f.Q(n+e,r)}var x=class{constructor(t){this.scroll=t,this.delta=this.getDelta()}applyDelta(t){this.scroll.update();let e=this.scroll.length();this.scroll.batchStart();const n=v(t),l=new(o());return function(t){const e=[];return t.forEach((t=>{"string"==typeof t.insert?t.insert.split("\n").forEach(((n,r)=>{r&&e.push({insert:"\n",attributes:t.attributes}),n&&e.push({insert:n,attributes:t.attributes})})):e.push(t)})),e}(n.ops.slice()).reduce(((t,n)=>{const o=s.Op.length(n);let a=n.attributes||{},u=!1,h=!1;if(null!=n.insert){if(l.retain(o),"string"==typeof n.insert){const o=n.insert;h=!o.endsWith("\n")&&(e<=t||!!this.scroll.descendant(c.zo,t)[0]),this.scroll.insertAt(t,o);const[l,u]=this.scroll.line(t);let d=(0,r.A)({},(0,c.Ji)(l));if(l instanceof c.Ay){const[t]=l.descendant(i.LeafBlot,u);t&&(d=(0,r.A)(d,(0,c.Ji)(t)))}a=s.AttributeMap.diff(d,a)||{}}else if("object"==typeof n.insert){const o=Object.keys(n.insert)[0];if(null==o)return t;const l=null!=this.scroll.query(o,i.Scope.INLINE);if(l)(e<=t||this.scroll.descendant(c.zo,t)[0])&&(h=!0);else if(t>0){const[e,n]=this.scroll.descendant(i.LeafBlot,t-1);e instanceof d.A?"\n"!==e.value()[n]&&(u=!0):e instanceof i.EmbedBlot&&e.statics.scope===i.Scope.INLINE_BLOT&&(u=!0)}if(this.scroll.insertAt(t,o,n.insert[o]),l){const[e]=this.scroll.descendant(i.LeafBlot,t);if(e){const t=(0,r.A)({},(0,c.Ji)(e));a=s.AttributeMap.diff(t,a)||{}}}}e+=o}else if(l.push(n),null!==n.retain&&"object"==typeof n.retain){const e=Object.keys(n.retain)[0];if(null==e)return t;this.scroll.updateEmbedAt(t,e,n.retain[e])}Object.keys(a).forEach((e=>{this.scroll.formatAt(t,o,e,a[e])}));const f=u?1:0,p=h?1:0;return e+=f+p,l.retain(f),l.delete(p),t+o+f+p}),0),l.reduce(((t,e)=>"number"==typeof e.delete?(this.scroll.deleteAt(t,e.delete),t):t+s.Op.length(e)),0),this.scroll.batchEnd(),this.scroll.optimize(),this.update(n)}deleteText(t,e){return this.scroll.deleteAt(t,e),this.update((new(o())).retain(t).delete(e))}formatLine(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};this.scroll.update(),Object.keys(n).forEach((r=>{this.scroll.lines(t,Math.max(e,1)).forEach((t=>{t.format(r,n[r])}))})),this.scroll.optimize();const r=(new(o())).retain(t).retain(e,(0,l.A)(n));return this.update(r)}formatText(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};Object.keys(n).forEach((r=>{this.scroll.formatAt(t,e,r,n[r])}));const r=(new(o())).retain(t).retain(e,(0,l.A)(n));return this.update(r)}getContents(t,e){return this.delta.slice(t,t+e)}getDelta(){return this.scroll.lines().reduce(((t,e)=>t.concat(e.delta())),new(o()))}getFormat(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=[],r=[];0===e?this.scroll.path(t).forEach((t=>{const[e]=t;e instanceof c.Ay?n.push(e):e instanceof i.LeafBlot&&r.push(e)})):(n=this.scroll.lines(t,e),r=this.scroll.descendants(i.LeafBlot,t,e));const[s,o]=[n,r].map((t=>{const e=t.shift();if(null==e)return{};let n=(0,c.Ji)(e);for(;Object.keys(n).length>0;){const e=t.shift();if(null==e)return n;n=b((0,c.Ji)(e),n)}return n}));return{...s,...o}}getHTML(t,e){const[n,r]=this.scroll.line(t);if(n){const i=n.length();return n.length()>=r+e&&(0!==r||e!==i)?m(n,r,e,!0):m(this.scroll,t,e,!0)}return""}getText(t,e){return this.getContents(t,e).filter((t=>"string"==typeof t.insert)).map((t=>t.insert)).join("")}insertContents(t,e){const n=v(e),r=(new(o())).retain(t).concat(n);return this.scroll.insertContents(t,n),this.update(r)}insertEmbed(t,e,n){return this.scroll.insertAt(t,e,n),this.update((new(o())).retain(t).insert({[e]:n}))}insertText(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return e=e.replace(/\r\n/g,"\n").replace(/\r/g,"\n"),this.scroll.insertAt(t,e),Object.keys(n).forEach((r=>{this.scroll.formatAt(t,e.length,r,n[r])})),this.update((new(o())).retain(t).insert(e,(0,l.A)(n)))}isBlank(){if(0===this.scroll.children.length)return!0;if(this.scroll.children.length>1)return!1;const t=this.scroll.children.head;if(t?.statics.blotName!==c.Ay.blotName)return!1;const e=t;return!(e.children.length>1)&&e.children.head instanceof u.A}removeFormat(t,e){const n=this.getText(t,e),[r,i]=this.scroll.line(t+e);let s=0,l=new(o());null!=r&&(s=r.length()-i,l=r.delta().slice(i,i+s-1).insert("\n"));const a=this.getContents(t,e+s).diff((new(o())).insert(n).concat(l)),c=(new(o())).retain(t).concat(a);return this.applyDelta(c)}update(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;const r=this.delta;if(1===e.length&&"characterData"===e[0].type&&e[0].target.data.match(p)&&this.scroll.find(e[0].target)){const i=this.scroll.find(e[0].target),s=(0,c.Ji)(i),l=i.offset(this.scroll),a=e[0].oldValue.replace(h.A.CONTENTS,""),u=(new(o())).insert(a),d=(new(o())).insert(i.value()),f=n&&{oldRange:A(n.oldRange,-l),newRange:A(n.newRange,-l)};t=(new(o())).retain(l).concat(u.diff(d,f)).reduce(((t,e)=>e.insert?t.insert(e.insert,s):t.push(e)),new(o())),this.delta=r.compose(t)}else this.delta=this.getDelta(),t&&(0,a.A)(r.compose(t),this.delta)||(t=r.diff(this.delta,n));return t}},N=n(5374),E=n(7356),w=n(6078),q=n(4266),k=n(746),_=class{isComposing=!1;constructor(t,e){this.scroll=t,this.emitter=e,this.setupListeners()}setupListeners(){this.scroll.domNode.addEventListener("compositionstart",(t=>{this.isComposing||this.handleCompositionStart(t)})),this.scroll.domNode.addEventListener("compositionend",(t=>{this.isComposing&&queueMicrotask((()=>{this.handleCompositionEnd(t)}))}))}handleCompositionStart(t){const e=t.target instanceof Node?this.scroll.find(t.target,!0):null;!e||e instanceof k.A||(this.emitter.emit(N.A.events.COMPOSITION_BEFORE_START,t),this.scroll.batchStart(),this.emitter.emit(N.A.events.COMPOSITION_START,t),this.isComposing=!0)}handleCompositionEnd(t){this.emitter.emit(N.A.events.COMPOSITION_BEFORE_END,t),this.scroll.batchEnd(),this.emitter.emit(N.A.events.COMPOSITION_END,t),this.isComposing=!1}},L=n(9609);const S=t=>{const e=t.getBoundingClientRect(),n="offsetWidth"in t&&Math.abs(e.width)/t.offsetWidth||1,r="offsetHeight"in t&&Math.abs(e.height)/t.offsetHeight||1;return{top:e.top,right:e.left+t.clientWidth*n,bottom:e.top+t.clientHeight*r,left:e.left}},O=t=>{const e=parseInt(t,10);return Number.isNaN(e)?0:e},T=(t,e,n,r,i,s)=>tr?0:tr?e-t>r-n?t+i-n:e-r+s:0;const j=["block","break","cursor","inline","scroll","text"];const C=(0,w.A)("quill"),R=new i.Registry;i.ParentBlot.uiClass="ql-ui";class I{static DEFAULTS={bounds:null,modules:{clipboard:!0,keyboard:!0,history:!0,uploader:!0},placeholder:"",readOnly:!1,registry:R,theme:"default"};static events=N.A.events;static sources=N.A.sources;static version="2.0.3";static imports={delta:o(),parchment:i,"core/module":q.A,"core/theme":L.A};static debug(t){!0===t&&(t="log"),w.A.level(t)}static find(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return E.A.get(t)||R.find(t,e)}static import(t){return null==this.imports[t]&&C.error(`Cannot import ${t}. Are you sure it was registered?`),this.imports[t]}static register(){if("string"!=typeof(arguments.length<=0?void 0:arguments[0])){const t=arguments.length<=0?void 0:arguments[0],e=!!(arguments.length<=1?void 0:arguments[1]),n="attrName"in t?t.attrName:t.blotName;"string"==typeof n?this.register(`formats/${n}`,t,e):Object.keys(t).forEach((n=>{this.register(n,t[n],e)}))}else{const t=arguments.length<=0?void 0:arguments[0],e=arguments.length<=1?void 0:arguments[1],n=!!(arguments.length<=2?void 0:arguments[2]);null==this.imports[t]||n||C.warn(`Overwriting ${t} with`,e),this.imports[t]=e,(t.startsWith("blots/")||t.startsWith("formats/"))&&e&&"boolean"!=typeof e&&"abstract"!==e.blotName&&R.register(e),"function"==typeof e.register&&e.register(R)}}constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(this.options=function(t,e){const n=B(t);if(!n)throw new Error("Invalid Quill container");const s=!e.theme||e.theme===I.DEFAULTS.theme?L.A:I.import(`themes/${e.theme}`);if(!s)throw new Error(`Invalid theme ${e.theme}. Did you register it?`);const{modules:o,...l}=I.DEFAULTS,{modules:a,...c}=s.DEFAULTS;let u=M(e.modules);null!=u&&u.toolbar&&u.toolbar.constructor!==Object&&(u={...u,toolbar:{container:u.toolbar}});const h=(0,r.A)({},M(o),M(a),u),d={...l,...U(c),...U(e)};let f=e.registry;return f?e.formats&&C.warn('Ignoring "formats" option because "registry" is specified'):f=e.formats?((t,e,n)=>{const r=new i.Registry;return j.forEach((t=>{const n=e.query(t);n&&r.register(n)})),t.forEach((t=>{let i=e.query(t);i||n.error(`Cannot register "${t}" specified in "formats" config. Are you sure it was registered?`);let s=0;for(;i;)if(r.register(i),i="blotName"in i?i.requiredContainer??null:null,s+=1,s>100){n.error(`Cycle detected in registering blot requiredContainer: "${t}"`);break}})),r})(e.formats,d.registry,C):d.registry,{...d,registry:f,container:n,theme:s,modules:Object.entries(h).reduce(((t,e)=>{let[n,i]=e;if(!i)return t;const s=I.import(`modules/${n}`);return null==s?(C.error(`Cannot load ${n} module. Are you sure you registered it?`),t):{...t,[n]:(0,r.A)({},s.DEFAULTS||{},i)}}),{}),bounds:B(d.bounds)}}(t,e),this.container=this.options.container,null==this.container)return void C.error("Invalid Quill container",t);this.options.debug&&I.debug(this.options.debug);const n=this.container.innerHTML.trim();this.container.classList.add("ql-container"),this.container.innerHTML="",E.A.set(this.container,this),this.root=this.addContainer("ql-editor"),this.root.classList.add("ql-blank"),this.emitter=new N.A;const s=i.ScrollBlot.blotName,l=this.options.registry.query(s);if(!l||!("blotName"in l))throw new Error(`Cannot initialize Quill without "${s}" blot`);if(this.scroll=new l(this.options.registry,this.root,{emitter:this.emitter}),this.editor=new x(this.scroll),this.selection=new f.A(this.scroll,this.emitter),this.composition=new _(this.scroll,this.emitter),this.theme=new this.options.theme(this,this.options),this.keyboard=this.theme.addModule("keyboard"),this.clipboard=this.theme.addModule("clipboard"),this.history=this.theme.addModule("history"),this.uploader=this.theme.addModule("uploader"),this.theme.addModule("input"),this.theme.addModule("uiNode"),this.theme.init(),this.emitter.on(N.A.events.EDITOR_CHANGE,(t=>{t===N.A.events.TEXT_CHANGE&&this.root.classList.toggle("ql-blank",this.editor.isBlank())})),this.emitter.on(N.A.events.SCROLL_UPDATE,((t,e)=>{const n=this.selection.lastRange,[r]=this.selection.getRange(),i=n&&r?{oldRange:n,newRange:r}:void 0;D.call(this,(()=>this.editor.update(null,e,i)),t)})),this.emitter.on(N.A.events.SCROLL_EMBED_UPDATE,((t,e)=>{const n=this.selection.lastRange,[r]=this.selection.getRange(),i=n&&r?{oldRange:n,newRange:r}:void 0;D.call(this,(()=>{const n=(new(o())).retain(t.offset(this)).retain({[t.statics.blotName]:e});return this.editor.update(n,[],i)}),I.sources.USER)})),n){const t=this.clipboard.convert({html:`${n}


    `,text:"\n"});this.setContents(t)}this.history.clear(),this.options.placeholder&&this.root.setAttribute("data-placeholder",this.options.placeholder),this.options.readOnly&&this.disable(),this.allowReadOnlyEdits=!1}addContainer(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if("string"==typeof t){const e=t;(t=document.createElement("div")).classList.add(e)}return this.container.insertBefore(t,e),t}blur(){this.selection.setRange(null)}deleteText(t,e,n){return[t,e,,n]=P(t,e,n),D.call(this,(()=>this.editor.deleteText(t,e)),n,t,-1*e)}disable(){this.enable(!1)}editReadOnly(t){this.allowReadOnlyEdits=!0;const e=t();return this.allowReadOnlyEdits=!1,e}enable(){let t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.scroll.enable(t),this.container.classList.toggle("ql-disabled",!t)}focus(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.selection.focus(),t.preventScroll||this.scrollSelectionIntoView()}format(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:N.A.sources.API;return D.call(this,(()=>{const n=this.getSelection(!0);let r=new(o());if(null==n)return r;if(this.scroll.query(t,i.Scope.BLOCK))r=this.editor.formatLine(n.index,n.length,{[t]:e});else{if(0===n.length)return this.selection.format(t,e),r;r=this.editor.formatText(n.index,n.length,{[t]:e})}return this.setSelection(n,N.A.sources.SILENT),r}),n)}formatLine(t,e,n,r,i){let s;return[t,e,s,i]=P(t,e,n,r,i),D.call(this,(()=>this.editor.formatLine(t,e,s)),i,t,0)}formatText(t,e,n,r,i){let s;return[t,e,s,i]=P(t,e,n,r,i),D.call(this,(()=>this.editor.formatText(t,e,s)),i,t,0)}getBounds(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=null;if(n="number"==typeof t?this.selection.getBounds(t,e):this.selection.getBounds(t.index,t.length),!n)return null;const r=this.container.getBoundingClientRect();return{bottom:n.bottom-r.top,height:n.height,left:n.left-r.left,right:n.right-r.left,top:n.top-r.top,width:n.width}}getContents(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.getLength()-t;return[t,e]=P(t,e),this.editor.getContents(t,e)}getFormat(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.getSelection(!0),e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return"number"==typeof t?this.editor.getFormat(t,e):this.editor.getFormat(t.index,t.length)}getIndex(t){return t.offset(this.scroll)}getLength(){return this.scroll.length()}getLeaf(t){return this.scroll.leaf(t)}getLine(t){return this.scroll.line(t)}getLines(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Number.MAX_VALUE;return"number"!=typeof t?this.scroll.lines(t.index,t.length):this.scroll.lines(t,e)}getModule(t){return this.theme.modules[t]}getSelection(){return arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&this.focus(),this.update(),this.selection.getRange()[0]}getSemanticHTML(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1?arguments[1]:void 0;return"number"==typeof t&&(e=e??this.getLength()-t),[t,e]=P(t,e),this.editor.getHTML(t,e)}getText(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1?arguments[1]:void 0;return"number"==typeof t&&(e=e??this.getLength()-t),[t,e]=P(t,e),this.editor.getText(t,e)}hasFocus(){return this.selection.hasFocus()}insertEmbed(t,e,n){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:I.sources.API;return D.call(this,(()=>this.editor.insertEmbed(t,e,n)),r,t)}insertText(t,e,n,r,i){let s;return[t,,s,i]=P(t,0,n,r,i),D.call(this,(()=>this.editor.insertText(t,e,s)),i,t,e.length)}isEnabled(){return this.scroll.isEnabled()}off(){return this.emitter.off(...arguments)}on(){return this.emitter.on(...arguments)}once(){return this.emitter.once(...arguments)}removeFormat(t,e,n){return[t,e,,n]=P(t,e,n),D.call(this,(()=>this.editor.removeFormat(t,e)),n,t)}scrollRectIntoView(t){((t,e)=>{const n=t.ownerDocument;let r=e,i=t;for(;i;){const t=i===n.body,e=t?{top:0,right:window.visualViewport?.width??n.documentElement.clientWidth,bottom:window.visualViewport?.height??n.documentElement.clientHeight,left:0}:S(i),o=getComputedStyle(i),l=T(r.left,r.right,e.left,e.right,O(o.scrollPaddingLeft),O(o.scrollPaddingRight)),a=T(r.top,r.bottom,e.top,e.bottom,O(o.scrollPaddingTop),O(o.scrollPaddingBottom));if(l||a)if(t)n.defaultView?.scrollBy(l,a);else{const{scrollLeft:t,scrollTop:e}=i;a&&(i.scrollTop+=a),l&&(i.scrollLeft+=l);const n=i.scrollLeft-t,s=i.scrollTop-e;r={left:r.left-n,top:r.top-s,right:r.right-n,bottom:r.bottom-s}}i=t||"fixed"===o.position?null:(s=i).parentElement||s.getRootNode().host||null}var s})(this.root,t)}scrollIntoView(){console.warn("Quill#scrollIntoView() has been deprecated and will be removed in the near future. Please use Quill#scrollSelectionIntoView() instead."),this.scrollSelectionIntoView()}scrollSelectionIntoView(){const t=this.selection.lastRange,e=t&&this.selection.getBounds(t.index,t.length);e&&this.scrollRectIntoView(e)}setContents(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:N.A.sources.API;return D.call(this,(()=>{t=new(o())(t);const e=this.getLength(),n=this.editor.deleteText(0,e),r=this.editor.insertContents(0,t),i=this.editor.deleteText(this.getLength()-1,1);return n.compose(r).compose(i)}),e)}setSelection(t,e,n){null==t?this.selection.setRange(null,e||I.sources.API):([t,e,,n]=P(t,e,n),this.selection.setRange(new f.Q(Math.max(0,t),e),n),n!==N.A.sources.SILENT&&this.scrollSelectionIntoView())}setText(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:N.A.sources.API;const n=(new(o())).insert(t);return this.setContents(n,e)}update(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:N.A.sources.USER;const e=this.scroll.update(t);return this.selection.update(t),e}updateContents(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:N.A.sources.API;return D.call(this,(()=>(t=new(o())(t),this.editor.applyDelta(t))),e,!0)}}function B(t){return"string"==typeof t?document.querySelector(t):t}function M(t){return Object.entries(t??{}).reduce(((t,e)=>{let[n,r]=e;return{...t,[n]:!0===r?{}:r}}),{})}function U(t){return Object.fromEntries(Object.entries(t).filter((t=>void 0!==t[1])))}function D(t,e,n,r){if(!this.isEnabled()&&e===N.A.sources.USER&&!this.allowReadOnlyEdits)return new(o());let i=null==n?null:this.getSelection();const s=this.editor.delta,l=t();if(null!=i&&(!0===n&&(n=i.index),null==r?i=z(i,l,e):0!==r&&(i=z(i,n,r,e)),this.setSelection(i,N.A.sources.SILENT)),l.length()>0){const t=[N.A.events.TEXT_CHANGE,l,s,e];this.emitter.emit(N.A.events.EDITOR_CHANGE,...t),e!==N.A.sources.SILENT&&this.emitter.emit(...t)}return l}function P(t,e,n,r,i){let s={};return"number"==typeof t.index&&"number"==typeof t.length?"number"!=typeof e?(i=r,r=n,n=e,e=t.length,t=t.index):(e=t.length,t=t.index):"number"!=typeof e&&(i=r,r=n,n=e,e=0),"object"==typeof n?(s=n,i=r):"string"==typeof n&&(null!=r?s[n]=r:i=n),[t,e,s,i=i||N.A.sources.API]}function z(t,e,n,r){const i="number"==typeof n?n:0;if(null==t)return null;let s,o;return e&&"function"==typeof e.transformPosition?[s,o]=[t.index,t.index+t.length].map((t=>e.transformPosition(t,r!==N.A.sources.USER))):[s,o]=[t.index,t.index+t.length].map((t=>t=0?t+i:Math.max(e,t+i))),new f.Q(s,o-s)}},8298:function(t,e,n){"use strict";n.d(e,{Q:function(){return a}});var r=n(6003),i=n(5123),s=n(3707),o=n(5374);const l=(0,n(6078).A)("quill:selection");class a{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;this.index=t,this.length=e}}function c(t,e){try{e.parentNode}catch(t){return!1}return t.contains(e)}e.A=class{constructor(t,e){this.emitter=e,this.scroll=t,this.composing=!1,this.mouseDown=!1,this.root=this.scroll.domNode,this.cursor=this.scroll.create("cursor",this),this.savedRange=new a(0,0),this.lastRange=this.savedRange,this.lastNative=null,this.handleComposition(),this.handleDragging(),this.emitter.listenDOM("selectionchange",document,(()=>{this.mouseDown||this.composing||setTimeout(this.update.bind(this,o.A.sources.USER),1)})),this.emitter.on(o.A.events.SCROLL_BEFORE_UPDATE,(()=>{if(!this.hasFocus())return;const t=this.getNativeRange();null!=t&&t.start.node!==this.cursor.textNode&&this.emitter.once(o.A.events.SCROLL_UPDATE,((e,n)=>{try{this.root.contains(t.start.node)&&this.root.contains(t.end.node)&&this.setNativeRange(t.start.node,t.start.offset,t.end.node,t.end.offset);const r=n.some((t=>"characterData"===t.type||"childList"===t.type||"attributes"===t.type&&t.target===this.root));this.update(r?o.A.sources.SILENT:e)}catch(t){}}))})),this.emitter.on(o.A.events.SCROLL_OPTIMIZE,((t,e)=>{if(e.range){const{startNode:t,startOffset:n,endNode:r,endOffset:i}=e.range;this.setNativeRange(t,n,r,i),this.update(o.A.sources.SILENT)}})),this.update(o.A.sources.SILENT)}handleComposition(){this.emitter.on(o.A.events.COMPOSITION_BEFORE_START,(()=>{this.composing=!0})),this.emitter.on(o.A.events.COMPOSITION_END,(()=>{if(this.composing=!1,this.cursor.parent){const t=this.cursor.restore();if(!t)return;setTimeout((()=>{this.setNativeRange(t.startNode,t.startOffset,t.endNode,t.endOffset)}),1)}}))}handleDragging(){this.emitter.listenDOM("mousedown",document.body,(()=>{this.mouseDown=!0})),this.emitter.listenDOM("mouseup",document.body,(()=>{this.mouseDown=!1,this.update(o.A.sources.USER)}))}focus(){this.hasFocus()||(this.root.focus({preventScroll:!0}),this.setRange(this.savedRange))}format(t,e){this.scroll.update();const n=this.getNativeRange();if(null!=n&&n.native.collapsed&&!this.scroll.query(t,r.Scope.BLOCK)){if(n.start.node!==this.cursor.textNode){const t=this.scroll.find(n.start.node,!1);if(null==t)return;if(t instanceof r.LeafBlot){const e=t.split(n.start.offset);t.parent.insertBefore(this.cursor,e)}else t.insertBefore(this.cursor,n.start.node);this.cursor.attach()}this.cursor.format(t,e),this.scroll.optimize(),this.setNativeRange(this.cursor.textNode,this.cursor.textNode.data.length),this.update()}}getBounds(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;const n=this.scroll.length();let r;t=Math.min(t,n-1),e=Math.min(t+e,n-1)-t;let[i,s]=this.scroll.leaf(t);if(null==i)return null;if(e>0&&s===i.length()){const[e]=this.scroll.leaf(t+1);if(e){const[n]=this.scroll.line(t),[r]=this.scroll.line(t+1);n===r&&(i=e,s=0)}}[r,s]=i.position(s,!0);const o=document.createRange();if(e>0)return o.setStart(r,s),[i,s]=this.scroll.leaf(t+e),null==i?null:([r,s]=i.position(s,!0),o.setEnd(r,s),o.getBoundingClientRect());let l,a="left";if(r instanceof Text){if(!r.data.length)return null;s0&&(a="right")}return{bottom:l.top+l.height,height:l.height,left:l[a],right:l[a],top:l.top,width:0}}getNativeRange(){const t=document.getSelection();if(null==t||t.rangeCount<=0)return null;const e=t.getRangeAt(0);if(null==e)return null;const n=this.normalizeNative(e);return l.info("getNativeRange",n),n}getRange(){const t=this.scroll.domNode;if("isConnected"in t&&!t.isConnected)return[null,null];const e=this.getNativeRange();return null==e?[null,null]:[this.normalizedToRange(e),e]}hasFocus(){return document.activeElement===this.root||null!=document.activeElement&&c(this.root,document.activeElement)}normalizedToRange(t){const e=[[t.start.node,t.start.offset]];t.native.collapsed||e.push([t.end.node,t.end.offset]);const n=e.map((t=>{const[e,n]=t,i=this.scroll.find(e,!0),s=i.offset(this.scroll);return 0===n?s:i instanceof r.LeafBlot?s+i.index(e,n):s+i.length()})),i=Math.min(Math.max(...n),this.scroll.length()-1),s=Math.min(i,...n);return new a(s,i-s)}normalizeNative(t){if(!c(this.root,t.startContainer)||!t.collapsed&&!c(this.root,t.endContainer))return null;const e={start:{node:t.startContainer,offset:t.startOffset},end:{node:t.endContainer,offset:t.endOffset},native:t};return[e.start,e.end].forEach((t=>{let{node:e,offset:n}=t;for(;!(e instanceof Text)&&e.childNodes.length>0;)if(e.childNodes.length>n)e=e.childNodes[n],n=0;else{if(e.childNodes.length!==n)break;e=e.lastChild,n=e instanceof Text?e.data.length:e.childNodes.length>0?e.childNodes.length:e.childNodes.length+1}t.node=e,t.offset=n})),e}rangeToNative(t){const e=this.scroll.length(),n=(t,n)=>{t=Math.min(e-1,t);const[r,i]=this.scroll.leaf(t);return r?r.position(i,n):[null,-1]};return[...n(t.index,!1),...n(t.index+t.length,!0)]}setNativeRange(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:e,i=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if(l.info("setNativeRange",t,e,n,r),null!=t&&(null==this.root.parentNode||null==t.parentNode||null==n.parentNode))return;const s=document.getSelection();if(null!=s)if(null!=t){this.hasFocus()||this.root.focus({preventScroll:!0});const{native:o}=this.getNativeRange()||{};if(null==o||i||t!==o.startContainer||e!==o.startOffset||n!==o.endContainer||r!==o.endOffset){t instanceof Element&&"BR"===t.tagName&&(e=Array.from(t.parentNode.childNodes).indexOf(t),t=t.parentNode),n instanceof Element&&"BR"===n.tagName&&(r=Array.from(n.parentNode.childNodes).indexOf(n),n=n.parentNode);const i=document.createRange();i.setStart(t,e),i.setEnd(n,r),s.removeAllRanges(),s.addRange(i)}}else s.removeAllRanges(),this.root.blur()}setRange(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:o.A.sources.API;if("string"==typeof e&&(n=e,e=!1),l.info("setRange",t),null!=t){const n=this.rangeToNative(t);this.setNativeRange(...n,e)}else this.setNativeRange(null);this.update(n)}update(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o.A.sources.USER;const e=this.lastRange,[n,r]=this.getRange();if(this.lastRange=n,this.lastNative=r,null!=this.lastRange&&(this.savedRange=this.lastRange),!(0,i.A)(e,this.lastRange)){if(!this.composing&&null!=r&&r.native.collapsed&&r.start.node!==this.cursor.textNode){const t=this.cursor.restore();t&&this.setNativeRange(t.startNode,t.startOffset,t.endNode,t.endOffset)}const n=[o.A.events.SELECTION_CHANGE,(0,s.A)(this.lastRange),(0,s.A)(e),t];this.emitter.emit(o.A.events.EDITOR_CHANGE,...n),t!==o.A.sources.SILENT&&this.emitter.emit(...n)}}}},9609:function(t,e){"use strict";class n{static DEFAULTS={modules:{}};static themes={default:n};modules={};constructor(t,e){this.quill=t,this.options=e}init(){Object.keys(this.options.modules).forEach((t=>{null==this.modules[t]&&this.addModule(t)}))}addModule(t){const e=this.quill.constructor.import(`modules/${t}`);return this.modules[t]=new e(this.quill,this.options.modules[t]||{}),this.modules[t]}}e.A=n},8276:function(t,e,n){"use strict";n.d(e,{Hu:function(){return l},gS:function(){return s},qh:function(){return o}});var r=n(6003);const i={scope:r.Scope.BLOCK,whitelist:["right","center","justify"]},s=new r.Attributor("align","align",i),o=new r.ClassAttributor("align","ql-align",i),l=new r.StyleAttributor("align","text-align",i)},9541:function(t,e,n){"use strict";n.d(e,{l:function(){return s},s:function(){return o}});var r=n(6003),i=n(8638);const s=new r.ClassAttributor("background","ql-bg",{scope:r.Scope.INLINE}),o=new i.a2("background","background-color",{scope:r.Scope.INLINE})},9404:function(t,e,n){"use strict";n.d(e,{Ay:function(){return h},Cy:function(){return d},EJ:function(){return u}});var r=n(9698),i=n(3036),s=n(4541),o=n(4850),l=n(5508),a=n(580),c=n(6142);class u extends a.A{static create(t){const e=super.create(t);return e.setAttribute("spellcheck","false"),e}code(t,e){return this.children.map((t=>t.length()<=1?"":t.domNode.innerText)).join("\n").slice(t,t+e)}html(t,e){return`
    \n${(0,l.X)(this.code(t,e))}\n
    `}}class h extends r.Ay{static TAB=" ";static register(){c.Ay.register(u)}}class d extends o.A{}d.blotName="code",d.tagName="CODE",h.blotName="code-block",h.className="ql-code-block",h.tagName="DIV",u.blotName="code-block-container",u.className="ql-code-block-container",u.tagName="DIV",u.allowedChildren=[h],h.allowedChildren=[l.A,i.A,s.A],h.requiredContainer=u},8638:function(t,e,n){"use strict";n.d(e,{JM:function(){return o},a2:function(){return i},g3:function(){return s}});var r=n(6003);class i extends r.StyleAttributor{value(t){let e=super.value(t);return e.startsWith("rgb(")?(e=e.replace(/^[^\d]+/,"").replace(/[^\d]+$/,""),`#${e.split(",").map((t=>`00${parseInt(t,10).toString(16)}`.slice(-2))).join("")}`):e}}const s=new r.ClassAttributor("color","ql-color",{scope:r.Scope.INLINE}),o=new i("color","color",{scope:r.Scope.INLINE})},7912:function(t,e,n){"use strict";n.d(e,{Mc:function(){return s},VL:function(){return l},sY:function(){return o}});var r=n(6003);const i={scope:r.Scope.BLOCK,whitelist:["rtl"]},s=new r.Attributor("direction","dir",i),o=new r.ClassAttributor("direction","ql-direction",i),l=new r.StyleAttributor("direction","direction",i)},6772:function(t,e,n){"use strict";n.d(e,{q:function(){return s},z:function(){return l}});var r=n(6003);const i={scope:r.Scope.INLINE,whitelist:["serif","monospace"]},s=new r.ClassAttributor("font","ql-font",i);class o extends r.StyleAttributor{value(t){return super.value(t).replace(/["']/g,"")}}const l=new o("font","font-family",i)},664:function(t,e,n){"use strict";n.d(e,{U:function(){return i},r:function(){return s}});var r=n(6003);const i=new r.ClassAttributor("size","ql-size",{scope:r.Scope.INLINE,whitelist:["small","large","huge"]}),s=new r.StyleAttributor("size","font-size",{scope:r.Scope.INLINE,whitelist:["10px","18px","32px"]})},584:function(t,e,n){"use strict";n.d(e,{Ay:function(){return S},hV:function(){return I}});var r=n(6003),i=n(5232),s=n.n(i),o=n(9698),l=n(6078),a=n(4266),c=n(6142),u=n(8276),h=n(9541),d=n(9404),f=n(8638),p=n(7912),g=n(6772),m=n(664),b=n(8123);const y=/font-weight:\s*normal/,v=["P","OL","UL"],A=t=>t&&v.includes(t.tagName),x=/\bmso-list:[^;]*ignore/i,N=/\bmso-list:[^;]*\bl(\d+)/i,E=/\bmso-list:[^;]*\blevel(\d+)/i,w=[function(t){"urn:schemas-microsoft-com:office:word"===t.documentElement.getAttribute("xmlns:w")&&(t=>{const e=Array.from(t.querySelectorAll("[style*=mso-list]")),n=[],r=[];e.forEach((t=>{(t.getAttribute("style")||"").match(x)?n.push(t):r.push(t)})),n.forEach((t=>t.parentNode?.removeChild(t)));const i=t.documentElement.innerHTML,s=r.map((t=>((t,e)=>{const n=t.getAttribute("style"),r=n?.match(N);if(!r)return null;const i=Number(r[1]),s=n?.match(E),o=s?Number(s[1]):1,l=new RegExp(`@list l${i}:level${o}\\s*\\{[^\\}]*mso-level-number-format:\\s*([\\w-]+)`,"i"),a=e.match(l);return{id:i,indent:o,type:a&&"bullet"===a[1]?"bullet":"ordered",element:t}})(t,i))).filter((t=>t));for(;s.length;){const t=[];let e=s.shift();for(;e;)t.push(e),e=s.length&&s[0]?.element===e.element.nextElementSibling&&s[0].id===e.id?s.shift():null;const n=document.createElement("ul");t.forEach((t=>{const e=document.createElement("li");e.setAttribute("data-list",t.type),t.indent>1&&e.setAttribute("class","ql-indent-"+(t.indent-1)),e.innerHTML=t.element.innerHTML,n.appendChild(e)}));const r=t[0]?.element,{parentNode:i}=r??{};r&&i?.replaceChild(n,r),t.slice(1).forEach((t=>{let{element:e}=t;i?.removeChild(e)}))}})(t)},function(t){t.querySelector('[id^="docs-internal-guid-"]')&&((t=>{Array.from(t.querySelectorAll('b[style*="font-weight"]')).filter((t=>t.getAttribute("style")?.match(y))).forEach((e=>{const n=t.createDocumentFragment();n.append(...e.childNodes),e.parentNode?.replaceChild(n,e)}))})(t),(t=>{Array.from(t.querySelectorAll("br")).filter((t=>A(t.previousElementSibling)&&A(t.nextElementSibling))).forEach((t=>{t.parentNode?.removeChild(t)}))})(t))}];const q=(0,l.A)("quill:clipboard"),k=[[Node.TEXT_NODE,function(t,e,n){let r=t.data;if("O:P"===t.parentElement?.tagName)return e.insert(r.trim());if(!R(t)){if(0===r.trim().length&&r.includes("\n")&&!function(t,e){return t.previousElementSibling&&t.nextElementSibling&&!j(t.previousElementSibling,e)&&!j(t.nextElementSibling,e)}(t,n))return e;r=r.replace(/[^\S\u00a0]/g," "),r=r.replace(/ {2,}/g," "),(null==t.previousSibling&&null!=t.parentElement&&j(t.parentElement,n)||t.previousSibling instanceof Element&&j(t.previousSibling,n))&&(r=r.replace(/^ /,"")),(null==t.nextSibling&&null!=t.parentElement&&j(t.parentElement,n)||t.nextSibling instanceof Element&&j(t.nextSibling,n))&&(r=r.replace(/ $/,"")),r=r.replaceAll(" "," ")}return e.insert(r)}],[Node.TEXT_NODE,M],["br",function(t,e){return T(e,"\n")||e.insert("\n"),e}],[Node.ELEMENT_NODE,M],[Node.ELEMENT_NODE,function(t,e,n){const i=n.query(t);if(null==i)return e;if(i.prototype instanceof r.EmbedBlot){const e={},r=i.value(t);if(null!=r)return e[i.blotName]=r,(new(s())).insert(e,i.formats(t,n))}else if(i.prototype instanceof r.BlockBlot&&!T(e,"\n")&&e.insert("\n"),"blotName"in i&&"formats"in i&&"function"==typeof i.formats)return O(e,i.blotName,i.formats(t,n),n);return e}],[Node.ELEMENT_NODE,function(t,e,n){const i=r.Attributor.keys(t),s=r.ClassAttributor.keys(t),o=r.StyleAttributor.keys(t),l={};return i.concat(s).concat(o).forEach((e=>{let i=n.query(e,r.Scope.ATTRIBUTE);null!=i&&(l[i.attrName]=i.value(t),l[i.attrName])||(i=_[e],null==i||i.attrName!==e&&i.keyName!==e||(l[i.attrName]=i.value(t)||void 0),i=L[e],null==i||i.attrName!==e&&i.keyName!==e||(i=L[e],l[i.attrName]=i.value(t)||void 0))})),Object.entries(l).reduce(((t,e)=>{let[r,i]=e;return O(t,r,i,n)}),e)}],[Node.ELEMENT_NODE,function(t,e,n){const r={},i=t.style||{};return"italic"===i.fontStyle&&(r.italic=!0),"underline"===i.textDecoration&&(r.underline=!0),"line-through"===i.textDecoration&&(r.strike=!0),(i.fontWeight?.startsWith("bold")||parseInt(i.fontWeight,10)>=700)&&(r.bold=!0),e=Object.entries(r).reduce(((t,e)=>{let[r,i]=e;return O(t,r,i,n)}),e),parseFloat(i.textIndent||0)>0?(new(s())).insert("\t").concat(e):e}],["li",function(t,e,n){const r=n.query(t);if(null==r||"list"!==r.blotName||!T(e,"\n"))return e;let i=-1,o=t.parentNode;for(;null!=o;)["OL","UL"].includes(o.tagName)&&(i+=1),o=o.parentNode;return i<=0?e:e.reduce(((t,e)=>e.insert?e.attributes&&"number"==typeof e.attributes.indent?t.push(e):t.insert(e.insert,{indent:i,...e.attributes||{}}):t),new(s()))}],["ol, ul",function(t,e,n){const r=t;let i="OL"===r.tagName?"ordered":"bullet";const s=r.getAttribute("data-checked");return s&&(i="true"===s?"checked":"unchecked"),O(e,"list",i,n)}],["pre",function(t,e,n){const r=n.query("code-block");return O(e,"code-block",!r||!("formats"in r)||"function"!=typeof r.formats||r.formats(t,n),n)}],["tr",function(t,e,n){const r="TABLE"===t.parentElement?.tagName?t.parentElement:t.parentElement?.parentElement;return null!=r?O(e,"table",Array.from(r.querySelectorAll("tr")).indexOf(t)+1,n):e}],["b",B("bold")],["i",B("italic")],["strike",B("strike")],["style",function(){return new(s())}]],_=[u.gS,p.Mc].reduce(((t,e)=>(t[e.keyName]=e,t)),{}),L=[u.Hu,h.s,f.JM,p.VL,g.z,m.r].reduce(((t,e)=>(t[e.keyName]=e,t)),{});class S extends a.A{static DEFAULTS={matchers:[]};constructor(t,e){super(t,e),this.quill.root.addEventListener("copy",(t=>this.onCaptureCopy(t,!1))),this.quill.root.addEventListener("cut",(t=>this.onCaptureCopy(t,!0))),this.quill.root.addEventListener("paste",this.onCapturePaste.bind(this)),this.matchers=[],k.concat(this.options.matchers??[]).forEach((t=>{let[e,n]=t;this.addMatcher(e,n)}))}addMatcher(t,e){this.matchers.push([t,e])}convert(t){let{html:e,text:n}=t,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(r[d.Ay.blotName])return(new(s())).insert(n||"",{[d.Ay.blotName]:r[d.Ay.blotName]});if(!e)return(new(s())).insert(n||"",r);const i=this.convertHTML(e);return T(i,"\n")&&(null==i.ops[i.ops.length-1].attributes||r.table)?i.compose((new(s())).retain(i.length()-1).delete(1)):i}normalizeHTML(t){(t=>{t.documentElement&&w.forEach((e=>{e(t)}))})(t)}convertHTML(t){const e=(new DOMParser).parseFromString(t,"text/html");this.normalizeHTML(e);const n=e.body,r=new WeakMap,[i,s]=this.prepareMatching(n,r);return I(this.quill.scroll,n,i,s,r)}dangerouslyPasteHTML(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:c.Ay.sources.API;if("string"==typeof t){const n=this.convert({html:t,text:""});this.quill.setContents(n,e),this.quill.setSelection(0,c.Ay.sources.SILENT)}else{const r=this.convert({html:e,text:""});this.quill.updateContents((new(s())).retain(t).concat(r),n),this.quill.setSelection(t+r.length(),c.Ay.sources.SILENT)}}onCaptureCopy(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(t.defaultPrevented)return;t.preventDefault();const[n]=this.quill.selection.getRange();if(null==n)return;const{html:r,text:i}=this.onCopy(n,e);t.clipboardData?.setData("text/plain",i),t.clipboardData?.setData("text/html",r),e&&(0,b.Xo)({range:n,quill:this.quill})}normalizeURIList(t){return t.split(/\r?\n/).filter((t=>"#"!==t[0])).join("\n")}onCapturePaste(t){if(t.defaultPrevented||!this.quill.isEnabled())return;t.preventDefault();const e=this.quill.getSelection(!0);if(null==e)return;const n=t.clipboardData?.getData("text/html");let r=t.clipboardData?.getData("text/plain");if(!n&&!r){const e=t.clipboardData?.getData("text/uri-list");e&&(r=this.normalizeURIList(e))}const i=Array.from(t.clipboardData?.files||[]);if(!n&&i.length>0)this.quill.uploader.upload(e,i);else{if(n&&i.length>0){const t=(new DOMParser).parseFromString(n,"text/html");if(1===t.body.childElementCount&&"IMG"===t.body.firstElementChild?.tagName)return void this.quill.uploader.upload(e,i)}this.onPaste(e,{html:n,text:r})}}onCopy(t){const e=this.quill.getText(t);return{html:this.quill.getSemanticHTML(t),text:e}}onPaste(t,e){let{text:n,html:r}=e;const i=this.quill.getFormat(t.index),o=this.convert({text:n,html:r},i);q.log("onPaste",o,{text:n,html:r});const l=(new(s())).retain(t.index).delete(t.length).concat(o);this.quill.updateContents(l,c.Ay.sources.USER),this.quill.setSelection(l.length()-t.length,c.Ay.sources.SILENT),this.quill.scrollSelectionIntoView()}prepareMatching(t,e){const n=[],r=[];return this.matchers.forEach((i=>{const[s,o]=i;switch(s){case Node.TEXT_NODE:r.push(o);break;case Node.ELEMENT_NODE:n.push(o);break;default:Array.from(t.querySelectorAll(s)).forEach((t=>{if(e.has(t)){const n=e.get(t);n?.push(o)}else e.set(t,[o])}))}})),[n,r]}}function O(t,e,n,r){return r.query(e)?t.reduce(((t,r)=>{if(!r.insert)return t;if(r.attributes&&r.attributes[e])return t.push(r);const i=n?{[e]:n}:{};return t.insert(r.insert,{...i,...r.attributes})}),new(s())):t}function T(t,e){let n="";for(let r=t.ops.length-1;r>=0&&n.lengthr(e,n,t)),new(s())):e.nodeType===e.ELEMENT_NODE?Array.from(e.childNodes||[]).reduce(((s,o)=>{let l=I(t,o,n,r,i);return o.nodeType===e.ELEMENT_NODE&&(l=n.reduce(((e,n)=>n(o,e,t)),l),l=(i.get(o)||[]).reduce(((e,n)=>n(o,e,t)),l)),s.concat(l)}),new(s())):new(s())}function B(t){return(e,n,r)=>O(n,t,!0,r)}function M(t,e,n){if(!T(e,"\n")){if(j(t,n)&&(t.childNodes.length>0||t instanceof HTMLParagraphElement))return e.insert("\n");if(e.length()>0&&t.nextSibling){let r=t.nextSibling;for(;null!=r;){if(j(r,n))return e.insert("\n");const t=n.query(r);if(t&&t.prototype instanceof o.zo)return e.insert("\n");r=r.firstChild}}}return e}},8123:function(t,e,n){"use strict";n.d(e,{Ay:function(){return f},Xo:function(){return v}});var r=n(5123),i=n(3707),s=n(5232),o=n.n(s),l=n(6003),a=n(6142),c=n(6078),u=n(4266);const h=(0,c.A)("quill:keyboard"),d=/Mac/i.test(navigator.platform)?"metaKey":"ctrlKey";class f extends u.A{static match(t,e){return!["altKey","ctrlKey","metaKey","shiftKey"].some((n=>!!e[n]!==t[n]&&null!==e[n]))&&(e.key===t.key||e.key===t.which)}constructor(t,e){super(t,e),this.bindings={},Object.keys(this.options.bindings).forEach((t=>{this.options.bindings[t]&&this.addBinding(this.options.bindings[t])})),this.addBinding({key:"Enter",shiftKey:null},this.handleEnter),this.addBinding({key:"Enter",metaKey:null,ctrlKey:null,altKey:null},(()=>{})),/Firefox/i.test(navigator.userAgent)?(this.addBinding({key:"Backspace"},{collapsed:!0},this.handleBackspace),this.addBinding({key:"Delete"},{collapsed:!0},this.handleDelete)):(this.addBinding({key:"Backspace"},{collapsed:!0,prefix:/^.?$/},this.handleBackspace),this.addBinding({key:"Delete"},{collapsed:!0,suffix:/^.?$/},this.handleDelete)),this.addBinding({key:"Backspace"},{collapsed:!1},this.handleDeleteRange),this.addBinding({key:"Delete"},{collapsed:!1},this.handleDeleteRange),this.addBinding({key:"Backspace",altKey:null,ctrlKey:null,metaKey:null,shiftKey:null},{collapsed:!0,offset:0},this.handleBackspace),this.listen()}addBinding(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const r=function(t){if("string"==typeof t||"number"==typeof t)t={key:t};else{if("object"!=typeof t)return null;t=(0,i.A)(t)}return t.shortKey&&(t[d]=t.shortKey,delete t.shortKey),t}(t);null!=r?("function"==typeof e&&(e={handler:e}),"function"==typeof n&&(n={handler:n}),(Array.isArray(r.key)?r.key:[r.key]).forEach((t=>{const i={...r,key:t,...e,...n};this.bindings[i.key]=this.bindings[i.key]||[],this.bindings[i.key].push(i)}))):h.warn("Attempted to add invalid keyboard binding",r)}listen(){this.quill.root.addEventListener("keydown",(t=>{if(t.defaultPrevented||t.isComposing)return;if(229===t.keyCode&&("Enter"===t.key||"Backspace"===t.key))return;const e=(this.bindings[t.key]||[]).concat(this.bindings[t.which]||[]).filter((e=>f.match(t,e)));if(0===e.length)return;const n=a.Ay.find(t.target,!0);if(n&&n.scroll!==this.quill.scroll)return;const i=this.quill.getSelection();if(null==i||!this.quill.hasFocus())return;const[s,o]=this.quill.getLine(i.index),[c,u]=this.quill.getLeaf(i.index),[h,d]=0===i.length?[c,u]:this.quill.getLeaf(i.index+i.length),p=c instanceof l.TextBlot?c.value().slice(0,u):"",g=h instanceof l.TextBlot?h.value().slice(d):"",m={collapsed:0===i.length,empty:0===i.length&&s.length()<=1,format:this.quill.getFormat(i),line:s,offset:o,prefix:p,suffix:g,event:t};e.some((t=>{if(null!=t.collapsed&&t.collapsed!==m.collapsed)return!1;if(null!=t.empty&&t.empty!==m.empty)return!1;if(null!=t.offset&&t.offset!==m.offset)return!1;if(Array.isArray(t.format)){if(t.format.every((t=>null==m.format[t])))return!1}else if("object"==typeof t.format&&!Object.keys(t.format).every((e=>!0===t.format[e]?null!=m.format[e]:!1===t.format[e]?null==m.format[e]:(0,r.A)(t.format[e],m.format[e]))))return!1;return!(null!=t.prefix&&!t.prefix.test(m.prefix)||null!=t.suffix&&!t.suffix.test(m.suffix)||!0===t.handler.call(this,i,m,t))}))&&t.preventDefault()}))}handleBackspace(t,e){const n=/[\uD800-\uDBFF][\uDC00-\uDFFF]$/.test(e.prefix)?2:1;if(0===t.index||this.quill.getLength()<=1)return;let r={};const[i]=this.quill.getLine(t.index);let l=(new(o())).retain(t.index-n).delete(n);if(0===e.offset){const[e]=this.quill.getLine(t.index-1);if(e&&!("block"===e.statics.blotName&&e.length()<=1)){const e=i.formats(),n=this.quill.getFormat(t.index-1,1);if(r=s.AttributeMap.diff(e,n)||{},Object.keys(r).length>0){const e=(new(o())).retain(t.index+i.length()-2).retain(1,r);l=l.compose(e)}}}this.quill.updateContents(l,a.Ay.sources.USER),this.quill.focus()}handleDelete(t,e){const n=/^[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(e.suffix)?2:1;if(t.index>=this.quill.getLength()-n)return;let r={};const[i]=this.quill.getLine(t.index);let l=(new(o())).retain(t.index).delete(n);if(e.offset>=i.length()-1){const[e]=this.quill.getLine(t.index+1);if(e){const n=i.formats(),o=this.quill.getFormat(t.index,1);r=s.AttributeMap.diff(n,o)||{},Object.keys(r).length>0&&(l=l.retain(e.length()-1).retain(1,r))}}this.quill.updateContents(l,a.Ay.sources.USER),this.quill.focus()}handleDeleteRange(t){v({range:t,quill:this.quill}),this.quill.focus()}handleEnter(t,e){const n=Object.keys(e.format).reduce(((t,n)=>(this.quill.scroll.query(n,l.Scope.BLOCK)&&!Array.isArray(e.format[n])&&(t[n]=e.format[n]),t)),{}),r=(new(o())).retain(t.index).delete(t.length).insert("\n",n);this.quill.updateContents(r,a.Ay.sources.USER),this.quill.setSelection(t.index+1,a.Ay.sources.SILENT),this.quill.focus()}}const p={bindings:{bold:b("bold"),italic:b("italic"),underline:b("underline"),indent:{key:"Tab",format:["blockquote","indent","list"],handler(t,e){return!(!e.collapsed||0===e.offset)||(this.quill.format("indent","+1",a.Ay.sources.USER),!1)}},outdent:{key:"Tab",shiftKey:!0,format:["blockquote","indent","list"],handler(t,e){return!(!e.collapsed||0===e.offset)||(this.quill.format("indent","-1",a.Ay.sources.USER),!1)}},"outdent backspace":{key:"Backspace",collapsed:!0,shiftKey:null,metaKey:null,ctrlKey:null,altKey:null,format:["indent","list"],offset:0,handler(t,e){null!=e.format.indent?this.quill.format("indent","-1",a.Ay.sources.USER):null!=e.format.list&&this.quill.format("list",!1,a.Ay.sources.USER)}},"indent code-block":g(!0),"outdent code-block":g(!1),"remove tab":{key:"Tab",shiftKey:!0,collapsed:!0,prefix:/\t$/,handler(t){this.quill.deleteText(t.index-1,1,a.Ay.sources.USER)}},tab:{key:"Tab",handler(t,e){if(e.format.table)return!0;this.quill.history.cutoff();const n=(new(o())).retain(t.index).delete(t.length).insert("\t");return this.quill.updateContents(n,a.Ay.sources.USER),this.quill.history.cutoff(),this.quill.setSelection(t.index+1,a.Ay.sources.SILENT),!1}},"blockquote empty enter":{key:"Enter",collapsed:!0,format:["blockquote"],empty:!0,handler(){this.quill.format("blockquote",!1,a.Ay.sources.USER)}},"list empty enter":{key:"Enter",collapsed:!0,format:["list"],empty:!0,handler(t,e){const n={list:!1};e.format.indent&&(n.indent=!1),this.quill.formatLine(t.index,t.length,n,a.Ay.sources.USER)}},"checklist enter":{key:"Enter",collapsed:!0,format:{list:"checked"},handler(t){const[e,n]=this.quill.getLine(t.index),r={...e.formats(),list:"checked"},i=(new(o())).retain(t.index).insert("\n",r).retain(e.length()-n-1).retain(1,{list:"unchecked"});this.quill.updateContents(i,a.Ay.sources.USER),this.quill.setSelection(t.index+1,a.Ay.sources.SILENT),this.quill.scrollSelectionIntoView()}},"header enter":{key:"Enter",collapsed:!0,format:["header"],suffix:/^$/,handler(t,e){const[n,r]=this.quill.getLine(t.index),i=(new(o())).retain(t.index).insert("\n",e.format).retain(n.length()-r-1).retain(1,{header:null});this.quill.updateContents(i,a.Ay.sources.USER),this.quill.setSelection(t.index+1,a.Ay.sources.SILENT),this.quill.scrollSelectionIntoView()}},"table backspace":{key:"Backspace",format:["table"],collapsed:!0,offset:0,handler(){}},"table delete":{key:"Delete",format:["table"],collapsed:!0,suffix:/^$/,handler(){}},"table enter":{key:"Enter",shiftKey:null,format:["table"],handler(t){const e=this.quill.getModule("table");if(e){const[n,r,i,s]=e.getTable(t),l=function(t,e,n,r){return null==e.prev&&null==e.next?null==n.prev&&null==n.next?0===r?-1:1:null==n.prev?-1:1:null==e.prev?-1:null==e.next?1:null}(0,r,i,s);if(null==l)return;let c=n.offset();if(l<0){const e=(new(o())).retain(c).insert("\n");this.quill.updateContents(e,a.Ay.sources.USER),this.quill.setSelection(t.index+1,t.length,a.Ay.sources.SILENT)}else if(l>0){c+=n.length();const t=(new(o())).retain(c).insert("\n");this.quill.updateContents(t,a.Ay.sources.USER),this.quill.setSelection(c,a.Ay.sources.USER)}}}},"table tab":{key:"Tab",shiftKey:null,format:["table"],handler(t,e){const{event:n,line:r}=e,i=r.offset(this.quill.scroll);n.shiftKey?this.quill.setSelection(i-1,a.Ay.sources.USER):this.quill.setSelection(i+r.length(),a.Ay.sources.USER)}},"list autofill":{key:" ",shiftKey:null,collapsed:!0,format:{"code-block":!1,blockquote:!1,table:!1},prefix:/^\s*?(\d+\.|-|\*|\[ ?\]|\[x\])$/,handler(t,e){if(null==this.quill.scroll.query("list"))return!0;const{length:n}=e.prefix,[r,i]=this.quill.getLine(t.index);if(i>n)return!0;let s;switch(e.prefix.trim()){case"[]":case"[ ]":s="unchecked";break;case"[x]":s="checked";break;case"-":case"*":s="bullet";break;default:s="ordered"}this.quill.insertText(t.index," ",a.Ay.sources.USER),this.quill.history.cutoff();const l=(new(o())).retain(t.index-i).delete(n+1).retain(r.length()-2-i).retain(1,{list:s});return this.quill.updateContents(l,a.Ay.sources.USER),this.quill.history.cutoff(),this.quill.setSelection(t.index-n,a.Ay.sources.SILENT),!1}},"code exit":{key:"Enter",collapsed:!0,format:["code-block"],prefix:/^$/,suffix:/^\s*$/,handler(t){const[e,n]=this.quill.getLine(t.index);let r=2,i=e;for(;null!=i&&i.length()<=1&&i.formats()["code-block"];)if(i=i.prev,r-=1,r<=0){const r=(new(o())).retain(t.index+e.length()-n-2).retain(1,{"code-block":null}).delete(1);return this.quill.updateContents(r,a.Ay.sources.USER),this.quill.setSelection(t.index-1,a.Ay.sources.SILENT),!1}return!0}},"embed left":m("ArrowLeft",!1),"embed left shift":m("ArrowLeft",!0),"embed right":m("ArrowRight",!1),"embed right shift":m("ArrowRight",!0),"table down":y(!1),"table up":y(!0)}};function g(t){return{key:"Tab",shiftKey:!t,format:{"code-block":!0},handler(e,n){let{event:r}=n;const i=this.quill.scroll.query("code-block"),{TAB:s}=i;if(0===e.length&&!r.shiftKey)return this.quill.insertText(e.index,s,a.Ay.sources.USER),void this.quill.setSelection(e.index+s.length,a.Ay.sources.SILENT);const o=0===e.length?this.quill.getLines(e.index,1):this.quill.getLines(e);let{index:l,length:c}=e;o.forEach(((e,n)=>{t?(e.insertAt(0,s),0===n?l+=s.length:c+=s.length):e.domNode.textContent.startsWith(s)&&(e.deleteAt(0,s.length),0===n?l-=s.length:c-=s.length)})),this.quill.update(a.Ay.sources.USER),this.quill.setSelection(l,c,a.Ay.sources.SILENT)}}}function m(t,e){return{key:t,shiftKey:e,altKey:null,["ArrowLeft"===t?"prefix":"suffix"]:/^$/,handler(n){let{index:r}=n;"ArrowRight"===t&&(r+=n.length+1);const[i]=this.quill.getLeaf(r);return!(i instanceof l.EmbedBlot&&("ArrowLeft"===t?e?this.quill.setSelection(n.index-1,n.length+1,a.Ay.sources.USER):this.quill.setSelection(n.index-1,a.Ay.sources.USER):e?this.quill.setSelection(n.index,n.length+1,a.Ay.sources.USER):this.quill.setSelection(n.index+n.length+1,a.Ay.sources.USER),1))}}}function b(t){return{key:t[0],shortKey:!0,handler(e,n){this.quill.format(t,!n.format[t],a.Ay.sources.USER)}}}function y(t){return{key:t?"ArrowUp":"ArrowDown",collapsed:!0,format:["table"],handler(e,n){const r=t?"prev":"next",i=n.line,s=i.parent[r];if(null!=s){if("table-row"===s.statics.blotName){let t=s.children.head,e=i;for(;null!=e.prev;)e=e.prev,t=t.next;const r=t.offset(this.quill.scroll)+Math.min(n.offset,t.length()-1);this.quill.setSelection(r,0,a.Ay.sources.USER)}}else{const e=i.table()[r];null!=e&&(t?this.quill.setSelection(e.offset(this.quill.scroll)+e.length()-1,0,a.Ay.sources.USER):this.quill.setSelection(e.offset(this.quill.scroll),0,a.Ay.sources.USER))}return!1}}}function v(t){let{quill:e,range:n}=t;const r=e.getLines(n);let i={};if(r.length>1){const t=r[0].formats(),e=r[r.length-1].formats();i=s.AttributeMap.diff(e,t)||{}}e.deleteText(n,a.Ay.sources.USER),Object.keys(i).length>0&&e.formatLine(n.index,1,i,a.Ay.sources.USER),e.setSelection(n.index,a.Ay.sources.SILENT)}f.DEFAULTS=p},8920:function(t){"use strict";var e=Object.prototype.hasOwnProperty,n="~";function r(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function s(t,e,r,s,o){if("function"!=typeof r)throw new TypeError("The listener must be a function");var l=new i(r,s||t,o),a=n?n+e:e;return t._events[a]?t._events[a].fn?t._events[a]=[t._events[a],l]:t._events[a].push(l):(t._events[a]=l,t._eventsCount++),t}function o(t,e){0==--t._eventsCount?t._events=new r:delete t._events[e]}function l(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),l.prototype.eventNames=function(){var t,r,i=[];if(0===this._eventsCount)return i;for(r in t=this._events)e.call(t,r)&&i.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?i.concat(Object.getOwnPropertySymbols(t)):i},l.prototype.listeners=function(t){var e=n?n+t:t,r=this._events[e];if(!r)return[];if(r.fn)return[r.fn];for(var i=0,s=r.length,o=new Array(s);io)){var d=e.slice(0,h);if((g=e.slice(h))===c){var f=Math.min(l,h);if((b=a.slice(0,f))===(A=d.slice(0,f)))return v(b,a.slice(f),d.slice(f),c)}}if(null===u||u===l){var p=l,g=(d=e.slice(0,p),e.slice(p));if(d===a){var m=Math.min(s-p,o-p);if((y=c.slice(c.length-m))===(x=g.slice(g.length-m)))return v(a,c.slice(0,c.length-m),g.slice(0,g.length-m),y)}}}if(r.length>0&&i&&0===i.length){var b=t.slice(0,r.index),y=t.slice(r.index+r.length);if(!(o<(f=b.length)+(m=y.length))){var A=e.slice(0,f),x=e.slice(o-m);if(b===A&&y===x)return v(b,t.slice(f,s-m),e.slice(f,o-m),y)}}return null}(t,g,m);if(A)return A}var x=o(t,g),N=t.substring(0,x);x=a(t=t.substring(x),g=g.substring(x));var E=t.substring(t.length-x),w=function(t,l){var c;if(!t)return[[n,l]];if(!l)return[[e,t]];var u=t.length>l.length?t:l,h=t.length>l.length?l:t,d=u.indexOf(h);if(-1!==d)return c=[[n,u.substring(0,d)],[r,h],[n,u.substring(d+h.length)]],t.length>l.length&&(c[0][0]=c[2][0]=e),c;if(1===h.length)return[[e,t],[n,l]];var f=function(t,e){var n=t.length>e.length?t:e,r=t.length>e.length?e:t;if(n.length<4||2*r.length=t.length?[r,i,s,l,h]:null}var s,l,c,u,h,d=i(n,r,Math.ceil(n.length/4)),f=i(n,r,Math.ceil(n.length/2));return d||f?(s=f?d&&d[4].length>f[4].length?d:f:d,t.length>e.length?(l=s[0],c=s[1],u=s[2],h=s[3]):(u=s[0],h=s[1],l=s[2],c=s[3]),[l,c,u,h,s[4]]):null}(t,l);if(f){var p=f[0],g=f[1],m=f[2],b=f[3],y=f[4],v=i(p,m),A=i(g,b);return v.concat([[r,y]],A)}return function(t,r){for(var i=t.length,o=r.length,l=Math.ceil((i+o)/2),a=l,c=2*l,u=new Array(c),h=new Array(c),d=0;di)m+=2;else if(N>o)g+=2;else if(p&&(q=a+f-A)>=0&&q=(w=i-h[q]))return s(t,r,_,N)}for(var E=-v+b;E<=v-y;E+=2){for(var w,q=a+E,k=(w=E===-v||E!==v&&h[q-1]i)y+=2;else if(k>o)b+=2;else if(!p){var _;if((x=a+f-E)>=0&&x=(w=i-w))return s(t,r,_,N)}}}return[[e,t],[n,r]]}(t,l)}(t=t.substring(0,t.length-x),g=g.substring(0,g.length-x));return N&&w.unshift([r,N]),E&&w.push([r,E]),p(w,y),b&&function(t){for(var i=!1,s=[],o=0,g=null,m=0,b=0,y=0,v=0,A=0;m0?s[o-1]:-1,b=0,y=0,v=0,A=0,g=null,i=!0)),m++;for(i&&p(t),function(t){function e(t,e){if(!t||!e)return 6;var n=t.charAt(t.length-1),r=e.charAt(0),i=n.match(c),s=r.match(c),o=i&&n.match(u),l=s&&r.match(u),a=o&&n.match(h),p=l&&r.match(h),g=a&&t.match(d),m=p&&e.match(f);return g||m?5:a||p?4:i&&!o&&l?3:o||l?2:i||s?1:0}for(var n=1;n=y&&(y=v,g=i,m=s,b=o)}t[n-1][1]!=g&&(g?t[n-1][1]=g:(t.splice(n-1,1),n--),t[n][1]=m,b?t[n+1][1]=b:(t.splice(n+1,1),n--))}n++}}(t),m=1;m=w?(E>=x.length/2||E>=N.length/2)&&(t.splice(m,0,[r,N.substring(0,E)]),t[m-1][1]=x.substring(0,x.length-E),t[m+1][1]=N.substring(E),m++):(w>=x.length/2||w>=N.length/2)&&(t.splice(m,0,[r,x.substring(0,w)]),t[m-1][0]=n,t[m-1][1]=N.substring(0,N.length-w),t[m+1][0]=e,t[m+1][1]=x.substring(w),m++),m++}m++}}(w),w}function s(t,e,n,r){var s=t.substring(0,n),o=e.substring(0,r),l=t.substring(n),a=e.substring(r),c=i(s,o),u=i(l,a);return c.concat(u)}function o(t,e){if(!t||!e||t.charAt(0)!==e.charAt(0))return 0;for(var n=0,r=Math.min(t.length,e.length),i=r,s=0;nr?t=t.substring(n-r):n=0&&y(t[f][1])){var g=t[f][1].slice(-1);if(t[f][1]=t[f][1].slice(0,-1),h=g+h,d=g+d,!t[f][1]){t.splice(f,1),l--;var m=f-1;t[m]&&t[m][0]===n&&(u++,d=t[m][1]+d,m--),t[m]&&t[m][0]===e&&(c++,h=t[m][1]+h,m--),f=m}}b(t[l][1])&&(g=t[l][1].charAt(0),t[l][1]=t[l][1].slice(1),h+=g,d+=g)}if(l0||d.length>0){h.length>0&&d.length>0&&(0!==(s=o(d,h))&&(f>=0?t[f][1]+=d.substring(0,s):(t.splice(0,0,[r,d.substring(0,s)]),l++),d=d.substring(s),h=h.substring(s)),0!==(s=a(d,h))&&(t[l][1]=d.substring(d.length-s)+t[l][1],d=d.substring(0,d.length-s),h=h.substring(0,h.length-s)));var v=u+c;0===h.length&&0===d.length?(t.splice(l-v,v),l-=v):0===h.length?(t.splice(l-v,v,[n,d]),l=l-v+1):0===d.length?(t.splice(l-v,v,[e,h]),l=l-v+1):(t.splice(l-v,v,[e,h],[n,d]),l=l-v+2)}0!==l&&t[l-1][0]===r?(t[l-1][1]+=t[l][1],t.splice(l,1)):l++,u=0,c=0,h="",d=""}""===t[t.length-1][1]&&t.pop();var A=!1;for(l=1;l=55296&&t<=56319}function m(t){return t>=56320&&t<=57343}function b(t){return m(t.charCodeAt(0))}function y(t){return g(t.charCodeAt(t.length-1))}function v(t,i,s,o){return y(t)||b(o)?null:function(t){for(var e=[],n=0;n0&&e.push(t[n]);return e}([[r,t],[e,i],[n,s],[r,o]])}function A(t,e,n,r){return i(t,e,n,r,!0)}A.INSERT=n,A.DELETE=e,A.EQUAL=r,t.exports=A},9629:function(t,e,n){t=n.nmd(t);var r="__lodash_hash_undefined__",i=9007199254740991,s="[object Arguments]",o="[object Boolean]",l="[object Date]",a="[object Function]",c="[object GeneratorFunction]",u="[object Map]",h="[object Number]",d="[object Object]",f="[object Promise]",p="[object RegExp]",g="[object Set]",m="[object String]",b="[object Symbol]",y="[object WeakMap]",v="[object ArrayBuffer]",A="[object DataView]",x="[object Float32Array]",N="[object Float64Array]",E="[object Int8Array]",w="[object Int16Array]",q="[object Int32Array]",k="[object Uint8Array]",_="[object Uint8ClampedArray]",L="[object Uint16Array]",S="[object Uint32Array]",O=/\w*$/,T=/^\[object .+?Constructor\]$/,j=/^(?:0|[1-9]\d*)$/,C={};C[s]=C["[object Array]"]=C[v]=C[A]=C[o]=C[l]=C[x]=C[N]=C[E]=C[w]=C[q]=C[u]=C[h]=C[d]=C[p]=C[g]=C[m]=C[b]=C[k]=C[_]=C[L]=C[S]=!0,C["[object Error]"]=C[a]=C[y]=!1;var R="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g,I="object"==typeof self&&self&&self.Object===Object&&self,B=R||I||Function("return this")(),M=e&&!e.nodeType&&e,U=M&&t&&!t.nodeType&&t,D=U&&U.exports===M;function P(t,e){return t.set(e[0],e[1]),t}function z(t,e){return t.add(e),t}function F(t,e,n,r){var i=-1,s=t?t.length:0;for(r&&s&&(n=t[++i]);++i-1},_t.prototype.set=function(t,e){var n=this.__data__,r=Tt(n,t);return r<0?n.push([t,e]):n[r][1]=e,this},Lt.prototype.clear=function(){this.__data__={hash:new kt,map:new(pt||_t),string:new kt}},Lt.prototype.delete=function(t){return It(this,t).delete(t)},Lt.prototype.get=function(t){return It(this,t).get(t)},Lt.prototype.has=function(t){return It(this,t).has(t)},Lt.prototype.set=function(t,e){return It(this,t).set(t,e),this},St.prototype.clear=function(){this.__data__=new _t},St.prototype.delete=function(t){return this.__data__.delete(t)},St.prototype.get=function(t){return this.__data__.get(t)},St.prototype.has=function(t){return this.__data__.has(t)},St.prototype.set=function(t,e){var n=this.__data__;if(n instanceof _t){var r=n.__data__;if(!pt||r.length<199)return r.push([t,e]),this;n=this.__data__=new Lt(r)}return n.set(t,e),this};var Mt=ut?V(ut,Object):function(){return[]},Ut=function(t){return et.call(t)};function Dt(t,e){return!!(e=null==e?i:e)&&("number"==typeof t||j.test(t))&&t>-1&&t%1==0&&t-1&&t%1==0&&t<=i}(t.length)&&!Kt(t)}var Vt=ht||function(){return!1};function Kt(t){var e=Wt(t)?et.call(t):"";return e==a||e==c}function Wt(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function Zt(t){return $t(t)?function(t,e){var n=Ht(t)||function(t){return function(t){return function(t){return!!t&&"object"==typeof t}(t)&&$t(t)}(t)&&tt.call(t,"callee")&&(!at.call(t,"callee")||et.call(t)==s)}(t)?function(t,e){for(var n=-1,r=Array(t);++nc))return!1;var h=l.get(t);if(h&&l.get(e))return h==e;var d=-1,f=!0,p=n&s?new kt:void 0;for(l.set(t,e),l.set(e,t);++d-1},wt.prototype.set=function(t,e){var n=this.__data__,r=Lt(n,t);return r<0?(++this.size,n.push([t,e])):n[r][1]=e,this},qt.prototype.clear=function(){this.size=0,this.__data__={hash:new Et,map:new(ht||wt),string:new Et}},qt.prototype.delete=function(t){var e=Rt(this,t).delete(t);return this.size-=e?1:0,e},qt.prototype.get=function(t){return Rt(this,t).get(t)},qt.prototype.has=function(t){return Rt(this,t).has(t)},qt.prototype.set=function(t,e){var n=Rt(this,t),r=n.size;return n.set(t,e),this.size+=n.size==r?0:1,this},kt.prototype.add=kt.prototype.push=function(t){return this.__data__.set(t,r),this},kt.prototype.has=function(t){return this.__data__.has(t)},_t.prototype.clear=function(){this.__data__=new wt,this.size=0},_t.prototype.delete=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n},_t.prototype.get=function(t){return this.__data__.get(t)},_t.prototype.has=function(t){return this.__data__.has(t)},_t.prototype.set=function(t,e){var n=this.__data__;if(n instanceof wt){var r=n.__data__;if(!ht||r.length<199)return r.push([t,e]),this.size=++n.size,this;n=this.__data__=new qt(r)}return n.set(t,e),this.size=n.size,this};var Bt=lt?function(t){return null==t?[]:(t=Object(t),function(e,n){for(var r=-1,i=null==e?0:e.length,s=0,o=[];++r-1&&t%1==0&&t-1&&t%1==0&&t<=o}function Kt(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function Wt(t){return null!=t&&"object"==typeof t}var Zt=D?function(t){return function(e){return t(e)}}(D):function(t){return Wt(t)&&Vt(t.length)&&!!O[St(t)]};function Gt(t){return null!=(e=t)&&Vt(e.length)&&!$t(e)?function(t,e){var n=Ft(t),r=!n&&zt(t),i=!n&&!r&&Ht(t),s=!n&&!r&&!i&&Zt(t),o=n||r||i||s,l=o?function(t,e){for(var n=-1,r=Array(t);++n(null!=i[e]&&(t[e]=i[e]),t)),{}));for(const n in t)void 0!==t[n]&&void 0===e[n]&&(i[n]=t[n]);return Object.keys(i).length>0?i:void 0},t.diff=function(t={},e={}){"object"!=typeof t&&(t={}),"object"!=typeof e&&(e={});const n=Object.keys(t).concat(Object.keys(e)).reduce(((n,r)=>(i(t[r],e[r])||(n[r]=void 0===e[r]?null:e[r]),n)),{});return Object.keys(n).length>0?n:void 0},t.invert=function(t={},e={}){t=t||{};const n=Object.keys(e).reduce(((n,r)=>(e[r]!==t[r]&&void 0!==t[r]&&(n[r]=e[r]),n)),{});return Object.keys(t).reduce(((n,r)=>(t[r]!==e[r]&&void 0===e[r]&&(n[r]=null),n)),n)},t.transform=function(t,e,n=!1){if("object"!=typeof t)return e;if("object"!=typeof e)return;if(!n)return e;const r=Object.keys(e).reduce(((n,r)=>(void 0===t[r]&&(n[r]=e[r]),n)),{});return Object.keys(r).length>0?r:void 0}}(s||(s={})),e.default=s},5232:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AttributeMap=e.OpIterator=e.Op=void 0;const r=n(5090),i=n(9629),s=n(4162),o=n(1270);e.AttributeMap=o.default;const l=n(4123);e.Op=l.default;const a=n(7033);e.OpIterator=a.default;const c=String.fromCharCode(0),u=(t,e)=>{if("object"!=typeof t||null===t)throw new Error("cannot retain a "+typeof t);if("object"!=typeof e||null===e)throw new Error("cannot retain a "+typeof e);const n=Object.keys(t)[0];if(!n||n!==Object.keys(e)[0])throw new Error(`embed types not matched: ${n} != ${Object.keys(e)[0]}`);return[n,t[n],e[n]]};class h{constructor(t){Array.isArray(t)?this.ops=t:null!=t&&Array.isArray(t.ops)?this.ops=t.ops:this.ops=[]}static registerEmbed(t,e){this.handlers[t]=e}static unregisterEmbed(t){delete this.handlers[t]}static getHandler(t){const e=this.handlers[t];if(!e)throw new Error(`no handlers for embed type "${t}"`);return e}insert(t,e){const n={};return"string"==typeof t&&0===t.length?this:(n.insert=t,null!=e&&"object"==typeof e&&Object.keys(e).length>0&&(n.attributes=e),this.push(n))}delete(t){return t<=0?this:this.push({delete:t})}retain(t,e){if("number"==typeof t&&t<=0)return this;const n={retain:t};return null!=e&&"object"==typeof e&&Object.keys(e).length>0&&(n.attributes=e),this.push(n)}push(t){let e=this.ops.length,n=this.ops[e-1];if(t=i(t),"object"==typeof n){if("number"==typeof t.delete&&"number"==typeof n.delete)return this.ops[e-1]={delete:n.delete+t.delete},this;if("number"==typeof n.delete&&null!=t.insert&&(e-=1,n=this.ops[e-1],"object"!=typeof n))return this.ops.unshift(t),this;if(s(t.attributes,n.attributes)){if("string"==typeof t.insert&&"string"==typeof n.insert)return this.ops[e-1]={insert:n.insert+t.insert},"object"==typeof t.attributes&&(this.ops[e-1].attributes=t.attributes),this;if("number"==typeof t.retain&&"number"==typeof n.retain)return this.ops[e-1]={retain:n.retain+t.retain},"object"==typeof t.attributes&&(this.ops[e-1].attributes=t.attributes),this}}return e===this.ops.length?this.ops.push(t):this.ops.splice(e,0,t),this}chop(){const t=this.ops[this.ops.length-1];return t&&"number"==typeof t.retain&&!t.attributes&&this.ops.pop(),this}filter(t){return this.ops.filter(t)}forEach(t){this.ops.forEach(t)}map(t){return this.ops.map(t)}partition(t){const e=[],n=[];return this.forEach((r=>{(t(r)?e:n).push(r)})),[e,n]}reduce(t,e){return this.ops.reduce(t,e)}changeLength(){return this.reduce(((t,e)=>e.insert?t+l.default.length(e):e.delete?t-e.delete:t),0)}length(){return this.reduce(((t,e)=>t+l.default.length(e)),0)}slice(t=0,e=1/0){const n=[],r=new a.default(this.ops);let i=0;for(;i0&&n.next(i.retain-t)}const l=new h(r);for(;e.hasNext()||n.hasNext();)if("insert"===n.peekType())l.push(n.next());else if("delete"===e.peekType())l.push(e.next());else{const t=Math.min(e.peekLength(),n.peekLength()),r=e.next(t),i=n.next(t);if(i.retain){const a={};if("number"==typeof r.retain)a.retain="number"==typeof i.retain?t:i.retain;else if("number"==typeof i.retain)null==r.retain?a.insert=r.insert:a.retain=r.retain;else{const t=null==r.retain?"insert":"retain",[e,n,s]=u(r[t],i.retain),o=h.getHandler(e);a[t]={[e]:o.compose(n,s,"retain"===t)}}const c=o.default.compose(r.attributes,i.attributes,"number"==typeof r.retain);if(c&&(a.attributes=c),l.push(a),!n.hasNext()&&s(l.ops[l.ops.length-1],a)){const t=new h(e.rest());return l.concat(t).chop()}}else"number"==typeof i.delete&&("number"==typeof r.retain||"object"==typeof r.retain&&null!==r.retain)&&l.push(i)}return l.chop()}concat(t){const e=new h(this.ops.slice());return t.ops.length>0&&(e.push(t.ops[0]),e.ops=e.ops.concat(t.ops.slice(1))),e}diff(t,e){if(this.ops===t.ops)return new h;const n=[this,t].map((e=>e.map((n=>{if(null!=n.insert)return"string"==typeof n.insert?n.insert:c;throw new Error("diff() called "+(e===t?"on":"with")+" non-document")})).join(""))),i=new h,l=r(n[0],n[1],e,!0),u=new a.default(this.ops),d=new a.default(t.ops);return l.forEach((t=>{let e=t[1].length;for(;e>0;){let n=0;switch(t[0]){case r.INSERT:n=Math.min(d.peekLength(),e),i.push(d.next(n));break;case r.DELETE:n=Math.min(e,u.peekLength()),u.next(n),i.delete(n);break;case r.EQUAL:n=Math.min(u.peekLength(),d.peekLength(),e);const t=u.next(n),l=d.next(n);s(t.insert,l.insert)?i.retain(n,o.default.diff(t.attributes,l.attributes)):i.push(l).delete(n)}e-=n}})),i.chop()}eachLine(t,e="\n"){const n=new a.default(this.ops);let r=new h,i=0;for(;n.hasNext();){if("insert"!==n.peekType())return;const s=n.peek(),o=l.default.length(s)-n.peekLength(),a="string"==typeof s.insert?s.insert.indexOf(e,o)-o:-1;if(a<0)r.push(n.next());else if(a>0)r.push(n.next(a));else{if(!1===t(r,n.next(1).attributes||{},i))return;i+=1,r=new h}}r.length()>0&&t(r,{},i)}invert(t){const e=new h;return this.reduce(((n,r)=>{if(r.insert)e.delete(l.default.length(r));else{if("number"==typeof r.retain&&null==r.attributes)return e.retain(r.retain),n+r.retain;if(r.delete||"number"==typeof r.retain){const i=r.delete||r.retain;return t.slice(n,n+i).forEach((t=>{r.delete?e.push(t):r.retain&&r.attributes&&e.retain(l.default.length(t),o.default.invert(r.attributes,t.attributes))})),n+i}if("object"==typeof r.retain&&null!==r.retain){const i=t.slice(n,n+1),s=new a.default(i.ops).next(),[l,c,d]=u(r.retain,s.insert),f=h.getHandler(l);return e.retain({[l]:f.invert(c,d)},o.default.invert(r.attributes,s.attributes)),n+1}}return n}),0),e.chop()}transform(t,e=!1){if(e=!!e,"number"==typeof t)return this.transformPosition(t,e);const n=t,r=new a.default(this.ops),i=new a.default(n.ops),s=new h;for(;r.hasNext()||i.hasNext();)if("insert"!==r.peekType()||!e&&"insert"===i.peekType())if("insert"===i.peekType())s.push(i.next());else{const t=Math.min(r.peekLength(),i.peekLength()),n=r.next(t),l=i.next(t);if(n.delete)continue;if(l.delete)s.push(l);else{const r=n.retain,i=l.retain;let a="object"==typeof i&&null!==i?i:t;if("object"==typeof r&&null!==r&&"object"==typeof i&&null!==i){const t=Object.keys(r)[0];if(t===Object.keys(i)[0]){const n=h.getHandler(t);n&&(a={[t]:n.transform(r[t],i[t],e)})}}s.retain(a,o.default.transform(n.attributes,l.attributes,e))}}else s.retain(l.default.length(r.next()));return s.chop()}transformPosition(t,e=!1){e=!!e;const n=new a.default(this.ops);let r=0;for(;n.hasNext()&&r<=t;){const i=n.peekLength(),s=n.peekType();n.next(),"delete"!==s?("insert"===s&&(r=i-n?(t=i-n,this.index+=1,this.offset=0):this.offset+=t,"number"==typeof e.delete)return{delete:t};{const r={};return e.attributes&&(r.attributes=e.attributes),"number"==typeof e.retain?r.retain=t:"object"==typeof e.retain&&null!==e.retain?r.retain=e.retain:"string"==typeof e.insert?r.insert=e.insert.substr(n,t):r.insert=e.insert,r}}return{retain:1/0}}peek(){return this.ops[this.index]}peekLength(){return this.ops[this.index]?r.default.length(this.ops[this.index])-this.offset:1/0}peekType(){const t=this.ops[this.index];return t?"number"==typeof t.delete?"delete":"number"==typeof t.retain||"object"==typeof t.retain&&null!==t.retain?"retain":"insert":"retain"}rest(){if(this.hasNext()){if(0===this.offset)return this.ops.slice(this.index);{const t=this.offset,e=this.index,n=this.next(),r=this.ops.slice(this.index);return this.offset=t,this.index=e,[n].concat(r)}}return[]}}},8820:function(t,e,n){"use strict";n.d(e,{A:function(){return l}});var r=n(8138),i=function(t,e){for(var n=t.length;n--;)if((0,r.A)(t[n][0],e))return n;return-1},s=Array.prototype.splice;function o(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1},o.prototype.set=function(t,e){var n=this.__data__,r=i(n,t);return r<0?(++this.size,n.push([t,e])):n[r][1]=e,this};var l=o},2461:function(t,e,n){"use strict";var r=n(2281),i=n(5507),s=(0,r.A)(i.A,"Map");e.A=s},3558:function(t,e,n){"use strict";n.d(e,{A:function(){return d}});var r=(0,n(2281).A)(Object,"create"),i=Object.prototype.hasOwnProperty,s=Object.prototype.hasOwnProperty;function o(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&tc))return!1;var h=s.get(t),d=s.get(e);if(h&&d)return h==e&&d==t;var f=-1,p=!0,g=2&n?new o:void 0;for(s.set(t,e),s.set(e,t);++f-1&&t%1==0&&t<=9007199254740991}},659:function(t,e){"use strict";e.A=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},7948:function(t,e){"use strict";e.A=function(t){return null!=t&&"object"==typeof t}},5755:function(t,e,n){"use strict";n.d(e,{A:function(){return u}});var r=n(2159),i=n(1628),s=n(7948),o={};o["[object Float32Array]"]=o["[object Float64Array]"]=o["[object Int8Array]"]=o["[object Int16Array]"]=o["[object Int32Array]"]=o["[object Uint8Array]"]=o["[object Uint8ClampedArray]"]=o["[object Uint16Array]"]=o["[object Uint32Array]"]=!0,o["[object Arguments]"]=o["[object Array]"]=o["[object ArrayBuffer]"]=o["[object Boolean]"]=o["[object DataView]"]=o["[object Date]"]=o["[object Error]"]=o["[object Function]"]=o["[object Map]"]=o["[object Number]"]=o["[object Object]"]=o["[object RegExp]"]=o["[object Set]"]=o["[object String]"]=o["[object WeakMap]"]=!1;var l=n(5771),a=n(8795),c=a.A&&a.A.isTypedArray,u=c?(0,l.A)(c):function(t){return(0,s.A)(t)&&(0,i.A)(t.length)&&!!o[(0,r.A)(t)]}},3169:function(t,e,n){"use strict";n.d(e,{A:function(){return a}});var r=n(6753),i=n(501),s=(0,n(2217).A)(Object.keys,Object),o=Object.prototype.hasOwnProperty,l=n(3628),a=function(t){return(0,l.A)(t)?(0,r.A)(t):function(t){if(!(0,i.A)(t))return s(t);var e=[];for(var n in Object(t))o.call(t,n)&&"constructor"!=n&&e.push(n);return e}(t)}},2624:function(t,e,n){"use strict";n.d(e,{A:function(){return c}});var r=n(6753),i=n(659),s=n(501),o=Object.prototype.hasOwnProperty,l=function(t){if(!(0,i.A)(t))return function(t){var e=[];if(null!=t)for(var n in Object(t))e.push(n);return e}(t);var e=(0,s.A)(t),n=[];for(var r in t)("constructor"!=r||!e&&o.call(t,r))&&n.push(r);return n},a=n(3628),c=function(t){return(0,a.A)(t)?(0,r.A)(t,!0):l(t)}},8347:function(t,e,n){"use strict";n.d(e,{A:function(){return $}});var r,i,s,o,l=n(2673),a=n(6770),c=n(8138),u=function(t,e,n){(void 0!==n&&!(0,c.A)(t[e],n)||void 0===n&&!(e in t))&&(0,a.A)(t,e,n)},h=function(t,e,n){for(var r=-1,i=Object(t),s=n(t),o=s.length;o--;){var l=s[++r];if(!1===e(i[l],l,i))break}return t},d=n(3812),f=n(1827),p=n(4405),g=n(1683),m=n(8412),b=n(723),y=n(3628),v=n(7948),A=n(776),x=n(7572),N=n(659),E=n(2159),w=n(8769),q=Function.prototype,k=Object.prototype,_=q.toString,L=k.hasOwnProperty,S=_.call(Object),O=n(5755),T=function(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]},j=n(9601),C=n(2624),R=function(t,e,n,r,i,s,o){var l,a=T(t,n),c=T(e,n),h=o.get(c);if(h)u(t,n,h);else{var q=s?s(a,c,n+"",t,e,o):void 0,k=void 0===q;if(k){var R=(0,b.A)(c),I=!R&&(0,A.A)(c),B=!R&&!I&&(0,O.A)(c);q=c,R||I||B?(0,b.A)(a)?q=a:(l=a,(0,v.A)(l)&&(0,y.A)(l)?q=(0,p.A)(a):I?(k=!1,q=(0,d.A)(c,!0)):B?(k=!1,q=(0,f.A)(c,!0)):q=[]):function(t){if(!(0,v.A)(t)||"[object Object]"!=(0,E.A)(t))return!1;var e=(0,w.A)(t);if(null===e)return!0;var n=L.call(e,"constructor")&&e.constructor;return"function"==typeof n&&n instanceof n&&_.call(n)==S}(c)||(0,m.A)(c)?(q=a,(0,m.A)(a)?q=function(t){return(0,j.A)(t,(0,C.A)(t))}(a):(0,N.A)(a)&&!(0,x.A)(a)||(q=(0,g.A)(c))):k=!1}k&&(o.set(c,q),i(q,c,r,s,o),o.delete(c)),u(t,n,q)}},I=function t(e,n,r,i,s){e!==n&&h(n,(function(o,a){if(s||(s=new l.A),(0,N.A)(o))R(e,n,a,r,t,i,s);else{var c=i?i(T(e,a),o,a+"",e,n,s):void 0;void 0===c&&(c=o),u(e,a,c)}}),C.A)},B=function(t){return t},M=Math.max,U=n(7889),D=U.A?function(t,e){return(0,U.A)(t,"toString",{configurable:!0,enumerable:!1,value:(n=e,function(){return n}),writable:!0});var n}:B,P=Date.now,z=(r=D,i=0,s=0,function(){var t=P(),e=16-(t-s);if(s=t,e>0){if(++i>=800)return arguments[0]}else i=0;return r.apply(void 0,arguments)}),F=function(t,e){return z(function(t,e,n){return e=M(void 0===e?t.length-1:e,0),function(){for(var r=arguments,i=-1,s=M(r.length-e,0),o=Array(s);++i1?e[r-1]:void 0,s=r>2?e[2]:void 0;for(i=o.length>3&&"function"==typeof i?(r--,i):void 0,s&&function(t,e,n){if(!(0,N.A)(n))return!1;var r=typeof e;return!!("number"==r?(0,y.A)(n)&&(0,H.A)(e,n.length):"string"==r&&e in n)&&(0,c.A)(n[e],t)}(e[0],e[1],s)&&(i=r<3?void 0:i,r=1),t=Object(t);++n(t[t.TYPE=3]="TYPE",t[t.LEVEL=12]="LEVEL",t[t.ATTRIBUTE=13]="ATTRIBUTE",t[t.BLOT=14]="BLOT",t[t.INLINE=7]="INLINE",t[t.BLOCK=11]="BLOCK",t[t.BLOCK_BLOT=10]="BLOCK_BLOT",t[t.INLINE_BLOT=6]="INLINE_BLOT",t[t.BLOCK_ATTRIBUTE=9]="BLOCK_ATTRIBUTE",t[t.INLINE_ATTRIBUTE=5]="INLINE_ATTRIBUTE",t[t.ANY=15]="ANY",t))(r||{});class i{constructor(t,e,n={}){this.attrName=t,this.keyName=e;const i=r.TYPE&r.ATTRIBUTE;this.scope=null!=n.scope?n.scope&r.LEVEL|i:r.ATTRIBUTE,null!=n.whitelist&&(this.whitelist=n.whitelist)}static keys(t){return Array.from(t.attributes).map((t=>t.name))}add(t,e){return!!this.canAdd(t,e)&&(t.setAttribute(this.keyName,e),!0)}canAdd(t,e){return null==this.whitelist||("string"==typeof e?this.whitelist.indexOf(e.replace(/["']/g,""))>-1:this.whitelist.indexOf(e)>-1)}remove(t){t.removeAttribute(this.keyName)}value(t){const e=t.getAttribute(this.keyName);return this.canAdd(t,e)&&e?e:""}}class s extends Error{constructor(t){super(t="[Parchment] "+t),this.message=t,this.name=this.constructor.name}}const o=class t{constructor(){this.attributes={},this.classes={},this.tags={},this.types={}}static find(t,e=!1){if(null==t)return null;if(this.blots.has(t))return this.blots.get(t)||null;if(e){let n=null;try{n=t.parentNode}catch{return null}return this.find(n,e)}return null}create(e,n,r){const i=this.query(n);if(null==i)throw new s(`Unable to create ${n} blot`);const o=i,l=n instanceof Node||n.nodeType===Node.TEXT_NODE?n:o.create(r),a=new o(e,l,r);return t.blots.set(a.domNode,a),a}find(e,n=!1){return t.find(e,n)}query(t,e=r.ANY){let n;return"string"==typeof t?n=this.types[t]||this.attributes[t]:t instanceof Text||t.nodeType===Node.TEXT_NODE?n=this.types.text:"number"==typeof t?t&r.LEVEL&r.BLOCK?n=this.types.block:t&r.LEVEL&r.INLINE&&(n=this.types.inline):t instanceof Element&&((t.getAttribute("class")||"").split(/\s+/).some((t=>(n=this.classes[t],!!n))),n=n||this.tags[t.tagName]),null==n?null:"scope"in n&&e&r.LEVEL&n.scope&&e&r.TYPE&n.scope?n:null}register(...t){return t.map((t=>{const e="blotName"in t,n="attrName"in t;if(!e&&!n)throw new s("Invalid definition");if(e&&"abstract"===t.blotName)throw new s("Cannot register abstract class");const r=e?t.blotName:n?t.attrName:void 0;return this.types[r]=t,n?"string"==typeof t.keyName&&(this.attributes[t.keyName]=t):e&&(t.className&&(this.classes[t.className]=t),t.tagName&&(Array.isArray(t.tagName)?t.tagName=t.tagName.map((t=>t.toUpperCase())):t.tagName=t.tagName.toUpperCase(),(Array.isArray(t.tagName)?t.tagName:[t.tagName]).forEach((e=>{(null==this.tags[e]||null==t.className)&&(this.tags[e]=t)})))),t}))}};o.blots=new WeakMap;let l=o;function a(t,e){return(t.getAttribute("class")||"").split(/\s+/).filter((t=>0===t.indexOf(`${e}-`)))}const c=class extends i{static keys(t){return(t.getAttribute("class")||"").split(/\s+/).map((t=>t.split("-").slice(0,-1).join("-")))}add(t,e){return!!this.canAdd(t,e)&&(this.remove(t),t.classList.add(`${this.keyName}-${e}`),!0)}remove(t){a(t,this.keyName).forEach((e=>{t.classList.remove(e)})),0===t.classList.length&&t.removeAttribute("class")}value(t){const e=(a(t,this.keyName)[0]||"").slice(this.keyName.length+1);return this.canAdd(t,e)?e:""}};function u(t){const e=t.split("-"),n=e.slice(1).map((t=>t[0].toUpperCase()+t.slice(1))).join("");return e[0]+n}const h=class extends i{static keys(t){return(t.getAttribute("style")||"").split(";").map((t=>t.split(":")[0].trim()))}add(t,e){return!!this.canAdd(t,e)&&(t.style[u(this.keyName)]=e,!0)}remove(t){t.style[u(this.keyName)]="",t.getAttribute("style")||t.removeAttribute("style")}value(t){const e=t.style[u(this.keyName)];return this.canAdd(t,e)?e:""}},d=class{constructor(t){this.attributes={},this.domNode=t,this.build()}attribute(t,e){e?t.add(this.domNode,e)&&(null!=t.value(this.domNode)?this.attributes[t.attrName]=t:delete this.attributes[t.attrName]):(t.remove(this.domNode),delete this.attributes[t.attrName])}build(){this.attributes={};const t=l.find(this.domNode);if(null==t)return;const e=i.keys(this.domNode),n=c.keys(this.domNode),s=h.keys(this.domNode);e.concat(n).concat(s).forEach((e=>{const n=t.scroll.query(e,r.ATTRIBUTE);n instanceof i&&(this.attributes[n.attrName]=n)}))}copy(t){Object.keys(this.attributes).forEach((e=>{const n=this.attributes[e].value(this.domNode);t.format(e,n)}))}move(t){this.copy(t),Object.keys(this.attributes).forEach((t=>{this.attributes[t].remove(this.domNode)})),this.attributes={}}values(){return Object.keys(this.attributes).reduce(((t,e)=>(t[e]=this.attributes[e].value(this.domNode),t)),{})}},f=class{constructor(t,e){this.scroll=t,this.domNode=e,l.blots.set(e,this),this.prev=null,this.next=null}static create(t){if(null==this.tagName)throw new s("Blot definition missing tagName");let e,n;return Array.isArray(this.tagName)?("string"==typeof t?(n=t.toUpperCase(),parseInt(n,10).toString()===n&&(n=parseInt(n,10))):"number"==typeof t&&(n=t),e="number"==typeof n?document.createElement(this.tagName[n-1]):n&&this.tagName.indexOf(n)>-1?document.createElement(n):document.createElement(this.tagName[0])):e=document.createElement(this.tagName),this.className&&e.classList.add(this.className),e}get statics(){return this.constructor}attach(){}clone(){const t=this.domNode.cloneNode(!1);return this.scroll.create(t)}detach(){null!=this.parent&&this.parent.removeChild(this),l.blots.delete(this.domNode)}deleteAt(t,e){this.isolate(t,e).remove()}formatAt(t,e,n,i){const s=this.isolate(t,e);if(null!=this.scroll.query(n,r.BLOT)&&i)s.wrap(n,i);else if(null!=this.scroll.query(n,r.ATTRIBUTE)){const t=this.scroll.create(this.statics.scope);s.wrap(t),t.format(n,i)}}insertAt(t,e,n){const r=null==n?this.scroll.create("text",e):this.scroll.create(e,n),i=this.split(t);this.parent.insertBefore(r,i||void 0)}isolate(t,e){const n=this.split(t);if(null==n)throw new Error("Attempt to isolate at end");return n.split(e),n}length(){return 1}offset(t=this.parent){return null==this.parent||this===t?0:this.parent.children.offset(this)+this.parent.offset(t)}optimize(t){this.statics.requiredContainer&&!(this.parent instanceof this.statics.requiredContainer)&&this.wrap(this.statics.requiredContainer.blotName)}remove(){null!=this.domNode.parentNode&&this.domNode.parentNode.removeChild(this.domNode),this.detach()}replaceWith(t,e){const n="string"==typeof t?this.scroll.create(t,e):t;return null!=this.parent&&(this.parent.insertBefore(n,this.next||void 0),this.remove()),n}split(t,e){return 0===t?this:this.next}update(t,e){}wrap(t,e){const n="string"==typeof t?this.scroll.create(t,e):t;if(null!=this.parent&&this.parent.insertBefore(n,this.next||void 0),"function"!=typeof n.appendChild)throw new s(`Cannot wrap ${t}`);return n.appendChild(this),n}};f.blotName="abstract";let p=f;const g=class extends p{static value(t){return!0}index(t,e){return this.domNode===t||this.domNode.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_CONTAINED_BY?Math.min(e,1):-1}position(t,e){let n=Array.from(this.parent.domNode.childNodes).indexOf(this.domNode);return t>0&&(n+=1),[this.parent.domNode,n]}value(){return{[this.statics.blotName]:this.statics.value(this.domNode)||!0}}};g.scope=r.INLINE_BLOT;const m=g;class b{constructor(){this.head=null,this.tail=null,this.length=0}append(...t){if(this.insertBefore(t[0],null),t.length>1){const e=t.slice(1);this.append(...e)}}at(t){const e=this.iterator();let n=e();for(;n&&t>0;)t-=1,n=e();return n}contains(t){const e=this.iterator();let n=e();for(;n;){if(n===t)return!0;n=e()}return!1}indexOf(t){const e=this.iterator();let n=e(),r=0;for(;n;){if(n===t)return r;r+=1,n=e()}return-1}insertBefore(t,e){null!=t&&(this.remove(t),t.next=e,null!=e?(t.prev=e.prev,null!=e.prev&&(e.prev.next=t),e.prev=t,e===this.head&&(this.head=t)):null!=this.tail?(this.tail.next=t,t.prev=this.tail,this.tail=t):(t.prev=null,this.head=this.tail=t),this.length+=1)}offset(t){let e=0,n=this.head;for(;null!=n;){if(n===t)return e;e+=n.length(),n=n.next}return-1}remove(t){this.contains(t)&&(null!=t.prev&&(t.prev.next=t.next),null!=t.next&&(t.next.prev=t.prev),t===this.head&&(this.head=t.next),t===this.tail&&(this.tail=t.prev),this.length-=1)}iterator(t=this.head){return()=>{const e=t;return null!=t&&(t=t.next),e}}find(t,e=!1){const n=this.iterator();let r=n();for(;r;){const i=r.length();if(ts?n(l,t-s,Math.min(e,s+r-t)):n(l,0,Math.min(r,t+e-s)),s+=r,l=o()}}map(t){return this.reduce(((e,n)=>(e.push(t(n)),e)),[])}reduce(t,e){const n=this.iterator();let r=n();for(;r;)e=t(e,r),r=n();return e}}function y(t,e){const n=e.find(t);if(n)return n;try{return e.create(t)}catch{const n=e.create(r.INLINE);return Array.from(t.childNodes).forEach((t=>{n.domNode.appendChild(t)})),t.parentNode&&t.parentNode.replaceChild(n.domNode,t),n.attach(),n}}const v=class t extends p{constructor(t,e){super(t,e),this.uiNode=null,this.build()}appendChild(t){this.insertBefore(t)}attach(){super.attach(),this.children.forEach((t=>{t.attach()}))}attachUI(e){null!=this.uiNode&&this.uiNode.remove(),this.uiNode=e,t.uiClass&&this.uiNode.classList.add(t.uiClass),this.uiNode.setAttribute("contenteditable","false"),this.domNode.insertBefore(this.uiNode,this.domNode.firstChild)}build(){this.children=new b,Array.from(this.domNode.childNodes).filter((t=>t!==this.uiNode)).reverse().forEach((t=>{try{const e=y(t,this.scroll);this.insertBefore(e,this.children.head||void 0)}catch(t){if(t instanceof s)return;throw t}}))}deleteAt(t,e){if(0===t&&e===this.length())return this.remove();this.children.forEachAt(t,e,((t,e,n)=>{t.deleteAt(e,n)}))}descendant(e,n=0){const[r,i]=this.children.find(n);return null==e.blotName&&e(r)||null!=e.blotName&&r instanceof e?[r,i]:r instanceof t?r.descendant(e,i):[null,-1]}descendants(e,n=0,r=Number.MAX_VALUE){let i=[],s=r;return this.children.forEachAt(n,r,((n,r,o)=>{(null==e.blotName&&e(n)||null!=e.blotName&&n instanceof e)&&i.push(n),n instanceof t&&(i=i.concat(n.descendants(e,r,s))),s-=o})),i}detach(){this.children.forEach((t=>{t.detach()})),super.detach()}enforceAllowedChildren(){let e=!1;this.children.forEach((n=>{e||this.statics.allowedChildren.some((t=>n instanceof t))||(n.statics.scope===r.BLOCK_BLOT?(null!=n.next&&this.splitAfter(n),null!=n.prev&&this.splitAfter(n.prev),n.parent.unwrap(),e=!0):n instanceof t?n.unwrap():n.remove())}))}formatAt(t,e,n,r){this.children.forEachAt(t,e,((t,e,i)=>{t.formatAt(e,i,n,r)}))}insertAt(t,e,n){const[r,i]=this.children.find(t);if(r)r.insertAt(i,e,n);else{const t=null==n?this.scroll.create("text",e):this.scroll.create(e,n);this.appendChild(t)}}insertBefore(t,e){null!=t.parent&&t.parent.children.remove(t);let n=null;this.children.insertBefore(t,e||null),t.parent=this,null!=e&&(n=e.domNode),(this.domNode.parentNode!==t.domNode||this.domNode.nextSibling!==n)&&this.domNode.insertBefore(t.domNode,n),t.attach()}length(){return this.children.reduce(((t,e)=>t+e.length()),0)}moveChildren(t,e){this.children.forEach((n=>{t.insertBefore(n,e)}))}optimize(t){if(super.optimize(t),this.enforceAllowedChildren(),null!=this.uiNode&&this.uiNode!==this.domNode.firstChild&&this.domNode.insertBefore(this.uiNode,this.domNode.firstChild),0===this.children.length)if(null!=this.statics.defaultChild){const t=this.scroll.create(this.statics.defaultChild.blotName);this.appendChild(t)}else this.remove()}path(e,n=!1){const[r,i]=this.children.find(e,n),s=[[this,e]];return r instanceof t?s.concat(r.path(i,n)):(null!=r&&s.push([r,i]),s)}removeChild(t){this.children.remove(t)}replaceWith(e,n){const r="string"==typeof e?this.scroll.create(e,n):e;return r instanceof t&&this.moveChildren(r),super.replaceWith(r)}split(t,e=!1){if(!e){if(0===t)return this;if(t===this.length())return this.next}const n=this.clone();return this.parent&&this.parent.insertBefore(n,this.next||void 0),this.children.forEachAt(t,this.length(),((t,r,i)=>{const s=t.split(r,e);null!=s&&n.appendChild(s)})),n}splitAfter(t){const e=this.clone();for(;null!=t.next;)e.appendChild(t.next);return this.parent&&this.parent.insertBefore(e,this.next||void 0),e}unwrap(){this.parent&&this.moveChildren(this.parent,this.next||void 0),this.remove()}update(t,e){const n=[],r=[];t.forEach((t=>{t.target===this.domNode&&"childList"===t.type&&(n.push(...t.addedNodes),r.push(...t.removedNodes))})),r.forEach((t=>{if(null!=t.parentNode&&"IFRAME"!==t.tagName&&document.body.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_CONTAINED_BY)return;const e=this.scroll.find(t);null!=e&&(null==e.domNode.parentNode||e.domNode.parentNode===this.domNode)&&e.detach()})),n.filter((t=>t.parentNode===this.domNode&&t!==this.uiNode)).sort(((t,e)=>t===e?0:t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING?1:-1)).forEach((t=>{let e=null;null!=t.nextSibling&&(e=this.scroll.find(t.nextSibling));const n=y(t,this.scroll);(n.next!==e||null==n.next)&&(null!=n.parent&&n.parent.removeChild(this),this.insertBefore(n,e||void 0))})),this.enforceAllowedChildren()}};v.uiClass="";const A=v,x=class t extends A{static create(t){return super.create(t)}static formats(e,n){const r=n.query(t.blotName);if(null==r||e.tagName!==r.tagName){if("string"==typeof this.tagName)return!0;if(Array.isArray(this.tagName))return e.tagName.toLowerCase()}}constructor(t,e){super(t,e),this.attributes=new d(this.domNode)}format(e,n){if(e!==this.statics.blotName||n){const t=this.scroll.query(e,r.INLINE);if(null==t)return;t instanceof i?this.attributes.attribute(t,n):n&&(e!==this.statics.blotName||this.formats()[e]!==n)&&this.replaceWith(e,n)}else this.children.forEach((e=>{e instanceof t||(e=e.wrap(t.blotName,!0)),this.attributes.copy(e)})),this.unwrap()}formats(){const t=this.attributes.values(),e=this.statics.formats(this.domNode,this.scroll);return null!=e&&(t[this.statics.blotName]=e),t}formatAt(t,e,n,i){null!=this.formats()[n]||this.scroll.query(n,r.ATTRIBUTE)?this.isolate(t,e).format(n,i):super.formatAt(t,e,n,i)}optimize(e){super.optimize(e);const n=this.formats();if(0===Object.keys(n).length)return this.unwrap();const r=this.next;r instanceof t&&r.prev===this&&function(t,e){if(Object.keys(t).length!==Object.keys(e).length)return!1;for(const n in t)if(t[n]!==e[n])return!1;return!0}(n,r.formats())&&(r.moveChildren(this),r.remove())}replaceWith(t,e){const n=super.replaceWith(t,e);return this.attributes.copy(n),n}update(t,e){super.update(t,e),t.some((t=>t.target===this.domNode&&"attributes"===t.type))&&this.attributes.build()}wrap(e,n){const r=super.wrap(e,n);return r instanceof t&&this.attributes.move(r),r}};x.allowedChildren=[x,m],x.blotName="inline",x.scope=r.INLINE_BLOT,x.tagName="SPAN";const N=x,E=class t extends A{static create(t){return super.create(t)}static formats(e,n){const r=n.query(t.blotName);if(null==r||e.tagName!==r.tagName){if("string"==typeof this.tagName)return!0;if(Array.isArray(this.tagName))return e.tagName.toLowerCase()}}constructor(t,e){super(t,e),this.attributes=new d(this.domNode)}format(e,n){const s=this.scroll.query(e,r.BLOCK);null!=s&&(s instanceof i?this.attributes.attribute(s,n):e!==this.statics.blotName||n?n&&(e!==this.statics.blotName||this.formats()[e]!==n)&&this.replaceWith(e,n):this.replaceWith(t.blotName))}formats(){const t=this.attributes.values(),e=this.statics.formats(this.domNode,this.scroll);return null!=e&&(t[this.statics.blotName]=e),t}formatAt(t,e,n,i){null!=this.scroll.query(n,r.BLOCK)?this.format(n,i):super.formatAt(t,e,n,i)}insertAt(t,e,n){if(null==n||null!=this.scroll.query(e,r.INLINE))super.insertAt(t,e,n);else{const r=this.split(t);if(null==r)throw new Error("Attempt to insertAt after block boundaries");{const t=this.scroll.create(e,n);r.parent.insertBefore(t,r)}}}replaceWith(t,e){const n=super.replaceWith(t,e);return this.attributes.copy(n),n}update(t,e){super.update(t,e),t.some((t=>t.target===this.domNode&&"attributes"===t.type))&&this.attributes.build()}};E.blotName="block",E.scope=r.BLOCK_BLOT,E.tagName="P",E.allowedChildren=[N,E,m];const w=E,q=class extends A{checkMerge(){return null!==this.next&&this.next.statics.blotName===this.statics.blotName}deleteAt(t,e){super.deleteAt(t,e),this.enforceAllowedChildren()}formatAt(t,e,n,r){super.formatAt(t,e,n,r),this.enforceAllowedChildren()}insertAt(t,e,n){super.insertAt(t,e,n),this.enforceAllowedChildren()}optimize(t){super.optimize(t),this.children.length>0&&null!=this.next&&this.checkMerge()&&(this.next.moveChildren(this),this.next.remove())}};q.blotName="container",q.scope=r.BLOCK_BLOT;const k=q,_=class extends m{static formats(t,e){}format(t,e){super.formatAt(0,this.length(),t,e)}formatAt(t,e,n,r){0===t&&e===this.length()?this.format(n,r):super.formatAt(t,e,n,r)}formats(){return this.statics.formats(this.domNode,this.scroll)}},L={attributes:!0,characterData:!0,characterDataOldValue:!0,childList:!0,subtree:!0},S=class extends A{constructor(t,e){super(null,e),this.registry=t,this.scroll=this,this.build(),this.observer=new MutationObserver((t=>{this.update(t)})),this.observer.observe(this.domNode,L),this.attach()}create(t,e){return this.registry.create(this,t,e)}find(t,e=!1){const n=this.registry.find(t,e);return n?n.scroll===this?n:e?this.find(n.scroll.domNode.parentNode,!0):null:null}query(t,e=r.ANY){return this.registry.query(t,e)}register(...t){return this.registry.register(...t)}build(){null!=this.scroll&&super.build()}detach(){super.detach(),this.observer.disconnect()}deleteAt(t,e){this.update(),0===t&&e===this.length()?this.children.forEach((t=>{t.remove()})):super.deleteAt(t,e)}formatAt(t,e,n,r){this.update(),super.formatAt(t,e,n,r)}insertAt(t,e,n){this.update(),super.insertAt(t,e,n)}optimize(t=[],e={}){super.optimize(e);const n=e.mutationsMap||new WeakMap;let r=Array.from(this.observer.takeRecords());for(;r.length>0;)t.push(r.pop());const i=(t,e=!0)=>{null==t||t===this||null!=t.domNode.parentNode&&(n.has(t.domNode)||n.set(t.domNode,[]),e&&i(t.parent))},s=t=>{n.has(t.domNode)&&(t instanceof A&&t.children.forEach(s),n.delete(t.domNode),t.optimize(e))};let o=t;for(let e=0;o.length>0;e+=1){if(e>=100)throw new Error("[Parchment] Maximum optimize iterations reached");for(o.forEach((t=>{const e=this.find(t.target,!0);null!=e&&(e.domNode===t.target&&("childList"===t.type?(i(this.find(t.previousSibling,!1)),Array.from(t.addedNodes).forEach((t=>{const e=this.find(t,!1);i(e,!1),e instanceof A&&e.children.forEach((t=>{i(t,!1)}))}))):"attributes"===t.type&&i(e.prev)),i(e))})),this.children.forEach(s),o=Array.from(this.observer.takeRecords()),r=o.slice();r.length>0;)t.push(r.pop())}}update(t,e={}){t=t||this.observer.takeRecords();const n=new WeakMap;t.map((t=>{const e=this.find(t.target,!0);return null==e?null:n.has(e.domNode)?(n.get(e.domNode).push(t),null):(n.set(e.domNode,[t]),e)})).forEach((t=>{null!=t&&t!==this&&n.has(t.domNode)&&t.update(n.get(t.domNode)||[],e)})),e.mutationsMap=n,n.has(this.domNode)&&super.update(n.get(this.domNode),e),this.optimize(t,e)}};S.blotName="scroll",S.defaultChild=w,S.allowedChildren=[w,k],S.scope=r.BLOCK_BLOT,S.tagName="DIV";const O=S,T=class t extends m{static create(t){return document.createTextNode(t)}static value(t){return t.data}constructor(t,e){super(t,e),this.text=this.statics.value(this.domNode)}deleteAt(t,e){this.domNode.data=this.text=this.text.slice(0,t)+this.text.slice(t+e)}index(t,e){return this.domNode===t?e:-1}insertAt(t,e,n){null==n?(this.text=this.text.slice(0,t)+e+this.text.slice(t),this.domNode.data=this.text):super.insertAt(t,e,n)}length(){return this.text.length}optimize(e){super.optimize(e),this.text=this.statics.value(this.domNode),0===this.text.length?this.remove():this.next instanceof t&&this.next.prev===this&&(this.insertAt(this.length(),this.next.value()),this.next.remove())}position(t,e=!1){return[this.domNode,t]}split(t,e=!1){if(!e){if(0===t)return this;if(t===this.length())return this.next}const n=this.scroll.create(this.domNode.splitText(t));return this.parent.insertBefore(n,this.next||void 0),this.text=this.statics.value(this.domNode),n}update(t,e){t.some((t=>"characterData"===t.type&&t.target===this.domNode))&&(this.text=this.statics.value(this.domNode))}value(){return this.text}};T.blotName="text",T.scope=r.INLINE_BLOT;const j=T}},e={};function n(r){var i=e[r];if(void 0!==i)return i.exports;var s=e[r]={id:r,loaded:!1,exports:{}};return t[r](s,s.exports,n),s.loaded=!0,s.exports}n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,{a:e}),e},n.d=function(t,e){for(var r in e)n.o(e,r)&&!n.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.nmd=function(t){return t.paths=[],t.children||(t.children=[]),t};var r={};return function(){"use strict";n.d(r,{default:function(){return It}});var t=n(3729),e=n(8276),i=n(7912),s=n(6003);class o extends s.ClassAttributor{add(t,e){let n=0;if("+1"===e||"-1"===e){const r=this.value(t)||0;n="+1"===e?r+1:r-1}else"number"==typeof e&&(n=e);return 0===n?(this.remove(t),!0):super.add(t,n.toString())}canAdd(t,e){return super.canAdd(t,e)||super.canAdd(t,parseInt(e,10))}value(t){return parseInt(super.value(t),10)||void 0}}var l=new o("indent","ql-indent",{scope:s.Scope.BLOCK,whitelist:[1,2,3,4,5,6,7,8]}),a=n(9698);class c extends a.Ay{static blotName="blockquote";static tagName="blockquote"}var u=c;class h extends a.Ay{static blotName="header";static tagName=["H1","H2","H3","H4","H5","H6"];static formats(t){return this.tagName.indexOf(t.tagName)+1}}var d=h,f=n(580),p=n(6142);class g extends f.A{}g.blotName="list-container",g.tagName="OL";class m extends a.Ay{static create(t){const e=super.create();return e.setAttribute("data-list",t),e}static formats(t){return t.getAttribute("data-list")||void 0}static register(){p.Ay.register(g)}constructor(t,e){super(t,e);const n=e.ownerDocument.createElement("span"),r=n=>{if(!t.isEnabled())return;const r=this.statics.formats(e,t);"checked"===r?(this.format("list","unchecked"),n.preventDefault()):"unchecked"===r&&(this.format("list","checked"),n.preventDefault())};n.addEventListener("mousedown",r),n.addEventListener("touchstart",r),this.attachUI(n)}format(t,e){t===this.statics.blotName&&e?this.domNode.setAttribute("data-list",e):super.format(t,e)}}m.blotName="list",m.tagName="LI",g.allowedChildren=[m],m.requiredContainer=g;var b=n(9541),y=n(8638),v=n(6772),A=n(664),x=n(4850);class N extends x.A{static blotName="bold";static tagName=["STRONG","B"];static create(){return super.create()}static formats(){return!0}optimize(t){super.optimize(t),this.domNode.tagName!==this.statics.tagName[0]&&this.replaceWith(this.statics.blotName)}}var E=N;class w extends x.A{static blotName="link";static tagName="A";static SANITIZED_URL="about:blank";static PROTOCOL_WHITELIST=["http","https","mailto","tel","sms"];static create(t){const e=super.create(t);return e.setAttribute("href",this.sanitize(t)),e.setAttribute("rel","noopener noreferrer"),e.setAttribute("target","_blank"),e}static formats(t){return t.getAttribute("href")}static sanitize(t){return q(t,this.PROTOCOL_WHITELIST)?t:this.SANITIZED_URL}format(t,e){t===this.statics.blotName&&e?this.domNode.setAttribute("href",this.constructor.sanitize(e)):super.format(t,e)}}function q(t,e){const n=document.createElement("a");n.href=t;const r=n.href.slice(0,n.href.indexOf(":"));return e.indexOf(r)>-1}class k extends x.A{static blotName="script";static tagName=["SUB","SUP"];static create(t){return"super"===t?document.createElement("sup"):"sub"===t?document.createElement("sub"):super.create(t)}static formats(t){return"SUB"===t.tagName?"sub":"SUP"===t.tagName?"super":void 0}}var _=k;class L extends x.A{static blotName="underline";static tagName="U"}var S=L,O=n(746);class T extends O.A{static blotName="formula";static className="ql-formula";static tagName="SPAN";static create(t){if(null==window.katex)throw new Error("Formula module requires KaTeX.");const e=super.create(t);return"string"==typeof t&&(window.katex.render(t,e,{throwOnError:!1,errorColor:"#f00"}),e.setAttribute("data-value",t)),e}static value(t){return t.getAttribute("data-value")}html(){const{formula:t}=this.value();return`${t}`}}var j=T;const C=["alt","height","width"];class R extends s.EmbedBlot{static blotName="image";static tagName="IMG";static create(t){const e=super.create(t);return"string"==typeof t&&e.setAttribute("src",this.sanitize(t)),e}static formats(t){return C.reduce(((e,n)=>(t.hasAttribute(n)&&(e[n]=t.getAttribute(n)),e)),{})}static match(t){return/\.(jpe?g|gif|png)$/.test(t)||/^data:image\/.+;base64/.test(t)}static sanitize(t){return q(t,["http","https","data"])?t:"//:0"}static value(t){return t.getAttribute("src")}format(t,e){C.indexOf(t)>-1?e?this.domNode.setAttribute(t,e):this.domNode.removeAttribute(t):super.format(t,e)}}var I=R;const B=["height","width"];class M extends a.zo{static blotName="video";static className="ql-video";static tagName="IFRAME";static create(t){const e=super.create(t);return e.setAttribute("frameborder","0"),e.setAttribute("allowfullscreen","true"),e.setAttribute("src",this.sanitize(t)),e}static formats(t){return B.reduce(((e,n)=>(t.hasAttribute(n)&&(e[n]=t.getAttribute(n)),e)),{})}static sanitize(t){return w.sanitize(t)}static value(t){return t.getAttribute("src")}format(t,e){B.indexOf(t)>-1?e?this.domNode.setAttribute(t,e):this.domNode.removeAttribute(t):super.format(t,e)}html(){const{video:t}=this.value();return`
    ${t}`}}var U=M,D=n(9404),P=n(5232),z=n.n(P),F=n(4266),H=n(3036),$=n(4541),V=n(5508),K=n(584);const W=new s.ClassAttributor("code-token","hljs",{scope:s.Scope.INLINE});class Z extends x.A{static formats(t,e){for(;null!=t&&t!==e.domNode;){if(t.classList&&t.classList.contains(D.Ay.className))return super.formats(t,e);t=t.parentNode}}constructor(t,e,n){super(t,e,n),W.add(this.domNode,n)}format(t,e){t!==Z.blotName?super.format(t,e):e?W.add(this.domNode,e):(W.remove(this.domNode),this.domNode.classList.remove(this.statics.className))}optimize(){super.optimize(...arguments),W.value(this.domNode)||this.unwrap()}}Z.blotName="code-token",Z.className="ql-token";class G extends D.Ay{static create(t){const e=super.create(t);return"string"==typeof t&&e.setAttribute("data-language",t),e}static formats(t){return t.getAttribute("data-language")||"plain"}static register(){}format(t,e){t===this.statics.blotName&&e?this.domNode.setAttribute("data-language",e):super.format(t,e)}replaceWith(t,e){return this.formatAt(0,this.length(),Z.blotName,!1),super.replaceWith(t,e)}}class X extends D.EJ{attach(){super.attach(),this.forceNext=!1,this.scroll.emitMount(this)}format(t,e){t===G.blotName&&(this.forceNext=!0,this.children.forEach((n=>{n.format(t,e)})))}formatAt(t,e,n,r){n===G.blotName&&(this.forceNext=!0),super.formatAt(t,e,n,r)}highlight(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(null==this.children.head)return;const n=`${Array.from(this.domNode.childNodes).filter((t=>t!==this.uiNode)).map((t=>t.textContent)).join("\n")}\n`,r=G.formats(this.children.head.domNode);if(e||this.forceNext||this.cachedText!==n){if(n.trim().length>0||null==this.cachedText){const e=this.children.reduce(((t,e)=>t.concat((0,a.mG)(e,!1))),new(z())),i=t(n,r);e.diff(i).reduce(((t,e)=>{let{retain:n,attributes:r}=e;return n?(r&&Object.keys(r).forEach((e=>{[G.blotName,Z.blotName].includes(e)&&this.formatAt(t,n,e,r[e])})),t+n):t}),0)}this.cachedText=n,this.forceNext=!1}}html(t,e){const[n]=this.children.find(t);return`
    \n${(0,V.X)(this.code(t,e))}\n
    `}optimize(t){if(super.optimize(t),null!=this.parent&&null!=this.children.head&&null!=this.uiNode){const t=G.formats(this.children.head.domNode);t!==this.uiNode.value&&(this.uiNode.value=t)}}}X.allowedChildren=[G],G.requiredContainer=X,G.allowedChildren=[Z,$.A,V.A,H.A];class Q extends F.A{static register(){p.Ay.register(Z,!0),p.Ay.register(G,!0),p.Ay.register(X,!0)}constructor(t,e){if(super(t,e),null==this.options.hljs)throw new Error("Syntax module requires highlight.js. Please include the library on the page before Quill.");this.languages=this.options.languages.reduce(((t,e)=>{let{key:n}=e;return t[n]=!0,t}),{}),this.highlightBlot=this.highlightBlot.bind(this),this.initListener(),this.initTimer()}initListener(){this.quill.on(p.Ay.events.SCROLL_BLOT_MOUNT,(t=>{if(!(t instanceof X))return;const e=this.quill.root.ownerDocument.createElement("select");this.options.languages.forEach((t=>{let{key:n,label:r}=t;const i=e.ownerDocument.createElement("option");i.textContent=r,i.setAttribute("value",n),e.appendChild(i)})),e.addEventListener("change",(()=>{t.format(G.blotName,e.value),this.quill.root.focus(),this.highlight(t,!0)})),null==t.uiNode&&(t.attachUI(e),t.children.head&&(e.value=G.formats(t.children.head.domNode)))}))}initTimer(){let t=null;this.quill.on(p.Ay.events.SCROLL_OPTIMIZE,(()=>{t&&clearTimeout(t),t=setTimeout((()=>{this.highlight(),t=null}),this.options.interval)}))}highlight(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.quill.selection.composing)return;this.quill.update(p.Ay.sources.USER);const n=this.quill.getSelection();(null==t?this.quill.scroll.descendants(X):[t]).forEach((t=>{t.highlight(this.highlightBlot,e)})),this.quill.update(p.Ay.sources.SILENT),null!=n&&this.quill.setSelection(n,p.Ay.sources.SILENT)}highlightBlot(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"plain";if(e=this.languages[e]?e:"plain","plain"===e)return(0,V.X)(t).split("\n").reduce(((t,n,r)=>(0!==r&&t.insert("\n",{[D.Ay.blotName]:e}),t.insert(n))),new(z()));const n=this.quill.root.ownerDocument.createElement("div");return n.classList.add(D.Ay.className),n.innerHTML=((t,e,n)=>{if("string"==typeof t.versionString){const r=t.versionString.split(".")[0];if(parseInt(r,10)>=11)return t.highlight(n,{language:e}).value}return t.highlight(e,n).value})(this.options.hljs,e,t),(0,K.hV)(this.quill.scroll,n,[(t,e)=>{const n=W.value(t);return n?e.compose((new(z())).retain(e.length(),{[Z.blotName]:n})):e}],[(t,n)=>t.data.split("\n").reduce(((t,n,r)=>(0!==r&&t.insert("\n",{[D.Ay.blotName]:e}),t.insert(n))),n)],new WeakMap)}}Q.DEFAULTS={hljs:window.hljs,interval:1e3,languages:[{key:"plain",label:"Plain"},{key:"bash",label:"Bash"},{key:"cpp",label:"C++"},{key:"cs",label:"C#"},{key:"css",label:"CSS"},{key:"diff",label:"Diff"},{key:"xml",label:"HTML/XML"},{key:"java",label:"Java"},{key:"javascript",label:"JavaScript"},{key:"markdown",label:"Markdown"},{key:"php",label:"PHP"},{key:"python",label:"Python"},{key:"ruby",label:"Ruby"},{key:"sql",label:"SQL"}]};class J extends a.Ay{static blotName="table";static tagName="TD";static create(t){const e=super.create();return t?e.setAttribute("data-row",t):e.setAttribute("data-row",nt()),e}static formats(t){if(t.hasAttribute("data-row"))return t.getAttribute("data-row")}cellOffset(){return this.parent?this.parent.children.indexOf(this):-1}format(t,e){t===J.blotName&&e?this.domNode.setAttribute("data-row",e):super.format(t,e)}row(){return this.parent}rowOffset(){return this.row()?this.row().rowOffset():-1}table(){return this.row()&&this.row().table()}}class Y extends f.A{static blotName="table-row";static tagName="TR";checkMerge(){if(super.checkMerge()&&null!=this.next.children.head){const t=this.children.head.formats(),e=this.children.tail.formats(),n=this.next.children.head.formats(),r=this.next.children.tail.formats();return t.table===e.table&&t.table===n.table&&t.table===r.table}return!1}optimize(t){super.optimize(t),this.children.forEach((t=>{if(null==t.next)return;const e=t.formats(),n=t.next.formats();if(e.table!==n.table){const e=this.splitAfter(t);e&&e.optimize(),this.prev&&this.prev.optimize()}}))}rowOffset(){return this.parent?this.parent.children.indexOf(this):-1}table(){return this.parent&&this.parent.parent}}class tt extends f.A{static blotName="table-body";static tagName="TBODY"}class et extends f.A{static blotName="table-container";static tagName="TABLE";balanceCells(){const t=this.descendants(Y),e=t.reduce(((t,e)=>Math.max(e.children.length,t)),0);t.forEach((t=>{new Array(e-t.children.length).fill(0).forEach((()=>{let e;null!=t.children.head&&(e=J.formats(t.children.head.domNode));const n=this.scroll.create(J.blotName,e);t.appendChild(n),n.optimize()}))}))}cells(t){return this.rows().map((e=>e.children.at(t)))}deleteColumn(t){const[e]=this.descendant(tt);null!=e&&null!=e.children.head&&e.children.forEach((e=>{const n=e.children.at(t);null!=n&&n.remove()}))}insertColumn(t){const[e]=this.descendant(tt);null!=e&&null!=e.children.head&&e.children.forEach((e=>{const n=e.children.at(t),r=J.formats(e.children.head.domNode),i=this.scroll.create(J.blotName,r);e.insertBefore(i,n)}))}insertRow(t){const[e]=this.descendant(tt);if(null==e||null==e.children.head)return;const n=nt(),r=this.scroll.create(Y.blotName);e.children.head.children.forEach((()=>{const t=this.scroll.create(J.blotName,n);r.appendChild(t)}));const i=e.children.at(t);e.insertBefore(r,i)}rows(){const t=this.children.head;return null==t?[]:t.children.map((t=>t))}}function nt(){return`row-${Math.random().toString(36).slice(2,6)}`}et.allowedChildren=[tt],tt.requiredContainer=et,tt.allowedChildren=[Y],Y.requiredContainer=tt,Y.allowedChildren=[J],J.requiredContainer=Y;class rt extends F.A{static register(){p.Ay.register(J),p.Ay.register(Y),p.Ay.register(tt),p.Ay.register(et)}constructor(){super(...arguments),this.listenBalanceCells()}balanceTables(){this.quill.scroll.descendants(et).forEach((t=>{t.balanceCells()}))}deleteColumn(){const[t,,e]=this.getTable();null!=e&&(t.deleteColumn(e.cellOffset()),this.quill.update(p.Ay.sources.USER))}deleteRow(){const[,t]=this.getTable();null!=t&&(t.remove(),this.quill.update(p.Ay.sources.USER))}deleteTable(){const[t]=this.getTable();if(null==t)return;const e=t.offset();t.remove(),this.quill.update(p.Ay.sources.USER),this.quill.setSelection(e,p.Ay.sources.SILENT)}getTable(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.quill.getSelection();if(null==t)return[null,null,null,-1];const[e,n]=this.quill.getLine(t.index);if(null==e||e.statics.blotName!==J.blotName)return[null,null,null,-1];const r=e.parent;return[r.parent.parent,r,e,n]}insertColumn(t){const e=this.quill.getSelection();if(!e)return;const[n,r,i]=this.getTable(e);if(null==i)return;const s=i.cellOffset();n.insertColumn(s+t),this.quill.update(p.Ay.sources.USER);let o=r.rowOffset();0===t&&(o+=1),this.quill.setSelection(e.index+o,e.length,p.Ay.sources.SILENT)}insertColumnLeft(){this.insertColumn(0)}insertColumnRight(){this.insertColumn(1)}insertRow(t){const e=this.quill.getSelection();if(!e)return;const[n,r,i]=this.getTable(e);if(null==i)return;const s=r.rowOffset();n.insertRow(s+t),this.quill.update(p.Ay.sources.USER),t>0?this.quill.setSelection(e,p.Ay.sources.SILENT):this.quill.setSelection(e.index+r.children.length,e.length,p.Ay.sources.SILENT)}insertRowAbove(){this.insertRow(0)}insertRowBelow(){this.insertRow(1)}insertTable(t,e){const n=this.quill.getSelection();if(null==n)return;const r=new Array(t).fill(0).reduce((t=>{const n=new Array(e).fill("\n").join("");return t.insert(n,{table:nt()})}),(new(z())).retain(n.index));this.quill.updateContents(r,p.Ay.sources.USER),this.quill.setSelection(n.index,p.Ay.sources.SILENT),this.balanceTables()}listenBalanceCells(){this.quill.on(p.Ay.events.SCROLL_OPTIMIZE,(t=>{t.some((t=>!!["TD","TR","TBODY","TABLE"].includes(t.target.tagName)&&(this.quill.once(p.Ay.events.TEXT_CHANGE,((t,e,n)=>{n===p.Ay.sources.USER&&this.balanceTables()})),!0)))}))}}var it=rt;const st=(0,n(6078).A)("quill:toolbar");class ot extends F.A{constructor(t,e){if(super(t,e),Array.isArray(this.options.container)){const e=document.createElement("div");e.setAttribute("role","toolbar"),function(t,e){Array.isArray(e[0])||(e=[e]),e.forEach((e=>{const n=document.createElement("span");n.classList.add("ql-formats"),e.forEach((t=>{if("string"==typeof t)lt(n,t);else{const e=Object.keys(t)[0],r=t[e];Array.isArray(r)?function(t,e,n){const r=document.createElement("select");r.classList.add(`ql-${e}`),n.forEach((t=>{const e=document.createElement("option");!1!==t?e.setAttribute("value",String(t)):e.setAttribute("selected","selected"),r.appendChild(e)})),t.appendChild(r)}(n,e,r):lt(n,e,r)}})),t.appendChild(n)}))}(e,this.options.container),t.container?.parentNode?.insertBefore(e,t.container),this.container=e}else"string"==typeof this.options.container?this.container=document.querySelector(this.options.container):this.container=this.options.container;this.container instanceof HTMLElement?(this.container.classList.add("ql-toolbar"),this.controls=[],this.handlers={},this.options.handlers&&Object.keys(this.options.handlers).forEach((t=>{const e=this.options.handlers?.[t];e&&this.addHandler(t,e)})),Array.from(this.container.querySelectorAll("button, select")).forEach((t=>{this.attach(t)})),this.quill.on(p.Ay.events.EDITOR_CHANGE,(()=>{const[t]=this.quill.selection.getRange();this.update(t)}))):st.error("Container required for toolbar",this.options)}addHandler(t,e){this.handlers[t]=e}attach(t){let e=Array.from(t.classList).find((t=>0===t.indexOf("ql-")));if(!e)return;if(e=e.slice(3),"BUTTON"===t.tagName&&t.setAttribute("type","button"),null==this.handlers[e]&&null==this.quill.scroll.query(e))return void st.warn("ignoring attaching to nonexistent format",e,t);const n="SELECT"===t.tagName?"change":"click";t.addEventListener(n,(n=>{let r;if("SELECT"===t.tagName){if(t.selectedIndex<0)return;const e=t.options[t.selectedIndex];r=!e.hasAttribute("selected")&&(e.value||!1)}else r=!t.classList.contains("ql-active")&&(t.value||!t.hasAttribute("value")),n.preventDefault();this.quill.focus();const[i]=this.quill.selection.getRange();if(null!=this.handlers[e])this.handlers[e].call(this,r);else if(this.quill.scroll.query(e).prototype instanceof s.EmbedBlot){if(r=prompt(`Enter ${e}`),!r)return;this.quill.updateContents((new(z())).retain(i.index).delete(i.length).insert({[e]:r}),p.Ay.sources.USER)}else this.quill.format(e,r,p.Ay.sources.USER);this.update(i)})),this.controls.push([e,t])}update(t){const e=null==t?{}:this.quill.getFormat(t);this.controls.forEach((n=>{const[r,i]=n;if("SELECT"===i.tagName){let n=null;if(null==t)n=null;else if(null==e[r])n=i.querySelector("option[selected]");else if(!Array.isArray(e[r])){let t=e[r];"string"==typeof t&&(t=t.replace(/"/g,'\\"')),n=i.querySelector(`option[value="${t}"]`)}null==n?(i.value="",i.selectedIndex=-1):n.selected=!0}else if(null==t)i.classList.remove("ql-active"),i.setAttribute("aria-pressed","false");else if(i.hasAttribute("value")){const t=e[r],n=t===i.getAttribute("value")||null!=t&&t.toString()===i.getAttribute("value")||null==t&&!i.getAttribute("value");i.classList.toggle("ql-active",n),i.setAttribute("aria-pressed",n.toString())}else{const t=null!=e[r];i.classList.toggle("ql-active",t),i.setAttribute("aria-pressed",t.toString())}}))}}function lt(t,e,n){const r=document.createElement("button");r.setAttribute("type","button"),r.classList.add(`ql-${e}`),r.setAttribute("aria-pressed","false"),null!=n?(r.value=n,r.setAttribute("aria-label",`${e}: ${n}`)):r.setAttribute("aria-label",e),t.appendChild(r)}ot.DEFAULTS={},ot.DEFAULTS={container:null,handlers:{clean(){const t=this.quill.getSelection();if(null!=t)if(0===t.length){const t=this.quill.getFormat();Object.keys(t).forEach((t=>{null!=this.quill.scroll.query(t,s.Scope.INLINE)&&this.quill.format(t,!1,p.Ay.sources.USER)}))}else this.quill.removeFormat(t.index,t.length,p.Ay.sources.USER)},direction(t){const{align:e}=this.quill.getFormat();"rtl"===t&&null==e?this.quill.format("align","right",p.Ay.sources.USER):t||"right"!==e||this.quill.format("align",!1,p.Ay.sources.USER),this.quill.format("direction",t,p.Ay.sources.USER)},indent(t){const e=this.quill.getSelection(),n=this.quill.getFormat(e),r=parseInt(n.indent||0,10);if("+1"===t||"-1"===t){let e="+1"===t?1:-1;"rtl"===n.direction&&(e*=-1),this.quill.format("indent",r+e,p.Ay.sources.USER)}},link(t){!0===t&&(t=prompt("Enter link URL:")),this.quill.format("link",t,p.Ay.sources.USER)},list(t){const e=this.quill.getSelection(),n=this.quill.getFormat(e);"check"===t?"checked"===n.list||"unchecked"===n.list?this.quill.format("list",!1,p.Ay.sources.USER):this.quill.format("list","unchecked",p.Ay.sources.USER):this.quill.format("list",t,p.Ay.sources.USER)}}};const at='';var ct={align:{"":'',center:'',right:'',justify:''},background:'',blockquote:'',bold:'',clean:'',code:at,"code-block":at,color:'',direction:{"":'',rtl:''},formula:'',header:{1:'',2:'',3:'',4:'',5:'',6:''},italic:'',image:'',indent:{"+1":'',"-1":''},link:'',list:{bullet:'',check:'',ordered:''},script:{sub:'',super:''},strike:'',table:'',underline:'',video:''};let ut=0;function ht(t,e){t.setAttribute(e,`${!("true"===t.getAttribute(e))}`)}var dt=class{constructor(t){this.select=t,this.container=document.createElement("span"),this.buildPicker(),this.select.style.display="none",this.select.parentNode.insertBefore(this.container,this.select),this.label.addEventListener("mousedown",(()=>{this.togglePicker()})),this.label.addEventListener("keydown",(t=>{switch(t.key){case"Enter":this.togglePicker();break;case"Escape":this.escape(),t.preventDefault()}})),this.select.addEventListener("change",this.update.bind(this))}togglePicker(){this.container.classList.toggle("ql-expanded"),ht(this.label,"aria-expanded"),ht(this.options,"aria-hidden")}buildItem(t){const e=document.createElement("span");e.tabIndex="0",e.setAttribute("role","button"),e.classList.add("ql-picker-item");const n=t.getAttribute("value");return n&&e.setAttribute("data-value",n),t.textContent&&e.setAttribute("data-label",t.textContent),e.addEventListener("click",(()=>{this.selectItem(e,!0)})),e.addEventListener("keydown",(t=>{switch(t.key){case"Enter":this.selectItem(e,!0),t.preventDefault();break;case"Escape":this.escape(),t.preventDefault()}})),e}buildLabel(){const t=document.createElement("span");return t.classList.add("ql-picker-label"),t.innerHTML='',t.tabIndex="0",t.setAttribute("role","button"),t.setAttribute("aria-expanded","false"),this.container.appendChild(t),t}buildOptions(){const t=document.createElement("span");t.classList.add("ql-picker-options"),t.setAttribute("aria-hidden","true"),t.tabIndex="-1",t.id=`ql-picker-options-${ut}`,ut+=1,this.label.setAttribute("aria-controls",t.id),this.options=t,Array.from(this.select.options).forEach((e=>{const n=this.buildItem(e);t.appendChild(n),!0===e.selected&&this.selectItem(n)})),this.container.appendChild(t)}buildPicker(){Array.from(this.select.attributes).forEach((t=>{this.container.setAttribute(t.name,t.value)})),this.container.classList.add("ql-picker"),this.label=this.buildLabel(),this.buildOptions()}escape(){this.close(),setTimeout((()=>this.label.focus()),1)}close(){this.container.classList.remove("ql-expanded"),this.label.setAttribute("aria-expanded","false"),this.options.setAttribute("aria-hidden","true")}selectItem(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const n=this.container.querySelector(".ql-selected");t!==n&&(null!=n&&n.classList.remove("ql-selected"),null!=t&&(t.classList.add("ql-selected"),this.select.selectedIndex=Array.from(t.parentNode.children).indexOf(t),t.hasAttribute("data-value")?this.label.setAttribute("data-value",t.getAttribute("data-value")):this.label.removeAttribute("data-value"),t.hasAttribute("data-label")?this.label.setAttribute("data-label",t.getAttribute("data-label")):this.label.removeAttribute("data-label"),e&&(this.select.dispatchEvent(new Event("change")),this.close())))}update(){let t;if(this.select.selectedIndex>-1){const e=this.container.querySelector(".ql-picker-options").children[this.select.selectedIndex];t=this.select.options[this.select.selectedIndex],this.selectItem(e)}else this.selectItem(null);const e=null!=t&&t!==this.select.querySelector("option[selected]");this.label.classList.toggle("ql-active",e)}},ft=class extends dt{constructor(t,e){super(t),this.label.innerHTML=e,this.container.classList.add("ql-color-picker"),Array.from(this.container.querySelectorAll(".ql-picker-item")).slice(0,7).forEach((t=>{t.classList.add("ql-primary")}))}buildItem(t){const e=super.buildItem(t);return e.style.backgroundColor=t.getAttribute("value")||"",e}selectItem(t,e){super.selectItem(t,e);const n=this.label.querySelector(".ql-color-label"),r=t&&t.getAttribute("data-value")||"";n&&("line"===n.tagName?n.style.stroke=r:n.style.fill=r)}},pt=class extends dt{constructor(t,e){super(t),this.container.classList.add("ql-icon-picker"),Array.from(this.container.querySelectorAll(".ql-picker-item")).forEach((t=>{t.innerHTML=e[t.getAttribute("data-value")||""]})),this.defaultItem=this.container.querySelector(".ql-selected"),this.selectItem(this.defaultItem)}selectItem(t,e){super.selectItem(t,e);const n=t||this.defaultItem;if(null!=n){if(this.label.innerHTML===n.innerHTML)return;this.label.innerHTML=n.innerHTML}}},gt=class{constructor(t,e){this.quill=t,this.boundsContainer=e||document.body,this.root=t.addContainer("ql-tooltip"),this.root.innerHTML=this.constructor.TEMPLATE,(t=>{const{overflowY:e}=getComputedStyle(t,null);return"visible"!==e&&"clip"!==e})(this.quill.root)&&this.quill.root.addEventListener("scroll",(()=>{this.root.style.marginTop=-1*this.quill.root.scrollTop+"px"})),this.hide()}hide(){this.root.classList.add("ql-hidden")}position(t){const e=t.left+t.width/2-this.root.offsetWidth/2,n=t.bottom+this.quill.root.scrollTop;this.root.style.left=`${e}px`,this.root.style.top=`${n}px`,this.root.classList.remove("ql-flip");const r=this.boundsContainer.getBoundingClientRect(),i=this.root.getBoundingClientRect();let s=0;if(i.right>r.right&&(s=r.right-i.right,this.root.style.left=`${e+s}px`),i.leftr.bottom){const e=i.bottom-i.top,r=t.bottom-t.top+e;this.root.style.top=n-r+"px",this.root.classList.add("ql-flip")}return s}show(){this.root.classList.remove("ql-editing"),this.root.classList.remove("ql-hidden")}},mt=n(8347),bt=n(5374),yt=n(9609);const vt=[!1,"center","right","justify"],At=["#000000","#e60000","#ff9900","#ffff00","#008a00","#0066cc","#9933ff","#ffffff","#facccc","#ffebcc","#ffffcc","#cce8cc","#cce0f5","#ebd6ff","#bbbbbb","#f06666","#ffc266","#ffff66","#66b966","#66a3e0","#c285ff","#888888","#a10000","#b26b00","#b2b200","#006100","#0047b2","#6b24b2","#444444","#5c0000","#663d00","#666600","#003700","#002966","#3d1466"],xt=[!1,"serif","monospace"],Nt=["1","2","3",!1],Et=["small",!1,"large","huge"];class wt extends yt.A{constructor(t,e){super(t,e);const n=e=>{document.body.contains(t.root)?(null==this.tooltip||this.tooltip.root.contains(e.target)||document.activeElement===this.tooltip.textbox||this.quill.hasFocus()||this.tooltip.hide(),null!=this.pickers&&this.pickers.forEach((t=>{t.container.contains(e.target)||t.close()}))):document.body.removeEventListener("click",n)};t.emitter.listenDOM("click",document.body,n)}addModule(t){const e=super.addModule(t);return"toolbar"===t&&this.extendToolbar(e),e}buildButtons(t,e){Array.from(t).forEach((t=>{(t.getAttribute("class")||"").split(/\s+/).forEach((n=>{if(n.startsWith("ql-")&&(n=n.slice(3),null!=e[n]))if("direction"===n)t.innerHTML=e[n][""]+e[n].rtl;else if("string"==typeof e[n])t.innerHTML=e[n];else{const r=t.value||"";null!=r&&e[n][r]&&(t.innerHTML=e[n][r])}}))}))}buildPickers(t,e){this.pickers=Array.from(t).map((t=>{if(t.classList.contains("ql-align")&&(null==t.querySelector("option")&&kt(t,vt),"object"==typeof e.align))return new pt(t,e.align);if(t.classList.contains("ql-background")||t.classList.contains("ql-color")){const n=t.classList.contains("ql-background")?"background":"color";return null==t.querySelector("option")&&kt(t,At,"background"===n?"#ffffff":"#000000"),new ft(t,e[n])}return null==t.querySelector("option")&&(t.classList.contains("ql-font")?kt(t,xt):t.classList.contains("ql-header")?kt(t,Nt):t.classList.contains("ql-size")&&kt(t,Et)),new dt(t)})),this.quill.on(bt.A.events.EDITOR_CHANGE,(()=>{this.pickers.forEach((t=>{t.update()}))}))}}wt.DEFAULTS=(0,mt.A)({},yt.A.DEFAULTS,{modules:{toolbar:{handlers:{formula(){this.quill.theme.tooltip.edit("formula")},image(){let t=this.container.querySelector("input.ql-image[type=file]");null==t&&(t=document.createElement("input"),t.setAttribute("type","file"),t.setAttribute("accept",this.quill.uploader.options.mimetypes.join(", ")),t.classList.add("ql-image"),t.addEventListener("change",(()=>{const e=this.quill.getSelection(!0);this.quill.uploader.upload(e,t.files),t.value=""})),this.container.appendChild(t)),t.click()},video(){this.quill.theme.tooltip.edit("video")}}}}});class qt extends gt{constructor(t,e){super(t,e),this.textbox=this.root.querySelector('input[type="text"]'),this.listen()}listen(){this.textbox.addEventListener("keydown",(t=>{"Enter"===t.key?(this.save(),t.preventDefault()):"Escape"===t.key&&(this.cancel(),t.preventDefault())}))}cancel(){this.hide(),this.restoreFocus()}edit(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"link",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(this.root.classList.remove("ql-hidden"),this.root.classList.add("ql-editing"),null==this.textbox)return;null!=e?this.textbox.value=e:t!==this.root.getAttribute("data-mode")&&(this.textbox.value="");const n=this.quill.getBounds(this.quill.selection.savedRange);null!=n&&this.position(n),this.textbox.select(),this.textbox.setAttribute("placeholder",this.textbox.getAttribute(`data-${t}`)||""),this.root.setAttribute("data-mode",t)}restoreFocus(){this.quill.focus({preventScroll:!0})}save(){let{value:t}=this.textbox;switch(this.root.getAttribute("data-mode")){case"link":{const{scrollTop:e}=this.quill.root;this.linkRange?(this.quill.formatText(this.linkRange,"link",t,bt.A.sources.USER),delete this.linkRange):(this.restoreFocus(),this.quill.format("link",t,bt.A.sources.USER)),this.quill.root.scrollTop=e;break}case"video":t=function(t){let e=t.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtube\.com\/watch.*v=([a-zA-Z0-9_-]+)/)||t.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtu\.be\/([a-zA-Z0-9_-]+)/);return e?`${e[1]||"https"}://www.youtube.com/embed/${e[2]}?showinfo=0`:(e=t.match(/^(?:(https?):\/\/)?(?:www\.)?vimeo\.com\/(\d+)/))?`${e[1]||"https"}://player.vimeo.com/video/${e[2]}/`:t}(t);case"formula":{if(!t)break;const e=this.quill.getSelection(!0);if(null!=e){const n=e.index+e.length;this.quill.insertEmbed(n,this.root.getAttribute("data-mode"),t,bt.A.sources.USER),"formula"===this.root.getAttribute("data-mode")&&this.quill.insertText(n+1," ",bt.A.sources.USER),this.quill.setSelection(n+2,bt.A.sources.USER)}break}}this.textbox.value="",this.hide()}}function kt(t,e){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e.forEach((e=>{const r=document.createElement("option");e===n?r.setAttribute("selected","selected"):r.setAttribute("value",String(e)),t.appendChild(r)}))}var _t=n(8298);const Lt=[["bold","italic","link"],[{header:1},{header:2},"blockquote"]];class St extends qt{static TEMPLATE=['','
    ','','',"
    "].join("");constructor(t,e){super(t,e),this.quill.on(bt.A.events.EDITOR_CHANGE,((t,e,n,r)=>{if(t===bt.A.events.SELECTION_CHANGE)if(null!=e&&e.length>0&&r===bt.A.sources.USER){this.show(),this.root.style.left="0px",this.root.style.width="",this.root.style.width=`${this.root.offsetWidth}px`;const t=this.quill.getLines(e.index,e.length);if(1===t.length){const t=this.quill.getBounds(e);null!=t&&this.position(t)}else{const n=t[t.length-1],r=this.quill.getIndex(n),i=Math.min(n.length()-1,e.index+e.length-r),s=this.quill.getBounds(new _t.Q(r,i));null!=s&&this.position(s)}}else document.activeElement!==this.textbox&&this.quill.hasFocus()&&this.hide()}))}listen(){super.listen(),this.root.querySelector(".ql-close").addEventListener("click",(()=>{this.root.classList.remove("ql-editing")})),this.quill.on(bt.A.events.SCROLL_OPTIMIZE,(()=>{setTimeout((()=>{if(this.root.classList.contains("ql-hidden"))return;const t=this.quill.getSelection();if(null!=t){const e=this.quill.getBounds(t);null!=e&&this.position(e)}}),1)}))}cancel(){this.show()}position(t){const e=super.position(t),n=this.root.querySelector(".ql-tooltip-arrow");return n.style.marginLeft="",0!==e&&(n.style.marginLeft=-1*e-n.offsetWidth/2+"px"),e}}class Ot extends wt{constructor(t,e){null!=e.modules.toolbar&&null==e.modules.toolbar.container&&(e.modules.toolbar.container=Lt),super(t,e),this.quill.container.classList.add("ql-bubble")}extendToolbar(t){this.tooltip=new St(this.quill,this.options.bounds),null!=t.container&&(this.tooltip.root.appendChild(t.container),this.buildButtons(t.container.querySelectorAll("button"),ct),this.buildPickers(t.container.querySelectorAll("select"),ct))}}Ot.DEFAULTS=(0,mt.A)({},wt.DEFAULTS,{modules:{toolbar:{handlers:{link(t){t?this.quill.theme.tooltip.edit():this.quill.format("link",!1,p.Ay.sources.USER)}}}}});const Tt=[[{header:["1","2","3",!1]}],["bold","italic","underline","link"],[{list:"ordered"},{list:"bullet"}],["clean"]];class jt extends qt{static TEMPLATE=['','','',''].join("");preview=this.root.querySelector("a.ql-preview");listen(){super.listen(),this.root.querySelector("a.ql-action").addEventListener("click",(t=>{this.root.classList.contains("ql-editing")?this.save():this.edit("link",this.preview.textContent),t.preventDefault()})),this.root.querySelector("a.ql-remove").addEventListener("click",(t=>{if(null!=this.linkRange){const t=this.linkRange;this.restoreFocus(),this.quill.formatText(t,"link",!1,bt.A.sources.USER),delete this.linkRange}t.preventDefault(),this.hide()})),this.quill.on(bt.A.events.SELECTION_CHANGE,((t,e,n)=>{if(null!=t){if(0===t.length&&n===bt.A.sources.USER){const[e,n]=this.quill.scroll.descendant(w,t.index);if(null!=e){this.linkRange=new _t.Q(t.index-n,e.length());const r=w.formats(e.domNode);this.preview.textContent=r,this.preview.setAttribute("href",r),this.show();const i=this.quill.getBounds(this.linkRange);return void(null!=i&&this.position(i))}}else delete this.linkRange;this.hide()}}))}show(){super.show(),this.root.removeAttribute("data-mode")}}class Ct extends wt{constructor(t,e){null!=e.modules.toolbar&&null==e.modules.toolbar.container&&(e.modules.toolbar.container=Tt),super(t,e),this.quill.container.classList.add("ql-snow")}extendToolbar(t){null!=t.container&&(t.container.classList.add("ql-snow"),this.buildButtons(t.container.querySelectorAll("button"),ct),this.buildPickers(t.container.querySelectorAll("select"),ct),this.tooltip=new jt(this.quill,this.options.bounds),t.container.querySelector(".ql-link")&&this.quill.keyboard.addBinding({key:"k",shortKey:!0},((e,n)=>{t.handlers.link.call(t,!n.format.link)})))}}Ct.DEFAULTS=(0,mt.A)({},wt.DEFAULTS,{modules:{toolbar:{handlers:{link(t){if(t){const t=this.quill.getSelection();if(null==t||0===t.length)return;let e=this.quill.getText(t);/^\S+@\S+\.\S+$/.test(e)&&0!==e.indexOf("mailto:")&&(e=`mailto:${e}`);const{tooltip:n}=this.quill.theme;n.edit("link",e)}else this.quill.format("link",!1,p.Ay.sources.USER)}}}}});var Rt=Ct;t.default.register({"attributors/attribute/direction":i.Mc,"attributors/class/align":e.qh,"attributors/class/background":b.l,"attributors/class/color":y.g3,"attributors/class/direction":i.sY,"attributors/class/font":v.q,"attributors/class/size":A.U,"attributors/style/align":e.Hu,"attributors/style/background":b.s,"attributors/style/color":y.JM,"attributors/style/direction":i.VL,"attributors/style/font":v.z,"attributors/style/size":A.r},!0),t.default.register({"formats/align":e.qh,"formats/direction":i.sY,"formats/indent":l,"formats/background":b.s,"formats/color":y.JM,"formats/font":v.q,"formats/size":A.U,"formats/blockquote":u,"formats/code-block":D.Ay,"formats/header":d,"formats/list":m,"formats/bold":E,"formats/code":D.Cy,"formats/italic":class extends E{static blotName="italic";static tagName=["EM","I"]},"formats/link":w,"formats/script":_,"formats/strike":class extends E{static blotName="strike";static tagName=["S","STRIKE"]},"formats/underline":S,"formats/formula":j,"formats/image":I,"formats/video":U,"modules/syntax":Q,"modules/table":it,"modules/toolbar":ot,"themes/bubble":Ot,"themes/snow":Rt,"ui/icons":ct,"ui/picker":dt,"ui/icon-picker":pt,"ui/color-picker":ft,"ui/tooltip":gt},!0);var It=t.default}(),r.default}()})); +//# sourceMappingURL=quill.js.map \ No newline at end of file diff --git a/hybrid/html/js/uni.webview.1.5.5.js b/hybrid/html/js/uni.webview.1.5.5.js new file mode 100644 index 0000000..2c9b980 --- /dev/null +++ b/hybrid/html/js/uni.webview.1.5.5.js @@ -0,0 +1 @@ +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function i(e,i){return n.call(e,i)}var t=[];function o(){return window.__dcloud_weex_postMessage||window.__dcloud_weex_}function a(){return window.__uniapp_x_postMessage||window.__uniapp_x_}var r=function(e,n){var i={options:{timestamp:+new Date},name:e,arg:n};if(a()){if("postMessage"===e){var r={data:n};return window.__uniapp_x_postMessage?window.__uniapp_x_postMessage(r):window.__uniapp_x_.postMessage(JSON.stringify(r))}var d={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__uniapp_x_postMessage?window.__uniapp_x_postMessageToService(d):window.__uniapp_x_.postMessageToService(JSON.stringify(d))}else if(o()){if("postMessage"===e){var s={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(s):window.__dcloud_weex_.postMessage(JSON.stringify(s))}var w={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(w):window.__dcloud_weex_.postMessageToService(JSON.stringify(w))}else{if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:i,pageId:""},"*");if(0===t.length){var u=plus.webview.currentWebview();if(!u)throw new Error("plus.webview.currentWebview() is undefined");var g=u.parent(),v="";v=g?g.id:u.id,t.push(v)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}},"__uniapp__service");else{var c=JSON.stringify(i);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(c,",").concat(JSON.stringify(t),");"))}}},d={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;r("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("redirectTo",{url:encodeURI(n)})},getEnv:function(e){a()?e({uvue:!0}):o()?e({nvue:!0}):window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};r("postMessage",e.data||{})}},s=/uni-app/i.test(navigator.userAgent),w=/Html5Plus/i.test(navigator.userAgent),u=/complete|loaded|interactive/;var g=window.my&&navigator.userAgent.indexOf(["t","n","e","i","l","C","y","a","p","i","l","A"].reverse().join(""))>-1;var v=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var _=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var m=window.qa&&/quickapp/i.test(navigator.userAgent);var f=window.ks&&window.ks.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var l=window.tt&&window.tt.miniProgram&&/Lark|Feishu/i.test(navigator.userAgent);var E=window.jd&&window.jd.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var x=window.xhs&&window.xhs.miniProgram&&/xhsminiapp/i.test(navigator.userAgent);for(var S,h=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},y=[function(e){if(s||w)return window.__uniapp_x_postMessage||window.__uniapp_x_||window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&u.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),d},function(e){if(_)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(g){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(v)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(p)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(m){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(f)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.ks.miniProgram},function(e){if(l)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(E)return window.JDJSBridgeReady&&window.JDJSBridgeReady.invoke?setTimeout(e,0):document.addEventListener("JDJSBridgeReady",e),window.jd.miniProgram},function(e){if(x)return window.xhs.miniProgram},function(e){return document.addEventListener("DOMContentLoaded",e),d}],M=0;M + + + + + 本地网页 + + + + +
    + +
    + + + + + + \ No newline at end of file diff --git a/hybrid/html/preview.html b/hybrid/html/preview.html new file mode 100644 index 0000000..792f9cc --- /dev/null +++ b/hybrid/html/preview.html @@ -0,0 +1,267 @@ + + + + + + + + + + +
    + +
    + + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..68275be --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
    + + + diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..9fe1cf9 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,25 @@ +module.exports = { + "is-custom-runtime": false, + "compile": true, + watchPathIgnorePatterns: ['/node_modules/', '/dist/', '/.git/'], + moduleFileExtensions: ['js'], + rootDir: __dirname, + testMatch: ["/pages/**/*test.[jt]s?(x)","/pages/*test.[jt]s?(x)"], + testPathIgnorePatterns: [ + '/node_modules/', + '/testbao/', + '/tmicon/', + '/tmicon/', + '/myUtools/', + '/myUtools/', + '/uni_modules/', + '/unpackage/', + '/static/', + '/hybrid/', + '/jtest/', + '/docsBuildCli/', + '/docweb/', + '/logo资源/', + '/tmy-ui/', + ] +} diff --git a/jtest/screenshot/button.png b/jtest/screenshot/button.png new file mode 100644 index 0000000..83ad614 Binary files /dev/null and b/jtest/screenshot/button.png differ diff --git a/jtest/screenshot/global.png b/jtest/screenshot/global.png new file mode 100644 index 0000000..2898ecf Binary files /dev/null and b/jtest/screenshot/global.png differ diff --git a/jtest/screenshot/index.png b/jtest/screenshot/index.png new file mode 100644 index 0000000..5b1d19e Binary files /dev/null and b/jtest/screenshot/index.png differ diff --git a/libs/appRunLaunch.uts b/libs/appRunLaunch.uts new file mode 100644 index 0000000..3f6a8ea --- /dev/null +++ b/libs/appRunLaunch.uts @@ -0,0 +1,66 @@ +// #ifndef MP +import { showRunLogo, hideRunLogo ,XRUN_START_LOGO_OPTS} from "@/uni_modules/x-runstart-logo" +import { showModal,X_MODAL_TYPE } from "@/uni_modules/x-modal-s" + + +// #endif + + +// #ifndef MP +function setAgree() { + uni.setStorageSync('xTmui4.0Xieyi', 'true') +} +function getAgree() : boolean { + let tonyixie = uni.getStorageSync('xTmui4.0Xieyi') + + return tonyixie == null || tonyixie == '' +} +export function showAgree() { + const needAgree = getAgree() + if (!needAgree) return; + showRunLogo({ + bgColor: '#006deb', + logo: 'logo.png', + width: 60, + height: 60, + logoPadding: 20, + round: 14, + logoBgColor: '#ffffff', + rightText: 'tmui4.0x / 2025 by tmzdy', + fontSize: 11, + fontColor: '#ffffff' + } as XRUN_START_LOGO_OPTS) + showModal({ + title: "隐私政策", + content: "
    我同意《TMUIX4.0使用协议》我确认我使用的是正版tmuix4.0组件及附带插件软件,并承担相应法律风险,同意请点我同意,不同意请点不同意终止访问.
    ", + cancelText: '不同意', + confirmText: "我同意", + height:120, + confirmIcon:"EB80", + cancelIcon:"ECA0", + clickMaskClose: false, + clickLink(url:string){ + console.log(url) + + uni.showModal({ + title:"阅读协议", + content:`这个是协议,请阅读`, + showCancel:false, + confirmText:"已阅读" + }) + }, + confirm() { + setAgree() + setTimeout(function () { + hideRunLogo() + }, 1000); + }, + cancel() { + // #ifdef APP + uni.exit() + // #endif + } + } as X_MODAL_TYPE) + +} +// #endif \ No newline at end of file diff --git a/libs/demoStore.uts b/libs/demoStore.uts new file mode 100644 index 0000000..926159c --- /dev/null +++ b/libs/demoStore.uts @@ -0,0 +1,6 @@ +type demoStoreType = { + homeMenuOpened:boolean +} +export const demoStore = reactive({ + homeMenuOpened:false +} as demoStoreType) diff --git a/main.uts b/main.uts new file mode 100644 index 0000000..9c644f6 --- /dev/null +++ b/main.uts @@ -0,0 +1,57 @@ +import App from './App' +import {xui} from "@/uni_modules/tmx-ui/index.uts" +import {Tmui4xOptions} from "@/uni_modules/tmx-ui/interface.uts" +import { I18nOptions } from "@/uni_modules/x-vuei18n-s/interface.uts" + +import en from "@/uni_modules/tmx-ui/localLanuage/en.json" +import zhHans from "@/uni_modules/tmx-ui/localLanuage/zh-Hans.json" +import zhHant from "@/uni_modules/tmx-ui/localLanuage/zh-Hant.json" +import ko from "@/uni_modules/tmx-ui/localLanuage/ko.json" +import ja from "@/uni_modules/tmx-ui/localLanuage/ja.json" + +/** + * 组件语言包(与自定义语言包合并,共用一个实例) + */ +const messages : UTSJSONObject = { + "en":{ + ...en, + "hellow":"Hi~" + }, + "zh-Hans":{ + ...zhHans, + "hellow":"哈喽" + }, + "zh-Hant":zhHant, + "ko":ko, + "ja":ja +} +import { createSSRApp } from 'vue' + +/** + * 医院救援平台全局配置 + * - designSize 375:与《移动端 UI 设计稿 v2》基准画布一致 + * - color #2563EB:医疗蓝主色 + * - dark light:医疗场景锁定亮色,避免跟随系统暗黑造成还原偏差 + */ +const hrConfig : UTSJSONObject = { + designSize: 375, + unit: 'px', + color: '#2563EB', + dark: 'light', + inputRadius: '11', + buttonRadius: '12', + cardRound: '13', + tagRadius: '6', + placeholderStyle: 'color:#9CA3AF' +} + +export function createApp() { + const app = createSSRApp(App) + app.use(xui, { + i18nOptions: { locale: "zh-Hans", messages } as I18nOptions, + config: hrConfig + } as Tmui4xOptions) + return { + app + } +} diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..238e21f --- /dev/null +++ b/manifest.json @@ -0,0 +1,131 @@ +{ + "name": "医院救援管理平台", + "appid": "__UNI__B73859A", + "description": "医院智慧后勤管理平台 · 移动端(救援人员端 / 仓管人员端)", + "versionName": "2.0.0", + "versionCode": "200", + "uni-app-x": {}, + /* 快应用特有相关 */ + "quickapp": {}, + /* 小程序特有相关 */ + "mp-weixin": { + "appid": "wxb30698c4b9f69030", + "darkmode": true, + "defaultAppTheme": "dark", + "permission": { + "scope.camera": { + "desc": "用于拍照及扫码识别" + } + }, + "setting": { + "urlCheck": true, + "es6": true, + "minified": true + }, + "usingComponents": true + }, + "mp-alipay": { + "usingComponents": true + }, + "mp-baidu": { + "usingComponents": true + }, + "mp-toutiao": { + "usingComponents": true + }, + "uniStatistics": { + "enable": false + }, + "vueVersion": "3", + "app": { + "defaultAppTheme": "light", + "distribute": { + "modules": { + "uni-createInnerAudioContext": {} + }, + "icons": { + "android": { + "hdpi": "unpackage/res/icons/72x72.png", + "xhdpi": "unpackage/res/icons/96x96.png", + "xxhdpi": "unpackage/res/icons/144x144.png", + "xxxhdpi": "unpackage/res/icons/192x192.png" + }, + "ios": { + "appstore": "unpackage/res/icons/1024x1024.png" + } + } + } + }, + "web": { + "title": "医院救援管理平台", + "rpxCalcMaxDeviceWidth": 480, + "rpxCalcBaseDeviceWidth": 480, + "rpxCalcIncludeWidth": 750, + "router": { + "mode": "hash", + "base": "./" + }, + "devServer": { + "port": 3721 + } + }, + "app-android": { + "distribute": { + "modules": { + "uni-createInnerAudioContext": {} + }, + "icons": { + "hdpi": "", + "xhdpi": "", + "xxhdpi": "", + "xxxhdpi": "" + }, + "splashScreens": { + "default": {} + } + } + }, + "app-ios": { + "distribute": { + "modules": { + "uni-createInnerAudioContext": {} + }, + "icons": { + "appstore": "" + }, + "splashScreens": {} + } + }, + "app-harmony": { + "distribute": { + "bundleName": "UNI.APP.B73859A", + "icons": { + "foreground": "logo资源/logo/logo-rect.png", + "background": "logo资源/logo/logo-rect.png" + }, + "splashScreens": { + "startWindowIcon": "logo资源/logo/logo-rect.png" + }, + "signingConfigs": { + "default": { + "certpath": "/Volumes/app/myProjects/tmui4xPravite/logo资源/鸿蒙证书/鸿蒙调试证书/调试证书.cer", + "keyAlias": "tmui4xTestHaHa", + "keyPassword": "0000001AAE6DEADCC1BD7D1544384BE5806C3858AACC25643D9A0ADCE77E7FE5D28DA4764A4EBDE65CD3", + "profile": "/Volumes/app/myProjects/tmui4xPravite/logo资源/鸿蒙证书/鸿蒙调试证书/调试证书描述Debug.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "/Volumes/app/myProjects/tmui4xPravite/logo资源/鸿蒙证书/鸿蒙调试证书/调试keystore.p12", + "storePassword": "0000001AD3619DBB1D23483C207D64709AA30A897411EBC5C5C63FA88A89F2B1053DC049F051BAB1CD8A" + }, + "release": { + "certpath": "/Volumes/app/myProjects/tmui4xPravite/logo资源/鸿蒙证书/tmui4xDebug.cer", + "keyAlias": "tmui4xDebug", + "keyPassword": "0000001C407505F426690725620F8B5F257FA36D43963607BF4DE48A36962C503A468B14FB553ADA962A5EBB", + "profile": "/Volumes/app/myProjects/tmui4xPravite/logo资源/鸿蒙证书/tmui4xDebugRelease.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "/Volumes/app/myProjects/tmui4xPravite/logo资源/鸿蒙证书/tmui4xKeyStore.p12", + "storePassword": "0000001C388F5AEF60B4A6713552A68C80FEFE801042A072E40FEF6B23EB74D31772502E96E5DBE47C63E36D" + } + } + } + } +} \ No newline at end of file diff --git a/mock/index.uts b/mock/index.uts new file mode 100644 index 0000000..4426aa0 --- /dev/null +++ b/mock/index.uts @@ -0,0 +1,549 @@ +/** + * 医院救援管理平台 · 移动端 Mock 数据 + * ------------------------------------------------------------ + * 所有页面数据均从本文件读取,后续对接接口时只需替换本文件的取数实现, + * 页面层无需改动(保持低耦合)。 + */ +import { + HrUser, HrTodoTask, HrActivity, HrToolBox, + HrCatalog, HrGroup, HrSubject, HrMaterial, + HrExamRecord, HrCert, HrExamPlan, HrQuestion, HrOption, HrPracticeMeta, + HrInjuryMark, HrVital, HrTimelineNode, HrVictim, + HrEventMember, HrEventItem, HrEventDetail, + HrScanFeedback, HrScanRecord, HrStockItem, HrGoods, HrDevice, HrDeviceCheck, + HrMsg, HrMsgGroup, HrContact, HrContactGroup, HrOfflineTask, + HrSettingSwitch, HrSettingRow, HrDesignSection, HrSwatch, HrTokenRow +} from './types.uts' + +/* ============================ 用户 ============================ */ +export const rescuerUser : HrUser = { + name: '张明远', avatar: '张', title: '主治医师', dept: '急诊科', jobNo: '1247', + role: 'rescuer', roleLabel: '救援人员 · 急救中心', + tags: ['ACLS 认证', 'BLS 认证', '创伤急救', '培训等级 B'], + hours: 42.5, courseCount: 12, certCount: 3 +} as HrUser + +export const keeperUser : HrUser = { + name: '陈志强', avatar: '陈', title: '物资管理员', dept: '后勤保障科', jobNo: '2083', + role: 'keeper', roleLabel: '仓管人员 · 后勤保障科', + tags: ['仓储管理', '设备维保', '危化品资质', '培训等级 A'], + hours: 26.0, courseCount: 8, certCount: 2 +} as HrUser + +/* ============================ 学员首页 ============================ */ +export const todoTasks : HrTodoTask[] = [ + { icon: '⚑', iconTheme: 'amb', title: '成人 CPR 课题 · 还剩 2 份资料', sub: '09-30 截止 · 已学 68%', action: '继续 ›' } as HrTodoTask, + { icon: '✓', iconTheme: 'red', title: '年度急救复训 · 报名确认', sub: '09-30 截止 · 未开始', action: '去完成 ›' } as HrTodoTask +] + +export const activities : HrActivity[] = [ + { icon: '▦', iconTheme: 'pri', title: '完成「创伤评估」资料学习', sub: '今天 09:20 · 学习 38 分钟' } as HrActivity, + { icon: '✗', iconTheme: 'red', title: '错题 +2(已复习 1)', sub: '昨天 21:12 · 心肺复苏' } as HrActivity, + { icon: '▤', iconTheme: 'grn', title: '获得「AED 操作」证书', sub: '2 天前 · 有效期至 2028-09' } as HrActivity +] + +export const toolBox : HrToolBox[] = [ + { icon: 'book-2-line', name: '课程库', iconBg: '#EFF6FF', iconColor: '#2563EB' } as HrToolBox, + { icon: 'file-edit-line', name: '我的考试', iconBg: '#FEF3C7', iconColor: '#B45309' } as HrToolBox, + { icon: 'award-line', name: '我的证书', iconBg: '#ECFDF5', iconColor: '#059669' } as HrToolBox, + { icon: 'file-warning-line', name: '错题本', iconBg: '#FEF2F2', iconColor: '#DC2626' } as HrToolBox +] + +/* ============================ 课程库 ============================ */ +export const catalogList : HrCatalog[] = [ + { id: 'c1', name: '急救基础', count: 11, icon: '+', iconBg: '#FEF2F2', iconColor: '#DC2626' } as HrCatalog, + { id: 'c2', name: '创伤急救', count: 9, icon: '⚡', iconBg: '#FEF3C7', iconColor: '#B45309' } as HrCatalog, + { id: 'c3', name: 'ACLS / BLS', count: 8, icon: '✓', iconBg: '#ECFDF5', iconColor: '#059669' } as HrCatalog, + { id: 'c4', name: '检伤分类', count: 6, icon: '♡', iconBg: '#EFF6FF', iconColor: '#2563EB' } as HrCatalog, + { id: 'c5', name: '设备操作', count: 5, icon: '⚙', iconBg: '#F5F3FF', iconColor: '#7C3AED' } as HrCatalog, + { id: 'c6', name: '心理干预', count: 4, icon: '◈', iconBg: '#FFFBEB', iconColor: '#92400E' } as HrCatalog, + { id: 'c7', name: '中毒急救', count: 3, icon: '☣', iconBg: '#FEF2F2', iconColor: '#B91C1C' } as HrCatalog, + { id: 'c8', name: '应急指挥', count: 3, icon: '⚠', iconBg: '#ECFEFF', iconColor: '#0E7490' } as HrCatalog +] + +/** 每个一级分类下的二级分组(三级课题为唯一可点项) */ +export const courseGroups : HrGroup[] = [ + { + name: '心肺复苏', count: 4, + items: [ + { no: '01', name: '成人 CPR(高级生命支持)', meta: '资料 6 份 · 题库 50 · 必修' } as HrSubject, + { no: '02', name: '儿童 CPR', meta: '资料 4 份 · 题库 32 · 必修' } as HrSubject, + { no: '03', name: '婴儿 CPR', meta: '资料 4 份 · 题库 28 · 必修' } as HrSubject, + { no: '04', name: '溺水者心肺复苏', meta: '资料 3 份 · 题库 18 · 选修' } as HrSubject + ] + } as HrGroup, + { + name: 'AED 操作', count: 3, + items: [ + { no: '01', name: 'AED 设备认知与自检', meta: '资料 3 份 · 题库 20 · 必修' } as HrSubject, + { no: '02', name: 'AED 操作流程与除颤时机', meta: '资料 4 份 · 题库 26 · 必修' } as HrSubject, + { no: '03', name: '特殊场景 AED(潮湿 / 儿童 / 起搏器)', meta: '资料 2 份 · 题库 15 · 选修' } as HrSubject + ] + } as HrGroup, + { + name: '气道管理', count: 4, + items: [ + { no: '01', name: '气道开放与评估', meta: '资料 3 份 · 题库 22 · 必修' } as HrSubject, + { no: '02', name: '球囊面罩通气', meta: '资料 3 份 · 题库 18 · 必修' } as HrSubject, + { no: '03', name: '气管插管术', meta: '资料 5 份 · 题库 30 · 认证' } as HrSubject, + { no: '04', name: '喉罩与声门上气道', meta: '资料 2 份 · 题库 16 · 选修' } as HrSubject + ] + } as HrGroup +] + +/** 课题详情对应的资料列表 */ +export const subjectMaterials : HrMaterial[] = [ + { id: 'm1', kind: 'video', badge: '视频', badgeColor: '#7C3AED', icon: '▶', title: '高质量胸外按压操作示范', meta: '视频 · 时长 08:24 · 09-20 更新', summary: '由急诊科教学组录制,演示成人胸外按压的手位、深度、频率与胸廓回弹要点,并对比 3 处常见错误动作。', from: '成人 CPR(高级生命支持) · 急救基础 / 心肺复苏', progress: 62 } as HrMaterial, + { id: 'm2', kind: 'doc', badge: 'PDF', badgeColor: '#DC2626', icon: 'PDF', title: '成人 CPR 操作流程(2025 版)', meta: '文档 · PDF · 2.4 MB · 12 页', summary: '依据《2025 心肺复苏与心血管急救指南》整理的操作流程速查手册,含成人基础生命支持流程图、除颤时机判定表与 3 个常见错误对照。', from: '成人 CPR(高级生命支持) · 急救基础 / 心肺复苏', progress: 0 } as HrMaterial, + { id: 'm3', kind: 'doc', badge: 'DOC', badgeColor: '#2563EB', icon: 'DOC', title: '高质量胸外按压要点', meta: '文档 · Word · 860 KB · 6 页', summary: '按压深度 5~6cm、频率 100~120 次/分,每次按压后必须保证胸廓完全回弹,中断控制在 10 秒以内。', from: '成人 CPR(高级生命支持) · 急救基础 / 心肺复苏', progress: 100 } as HrMaterial, + { id: 'm4', kind: 'doc', badge: 'PPT', badgeColor: '#D97706', icon: 'PPT', title: '心肺复苏教学课件', meta: '文档 · PPT · 5.6 MB · 38 页', summary: '急救基础课程配套课件,覆盖 BLS 全流程、团队分工与考核要点。', from: '成人 CPR(高级生命支持) · 急救基础 / 心肺复苏', progress: 0 } as HrMaterial, + { id: 'm5', kind: 'doc', badge: 'XLS', badgeColor: '#059669', icon: 'XLS', title: 'CPR 考核评分表', meta: '文档 · Excel · 124 KB · 2 个工作表', summary: '实操考核使用评分表,包含操作步骤分值、扣分项与总评标准。', from: '成人 CPR(高级生命支持) · 急救基础 / 心肺复苏', progress: 0 } as HrMaterial, + { id: 'm6', kind: 'video', badge: '视频', badgeColor: '#7C3AED', icon: '▶', title: '双人配合通气节律演示', meta: '视频 · 时长 06:12 · 09-12 更新', summary: '双人配合心肺复苏中通气节律与按压衔接的演示视频。', from: '成人 CPR(高级生命支持) · 急救基础 / 心肺复苏', progress: 0 } as HrMaterial +] + +/* ============================ 练习 / 考试 / 证书 ============================ */ +export const practiceMeta : HrPracticeMeta = { + subject: '成人 CPR(高级生命支持)', + total: 50, + minutes: 30, + goal: '80%', + lastTime: '09-21 21:08', + lastDone: 18, + lastRate: 72 +} as HrPracticeMeta + +export const quizQuestions : HrQuestion[] = [ + { + id: 'q1', stem: '成人心肺复苏时,胸外按压的深度应达到多少?', answer: 1, + options: [ + { key: 'A', text: '3 ~ 4 cm' } as HrOption, + { key: 'B', text: '5 ~ 6 cm' } as HrOption, + { key: 'C', text: '6 ~ 8 cm' } as HrOption, + { key: 'D', text: '按压至胸廓完全塌陷即可' } as HrOption + ], + analysis: '成人胸外按压深度为 5~6 cm,过浅无法产生有效心排血量,过深易造成肋骨骨折等损伤。', + from: '成人 CPR' + } as HrQuestion, + { + id: 'q2', stem: '成人胸外按压的频率应保持在每分钟多少次?', answer: 1, + options: [ + { key: 'A', text: '60 ~ 80 次' } as HrOption, + { key: 'B', text: '100 ~ 120 次' } as HrOption, + { key: 'C', text: '120 ~ 140 次' } as HrOption, + { key: 'D', text: '越快越好' } as HrOption + ], + analysis: '指南推荐成人胸外按压频率为 100~120 次/分,过快会降低按压深度与回弹质量。', + from: '成人 CPR' + } as HrQuestion, + { + id: 'q3', stem: '球囊面罩通气时,成人推荐的通气频率是?', answer: 0, + options: [ + { key: 'A', text: '每 6 秒 1 次(10 次/分)' } as HrOption, + { key: 'B', text: '每 3 秒 1 次(20 次/分)' } as HrOption, + { key: 'C', text: '每 10 秒 1 次(6 次/分)' } as HrOption, + { key: 'D', text: '每 6 秒 1 次(6 次/分)' } as HrOption + ], + analysis: '建立高级气道后,成人通气频率为每 6 秒 1 次,即 10 次/分,且不再与按压交替中断。', + from: '气道管理' + } as HrQuestion, + { + id: 'q4', stem: '发现有人倒地无反应、无呼吸,首先应当?', answer: 2, + options: [ + { key: 'A', text: '立即开始胸外按压' } as HrOption, + { key: 'B', text: '先寻找 AED' } as HrOption, + { key: 'C', text: '判断环境安全并呼救、启动应急系统' } as HrOption, + { key: 'D', text: '掐人中并等待家属到来' } as HrOption + ], + analysis: '施救前必须先确认现场环境安全,随后判断反应与呼吸,呼救并启动应急反应系统,再开始 CPR。', + from: '成人 CPR' + } as HrQuestion, + { + id: 'q5', stem: 'AED 到达后,正确做法是?', answer: 1, + options: [ + { key: 'A', text: '先停止按压擦干胸部再贴电极片' } as HrOption, + { key: 'B', text: '尽量不中断按压,开机贴片后按提示操作' } as HrOption, + { key: 'C', text: '等专业医护到场再使用' } as HrOption, + { key: 'D', text: '除颤后不需要继续按压' } as HrOption + ], + analysis: 'AED 到达应尽快使用,尽量缩短按压中断;电击后立即恢复胸外按压。', + from: 'AED 操作' + } as HrQuestion +] + +export const examPlans : HrExamPlan[] = [ + { name: 'BLS 基础生命支持 · 年度复训', priority: 0, countdown: '距开考 02 天 04 小时 12 分', time: '2026-09-24 14:00', place: '临床技能中心 3F' } as HrExamPlan +] + +export const examRecords : HrExamRecord[] = [ + { name: '心肺复苏理论测验', date: '09-18', score: 92, passed: true } as HrExamRecord, + { name: 'AED 操作规范考核', date: '08-30', score: 88, passed: true } as HrExamRecord, + { name: '创伤急救理论测验', date: '08-12', score: 71, passed: false } as HrExamRecord +] + +export const certList : HrCert[] = [ + { name: 'AED 操作证书', gotAt: '2025-09', expireAt: '2028-09', status: '有效', statusTheme: 'grn' } as HrCert, + { name: '成人心肺复苏(CPR)证书', gotAt: '2025-06', expireAt: '2028-06', status: '有效', statusTheme: 'grn' } as HrCert, + { name: 'BLS 基础生命支持证书', gotAt: '2024-10', expireAt: '2026-10-15', status: '即将到期', statusTheme: 'amb' } as HrCert +] + +/** 错题本 / 学习中心共用 */ +export const wrongQuestions : HrQuestion[] = [ + { + id: 'w1', stem: '成人心肺复苏时,胸外按压的深度应达到多少?', answer: 1, + options: [ { key: 'A', text: '3 ~ 4 cm' } as HrOption, { key: 'B', text: '5 ~ 6 cm' } as HrOption ], + analysis: '成人胸外按压深度为 5~6 cm。', from: '成人 CPR' + } as HrQuestion, + { + id: 'w2', stem: '成人胸外按压的频率应保持在每分钟多少次?', answer: 1, + options: [ { key: 'A', text: '60 ~ 80 次' } as HrOption, { key: 'B', text: '100 ~ 120 次' } as HrOption ], + analysis: '推荐频率为 100~120 次/分。', from: '成人 CPR' + } as HrQuestion, + { + id: 'w3', stem: '球囊面罩通气时,成人推荐的通气频率是?', answer: 0, + options: [ { key: 'A', text: '每 6 秒 1 次(10 次/分)' } as HrOption, { key: 'D', text: '每 6 秒 1 次' } as HrOption ], + analysis: '建立高级气道后每 6 秒 1 次,即 10 次/分。', from: '气道管理' + } as HrQuestion +] + +/* ============================ 伤员 ============================ */ +export const victimList : HrVictim[] = [ + { id: 'v1', name: '王建国', gender: '男', age: 52, code: 'TRIAGE-20260922-0001', level: 1, injury: '开放性颅脑损伤、左股骨骨折 · 意识模糊,GCS 9 分', status: '已转运 · 协和医院急诊', statusTheme: 'pri', createdAt: '14:21 建档' } as HrVictim, + { id: 'v2', name: '李华', gender: '男', age: 35, code: 'TRIAGE-20260922-0003', level: 2, injury: '头部开放性外伤、右前臂疑似骨折、左小腿挤压伤', status: '转运中 · 平车 → 创伤外科', statusTheme: 'amb', createdAt: '14:23 建档' } as HrVictim, + { id: 'v3', name: '陈小梅', gender: '女', age: 28, code: 'TRIAGE-20260922-0006', level: 3, injury: '右膝软组织挫伤 · 可自行行走,生命体征平稳', status: '待转运 · 轻症观察区', statusTheme: 'grn', createdAt: '14:31 建档' } as HrVictim, + { id: 'v4', name: '赵国强', gender: '男', age: 41, code: 'TRIAGE-20260922-0008', level: 2, injury: '胸部挤压伤、多发肋骨骨折(4-7 肋) · 呼吸 26 次/分', status: '未转运 · 现场待命', statusTheme: 'gray', createdAt: '14:38 建档' } as HrVictim, + { id: 'v5', name: '吴长胜', gender: '男', age: 61, code: 'TRIAGE-20260922-0012', level: 4, injury: '重度颅脑损伤 · 无呼吸无脉搏,经确认已无生命体征', status: '已确认 · 待移交', statusTheme: 'gray', createdAt: '14:45 建档' } as HrVictim +] + +/** 检伤分级(一行四级) */ +export const gradeList : string[] = ['轻伤', '重伤', '危重', '死亡'] + +/** 2D 人体图鉴标记 */ +export const injuryMarks : HrInjuryMark[] = [ + { no: '1', title: '头部 · 开放性外伤', sub: '顶枕部裂伤约 4cm · 出血中', theme: 'red' } as HrInjuryMark, + { no: '2', title: '右前臂 · 疑似骨折', sub: '肿胀畸形 · 触痛明显', theme: 'amb' } as HrInjuryMark, + { no: '3', title: '左小腿 · 挤压伤', sub: '皮肤瘀斑 · 局部压痛', theme: 'amb' } as HrInjuryMark +] + +/** 生命体征 */ +export const vitalSigns : HrVital[] = [ + { value: '37.8', unit: 'T ℃', abnormal: false } as HrVital, + { value: '102', unit: 'P 次/分', abnormal: true } as HrVital, + { value: '22', unit: 'R 次/分', abnormal: false } as HrVital, + { value: '95/60', unit: 'BP mmHg', abnormal: true } as HrVital, + { value: '88', unit: 'SpO₂ %', abnormal: true } as HrVital +] + +/** 检伤评估下拉 */ +export const triagePickList : string[] = ['行走能力', '呼吸', '循环', '意识 AVPU'] +export const triagePickValues : string[] = ['不可走', '受限', '出血', '声音'] +export const triagePickOptions : string[][] = [ + ['可走', '不可走'], + ['正常', '受限', '无呼吸'], + ['循环正常', '出血', '脉搏消失'], + ['清醒', '声音', '疼痛', '无反应'] +] + +/** 伤员详情:流转时间线 */ +export const victimTimeline : HrTimelineNode[] = [ + { time: '14:23', title: '现场检伤建档', sub: '张明 于坍塌现场完成建档,标记 3 处伤情,判定「重伤」', theme: 'normal' } as HrTimelineNode, + { time: '14:28', title: '分级确认', sub: '现场检伤组 3 组复核,维持「重伤」· 操作人 张明', theme: 'ok' } as HrTimelineNode, + { time: '14:35', title: '转运交接', sub: '平车送达 协和医院 创伤外科,转出方 张明 / 接收方 刘伟 电子签字', theme: 'normal' } as HrTimelineNode, + { time: '15:10', title: '院内处置', sub: '创伤外科接诊,建立静脉通路 + 持续心电监护,清创缝合待执行', theme: 'warn' } as HrTimelineNode +] + +/** 处置记录时间线 */ +export const treatRecords : HrTimelineNode[] = [ + { time: '15:25', title: '分级调整:重伤 → 危重', sub: 'BP 88/56 mmHg · 判断失血性休克进展', theme: 'warn' } as HrTimelineNode, + { time: '15:10', title: '建立静脉通路', sub: '左上肢 · 16G · 生理盐水 500 ml 快滴', theme: 'normal' } as HrTimelineNode, + { time: '15:02', title: '止血包扎', sub: '右前臂加压包扎 + 额部敷料', theme: 'ok' } as HrTimelineNode, + { time: '14:55', title: '检伤分级', sub: '判定「重伤」· START 协议', theme: 'normal' } as HrTimelineNode +] + +/* ============================ 转运 ============================ */ +export const hospitalList : string[] = ['协和医院 · 急诊创伤中心', '市第一人民医院 · 急诊', '同仁医院 · 急诊'] +export const hospitalMeta : string[] = ['距现场 6.2 km · 约 14 分钟', '距现场 8.9 km · 约 21 分钟', '距现场 4.1 km · 但急诊已满'] +export const hospitalBed : string[] = ['床位 2', '床位 5', '满员 ✕'] +export const hospitalAvail : boolean[] = [true, true, false] + +/* ============================ 离线队列 ============================ */ +export const offlineTasks : HrOfflineTask[] = [ + { icon: '⇅', theme: 'amb', title: '检伤建档 · 李华(含 3 个附件)', sub: '15:32 暂存 · 等待上传', status: '待传', statusColor: '#D97706' } as HrOfflineTask, + { icon: '⇅', theme: 'amb', title: '检伤建档 · 赵国强', sub: '15:28 暂存 · 等待上传', status: '待传', statusColor: '#D97706' } as HrOfflineTask, + { icon: '✓', theme: 'grn', title: '处置记录 · 李华止血包扎', sub: '15:02 提交成功', status: '已同步', statusColor: '#059669' } as HrOfflineTask +] + +/* ============================ 事件 ============================ */ +export const eventList : HrEventItem[] = [ + { + id: 'e1', name: '京港澳高速 K120 多车追尾', kind: '大型交通事故', place: '京港澳高速 K120', distance: '距您 3.2 km', + priority: 0, dotColor: '#DC2626', stage: 'ongoing', urgent: false, + members: [ + { name: '张', avatar: '张', theme: 'blue' } as HrEventMember, + { name: '李', avatar: '李', theme: 'gn' } as HrEventMember, + { name: '王', avatar: '王', theme: 'ag' } as HrEventMember + ] + } as HrEventItem, + { + id: 'e2', name: '阳光养老院 · 老人跌倒', kind: '一般救援', place: '阳光养老院 3 号楼', distance: '距您 1.1 km', + priority: 2, dotColor: '#10B981', stage: 'ongoing', urgent: false, + members: [ { name: '陈', avatar: '陈', theme: 'gn' } as HrEventMember ] + } as HrEventItem, + { + id: 'e3', name: '城东工业园区 · 化学品泄漏', kind: '危化品事故', place: '城东工业园 B 区', distance: '距您 9.6 km', + priority: 0, dotColor: '#DC2626', stage: 'pending', urgent: true, members: [] as HrEventMember[] + } as HrEventItem, + { + id: 'e4', name: '城南小学 · 学生集体腹痛', kind: '群体性事件', place: '城南小学食堂', distance: '距您 4.3 km', + priority: 1, dotColor: '#F59E0B', stage: 'pending', urgent: true, members: [] as HrEventMember[] + } as HrEventItem, + { + id: 'e5', name: '幸福小区 · 老人心梗', kind: '一般救援', place: '幸福小区 6 号楼', distance: '距您 2.4 km', + priority: 1, dotColor: '#F59E0B', stage: 'history', urgent: false, + members: [ { name: '张', avatar: '张', theme: 'blue' } as HrEventMember ] + } as HrEventItem, + { + id: 'e6', name: '滨江路 · 电动车相撞', kind: '交通事故', place: '滨江路与建设街路口', distance: '已完成', + priority: 2, dotColor: '#9CA3AF', stage: 'history', urgent: false, + members: [ { name: '李', avatar: '李', theme: 'gn' } as HrEventMember ] + } as HrEventItem, + { + id: 'e7', name: '第一中学 · 学生运动损伤', kind: '一般救援', place: '第一中学操场', distance: '已完成', + priority: 2, dotColor: '#9CA3AF', stage: 'history', urgent: false, + members: [ { name: '陈', avatar: '陈', theme: 'gy' } as HrEventMember ] + } as HrEventItem, + { + id: 'e8', name: '老城街区 · 煤气泄漏排查', kind: '危化品事故', place: '老城街区 12 巷', distance: '已完成', + priority: 1, dotColor: '#9CA3AF', stage: 'history', urgent: false, + members: [ { name: '王', avatar: '王', theme: 'ag' } as HrEventMember ] + } as HrEventItem, + { + id: 'e9', name: '火车站 · 旅客突发晕厥', kind: '一般救援', place: '火车站候车大厅', distance: '已完成', + priority: 2, dotColor: '#9CA3AF', stage: 'history', urgent: false, + members: [ { name: '赵', avatar: '赵', theme: 'blue' } as HrEventMember ] + } as HrEventItem +] + +export const eventDetail : HrEventDetail = { + id: 'e1', + name: '京港澳高速 K120 多车追尾', + sub: '大型交通事故 · 京港澳高速 K120 · 距您 3.2 km', + teamKey: '小组类型', + teamValue: '现场搜救组 · 组长 张明远', + tags: ['P0 紧急', '已抵达现场'], + victimTotal: 8, transferred: 5, pending: 3, + redCount: 3, amberCount: 2, greenCount: 1, blackCount: 2, + members: [ + { name: '张', avatar: '张', theme: 'blue' } as HrEventMember, + { name: '李', avatar: '李', theme: 'gn' } as HrEventMember, + { name: '王', avatar: '王', theme: 'ag' } as HrEventMember, + { name: '陈', avatar: '陈', theme: 'gy' } as HrEventMember, + { name: '赵', avatar: '赵', theme: 'blue' } as HrEventMember + ], + timeline: [ + { time: '15:20', title: '已完成首轮检伤', sub: '8 人全部分级 · 红 3 / 黄 2 / 绿 1 / 黑 2', theme: 'normal' } as HrTimelineNode, + { time: '14:50', title: '抵达现场 · 建立临时指挥点', sub: '现场 A 区 · 已设置警戒', theme: 'ok' } as HrTimelineNode, + { time: '14:35', title: '接收派单并出发', sub: '响应耗时 3 分钟', theme: 'normal' } as HrTimelineNode, + { time: '14:32', title: '后台调度派单', sub: 'P0 紧急 · 已推送全屏告警', theme: 'normal' } as HrTimelineNode + ] +} as HrEventDetail + +/* ============================ 扫码作业(批量处置 / 转运) ============================ */ +export const scanVictims : HrVictim[] = [ + { id: 'v1', name: '王建国', gender: '男', age: 52, code: 'TRIAGE-20260922-0001', level: 1, injury: '开放性颅脑损伤', status: '', statusTheme: '', createdAt: '' } as HrVictim, + { id: 'v2', name: '李华', gender: '男', age: 35, code: 'TRIAGE-20260922-0003', level: 2, injury: '头部外伤 / 右前臂骨折', status: '', statusTheme: '', createdAt: '' } as HrVictim, + { id: 'v3', name: '陈小梅', gender: '女', age: 28, code: 'TRIAGE-20260922-0006', level: 3, injury: '右膝软组织挫伤', status: '', statusTheme: '', createdAt: '' } as HrVictim, + { id: 'v4', name: '赵国强', gender: '男', age: 41, code: 'TRIAGE-20260922-0008', level: 2, injury: '胸部挤压伤 / 多发肋骨骨折', status: '', statusTheme: '', createdAt: '' } as HrVictim, + { id: 'v5', name: '吴长胜', gender: '男', age: 61, code: 'TRIAGE-20260922-0012', level: 4, injury: '重度颅脑损伤', status: '', statusTheme: '', createdAt: '' } as HrVictim +] + +/** 批量处置 · 处置类型 */ +export const treatTypes : string[] = ['止血包扎', '固定制动', '静脉通路', '清创消毒', '给氧'] + +/* ============================ 仓管 · 扫码 ============================ */ +export const scanFeedbacks : HrScanFeedback[] = [ + { theme: 'ok', icon: '✓', title: '一次性医用口罩 · 入库成功', sub: '规格 50 只/盒 · 现存 320 盒 · 张明远' } as HrScanFeedback, + { theme: 'warn', icon: '!', title: 'N95 防护口罩 · 库存不足', sub: '当前仅 8 盒,低于预警线 20 盒,请及时补货' } as HrScanFeedback, + { theme: 'err', icon: '✕', title: '条码未登记 · 无法识别', sub: '该编码不在物资台账中,请先建档或联系管理员' } as HrScanFeedback +] + +export const scanRecords : HrScanRecord[] = [ + { name: '一次性医用口罩', time: '15:41', delta: '+20 盒', status: '已入库', theme: 'grn', icon: '✓' } as HrScanRecord, + { name: '医用无菌纱布', time: '15:40', delta: '+12 包', status: '已入库', theme: 'grn', icon: '✓' } as HrScanRecord, + { name: 'N95 防护口罩', time: '15:39', delta: '库存不足未入库', status: '待处理', theme: 'amb', icon: '!' } as HrScanRecord +] + +/* ============================ 仓管 · 库存 ============================ */ +export const stockWarn : HrStockItem[] = [ + { name: 'N95 防护口罩', spec: '现存 8 盒 · 预警线 20 盒', value: '严重不足 ›', valueTheme: 'red', low: true, icon: '!' } as HrStockItem, + { name: '肾上腺素注射液', spec: '现存 12 支 · 预警线 30 支', value: '严重不足 ›', valueTheme: 'red', low: true, icon: '!' } as HrStockItem, + { name: '一次性输液器', spec: '现存 46 套 · 预警线 50 套', value: '接近预警 ›', valueTheme: 'amb', low: false, icon: '!' } as HrStockItem +] + +export const stockAll : HrStockItem[] = [ + { name: '一次性医用口罩', spec: '规格 50 只/盒 · 09-20 入库', value: '320', valueTheme: 't1', low: false, icon: '▦' } as HrStockItem, + { name: '医用无菌纱布', spec: '规格 8×10cm · 09-18 入库', value: '186', valueTheme: 't1', low: false, icon: '▦' } as HrStockItem, + { name: '一次性输液器', spec: '规格 1.2m · 09-15 入库', value: '46', valueTheme: 'amb', low: true, icon: '▦' } as HrStockItem, + { name: '肾上腺素注射液', spec: '规格 1mg/1ml · 09-12 入库', value: '12', valueTheme: 'red', low: true, icon: '▦' } as HrStockItem +] + +export const goodsDetail : HrGoods = { + id: 'g1', name: 'N95 防护口罩', code: 'MZ-0042', spec: '规格 20 只/盒', + stock: 8, unit: '盒', warnLine: 20, statusLabel: '库存告急', + out30: 72, dailyUse: '日均消耗 2.4 盒', lastIn: '09-12 · 供应商 XX 医疗', lastInQty: '+40 盒', + trend: [38, 52, 44, 68, 56, 84, 96] +} as HrGoods + +/* ============================ 仓管 · 设备 ============================ */ +export const deviceList : HrDevice[] = [ + { id: 'd1', name: '便携式除颤仪(AED)', code: 'SB-0018', meta: '编码 SB-0018 · 电池 82% · 03-15 维护', status: '可借', theme: 'grn', icon: 'flashlight-line', iconBg: '#EFF6FF', iconColor: '#2563EB', checkList: [] as HrDeviceCheck[], maintain: [] as HrTimelineNode[] } as HrDevice, + { id: 'd2', name: '折叠式担架', code: 'SB-0031', meta: '编码 SB-0031 · 承重 150kg · 06-20 维护', status: '借用中', theme: 'amb', icon: 'file-list-3-line', iconBg: '#FEF3C7', iconColor: '#B45309', checkList: [] as HrDeviceCheck[], maintain: [] as HrTimelineNode[] } as HrDevice, + { id: 'd3', name: '便携式氧气瓶(2L)', code: 'SB-0055', meta: '编码 SB-0055 · 压力正常 · 09-01 检查', status: '可借', theme: 'grn', icon: 'bubble-chart-line', iconBg: '#ECFDF5', iconColor: '#059669', checkList: [] as HrDeviceCheck[], maintain: [] as HrTimelineNode[] } as HrDevice, + { id: 'd4', name: '多参数监护仪', code: 'SB-0063', meta: '编码 SB-0063 · 屏幕故障 · 待维修', status: '维修中', theme: 'red', icon: 'monitor-line', iconBg: '#FEF2F2', iconColor: '#DC2626', checkList: [] as HrDeviceCheck[], maintain: [] as HrTimelineNode[] } as HrDevice +] + +export const deviceDetail : HrDevice = { + id: 'd1', name: '便携式除颤仪(AED)', code: 'SB-0018', meta: '编码 SB-0018 · 型号 HeartSave PAD', + status: '可借用', theme: 'pri', icon: '⚡', iconBg: '#EFF6FF', iconColor: '#2563EB', + checkList: [ + { title: '电池电量 ≥ 50%', sub: '当前 82% · 满足', checked: true } as HrDeviceCheck, + { title: '电极片在有效期内', sub: '有效期至 2027-03', checked: true } as HrDeviceCheck, + { title: '设备外观无破损', sub: '外壳 / 按键 / 屏幕正常', checked: true } as HrDeviceCheck, + { title: '自检指示正常', sub: '开机绿灯闪烁 · 待确认', checked: false } as HrDeviceCheck, + { title: '附件齐全(剪刀 / 剃刀 / 手套)', sub: '待确认', checked: false } as HrDeviceCheck + ], + maintain: [ + { time: '03-15', title: '季度维护完成', sub: '更换电极片 · 电池校准 · 设备科 陈工', theme: 'ok' } as HrTimelineNode, + { time: '2025-12-08', title: '电池更换', sub: '更换原厂电池组', theme: 'normal' } as HrTimelineNode + ] +} as HrDevice + +/* ============================ 消息中心 ============================ */ +export const keeperMsgGroups : HrMsgGroup[] = [ + { + title: '库存预警', count: 4, danger: true, + items: [ + { icon: '!', theme: 'red', title: 'N95 防护口罩库存告急', sub: '现存 8 盒,低于预警线 · 10 分钟前', action: '', unread: 1 } as HrMsg, + { icon: '!', theme: 'red', title: '肾上腺素注射液库存告急', sub: '现存 12 支,低于预警线 · 1 小时前', action: '', unread: 1 } as HrMsg + ] + } as HrMsgGroup, + { + title: '借用审批', count: 3, danger: false, + items: [ + { icon: '⚑', theme: 'amb', title: '张明远 申请借用「便携式除颤仪」', sub: '用途:院前急救 · 2 小时前', action: '去审批 ›', unread: 0 } as HrMsg, + { icon: '✓', theme: 'grn', title: '李承志 借用「折叠担架」已通过', sub: '预计 09-24 归还 · 昨天', action: '', unread: 0 } as HrMsg + ] + } as HrMsgGroup, + { + title: '系统通知', count: 0, danger: false, + items: [ + { icon: '⚙', theme: 'gray', title: '9 月物资盘点任务已下发', sub: '09-30 前完成 · 3 天前', action: '', unread: 0 } as HrMsg + ] + } as HrMsgGroup +] + +export const rescuerMsgGroups : HrMsgGroup[] = [ + { + title: '派单通知', count: 2, danger: true, + items: [ + { icon: '⚠', theme: 'red', title: 'P0 派单 · 城东工业园区化学品泄漏', sub: '15:38 · 距您 9.6 km · 待接收', action: '去接收 ›', unread: 0 } as HrMsg, + { icon: '⚠', theme: 'amb', title: '事件已归档 · 幸福小区老人心梗', sub: '09-21 08:12 · 系统自动归档', action: '', unread: 0 } as HrMsg + ] + } as HrMsgGroup, + { + title: '系统消息', count: 3, danger: false, + items: [ + { icon: '▤', theme: 'amb', title: 'BLS 证书即将到期提醒', sub: '2026-10-15 到期 · 请完成复训', action: '', unread: 0 } as HrMsg, + { icon: '▦', theme: 'pri', title: '新课题已上线:溺水者心肺复苏', sub: '昨天 · 急救基础 / 心肺复苏', action: '', unread: 0 } as HrMsg, + { icon: '⚙', theme: 'gray', title: '系统将于本周日凌晨维护', sub: '09-19 · 预计 2 小时', action: '', unread: 0 } as HrMsg + ] + } as HrMsgGroup +] + +/* ============================ 通讯录 ============================ */ +export const contactGroups : HrContactGroup[] = [ + { + title: '指挥调度', + items: [ + { name: '刘建国 · 调度室主任', duty: '', phone: '值班室 8801 · 手机 138****2201', avatar: '刘', theme: 'blue', useAvatar: true, icon: '' } as HrContact, + { name: '陈静 · 现场指挥', duty: '', phone: '值班室 8802 · 手机 139****3387', avatar: '陈', theme: 'blue', useAvatar: true, icon: '' } as HrContact + ] + } as HrContactGroup, + { + title: '协作医院', + items: [ + { name: '协和医院 · 急诊创伤中心', duty: '', phone: '急诊台 010-6688 0001', avatar: '', theme: 'pri', useAvatar: false, icon: '▤' } as HrContact, + { name: '市第一人民医院 · 急诊', duty: '', phone: '急诊台 010-6688 0022', avatar: '', theme: 'pri', useAvatar: false, icon: '▤' } as HrContact + ] + } as HrContactGroup, + { + title: '本队同事', + items: [ + { name: '李承志 · 主治医师', duty: '', phone: '急诊科 · 工号 1248', avatar: '李', theme: 'gn', useAvatar: true, icon: '' } as HrContact, + { name: '王志远 · 主管护师', duty: '', phone: '急诊科 · 工号 1252', avatar: '王', theme: 'ag', useAvatar: true, icon: '' } as HrContact + ] + } as HrContactGroup +] + +/* ============================ 设置 ============================ */ +export const settingSwitches : HrSettingSwitch[] = [ + { title: 'P0 派单强提醒', sub: '全屏告警 + 强制震动', on: true } as HrSettingSwitch, + { title: '任务推送', sub: '跟随调度后台的派单通知', on: true } as HrSettingSwitch, + { title: '学习提醒', sub: '课程与考试到期提醒', on: true } as HrSettingSwitch +] + +export const offlineSettingRows : HrSettingRow[] = [ + { title: '离线队列', sub: '3 条待上传', value: '›' } as HrSettingRow, + { title: '已下载学习资料', sub: '占用 8.6 MB', value: '清理 ›' } as HrSettingRow +] + +export const commonSettingRows : HrSettingRow[] = [ + { title: '清理缓存', sub: '当前 24.3 MB', value: '清理 ›' } as HrSettingRow, + { title: '关于我们', sub: '版本 v2.0.0', value: '›' } as HrSettingRow, + { title: '隐私政策', sub: '', value: '›' } as HrSettingRow +] + +/* ============================ 设计系统 ============================ */ +export const designSections : HrDesignSection[] = [ + { + title: '主色 / 语义色', + swatches: [ + { label: '主色', color: '#2563EB', hex: '#2563EB' } as HrSwatch, + { label: '主色深', color: '#1D4ED8', hex: '#1D4ED8' } as HrSwatch, + { label: '浅底', color: '#EFF6FF', hex: '#EFF6FF' } as HrSwatch, + { label: '页面底', color: '#F3F4F6', hex: '#F3F4F6' } as HrSwatch + ], + rows: [] as HrTokenRow[] + } as HrDesignSection, + { + title: '四色腕带分级(颜色 + 文字双重编码)', + swatches: [ + { label: 'I 级 红', color: '#DC2626', hex: '#DC2626' } as HrSwatch, + { label: 'II 级 黄', color: '#F59E0B', hex: '#F59E0B' } as HrSwatch, + { label: 'III 级 绿', color: '#10B981', hex: '#10B981' } as HrSwatch, + { label: 'IV 级 黑', color: '#1F2937', hex: '#1F2937' } as HrSwatch + ], + rows: [] as HrTokenRow[] + } as HrDesignSection, + { + title: '字号梯度', + swatches: [] as HrSwatch[], + rows: [ + { key: '标题 / 32', value: '救援事件' } as HrTokenRow, + { key: '小标题 / 20', value: '伤员查询' } as HrTokenRow, + { key: '正文 / 14', value: '创伤性失血' } as HrTokenRow, + { key: '辅助 / 12', value: '14:55 建档' } as HrTokenRow, + { key: '角标 / 10', value: 'I 级 · 红' } as HrTokenRow + ] + } as HrDesignSection, + { + title: '圆角 / 间距 / 触控', + swatches: [] as HrSwatch[], + rows: [ + { key: '圆角', value: '8 / 12 / 16 / 24' } as HrTokenRow, + { key: '间距', value: '8 点网格' } as HrTokenRow, + { key: '主按钮高度', value: '≥ 56pt' } as HrTokenRow, + { key: '其他可点高度', value: '≥ 44pt' } as HrTokenRow, + { key: '正文对比度', value: '≥ 4.5:1(WCAG AA)' } as HrTokenRow + ] + } as HrDesignSection +] diff --git a/mock/types.uts b/mock/types.uts new file mode 100644 index 0000000..add30ef --- /dev/null +++ b/mock/types.uts @@ -0,0 +1,380 @@ +/** + * 医院救援管理平台 · 移动端 数据模型定义 + * ------------------------------------------------------------ + * 说明:本文件只放类型定义,不放数据。 + * 后续对接接口时,仅需保证后端返回结构与此处类型一致(或在此处做一层适配)。 + */ + +/** 角色:救护人员端 / 仓管人员端 */ +export type HrRole = 'rescuer' | 'keeper' + +/** 伤情腕带分级:1 危重(红) / 2 重伤(黄) / 3 轻伤(绿) / 4 死亡(黑) */ +export type HrLevel = 1 | 2 | 3 | 4 + +/** 优先级 */ +export type HrPriority = 0 | 1 | 2 + +/* ============================ 用户 ============================ */ +export type HrUser = { + /** 姓名 */ + name : string + /** 头像文字 */ + avatar : string + /** 职称 */ + title : string + /** 科室 */ + dept : string + /** 工号(角色由后台按工号识别) */ + jobNo : string + /** 角色 */ + role : HrRole + /** 角色中文名 */ + roleLabel : string + /** 能力标签 */ + tags : string[] + /** 累计学时 */ + hours : number + /** 完成课程数 */ + courseCount : number + /** 有效证书数 */ + certCount : number +} + +/* ============================ 培训学习 ============================ */ +export type HrTodoTask = { + icon : string + iconTheme : string + title : string + sub : string + action : string +} + +export type HrActivity = { + icon : string + iconTheme : string + title : string + sub : string +} + +export type HrToolBox = { + icon : string + name : string + iconBg : string + iconColor : string +} + +/** 课程库一级分类 */ +export type HrCatalog = { + id : string + name : string + count : number + icon : string + iconBg : string + iconColor : string +} + +/** 课程库二级分组(仅作分组标题,不可点) */ +export type HrGroup = { + name : string + count : number + items : HrSubject[] +} + +/** 课程库三级课题(唯一可点) */ +export type HrSubject = { + no : string + name : string + meta : string +} + +/** 学习资料(视频 / 各类文档共用) */ +export type HrMaterial = { + id : string + /** video | doc */ + kind : string + /** PDF / DOC / PPT / XLS / 视频 */ + badge : string + badgeColor : string + icon : string + title : string + meta : string + /** 资料简介 */ + summary : string + /** 关联课题 */ + from : string + /** 学习/观看进度 0~100 */ + progress : number +} + +/** 考试记录 */ +export type HrExamRecord = { + name : string + date : string + score : number + passed : boolean +} + +/** 证书 */ +export type HrCert = { + name : string + gotAt : string + expireAt : string + status : string + statusTheme : string +} + +/** 待考安排 */ +export type HrExamPlan = { + name : string + priority : HrPriority + countdown : string + time : string + place : string +} + +/** 顺序练习信息 */ +export type HrPracticeMeta = { + subject : string + total : number + minutes : number + goal : string + lastTime : string + lastDone : number + lastRate : number +} + +/** 题目选项 */ +export type HrOption = { + key : string + text : string +} + +/** 题目 */ +export type HrQuestion = { + id : string + stem : string + options : HrOption[] + /** 正确选项下标 */ + answer : number + analysis : string + /** 所属课题 */ + from : string +} + +/* ============================ 检伤 / 伤员 ============================ */ +export type HrInjuryMark = { + no : string + title : string + sub : string + /** 标记点色:red / amb */ + theme : string +} + +export type HrVital = { + /** 数值,如 37.8 / 95/60 */ + value : string + /** 指标名 + 单位,如 T ℃ */ + unit : string + /** 是否异常(异常高亮为红) */ + abnormal : boolean +} + +export type HrTimelineNode = { + time : string + title : string + sub : string + /** normal | ok | warn */ + theme : string +} + +export type HrVictim = { + id : string + name : string + gender : string + age : number + code : string + level : HrLevel + /** 伤情摘要 */ + injury : string + /** 转运/处置状态文案 */ + status : string + statusTheme : string + createdAt : string +} + +/* ============================ 应急事件 ============================ */ +export type HrEventMember = { + name : string + avatar : string + theme : string +} + +export type HrEventItem = { + id : string + name : string + kind : string + place : string + distance : string + priority : HrPriority + dotColor : string + /**进行中 / 待接收 / 历史 */ + stage : string + urgent : boolean + members : HrEventMember[] +} + +export type HrEventDetail = { + id : string + name : string + sub : string + teamKey : string + teamValue : string + tags : string[] + victimTotal : number + transferred : number + pending : number + redCount : number + amberCount : number + greenCount : number + blackCount : number + members : HrEventMember[] + timeline : HrTimelineNode[] +} + +/* ============================ 仓管 ============================ */ +export type HrScanFeedback = { + /** ok | warn | err */ + theme : string + icon : string + title : string + sub : string +} + +export type HrScanRecord = { + name : string + time : string + delta : string + status : string + theme : string + icon : string +} + +export type HrStockItem = { + name : string + spec : string + value : string + valueTheme : string + low : boolean + icon : string +} + +export type HrGoods = { + id : string + name : string + code : string + spec : string + stock : number + unit : string + warnLine : number + statusLabel : string + out30 : number + dailyUse : string + lastIn : string + lastInQty : string + /** 趋势柱高百分比 */ + trend : number[] +} + +export type HrDevice = { + id : string + name : string + code : string + meta : string + status : string + theme : string + icon : string + iconBg : string + iconColor : string + checkList : HrDeviceCheck[] + maintain : HrTimelineNode[] +} + +export type HrDeviceCheck = { + title : string + sub : string + checked : boolean +} + +/* ============================ 消息 / 通讯录 ============================ */ +export type HrMsg = { + icon : string + theme : string + title : string + sub : string + action : string + unread : number +} + +export type HrMsgGroup = { + title : string + count : number + danger : boolean + items : HrMsg[] +} + +export type HrContact = { + name : string + duty : string + phone : string + avatar : string + theme : string + /** true 用图标,false 用文字头像 */ + useAvatar : boolean + icon : string +} + +export type HrContactGroup = { + title : string + items : HrContact[] +} + +/* ============================ 离线队列 ============================ */ +export type HrOfflineTask = { + icon : string + theme : string + title : string + sub : string + status : string + statusColor : string +} + +/* ============================ 设置 ============================ */ +export type HrSettingSwitch = { + title : string + sub : string + on : boolean +} + +export type HrSettingRow = { + title : string + sub : string + value : string +} + +/* ============================ 设计系统 ============================ */ +export type HrSwatch = { + label : string + color : string + hex : string +} + +export type HrTokenRow = { + key : string + value : string +} + +export type HrDesignSection = { + title : string + swatches : HrSwatch[] + rows : HrTokenRow[] +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..9a68866 --- /dev/null +++ b/pages.json @@ -0,0 +1,282 @@ +{ + "easycom": { + "autoscan": true + }, + "pages": [ + { + "path": "pages/login/index", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "登录" + } + }, + { + "path": "pages/home/index", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "首页" + } + }, + { + "path": "pages/event/index", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "事件" + } + }, + { + "path": "pages/event/detail", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "事件详情" + } + }, + { + "path": "pages/mine/index", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "我的" + } + }, + { + "path": "pages/mine/settings", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "设置" + } + }, + { + "path": "pages/course/library", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "课程库" + } + }, + { + "path": "pages/course/subject", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "课题详情" + } + }, + { + "path": "pages/course/media", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "资料详情" + } + }, + { + "path": "pages/course/practice", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "顺序练习" + } + }, + { + "path": "pages/course/quiz", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "答题" + } + }, + { + "path": "pages/course/answer-card", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "答题卡" + } + }, + { + "path": "pages/study/exams", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "我的考试" + } + }, + { + "path": "pages/study/certificates", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "我的证书" + } + }, + { + "path": "pages/study/wrong-book", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "错题本" + } + }, + { + "path": "pages/study/center", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "学习中心" + } + }, + { + "path": "pages/triage/victims", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "伤员查询" + } + }, + { + "path": "pages/triage/create", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "检伤建档" + } + }, + { + "path": "pages/triage/detail", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "伤员详情" + } + }, + { + "path": "pages/triage/batch-treat", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "批量处置" + } + }, + { + "path": "pages/triage/batch-transfer", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "批量转运" + } + }, + { + "path": "pages/triage/transfer", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "转运登记" + } + }, + { + "path": "pages/triage/treat-records", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "处置记录" + } + }, + { + "path": "pages/triage/offline-sync", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "离线同步" + } + }, + { + "path": "pages/warehouse/scan", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "扫码出入库" + } + }, + { + "path": "pages/warehouse/stock", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "库存查询" + } + }, + { + "path": "pages/warehouse/goods-detail", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "物资详情" + } + }, + { + "path": "pages/warehouse/devices", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "设备借用" + } + }, + { + "path": "pages/warehouse/device-detail", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "设备详情" + } + }, + { + "path": "pages/message/index", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "消息" + } + }, + { + "path": "pages/message/list", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "消息中心" + } + }, + { + "path": "pages/message/contacts", + "style": { + "navigationStyle": "custom", + "disableScroll": true, + "navigationBarTitleText": "通讯录" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "@navTxtStyle", + "navigationBarBackgroundColor": "@navBgColor", + "backgroundColorContent": "@backgroundColor", + "backgroundColor": "@backgroundColor", + "navigationBarTitleText": "医院救援管理平台", + "pageOrientation": "portrait" + }, + "uniIdRouter": {}, + "condition": { + "current": 0, + "list": [ + { + "name": "登录", + "path": "pages/login/index", + "query": "" + } + ] + } +} diff --git a/pages/course/answer-card.uvue b/pages/course/answer-card.uvue new file mode 100644 index 0000000..93d82b7 --- /dev/null +++ b/pages/course/answer-card.uvue @@ -0,0 +1,223 @@ + + + + + diff --git a/pages/course/library.uvue b/pages/course/library.uvue new file mode 100644 index 0000000..d52ff48 --- /dev/null +++ b/pages/course/library.uvue @@ -0,0 +1,331 @@ + + + + + \ No newline at end of file diff --git a/pages/course/media.uvue b/pages/course/media.uvue new file mode 100644 index 0000000..83d6709 --- /dev/null +++ b/pages/course/media.uvue @@ -0,0 +1,490 @@ + + + + + diff --git a/pages/course/practice.uvue b/pages/course/practice.uvue new file mode 100644 index 0000000..d5bc3fe --- /dev/null +++ b/pages/course/practice.uvue @@ -0,0 +1,166 @@ + + + + + diff --git a/pages/course/quiz.uvue b/pages/course/quiz.uvue new file mode 100644 index 0000000..162365a --- /dev/null +++ b/pages/course/quiz.uvue @@ -0,0 +1,396 @@ + + + + + diff --git a/pages/course/subject.uvue b/pages/course/subject.uvue new file mode 100644 index 0000000..c93c2f8 --- /dev/null +++ b/pages/course/subject.uvue @@ -0,0 +1,361 @@ + + + + + \ No newline at end of file diff --git a/pages/event/detail.uvue b/pages/event/detail.uvue new file mode 100644 index 0000000..f18f902 --- /dev/null +++ b/pages/event/detail.uvue @@ -0,0 +1,291 @@ + + + + + diff --git a/pages/event/index.uvue b/pages/event/index.uvue new file mode 100644 index 0000000..0764ecf --- /dev/null +++ b/pages/event/index.uvue @@ -0,0 +1,275 @@ + + + + + \ No newline at end of file diff --git a/pages/home/index.uvue b/pages/home/index.uvue new file mode 100644 index 0000000..a687cb3 --- /dev/null +++ b/pages/home/index.uvue @@ -0,0 +1,314 @@ + + + + + \ No newline at end of file diff --git a/pages/login/index.uvue b/pages/login/index.uvue new file mode 100644 index 0000000..ae574a1 --- /dev/null +++ b/pages/login/index.uvue @@ -0,0 +1,237 @@ + + + + + diff --git a/pages/message/contacts.uvue b/pages/message/contacts.uvue new file mode 100644 index 0000000..1747820 --- /dev/null +++ b/pages/message/contacts.uvue @@ -0,0 +1,147 @@ + + + + + diff --git a/pages/message/index.uvue b/pages/message/index.uvue new file mode 100644 index 0000000..f7ec150 --- /dev/null +++ b/pages/message/index.uvue @@ -0,0 +1,191 @@ + + + + + diff --git a/pages/message/list.uvue b/pages/message/list.uvue new file mode 100644 index 0000000..56c7f6c --- /dev/null +++ b/pages/message/list.uvue @@ -0,0 +1,88 @@ + + + diff --git a/pages/mine/index.uvue b/pages/mine/index.uvue new file mode 100644 index 0000000..62759ea --- /dev/null +++ b/pages/mine/index.uvue @@ -0,0 +1,300 @@ + + + + + diff --git a/pages/mine/settings.uvue b/pages/mine/settings.uvue new file mode 100644 index 0000000..fea5d42 --- /dev/null +++ b/pages/mine/settings.uvue @@ -0,0 +1,80 @@ + + + diff --git a/pages/study/center.uvue b/pages/study/center.uvue new file mode 100644 index 0000000..968ee94 --- /dev/null +++ b/pages/study/center.uvue @@ -0,0 +1,288 @@ + + + + + diff --git a/pages/study/certificates.uvue b/pages/study/certificates.uvue new file mode 100644 index 0000000..af26800 --- /dev/null +++ b/pages/study/certificates.uvue @@ -0,0 +1,81 @@ + + + + + diff --git a/pages/study/exams.uvue b/pages/study/exams.uvue new file mode 100644 index 0000000..a1c2640 --- /dev/null +++ b/pages/study/exams.uvue @@ -0,0 +1,185 @@ + + + + + diff --git a/pages/study/wrong-book.uvue b/pages/study/wrong-book.uvue new file mode 100644 index 0000000..6437b8b --- /dev/null +++ b/pages/study/wrong-book.uvue @@ -0,0 +1,270 @@ + + + + + diff --git a/pages/triage/batch-transfer.uvue b/pages/triage/batch-transfer.uvue new file mode 100644 index 0000000..8f17b5b --- /dev/null +++ b/pages/triage/batch-transfer.uvue @@ -0,0 +1,356 @@ + + + + + diff --git a/pages/triage/batch-treat.uvue b/pages/triage/batch-treat.uvue new file mode 100644 index 0000000..ddcdefa --- /dev/null +++ b/pages/triage/batch-treat.uvue @@ -0,0 +1,247 @@ + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-input/x-input.uvue b/uni_modules/tmx-ui/components/x-input/x-input.uvue new file mode 100644 index 0000000..70a4a59 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-input/x-input.uvue @@ -0,0 +1,847 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-keyboard-car/x-keyboard-car.uvue b/uni_modules/tmx-ui/components/x-keyboard-car/x-keyboard-car.uvue new file mode 100644 index 0000000..ddc0e53 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-keyboard-car/x-keyboard-car.uvue @@ -0,0 +1,411 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-keyboard-idcard/idcard.uts b/uni_modules/tmx-ui/components/x-keyboard-idcard/idcard.uts new file mode 100644 index 0000000..7668624 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-keyboard-idcard/idcard.uts @@ -0,0 +1,130 @@ +export function validateIdCard(idCard: string):boolean { + let vcity = new Map([ + [11, "北京"], [12, "天津"], [13, "河北"], [14, "山西"], [15, "内蒙古"], + [21, "辽宁"], [22, "吉林"], [23, "黑龙江"], [31, "上海"], [32, "江苏"], + [33, "浙江"], [34, "安徽"], [35, "福建"], [36, "江西"], [37, "山东"], [41, "河南"], + [42, "湖北"], [43, "湖南"], [44, "广东"], [45, "广西"], [46, "海南"], [50, "重庆"], + [51, "四川"], [52, "贵州"], [53, "云南"], [54, "西藏"], [61, "陕西"], [62, "甘肃"], + [63, "青海"], [64, "宁夏"], [65, "新疆"], [71, "台湾"], [81, "香港"], [82, "澳门"], [91, "国外"] +]);; + //是否为空 + if (idCard === '') { + return false; + } + //校验长度,类型 + if (isCardNo(idCard) === false) { + return false; + } + //检查省份 + if (checkProvince(idCard, vcity) === false) { + return false; + } + + //校验生日 + if (checkBirthday(idCard) === false) { + + return false; + } + + //检验位的检测 + if (checkParity(idCard) === false) { + return false; + } + return true; +} +function isCardNo(card:string):boolean { + //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X + let reg = /(^\d{15}$)|(^\d{17}(\d|X|x)$)/; + if (reg.test(card) === false) { + return false; + } + return true; +} +function checkProvince(card:string, vcity:Map):boolean { + let province = card.substring(0,2) + + if (!vcity.has(parseInt(province))) { + return false; + } + return true; +}; +function checkBirthday(card:string):boolean { + let len = card.length; + //身份证15位时,次序为省(3位)市(3位)年(2位)月(2位)日(2位)校验位(3位),皆为数字 + if (len == 15) { + let re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/; + let arr_data = card.match(re_fifteen); + if(arr_data==null) return false + let year = arr_data[2]; + let month = arr_data[3]; + let day = arr_data[4]; + if(year==null||month==null||day==null) return false + let birthday = new Date('19' + year + '/' + month + '/' + day); + return verifyBirthday(parseInt('19' + year), parseInt(month), parseInt(day), birthday); + } + //身份证18位时,次序为省(3位)市(3位)年(4位)月(2位)日(2位)校验位(4位),校验位末尾可能为X + if (len == 18) { + let re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X|x)$/; + let arr_data = card.match(re_eighteen); + if(arr_data==null) return false + let year = arr_data[2]; + let month = arr_data[3]; + let day = arr_data[4]; + if(year==null||month==null||day==null) return false + let birthday = new Date(year + '/' + month + '/' + day); + return verifyBirthday(parseInt(year), parseInt(month), parseInt(day), birthday); + } + return false; +}; +function verifyBirthday(year:number, month:number, day:number, birthday:Date):boolean { + let now = new Date(); + let now_year = now.getFullYear(); + //年月日是否合理 + if (birthday.getFullYear() == year && (birthday.getMonth() + 1) == month && birthday.getDate() == day) { + //判断年份的范围(0岁到100岁之间) + let time = now_year - year; + if (time >= 0 && time <= 100) { + return true; + } + return false; + } + return false; +} +function checkParity(card:string):boolean { + //15位转18位 + card = changeFivteenToEighteen(card); + let len = card.length; + if (len == 18) { + let arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); + let arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); + let cardTemp = 0 + let i =0; + let valnum = ''; + + for (i = 0; i < 17; i++) { + cardTemp += parseInt(card.charAt(i)) * arrInt[i]; + } + + valnum = arrCh[cardTemp % 11]; + if (valnum == card.substring(17).toLocaleUpperCase()) { + return true; + } + return false; + } + return false; +} +function changeFivteenToEighteen(card:string):string { + if (card.length == 15) { + let arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); + let arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); + let cardTemp = 0 + let i =0; + card = card.substring(0, 6) + '19' + card.substring(6, card.length - 6); + for (i = 0; i < 17; i++) { + cardTemp += parseInt(card.substring(i, 1)) * arrInt[i]; + } + card += arrCh[cardTemp % 11]; + return card; + } + return card; +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-keyboard-idcard/x-keyboard-idcard.uvue b/uni_modules/tmx-ui/components/x-keyboard-idcard/x-keyboard-idcard.uvue new file mode 100644 index 0000000..5563e2e --- /dev/null +++ b/uni_modules/tmx-ui/components/x-keyboard-idcard/x-keyboard-idcard.uvue @@ -0,0 +1,356 @@ + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-keyboard-number/x-keyboard-number.uvue b/uni_modules/tmx-ui/components/x-keyboard-number/x-keyboard-number.uvue new file mode 100644 index 0000000..340b338 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-keyboard-number/x-keyboard-number.uvue @@ -0,0 +1,412 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-keyboard/x-keyboard.uvue b/uni_modules/tmx-ui/components/x-keyboard/x-keyboard.uvue new file mode 100644 index 0000000..7c1e9f6 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-keyboard/x-keyboard.uvue @@ -0,0 +1,406 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-layout/x-layout.uvue b/uni_modules/tmx-ui/components/x-layout/x-layout.uvue new file mode 100644 index 0000000..5989670 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-layout/x-layout.uvue @@ -0,0 +1,127 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-link/x-link.uvue b/uni_modules/tmx-ui/components/x-link/x-link.uvue new file mode 100644 index 0000000..5cc3ca6 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-link/x-link.uvue @@ -0,0 +1,216 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-loading/x-loading.uvue b/uni_modules/tmx-ui/components/x-loading/x-loading.uvue new file mode 100644 index 0000000..106a125 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-loading/x-loading.uvue @@ -0,0 +1,113 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-markdown/default.min.css b/uni_modules/tmx-ui/components/x-markdown/default.min.css new file mode 100644 index 0000000..69edcf1 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/default.min.css @@ -0,0 +1,9 @@ +/*! + Theme: Default + Description: Original highlight.js style + Author: (c) Ivan Sagalaev + Maintainer: @highlightjs/core-team + Website: https://highlightjs.org/ + License: see project LICENSE + Touched: 2021 +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} diff --git a/uni_modules/tmx-ui/components/x-markdown/fonts.zip b/uni_modules/tmx-ui/components/x-markdown/fonts.zip new file mode 100644 index 0000000..c8414aa Binary files /dev/null and b/uni_modules/tmx-ui/components/x-markdown/fonts.zip differ diff --git a/uni_modules/tmx-ui/components/x-markdown/highlight.min.js b/uni_modules/tmx-ui/components/x-markdown/highlight.min.js new file mode 100644 index 0000000..3b5f27e --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/highlight.min.js @@ -0,0 +1,4620 @@ +/*! + Highlight.js v11.10.0 (git: 366a8bd012) + (c) 2006-2024 Josh Goebel and other contributors + License: BSD-3-Clause + */ +export const hljs = function() { + "use strict"; + + function e(t) { + return t instanceof Map ? t.clear = t.delete = t.set = () => { + throw Error("map is read-only") + } : t instanceof Set && (t.add = t.clear = t.delete = () => { + throw Error("set is read-only") + }), Object.freeze(t), Object.getOwnPropertyNames(t).forEach((n => { + const i = t[n], + s = typeof i; + "object" !== s && "function" !== s || Object.isFrozen(i) || e(i) + })), t + } + class t { + constructor(e) { + void 0 === e.data && (e.data = {}), this.data = e.data, this.isMatchIgnored = !1 + } + ignoreMatch() { + this.isMatchIgnored = !0 + } + } + + function n(e) { + return e.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace( + /'/g, "'") + } + + function i(e, ...t) { + const n = Object.create(null); + for (const t in e) n[t] = e[t]; + return t.forEach((e => { + for (const t in e) n[t] = e[t] + })), n + } + const s = e => !!e.scope; + class o { + constructor(e, t) { + this.buffer = "", this.classPrefix = t.classPrefix, e.walk(this) + } + addText(e) { + this.buffer += n(e) + } + openNode(e) { + if (!s(e)) return; + const t = ((e, { + prefix: t + }) => { + if (e.startsWith("language:")) return e.replace("language:", "language-"); + if (e.includes(".")) { + const n = e.split("."); + return [`${t}${n.shift()}`, ...n.map(((e, t) => `${e}${"_".repeat(t+1)}`))].join( + " ") + } + return `${t}${e}` + })(e.scope, { + prefix: this.classPrefix + }); + this.span(t) + } + closeNode(e) { + s(e) && (this.buffer += "") + } + value() { + return this.buffer + } + span(e) { + this.buffer += `` + } + } + const r = (e = {}) => { + const t = { + children: [] + }; + return Object.assign(t, e), t + }; + class a { + constructor() { + this.rootNode = r(), this.stack = [this.rootNode] + } + get top() { + return this.stack[this.stack.length - 1] + } + get root() { + return this.rootNode + } + add(e) { + this.top.children.push(e) + } + openNode(e) { + const t = r({ + scope: e + }); + this.add(t), this.stack.push(t) + } + closeNode() { + if (this.stack.length > 1) return this.stack.pop() + } + closeAllNodes() { + for (; this.closeNode();); + } + toJSON() { + return JSON.stringify(this.rootNode, null, 4) + } + walk(e) { + return this.constructor._walk(e, this.rootNode) + } + static _walk(e, t) { + return "string" == typeof t ? e.addText(t) : t.children && (e.openNode(t), + t.children.forEach((t => this._walk(e, t))), e.closeNode(t)), e + } + static _collapse(e) { + "string" != typeof e && e.children && (e.children.every((e => "string" == typeof e)) ? e + .children = [e.children.join("")] : e.children.forEach((e => { + a._collapse(e) + }))) + } + } + class c extends a { + constructor(e) { + super(), this.options = e + } + addText(e) { + "" !== e && this.add(e) + } + startScope(e) { + this.openNode(e) + } + endScope() { + this.closeNode() + } + __addSublanguage(e, t) { + const n = e.root; + t && (n.scope = "language:" + t), this.add(n) + } + toHTML() { + return new o(this, this.options).value() + } + finalize() { + return this.closeAllNodes(), !0 + } + } + + function l(e) { + return e ? "string" == typeof e ? e : e.source : null + } + + function g(e) { + return h("(?=", e, ")") + } + + function u(e) { + return h("(?:", e, ")*") + } + + function d(e) { + return h("(?:", e, ")?") + } + + function h(...e) { + return e.map((e => l(e))).join("") + } + + function f(...e) { + const t = (e => { + const t = e[e.length - 1]; + return "object" == typeof t && t.constructor === Object ? (e.splice(e.length - 1, 1), t) : {} + })(e); + return "(" + (t.capture ? "" : "?:") + e.map((e => l(e))).join("|") + ")" + } + + function p(e) { + return RegExp(e.toString() + "|").exec("").length - 1 + } + const b = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./; + + function m(e, { + joinWith: t + }) { + let n = 0; + return e.map((e => { + n += 1; + const t = n; + let i = l(e), + s = ""; + for (; i.length > 0;) { + const e = b.exec(i); + if (!e) { + s += i; + break + } + s += i.substring(0, e.index), + i = i.substring(e.index + e[0].length), "\\" === e[0][0] && e[1] ? s += "\\" + ( + Number(e[1]) + t) : (s += e[0], + "(" === e[0] && n++) + } + return s + })).map((e => `(${e})`)).join(t) + } + const E = "[a-zA-Z]\\w*", + x = "[a-zA-Z_]\\w*", + w = "\\b\\d+(\\.\\d+)?", + y = "(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)", + _ = "\\b(0b[01]+)", + O = { + begin: "\\\\[\\s\\S]", + relevance: 0 + }, + v = { + scope: "string", + begin: "'", + end: "'", + illegal: "\\n", + contains: [O] + }, + k = { + scope: "string", + begin: '"', + end: '"', + illegal: "\\n", + contains: [O] + }, + N = (e, t, n = {}) => { + const s = i({ + scope: "comment", + begin: e, + end: t, + contains: [] + }, n); + s.contains.push({ + scope: "doctag", + begin: "[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", + end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/, + excludeBegin: !0, + relevance: 0 + }); + const o = f("I", "a", "is", "so", "us", "to", "at", "if", "in", "it", "on", + /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, /[A-Za-z]+[-][a-z]+/, /[A-Za-z][a-z]{2,}/); + return s.contains.push({ + begin: h(/[ ]+/, "(", o, /[.]?[:]?([.][ ]|[ ])/, "){3}") + }), s + }, + S = N("//", "$"), + M = N("/\\*", "\\*/"), + R = N("#", "$"); + var j = Object.freeze({ + __proto__: null, + APOS_STRING_MODE: v, + BACKSLASH_ESCAPE: O, + BINARY_NUMBER_MODE: { + scope: "number", + begin: _, + relevance: 0 + }, + BINARY_NUMBER_RE: _, + COMMENT: N, + C_BLOCK_COMMENT_MODE: M, + C_LINE_COMMENT_MODE: S, + C_NUMBER_MODE: { + scope: "number", + begin: y, + relevance: 0 + }, + C_NUMBER_RE: y, + END_SAME_AS_BEGIN: e => Object.assign(e, { + "on:begin": (e, t) => { + t.data._beginMatch = e[1] + }, + "on:end": (e, t) => { + t.data._beginMatch !== e[1] && t.ignoreMatch() + } + }), + HASH_COMMENT_MODE: R, + IDENT_RE: E, + MATCH_NOTHING_RE: /\b\B/, + METHOD_GUARD: { + begin: "\\.\\s*" + x, + relevance: 0 + }, + NUMBER_MODE: { + scope: "number", + begin: w, + relevance: 0 + }, + NUMBER_RE: w, + PHRASAL_WORDS_MODE: { + begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ + }, + QUOTE_STRING_MODE: k, + REGEXP_MODE: { + scope: "regexp", + begin: /\/(?=[^/\n]*\/)/, + end: /\/[gimuy]*/, + contains: [O, { + begin: /\[/, + end: /\]/, + relevance: 0, + contains: [O] + }] + }, + RE_STARTERS_RE: "!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", + SHEBANG: (e = {}) => { + const t = /^#![ ]*\//; + return e.binary && (e.begin = h(t, /.*\b/, e.binary, /\b.*/)), i({ + scope: "meta", + begin: t, + end: /$/, + relevance: 0, + "on:begin": (e, t) => { + 0 !== e.index && t.ignoreMatch() + } + }, e) + }, + TITLE_MODE: { + scope: "title", + begin: E, + relevance: 0 + }, + UNDERSCORE_IDENT_RE: x, + UNDERSCORE_TITLE_MODE: { + scope: "title", + begin: x, + relevance: 0 + } + }); + + function A(e, t) { + "." === e.input[e.index - 1] && t.ignoreMatch() + } + + function I(e, t) { + void 0 !== e.className && (e.scope = e.className, delete e.className) + } + + function T(e, t) { + t && e.beginKeywords && (e.begin = "\\b(" + e.beginKeywords.split(" ").join("|") + ")(?!\\.)(?=\\b|\\s)", + e.__beforeBegin = A, e.keywords = e.keywords || e.beginKeywords, delete e.beginKeywords, + void 0 === e.relevance && (e.relevance = 0)) + } + + function L(e, t) { + Array.isArray(e.illegal) && (e.illegal = f(...e.illegal)) + } + + function B(e, t) { + if (e.match) { + if (e.begin || e.end) throw Error("begin & end are not supported with match"); + e.begin = e.match, delete e.match + } + } + + function P(e, t) { + void 0 === e.relevance && (e.relevance = 1) + } + const D = (e, t) => { + if (!e.beforeMatch) return; + if (e.starts) throw Error("beforeMatch cannot be used with starts"); + const n = Object.assign({}, e); + Object.keys(e).forEach((t => { + delete e[t] + })), e.keywords = n.keywords, e.begin = h(n.beforeMatch, g(n.begin)), e.starts = { + relevance: 0, + contains: [Object.assign(n, { + endsParent: !0 + })] + }, e.relevance = 0, delete n.beforeMatch + }, + H = ["of", "and", "for", "in", "not", "or", "if", "then", "parent", "list", "value"], + C = "keyword"; + + function $(e, t, n = C) { + const i = Object.create(null); + return "string" == typeof e ? s(n, e.split(" ")) : Array.isArray(e) ? s(n, e) : Object.keys(e).forEach(( + n => { + Object.assign(i, $(e[n], t, n)) + })), i; + + function s(e, n) { + t && (n = n.map((e => e.toLowerCase()))), n.forEach((t => { + const n = t.split("|"); + i[n[0]] = [e, U(n[0], n[1])] + })) + } + } + + function U(e, t) { + return t ? Number(t) : (e => H.includes(e.toLowerCase()))(e) ? 0 : 1 + } + const z = {}, + W = e => { + console.error(e) + }, + X = (e, ...t) => { + console.log("WARN: " + e, ...t) + }, + G = (e, t) => { + z[`${e}/${t}`] || (console.log(`Deprecated as of ${e}. ${t}`), z[`${e}/${t}`] = !0) + }, + K = Error(); + + function F(e, t, { + key: n + }) { + let i = 0; + const s = e[n], + o = {}, + r = {}; + for (let e = 1; e <= t.length; e++) r[e + i] = s[e], o[e + i] = !0, i += p(t[e - 1]); + e[n] = r, e[n]._emit = o, e[n]._multi = !0 + } + + function Z(e) { + (e => { + e.scope && "object" == typeof e.scope && null !== e.scope && (e.beginScope = e.scope, + delete e.scope) + })(e), "string" == typeof e.beginScope && (e.beginScope = { + _wrap: e.beginScope + }), "string" == typeof e.endScope && (e.endScope = { + _wrap: e.endScope + }), (e => { + if (Array.isArray(e.begin)) { + if (e.skip || e.excludeBegin || e.returnBegin) throw W( + "skip, excludeBegin, returnBegin not compatible with beginScope: {}"), + K; + if ("object" != typeof e.beginScope || null === e.beginScope) throw W( + "beginScope must be object"), + K; + F(e, e.begin, { + key: "beginScope" + }), e.begin = m(e.begin, { + joinWith: "" + }) + } + })(e), (e => { + if (Array.isArray(e.end)) { + if (e.skip || e.excludeEnd || e.returnEnd) throw W( + "skip, excludeEnd, returnEnd not compatible with endScope: {}"), + K; + if ("object" != typeof e.endScope || null === e.endScope) throw W( + "endScope must be object"), + K; + F(e, e.end, { + key: "endScope" + }), e.end = m(e.end, { + joinWith: "" + }) + } + })(e) + } + + function V(e) { + function t(t, n) { + return RegExp(l(t), "m" + (e.case_insensitive ? "i" : "") + (e.unicodeRegex ? "u" : "") + (n ? "g" : + "")) + } + class n { + constructor() { + this.matchIndexes = {}, this.regexes = [], this.matchAt = 1, this.position = 0 + } + addRule(e, t) { + t.position = this.position++, this.matchIndexes[this.matchAt] = t, this.regexes.push([t, e]), + this.matchAt += p(e) + 1 + } + compile() { + 0 === this.regexes.length && (this.exec = () => null); + const e = this.regexes.map((e => e[1])); + this.matcherRe = t(m(e, { + joinWith: "|" + }), !0), this.lastIndex = 0 + } + exec(e) { + this.matcherRe.lastIndex = this.lastIndex; + const t = this.matcherRe.exec(e); + if (!t) return null; + const n = t.findIndex(((e, t) => t > 0 && void 0 !== e)), + i = this.matchIndexes[n]; + return t.splice(0, n), Object.assign(t, i) + } + } + class s { + constructor() { + this.rules = [], this.multiRegexes = [], + this.count = 0, this.lastIndex = 0, this.regexIndex = 0 + } + getMatcher(e) { + if (this.multiRegexes[e]) return this.multiRegexes[e]; + const t = new n; + return this.rules.slice(e).forEach((([e, n]) => t.addRule(e, n))), + t.compile(), this.multiRegexes[e] = t, t + } + resumingScanAtSamePosition() { + return 0 !== this.regexIndex + } + considerAll() { + this.regexIndex = 0 + } + addRule(e, t) { + this.rules.push([e, t]), "begin" === t.type && this.count++ + } + exec(e) { + const t = this.getMatcher(this.regexIndex); + t.lastIndex = this.lastIndex; + let n = t.exec(e); + if (this.resumingScanAtSamePosition()) + if (n && n.index === this.lastIndex); + else { + const t = this.getMatcher(0); + t.lastIndex = this.lastIndex + 1, n = t.exec(e) + } + return n && (this.regexIndex += n.position + 1, + this.regexIndex === this.count && this.considerAll()), n + } + } + if (e.compilerExtensions || (e.compilerExtensions = []), + e.contains && e.contains.includes("self")) throw Error( + "ERR: contains `self` is not supported at the top-level of a language. See documentation."); + return e.classNameAliases = i(e.classNameAliases || {}), + function n(o, r) { + const a = o; + if (o.isCompiled) return a; + [I, B, Z, D].forEach((e => e(o, r))), e.compilerExtensions.forEach((e => e(o, r))), + o.__beforeBegin = null, [T, L, P].forEach((e => e(o, r))), o.isCompiled = !0; + let c = null; + return "object" == typeof o.keywords && o.keywords.$pattern && (o.keywords = Object.assign({}, o + .keywords), + c = o.keywords.$pattern, + delete o.keywords.$pattern), c = c || /\w+/, o.keywords && (o.keywords = $(o.keywords, e + .case_insensitive)), + a.keywordPatternRe = t(c, !0), + r && (o.begin || (o.begin = /\B|\b/), a.beginRe = t(a.begin), o.end || o.endsWithParent || (o + .end = /\B|\b/), + o.end && (a.endRe = t(a.end)), + a.terminatorEnd = l(a.end) || "", o.endsWithParent && r.terminatorEnd && (a.terminatorEnd += + (o.end ? "|" : "") + r.terminatorEnd)), + o.illegal && (a.illegalRe = t(o.illegal)), + o.contains || (o.contains = []), o.contains = [].concat(...o.contains.map((e => (e => (e + .variants && !e.cachedVariants && (e.cachedVariants = e.variants.map((t => + i(e, { + variants: null + }, t)))), e.cachedVariants ? e.cachedVariants : q(e) ? i(e, { + starts: e.starts ? i(e.starts) : null + }) : Object.isFrozen(e) ? i(e) : e))("self" === e ? o : e)))), o.contains.forEach((e => { + n(e, a) + })), o.starts && n(o.starts, r), a.matcher = (e => { + const t = new s; + return e.contains.forEach((e => t.addRule(e.begin, { + rule: e, + type: "begin" + }))), e.terminatorEnd && t.addRule(e.terminatorEnd, { + type: "end" + }), e.illegal && t.addRule(e.illegal, { + type: "illegal" + }), t + })(a), a + }(e) + } + + function q(e) { + return !!e && (e.endsWithParent || q(e.starts)) + } + class J extends Error { + constructor(e, t) { + super(e), this.name = "HTMLInjectionError", this.html = t + } + } + const Y = n, + Q = i, + ee = Symbol("nomatch"), + te = n => { + const i = Object.create(null), + s = Object.create(null), + o = []; + let r = !0; + const a = "Could not find the language '{}', did you forget to load/include a language module?", + l = { + disableAutodetect: !0, + name: "Plain text", + contains: [] + }; + let p = { + ignoreUnescapedHTML: !1, + throwUnescapedHTML: !1, + noHighlightRe: /^(no-?highlight)$/i, + languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i, + classPrefix: "hljs-", + cssSelector: "pre code", + languages: null, + __emitter: c + }; + + function b(e) { + return p.noHighlightRe.test(e) + } + + function m(e, t, n) { + let i = "", + s = ""; + "object" == typeof t ? (i = e, + n = t.ignoreIllegals, s = t.language) : (G("10.7.0", + "highlight(lang, code, ...args) has been deprecated."), + G("10.7.0", + "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277" + ), + s = e, i = t), void 0 === n && (n = !0); + const o = { + code: i, + language: s + }; + N("before:highlight", o); + const r = o.result ? o.result : E(o.language, o.code, n); + return r.code = o.code, N("after:highlight", r), r + } + + function E(e, n, s, o) { + const c = Object.create(null); + + function l() { + if (!N.keywords) return void M.addText(R); + let e = 0; + N.keywordPatternRe.lastIndex = 0; + let t = N.keywordPatternRe.exec(R), + n = ""; + for (; t;) { + n += R.substring(e, t.index); + const s = _.case_insensitive ? t[0].toLowerCase() : t[0], + o = (i = s, N.keywords[i]); + if (o) { + const [e, i] = o + ; + if (M.addText(n), n = "", c[s] = (c[s] || 0) + 1, c[s] <= 7 && (j += i), e.startsWith( + "_")) n += t[0]; + else { + const n = _.classNameAliases[e] || e; + u(t[0], n) + } + } else n += t[0]; + e = N.keywordPatternRe.lastIndex, t = N.keywordPatternRe.exec(R) + } + var i; + n += R.substring(e), M.addText(n) + } + + function g() { + null != N.subLanguage ? (() => { + if ("" === R) return; + let e = null; + if ("string" == typeof N.subLanguage) { + if (!i[N.subLanguage]) return void M.addText(R); + e = E(N.subLanguage, R, !0, S[N.subLanguage]), S[N.subLanguage] = e._top + } else e = x(R, N.subLanguage.length ? N.subLanguage : null); + N.relevance > 0 && (j += e.relevance), M.__addSublanguage(e._emitter, e.language) + })() : l(), R = "" + } + + function u(e, t) { + "" !== e && (M.startScope(t), M.addText(e), M.endScope()) + } + + function d(e, t) { + let n = 1; + const i = t.length - 1; + for (; n <= i;) { + if (!e._emit[n]) { + n++; + continue + } + const i = _.classNameAliases[e[n]] || e[n], + s = t[n]; + i ? u(s, i) : (R = s, l(), R = ""), n++ + } + } + + function h(e, t) { + return e.scope && "string" == typeof e.scope && M.openNode(_.classNameAliases[e.scope] || e + .scope), + e.beginScope && (e.beginScope._wrap ? (u(R, _.classNameAliases[e.beginScope._wrap] || e + .beginScope._wrap), + R = "") : e.beginScope._multi && (d(e.beginScope, t), R = "")), N = Object.create(e, { + parent: { + value: N + } + }), N + } + + function f(e, n, i) { + let s = ((e, t) => { + const n = e && e.exec(t); + return n && 0 === n.index + })(e.endRe, i); + if (s) { + if (e["on:end"]) { + const i = new t(e); + e["on:end"](n, i), i.isMatchIgnored && (s = !1) + } + if (s) { + for (; e.endsParent && e.parent;) e = e.parent; + return e + } + } + if (e.endsWithParent) return f(e.parent, n, i) + } + + function b(e) { + return 0 === N.matcher.regexIndex ? (R += e[0], 1) : (T = !0, 0) + } + + function m(e) { + const t = e[0], + i = n.substring(e.index), + s = f(N, e, i); + if (!s) return ee; + const o = N; + N.endScope && N.endScope._wrap ? (g(), + u(t, N.endScope._wrap)) : N.endScope && N.endScope._multi ? (g(), + d(N.endScope, e)) : o.skip ? R += t : (o.returnEnd || o.excludeEnd || (R += t), + g(), o.excludeEnd && (R = t)); + do { + N.scope && M.closeNode(), N.skip || N.subLanguage || (j += N.relevance), N = N.parent + } while (N !== s.parent); + return s.starts && h(s.starts, e), o.returnEnd ? 0 : t.length + } + let w = {}; + + function y(i, o) { + const a = o && o[0]; + if (R += i, null == a) return g(), 0; + if ("begin" === w.type && "end" === o.type && w.index === o.index && "" === a) { + if (R += n.slice(o.index, o.index + 1), !r) { + const t = Error(`0 width match regex (${e})`); + throw t.languageName = e, t.badRule = w.rule, t + } + return 1 + } + if (w = o, "begin" === o.type) return (e => { + const n = e[0], + i = e.rule, + s = new t(i), + o = [i.__beforeBegin, i["on:begin"]]; + for (const t of o) + if (t && (t(e, s), s.isMatchIgnored)) return b(n); + return i.skip ? R += n : (i.excludeBegin && (R += n), + g(), i.returnBegin || i.excludeBegin || (R = n)), h(i, e), i + .returnBegin ? 0 : n.length + })(o); + if ("illegal" === o.type && !s) { + const e = Error('Illegal lexeme "' + a + '" for mode "' + (N.scope || "") + '"'); + throw e.mode = N, e + } + if ("end" === o.type) { + const e = m(o); + if (e !== ee) return e + } + if ("illegal" === o.type && "" === a) return 1; + if (I > 1e5 && I > 3 * o.index) throw Error( + "potential infinite loop, way more iterations than matches"); + return R += a, a.length + } + const _ = O(e); + if (!_) throw W(a.replace("{}", e)), Error('Unknown language: "' + e + '"'); + const v = V(_); + let k = "", + N = o || v; + const S = {}, + M = new p.__emitter(p); + (() => { + const e = []; + for (let t = N; t !== _; t = t.parent) t.scope && e.unshift(t.scope); + e.forEach((e => M.openNode(e))) + })(); + let R = "", + j = 0, + A = 0, + I = 0, + T = !1; + try { + if (_.__emitTokens) _.__emitTokens(n, M); + else { + for (N.matcher.considerAll();;) { + I++, T ? T = !1 : N.matcher.considerAll(), N.matcher.lastIndex = A; + const e = N.matcher.exec(n); + if (!e) break; + const t = y(n.substring(A, e.index), e); + A = e.index + t + } + y(n.substring(A)) + } + return M.finalize(), k = M.toHTML(), { + language: e, + value: k, + relevance: j, + illegal: !1, + _emitter: M, + _top: N + } + } catch (t) { + if (t.message && t.message.includes("Illegal")) return { + language: e, + value: Y(n), + illegal: !0, + relevance: 0, + _illegalBy: { + message: t.message, + index: A, + context: n.slice(A - 100, A + 100), + mode: t.mode, + resultSoFar: k + }, + _emitter: M + }; + if (r) return { + language: e, + value: Y(n), + illegal: !1, + relevance: 0, + errorRaised: t, + _emitter: M, + _top: N + }; + throw t + } + } + + function x(e, t) { + t = t || p.languages || Object.keys(i); + const n = (e => { + const t = { + value: Y(e), + illegal: !1, + relevance: 0, + _top: l, + _emitter: new p.__emitter(p) + }; + return t._emitter.addText(e), t + })(e), + s = t.filter(O).filter(k).map((t => E(t, e, !1))); + s.unshift(n); + const o = s.sort(((e, t) => { + if (e.relevance !== t.relevance) return t.relevance - e.relevance; + if (e.language && t.language) { + if (O(e.language).supersetOf === t.language) return 1; + if (O(t.language).supersetOf === e.language) return -1 + } + return 0 + })), + [r, a] = o, + c = r; + return c.secondBest = a, c + } + + function w(e) { + let t = null; + const n = (e => { + let t = e.className + " "; + t += e.parentNode ? e.parentNode.className : ""; + const n = p.languageDetectRe.exec(t); + if (n) { + const t = O(n[1]); + return t || (X(a.replace("{}", n[1])), + X("Falling back to no-highlight mode for this block.", e)), t ? n[1] : + "no-highlight" + } + return t.split(/\s+/).find((e => b(e) || O(e))) + })(e); + if (b(n)) return; + if (N("before:highlightElement", { + el: e, + language: n + }), e.dataset.highlighted) return void console.log( + "Element previously highlighted. To highlight again, first unset `dataset.highlighted`.", + e); + if (e.children.length > 0 && (p.ignoreUnescapedHTML || (console.warn( + "One of your code blocks includes unescaped HTML. This is a potentially serious security risk." + ), + console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), + console.warn("The element with unescaped HTML:"), + console.warn(e)), p.throwUnescapedHTML)) throw new J( + "One of your code blocks includes unescaped HTML.", e.innerHTML); + t = e; + const i = t.textContent, + o = n ? m(i, { + language: n, + ignoreIllegals: !0 + }) : x(i); + e.innerHTML = o.value, e.dataset.highlighted = "yes", ((e, t, n) => { + const i = t && s[t] || n; + e.classList.add("hljs"), e.classList.add("language-" + i) + })(e, n, o.language), e.result = { + language: o.language, + re: o.relevance, + relevance: o.relevance + }, o.secondBest && (e.secondBest = { + language: o.secondBest.language, + relevance: o.secondBest.relevance + }), N("after:highlightElement", { + el: e, + result: o, + text: i + }) + } + let y = !1; + + function _() { + "loading" !== document.readyState ? document.querySelectorAll(p.cssSelector).forEach(w) : y = !0 + } + + function O(e) { + return e = (e || "").toLowerCase(), i[e] || i[s[e]] + } + + function v(e, { + languageName: t + }) { + "string" == typeof e && (e = [e]), e.forEach((e => { + s[e.toLowerCase()] = t + })) + } + + function k(e) { + const t = O(e); + return t && !t.disableAutodetect + } + + function N(e, t) { + const n = e; + o.forEach((e => { + e[n] && e[n](t) + })) + } + "undefined" != typeof window && window.addEventListener && window.addEventListener("DOMContentLoaded", ( + () => { + y && _() + }), !1), Object.assign(n, { + highlight: m, + highlightAuto: x, + highlightAll: _, + highlightElement: w, + highlightBlock: e => (G("10.7.0", "highlightBlock will be removed entirely in v12.0"), + G("10.7.0", "Please use highlightElement now."), w(e)), + configure: e => { + p = Q(p, e) + }, + initHighlighting: () => { + _(), G("10.6.0", "initHighlighting() deprecated. Use highlightAll() now.") + }, + initHighlightingOnLoad: () => { + _(), G("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now.") + }, + registerLanguage: (e, t) => { + let s = null; + try { + s = t(n) + } catch (t) { + if (W("Language definition for '{}' could not be registered.".replace("{}", e)), + !r) throw t; + W(t), s = l + } + s.name || (s.name = e), i[e] = s, s.rawDefinition = t.bind(null, n), s.aliases && v( + s.aliases, { + languageName: e + }) + }, + unregisterLanguage: e => { + delete i[e]; + for (const t of Object.keys(s)) s[t] === e && delete s[t] + }, + listLanguages: () => Object.keys(i), + getLanguage: O, + registerAliases: v, + autoDetection: k, + inherit: Q, + addPlugin: e => { + (e => { + e["before:highlightBlock"] && !e["before:highlightElement"] && (e[ + "before:highlightElement"] = t => { + e["before:highlightBlock"](Object.assign({ + block: t.el + }, t)) + }), e["after:highlightBlock"] && !e["after:highlightElement"] && (e[ + "after:highlightElement"] = t => { + e["after:highlightBlock"](Object.assign({ + block: t.el + }, t)) + }) + })(e), o.push(e) + }, + removePlugin: e => { + const t = o.indexOf(e); - 1 !== t && o.splice(t, 1) + } + }), n.debugMode = () => { + r = !1 + }, n.safeMode = () => { + r = !0 + }, n.versionString = "11.10.0", n.regex = { + concat: h, + lookahead: g, + either: f, + optional: d, + anyNumberOfTimes: u + }; + for (const t in j) "object" == typeof j[t] && e(j[t]); + return Object.assign(n, j), n + }, + ne = te({}); + return ne.newInstance = () => te({}), ne +}(); + +(() => { + var e = (() => { + "use strict"; + return e => { + const n = e.regex, + t = e.COMMENT("//", "$", { + contains: [{ + begin: /\\\n/ + }] + }), + a = "decltype\\(auto\\)", + s = "[a-zA-Z_]\\w*::", + i = "(" + a + "|" + n.optional(s) + "[a-zA-Z_]\\w*" + n.optional("<[^<>]+>") + ")", + r = { + className: "type", + variants: [{ + begin: "\\b[a-z\\d_]*_t\\b" + }, { + match: /\batomic_[a-z]{3,6}\b/ + }] + }, + l = { + className: "string", + variants: [{ + begin: '(u8?|U|L)?"', + end: '"', + illegal: "\\n", + contains: [e.BACKSLASH_ESCAPE] + }, { + begin: "(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", + end: "'", + illegal: "." + }, e.END_SAME_AS_BEGIN({ + begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/, + end: /\)([^()\\ ]{0,16})"/ + })] + }, + o = { + className: "number", + variants: [{ + begin: "\\b(0b[01']+)" + }, { + begin: "(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" + }, { + begin: "(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" + }], + relevance: 0 + }, + c = { + className: "meta", + begin: /#\s*[a-z]+\b/, + end: /$/, + keywords: { + keyword: "if else elif endif define undef warning error line pragma _Pragma ifdef ifndef elifdef elifndef include" + }, + contains: [{ + begin: /\\\n/, + relevance: 0 + }, e.inherit(l, { + className: "string" + }), { + className: "string", + begin: /<.*?>/ + }, t, e.C_BLOCK_COMMENT_MODE] + }, + d = { + className: "title", + begin: n.optional(s) + e.IDENT_RE, + relevance: 0 + }, + _ = n.optional(s) + e.IDENT_RE + "\\s*\\(", + u = { + keyword: ["asm", "auto", "break", "case", "continue", "default", "do", "else", + "enum", "extern", "for", "fortran", "goto", "if", "inline", "register", + "restrict", "return", "sizeof", "typeof", "typeof_unqual", "struct", + "switch", "typedef", "union", "volatile", "while", "_Alignas", "_Alignof", + "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local", + "alignas", "alignof", "noreturn", "static_assert", "thread_local", "_Pragma" + ], + type: ["float", "double", "signed", "unsigned", "int", "short", "long", "char", + "void", "_Bool", "_BitInt", "_Complex", "_Imaginary", "_Decimal32", + "_Decimal64", "_Decimal96", "_Decimal128", "_Decimal64x", "_Decimal128x", + "_Float16", "_Float32", "_Float64", "_Float128", "_Float32x", "_Float64x", + "_Float128x", "const", "static", "constexpr", "complex", "bool", "imaginary" + ], + literal: "true false NULL", + built_in: "std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" + }, + g = [c, r, t, e.C_BLOCK_COMMENT_MODE, o, l], + m = { + variants: [{ + begin: /=/, + end: /;/ + }, { + begin: /\(/, + end: /\)/ + }, { + beginKeywords: "new throw return else", + end: /;/ + }], + keywords: u, + contains: g.concat([{ + begin: /\(/, + end: /\)/, + keywords: u, + contains: g.concat(["self"]), + relevance: 0 + }]), + relevance: 0 + }, + p = { + begin: "(" + i + "[\\*&\\s]+)+" + _, + returnBegin: !0, + end: /[{;=]/, + excludeEnd: !0, + keywords: u, + illegal: /[^\w\s\*&:<>.]/, + contains: [{ + begin: a, + keywords: u, + relevance: 0 + }, { + begin: _, + returnBegin: !0, + contains: [e.inherit(d, { + className: "title.function" + })], + relevance: 0 + }, { + relevance: 0, + match: /,/ + }, { + className: "params", + begin: /\(/, + end: /\)/, + keywords: u, + relevance: 0, + contains: [t, e.C_BLOCK_COMMENT_MODE, l, o, r, { + begin: /\(/, + end: /\)/, + keywords: u, + relevance: 0, + contains: ["self", t, e.C_BLOCK_COMMENT_MODE, l, o, r] + }] + }, r, t, e.C_BLOCK_COMMENT_MODE, c] + }; + return { + name: "C", + aliases: ["h"], + keywords: u, + disableAutodetect: !0, + illegal: "=]/, + contains: [{ + beginKeywords: "final class struct" + }, e.TITLE_MODE] + }]), + exports: { + preprocessor: c, + strings: l, + keywords: u + } + } + } + })(); + hljs.registerLanguage("c", e) +})(); /*! `cpp` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const t = e.regex, + a = e.COMMENT("//", "$", { + contains: [{ + begin: /\\\n/ + }] + }), + n = "decltype\\(auto\\)", + r = "[a-zA-Z_]\\w*::", + i = "(?!struct)(" + n + "|" + t.optional(r) + "[a-zA-Z_]\\w*" + t.optional("<[^<>]+>") + + ")", + s = { + className: "type", + begin: "\\b[a-z\\d_]*_t\\b" + }, + c = { + className: "string", + variants: [{ + begin: '(u8?|U|L)?"', + end: '"', + illegal: "\\n", + contains: [e.BACKSLASH_ESCAPE] + }, { + begin: "(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", + end: "'", + illegal: "." + }, e.END_SAME_AS_BEGIN({ + begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/, + end: /\)([^()\\ ]{0,16})"/ + })] + }, + o = { + className: "number", + variants: [{ + begin: "[+-]?(?:(?:[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?|\\.[0-9](?:'?[0-9])*)(?:[Ee][+-]?[0-9](?:'?[0-9])*)?|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*|0[Xx](?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)[Pp][+-]?[0-9](?:'?[0-9])*)(?:[Ff](?:16|32|64|128)?|(BF|bf)16|[Ll]|)" + }, { + begin: "[+-]?\\b(?:0[Bb][01](?:'?[01])*|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*|0(?:'?[0-7])*|[1-9](?:'?[0-9])*)(?:[Uu](?:LL?|ll?)|[Uu][Zz]?|(?:LL?|ll?)[Uu]?|[Zz][Uu]|)" + }], + relevance: 0 + }, + l = { + className: "meta", + begin: /#\s*[a-z]+\b/, + end: /$/, + keywords: { + keyword: "if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" + }, + contains: [{ + begin: /\\\n/, + relevance: 0 + }, e.inherit(c, { + className: "string" + }), { + className: "string", + begin: /<.*?>/ + }, a, e.C_BLOCK_COMMENT_MODE] + }, + u = { + className: "title", + begin: t.optional(r) + e.IDENT_RE, + relevance: 0 + }, + d = t.optional(r) + e.IDENT_RE + "\\s*\\(", + p = { + type: ["bool", "char", "char16_t", "char32_t", "char8_t", "double", "float", "int", + "long", "short", "void", "wchar_t", "unsigned", "signed", "const", "static" + ], + keyword: ["alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", + "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "break", + "case", "catch", "class", "co_await", "co_return", "co_yield", "compl", + "concept", "const_cast|10", "consteval", "constexpr", "constinit", + "continue", "decltype", "default", "delete", "do", "dynamic_cast|10", + "else", "enum", "explicit", "export", "extern", "false", "final", "for", + "friend", "goto", "if", "import", "inline", "module", "mutable", + "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", + "or", "or_eq", "override", "private", "protected", "public", "reflexpr", + "register", "reinterpret_cast|10", "requires", "return", "sizeof", + "static_assert", "static_cast|10", "struct", "switch", "synchronized", + "template", "this", "thread_local", "throw", "transaction_safe", + "transaction_safe_dynamic", "true", "try", "typedef", "typeid", "typename", + "union", "using", "virtual", "volatile", "while", "xor", "xor_eq" + ], + literal: ["NULL", "false", "nullopt", "nullptr", "true"], + built_in: ["_Pragma"], + _type_hints: ["any", "auto_ptr", "barrier", "binary_semaphore", "bitset", "complex", + "condition_variable", "condition_variable_any", "counting_semaphore", + "deque", "false_type", "future", "imaginary", "initializer_list", + "istringstream", "jthread", "latch", "lock_guard", "multimap", "multiset", + "mutex", "optional", "ostringstream", "packaged_task", "pair", "promise", + "priority_queue", "queue", "recursive_mutex", "recursive_timed_mutex", + "scoped_lock", "set", "shared_future", "shared_lock", "shared_mutex", + "shared_timed_mutex", "shared_ptr", "stack", "string_view", "stringstream", + "timed_mutex", "thread", "true_type", "tuple", "unique_lock", "unique_ptr", + "unordered_map", "unordered_multimap", "unordered_multiset", + "unordered_set", "variant", "vector", "weak_ptr", "wstring", "wstring_view" + ] + }, + _ = { + className: "function.dispatch", + relevance: 0, + keywords: { + _hint: ["abort", "abs", "acos", "apply", "as_const", "asin", "atan", "atan2", + "calloc", "ceil", "cerr", "cin", "clog", "cos", "cosh", "cout", + "declval", "endl", "exchange", "exit", "exp", "fabs", "floor", "fmod", + "forward", "fprintf", "fputs", "free", "frexp", "fscanf", "future", + "invoke", "isalnum", "isalpha", "iscntrl", "isdigit", "isgraph", + "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit", + "labs", "launder", "ldexp", "log", "log10", "make_pair", "make_shared", + "make_shared_for_overwrite", "make_tuple", "make_unique", "malloc", + "memchr", "memcmp", "memcpy", "memset", "modf", "move", "pow", "printf", + "putchar", "puts", "realloc", "scanf", "sin", "sinh", "snprintf", + "sprintf", "sqrt", "sscanf", "std", "stderr", "stdin", "stdout", + "strcat", "strchr", "strcmp", "strcpy", "strcspn", "strlen", "strncat", + "strncmp", "strncpy", "strpbrk", "strrchr", "strspn", "strstr", "swap", + "tan", "tanh", "terminate", "to_underlying", "tolower", "toupper", + "vfprintf", "visit", "vprintf", "vsprintf" + ] + }, + begin: t.concat(/\b/, /(?!decltype)/, /(?!if)/, /(?!for)/, /(?!switch)/, + /(?!while)/, e.IDENT_RE, t.lookahead(/(<[^<>]+>|)\s*\(/)) + }, + m = [_, l, s, a, e.C_BLOCK_COMMENT_MODE, o, c], + f = { + variants: [{ + begin: /=/, + end: /;/ + }, { + begin: /\(/, + end: /\)/ + }, { + beginKeywords: "new throw return else", + end: /;/ + }], + keywords: p, + contains: m.concat([{ + begin: /\(/, + end: /\)/, + keywords: p, + contains: m.concat(["self"]), + relevance: 0 + }]), + relevance: 0 + }, + g = { + className: "function", + begin: "(" + i + "[\\*&\\s]+)+" + d, + returnBegin: !0, + end: /[{;=]/, + excludeEnd: !0, + keywords: p, + illegal: /[^\w\s\*&:<>.]/, + contains: [{ + begin: n, + keywords: p, + relevance: 0 + }, { + begin: d, + returnBegin: !0, + contains: [u], + relevance: 0 + }, { + begin: /::/, + relevance: 0 + }, { + begin: /:/, + endsWithParent: !0, + contains: [c, o] + }, { + relevance: 0, + match: /,/ + }, { + className: "params", + begin: /\(/, + end: /\)/, + keywords: p, + relevance: 0, + contains: [a, e.C_BLOCK_COMMENT_MODE, c, o, s, { + begin: /\(/, + end: /\)/, + keywords: p, + relevance: 0, + contains: ["self", a, e.C_BLOCK_COMMENT_MODE, c, o, s] + }] + }, s, a, e.C_BLOCK_COMMENT_MODE, l] + }; + return { + name: "C++", + aliases: ["cc", "c++", "h++", "hpp", "hh", "hxx", "cxx"], + keywords: p, + illegal: "", + keywords: p, + contains: ["self", s] + }, { + begin: e.IDENT_RE + "::", + keywords: p + }, { + match: [/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/, /\s+/, + /\w+/ + ], + className: { + 1: "keyword", + 3: "title.class" + } + }]) + } + } + })(); + hljs.registerLanguage("cpp", e) +})(); /*! `css` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + const e = ["a", "abbr", "address", "article", "aside", "audio", "b", "blockquote", "body", "button", + "canvas", "caption", "cite", "code", "dd", "del", "details", "dfn", "div", "dl", "dt", "em", + "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", + "header", "hgroup", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", + "li", "main", "mark", "menu", "nav", "object", "ol", "optgroup", "option", "p", "picture", + "q", "quote", "samp", "section", "select", "source", "span", "strong", "summary", "sup", + "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "time", "tr", "ul", "var", + "video", "defs", "g", "marker", "mask", "pattern", "svg", "switch", "symbol", "feBlend", + "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", + "feDiffuseLighting", "feDisplacementMap", "feFlood", "feGaussianBlur", "feImage", "feMerge", + "feMorphology", "feOffset", "feSpecularLighting", "feTile", "feTurbulence", + "linearGradient", "radialGradient", "stop", "circle", "ellipse", "image", "line", "path", + "polygon", "polyline", "rect", "text", "use", "textPath", "tspan", "foreignObject", + "clipPath" + ], + r = ["any-hover", "any-pointer", "aspect-ratio", "color", "color-gamut", "color-index", + "device-aspect-ratio", "device-height", "device-width", "display-mode", "forced-colors", + "grid", "height", "hover", "inverted-colors", "monochrome", "orientation", "overflow-block", + "overflow-inline", "pointer", "prefers-color-scheme", "prefers-contrast", + "prefers-reduced-motion", "prefers-reduced-transparency", "resolution", "scan", "scripting", + "update", "width", "min-width", "max-width", "min-height", "max-height" + ].sort().reverse(), + t = ["active", "any-link", "blank", "checked", "current", "default", "defined", "dir", + "disabled", "drop", "empty", "enabled", "first", "first-child", "first-of-type", + "fullscreen", "future", "focus", "focus-visible", "focus-within", "has", "host", + "host-context", "hover", "indeterminate", "in-range", "invalid", "is", "lang", "last-child", + "last-of-type", "left", "link", "local-link", "not", "nth-child", "nth-col", + "nth-last-child", "nth-last-col", "nth-last-of-type", "nth-of-type", "only-child", + "only-of-type", "optional", "out-of-range", "past", "placeholder-shown", "read-only", + "read-write", "required", "right", "root", "scope", "target", "target-within", + "user-invalid", "valid", "visited", "where" + ].sort().reverse(), + i = ["after", "backdrop", "before", "cue", "cue-region", "first-letter", "first-line", + "grammar-error", "marker", "part", "placeholder", "selection", "slotted", "spelling-error" + ].sort().reverse(), + o = ["accent-color", "align-content", "align-items", "align-self", "alignment-baseline", "all", + "animation", "animation-delay", "animation-direction", "animation-duration", + "animation-fill-mode", "animation-iteration-count", "animation-name", + "animation-play-state", "animation-timing-function", "appearance", "backface-visibility", + "background", "background-attachment", "background-blend-mode", "background-clip", + "background-color", "background-image", "background-origin", "background-position", + "background-repeat", "background-size", "baseline-shift", "block-size", "border", + "border-block", "border-block-color", "border-block-end", "border-block-end-color", + "border-block-end-style", "border-block-end-width", "border-block-start", + "border-block-start-color", "border-block-start-style", "border-block-start-width", + "border-block-style", "border-block-width", "border-bottom", "border-bottom-color", + "border-bottom-left-radius", "border-bottom-right-radius", "border-bottom-style", + "border-bottom-width", "border-collapse", "border-color", "border-image", + "border-image-outset", "border-image-repeat", "border-image-slice", "border-image-source", + "border-image-width", "border-inline", "border-inline-color", "border-inline-end", + "border-inline-end-color", "border-inline-end-style", "border-inline-end-width", + "border-inline-start", "border-inline-start-color", "border-inline-start-style", + "border-inline-start-width", "border-inline-style", "border-inline-width", "border-left", + "border-left-color", "border-left-style", "border-left-width", "border-radius", + "border-right", "border-end-end-radius", "border-end-start-radius", "border-right-color", + "border-right-style", "border-right-width", "border-spacing", "border-start-end-radius", + "border-start-start-radius", "border-style", "border-top", "border-top-color", + "border-top-left-radius", "border-top-right-radius", "border-top-style", "border-top-width", + "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing", "break-after", + "break-before", "break-inside", "cx", "cy", "caption-side", "caret-color", "clear", "clip", + "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", + "color-profile", "color-rendering", "color-scheme", "column-count", "column-fill", + "column-gap", "column-rule", "column-rule-color", "column-rule-style", "column-rule-width", + "column-span", "column-width", "columns", "contain", "content", "content-visibility", + "counter-increment", "counter-reset", "cue", "cue-after", "cue-before", "cursor", + "direction", "display", "dominant-baseline", "empty-cells", "enable-background", "fill", + "fill-opacity", "fill-rule", "filter", "flex", "flex-basis", "flex-direction", "flex-flow", + "flex-grow", "flex-shrink", "flex-wrap", "float", "flow", "flood-color", "flood-opacity", + "font", "font-display", "font-family", "font-feature-settings", "font-kerning", + "font-language-override", "font-size", "font-size-adjust", "font-smoothing", "font-stretch", + "font-style", "font-synthesis", "font-variant", "font-variant-caps", + "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", + "font-variant-position", "font-variation-settings", "font-weight", "gap", + "glyph-orientation-horizontal", "glyph-orientation-vertical", "grid", "grid-area", + "grid-auto-columns", "grid-auto-flow", "grid-auto-rows", "grid-column", "grid-column-end", + "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-start", + "grid-template", "grid-template-areas", "grid-template-columns", "grid-template-rows", + "hanging-punctuation", "height", "hyphens", "icon", "image-orientation", "image-rendering", + "image-resolution", "ime-mode", "inline-size", "inset", "inset-block", "inset-block-end", + "inset-block-start", "inset-inline", "inset-inline-end", "inset-inline-start", "isolation", + "kerning", "justify-content", "justify-items", "justify-self", "left", "letter-spacing", + "lighting-color", "line-break", "line-height", "list-style", "list-style-image", + "list-style-position", "list-style-type", "marker", "marker-end", "marker-mid", + "marker-start", "mask", "margin", "margin-block", "margin-block-end", "margin-block-start", + "margin-bottom", "margin-inline", "margin-inline-end", "margin-inline-start", "margin-left", + "margin-right", "margin-top", "marks", "mask", "mask-border", "mask-border-mode", + "mask-border-outset", "mask-border-repeat", "mask-border-slice", "mask-border-source", + "mask-border-width", "mask-clip", "mask-composite", "mask-image", "mask-mode", + "mask-origin", "mask-position", "mask-repeat", "mask-size", "mask-type", "max-block-size", + "max-height", "max-inline-size", "max-width", "min-block-size", "min-height", + "min-inline-size", "min-width", "mix-blend-mode", "nav-down", "nav-index", "nav-left", + "nav-right", "nav-up", "none", "normal", "object-fit", "object-position", "opacity", + "order", "orphans", "outline", "outline-color", "outline-offset", "outline-style", + "outline-width", "overflow", "overflow-wrap", "overflow-x", "overflow-y", "padding", + "padding-block", "padding-block-end", "padding-block-start", "padding-bottom", + "padding-inline", "padding-inline-end", "padding-inline-start", "padding-left", + "padding-right", "padding-top", "page-break-after", "page-break-before", + "page-break-inside", "pause", "pause-after", "pause-before", "perspective", + "perspective-origin", "pointer-events", "position", "quotes", "r", "resize", "rest", + "rest-after", "rest-before", "right", "rotate", "row-gap", "scale", "scroll-margin", + "scroll-margin-block", "scroll-margin-block-end", "scroll-margin-block-start", + "scroll-margin-bottom", "scroll-margin-inline", "scroll-margin-inline-end", + "scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right", + "scroll-margin-top", "scroll-padding", "scroll-padding-block", "scroll-padding-block-end", + "scroll-padding-block-start", "scroll-padding-bottom", "scroll-padding-inline", + "scroll-padding-inline-end", "scroll-padding-inline-start", "scroll-padding-left", + "scroll-padding-right", "scroll-padding-top", "scroll-snap-align", "scroll-snap-stop", + "scroll-snap-type", "scrollbar-color", "scrollbar-gutter", "scrollbar-width", + "shape-image-threshold", "shape-margin", "shape-outside", "shape-rendering", "stop-color", + "stop-opacity", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", + "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "speak", + "speak-as", "src", "tab-size", "table-layout", "text-anchor", "text-align", + "text-align-all", "text-align-last", "text-combine-upright", "text-decoration", + "text-decoration-color", "text-decoration-line", "text-decoration-skip-ink", + "text-decoration-style", "text-decoration-thickness", "text-emphasis", + "text-emphasis-color", "text-emphasis-position", "text-emphasis-style", "text-indent", + "text-justify", "text-orientation", "text-overflow", "text-rendering", "text-shadow", + "text-transform", "text-underline-offset", "text-underline-position", "top", "transform", + "transform-box", "transform-origin", "transform-style", "transition", "transition-delay", + "transition-duration", "transition-property", "transition-timing-function", "translate", + "unicode-bidi", "vector-effect", "vertical-align", "visibility", "voice-balance", + "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate", + "voice-stress", "voice-volume", "white-space", "widows", "width", "will-change", + "word-break", "word-spacing", "word-wrap", "writing-mode", "x", "y", "z-index" + ].sort().reverse(); + return n => { + const a = n.regex, + l = (e => ({ + IMPORTANT: { + scope: "meta", + begin: "!important" + }, + BLOCK_COMMENT: e.C_BLOCK_COMMENT_MODE, + HEXCOLOR: { + scope: "number", + begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/ + }, + FUNCTION_DISPATCH: { + className: "built_in", + begin: /[\w-]+(?=\()/ + }, + ATTRIBUTE_SELECTOR_MODE: { + scope: "selector-attr", + begin: /\[/, + end: /\]/, + illegal: "$", + contains: [e.APOS_STRING_MODE, e.QUOTE_STRING_MODE] + }, + CSS_NUMBER_MODE: { + scope: "number", + begin: e.NUMBER_RE + + "(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", + relevance: 0 + }, + CSS_VARIABLE: { + className: "attr", + begin: /--[A-Za-z_][A-Za-z0-9_-]*/ + } + }))(n), + s = [n.APOS_STRING_MODE, n.QUOTE_STRING_MODE]; + return { + name: "CSS", + case_insensitive: !0, + illegal: /[=|'\$]/, + keywords: { + keyframePosition: "from to" + }, + classNameAliases: { + keyframePosition: "selector-tag" + }, + contains: [l.BLOCK_COMMENT, { + begin: /-(webkit|moz|ms|o)-(?=[a-z])/ + }, l.CSS_NUMBER_MODE, { + className: "selector-id", + begin: /#[A-Za-z0-9_-]+/, + relevance: 0 + }, { + className: "selector-class", + begin: "\\.[a-zA-Z-][a-zA-Z0-9_-]*", + relevance: 0 + }, l.ATTRIBUTE_SELECTOR_MODE, { + className: "selector-pseudo", + variants: [{ + begin: ":(" + t.join("|") + ")" + }, { + begin: ":(:)?(" + i.join("|") + ")" + }] + }, l.CSS_VARIABLE, { + className: "attribute", + begin: "\\b(" + o.join("|") + ")\\b" + }, { + begin: /:/, + end: /[;}{]/, + contains: [l.BLOCK_COMMENT, l.HEXCOLOR, l.IMPORTANT, l.CSS_NUMBER_MODE, ... + s, { + begin: /(url|data-uri)\(/, + end: /\)/, + relevance: 0, + keywords: { + built_in: "url data-uri" + }, + contains: [...s, { + className: "string", + begin: /[^)]/, + endsWithParent: !0, + excludeEnd: !0 + }] + }, + l.FUNCTION_DISPATCH + ] + }, { + begin: a.lookahead(/@/), + end: "[{;]", + relevance: 0, + illegal: /:/, + contains: [{ + className: "keyword", + begin: /@-?\w[\w]*(-\w+)*/ + }, { + begin: /\s/, + endsWithParent: !0, + excludeEnd: !0, + relevance: 0, + keywords: { + $pattern: /[a-z-]+/, + keyword: "and or not only", + attribute: r.join(" ") + }, + contains: [{ + begin: /[a-z-]+(?=:)/, + className: "attribute" + }, ...s, l.CSS_NUMBER_MODE] + }] + }, { + className: "selector-tag", + begin: "\\b(" + e.join("|") + ")\\b" + }] + } + } + })(); + hljs.registerLanguage("css", e) +})(); /*! `go` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const a = { + keyword: ["break", "case", "chan", "const", "continue", "default", "defer", "else", + "fallthrough", "for", "func", "go", "goto", "if", "import", "interface", + "map", "package", "range", "return", "select", "struct", "switch", "type", + "var" + ], + type: ["bool", "byte", "complex64", "complex128", "error", "float32", "float64", + "int8", "int16", "int32", "int64", "string", "uint8", "uint16", "uint32", + "uint64", "int", "uint", "uintptr", "rune" + ], + literal: ["true", "false", "iota", "nil"], + built_in: ["append", "cap", "close", "complex", "copy", "imag", "len", "make", + "new", "panic", "print", "println", "real", "recover", "delete" + ] + }; + return { + name: "Go", + aliases: ["golang"], + keywords: a, + illegal: " { + var e = (() => { + "use strict"; + return e => { + const n = "HTTP/([32]|1\\.[01])", + a = { + className: "attribute", + begin: e.regex.concat("^", /[A-Za-z][A-Za-z0-9-]*/, "(?=\\:\\s)"), + starts: { + contains: [{ + className: "punctuation", + begin: /: /, + relevance: 0, + starts: { + end: "$", + relevance: 0 + } + }] + } + }, + s = [a, { + begin: "\\n\\n", + starts: { + subLanguage: [], + endsWithParent: !0 + } + }]; + return { + name: "HTTP", + aliases: ["https"], + illegal: /\S/, + contains: [{ + begin: "^(?=" + n + " \\d{3})", + end: /$/, + contains: [{ + className: "meta", + begin: n + }, { + className: "number", + begin: "\\b\\d{3}\\b" + }], + starts: { + end: /\b\B/, + illegal: /\S/, + contains: s + } + }, { + begin: "(?=^[A-Z]+ (.*?) " + n + "$)", + end: /$/, + contains: [{ + className: "string", + begin: " ", + end: " ", + excludeBegin: !0, + excludeEnd: !0 + }, { + className: "meta", + begin: n + }, { + className: "keyword", + begin: "[A-Z]+" + }], + starts: { + end: /\b\B/, + illegal: /\S/, + contains: s + } + }, e.inherit(a, { + relevance: 0 + })] + } + } + })(); + hljs.registerLanguage("http", e) +})(); /*! `ini` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const n = e.regex, + a = { + className: "number", + relevance: 0, + variants: [{ + begin: /([+-]+)?[\d]+_[\d_]+/ + }, { + begin: e.NUMBER_RE + }] + }, + s = e.COMMENT(); + s.variants = [{ + begin: /;/, + end: /$/ + }, { + begin: /#/, + end: /$/ + }]; + const i = { + className: "variable", + variants: [{ + begin: /\$[\w\d"][\w\d_]*/ + }, { + begin: /\$\{(.*?)\}/ + }] + }, + t = { + className: "literal", + begin: /\bon|off|true|false|yes|no\b/ + }, + r = { + className: "string", + contains: [e.BACKSLASH_ESCAPE], + variants: [{ + begin: "'''", + end: "'''", + relevance: 10 + }, { + begin: '"""', + end: '"""', + relevance: 10 + }, { + begin: '"', + end: '"' + }, { + begin: "'", + end: "'" + }] + }, + l = { + begin: /\[/, + end: /\]/, + contains: [s, t, i, r, a, "self"], + relevance: 0 + }, + c = n.either(/[A-Za-z0-9_-]+/, /"(\\"|[^"])*"/, /'[^']*'/); + return { + name: "TOML, also INI", + aliases: ["toml"], + case_insensitive: !0, + illegal: /\S/, + contains: [s, { + className: "section", + begin: /\[+/, + end: /\]+/ + }, { + begin: n.concat(c, "(\\s*\\.\\s*", c, ")*", n.lookahead(/\s*=\s*[^#\s]/)), + className: "attr", + starts: { + end: /$/, + contains: [s, l, t, i, r, a] + } + }] + } + } + })(); + hljs.registerLanguage("ini", e) +})(); /*! `java` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + var e = "[0-9](_*[0-9])*", + a = `\\.(${e})`, + n = "[0-9a-fA-F](_*[0-9a-fA-F])*", + s = { + className: "number", + variants: [{ + begin: `(\\b(${e})((${a})|\\.)?|(${a}))[eE][+-]?(${e})[fFdD]?\\b` + }, { + begin: `\\b(${e})((${a})[fFdD]?\\b|\\.([fFdD]\\b)?)` + }, { + begin: `(${a})[fFdD]?\\b` + }, { + begin: `\\b(${e})[fFdD]\\b` + }, { + begin: `\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?(${e})[fFdD]?\\b` + }, { + begin: "\\b(0|[1-9](_*[0-9])*)[lL]?\\b" + }, { + begin: `\\b0[xX](${n})[lL]?\\b` + }, { + begin: "\\b0(_*[0-7])*[lL]?\\b" + }, { + begin: "\\b0[bB][01](_*[01])*[lL]?\\b" + }], + relevance: 0 + }; + + function t(e, a, n) { + return -1 === n ? "" : e.replace(a, (s => t(e, a, n - 1))) + } + return e => { + const a = e.regex, + n = "[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*", + i = n + t("(?:<" + n + "~~~(?:\\s*,\\s*" + n + "~~~)*>)?", /~~~/g, 2), + r = { + keyword: ["synchronized", "abstract", "private", "var", "static", "if", "const ", + "for", "while", "strictfp", "finally", "protected", "import", "native", + "final", "void", "enum", "else", "break", "transient", "catch", + "instanceof", "volatile", "case", "assert", "package", "default", "public", + "try", "switch", "continue", "throws", "protected", "public", "private", + "module", "requires", "exports", "do", "sealed", "yield", "permits", "goto" + ], + literal: ["false", "true", "null"], + type: ["char", "boolean", "long", "float", "int", "byte", "short", "double"], + built_in: ["super", "this"] + }, + l = { + className: "meta", + begin: "@" + n, + contains: [{ + begin: /\(/, + end: /\)/, + contains: ["self"] + }] + }, + c = { + className: "params", + begin: /\(/, + end: /\)/, + keywords: r, + relevance: 0, + contains: [e.C_BLOCK_COMMENT_MODE], + endsParent: !0 + }; + return { + name: "Java", + aliases: ["jsp"], + keywords: r, + illegal: /<\/|#/, + contains: [e.COMMENT("/\\*\\*", "\\*/", { + relevance: 0, + contains: [{ + begin: /\w+@/, + relevance: 0 + }, { + className: "doctag", + begin: "@[A-Za-z]+" + }] + }), { + begin: /import java\.[a-z]+\./, + keywords: "import", + relevance: 2 + }, e.C_LINE_COMMENT_MODE, e.C_BLOCK_COMMENT_MODE, { + begin: /"""/, + end: /"""/, + className: "string", + contains: [e.BACKSLASH_ESCAPE] + }, e.APOS_STRING_MODE, e.QUOTE_STRING_MODE, { + match: [/\b(?:class|interface|enum|extends|implements|new)/, /\s+/, n], + className: { + 1: "keyword", + 3: "title.class" + } + }, { + match: /non-sealed/, + scope: "keyword" + }, { + begin: [a.concat(/(?!else)/, n), /\s+/, n, /\s+/, /=(?!=)/], + className: { + 1: "type", + 3: "variable", + 5: "operator" + } + }, { + begin: [/record/, /\s+/, n], + className: { + 1: "keyword", + 3: "title.class" + }, + contains: [c, e.C_LINE_COMMENT_MODE, e.C_BLOCK_COMMENT_MODE] + }, { + beginKeywords: "new throw return else", + relevance: 0 + }, { + begin: ["(?:" + i + "\\s+)", e.UNDERSCORE_IDENT_RE, /\s*(?=\()/], + className: { + 2: "title.function" + }, + keywords: r, + contains: [{ + className: "params", + begin: /\(/, + end: /\)/, + keywords: r, + relevance: 0, + contains: [l, e.APOS_STRING_MODE, e.QUOTE_STRING_MODE, s, e + .C_BLOCK_COMMENT_MODE + ] + }, e.C_LINE_COMMENT_MODE, e.C_BLOCK_COMMENT_MODE] + }, s, l] + } + } + })(); + hljs.registerLanguage("java", e) +})(); /*! `javascript` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + const e = "[A-Za-z$_][0-9A-Za-z$_]*", + n = ["as", "in", "of", "if", "for", "while", "finally", "var", "new", "function", "do", + "return", "void", "else", "break", "catch", "instanceof", "with", "throw", "case", + "default", "try", "switch", "continue", "typeof", "delete", "let", "yield", "const", + "class", "debugger", "async", "await", "static", "import", "from", "export", "extends" + ], + a = ["true", "false", "null", "undefined", "NaN", "Infinity"], + t = ["Object", "Function", "Boolean", "Symbol", "Math", "Date", "Number", "BigInt", "String", + "RegExp", "Array", "Float32Array", "Float64Array", "Int8Array", "Uint8Array", + "Uint8ClampedArray", "Int16Array", "Int32Array", "Uint16Array", "Uint32Array", + "BigInt64Array", "BigUint64Array", "Set", "Map", "WeakSet", "WeakMap", "ArrayBuffer", + "SharedArrayBuffer", "Atomics", "DataView", "JSON", "Promise", "Generator", + "GeneratorFunction", "AsyncFunction", "Reflect", "Proxy", "Intl", "WebAssembly" + ], + s = ["Error", "EvalError", "InternalError", "RangeError", "ReferenceError", "SyntaxError", + "TypeError", "URIError" + ], + r = ["setInterval", "setTimeout", "clearInterval", "clearTimeout", "require", "exports", "eval", + "isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", + "encodeURI", "encodeURIComponent", "escape", "unescape" + ], + c = ["arguments", "this", "super", "console", "window", "document", "localStorage", + "sessionStorage", "module", "global" + ], + i = [].concat(r, t, s); + return o => { + const l = o.regex, + b = e, + d = { + begin: /<[A-Za-z0-9\\._:-]+/, + end: /\/[A-Za-z0-9\\._:-]+>|\/>/, + isTrulyOpeningTag: (e, n) => { + const a = e[0].length + e.index, + t = e.input[a]; + if ("<" === t || "," === t) return void n.ignoreMatch(); + let s; + ">" === t && (((e, { + after: n + }) => { + const a = " e + "\\s*\\(")), + l.concat("(?!", T.join("|"), ")")), b, l.lookahead(/\s*\(/)), + className: "title.function", + relevance: 0 + }; + var T; + const C = { + begin: l.concat(/\./, l.lookahead(l.concat(b, /(?![0-9A-Za-z$_(])/))), + end: b, + excludeBegin: !0, + keywords: "prototype", + className: "property", + relevance: 0 + }, + M = { + match: [/get|set/, /\s+/, b, /(?=\()/], + className: { + 1: "keyword", + 3: "title.function" + }, + contains: [{ + begin: /\(\)/ + }, R] + }, + B = "(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|" + o.UNDERSCORE_IDENT_RE + + ")\\s*=>", + $ = { + match: [/const|var|let/, /\s+/, b, /\s*/, /=\s*/, /(async\s*)?/, l.lookahead(B)], + keywords: "async", + className: { + 1: "keyword", + 3: "title.function" + }, + contains: [R] + }; + return { + name: "JavaScript", + aliases: ["js", "jsx", "mjs", "cjs"], + keywords: g, + exports: { + PARAMS_CONTAINS: w, + CLASS_REFERENCE: k + }, + illegal: /#(?![$_A-z])/, + contains: [o.SHEBANG({ + label: "shebang", + binary: "node", + relevance: 5 + }), { + label: "use_strict", + className: "meta", + relevance: 10, + begin: /^\s*['"]use (strict|asm)['"]/ + }, o.APOS_STRING_MODE, o.QUOTE_STRING_MODE, h, N, _, f, p, { + match: /\$\d+/ + }, A, k, { + className: "attr", + begin: b + l.lookahead(":"), + relevance: 0 + }, $, { + begin: "(" + o.RE_STARTERS_RE + "|\\b(case|return|throw)\\b)\\s*", + keywords: "return throw case", + relevance: 0, + contains: [p, o.REGEXP_MODE, { + className: "function", + begin: B, + returnBegin: !0, + end: "\\s*=>", + contains: [{ + className: "params", + variants: [{ + begin: o.UNDERSCORE_IDENT_RE, + relevance: 0 + }, { + className: null, + begin: /\(\s*\)/, + skip: !0 + }, { + begin: /(\s*)\(/, + end: /\)/, + excludeBegin: !0, + excludeEnd: !0, + keywords: g, + contains: w + }] + }] + }, { + begin: /,/, + relevance: 0 + }, { + match: /\s+/, + relevance: 0 + }, { + variants: [{ + begin: "<>", + end: "" + }, { + match: /<[A-Za-z0-9\\._:-]+\s*\/>/ + }, { + begin: d.begin, + "on:begin": d.isTrulyOpeningTag, + end: d.end + }], + subLanguage: "xml", + contains: [{ + begin: d.begin, + end: d.end, + skip: !0, + contains: ["self"] + }] + }] + }, I, { + beginKeywords: "while if switch catch for" + }, { + begin: "\\b(?!function)" + o.UNDERSCORE_IDENT_RE + + "\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", + returnBegin: !0, + label: "func.def", + contains: [R, o.inherit(o.TITLE_MODE, { + begin: b, + className: "title.function" + })] + }, { + match: /\.\.\./, + relevance: 0 + }, C, { + match: "\\$" + b, + relevance: 0 + }, { + match: [/\bconstructor(?=\s*\()/], + className: { + 1: "title.function" + }, + contains: [R] + }, x, { + relevance: 0, + match: /\b[A-Z][A-Z_0-9]+\b/, + className: "variable.constant" + }, O, M, { + match: /\$[(.]/ + }] + } + } + })(); + hljs.registerLanguage("javascript", e) +})(); /*! `json` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const a = ["true", "false", "null"], + s = { + scope: "literal", + beginKeywords: a.join(" ") + }; + return { + name: "JSON", + aliases: ["jsonc"], + keywords: { + literal: a + }, + contains: [{ + className: "attr", + begin: /"(\\.|[^\\"\r\n])*"(?=\s*:)/, + relevance: 1.01 + }, { + match: /[{}[\],:]/, + className: "punctuation", + relevance: 0 + }, e.QUOTE_STRING_MODE, s, e.C_NUMBER_MODE, e.C_LINE_COMMENT_MODE, e + .C_BLOCK_COMMENT_MODE + ], + illegal: "\\S" + } + } + })(); + hljs.registerLanguage("json", e) +})(); /*! `less` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + const e = ["a", "abbr", "address", "article", "aside", "audio", "b", "blockquote", "body", "button", + "canvas", "caption", "cite", "code", "dd", "del", "details", "dfn", "div", "dl", "dt", "em", + "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", + "header", "hgroup", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", + "li", "main", "mark", "menu", "nav", "object", "ol", "optgroup", "option", "p", "picture", + "q", "quote", "samp", "section", "select", "source", "span", "strong", "summary", "sup", + "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "time", "tr", "ul", "var", + "video", "defs", "g", "marker", "mask", "pattern", "svg", "switch", "symbol", "feBlend", + "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", + "feDiffuseLighting", "feDisplacementMap", "feFlood", "feGaussianBlur", "feImage", "feMerge", + "feMorphology", "feOffset", "feSpecularLighting", "feTile", "feTurbulence", + "linearGradient", "radialGradient", "stop", "circle", "ellipse", "image", "line", "path", + "polygon", "polyline", "rect", "text", "use", "textPath", "tspan", "foreignObject", + "clipPath" + ], + t = ["any-hover", "any-pointer", "aspect-ratio", "color", "color-gamut", "color-index", + "device-aspect-ratio", "device-height", "device-width", "display-mode", "forced-colors", + "grid", "height", "hover", "inverted-colors", "monochrome", "orientation", "overflow-block", + "overflow-inline", "pointer", "prefers-color-scheme", "prefers-contrast", + "prefers-reduced-motion", "prefers-reduced-transparency", "resolution", "scan", "scripting", + "update", "width", "min-width", "max-width", "min-height", "max-height" + ].sort().reverse(), + r = ["active", "any-link", "blank", "checked", "current", "default", "defined", "dir", + "disabled", "drop", "empty", "enabled", "first", "first-child", "first-of-type", + "fullscreen", "future", "focus", "focus-visible", "focus-within", "has", "host", + "host-context", "hover", "indeterminate", "in-range", "invalid", "is", "lang", "last-child", + "last-of-type", "left", "link", "local-link", "not", "nth-child", "nth-col", + "nth-last-child", "nth-last-col", "nth-last-of-type", "nth-of-type", "only-child", + "only-of-type", "optional", "out-of-range", "past", "placeholder-shown", "read-only", + "read-write", "required", "right", "root", "scope", "target", "target-within", + "user-invalid", "valid", "visited", "where" + ].sort().reverse(), + i = ["after", "backdrop", "before", "cue", "cue-region", "first-letter", "first-line", + "grammar-error", "marker", "part", "placeholder", "selection", "slotted", "spelling-error" + ].sort().reverse(), + o = ["accent-color", "align-content", "align-items", "align-self", "alignment-baseline", "all", + "animation", "animation-delay", "animation-direction", "animation-duration", + "animation-fill-mode", "animation-iteration-count", "animation-name", + "animation-play-state", "animation-timing-function", "appearance", "backface-visibility", + "background", "background-attachment", "background-blend-mode", "background-clip", + "background-color", "background-image", "background-origin", "background-position", + "background-repeat", "background-size", "baseline-shift", "block-size", "border", + "border-block", "border-block-color", "border-block-end", "border-block-end-color", + "border-block-end-style", "border-block-end-width", "border-block-start", + "border-block-start-color", "border-block-start-style", "border-block-start-width", + "border-block-style", "border-block-width", "border-bottom", "border-bottom-color", + "border-bottom-left-radius", "border-bottom-right-radius", "border-bottom-style", + "border-bottom-width", "border-collapse", "border-color", "border-image", + "border-image-outset", "border-image-repeat", "border-image-slice", "border-image-source", + "border-image-width", "border-inline", "border-inline-color", "border-inline-end", + "border-inline-end-color", "border-inline-end-style", "border-inline-end-width", + "border-inline-start", "border-inline-start-color", "border-inline-start-style", + "border-inline-start-width", "border-inline-style", "border-inline-width", "border-left", + "border-left-color", "border-left-style", "border-left-width", "border-radius", + "border-right", "border-end-end-radius", "border-end-start-radius", "border-right-color", + "border-right-style", "border-right-width", "border-spacing", "border-start-end-radius", + "border-start-start-radius", "border-style", "border-top", "border-top-color", + "border-top-left-radius", "border-top-right-radius", "border-top-style", "border-top-width", + "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing", "break-after", + "break-before", "break-inside", "cx", "cy", "caption-side", "caret-color", "clear", "clip", + "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", + "color-profile", "color-rendering", "color-scheme", "column-count", "column-fill", + "column-gap", "column-rule", "column-rule-color", "column-rule-style", "column-rule-width", + "column-span", "column-width", "columns", "contain", "content", "content-visibility", + "counter-increment", "counter-reset", "cue", "cue-after", "cue-before", "cursor", + "direction", "display", "dominant-baseline", "empty-cells", "enable-background", "fill", + "fill-opacity", "fill-rule", "filter", "flex", "flex-basis", "flex-direction", "flex-flow", + "flex-grow", "flex-shrink", "flex-wrap", "float", "flow", "flood-color", "flood-opacity", + "font", "font-display", "font-family", "font-feature-settings", "font-kerning", + "font-language-override", "font-size", "font-size-adjust", "font-smoothing", "font-stretch", + "font-style", "font-synthesis", "font-variant", "font-variant-caps", + "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", + "font-variant-position", "font-variation-settings", "font-weight", "gap", + "glyph-orientation-horizontal", "glyph-orientation-vertical", "grid", "grid-area", + "grid-auto-columns", "grid-auto-flow", "grid-auto-rows", "grid-column", "grid-column-end", + "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-start", + "grid-template", "grid-template-areas", "grid-template-columns", "grid-template-rows", + "hanging-punctuation", "height", "hyphens", "icon", "image-orientation", "image-rendering", + "image-resolution", "ime-mode", "inline-size", "inset", "inset-block", "inset-block-end", + "inset-block-start", "inset-inline", "inset-inline-end", "inset-inline-start", "isolation", + "kerning", "justify-content", "justify-items", "justify-self", "left", "letter-spacing", + "lighting-color", "line-break", "line-height", "list-style", "list-style-image", + "list-style-position", "list-style-type", "marker", "marker-end", "marker-mid", + "marker-start", "mask", "margin", "margin-block", "margin-block-end", "margin-block-start", + "margin-bottom", "margin-inline", "margin-inline-end", "margin-inline-start", "margin-left", + "margin-right", "margin-top", "marks", "mask", "mask-border", "mask-border-mode", + "mask-border-outset", "mask-border-repeat", "mask-border-slice", "mask-border-source", + "mask-border-width", "mask-clip", "mask-composite", "mask-image", "mask-mode", + "mask-origin", "mask-position", "mask-repeat", "mask-size", "mask-type", "max-block-size", + "max-height", "max-inline-size", "max-width", "min-block-size", "min-height", + "min-inline-size", "min-width", "mix-blend-mode", "nav-down", "nav-index", "nav-left", + "nav-right", "nav-up", "none", "normal", "object-fit", "object-position", "opacity", + "order", "orphans", "outline", "outline-color", "outline-offset", "outline-style", + "outline-width", "overflow", "overflow-wrap", "overflow-x", "overflow-y", "padding", + "padding-block", "padding-block-end", "padding-block-start", "padding-bottom", + "padding-inline", "padding-inline-end", "padding-inline-start", "padding-left", + "padding-right", "padding-top", "page-break-after", "page-break-before", + "page-break-inside", "pause", "pause-after", "pause-before", "perspective", + "perspective-origin", "pointer-events", "position", "quotes", "r", "resize", "rest", + "rest-after", "rest-before", "right", "rotate", "row-gap", "scale", "scroll-margin", + "scroll-margin-block", "scroll-margin-block-end", "scroll-margin-block-start", + "scroll-margin-bottom", "scroll-margin-inline", "scroll-margin-inline-end", + "scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right", + "scroll-margin-top", "scroll-padding", "scroll-padding-block", "scroll-padding-block-end", + "scroll-padding-block-start", "scroll-padding-bottom", "scroll-padding-inline", + "scroll-padding-inline-end", "scroll-padding-inline-start", "scroll-padding-left", + "scroll-padding-right", "scroll-padding-top", "scroll-snap-align", "scroll-snap-stop", + "scroll-snap-type", "scrollbar-color", "scrollbar-gutter", "scrollbar-width", + "shape-image-threshold", "shape-margin", "shape-outside", "shape-rendering", "stop-color", + "stop-opacity", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", + "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "speak", + "speak-as", "src", "tab-size", "table-layout", "text-anchor", "text-align", + "text-align-all", "text-align-last", "text-combine-upright", "text-decoration", + "text-decoration-color", "text-decoration-line", "text-decoration-skip-ink", + "text-decoration-style", "text-decoration-thickness", "text-emphasis", + "text-emphasis-color", "text-emphasis-position", "text-emphasis-style", "text-indent", + "text-justify", "text-orientation", "text-overflow", "text-rendering", "text-shadow", + "text-transform", "text-underline-offset", "text-underline-position", "top", "transform", + "transform-box", "transform-origin", "transform-style", "transition", "transition-delay", + "transition-duration", "transition-property", "transition-timing-function", "translate", + "unicode-bidi", "vector-effect", "vertical-align", "visibility", "voice-balance", + "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate", + "voice-stress", "voice-volume", "white-space", "widows", "width", "will-change", + "word-break", "word-spacing", "word-wrap", "writing-mode", "x", "y", "z-index" + ].sort().reverse(), + n = r.concat(i).sort().reverse(); + return a => { + const l = (e => ({ + IMPORTANT: { + scope: "meta", + begin: "!important" + }, + BLOCK_COMMENT: e.C_BLOCK_COMMENT_MODE, + HEXCOLOR: { + scope: "number", + begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/ + }, + FUNCTION_DISPATCH: { + className: "built_in", + begin: /[\w-]+(?=\()/ + }, + ATTRIBUTE_SELECTOR_MODE: { + scope: "selector-attr", + begin: /\[/, + end: /\]/, + illegal: "$", + contains: [e.APOS_STRING_MODE, e.QUOTE_STRING_MODE] + }, + CSS_NUMBER_MODE: { + scope: "number", + begin: e.NUMBER_RE + + "(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", + relevance: 0 + }, + CSS_VARIABLE: { + className: "attr", + begin: /--[A-Za-z_][A-Za-z0-9_-]*/ + } + }))(a), + s = n, + d = "[\\w-]+", + c = "(" + d + "|@\\{" + d + "\\})", + g = [], + b = [], + m = e => ({ + className: "string", + begin: "~?" + e + ".*?" + e + }), + p = (e, t, r) => ({ + className: e, + begin: t, + relevance: r + }), + f = { + $pattern: /[a-z-]+/, + keyword: "and or not only", + attribute: t.join(" ") + }, + u = { + begin: "\\(", + end: "\\)", + contains: b, + keywords: f, + relevance: 0 + }; + b.push(a.C_LINE_COMMENT_MODE, a.C_BLOCK_COMMENT_MODE, m("'"), m('"'), l.CSS_NUMBER_MODE, { + begin: "(url|data-uri)\\(", + starts: { + className: "string", + end: "[\\)\\n]", + excludeEnd: !0 + } + }, l.HEXCOLOR, u, p("variable", "@@?" + d, 10), p("variable", "@\\{" + d + "\\}"), + p("built_in", "~?`[^`]*?`"), { + className: "attribute", + begin: d + "\\s*:", + end: ":", + returnBegin: !0, + excludeEnd: !0 + }, l.IMPORTANT, { + beginKeywords: "and not" + }, l.FUNCTION_DISPATCH); + const h = b.concat({ + begin: /\{/, + end: /\}/, + contains: g + }), + k = { + beginKeywords: "when", + endsWithParent: !0, + contains: [{ + beginKeywords: "and not" + }].concat(b) + }, + v = { + begin: c + "\\s*:", + returnBegin: !0, + end: /[;}]/, + relevance: 0, + contains: [{ + begin: /-(webkit|moz|ms|o)-/ + }, l.CSS_VARIABLE, { + className: "attribute", + begin: "\\b(" + o.join("|") + ")\\b", + end: /(?=:)/, + starts: { + endsWithParent: !0, + illegal: "[<=$]", + relevance: 0, + contains: b + } + }] + }, + y = { + className: "keyword", + begin: "@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b", + starts: { + end: "[;{}]", + keywords: f, + returnEnd: !0, + contains: b, + relevance: 0 + } + }, + w = { + className: "variable", + variants: [{ + begin: "@" + d + "\\s*:", + relevance: 15 + }, { + begin: "@" + d + }], + starts: { + end: "[;}]", + returnEnd: !0, + contains: h + } + }, + x = { + variants: [{ + begin: "[\\.#:&\\[>]", + end: "[;{}]" + }, { + begin: c, + end: /\{/ + }], + returnBegin: !0, + returnEnd: !0, + illegal: "[<='$\"]", + relevance: 0, + contains: [a.C_LINE_COMMENT_MODE, a.C_BLOCK_COMMENT_MODE, k, p("keyword", "all\\b"), + p("variable", "@\\{" + d + "\\}"), { + begin: "\\b(" + e.join("|") + ")\\b", + className: "selector-tag" + }, + l.CSS_NUMBER_MODE, p("selector-tag", c, 0), p("selector-id", "#" + c), p( + "selector-class", "\\." + c, 0), p("selector-tag", "&", 0), l + .ATTRIBUTE_SELECTOR_MODE, { + className: "selector-pseudo", + begin: ":(" + r.join("|") + ")" + }, { + className: "selector-pseudo", + begin: ":(:)?(" + i.join("|") + ")" + }, { + begin: /\(/, + end: /\)/, + relevance: 0, + contains: h + }, { + begin: "!important" + }, + l.FUNCTION_DISPATCH + ] + }, + _ = { + begin: d + ":(:)?" + `(${s.join("|")})`, + returnBegin: !0, + contains: [x] + }; + return g.push(a.C_LINE_COMMENT_MODE, a.C_BLOCK_COMMENT_MODE, y, w, _, v, x, k, l + .FUNCTION_DISPATCH), { + name: "Less", + case_insensitive: !0, + illegal: "[=>'/<($\"]", + contains: g + } + } + })(); + hljs.registerLanguage("less", e) +})(); /*! `nginx` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const n = e.regex, + a = { + className: "variable", + variants: [{ + begin: /\$\d+/ + }, { + begin: /\$\{\w+\}/ + }, { + begin: n.concat(/[$@]/, e.UNDERSCORE_IDENT_RE) + }] + }, + s = { + endsWithParent: !0, + keywords: { + $pattern: /[a-z_]{2,}|\/dev\/poll/, + literal: ["on", "off", "yes", "no", "true", "false", "none", "blocked", "debug", + "info", "notice", "warn", "error", "crit", "select", "break", "last", + "permanent", "redirect", "kqueue", "rtsig", "epoll", "poll", "/dev/poll" + ] + }, + relevance: 0, + illegal: "=>", + contains: [e.HASH_COMMENT_MODE, { + className: "string", + contains: [e.BACKSLASH_ESCAPE, a], + variants: [{ + begin: /"/, + end: /"/ + }, { + begin: /'/, + end: /'/ + }] + }, { + begin: "([a-z]+):/", + end: "\\s", + endsWithParent: !0, + excludeEnd: !0, + contains: [a] + }, { + className: "regexp", + contains: [e.BACKSLASH_ESCAPE, a], + variants: [{ + begin: "\\s\\^", + end: "\\s|\\{|;", + returnEnd: !0 + }, { + begin: "~\\*?\\s+", + end: "\\s|\\{|;", + returnEnd: !0 + }, { + begin: "\\*(\\.[a-z\\-]+)+" + }, { + begin: "([a-z\\-]+\\.)+\\*" + }] + }, { + className: "number", + begin: "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b" + }, { + className: "number", + begin: "\\b\\d+[kKmMgGdshdwy]?\\b", + relevance: 0 + }, a] + }; + return { + name: "Nginx config", + aliases: ["nginxconf"], + contains: [e.HASH_COMMENT_MODE, { + beginKeywords: "upstream location", + end: /;|\{/, + contains: s.contains, + keywords: { + section: "upstream location" + } + }, { + className: "section", + begin: n.concat(e.UNDERSCORE_IDENT_RE + n.lookahead(/\s+\{/)), + relevance: 0 + }, { + begin: n.lookahead(e.UNDERSCORE_IDENT_RE + "\\s"), + end: ";|\\{", + contains: [{ + className: "attribute", + begin: e.UNDERSCORE_IDENT_RE, + starts: s + }], + relevance: 0 + }], + illegal: "[^\\s\\}\\{]" + } + } + })(); + hljs.registerLanguage("nginx", e) +})(); /*! `php` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const t = e.regex, + a = /(?![A-Za-z0-9])(?![$])/, + r = t.concat(/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/, a), + n = t.concat(/(\\?[A-Z][a-z0-9_\x7f-\xff]+|\\?[A-Z]+(?=[A-Z][a-z0-9_\x7f-\xff])){1,}/, + a), + o = { + scope: "variable", + match: "\\$+" + r + }, + c = { + scope: "subst", + variants: [{ + begin: /\$\w+/ + }, { + begin: /\{\$/, + end: /\}/ + }] + }, + i = e.inherit(e.APOS_STRING_MODE, { + illegal: null + }), + s = "[ \t\n]", + l = { + scope: "string", + variants: [e.inherit(e.QUOTE_STRING_MODE, { + illegal: null, + contains: e.QUOTE_STRING_MODE.contains.concat(c) + }), i, { + begin: /<<<[ \t]*(?:(\w+)|"(\w+)")\n/, + end: /[ \t]*(\w+)\b/, + contains: e.QUOTE_STRING_MODE.contains.concat(c), + "on:begin": (e, t) => { + t.data._beginMatch = e[1] || e[2] + }, + "on:end": (e, t) => { + t.data._beginMatch !== e[1] && t.ignoreMatch() + } + }, e.END_SAME_AS_BEGIN({ + begin: /<<<[ \t]*'(\w+)'\n/, + end: /[ \t]*(\w+)\b/ + })] + }, + d = { + scope: "number", + variants: [{ + begin: "\\b0[bB][01]+(?:_[01]+)*\\b" + }, { + begin: "\\b0[oO][0-7]+(?:_[0-7]+)*\\b" + }, { + begin: "\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b" + }, { + begin: "(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?" + }], + relevance: 0 + }, + _ = ["false", "null", "true"], + p = ["__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__", "__COMPILER_HALT_OFFSET__", + "__LINE__", "__METHOD__", "__NAMESPACE__", "__TRAIT__", "die", "echo", "exit", + "include", "include_once", "print", "require", "require_once", "array", "abstract", + "and", "as", "binary", "bool", "boolean", "break", "callable", "case", "catch", + "class", "clone", "const", "continue", "declare", "default", "do", "double", "else", + "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", + "endwhile", "enum", "eval", "extends", "final", "finally", "float", "for", + "foreach", "from", "global", "goto", "if", "implements", "instanceof", "insteadof", + "int", "integer", "interface", "isset", "iterable", "list", "match|0", "mixed", + "new", "never", "object", "or", "private", "protected", "public", "readonly", + "real", "return", "string", "switch", "throw", "trait", "try", "unset", "use", + "var", "void", "while", "xor", "yield" + ], + b = ["Error|0", "AppendIterator", "ArgumentCountError", "ArithmeticError", + "ArrayIterator", "ArrayObject", "AssertionError", "BadFunctionCallException", + "BadMethodCallException", "CachingIterator", "CallbackFilterIterator", + "CompileError", "Countable", "DirectoryIterator", "DivisionByZeroError", + "DomainException", "EmptyIterator", "ErrorException", "Exception", + "FilesystemIterator", "FilterIterator", "GlobIterator", "InfiniteIterator", + "InvalidArgumentException", "IteratorIterator", "LengthException", "LimitIterator", + "LogicException", "MultipleIterator", "NoRewindIterator", "OutOfBoundsException", + "OutOfRangeException", "OuterIterator", "OverflowException", "ParentIterator", + "ParseError", "RangeException", "RecursiveArrayIterator", + "RecursiveCachingIterator", "RecursiveCallbackFilterIterator", + "RecursiveDirectoryIterator", "RecursiveFilterIterator", "RecursiveIterator", + "RecursiveIteratorIterator", "RecursiveRegexIterator", "RecursiveTreeIterator", + "RegexIterator", "RuntimeException", "SeekableIterator", "SplDoublyLinkedList", + "SplFileInfo", "SplFileObject", "SplFixedArray", "SplHeap", "SplMaxHeap", + "SplMinHeap", "SplObjectStorage", "SplObserver", "SplPriorityQueue", "SplQueue", + "SplStack", "SplSubject", "SplTempFileObject", "TypeError", "UnderflowException", + "UnexpectedValueException", "UnhandledMatchError", "ArrayAccess", "BackedEnum", + "Closure", "Fiber", "Generator", "Iterator", "IteratorAggregate", "Serializable", + "Stringable", "Throwable", "Traversable", "UnitEnum", "WeakReference", "WeakMap", + "Directory", "__PHP_Incomplete_Class", "parent", "php_user_filter", "self", + "static", "stdClass" + ], + E = { + keyword: p, + literal: (e => { + const t = []; + return e.forEach((e => { + t.push(e), e.toLowerCase() === e ? t.push(e + .toUpperCase()) : t.push(e.toLowerCase()) + })), t + })(_), + built_in: b + }, + u = e => e.map((e => e.replace(/\|\d+$/, ""))), + g = { + variants: [{ + match: [/new/, t.concat(s, "+"), t.concat("(?!", u(b).join("\\b|"), + "\\b)"), n], + scope: { + 1: "keyword", + 4: "title.class" + } + }] + }, + h = t.concat(r, "\\b(?!\\()"), + m = { + variants: [{ + match: [t.concat(/::/, t.lookahead(/(?!class\b)/)), h], + scope: { + 2: "variable.constant" + } + }, { + match: [/::/, /class/], + scope: { + 2: "variable.language" + } + }, { + match: [n, t.concat(/::/, t.lookahead(/(?!class\b)/)), h], + scope: { + 1: "title.class", + 3: "variable.constant" + } + }, { + match: [n, t.concat("::", t.lookahead(/(?!class\b)/))], + scope: { + 1: "title.class" + } + }, { + match: [n, /::/, /class/], + scope: { + 1: "title.class", + 3: "variable.language" + } + }] + }, + I = { + scope: "attr", + match: t.concat(r, t.lookahead(":"), t.lookahead(/(?!::)/)) + }, + f = { + relevance: 0, + begin: /\(/, + end: /\)/, + keywords: E, + contains: [I, o, m, e.C_BLOCK_COMMENT_MODE, l, d, g] + }, + O = { + relevance: 0, + match: [/\b/, t.concat("(?!fn\\b|function\\b|", u(p).join("\\b|"), "|", u(b).join( + "\\b|"), "\\b)"), r, t.concat(s, "*"), t.lookahead(/(?=\()/)], + scope: { + 3: "title.function.invoke" + }, + contains: [f] + }; + f.contains.push(O); + const v = [I, m, e.C_BLOCK_COMMENT_MODE, l, d, g]; + return { + case_insensitive: !1, + keywords: E, + contains: [{ + begin: t.concat(/#\[\s*/, n), + beginScope: "meta", + end: /]/, + endScope: "meta", + keywords: { + literal: _, + keyword: ["new", "array"] + }, + contains: [{ + begin: /\[/, + end: /]/, + keywords: { + literal: _, + keyword: ["new", "array"] + }, + contains: ["self", ...v] + }, ...v, { + scope: "meta", + match: n + }] + }, e.HASH_COMMENT_MODE, e.COMMENT("//", "$"), e.COMMENT("/\\*", "\\*/", { + contains: [{ + scope: "doctag", + match: "@[A-Za-z]+" + }] + }), { + match: /__halt_compiler\(\);/, + keywords: "__halt_compiler", + starts: { + scope: "comment", + end: e.MATCH_NOTHING_RE, + contains: [{ + match: /\?>/, + scope: "meta", + endsParent: !0 + }] + } + }, { + scope: "meta", + variants: [{ + begin: /<\?php/, + relevance: 10 + }, { + begin: /<\?=/ + }, { + begin: /<\?/, + relevance: .1 + }, { + begin: /\?>/ + }] + }, { + scope: "variable.language", + match: /\$this\b/ + }, o, O, m, { + match: [/const/, /\s/, r], + scope: { + 1: "keyword", + 3: "variable.constant" + } + }, g, { + scope: "function", + relevance: 0, + beginKeywords: "fn function", + end: /[;{]/, + excludeEnd: !0, + illegal: "[$%\\[]", + contains: [{ + beginKeywords: "use" + }, e.UNDERSCORE_TITLE_MODE, { + begin: "=>", + endsParent: !0 + }, { + scope: "params", + begin: "\\(", + end: "\\)", + excludeBegin: !0, + excludeEnd: !0, + keywords: E, + contains: ["self", o, m, e.C_BLOCK_COMMENT_MODE, l, d] + }] + }, { + scope: "class", + variants: [{ + beginKeywords: "enum", + illegal: /[($"]/ + }, { + beginKeywords: "class interface trait", + illegal: /[:($"]/ + }], + relevance: 0, + end: /\{/, + excludeEnd: !0, + contains: [{ + beginKeywords: "extends implements" + }, e.UNDERSCORE_TITLE_MODE] + }, { + beginKeywords: "namespace", + relevance: 0, + end: ";", + illegal: /[.']/, + contains: [e.inherit(e.UNDERSCORE_TITLE_MODE, { + scope: "title.class" + })] + }, { + beginKeywords: "use", + relevance: 0, + end: ";", + contains: [{ + match: /\b(as|const|function)\b/, + scope: "keyword" + }, e.UNDERSCORE_TITLE_MODE] + }, l, d] + } + } + })(); + hljs.registerLanguage("php", e) +})(); /*! `python` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const n = e.regex, + a = /[\p{XID_Start}_]\p{XID_Continue}*/u, + s = ["and", "as", "assert", "async", "await", "break", "case", "class", "continue", + "def", "del", "elif", "else", "except", "finally", "for", "from", "global", "if", + "import", "in", "is", "lambda", "match", "nonlocal|10", "not", "or", "pass", + "raise", "return", "try", "while", "with", "yield" + ], + t = { + $pattern: /[A-Za-z]\w+|__\w+__/, + keyword: s, + built_in: ["__import__", "abs", "all", "any", "ascii", "bin", "bool", "breakpoint", + "bytearray", "bytes", "callable", "chr", "classmethod", "compile", + "complex", "delattr", "dict", "dir", "divmod", "enumerate", "eval", "exec", + "filter", "float", "format", "frozenset", "getattr", "globals", "hasattr", + "hash", "help", "hex", "id", "input", "int", "isinstance", "issubclass", + "iter", "len", "list", "locals", "map", "max", "memoryview", "min", "next", + "object", "oct", "open", "ord", "pow", "print", "property", "range", "repr", + "reversed", "round", "set", "setattr", "slice", "sorted", "staticmethod", + "str", "sum", "super", "tuple", "type", "vars", "zip" + ], + literal: ["__debug__", "Ellipsis", "False", "None", "NotImplemented", "True"], + type: ["Any", "Callable", "Coroutine", "Dict", "List", "Literal", "Generic", + "Optional", "Sequence", "Set", "Tuple", "Type", "Union" + ] + }, + i = { + className: "meta", + begin: /^(>>>|\.\.\.) / + }, + r = { + className: "subst", + begin: /\{/, + end: /\}/, + keywords: t, + illegal: /#/ + }, + l = { + begin: /\{\{/, + relevance: 0 + }, + o = { + className: "string", + contains: [e.BACKSLASH_ESCAPE], + variants: [{ + begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/, + end: /'''/, + contains: [e.BACKSLASH_ESCAPE, i], + relevance: 10 + }, { + begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/, + end: /"""/, + contains: [e.BACKSLASH_ESCAPE, i], + relevance: 10 + }, { + begin: /([fF][rR]|[rR][fF]|[fF])'''/, + end: /'''/, + contains: [e.BACKSLASH_ESCAPE, i, l, r] + }, { + begin: /([fF][rR]|[rR][fF]|[fF])"""/, + end: /"""/, + contains: [e.BACKSLASH_ESCAPE, i, l, r] + }, { + begin: /([uU]|[rR])'/, + end: /'/, + relevance: 10 + }, { + begin: /([uU]|[rR])"/, + end: /"/, + relevance: 10 + }, { + begin: /([bB]|[bB][rR]|[rR][bB])'/, + end: /'/ + }, { + begin: /([bB]|[bB][rR]|[rR][bB])"/, + end: /"/ + }, { + begin: /([fF][rR]|[rR][fF]|[fF])'/, + end: /'/, + contains: [e.BACKSLASH_ESCAPE, l, r] + }, { + begin: /([fF][rR]|[rR][fF]|[fF])"/, + end: /"/, + contains: [e.BACKSLASH_ESCAPE, l, r] + }, e.APOS_STRING_MODE, e.QUOTE_STRING_MODE] + }, + b = "[0-9](_?[0-9])*", + c = `(\\b(${b}))?\\.(${b})|\\b(${b})\\.`, + d = "\\b|" + s.join("|"), + g = { + className: "number", + relevance: 0, + variants: [{ + begin: `(\\b(${b})|(${c}))[eE][+-]?(${b})[jJ]?(?=${d})` + }, { + begin: `(${c})[jJ]?` + }, { + begin: `\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})` + }, { + begin: `\\b0[bB](_?[01])+[lL]?(?=${d})` + }, { + begin: `\\b0[oO](_?[0-7])+[lL]?(?=${d})` + }, { + begin: `\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})` + }, { + begin: `\\b(${b})[jJ](?=${d})` + }] + }, + p = { + className: "comment", + begin: n.lookahead(/# type:/), + end: /$/, + keywords: t, + contains: [{ + begin: /# type:/ + }, { + begin: /#/, + end: /\b\B/, + endsWithParent: !0 + }] + }, + m = { + className: "params", + variants: [{ + className: "", + begin: /\(\s*\)/, + skip: !0 + }, { + begin: /\(/, + end: /\)/, + excludeBegin: !0, + excludeEnd: !0, + keywords: t, + contains: ["self", i, g, o, e.HASH_COMMENT_MODE] + }] + }; + return r.contains = [o, g, i], { + name: "Python", + aliases: ["py", "gyp", "ipython"], + unicodeRegex: !0, + keywords: t, + illegal: /(<\/|\?)|=>/, + contains: [i, g, { + scope: "variable.language", + match: /\bself\b/ + }, { + beginKeywords: "if", + relevance: 0 + }, { + match: /\bor\b/, + scope: "keyword" + }, o, p, e.HASH_COMMENT_MODE, { + match: [/\bdef/, /\s+/, a], + scope: { + 1: "keyword", + 3: "title.function" + }, + contains: [m] + }, { + variants: [{ + match: [/\bclass/, /\s+/, a, /\s*/, /\(\s*/, a, /\s*\)/] + }, { + match: [/\bclass/, /\s+/, a] + }], + scope: { + 1: "keyword", + 3: "title.class", + 6: "title.class.inherited" + } + }, { + className: "meta", + begin: /^[\t ]*@/, + end: /(?=#)|$/, + contains: [g, m, o] + }] + } + } + })(); + hljs.registerLanguage("python", e) +})(); /*! `rust` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const t = e.regex, + n = /(r#)?/, + a = t.concat(n, e.UNDERSCORE_IDENT_RE), + i = t.concat(n, e.IDENT_RE), + r = { + className: "title.function.invoke", + relevance: 0, + begin: t.concat(/\b/, /(?!let|for|while|if|else|match\b)/, i, t.lookahead(/\s*\(/)) + }, + s = "([ui](8|16|32|64|128|size)|f(32|64))?", + l = ["drop ", "Copy", "Send", "Sized", "Sync", "Drop", "Fn", "FnMut", "FnOnce", + "ToOwned", "Clone", "Debug", "PartialEq", "PartialOrd", "Eq", "Ord", "AsRef", + "AsMut", "Into", "From", "Default", "Iterator", "Extend", "IntoIterator", + "DoubleEndedIterator", "ExactSizeIterator", "SliceConcatExt", "ToString", "assert!", + "assert_eq!", "bitflags!", "bytes!", "cfg!", "col!", "concat!", "concat_idents!", + "debug_assert!", "debug_assert_eq!", "env!", "eprintln!", "panic!", "file!", + "format!", "format_args!", "include_bytes!", "include_str!", "line!", + "local_data_key!", "module_path!", "option_env!", "print!", "println!", "select!", + "stringify!", "try!", "unimplemented!", "unreachable!", "vec!", "write!", + "writeln!", "macro_rules!", "assert_ne!", "debug_assert_ne!" + ], + o = ["i8", "i16", "i32", "i64", "i128", "isize", "u8", "u16", "u32", "u64", "u128", + "usize", "f32", "f64", "str", "char", "bool", "Box", "Option", "Result", "String", + "Vec" + ]; + return { + name: "Rust", + aliases: ["rs"], + keywords: { + $pattern: e.IDENT_RE + "!?", + type: o, + keyword: ["abstract", "as", "async", "await", "become", "box", "break", "const", + "continue", "crate", "do", "dyn", "else", "enum", "extern", "false", + "final", "fn", "for", "if", "impl", "in", "let", "loop", "macro", "match", + "mod", "move", "mut", "override", "priv", "pub", "ref", "return", "self", + "Self", "static", "struct", "super", "trait", "true", "try", "type", + "typeof", "union", "unsafe", "unsized", "use", "virtual", "where", "while", + "yield" + ], + literal: ["true", "false", "Some", "None", "Ok", "Err"], + built_in: l + }, + illegal: "" + }, r] + } + } + })(); + hljs.registerLanguage("rust", e) +})(); /*! `scss` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + const e = ["a", "abbr", "address", "article", "aside", "audio", "b", "blockquote", "body", "button", + "canvas", "caption", "cite", "code", "dd", "del", "details", "dfn", "div", "dl", "dt", "em", + "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", + "header", "hgroup", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", + "li", "main", "mark", "menu", "nav", "object", "ol", "optgroup", "option", "p", "picture", + "q", "quote", "samp", "section", "select", "source", "span", "strong", "summary", "sup", + "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "time", "tr", "ul", "var", + "video", "defs", "g", "marker", "mask", "pattern", "svg", "switch", "symbol", "feBlend", + "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", + "feDiffuseLighting", "feDisplacementMap", "feFlood", "feGaussianBlur", "feImage", "feMerge", + "feMorphology", "feOffset", "feSpecularLighting", "feTile", "feTurbulence", + "linearGradient", "radialGradient", "stop", "circle", "ellipse", "image", "line", "path", + "polygon", "polyline", "rect", "text", "use", "textPath", "tspan", "foreignObject", + "clipPath" + ], + r = ["any-hover", "any-pointer", "aspect-ratio", "color", "color-gamut", "color-index", + "device-aspect-ratio", "device-height", "device-width", "display-mode", "forced-colors", + "grid", "height", "hover", "inverted-colors", "monochrome", "orientation", "overflow-block", + "overflow-inline", "pointer", "prefers-color-scheme", "prefers-contrast", + "prefers-reduced-motion", "prefers-reduced-transparency", "resolution", "scan", "scripting", + "update", "width", "min-width", "max-width", "min-height", "max-height" + ].sort().reverse(), + t = ["active", "any-link", "blank", "checked", "current", "default", "defined", "dir", + "disabled", "drop", "empty", "enabled", "first", "first-child", "first-of-type", + "fullscreen", "future", "focus", "focus-visible", "focus-within", "has", "host", + "host-context", "hover", "indeterminate", "in-range", "invalid", "is", "lang", "last-child", + "last-of-type", "left", "link", "local-link", "not", "nth-child", "nth-col", + "nth-last-child", "nth-last-col", "nth-last-of-type", "nth-of-type", "only-child", + "only-of-type", "optional", "out-of-range", "past", "placeholder-shown", "read-only", + "read-write", "required", "right", "root", "scope", "target", "target-within", + "user-invalid", "valid", "visited", "where" + ].sort().reverse(), + i = ["after", "backdrop", "before", "cue", "cue-region", "first-letter", "first-line", + "grammar-error", "marker", "part", "placeholder", "selection", "slotted", "spelling-error" + ].sort().reverse(), + o = ["accent-color", "align-content", "align-items", "align-self", "alignment-baseline", "all", + "animation", "animation-delay", "animation-direction", "animation-duration", + "animation-fill-mode", "animation-iteration-count", "animation-name", + "animation-play-state", "animation-timing-function", "appearance", "backface-visibility", + "background", "background-attachment", "background-blend-mode", "background-clip", + "background-color", "background-image", "background-origin", "background-position", + "background-repeat", "background-size", "baseline-shift", "block-size", "border", + "border-block", "border-block-color", "border-block-end", "border-block-end-color", + "border-block-end-style", "border-block-end-width", "border-block-start", + "border-block-start-color", "border-block-start-style", "border-block-start-width", + "border-block-style", "border-block-width", "border-bottom", "border-bottom-color", + "border-bottom-left-radius", "border-bottom-right-radius", "border-bottom-style", + "border-bottom-width", "border-collapse", "border-color", "border-image", + "border-image-outset", "border-image-repeat", "border-image-slice", "border-image-source", + "border-image-width", "border-inline", "border-inline-color", "border-inline-end", + "border-inline-end-color", "border-inline-end-style", "border-inline-end-width", + "border-inline-start", "border-inline-start-color", "border-inline-start-style", + "border-inline-start-width", "border-inline-style", "border-inline-width", "border-left", + "border-left-color", "border-left-style", "border-left-width", "border-radius", + "border-right", "border-end-end-radius", "border-end-start-radius", "border-right-color", + "border-right-style", "border-right-width", "border-spacing", "border-start-end-radius", + "border-start-start-radius", "border-style", "border-top", "border-top-color", + "border-top-left-radius", "border-top-right-radius", "border-top-style", "border-top-width", + "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing", "break-after", + "break-before", "break-inside", "cx", "cy", "caption-side", "caret-color", "clear", "clip", + "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", + "color-profile", "color-rendering", "color-scheme", "column-count", "column-fill", + "column-gap", "column-rule", "column-rule-color", "column-rule-style", "column-rule-width", + "column-span", "column-width", "columns", "contain", "content", "content-visibility", + "counter-increment", "counter-reset", "cue", "cue-after", "cue-before", "cursor", + "direction", "display", "dominant-baseline", "empty-cells", "enable-background", "fill", + "fill-opacity", "fill-rule", "filter", "flex", "flex-basis", "flex-direction", "flex-flow", + "flex-grow", "flex-shrink", "flex-wrap", "float", "flow", "flood-color", "flood-opacity", + "font", "font-display", "font-family", "font-feature-settings", "font-kerning", + "font-language-override", "font-size", "font-size-adjust", "font-smoothing", "font-stretch", + "font-style", "font-synthesis", "font-variant", "font-variant-caps", + "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", + "font-variant-position", "font-variation-settings", "font-weight", "gap", + "glyph-orientation-horizontal", "glyph-orientation-vertical", "grid", "grid-area", + "grid-auto-columns", "grid-auto-flow", "grid-auto-rows", "grid-column", "grid-column-end", + "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-start", + "grid-template", "grid-template-areas", "grid-template-columns", "grid-template-rows", + "hanging-punctuation", "height", "hyphens", "icon", "image-orientation", "image-rendering", + "image-resolution", "ime-mode", "inline-size", "inset", "inset-block", "inset-block-end", + "inset-block-start", "inset-inline", "inset-inline-end", "inset-inline-start", "isolation", + "kerning", "justify-content", "justify-items", "justify-self", "left", "letter-spacing", + "lighting-color", "line-break", "line-height", "list-style", "list-style-image", + "list-style-position", "list-style-type", "marker", "marker-end", "marker-mid", + "marker-start", "mask", "margin", "margin-block", "margin-block-end", "margin-block-start", + "margin-bottom", "margin-inline", "margin-inline-end", "margin-inline-start", "margin-left", + "margin-right", "margin-top", "marks", "mask", "mask-border", "mask-border-mode", + "mask-border-outset", "mask-border-repeat", "mask-border-slice", "mask-border-source", + "mask-border-width", "mask-clip", "mask-composite", "mask-image", "mask-mode", + "mask-origin", "mask-position", "mask-repeat", "mask-size", "mask-type", "max-block-size", + "max-height", "max-inline-size", "max-width", "min-block-size", "min-height", + "min-inline-size", "min-width", "mix-blend-mode", "nav-down", "nav-index", "nav-left", + "nav-right", "nav-up", "none", "normal", "object-fit", "object-position", "opacity", + "order", "orphans", "outline", "outline-color", "outline-offset", "outline-style", + "outline-width", "overflow", "overflow-wrap", "overflow-x", "overflow-y", "padding", + "padding-block", "padding-block-end", "padding-block-start", "padding-bottom", + "padding-inline", "padding-inline-end", "padding-inline-start", "padding-left", + "padding-right", "padding-top", "page-break-after", "page-break-before", + "page-break-inside", "pause", "pause-after", "pause-before", "perspective", + "perspective-origin", "pointer-events", "position", "quotes", "r", "resize", "rest", + "rest-after", "rest-before", "right", "rotate", "row-gap", "scale", "scroll-margin", + "scroll-margin-block", "scroll-margin-block-end", "scroll-margin-block-start", + "scroll-margin-bottom", "scroll-margin-inline", "scroll-margin-inline-end", + "scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right", + "scroll-margin-top", "scroll-padding", "scroll-padding-block", "scroll-padding-block-end", + "scroll-padding-block-start", "scroll-padding-bottom", "scroll-padding-inline", + "scroll-padding-inline-end", "scroll-padding-inline-start", "scroll-padding-left", + "scroll-padding-right", "scroll-padding-top", "scroll-snap-align", "scroll-snap-stop", + "scroll-snap-type", "scrollbar-color", "scrollbar-gutter", "scrollbar-width", + "shape-image-threshold", "shape-margin", "shape-outside", "shape-rendering", "stop-color", + "stop-opacity", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", + "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "speak", + "speak-as", "src", "tab-size", "table-layout", "text-anchor", "text-align", + "text-align-all", "text-align-last", "text-combine-upright", "text-decoration", + "text-decoration-color", "text-decoration-line", "text-decoration-skip-ink", + "text-decoration-style", "text-decoration-thickness", "text-emphasis", + "text-emphasis-color", "text-emphasis-position", "text-emphasis-style", "text-indent", + "text-justify", "text-orientation", "text-overflow", "text-rendering", "text-shadow", + "text-transform", "text-underline-offset", "text-underline-position", "top", "transform", + "transform-box", "transform-origin", "transform-style", "transition", "transition-delay", + "transition-duration", "transition-property", "transition-timing-function", "translate", + "unicode-bidi", "vector-effect", "vertical-align", "visibility", "voice-balance", + "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate", + "voice-stress", "voice-volume", "white-space", "widows", "width", "will-change", + "word-break", "word-spacing", "word-wrap", "writing-mode", "x", "y", "z-index" + ].sort().reverse(); + return n => { + const a = (e => ({ + IMPORTANT: { + scope: "meta", + begin: "!important" + }, + BLOCK_COMMENT: e.C_BLOCK_COMMENT_MODE, + HEXCOLOR: { + scope: "number", + begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/ + }, + FUNCTION_DISPATCH: { + className: "built_in", + begin: /[\w-]+(?=\()/ + }, + ATTRIBUTE_SELECTOR_MODE: { + scope: "selector-attr", + begin: /\[/, + end: /\]/, + illegal: "$", + contains: [e.APOS_STRING_MODE, e.QUOTE_STRING_MODE] + }, + CSS_NUMBER_MODE: { + scope: "number", + begin: e.NUMBER_RE + + "(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", + relevance: 0 + }, + CSS_VARIABLE: { + className: "attr", + begin: /--[A-Za-z_][A-Za-z0-9_-]*/ + } + }))(n), + l = i, + s = t, + d = "@[a-z-]+", + c = { + className: "variable", + begin: "(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b", + relevance: 0 + }; + return { + name: "SCSS", + case_insensitive: !0, + illegal: "[=/|']", + contains: [n.C_LINE_COMMENT_MODE, n.C_BLOCK_COMMENT_MODE, a.CSS_NUMBER_MODE, { + className: "selector-id", + begin: "#[A-Za-z0-9_-]+", + relevance: 0 + }, { + className: "selector-class", + begin: "\\.[A-Za-z0-9_-]+", + relevance: 0 + }, a.ATTRIBUTE_SELECTOR_MODE, { + className: "selector-tag", + begin: "\\b(" + e.join("|") + ")\\b", + relevance: 0 + }, { + className: "selector-pseudo", + begin: ":(" + s.join("|") + ")" + }, { + className: "selector-pseudo", + begin: ":(:)?(" + l.join("|") + ")" + }, c, { + begin: /\(/, + end: /\)/, + contains: [a.CSS_NUMBER_MODE] + }, a.CSS_VARIABLE, { + className: "attribute", + begin: "\\b(" + o.join("|") + ")\\b" + }, { + begin: "\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b" + }, { + begin: /:/, + end: /[;}{]/, + relevance: 0, + contains: [a.BLOCK_COMMENT, c, a.HEXCOLOR, a.CSS_NUMBER_MODE, n + .QUOTE_STRING_MODE, n.APOS_STRING_MODE, a.IMPORTANT, a + .FUNCTION_DISPATCH + ] + }, { + begin: "@(page|font-face)", + keywords: { + $pattern: d, + keyword: "@page @font-face" + } + }, { + begin: "@", + end: "[{;]", + returnBegin: !0, + keywords: { + $pattern: /[a-z-]+/, + keyword: "and or not only", + attribute: r.join(" ") + }, + contains: [{ + begin: d, + className: "keyword" + }, { + begin: /[a-z-]+(?=:)/, + className: "attribute" + }, c, n.QUOTE_STRING_MODE, n.APOS_STRING_MODE, a.HEXCOLOR, a + .CSS_NUMBER_MODE + ] + }, a.FUNCTION_DISPATCH] + } + } + })(); + hljs.registerLanguage("scss", e) +})(); /*! `swift` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + + function e(e) { + return e ? "string" == typeof e ? e : e.source : null + } + + function n(e) { + return t("(?=", e, ")") + } + + function t(...n) { + return n.map((n => e(n))).join("") + } + + function a(...n) { + const t = (e => { + const n = e[e.length - 1]; + return "object" == typeof n && n.constructor === Object ? (e.splice(e.length - 1, + 1), n) : {} + })(n); + return "(" + (t.capture ? "" : "?:") + n.map((n => e(n))).join("|") + ")" + } + const i = e => t(/\b/, e, /\w$/.test(e) ? /\b/ : /\B/), + s = ["Protocol", "Type"].map(i), + c = ["init", "self"].map(i), + u = ["Any", "Self"], + o = ["actor", "any", "associatedtype", "async", "await", /as\?/, /as!/, "as", "borrowing", + "break", "case", "catch", "class", "consume", "consuming", "continue", "convenience", + "copy", "default", "defer", "deinit", "didSet", "distributed", "do", "dynamic", "each", + "else", "enum", "extension", "fallthrough", /fileprivate\(set\)/, "fileprivate", "final", + "for", "func", "get", "guard", "if", "import", "indirect", "infix", /init\?/, /init!/, + "inout", /internal\(set\)/, "internal", "in", "is", "isolated", "nonisolated", "lazy", + "let", "macro", "mutating", "nonmutating", /open\(set\)/, "open", "operator", "optional", + "override", "package", "postfix", "precedencegroup", "prefix", /private\(set\)/, "private", + "protocol", /public\(set\)/, "public", "repeat", "required", "rethrows", "return", "set", + "some", "static", "struct", "subscript", "super", "switch", "throws", "throw", /try\?/, + /try!/, "try", "typealias", /unowned\(safe\)/, /unowned\(unsafe\)/, "unowned", "var", + "weak", "where", "while", "willSet" + ], + r = ["false", "nil", "true"], + l = ["assignment", "associativity", "higherThan", "left", "lowerThan", "none", "right"], + m = ["#colorLiteral", "#column", "#dsohandle", "#else", "#elseif", "#endif", "#error", "#file", + "#fileID", "#fileLiteral", "#filePath", "#function", "#if", "#imageLiteral", "#keyPath", + "#line", "#selector", "#sourceLocation", "#warning" + ], + p = ["abs", "all", "any", "assert", "assertionFailure", "debugPrint", "dump", "fatalError", + "getVaList", "isKnownUniquelyReferenced", "max", "min", "numericCast", "pointwiseMax", + "pointwiseMin", "precondition", "preconditionFailure", "print", "readLine", "repeatElement", + "sequence", "stride", "swap", "swift_unboxFromSwiftValueWithType", "transcode", "type", + "unsafeBitCast", "unsafeDowncast", "withExtendedLifetime", "withUnsafeMutablePointer", + "withUnsafePointer", "withVaList", "withoutActuallyEscaping", "zip" + ], + d = a(/[/=\-+!*%<>&|^~?]/, /[\u00A1-\u00A7]/, /[\u00A9\u00AB]/, /[\u00AC\u00AE]/, + /[\u00B0\u00B1]/, /[\u00B6\u00BB\u00BF\u00D7\u00F7]/, /[\u2016-\u2017]/, /[\u2020-\u2027]/, + /[\u2030-\u203E]/, /[\u2041-\u2053]/, /[\u2055-\u205E]/, /[\u2190-\u23FF]/, + /[\u2500-\u2775]/, /[\u2794-\u2BFF]/, /[\u2E00-\u2E7F]/, /[\u3001-\u3003]/, + /[\u3008-\u3020]/, /[\u3030]/), + F = a(d, /[\u0300-\u036F]/, /[\u1DC0-\u1DFF]/, /[\u20D0-\u20FF]/, /[\uFE00-\uFE0F]/, + /[\uFE20-\uFE2F]/), + b = t(d, F, "*"), + h = a(/[a-zA-Z_]/, /[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/, + /[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/, + /[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/, /[\u1E00-\u1FFF]/, + /[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/, + /[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/, /[\u2C00-\u2DFF\u2E80-\u2FFF]/, + /[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/, + /[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/, /[\uFE47-\uFEFE\uFF00-\uFFFD]/), + f = a(h, /\d/, /[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/), + w = t(h, f, "*"), + g = t(/[A-Z]/, f, "*"), + y = ["attached", "autoclosure", t(/convention\(/, a("swift", "block", "c"), /\)/), + "discardableResult", "dynamicCallable", "dynamicMemberLookup", "escaping", "freestanding", + "frozen", "GKInspectable", "IBAction", "IBDesignable", "IBInspectable", "IBOutlet", + "IBSegueAction", "inlinable", "main", "nonobjc", "NSApplicationMain", "NSCopying", + "NSManaged", t(/objc\(/, w, /\)/), "objc", "objcMembers", "propertyWrapper", + "requires_stored_property_inits", "resultBuilder", "Sendable", "testable", + "UIApplicationMain", "unchecked", "unknown", "usableFromInline", "warn_unqualified_access" + ], + v = ["iOS", "iOSApplicationExtension", "macOS", "macOSApplicationExtension", "macCatalyst", + "macCatalystApplicationExtension", "watchOS", "watchOSApplicationExtension", "tvOS", + "tvOSApplicationExtension", "swift" + ]; + return e => { + const d = { + match: /\s+/, + relevance: 0 + }, + h = e.COMMENT("/\\*", "\\*/", { + contains: ["self"] + }), + E = [e.C_LINE_COMMENT_MODE, h], + A = { + match: [/\./, a(...s, ...c)], + className: { + 2: "keyword" + } + }, + C = { + match: t(/\./, a(...o)), + relevance: 0 + }, + k = o.filter((e => "string" == typeof e)).concat(["_|0"]), + N = { + variants: [{ + className: "keyword", + match: a(...o.filter((e => "string" != typeof e)).concat(u).map(i), ... + c) + }] + }, + S = { + $pattern: a(/\b\w+/, /#\w+/), + keyword: k.concat(m), + literal: r + }, + B = [A, C, N], + D = [{ + match: t(/\./, a(...p)), + relevance: 0 + }, { + className: "built_in", + match: t(/\b/, a(...p), /(?=\()/) + }], + _ = { + match: /->/, + relevance: 0 + }, + M = [_, { + className: "operator", + relevance: 0, + variants: [{ + match: b + }, { + match: `\\.(\\.|${F})+` + }] + }], + x = "([0-9]_*)+", + L = "([0-9a-fA-F]_*)+", + $ = { + className: "number", + relevance: 0, + variants: [{ + match: `\\b(${x})(\\.(${x}))?([eE][+-]?(${x}))?\\b` + }, { + match: `\\b0x(${L})(\\.(${L}))?([pP][+-]?(${x}))?\\b` + }, { + match: /\b0o([0-7]_*)+\b/ + }, { + match: /\b0b([01]_*)+\b/ + }] + }, + I = (e = "") => ({ + className: "subst", + variants: [{ + match: t(/\\/, e, /[0\\tnr"']/) + }, { + match: t(/\\/, e, /u\{[0-9a-fA-F]{1,8}\}/) + }] + }), + O = (e = "") => ({ + className: "subst", + match: t(/\\/, e, /[\t ]*(?:[\r\n]|\r\n)/) + }), + P = (e = "") => ({ + className: "subst", + label: "interpol", + begin: t(/\\/, e, /\(/), + end: /\)/ + }), + j = (e = "") => ({ + begin: t(e, /"""/), + end: t(/"""/, e), + contains: [I(e), O(e), P(e)] + }), + K = (e = "") => ({ + begin: t(e, /"/), + end: t(/"/, e), + contains: [I(e), P(e)] + }), + T = { + className: "string", + variants: [j(), j("#"), j("##"), j("###"), K(), K("#"), K("##"), K("###")] + }, + q = [e.BACKSLASH_ESCAPE, { + begin: /\[/, + end: /\]/, + relevance: 0, + contains: [e.BACKSLASH_ESCAPE] + }], + U = { + begin: /\/[^\s](?=[^/\n]*\/)/, + end: /\//, + contains: q + }, + z = e => { + const n = t(e, /\//), + a = t(/\//, e); + return { + begin: n, + end: a, + contains: [...q, { + scope: "comment", + begin: `#(?!.*${a})`, + end: /$/ + }] + } + }, + V = { + scope: "regexp", + variants: [z("###"), z("##"), z("#"), U] + }, + W = { + match: t(/`/, w, /`/) + }, + Z = [W, { + className: "variable", + match: /\$\d+/ + }, { + className: "variable", + match: `\\$${f}+` + }], + G = [{ + match: /(@|#(un)?)available/, + scope: "keyword", + starts: { + contains: [{ + begin: /\(/, + end: /\)/, + keywords: v, + contains: [...M, $, T] + }] + } + }, { + scope: "keyword", + match: t(/@/, a(...y), n(a(/\(/, /\s+/))) + }, { + scope: "meta", + match: t(/@/, w) + }], + H = { + match: n(/\b[A-Z]/), + relevance: 0, + contains: [{ + className: "type", + match: t( + /(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/, + f, "+") + }, { + className: "type", + match: g, + relevance: 0 + }, { + match: /[?!]+/, + relevance: 0 + }, { + match: /\.\.\./, + relevance: 0 + }, { + match: t(/\s+&\s+/, n(g)), + relevance: 0 + }] + }, + R = { + begin: //, + keywords: S, + contains: [...E, ...B, ...G, _, H] + }; + H.contains.push(R); + const X = { + begin: /\(/, + end: /\)/, + relevance: 0, + keywords: S, + contains: ["self", { + match: t(w, /\s*:/), + keywords: "_|0", + relevance: 0 + }, ...E, V, ...B, ...D, ...M, $, T, ...Z, ...G, H] + }, + J = { + begin: //, + keywords: "repeat each", + contains: [...E, H] + }, + Q = { + begin: /\(/, + end: /\)/, + keywords: S, + contains: [{ + begin: a(n(t(w, /\s*:/)), n(t(w, /\s+/, w, /\s*:/))), + end: /:/, + relevance: 0, + contains: [{ + className: "keyword", + match: /\b_\b/ + }, { + className: "params", + match: w + }] + }, ...E, ...B, ...M, $, T, ...G, H, X], + endsParent: !0, + illegal: /["']/ + }, + Y = { + match: [/(func|macro)/, /\s+/, a(W.match, w, b)], + className: { + 1: "keyword", + 3: "title.function" + }, + contains: [J, Q, d], + illegal: [/\[/, /%/] + }, + ee = { + match: [/\b(?:subscript|init[?!]?)/, /\s*(?=[<(])/], + className: { + 1: "keyword" + }, + contains: [J, Q, d], + illegal: /\[|%/ + }, + ne = { + match: [/operator/, /\s+/, b], + className: { + 1: "keyword", + 3: "title" + } + }, + te = { + begin: [/precedencegroup/, /\s+/, g], + className: { + 1: "keyword", + 3: "title" + }, + contains: [H], + keywords: [...l, ...r], + end: /}/ + }, + ae = { + begin: [/(struct|protocol|class|extension|enum|actor)/, /\s+/, w, /\s*/], + beginScope: { + 1: "keyword", + 3: "title.class" + }, + keywords: S, + contains: [J, ...B, { + begin: /:/, + end: /\{/, + keywords: S, + contains: [{ + scope: "title.class.inherited", + match: g + }, ...B], + relevance: 0 + }] + }; + for (const e of T.variants) { + const n = e.contains.find((e => "interpol" === e.label)); + n.keywords = S; + const t = [...B, ...D, ...M, $, T, ...Z]; + n.contains = [...t, { + begin: /\(/, + end: /\)/, + contains: ["self", ...t] + }] + } + return { + name: "Swift", + keywords: S, + contains: [...E, Y, ee, ae, ne, te, { + beginKeywords: "import", + end: /$/, + contains: [...E], + relevance: 0 + }, V, ...B, ...D, ...M, $, T, ...Z, ...G, H, X] + } + } + })(); + hljs.registerLanguage("swift", e) +})(); /*! `typescript` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + const e = "[A-Za-z$_][0-9A-Za-z$_]*", + n = ["as", "in", "of", "if", "for", "while", "finally", "var", "new", "function", "do", + "return", "void", "else", "break", "catch", "instanceof", "with", "throw", "case", + "default", "try", "switch", "continue", "typeof", "delete", "let", "yield", "const", + "class", "debugger", "async", "await", "static", "import", "from", "export", "extends" + ], + a = ["true", "false", "null", "undefined", "NaN", "Infinity"], + t = ["Object", "Function", "Boolean", "Symbol", "Math", "Date", "Number", "BigInt", "String", + "RegExp", "Array", "Float32Array", "Float64Array", "Int8Array", "Uint8Array", + "Uint8ClampedArray", "Int16Array", "Int32Array", "Uint16Array", "Uint32Array", + "BigInt64Array", "BigUint64Array", "Set", "Map", "WeakSet", "WeakMap", "ArrayBuffer", + "SharedArrayBuffer", "Atomics", "DataView", "JSON", "Promise", "Generator", + "GeneratorFunction", "AsyncFunction", "Reflect", "Proxy", "Intl", "WebAssembly" + ], + s = ["Error", "EvalError", "InternalError", "RangeError", "ReferenceError", "SyntaxError", + "TypeError", "URIError" + ], + r = ["setInterval", "setTimeout", "clearInterval", "clearTimeout", "require", "exports", "eval", + "isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", + "encodeURI", "encodeURIComponent", "escape", "unescape" + ], + c = ["arguments", "this", "super", "console", "window", "document", "localStorage", + "sessionStorage", "module", "global" + ], + i = [].concat(r, t, s); + + function o(o) { + const l = o.regex, + d = e, + b = { + begin: /<[A-Za-z0-9\\._:-]+/, + end: /\/[A-Za-z0-9\\._:-]+>|\/>/, + isTrulyOpeningTag: (e, n) => { + const a = e[0].length + e.index, + t = e.input[a]; + if ("<" === t || "," === t) return void n.ignoreMatch(); + let s; + ">" === t && (((e, { + after: n + }) => { + const a = " e + "\\s*\\(")), + l.concat("(?!", C.join("|"), ")")), d, l.lookahead(/\s*\(/)), + className: "title.function", + relevance: 0 + }; + var C; + const T = { + begin: l.concat(/\./, l.lookahead(l.concat(d, /(?![0-9A-Za-z$_(])/))), + end: d, + excludeBegin: !0, + keywords: "prototype", + className: "property", + relevance: 0 + }, + M = { + match: [/get|set/, /\s+/, d, /(?=\()/], + className: { + 1: "keyword", + 3: "title.function" + }, + contains: [{ + begin: /\(\)/ + }, R] + }, + B = "(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|" + o.UNDERSCORE_IDENT_RE + + ")\\s*=>", + $ = { + match: [/const|var|let/, /\s+/, d, /\s*/, /=\s*/, /(async\s*)?/, l.lookahead(B)], + keywords: "async", + className: { + 1: "keyword", + 3: "title.function" + }, + contains: [R] + }; + return { + name: "JavaScript", + aliases: ["js", "jsx", "mjs", "cjs"], + keywords: g, + exports: { + PARAMS_CONTAINS: w, + CLASS_REFERENCE: x + }, + illegal: /#(?![$_A-z])/, + contains: [o.SHEBANG({ + label: "shebang", + binary: "node", + relevance: 5 + }), { + label: "use_strict", + className: "meta", + relevance: 10, + begin: /^\s*['"]use (strict|asm)['"]/ + }, o.APOS_STRING_MODE, o.QUOTE_STRING_MODE, p, N, f, _, h, { + match: /\$\d+/ + }, A, x, { + className: "attr", + begin: d + l.lookahead(":"), + relevance: 0 + }, $, { + begin: "(" + o.RE_STARTERS_RE + "|\\b(case|return|throw)\\b)\\s*", + keywords: "return throw case", + relevance: 0, + contains: [h, o.REGEXP_MODE, { + className: "function", + begin: B, + returnBegin: !0, + end: "\\s*=>", + contains: [{ + className: "params", + variants: [{ + begin: o.UNDERSCORE_IDENT_RE, + relevance: 0 + }, { + className: null, + begin: /\(\s*\)/, + skip: !0 + }, { + begin: /(\s*)\(/, + end: /\)/, + excludeBegin: !0, + excludeEnd: !0, + keywords: g, + contains: w + }] + }] + }, { + begin: /,/, + relevance: 0 + }, { + match: /\s+/, + relevance: 0 + }, { + variants: [{ + begin: "<>", + end: "" + }, { + match: /<[A-Za-z0-9\\._:-]+\s*\/>/ + }, { + begin: b.begin, + "on:begin": b.isTrulyOpeningTag, + end: b.end + }], + subLanguage: "xml", + contains: [{ + begin: b.begin, + end: b.end, + skip: !0, + contains: ["self"] + }] + }] + }, O, { + beginKeywords: "while if switch catch for" + }, { + begin: "\\b(?!function)" + o.UNDERSCORE_IDENT_RE + + "\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", + returnBegin: !0, + label: "func.def", + contains: [R, o.inherit(o.TITLE_MODE, { + begin: d, + className: "title.function" + })] + }, { + match: /\.\.\./, + relevance: 0 + }, T, { + match: "\\$" + d, + relevance: 0 + }, { + match: [/\bconstructor(?=\s*\()/], + className: { + 1: "title.function" + }, + contains: [R] + }, I, { + relevance: 0, + match: /\b[A-Z][A-Z_0-9]+\b/, + className: "variable.constant" + }, k, M, { + match: /\$[(.]/ + }] + } + } + return t => { + const s = o(t), + r = e, + l = ["any", "void", "number", "boolean", "string", "object", "never", "symbol", + "bigint", "unknown" + ], + d = { + begin: [/namespace/, /\s+/, t.IDENT_RE], + beginScope: { + 1: "keyword", + 3: "title.class" + } + }, + b = { + beginKeywords: "interface", + end: /\{/, + excludeEnd: !0, + keywords: { + keyword: "interface extends", + built_in: l + }, + contains: [s.exports.CLASS_REFERENCE] + }, + g = { + $pattern: e, + keyword: n.concat(["type", "interface", "public", "private", "protected", + "implements", "declare", "abstract", "readonly", "enum", "override", + "satisfies" + ]), + literal: a, + built_in: i.concat(l), + "variable.language": c + }, + u = { + className: "meta", + begin: "@" + r + }, + m = (e, n, a) => { + const t = e.contains.findIndex((e => e.label === n)); + if (-1 === t) throw Error("can not find mode to replace"); + e.contains.splice(t, 1, a) + }; + Object.assign(s.keywords, g), s.exports.PARAMS_CONTAINS.push(u); + const E = s.contains.find((e => "attr" === e.className)); + return s.exports.PARAMS_CONTAINS.push([s.exports.CLASS_REFERENCE, E]), + s.contains = s.contains.concat([u, d, b]), + m(s, "shebang", t.SHEBANG()), m(s, "use_strict", { + className: "meta", + relevance: 10, + begin: /^\s*['"]use strict['"]/ + }), s.contains.find((e => "func.def" === e.label)).relevance = 0, Object.assign(s, { + name: "TypeScript", + aliases: ["ts", "tsx", "mts", "cts"] + }), s + } + })(); + hljs.registerLanguage("typescript", e) +})(); /*! `xml` grammar compiled for Highlight.js 11.10.0 */ +(() => { + var e = (() => { + "use strict"; + return e => { + const a = e.regex, + n = a.concat(/[\p{L}_]/u, a.optional(/[\p{L}0-9_.-]*:/u), /[\p{L}0-9_.-]*/u), + s = { + className: "symbol", + begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/ + }, + t = { + begin: /\s/, + contains: [{ + className: "keyword", + begin: /#?[a-z_][a-z1-9_-]+/, + illegal: /\n/ + }] + }, + i = e.inherit(t, { + begin: /\(/, + end: /\)/ + }), + c = e.inherit(e.APOS_STRING_MODE, { + className: "string" + }), + l = e.inherit(e.QUOTE_STRING_MODE, { + className: "string" + }), + r = { + endsWithParent: !0, + illegal: /`]+/ + }] + }] + }] + }; + return { + name: "HTML, XML", + aliases: ["html", "xhtml", "rss", "atom", "xjb", "xsd", "xsl", "plist", "wsf", "svg"], + case_insensitive: !0, + unicodeRegex: !0, + contains: [{ + className: "meta", + begin: //, + relevance: 10, + contains: [t, l, c, i, { + begin: /\[/, + end: /\]/, + contains: [{ + className: "meta", + begin: //, + contains: [t, i, l, c] + }] + }] + }, e.COMMENT(//, { + relevance: 10 + }), { + begin: //, + relevance: 10 + }, s, { + className: "meta", + end: /\?>/, + variants: [{ + begin: /<\?xml/, + relevance: 10, + contains: [l] + }, { + begin: /<\?[a-z][a-z0-9]+/ + }] + }, { + className: "tag", + begin: /)/, + end: />/, + keywords: { + name: "style" + }, + contains: [r], + starts: { + end: /<\/style>/, + returnEnd: !0, + subLanguage: ["css", "xml"] + } + }, { + className: "tag", + begin: /)/, + end: />/, + keywords: { + name: "script" + }, + contains: [r], + starts: { + end: /<\/script>/, + returnEnd: !0, + subLanguage: ["javascript", "handlebars", "xml"] + } + }, { + className: "tag", + begin: /<>|<\/>/ + }, { + className: "tag", + begin: a.concat(//, />/, /\s/)))), + end: /\/?>/, + contains: [{ + className: "name", + begin: n, + relevance: 0, + starts: r + }] + }, { + className: "tag", + begin: a.concat(/<\//, a.lookahead(a.concat(n, />/))), + contains: [{ + className: "name", + begin: n, + relevance: 0 + }, { + begin: />/, + relevance: 0, + endsParent: !0 + }] + }] + } + } + })(); + hljs.registerLanguage("xml", e) +})(); + diff --git a/uni_modules/tmx-ui/components/x-markdown/index.js b/uni_modules/tmx-ui/components/x-markdown/index.js new file mode 100644 index 0000000..e0c3d06 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/index.js @@ -0,0 +1,201 @@ +import * as l from "./katex.js" +const g = /([A-Z])/g, o = function(r) { + return r.replace(g, "-$1").toLowerCase(); +}, p = { + "&": "&", + ">": ">", + "<": "<", + '"': """, + "'": "'" +}, d = /[&><"']/g; +function h(r) { + return String(r).replace(d, (t) => p[t]); +} +const y = (r) => "data:image/svg+xml," + encodeURIComponent(r.replace(/\s+/g, " ")), x = (r, t, e) => { + let n = !1; + t.classes && t.classes.length > 0 && (n = !0); + const i = h(b(t.classes)); + let a = ""; + r === "text" && t.italic > 0 && (a += "margin-right:" + t.italic + "em;"); + for (const s in t.style) + t.style.hasOwnProperty(s) && (a += `${o(s)}:${t.style[s]};`); + a && (n = !0); + for (const s in t.attributes) + t.attributes.hasOwnProperty(s) && h(t.attributes[s]); + if (r === "span") + return { + name: "span", + attrs: { + class: i + " katex-span", + style: a + }, + children: e + }; + if (r === "img") + return { + name: "img", + attrs: { + class: i + " katex-img", + style: a + }, + children: e + }; + if (r === "text") { + const s = h(t.text); + return n ? { + name: "span", + attrs: { + class: i, + style: a + }, + children: [ + { + type: "text", + text: s + } + ] + } : { + type: "text", + text: s + }; + } + if (r === "svg") { + const s = t.toMarkup(); + return { + name: "img", + attrs: { + src: y(s), + class: "katex-svg" + } + }; + } + return null; +}, b = function(r) { + return (r == null ? void 0 : r.filter((t) => t).join(" ")) ?? ""; +}, u = (r, t) => r.map((e) => { + var s; + let n = t; + (s = e == null ? void 0 : e.style) != null && s.color && (n = e.style.color); + let i; + e instanceof l.__domTree.Span && (i = "span"), e instanceof l.__domTree.Anchor && (i = "anchor"), e instanceof l.__domTree.LineNode && (i = "line"), e instanceof l.__domTree.PathNode && (i = "path"), e instanceof l.__domTree.SvgNode && (i = "svg", n && (e.attributes.fill = n)), e instanceof l.__domTree.SymbolNode && (i = "text"); + const a = e.children && e.children.length > 0 ? u(e.children, n) : []; + return i ? x(i, e, a) : a; +}).reduce((e, n) => (Array.isArray(n) ? e.push(...n) : e.push(n), e), []).filter((e) => !!e), _ = (r, t = {}) => { + const { throwError: e, ...n } = t || {}; + try { + const i = l.__renderToDomTree(r, { + ...n, + output: "html" + }); + return u([i]); + } catch (i) { + if (e) throw i; + return [ + { + name: "span", + attrs: { + style: "color:red;" + }, + children: [{ type: "text", text: i.message }] + } + ]; + } +}, w = function(r, t, e) { + let n = e, i = 0; + const a = r.length; + for (; n < t.length; ) { + const s = t[n]; + if (i <= 0 && t.slice(n, n + a) === r) + return n; + s === "\\" ? n++ : s === "{" ? i++ : s === "}" && i--, n++; + } + return -1; +}, k = function(r) { + return r.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); +}, E = /^\\begin{/, T = function(r, t) { + let e; + const n = [], i = new RegExp( + "(" + t.map((a) => k(a.left)).join("|") + ")" + ); + for (; e = r.search(i), e !== -1; ) { + e > 0 && (n.push({ + type: "text", + data: r.slice(0, e) + }), r = r.slice(e)); + const a = t.findIndex((c) => r.startsWith(c.left)); + if (e = w(t[a].right, r, t[a].left.length), e === -1) + break; + const s = r.slice(0, e + t[a].right.length), f = E.test(s) ? s : r.slice(t[a].left.length, e); + n.push({ + type: "math", + data: f, + rawData: s, + display: t[a].display + }), r = r.slice(e + t[a].right.length); + } + return r !== "" && n.push({ + type: "text", + data: r + }), n; +}, P = function(r, t) { + var i; + const e = T( + r, + (t == null ? void 0 : t.delimiters) ?? [ + { left: "$$", right: "$$", display: !0 }, + { left: "\\(", right: "\\)", display: !1 }, + { left: "\\begin{equation}", right: "\\end{equation}", display: !0 }, + { left: "\\begin{align}", right: "\\end{align}", display: !0 }, + { left: "\\begin{alignat}", right: "\\end{alignat}", display: !0 }, + { left: "\\begin{gather}", right: "\\end{gather}", display: !0 }, + { left: "\\begin{CD}", right: "\\end{CD}", display: !0 }, + { left: "\\[", right: "\\]", display: !0 } + ] + ); + if (e.length === 1 && e[0].type === "text") + return e[0].data; + const n = []; + for (let a = 0; a < e.length; a++) + if (e[a].type === "text") + n.push({ + type: "node", + name: "span", + attrs: { + style: "white-space: pre-wrap;" + }, + children: [ + { + type: "text", + text: e[a].data + } + ] + }); + else { + const s = { + ...t + }; + let f = e[a].data; + s.displayMode = e[a].display; + try { + s.preProcess && (f = s.preProcess(f)); + const c = _(f, s); + n.push(...c); + } catch (c) { + if (!(c instanceof l.ParseError)) + throw c; + (i = t.errorCallback) == null || i.call( + t, + "KaTeX auto-render: Failed to parse `" + e[a].data + "` with ", + c + ), n.push(e[a].rawData); + continue; + } + } + return n; +}; +export { + b as createClass, + _ as default, + _ as parseLatex, + P as renderMathInText +}; diff --git a/uni_modules/tmx-ui/components/x-markdown/katex.js b/uni_modules/tmx-ui/components/x-markdown/katex.js new file mode 100644 index 0000000..9fe249f --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/katex.js @@ -0,0 +1,18549 @@ +/** + * Lexing or parsing positional information for error reporting. + * This object is immutable. + */ +class SourceLocation { + // The + prefix indicates that these fields aren't writeable + // Lexer holding the input string. + // Start offset, zero-based inclusive. + // End offset, zero-based exclusive. + constructor(lexer, start, end) { + this.lexer = void 0; + this.start = void 0; + this.end = void 0; + this.lexer = lexer; + this.start = start; + this.end = end; + } + /** + * Merges two `SourceLocation`s from location providers, given they are + * provided in order of appearance. + * - Returns the first one's location if only the first is provided. + * - Returns a merged range of the first and the last if both are provided + * and their lexers match. + * - Otherwise, returns null. + */ + + + static range(first, second) { + if (!second) { + return first && first.loc; + } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { + return null; + } else { + return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); + } + } + +} + +/** + * Interface required to break circular dependency between Token, Lexer, and + * ParseError. + */ + +/** + * The resulting token returned from `lex`. + * + * It consists of the token text plus some position information. + * The position information is essentially a range in an input string, + * but instead of referencing the bare input string, we refer to the lexer. + * That way it is possible to attach extra metadata to the input string, + * like for example a file name or similar. + * + * The position information is optional, so it is OK to construct synthetic + * tokens if appropriate. Not providing available position information may + * lead to degraded error reporting, though. + */ +class Token { + // don't expand the token + // used in \noexpand + constructor(text, // the text of this token + loc) { + this.text = void 0; + this.loc = void 0; + this.noexpand = void 0; + this.treatAsRelax = void 0; + this.text = text; + this.loc = loc; + } + /** + * Given a pair of tokens (this and endToken), compute a `Token` encompassing + * the whole input range enclosed by these two. + */ + + + range(endToken, // last token of the range, inclusive + text // the text of the newly constructed token + ) { + return new Token(text, SourceLocation.range(this, endToken)); + } + +} + +/** + * This is the ParseError class, which is the main error thrown by KaTeX + * functions when something has gone wrong. This is used to distinguish internal + * errors from errors in the expression that the user provided. + * + * If possible, a caller should provide a Token or ParseNode with information + * about where in the source string the problem occurred. + */ +class ParseError { + // Error start position based on passed-in Token or ParseNode. + // Length of affected text based on passed-in Token or ParseNode. + // The underlying error message without any context added. + constructor(message, // The error message + token // An object providing position information + ) { + this.name = void 0; + this.position = void 0; + this.length = void 0; + this.rawMessage = void 0; + var error = "KaTeX parse error: " + message; + var start; + var end; + var loc = token && token.loc; + + if (loc && loc.start <= loc.end) { + // If we have the input and a position, make the error a bit fancier + // Get the input + var input = loc.lexer.input; // Prepend some information + + start = loc.start; + end = loc.end; + + if (start === input.length) { + error += " at end of input: "; + } else { + error += " at position " + (start + 1) + ": "; + } // Underline token in question using combining underscores + + + var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error + + var left; + + if (start > 15) { + left = "…" + input.slice(start - 15, start); + } else { + left = input.slice(0, start); + } + + var right; + + if (end + 15 < input.length) { + right = input.slice(end, end + 15) + "…"; + } else { + right = input.slice(end); + } + + error += left + underlined + right; + } // Some hackery to make ParseError a prototype of Error + // See http://stackoverflow.com/a/8460753 + // $FlowFixMe + + + var self = new Error(error); + self.name = "ParseError"; // $FlowFixMe + + self.__proto__ = ParseError.prototype; + self.position = start; + + if (start != null && end != null) { + self.length = end - start; + } + + self.rawMessage = message; + return self; + } + +} // $FlowFixMe More hackery + + +ParseError.prototype.__proto__ = Error.prototype; + +/** + * This file contains a list of utility functions which are useful in other + * files. + */ + +/** + * Return whether an element is contained in a list + */ +var contains = function contains(list, elem) { + return list.indexOf(elem) !== -1; +}; +/** + * Provide a default value if a setting is undefined + * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022. + */ + + +var deflt = function deflt(setting, defaultIfUndefined) { + return setting === undefined ? defaultIfUndefined : setting; +}; // hyphenate and escape adapted from Facebook's React under Apache 2 license + + +var uppercase = /([A-Z])/g; + +var hyphenate = function hyphenate(str) { + return str.replace(uppercase, "-$1").toLowerCase(); +}; + +var ESCAPE_LOOKUP = { + "&": "&", + ">": ">", + "<": "<", + "\"": """, + "'": "'" +}; +var ESCAPE_REGEX = /[&><"']/g; +/** + * Escapes text to prevent scripting attacks. + */ + +function escape(text) { + return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]); +} +/** + * Sometimes we want to pull out the innermost element of a group. In most + * cases, this will just be the group itself, but when ordgroups and colors have + * a single element, we want to pull that out. + */ + + +var getBaseElem = function getBaseElem(group) { + if (group.type === "ordgroup") { + if (group.body.length === 1) { + return getBaseElem(group.body[0]); + } else { + return group; + } + } else if (group.type === "color") { + if (group.body.length === 1) { + return getBaseElem(group.body[0]); + } else { + return group; + } + } else if (group.type === "font") { + return getBaseElem(group.body); + } else { + return group; + } +}; +/** + * TeXbook algorithms often reference "character boxes", which are simply groups + * with a single character in them. To decide if something is a character box, + * we find its innermost group, and see if it is a single character. + */ + + +var isCharacterBox = function isCharacterBox(group) { + var baseElem = getBaseElem(group); // These are all they types of groups which hold single characters + + return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom"; +}; + +var assert = function assert(value) { + if (!value) { + throw new Error('Expected non-null, but got ' + String(value)); + } + + return value; +}; +/** + * Return the protocol of a URL, or "_relative" if the URL does not specify a + * protocol (and thus is relative), or `null` if URL has invalid protocol + * (so should be outright rejected). + */ + +var protocolFromUrl = function protocolFromUrl(url) { + // Check for possible leading protocol. + // https://url.spec.whatwg.org/#url-parsing strips leading whitespace + // (U+20) or C0 control (U+00-U+1F) characters. + // eslint-disable-next-line no-control-regex + var protocol = /^[\x00-\x20]*([^\\/#?]*?)(:|�*58|�*3a|&colon)/i.exec(url); + + if (!protocol) { + return "_relative"; + } // Reject weird colons + + + if (protocol[2] !== ":") { + return null; + } // Reject invalid characters in scheme according to + // https://datatracker.ietf.org/doc/html/rfc3986#section-3.1 + + + if (!/^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(protocol[1])) { + return null; + } // Lowercase the protocol + + + return protocol[1].toLowerCase(); +}; +var utils = { + contains, + deflt, + escape, + hyphenate, + getBaseElem, + isCharacterBox, + protocolFromUrl +}; + +/* eslint no-console:0 */ +// TODO: automatically generate documentation +// TODO: check all properties on Settings exist +// TODO: check the type of a property on Settings matches +var SETTINGS_SCHEMA = { + displayMode: { + type: "boolean", + description: "Render math in display mode, which puts the math in " + "display style (so \\int and \\sum are large, for example), and " + "centers the math on the page on its own line.", + cli: "-d, --display-mode" + }, + output: { + type: { + enum: ["htmlAndMathml", "html", "mathml"] + }, + description: "Determines the markup language of the output.", + cli: "-F, --format " + }, + leqno: { + type: "boolean", + description: "Render display math in leqno style (left-justified tags)." + }, + fleqn: { + type: "boolean", + description: "Render display math flush left." + }, + throwOnError: { + type: "boolean", + default: true, + cli: "-t, --no-throw-on-error", + cliDescription: "Render errors (in the color given by --error-color) ins" + "tead of throwing a ParseError exception when encountering an error." + }, + errorColor: { + type: "string", + default: "#cc0000", + cli: "-c, --error-color ", + cliDescription: "A color string given in the format 'rgb' or 'rrggbb' " + "(no #). This option determines the color of errors rendered by the " + "-t option.", + cliProcessor: color => "#" + color + }, + macros: { + type: "object", + cli: "-m, --macro ", + cliDescription: "Define custom macro of the form '\\foo:expansion' (use " + "multiple -m arguments for multiple macros).", + cliDefault: [], + cliProcessor: (def, defs) => { + defs.push(def); + return defs; + } + }, + minRuleThickness: { + type: "number", + description: "Specifies a minimum thickness, in ems, for fraction lines," + " `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, " + "`\\hdashline`, `\\underline`, `\\overline`, and the borders of " + "`\\fbox`, `\\boxed`, and `\\fcolorbox`.", + processor: t => Math.max(0, t), + cli: "--min-rule-thickness ", + cliProcessor: parseFloat + }, + colorIsTextColor: { + type: "boolean", + description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, " + "instead of LaTeX's one-argument \\color mode change.", + cli: "-b, --color-is-text-color" + }, + strict: { + type: [{ + enum: ["warn", "ignore", "error"] + }, "boolean", "function"], + description: "Turn on strict / LaTeX faithfulness mode, which throws an " + "error if the input uses features that are not supported by LaTeX.", + cli: "-S, --strict", + cliDefault: false + }, + trust: { + type: ["boolean", "function"], + description: "Trust the input, enabling all HTML features such as \\url.", + cli: "-T, --trust" + }, + maxSize: { + type: "number", + default: Infinity, + description: "If non-zero, all user-specified sizes, e.g. in " + "\\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, " + "elements and spaces can be arbitrarily large", + processor: s => Math.max(0, s), + cli: "-s, --max-size ", + cliProcessor: parseInt + }, + maxExpand: { + type: "number", + default: 1000, + description: "Limit the number of macro expansions to the specified " + "number, to prevent e.g. infinite macro loops. If set to Infinity, " + "the macro expander will try to fully expand as in LaTeX.", + processor: n => Math.max(0, n), + cli: "-e, --max-expand ", + cliProcessor: n => n === "Infinity" ? Infinity : parseInt(n) + }, + globalGroup: { + type: "boolean", + cli: false + } +}; + +function getDefaultValue(schema) { + if (schema.default) { + return schema.default; + } + + var type = schema.type; + var defaultType = Array.isArray(type) ? type[0] : type; + + if (typeof defaultType !== 'string') { + return defaultType.enum[0]; + } + + switch (defaultType) { + case 'boolean': + return false; + + case 'string': + return ''; + + case 'number': + return 0; + + case 'object': + return {}; + } +} +/** + * The main Settings object + * + * The current options stored are: + * - displayMode: Whether the expression should be typeset as inline math + * (false, the default), meaning that the math starts in + * \textstyle and is placed in an inline-block); or as display + * math (true), meaning that the math starts in \displaystyle + * and is placed in a block with vertical margin. + */ + + +class Settings { + constructor(options) { + this.displayMode = void 0; + this.output = void 0; + this.leqno = void 0; + this.fleqn = void 0; + this.throwOnError = void 0; + this.errorColor = void 0; + this.macros = void 0; + this.minRuleThickness = void 0; + this.colorIsTextColor = void 0; + this.strict = void 0; + this.trust = void 0; + this.maxSize = void 0; + this.maxExpand = void 0; + this.globalGroup = void 0; + // allow null options + options = options || {}; + + for (var prop in SETTINGS_SCHEMA) { + if (SETTINGS_SCHEMA.hasOwnProperty(prop)) { + // $FlowFixMe + var schema = SETTINGS_SCHEMA[prop]; // TODO: validate options + // $FlowFixMe + + this[prop] = options[prop] !== undefined ? schema.processor ? schema.processor(options[prop]) : options[prop] : getDefaultValue(schema); + } + } + } + /** + * Report nonstrict (non-LaTeX-compatible) input. + * Can safely not be called if `this.strict` is false in JavaScript. + */ + + + reportNonstrict(errorCode, errorMsg, token) { + var strict = this.strict; + + if (typeof strict === "function") { + // Allow return value of strict function to be boolean or string + // (or null/undefined, meaning no further processing). + strict = strict(errorCode, errorMsg, token); + } + + if (!strict || strict === "ignore") { + return; + } else if (strict === true || strict === "error") { + throw new ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + (errorMsg + " [" + errorCode + "]"), token); + } else if (strict === "warn") { + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]")); + } else { + // won't happen in type-safe code + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]")); + } + } + /** + * Check whether to apply strict (LaTeX-adhering) behavior for unusual + * input (like `\\`). Unlike `nonstrict`, will not throw an error; + * instead, "error" translates to a return value of `true`, while "ignore" + * translates to a return value of `false`. May still print a warning: + * "warn" prints a warning and returns `false`. + * This is for the second category of `errorCode`s listed in the README. + */ + + + useStrictBehavior(errorCode, errorMsg, token) { + var strict = this.strict; + + if (typeof strict === "function") { + // Allow return value of strict function to be boolean or string + // (or null/undefined, meaning no further processing). + // But catch any exceptions thrown by function, treating them + // like "error". + try { + strict = strict(errorCode, errorMsg, token); + } catch (error) { + strict = "error"; + } + } + + if (!strict || strict === "ignore") { + return false; + } else if (strict === true || strict === "error") { + return true; + } else if (strict === "warn") { + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]")); + return false; + } else { + // won't happen in type-safe code + typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]")); + return false; + } + } + /** + * Check whether to test potentially dangerous input, and return + * `true` (trusted) or `false` (untrusted). The sole argument `context` + * should be an object with `command` field specifying the relevant LaTeX + * command (as a string starting with `\`), and any other arguments, etc. + * If `context` has a `url` field, a `protocol` field will automatically + * get added by this function (changing the specified object). + */ + + + isTrusted(context) { + if (context.url && !context.protocol) { + var protocol = utils.protocolFromUrl(context.url); + + if (protocol == null) { + return false; + } + + context.protocol = protocol; + } + + var trust = typeof this.trust === "function" ? this.trust(context) : this.trust; + return Boolean(trust); + } + +} + +/** + * This file contains information and classes for the various kinds of styles + * used in TeX. It provides a generic `Style` class, which holds information + * about a specific style. It then provides instances of all the different kinds + * of styles possible, and provides functions to move between them and get + * information about them. + */ + +/** + * The main style class. Contains a unique id for the style, a size (which is + * the same for cramped and uncramped version of a style), and a cramped flag. + */ +class Style { + constructor(id, size, cramped) { + this.id = void 0; + this.size = void 0; + this.cramped = void 0; + this.id = id; + this.size = size; + this.cramped = cramped; + } + /** + * Get the style of a superscript given a base in the current style. + */ + + + sup() { + return styles[sup[this.id]]; + } + /** + * Get the style of a subscript given a base in the current style. + */ + + + sub() { + return styles[sub[this.id]]; + } + /** + * Get the style of a fraction numerator given the fraction in the current + * style. + */ + + + fracNum() { + return styles[fracNum[this.id]]; + } + /** + * Get the style of a fraction denominator given the fraction in the current + * style. + */ + + + fracDen() { + return styles[fracDen[this.id]]; + } + /** + * Get the cramped version of a style (in particular, cramping a cramped style + * doesn't change the style). + */ + + + cramp() { + return styles[cramp[this.id]]; + } + /** + * Get a text or display version of this style. + */ + + + text() { + return styles[text$1[this.id]]; + } + /** + * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle) + */ + + + isTight() { + return this.size >= 2; + } + +} // Export an interface for type checking, but don't expose the implementation. +// This way, no more styles can be generated. + + +// IDs of the different styles +var D = 0; +var Dc = 1; +var T = 2; +var Tc = 3; +var S = 4; +var Sc = 5; +var SS = 6; +var SSc = 7; // Instances of the different styles + +var styles = [new Style(D, 0, false), new Style(Dc, 0, true), new Style(T, 1, false), new Style(Tc, 1, true), new Style(S, 2, false), new Style(Sc, 2, true), new Style(SS, 3, false), new Style(SSc, 3, true)]; // Lookup tables for switching from one style to another + +var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; +var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; +var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; +var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; +var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; +var text$1 = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles. + +var Style$1 = { + DISPLAY: styles[D], + TEXT: styles[T], + SCRIPT: styles[S], + SCRIPTSCRIPT: styles[SS] +}; + +/* + * This file defines the Unicode scripts and script families that we + * support. To add new scripts or families, just add a new entry to the + * scriptData array below. Adding scripts to the scriptData array allows + * characters from that script to appear in \text{} environments. + */ + +/** + * Each script or script family has a name and an array of blocks. + * Each block is an array of two numbers which specify the start and + * end points (inclusive) of a block of Unicode codepoints. + */ + +/** + * Unicode block data for the families of scripts we support in \text{}. + * Scripts only need to appear here if they do not have font metrics. + */ +var scriptData = [{ + // Latin characters beyond the Latin-1 characters we have metrics for. + // Needed for Czech, Hungarian and Turkish text, for example. + name: 'latin', + blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B + [0x0300, 0x036f] // Combining Diacritical marks + ] +}, { + // The Cyrillic script used by Russian and related languages. + // A Cyrillic subset used to be supported as explicitly defined + // symbols in symbols.js + name: 'cyrillic', + blocks: [[0x0400, 0x04ff]] +}, { + // Armenian + name: 'armenian', + blocks: [[0x0530, 0x058F]] +}, { + // The Brahmic scripts of South and Southeast Asia + // Devanagari (0900–097F) + // Bengali (0980–09FF) + // Gurmukhi (0A00–0A7F) + // Gujarati (0A80–0AFF) + // Oriya (0B00–0B7F) + // Tamil (0B80–0BFF) + // Telugu (0C00–0C7F) + // Kannada (0C80–0CFF) + // Malayalam (0D00–0D7F) + // Sinhala (0D80–0DFF) + // Thai (0E00–0E7F) + // Lao (0E80–0EFF) + // Tibetan (0F00–0FFF) + // Myanmar (1000–109F) + name: 'brahmic', + blocks: [[0x0900, 0x109F]] +}, { + name: 'georgian', + blocks: [[0x10A0, 0x10ff]] +}, { + // Chinese and Japanese. + // The "k" in cjk is for Korean, but we've separated Korean out + name: "cjk", + blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana + [0x4E00, 0x9FAF], // CJK ideograms + [0xFF00, 0xFF60] // Fullwidth punctuation + // TODO: add halfwidth Katakana and Romanji glyphs + ] +}, { + // Korean + name: 'hangul', + blocks: [[0xAC00, 0xD7AF]] +}]; +/** + * Given a codepoint, return the name of the script or script family + * it is from, or null if it is not part of a known block + */ + +function scriptFromCodepoint(codepoint) { + for (var i = 0; i < scriptData.length; i++) { + var script = scriptData[i]; + + for (var _i = 0; _i < script.blocks.length; _i++) { + var block = script.blocks[_i]; + + if (codepoint >= block[0] && codepoint <= block[1]) { + return script.name; + } + } + } + + return null; +} +/** + * A flattened version of all the supported blocks in a single array. + * This is an optimization to make supportedCodepoint() fast. + */ + +var allBlocks = []; +scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b))); +/** + * Given a codepoint, return true if it falls within one of the + * scripts or script families defined above and false otherwise. + * + * Micro benchmarks shows that this is faster than + * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() + * in Firefox, Chrome and Node. + */ + +function supportedCodepoint(codepoint) { + for (var i = 0; i < allBlocks.length; i += 2) { + if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { + return true; + } + } + + return false; +} + +/** + * This file provides support to domTree.js and delimiter.js. + * It's a storehouse of path geometry for SVG images. + */ +// In all paths below, the viewBox-to-em scale is 1000:1. +var hLinePad = 80; // padding above a sqrt vinculum. Prevents image cropping. +// The vinculum of a \sqrt can be made thicker by a KaTeX rendering option. +// Think of variable extraVinculum as two detours in the SVG path. +// The detour begins at the lower left of the area labeled extraVinculum below. +// The detour proceeds one extraVinculum distance up and slightly to the right, +// displacing the radiused corner between surd and vinculum. The radius is +// traversed as usual, then the detour resumes. It goes right, to the end of +// the very long vinculum, then down one extraVinculum distance, +// after which it resumes regular path geometry for the radical. + +/* vinculum + / + /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraVinculum + / █████████████████████←0.04em (40 unit) std vinculum thickness + / / + / / + / /\ + / / surd +*/ + +var sqrtMain = function sqrtMain(extraVinculum, hLinePad) { + // sqrtMain path geometry is from glyph U221A in the font KaTeX Main + return "M95," + (622 + extraVinculum + hLinePad) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + extraVinculum / 2.075 + " -" + extraVinculum + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + extraVinculum) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +var sqrtSize1 = function sqrtSize1(extraVinculum, hLinePad) { + // size1 is from glyph U221A in the font KaTeX_Size1-Regular + return "M263," + (601 + extraVinculum + hLinePad) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + extraVinculum / 2.084 + " -" + extraVinculum + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + extraVinculum) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +var sqrtSize2 = function sqrtSize2(extraVinculum, hLinePad) { + // size2 is from glyph U221A in the font KaTeX_Size2-Regular + return "M983 " + (10 + extraVinculum + hLinePad) + "\nl" + extraVinculum / 3.13 + " -" + extraVinculum + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + extraVinculum) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +var sqrtSize3 = function sqrtSize3(extraVinculum, hLinePad) { + // size3 is from glyph U221A in the font KaTeX_Size3-Regular + return "M424," + (2398 + extraVinculum + hLinePad) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + extraVinculum / 4.223 + " -" + extraVinculum + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + extraVinculum) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + extraVinculum) + " " + hLinePad + "\nh400000v" + (40 + extraVinculum) + "h-400000z"; +}; + +var sqrtSize4 = function sqrtSize4(extraVinculum, hLinePad) { + // size4 is from glyph U221A in the font KaTeX_Size4-Regular + return "M473," + (2713 + extraVinculum + hLinePad) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + extraVinculum / 5.298 + " -" + extraVinculum + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + extraVinculum) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "H1017.7z"; +}; + +var phasePath = function phasePath(y) { + var x = y / 2; // x coordinate at top of angle + + return "M400000 " + y + " H0 L" + x + " 0 l65 45 L145 " + (y - 80) + " H400000z"; +}; + +var sqrtTall = function sqrtTall(extraVinculum, hLinePad, viewBoxHeight) { + // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular + // One path edge has a variable length. It runs vertically from the vinculum + // to a point near (14 units) the bottom of the surd. The vinculum + // is normally 40 units thick. So the length of the line in question is: + var vertSegment = viewBoxHeight - 54 - hLinePad - extraVinculum; + return "M702 " + (extraVinculum + hLinePad) + "H400000" + (40 + extraVinculum) + "\nH742v" + vertSegment + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + hLinePad + "H400000v" + (40 + extraVinculum) + "H742z"; +}; + +var sqrtPath = function sqrtPath(size, extraVinculum, viewBoxHeight) { + extraVinculum = 1000 * extraVinculum; // Convert from document ems to viewBox. + + var path = ""; + + switch (size) { + case "sqrtMain": + path = sqrtMain(extraVinculum, hLinePad); + break; + + case "sqrtSize1": + path = sqrtSize1(extraVinculum, hLinePad); + break; + + case "sqrtSize2": + path = sqrtSize2(extraVinculum, hLinePad); + break; + + case "sqrtSize3": + path = sqrtSize3(extraVinculum, hLinePad); + break; + + case "sqrtSize4": + path = sqrtSize4(extraVinculum, hLinePad); + break; + + case "sqrtTall": + path = sqrtTall(extraVinculum, hLinePad, viewBoxHeight); + } + + return path; +}; +var innerPath = function innerPath(name, height) { + // The inner part of stretchy tall delimiters + switch (name) { + case "\u239c": + return "M291 0 H417 V" + height + " H291z M291 0 H417 V" + height + " H291z"; + + case "\u2223": + return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z"; + + case "\u2225": + return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z" + ("M367 0 H410 V" + height + " H367z M367 0 H410 V" + height + " H367z"); + + case "\u239f": + return "M457 0 H583 V" + height + " H457z M457 0 H583 V" + height + " H457z"; + + case "\u23a2": + return "M319 0 H403 V" + height + " H319z M319 0 H403 V" + height + " H319z"; + + case "\u23a5": + return "M263 0 H347 V" + height + " H263z M263 0 H347 V" + height + " H263z"; + + case "\u23aa": + return "M384 0 H504 V" + height + " H384z M384 0 H504 V" + height + " H384z"; + + case "\u23d0": + return "M312 0 H355 V" + height + " H312z M312 0 H355 V" + height + " H312z"; + + case "\u2016": + return "M257 0 H300 V" + height + " H257z M257 0 H300 V" + height + " H257z" + ("M478 0 H521 V" + height + " H478z M478 0 H521 V" + height + " H478z"); + + default: + return ""; + } +}; +var path = { + // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main + doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z", + // doublerightarrow is from glyph U+21D2 in font KaTeX Main + doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z", + // leftarrow is from glyph U+2190 in font KaTeX Main + leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z", + // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular + leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z", + leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z", + // overgroup is from the MnSymbol package (public domain) + leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z", + leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z", + // Harpoons are from glyph U+21BD in font KaTeX Main + leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z", + leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z", + leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z", + leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z", + // hook is from glyph U+21A9 in font KaTeX Main + lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z", + leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z", + leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z", + // tofrom is from glyph U+21C4 in font KaTeX AMS Regular + leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z", + longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z", + midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z", + midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z", + oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z", + oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z", + oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z", + oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z", + rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z", + rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z", + rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z", + rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z", + rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z", + rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z", + rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z", + rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z", + rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z", + righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z", + rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z", + rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z", + // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular + twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z", + twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z", + // tilde1 is a modified version of a glyph from the MnSymbol package + tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z", + // ditto tilde2, tilde3, & tilde4 + tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z", + tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z", + tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z", + // vec is from glyph U+20D7 in font KaTeX Main + vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z", + // widehat1 is a modified version of a glyph from the MnSymbol package + widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z", + // ditto widehat2, widehat3, & widehat4 + widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", + widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", + widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", + // widecheck paths are all inverted versions of widehat + widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z", + widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", + widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", + widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", + // The next ten paths support reaction arrows from the mhchem package. + // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX + // baraboveleftarrow is mostly from glyph U+2190 in font KaTeX Main + baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z", + // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main + rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z", + // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end. + // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em + baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z", + rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z", + shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z", + shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z" +}; +var tallDelim = function tallDelim(label, midHeight) { + switch (label) { + case "lbrack": + return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v" + midHeight + " v1759 h84z"; + + case "rbrack": + return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v" + midHeight + " v1759 h84z"; + + case "vert": + return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z"; + + case "doublevert": + return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z\nM367 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v" + midHeight + " v585 h43z"; + + case "lfloor": + return "M319 602 V0 H403 V602 v" + midHeight + " v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z"; + + case "rfloor": + return "M319 602 V0 H403 V602 v" + midHeight + " v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z"; + + case "lceil": + return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v602 h84z\nM403 1759 V0 H319 V1759 v" + midHeight + " v602 h84z"; + + case "rceil": + return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v602 h84z\nM347 1759 V0 h-84 V1759 v" + midHeight + " v602 h84z"; + + case "lparen": + return "M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0," + (midHeight + 84) + "c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-" + (midHeight + 92) + "c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"; + + case "rparen": + return "M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0," + (midHeight + 9) + "\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-" + (midHeight + 144) + "c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"; + + default: + // We should not ever get here. + throw new Error("Unknown stretchy delimiter."); + } +}; + +/** + * This node represents a document fragment, which contains elements, but when + * placed into the DOM doesn't have any representation itself. It only contains + * children and doesn't have any DOM node properties. + */ +class DocumentFragment { + // HtmlDomNode + // Never used; needed for satisfying interface. + constructor(children) { + this.children = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.maxFontSize = void 0; + this.style = void 0; + this.children = children; + this.classes = []; + this.height = 0; + this.depth = 0; + this.maxFontSize = 0; + this.style = {}; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + /** Convert the fragment into a node. */ + + + toNode() { + var frag = document.createDocumentFragment(); + + for (var i = 0; i < this.children.length; i++) { + frag.appendChild(this.children[i].toNode()); + } + + return frag; + } + /** Convert the fragment into HTML markup. */ + + + toMarkup() { + var markup = ""; // Simply concatenate the markup for the children together. + + for (var i = 0; i < this.children.length; i++) { + markup += this.children[i].toMarkup(); + } + + return markup; + } + /** + * Converts the math node into a string, similar to innerText. Applies to + * MathDomNode's only. + */ + + + toText() { + // To avoid this, we would subclass documentFragment separately for + // MathML, but polyfills for subclassing is expensive per PR 1469. + // $FlowFixMe: Only works for ChildType = MathDomNode. + var toText = child => child.toText(); + + return this.children.map(toText).join(""); + } + +} + +// This file is GENERATED by buildMetrics.sh. DO NOT MODIFY. +var fontMetricsData = { + "AMS-Regular": { + "32": [0, 0, 0, 0, 0.25], + "65": [0, 0.68889, 0, 0, 0.72222], + "66": [0, 0.68889, 0, 0, 0.66667], + "67": [0, 0.68889, 0, 0, 0.72222], + "68": [0, 0.68889, 0, 0, 0.72222], + "69": [0, 0.68889, 0, 0, 0.66667], + "70": [0, 0.68889, 0, 0, 0.61111], + "71": [0, 0.68889, 0, 0, 0.77778], + "72": [0, 0.68889, 0, 0, 0.77778], + "73": [0, 0.68889, 0, 0, 0.38889], + "74": [0.16667, 0.68889, 0, 0, 0.5], + "75": [0, 0.68889, 0, 0, 0.77778], + "76": [0, 0.68889, 0, 0, 0.66667], + "77": [0, 0.68889, 0, 0, 0.94445], + "78": [0, 0.68889, 0, 0, 0.72222], + "79": [0.16667, 0.68889, 0, 0, 0.77778], + "80": [0, 0.68889, 0, 0, 0.61111], + "81": [0.16667, 0.68889, 0, 0, 0.77778], + "82": [0, 0.68889, 0, 0, 0.72222], + "83": [0, 0.68889, 0, 0, 0.55556], + "84": [0, 0.68889, 0, 0, 0.66667], + "85": [0, 0.68889, 0, 0, 0.72222], + "86": [0, 0.68889, 0, 0, 0.72222], + "87": [0, 0.68889, 0, 0, 1.0], + "88": [0, 0.68889, 0, 0, 0.72222], + "89": [0, 0.68889, 0, 0, 0.72222], + "90": [0, 0.68889, 0, 0, 0.66667], + "107": [0, 0.68889, 0, 0, 0.55556], + "160": [0, 0, 0, 0, 0.25], + "165": [0, 0.675, 0.025, 0, 0.75], + "174": [0.15559, 0.69224, 0, 0, 0.94666], + "240": [0, 0.68889, 0, 0, 0.55556], + "295": [0, 0.68889, 0, 0, 0.54028], + "710": [0, 0.825, 0, 0, 2.33334], + "732": [0, 0.9, 0, 0, 2.33334], + "770": [0, 0.825, 0, 0, 2.33334], + "771": [0, 0.9, 0, 0, 2.33334], + "989": [0.08167, 0.58167, 0, 0, 0.77778], + "1008": [0, 0.43056, 0.04028, 0, 0.66667], + "8245": [0, 0.54986, 0, 0, 0.275], + "8463": [0, 0.68889, 0, 0, 0.54028], + "8487": [0, 0.68889, 0, 0, 0.72222], + "8498": [0, 0.68889, 0, 0, 0.55556], + "8502": [0, 0.68889, 0, 0, 0.66667], + "8503": [0, 0.68889, 0, 0, 0.44445], + "8504": [0, 0.68889, 0, 0, 0.66667], + "8513": [0, 0.68889, 0, 0, 0.63889], + "8592": [-0.03598, 0.46402, 0, 0, 0.5], + "8594": [-0.03598, 0.46402, 0, 0, 0.5], + "8602": [-0.13313, 0.36687, 0, 0, 1.0], + "8603": [-0.13313, 0.36687, 0, 0, 1.0], + "8606": [0.01354, 0.52239, 0, 0, 1.0], + "8608": [0.01354, 0.52239, 0, 0, 1.0], + "8610": [0.01354, 0.52239, 0, 0, 1.11111], + "8611": [0.01354, 0.52239, 0, 0, 1.11111], + "8619": [0, 0.54986, 0, 0, 1.0], + "8620": [0, 0.54986, 0, 0, 1.0], + "8621": [-0.13313, 0.37788, 0, 0, 1.38889], + "8622": [-0.13313, 0.36687, 0, 0, 1.0], + "8624": [0, 0.69224, 0, 0, 0.5], + "8625": [0, 0.69224, 0, 0, 0.5], + "8630": [0, 0.43056, 0, 0, 1.0], + "8631": [0, 0.43056, 0, 0, 1.0], + "8634": [0.08198, 0.58198, 0, 0, 0.77778], + "8635": [0.08198, 0.58198, 0, 0, 0.77778], + "8638": [0.19444, 0.69224, 0, 0, 0.41667], + "8639": [0.19444, 0.69224, 0, 0, 0.41667], + "8642": [0.19444, 0.69224, 0, 0, 0.41667], + "8643": [0.19444, 0.69224, 0, 0, 0.41667], + "8644": [0.1808, 0.675, 0, 0, 1.0], + "8646": [0.1808, 0.675, 0, 0, 1.0], + "8647": [0.1808, 0.675, 0, 0, 1.0], + "8648": [0.19444, 0.69224, 0, 0, 0.83334], + "8649": [0.1808, 0.675, 0, 0, 1.0], + "8650": [0.19444, 0.69224, 0, 0, 0.83334], + "8651": [0.01354, 0.52239, 0, 0, 1.0], + "8652": [0.01354, 0.52239, 0, 0, 1.0], + "8653": [-0.13313, 0.36687, 0, 0, 1.0], + "8654": [-0.13313, 0.36687, 0, 0, 1.0], + "8655": [-0.13313, 0.36687, 0, 0, 1.0], + "8666": [0.13667, 0.63667, 0, 0, 1.0], + "8667": [0.13667, 0.63667, 0, 0, 1.0], + "8669": [-0.13313, 0.37788, 0, 0, 1.0], + "8672": [-0.064, 0.437, 0, 0, 1.334], + "8674": [-0.064, 0.437, 0, 0, 1.334], + "8705": [0, 0.825, 0, 0, 0.5], + "8708": [0, 0.68889, 0, 0, 0.55556], + "8709": [0.08167, 0.58167, 0, 0, 0.77778], + "8717": [0, 0.43056, 0, 0, 0.42917], + "8722": [-0.03598, 0.46402, 0, 0, 0.5], + "8724": [0.08198, 0.69224, 0, 0, 0.77778], + "8726": [0.08167, 0.58167, 0, 0, 0.77778], + "8733": [0, 0.69224, 0, 0, 0.77778], + "8736": [0, 0.69224, 0, 0, 0.72222], + "8737": [0, 0.69224, 0, 0, 0.72222], + "8738": [0.03517, 0.52239, 0, 0, 0.72222], + "8739": [0.08167, 0.58167, 0, 0, 0.22222], + "8740": [0.25142, 0.74111, 0, 0, 0.27778], + "8741": [0.08167, 0.58167, 0, 0, 0.38889], + "8742": [0.25142, 0.74111, 0, 0, 0.5], + "8756": [0, 0.69224, 0, 0, 0.66667], + "8757": [0, 0.69224, 0, 0, 0.66667], + "8764": [-0.13313, 0.36687, 0, 0, 0.77778], + "8765": [-0.13313, 0.37788, 0, 0, 0.77778], + "8769": [-0.13313, 0.36687, 0, 0, 0.77778], + "8770": [-0.03625, 0.46375, 0, 0, 0.77778], + "8774": [0.30274, 0.79383, 0, 0, 0.77778], + "8776": [-0.01688, 0.48312, 0, 0, 0.77778], + "8778": [0.08167, 0.58167, 0, 0, 0.77778], + "8782": [0.06062, 0.54986, 0, 0, 0.77778], + "8783": [0.06062, 0.54986, 0, 0, 0.77778], + "8785": [0.08198, 0.58198, 0, 0, 0.77778], + "8786": [0.08198, 0.58198, 0, 0, 0.77778], + "8787": [0.08198, 0.58198, 0, 0, 0.77778], + "8790": [0, 0.69224, 0, 0, 0.77778], + "8791": [0.22958, 0.72958, 0, 0, 0.77778], + "8796": [0.08198, 0.91667, 0, 0, 0.77778], + "8806": [0.25583, 0.75583, 0, 0, 0.77778], + "8807": [0.25583, 0.75583, 0, 0, 0.77778], + "8808": [0.25142, 0.75726, 0, 0, 0.77778], + "8809": [0.25142, 0.75726, 0, 0, 0.77778], + "8812": [0.25583, 0.75583, 0, 0, 0.5], + "8814": [0.20576, 0.70576, 0, 0, 0.77778], + "8815": [0.20576, 0.70576, 0, 0, 0.77778], + "8816": [0.30274, 0.79383, 0, 0, 0.77778], + "8817": [0.30274, 0.79383, 0, 0, 0.77778], + "8818": [0.22958, 0.72958, 0, 0, 0.77778], + "8819": [0.22958, 0.72958, 0, 0, 0.77778], + "8822": [0.1808, 0.675, 0, 0, 0.77778], + "8823": [0.1808, 0.675, 0, 0, 0.77778], + "8828": [0.13667, 0.63667, 0, 0, 0.77778], + "8829": [0.13667, 0.63667, 0, 0, 0.77778], + "8830": [0.22958, 0.72958, 0, 0, 0.77778], + "8831": [0.22958, 0.72958, 0, 0, 0.77778], + "8832": [0.20576, 0.70576, 0, 0, 0.77778], + "8833": [0.20576, 0.70576, 0, 0, 0.77778], + "8840": [0.30274, 0.79383, 0, 0, 0.77778], + "8841": [0.30274, 0.79383, 0, 0, 0.77778], + "8842": [0.13597, 0.63597, 0, 0, 0.77778], + "8843": [0.13597, 0.63597, 0, 0, 0.77778], + "8847": [0.03517, 0.54986, 0, 0, 0.77778], + "8848": [0.03517, 0.54986, 0, 0, 0.77778], + "8858": [0.08198, 0.58198, 0, 0, 0.77778], + "8859": [0.08198, 0.58198, 0, 0, 0.77778], + "8861": [0.08198, 0.58198, 0, 0, 0.77778], + "8862": [0, 0.675, 0, 0, 0.77778], + "8863": [0, 0.675, 0, 0, 0.77778], + "8864": [0, 0.675, 0, 0, 0.77778], + "8865": [0, 0.675, 0, 0, 0.77778], + "8872": [0, 0.69224, 0, 0, 0.61111], + "8873": [0, 0.69224, 0, 0, 0.72222], + "8874": [0, 0.69224, 0, 0, 0.88889], + "8876": [0, 0.68889, 0, 0, 0.61111], + "8877": [0, 0.68889, 0, 0, 0.61111], + "8878": [0, 0.68889, 0, 0, 0.72222], + "8879": [0, 0.68889, 0, 0, 0.72222], + "8882": [0.03517, 0.54986, 0, 0, 0.77778], + "8883": [0.03517, 0.54986, 0, 0, 0.77778], + "8884": [0.13667, 0.63667, 0, 0, 0.77778], + "8885": [0.13667, 0.63667, 0, 0, 0.77778], + "8888": [0, 0.54986, 0, 0, 1.11111], + "8890": [0.19444, 0.43056, 0, 0, 0.55556], + "8891": [0.19444, 0.69224, 0, 0, 0.61111], + "8892": [0.19444, 0.69224, 0, 0, 0.61111], + "8901": [0, 0.54986, 0, 0, 0.27778], + "8903": [0.08167, 0.58167, 0, 0, 0.77778], + "8905": [0.08167, 0.58167, 0, 0, 0.77778], + "8906": [0.08167, 0.58167, 0, 0, 0.77778], + "8907": [0, 0.69224, 0, 0, 0.77778], + "8908": [0, 0.69224, 0, 0, 0.77778], + "8909": [-0.03598, 0.46402, 0, 0, 0.77778], + "8910": [0, 0.54986, 0, 0, 0.76042], + "8911": [0, 0.54986, 0, 0, 0.76042], + "8912": [0.03517, 0.54986, 0, 0, 0.77778], + "8913": [0.03517, 0.54986, 0, 0, 0.77778], + "8914": [0, 0.54986, 0, 0, 0.66667], + "8915": [0, 0.54986, 0, 0, 0.66667], + "8916": [0, 0.69224, 0, 0, 0.66667], + "8918": [0.0391, 0.5391, 0, 0, 0.77778], + "8919": [0.0391, 0.5391, 0, 0, 0.77778], + "8920": [0.03517, 0.54986, 0, 0, 1.33334], + "8921": [0.03517, 0.54986, 0, 0, 1.33334], + "8922": [0.38569, 0.88569, 0, 0, 0.77778], + "8923": [0.38569, 0.88569, 0, 0, 0.77778], + "8926": [0.13667, 0.63667, 0, 0, 0.77778], + "8927": [0.13667, 0.63667, 0, 0, 0.77778], + "8928": [0.30274, 0.79383, 0, 0, 0.77778], + "8929": [0.30274, 0.79383, 0, 0, 0.77778], + "8934": [0.23222, 0.74111, 0, 0, 0.77778], + "8935": [0.23222, 0.74111, 0, 0, 0.77778], + "8936": [0.23222, 0.74111, 0, 0, 0.77778], + "8937": [0.23222, 0.74111, 0, 0, 0.77778], + "8938": [0.20576, 0.70576, 0, 0, 0.77778], + "8939": [0.20576, 0.70576, 0, 0, 0.77778], + "8940": [0.30274, 0.79383, 0, 0, 0.77778], + "8941": [0.30274, 0.79383, 0, 0, 0.77778], + "8994": [0.19444, 0.69224, 0, 0, 0.77778], + "8995": [0.19444, 0.69224, 0, 0, 0.77778], + "9416": [0.15559, 0.69224, 0, 0, 0.90222], + "9484": [0, 0.69224, 0, 0, 0.5], + "9488": [0, 0.69224, 0, 0, 0.5], + "9492": [0, 0.37788, 0, 0, 0.5], + "9496": [0, 0.37788, 0, 0, 0.5], + "9585": [0.19444, 0.68889, 0, 0, 0.88889], + "9586": [0.19444, 0.74111, 0, 0, 0.88889], + "9632": [0, 0.675, 0, 0, 0.77778], + "9633": [0, 0.675, 0, 0, 0.77778], + "9650": [0, 0.54986, 0, 0, 0.72222], + "9651": [0, 0.54986, 0, 0, 0.72222], + "9654": [0.03517, 0.54986, 0, 0, 0.77778], + "9660": [0, 0.54986, 0, 0, 0.72222], + "9661": [0, 0.54986, 0, 0, 0.72222], + "9664": [0.03517, 0.54986, 0, 0, 0.77778], + "9674": [0.11111, 0.69224, 0, 0, 0.66667], + "9733": [0.19444, 0.69224, 0, 0, 0.94445], + "10003": [0, 0.69224, 0, 0, 0.83334], + "10016": [0, 0.69224, 0, 0, 0.83334], + "10731": [0.11111, 0.69224, 0, 0, 0.66667], + "10846": [0.19444, 0.75583, 0, 0, 0.61111], + "10877": [0.13667, 0.63667, 0, 0, 0.77778], + "10878": [0.13667, 0.63667, 0, 0, 0.77778], + "10885": [0.25583, 0.75583, 0, 0, 0.77778], + "10886": [0.25583, 0.75583, 0, 0, 0.77778], + "10887": [0.13597, 0.63597, 0, 0, 0.77778], + "10888": [0.13597, 0.63597, 0, 0, 0.77778], + "10889": [0.26167, 0.75726, 0, 0, 0.77778], + "10890": [0.26167, 0.75726, 0, 0, 0.77778], + "10891": [0.48256, 0.98256, 0, 0, 0.77778], + "10892": [0.48256, 0.98256, 0, 0, 0.77778], + "10901": [0.13667, 0.63667, 0, 0, 0.77778], + "10902": [0.13667, 0.63667, 0, 0, 0.77778], + "10933": [0.25142, 0.75726, 0, 0, 0.77778], + "10934": [0.25142, 0.75726, 0, 0, 0.77778], + "10935": [0.26167, 0.75726, 0, 0, 0.77778], + "10936": [0.26167, 0.75726, 0, 0, 0.77778], + "10937": [0.26167, 0.75726, 0, 0, 0.77778], + "10938": [0.26167, 0.75726, 0, 0, 0.77778], + "10949": [0.25583, 0.75583, 0, 0, 0.77778], + "10950": [0.25583, 0.75583, 0, 0, 0.77778], + "10955": [0.28481, 0.79383, 0, 0, 0.77778], + "10956": [0.28481, 0.79383, 0, 0, 0.77778], + "57350": [0.08167, 0.58167, 0, 0, 0.22222], + "57351": [0.08167, 0.58167, 0, 0, 0.38889], + "57352": [0.08167, 0.58167, 0, 0, 0.77778], + "57353": [0, 0.43056, 0.04028, 0, 0.66667], + "57356": [0.25142, 0.75726, 0, 0, 0.77778], + "57357": [0.25142, 0.75726, 0, 0, 0.77778], + "57358": [0.41951, 0.91951, 0, 0, 0.77778], + "57359": [0.30274, 0.79383, 0, 0, 0.77778], + "57360": [0.30274, 0.79383, 0, 0, 0.77778], + "57361": [0.41951, 0.91951, 0, 0, 0.77778], + "57366": [0.25142, 0.75726, 0, 0, 0.77778], + "57367": [0.25142, 0.75726, 0, 0, 0.77778], + "57368": [0.25142, 0.75726, 0, 0, 0.77778], + "57369": [0.25142, 0.75726, 0, 0, 0.77778], + "57370": [0.13597, 0.63597, 0, 0, 0.77778], + "57371": [0.13597, 0.63597, 0, 0, 0.77778] + }, + "Caligraphic-Regular": { + "32": [0, 0, 0, 0, 0.25], + "65": [0, 0.68333, 0, 0.19445, 0.79847], + "66": [0, 0.68333, 0.03041, 0.13889, 0.65681], + "67": [0, 0.68333, 0.05834, 0.13889, 0.52653], + "68": [0, 0.68333, 0.02778, 0.08334, 0.77139], + "69": [0, 0.68333, 0.08944, 0.11111, 0.52778], + "70": [0, 0.68333, 0.09931, 0.11111, 0.71875], + "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487], + "72": [0, 0.68333, 0.00965, 0.11111, 0.84452], + "73": [0, 0.68333, 0.07382, 0, 0.54452], + "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778], + "75": [0, 0.68333, 0.01445, 0.05556, 0.76195], + "76": [0, 0.68333, 0, 0.13889, 0.68972], + "77": [0, 0.68333, 0, 0.13889, 1.2009], + "78": [0, 0.68333, 0.14736, 0.08334, 0.82049], + "79": [0, 0.68333, 0.02778, 0.11111, 0.79611], + "80": [0, 0.68333, 0.08222, 0.08334, 0.69556], + "81": [0.09722, 0.68333, 0, 0.11111, 0.81667], + "82": [0, 0.68333, 0, 0.08334, 0.8475], + "83": [0, 0.68333, 0.075, 0.13889, 0.60556], + "84": [0, 0.68333, 0.25417, 0, 0.54464], + "85": [0, 0.68333, 0.09931, 0.08334, 0.62583], + "86": [0, 0.68333, 0.08222, 0, 0.61278], + "87": [0, 0.68333, 0.08222, 0.08334, 0.98778], + "88": [0, 0.68333, 0.14643, 0.13889, 0.7133], + "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834], + "90": [0, 0.68333, 0.07944, 0.13889, 0.72473], + "160": [0, 0, 0, 0, 0.25] + }, + "Fraktur-Regular": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69141, 0, 0, 0.29574], + "34": [0, 0.69141, 0, 0, 0.21471], + "38": [0, 0.69141, 0, 0, 0.73786], + "39": [0, 0.69141, 0, 0, 0.21201], + "40": [0.24982, 0.74947, 0, 0, 0.38865], + "41": [0.24982, 0.74947, 0, 0, 0.38865], + "42": [0, 0.62119, 0, 0, 0.27764], + "43": [0.08319, 0.58283, 0, 0, 0.75623], + "44": [0, 0.10803, 0, 0, 0.27764], + "45": [0.08319, 0.58283, 0, 0, 0.75623], + "46": [0, 0.10803, 0, 0, 0.27764], + "47": [0.24982, 0.74947, 0, 0, 0.50181], + "48": [0, 0.47534, 0, 0, 0.50181], + "49": [0, 0.47534, 0, 0, 0.50181], + "50": [0, 0.47534, 0, 0, 0.50181], + "51": [0.18906, 0.47534, 0, 0, 0.50181], + "52": [0.18906, 0.47534, 0, 0, 0.50181], + "53": [0.18906, 0.47534, 0, 0, 0.50181], + "54": [0, 0.69141, 0, 0, 0.50181], + "55": [0.18906, 0.47534, 0, 0, 0.50181], + "56": [0, 0.69141, 0, 0, 0.50181], + "57": [0.18906, 0.47534, 0, 0, 0.50181], + "58": [0, 0.47534, 0, 0, 0.21606], + "59": [0.12604, 0.47534, 0, 0, 0.21606], + "61": [-0.13099, 0.36866, 0, 0, 0.75623], + "63": [0, 0.69141, 0, 0, 0.36245], + "65": [0, 0.69141, 0, 0, 0.7176], + "66": [0, 0.69141, 0, 0, 0.88397], + "67": [0, 0.69141, 0, 0, 0.61254], + "68": [0, 0.69141, 0, 0, 0.83158], + "69": [0, 0.69141, 0, 0, 0.66278], + "70": [0.12604, 0.69141, 0, 0, 0.61119], + "71": [0, 0.69141, 0, 0, 0.78539], + "72": [0.06302, 0.69141, 0, 0, 0.7203], + "73": [0, 0.69141, 0, 0, 0.55448], + "74": [0.12604, 0.69141, 0, 0, 0.55231], + "75": [0, 0.69141, 0, 0, 0.66845], + "76": [0, 0.69141, 0, 0, 0.66602], + "77": [0, 0.69141, 0, 0, 1.04953], + "78": [0, 0.69141, 0, 0, 0.83212], + "79": [0, 0.69141, 0, 0, 0.82699], + "80": [0.18906, 0.69141, 0, 0, 0.82753], + "81": [0.03781, 0.69141, 0, 0, 0.82699], + "82": [0, 0.69141, 0, 0, 0.82807], + "83": [0, 0.69141, 0, 0, 0.82861], + "84": [0, 0.69141, 0, 0, 0.66899], + "85": [0, 0.69141, 0, 0, 0.64576], + "86": [0, 0.69141, 0, 0, 0.83131], + "87": [0, 0.69141, 0, 0, 1.04602], + "88": [0, 0.69141, 0, 0, 0.71922], + "89": [0.18906, 0.69141, 0, 0, 0.83293], + "90": [0.12604, 0.69141, 0, 0, 0.60201], + "91": [0.24982, 0.74947, 0, 0, 0.27764], + "93": [0.24982, 0.74947, 0, 0, 0.27764], + "94": [0, 0.69141, 0, 0, 0.49965], + "97": [0, 0.47534, 0, 0, 0.50046], + "98": [0, 0.69141, 0, 0, 0.51315], + "99": [0, 0.47534, 0, 0, 0.38946], + "100": [0, 0.62119, 0, 0, 0.49857], + "101": [0, 0.47534, 0, 0, 0.40053], + "102": [0.18906, 0.69141, 0, 0, 0.32626], + "103": [0.18906, 0.47534, 0, 0, 0.5037], + "104": [0.18906, 0.69141, 0, 0, 0.52126], + "105": [0, 0.69141, 0, 0, 0.27899], + "106": [0, 0.69141, 0, 0, 0.28088], + "107": [0, 0.69141, 0, 0, 0.38946], + "108": [0, 0.69141, 0, 0, 0.27953], + "109": [0, 0.47534, 0, 0, 0.76676], + "110": [0, 0.47534, 0, 0, 0.52666], + "111": [0, 0.47534, 0, 0, 0.48885], + "112": [0.18906, 0.52396, 0, 0, 0.50046], + "113": [0.18906, 0.47534, 0, 0, 0.48912], + "114": [0, 0.47534, 0, 0, 0.38919], + "115": [0, 0.47534, 0, 0, 0.44266], + "116": [0, 0.62119, 0, 0, 0.33301], + "117": [0, 0.47534, 0, 0, 0.5172], + "118": [0, 0.52396, 0, 0, 0.5118], + "119": [0, 0.52396, 0, 0, 0.77351], + "120": [0.18906, 0.47534, 0, 0, 0.38865], + "121": [0.18906, 0.47534, 0, 0, 0.49884], + "122": [0.18906, 0.47534, 0, 0, 0.39054], + "160": [0, 0, 0, 0, 0.25], + "8216": [0, 0.69141, 0, 0, 0.21471], + "8217": [0, 0.69141, 0, 0, 0.21471], + "58112": [0, 0.62119, 0, 0, 0.49749], + "58113": [0, 0.62119, 0, 0, 0.4983], + "58114": [0.18906, 0.69141, 0, 0, 0.33328], + "58115": [0.18906, 0.69141, 0, 0, 0.32923], + "58116": [0.18906, 0.47534, 0, 0, 0.50343], + "58117": [0, 0.69141, 0, 0, 0.33301], + "58118": [0, 0.62119, 0, 0, 0.33409], + "58119": [0, 0.47534, 0, 0, 0.50073] + }, + "Main-Bold": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.35], + "34": [0, 0.69444, 0, 0, 0.60278], + "35": [0.19444, 0.69444, 0, 0, 0.95833], + "36": [0.05556, 0.75, 0, 0, 0.575], + "37": [0.05556, 0.75, 0, 0, 0.95833], + "38": [0, 0.69444, 0, 0, 0.89444], + "39": [0, 0.69444, 0, 0, 0.31944], + "40": [0.25, 0.75, 0, 0, 0.44722], + "41": [0.25, 0.75, 0, 0, 0.44722], + "42": [0, 0.75, 0, 0, 0.575], + "43": [0.13333, 0.63333, 0, 0, 0.89444], + "44": [0.19444, 0.15556, 0, 0, 0.31944], + "45": [0, 0.44444, 0, 0, 0.38333], + "46": [0, 0.15556, 0, 0, 0.31944], + "47": [0.25, 0.75, 0, 0, 0.575], + "48": [0, 0.64444, 0, 0, 0.575], + "49": [0, 0.64444, 0, 0, 0.575], + "50": [0, 0.64444, 0, 0, 0.575], + "51": [0, 0.64444, 0, 0, 0.575], + "52": [0, 0.64444, 0, 0, 0.575], + "53": [0, 0.64444, 0, 0, 0.575], + "54": [0, 0.64444, 0, 0, 0.575], + "55": [0, 0.64444, 0, 0, 0.575], + "56": [0, 0.64444, 0, 0, 0.575], + "57": [0, 0.64444, 0, 0, 0.575], + "58": [0, 0.44444, 0, 0, 0.31944], + "59": [0.19444, 0.44444, 0, 0, 0.31944], + "60": [0.08556, 0.58556, 0, 0, 0.89444], + "61": [-0.10889, 0.39111, 0, 0, 0.89444], + "62": [0.08556, 0.58556, 0, 0, 0.89444], + "63": [0, 0.69444, 0, 0, 0.54305], + "64": [0, 0.69444, 0, 0, 0.89444], + "65": [0, 0.68611, 0, 0, 0.86944], + "66": [0, 0.68611, 0, 0, 0.81805], + "67": [0, 0.68611, 0, 0, 0.83055], + "68": [0, 0.68611, 0, 0, 0.88194], + "69": [0, 0.68611, 0, 0, 0.75555], + "70": [0, 0.68611, 0, 0, 0.72361], + "71": [0, 0.68611, 0, 0, 0.90416], + "72": [0, 0.68611, 0, 0, 0.9], + "73": [0, 0.68611, 0, 0, 0.43611], + "74": [0, 0.68611, 0, 0, 0.59444], + "75": [0, 0.68611, 0, 0, 0.90138], + "76": [0, 0.68611, 0, 0, 0.69166], + "77": [0, 0.68611, 0, 0, 1.09166], + "78": [0, 0.68611, 0, 0, 0.9], + "79": [0, 0.68611, 0, 0, 0.86388], + "80": [0, 0.68611, 0, 0, 0.78611], + "81": [0.19444, 0.68611, 0, 0, 0.86388], + "82": [0, 0.68611, 0, 0, 0.8625], + "83": [0, 0.68611, 0, 0, 0.63889], + "84": [0, 0.68611, 0, 0, 0.8], + "85": [0, 0.68611, 0, 0, 0.88472], + "86": [0, 0.68611, 0.01597, 0, 0.86944], + "87": [0, 0.68611, 0.01597, 0, 1.18888], + "88": [0, 0.68611, 0, 0, 0.86944], + "89": [0, 0.68611, 0.02875, 0, 0.86944], + "90": [0, 0.68611, 0, 0, 0.70277], + "91": [0.25, 0.75, 0, 0, 0.31944], + "92": [0.25, 0.75, 0, 0, 0.575], + "93": [0.25, 0.75, 0, 0, 0.31944], + "94": [0, 0.69444, 0, 0, 0.575], + "95": [0.31, 0.13444, 0.03194, 0, 0.575], + "97": [0, 0.44444, 0, 0, 0.55902], + "98": [0, 0.69444, 0, 0, 0.63889], + "99": [0, 0.44444, 0, 0, 0.51111], + "100": [0, 0.69444, 0, 0, 0.63889], + "101": [0, 0.44444, 0, 0, 0.52708], + "102": [0, 0.69444, 0.10903, 0, 0.35139], + "103": [0.19444, 0.44444, 0.01597, 0, 0.575], + "104": [0, 0.69444, 0, 0, 0.63889], + "105": [0, 0.69444, 0, 0, 0.31944], + "106": [0.19444, 0.69444, 0, 0, 0.35139], + "107": [0, 0.69444, 0, 0, 0.60694], + "108": [0, 0.69444, 0, 0, 0.31944], + "109": [0, 0.44444, 0, 0, 0.95833], + "110": [0, 0.44444, 0, 0, 0.63889], + "111": [0, 0.44444, 0, 0, 0.575], + "112": [0.19444, 0.44444, 0, 0, 0.63889], + "113": [0.19444, 0.44444, 0, 0, 0.60694], + "114": [0, 0.44444, 0, 0, 0.47361], + "115": [0, 0.44444, 0, 0, 0.45361], + "116": [0, 0.63492, 0, 0, 0.44722], + "117": [0, 0.44444, 0, 0, 0.63889], + "118": [0, 0.44444, 0.01597, 0, 0.60694], + "119": [0, 0.44444, 0.01597, 0, 0.83055], + "120": [0, 0.44444, 0, 0, 0.60694], + "121": [0.19444, 0.44444, 0.01597, 0, 0.60694], + "122": [0, 0.44444, 0, 0, 0.51111], + "123": [0.25, 0.75, 0, 0, 0.575], + "124": [0.25, 0.75, 0, 0, 0.31944], + "125": [0.25, 0.75, 0, 0, 0.575], + "126": [0.35, 0.34444, 0, 0, 0.575], + "160": [0, 0, 0, 0, 0.25], + "163": [0, 0.69444, 0, 0, 0.86853], + "168": [0, 0.69444, 0, 0, 0.575], + "172": [0, 0.44444, 0, 0, 0.76666], + "176": [0, 0.69444, 0, 0, 0.86944], + "177": [0.13333, 0.63333, 0, 0, 0.89444], + "184": [0.17014, 0, 0, 0, 0.51111], + "198": [0, 0.68611, 0, 0, 1.04166], + "215": [0.13333, 0.63333, 0, 0, 0.89444], + "216": [0.04861, 0.73472, 0, 0, 0.89444], + "223": [0, 0.69444, 0, 0, 0.59722], + "230": [0, 0.44444, 0, 0, 0.83055], + "247": [0.13333, 0.63333, 0, 0, 0.89444], + "248": [0.09722, 0.54167, 0, 0, 0.575], + "305": [0, 0.44444, 0, 0, 0.31944], + "338": [0, 0.68611, 0, 0, 1.16944], + "339": [0, 0.44444, 0, 0, 0.89444], + "567": [0.19444, 0.44444, 0, 0, 0.35139], + "710": [0, 0.69444, 0, 0, 0.575], + "711": [0, 0.63194, 0, 0, 0.575], + "713": [0, 0.59611, 0, 0, 0.575], + "714": [0, 0.69444, 0, 0, 0.575], + "715": [0, 0.69444, 0, 0, 0.575], + "728": [0, 0.69444, 0, 0, 0.575], + "729": [0, 0.69444, 0, 0, 0.31944], + "730": [0, 0.69444, 0, 0, 0.86944], + "732": [0, 0.69444, 0, 0, 0.575], + "733": [0, 0.69444, 0, 0, 0.575], + "915": [0, 0.68611, 0, 0, 0.69166], + "916": [0, 0.68611, 0, 0, 0.95833], + "920": [0, 0.68611, 0, 0, 0.89444], + "923": [0, 0.68611, 0, 0, 0.80555], + "926": [0, 0.68611, 0, 0, 0.76666], + "928": [0, 0.68611, 0, 0, 0.9], + "931": [0, 0.68611, 0, 0, 0.83055], + "933": [0, 0.68611, 0, 0, 0.89444], + "934": [0, 0.68611, 0, 0, 0.83055], + "936": [0, 0.68611, 0, 0, 0.89444], + "937": [0, 0.68611, 0, 0, 0.83055], + "8211": [0, 0.44444, 0.03194, 0, 0.575], + "8212": [0, 0.44444, 0.03194, 0, 1.14999], + "8216": [0, 0.69444, 0, 0, 0.31944], + "8217": [0, 0.69444, 0, 0, 0.31944], + "8220": [0, 0.69444, 0, 0, 0.60278], + "8221": [0, 0.69444, 0, 0, 0.60278], + "8224": [0.19444, 0.69444, 0, 0, 0.51111], + "8225": [0.19444, 0.69444, 0, 0, 0.51111], + "8242": [0, 0.55556, 0, 0, 0.34444], + "8407": [0, 0.72444, 0.15486, 0, 0.575], + "8463": [0, 0.69444, 0, 0, 0.66759], + "8465": [0, 0.69444, 0, 0, 0.83055], + "8467": [0, 0.69444, 0, 0, 0.47361], + "8472": [0.19444, 0.44444, 0, 0, 0.74027], + "8476": [0, 0.69444, 0, 0, 0.83055], + "8501": [0, 0.69444, 0, 0, 0.70277], + "8592": [-0.10889, 0.39111, 0, 0, 1.14999], + "8593": [0.19444, 0.69444, 0, 0, 0.575], + "8594": [-0.10889, 0.39111, 0, 0, 1.14999], + "8595": [0.19444, 0.69444, 0, 0, 0.575], + "8596": [-0.10889, 0.39111, 0, 0, 1.14999], + "8597": [0.25, 0.75, 0, 0, 0.575], + "8598": [0.19444, 0.69444, 0, 0, 1.14999], + "8599": [0.19444, 0.69444, 0, 0, 1.14999], + "8600": [0.19444, 0.69444, 0, 0, 1.14999], + "8601": [0.19444, 0.69444, 0, 0, 1.14999], + "8636": [-0.10889, 0.39111, 0, 0, 1.14999], + "8637": [-0.10889, 0.39111, 0, 0, 1.14999], + "8640": [-0.10889, 0.39111, 0, 0, 1.14999], + "8641": [-0.10889, 0.39111, 0, 0, 1.14999], + "8656": [-0.10889, 0.39111, 0, 0, 1.14999], + "8657": [0.19444, 0.69444, 0, 0, 0.70277], + "8658": [-0.10889, 0.39111, 0, 0, 1.14999], + "8659": [0.19444, 0.69444, 0, 0, 0.70277], + "8660": [-0.10889, 0.39111, 0, 0, 1.14999], + "8661": [0.25, 0.75, 0, 0, 0.70277], + "8704": [0, 0.69444, 0, 0, 0.63889], + "8706": [0, 0.69444, 0.06389, 0, 0.62847], + "8707": [0, 0.69444, 0, 0, 0.63889], + "8709": [0.05556, 0.75, 0, 0, 0.575], + "8711": [0, 0.68611, 0, 0, 0.95833], + "8712": [0.08556, 0.58556, 0, 0, 0.76666], + "8715": [0.08556, 0.58556, 0, 0, 0.76666], + "8722": [0.13333, 0.63333, 0, 0, 0.89444], + "8723": [0.13333, 0.63333, 0, 0, 0.89444], + "8725": [0.25, 0.75, 0, 0, 0.575], + "8726": [0.25, 0.75, 0, 0, 0.575], + "8727": [-0.02778, 0.47222, 0, 0, 0.575], + "8728": [-0.02639, 0.47361, 0, 0, 0.575], + "8729": [-0.02639, 0.47361, 0, 0, 0.575], + "8730": [0.18, 0.82, 0, 0, 0.95833], + "8733": [0, 0.44444, 0, 0, 0.89444], + "8734": [0, 0.44444, 0, 0, 1.14999], + "8736": [0, 0.69224, 0, 0, 0.72222], + "8739": [0.25, 0.75, 0, 0, 0.31944], + "8741": [0.25, 0.75, 0, 0, 0.575], + "8743": [0, 0.55556, 0, 0, 0.76666], + "8744": [0, 0.55556, 0, 0, 0.76666], + "8745": [0, 0.55556, 0, 0, 0.76666], + "8746": [0, 0.55556, 0, 0, 0.76666], + "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875], + "8764": [-0.10889, 0.39111, 0, 0, 0.89444], + "8768": [0.19444, 0.69444, 0, 0, 0.31944], + "8771": [0.00222, 0.50222, 0, 0, 0.89444], + "8773": [0.027, 0.638, 0, 0, 0.894], + "8776": [0.02444, 0.52444, 0, 0, 0.89444], + "8781": [0.00222, 0.50222, 0, 0, 0.89444], + "8801": [0.00222, 0.50222, 0, 0, 0.89444], + "8804": [0.19667, 0.69667, 0, 0, 0.89444], + "8805": [0.19667, 0.69667, 0, 0, 0.89444], + "8810": [0.08556, 0.58556, 0, 0, 1.14999], + "8811": [0.08556, 0.58556, 0, 0, 1.14999], + "8826": [0.08556, 0.58556, 0, 0, 0.89444], + "8827": [0.08556, 0.58556, 0, 0, 0.89444], + "8834": [0.08556, 0.58556, 0, 0, 0.89444], + "8835": [0.08556, 0.58556, 0, 0, 0.89444], + "8838": [0.19667, 0.69667, 0, 0, 0.89444], + "8839": [0.19667, 0.69667, 0, 0, 0.89444], + "8846": [0, 0.55556, 0, 0, 0.76666], + "8849": [0.19667, 0.69667, 0, 0, 0.89444], + "8850": [0.19667, 0.69667, 0, 0, 0.89444], + "8851": [0, 0.55556, 0, 0, 0.76666], + "8852": [0, 0.55556, 0, 0, 0.76666], + "8853": [0.13333, 0.63333, 0, 0, 0.89444], + "8854": [0.13333, 0.63333, 0, 0, 0.89444], + "8855": [0.13333, 0.63333, 0, 0, 0.89444], + "8856": [0.13333, 0.63333, 0, 0, 0.89444], + "8857": [0.13333, 0.63333, 0, 0, 0.89444], + "8866": [0, 0.69444, 0, 0, 0.70277], + "8867": [0, 0.69444, 0, 0, 0.70277], + "8868": [0, 0.69444, 0, 0, 0.89444], + "8869": [0, 0.69444, 0, 0, 0.89444], + "8900": [-0.02639, 0.47361, 0, 0, 0.575], + "8901": [-0.02639, 0.47361, 0, 0, 0.31944], + "8902": [-0.02778, 0.47222, 0, 0, 0.575], + "8968": [0.25, 0.75, 0, 0, 0.51111], + "8969": [0.25, 0.75, 0, 0, 0.51111], + "8970": [0.25, 0.75, 0, 0, 0.51111], + "8971": [0.25, 0.75, 0, 0, 0.51111], + "8994": [-0.13889, 0.36111, 0, 0, 1.14999], + "8995": [-0.13889, 0.36111, 0, 0, 1.14999], + "9651": [0.19444, 0.69444, 0, 0, 1.02222], + "9657": [-0.02778, 0.47222, 0, 0, 0.575], + "9661": [0.19444, 0.69444, 0, 0, 1.02222], + "9667": [-0.02778, 0.47222, 0, 0, 0.575], + "9711": [0.19444, 0.69444, 0, 0, 1.14999], + "9824": [0.12963, 0.69444, 0, 0, 0.89444], + "9825": [0.12963, 0.69444, 0, 0, 0.89444], + "9826": [0.12963, 0.69444, 0, 0, 0.89444], + "9827": [0.12963, 0.69444, 0, 0, 0.89444], + "9837": [0, 0.75, 0, 0, 0.44722], + "9838": [0.19444, 0.69444, 0, 0, 0.44722], + "9839": [0.19444, 0.69444, 0, 0, 0.44722], + "10216": [0.25, 0.75, 0, 0, 0.44722], + "10217": [0.25, 0.75, 0, 0, 0.44722], + "10815": [0, 0.68611, 0, 0, 0.9], + "10927": [0.19667, 0.69667, 0, 0, 0.89444], + "10928": [0.19667, 0.69667, 0, 0, 0.89444], + "57376": [0.19444, 0.69444, 0, 0, 0] + }, + "Main-BoldItalic": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0.11417, 0, 0.38611], + "34": [0, 0.69444, 0.07939, 0, 0.62055], + "35": [0.19444, 0.69444, 0.06833, 0, 0.94444], + "37": [0.05556, 0.75, 0.12861, 0, 0.94444], + "38": [0, 0.69444, 0.08528, 0, 0.88555], + "39": [0, 0.69444, 0.12945, 0, 0.35555], + "40": [0.25, 0.75, 0.15806, 0, 0.47333], + "41": [0.25, 0.75, 0.03306, 0, 0.47333], + "42": [0, 0.75, 0.14333, 0, 0.59111], + "43": [0.10333, 0.60333, 0.03306, 0, 0.88555], + "44": [0.19444, 0.14722, 0, 0, 0.35555], + "45": [0, 0.44444, 0.02611, 0, 0.41444], + "46": [0, 0.14722, 0, 0, 0.35555], + "47": [0.25, 0.75, 0.15806, 0, 0.59111], + "48": [0, 0.64444, 0.13167, 0, 0.59111], + "49": [0, 0.64444, 0.13167, 0, 0.59111], + "50": [0, 0.64444, 0.13167, 0, 0.59111], + "51": [0, 0.64444, 0.13167, 0, 0.59111], + "52": [0.19444, 0.64444, 0.13167, 0, 0.59111], + "53": [0, 0.64444, 0.13167, 0, 0.59111], + "54": [0, 0.64444, 0.13167, 0, 0.59111], + "55": [0.19444, 0.64444, 0.13167, 0, 0.59111], + "56": [0, 0.64444, 0.13167, 0, 0.59111], + "57": [0, 0.64444, 0.13167, 0, 0.59111], + "58": [0, 0.44444, 0.06695, 0, 0.35555], + "59": [0.19444, 0.44444, 0.06695, 0, 0.35555], + "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555], + "63": [0, 0.69444, 0.11472, 0, 0.59111], + "64": [0, 0.69444, 0.09208, 0, 0.88555], + "65": [0, 0.68611, 0, 0, 0.86555], + "66": [0, 0.68611, 0.0992, 0, 0.81666], + "67": [0, 0.68611, 0.14208, 0, 0.82666], + "68": [0, 0.68611, 0.09062, 0, 0.87555], + "69": [0, 0.68611, 0.11431, 0, 0.75666], + "70": [0, 0.68611, 0.12903, 0, 0.72722], + "71": [0, 0.68611, 0.07347, 0, 0.89527], + "72": [0, 0.68611, 0.17208, 0, 0.8961], + "73": [0, 0.68611, 0.15681, 0, 0.47166], + "74": [0, 0.68611, 0.145, 0, 0.61055], + "75": [0, 0.68611, 0.14208, 0, 0.89499], + "76": [0, 0.68611, 0, 0, 0.69777], + "77": [0, 0.68611, 0.17208, 0, 1.07277], + "78": [0, 0.68611, 0.17208, 0, 0.8961], + "79": [0, 0.68611, 0.09062, 0, 0.85499], + "80": [0, 0.68611, 0.0992, 0, 0.78721], + "81": [0.19444, 0.68611, 0.09062, 0, 0.85499], + "82": [0, 0.68611, 0.02559, 0, 0.85944], + "83": [0, 0.68611, 0.11264, 0, 0.64999], + "84": [0, 0.68611, 0.12903, 0, 0.7961], + "85": [0, 0.68611, 0.17208, 0, 0.88083], + "86": [0, 0.68611, 0.18625, 0, 0.86555], + "87": [0, 0.68611, 0.18625, 0, 1.15999], + "88": [0, 0.68611, 0.15681, 0, 0.86555], + "89": [0, 0.68611, 0.19803, 0, 0.86555], + "90": [0, 0.68611, 0.14208, 0, 0.70888], + "91": [0.25, 0.75, 0.1875, 0, 0.35611], + "93": [0.25, 0.75, 0.09972, 0, 0.35611], + "94": [0, 0.69444, 0.06709, 0, 0.59111], + "95": [0.31, 0.13444, 0.09811, 0, 0.59111], + "97": [0, 0.44444, 0.09426, 0, 0.59111], + "98": [0, 0.69444, 0.07861, 0, 0.53222], + "99": [0, 0.44444, 0.05222, 0, 0.53222], + "100": [0, 0.69444, 0.10861, 0, 0.59111], + "101": [0, 0.44444, 0.085, 0, 0.53222], + "102": [0.19444, 0.69444, 0.21778, 0, 0.4], + "103": [0.19444, 0.44444, 0.105, 0, 0.53222], + "104": [0, 0.69444, 0.09426, 0, 0.59111], + "105": [0, 0.69326, 0.11387, 0, 0.35555], + "106": [0.19444, 0.69326, 0.1672, 0, 0.35555], + "107": [0, 0.69444, 0.11111, 0, 0.53222], + "108": [0, 0.69444, 0.10861, 0, 0.29666], + "109": [0, 0.44444, 0.09426, 0, 0.94444], + "110": [0, 0.44444, 0.09426, 0, 0.64999], + "111": [0, 0.44444, 0.07861, 0, 0.59111], + "112": [0.19444, 0.44444, 0.07861, 0, 0.59111], + "113": [0.19444, 0.44444, 0.105, 0, 0.53222], + "114": [0, 0.44444, 0.11111, 0, 0.50167], + "115": [0, 0.44444, 0.08167, 0, 0.48694], + "116": [0, 0.63492, 0.09639, 0, 0.385], + "117": [0, 0.44444, 0.09426, 0, 0.62055], + "118": [0, 0.44444, 0.11111, 0, 0.53222], + "119": [0, 0.44444, 0.11111, 0, 0.76777], + "120": [0, 0.44444, 0.12583, 0, 0.56055], + "121": [0.19444, 0.44444, 0.105, 0, 0.56166], + "122": [0, 0.44444, 0.13889, 0, 0.49055], + "126": [0.35, 0.34444, 0.11472, 0, 0.59111], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.69444, 0.11473, 0, 0.59111], + "176": [0, 0.69444, 0, 0, 0.94888], + "184": [0.17014, 0, 0, 0, 0.53222], + "198": [0, 0.68611, 0.11431, 0, 1.02277], + "216": [0.04861, 0.73472, 0.09062, 0, 0.88555], + "223": [0.19444, 0.69444, 0.09736, 0, 0.665], + "230": [0, 0.44444, 0.085, 0, 0.82666], + "248": [0.09722, 0.54167, 0.09458, 0, 0.59111], + "305": [0, 0.44444, 0.09426, 0, 0.35555], + "338": [0, 0.68611, 0.11431, 0, 1.14054], + "339": [0, 0.44444, 0.085, 0, 0.82666], + "567": [0.19444, 0.44444, 0.04611, 0, 0.385], + "710": [0, 0.69444, 0.06709, 0, 0.59111], + "711": [0, 0.63194, 0.08271, 0, 0.59111], + "713": [0, 0.59444, 0.10444, 0, 0.59111], + "714": [0, 0.69444, 0.08528, 0, 0.59111], + "715": [0, 0.69444, 0, 0, 0.59111], + "728": [0, 0.69444, 0.10333, 0, 0.59111], + "729": [0, 0.69444, 0.12945, 0, 0.35555], + "730": [0, 0.69444, 0, 0, 0.94888], + "732": [0, 0.69444, 0.11472, 0, 0.59111], + "733": [0, 0.69444, 0.11472, 0, 0.59111], + "915": [0, 0.68611, 0.12903, 0, 0.69777], + "916": [0, 0.68611, 0, 0, 0.94444], + "920": [0, 0.68611, 0.09062, 0, 0.88555], + "923": [0, 0.68611, 0, 0, 0.80666], + "926": [0, 0.68611, 0.15092, 0, 0.76777], + "928": [0, 0.68611, 0.17208, 0, 0.8961], + "931": [0, 0.68611, 0.11431, 0, 0.82666], + "933": [0, 0.68611, 0.10778, 0, 0.88555], + "934": [0, 0.68611, 0.05632, 0, 0.82666], + "936": [0, 0.68611, 0.10778, 0, 0.88555], + "937": [0, 0.68611, 0.0992, 0, 0.82666], + "8211": [0, 0.44444, 0.09811, 0, 0.59111], + "8212": [0, 0.44444, 0.09811, 0, 1.18221], + "8216": [0, 0.69444, 0.12945, 0, 0.35555], + "8217": [0, 0.69444, 0.12945, 0, 0.35555], + "8220": [0, 0.69444, 0.16772, 0, 0.62055], + "8221": [0, 0.69444, 0.07939, 0, 0.62055] + }, + "Main-Italic": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0.12417, 0, 0.30667], + "34": [0, 0.69444, 0.06961, 0, 0.51444], + "35": [0.19444, 0.69444, 0.06616, 0, 0.81777], + "37": [0.05556, 0.75, 0.13639, 0, 0.81777], + "38": [0, 0.69444, 0.09694, 0, 0.76666], + "39": [0, 0.69444, 0.12417, 0, 0.30667], + "40": [0.25, 0.75, 0.16194, 0, 0.40889], + "41": [0.25, 0.75, 0.03694, 0, 0.40889], + "42": [0, 0.75, 0.14917, 0, 0.51111], + "43": [0.05667, 0.56167, 0.03694, 0, 0.76666], + "44": [0.19444, 0.10556, 0, 0, 0.30667], + "45": [0, 0.43056, 0.02826, 0, 0.35778], + "46": [0, 0.10556, 0, 0, 0.30667], + "47": [0.25, 0.75, 0.16194, 0, 0.51111], + "48": [0, 0.64444, 0.13556, 0, 0.51111], + "49": [0, 0.64444, 0.13556, 0, 0.51111], + "50": [0, 0.64444, 0.13556, 0, 0.51111], + "51": [0, 0.64444, 0.13556, 0, 0.51111], + "52": [0.19444, 0.64444, 0.13556, 0, 0.51111], + "53": [0, 0.64444, 0.13556, 0, 0.51111], + "54": [0, 0.64444, 0.13556, 0, 0.51111], + "55": [0.19444, 0.64444, 0.13556, 0, 0.51111], + "56": [0, 0.64444, 0.13556, 0, 0.51111], + "57": [0, 0.64444, 0.13556, 0, 0.51111], + "58": [0, 0.43056, 0.0582, 0, 0.30667], + "59": [0.19444, 0.43056, 0.0582, 0, 0.30667], + "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666], + "63": [0, 0.69444, 0.1225, 0, 0.51111], + "64": [0, 0.69444, 0.09597, 0, 0.76666], + "65": [0, 0.68333, 0, 0, 0.74333], + "66": [0, 0.68333, 0.10257, 0, 0.70389], + "67": [0, 0.68333, 0.14528, 0, 0.71555], + "68": [0, 0.68333, 0.09403, 0, 0.755], + "69": [0, 0.68333, 0.12028, 0, 0.67833], + "70": [0, 0.68333, 0.13305, 0, 0.65277], + "71": [0, 0.68333, 0.08722, 0, 0.77361], + "72": [0, 0.68333, 0.16389, 0, 0.74333], + "73": [0, 0.68333, 0.15806, 0, 0.38555], + "74": [0, 0.68333, 0.14028, 0, 0.525], + "75": [0, 0.68333, 0.14528, 0, 0.76888], + "76": [0, 0.68333, 0, 0, 0.62722], + "77": [0, 0.68333, 0.16389, 0, 0.89666], + "78": [0, 0.68333, 0.16389, 0, 0.74333], + "79": [0, 0.68333, 0.09403, 0, 0.76666], + "80": [0, 0.68333, 0.10257, 0, 0.67833], + "81": [0.19444, 0.68333, 0.09403, 0, 0.76666], + "82": [0, 0.68333, 0.03868, 0, 0.72944], + "83": [0, 0.68333, 0.11972, 0, 0.56222], + "84": [0, 0.68333, 0.13305, 0, 0.71555], + "85": [0, 0.68333, 0.16389, 0, 0.74333], + "86": [0, 0.68333, 0.18361, 0, 0.74333], + "87": [0, 0.68333, 0.18361, 0, 0.99888], + "88": [0, 0.68333, 0.15806, 0, 0.74333], + "89": [0, 0.68333, 0.19383, 0, 0.74333], + "90": [0, 0.68333, 0.14528, 0, 0.61333], + "91": [0.25, 0.75, 0.1875, 0, 0.30667], + "93": [0.25, 0.75, 0.10528, 0, 0.30667], + "94": [0, 0.69444, 0.06646, 0, 0.51111], + "95": [0.31, 0.12056, 0.09208, 0, 0.51111], + "97": [0, 0.43056, 0.07671, 0, 0.51111], + "98": [0, 0.69444, 0.06312, 0, 0.46], + "99": [0, 0.43056, 0.05653, 0, 0.46], + "100": [0, 0.69444, 0.10333, 0, 0.51111], + "101": [0, 0.43056, 0.07514, 0, 0.46], + "102": [0.19444, 0.69444, 0.21194, 0, 0.30667], + "103": [0.19444, 0.43056, 0.08847, 0, 0.46], + "104": [0, 0.69444, 0.07671, 0, 0.51111], + "105": [0, 0.65536, 0.1019, 0, 0.30667], + "106": [0.19444, 0.65536, 0.14467, 0, 0.30667], + "107": [0, 0.69444, 0.10764, 0, 0.46], + "108": [0, 0.69444, 0.10333, 0, 0.25555], + "109": [0, 0.43056, 0.07671, 0, 0.81777], + "110": [0, 0.43056, 0.07671, 0, 0.56222], + "111": [0, 0.43056, 0.06312, 0, 0.51111], + "112": [0.19444, 0.43056, 0.06312, 0, 0.51111], + "113": [0.19444, 0.43056, 0.08847, 0, 0.46], + "114": [0, 0.43056, 0.10764, 0, 0.42166], + "115": [0, 0.43056, 0.08208, 0, 0.40889], + "116": [0, 0.61508, 0.09486, 0, 0.33222], + "117": [0, 0.43056, 0.07671, 0, 0.53666], + "118": [0, 0.43056, 0.10764, 0, 0.46], + "119": [0, 0.43056, 0.10764, 0, 0.66444], + "120": [0, 0.43056, 0.12042, 0, 0.46389], + "121": [0.19444, 0.43056, 0.08847, 0, 0.48555], + "122": [0, 0.43056, 0.12292, 0, 0.40889], + "126": [0.35, 0.31786, 0.11585, 0, 0.51111], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.66786, 0.10474, 0, 0.51111], + "176": [0, 0.69444, 0, 0, 0.83129], + "184": [0.17014, 0, 0, 0, 0.46], + "198": [0, 0.68333, 0.12028, 0, 0.88277], + "216": [0.04861, 0.73194, 0.09403, 0, 0.76666], + "223": [0.19444, 0.69444, 0.10514, 0, 0.53666], + "230": [0, 0.43056, 0.07514, 0, 0.71555], + "248": [0.09722, 0.52778, 0.09194, 0, 0.51111], + "338": [0, 0.68333, 0.12028, 0, 0.98499], + "339": [0, 0.43056, 0.07514, 0, 0.71555], + "710": [0, 0.69444, 0.06646, 0, 0.51111], + "711": [0, 0.62847, 0.08295, 0, 0.51111], + "713": [0, 0.56167, 0.10333, 0, 0.51111], + "714": [0, 0.69444, 0.09694, 0, 0.51111], + "715": [0, 0.69444, 0, 0, 0.51111], + "728": [0, 0.69444, 0.10806, 0, 0.51111], + "729": [0, 0.66786, 0.11752, 0, 0.30667], + "730": [0, 0.69444, 0, 0, 0.83129], + "732": [0, 0.66786, 0.11585, 0, 0.51111], + "733": [0, 0.69444, 0.1225, 0, 0.51111], + "915": [0, 0.68333, 0.13305, 0, 0.62722], + "916": [0, 0.68333, 0, 0, 0.81777], + "920": [0, 0.68333, 0.09403, 0, 0.76666], + "923": [0, 0.68333, 0, 0, 0.69222], + "926": [0, 0.68333, 0.15294, 0, 0.66444], + "928": [0, 0.68333, 0.16389, 0, 0.74333], + "931": [0, 0.68333, 0.12028, 0, 0.71555], + "933": [0, 0.68333, 0.11111, 0, 0.76666], + "934": [0, 0.68333, 0.05986, 0, 0.71555], + "936": [0, 0.68333, 0.11111, 0, 0.76666], + "937": [0, 0.68333, 0.10257, 0, 0.71555], + "8211": [0, 0.43056, 0.09208, 0, 0.51111], + "8212": [0, 0.43056, 0.09208, 0, 1.02222], + "8216": [0, 0.69444, 0.12417, 0, 0.30667], + "8217": [0, 0.69444, 0.12417, 0, 0.30667], + "8220": [0, 0.69444, 0.1685, 0, 0.51444], + "8221": [0, 0.69444, 0.06961, 0, 0.51444], + "8463": [0, 0.68889, 0, 0, 0.54028] + }, + "Main-Regular": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.27778], + "34": [0, 0.69444, 0, 0, 0.5], + "35": [0.19444, 0.69444, 0, 0, 0.83334], + "36": [0.05556, 0.75, 0, 0, 0.5], + "37": [0.05556, 0.75, 0, 0, 0.83334], + "38": [0, 0.69444, 0, 0, 0.77778], + "39": [0, 0.69444, 0, 0, 0.27778], + "40": [0.25, 0.75, 0, 0, 0.38889], + "41": [0.25, 0.75, 0, 0, 0.38889], + "42": [0, 0.75, 0, 0, 0.5], + "43": [0.08333, 0.58333, 0, 0, 0.77778], + "44": [0.19444, 0.10556, 0, 0, 0.27778], + "45": [0, 0.43056, 0, 0, 0.33333], + "46": [0, 0.10556, 0, 0, 0.27778], + "47": [0.25, 0.75, 0, 0, 0.5], + "48": [0, 0.64444, 0, 0, 0.5], + "49": [0, 0.64444, 0, 0, 0.5], + "50": [0, 0.64444, 0, 0, 0.5], + "51": [0, 0.64444, 0, 0, 0.5], + "52": [0, 0.64444, 0, 0, 0.5], + "53": [0, 0.64444, 0, 0, 0.5], + "54": [0, 0.64444, 0, 0, 0.5], + "55": [0, 0.64444, 0, 0, 0.5], + "56": [0, 0.64444, 0, 0, 0.5], + "57": [0, 0.64444, 0, 0, 0.5], + "58": [0, 0.43056, 0, 0, 0.27778], + "59": [0.19444, 0.43056, 0, 0, 0.27778], + "60": [0.0391, 0.5391, 0, 0, 0.77778], + "61": [-0.13313, 0.36687, 0, 0, 0.77778], + "62": [0.0391, 0.5391, 0, 0, 0.77778], + "63": [0, 0.69444, 0, 0, 0.47222], + "64": [0, 0.69444, 0, 0, 0.77778], + "65": [0, 0.68333, 0, 0, 0.75], + "66": [0, 0.68333, 0, 0, 0.70834], + "67": [0, 0.68333, 0, 0, 0.72222], + "68": [0, 0.68333, 0, 0, 0.76389], + "69": [0, 0.68333, 0, 0, 0.68056], + "70": [0, 0.68333, 0, 0, 0.65278], + "71": [0, 0.68333, 0, 0, 0.78472], + "72": [0, 0.68333, 0, 0, 0.75], + "73": [0, 0.68333, 0, 0, 0.36111], + "74": [0, 0.68333, 0, 0, 0.51389], + "75": [0, 0.68333, 0, 0, 0.77778], + "76": [0, 0.68333, 0, 0, 0.625], + "77": [0, 0.68333, 0, 0, 0.91667], + "78": [0, 0.68333, 0, 0, 0.75], + "79": [0, 0.68333, 0, 0, 0.77778], + "80": [0, 0.68333, 0, 0, 0.68056], + "81": [0.19444, 0.68333, 0, 0, 0.77778], + "82": [0, 0.68333, 0, 0, 0.73611], + "83": [0, 0.68333, 0, 0, 0.55556], + "84": [0, 0.68333, 0, 0, 0.72222], + "85": [0, 0.68333, 0, 0, 0.75], + "86": [0, 0.68333, 0.01389, 0, 0.75], + "87": [0, 0.68333, 0.01389, 0, 1.02778], + "88": [0, 0.68333, 0, 0, 0.75], + "89": [0, 0.68333, 0.025, 0, 0.75], + "90": [0, 0.68333, 0, 0, 0.61111], + "91": [0.25, 0.75, 0, 0, 0.27778], + "92": [0.25, 0.75, 0, 0, 0.5], + "93": [0.25, 0.75, 0, 0, 0.27778], + "94": [0, 0.69444, 0, 0, 0.5], + "95": [0.31, 0.12056, 0.02778, 0, 0.5], + "97": [0, 0.43056, 0, 0, 0.5], + "98": [0, 0.69444, 0, 0, 0.55556], + "99": [0, 0.43056, 0, 0, 0.44445], + "100": [0, 0.69444, 0, 0, 0.55556], + "101": [0, 0.43056, 0, 0, 0.44445], + "102": [0, 0.69444, 0.07778, 0, 0.30556], + "103": [0.19444, 0.43056, 0.01389, 0, 0.5], + "104": [0, 0.69444, 0, 0, 0.55556], + "105": [0, 0.66786, 0, 0, 0.27778], + "106": [0.19444, 0.66786, 0, 0, 0.30556], + "107": [0, 0.69444, 0, 0, 0.52778], + "108": [0, 0.69444, 0, 0, 0.27778], + "109": [0, 0.43056, 0, 0, 0.83334], + "110": [0, 0.43056, 0, 0, 0.55556], + "111": [0, 0.43056, 0, 0, 0.5], + "112": [0.19444, 0.43056, 0, 0, 0.55556], + "113": [0.19444, 0.43056, 0, 0, 0.52778], + "114": [0, 0.43056, 0, 0, 0.39167], + "115": [0, 0.43056, 0, 0, 0.39445], + "116": [0, 0.61508, 0, 0, 0.38889], + "117": [0, 0.43056, 0, 0, 0.55556], + "118": [0, 0.43056, 0.01389, 0, 0.52778], + "119": [0, 0.43056, 0.01389, 0, 0.72222], + "120": [0, 0.43056, 0, 0, 0.52778], + "121": [0.19444, 0.43056, 0.01389, 0, 0.52778], + "122": [0, 0.43056, 0, 0, 0.44445], + "123": [0.25, 0.75, 0, 0, 0.5], + "124": [0.25, 0.75, 0, 0, 0.27778], + "125": [0.25, 0.75, 0, 0, 0.5], + "126": [0.35, 0.31786, 0, 0, 0.5], + "160": [0, 0, 0, 0, 0.25], + "163": [0, 0.69444, 0, 0, 0.76909], + "167": [0.19444, 0.69444, 0, 0, 0.44445], + "168": [0, 0.66786, 0, 0, 0.5], + "172": [0, 0.43056, 0, 0, 0.66667], + "176": [0, 0.69444, 0, 0, 0.75], + "177": [0.08333, 0.58333, 0, 0, 0.77778], + "182": [0.19444, 0.69444, 0, 0, 0.61111], + "184": [0.17014, 0, 0, 0, 0.44445], + "198": [0, 0.68333, 0, 0, 0.90278], + "215": [0.08333, 0.58333, 0, 0, 0.77778], + "216": [0.04861, 0.73194, 0, 0, 0.77778], + "223": [0, 0.69444, 0, 0, 0.5], + "230": [0, 0.43056, 0, 0, 0.72222], + "247": [0.08333, 0.58333, 0, 0, 0.77778], + "248": [0.09722, 0.52778, 0, 0, 0.5], + "305": [0, 0.43056, 0, 0, 0.27778], + "338": [0, 0.68333, 0, 0, 1.01389], + "339": [0, 0.43056, 0, 0, 0.77778], + "567": [0.19444, 0.43056, 0, 0, 0.30556], + "710": [0, 0.69444, 0, 0, 0.5], + "711": [0, 0.62847, 0, 0, 0.5], + "713": [0, 0.56778, 0, 0, 0.5], + "714": [0, 0.69444, 0, 0, 0.5], + "715": [0, 0.69444, 0, 0, 0.5], + "728": [0, 0.69444, 0, 0, 0.5], + "729": [0, 0.66786, 0, 0, 0.27778], + "730": [0, 0.69444, 0, 0, 0.75], + "732": [0, 0.66786, 0, 0, 0.5], + "733": [0, 0.69444, 0, 0, 0.5], + "915": [0, 0.68333, 0, 0, 0.625], + "916": [0, 0.68333, 0, 0, 0.83334], + "920": [0, 0.68333, 0, 0, 0.77778], + "923": [0, 0.68333, 0, 0, 0.69445], + "926": [0, 0.68333, 0, 0, 0.66667], + "928": [0, 0.68333, 0, 0, 0.75], + "931": [0, 0.68333, 0, 0, 0.72222], + "933": [0, 0.68333, 0, 0, 0.77778], + "934": [0, 0.68333, 0, 0, 0.72222], + "936": [0, 0.68333, 0, 0, 0.77778], + "937": [0, 0.68333, 0, 0, 0.72222], + "8211": [0, 0.43056, 0.02778, 0, 0.5], + "8212": [0, 0.43056, 0.02778, 0, 1.0], + "8216": [0, 0.69444, 0, 0, 0.27778], + "8217": [0, 0.69444, 0, 0, 0.27778], + "8220": [0, 0.69444, 0, 0, 0.5], + "8221": [0, 0.69444, 0, 0, 0.5], + "8224": [0.19444, 0.69444, 0, 0, 0.44445], + "8225": [0.19444, 0.69444, 0, 0, 0.44445], + "8230": [0, 0.123, 0, 0, 1.172], + "8242": [0, 0.55556, 0, 0, 0.275], + "8407": [0, 0.71444, 0.15382, 0, 0.5], + "8463": [0, 0.68889, 0, 0, 0.54028], + "8465": [0, 0.69444, 0, 0, 0.72222], + "8467": [0, 0.69444, 0, 0.11111, 0.41667], + "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646], + "8476": [0, 0.69444, 0, 0, 0.72222], + "8501": [0, 0.69444, 0, 0, 0.61111], + "8592": [-0.13313, 0.36687, 0, 0, 1.0], + "8593": [0.19444, 0.69444, 0, 0, 0.5], + "8594": [-0.13313, 0.36687, 0, 0, 1.0], + "8595": [0.19444, 0.69444, 0, 0, 0.5], + "8596": [-0.13313, 0.36687, 0, 0, 1.0], + "8597": [0.25, 0.75, 0, 0, 0.5], + "8598": [0.19444, 0.69444, 0, 0, 1.0], + "8599": [0.19444, 0.69444, 0, 0, 1.0], + "8600": [0.19444, 0.69444, 0, 0, 1.0], + "8601": [0.19444, 0.69444, 0, 0, 1.0], + "8614": [0.011, 0.511, 0, 0, 1.0], + "8617": [0.011, 0.511, 0, 0, 1.126], + "8618": [0.011, 0.511, 0, 0, 1.126], + "8636": [-0.13313, 0.36687, 0, 0, 1.0], + "8637": [-0.13313, 0.36687, 0, 0, 1.0], + "8640": [-0.13313, 0.36687, 0, 0, 1.0], + "8641": [-0.13313, 0.36687, 0, 0, 1.0], + "8652": [0.011, 0.671, 0, 0, 1.0], + "8656": [-0.13313, 0.36687, 0, 0, 1.0], + "8657": [0.19444, 0.69444, 0, 0, 0.61111], + "8658": [-0.13313, 0.36687, 0, 0, 1.0], + "8659": [0.19444, 0.69444, 0, 0, 0.61111], + "8660": [-0.13313, 0.36687, 0, 0, 1.0], + "8661": [0.25, 0.75, 0, 0, 0.61111], + "8704": [0, 0.69444, 0, 0, 0.55556], + "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309], + "8707": [0, 0.69444, 0, 0, 0.55556], + "8709": [0.05556, 0.75, 0, 0, 0.5], + "8711": [0, 0.68333, 0, 0, 0.83334], + "8712": [0.0391, 0.5391, 0, 0, 0.66667], + "8715": [0.0391, 0.5391, 0, 0, 0.66667], + "8722": [0.08333, 0.58333, 0, 0, 0.77778], + "8723": [0.08333, 0.58333, 0, 0, 0.77778], + "8725": [0.25, 0.75, 0, 0, 0.5], + "8726": [0.25, 0.75, 0, 0, 0.5], + "8727": [-0.03472, 0.46528, 0, 0, 0.5], + "8728": [-0.05555, 0.44445, 0, 0, 0.5], + "8729": [-0.05555, 0.44445, 0, 0, 0.5], + "8730": [0.2, 0.8, 0, 0, 0.83334], + "8733": [0, 0.43056, 0, 0, 0.77778], + "8734": [0, 0.43056, 0, 0, 1.0], + "8736": [0, 0.69224, 0, 0, 0.72222], + "8739": [0.25, 0.75, 0, 0, 0.27778], + "8741": [0.25, 0.75, 0, 0, 0.5], + "8743": [0, 0.55556, 0, 0, 0.66667], + "8744": [0, 0.55556, 0, 0, 0.66667], + "8745": [0, 0.55556, 0, 0, 0.66667], + "8746": [0, 0.55556, 0, 0, 0.66667], + "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667], + "8764": [-0.13313, 0.36687, 0, 0, 0.77778], + "8768": [0.19444, 0.69444, 0, 0, 0.27778], + "8771": [-0.03625, 0.46375, 0, 0, 0.77778], + "8773": [-0.022, 0.589, 0, 0, 0.778], + "8776": [-0.01688, 0.48312, 0, 0, 0.77778], + "8781": [-0.03625, 0.46375, 0, 0, 0.77778], + "8784": [-0.133, 0.673, 0, 0, 0.778], + "8801": [-0.03625, 0.46375, 0, 0, 0.77778], + "8804": [0.13597, 0.63597, 0, 0, 0.77778], + "8805": [0.13597, 0.63597, 0, 0, 0.77778], + "8810": [0.0391, 0.5391, 0, 0, 1.0], + "8811": [0.0391, 0.5391, 0, 0, 1.0], + "8826": [0.0391, 0.5391, 0, 0, 0.77778], + "8827": [0.0391, 0.5391, 0, 0, 0.77778], + "8834": [0.0391, 0.5391, 0, 0, 0.77778], + "8835": [0.0391, 0.5391, 0, 0, 0.77778], + "8838": [0.13597, 0.63597, 0, 0, 0.77778], + "8839": [0.13597, 0.63597, 0, 0, 0.77778], + "8846": [0, 0.55556, 0, 0, 0.66667], + "8849": [0.13597, 0.63597, 0, 0, 0.77778], + "8850": [0.13597, 0.63597, 0, 0, 0.77778], + "8851": [0, 0.55556, 0, 0, 0.66667], + "8852": [0, 0.55556, 0, 0, 0.66667], + "8853": [0.08333, 0.58333, 0, 0, 0.77778], + "8854": [0.08333, 0.58333, 0, 0, 0.77778], + "8855": [0.08333, 0.58333, 0, 0, 0.77778], + "8856": [0.08333, 0.58333, 0, 0, 0.77778], + "8857": [0.08333, 0.58333, 0, 0, 0.77778], + "8866": [0, 0.69444, 0, 0, 0.61111], + "8867": [0, 0.69444, 0, 0, 0.61111], + "8868": [0, 0.69444, 0, 0, 0.77778], + "8869": [0, 0.69444, 0, 0, 0.77778], + "8872": [0.249, 0.75, 0, 0, 0.867], + "8900": [-0.05555, 0.44445, 0, 0, 0.5], + "8901": [-0.05555, 0.44445, 0, 0, 0.27778], + "8902": [-0.03472, 0.46528, 0, 0, 0.5], + "8904": [0.005, 0.505, 0, 0, 0.9], + "8942": [0.03, 0.903, 0, 0, 0.278], + "8943": [-0.19, 0.313, 0, 0, 1.172], + "8945": [-0.1, 0.823, 0, 0, 1.282], + "8968": [0.25, 0.75, 0, 0, 0.44445], + "8969": [0.25, 0.75, 0, 0, 0.44445], + "8970": [0.25, 0.75, 0, 0, 0.44445], + "8971": [0.25, 0.75, 0, 0, 0.44445], + "8994": [-0.14236, 0.35764, 0, 0, 1.0], + "8995": [-0.14236, 0.35764, 0, 0, 1.0], + "9136": [0.244, 0.744, 0, 0, 0.412], + "9137": [0.244, 0.745, 0, 0, 0.412], + "9651": [0.19444, 0.69444, 0, 0, 0.88889], + "9657": [-0.03472, 0.46528, 0, 0, 0.5], + "9661": [0.19444, 0.69444, 0, 0, 0.88889], + "9667": [-0.03472, 0.46528, 0, 0, 0.5], + "9711": [0.19444, 0.69444, 0, 0, 1.0], + "9824": [0.12963, 0.69444, 0, 0, 0.77778], + "9825": [0.12963, 0.69444, 0, 0, 0.77778], + "9826": [0.12963, 0.69444, 0, 0, 0.77778], + "9827": [0.12963, 0.69444, 0, 0, 0.77778], + "9837": [0, 0.75, 0, 0, 0.38889], + "9838": [0.19444, 0.69444, 0, 0, 0.38889], + "9839": [0.19444, 0.69444, 0, 0, 0.38889], + "10216": [0.25, 0.75, 0, 0, 0.38889], + "10217": [0.25, 0.75, 0, 0, 0.38889], + "10222": [0.244, 0.744, 0, 0, 0.412], + "10223": [0.244, 0.745, 0, 0, 0.412], + "10229": [0.011, 0.511, 0, 0, 1.609], + "10230": [0.011, 0.511, 0, 0, 1.638], + "10231": [0.011, 0.511, 0, 0, 1.859], + "10232": [0.024, 0.525, 0, 0, 1.609], + "10233": [0.024, 0.525, 0, 0, 1.638], + "10234": [0.024, 0.525, 0, 0, 1.858], + "10236": [0.011, 0.511, 0, 0, 1.638], + "10815": [0, 0.68333, 0, 0, 0.75], + "10927": [0.13597, 0.63597, 0, 0, 0.77778], + "10928": [0.13597, 0.63597, 0, 0, 0.77778], + "57376": [0.19444, 0.69444, 0, 0, 0] + }, + "Math-BoldItalic": { + "32": [0, 0, 0, 0, 0.25], + "48": [0, 0.44444, 0, 0, 0.575], + "49": [0, 0.44444, 0, 0, 0.575], + "50": [0, 0.44444, 0, 0, 0.575], + "51": [0.19444, 0.44444, 0, 0, 0.575], + "52": [0.19444, 0.44444, 0, 0, 0.575], + "53": [0.19444, 0.44444, 0, 0, 0.575], + "54": [0, 0.64444, 0, 0, 0.575], + "55": [0.19444, 0.44444, 0, 0, 0.575], + "56": [0, 0.64444, 0, 0, 0.575], + "57": [0.19444, 0.44444, 0, 0, 0.575], + "65": [0, 0.68611, 0, 0, 0.86944], + "66": [0, 0.68611, 0.04835, 0, 0.8664], + "67": [0, 0.68611, 0.06979, 0, 0.81694], + "68": [0, 0.68611, 0.03194, 0, 0.93812], + "69": [0, 0.68611, 0.05451, 0, 0.81007], + "70": [0, 0.68611, 0.15972, 0, 0.68889], + "71": [0, 0.68611, 0, 0, 0.88673], + "72": [0, 0.68611, 0.08229, 0, 0.98229], + "73": [0, 0.68611, 0.07778, 0, 0.51111], + "74": [0, 0.68611, 0.10069, 0, 0.63125], + "75": [0, 0.68611, 0.06979, 0, 0.97118], + "76": [0, 0.68611, 0, 0, 0.75555], + "77": [0, 0.68611, 0.11424, 0, 1.14201], + "78": [0, 0.68611, 0.11424, 0, 0.95034], + "79": [0, 0.68611, 0.03194, 0, 0.83666], + "80": [0, 0.68611, 0.15972, 0, 0.72309], + "81": [0.19444, 0.68611, 0, 0, 0.86861], + "82": [0, 0.68611, 0.00421, 0, 0.87235], + "83": [0, 0.68611, 0.05382, 0, 0.69271], + "84": [0, 0.68611, 0.15972, 0, 0.63663], + "85": [0, 0.68611, 0.11424, 0, 0.80027], + "86": [0, 0.68611, 0.25555, 0, 0.67778], + "87": [0, 0.68611, 0.15972, 0, 1.09305], + "88": [0, 0.68611, 0.07778, 0, 0.94722], + "89": [0, 0.68611, 0.25555, 0, 0.67458], + "90": [0, 0.68611, 0.06979, 0, 0.77257], + "97": [0, 0.44444, 0, 0, 0.63287], + "98": [0, 0.69444, 0, 0, 0.52083], + "99": [0, 0.44444, 0, 0, 0.51342], + "100": [0, 0.69444, 0, 0, 0.60972], + "101": [0, 0.44444, 0, 0, 0.55361], + "102": [0.19444, 0.69444, 0.11042, 0, 0.56806], + "103": [0.19444, 0.44444, 0.03704, 0, 0.5449], + "104": [0, 0.69444, 0, 0, 0.66759], + "105": [0, 0.69326, 0, 0, 0.4048], + "106": [0.19444, 0.69326, 0.0622, 0, 0.47083], + "107": [0, 0.69444, 0.01852, 0, 0.6037], + "108": [0, 0.69444, 0.0088, 0, 0.34815], + "109": [0, 0.44444, 0, 0, 1.0324], + "110": [0, 0.44444, 0, 0, 0.71296], + "111": [0, 0.44444, 0, 0, 0.58472], + "112": [0.19444, 0.44444, 0, 0, 0.60092], + "113": [0.19444, 0.44444, 0.03704, 0, 0.54213], + "114": [0, 0.44444, 0.03194, 0, 0.5287], + "115": [0, 0.44444, 0, 0, 0.53125], + "116": [0, 0.63492, 0, 0, 0.41528], + "117": [0, 0.44444, 0, 0, 0.68102], + "118": [0, 0.44444, 0.03704, 0, 0.56666], + "119": [0, 0.44444, 0.02778, 0, 0.83148], + "120": [0, 0.44444, 0, 0, 0.65903], + "121": [0.19444, 0.44444, 0.03704, 0, 0.59028], + "122": [0, 0.44444, 0.04213, 0, 0.55509], + "160": [0, 0, 0, 0, 0.25], + "915": [0, 0.68611, 0.15972, 0, 0.65694], + "916": [0, 0.68611, 0, 0, 0.95833], + "920": [0, 0.68611, 0.03194, 0, 0.86722], + "923": [0, 0.68611, 0, 0, 0.80555], + "926": [0, 0.68611, 0.07458, 0, 0.84125], + "928": [0, 0.68611, 0.08229, 0, 0.98229], + "931": [0, 0.68611, 0.05451, 0, 0.88507], + "933": [0, 0.68611, 0.15972, 0, 0.67083], + "934": [0, 0.68611, 0, 0, 0.76666], + "936": [0, 0.68611, 0.11653, 0, 0.71402], + "937": [0, 0.68611, 0.04835, 0, 0.8789], + "945": [0, 0.44444, 0, 0, 0.76064], + "946": [0.19444, 0.69444, 0.03403, 0, 0.65972], + "947": [0.19444, 0.44444, 0.06389, 0, 0.59003], + "948": [0, 0.69444, 0.03819, 0, 0.52222], + "949": [0, 0.44444, 0, 0, 0.52882], + "950": [0.19444, 0.69444, 0.06215, 0, 0.50833], + "951": [0.19444, 0.44444, 0.03704, 0, 0.6], + "952": [0, 0.69444, 0.03194, 0, 0.5618], + "953": [0, 0.44444, 0, 0, 0.41204], + "954": [0, 0.44444, 0, 0, 0.66759], + "955": [0, 0.69444, 0, 0, 0.67083], + "956": [0.19444, 0.44444, 0, 0, 0.70787], + "957": [0, 0.44444, 0.06898, 0, 0.57685], + "958": [0.19444, 0.69444, 0.03021, 0, 0.50833], + "959": [0, 0.44444, 0, 0, 0.58472], + "960": [0, 0.44444, 0.03704, 0, 0.68241], + "961": [0.19444, 0.44444, 0, 0, 0.6118], + "962": [0.09722, 0.44444, 0.07917, 0, 0.42361], + "963": [0, 0.44444, 0.03704, 0, 0.68588], + "964": [0, 0.44444, 0.13472, 0, 0.52083], + "965": [0, 0.44444, 0.03704, 0, 0.63055], + "966": [0.19444, 0.44444, 0, 0, 0.74722], + "967": [0.19444, 0.44444, 0, 0, 0.71805], + "968": [0.19444, 0.69444, 0.03704, 0, 0.75833], + "969": [0, 0.44444, 0.03704, 0, 0.71782], + "977": [0, 0.69444, 0, 0, 0.69155], + "981": [0.19444, 0.69444, 0, 0, 0.7125], + "982": [0, 0.44444, 0.03194, 0, 0.975], + "1009": [0.19444, 0.44444, 0, 0, 0.6118], + "1013": [0, 0.44444, 0, 0, 0.48333], + "57649": [0, 0.44444, 0, 0, 0.39352], + "57911": [0.19444, 0.44444, 0, 0, 0.43889] + }, + "Math-Italic": { + "32": [0, 0, 0, 0, 0.25], + "48": [0, 0.43056, 0, 0, 0.5], + "49": [0, 0.43056, 0, 0, 0.5], + "50": [0, 0.43056, 0, 0, 0.5], + "51": [0.19444, 0.43056, 0, 0, 0.5], + "52": [0.19444, 0.43056, 0, 0, 0.5], + "53": [0.19444, 0.43056, 0, 0, 0.5], + "54": [0, 0.64444, 0, 0, 0.5], + "55": [0.19444, 0.43056, 0, 0, 0.5], + "56": [0, 0.64444, 0, 0, 0.5], + "57": [0.19444, 0.43056, 0, 0, 0.5], + "65": [0, 0.68333, 0, 0.13889, 0.75], + "66": [0, 0.68333, 0.05017, 0.08334, 0.75851], + "67": [0, 0.68333, 0.07153, 0.08334, 0.71472], + "68": [0, 0.68333, 0.02778, 0.05556, 0.82792], + "69": [0, 0.68333, 0.05764, 0.08334, 0.7382], + "70": [0, 0.68333, 0.13889, 0.08334, 0.64306], + "71": [0, 0.68333, 0, 0.08334, 0.78625], + "72": [0, 0.68333, 0.08125, 0.05556, 0.83125], + "73": [0, 0.68333, 0.07847, 0.11111, 0.43958], + "74": [0, 0.68333, 0.09618, 0.16667, 0.55451], + "75": [0, 0.68333, 0.07153, 0.05556, 0.84931], + "76": [0, 0.68333, 0, 0.02778, 0.68056], + "77": [0, 0.68333, 0.10903, 0.08334, 0.97014], + "78": [0, 0.68333, 0.10903, 0.08334, 0.80347], + "79": [0, 0.68333, 0.02778, 0.08334, 0.76278], + "80": [0, 0.68333, 0.13889, 0.08334, 0.64201], + "81": [0.19444, 0.68333, 0, 0.08334, 0.79056], + "82": [0, 0.68333, 0.00773, 0.08334, 0.75929], + "83": [0, 0.68333, 0.05764, 0.08334, 0.6132], + "84": [0, 0.68333, 0.13889, 0.08334, 0.58438], + "85": [0, 0.68333, 0.10903, 0.02778, 0.68278], + "86": [0, 0.68333, 0.22222, 0, 0.58333], + "87": [0, 0.68333, 0.13889, 0, 0.94445], + "88": [0, 0.68333, 0.07847, 0.08334, 0.82847], + "89": [0, 0.68333, 0.22222, 0, 0.58056], + "90": [0, 0.68333, 0.07153, 0.08334, 0.68264], + "97": [0, 0.43056, 0, 0, 0.52859], + "98": [0, 0.69444, 0, 0, 0.42917], + "99": [0, 0.43056, 0, 0.05556, 0.43276], + "100": [0, 0.69444, 0, 0.16667, 0.52049], + "101": [0, 0.43056, 0, 0.05556, 0.46563], + "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959], + "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697], + "104": [0, 0.69444, 0, 0, 0.57616], + "105": [0, 0.65952, 0, 0, 0.34451], + "106": [0.19444, 0.65952, 0.05724, 0, 0.41181], + "107": [0, 0.69444, 0.03148, 0, 0.5206], + "108": [0, 0.69444, 0.01968, 0.08334, 0.29838], + "109": [0, 0.43056, 0, 0, 0.87801], + "110": [0, 0.43056, 0, 0, 0.60023], + "111": [0, 0.43056, 0, 0.05556, 0.48472], + "112": [0.19444, 0.43056, 0, 0.08334, 0.50313], + "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641], + "114": [0, 0.43056, 0.02778, 0.05556, 0.45116], + "115": [0, 0.43056, 0, 0.05556, 0.46875], + "116": [0, 0.61508, 0, 0.08334, 0.36111], + "117": [0, 0.43056, 0, 0.02778, 0.57246], + "118": [0, 0.43056, 0.03588, 0.02778, 0.48472], + "119": [0, 0.43056, 0.02691, 0.08334, 0.71592], + "120": [0, 0.43056, 0, 0.02778, 0.57153], + "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028], + "122": [0, 0.43056, 0.04398, 0.05556, 0.46505], + "160": [0, 0, 0, 0, 0.25], + "915": [0, 0.68333, 0.13889, 0.08334, 0.61528], + "916": [0, 0.68333, 0, 0.16667, 0.83334], + "920": [0, 0.68333, 0.02778, 0.08334, 0.76278], + "923": [0, 0.68333, 0, 0.16667, 0.69445], + "926": [0, 0.68333, 0.07569, 0.08334, 0.74236], + "928": [0, 0.68333, 0.08125, 0.05556, 0.83125], + "931": [0, 0.68333, 0.05764, 0.08334, 0.77986], + "933": [0, 0.68333, 0.13889, 0.05556, 0.58333], + "934": [0, 0.68333, 0, 0.08334, 0.66667], + "936": [0, 0.68333, 0.11, 0.05556, 0.61222], + "937": [0, 0.68333, 0.05017, 0.08334, 0.7724], + "945": [0, 0.43056, 0.0037, 0.02778, 0.6397], + "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563], + "947": [0.19444, 0.43056, 0.05556, 0, 0.51773], + "948": [0, 0.69444, 0.03785, 0.05556, 0.44444], + "949": [0, 0.43056, 0, 0.08334, 0.46632], + "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375], + "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653], + "952": [0, 0.69444, 0.02778, 0.08334, 0.46944], + "953": [0, 0.43056, 0, 0.05556, 0.35394], + "954": [0, 0.43056, 0, 0, 0.57616], + "955": [0, 0.69444, 0, 0, 0.58334], + "956": [0.19444, 0.43056, 0, 0.02778, 0.60255], + "957": [0, 0.43056, 0.06366, 0.02778, 0.49398], + "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375], + "959": [0, 0.43056, 0, 0.05556, 0.48472], + "960": [0, 0.43056, 0.03588, 0, 0.57003], + "961": [0.19444, 0.43056, 0, 0.08334, 0.51702], + "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285], + "963": [0, 0.43056, 0.03588, 0, 0.57141], + "964": [0, 0.43056, 0.1132, 0.02778, 0.43715], + "965": [0, 0.43056, 0.03588, 0.02778, 0.54028], + "966": [0.19444, 0.43056, 0, 0.08334, 0.65417], + "967": [0.19444, 0.43056, 0, 0.05556, 0.62569], + "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139], + "969": [0, 0.43056, 0.03588, 0, 0.62245], + "977": [0, 0.69444, 0, 0.08334, 0.59144], + "981": [0.19444, 0.69444, 0, 0.08334, 0.59583], + "982": [0, 0.43056, 0.02778, 0, 0.82813], + "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702], + "1013": [0, 0.43056, 0, 0.05556, 0.4059], + "57649": [0, 0.43056, 0, 0.02778, 0.32246], + "57911": [0.19444, 0.43056, 0, 0.08334, 0.38403] + }, + "SansSerif-Bold": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.36667], + "34": [0, 0.69444, 0, 0, 0.55834], + "35": [0.19444, 0.69444, 0, 0, 0.91667], + "36": [0.05556, 0.75, 0, 0, 0.55], + "37": [0.05556, 0.75, 0, 0, 1.02912], + "38": [0, 0.69444, 0, 0, 0.83056], + "39": [0, 0.69444, 0, 0, 0.30556], + "40": [0.25, 0.75, 0, 0, 0.42778], + "41": [0.25, 0.75, 0, 0, 0.42778], + "42": [0, 0.75, 0, 0, 0.55], + "43": [0.11667, 0.61667, 0, 0, 0.85556], + "44": [0.10556, 0.13056, 0, 0, 0.30556], + "45": [0, 0.45833, 0, 0, 0.36667], + "46": [0, 0.13056, 0, 0, 0.30556], + "47": [0.25, 0.75, 0, 0, 0.55], + "48": [0, 0.69444, 0, 0, 0.55], + "49": [0, 0.69444, 0, 0, 0.55], + "50": [0, 0.69444, 0, 0, 0.55], + "51": [0, 0.69444, 0, 0, 0.55], + "52": [0, 0.69444, 0, 0, 0.55], + "53": [0, 0.69444, 0, 0, 0.55], + "54": [0, 0.69444, 0, 0, 0.55], + "55": [0, 0.69444, 0, 0, 0.55], + "56": [0, 0.69444, 0, 0, 0.55], + "57": [0, 0.69444, 0, 0, 0.55], + "58": [0, 0.45833, 0, 0, 0.30556], + "59": [0.10556, 0.45833, 0, 0, 0.30556], + "61": [-0.09375, 0.40625, 0, 0, 0.85556], + "63": [0, 0.69444, 0, 0, 0.51945], + "64": [0, 0.69444, 0, 0, 0.73334], + "65": [0, 0.69444, 0, 0, 0.73334], + "66": [0, 0.69444, 0, 0, 0.73334], + "67": [0, 0.69444, 0, 0, 0.70278], + "68": [0, 0.69444, 0, 0, 0.79445], + "69": [0, 0.69444, 0, 0, 0.64167], + "70": [0, 0.69444, 0, 0, 0.61111], + "71": [0, 0.69444, 0, 0, 0.73334], + "72": [0, 0.69444, 0, 0, 0.79445], + "73": [0, 0.69444, 0, 0, 0.33056], + "74": [0, 0.69444, 0, 0, 0.51945], + "75": [0, 0.69444, 0, 0, 0.76389], + "76": [0, 0.69444, 0, 0, 0.58056], + "77": [0, 0.69444, 0, 0, 0.97778], + "78": [0, 0.69444, 0, 0, 0.79445], + "79": [0, 0.69444, 0, 0, 0.79445], + "80": [0, 0.69444, 0, 0, 0.70278], + "81": [0.10556, 0.69444, 0, 0, 0.79445], + "82": [0, 0.69444, 0, 0, 0.70278], + "83": [0, 0.69444, 0, 0, 0.61111], + "84": [0, 0.69444, 0, 0, 0.73334], + "85": [0, 0.69444, 0, 0, 0.76389], + "86": [0, 0.69444, 0.01528, 0, 0.73334], + "87": [0, 0.69444, 0.01528, 0, 1.03889], + "88": [0, 0.69444, 0, 0, 0.73334], + "89": [0, 0.69444, 0.0275, 0, 0.73334], + "90": [0, 0.69444, 0, 0, 0.67223], + "91": [0.25, 0.75, 0, 0, 0.34306], + "93": [0.25, 0.75, 0, 0, 0.34306], + "94": [0, 0.69444, 0, 0, 0.55], + "95": [0.35, 0.10833, 0.03056, 0, 0.55], + "97": [0, 0.45833, 0, 0, 0.525], + "98": [0, 0.69444, 0, 0, 0.56111], + "99": [0, 0.45833, 0, 0, 0.48889], + "100": [0, 0.69444, 0, 0, 0.56111], + "101": [0, 0.45833, 0, 0, 0.51111], + "102": [0, 0.69444, 0.07639, 0, 0.33611], + "103": [0.19444, 0.45833, 0.01528, 0, 0.55], + "104": [0, 0.69444, 0, 0, 0.56111], + "105": [0, 0.69444, 0, 0, 0.25556], + "106": [0.19444, 0.69444, 0, 0, 0.28611], + "107": [0, 0.69444, 0, 0, 0.53056], + "108": [0, 0.69444, 0, 0, 0.25556], + "109": [0, 0.45833, 0, 0, 0.86667], + "110": [0, 0.45833, 0, 0, 0.56111], + "111": [0, 0.45833, 0, 0, 0.55], + "112": [0.19444, 0.45833, 0, 0, 0.56111], + "113": [0.19444, 0.45833, 0, 0, 0.56111], + "114": [0, 0.45833, 0.01528, 0, 0.37222], + "115": [0, 0.45833, 0, 0, 0.42167], + "116": [0, 0.58929, 0, 0, 0.40417], + "117": [0, 0.45833, 0, 0, 0.56111], + "118": [0, 0.45833, 0.01528, 0, 0.5], + "119": [0, 0.45833, 0.01528, 0, 0.74445], + "120": [0, 0.45833, 0, 0, 0.5], + "121": [0.19444, 0.45833, 0.01528, 0, 0.5], + "122": [0, 0.45833, 0, 0, 0.47639], + "126": [0.35, 0.34444, 0, 0, 0.55], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.69444, 0, 0, 0.55], + "176": [0, 0.69444, 0, 0, 0.73334], + "180": [0, 0.69444, 0, 0, 0.55], + "184": [0.17014, 0, 0, 0, 0.48889], + "305": [0, 0.45833, 0, 0, 0.25556], + "567": [0.19444, 0.45833, 0, 0, 0.28611], + "710": [0, 0.69444, 0, 0, 0.55], + "711": [0, 0.63542, 0, 0, 0.55], + "713": [0, 0.63778, 0, 0, 0.55], + "728": [0, 0.69444, 0, 0, 0.55], + "729": [0, 0.69444, 0, 0, 0.30556], + "730": [0, 0.69444, 0, 0, 0.73334], + "732": [0, 0.69444, 0, 0, 0.55], + "733": [0, 0.69444, 0, 0, 0.55], + "915": [0, 0.69444, 0, 0, 0.58056], + "916": [0, 0.69444, 0, 0, 0.91667], + "920": [0, 0.69444, 0, 0, 0.85556], + "923": [0, 0.69444, 0, 0, 0.67223], + "926": [0, 0.69444, 0, 0, 0.73334], + "928": [0, 0.69444, 0, 0, 0.79445], + "931": [0, 0.69444, 0, 0, 0.79445], + "933": [0, 0.69444, 0, 0, 0.85556], + "934": [0, 0.69444, 0, 0, 0.79445], + "936": [0, 0.69444, 0, 0, 0.85556], + "937": [0, 0.69444, 0, 0, 0.79445], + "8211": [0, 0.45833, 0.03056, 0, 0.55], + "8212": [0, 0.45833, 0.03056, 0, 1.10001], + "8216": [0, 0.69444, 0, 0, 0.30556], + "8217": [0, 0.69444, 0, 0, 0.30556], + "8220": [0, 0.69444, 0, 0, 0.55834], + "8221": [0, 0.69444, 0, 0, 0.55834] + }, + "SansSerif-Italic": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0.05733, 0, 0.31945], + "34": [0, 0.69444, 0.00316, 0, 0.5], + "35": [0.19444, 0.69444, 0.05087, 0, 0.83334], + "36": [0.05556, 0.75, 0.11156, 0, 0.5], + "37": [0.05556, 0.75, 0.03126, 0, 0.83334], + "38": [0, 0.69444, 0.03058, 0, 0.75834], + "39": [0, 0.69444, 0.07816, 0, 0.27778], + "40": [0.25, 0.75, 0.13164, 0, 0.38889], + "41": [0.25, 0.75, 0.02536, 0, 0.38889], + "42": [0, 0.75, 0.11775, 0, 0.5], + "43": [0.08333, 0.58333, 0.02536, 0, 0.77778], + "44": [0.125, 0.08333, 0, 0, 0.27778], + "45": [0, 0.44444, 0.01946, 0, 0.33333], + "46": [0, 0.08333, 0, 0, 0.27778], + "47": [0.25, 0.75, 0.13164, 0, 0.5], + "48": [0, 0.65556, 0.11156, 0, 0.5], + "49": [0, 0.65556, 0.11156, 0, 0.5], + "50": [0, 0.65556, 0.11156, 0, 0.5], + "51": [0, 0.65556, 0.11156, 0, 0.5], + "52": [0, 0.65556, 0.11156, 0, 0.5], + "53": [0, 0.65556, 0.11156, 0, 0.5], + "54": [0, 0.65556, 0.11156, 0, 0.5], + "55": [0, 0.65556, 0.11156, 0, 0.5], + "56": [0, 0.65556, 0.11156, 0, 0.5], + "57": [0, 0.65556, 0.11156, 0, 0.5], + "58": [0, 0.44444, 0.02502, 0, 0.27778], + "59": [0.125, 0.44444, 0.02502, 0, 0.27778], + "61": [-0.13, 0.37, 0.05087, 0, 0.77778], + "63": [0, 0.69444, 0.11809, 0, 0.47222], + "64": [0, 0.69444, 0.07555, 0, 0.66667], + "65": [0, 0.69444, 0, 0, 0.66667], + "66": [0, 0.69444, 0.08293, 0, 0.66667], + "67": [0, 0.69444, 0.11983, 0, 0.63889], + "68": [0, 0.69444, 0.07555, 0, 0.72223], + "69": [0, 0.69444, 0.11983, 0, 0.59722], + "70": [0, 0.69444, 0.13372, 0, 0.56945], + "71": [0, 0.69444, 0.11983, 0, 0.66667], + "72": [0, 0.69444, 0.08094, 0, 0.70834], + "73": [0, 0.69444, 0.13372, 0, 0.27778], + "74": [0, 0.69444, 0.08094, 0, 0.47222], + "75": [0, 0.69444, 0.11983, 0, 0.69445], + "76": [0, 0.69444, 0, 0, 0.54167], + "77": [0, 0.69444, 0.08094, 0, 0.875], + "78": [0, 0.69444, 0.08094, 0, 0.70834], + "79": [0, 0.69444, 0.07555, 0, 0.73611], + "80": [0, 0.69444, 0.08293, 0, 0.63889], + "81": [0.125, 0.69444, 0.07555, 0, 0.73611], + "82": [0, 0.69444, 0.08293, 0, 0.64584], + "83": [0, 0.69444, 0.09205, 0, 0.55556], + "84": [0, 0.69444, 0.13372, 0, 0.68056], + "85": [0, 0.69444, 0.08094, 0, 0.6875], + "86": [0, 0.69444, 0.1615, 0, 0.66667], + "87": [0, 0.69444, 0.1615, 0, 0.94445], + "88": [0, 0.69444, 0.13372, 0, 0.66667], + "89": [0, 0.69444, 0.17261, 0, 0.66667], + "90": [0, 0.69444, 0.11983, 0, 0.61111], + "91": [0.25, 0.75, 0.15942, 0, 0.28889], + "93": [0.25, 0.75, 0.08719, 0, 0.28889], + "94": [0, 0.69444, 0.0799, 0, 0.5], + "95": [0.35, 0.09444, 0.08616, 0, 0.5], + "97": [0, 0.44444, 0.00981, 0, 0.48056], + "98": [0, 0.69444, 0.03057, 0, 0.51667], + "99": [0, 0.44444, 0.08336, 0, 0.44445], + "100": [0, 0.69444, 0.09483, 0, 0.51667], + "101": [0, 0.44444, 0.06778, 0, 0.44445], + "102": [0, 0.69444, 0.21705, 0, 0.30556], + "103": [0.19444, 0.44444, 0.10836, 0, 0.5], + "104": [0, 0.69444, 0.01778, 0, 0.51667], + "105": [0, 0.67937, 0.09718, 0, 0.23889], + "106": [0.19444, 0.67937, 0.09162, 0, 0.26667], + "107": [0, 0.69444, 0.08336, 0, 0.48889], + "108": [0, 0.69444, 0.09483, 0, 0.23889], + "109": [0, 0.44444, 0.01778, 0, 0.79445], + "110": [0, 0.44444, 0.01778, 0, 0.51667], + "111": [0, 0.44444, 0.06613, 0, 0.5], + "112": [0.19444, 0.44444, 0.0389, 0, 0.51667], + "113": [0.19444, 0.44444, 0.04169, 0, 0.51667], + "114": [0, 0.44444, 0.10836, 0, 0.34167], + "115": [0, 0.44444, 0.0778, 0, 0.38333], + "116": [0, 0.57143, 0.07225, 0, 0.36111], + "117": [0, 0.44444, 0.04169, 0, 0.51667], + "118": [0, 0.44444, 0.10836, 0, 0.46111], + "119": [0, 0.44444, 0.10836, 0, 0.68334], + "120": [0, 0.44444, 0.09169, 0, 0.46111], + "121": [0.19444, 0.44444, 0.10836, 0, 0.46111], + "122": [0, 0.44444, 0.08752, 0, 0.43472], + "126": [0.35, 0.32659, 0.08826, 0, 0.5], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.67937, 0.06385, 0, 0.5], + "176": [0, 0.69444, 0, 0, 0.73752], + "184": [0.17014, 0, 0, 0, 0.44445], + "305": [0, 0.44444, 0.04169, 0, 0.23889], + "567": [0.19444, 0.44444, 0.04169, 0, 0.26667], + "710": [0, 0.69444, 0.0799, 0, 0.5], + "711": [0, 0.63194, 0.08432, 0, 0.5], + "713": [0, 0.60889, 0.08776, 0, 0.5], + "714": [0, 0.69444, 0.09205, 0, 0.5], + "715": [0, 0.69444, 0, 0, 0.5], + "728": [0, 0.69444, 0.09483, 0, 0.5], + "729": [0, 0.67937, 0.07774, 0, 0.27778], + "730": [0, 0.69444, 0, 0, 0.73752], + "732": [0, 0.67659, 0.08826, 0, 0.5], + "733": [0, 0.69444, 0.09205, 0, 0.5], + "915": [0, 0.69444, 0.13372, 0, 0.54167], + "916": [0, 0.69444, 0, 0, 0.83334], + "920": [0, 0.69444, 0.07555, 0, 0.77778], + "923": [0, 0.69444, 0, 0, 0.61111], + "926": [0, 0.69444, 0.12816, 0, 0.66667], + "928": [0, 0.69444, 0.08094, 0, 0.70834], + "931": [0, 0.69444, 0.11983, 0, 0.72222], + "933": [0, 0.69444, 0.09031, 0, 0.77778], + "934": [0, 0.69444, 0.04603, 0, 0.72222], + "936": [0, 0.69444, 0.09031, 0, 0.77778], + "937": [0, 0.69444, 0.08293, 0, 0.72222], + "8211": [0, 0.44444, 0.08616, 0, 0.5], + "8212": [0, 0.44444, 0.08616, 0, 1.0], + "8216": [0, 0.69444, 0.07816, 0, 0.27778], + "8217": [0, 0.69444, 0.07816, 0, 0.27778], + "8220": [0, 0.69444, 0.14205, 0, 0.5], + "8221": [0, 0.69444, 0.00316, 0, 0.5] + }, + "SansSerif-Regular": { + "32": [0, 0, 0, 0, 0.25], + "33": [0, 0.69444, 0, 0, 0.31945], + "34": [0, 0.69444, 0, 0, 0.5], + "35": [0.19444, 0.69444, 0, 0, 0.83334], + "36": [0.05556, 0.75, 0, 0, 0.5], + "37": [0.05556, 0.75, 0, 0, 0.83334], + "38": [0, 0.69444, 0, 0, 0.75834], + "39": [0, 0.69444, 0, 0, 0.27778], + "40": [0.25, 0.75, 0, 0, 0.38889], + "41": [0.25, 0.75, 0, 0, 0.38889], + "42": [0, 0.75, 0, 0, 0.5], + "43": [0.08333, 0.58333, 0, 0, 0.77778], + "44": [0.125, 0.08333, 0, 0, 0.27778], + "45": [0, 0.44444, 0, 0, 0.33333], + "46": [0, 0.08333, 0, 0, 0.27778], + "47": [0.25, 0.75, 0, 0, 0.5], + "48": [0, 0.65556, 0, 0, 0.5], + "49": [0, 0.65556, 0, 0, 0.5], + "50": [0, 0.65556, 0, 0, 0.5], + "51": [0, 0.65556, 0, 0, 0.5], + "52": [0, 0.65556, 0, 0, 0.5], + "53": [0, 0.65556, 0, 0, 0.5], + "54": [0, 0.65556, 0, 0, 0.5], + "55": [0, 0.65556, 0, 0, 0.5], + "56": [0, 0.65556, 0, 0, 0.5], + "57": [0, 0.65556, 0, 0, 0.5], + "58": [0, 0.44444, 0, 0, 0.27778], + "59": [0.125, 0.44444, 0, 0, 0.27778], + "61": [-0.13, 0.37, 0, 0, 0.77778], + "63": [0, 0.69444, 0, 0, 0.47222], + "64": [0, 0.69444, 0, 0, 0.66667], + "65": [0, 0.69444, 0, 0, 0.66667], + "66": [0, 0.69444, 0, 0, 0.66667], + "67": [0, 0.69444, 0, 0, 0.63889], + "68": [0, 0.69444, 0, 0, 0.72223], + "69": [0, 0.69444, 0, 0, 0.59722], + "70": [0, 0.69444, 0, 0, 0.56945], + "71": [0, 0.69444, 0, 0, 0.66667], + "72": [0, 0.69444, 0, 0, 0.70834], + "73": [0, 0.69444, 0, 0, 0.27778], + "74": [0, 0.69444, 0, 0, 0.47222], + "75": [0, 0.69444, 0, 0, 0.69445], + "76": [0, 0.69444, 0, 0, 0.54167], + "77": [0, 0.69444, 0, 0, 0.875], + "78": [0, 0.69444, 0, 0, 0.70834], + "79": [0, 0.69444, 0, 0, 0.73611], + "80": [0, 0.69444, 0, 0, 0.63889], + "81": [0.125, 0.69444, 0, 0, 0.73611], + "82": [0, 0.69444, 0, 0, 0.64584], + "83": [0, 0.69444, 0, 0, 0.55556], + "84": [0, 0.69444, 0, 0, 0.68056], + "85": [0, 0.69444, 0, 0, 0.6875], + "86": [0, 0.69444, 0.01389, 0, 0.66667], + "87": [0, 0.69444, 0.01389, 0, 0.94445], + "88": [0, 0.69444, 0, 0, 0.66667], + "89": [0, 0.69444, 0.025, 0, 0.66667], + "90": [0, 0.69444, 0, 0, 0.61111], + "91": [0.25, 0.75, 0, 0, 0.28889], + "93": [0.25, 0.75, 0, 0, 0.28889], + "94": [0, 0.69444, 0, 0, 0.5], + "95": [0.35, 0.09444, 0.02778, 0, 0.5], + "97": [0, 0.44444, 0, 0, 0.48056], + "98": [0, 0.69444, 0, 0, 0.51667], + "99": [0, 0.44444, 0, 0, 0.44445], + "100": [0, 0.69444, 0, 0, 0.51667], + "101": [0, 0.44444, 0, 0, 0.44445], + "102": [0, 0.69444, 0.06944, 0, 0.30556], + "103": [0.19444, 0.44444, 0.01389, 0, 0.5], + "104": [0, 0.69444, 0, 0, 0.51667], + "105": [0, 0.67937, 0, 0, 0.23889], + "106": [0.19444, 0.67937, 0, 0, 0.26667], + "107": [0, 0.69444, 0, 0, 0.48889], + "108": [0, 0.69444, 0, 0, 0.23889], + "109": [0, 0.44444, 0, 0, 0.79445], + "110": [0, 0.44444, 0, 0, 0.51667], + "111": [0, 0.44444, 0, 0, 0.5], + "112": [0.19444, 0.44444, 0, 0, 0.51667], + "113": [0.19444, 0.44444, 0, 0, 0.51667], + "114": [0, 0.44444, 0.01389, 0, 0.34167], + "115": [0, 0.44444, 0, 0, 0.38333], + "116": [0, 0.57143, 0, 0, 0.36111], + "117": [0, 0.44444, 0, 0, 0.51667], + "118": [0, 0.44444, 0.01389, 0, 0.46111], + "119": [0, 0.44444, 0.01389, 0, 0.68334], + "120": [0, 0.44444, 0, 0, 0.46111], + "121": [0.19444, 0.44444, 0.01389, 0, 0.46111], + "122": [0, 0.44444, 0, 0, 0.43472], + "126": [0.35, 0.32659, 0, 0, 0.5], + "160": [0, 0, 0, 0, 0.25], + "168": [0, 0.67937, 0, 0, 0.5], + "176": [0, 0.69444, 0, 0, 0.66667], + "184": [0.17014, 0, 0, 0, 0.44445], + "305": [0, 0.44444, 0, 0, 0.23889], + "567": [0.19444, 0.44444, 0, 0, 0.26667], + "710": [0, 0.69444, 0, 0, 0.5], + "711": [0, 0.63194, 0, 0, 0.5], + "713": [0, 0.60889, 0, 0, 0.5], + "714": [0, 0.69444, 0, 0, 0.5], + "715": [0, 0.69444, 0, 0, 0.5], + "728": [0, 0.69444, 0, 0, 0.5], + "729": [0, 0.67937, 0, 0, 0.27778], + "730": [0, 0.69444, 0, 0, 0.66667], + "732": [0, 0.67659, 0, 0, 0.5], + "733": [0, 0.69444, 0, 0, 0.5], + "915": [0, 0.69444, 0, 0, 0.54167], + "916": [0, 0.69444, 0, 0, 0.83334], + "920": [0, 0.69444, 0, 0, 0.77778], + "923": [0, 0.69444, 0, 0, 0.61111], + "926": [0, 0.69444, 0, 0, 0.66667], + "928": [0, 0.69444, 0, 0, 0.70834], + "931": [0, 0.69444, 0, 0, 0.72222], + "933": [0, 0.69444, 0, 0, 0.77778], + "934": [0, 0.69444, 0, 0, 0.72222], + "936": [0, 0.69444, 0, 0, 0.77778], + "937": [0, 0.69444, 0, 0, 0.72222], + "8211": [0, 0.44444, 0.02778, 0, 0.5], + "8212": [0, 0.44444, 0.02778, 0, 1.0], + "8216": [0, 0.69444, 0, 0, 0.27778], + "8217": [0, 0.69444, 0, 0, 0.27778], + "8220": [0, 0.69444, 0, 0, 0.5], + "8221": [0, 0.69444, 0, 0, 0.5] + }, + "Script-Regular": { + "32": [0, 0, 0, 0, 0.25], + "65": [0, 0.7, 0.22925, 0, 0.80253], + "66": [0, 0.7, 0.04087, 0, 0.90757], + "67": [0, 0.7, 0.1689, 0, 0.66619], + "68": [0, 0.7, 0.09371, 0, 0.77443], + "69": [0, 0.7, 0.18583, 0, 0.56162], + "70": [0, 0.7, 0.13634, 0, 0.89544], + "71": [0, 0.7, 0.17322, 0, 0.60961], + "72": [0, 0.7, 0.29694, 0, 0.96919], + "73": [0, 0.7, 0.19189, 0, 0.80907], + "74": [0.27778, 0.7, 0.19189, 0, 1.05159], + "75": [0, 0.7, 0.31259, 0, 0.91364], + "76": [0, 0.7, 0.19189, 0, 0.87373], + "77": [0, 0.7, 0.15981, 0, 1.08031], + "78": [0, 0.7, 0.3525, 0, 0.9015], + "79": [0, 0.7, 0.08078, 0, 0.73787], + "80": [0, 0.7, 0.08078, 0, 1.01262], + "81": [0, 0.7, 0.03305, 0, 0.88282], + "82": [0, 0.7, 0.06259, 0, 0.85], + "83": [0, 0.7, 0.19189, 0, 0.86767], + "84": [0, 0.7, 0.29087, 0, 0.74697], + "85": [0, 0.7, 0.25815, 0, 0.79996], + "86": [0, 0.7, 0.27523, 0, 0.62204], + "87": [0, 0.7, 0.27523, 0, 0.80532], + "88": [0, 0.7, 0.26006, 0, 0.94445], + "89": [0, 0.7, 0.2939, 0, 0.70961], + "90": [0, 0.7, 0.24037, 0, 0.8212], + "160": [0, 0, 0, 0, 0.25] + }, + "Size1-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [0.35001, 0.85, 0, 0, 0.45834], + "41": [0.35001, 0.85, 0, 0, 0.45834], + "47": [0.35001, 0.85, 0, 0, 0.57778], + "91": [0.35001, 0.85, 0, 0, 0.41667], + "92": [0.35001, 0.85, 0, 0, 0.57778], + "93": [0.35001, 0.85, 0, 0, 0.41667], + "123": [0.35001, 0.85, 0, 0, 0.58334], + "125": [0.35001, 0.85, 0, 0, 0.58334], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.72222, 0, 0, 0.55556], + "732": [0, 0.72222, 0, 0, 0.55556], + "770": [0, 0.72222, 0, 0, 0.55556], + "771": [0, 0.72222, 0, 0, 0.55556], + "8214": [-0.00099, 0.601, 0, 0, 0.77778], + "8593": [1e-05, 0.6, 0, 0, 0.66667], + "8595": [1e-05, 0.6, 0, 0, 0.66667], + "8657": [1e-05, 0.6, 0, 0, 0.77778], + "8659": [1e-05, 0.6, 0, 0, 0.77778], + "8719": [0.25001, 0.75, 0, 0, 0.94445], + "8720": [0.25001, 0.75, 0, 0, 0.94445], + "8721": [0.25001, 0.75, 0, 0, 1.05556], + "8730": [0.35001, 0.85, 0, 0, 1.0], + "8739": [-0.00599, 0.606, 0, 0, 0.33333], + "8741": [-0.00599, 0.606, 0, 0, 0.55556], + "8747": [0.30612, 0.805, 0.19445, 0, 0.47222], + "8748": [0.306, 0.805, 0.19445, 0, 0.47222], + "8749": [0.306, 0.805, 0.19445, 0, 0.47222], + "8750": [0.30612, 0.805, 0.19445, 0, 0.47222], + "8896": [0.25001, 0.75, 0, 0, 0.83334], + "8897": [0.25001, 0.75, 0, 0, 0.83334], + "8898": [0.25001, 0.75, 0, 0, 0.83334], + "8899": [0.25001, 0.75, 0, 0, 0.83334], + "8968": [0.35001, 0.85, 0, 0, 0.47222], + "8969": [0.35001, 0.85, 0, 0, 0.47222], + "8970": [0.35001, 0.85, 0, 0, 0.47222], + "8971": [0.35001, 0.85, 0, 0, 0.47222], + "9168": [-0.00099, 0.601, 0, 0, 0.66667], + "10216": [0.35001, 0.85, 0, 0, 0.47222], + "10217": [0.35001, 0.85, 0, 0, 0.47222], + "10752": [0.25001, 0.75, 0, 0, 1.11111], + "10753": [0.25001, 0.75, 0, 0, 1.11111], + "10754": [0.25001, 0.75, 0, 0, 1.11111], + "10756": [0.25001, 0.75, 0, 0, 0.83334], + "10758": [0.25001, 0.75, 0, 0, 0.83334] + }, + "Size2-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [0.65002, 1.15, 0, 0, 0.59722], + "41": [0.65002, 1.15, 0, 0, 0.59722], + "47": [0.65002, 1.15, 0, 0, 0.81111], + "91": [0.65002, 1.15, 0, 0, 0.47222], + "92": [0.65002, 1.15, 0, 0, 0.81111], + "93": [0.65002, 1.15, 0, 0, 0.47222], + "123": [0.65002, 1.15, 0, 0, 0.66667], + "125": [0.65002, 1.15, 0, 0, 0.66667], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.75, 0, 0, 1.0], + "732": [0, 0.75, 0, 0, 1.0], + "770": [0, 0.75, 0, 0, 1.0], + "771": [0, 0.75, 0, 0, 1.0], + "8719": [0.55001, 1.05, 0, 0, 1.27778], + "8720": [0.55001, 1.05, 0, 0, 1.27778], + "8721": [0.55001, 1.05, 0, 0, 1.44445], + "8730": [0.65002, 1.15, 0, 0, 1.0], + "8747": [0.86225, 1.36, 0.44445, 0, 0.55556], + "8748": [0.862, 1.36, 0.44445, 0, 0.55556], + "8749": [0.862, 1.36, 0.44445, 0, 0.55556], + "8750": [0.86225, 1.36, 0.44445, 0, 0.55556], + "8896": [0.55001, 1.05, 0, 0, 1.11111], + "8897": [0.55001, 1.05, 0, 0, 1.11111], + "8898": [0.55001, 1.05, 0, 0, 1.11111], + "8899": [0.55001, 1.05, 0, 0, 1.11111], + "8968": [0.65002, 1.15, 0, 0, 0.52778], + "8969": [0.65002, 1.15, 0, 0, 0.52778], + "8970": [0.65002, 1.15, 0, 0, 0.52778], + "8971": [0.65002, 1.15, 0, 0, 0.52778], + "10216": [0.65002, 1.15, 0, 0, 0.61111], + "10217": [0.65002, 1.15, 0, 0, 0.61111], + "10752": [0.55001, 1.05, 0, 0, 1.51112], + "10753": [0.55001, 1.05, 0, 0, 1.51112], + "10754": [0.55001, 1.05, 0, 0, 1.51112], + "10756": [0.55001, 1.05, 0, 0, 1.11111], + "10758": [0.55001, 1.05, 0, 0, 1.11111] + }, + "Size3-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [0.95003, 1.45, 0, 0, 0.73611], + "41": [0.95003, 1.45, 0, 0, 0.73611], + "47": [0.95003, 1.45, 0, 0, 1.04445], + "91": [0.95003, 1.45, 0, 0, 0.52778], + "92": [0.95003, 1.45, 0, 0, 1.04445], + "93": [0.95003, 1.45, 0, 0, 0.52778], + "123": [0.95003, 1.45, 0, 0, 0.75], + "125": [0.95003, 1.45, 0, 0, 0.75], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.75, 0, 0, 1.44445], + "732": [0, 0.75, 0, 0, 1.44445], + "770": [0, 0.75, 0, 0, 1.44445], + "771": [0, 0.75, 0, 0, 1.44445], + "8730": [0.95003, 1.45, 0, 0, 1.0], + "8968": [0.95003, 1.45, 0, 0, 0.58334], + "8969": [0.95003, 1.45, 0, 0, 0.58334], + "8970": [0.95003, 1.45, 0, 0, 0.58334], + "8971": [0.95003, 1.45, 0, 0, 0.58334], + "10216": [0.95003, 1.45, 0, 0, 0.75], + "10217": [0.95003, 1.45, 0, 0, 0.75] + }, + "Size4-Regular": { + "32": [0, 0, 0, 0, 0.25], + "40": [1.25003, 1.75, 0, 0, 0.79167], + "41": [1.25003, 1.75, 0, 0, 0.79167], + "47": [1.25003, 1.75, 0, 0, 1.27778], + "91": [1.25003, 1.75, 0, 0, 0.58334], + "92": [1.25003, 1.75, 0, 0, 1.27778], + "93": [1.25003, 1.75, 0, 0, 0.58334], + "123": [1.25003, 1.75, 0, 0, 0.80556], + "125": [1.25003, 1.75, 0, 0, 0.80556], + "160": [0, 0, 0, 0, 0.25], + "710": [0, 0.825, 0, 0, 1.8889], + "732": [0, 0.825, 0, 0, 1.8889], + "770": [0, 0.825, 0, 0, 1.8889], + "771": [0, 0.825, 0, 0, 1.8889], + "8730": [1.25003, 1.75, 0, 0, 1.0], + "8968": [1.25003, 1.75, 0, 0, 0.63889], + "8969": [1.25003, 1.75, 0, 0, 0.63889], + "8970": [1.25003, 1.75, 0, 0, 0.63889], + "8971": [1.25003, 1.75, 0, 0, 0.63889], + "9115": [0.64502, 1.155, 0, 0, 0.875], + "9116": [1e-05, 0.6, 0, 0, 0.875], + "9117": [0.64502, 1.155, 0, 0, 0.875], + "9118": [0.64502, 1.155, 0, 0, 0.875], + "9119": [1e-05, 0.6, 0, 0, 0.875], + "9120": [0.64502, 1.155, 0, 0, 0.875], + "9121": [0.64502, 1.155, 0, 0, 0.66667], + "9122": [-0.00099, 0.601, 0, 0, 0.66667], + "9123": [0.64502, 1.155, 0, 0, 0.66667], + "9124": [0.64502, 1.155, 0, 0, 0.66667], + "9125": [-0.00099, 0.601, 0, 0, 0.66667], + "9126": [0.64502, 1.155, 0, 0, 0.66667], + "9127": [1e-05, 0.9, 0, 0, 0.88889], + "9128": [0.65002, 1.15, 0, 0, 0.88889], + "9129": [0.90001, 0, 0, 0, 0.88889], + "9130": [0, 0.3, 0, 0, 0.88889], + "9131": [1e-05, 0.9, 0, 0, 0.88889], + "9132": [0.65002, 1.15, 0, 0, 0.88889], + "9133": [0.90001, 0, 0, 0, 0.88889], + "9143": [0.88502, 0.915, 0, 0, 1.05556], + "10216": [1.25003, 1.75, 0, 0, 0.80556], + "10217": [1.25003, 1.75, 0, 0, 0.80556], + "57344": [-0.00499, 0.605, 0, 0, 1.05556], + "57345": [-0.00499, 0.605, 0, 0, 1.05556], + "57680": [0, 0.12, 0, 0, 0.45], + "57681": [0, 0.12, 0, 0, 0.45], + "57682": [0, 0.12, 0, 0, 0.45], + "57683": [0, 0.12, 0, 0, 0.45] + }, + "Typewriter-Regular": { + "32": [0, 0, 0, 0, 0.525], + "33": [0, 0.61111, 0, 0, 0.525], + "34": [0, 0.61111, 0, 0, 0.525], + "35": [0, 0.61111, 0, 0, 0.525], + "36": [0.08333, 0.69444, 0, 0, 0.525], + "37": [0.08333, 0.69444, 0, 0, 0.525], + "38": [0, 0.61111, 0, 0, 0.525], + "39": [0, 0.61111, 0, 0, 0.525], + "40": [0.08333, 0.69444, 0, 0, 0.525], + "41": [0.08333, 0.69444, 0, 0, 0.525], + "42": [0, 0.52083, 0, 0, 0.525], + "43": [-0.08056, 0.53055, 0, 0, 0.525], + "44": [0.13889, 0.125, 0, 0, 0.525], + "45": [-0.08056, 0.53055, 0, 0, 0.525], + "46": [0, 0.125, 0, 0, 0.525], + "47": [0.08333, 0.69444, 0, 0, 0.525], + "48": [0, 0.61111, 0, 0, 0.525], + "49": [0, 0.61111, 0, 0, 0.525], + "50": [0, 0.61111, 0, 0, 0.525], + "51": [0, 0.61111, 0, 0, 0.525], + "52": [0, 0.61111, 0, 0, 0.525], + "53": [0, 0.61111, 0, 0, 0.525], + "54": [0, 0.61111, 0, 0, 0.525], + "55": [0, 0.61111, 0, 0, 0.525], + "56": [0, 0.61111, 0, 0, 0.525], + "57": [0, 0.61111, 0, 0, 0.525], + "58": [0, 0.43056, 0, 0, 0.525], + "59": [0.13889, 0.43056, 0, 0, 0.525], + "60": [-0.05556, 0.55556, 0, 0, 0.525], + "61": [-0.19549, 0.41562, 0, 0, 0.525], + "62": [-0.05556, 0.55556, 0, 0, 0.525], + "63": [0, 0.61111, 0, 0, 0.525], + "64": [0, 0.61111, 0, 0, 0.525], + "65": [0, 0.61111, 0, 0, 0.525], + "66": [0, 0.61111, 0, 0, 0.525], + "67": [0, 0.61111, 0, 0, 0.525], + "68": [0, 0.61111, 0, 0, 0.525], + "69": [0, 0.61111, 0, 0, 0.525], + "70": [0, 0.61111, 0, 0, 0.525], + "71": [0, 0.61111, 0, 0, 0.525], + "72": [0, 0.61111, 0, 0, 0.525], + "73": [0, 0.61111, 0, 0, 0.525], + "74": [0, 0.61111, 0, 0, 0.525], + "75": [0, 0.61111, 0, 0, 0.525], + "76": [0, 0.61111, 0, 0, 0.525], + "77": [0, 0.61111, 0, 0, 0.525], + "78": [0, 0.61111, 0, 0, 0.525], + "79": [0, 0.61111, 0, 0, 0.525], + "80": [0, 0.61111, 0, 0, 0.525], + "81": [0.13889, 0.61111, 0, 0, 0.525], + "82": [0, 0.61111, 0, 0, 0.525], + "83": [0, 0.61111, 0, 0, 0.525], + "84": [0, 0.61111, 0, 0, 0.525], + "85": [0, 0.61111, 0, 0, 0.525], + "86": [0, 0.61111, 0, 0, 0.525], + "87": [0, 0.61111, 0, 0, 0.525], + "88": [0, 0.61111, 0, 0, 0.525], + "89": [0, 0.61111, 0, 0, 0.525], + "90": [0, 0.61111, 0, 0, 0.525], + "91": [0.08333, 0.69444, 0, 0, 0.525], + "92": [0.08333, 0.69444, 0, 0, 0.525], + "93": [0.08333, 0.69444, 0, 0, 0.525], + "94": [0, 0.61111, 0, 0, 0.525], + "95": [0.09514, 0, 0, 0, 0.525], + "96": [0, 0.61111, 0, 0, 0.525], + "97": [0, 0.43056, 0, 0, 0.525], + "98": [0, 0.61111, 0, 0, 0.525], + "99": [0, 0.43056, 0, 0, 0.525], + "100": [0, 0.61111, 0, 0, 0.525], + "101": [0, 0.43056, 0, 0, 0.525], + "102": [0, 0.61111, 0, 0, 0.525], + "103": [0.22222, 0.43056, 0, 0, 0.525], + "104": [0, 0.61111, 0, 0, 0.525], + "105": [0, 0.61111, 0, 0, 0.525], + "106": [0.22222, 0.61111, 0, 0, 0.525], + "107": [0, 0.61111, 0, 0, 0.525], + "108": [0, 0.61111, 0, 0, 0.525], + "109": [0, 0.43056, 0, 0, 0.525], + "110": [0, 0.43056, 0, 0, 0.525], + "111": [0, 0.43056, 0, 0, 0.525], + "112": [0.22222, 0.43056, 0, 0, 0.525], + "113": [0.22222, 0.43056, 0, 0, 0.525], + "114": [0, 0.43056, 0, 0, 0.525], + "115": [0, 0.43056, 0, 0, 0.525], + "116": [0, 0.55358, 0, 0, 0.525], + "117": [0, 0.43056, 0, 0, 0.525], + "118": [0, 0.43056, 0, 0, 0.525], + "119": [0, 0.43056, 0, 0, 0.525], + "120": [0, 0.43056, 0, 0, 0.525], + "121": [0.22222, 0.43056, 0, 0, 0.525], + "122": [0, 0.43056, 0, 0, 0.525], + "123": [0.08333, 0.69444, 0, 0, 0.525], + "124": [0.08333, 0.69444, 0, 0, 0.525], + "125": [0.08333, 0.69444, 0, 0, 0.525], + "126": [0, 0.61111, 0, 0, 0.525], + "127": [0, 0.61111, 0, 0, 0.525], + "160": [0, 0, 0, 0, 0.525], + "176": [0, 0.61111, 0, 0, 0.525], + "184": [0.19445, 0, 0, 0, 0.525], + "305": [0, 0.43056, 0, 0, 0.525], + "567": [0.22222, 0.43056, 0, 0, 0.525], + "711": [0, 0.56597, 0, 0, 0.525], + "713": [0, 0.56555, 0, 0, 0.525], + "714": [0, 0.61111, 0, 0, 0.525], + "715": [0, 0.61111, 0, 0, 0.525], + "728": [0, 0.61111, 0, 0, 0.525], + "730": [0, 0.61111, 0, 0, 0.525], + "770": [0, 0.61111, 0, 0, 0.525], + "771": [0, 0.61111, 0, 0, 0.525], + "776": [0, 0.61111, 0, 0, 0.525], + "915": [0, 0.61111, 0, 0, 0.525], + "916": [0, 0.61111, 0, 0, 0.525], + "920": [0, 0.61111, 0, 0, 0.525], + "923": [0, 0.61111, 0, 0, 0.525], + "926": [0, 0.61111, 0, 0, 0.525], + "928": [0, 0.61111, 0, 0, 0.525], + "931": [0, 0.61111, 0, 0, 0.525], + "933": [0, 0.61111, 0, 0, 0.525], + "934": [0, 0.61111, 0, 0, 0.525], + "936": [0, 0.61111, 0, 0, 0.525], + "937": [0, 0.61111, 0, 0, 0.525], + "8216": [0, 0.61111, 0, 0, 0.525], + "8217": [0, 0.61111, 0, 0, 0.525], + "8242": [0, 0.61111, 0, 0, 0.525], + "9251": [0.11111, 0.21944, 0, 0, 0.525] + } +}; + +/** + * This file contains metrics regarding fonts and individual symbols. The sigma + * and xi variables, as well as the metricMap map contain data extracted from + * TeX, TeX font metrics, and the TTF files. These data are then exposed via the + * `metrics` variable and the getCharacterMetrics function. + */ +// In TeX, there are actually three sets of dimensions, one for each of +// textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4: +// 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt). These are +// provided in the arrays below, in that order. +// +// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respectively. +// This was determined by running the following script: +// +// latex -interaction=nonstopmode \ +// '\documentclass{article}\usepackage{amsmath}\begin{document}' \ +// '$a$ \expandafter\show\the\textfont2' \ +// '\expandafter\show\the\scriptfont2' \ +// '\expandafter\show\the\scriptscriptfont2' \ +// '\stop' +// +// The metrics themselves were retrieved using the following commands: +// +// tftopl cmsy10 +// tftopl cmsy7 +// tftopl cmsy5 +// +// The output of each of these commands is quite lengthy. The only part we +// care about is the FONTDIMEN section. Each value is measured in EMs. +var sigmasAndXis = { + slant: [0.250, 0.250, 0.250], + // sigma1 + space: [0.000, 0.000, 0.000], + // sigma2 + stretch: [0.000, 0.000, 0.000], + // sigma3 + shrink: [0.000, 0.000, 0.000], + // sigma4 + xHeight: [0.431, 0.431, 0.431], + // sigma5 + quad: [1.000, 1.171, 1.472], + // sigma6 + extraSpace: [0.000, 0.000, 0.000], + // sigma7 + num1: [0.677, 0.732, 0.925], + // sigma8 + num2: [0.394, 0.384, 0.387], + // sigma9 + num3: [0.444, 0.471, 0.504], + // sigma10 + denom1: [0.686, 0.752, 1.025], + // sigma11 + denom2: [0.345, 0.344, 0.532], + // sigma12 + sup1: [0.413, 0.503, 0.504], + // sigma13 + sup2: [0.363, 0.431, 0.404], + // sigma14 + sup3: [0.289, 0.286, 0.294], + // sigma15 + sub1: [0.150, 0.143, 0.200], + // sigma16 + sub2: [0.247, 0.286, 0.400], + // sigma17 + supDrop: [0.386, 0.353, 0.494], + // sigma18 + subDrop: [0.050, 0.071, 0.100], + // sigma19 + delim1: [2.390, 1.700, 1.980], + // sigma20 + delim2: [1.010, 1.157, 1.420], + // sigma21 + axisHeight: [0.250, 0.250, 0.250], + // sigma22 + // These font metrics are extracted from TeX by using tftopl on cmex10.tfm; + // they correspond to the font parameters of the extension fonts (family 3). + // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to + // match cmex7, we'd use cmex7.tfm values for script and scriptscript + // values. + defaultRuleThickness: [0.04, 0.049, 0.049], + // xi8; cmex7: 0.049 + bigOpSpacing1: [0.111, 0.111, 0.111], + // xi9 + bigOpSpacing2: [0.166, 0.166, 0.166], + // xi10 + bigOpSpacing3: [0.2, 0.2, 0.2], + // xi11 + bigOpSpacing4: [0.6, 0.611, 0.611], + // xi12; cmex7: 0.611 + bigOpSpacing5: [0.1, 0.143, 0.143], + // xi13; cmex7: 0.143 + // The \sqrt rule width is taken from the height of the surd character. + // Since we use the same font at all sizes, this thickness doesn't scale. + sqrtRuleThickness: [0.04, 0.04, 0.04], + // This value determines how large a pt is, for metrics which are defined + // in terms of pts. + // This value is also used in katex.scss; if you change it make sure the + // values match. + ptPerEm: [10.0, 10.0, 10.0], + // The space between adjacent `|` columns in an array definition. From + // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm. + doubleRuleSep: [0.2, 0.2, 0.2], + // The width of separator lines in {array} environments. From + // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm. + arrayRuleWidth: [0.04, 0.04, 0.04], + // Two values from LaTeX source2e: + fboxsep: [0.3, 0.3, 0.3], + // 3 pt / ptPerEm + fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm + +}; // This map contains a mapping from font name and character code to character +// should have Latin-1 and Cyrillic characters, but may not depending on the +// operating system. The metrics do not account for extra height from the +// accents. In the case of Cyrillic characters which have both ascenders and +// descenders we prefer approximations with ascenders, primarily to prevent +// the fraction bar or root line from intersecting the glyph. +// TODO(kevinb) allow union of multiple glyph metrics for better accuracy. + +var extraCharacterMap = { + // Latin-1 + 'Å': 'A', + 'Ð': 'D', + 'Þ': 'o', + 'å': 'a', + 'ð': 'd', + 'þ': 'o', + // Cyrillic + 'А': 'A', + 'Б': 'B', + 'В': 'B', + 'Г': 'F', + 'Д': 'A', + 'Е': 'E', + 'Ж': 'K', + 'З': '3', + 'И': 'N', + 'Й': 'N', + 'К': 'K', + 'Л': 'N', + 'М': 'M', + 'Н': 'H', + 'О': 'O', + 'П': 'N', + 'Р': 'P', + 'С': 'C', + 'Т': 'T', + 'У': 'y', + 'Ф': 'O', + 'Х': 'X', + 'Ц': 'U', + 'Ч': 'h', + 'Ш': 'W', + 'Щ': 'W', + 'Ъ': 'B', + 'Ы': 'X', + 'Ь': 'B', + 'Э': '3', + 'Ю': 'X', + 'Я': 'R', + 'а': 'a', + 'б': 'b', + 'в': 'a', + 'г': 'r', + 'д': 'y', + 'е': 'e', + 'ж': 'm', + 'з': 'e', + 'и': 'n', + 'й': 'n', + 'к': 'n', + 'л': 'n', + 'м': 'm', + 'н': 'n', + 'о': 'o', + 'п': 'n', + 'р': 'p', + 'с': 'c', + 'т': 'o', + 'у': 'y', + 'ф': 'b', + 'х': 'x', + 'ц': 'n', + 'ч': 'n', + 'ш': 'w', + 'щ': 'w', + 'ъ': 'a', + 'ы': 'm', + 'ь': 'a', + 'э': 'e', + 'ю': 'm', + 'я': 'r' +}; + +/** + * This function adds new font metrics to default metricMap + * It can also override existing metrics + */ +function setFontMetrics(fontName, metrics) { + fontMetricsData[fontName] = metrics; +} +/** + * This function is a convenience function for looking up information in the + * metricMap table. It takes a character as a string, and a font. + * + * Note: the `width` property may be undefined if fontMetricsData.js wasn't + * built using `Make extended_metrics`. + */ + +function getCharacterMetrics(character, font, mode) { + if (!fontMetricsData[font]) { + throw new Error("Font metrics not found for font: " + font + "."); + } + + var ch = character.charCodeAt(0); + var metrics = fontMetricsData[font][ch]; + + if (!metrics && character[0] in extraCharacterMap) { + ch = extraCharacterMap[character[0]].charCodeAt(0); + metrics = fontMetricsData[font][ch]; + } + + if (!metrics && mode === 'text') { + // We don't typically have font metrics for Asian scripts. + // But since we support them in text mode, we need to return + // some sort of metrics. + // So if the character is in a script we support but we + // don't have metrics for it, just use the metrics for + // the Latin capital letter M. This is close enough because + // we (currently) only care about the height of the glyph + // not its width. + if (supportedCodepoint(ch)) { + metrics = fontMetricsData[font][77]; // 77 is the charcode for 'M' + } + } + + if (metrics) { + return { + depth: metrics[0], + height: metrics[1], + italic: metrics[2], + skew: metrics[3], + width: metrics[4] + }; + } +} +var fontMetricsBySizeIndex = {}; +/** + * Get the font metrics for a given size. + */ + +function getGlobalMetrics(size) { + var sizeIndex; + + if (size >= 5) { + sizeIndex = 0; + } else if (size >= 3) { + sizeIndex = 1; + } else { + sizeIndex = 2; + } + + if (!fontMetricsBySizeIndex[sizeIndex]) { + var metrics = fontMetricsBySizeIndex[sizeIndex] = { + cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18 + }; + + for (var key in sigmasAndXis) { + if (sigmasAndXis.hasOwnProperty(key)) { + metrics[key] = sigmasAndXis[key][sizeIndex]; + } + } + } + + return fontMetricsBySizeIndex[sizeIndex]; +} + +/** + * This file contains information about the options that the Parser carries + * around with it while parsing. Data is held in an `Options` object, and when + * recursing, a new `Options` object can be created with the `.with*` and + * `.reset` functions. + */ +var sizeStyleMap = [// Each element contains [textsize, scriptsize, scriptscriptsize]. +// The size mappings are taken from TeX with \normalsize=10pt. +[1, 1, 1], // size1: [5, 5, 5] \tiny +[2, 1, 1], // size2: [6, 5, 5] +[3, 1, 1], // size3: [7, 5, 5] \scriptsize +[4, 2, 1], // size4: [8, 6, 5] \footnotesize +[5, 2, 1], // size5: [9, 6, 5] \small +[6, 3, 1], // size6: [10, 7, 5] \normalsize +[7, 4, 2], // size7: [12, 8, 6] \large +[8, 6, 3], // size8: [14.4, 10, 7] \Large +[9, 7, 6], // size9: [17.28, 12, 10] \LARGE +[10, 8, 7], // size10: [20.74, 14.4, 12] \huge +[11, 10, 9] // size11: [24.88, 20.74, 17.28] \HUGE +]; +var sizeMultipliers = [// fontMetrics.js:getGlobalMetrics also uses size indexes, so if +// you change size indexes, change that function. +0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488]; + +var sizeAtStyle = function sizeAtStyle(size, style) { + return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1]; +}; // In these types, "" (empty string) means "no change". + + +/** + * This is the main options class. It contains the current style, size, color, + * and font. + * + * Options objects should not be modified. To create a new Options with + * different properties, call a `.having*` method. + */ +class Options { + // A font family applies to a group of fonts (i.e. SansSerif), while a font + // represents a specific font (i.e. SansSerif Bold). + // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm + + /** + * The base size index. + */ + constructor(data) { + this.style = void 0; + this.color = void 0; + this.size = void 0; + this.textSize = void 0; + this.phantom = void 0; + this.font = void 0; + this.fontFamily = void 0; + this.fontWeight = void 0; + this.fontShape = void 0; + this.sizeMultiplier = void 0; + this.maxSize = void 0; + this.minRuleThickness = void 0; + this._fontMetrics = void 0; + this.style = data.style; + this.color = data.color; + this.size = data.size || Options.BASESIZE; + this.textSize = data.textSize || this.size; + this.phantom = !!data.phantom; + this.font = data.font || ""; + this.fontFamily = data.fontFamily || ""; + this.fontWeight = data.fontWeight || ''; + this.fontShape = data.fontShape || ''; + this.sizeMultiplier = sizeMultipliers[this.size - 1]; + this.maxSize = data.maxSize; + this.minRuleThickness = data.minRuleThickness; + this._fontMetrics = undefined; + } + /** + * Returns a new options object with the same properties as "this". Properties + * from "extension" will be copied to the new options object. + */ + + + extend(extension) { + var data = { + style: this.style, + size: this.size, + textSize: this.textSize, + color: this.color, + phantom: this.phantom, + font: this.font, + fontFamily: this.fontFamily, + fontWeight: this.fontWeight, + fontShape: this.fontShape, + maxSize: this.maxSize, + minRuleThickness: this.minRuleThickness + }; + + for (var key in extension) { + if (extension.hasOwnProperty(key)) { + data[key] = extension[key]; + } + } + + return new Options(data); + } + /** + * Return an options object with the given style. If `this.style === style`, + * returns `this`. + */ + + + havingStyle(style) { + if (this.style === style) { + return this; + } else { + return this.extend({ + style: style, + size: sizeAtStyle(this.textSize, style) + }); + } + } + /** + * Return an options object with a cramped version of the current style. If + * the current style is cramped, returns `this`. + */ + + + havingCrampedStyle() { + return this.havingStyle(this.style.cramp()); + } + /** + * Return an options object with the given size and in at least `\textstyle`. + * Returns `this` if appropriate. + */ + + + havingSize(size) { + if (this.size === size && this.textSize === size) { + return this; + } else { + return this.extend({ + style: this.style.text(), + size: size, + textSize: size, + sizeMultiplier: sizeMultipliers[size - 1] + }); + } + } + /** + * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted, + * changes to at least `\textstyle`. + */ + + + havingBaseStyle(style) { + style = style || this.style.text(); + var wantSize = sizeAtStyle(Options.BASESIZE, style); + + if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) { + return this; + } else { + return this.extend({ + style: style, + size: wantSize + }); + } + } + /** + * Remove the effect of sizing changes such as \Huge. + * Keep the effect of the current style, such as \scriptstyle. + */ + + + havingBaseSizing() { + var size; + + switch (this.style.id) { + case 4: + case 5: + size = 3; // normalsize in scriptstyle + + break; + + case 6: + case 7: + size = 1; // normalsize in scriptscriptstyle + + break; + + default: + size = 6; + // normalsize in textstyle or displaystyle + } + + return this.extend({ + style: this.style.text(), + size: size + }); + } + /** + * Create a new options object with the given color. + */ + + + withColor(color) { + return this.extend({ + color: color + }); + } + /** + * Create a new options object with "phantom" set to true. + */ + + + withPhantom() { + return this.extend({ + phantom: true + }); + } + /** + * Creates a new options object with the given math font or old text font. + * @type {[type]} + */ + + + withFont(font) { + return this.extend({ + font + }); + } + /** + * Create a new options objects with the given fontFamily. + */ + + + withTextFontFamily(fontFamily) { + return this.extend({ + fontFamily, + font: "" + }); + } + /** + * Creates a new options object with the given font weight + */ + + + withTextFontWeight(fontWeight) { + return this.extend({ + fontWeight, + font: "" + }); + } + /** + * Creates a new options object with the given font weight + */ + + + withTextFontShape(fontShape) { + return this.extend({ + fontShape, + font: "" + }); + } + /** + * Return the CSS sizing classes required to switch from enclosing options + * `oldOptions` to `this`. Returns an array of classes. + */ + + + sizingClasses(oldOptions) { + if (oldOptions.size !== this.size) { + return ["sizing", "reset-size" + oldOptions.size, "size" + this.size]; + } else { + return []; + } + } + /** + * Return the CSS sizing classes required to switch to the base size. Like + * `this.havingSize(BASESIZE).sizingClasses(this)`. + */ + + + baseSizingClasses() { + if (this.size !== Options.BASESIZE) { + return ["sizing", "reset-size" + this.size, "size" + Options.BASESIZE]; + } else { + return []; + } + } + /** + * Return the font metrics for this size. + */ + + + fontMetrics() { + if (!this._fontMetrics) { + this._fontMetrics = getGlobalMetrics(this.size); + } + + return this._fontMetrics; + } + /** + * Gets the CSS color of the current options object + */ + + + getColor() { + if (this.phantom) { + return "transparent"; + } else { + return this.color; + } + } + +} + +Options.BASESIZE = 6; + +/** + * This file does conversion between units. In particular, it provides + * calculateSize to convert other units into ems. + */ +// Thus, multiplying a length by this number converts the length from units +// into pts. Dividing the result by ptPerEm gives the number of ems +// *assuming* a font size of ptPerEm (normal size, normal style). + +var ptPerUnit = { + // https://en.wikibooks.org/wiki/LaTeX/Lengths and + // https://tex.stackexchange.com/a/8263 + "pt": 1, + // TeX point + "mm": 7227 / 2540, + // millimeter + "cm": 7227 / 254, + // centimeter + "in": 72.27, + // inch + "bp": 803 / 800, + // big (PostScript) points + "pc": 12, + // pica + "dd": 1238 / 1157, + // didot + "cc": 14856 / 1157, + // cicero (12 didot) + "nd": 685 / 642, + // new didot + "nc": 1370 / 107, + // new cicero (12 new didot) + "sp": 1 / 65536, + // scaled point (TeX's internal smallest unit) + // https://tex.stackexchange.com/a/41371 + "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX + +}; // Dictionary of relative units, for fast validity testing. + +var relativeUnit = { + "ex": true, + "em": true, + "mu": true +}; + +/** + * Determine whether the specified unit (either a string defining the unit + * or a "size" parse node containing a unit field) is valid. + */ +var validUnit = function validUnit(unit) { + if (typeof unit !== "string") { + unit = unit.unit; + } + + return unit in ptPerUnit || unit in relativeUnit || unit === "ex"; +}; +/* + * Convert a "size" parse node (with numeric "number" and string "unit" fields, + * as parsed by functions.js argType "size") into a CSS em value for the + * current style/scale. `options` gives the current options. + */ + +var calculateSize = function calculateSize(sizeValue, options) { + var scale; + + if (sizeValue.unit in ptPerUnit) { + // Absolute units + scale = ptPerUnit[sizeValue.unit] // Convert unit to pt + / options.fontMetrics().ptPerEm // Convert pt to CSS em + / options.sizeMultiplier; // Unscale to make absolute units + } else if (sizeValue.unit === "mu") { + // `mu` units scale with scriptstyle/scriptscriptstyle. + scale = options.fontMetrics().cssEmPerMu; + } else { + // Other relative units always refer to the *textstyle* font + // in the current size. + var unitOptions; + + if (options.style.isTight()) { + // isTight() means current style is script/scriptscript. + unitOptions = options.havingStyle(options.style.text()); + } else { + unitOptions = options; + } // TODO: In TeX these units are relative to the quad of the current + // *text* font, e.g. cmr10. KaTeX instead uses values from the + // comparably-sized *Computer Modern symbol* font. At 10pt, these + // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641; + // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$. + // TeX \showlists shows a kern of 1.13889 * fontsize; + // KaTeX shows a kern of 1.171 * fontsize. + + + if (sizeValue.unit === "ex") { + scale = unitOptions.fontMetrics().xHeight; + } else if (sizeValue.unit === "em") { + scale = unitOptions.fontMetrics().quad; + } else { + throw new ParseError("Invalid unit: '" + sizeValue.unit + "'"); + } + + if (unitOptions !== options) { + scale *= unitOptions.sizeMultiplier / options.sizeMultiplier; + } + } + + return Math.min(sizeValue.number * scale, options.maxSize); +}; +/** + * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. See + * https://github.com/KaTeX/KaTeX/pull/2460. + */ + +var makeEm = function makeEm(n) { + return +n.toFixed(4) + "em"; +}; + +/** + * These objects store the data about the DOM nodes we create, as well as some + * extra data. They can then be transformed into real DOM nodes with the + * `toNode` function or HTML markup using `toMarkup`. They are useful for both + * storing extra properties on the nodes, as well as providing a way to easily + * work with the DOM. + * + * Similar functions for working with MathML nodes exist in mathMLTree.js. + * + * TODO: refactor `span` and `anchor` into common superclass when + * target environments support class inheritance + */ + +/** + * Create an HTML className based on a list of classes. In addition to joining + * with spaces, we also remove empty classes. + */ +var createClass = function createClass(classes) { + return classes.filter(cls => cls).join(" "); +}; + +var initNode = function initNode(classes, options, style) { + this.classes = classes || []; + this.attributes = {}; + this.height = 0; + this.depth = 0; + this.maxFontSize = 0; + this.style = style || {}; + + if (options) { + if (options.style.isTight()) { + this.classes.push("mtight"); + } + + var color = options.getColor(); + + if (color) { + this.style.color = color; + } + } +}; +/** + * Convert into an HTML node + */ + + +var toNode = function toNode(tagName) { + var node = document.createElement(tagName); // Apply the class + + node.className = createClass(this.classes); // Apply inline styles + + for (var style in this.style) { + if (this.style.hasOwnProperty(style)) { + // $FlowFixMe Flow doesn't seem to understand span.style's type. + node.style[style] = this.style[style]; + } + } // Apply attributes + + + for (var attr in this.attributes) { + if (this.attributes.hasOwnProperty(attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } // Append the children, also as HTML nodes + + + for (var i = 0; i < this.children.length; i++) { + node.appendChild(this.children[i].toNode()); + } + + return node; +}; +/** + * https://w3c.github.io/html-reference/syntax.html#syntax-attributes + * + * > Attribute Names must consist of one or more characters + * other than the space characters, U+0000 NULL, + * '"', "'", ">", "/", "=", the control characters, + * and any characters that are not defined by Unicode. + */ + + +var invalidAttributeNameRegex = /[\s"'>/=\x00-\x1f]/; +/** + * Convert into an HTML markup string + */ + +var toMarkup = function toMarkup(tagName) { + var markup = "<" + tagName; // Add the class + + if (this.classes.length) { + markup += " class=\"" + utils.escape(createClass(this.classes)) + "\""; + } + + var styles = ""; // Add the styles, after hyphenation + + for (var style in this.style) { + if (this.style.hasOwnProperty(style)) { + styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; + } + } + + if (styles) { + markup += " style=\"" + utils.escape(styles) + "\""; + } // Add the attributes + + + for (var attr in this.attributes) { + if (this.attributes.hasOwnProperty(attr)) { + if (invalidAttributeNameRegex.test(attr)) { + throw new ParseError("Invalid attribute name '" + attr + "'"); + } + + markup += " " + attr + "=\"" + utils.escape(this.attributes[attr]) + "\""; + } + } + + markup += ">"; // Add the markup of the children, also as markup + + for (var i = 0; i < this.children.length; i++) { + markup += this.children[i].toMarkup(); + } + + markup += ""; + return markup; +}; // Making the type below exact with all optional fields doesn't work due to +// - https://github.com/facebook/flow/issues/4582 +// - https://github.com/facebook/flow/issues/5688 +// However, since *all* fields are optional, $Shape<> works as suggested in 5688 +// above. +// This type does not include all CSS properties. Additional properties should +// be added as needed. + + +/** + * This node represents a span node, with a className, a list of children, and + * an inline style. It also contains information about its height, depth, and + * maxFontSize. + * + * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan + * otherwise. This typesafety is important when HTML builders access a span's + * children. + */ +class Span { + constructor(classes, children, options, style) { + this.children = void 0; + this.attributes = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.width = void 0; + this.maxFontSize = void 0; + this.style = void 0; + initNode.call(this, classes, options, style); + this.children = children || []; + } + /** + * Sets an arbitrary attribute on the span. Warning: use this wisely. Not + * all browsers support attributes the same, and having too many custom + * attributes is probably bad. + */ + + + setAttribute(attribute, value) { + this.attributes[attribute] = value; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + + toNode() { + return toNode.call(this, "span"); + } + + toMarkup() { + return toMarkup.call(this, "span"); + } + +} +/** + * This node represents an anchor () element with a hyperlink. See `span` + * for further details. + */ + +class Anchor { + constructor(href, classes, children, options) { + this.children = void 0; + this.attributes = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.maxFontSize = void 0; + this.style = void 0; + initNode.call(this, classes, options); + this.children = children || []; + this.setAttribute('href', href); + } + + setAttribute(attribute, value) { + this.attributes[attribute] = value; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + + toNode() { + return toNode.call(this, "a"); + } + + toMarkup() { + return toMarkup.call(this, "a"); + } + +} +/** + * This node represents an image embed () element. + */ + +class Img { + constructor(src, alt, style) { + this.src = void 0; + this.alt = void 0; + this.classes = void 0; + this.height = void 0; + this.depth = void 0; + this.maxFontSize = void 0; + this.style = void 0; + this.alt = alt; + this.src = src; + this.classes = ["mord"]; + this.style = style; + } + + hasClass(className) { + return utils.contains(this.classes, className); + } + + toNode() { + var node = document.createElement("img"); + node.src = this.src; + node.alt = this.alt; + node.className = "mord"; // Apply inline styles + + for (var style in this.style) { + if (this.style.hasOwnProperty(style)) { + // $FlowFixMe + node.style[style] = this.style[style]; + } + } + + return node; + } + + toMarkup() { + var markup = "\"" 0) { + span = document.createElement("span"); + span.style.marginRight = makeEm(this.italic); + } + + if (this.classes.length > 0) { + span = span || document.createElement("span"); + span.className = createClass(this.classes); + } + + for (var style in this.style) { + if (this.style.hasOwnProperty(style)) { + span = span || document.createElement("span"); // $FlowFixMe Flow doesn't seem to understand span.style's type. + + span.style[style] = this.style[style]; + } + } + + if (span) { + span.appendChild(node); + return span; + } else { + return node; + } + } + /** + * Creates markup for a symbol node. + */ + + + toMarkup() { + // TODO(alpert): More duplication than I'd like from + // span.prototype.toMarkup and symbolNode.prototype.toNode... + var needsSpan = false; + var markup = " 0) { + styles += "margin-right:" + this.italic + "em;"; + } + + for (var style in this.style) { + if (this.style.hasOwnProperty(style)) { + styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; + } + } + + if (styles) { + needsSpan = true; + markup += " style=\"" + utils.escape(styles) + "\""; + } + + var escaped = utils.escape(this.text); + + if (needsSpan) { + markup += ">"; + markup += escaped; + markup += ""; + return markup; + } else { + return escaped; + } + } + +} +/** + * SVG nodes are used to render stretchy wide elements. + */ + +class SvgNode { + constructor(children, attributes) { + this.children = void 0; + this.attributes = void 0; + this.children = children || []; + this.attributes = attributes || {}; + } + + toNode() { + var svgNS = "http://www.w3.org/2000/svg"; + var node = document.createElementNS(svgNS, "svg"); // Apply attributes + + for (var attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } + + for (var i = 0; i < this.children.length; i++) { + node.appendChild(this.children[i].toNode()); + } + + return node; + } + + toMarkup() { + var markup = ""; + } else { + return ""; + } + } + +} +class LineNode { + constructor(attributes) { + this.attributes = void 0; + this.attributes = attributes || {}; + } + + toNode() { + var svgNS = "http://www.w3.org/2000/svg"; + var node = document.createElementNS(svgNS, "line"); // Apply attributes + + for (var attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } + + return node; + } + + toMarkup() { + var markup = " but got " + String(group) + "."); + } +} + +/** + * This file holds a list of all no-argument functions and single-character + * symbols (like 'a' or ';'). + * + * For each of the symbols, there are three properties they can have: + * - font (required): the font to be used for this symbol. Either "main" (the + normal font), or "ams" (the ams fonts). + * - group (required): the ParseNode group type the symbol should have (i.e. + "textord", "mathord", etc). + See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types + * - replace: the character that this symbol or function should be + * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi + * character in the main font). + * + * The outermost map in the table indicates what mode the symbols should be + * accepted in (e.g. "math" or "text"). + */ +// Some of these have a "-token" suffix since these are also used as `ParseNode` +// types for raw text tokens, and we want to avoid conflicts with higher-level +// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by +// looking up the `symbols` map. +var ATOMS = { + "bin": 1, + "close": 1, + "inner": 1, + "open": 1, + "punct": 1, + "rel": 1 +}; +var NON_ATOMS = { + "accent-token": 1, + "mathord": 1, + "op-token": 1, + "spacing": 1, + "textord": 1 +}; +var symbols = { + "math": {}, + "text": {} +}; +/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ + +function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) { + symbols[mode][name] = { + font, + group, + replace + }; + + if (acceptUnicodeChar && replace) { + symbols[mode][replace] = symbols[mode][name]; + } +} // Some abbreviations for commonly used strings. +// This helps minify the code, and also spotting typos using jshint. +// modes: + +var math = "math"; +var text = "text"; // fonts: + +var main = "main"; +var ams = "ams"; // groups: + +var accent = "accent-token"; +var bin = "bin"; +var close = "close"; +var inner = "inner"; +var mathord = "mathord"; +var op = "op-token"; +var open = "open"; +var punct = "punct"; +var rel = "rel"; +var spacing = "spacing"; +var textord = "textord"; // Now comes the symbol table +// Relation Symbols + +defineSymbol(math, main, rel, "\u2261", "\\equiv", true); +defineSymbol(math, main, rel, "\u227a", "\\prec", true); +defineSymbol(math, main, rel, "\u227b", "\\succ", true); +defineSymbol(math, main, rel, "\u223c", "\\sim", true); +defineSymbol(math, main, rel, "\u22a5", "\\perp"); +defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true); +defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true); +defineSymbol(math, main, rel, "\u2243", "\\simeq", true); +defineSymbol(math, main, rel, "\u2223", "\\mid", true); +defineSymbol(math, main, rel, "\u226a", "\\ll", true); +defineSymbol(math, main, rel, "\u226b", "\\gg", true); +defineSymbol(math, main, rel, "\u224d", "\\asymp", true); +defineSymbol(math, main, rel, "\u2225", "\\parallel"); +defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true); +defineSymbol(math, main, rel, "\u2323", "\\smile", true); +defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true); +defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true); +defineSymbol(math, main, rel, "\u2250", "\\doteq", true); +defineSymbol(math, main, rel, "\u2322", "\\frown", true); +defineSymbol(math, main, rel, "\u220b", "\\ni", true); +defineSymbol(math, main, rel, "\u221d", "\\propto", true); +defineSymbol(math, main, rel, "\u22a2", "\\vdash", true); +defineSymbol(math, main, rel, "\u22a3", "\\dashv", true); +defineSymbol(math, main, rel, "\u220b", "\\owns"); // Punctuation + +defineSymbol(math, main, punct, "\u002e", "\\ldotp"); +defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); // Misc Symbols + +defineSymbol(math, main, textord, "\u0023", "\\#"); +defineSymbol(text, main, textord, "\u0023", "\\#"); +defineSymbol(math, main, textord, "\u0026", "\\&"); +defineSymbol(text, main, textord, "\u0026", "\\&"); +defineSymbol(math, main, textord, "\u2135", "\\aleph", true); +defineSymbol(math, main, textord, "\u2200", "\\forall", true); +defineSymbol(math, main, textord, "\u210f", "\\hbar", true); +defineSymbol(math, main, textord, "\u2203", "\\exists", true); +defineSymbol(math, main, textord, "\u2207", "\\nabla", true); +defineSymbol(math, main, textord, "\u266d", "\\flat", true); +defineSymbol(math, main, textord, "\u2113", "\\ell", true); +defineSymbol(math, main, textord, "\u266e", "\\natural", true); +defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true); +defineSymbol(math, main, textord, "\u2118", "\\wp", true); +defineSymbol(math, main, textord, "\u266f", "\\sharp", true); +defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true); +defineSymbol(math, main, textord, "\u211c", "\\Re", true); +defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true); +defineSymbol(math, main, textord, "\u2111", "\\Im", true); +defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true); +defineSymbol(math, main, textord, "\u00a7", "\\S", true); +defineSymbol(text, main, textord, "\u00a7", "\\S"); +defineSymbol(math, main, textord, "\u00b6", "\\P", true); +defineSymbol(text, main, textord, "\u00b6", "\\P"); // Math and Text + +defineSymbol(math, main, textord, "\u2020", "\\dag"); +defineSymbol(text, main, textord, "\u2020", "\\dag"); +defineSymbol(text, main, textord, "\u2020", "\\textdagger"); +defineSymbol(math, main, textord, "\u2021", "\\ddag"); +defineSymbol(text, main, textord, "\u2021", "\\ddag"); +defineSymbol(text, main, textord, "\u2021", "\\textdaggerdbl"); // Large Delimiters + +defineSymbol(math, main, close, "\u23b1", "\\rmoustache", true); +defineSymbol(math, main, open, "\u23b0", "\\lmoustache", true); +defineSymbol(math, main, close, "\u27ef", "\\rgroup", true); +defineSymbol(math, main, open, "\u27ee", "\\lgroup", true); // Binary Operators + +defineSymbol(math, main, bin, "\u2213", "\\mp", true); +defineSymbol(math, main, bin, "\u2296", "\\ominus", true); +defineSymbol(math, main, bin, "\u228e", "\\uplus", true); +defineSymbol(math, main, bin, "\u2293", "\\sqcap", true); +defineSymbol(math, main, bin, "\u2217", "\\ast"); +defineSymbol(math, main, bin, "\u2294", "\\sqcup", true); +defineSymbol(math, main, bin, "\u25ef", "\\bigcirc", true); +defineSymbol(math, main, bin, "\u2219", "\\bullet", true); +defineSymbol(math, main, bin, "\u2021", "\\ddagger"); +defineSymbol(math, main, bin, "\u2240", "\\wr", true); +defineSymbol(math, main, bin, "\u2a3f", "\\amalg"); +defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath +// Arrow Symbols + +defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true); +defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true); +defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true); +defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true); +defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true); +defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true); +defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true); +defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true); +defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true); +defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true); +defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true); +defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true); +defineSymbol(math, main, rel, "\u2197", "\\nearrow", true); +defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true); +defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true); +defineSymbol(math, main, rel, "\u2198", "\\searrow", true); +defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true); +defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true); +defineSymbol(math, main, rel, "\u2199", "\\swarrow", true); +defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true); +defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true); +defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true); +defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true); // AMS Negated Binary Relations + +defineSymbol(math, ams, rel, "\u226e", "\\nless", true); // Symbol names preceded by "@" each have a corresponding macro. + +defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant"); +defineSymbol(math, ams, rel, "\ue011", "\\@nleqq"); +defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true); +defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true); +defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq"); +defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true); +defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true); +defineSymbol(math, ams, rel, "\u2280", "\\nprec", true); // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true); +defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true); +defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true); +defineSymbol(math, ams, rel, "\u2241", "\\nsim", true); +defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid"); +defineSymbol(math, ams, rel, "\u2224", "\\nmid", true); +defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true); +defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true); +defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft"); +defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true); +defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true); +defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq"); +defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true); +defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq"); +defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true); +defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant"); +defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq"); +defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true); +defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true); +defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq"); +defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true); +defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true); +defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true); // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true); +defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true); +defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true); // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u2246", "\\ncong", true); +defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel"); +defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true); +defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true); +defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright"); +defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true); +defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq"); +defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true); +defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq"); +defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true); +defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq"); +defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true); +defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true); +defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true); +defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq"); +defineSymbol(math, ams, bin, "\u22b4", "\\unlhd"); +defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); // AMS Negated Arrows + +defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true); +defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true); +defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true); +defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true); +defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true); +defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true); // AMS Misc + +defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle"); +defineSymbol(math, ams, textord, "\u210f", "\\hslash"); +defineSymbol(math, ams, textord, "\u25bd", "\\triangledown"); +defineSymbol(math, ams, textord, "\u25ca", "\\lozenge"); +defineSymbol(math, ams, textord, "\u24c8", "\\circledS"); +defineSymbol(math, ams, textord, "\u00ae", "\\circledR"); +defineSymbol(text, ams, textord, "\u00ae", "\\circledR"); +defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true); +defineSymbol(math, ams, textord, "\u2204", "\\nexists"); +defineSymbol(math, ams, textord, "\u2127", "\\mho"); +defineSymbol(math, ams, textord, "\u2132", "\\Finv", true); +defineSymbol(math, ams, textord, "\u2141", "\\Game", true); +defineSymbol(math, ams, textord, "\u2035", "\\backprime"); +defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle"); +defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown"); +defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare"); +defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge"); +defineSymbol(math, ams, textord, "\u2605", "\\bigstar"); +defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true); +defineSymbol(math, ams, textord, "\u2201", "\\complement", true); // unicode-math maps U+F0 to \matheth. We map to AMS function \eth + +defineSymbol(math, ams, textord, "\u00f0", "\\eth", true); +defineSymbol(text, main, textord, "\u00f0", "\u00f0"); +defineSymbol(math, ams, textord, "\u2571", "\\diagup"); +defineSymbol(math, ams, textord, "\u2572", "\\diagdown"); +defineSymbol(math, ams, textord, "\u25a1", "\\square"); +defineSymbol(math, ams, textord, "\u25a1", "\\Box"); +defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen + +defineSymbol(math, ams, textord, "\u00a5", "\\yen", true); +defineSymbol(text, ams, textord, "\u00a5", "\\yen", true); +defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true); +defineSymbol(text, ams, textord, "\u2713", "\\checkmark"); // AMS Hebrew + +defineSymbol(math, ams, textord, "\u2136", "\\beth", true); +defineSymbol(math, ams, textord, "\u2138", "\\daleth", true); +defineSymbol(math, ams, textord, "\u2137", "\\gimel", true); // AMS Greek + +defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true); +defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); // AMS Delimiters + +defineSymbol(math, ams, open, "\u250c", "\\@ulcorner", true); +defineSymbol(math, ams, close, "\u2510", "\\@urcorner", true); +defineSymbol(math, ams, open, "\u2514", "\\@llcorner", true); +defineSymbol(math, ams, close, "\u2518", "\\@lrcorner", true); // AMS Binary Relations + +defineSymbol(math, ams, rel, "\u2266", "\\leqq", true); +defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true); +defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true); +defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true); +defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true); +defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true); +defineSymbol(math, ams, bin, "\u22d6", "\\lessdot"); +defineSymbol(math, ams, rel, "\u22d8", "\\lll", true); +defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true); +defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true); +defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true); +defineSymbol(math, ams, rel, "\u2251", "\\doteqdot"); +defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true); +defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true); +defineSymbol(math, ams, rel, "\u223d", "\\backsim", true); +defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true); +defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true); +defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true); +defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true); +defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true); +defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true); +defineSymbol(math, ams, rel, "\u227e", "\\precsim", true); +defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true); +defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft"); +defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq"); +defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true); +defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true); +defineSymbol(math, ams, rel, "\u2323", "\\smallsmile"); +defineSymbol(math, ams, rel, "\u2322", "\\smallfrown"); +defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true); +defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true); +defineSymbol(math, ams, rel, "\u2267", "\\geqq", true); +defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true); +defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true); +defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true); +defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true); +defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot"); +defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true); +defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true); +defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true); +defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true); +defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true); +defineSymbol(math, ams, rel, "\u2257", "\\circeq", true); +defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true); +defineSymbol(math, ams, rel, "\u223c", "\\thicksim"); +defineSymbol(math, ams, rel, "\u2248", "\\thickapprox"); +defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true); +defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true); +defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true); +defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true); +defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true); +defineSymbol(math, ams, rel, "\u227f", "\\succsim", true); +defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true); +defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright"); +defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq"); +defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true); +defineSymbol(math, ams, rel, "\u2223", "\\shortmid"); +defineSymbol(math, ams, rel, "\u2225", "\\shortparallel"); +defineSymbol(math, ams, rel, "\u226c", "\\between", true); +defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true); +defineSymbol(math, ams, rel, "\u221d", "\\varpropto"); +defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); // unicode-math says that \therefore is a mathord atom. +// We kept the amssymb atom type, which is rel. + +defineSymbol(math, ams, rel, "\u2234", "\\therefore", true); +defineSymbol(math, ams, rel, "\u220d", "\\backepsilon"); +defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); // unicode-math says that \because is a mathord atom. +// We kept the amssymb atom type, which is rel. + +defineSymbol(math, ams, rel, "\u2235", "\\because", true); +defineSymbol(math, ams, rel, "\u22d8", "\\llless"); +defineSymbol(math, ams, rel, "\u22d9", "\\gggtr"); +defineSymbol(math, ams, bin, "\u22b2", "\\lhd"); +defineSymbol(math, ams, bin, "\u22b3", "\\rhd"); +defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true); +defineSymbol(math, main, rel, "\u22c8", "\\Join"); +defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true); // AMS Binary Operators + +defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true); +defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus"); +defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true); +defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true); +defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true); +defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true); +defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true); +defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true); +defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true); +defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true); +defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true); +defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true); +defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true); +defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true); +defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true); +defineSymbol(math, ams, bin, "\u229b", "\\circledast", true); +defineSymbol(math, ams, bin, "\u22c5", "\\centerdot"); +defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true); +defineSymbol(math, ams, bin, "\u22d2", "\\doublecap"); +defineSymbol(math, ams, bin, "\u22d3", "\\doublecup"); +defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true); // AMS Arrows +// Note: unicode-math maps \u21e2 to their own function \rightdasharrow. +// We'll map it to AMS function \dashrightarrow. It produces the same atom. + +defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true); // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true); +defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true); +defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true); +defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true); +defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true); +defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true); +defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true); +defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true); +defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true); // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true); +defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true); +defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true); +defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true); +defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true); +defineSymbol(math, main, rel, "\u22b6", "\\origof", true); // not in font + +defineSymbol(math, main, rel, "\u22b7", "\\imageof", true); // not in font + +defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true); +defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true); +defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true); +defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true); +defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true); +defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true); +defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true); +defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true); // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. + +defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true); +defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true); +defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true); +defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true); +defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true); +defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true); +defineSymbol(math, ams, rel, "\u21dd", "\\leadsto"); +defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true); +defineSymbol(math, ams, rel, "\u21be", "\\restriction"); +defineSymbol(math, main, textord, "\u2018", "`"); +defineSymbol(math, main, textord, "$", "\\$"); +defineSymbol(text, main, textord, "$", "\\$"); +defineSymbol(text, main, textord, "$", "\\textdollar"); +defineSymbol(math, main, textord, "%", "\\%"); +defineSymbol(text, main, textord, "%", "\\%"); +defineSymbol(math, main, textord, "_", "\\_"); +defineSymbol(text, main, textord, "_", "\\_"); +defineSymbol(text, main, textord, "_", "\\textunderscore"); +defineSymbol(math, main, textord, "\u2220", "\\angle", true); +defineSymbol(math, main, textord, "\u221e", "\\infty", true); +defineSymbol(math, main, textord, "\u2032", "\\prime"); +defineSymbol(math, main, textord, "\u25b3", "\\triangle"); +defineSymbol(math, main, textord, "\u0393", "\\Gamma", true); +defineSymbol(math, main, textord, "\u0394", "\\Delta", true); +defineSymbol(math, main, textord, "\u0398", "\\Theta", true); +defineSymbol(math, main, textord, "\u039b", "\\Lambda", true); +defineSymbol(math, main, textord, "\u039e", "\\Xi", true); +defineSymbol(math, main, textord, "\u03a0", "\\Pi", true); +defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true); +defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true); +defineSymbol(math, main, textord, "\u03a6", "\\Phi", true); +defineSymbol(math, main, textord, "\u03a8", "\\Psi", true); +defineSymbol(math, main, textord, "\u03a9", "\\Omega", true); +defineSymbol(math, main, textord, "A", "\u0391"); +defineSymbol(math, main, textord, "B", "\u0392"); +defineSymbol(math, main, textord, "E", "\u0395"); +defineSymbol(math, main, textord, "Z", "\u0396"); +defineSymbol(math, main, textord, "H", "\u0397"); +defineSymbol(math, main, textord, "I", "\u0399"); +defineSymbol(math, main, textord, "K", "\u039A"); +defineSymbol(math, main, textord, "M", "\u039C"); +defineSymbol(math, main, textord, "N", "\u039D"); +defineSymbol(math, main, textord, "O", "\u039F"); +defineSymbol(math, main, textord, "P", "\u03A1"); +defineSymbol(math, main, textord, "T", "\u03A4"); +defineSymbol(math, main, textord, "X", "\u03A7"); +defineSymbol(math, main, textord, "\u00ac", "\\neg", true); +defineSymbol(math, main, textord, "\u00ac", "\\lnot"); +defineSymbol(math, main, textord, "\u22a4", "\\top"); +defineSymbol(math, main, textord, "\u22a5", "\\bot"); +defineSymbol(math, main, textord, "\u2205", "\\emptyset"); +defineSymbol(math, ams, textord, "\u2205", "\\varnothing"); +defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true); +defineSymbol(math, main, mathord, "\u03b2", "\\beta", true); +defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true); +defineSymbol(math, main, mathord, "\u03b4", "\\delta", true); +defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true); +defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true); +defineSymbol(math, main, mathord, "\u03b7", "\\eta", true); +defineSymbol(math, main, mathord, "\u03b8", "\\theta", true); +defineSymbol(math, main, mathord, "\u03b9", "\\iota", true); +defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true); +defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true); +defineSymbol(math, main, mathord, "\u03bc", "\\mu", true); +defineSymbol(math, main, mathord, "\u03bd", "\\nu", true); +defineSymbol(math, main, mathord, "\u03be", "\\xi", true); +defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true); +defineSymbol(math, main, mathord, "\u03c0", "\\pi", true); +defineSymbol(math, main, mathord, "\u03c1", "\\rho", true); +defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true); +defineSymbol(math, main, mathord, "\u03c4", "\\tau", true); +defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true); +defineSymbol(math, main, mathord, "\u03d5", "\\phi", true); +defineSymbol(math, main, mathord, "\u03c7", "\\chi", true); +defineSymbol(math, main, mathord, "\u03c8", "\\psi", true); +defineSymbol(math, main, mathord, "\u03c9", "\\omega", true); +defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true); +defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true); +defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true); +defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true); +defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true); +defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true); +defineSymbol(math, main, bin, "\u2217", "*", true); +defineSymbol(math, main, bin, "+", "+"); +defineSymbol(math, main, bin, "\u2212", "-", true); +defineSymbol(math, main, bin, "\u22c5", "\\cdot", true); +defineSymbol(math, main, bin, "\u2218", "\\circ", true); +defineSymbol(math, main, bin, "\u00f7", "\\div", true); +defineSymbol(math, main, bin, "\u00b1", "\\pm", true); +defineSymbol(math, main, bin, "\u00d7", "\\times", true); +defineSymbol(math, main, bin, "\u2229", "\\cap", true); +defineSymbol(math, main, bin, "\u222a", "\\cup", true); +defineSymbol(math, main, bin, "\u2216", "\\setminus", true); +defineSymbol(math, main, bin, "\u2227", "\\land"); +defineSymbol(math, main, bin, "\u2228", "\\lor"); +defineSymbol(math, main, bin, "\u2227", "\\wedge", true); +defineSymbol(math, main, bin, "\u2228", "\\vee", true); +defineSymbol(math, main, textord, "\u221a", "\\surd"); +defineSymbol(math, main, open, "\u27e8", "\\langle", true); +defineSymbol(math, main, open, "\u2223", "\\lvert"); +defineSymbol(math, main, open, "\u2225", "\\lVert"); +defineSymbol(math, main, close, "?", "?"); +defineSymbol(math, main, close, "!", "!"); +defineSymbol(math, main, close, "\u27e9", "\\rangle", true); +defineSymbol(math, main, close, "\u2223", "\\rvert"); +defineSymbol(math, main, close, "\u2225", "\\rVert"); +defineSymbol(math, main, rel, "=", "="); +defineSymbol(math, main, rel, ":", ":"); +defineSymbol(math, main, rel, "\u2248", "\\approx", true); +defineSymbol(math, main, rel, "\u2245", "\\cong", true); +defineSymbol(math, main, rel, "\u2265", "\\ge"); +defineSymbol(math, main, rel, "\u2265", "\\geq", true); +defineSymbol(math, main, rel, "\u2190", "\\gets"); +defineSymbol(math, main, rel, ">", "\\gt", true); +defineSymbol(math, main, rel, "\u2208", "\\in", true); +defineSymbol(math, main, rel, "\ue020", "\\@not"); +defineSymbol(math, main, rel, "\u2282", "\\subset", true); +defineSymbol(math, main, rel, "\u2283", "\\supset", true); +defineSymbol(math, main, rel, "\u2286", "\\subseteq", true); +defineSymbol(math, main, rel, "\u2287", "\\supseteq", true); +defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true); +defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true); +defineSymbol(math, main, rel, "\u22a8", "\\models"); +defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true); +defineSymbol(math, main, rel, "\u2264", "\\le"); +defineSymbol(math, main, rel, "\u2264", "\\leq", true); +defineSymbol(math, main, rel, "<", "\\lt", true); +defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true); +defineSymbol(math, main, rel, "\u2192", "\\to"); +defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true); +defineSymbol(math, ams, rel, "\u2270", "\\nleq", true); +defineSymbol(math, main, spacing, "\u00a0", "\\ "); +defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% + +defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace"); +defineSymbol(text, main, spacing, "\u00a0", "\\ "); +defineSymbol(text, main, spacing, "\u00a0", " "); +defineSymbol(text, main, spacing, "\u00a0", "\\space"); +defineSymbol(text, main, spacing, "\u00a0", "\\nobreakspace"); +defineSymbol(math, main, spacing, null, "\\nobreak"); +defineSymbol(math, main, spacing, null, "\\allowbreak"); +defineSymbol(math, main, punct, ",", ","); +defineSymbol(math, main, punct, ";", ";"); +defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true); +defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true); +defineSymbol(math, main, bin, "\u2299", "\\odot", true); +defineSymbol(math, main, bin, "\u2295", "\\oplus", true); +defineSymbol(math, main, bin, "\u2297", "\\otimes", true); +defineSymbol(math, main, textord, "\u2202", "\\partial", true); +defineSymbol(math, main, bin, "\u2298", "\\oslash", true); +defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true); +defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true); +defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup"); +defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown"); +defineSymbol(math, main, bin, "\u2020", "\\dagger"); +defineSymbol(math, main, bin, "\u22c4", "\\diamond"); +defineSymbol(math, main, bin, "\u22c6", "\\star"); +defineSymbol(math, main, bin, "\u25c3", "\\triangleleft"); +defineSymbol(math, main, bin, "\u25b9", "\\triangleright"); +defineSymbol(math, main, open, "{", "\\{"); +defineSymbol(text, main, textord, "{", "\\{"); +defineSymbol(text, main, textord, "{", "\\textbraceleft"); +defineSymbol(math, main, close, "}", "\\}"); +defineSymbol(text, main, textord, "}", "\\}"); +defineSymbol(text, main, textord, "}", "\\textbraceright"); +defineSymbol(math, main, open, "{", "\\lbrace"); +defineSymbol(math, main, close, "}", "\\rbrace"); +defineSymbol(math, main, open, "[", "\\lbrack", true); +defineSymbol(text, main, textord, "[", "\\lbrack", true); +defineSymbol(math, main, close, "]", "\\rbrack", true); +defineSymbol(text, main, textord, "]", "\\rbrack", true); +defineSymbol(math, main, open, "(", "\\lparen", true); +defineSymbol(math, main, close, ")", "\\rparen", true); +defineSymbol(text, main, textord, "<", "\\textless", true); // in T1 fontenc + +defineSymbol(text, main, textord, ">", "\\textgreater", true); // in T1 fontenc + +defineSymbol(math, main, open, "\u230a", "\\lfloor", true); +defineSymbol(math, main, close, "\u230b", "\\rfloor", true); +defineSymbol(math, main, open, "\u2308", "\\lceil", true); +defineSymbol(math, main, close, "\u2309", "\\rceil", true); +defineSymbol(math, main, textord, "\\", "\\backslash"); +defineSymbol(math, main, textord, "\u2223", "|"); +defineSymbol(math, main, textord, "\u2223", "\\vert"); +defineSymbol(text, main, textord, "|", "\\textbar", true); // in T1 fontenc + +defineSymbol(math, main, textord, "\u2225", "\\|"); +defineSymbol(math, main, textord, "\u2225", "\\Vert"); +defineSymbol(text, main, textord, "\u2225", "\\textbardbl"); +defineSymbol(text, main, textord, "~", "\\textasciitilde"); +defineSymbol(text, main, textord, "\\", "\\textbackslash"); +defineSymbol(text, main, textord, "^", "\\textasciicircum"); +defineSymbol(math, main, rel, "\u2191", "\\uparrow", true); +defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true); +defineSymbol(math, main, rel, "\u2193", "\\downarrow", true); +defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true); +defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true); +defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true); +defineSymbol(math, main, op, "\u2210", "\\coprod"); +defineSymbol(math, main, op, "\u22c1", "\\bigvee"); +defineSymbol(math, main, op, "\u22c0", "\\bigwedge"); +defineSymbol(math, main, op, "\u2a04", "\\biguplus"); +defineSymbol(math, main, op, "\u22c2", "\\bigcap"); +defineSymbol(math, main, op, "\u22c3", "\\bigcup"); +defineSymbol(math, main, op, "\u222b", "\\int"); +defineSymbol(math, main, op, "\u222b", "\\intop"); +defineSymbol(math, main, op, "\u222c", "\\iint"); +defineSymbol(math, main, op, "\u222d", "\\iiint"); +defineSymbol(math, main, op, "\u220f", "\\prod"); +defineSymbol(math, main, op, "\u2211", "\\sum"); +defineSymbol(math, main, op, "\u2a02", "\\bigotimes"); +defineSymbol(math, main, op, "\u2a01", "\\bigoplus"); +defineSymbol(math, main, op, "\u2a00", "\\bigodot"); +defineSymbol(math, main, op, "\u222e", "\\oint"); +defineSymbol(math, main, op, "\u222f", "\\oiint"); +defineSymbol(math, main, op, "\u2230", "\\oiiint"); +defineSymbol(math, main, op, "\u2a06", "\\bigsqcup"); +defineSymbol(math, main, op, "\u222b", "\\smallint"); +defineSymbol(text, main, inner, "\u2026", "\\textellipsis"); +defineSymbol(math, main, inner, "\u2026", "\\mathellipsis"); +defineSymbol(text, main, inner, "\u2026", "\\ldots", true); +defineSymbol(math, main, inner, "\u2026", "\\ldots", true); +defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true); +defineSymbol(math, main, inner, "\u22f1", "\\ddots", true); // \vdots is a macro that uses one of these two symbols (with made-up names): + +defineSymbol(math, main, textord, "\u22ee", "\\varvdots"); +defineSymbol(text, main, textord, "\u22ee", "\\varvdots"); +defineSymbol(math, main, accent, "\u02ca", "\\acute"); +defineSymbol(math, main, accent, "\u02cb", "\\grave"); +defineSymbol(math, main, accent, "\u00a8", "\\ddot"); +defineSymbol(math, main, accent, "\u007e", "\\tilde"); +defineSymbol(math, main, accent, "\u02c9", "\\bar"); +defineSymbol(math, main, accent, "\u02d8", "\\breve"); +defineSymbol(math, main, accent, "\u02c7", "\\check"); +defineSymbol(math, main, accent, "\u005e", "\\hat"); +defineSymbol(math, main, accent, "\u20d7", "\\vec"); +defineSymbol(math, main, accent, "\u02d9", "\\dot"); +defineSymbol(math, main, accent, "\u02da", "\\mathring"); // \imath and \jmath should be invariant to \mathrm, \mathbf, etc., so use PUA + +defineSymbol(math, main, mathord, "\ue131", "\\@imath"); +defineSymbol(math, main, mathord, "\ue237", "\\@jmath"); +defineSymbol(math, main, textord, "\u0131", "\u0131"); +defineSymbol(math, main, textord, "\u0237", "\u0237"); +defineSymbol(text, main, textord, "\u0131", "\\i", true); +defineSymbol(text, main, textord, "\u0237", "\\j", true); +defineSymbol(text, main, textord, "\u00df", "\\ss", true); +defineSymbol(text, main, textord, "\u00e6", "\\ae", true); +defineSymbol(text, main, textord, "\u0153", "\\oe", true); +defineSymbol(text, main, textord, "\u00f8", "\\o", true); +defineSymbol(text, main, textord, "\u00c6", "\\AE", true); +defineSymbol(text, main, textord, "\u0152", "\\OE", true); +defineSymbol(text, main, textord, "\u00d8", "\\O", true); +defineSymbol(text, main, accent, "\u02ca", "\\'"); // acute + +defineSymbol(text, main, accent, "\u02cb", "\\`"); // grave + +defineSymbol(text, main, accent, "\u02c6", "\\^"); // circumflex + +defineSymbol(text, main, accent, "\u02dc", "\\~"); // tilde + +defineSymbol(text, main, accent, "\u02c9", "\\="); // macron + +defineSymbol(text, main, accent, "\u02d8", "\\u"); // breve + +defineSymbol(text, main, accent, "\u02d9", "\\."); // dot above + +defineSymbol(text, main, accent, "\u00b8", "\\c"); // cedilla + +defineSymbol(text, main, accent, "\u02da", "\\r"); // ring above + +defineSymbol(text, main, accent, "\u02c7", "\\v"); // caron + +defineSymbol(text, main, accent, "\u00a8", '\\"'); // diaeresis + +defineSymbol(text, main, accent, "\u02dd", "\\H"); // double acute + +defineSymbol(text, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph +// These ligatures are detected and created in Parser.js's `formLigatures`. + +var ligatures = { + "--": true, + "---": true, + "``": true, + "''": true +}; +defineSymbol(text, main, textord, "\u2013", "--", true); +defineSymbol(text, main, textord, "\u2013", "\\textendash"); +defineSymbol(text, main, textord, "\u2014", "---", true); +defineSymbol(text, main, textord, "\u2014", "\\textemdash"); +defineSymbol(text, main, textord, "\u2018", "`", true); +defineSymbol(text, main, textord, "\u2018", "\\textquoteleft"); +defineSymbol(text, main, textord, "\u2019", "'", true); +defineSymbol(text, main, textord, "\u2019", "\\textquoteright"); +defineSymbol(text, main, textord, "\u201c", "``", true); +defineSymbol(text, main, textord, "\u201c", "\\textquotedblleft"); +defineSymbol(text, main, textord, "\u201d", "''", true); +defineSymbol(text, main, textord, "\u201d", "\\textquotedblright"); // \degree from gensymb package + +defineSymbol(math, main, textord, "\u00b0", "\\degree", true); +defineSymbol(text, main, textord, "\u00b0", "\\degree"); // \textdegree from inputenc package + +defineSymbol(text, main, textord, "\u00b0", "\\textdegree", true); // TODO: In LaTeX, \pounds can generate a different character in text and math +// mode, but among our fonts, only Main-Regular defines this character "163". + +defineSymbol(math, main, textord, "\u00a3", "\\pounds"); +defineSymbol(math, main, textord, "\u00a3", "\\mathsterling", true); +defineSymbol(text, main, textord, "\u00a3", "\\pounds"); +defineSymbol(text, main, textord, "\u00a3", "\\textsterling", true); +defineSymbol(math, ams, textord, "\u2720", "\\maltese"); +defineSymbol(text, ams, textord, "\u2720", "\\maltese"); // There are lots of symbols which are the same, so we add them in afterwards. +// All of these are textords in math mode + +var mathTextSymbols = "0123456789/@.\""; + +for (var i = 0; i < mathTextSymbols.length; i++) { + var ch = mathTextSymbols.charAt(i); + defineSymbol(math, main, textord, ch, ch); +} // All of these are textords in text mode + + +var textSymbols = "0123456789!@*()-=+\";:?/.,"; + +for (var _i = 0; _i < textSymbols.length; _i++) { + var _ch = textSymbols.charAt(_i); + + defineSymbol(text, main, textord, _ch, _ch); +} // All of these are textords in text mode, and mathords in math mode + + +var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +for (var _i2 = 0; _i2 < letters.length; _i2++) { + var _ch2 = letters.charAt(_i2); + + defineSymbol(math, main, mathord, _ch2, _ch2); + defineSymbol(text, main, textord, _ch2, _ch2); +} // Blackboard bold and script letters in Unicode range + + +defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold + +defineSymbol(text, ams, textord, "C", "\u2102"); +defineSymbol(math, ams, textord, "H", "\u210D"); +defineSymbol(text, ams, textord, "H", "\u210D"); +defineSymbol(math, ams, textord, "N", "\u2115"); +defineSymbol(text, ams, textord, "N", "\u2115"); +defineSymbol(math, ams, textord, "P", "\u2119"); +defineSymbol(text, ams, textord, "P", "\u2119"); +defineSymbol(math, ams, textord, "Q", "\u211A"); +defineSymbol(text, ams, textord, "Q", "\u211A"); +defineSymbol(math, ams, textord, "R", "\u211D"); +defineSymbol(text, ams, textord, "R", "\u211D"); +defineSymbol(math, ams, textord, "Z", "\u2124"); +defineSymbol(text, ams, textord, "Z", "\u2124"); +defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant + +defineSymbol(text, main, mathord, "h", "\u210E"); // The next loop loads wide (surrogate pair) characters. +// We support some letters in the Unicode range U+1D400 to U+1D7FF, +// Mathematical Alphanumeric Symbols. +// Some editors do not deal well with wide characters. So don't write the +// string into this file. Instead, create the string from the surrogate pair. + +var wideChar = ""; + +for (var _i3 = 0; _i3 < letters.length; _i3++) { + var _ch3 = letters.charAt(_i3); // The hex numbers in the next line are a surrogate pair. + // 0xD835 is the high surrogate for all letters in the range we support. + // 0xDC00 is the low surrogate for bold A. + + + wideChar = String.fromCharCode(0xD835, 0xDC00 + _i3); // A-Z a-z bold + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDC34 + _i3); // A-Z a-z italic + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDC68 + _i3); // A-Z a-z bold italic + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDD04 + _i3); // A-Z a-z Fraktur + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDD6C + _i3); // A-Z a-z bold Fraktur + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDDA0 + _i3); // A-Z a-z sans-serif + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDDD4 + _i3); // A-Z a-z sans bold + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDE08 + _i3); // A-Z a-z sans italic + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDE70 + _i3); // A-Z a-z monospace + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + + if (_i3 < 26) { + // KaTeX fonts have only capital letters for blackboard bold and script. + // See exception for k below. + wideChar = String.fromCharCode(0xD835, 0xDD38 + _i3); // A-Z double struck + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDC9C + _i3); // A-Z script + + defineSymbol(math, main, mathord, _ch3, wideChar); + defineSymbol(text, main, textord, _ch3, wideChar); + } // TODO: Add bold script when it is supported by a KaTeX font. + +} // "k" is the only double struck lower case letter in the KaTeX fonts. + + +wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck + +defineSymbol(math, main, mathord, "k", wideChar); +defineSymbol(text, main, textord, "k", wideChar); // Next, some wide character numerals + +for (var _i4 = 0; _i4 < 10; _i4++) { + var _ch4 = _i4.toString(); + + wideChar = String.fromCharCode(0xD835, 0xDFCE + _i4); // 0-9 bold + + defineSymbol(math, main, mathord, _ch4, wideChar); + defineSymbol(text, main, textord, _ch4, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDFE2 + _i4); // 0-9 sans serif + + defineSymbol(math, main, mathord, _ch4, wideChar); + defineSymbol(text, main, textord, _ch4, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDFEC + _i4); // 0-9 bold sans + + defineSymbol(math, main, mathord, _ch4, wideChar); + defineSymbol(text, main, textord, _ch4, wideChar); + wideChar = String.fromCharCode(0xD835, 0xDFF6 + _i4); // 0-9 monospace + + defineSymbol(math, main, mathord, _ch4, wideChar); + defineSymbol(text, main, textord, _ch4, wideChar); +} // We add these Latin-1 letters as symbols for backwards-compatibility, +// but they are not actually in the font, nor are they supported by the +// Unicode accent mechanism, so they fall back to Times font and look ugly. +// TODO(edemaine): Fix this. + + +var extraLatin = "\u00d0\u00de\u00fe"; + +for (var _i5 = 0; _i5 < extraLatin.length; _i5++) { + var _ch5 = extraLatin.charAt(_i5); + + defineSymbol(math, main, mathord, _ch5, _ch5); + defineSymbol(text, main, textord, _ch5, _ch5); +} + +/** + * This file provides support for Unicode range U+1D400 to U+1D7FF, + * Mathematical Alphanumeric Symbols. + * + * Function wideCharacterFont takes a wide character as input and returns + * the font information necessary to render it properly. + */ +/** + * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf + * That document sorts characters into groups by font type, say bold or italic. + * + * In the arrays below, each subarray consists three elements: + * * The CSS class of that group when in math mode. + * * The CSS class of that group when in text mode. + * * The font name, so that KaTeX can get font metrics. + */ + +var wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"], // A-Z bold upright +["mathbf", "textbf", "Main-Bold"], // a-z bold upright +["mathnormal", "textit", "Math-Italic"], // A-Z italic +["mathnormal", "textit", "Math-Italic"], // a-z italic +["boldsymbol", "boldsymbol", "Main-BoldItalic"], // A-Z bold italic +["boldsymbol", "boldsymbol", "Main-BoldItalic"], // a-z bold italic +// Map fancy A-Z letters to script, not calligraphic. +// This aligns with unicode-math and math fonts (except Cambria Math). +["mathscr", "textscr", "Script-Regular"], // A-Z script +["", "", ""], // a-z script. No font +["", "", ""], // A-Z bold script. No font +["", "", ""], // a-z bold script. No font +["mathfrak", "textfrak", "Fraktur-Regular"], // A-Z Fraktur +["mathfrak", "textfrak", "Fraktur-Regular"], // a-z Fraktur +["mathbb", "textbb", "AMS-Regular"], // A-Z double-struck +["mathbb", "textbb", "AMS-Regular"], // k double-struck +// Note that we are using a bold font, but font metrics for regular Fraktur. +["mathboldfrak", "textboldfrak", "Fraktur-Regular"], // A-Z bold Fraktur +["mathboldfrak", "textboldfrak", "Fraktur-Regular"], // a-z bold Fraktur +["mathsf", "textsf", "SansSerif-Regular"], // A-Z sans-serif +["mathsf", "textsf", "SansSerif-Regular"], // a-z sans-serif +["mathboldsf", "textboldsf", "SansSerif-Bold"], // A-Z bold sans-serif +["mathboldsf", "textboldsf", "SansSerif-Bold"], // a-z bold sans-serif +["mathitsf", "textitsf", "SansSerif-Italic"], // A-Z italic sans-serif +["mathitsf", "textitsf", "SansSerif-Italic"], // a-z italic sans-serif +["", "", ""], // A-Z bold italic sans. No font +["", "", ""], // a-z bold italic sans. No font +["mathtt", "texttt", "Typewriter-Regular"], // A-Z monospace +["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace +]; +var wideNumeralData = [["mathbf", "textbf", "Main-Bold"], // 0-9 bold +["", "", ""], // 0-9 double-struck. No KaTeX font. +["mathsf", "textsf", "SansSerif-Regular"], // 0-9 sans-serif +["mathboldsf", "textboldsf", "SansSerif-Bold"], // 0-9 bold sans-serif +["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace +]; +var wideCharacterFont = function wideCharacterFont(wideChar, mode) { + // IE doesn't support codePointAt(). So work with the surrogate pair. + var H = wideChar.charCodeAt(0); // high surrogate + + var L = wideChar.charCodeAt(1); // low surrogate + + var codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000; + var j = mode === "math" ? 0 : 1; // column index for CSS class. + + if (0x1D400 <= codePoint && codePoint < 0x1D6A4) { + // wideLatinLetterData contains exactly 26 chars on each row. + // So we can calculate the relevant row. No traverse necessary. + var i = Math.floor((codePoint - 0x1D400) / 26); + return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]]; + } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) { + // Numerals, ten per row. + var _i = Math.floor((codePoint - 0x1D7CE) / 10); + + return [wideNumeralData[_i][2], wideNumeralData[_i][j]]; + } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) { + // dotless i or j + return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]]; + } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) { + // Greek letters. Not supported, yet. + return ["", ""]; + } else { + // We don't support any wide characters outside 1D400–1D7FF. + throw new ParseError("Unsupported character: " + wideChar); + } +}; + +/* eslint no-console:0 */ + +/** + * Looks up the given symbol in fontMetrics, after applying any symbol + * replacements defined in symbol.js + */ +var lookupSymbol = function lookupSymbol(value, // TODO(#963): Use a union type for this. +fontName, mode) { + // Replace the value with its replaced value from symbol.js + if (symbols[mode][value] && symbols[mode][value].replace) { + value = symbols[mode][value].replace; + } + + return { + value: value, + metrics: getCharacterMetrics(value, fontName, mode) + }; +}; +/** + * Makes a symbolNode after translation via the list of symbols in symbols.js. + * Correctly pulls out metrics for the character, and optionally takes a list of + * classes to be attached to the node. + * + * TODO: make argument order closer to makeSpan + * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which + * should if present come first in `classes`. + * TODO(#953): Make `options` mandatory and always pass it in. + */ + + +var makeSymbol = function makeSymbol(value, fontName, mode, options, classes) { + var lookup = lookupSymbol(value, fontName, mode); + var metrics = lookup.metrics; + value = lookup.value; + var symbolNode; + + if (metrics) { + var italic = metrics.italic; + + if (mode === "text" || options && options.font === "mathit") { + italic = 0; + } + + symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes); + } else { + // TODO(emily): Figure out a good way to only print this in development + typeof console !== "undefined" && console.warn("No character metrics " + ("for '" + value + "' in style '" + fontName + "' and mode '" + mode + "'")); + symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes); + } + + if (options) { + symbolNode.maxFontSize = options.sizeMultiplier; + + if (options.style.isTight()) { + symbolNode.classes.push("mtight"); + } + + var color = options.getColor(); + + if (color) { + symbolNode.style.color = color; + } + } + + return symbolNode; +}; +/** + * Makes a symbol in Main-Regular or AMS-Regular. + * Used for rel, bin, open, close, inner, and punct. + */ + + +var mathsym = function mathsym(value, mode, options, classes) { + if (classes === void 0) { + classes = []; + } + + // Decide what font to render the symbol in by its entry in the symbols + // table. + // Have a special case for when the value = \ because the \ is used as a + // textord in unsupported command errors but cannot be parsed as a regular + // text ordinal and is therefore not present as a symbol in the symbols + // table for text, as well as a special case for boldsymbol because it + // can be used for bold + and - + if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) { + return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"])); + } else if (value === "\\" || symbols[mode][value].font === "main") { + return makeSymbol(value, "Main-Regular", mode, options, classes); + } else { + return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"])); + } +}; +/** + * Determines which of the two font names (Main-Bold and Math-BoldItalic) and + * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol", + * depending on the symbol. Use this function instead of fontMap for font + * "boldsymbol". + */ + + +var boldsymbol = function boldsymbol(value, mode, options, classes, type) { + if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) { + return { + fontName: "Math-BoldItalic", + fontClass: "boldsymbol" + }; + } else { + // Some glyphs do not exist in Math-BoldItalic so we need to use + // Main-Bold instead. + return { + fontName: "Main-Bold", + fontClass: "mathbf" + }; + } +}; +/** + * Makes either a mathord or textord in the correct font and color. + */ + + +var makeOrd = function makeOrd(group, options, type) { + var mode = group.mode; + var text = group.text; + var classes = ["mord"]; // Math mode or Old font (i.e. \rm) + + var isFont = mode === "math" || mode === "text" && options.font; + var fontOrFamily = isFont ? options.font : options.fontFamily; + var wideFontName = ""; + var wideFontClass = ""; + + if (text.charCodeAt(0) === 0xD835) { + [wideFontName, wideFontClass] = wideCharacterFont(text, mode); + } + + if (wideFontName.length > 0) { + // surrogate pairs get special treatment + return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass)); + } else if (fontOrFamily) { + var fontName; + var fontClasses; + + if (fontOrFamily === "boldsymbol") { + var fontData = boldsymbol(text, mode, options, classes, type); + fontName = fontData.fontName; + fontClasses = [fontData.fontClass]; + } else if (isFont) { + fontName = fontMap[fontOrFamily].fontName; + fontClasses = [fontOrFamily]; + } else { + fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape); + fontClasses = [fontOrFamily, options.fontWeight, options.fontShape]; + } + + if (lookupSymbol(text, fontName, mode).metrics) { + return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses)); + } else if (ligatures.hasOwnProperty(text) && fontName.slice(0, 10) === "Typewriter") { + // Deconstruct ligatures in monospace fonts (\texttt, \tt). + var parts = []; + + for (var i = 0; i < text.length; i++) { + parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses))); + } + + return makeFragment(parts); + } + } // Makes a symbol in the default font for mathords and textords. + + + if (type === "mathord") { + return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"])); + } else if (type === "textord") { + var font = symbols[mode][text] && symbols[mode][text].font; + + if (font === "ams") { + var _fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape); + + return makeSymbol(text, _fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape)); + } else if (font === "main" || !font) { + var _fontName2 = retrieveTextFontName("textrm", options.fontWeight, options.fontShape); + + return makeSymbol(text, _fontName2, mode, options, classes.concat(options.fontWeight, options.fontShape)); + } else { + // fonts added by plugins + var _fontName3 = retrieveTextFontName(font, options.fontWeight, options.fontShape); // We add font name as a css class + + + return makeSymbol(text, _fontName3, mode, options, classes.concat(_fontName3, options.fontWeight, options.fontShape)); + } + } else { + throw new Error("unexpected type: " + type + " in makeOrd"); + } +}; +/** + * Returns true if subsequent symbolNodes have the same classes, skew, maxFont, + * and styles. + */ + + +var canCombine = (prev, next) => { + if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize) { + return false; + } // If prev and next both are just "mbin"s or "mord"s we don't combine them + // so that the proper spacing can be preserved. + + + if (prev.classes.length === 1) { + var cls = prev.classes[0]; + + if (cls === "mbin" || cls === "mord") { + return false; + } + } + + for (var style in prev.style) { + if (prev.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) { + return false; + } + } + + for (var _style in next.style) { + if (next.style.hasOwnProperty(_style) && prev.style[_style] !== next.style[_style]) { + return false; + } + } + + return true; +}; +/** + * Combine consecutive domTree.symbolNodes into a single symbolNode. + * Note: this function mutates the argument. + */ + + +var tryCombineChars = chars => { + for (var i = 0; i < chars.length - 1; i++) { + var prev = chars[i]; + var next = chars[i + 1]; + + if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) { + prev.text += next.text; + prev.height = Math.max(prev.height, next.height); + prev.depth = Math.max(prev.depth, next.depth); // Use the last character's italic correction since we use + // it to add padding to the right of the span created from + // the combined characters. + + prev.italic = next.italic; + chars.splice(i + 1, 1); + i--; + } + } + + return chars; +}; +/** + * Calculate the height, depth, and maxFontSize of an element based on its + * children. + */ + + +var sizeElementFromChildren = function sizeElementFromChildren(elem) { + var height = 0; + var depth = 0; + var maxFontSize = 0; + + for (var i = 0; i < elem.children.length; i++) { + var child = elem.children[i]; + + if (child.height > height) { + height = child.height; + } + + if (child.depth > depth) { + depth = child.depth; + } + + if (child.maxFontSize > maxFontSize) { + maxFontSize = child.maxFontSize; + } + } + + elem.height = height; + elem.depth = depth; + elem.maxFontSize = maxFontSize; +}; +/** + * Makes a span with the given list of classes, list of children, and options. + * + * TODO(#953): Ensure that `options` is always provided (currently some call + * sites don't pass it) and make the type below mandatory. + * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which + * should if present come first in `classes`. + */ + + +var makeSpan$2 = function makeSpan(classes, children, options, style) { + var span = new Span(classes, children, options, style); + sizeElementFromChildren(span); + return span; +}; // SVG one is simpler -- doesn't require height, depth, max-font setting. +// This is also a separate method for typesafety. + + +var makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style); + +var makeLineSpan = function makeLineSpan(className, options, thickness) { + var line = makeSpan$2([className], [], options); + line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness); + line.style.borderBottomWidth = makeEm(line.height); + line.maxFontSize = 1.0; + return line; +}; +/** + * Makes an anchor with the given href, list of classes, list of children, + * and options. + */ + + +var makeAnchor = function makeAnchor(href, classes, children, options) { + var anchor = new Anchor(href, classes, children, options); + sizeElementFromChildren(anchor); + return anchor; +}; +/** + * Makes a document fragment with the given list of children. + */ + + +var makeFragment = function makeFragment(children) { + var fragment = new DocumentFragment(children); + sizeElementFromChildren(fragment); + return fragment; +}; +/** + * Wraps group in a span if it's a document fragment, allowing to apply classes + * and styles + */ + + +var wrapFragment = function wrapFragment(group, options) { + if (group instanceof DocumentFragment) { + return makeSpan$2([], [group], options); + } + + return group; +}; // These are exact object types to catch typos in the names of the optional fields. + + +// Computes the updated `children` list and the overall depth. +// +// This helper function for makeVList makes it easier to enforce type safety by +// allowing early exits (returns) in the logic. +var getVListChildrenAndDepth = function getVListChildrenAndDepth(params) { + if (params.positionType === "individualShift") { + var oldChildren = params.children; + var children = [oldChildren[0]]; // Add in kerns to the list of params.children to get each element to be + // shifted to the correct specified shift + + var _depth = -oldChildren[0].shift - oldChildren[0].elem.depth; + + var currPos = _depth; + + for (var i = 1; i < oldChildren.length; i++) { + var diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth; + var size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth); + currPos = currPos + diff; + children.push({ + type: "kern", + size + }); + children.push(oldChildren[i]); + } + + return { + children, + depth: _depth + }; + } + + var depth; + + if (params.positionType === "top") { + // We always start at the bottom, so calculate the bottom by adding up + // all the sizes + var bottom = params.positionData; + + for (var _i = 0; _i < params.children.length; _i++) { + var child = params.children[_i]; + bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth; + } + + depth = bottom; + } else if (params.positionType === "bottom") { + depth = -params.positionData; + } else { + var firstChild = params.children[0]; + + if (firstChild.type !== "elem") { + throw new Error('First child must have type "elem".'); + } + + if (params.positionType === "shift") { + depth = -firstChild.elem.depth - params.positionData; + } else if (params.positionType === "firstBaseline") { + depth = -firstChild.elem.depth; + } else { + throw new Error("Invalid positionType " + params.positionType + "."); + } + } + + return { + children: params.children, + depth + }; +}; +/** + * Makes a vertical list by stacking elements and kerns on top of each other. + * Allows for many different ways of specifying the positioning method. + * + * See VListParam documentation above. + */ + + +var makeVList = function makeVList(params, options) { + var { + children, + depth + } = getVListChildrenAndDepth(params); // Create a strut that is taller than any list item. The strut is added to + // each item, where it will determine the item's baseline. Since it has + // `overflow:hidden`, the strut's top edge will sit on the item's line box's + // top edge and the strut's bottom edge will sit on the item's baseline, + // with no additional line-height spacing. This allows the item baseline to + // be positioned precisely without worrying about font ascent and + // line-height. + + var pstrutSize = 0; + + for (var i = 0; i < children.length; i++) { + var child = children[i]; + + if (child.type === "elem") { + var elem = child.elem; + pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height); + } + } + + pstrutSize += 2; + var pstrut = makeSpan$2(["pstrut"], []); + pstrut.style.height = makeEm(pstrutSize); // Create a new list of actual children at the correct offsets + + var realChildren = []; + var minPos = depth; + var maxPos = depth; + var currPos = depth; + + for (var _i2 = 0; _i2 < children.length; _i2++) { + var _child = children[_i2]; + + if (_child.type === "kern") { + currPos += _child.size; + } else { + var _elem = _child.elem; + var classes = _child.wrapperClasses || []; + var style = _child.wrapperStyle || {}; + var childWrap = makeSpan$2(classes, [pstrut, _elem], undefined, style); + childWrap.style.top = makeEm(-pstrutSize - currPos - _elem.depth); + + if (_child.marginLeft) { + childWrap.style.marginLeft = _child.marginLeft; + } + + if (_child.marginRight) { + childWrap.style.marginRight = _child.marginRight; + } + + realChildren.push(childWrap); + currPos += _elem.height + _elem.depth; + } + + minPos = Math.min(minPos, currPos); + maxPos = Math.max(maxPos, currPos); + } // The vlist contents go in a table-cell with `vertical-align:bottom`. + // This cell's bottom edge will determine the containing table's baseline + // without overly expanding the containing line-box. + + + var vlist = makeSpan$2(["vlist"], realChildren); + vlist.style.height = makeEm(maxPos); // A second row is used if necessary to represent the vlist's depth. + + var rows; + + if (minPos < 0) { + // We will define depth in an empty span with display: table-cell. + // It should render with the height that we define. But Chrome, in + // contenteditable mode only, treats that span as if it contains some + // text content. And that min-height over-rides our desired height. + // So we put another empty span inside the depth strut span. + var emptySpan = makeSpan$2([], []); + var depthStrut = makeSpan$2(["vlist"], [emptySpan]); + depthStrut.style.height = makeEm(-minPos); // Safari wants the first row to have inline content; otherwise it + // puts the bottom of the *second* row on the baseline. + + var topStrut = makeSpan$2(["vlist-s"], [new SymbolNode("\u200b")]); + rows = [makeSpan$2(["vlist-r"], [vlist, topStrut]), makeSpan$2(["vlist-r"], [depthStrut])]; + } else { + rows = [makeSpan$2(["vlist-r"], [vlist])]; + } + + var vtable = makeSpan$2(["vlist-t"], rows); + + if (rows.length === 2) { + vtable.classes.push("vlist-t2"); + } + + vtable.height = maxPos; + vtable.depth = -minPos; + return vtable; +}; // Glue is a concept from TeX which is a flexible space between elements in +// either a vertical or horizontal list. In KaTeX, at least for now, it's +// static space between elements in a horizontal layout. + + +var makeGlue = (measurement, options) => { + // Make an empty span for the space + var rule = makeSpan$2(["mspace"], [], options); + var size = calculateSize(measurement, options); + rule.style.marginRight = makeEm(size); + return rule; +}; // Takes font options, and returns the appropriate fontLookup name + + +var retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight, fontShape) { + var baseFontName = ""; + + switch (fontFamily) { + case "amsrm": + baseFontName = "AMS"; + break; + + case "textrm": + baseFontName = "Main"; + break; + + case "textsf": + baseFontName = "SansSerif"; + break; + + case "texttt": + baseFontName = "Typewriter"; + break; + + default: + baseFontName = fontFamily; + // use fonts added by a plugin + } + + var fontStylesName; + + if (fontWeight === "textbf" && fontShape === "textit") { + fontStylesName = "BoldItalic"; + } else if (fontWeight === "textbf") { + fontStylesName = "Bold"; + } else if (fontWeight === "textit") { + fontStylesName = "Italic"; + } else { + fontStylesName = "Regular"; + } + + return baseFontName + "-" + fontStylesName; +}; +/** + * Maps TeX font commands to objects containing: + * - variant: string used for "mathvariant" attribute in buildMathML.js + * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics + */ +// A map between tex font commands an MathML mathvariant attribute values + + +var fontMap = { + // styles + "mathbf": { + variant: "bold", + fontName: "Main-Bold" + }, + "mathrm": { + variant: "normal", + fontName: "Main-Regular" + }, + "textit": { + variant: "italic", + fontName: "Main-Italic" + }, + "mathit": { + variant: "italic", + fontName: "Main-Italic" + }, + "mathnormal": { + variant: "italic", + fontName: "Math-Italic" + }, + "mathsfit": { + variant: "sans-serif-italic", + fontName: "SansSerif-Italic" + }, + // "boldsymbol" is missing because they require the use of multiple fonts: + // Math-BoldItalic and Main-Bold. This is handled by a special case in + // makeOrd which ends up calling boldsymbol. + // families + "mathbb": { + variant: "double-struck", + fontName: "AMS-Regular" + }, + "mathcal": { + variant: "script", + fontName: "Caligraphic-Regular" + }, + "mathfrak": { + variant: "fraktur", + fontName: "Fraktur-Regular" + }, + "mathscr": { + variant: "script", + fontName: "Script-Regular" + }, + "mathsf": { + variant: "sans-serif", + fontName: "SansSerif-Regular" + }, + "mathtt": { + variant: "monospace", + fontName: "Typewriter-Regular" + } +}; +var svgData = { + // path, width, height + vec: ["vec", 0.471, 0.714], + // values from the font glyph + oiintSize1: ["oiintSize1", 0.957, 0.499], + // oval to overlay the integrand + oiintSize2: ["oiintSize2", 1.472, 0.659], + oiiintSize1: ["oiiintSize1", 1.304, 0.499], + oiiintSize2: ["oiiintSize2", 1.98, 0.659] +}; + +var staticSvg = function staticSvg(value, options) { + // Create a span with inline SVG for the element. + var [pathName, width, height] = svgData[value]; + var path = new PathNode(pathName); + var svgNode = new SvgNode([path], { + "width": makeEm(width), + "height": makeEm(height), + // Override CSS rule `.katex svg { width: 100% }` + "style": "width:" + makeEm(width), + "viewBox": "0 0 " + 1000 * width + " " + 1000 * height, + "preserveAspectRatio": "xMinYMin" + }); + var span = makeSvgSpan(["overlay"], [svgNode], options); + span.height = height; + span.style.height = makeEm(height); + span.style.width = makeEm(width); + return span; +}; + +var buildCommon = { + fontMap, + makeSymbol, + mathsym, + makeSpan: makeSpan$2, + makeSvgSpan, + makeLineSpan, + makeAnchor, + makeFragment, + wrapFragment, + makeVList, + makeOrd, + makeGlue, + staticSvg, + svgData, + tryCombineChars +}; + +/** + * Describes spaces between different classes of atoms. + */ +var thinspace = { + number: 3, + unit: "mu" +}; +var mediumspace = { + number: 4, + unit: "mu" +}; +var thickspace = { + number: 5, + unit: "mu" +}; // Making the type below exact with all optional fields doesn't work due to +// - https://github.com/facebook/flow/issues/4582 +// - https://github.com/facebook/flow/issues/5688 +// However, since *all* fields are optional, $Shape<> works as suggested in 5688 +// above. + +// Spacing relationships for display and text styles +var spacings = { + mord: { + mop: thinspace, + mbin: mediumspace, + mrel: thickspace, + minner: thinspace + }, + mop: { + mord: thinspace, + mop: thinspace, + mrel: thickspace, + minner: thinspace + }, + mbin: { + mord: mediumspace, + mop: mediumspace, + mopen: mediumspace, + minner: mediumspace + }, + mrel: { + mord: thickspace, + mop: thickspace, + mopen: thickspace, + minner: thickspace + }, + mopen: {}, + mclose: { + mop: thinspace, + mbin: mediumspace, + mrel: thickspace, + minner: thinspace + }, + mpunct: { + mord: thinspace, + mop: thinspace, + mrel: thickspace, + mopen: thinspace, + mclose: thinspace, + mpunct: thinspace, + minner: thinspace + }, + minner: { + mord: thinspace, + mop: thinspace, + mbin: mediumspace, + mrel: thickspace, + mopen: thinspace, + mpunct: thinspace, + minner: thinspace + } +}; // Spacing relationships for script and scriptscript styles + +var tightSpacings = { + mord: { + mop: thinspace + }, + mop: { + mord: thinspace, + mop: thinspace + }, + mbin: {}, + mrel: {}, + mopen: {}, + mclose: { + mop: thinspace + }, + mpunct: {}, + minner: { + mop: thinspace + } +}; + +/** Context provided to function handlers for error messages. */ +// Note: reverse the order of the return type union will cause a flow error. +// See https://github.com/facebook/flow/issues/3663. +// More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types) +// whose presence impacts super/subscripting. In this case, ParseNode<"supsub"> +// delegates its HTML building to the HtmlBuilder corresponding to these nodes. + +/** + * Final function spec for use at parse time. + * This is almost identical to `FunctionPropSpec`, except it + * 1. includes the function handler, and + * 2. requires all arguments except argTypes. + * It is generated by `defineFunction()` below. + */ + +/** + * All registered functions. + * `functions.js` just exports this same dictionary again and makes it public. + * `Parser.js` requires this dictionary. + */ +var _functions = {}; +/** + * All HTML builders. Should be only used in the `define*` and the `build*ML` + * functions. + */ + +var _htmlGroupBuilders = {}; +/** + * All MathML builders. Should be only used in the `define*` and the `build*ML` + * functions. + */ + +var _mathmlGroupBuilders = {}; +function defineFunction(_ref) { + var { + type, + names, + props, + handler, + htmlBuilder, + mathmlBuilder + } = _ref; + // Set default values of functions + var data = { + type, + numArgs: props.numArgs, + argTypes: props.argTypes, + allowedInArgument: !!props.allowedInArgument, + allowedInText: !!props.allowedInText, + allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, + numOptionalArgs: props.numOptionalArgs || 0, + infix: !!props.infix, + primitive: !!props.primitive, + handler: handler + }; + + for (var i = 0; i < names.length; ++i) { + _functions[names[i]] = data; + } + + if (type) { + if (htmlBuilder) { + _htmlGroupBuilders[type] = htmlBuilder; + } + + if (mathmlBuilder) { + _mathmlGroupBuilders[type] = mathmlBuilder; + } + } +} +/** + * Use this to register only the HTML and MathML builders for a function (e.g. + * if the function's ParseNode is generated in Parser.js rather than via a + * stand-alone handler provided to `defineFunction`). + */ + +function defineFunctionBuilders(_ref2) { + var { + type, + htmlBuilder, + mathmlBuilder + } = _ref2; + defineFunction({ + type, + names: [], + props: { + numArgs: 0 + }, + + handler() { + throw new Error('Should never be called.'); + }, + + htmlBuilder, + mathmlBuilder + }); +} +var normalizeArgument = function normalizeArgument(arg) { + return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg; +}; // Since the corresponding buildHTML/buildMathML function expects a +// list of elements, we normalize for different kinds of arguments + +var ordargument = function ordargument(arg) { + return arg.type === "ordgroup" ? arg.body : [arg]; +}; + +/** + * This file does the main work of building a domTree structure from a parse + * tree. The entry point is the `buildHTML` function, which takes a parse tree. + * Then, the buildExpression, buildGroup, and various groupBuilders functions + * are called, to produce a final HTML tree. + */ +var makeSpan$1 = buildCommon.makeSpan; // Binary atoms (first class `mbin`) change into ordinary atoms (`mord`) +// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6, +// and the text before Rule 19. + +var binLeftCanceller = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"]; +var binRightCanceller = ["rightmost", "mrel", "mclose", "mpunct"]; +var styleMap$1 = { + "display": Style$1.DISPLAY, + "text": Style$1.TEXT, + "script": Style$1.SCRIPT, + "scriptscript": Style$1.SCRIPTSCRIPT +}; +var DomEnum = { + mord: "mord", + mop: "mop", + mbin: "mbin", + mrel: "mrel", + mopen: "mopen", + mclose: "mclose", + mpunct: "mpunct", + minner: "minner" +}; + +/** + * Take a list of nodes, build them in order, and return a list of the built + * nodes. documentFragments are flattened into their contents, so the + * returned list contains no fragments. `isRealGroup` is true if `expression` + * is a real group (no atoms will be added on either side), as opposed to + * a partial group (e.g. one created by \color). `surrounding` is an array + * consisting type of nodes that will be added to the left and right. + */ +var buildExpression$1 = function buildExpression(expression, options, isRealGroup, surrounding) { + if (surrounding === void 0) { + surrounding = [null, null]; + } + + // Parse expressions into `groups`. + var groups = []; + + for (var i = 0; i < expression.length; i++) { + var output = buildGroup$1(expression[i], options); + + if (output instanceof DocumentFragment) { + var children = output.children; + groups.push(...children); + } else { + groups.push(output); + } + } // Combine consecutive domTree.symbolNodes into a single symbolNode. + + + buildCommon.tryCombineChars(groups); // If `expression` is a partial group, let the parent handle spacings + // to avoid processing groups multiple times. + + if (!isRealGroup) { + return groups; + } + + var glueOptions = options; + + if (expression.length === 1) { + var node = expression[0]; + + if (node.type === "sizing") { + glueOptions = options.havingSize(node.size); + } else if (node.type === "styling") { + glueOptions = options.havingStyle(styleMap$1[node.style]); + } + } // Dummy spans for determining spacings between surrounding atoms. + // If `expression` has no atoms on the left or right, class "leftmost" + // or "rightmost", respectively, is used to indicate it. + + + var dummyPrev = makeSpan$1([surrounding[0] || "leftmost"], [], options); + var dummyNext = makeSpan$1([surrounding[1] || "rightmost"], [], options); // TODO: These code assumes that a node's math class is the first element + // of its `classes` array. A later cleanup should ensure this, for + // instance by changing the signature of `makeSpan`. + // Before determining what spaces to insert, perform bin cancellation. + // Binary operators change to ordinary symbols in some contexts. + + var isRoot = isRealGroup === "root"; + traverseNonSpaceNodes(groups, (node, prev) => { + var prevType = prev.classes[0]; + var type = node.classes[0]; + + if (prevType === "mbin" && utils.contains(binRightCanceller, type)) { + prev.classes[0] = "mord"; + } else if (type === "mbin" && utils.contains(binLeftCanceller, prevType)) { + node.classes[0] = "mord"; + } + }, { + node: dummyPrev + }, dummyNext, isRoot); + traverseNonSpaceNodes(groups, (node, prev) => { + var prevType = getTypeOfDomTree(prev); + var type = getTypeOfDomTree(node); // 'mtight' indicates that the node is script or scriptscript style. + + var space = prevType && type ? node.hasClass("mtight") ? tightSpacings[prevType][type] : spacings[prevType][type] : null; + + if (space) { + // Insert glue (spacing) after the `prev`. + return buildCommon.makeGlue(space, glueOptions); + } + }, { + node: dummyPrev + }, dummyNext, isRoot); + return groups; +}; // Depth-first traverse non-space `nodes`, calling `callback` with the current and +// previous node as arguments, optionally returning a node to insert after the +// previous node. `prev` is an object with the previous node and `insertAfter` +// function to insert after it. `next` is a node that will be added to the right. +// Used for bin cancellation and inserting spacings. + +var traverseNonSpaceNodes = function traverseNonSpaceNodes(nodes, callback, prev, next, isRoot) { + if (next) { + // temporarily append the right node, if exists + nodes.push(next); + } + + var i = 0; + + for (; i < nodes.length; i++) { + var node = nodes[i]; + var partialGroup = checkPartialGroup(node); + + if (partialGroup) { + // Recursive DFS + // $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array + traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot); + continue; + } // Ignore explicit spaces (e.g., \;, \,) when determining what implicit + // spacing should go between atoms of different classes + + + var nonspace = !node.hasClass("mspace"); + + if (nonspace) { + var result = callback(node, prev.node); + + if (result) { + if (prev.insertAfter) { + prev.insertAfter(result); + } else { + // insert at front + nodes.unshift(result); + i++; + } + } + } + + if (nonspace) { + prev.node = node; + } else if (isRoot && node.hasClass("newline")) { + prev.node = makeSpan$1(["leftmost"]); // treat like beginning of line + } + + prev.insertAfter = (index => n => { + nodes.splice(index + 1, 0, n); + i++; + })(i); + } + + if (next) { + nodes.pop(); + } +}; // Check if given node is a partial group, i.e., does not affect spacing around. + + +var checkPartialGroup = function checkPartialGroup(node) { + if (node instanceof DocumentFragment || node instanceof Anchor || node instanceof Span && node.hasClass("enclosing")) { + return node; + } + + return null; +}; // Return the outermost node of a domTree. + + +var getOutermostNode = function getOutermostNode(node, side) { + var partialGroup = checkPartialGroup(node); + + if (partialGroup) { + var children = partialGroup.children; + + if (children.length) { + if (side === "right") { + return getOutermostNode(children[children.length - 1], "right"); + } else if (side === "left") { + return getOutermostNode(children[0], "left"); + } + } + } + + return node; +}; // Return math atom class (mclass) of a domTree. +// If `side` is given, it will get the type of the outermost node at given side. + + +var getTypeOfDomTree = function getTypeOfDomTree(node, side) { + if (!node) { + return null; + } + + if (side) { + node = getOutermostNode(node, side); + } // This makes a lot of assumptions as to where the type of atom + // appears. We should do a better job of enforcing this. + + + return DomEnum[node.classes[0]] || null; +}; +var makeNullDelimiter = function makeNullDelimiter(options, classes) { + var moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses()); + return makeSpan$1(classes.concat(moreClasses)); +}; +/** + * buildGroup is the function that takes a group and calls the correct groupType + * function for it. It also handles the interaction of size and style changes + * between parents and children. + */ + +var buildGroup$1 = function buildGroup(group, options, baseOptions) { + if (!group) { + return makeSpan$1(); + } + + if (_htmlGroupBuilders[group.type]) { + // Call the groupBuilders function + // $FlowFixMe + var groupNode = _htmlGroupBuilders[group.type](group, options); // If the size changed between the parent and the current group, account + // for that size difference. + + if (baseOptions && options.size !== baseOptions.size) { + groupNode = makeSpan$1(options.sizingClasses(baseOptions), [groupNode], options); + var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; + groupNode.height *= multiplier; + groupNode.depth *= multiplier; + } + + return groupNode; + } else { + throw new ParseError("Got group of unknown type: '" + group.type + "'"); + } +}; +/** + * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`) + * into an unbreakable HTML node of class .base, with proper struts to + * guarantee correct vertical extent. `buildHTML` calls this repeatedly to + * make up the entire expression as a sequence of unbreakable units. + */ + +function buildHTMLUnbreakable(children, options) { + // Compute height and depth of this chunk. + var body = makeSpan$1(["base"], children, options); // Add strut, which ensures that the top of the HTML element falls at + // the height of the expression, and the bottom of the HTML element + // falls at the depth of the expression. + + var strut = makeSpan$1(["strut"]); + strut.style.height = makeEm(body.height + body.depth); + + if (body.depth) { + strut.style.verticalAlign = makeEm(-body.depth); + } + + body.children.unshift(strut); + return body; +} +/** + * Take an entire parse tree, and build it into an appropriate set of HTML + * nodes. + */ + + +function buildHTML(tree, options) { + // Strip off outer tag wrapper for processing below. + var tag = null; + + if (tree.length === 1 && tree[0].type === "tag") { + tag = tree[0].tag; + tree = tree[0].body; + } // Build the expression contained in the tree + + + var expression = buildExpression$1(tree, options, "root"); + var eqnNum; + + if (expression.length === 2 && expression[1].hasClass("tag")) { + // An environment with automatic equation numbers, e.g. {gather}. + eqnNum = expression.pop(); + } + + var children = []; // Create one base node for each chunk between potential line breaks. + // The TeXBook [p.173] says "A formula will be broken only after a + // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary + // operation symbol like $+$ or $-$ or $\times$, where the relation or + // binary operation is on the ``outer level'' of the formula (i.e., not + // enclosed in {...} and not part of an \over construction)." + + var parts = []; + + for (var i = 0; i < expression.length; i++) { + parts.push(expression[i]); + + if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) { + // Put any post-operator glue on same line as operator. + // Watch for \nobreak along the way, and stop at \newline. + var nobreak = false; + + while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("newline")) { + i++; + parts.push(expression[i]); + + if (expression[i].hasClass("nobreak")) { + nobreak = true; + } + } // Don't allow break if \nobreak among the post-operator glue. + + + if (!nobreak) { + children.push(buildHTMLUnbreakable(parts, options)); + parts = []; + } + } else if (expression[i].hasClass("newline")) { + // Write the line except the newline + parts.pop(); + + if (parts.length > 0) { + children.push(buildHTMLUnbreakable(parts, options)); + parts = []; + } // Put the newline at the top level + + + children.push(expression[i]); + } + } + + if (parts.length > 0) { + children.push(buildHTMLUnbreakable(parts, options)); + } // Now, if there was a tag, build it too and append it as a final child. + + + var tagChild; + + if (tag) { + tagChild = buildHTMLUnbreakable(buildExpression$1(tag, options, true)); + tagChild.classes = ["tag"]; + children.push(tagChild); + } else if (eqnNum) { + children.push(eqnNum); + } + + var htmlNode = makeSpan$1(["katex-html"], children); + htmlNode.setAttribute("aria-hidden", "true"); // Adjust the strut of the tag to be the maximum height of all children + // (the height of the enclosing htmlNode) for proper vertical alignment. + + if (tagChild) { + var strut = tagChild.children[0]; + strut.style.height = makeEm(htmlNode.height + htmlNode.depth); + + if (htmlNode.depth) { + strut.style.verticalAlign = makeEm(-htmlNode.depth); + } + } + + return htmlNode; +} + +/** + * These objects store data about MathML nodes. This is the MathML equivalent + * of the types in domTree.js. Since MathML handles its own rendering, and + * since we're mainly using MathML to improve accessibility, we don't manage + * any of the styling state that the plain DOM nodes do. + * + * The `toNode` and `toMarkup` functions work similarly to how they do in + * domTree.js, creating namespaced DOM nodes and HTML text markup respectively. + */ +function newDocumentFragment(children) { + return new DocumentFragment(children); +} +/** + * This node represents a general purpose MathML node of any type. The + * constructor requires the type of node to create (for example, `"mo"` or + * `"mspace"`, corresponding to `` and `` tags). + */ + +class MathNode { + constructor(type, children, classes) { + this.type = void 0; + this.attributes = void 0; + this.children = void 0; + this.classes = void 0; + this.type = type; + this.attributes = {}; + this.children = children || []; + this.classes = classes || []; + } + /** + * Sets an attribute on a MathML node. MathML depends on attributes to convey a + * semantic content, so this is used heavily. + */ + + + setAttribute(name, value) { + this.attributes[name] = value; + } + /** + * Gets an attribute on a MathML node. + */ + + + getAttribute(name) { + return this.attributes[name]; + } + /** + * Converts the math node into a MathML-namespaced DOM element. + */ + + + toNode() { + var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); + + for (var attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + node.setAttribute(attr, this.attributes[attr]); + } + } + + if (this.classes.length > 0) { + node.className = createClass(this.classes); + } + + for (var i = 0; i < this.children.length; i++) { + // Combine multiple TextNodes into one TextNode, to prevent + // screen readers from reading each as a separate word [#3995] + if (this.children[i] instanceof TextNode && this.children[i + 1] instanceof TextNode) { + var text = this.children[i].toText() + this.children[++i].toText(); + + while (this.children[i + 1] instanceof TextNode) { + text += this.children[++i].toText(); + } + + node.appendChild(new TextNode(text).toNode()); + } else { + node.appendChild(this.children[i].toNode()); + } + } + + return node; + } + /** + * Converts the math node into an HTML markup string. + */ + + + toMarkup() { + var markup = "<" + this.type; // Add the attributes + + for (var attr in this.attributes) { + if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { + markup += " " + attr + "=\""; + markup += utils.escape(this.attributes[attr]); + markup += "\""; + } + } + + if (this.classes.length > 0) { + markup += " class =\"" + utils.escape(createClass(this.classes)) + "\""; + } + + markup += ">"; + + for (var i = 0; i < this.children.length; i++) { + markup += this.children[i].toMarkup(); + } + + markup += ""; + return markup; + } + /** + * Converts the math node into a string, similar to innerText, but escaped. + */ + + + toText() { + return this.children.map(child => child.toText()).join(""); + } + +} +/** + * This node represents a piece of text. + */ + +class TextNode { + constructor(text) { + this.text = void 0; + this.text = text; + } + /** + * Converts the text node into a DOM text node. + */ + + + toNode() { + return document.createTextNode(this.text); + } + /** + * Converts the text node into escaped HTML markup + * (representing the text itself). + */ + + + toMarkup() { + return utils.escape(this.toText()); + } + /** + * Converts the text node into a string + * (representing the text itself). + */ + + + toText() { + return this.text; + } + +} +/** + * This node represents a space, but may render as or as text, + * depending on the width. + */ + +class SpaceNode { + /** + * Create a Space node with width given in CSS ems. + */ + constructor(width) { + this.width = void 0; + this.character = void 0; + this.width = width; // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html + // for a table of space-like characters. We use Unicode + // representations instead of &LongNames; as it's not clear how to + // make the latter via document.createTextNode. + + if (width >= 0.05555 && width <= 0.05556) { + this.character = "\u200a"; //   + } else if (width >= 0.1666 && width <= 0.1667) { + this.character = "\u2009"; //   + } else if (width >= 0.2222 && width <= 0.2223) { + this.character = "\u2005"; //   + } else if (width >= 0.2777 && width <= 0.2778) { + this.character = "\u2005\u200a"; //    + } else if (width >= -0.05556 && width <= -0.05555) { + this.character = "\u200a\u2063"; // ​ + } else if (width >= -0.1667 && width <= -0.1666) { + this.character = "\u2009\u2063"; // ​ + } else if (width >= -0.2223 && width <= -0.2222) { + this.character = "\u205f\u2063"; // ​ + } else if (width >= -0.2778 && width <= -0.2777) { + this.character = "\u2005\u2063"; // ​ + } else { + this.character = null; + } + } + /** + * Converts the math node into a MathML-namespaced DOM element. + */ + + + toNode() { + if (this.character) { + return document.createTextNode(this.character); + } else { + var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace"); + node.setAttribute("width", makeEm(this.width)); + return node; + } + } + /** + * Converts the math node into an HTML markup string. + */ + + + toMarkup() { + if (this.character) { + return "" + this.character + ""; + } else { + return ""; + } + } + /** + * Converts the math node into a string, similar to innerText. + */ + + + toText() { + if (this.character) { + return this.character; + } else { + return " "; + } + } + +} + +var mathMLTree = { + MathNode, + TextNode, + SpaceNode, + newDocumentFragment +}; + +/** + * This file converts a parse tree into a corresponding MathML tree. The main + * entry point is the `buildMathML` function, which takes a parse tree from the + * parser. + */ + +/** + * Takes a symbol and converts it into a MathML text node after performing + * optional replacement from symbols.js. + */ +var makeText = function makeText(text, mode, options) { + if (symbols[mode][text] && symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(ligatures.hasOwnProperty(text) && options && (options.fontFamily && options.fontFamily.slice(4, 6) === "tt" || options.font && options.font.slice(4, 6) === "tt"))) { + text = symbols[mode][text].replace; + } + + return new mathMLTree.TextNode(text); +}; +/** + * Wrap the given array of nodes in an node if needed, i.e., + * unless the array has length 1. Always returns a single node. + */ + +var makeRow = function makeRow(body) { + if (body.length === 1) { + return body[0]; + } else { + return new mathMLTree.MathNode("mrow", body); + } +}; +/** + * Returns the math variant as a string or null if none is required. + */ + +var getVariant = function getVariant(group, options) { + // Handle \text... font specifiers as best we can. + // MathML has a limited list of allowable mathvariant specifiers; see + // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt + if (options.fontFamily === "texttt") { + return "monospace"; + } else if (options.fontFamily === "textsf") { + if (options.fontShape === "textit" && options.fontWeight === "textbf") { + return "sans-serif-bold-italic"; + } else if (options.fontShape === "textit") { + return "sans-serif-italic"; + } else if (options.fontWeight === "textbf") { + return "bold-sans-serif"; + } else { + return "sans-serif"; + } + } else if (options.fontShape === "textit" && options.fontWeight === "textbf") { + return "bold-italic"; + } else if (options.fontShape === "textit") { + return "italic"; + } else if (options.fontWeight === "textbf") { + return "bold"; + } + + var font = options.font; + + if (!font || font === "mathnormal") { + return null; + } + + var mode = group.mode; + + if (font === "mathit") { + return "italic"; + } else if (font === "boldsymbol") { + return group.type === "textord" ? "bold" : "bold-italic"; + } else if (font === "mathbf") { + return "bold"; + } else if (font === "mathbb") { + return "double-struck"; + } else if (font === "mathsfit") { + return "sans-serif-italic"; + } else if (font === "mathfrak") { + return "fraktur"; + } else if (font === "mathscr" || font === "mathcal") { + // MathML makes no distinction between script and calligraphic + return "script"; + } else if (font === "mathsf") { + return "sans-serif"; + } else if (font === "mathtt") { + return "monospace"; + } + + var text = group.text; + + if (utils.contains(["\\imath", "\\jmath"], text)) { + return null; + } + + if (symbols[mode][text] && symbols[mode][text].replace) { + text = symbols[mode][text].replace; + } + + var fontName = buildCommon.fontMap[font].fontName; + + if (getCharacterMetrics(text, fontName, mode)) { + return buildCommon.fontMap[font].variant; + } + + return null; +}; +/** + * Check for . which is how a dot renders in MathML, + * or , + * which is how a braced comma {,} renders in MathML + */ + +function isNumberPunctuation(group) { + if (!group) { + return false; + } + + if (group.type === 'mi' && group.children.length === 1) { + var child = group.children[0]; + return child instanceof TextNode && child.text === '.'; + } else if (group.type === 'mo' && group.children.length === 1 && group.getAttribute('separator') === 'true' && group.getAttribute('lspace') === '0em' && group.getAttribute('rspace') === '0em') { + var _child = group.children[0]; + return _child instanceof TextNode && _child.text === ','; + } else { + return false; + } +} +/** + * Takes a list of nodes, builds them, and returns a list of the generated + * MathML nodes. Also combine consecutive outputs into a single + * tag. + */ + + +var buildExpression = function buildExpression(expression, options, isOrdgroup) { + if (expression.length === 1) { + var group = buildGroup(expression[0], options); + + if (isOrdgroup && group instanceof MathNode && group.type === "mo") { + // When TeX writers want to suppress spacing on an operator, + // they often put the operator by itself inside braces. + group.setAttribute("lspace", "0em"); + group.setAttribute("rspace", "0em"); + } + + return [group]; + } + + var groups = []; + var lastGroup; + + for (var i = 0; i < expression.length; i++) { + var _group = buildGroup(expression[i], options); + + if (_group instanceof MathNode && lastGroup instanceof MathNode) { + // Concatenate adjacent s + if (_group.type === 'mtext' && lastGroup.type === 'mtext' && _group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) { + lastGroup.children.push(..._group.children); + continue; // Concatenate adjacent s + } else if (_group.type === 'mn' && lastGroup.type === 'mn') { + lastGroup.children.push(..._group.children); + continue; // Concatenate ... followed by . + } else if (isNumberPunctuation(_group) && lastGroup.type === 'mn') { + lastGroup.children.push(..._group.children); + continue; // Concatenate . followed by ... + } else if (_group.type === 'mn' && isNumberPunctuation(lastGroup)) { + _group.children = [...lastGroup.children, ..._group.children]; + groups.pop(); // Put preceding ... or . inside base of + // ...base......exponent... (or ) + } else if ((_group.type === 'msup' || _group.type === 'msub') && _group.children.length >= 1 && (lastGroup.type === 'mn' || isNumberPunctuation(lastGroup))) { + var base = _group.children[0]; + + if (base instanceof MathNode && base.type === 'mn') { + base.children = [...lastGroup.children, ...base.children]; + groups.pop(); + } // \not + + } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) { + var lastChild = lastGroup.children[0]; + + if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (_group.type === 'mo' || _group.type === 'mi' || _group.type === 'mn')) { + var child = _group.children[0]; + + if (child instanceof TextNode && child.text.length > 0) { + // Overlay with combining character long solidus + child.text = child.text.slice(0, 1) + "\u0338" + child.text.slice(1); + groups.pop(); + } + } + } + } + + groups.push(_group); + lastGroup = _group; + } + + return groups; +}; +/** + * Equivalent to buildExpression, but wraps the elements in an + * if there's more than one. Returns a single node instead of an array. + */ + +var buildExpressionRow = function buildExpressionRow(expression, options, isOrdgroup) { + return makeRow(buildExpression(expression, options, isOrdgroup)); +}; +/** + * Takes a group from the parser and calls the appropriate groupBuilders function + * on it to produce a MathML node. + */ + +var buildGroup = function buildGroup(group, options) { + if (!group) { + return new mathMLTree.MathNode("mrow"); + } + + if (_mathmlGroupBuilders[group.type]) { + // Call the groupBuilders function + // $FlowFixMe + var result = _mathmlGroupBuilders[group.type](group, options); // $FlowFixMe + + return result; + } else { + throw new ParseError("Got group of unknown type: '" + group.type + "'"); + } +}; +/** + * Takes a full parse tree and settings and builds a MathML representation of + * it. In particular, we put the elements from building the parse tree into a + * tag so we can also include that TeX source as an annotation. + * + * Note that we actually return a domTree element with a `` inside it so + * we can do appropriate styling. + */ + +function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly) { + var expression = buildExpression(tree, options); // TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes + // and add spacing nodes. This is necessary only adjacent to math operators + // like \sin or \lim or to subsup elements that contain math operators. + // MathML takes care of the other spacing issues. + // Wrap up the expression in an mrow so it is presented in the semantics + // tag correctly, unless it's a single or . + + var wrapper; + + if (expression.length === 1 && expression[0] instanceof MathNode && utils.contains(["mrow", "mtable"], expression[0].type)) { + wrapper = expression[0]; + } else { + wrapper = new mathMLTree.MathNode("mrow", expression); + } // Build a TeX annotation of the source + + + var annotation = new mathMLTree.MathNode("annotation", [new mathMLTree.TextNode(texExpression)]); + annotation.setAttribute("encoding", "application/x-tex"); + var semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); + var math = new mathMLTree.MathNode("math", [semantics]); + math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); + + if (isDisplayMode) { + math.setAttribute("display", "block"); + } // You can't style nodes, so we wrap the node in a span. + // NOTE: The span class is not typed to have nodes as children, and + // we don't want to make the children type more generic since the children + // of span are expected to have more fields in `buildHtml` contexts. + + + var wrapperClass = forMathmlOnly ? "katex" : "katex-mathml"; // $FlowFixMe + + return buildCommon.makeSpan([wrapperClass], [math]); +} + +var optionsFromSettings = function optionsFromSettings(settings) { + return new Options({ + style: settings.displayMode ? Style$1.DISPLAY : Style$1.TEXT, + maxSize: settings.maxSize, + minRuleThickness: settings.minRuleThickness + }); +}; + +var displayWrap = function displayWrap(node, settings) { + if (settings.displayMode) { + var classes = ["katex-display"]; + + if (settings.leqno) { + classes.push("leqno"); + } + + if (settings.fleqn) { + classes.push("fleqn"); + } + + node = buildCommon.makeSpan(classes, [node]); + } + + return node; +}; + +var buildTree = function buildTree(tree, expression, settings) { + var options = optionsFromSettings(settings); + var katexNode; + + if (settings.output === "mathml") { + return buildMathML(tree, expression, options, settings.displayMode, true); + } else if (settings.output === "html") { + var htmlNode = buildHTML(tree, options); + katexNode = buildCommon.makeSpan(["katex"], [htmlNode]); + } else { + var mathMLNode = buildMathML(tree, expression, options, settings.displayMode, false); + + var _htmlNode = buildHTML(tree, options); + + katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, _htmlNode]); + } + + return displayWrap(katexNode, settings); +}; +var buildHTMLTree = function buildHTMLTree(tree, expression, settings) { + var options = optionsFromSettings(settings); + var htmlNode = buildHTML(tree, options); + var katexNode = buildCommon.makeSpan(["katex"], [htmlNode]); + return displayWrap(katexNode, settings); +}; + +/** + * This file provides support to buildMathML.js and buildHTML.js + * for stretchy wide elements rendered from SVG files + * and other CSS trickery. + */ +var stretchyCodePoint = { + widehat: "^", + widecheck: "ˇ", + widetilde: "~", + utilde: "~", + overleftarrow: "\u2190", + underleftarrow: "\u2190", + xleftarrow: "\u2190", + overrightarrow: "\u2192", + underrightarrow: "\u2192", + xrightarrow: "\u2192", + underbrace: "\u23df", + overbrace: "\u23de", + overgroup: "\u23e0", + undergroup: "\u23e1", + overleftrightarrow: "\u2194", + underleftrightarrow: "\u2194", + xleftrightarrow: "\u2194", + Overrightarrow: "\u21d2", + xRightarrow: "\u21d2", + overleftharpoon: "\u21bc", + xleftharpoonup: "\u21bc", + overrightharpoon: "\u21c0", + xrightharpoonup: "\u21c0", + xLeftarrow: "\u21d0", + xLeftrightarrow: "\u21d4", + xhookleftarrow: "\u21a9", + xhookrightarrow: "\u21aa", + xmapsto: "\u21a6", + xrightharpoondown: "\u21c1", + xleftharpoondown: "\u21bd", + xrightleftharpoons: "\u21cc", + xleftrightharpoons: "\u21cb", + xtwoheadleftarrow: "\u219e", + xtwoheadrightarrow: "\u21a0", + xlongequal: "=", + xtofrom: "\u21c4", + xrightleftarrows: "\u21c4", + xrightequilibrium: "\u21cc", + // Not a perfect match. + xleftequilibrium: "\u21cb", + // None better available. + "\\cdrightarrow": "\u2192", + "\\cdleftarrow": "\u2190", + "\\cdlongequal": "=" +}; + +var mathMLnode = function mathMLnode(label) { + var node = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(stretchyCodePoint[label.replace(/^\\/, '')])]); + node.setAttribute("stretchy", "true"); + return node; +}; // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts. +// Copyright (c) 2009-2010, Design Science, Inc. () +// Copyright (c) 2014-2017 Khan Academy () +// Licensed under the SIL Open Font License, Version 1.1. +// See \nhttp://scripts.sil.org/OFL +// Very Long SVGs +// Many of the KaTeX stretchy wide elements use a long SVG image and an +// overflow: hidden tactic to achieve a stretchy image while avoiding +// distortion of arrowheads or brace corners. +// The SVG typically contains a very long (400 em) arrow. +// The SVG is in a container span that has overflow: hidden, so the span +// acts like a window that exposes only part of the SVG. +// The SVG always has a longer, thinner aspect ratio than the container span. +// After the SVG fills 100% of the height of the container span, +// there is a long arrow shaft left over. That left-over shaft is not shown. +// Instead, it is sliced off because the span's CSS has overflow: hidden. +// Thus, the reader sees an arrow that matches the subject matter width +// without distortion. +// Some functions, such as \cancel, need to vary their aspect ratio. These +// functions do not get the overflow SVG treatment. +// Second Brush Stroke +// Low resolution monitors struggle to display images in fine detail. +// So browsers apply anti-aliasing. A long straight arrow shaft therefore +// will sometimes appear as if it has a blurred edge. +// To mitigate this, these SVG files contain a second "brush-stroke" on the +// arrow shafts. That is, a second long thin rectangular SVG path has been +// written directly on top of each arrow shaft. This reinforcement causes +// some of the screen pixels to display as black instead of the anti-aliased +// gray pixel that a single path would generate. So we get arrow shafts +// whose edges appear to be sharper. +// In the katexImagesData object just below, the dimensions all +// correspond to path geometry inside the relevant SVG. +// For example, \overrightarrow uses the same arrowhead as glyph U+2192 +// from the KaTeX Main font. The scaling factor is 1000. +// That is, inside the font, that arrowhead is 522 units tall, which +// corresponds to 0.522 em inside the document. + + +var katexImagesData = { + // path(s), minWidth, height, align + overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], + overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], + underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], + underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], + xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"], + "\\cdrightarrow": [["rightarrow"], 3.0, 522, "xMaxYMin"], + // CD minwwidth2.5pc + xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"], + "\\cdleftarrow": [["leftarrow"], 3.0, 522, "xMinYMin"], + Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"], + xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"], + xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"], + overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"], + xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"], + xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"], + overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"], + xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"], + xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"], + xlongequal: [["longequal"], 0.888, 334, "xMinYMin"], + "\\cdlongequal": [["longequal"], 3.0, 334, "xMinYMin"], + xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"], + xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"], + overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], + overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548], + underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548], + underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], + xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522], + xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560], + xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716], + xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716], + xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522], + xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522], + overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], + underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], + overgroup: [["leftgroup", "rightgroup"], 0.888, 342], + undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342], + xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522], + xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528], + // The next three arrows are from the mhchem package. + // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the + // document as \xrightarrow or \xrightleftharpoons. Those have + // min-length = 1.75em, so we set min-length on these next three to match. + xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901], + xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716], + xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716] +}; + +var groupLength = function groupLength(arg) { + if (arg.type === "ordgroup") { + return arg.body.length; + } else { + return 1; + } +}; + +var svgSpan = function svgSpan(group, options) { + // Create a span with inline SVG for the element. + function buildSvgSpan_() { + var viewBoxWidth = 400000; // default + + var label = group.label.slice(1); + + if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) { + // Each type in the `if` statement corresponds to one of the ParseNode + // types below. This narrowing is required to access `grp.base`. + // $FlowFixMe + var grp = group; // There are four SVG images available for each function. + // Choose a taller image when there are more characters. + + var numChars = groupLength(grp.base); + var viewBoxHeight; + var pathName; + + var _height; + + if (numChars > 5) { + if (label === "widehat" || label === "widecheck") { + viewBoxHeight = 420; + viewBoxWidth = 2364; + _height = 0.42; + pathName = label + "4"; + } else { + viewBoxHeight = 312; + viewBoxWidth = 2340; + _height = 0.34; + pathName = "tilde4"; + } + } else { + var imgIndex = [1, 1, 2, 2, 3, 3][numChars]; + + if (label === "widehat" || label === "widecheck") { + viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex]; + viewBoxHeight = [0, 239, 300, 360, 420][imgIndex]; + _height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex]; + pathName = label + imgIndex; + } else { + viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex]; + viewBoxHeight = [0, 260, 286, 306, 312][imgIndex]; + _height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex]; + pathName = "tilde" + imgIndex; + } + } + + var path = new PathNode(pathName); + var svgNode = new SvgNode([path], { + "width": "100%", + "height": makeEm(_height), + "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight, + "preserveAspectRatio": "none" + }); + return { + span: buildCommon.makeSvgSpan([], [svgNode], options), + minWidth: 0, + height: _height + }; + } else { + var spans = []; + var data = katexImagesData[label]; + var [paths, _minWidth, _viewBoxHeight] = data; + + var _height2 = _viewBoxHeight / 1000; + + var numSvgChildren = paths.length; + var widthClasses; + var aligns; + + if (numSvgChildren === 1) { + // $FlowFixMe: All these cases must be of the 4-tuple type. + var align1 = data[3]; + widthClasses = ["hide-tail"]; + aligns = [align1]; + } else if (numSvgChildren === 2) { + widthClasses = ["halfarrow-left", "halfarrow-right"]; + aligns = ["xMinYMin", "xMaxYMin"]; + } else if (numSvgChildren === 3) { + widthClasses = ["brace-left", "brace-center", "brace-right"]; + aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"]; + } else { + throw new Error("Correct katexImagesData or update code here to support\n " + numSvgChildren + " children."); + } + + for (var i = 0; i < numSvgChildren; i++) { + var _path = new PathNode(paths[i]); + + var _svgNode = new SvgNode([_path], { + "width": "400em", + "height": makeEm(_height2), + "viewBox": "0 0 " + viewBoxWidth + " " + _viewBoxHeight, + "preserveAspectRatio": aligns[i] + " slice" + }); + + var _span = buildCommon.makeSvgSpan([widthClasses[i]], [_svgNode], options); + + if (numSvgChildren === 1) { + return { + span: _span, + minWidth: _minWidth, + height: _height2 + }; + } else { + _span.style.height = makeEm(_height2); + spans.push(_span); + } + } + + return { + span: buildCommon.makeSpan(["stretchy"], spans, options), + minWidth: _minWidth, + height: _height2 + }; + } + } // buildSvgSpan_() + + + var { + span, + minWidth, + height + } = buildSvgSpan_(); // Note that we are returning span.depth = 0. + // Any adjustments relative to the baseline must be done in buildHTML. + + span.height = height; + span.style.height = makeEm(height); + + if (minWidth > 0) { + span.style.minWidth = makeEm(minWidth); + } + + return span; +}; + +var encloseSpan = function encloseSpan(inner, label, topPad, bottomPad, options) { + // Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl + var img; + var totalHeight = inner.height + inner.depth + topPad + bottomPad; + + if (/fbox|color|angl/.test(label)) { + img = buildCommon.makeSpan(["stretchy", label], [], options); + + if (label === "fbox") { + var color = options.color && options.getColor(); + + if (color) { + img.style.borderColor = color; + } + } + } else { + // \cancel, \bcancel, or \xcancel + // Since \cancel's SVG is inline and it omits the viewBox attribute, + // its stroke-width will not vary with span area. + var lines = []; + + if (/^[bx]cancel$/.test(label)) { + lines.push(new LineNode({ + "x1": "0", + "y1": "0", + "x2": "100%", + "y2": "100%", + "stroke-width": "0.046em" + })); + } + + if (/^x?cancel$/.test(label)) { + lines.push(new LineNode({ + "x1": "0", + "y1": "100%", + "x2": "100%", + "y2": "0", + "stroke-width": "0.046em" + })); + } + + var svgNode = new SvgNode(lines, { + "width": "100%", + "height": makeEm(totalHeight) + }); + img = buildCommon.makeSvgSpan([], [svgNode], options); + } + + img.height = totalHeight; + img.style.height = makeEm(totalHeight); + return img; +}; + +var stretchy = { + encloseSpan, + mathMLnode, + svgSpan +}; + +/** + * Asserts that the node is of the given type and returns it with stricter + * typing. Throws if the node's type does not match. + */ +function assertNodeType(node, type) { + if (!node || node.type !== type) { + throw new Error("Expected node of type " + type + ", but got " + (node ? "node of type " + node.type : String(node))); + } // $FlowFixMe, >=0.125 + + + return node; +} +/** + * Returns the node more strictly typed iff it is of the given type. Otherwise, + * returns null. + */ + +function assertSymbolNodeType(node) { + var typedNode = checkSymbolNodeType(node); + + if (!typedNode) { + throw new Error("Expected node of symbol group type, but got " + (node ? "node of type " + node.type : String(node))); + } + + return typedNode; +} +/** + * Returns the node more strictly typed iff it is of the given type. Otherwise, + * returns null. + */ + +function checkSymbolNodeType(node) { + if (node && (node.type === "atom" || NON_ATOMS.hasOwnProperty(node.type))) { + // $FlowFixMe + return node; + } + + return null; +} + +// NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but +// also "supsub" since an accent can affect super/subscripting. +var htmlBuilder$a = (grp, options) => { + // Accents are handled in the TeXbook pg. 443, rule 12. + var base; + var group; + var supSubGroup; + + if (grp && grp.type === "supsub") { + // If our base is a character box, and we have superscripts and + // subscripts, the supsub will defer to us. In particular, we want + // to attach the superscripts and subscripts to the inner body (so + // that the position of the superscripts and subscripts won't be + // affected by the height of the accent). We accomplish this by + // sticking the base of the accent into the base of the supsub, and + // rendering that, while keeping track of where the accent is. + // The real accent group is the base of the supsub group + group = assertNodeType(grp.base, "accent"); // The character box is the base of the accent group + + base = group.base; // Stick the character box into the base of the supsub group + + grp.base = base; // Rerender the supsub group with its new base, and store that + // result. + + supSubGroup = assertSpan(buildGroup$1(grp, options)); // reset original base + + grp.base = group; + } else { + group = assertNodeType(grp, "accent"); + base = group.base; + } // Build the base group + + + var body = buildGroup$1(base, options.havingCrampedStyle()); // Does the accent need to shift for the skew of a character? + + var mustShift = group.isShifty && utils.isCharacterBox(base); // Calculate the skew of the accent. This is based on the line "If the + // nucleus is not a single character, let s = 0; otherwise set s to the + // kern amount for the nucleus followed by the \skewchar of its font." + // Note that our skew metrics are just the kern between each character + // and the skewchar. + + var skew = 0; + + if (mustShift) { + // If the base is a character box, then we want the skew of the + // innermost character. To do that, we find the innermost character: + var baseChar = utils.getBaseElem(base); // Then, we render its group to get the symbol inside it + + var baseGroup = buildGroup$1(baseChar, options.havingCrampedStyle()); // Finally, we pull the skew off of the symbol. + + skew = assertSymbolDomNode(baseGroup).skew; // Note that we now throw away baseGroup, because the layers we + // removed with getBaseElem might contain things like \color which + // we can't get rid of. + // TODO(emily): Find a better way to get the skew + } + + var accentBelow = group.label === "\\c"; // calculate the amount of space between the body and the accent + + var clearance = accentBelow ? body.height + body.depth : Math.min(body.height, options.fontMetrics().xHeight); // Build the accent + + var accentBody; + + if (!group.isStretchy) { + var accent; + var width; + + if (group.label === "\\vec") { + // Before version 0.9, \vec used the combining font glyph U+20D7. + // But browsers, especially Safari, are not consistent in how they + // render combining characters when not preceded by a character. + // So now we use an SVG. + // If Safari reforms, we should consider reverting to the glyph. + accent = buildCommon.staticSvg("vec", options); + width = buildCommon.svgData.vec[1]; + } else { + accent = buildCommon.makeOrd({ + mode: group.mode, + text: group.label + }, options, "textord"); + accent = assertSymbolDomNode(accent); // Remove the italic correction of the accent, because it only serves to + // shift the accent over to a place we don't want. + + accent.italic = 0; + width = accent.width; + + if (accentBelow) { + clearance += accent.depth; + } + } + + accentBody = buildCommon.makeSpan(["accent-body"], [accent]); // "Full" accents expand the width of the resulting symbol to be + // at least the width of the accent, and overlap directly onto the + // character without any vertical offset. + + var accentFull = group.label === "\\textcircled"; + + if (accentFull) { + accentBody.classes.push('accent-full'); + clearance = body.height; + } // Shift the accent over by the skew. + + + var left = skew; // CSS defines `.katex .accent .accent-body:not(.accent-full) { width: 0 }` + // so that the accent doesn't contribute to the bounding box. + // We need to shift the character by its width (effectively half + // its width) to compensate. + + if (!accentFull) { + left -= width / 2; + } + + accentBody.style.left = makeEm(left); // \textcircled uses the \bigcirc glyph, so it needs some + // vertical adjustment to match LaTeX. + + if (group.label === "\\textcircled") { + accentBody.style.top = ".2em"; + } + + accentBody = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: body + }, { + type: "kern", + size: -clearance + }, { + type: "elem", + elem: accentBody + }] + }, options); + } else { + accentBody = stretchy.svgSpan(group, options); + accentBody = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: body + }, { + type: "elem", + elem: accentBody, + wrapperClasses: ["svg-align"], + wrapperStyle: skew > 0 ? { + width: "calc(100% - " + makeEm(2 * skew) + ")", + marginLeft: makeEm(2 * skew) + } : undefined + }] + }, options); + } + + var accentWrap = buildCommon.makeSpan(["mord", "accent"], [accentBody], options); + + if (supSubGroup) { + // Here, we replace the "base" child of the supsub with our newly + // generated accent. + supSubGroup.children[0] = accentWrap; // Since we don't rerun the height calculation after replacing the + // accent, we manually recalculate height. + + supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height); // Accents should always be ords, even when their innards are not. + + supSubGroup.classes[0] = "mord"; + return supSubGroup; + } else { + return accentWrap; + } +}; + +var mathmlBuilder$9 = (group, options) => { + var accentNode = group.isStretchy ? stretchy.mathMLnode(group.label) : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); + var node = new mathMLTree.MathNode("mover", [buildGroup(group.base, options), accentNode]); + node.setAttribute("accent", "true"); + return node; +}; + +var NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => "\\" + accent).join("|")); // Accents + +defineFunction({ + type: "accent", + names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"], + props: { + numArgs: 1 + }, + handler: (context, args) => { + var base = normalizeArgument(args[0]); + var isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); + var isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck"; + return { + type: "accent", + mode: context.parser.mode, + label: context.funcName, + isStretchy: isStretchy, + isShifty: isShifty, + base: base + }; + }, + htmlBuilder: htmlBuilder$a, + mathmlBuilder: mathmlBuilder$9 +}); // Text-mode accents + +defineFunction({ + type: "accent", + names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\c", "\\r", "\\H", "\\v", "\\textcircled"], + props: { + numArgs: 1, + allowedInText: true, + allowedInMath: true, + // unless in strict mode + argTypes: ["primitive"] + }, + handler: (context, args) => { + var base = args[0]; + var mode = context.parser.mode; + + if (mode === "math") { + context.parser.settings.reportNonstrict("mathVsTextAccents", "LaTeX's accent " + context.funcName + " works only in text mode"); + mode = "text"; + } + + return { + type: "accent", + mode: mode, + label: context.funcName, + isStretchy: false, + isShifty: true, + base: base + }; + }, + htmlBuilder: htmlBuilder$a, + mathmlBuilder: mathmlBuilder$9 +}); + +// Horizontal overlap functions +defineFunction({ + type: "accentUnder", + names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"], + props: { + numArgs: 1 + }, + handler: (_ref, args) => { + var { + parser, + funcName + } = _ref; + var base = args[0]; + return { + type: "accentUnder", + mode: parser.mode, + label: funcName, + base: base + }; + }, + htmlBuilder: (group, options) => { + // Treat under accents much like underlines. + var innerGroup = buildGroup$1(group.base, options); + var accentBody = stretchy.svgSpan(group, options); + var kern = group.label === "\\utilde" ? 0.12 : 0; // Generate the vlist, with the appropriate kerns + + var vlist = buildCommon.makeVList({ + positionType: "top", + positionData: innerGroup.height, + children: [{ + type: "elem", + elem: accentBody, + wrapperClasses: ["svg-align"] + }, { + type: "kern", + size: kern + }, { + type: "elem", + elem: innerGroup + }] + }, options); + return buildCommon.makeSpan(["mord", "accentunder"], [vlist], options); + }, + mathmlBuilder: (group, options) => { + var accentNode = stretchy.mathMLnode(group.label); + var node = new mathMLTree.MathNode("munder", [buildGroup(group.base, options), accentNode]); + node.setAttribute("accentunder", "true"); + return node; + } +}); + +// Helper function +var paddedNode = group => { + var node = new mathMLTree.MathNode("mpadded", group ? [group] : []); + node.setAttribute("width", "+0.6em"); + node.setAttribute("lspace", "0.3em"); + return node; +}; // Stretchy arrows with an optional argument + + +defineFunction({ + type: "xArrow", + names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom", // The next 3 functions are here to support the mhchem extension. + // Direct use of these functions is discouraged and may break someday. + "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", // The next 3 functions are here only to support the {CD} environment. + "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"], + props: { + numArgs: 1, + numOptionalArgs: 1 + }, + + handler(_ref, args, optArgs) { + var { + parser, + funcName + } = _ref; + return { + type: "xArrow", + mode: parser.mode, + label: funcName, + body: args[0], + below: optArgs[0] + }; + }, + + // Flow is unable to correctly infer the type of `group`, even though it's + // unambiguously determined from the passed-in `type` above. + htmlBuilder(group, options) { + var style = options.style; // Build the argument groups in the appropriate style. + // Ref: amsmath.dtx: \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}% + // Some groups can return document fragments. Handle those by wrapping + // them in a span. + + var newOptions = options.havingStyle(style.sup()); + var upperGroup = buildCommon.wrapFragment(buildGroup$1(group.body, newOptions, options), options); + var arrowPrefix = group.label.slice(0, 2) === "\\x" ? "x" : "cd"; + upperGroup.classes.push(arrowPrefix + "-arrow-pad"); + var lowerGroup; + + if (group.below) { + // Build the lower group + newOptions = options.havingStyle(style.sub()); + lowerGroup = buildCommon.wrapFragment(buildGroup$1(group.below, newOptions, options), options); + lowerGroup.classes.push(arrowPrefix + "-arrow-pad"); + } + + var arrowBody = stretchy.svgSpan(group, options); // Re shift: Note that stretchy.svgSpan returned arrowBody.depth = 0. + // The point we want on the math axis is at 0.5 * arrowBody.height. + + var arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height; // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi + + var upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu + + if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") { + upperShift -= upperGroup.depth; // shift up if depth encroaches + } // Generate the vlist + + + var vlist; + + if (lowerGroup) { + var lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111; + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: upperGroup, + shift: upperShift + }, { + type: "elem", + elem: arrowBody, + shift: arrowShift + }, { + type: "elem", + elem: lowerGroup, + shift: lowerShift + }] + }, options); + } else { + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: upperGroup, + shift: upperShift + }, { + type: "elem", + elem: arrowBody, + shift: arrowShift + }] + }, options); + } // $FlowFixMe: Replace this with passing "svg-align" into makeVList. + + + vlist.children[0].children[0].children[1].classes.push("svg-align"); + return buildCommon.makeSpan(["mrel", "x-arrow"], [vlist], options); + }, + + mathmlBuilder(group, options) { + var arrowNode = stretchy.mathMLnode(group.label); + arrowNode.setAttribute("minsize", group.label.charAt(0) === "x" ? "1.75em" : "3.0em"); + var node; + + if (group.body) { + var upperNode = paddedNode(buildGroup(group.body, options)); + + if (group.below) { + var lowerNode = paddedNode(buildGroup(group.below, options)); + node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); + } else { + node = new mathMLTree.MathNode("mover", [arrowNode, upperNode]); + } + } else if (group.below) { + var _lowerNode = paddedNode(buildGroup(group.below, options)); + + node = new mathMLTree.MathNode("munder", [arrowNode, _lowerNode]); + } else { + // This should never happen. + // Parser.js throws an error if there is no argument. + node = paddedNode(); + node = new mathMLTree.MathNode("mover", [arrowNode, node]); + } + + return node; + } + +}); + +var makeSpan = buildCommon.makeSpan; + +function htmlBuilder$9(group, options) { + var elements = buildExpression$1(group.body, options, true); + return makeSpan([group.mclass], elements, options); +} + +function mathmlBuilder$8(group, options) { + var node; + var inner = buildExpression(group.body, options); + + if (group.mclass === "minner") { + node = new mathMLTree.MathNode("mpadded", inner); + } else if (group.mclass === "mord") { + if (group.isCharacterBox) { + node = inner[0]; + node.type = "mi"; + } else { + node = new mathMLTree.MathNode("mi", inner); + } + } else { + if (group.isCharacterBox) { + node = inner[0]; + node.type = "mo"; + } else { + node = new mathMLTree.MathNode("mo", inner); + } // Set spacing based on what is the most likely adjacent atom type. + // See TeXbook p170. + + + if (group.mclass === "mbin") { + node.attributes.lspace = "0.22em"; // medium space + + node.attributes.rspace = "0.22em"; + } else if (group.mclass === "mpunct") { + node.attributes.lspace = "0em"; + node.attributes.rspace = "0.17em"; // thinspace + } else if (group.mclass === "mopen" || group.mclass === "mclose") { + node.attributes.lspace = "0em"; + node.attributes.rspace = "0em"; + } else if (group.mclass === "minner") { + node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option + + node.attributes.width = "+0.1111em"; + } // MathML default space is 5/18 em, so needs no action. + // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo + + } + + return node; +} // Math class commands except \mathop + + +defineFunction({ + type: "mclass", + names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"], + props: { + numArgs: 1, + primitive: true + }, + + handler(_ref, args) { + var { + parser, + funcName + } = _ref; + var body = args[0]; + return { + type: "mclass", + mode: parser.mode, + mclass: "m" + funcName.slice(5), + // TODO(kevinb): don't prefix with 'm' + body: ordargument(body), + isCharacterBox: utils.isCharacterBox(body) + }; + }, + + htmlBuilder: htmlBuilder$9, + mathmlBuilder: mathmlBuilder$8 +}); +var binrelClass = arg => { + // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. + // (by rendering separately and with {}s before and after, and measuring + // the change in spacing). We'll do roughly the same by detecting the + // atom type directly. + var atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; + + if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { + return "m" + atom.family; + } else { + return "mord"; + } +}; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. +// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. + +defineFunction({ + type: "mclass", + names: ["\\@binrel"], + props: { + numArgs: 2 + }, + + handler(_ref2, args) { + var { + parser + } = _ref2; + return { + type: "mclass", + mode: parser.mode, + mclass: binrelClass(args[0]), + body: ordargument(args[1]), + isCharacterBox: utils.isCharacterBox(args[1]) + }; + } + +}); // Build a relation or stacked op by placing one symbol on top of another + +defineFunction({ + type: "mclass", + names: ["\\stackrel", "\\overset", "\\underset"], + props: { + numArgs: 2 + }, + + handler(_ref3, args) { + var { + parser, + funcName + } = _ref3; + var baseArg = args[1]; + var shiftedArg = args[0]; + var mclass; + + if (funcName !== "\\stackrel") { + // LaTeX applies \binrel spacing to \overset and \underset. + mclass = binrelClass(baseArg); + } else { + mclass = "mrel"; // for \stackrel + } + + var baseOp = { + type: "op", + mode: baseArg.mode, + limits: true, + alwaysHandleSupSub: true, + parentIsSupSub: false, + symbol: false, + suppressBaseShift: funcName !== "\\stackrel", + body: ordargument(baseArg) + }; + var supsub = { + type: "supsub", + mode: shiftedArg.mode, + base: baseOp, + sup: funcName === "\\underset" ? null : shiftedArg, + sub: funcName === "\\underset" ? shiftedArg : null + }; + return { + type: "mclass", + mode: parser.mode, + mclass, + body: [supsub], + isCharacterBox: utils.isCharacterBox(supsub) + }; + }, + + htmlBuilder: htmlBuilder$9, + mathmlBuilder: mathmlBuilder$8 +}); + +// \pmb is a simulation of bold font. +// The version of \pmb in ambsy.sty works by typesetting three copies +// with small offsets. We use CSS text-shadow. +// It's a hack. Not as good as a real bold font. Better than nothing. +defineFunction({ + type: "pmb", + names: ["\\pmb"], + props: { + numArgs: 1, + allowedInText: true + }, + + handler(_ref, args) { + var { + parser + } = _ref; + return { + type: "pmb", + mode: parser.mode, + mclass: binrelClass(args[0]), + body: ordargument(args[0]) + }; + }, + + htmlBuilder(group, options) { + var elements = buildExpression$1(group.body, options, true); + var node = buildCommon.makeSpan([group.mclass], elements, options); + node.style.textShadow = "0.02em 0.01em 0.04px"; + return node; + }, + + mathmlBuilder(group, style) { + var inner = buildExpression(group.body, style); // Wrap with an element. + + var node = new mathMLTree.MathNode("mstyle", inner); + node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"); + return node; + } + +}); + +var cdArrowFunctionName = { + ">": "\\\\cdrightarrow", + "<": "\\\\cdleftarrow", + "=": "\\\\cdlongequal", + "A": "\\uparrow", + "V": "\\downarrow", + "|": "\\Vert", + ".": "no arrow" +}; + +var newCell = () => { + // Create an empty cell, to be filled below with parse nodes. + // The parseTree from this module must be constructed like the + // one created by parseArray(), so an empty CD cell must + // be a ParseNode<"styling">. And CD is always displaystyle. + // So these values are fixed and flow can do implicit typing. + return { + type: "styling", + body: [], + mode: "math", + style: "display" + }; +}; + +var isStartOfArrow = node => { + return node.type === "textord" && node.text === "@"; +}; + +var isLabelEnd = (node, endChar) => { + return (node.type === "mathord" || node.type === "atom") && node.text === endChar; +}; + +function cdArrow(arrowChar, labels, parser) { + // Return a parse tree of an arrow and its labels. + // This acts in a way similar to a macro expansion. + var funcName = cdArrowFunctionName[arrowChar]; + + switch (funcName) { + case "\\\\cdrightarrow": + case "\\\\cdleftarrow": + return parser.callFunction(funcName, [labels[0]], [labels[1]]); + + case "\\uparrow": + case "\\downarrow": + { + var leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); + var bareArrow = { + type: "atom", + text: funcName, + mode: "math", + family: "rel" + }; + var sizedArrow = parser.callFunction("\\Big", [bareArrow], []); + var rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); + var arrowGroup = { + type: "ordgroup", + mode: "math", + body: [leftLabel, sizedArrow, rightLabel] + }; + return parser.callFunction("\\\\cdparent", [arrowGroup], []); + } + + case "\\\\cdlongequal": + return parser.callFunction("\\\\cdlongequal", [], []); + + case "\\Vert": + { + var arrow = { + type: "textord", + text: "\\Vert", + mode: "math" + }; + return parser.callFunction("\\Big", [arrow], []); + } + + default: + return { + type: "textord", + text: " ", + mode: "math" + }; + } +} + +function parseCD(parser) { + // Get the array's parse nodes with \\ temporarily mapped to \cr. + var parsedRows = []; + parser.gullet.beginGroup(); + parser.gullet.macros.set("\\cr", "\\\\\\relax"); + parser.gullet.beginGroup(); + + while (true) { + // eslint-disable-line no-constant-condition + // Get the parse nodes for the next row. + parsedRows.push(parser.parseExpression(false, "\\\\")); + parser.gullet.endGroup(); + parser.gullet.beginGroup(); + var next = parser.fetch().text; + + if (next === "&" || next === "\\\\") { + parser.consume(); + } else if (next === "\\end") { + if (parsedRows[parsedRows.length - 1].length === 0) { + parsedRows.pop(); // final row ended in \\ + } + + break; + } else { + throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); + } + } + + var row = []; + var body = [row]; // Loop thru the parse nodes. Collect them into cells and arrows. + + for (var i = 0; i < parsedRows.length; i++) { + // Start a new row. + var rowNodes = parsedRows[i]; // Create the first cell. + + var cell = newCell(); + + for (var j = 0; j < rowNodes.length; j++) { + if (!isStartOfArrow(rowNodes[j])) { + // If a parseNode is not an arrow, it goes into a cell. + cell.body.push(rowNodes[j]); + } else { + // Parse node j is an "@", the start of an arrow. + // Before starting on the arrow, push the cell into `row`. + row.push(cell); // Now collect parseNodes into an arrow. + // The character after "@" defines the arrow type. + + j += 1; + var arrowChar = assertSymbolNodeType(rowNodes[j]).text; // Create two empty label nodes. We may or may not use them. + + var labels = new Array(2); + labels[0] = { + type: "ordgroup", + mode: "math", + body: [] + }; + labels[1] = { + type: "ordgroup", + mode: "math", + body: [] + }; // Process the arrow. + + if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) { + // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take + // two optional labels. E.g. the right-point arrow syntax is + // really: @>{optional label}>{optional label}> + // Collect parseNodes into labels. + for (var labelNum = 0; labelNum < 2; labelNum++) { + var inLabel = true; + + for (var k = j + 1; k < rowNodes.length; k++) { + if (isLabelEnd(rowNodes[k], arrowChar)) { + inLabel = false; + j = k; + break; + } + + if (isStartOfArrow(rowNodes[k])) { + throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[k]); + } + + labels[labelNum].body.push(rowNodes[k]); + } + + if (inLabel) { + // isLabelEnd never returned a true. + throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[j]); + } + } + } else { + throw new ParseError("Expected one of \"<>AV=|.\" after @", rowNodes[j]); + } // Now join the arrow to its labels. + + + var arrow = cdArrow(arrowChar, labels, parser); // Wrap the arrow in ParseNode<"styling">. + // This is done to match parseArray() behavior. + + var wrappedArrow = { + type: "styling", + body: [arrow], + mode: "math", + style: "display" // CD is always displaystyle. + + }; + row.push(wrappedArrow); // In CD's syntax, cells are implicit. That is, everything that + // is not an arrow gets collected into a cell. So create an empty + // cell now. It will collect upcoming parseNodes. + + cell = newCell(); + } + } + + if (i % 2 === 0) { + // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell + // The last cell is not yet pushed into `row`, so: + row.push(cell); + } else { + // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow + // Remove the empty cell that was placed at the beginning of `row`. + row.shift(); + } + + row = []; + body.push(row); + } // End row group + + + parser.gullet.endGroup(); // End array group defining \\ + + parser.gullet.endGroup(); // define column separation. + + var cols = new Array(body[0].length).fill({ + type: "align", + align: "c", + pregap: 0.25, + // CD package sets \enskip between columns. + postgap: 0.25 // So pre and post each get half an \enskip, i.e. 0.25em. + + }); + return { + type: "array", + mode: "math", + body, + arraystretch: 1, + addJot: true, + rowGaps: [null], + cols, + colSeparationType: "CD", + hLinesBeforeRow: new Array(body.length + 1).fill([]) + }; +} // The functions below are not available for general use. +// They are here only for internal use by the {CD} environment in placing labels +// next to vertical arrows. +// We don't need any such functions for horizontal arrows because we can reuse +// the functionality that already exists for extensible arrows. + +defineFunction({ + type: "cdlabel", + names: ["\\\\cdleft", "\\\\cdright"], + props: { + numArgs: 1 + }, + + handler(_ref, args) { + var { + parser, + funcName + } = _ref; + return { + type: "cdlabel", + mode: parser.mode, + side: funcName.slice(4), + label: args[0] + }; + }, + + htmlBuilder(group, options) { + var newOptions = options.havingStyle(options.style.sup()); + var label = buildCommon.wrapFragment(buildGroup$1(group.label, newOptions, options), options); + label.classes.push("cd-label-" + group.side); + label.style.bottom = makeEm(0.8 - label.depth); // Zero out label height & depth, so vertical align of arrow is set + // by the arrow height, not by the label. + + label.height = 0; + label.depth = 0; + return label; + }, + + mathmlBuilder(group, options) { + var label = new mathMLTree.MathNode("mrow", [buildGroup(group.label, options)]); + label = new mathMLTree.MathNode("mpadded", [label]); + label.setAttribute("width", "0"); + + if (group.side === "left") { + label.setAttribute("lspace", "-1width"); + } // We have to guess at vertical alignment. We know the arrow is 1.8em tall, + // But we don't know the height or depth of the label. + + + label.setAttribute("voffset", "0.7em"); + label = new mathMLTree.MathNode("mstyle", [label]); + label.setAttribute("displaystyle", "false"); + label.setAttribute("scriptlevel", "1"); + return label; + } + +}); +defineFunction({ + type: "cdlabelparent", + names: ["\\\\cdparent"], + props: { + numArgs: 1 + }, + + handler(_ref2, args) { + var { + parser + } = _ref2; + return { + type: "cdlabelparent", + mode: parser.mode, + fragment: args[0] + }; + }, + + htmlBuilder(group, options) { + // Wrap the vertical arrow and its labels. + // The parent gets position: relative. The child gets position: absolute. + // So CSS can locate the label correctly. + var parent = buildCommon.wrapFragment(buildGroup$1(group.fragment, options), options); + parent.classes.push("cd-vert-arrow"); + return parent; + }, + + mathmlBuilder(group, options) { + return new mathMLTree.MathNode("mrow", [buildGroup(group.fragment, options)]); + } + +}); + +// {123} and converts into symbol with code 123. It is used by the *macro* +// \char defined in macros.js. + +defineFunction({ + type: "textord", + names: ["\\@char"], + props: { + numArgs: 1, + allowedInText: true + }, + + handler(_ref, args) { + var { + parser + } = _ref; + var arg = assertNodeType(args[0], "ordgroup"); + var group = arg.body; + var number = ""; + + for (var i = 0; i < group.length; i++) { + var node = assertNodeType(group[i], "textord"); + number += node.text; + } + + var code = parseInt(number); + var text; + + if (isNaN(code)) { + throw new ParseError("\\@char has non-numeric argument " + number); // If we drop IE support, the following code could be replaced with + // text = String.fromCodePoint(code) + } else if (code < 0 || code >= 0x10ffff) { + throw new ParseError("\\@char with invalid code point " + number); + } else if (code <= 0xffff) { + text = String.fromCharCode(code); + } else { + // Astral code point; split into surrogate halves + code -= 0x10000; + text = String.fromCharCode((code >> 10) + 0xd800, (code & 0x3ff) + 0xdc00); + } + + return { + type: "textord", + mode: parser.mode, + text: text + }; + } + +}); + +var htmlBuilder$8 = (group, options) => { + var elements = buildExpression$1(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains. + // To accomplish this, we wrap the results in a fragment, so the inner + // elements will be able to directly interact with their neighbors. For + // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3` + + return buildCommon.makeFragment(elements); +}; + +var mathmlBuilder$7 = (group, options) => { + var inner = buildExpression(group.body, options.withColor(group.color)); + var node = new mathMLTree.MathNode("mstyle", inner); + node.setAttribute("mathcolor", group.color); + return node; +}; + +defineFunction({ + type: "color", + names: ["\\textcolor"], + props: { + numArgs: 2, + allowedInText: true, + argTypes: ["color", "original"] + }, + + handler(_ref, args) { + var { + parser + } = _ref; + var color = assertNodeType(args[0], "color-token").color; + var body = args[1]; + return { + type: "color", + mode: parser.mode, + color, + body: ordargument(body) + }; + }, + + htmlBuilder: htmlBuilder$8, + mathmlBuilder: mathmlBuilder$7 +}); +defineFunction({ + type: "color", + names: ["\\color"], + props: { + numArgs: 1, + allowedInText: true, + argTypes: ["color"] + }, + + handler(_ref2, args) { + var { + parser, + breakOnTokenText + } = _ref2; + var color = assertNodeType(args[0], "color-token").color; // Set macro \current@color in current namespace to store the current + // color, mimicking the behavior of color.sty. + // This is currently used just to correctly color a \right + // that follows a \color command. + + parser.gullet.macros.set("\\current@color", color); // Parse out the implicit body that should be colored. + + var body = parser.parseExpression(true, breakOnTokenText); + return { + type: "color", + mode: parser.mode, + color, + body + }; + }, + + htmlBuilder: htmlBuilder$8, + mathmlBuilder: mathmlBuilder$7 +}); + +// Row breaks within tabular environments, and line breaks at top level + +defineFunction({ + type: "cr", + names: ["\\\\"], + props: { + numArgs: 0, + numOptionalArgs: 0, + allowedInText: true + }, + + handler(_ref, args, optArgs) { + var { + parser + } = _ref; + var size = parser.gullet.future().text === "[" ? parser.parseSizeGroup(true) : null; + var newLine = !parser.settings.displayMode || !parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode"); + return { + type: "cr", + mode: parser.mode, + newLine, + size: size && assertNodeType(size, "size").value + }; + }, + + // The following builders are called only at the top level, + // not within tabular/array environments. + htmlBuilder(group, options) { + var span = buildCommon.makeSpan(["mspace"], [], options); + + if (group.newLine) { + span.classes.push("newline"); + + if (group.size) { + span.style.marginTop = makeEm(calculateSize(group.size, options)); + } + } + + return span; + }, + + mathmlBuilder(group, options) { + var node = new mathMLTree.MathNode("mspace"); + + if (group.newLine) { + node.setAttribute("linebreak", "newline"); + + if (group.size) { + node.setAttribute("height", makeEm(calculateSize(group.size, options))); + } + } + + return node; + } + +}); + +var globalMap = { + "\\global": "\\global", + "\\long": "\\\\globallong", + "\\\\globallong": "\\\\globallong", + "\\def": "\\gdef", + "\\gdef": "\\gdef", + "\\edef": "\\xdef", + "\\xdef": "\\xdef", + "\\let": "\\\\globallet", + "\\futurelet": "\\\\globalfuture" +}; + +var checkControlSequence = tok => { + var name = tok.text; + + if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { + throw new ParseError("Expected a control sequence", tok); + } + + return name; +}; + +var getRHS = parser => { + var tok = parser.gullet.popToken(); + + if (tok.text === "=") { + // consume optional equals + tok = parser.gullet.popToken(); + + if (tok.text === " ") { + // consume one optional space + tok = parser.gullet.popToken(); + } + } + + return tok; +}; + +var letCommand = (parser, name, tok, global) => { + var macro = parser.gullet.macros.get(tok.text); + + if (macro == null) { + // don't expand it later even if a macro with the same name is defined + // e.g., \let\foo=\frac \def\frac{\relax} \frac12 + tok.noexpand = true; + macro = { + tokens: [tok], + numArgs: 0, + // reproduce the same behavior in expansion + unexpandable: !parser.gullet.isExpandable(tok.text) + }; + } + + parser.gullet.macros.set(name, macro, global); +}; // -> | +// -> |\global +// -> | +// -> \global|\long|\outer + + +defineFunction({ + type: "internal", + names: ["\\global", "\\long", "\\\\globallong" // can’t be entered directly + ], + props: { + numArgs: 0, + allowedInText: true + }, + + handler(_ref) { + var { + parser, + funcName + } = _ref; + parser.consumeSpaces(); + var token = parser.fetch(); + + if (globalMap[token.text]) { + // KaTeX doesn't have \par, so ignore \long + if (funcName === "\\global" || funcName === "\\\\globallong") { + token.text = globalMap[token.text]; + } + + return assertNodeType(parser.parseFunction(), "internal"); + } + + throw new ParseError("Invalid token after macro prefix", token); + } + +}); // Basic support for macro definitions: \def, \gdef, \edef, \xdef +// -> +// -> \def|\gdef|\edef|\xdef +// -> + +defineFunction({ + type: "internal", + names: ["\\def", "\\gdef", "\\edef", "\\xdef"], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref2) { + var { + parser, + funcName + } = _ref2; + var tok = parser.gullet.popToken(); + var name = tok.text; + + if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { + throw new ParseError("Expected a control sequence", tok); + } + + var numArgs = 0; + var insert; + var delimiters = [[]]; // contains no braces + + while (parser.gullet.future().text !== "{") { + tok = parser.gullet.popToken(); + + if (tok.text === "#") { + // If the very last character of the is #, so that + // this # is immediately followed by {, TeX will behave as if the { + // had been inserted at the right end of both the parameter text + // and the replacement text. + if (parser.gullet.future().text === "{") { + insert = parser.gullet.future(); + delimiters[numArgs].push("{"); + break; + } // A parameter, the first appearance of # must be followed by 1, + // the next by 2, and so on; up to nine #’s are allowed + + + tok = parser.gullet.popToken(); + + if (!/^[1-9]$/.test(tok.text)) { + throw new ParseError("Invalid argument number \"" + tok.text + "\""); + } + + if (parseInt(tok.text) !== numArgs + 1) { + throw new ParseError("Argument number \"" + tok.text + "\" out of order"); + } + + numArgs++; + delimiters.push([]); + } else if (tok.text === "EOF") { + throw new ParseError("Expected a macro definition"); + } else { + delimiters[numArgs].push(tok.text); + } + } // replacement text, enclosed in '{' and '}' and properly nested + + + var { + tokens + } = parser.gullet.consumeArg(); + + if (insert) { + tokens.unshift(insert); + } + + if (funcName === "\\edef" || funcName === "\\xdef") { + tokens = parser.gullet.expandTokens(tokens); + tokens.reverse(); // to fit in with stack order + } // Final arg is the expansion of the macro + + + parser.gullet.macros.set(name, { + tokens, + numArgs, + delimiters + }, funcName === globalMap[funcName]); + return { + type: "internal", + mode: parser.mode + }; + } + +}); // -> +// -> \futurelet +// | \let +// -> |= + +defineFunction({ + type: "internal", + names: ["\\let", "\\\\globallet" // can’t be entered directly + ], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref3) { + var { + parser, + funcName + } = _ref3; + var name = checkControlSequence(parser.gullet.popToken()); + parser.gullet.consumeSpaces(); + var tok = getRHS(parser); + letCommand(parser, name, tok, funcName === "\\\\globallet"); + return { + type: "internal", + mode: parser.mode + }; + } + +}); // ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf + +defineFunction({ + type: "internal", + names: ["\\futurelet", "\\\\globalfuture" // can’t be entered directly + ], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref4) { + var { + parser, + funcName + } = _ref4; + var name = checkControlSequence(parser.gullet.popToken()); + var middle = parser.gullet.popToken(); + var tok = parser.gullet.popToken(); + letCommand(parser, name, tok, funcName === "\\\\globalfuture"); + parser.gullet.pushToken(tok); + parser.gullet.pushToken(middle); + return { + type: "internal", + mode: parser.mode + }; + } + +}); + +/** + * This file deals with creating delimiters of various sizes. The TeXbook + * discusses these routines on page 441-442, in the "Another subroutine sets box + * x to a specified variable delimiter" paragraph. + * + * There are three main routines here. `makeSmallDelim` makes a delimiter in the + * normal font, but in either text, script, or scriptscript style. + * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1, + * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of + * smaller pieces that are stacked on top of one another. + * + * The functions take a parameter `center`, which determines if the delimiter + * should be centered around the axis. + * + * Then, there are three exposed functions. `sizedDelim` makes a delimiter in + * one of the given sizes. This is used for things like `\bigl`. + * `customSizedDelim` makes a delimiter with a given total height+depth. It is + * called in places like `\sqrt`. `leftRightDelim` makes an appropriate + * delimiter which surrounds an expression of a given height an depth. It is + * used in `\left` and `\right`. + */ + +/** + * Get the metrics for a given symbol and font, after transformation (i.e. + * after following replacement from symbols.js) + */ +var getMetrics = function getMetrics(symbol, font, mode) { + var replace = symbols.math[symbol] && symbols.math[symbol].replace; + var metrics = getCharacterMetrics(replace || symbol, font, mode); + + if (!metrics) { + throw new Error("Unsupported symbol " + symbol + " and font size " + font + "."); + } + + return metrics; +}; +/** + * Puts a delimiter span in a given style, and adds appropriate height, depth, + * and maxFontSizes. + */ + + +var styleWrap = function styleWrap(delim, toStyle, options, classes) { + var newOptions = options.havingBaseStyle(toStyle); + var span = buildCommon.makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options); + var delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier; + span.height *= delimSizeMultiplier; + span.depth *= delimSizeMultiplier; + span.maxFontSize = newOptions.sizeMultiplier; + return span; +}; + +var centerSpan = function centerSpan(span, options, style) { + var newOptions = options.havingBaseStyle(style); + var shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight; + span.classes.push("delimcenter"); + span.style.top = makeEm(shift); + span.height -= shift; + span.depth += shift; +}; +/** + * Makes a small delimiter. This is a delimiter that comes in the Main-Regular + * font, but is restyled to either be in textstyle, scriptstyle, or + * scriptscriptstyle. + */ + + +var makeSmallDelim = function makeSmallDelim(delim, style, center, options, mode, classes) { + var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options); + var span = styleWrap(text, style, options, classes); + + if (center) { + centerSpan(span, options, style); + } + + return span; +}; +/** + * Builds a symbol in the given font size (note size is an integer) + */ + + +var mathrmSize = function mathrmSize(value, size, mode, options) { + return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode, options); +}; +/** + * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2, + * Size3, or Size4 fonts. It is always rendered in textstyle. + */ + + +var makeLargeDelim = function makeLargeDelim(delim, size, center, options, mode, classes) { + var inner = mathrmSize(delim, size, mode, options); + var span = styleWrap(buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options), Style$1.TEXT, options, classes); + + if (center) { + centerSpan(span, options, Style$1.TEXT); + } + + return span; +}; +/** + * Make a span from a font glyph with the given offset and in the given font. + * This is used in makeStackedDelim to make the stacking pieces for the delimiter. + */ + + +var makeGlyphSpan = function makeGlyphSpan(symbol, font, mode) { + var sizeClass; // Apply the correct CSS class to choose the right font. + + if (font === "Size1-Regular") { + sizeClass = "delim-size1"; + } else + /* if (font === "Size4-Regular") */ + { + sizeClass = "delim-size4"; + } + + var corner = buildCommon.makeSpan(["delimsizinginner", sizeClass], [buildCommon.makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); // Since this will be passed into `makeVList` in the end, wrap the element + // in the appropriate tag that VList uses. + + return { + type: "elem", + elem: corner + }; +}; + +var makeInner = function makeInner(ch, height, options) { + // Create a span with inline SVG for the inner part of a tall stacked delimiter. + var width = fontMetricsData['Size4-Regular'][ch.charCodeAt(0)] ? fontMetricsData['Size4-Regular'][ch.charCodeAt(0)][4] : fontMetricsData['Size1-Regular'][ch.charCodeAt(0)][4]; + var path = new PathNode("inner", innerPath(ch, Math.round(1000 * height))); + var svgNode = new SvgNode([path], { + "width": makeEm(width), + "height": makeEm(height), + // Override CSS rule `.katex svg { width: 100% }` + "style": "width:" + makeEm(width), + "viewBox": "0 0 " + 1000 * width + " " + Math.round(1000 * height), + "preserveAspectRatio": "xMinYMin" + }); + var span = buildCommon.makeSvgSpan([], [svgNode], options); + span.height = height; + span.style.height = makeEm(height); + span.style.width = makeEm(width); + return { + type: "elem", + elem: span + }; +}; // Helpers for makeStackedDelim + + +var lapInEms = 0.008; +var lap = { + type: "kern", + size: -1 * lapInEms +}; +var verts = ["|", "\\lvert", "\\rvert", "\\vert"]; +var doubleVerts = ["\\|", "\\lVert", "\\rVert", "\\Vert"]; +/** + * Make a stacked delimiter out of a given delimiter, with the total height at + * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook. + */ + +var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, options, mode, classes) { + // There are four parts, the top, an optional middle, a repeated part, and a + // bottom. + var top; + var middle; + var repeat; + var bottom; + var svgLabel = ""; + var viewBoxWidth = 0; + top = repeat = bottom = delim; + middle = null; // Also keep track of what font the delimiters are in + + var font = "Size1-Regular"; // We set the parts and font based on the symbol. Note that we use + // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the + // repeats of the arrows + + if (delim === "\\uparrow") { + repeat = bottom = "\u23d0"; + } else if (delim === "\\Uparrow") { + repeat = bottom = "\u2016"; + } else if (delim === "\\downarrow") { + top = repeat = "\u23d0"; + } else if (delim === "\\Downarrow") { + top = repeat = "\u2016"; + } else if (delim === "\\updownarrow") { + top = "\\uparrow"; + repeat = "\u23d0"; + bottom = "\\downarrow"; + } else if (delim === "\\Updownarrow") { + top = "\\Uparrow"; + repeat = "\u2016"; + bottom = "\\Downarrow"; + } else if (utils.contains(verts, delim)) { + repeat = "\u2223"; + svgLabel = "vert"; + viewBoxWidth = 333; + } else if (utils.contains(doubleVerts, delim)) { + repeat = "\u2225"; + svgLabel = "doublevert"; + viewBoxWidth = 556; + } else if (delim === "[" || delim === "\\lbrack") { + top = "\u23a1"; + repeat = "\u23a2"; + bottom = "\u23a3"; + font = "Size4-Regular"; + svgLabel = "lbrack"; + viewBoxWidth = 667; + } else if (delim === "]" || delim === "\\rbrack") { + top = "\u23a4"; + repeat = "\u23a5"; + bottom = "\u23a6"; + font = "Size4-Regular"; + svgLabel = "rbrack"; + viewBoxWidth = 667; + } else if (delim === "\\lfloor" || delim === "\u230a") { + repeat = top = "\u23a2"; + bottom = "\u23a3"; + font = "Size4-Regular"; + svgLabel = "lfloor"; + viewBoxWidth = 667; + } else if (delim === "\\lceil" || delim === "\u2308") { + top = "\u23a1"; + repeat = bottom = "\u23a2"; + font = "Size4-Regular"; + svgLabel = "lceil"; + viewBoxWidth = 667; + } else if (delim === "\\rfloor" || delim === "\u230b") { + repeat = top = "\u23a5"; + bottom = "\u23a6"; + font = "Size4-Regular"; + svgLabel = "rfloor"; + viewBoxWidth = 667; + } else if (delim === "\\rceil" || delim === "\u2309") { + top = "\u23a4"; + repeat = bottom = "\u23a5"; + font = "Size4-Regular"; + svgLabel = "rceil"; + viewBoxWidth = 667; + } else if (delim === "(" || delim === "\\lparen") { + top = "\u239b"; + repeat = "\u239c"; + bottom = "\u239d"; + font = "Size4-Regular"; + svgLabel = "lparen"; + viewBoxWidth = 875; + } else if (delim === ")" || delim === "\\rparen") { + top = "\u239e"; + repeat = "\u239f"; + bottom = "\u23a0"; + font = "Size4-Regular"; + svgLabel = "rparen"; + viewBoxWidth = 875; + } else if (delim === "\\{" || delim === "\\lbrace") { + top = "\u23a7"; + middle = "\u23a8"; + bottom = "\u23a9"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\}" || delim === "\\rbrace") { + top = "\u23ab"; + middle = "\u23ac"; + bottom = "\u23ad"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\lgroup" || delim === "\u27ee") { + top = "\u23a7"; + bottom = "\u23a9"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\rgroup" || delim === "\u27ef") { + top = "\u23ab"; + bottom = "\u23ad"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\lmoustache" || delim === "\u23b0") { + top = "\u23a7"; + bottom = "\u23ad"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } else if (delim === "\\rmoustache" || delim === "\u23b1") { + top = "\u23ab"; + bottom = "\u23a9"; + repeat = "\u23aa"; + font = "Size4-Regular"; + } // Get the metrics of the four sections + + + var topMetrics = getMetrics(top, font, mode); + var topHeightTotal = topMetrics.height + topMetrics.depth; + var repeatMetrics = getMetrics(repeat, font, mode); + var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; + var bottomMetrics = getMetrics(bottom, font, mode); + var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; + var middleHeightTotal = 0; + var middleFactor = 1; + + if (middle !== null) { + var middleMetrics = getMetrics(middle, font, mode); + middleHeightTotal = middleMetrics.height + middleMetrics.depth; + middleFactor = 2; // repeat symmetrically above and below middle + } // Calculate the minimal height that the delimiter can have. + // It is at least the size of the top, bottom, and optional middle combined. + + + var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; // Compute the number of copies of the repeat symbol we will need + + var repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal))); // Compute the total height of the delimiter including all the symbols + + var realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // The center of the delimiter is placed at the center of the axis. Note + // that in this context, "center" means that the delimiter should be + // centered around the axis in the current style, while normally it is + // centered around the axis in textstyle. + + var axisHeight = options.fontMetrics().axisHeight; + + if (center) { + axisHeight *= options.sizeMultiplier; + } // Calculate the depth + + + var depth = realHeightTotal / 2 - axisHeight; // Now, we start building the pieces that will go into the vlist + // Keep a list of the pieces of the stacked delimiter + + var stack = []; + + if (svgLabel.length > 0) { + // Instead of stacking glyphs, create a single SVG. + // This evades browser problems with imprecise positioning of spans. + var midHeight = realHeightTotal - topHeightTotal - bottomHeightTotal; + var viewBoxHeight = Math.round(realHeightTotal * 1000); + var pathStr = tallDelim(svgLabel, Math.round(midHeight * 1000)); + var path = new PathNode(svgLabel, pathStr); + var width = (viewBoxWidth / 1000).toFixed(3) + "em"; + var height = (viewBoxHeight / 1000).toFixed(3) + "em"; + var svg = new SvgNode([path], { + "width": width, + "height": height, + "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight + }); + var wrapper = buildCommon.makeSvgSpan([], [svg], options); + wrapper.height = viewBoxHeight / 1000; + wrapper.style.width = width; + wrapper.style.height = height; + stack.push({ + type: "elem", + elem: wrapper + }); + } else { + // Stack glyphs + // Start by adding the bottom symbol + stack.push(makeGlyphSpan(bottom, font, mode)); + stack.push(lap); // overlap + + if (middle === null) { + // The middle section will be an SVG. Make it an extra 0.016em tall. + // We'll overlap by 0.008em at top and bottom. + var innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms; + stack.push(makeInner(repeat, innerHeight, options)); + } else { + // When there is a middle bit, we need the middle part and two repeated + // sections + var _innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms; + + stack.push(makeInner(repeat, _innerHeight, options)); // Now insert the middle of the brace. + + stack.push(lap); + stack.push(makeGlyphSpan(middle, font, mode)); + stack.push(lap); + stack.push(makeInner(repeat, _innerHeight, options)); + } // Add the top symbol + + + stack.push(lap); + stack.push(makeGlyphSpan(top, font, mode)); + } // Finally, build the vlist + + + var newOptions = options.havingBaseStyle(Style$1.TEXT); + var inner = buildCommon.makeVList({ + positionType: "bottom", + positionData: depth, + children: stack + }, newOptions); + return styleWrap(buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions), Style$1.TEXT, options, classes); +}; // All surds have 0.08em padding above the vinculum inside the SVG. +// That keeps browser span height rounding error from pinching the line. + + +var vbPad = 80; // padding above the surd, measured inside the viewBox. + +var emPad = 0.08; // padding, in ems, measured in the document. + +var sqrtSvg = function sqrtSvg(sqrtName, height, viewBoxHeight, extraVinculum, options) { + var path = sqrtPath(sqrtName, extraVinculum, viewBoxHeight); + var pathNode = new PathNode(sqrtName, path); + var svg = new SvgNode([pathNode], { + // Note: 1000:1 ratio of viewBox to document em width. + "width": "400em", + "height": makeEm(height), + "viewBox": "0 0 400000 " + viewBoxHeight, + "preserveAspectRatio": "xMinYMin slice" + }); + return buildCommon.makeSvgSpan(["hide-tail"], [svg], options); +}; +/** + * Make a sqrt image of the given height, + */ + + +var makeSqrtImage = function makeSqrtImage(height, options) { + // Define a newOptions that removes the effect of size changes such as \Huge. + // We don't pick different a height surd for \Huge. For it, we scale up. + var newOptions = options.havingBaseSizing(); // Pick the desired surd glyph from a sequence of surds. + + var delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions); + var sizeMultiplier = newOptions.sizeMultiplier; // default + // The standard sqrt SVGs each have a 0.04em thick vinculum. + // If Settings.minRuleThickness is larger than that, we add extraVinculum. + + var extraVinculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness); // Create a span containing an SVG image of a sqrt symbol. + + var span; + var spanHeight = 0; + var texHeight = 0; + var viewBoxHeight = 0; + var advanceWidth; // We create viewBoxes with 80 units of "padding" above each surd. + // Then browser rounding error on the parent span height will not + // encroach on the ink of the vinculum. But that padding is not + // included in the TeX-like `height` used for calculation of + // vertical alignment. So texHeight = span.height < span.style.height. + + if (delim.type === "small") { + // Get an SVG that is derived from glyph U+221A in font KaTeX-Main. + // 1000 unit normal glyph height. + viewBoxHeight = 1000 + 1000 * extraVinculum + vbPad; + + if (height < 1.0) { + sizeMultiplier = 1.0; // mimic a \textfont radical + } else if (height < 1.4) { + sizeMultiplier = 0.7; // mimic a \scriptfont radical + } + + spanHeight = (1.0 + extraVinculum + emPad) / sizeMultiplier; + texHeight = (1.00 + extraVinculum) / sizeMultiplier; + span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraVinculum, options); + span.style.minWidth = "0.853em"; + advanceWidth = 0.833 / sizeMultiplier; // from the font. + } else if (delim.type === "large") { + // These SVGs come from fonts: KaTeX_Size1, _Size2, etc. + viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size]; + texHeight = (sizeToMaxHeight[delim.size] + extraVinculum) / sizeMultiplier; + spanHeight = (sizeToMaxHeight[delim.size] + extraVinculum + emPad) / sizeMultiplier; + span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraVinculum, options); + span.style.minWidth = "1.02em"; + advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font. + } else { + // Tall sqrt. In TeX, this would be stacked using multiple glyphs. + // We'll use a single SVG to accomplish the same thing. + spanHeight = height + extraVinculum + emPad; + texHeight = height + extraVinculum; + viewBoxHeight = Math.floor(1000 * height + extraVinculum) + vbPad; + span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraVinculum, options); + span.style.minWidth = "0.742em"; + advanceWidth = 1.056; + } + + span.height = texHeight; + span.style.height = makeEm(spanHeight); + return { + span, + advanceWidth, + // Calculate the actual line width. + // This actually should depend on the chosen font -- e.g. \boldmath + // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and + // have thicker rules. + ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraVinculum) * sizeMultiplier + }; +}; // There are three kinds of delimiters, delimiters that stack when they become +// too large + + +var stackLargeDelimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]; // delimiters that always stack + +var stackAlwaysDelimiters = ["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"]; // and delimiters that never stack + +var stackNeverDelimiters = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]; // Metrics of the different sizes. Found by looking at TeX's output of +// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ +// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. + +var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; +/** + * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4. + */ + +var makeSizedDelim = function makeSizedDelim(delim, size, options, mode, classes) { + // < and > turn into \langle and \rangle in delimiters + if (delim === "<" || delim === "\\lt" || delim === "\u27e8") { + delim = "\\langle"; + } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") { + delim = "\\rangle"; + } // Sized delimiters are never centered. + + + if (utils.contains(stackLargeDelimiters, delim) || utils.contains(stackNeverDelimiters, delim)) { + return makeLargeDelim(delim, size, false, options, mode, classes); + } else if (utils.contains(stackAlwaysDelimiters, delim)) { + return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes); + } else { + throw new ParseError("Illegal delimiter: '" + delim + "'"); + } +}; +/** + * There are three different sequences of delimiter sizes that the delimiters + * follow depending on the kind of delimiter. This is used when creating custom + * sized delimiters to decide whether to create a small, large, or stacked + * delimiter. + * + * In real TeX, these sequences aren't explicitly defined, but are instead + * defined inside the font metrics. Since there are only three sequences that + * are possible for the delimiters that TeX defines, it is easier to just encode + * them explicitly here. + */ + + +// Delimiters that never stack try small delimiters and large delimiters only +var stackNeverDelimiterSequence = [{ + type: "small", + style: Style$1.SCRIPTSCRIPT +}, { + type: "small", + style: Style$1.SCRIPT +}, { + type: "small", + style: Style$1.TEXT +}, { + type: "large", + size: 1 +}, { + type: "large", + size: 2 +}, { + type: "large", + size: 3 +}, { + type: "large", + size: 4 +}]; // Delimiters that always stack try the small delimiters first, then stack + +var stackAlwaysDelimiterSequence = [{ + type: "small", + style: Style$1.SCRIPTSCRIPT +}, { + type: "small", + style: Style$1.SCRIPT +}, { + type: "small", + style: Style$1.TEXT +}, { + type: "stack" +}]; // Delimiters that stack when large try the small and then large delimiters, and +// stack afterwards + +var stackLargeDelimiterSequence = [{ + type: "small", + style: Style$1.SCRIPTSCRIPT +}, { + type: "small", + style: Style$1.SCRIPT +}, { + type: "small", + style: Style$1.TEXT +}, { + type: "large", + size: 1 +}, { + type: "large", + size: 2 +}, { + type: "large", + size: 3 +}, { + type: "large", + size: 4 +}, { + type: "stack" +}]; +/** + * Get the font used in a delimiter based on what kind of delimiter it is. + * TODO(#963) Use more specific font family return type once that is introduced. + */ + +var delimTypeToFont = function delimTypeToFont(type) { + if (type.type === "small") { + return "Main-Regular"; + } else if (type.type === "large") { + return "Size" + type.size + "-Regular"; + } else if (type.type === "stack") { + return "Size4-Regular"; + } else { + throw new Error("Add support for delim type '" + type.type + "' here."); + } +}; +/** + * Traverse a sequence of types of delimiters to decide what kind of delimiter + * should be used to create a delimiter of the given height+depth. + */ + + +var traverseSequence = function traverseSequence(delim, height, sequence, options) { + // Here, we choose the index we should start at in the sequences. In smaller + // sizes (which correspond to larger numbers in style.size) we start earlier + // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts + // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2 + var start = Math.min(2, 3 - options.style.size); + + for (var i = start; i < sequence.length; i++) { + if (sequence[i].type === "stack") { + // This is always the last delimiter, so we just break the loop now. + break; + } + + var metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math"); + var heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we + // account for the style change size. + + if (sequence[i].type === "small") { + var newOptions = options.havingBaseStyle(sequence[i].style); + heightDepth *= newOptions.sizeMultiplier; + } // Check if the delimiter at this size works for the given height. + + + if (heightDepth > height) { + return sequence[i]; + } + } // If we reached the end of the sequence, return the last sequence element. + + + return sequence[sequence.length - 1]; +}; +/** + * Make a delimiter of a given height+depth, with optional centering. Here, we + * traverse the sequences, and create a delimiter that the sequence tells us to. + */ + + +var makeCustomSizedDelim = function makeCustomSizedDelim(delim, height, center, options, mode, classes) { + if (delim === "<" || delim === "\\lt" || delim === "\u27e8") { + delim = "\\langle"; + } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") { + delim = "\\rangle"; + } // Decide what sequence to use + + + var sequence; + + if (utils.contains(stackNeverDelimiters, delim)) { + sequence = stackNeverDelimiterSequence; + } else if (utils.contains(stackLargeDelimiters, delim)) { + sequence = stackLargeDelimiterSequence; + } else { + sequence = stackAlwaysDelimiterSequence; + } // Look through the sequence + + + var delimType = traverseSequence(delim, height, sequence, options); // Get the delimiter from font glyphs. + // Depending on the sequence element we decided on, call the + // appropriate function. + + if (delimType.type === "small") { + return makeSmallDelim(delim, delimType.style, center, options, mode, classes); + } else if (delimType.type === "large") { + return makeLargeDelim(delim, delimType.size, center, options, mode, classes); + } else + /* if (delimType.type === "stack") */ + { + return makeStackedDelim(delim, height, center, options, mode, classes); + } +}; +/** + * Make a delimiter for use with `\left` and `\right`, given a height and depth + * of an expression that the delimiters surround. + */ + + +var makeLeftRightDelim = function makeLeftRightDelim(delim, height, depth, options, mode, classes) { + // We always center \left/\right delimiters, so the axis is always shifted + var axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right + + var delimiterFactor = 901; + var delimiterExtend = 5.0 / options.fontMetrics().ptPerEm; + var maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight); + var totalHeight = Math.max( // In real TeX, calculations are done using integral values which are + // 65536 per pt, or 655360 per em. So, the division here truncates in + // TeX but doesn't here, producing different results. If we wanted to + // exactly match TeX's calculation, we could do + // Math.floor(655360 * maxDistFromAxis / 500) * + // delimiterFactor / 655360 + // (To see the difference, compare + // x^{x^{\left(\rule{0.1em}{0.68em}\right)}} + // in TeX and KaTeX) + maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend); // Finally, we defer to `makeCustomSizedDelim` with our calculated total + // height + + return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes); +}; + +var delimiter = { + sqrtImage: makeSqrtImage, + sizedDelim: makeSizedDelim, + sizeToMaxHeight: sizeToMaxHeight, + customSizedDelim: makeCustomSizedDelim, + leftRightDelim: makeLeftRightDelim +}; + +// Extra data needed for the delimiter handler down below +var delimiterSizes = { + "\\bigl": { + mclass: "mopen", + size: 1 + }, + "\\Bigl": { + mclass: "mopen", + size: 2 + }, + "\\biggl": { + mclass: "mopen", + size: 3 + }, + "\\Biggl": { + mclass: "mopen", + size: 4 + }, + "\\bigr": { + mclass: "mclose", + size: 1 + }, + "\\Bigr": { + mclass: "mclose", + size: 2 + }, + "\\biggr": { + mclass: "mclose", + size: 3 + }, + "\\Biggr": { + mclass: "mclose", + size: 4 + }, + "\\bigm": { + mclass: "mrel", + size: 1 + }, + "\\Bigm": { + mclass: "mrel", + size: 2 + }, + "\\biggm": { + mclass: "mrel", + size: 3 + }, + "\\Biggm": { + mclass: "mrel", + size: 4 + }, + "\\big": { + mclass: "mord", + size: 1 + }, + "\\Big": { + mclass: "mord", + size: 2 + }, + "\\bigg": { + mclass: "mord", + size: 3 + }, + "\\Bigg": { + mclass: "mord", + size: 4 + } +}; +var delimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."]; + +// Delimiter functions +function checkDelimiter(delim, context) { + var symDelim = checkSymbolNodeType(delim); + + if (symDelim && utils.contains(delimiters, symDelim.text)) { + return symDelim; + } else if (symDelim) { + throw new ParseError("Invalid delimiter '" + symDelim.text + "' after '" + context.funcName + "'", delim); + } else { + throw new ParseError("Invalid delimiter type '" + delim.type + "'", delim); + } +} + +defineFunction({ + type: "delimsizing", + names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"], + props: { + numArgs: 1, + argTypes: ["primitive"] + }, + handler: (context, args) => { + var delim = checkDelimiter(args[0], context); + return { + type: "delimsizing", + mode: context.parser.mode, + size: delimiterSizes[context.funcName].size, + mclass: delimiterSizes[context.funcName].mclass, + delim: delim.text + }; + }, + htmlBuilder: (group, options) => { + if (group.delim === ".") { + // Empty delimiters still count as elements, even though they don't + // show anything. + return buildCommon.makeSpan([group.mclass]); + } // Use delimiter.sizedDelim to generate the delimiter. + + + return delimiter.sizedDelim(group.delim, group.size, options, group.mode, [group.mclass]); + }, + mathmlBuilder: group => { + var children = []; + + if (group.delim !== ".") { + children.push(makeText(group.delim, group.mode)); + } + + var node = new mathMLTree.MathNode("mo", children); + + if (group.mclass === "mopen" || group.mclass === "mclose") { + // Only some of the delimsizing functions act as fences, and they + // return "mopen" or "mclose" mclass. + node.setAttribute("fence", "true"); + } else { + // Explicitly disable fencing if it's not a fence, to override the + // defaults. + node.setAttribute("fence", "false"); + } + + node.setAttribute("stretchy", "true"); + var size = makeEm(delimiter.sizeToMaxHeight[group.size]); + node.setAttribute("minsize", size); + node.setAttribute("maxsize", size); + return node; + } +}); + +function assertParsed(group) { + if (!group.body) { + throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); + } +} + +defineFunction({ + type: "leftright-right", + names: ["\\right"], + props: { + numArgs: 1, + primitive: true + }, + handler: (context, args) => { + // \left case below triggers parsing of \right in + // `const right = parser.parseFunction();` + // uses this return value. + var color = context.parser.gullet.macros.get("\\current@color"); + + if (color && typeof color !== "string") { + throw new ParseError("\\current@color set to non-string in \\right"); + } + + return { + type: "leftright-right", + mode: context.parser.mode, + delim: checkDelimiter(args[0], context).text, + color // undefined if not set via \color + + }; + } +}); +defineFunction({ + type: "leftright", + names: ["\\left"], + props: { + numArgs: 1, + primitive: true + }, + handler: (context, args) => { + var delim = checkDelimiter(args[0], context); + var parser = context.parser; // Parse out the implicit body + + ++parser.leftrightDepth; // parseExpression stops before '\\right' + + var body = parser.parseExpression(false); + --parser.leftrightDepth; // Check the next token + + parser.expect("\\right", false); + var right = assertNodeType(parser.parseFunction(), "leftright-right"); + return { + type: "leftright", + mode: parser.mode, + body, + left: delim.text, + right: right.delim, + rightColor: right.color + }; + }, + htmlBuilder: (group, options) => { + assertParsed(group); // Build the inner expression + + var inner = buildExpression$1(group.body, options, true, ["mopen", "mclose"]); + var innerHeight = 0; + var innerDepth = 0; + var hadMiddle = false; // Calculate its height and depth + + for (var i = 0; i < inner.length; i++) { + // Property `isMiddle` not defined on `span`. See comment in + // "middle"'s htmlBuilder. + // $FlowFixMe + if (inner[i].isMiddle) { + hadMiddle = true; + } else { + innerHeight = Math.max(inner[i].height, innerHeight); + innerDepth = Math.max(inner[i].depth, innerDepth); + } + } // The size of delimiters is the same, regardless of what style we are + // in. Thus, to correctly calculate the size of delimiter we need around + // a group, we scale down the inner size based on the size. + + + innerHeight *= options.sizeMultiplier; + innerDepth *= options.sizeMultiplier; + var leftDelim; + + if (group.left === ".") { + // Empty delimiters in \left and \right make null delimiter spaces. + leftDelim = makeNullDelimiter(options, ["mopen"]); + } else { + // Otherwise, use leftRightDelim to generate the correct sized + // delimiter. + leftDelim = delimiter.leftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]); + } // Add it to the beginning of the expression + + + inner.unshift(leftDelim); // Handle middle delimiters + + if (hadMiddle) { + for (var _i = 1; _i < inner.length; _i++) { + var middleDelim = inner[_i]; // Property `isMiddle` not defined on `span`. See comment in + // "middle"'s htmlBuilder. + // $FlowFixMe + + var isMiddle = middleDelim.isMiddle; + + if (isMiddle) { + // Apply the options that were active when \middle was called + inner[_i] = delimiter.leftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []); + } + } + } + + var rightDelim; // Same for the right delimiter, but using color specified by \color + + if (group.right === ".") { + rightDelim = makeNullDelimiter(options, ["mclose"]); + } else { + var colorOptions = group.rightColor ? options.withColor(group.rightColor) : options; + rightDelim = delimiter.leftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]); + } // Add it to the end of the expression. + + + inner.push(rightDelim); + return buildCommon.makeSpan(["minner"], inner, options); + }, + mathmlBuilder: (group, options) => { + assertParsed(group); + var inner = buildExpression(group.body, options); + + if (group.left !== ".") { + var leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); + leftNode.setAttribute("fence", "true"); + inner.unshift(leftNode); + } + + if (group.right !== ".") { + var rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); + rightNode.setAttribute("fence", "true"); + + if (group.rightColor) { + rightNode.setAttribute("mathcolor", group.rightColor); + } + + inner.push(rightNode); + } + + return makeRow(inner); + } +}); +defineFunction({ + type: "middle", + names: ["\\middle"], + props: { + numArgs: 1, + primitive: true + }, + handler: (context, args) => { + var delim = checkDelimiter(args[0], context); + + if (!context.parser.leftrightDepth) { + throw new ParseError("\\middle without preceding \\left", delim); + } + + return { + type: "middle", + mode: context.parser.mode, + delim: delim.text + }; + }, + htmlBuilder: (group, options) => { + var middleDelim; + + if (group.delim === ".") { + middleDelim = makeNullDelimiter(options, []); + } else { + middleDelim = delimiter.sizedDelim(group.delim, 1, options, group.mode, []); + var isMiddle = { + delim: group.delim, + options + }; // Property `isMiddle` not defined on `span`. It is only used in + // this file above. + // TODO: Fix this violation of the `span` type and possibly rename + // things since `isMiddle` sounds like a boolean, but is a struct. + // $FlowFixMe + + middleDelim.isMiddle = isMiddle; + } + + return middleDelim; + }, + mathmlBuilder: (group, options) => { + // A Firefox \middle will stretch a character vertically only if it + // is in the fence part of the operator dictionary at: + // https://www.w3.org/TR/MathML3/appendixc.html. + // So we need to avoid U+2223 and use plain "|" instead. + var textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode); + var middleNode = new mathMLTree.MathNode("mo", [textNode]); + middleNode.setAttribute("fence", "true"); // MathML gives 5/18em spacing to each element. + // \middle should get delimiter spacing instead. + + middleNode.setAttribute("lspace", "0.05em"); + middleNode.setAttribute("rspace", "0.05em"); + return middleNode; + } +}); + +var htmlBuilder$7 = (group, options) => { + // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase + // Some groups can return document fragments. Handle those by wrapping + // them in a span. + var inner = buildCommon.wrapFragment(buildGroup$1(group.body, options), options); + var label = group.label.slice(1); + var scale = options.sizeMultiplier; + var img; + var imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different + // depending on whether the subject is wider than it is tall, or vice versa. + // We don't know the width of a group, so as a proxy, we test if + // the subject is a single character. This captures most of the + // subjects that should get the "tall" treatment. + + var isSingleChar = utils.isCharacterBox(group.body); + + if (label === "sout") { + img = buildCommon.makeSpan(["stretchy", "sout"]); + img.height = options.fontMetrics().defaultRuleThickness / scale; + imgShift = -0.5 * options.fontMetrics().xHeight; + } else if (label === "phase") { + // Set a couple of dimensions from the steinmetz package. + var lineWeight = calculateSize({ + number: 0.6, + unit: "pt" + }, options); + var clearance = calculateSize({ + number: 0.35, + unit: "ex" + }, options); // Prevent size changes like \Huge from affecting line thickness + + var newOptions = options.havingBaseSizing(); + scale = scale / newOptions.sizeMultiplier; + var angleHeight = inner.height + inner.depth + lineWeight + clearance; // Reserve a left pad for the angle. + + inner.style.paddingLeft = makeEm(angleHeight / 2 + lineWeight); // Create an SVG + + var viewBoxHeight = Math.floor(1000 * angleHeight * scale); + var path = phasePath(viewBoxHeight); + var svgNode = new SvgNode([new PathNode("phase", path)], { + "width": "400em", + "height": makeEm(viewBoxHeight / 1000), + "viewBox": "0 0 400000 " + viewBoxHeight, + "preserveAspectRatio": "xMinYMin slice" + }); // Wrap it in a span with overflow: hidden. + + img = buildCommon.makeSvgSpan(["hide-tail"], [svgNode], options); + img.style.height = makeEm(angleHeight); + imgShift = inner.depth + lineWeight + clearance; + } else { + // Add horizontal padding + if (/cancel/.test(label)) { + if (!isSingleChar) { + inner.classes.push("cancel-pad"); + } + } else if (label === "angl") { + inner.classes.push("anglpad"); + } else { + inner.classes.push("boxpad"); + } // Add vertical padding + + + var topPad = 0; + var bottomPad = 0; + var ruleThickness = 0; // ref: cancel package: \advance\totalheight2\p@ % "+2" + + if (/box/.test(label)) { + ruleThickness = Math.max(options.fontMetrics().fboxrule, // default + options.minRuleThickness // User override. + ); + topPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness); + bottomPad = topPad; + } else if (label === "angl") { + ruleThickness = Math.max(options.fontMetrics().defaultRuleThickness, options.minRuleThickness); + topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself. + + bottomPad = Math.max(0, 0.25 - inner.depth); + } else { + topPad = isSingleChar ? 0.2 : 0; + bottomPad = topPad; + } + + img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options); + + if (/fbox|boxed|fcolorbox/.test(label)) { + img.style.borderStyle = "solid"; + img.style.borderWidth = makeEm(ruleThickness); + } else if (label === "angl" && ruleThickness !== 0.049) { + img.style.borderTopWidth = makeEm(ruleThickness); + img.style.borderRightWidth = makeEm(ruleThickness); + } + + imgShift = inner.depth + bottomPad; + + if (group.backgroundColor) { + img.style.backgroundColor = group.backgroundColor; + + if (group.borderColor) { + img.style.borderColor = group.borderColor; + } + } + } + + var vlist; + + if (group.backgroundColor) { + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [// Put the color background behind inner; + { + type: "elem", + elem: img, + shift: imgShift + }, { + type: "elem", + elem: inner, + shift: 0 + }] + }, options); + } else { + var classes = /cancel|phase/.test(label) ? ["svg-align"] : []; + vlist = buildCommon.makeVList({ + positionType: "individualShift", + children: [// Write the \cancel stroke on top of inner. + { + type: "elem", + elem: inner, + shift: 0 + }, { + type: "elem", + elem: img, + shift: imgShift, + wrapperClasses: classes + }] + }, options); + } + + if (/cancel/.test(label)) { + // The cancel package documentation says that cancel lines add their height + // to the expression, but tests show that isn't how it actually works. + vlist.height = inner.height; + vlist.depth = inner.depth; + } + + if (/cancel/.test(label) && !isSingleChar) { + // cancel does not create horiz space for its line extension. + return buildCommon.makeSpan(["mord", "cancel-lap"], [vlist], options); + } else { + return buildCommon.makeSpan(["mord"], [vlist], options); + } +}; + +var mathmlBuilder$6 = (group, options) => { + var fboxsep = 0; + var node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildGroup(group.body, options)]); + + switch (group.label) { + case "\\cancel": + node.setAttribute("notation", "updiagonalstrike"); + break; + + case "\\bcancel": + node.setAttribute("notation", "downdiagonalstrike"); + break; + + case "\\phase": + node.setAttribute("notation", "phasorangle"); + break; + + case "\\sout": + node.setAttribute("notation", "horizontalstrike"); + break; + + case "\\fbox": + node.setAttribute("notation", "box"); + break; + + case "\\angl": + node.setAttribute("notation", "actuarial"); + break; + + case "\\fcolorbox": + case "\\colorbox": + // doesn't have a good notation option. So use + // instead. Set some attributes that come included with . + fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm; + node.setAttribute("width", "+" + 2 * fboxsep + "pt"); + node.setAttribute("height", "+" + 2 * fboxsep + "pt"); + node.setAttribute("lspace", fboxsep + "pt"); // + + node.setAttribute("voffset", fboxsep + "pt"); + + if (group.label === "\\fcolorbox") { + var thk = Math.max(options.fontMetrics().fboxrule, // default + options.minRuleThickness // user override + ); + node.setAttribute("style", "border: " + thk + "em solid " + String(group.borderColor)); + } + + break; + + case "\\xcancel": + node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); + break; + } + + if (group.backgroundColor) { + node.setAttribute("mathbackground", group.backgroundColor); + } + + return node; +}; + +defineFunction({ + type: "enclose", + names: ["\\colorbox"], + props: { + numArgs: 2, + allowedInText: true, + argTypes: ["color", "text"] + }, + + handler(_ref, args, optArgs) { + var { + parser, + funcName + } = _ref; + var color = assertNodeType(args[0], "color-token").color; + var body = args[1]; + return { + type: "enclose", + mode: parser.mode, + label: funcName, + backgroundColor: color, + body + }; + }, + + htmlBuilder: htmlBuilder$7, + mathmlBuilder: mathmlBuilder$6 +}); +defineFunction({ + type: "enclose", + names: ["\\fcolorbox"], + props: { + numArgs: 3, + allowedInText: true, + argTypes: ["color", "color", "text"] + }, + + handler(_ref2, args, optArgs) { + var { + parser, + funcName + } = _ref2; + var borderColor = assertNodeType(args[0], "color-token").color; + var backgroundColor = assertNodeType(args[1], "color-token").color; + var body = args[2]; + return { + type: "enclose", + mode: parser.mode, + label: funcName, + backgroundColor, + borderColor, + body + }; + }, + + htmlBuilder: htmlBuilder$7, + mathmlBuilder: mathmlBuilder$6 +}); +defineFunction({ + type: "enclose", + names: ["\\fbox"], + props: { + numArgs: 1, + argTypes: ["hbox"], + allowedInText: true + }, + + handler(_ref3, args) { + var { + parser + } = _ref3; + return { + type: "enclose", + mode: parser.mode, + label: "\\fbox", + body: args[0] + }; + } + +}); +defineFunction({ + type: "enclose", + names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"], + props: { + numArgs: 1 + }, + + handler(_ref4, args) { + var { + parser, + funcName + } = _ref4; + var body = args[0]; + return { + type: "enclose", + mode: parser.mode, + label: funcName, + body + }; + }, + + htmlBuilder: htmlBuilder$7, + mathmlBuilder: mathmlBuilder$6 +}); +defineFunction({ + type: "enclose", + names: ["\\angl"], + props: { + numArgs: 1, + argTypes: ["hbox"], + allowedInText: false + }, + + handler(_ref5, args) { + var { + parser + } = _ref5; + return { + type: "enclose", + mode: parser.mode, + label: "\\angl", + body: args[0] + }; + } + +}); + +/** + * All registered environments. + * `environments.js` exports this same dictionary again and makes it public. + * `Parser.js` requires this dictionary via `environments.js`. + */ +var _environments = {}; +function defineEnvironment(_ref) { + var { + type, + names, + props, + handler, + htmlBuilder, + mathmlBuilder + } = _ref; + // Set default values of environments. + var data = { + type, + numArgs: props.numArgs || 0, + allowedInText: false, + numOptionalArgs: 0, + handler + }; + + for (var i = 0; i < names.length; ++i) { + // TODO: The value type of _environments should be a type union of all + // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is + // an existential type. + _environments[names[i]] = data; + } + + if (htmlBuilder) { + _htmlGroupBuilders[type] = htmlBuilder; + } + + if (mathmlBuilder) { + _mathmlGroupBuilders[type] = mathmlBuilder; + } +} + +/** + * All registered global/built-in macros. + * `macros.js` exports this same dictionary again and makes it public. + * `Parser.js` requires this dictionary via `macros.js`. + */ +var _macros = {}; // This function might one day accept an additional argument and do more things. + +function defineMacro(name, body) { + _macros[name] = body; +} + +// Helper functions +function getHLines(parser) { + // Return an array. The array length = number of hlines. + // Each element in the array tells if the line is dashed. + var hlineInfo = []; + parser.consumeSpaces(); + var nxt = parser.fetch().text; + + if (nxt === "\\relax") { + // \relax is an artifact of the \cr macro below + parser.consume(); + parser.consumeSpaces(); + nxt = parser.fetch().text; + } + + while (nxt === "\\hline" || nxt === "\\hdashline") { + parser.consume(); + hlineInfo.push(nxt === "\\hdashline"); + parser.consumeSpaces(); + nxt = parser.fetch().text; + } + + return hlineInfo; +} + +var validateAmsEnvironmentContext = context => { + var settings = context.parser.settings; + + if (!settings.displayMode) { + throw new ParseError("{" + context.envName + "} can be used only in" + " display mode."); + } +}; // autoTag (an argument to parseArray) can be one of three values: +// * undefined: Regular (not-top-level) array; no tags on each row +// * true: Automatic equation numbering, overridable by \tag +// * false: Tags allowed on each row, but no automatic numbering +// This function *doesn't* work with the "split" environment name. + + +function getAutoTag(name) { + if (name.indexOf("ed") === -1) { + return name.indexOf("*") === -1; + } // return undefined; + +} +/** + * Parse the body of the environment, with rows delimited by \\ and + * columns delimited by &, and create a nested list in row-major order + * with one group per cell. If given an optional argument style + * ("text", "display", etc.), then each cell is cast into that style. + */ + + +function parseArray(parser, _ref, style) { + var { + hskipBeforeAndAfter, + addJot, + cols, + arraystretch, + colSeparationType, + autoTag, + singleRow, + emptySingleRow, + maxNumCols, + leqno + } = _ref; + parser.gullet.beginGroup(); + + if (!singleRow) { + // \cr is equivalent to \\ without the optional size argument (see below) + // TODO: provide helpful error when \cr is used outside array environment + parser.gullet.macros.set("\\cr", "\\\\\\relax"); + } // Get current arraystretch if it's not set by the environment + + + if (!arraystretch) { + var stretch = parser.gullet.expandMacroAsText("\\arraystretch"); + + if (stretch == null) { + // Default \arraystretch from lttab.dtx + arraystretch = 1; + } else { + arraystretch = parseFloat(stretch); + + if (!arraystretch || arraystretch < 0) { + throw new ParseError("Invalid \\arraystretch: " + stretch); + } + } + } // Start group for first cell + + + parser.gullet.beginGroup(); + var row = []; + var body = [row]; + var rowGaps = []; + var hLinesBeforeRow = []; + var tags = autoTag != null ? [] : undefined; // amsmath uses \global\@eqnswtrue and \global\@eqnswfalse to represent + // whether this row should have an equation number. Simulate this with + // a \@eqnsw macro set to 1 or 0. + + function beginRow() { + if (autoTag) { + parser.gullet.macros.set("\\@eqnsw", "1", true); + } + } + + function endRow() { + if (tags) { + if (parser.gullet.macros.get("\\df@tag")) { + tags.push(parser.subparse([new Token("\\df@tag")])); + parser.gullet.macros.set("\\df@tag", undefined, true); + } else { + tags.push(Boolean(autoTag) && parser.gullet.macros.get("\\@eqnsw") === "1"); + } + } + } + + beginRow(); // Test for \hline at the top of the array. + + hLinesBeforeRow.push(getHLines(parser)); + + while (true) { + // eslint-disable-line no-constant-condition + // Parse each cell in its own group (namespace) + var cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); + parser.gullet.endGroup(); + parser.gullet.beginGroup(); + cell = { + type: "ordgroup", + mode: parser.mode, + body: cell + }; + + if (style) { + cell = { + type: "styling", + mode: parser.mode, + style, + body: [cell] + }; + } + + row.push(cell); + var next = parser.fetch().text; + + if (next === "&") { + if (maxNumCols && row.length === maxNumCols) { + if (singleRow || colSeparationType) { + // {equation} or {split} + throw new ParseError("Too many tab characters: &", parser.nextToken); + } else { + // {array} environment + parser.settings.reportNonstrict("textEnv", "Too few columns " + "specified in the {array} column argument."); + } + } + + parser.consume(); + } else if (next === "\\end") { + endRow(); // Arrays terminate newlines with `\crcr` which consumes a `\cr` if + // the last line is empty. However, AMS environments keep the + // empty row if it's the only one. + // NOTE: Currently, `cell` is the last item added into `row`. + + if (row.length === 1 && cell.type === "styling" && cell.body[0].body.length === 0 && (body.length > 1 || !emptySingleRow)) { + body.pop(); + } + + if (hLinesBeforeRow.length < body.length + 1) { + hLinesBeforeRow.push([]); + } + + break; + } else if (next === "\\\\") { + parser.consume(); + var size = void 0; // \def\Let@{\let\\\math@cr} + // \def\math@cr{...\math@cr@} + // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} + // \def\math@cr@@[#1]{...\math@cr@@@...} + // \def\math@cr@@@{\cr} + + if (parser.gullet.future().text !== " ") { + size = parser.parseSizeGroup(true); + } + + rowGaps.push(size ? size.value : null); + endRow(); // check for \hline(s) following the row separator + + hLinesBeforeRow.push(getHLines(parser)); + row = []; + body.push(row); + beginRow(); + } else { + throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); + } + } // End cell group + + + parser.gullet.endGroup(); // End array group defining \cr + + parser.gullet.endGroup(); + return { + type: "array", + mode: parser.mode, + addJot, + arraystretch, + body, + cols, + rowGaps, + hskipBeforeAndAfter, + hLinesBeforeRow, + colSeparationType, + tags, + leqno + }; +} // Decides on a style for cells in an array according to whether the given +// environment name starts with the letter 'd'. + + +function dCellStyle(envName) { + if (envName.slice(0, 1) === "d") { + return "display"; + } else { + return "text"; + } +} + +var htmlBuilder$6 = function htmlBuilder(group, options) { + var r; + var c; + var nr = group.body.length; + var hLinesBeforeRow = group.hLinesBeforeRow; + var nc = 0; + var body = new Array(nr); + var hlines = []; + var ruleThickness = Math.max( // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em. + options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override. + ); // Horizontal spacing + + var pt = 1 / options.fontMetrics().ptPerEm; + var arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls + + if (group.colSeparationType && group.colSeparationType === "small") { + // We're in a {smallmatrix}. Default column space is \thickspace, + // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}. + // But that needs adjustment because LaTeX applies \scriptstyle to the + // entire array, including the colspace, but this function applies + // \scriptstyle only inside each element. + var localMultiplier = options.havingStyle(Style$1.SCRIPT).sizeMultiplier; + arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier); + } // Vertical spacing + + + var baselineskip = group.colSeparationType === "CD" ? calculateSize({ + number: 3, + unit: "ex" + }, options) : 12 * pt; // see size10.clo + // Default \jot from ltmath.dtx + // TODO(edemaine): allow overriding \jot via \setlength (#687) + + var jot = 3 * pt; + var arrayskip = group.arraystretch * baselineskip; + var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and + + var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx + + var totalHeight = 0; // Set a position for \hline(s) at the top of the array, if any. + + function setHLinePos(hlinesInGap) { + for (var i = 0; i < hlinesInGap.length; ++i) { + if (i > 0) { + totalHeight += 0.25; + } + + hlines.push({ + pos: totalHeight, + isDashed: hlinesInGap[i] + }); + } + } + + setHLinePos(hLinesBeforeRow[0]); + + for (r = 0; r < group.body.length; ++r) { + var inrow = group.body[r]; + var height = arstrutHeight; // \@array adds an \@arstrut + + var depth = arstrutDepth; // to each tow (via the template) + + if (nc < inrow.length) { + nc = inrow.length; + } + + var outrow = new Array(inrow.length); + + for (c = 0; c < inrow.length; ++c) { + var elt = buildGroup$1(inrow[c], options); + + if (depth < elt.depth) { + depth = elt.depth; + } + + if (height < elt.height) { + height = elt.height; + } + + outrow[c] = elt; + } + + var rowGap = group.rowGaps[r]; + var gap = 0; + + if (rowGap) { + gap = calculateSize(rowGap, options); + + if (gap > 0) { + // \@argarraycr + gap += arstrutDepth; + + if (depth < gap) { + depth = gap; // \@xargarraycr + } + + gap = 0; + } + } // In AMS multiline environments such as aligned and gathered, rows + // correspond to lines that have additional \jot added to the + // \baselineskip via \openup. + + + if (group.addJot) { + depth += jot; + } + + outrow.height = height; + outrow.depth = depth; + totalHeight += height; + outrow.pos = totalHeight; + totalHeight += depth + gap; // \@yargarraycr + + body[r] = outrow; // Set a position for \hline(s), if any. + + setHLinePos(hLinesBeforeRow[r + 1]); + } + + var offset = totalHeight / 2 + options.fontMetrics().axisHeight; + var colDescriptions = group.cols || []; + var cols = []; + var colSep; + var colDescrNum; + var tagSpans = []; + + if (group.tags && group.tags.some(tag => tag)) { + // An environment with manual tags and/or automatic equation numbers. + // Create node(s), the latter of which trigger CSS counter increment. + for (r = 0; r < nr; ++r) { + var rw = body[r]; + var shift = rw.pos - offset; + var tag = group.tags[r]; + var tagSpan = void 0; + + if (tag === true) { + // automatic numbering + tagSpan = buildCommon.makeSpan(["eqn-num"], [], options); + } else if (tag === false) { + // \nonumber/\notag or starred environment + tagSpan = buildCommon.makeSpan([], [], options); + } else { + // manual \tag + tagSpan = buildCommon.makeSpan([], buildExpression$1(tag, options, true), options); + } + + tagSpan.depth = rw.depth; + tagSpan.height = rw.height; + tagSpans.push({ + type: "elem", + elem: tagSpan, + shift + }); + } + } + + for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column + // descriptions, so trailing separators don't get lost. + c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) { + var colDescr = colDescriptions[colDescrNum] || {}; + var firstSeparator = true; + + while (colDescr.type === "separator") { + // If there is more than one separator in a row, add a space + // between them. + if (!firstSeparator) { + colSep = buildCommon.makeSpan(["arraycolsep"], []); + colSep.style.width = makeEm(options.fontMetrics().doubleRuleSep); + cols.push(colSep); + } + + if (colDescr.separator === "|" || colDescr.separator === ":") { + var lineType = colDescr.separator === "|" ? "solid" : "dashed"; + var separator = buildCommon.makeSpan(["vertical-separator"], [], options); + separator.style.height = makeEm(totalHeight); + separator.style.borderRightWidth = makeEm(ruleThickness); + separator.style.borderRightStyle = lineType; + separator.style.margin = "0 " + makeEm(-ruleThickness / 2); + + var _shift = totalHeight - offset; + + if (_shift) { + separator.style.verticalAlign = makeEm(-_shift); + } + + cols.push(separator); + } else { + throw new ParseError("Invalid separator type: " + colDescr.separator); + } + + colDescrNum++; + colDescr = colDescriptions[colDescrNum] || {}; + firstSeparator = false; + } + + if (c >= nc) { + continue; + } + + var sepwidth = void 0; + + if (c > 0 || group.hskipBeforeAndAfter) { + sepwidth = utils.deflt(colDescr.pregap, arraycolsep); + + if (sepwidth !== 0) { + colSep = buildCommon.makeSpan(["arraycolsep"], []); + colSep.style.width = makeEm(sepwidth); + cols.push(colSep); + } + } + + var col = []; + + for (r = 0; r < nr; ++r) { + var row = body[r]; + var elem = row[c]; + + if (!elem) { + continue; + } + + var _shift2 = row.pos - offset; + + elem.depth = row.depth; + elem.height = row.height; + col.push({ + type: "elem", + elem: elem, + shift: _shift2 + }); + } + + col = buildCommon.makeVList({ + positionType: "individualShift", + children: col + }, options); + col = buildCommon.makeSpan(["col-align-" + (colDescr.align || "c")], [col]); + cols.push(col); + + if (c < nc - 1 || group.hskipBeforeAndAfter) { + sepwidth = utils.deflt(colDescr.postgap, arraycolsep); + + if (sepwidth !== 0) { + colSep = buildCommon.makeSpan(["arraycolsep"], []); + colSep.style.width = makeEm(sepwidth); + cols.push(colSep); + } + } + } + + body = buildCommon.makeSpan(["mtable"], cols); // Add \hline(s), if any. + + if (hlines.length > 0) { + var line = buildCommon.makeLineSpan("hline", options, ruleThickness); + var dashes = buildCommon.makeLineSpan("hdashline", options, ruleThickness); + var vListElems = [{ + type: "elem", + elem: body, + shift: 0 + }]; + + while (hlines.length > 0) { + var hline = hlines.pop(); + var lineShift = hline.pos - offset; + + if (hline.isDashed) { + vListElems.push({ + type: "elem", + elem: dashes, + shift: lineShift + }); + } else { + vListElems.push({ + type: "elem", + elem: line, + shift: lineShift + }); + } + } + + body = buildCommon.makeVList({ + positionType: "individualShift", + children: vListElems + }, options); + } + + if (tagSpans.length === 0) { + return buildCommon.makeSpan(["mord"], [body], options); + } else { + var eqnNumCol = buildCommon.makeVList({ + positionType: "individualShift", + children: tagSpans + }, options); + eqnNumCol = buildCommon.makeSpan(["tag"], [eqnNumCol], options); + return buildCommon.makeFragment([body, eqnNumCol]); + } +}; + +var alignMap = { + c: "center ", + l: "left ", + r: "right " +}; + +var mathmlBuilder$5 = function mathmlBuilder(group, options) { + var tbl = []; + var glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]); + var tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]); + + for (var i = 0; i < group.body.length; i++) { + var rw = group.body[i]; + var row = []; + + for (var j = 0; j < rw.length; j++) { + row.push(new mathMLTree.MathNode("mtd", [buildGroup(rw[j], options)])); + } + + if (group.tags && group.tags[i]) { + row.unshift(glue); + row.push(glue); + + if (group.leqno) { + row.unshift(tag); + } else { + row.push(tag); + } + } + + tbl.push(new mathMLTree.MathNode("mtr", row)); + } + + var table = new mathMLTree.MathNode("mtable", tbl); // Set column alignment, row spacing, column spacing, and + // array lines by setting attributes on the table element. + // Set the row spacing. In MathML, we specify a gap distance. + // We do not use rowGap[] because MathML automatically increases + // cell height with the height/depth of the element content. + // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. + // We simulate this by adding (arraystretch - 1)em to the gap. This + // does a reasonable job of adjusting arrays containing 1 em tall content. + // The 0.16 and 0.09 values are found empirically. They produce an array + // similar to LaTeX and in which content does not interfere with \hlines. + + var gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray} + : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); + table.setAttribute("rowspacing", makeEm(gap)); // MathML table lines go only between cells. + // To place a line on an edge we'll use , if necessary. + + var menclose = ""; + var align = ""; + + if (group.cols && group.cols.length > 0) { + // Find column alignment, column spacing, and vertical lines. + var cols = group.cols; + var columnLines = ""; + var prevTypeWasAlign = false; + var iStart = 0; + var iEnd = cols.length; + + if (cols[0].type === "separator") { + menclose += "top "; + iStart = 1; + } + + if (cols[cols.length - 1].type === "separator") { + menclose += "bottom "; + iEnd -= 1; + } + + for (var _i = iStart; _i < iEnd; _i++) { + if (cols[_i].type === "align") { + align += alignMap[cols[_i].align]; + + if (prevTypeWasAlign) { + columnLines += "none "; + } + + prevTypeWasAlign = true; + } else if (cols[_i].type === "separator") { + // MathML accepts only single lines between cells. + // So we read only the first of consecutive separators. + if (prevTypeWasAlign) { + columnLines += cols[_i].separator === "|" ? "solid " : "dashed "; + prevTypeWasAlign = false; + } + } + } + + table.setAttribute("columnalign", align.trim()); + + if (/[sd]/.test(columnLines)) { + table.setAttribute("columnlines", columnLines.trim()); + } + } // Set column spacing. + + + if (group.colSeparationType === "align") { + var _cols = group.cols || []; + + var spacing = ""; + + for (var _i2 = 1; _i2 < _cols.length; _i2++) { + spacing += _i2 % 2 ? "0em " : "1em "; + } + + table.setAttribute("columnspacing", spacing.trim()); + } else if (group.colSeparationType === "alignat" || group.colSeparationType === "gather") { + table.setAttribute("columnspacing", "0em"); + } else if (group.colSeparationType === "small") { + table.setAttribute("columnspacing", "0.2778em"); + } else if (group.colSeparationType === "CD") { + table.setAttribute("columnspacing", "0.5em"); + } else { + table.setAttribute("columnspacing", "1em"); + } // Address \hline and \hdashline + + + var rowLines = ""; + var hlines = group.hLinesBeforeRow; + menclose += hlines[0].length > 0 ? "left " : ""; + menclose += hlines[hlines.length - 1].length > 0 ? "right " : ""; + + for (var _i3 = 1; _i3 < hlines.length - 1; _i3++) { + rowLines += hlines[_i3].length === 0 ? "none " // MathML accepts only a single line between rows. Read one element. + : hlines[_i3][0] ? "dashed " : "solid "; + } + + if (/[sd]/.test(rowLines)) { + table.setAttribute("rowlines", rowLines.trim()); + } + + if (menclose !== "") { + table = new mathMLTree.MathNode("menclose", [table]); + table.setAttribute("notation", menclose.trim()); + } + + if (group.arraystretch && group.arraystretch < 1) { + // A small array. Wrap in scriptstyle so row gap is not too large. + table = new mathMLTree.MathNode("mstyle", [table]); + table.setAttribute("scriptlevel", "1"); + } + + return table; +}; // Convenience function for align, align*, aligned, alignat, alignat*, alignedat. + + +var alignedHandler = function alignedHandler(context, args) { + if (context.envName.indexOf("ed") === -1) { + validateAmsEnvironmentContext(context); + } + + var cols = []; + var separationType = context.envName.indexOf("at") > -1 ? "alignat" : "align"; + var isSplit = context.envName === "split"; + var res = parseArray(context.parser, { + cols, + addJot: true, + autoTag: isSplit ? undefined : getAutoTag(context.envName), + emptySingleRow: true, + colSeparationType: separationType, + maxNumCols: isSplit ? 2 : undefined, + leqno: context.parser.settings.leqno + }, "display"); // Determining number of columns. + // 1. If the first argument is given, we use it as a number of columns, + // and makes sure that each row doesn't exceed that number. + // 2. Otherwise, just count number of columns = maximum number + // of cells in each row ("aligned" mode -- isAligned will be true). + // + // At the same time, prepend empty group {} at beginning of every second + // cell in each row (starting with second cell) so that operators become + // binary. This behavior is implemented in amsmath's \start@aligned. + + var numMaths; + var numCols = 0; + var emptyGroup = { + type: "ordgroup", + mode: context.mode, + body: [] + }; + + if (args[0] && args[0].type === "ordgroup") { + var arg0 = ""; + + for (var i = 0; i < args[0].body.length; i++) { + var textord = assertNodeType(args[0].body[i], "textord"); + arg0 += textord.text; + } + + numMaths = Number(arg0); + numCols = numMaths * 2; + } + + var isAligned = !numCols; + res.body.forEach(function (row) { + for (var _i4 = 1; _i4 < row.length; _i4 += 2) { + // Modify ordgroup node within styling node + var styling = assertNodeType(row[_i4], "styling"); + var ordgroup = assertNodeType(styling.body[0], "ordgroup"); + ordgroup.body.unshift(emptyGroup); + } + + if (!isAligned) { + // Case 1 + var curMaths = row.length / 2; + + if (numMaths < curMaths) { + throw new ParseError("Too many math in a row: " + ("expected " + numMaths + ", but got " + curMaths), row[0]); + } + } else if (numCols < row.length) { + // Case 2 + numCols = row.length; + } + }); // Adjusting alignment. + // In aligned mode, we add one \qquad between columns; + // otherwise we add nothing. + + for (var _i5 = 0; _i5 < numCols; ++_i5) { + var align = "r"; + var pregap = 0; + + if (_i5 % 2 === 1) { + align = "l"; + } else if (_i5 > 0 && isAligned) { + // "aligned" mode. + pregap = 1; // add one \quad + } + + cols[_i5] = { + type: "align", + align: align, + pregap: pregap, + postgap: 0 + }; + } + + res.colSeparationType = isAligned ? "align" : "alignat"; + return res; +}; // Arrays are part of LaTeX, defined in lttab.dtx so its documentation +// is part of the source2e.pdf file of LaTeX2e source documentation. +// {darray} is an {array} environment where cells are set in \displaystyle, +// as defined in nccmath.sty. + + +defineEnvironment({ + type: "array", + names: ["array", "darray"], + props: { + numArgs: 1 + }, + + handler(context, args) { + // Since no types are specified above, the two possibilities are + // - The argument is wrapped in {} or [], in which case Parser's + // parseGroup() returns an "ordgroup" wrapping some symbol node. + // - The argument is a bare symbol node. + var symNode = checkSymbolNodeType(args[0]); + var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; + var cols = colalign.map(function (nde) { + var node = assertSymbolNodeType(nde); + var ca = node.text; + + if ("lcr".indexOf(ca) !== -1) { + return { + type: "align", + align: ca + }; + } else if (ca === "|") { + return { + type: "separator", + separator: "|" + }; + } else if (ca === ":") { + return { + type: "separator", + separator: ":" + }; + } + + throw new ParseError("Unknown column alignment: " + ca, nde); + }); + var res = { + cols, + hskipBeforeAndAfter: true, + // \@preamble in lttab.dtx + maxNumCols: cols.length + }; + return parseArray(context.parser, res, dCellStyle(context.envName)); + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); // The matrix environments of amsmath builds on the array environment +// of LaTeX, which is discussed above. +// The mathtools package adds starred versions of the same environments. +// These have an optional argument to choose left|center|right justification. + +defineEnvironment({ + type: "array", + names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"], + props: { + numArgs: 0 + }, + + handler(context) { + var delimiters = { + "matrix": null, + "pmatrix": ["(", ")"], + "bmatrix": ["[", "]"], + "Bmatrix": ["\\{", "\\}"], + "vmatrix": ["|", "|"], + "Vmatrix": ["\\Vert", "\\Vert"] + }[context.envName.replace("*", "")]; // \hskip -\arraycolsep in amsmath + + var colAlign = "c"; + var payload = { + hskipBeforeAndAfter: false, + cols: [{ + type: "align", + align: colAlign + }] + }; + + if (context.envName.charAt(context.envName.length - 1) === "*") { + // It's one of the mathtools starred functions. + // Parse the optional alignment argument. + var parser = context.parser; + parser.consumeSpaces(); + + if (parser.fetch().text === "[") { + parser.consume(); + parser.consumeSpaces(); + colAlign = parser.fetch().text; + + if ("lcr".indexOf(colAlign) === -1) { + throw new ParseError("Expected l or c or r", parser.nextToken); + } + + parser.consume(); + parser.consumeSpaces(); + parser.expect("]"); + parser.consume(); + payload.cols = [{ + type: "align", + align: colAlign + }]; + } + } + + var res = parseArray(context.parser, payload, dCellStyle(context.envName)); // Populate cols with the correct number of column alignment specs. + + var numCols = Math.max(0, ...res.body.map(row => row.length)); + res.cols = new Array(numCols).fill({ + type: "align", + align: colAlign + }); + return delimiters ? { + type: "leftright", + mode: context.mode, + body: [res], + left: delimiters[0], + right: delimiters[1], + rightColor: undefined // \right uninfluenced by \color in array + + } : res; + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); +defineEnvironment({ + type: "array", + names: ["smallmatrix"], + props: { + numArgs: 0 + }, + + handler(context) { + var payload = { + arraystretch: 0.5 + }; + var res = parseArray(context.parser, payload, "script"); + res.colSeparationType = "small"; + return res; + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); +defineEnvironment({ + type: "array", + names: ["subarray"], + props: { + numArgs: 1 + }, + + handler(context, args) { + // Parsing of {subarray} is similar to {array} + var symNode = checkSymbolNodeType(args[0]); + var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; + var cols = colalign.map(function (nde) { + var node = assertSymbolNodeType(nde); + var ca = node.text; // {subarray} only recognizes "l" & "c" + + if ("lc".indexOf(ca) !== -1) { + return { + type: "align", + align: ca + }; + } + + throw new ParseError("Unknown column alignment: " + ca, nde); + }); + + if (cols.length > 1) { + throw new ParseError("{subarray} can contain only one column"); + } + + var res = { + cols, + hskipBeforeAndAfter: false, + arraystretch: 0.5 + }; + res = parseArray(context.parser, res, "script"); + + if (res.body.length > 0 && res.body[0].length > 1) { + throw new ParseError("{subarray} can contain only one column"); + } + + return res; + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); // A cases environment (in amsmath.sty) is almost equivalent to +// \def\arraystretch{1.2}% +// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. +// {dcases} is a {cases} environment where cells are set in \displaystyle, +// as defined in mathtools.sty. +// {rcases} is another mathtools environment. It's brace is on the right side. + +defineEnvironment({ + type: "array", + names: ["cases", "dcases", "rcases", "drcases"], + props: { + numArgs: 0 + }, + + handler(context) { + var payload = { + arraystretch: 1.2, + cols: [{ + type: "align", + align: "l", + pregap: 0, + // TODO(kevinb) get the current style. + // For now we use the metrics for TEXT style which is what we were + // doing before. Before attempting to get the current style we + // should look at TeX's behavior especially for \over and matrices. + postgap: 1.0 + /* 1em quad */ + + }, { + type: "align", + align: "l", + pregap: 0, + postgap: 0 + }] + }; + var res = parseArray(context.parser, payload, dCellStyle(context.envName)); + return { + type: "leftright", + mode: context.mode, + body: [res], + left: context.envName.indexOf("r") > -1 ? "." : "\\{", + right: context.envName.indexOf("r") > -1 ? "\\}" : ".", + rightColor: undefined + }; + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); // In the align environment, one uses ampersands, &, to specify number of +// columns in each row, and to locate spacing between each column. +// align gets automatic numbering. align* and aligned do not. +// The alignedat environment can be used in math mode. +// Note that we assume \nomallineskiplimit to be zero, +// so that \strut@ is the same as \strut. + +defineEnvironment({ + type: "array", + names: ["align", "align*", "aligned", "split"], + props: { + numArgs: 0 + }, + handler: alignedHandler, + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); // A gathered environment is like an array environment with one centered +// column, but where rows are considered lines so get \jot line spacing +// and contents are set in \displaystyle. + +defineEnvironment({ + type: "array", + names: ["gathered", "gather", "gather*"], + props: { + numArgs: 0 + }, + + handler(context) { + if (utils.contains(["gather", "gather*"], context.envName)) { + validateAmsEnvironmentContext(context); + } + + var res = { + cols: [{ + type: "align", + align: "c" + }], + addJot: true, + colSeparationType: "gather", + autoTag: getAutoTag(context.envName), + emptySingleRow: true, + leqno: context.parser.settings.leqno + }; + return parseArray(context.parser, res, "display"); + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); // alignat environment is like an align environment, but one must explicitly +// specify maximum number of columns in each row, and can adjust spacing between +// each columns. + +defineEnvironment({ + type: "array", + names: ["alignat", "alignat*", "alignedat"], + props: { + numArgs: 1 + }, + handler: alignedHandler, + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); +defineEnvironment({ + type: "array", + names: ["equation", "equation*"], + props: { + numArgs: 0 + }, + + handler(context) { + validateAmsEnvironmentContext(context); + var res = { + autoTag: getAutoTag(context.envName), + emptySingleRow: true, + singleRow: true, + maxNumCols: 1, + leqno: context.parser.settings.leqno + }; + return parseArray(context.parser, res, "display"); + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); +defineEnvironment({ + type: "array", + names: ["CD"], + props: { + numArgs: 0 + }, + + handler(context) { + validateAmsEnvironmentContext(context); + return parseCD(context.parser); + }, + + htmlBuilder: htmlBuilder$6, + mathmlBuilder: mathmlBuilder$5 +}); +defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}"); +defineMacro("\\notag", "\\nonumber"); // Catch \hline outside array environment + +defineFunction({ + type: "text", + // Doesn't matter what this is. + names: ["\\hline", "\\hdashline"], + props: { + numArgs: 0, + allowedInText: true, + allowedInMath: true + }, + + handler(context, args) { + throw new ParseError(context.funcName + " valid only within array environment"); + } + +}); + +var environments = _environments; + +// defineEnvironment definitions. + +defineFunction({ + type: "environment", + names: ["\\begin", "\\end"], + props: { + numArgs: 1, + argTypes: ["text"] + }, + + handler(_ref, args) { + var { + parser, + funcName + } = _ref; + var nameGroup = args[0]; + + if (nameGroup.type !== "ordgroup") { + throw new ParseError("Invalid environment name", nameGroup); + } + + var envName = ""; + + for (var i = 0; i < nameGroup.body.length; ++i) { + envName += assertNodeType(nameGroup.body[i], "textord").text; + } + + if (funcName === "\\begin") { + // begin...end is similar to left...right + if (!environments.hasOwnProperty(envName)) { + throw new ParseError("No such environment: " + envName, nameGroup); + } // Build the environment object. Arguments and other information will + // be made available to the begin and end methods using properties. + + + var env = environments[envName]; + var { + args: _args, + optArgs + } = parser.parseArguments("\\begin{" + envName + "}", env); + var context = { + mode: parser.mode, + envName, + parser + }; + var result = env.handler(context, _args, optArgs); + parser.expect("\\end", false); + var endNameToken = parser.nextToken; + var end = assertNodeType(parser.parseFunction(), "environment"); + + if (end.name !== envName) { + throw new ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken); + } // $FlowFixMe, "environment" handler returns an environment ParseNode + + + return result; + } + + return { + type: "environment", + mode: parser.mode, + name: envName, + nameGroup + }; + } + +}); + +// TODO(kevinb): implement \\sl and \\sc + +var htmlBuilder$5 = (group, options) => { + var font = group.font; + var newOptions = options.withFont(font); + return buildGroup$1(group.body, newOptions); +}; + +var mathmlBuilder$4 = (group, options) => { + var font = group.font; + var newOptions = options.withFont(font); + return buildGroup(group.body, newOptions); +}; + +var fontAliases = { + "\\Bbb": "\\mathbb", + "\\bold": "\\mathbf", + "\\frak": "\\mathfrak", + "\\bm": "\\boldsymbol" +}; +defineFunction({ + type: "font", + names: [// styles, except \boldsymbol defined below + "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", "\\mathsfit", // families + "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", // aliases, except \bm defined below + "\\Bbb", "\\bold", "\\frak"], + props: { + numArgs: 1, + allowedInArgument: true + }, + handler: (_ref, args) => { + var { + parser, + funcName + } = _ref; + var body = normalizeArgument(args[0]); + var func = funcName; + + if (func in fontAliases) { + func = fontAliases[func]; + } + + return { + type: "font", + mode: parser.mode, + font: func.slice(1), + body + }; + }, + htmlBuilder: htmlBuilder$5, + mathmlBuilder: mathmlBuilder$4 +}); +defineFunction({ + type: "mclass", + names: ["\\boldsymbol", "\\bm"], + props: { + numArgs: 1 + }, + handler: (_ref2, args) => { + var { + parser + } = _ref2; + var body = args[0]; + var isCharacterBox = utils.isCharacterBox(body); // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the + // argument's bin|rel|ord status + + return { + type: "mclass", + mode: parser.mode, + mclass: binrelClass(body), + body: [{ + type: "font", + mode: parser.mode, + font: "boldsymbol", + body + }], + isCharacterBox: isCharacterBox + }; + } +}); // Old font changing functions + +defineFunction({ + type: "font", + names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], + props: { + numArgs: 0, + allowedInText: true + }, + handler: (_ref3, args) => { + var { + parser, + funcName, + breakOnTokenText + } = _ref3; + var { + mode + } = parser; + var body = parser.parseExpression(true, breakOnTokenText); + var style = "math" + funcName.slice(1); + return { + type: "font", + mode: mode, + font: style, + body: { + type: "ordgroup", + mode: parser.mode, + body + } + }; + }, + htmlBuilder: htmlBuilder$5, + mathmlBuilder: mathmlBuilder$4 +}); + +var adjustStyle = (size, originalStyle) => { + // Figure out what style this fraction should be in based on the + // function used + var style = originalStyle; + + if (size === "display") { + // Get display style as a default. + // If incoming style is sub/sup, use style.text() to get correct size. + style = style.id >= Style$1.SCRIPT.id ? style.text() : Style$1.DISPLAY; + } else if (size === "text" && style.size === Style$1.DISPLAY.size) { + // We're in a \tfrac but incoming style is displaystyle, so: + style = Style$1.TEXT; + } else if (size === "script") { + style = Style$1.SCRIPT; + } else if (size === "scriptscript") { + style = Style$1.SCRIPTSCRIPT; + } + + return style; +}; + +var htmlBuilder$4 = (group, options) => { + // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e). + var style = adjustStyle(group.size, options.style); + var nstyle = style.fracNum(); + var dstyle = style.fracDen(); + var newOptions; + newOptions = options.havingStyle(nstyle); + var numerm = buildGroup$1(group.numer, newOptions, options); + + if (group.continued) { + // \cfrac inserts a \strut into the numerator. + // Get \strut dimensions from TeXbook page 353. + var hStrut = 8.5 / options.fontMetrics().ptPerEm; + var dStrut = 3.5 / options.fontMetrics().ptPerEm; + numerm.height = numerm.height < hStrut ? hStrut : numerm.height; + numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth; + } + + newOptions = options.havingStyle(dstyle); + var denomm = buildGroup$1(group.denom, newOptions, options); + var rule; + var ruleWidth; + var ruleSpacing; + + if (group.hasBarLine) { + if (group.barSize) { + ruleWidth = calculateSize(group.barSize, options); + rule = buildCommon.makeLineSpan("frac-line", options, ruleWidth); + } else { + rule = buildCommon.makeLineSpan("frac-line", options); + } + + ruleWidth = rule.height; + ruleSpacing = rule.height; + } else { + rule = null; + ruleWidth = 0; + ruleSpacing = options.fontMetrics().defaultRuleThickness; + } // Rule 15b + + + var numShift; + var clearance; + var denomShift; + + if (style.size === Style$1.DISPLAY.size || group.size === "display") { + numShift = options.fontMetrics().num1; + + if (ruleWidth > 0) { + clearance = 3 * ruleSpacing; + } else { + clearance = 7 * ruleSpacing; + } + + denomShift = options.fontMetrics().denom1; + } else { + if (ruleWidth > 0) { + numShift = options.fontMetrics().num2; + clearance = ruleSpacing; + } else { + numShift = options.fontMetrics().num3; + clearance = 3 * ruleSpacing; + } + + denomShift = options.fontMetrics().denom2; + } + + var frac; + + if (!rule) { + // Rule 15c + var candidateClearance = numShift - numerm.depth - (denomm.height - denomShift); + + if (candidateClearance < clearance) { + numShift += 0.5 * (clearance - candidateClearance); + denomShift += 0.5 * (clearance - candidateClearance); + } + + frac = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: denomm, + shift: denomShift + }, { + type: "elem", + elem: numerm, + shift: -numShift + }] + }, options); + } else { + // Rule 15d + var axisHeight = options.fontMetrics().axisHeight; + + if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) { + numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth)); + } + + if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) { + denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift)); + } + + var midShift = -(axisHeight - 0.5 * ruleWidth); + frac = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: denomm, + shift: denomShift + }, { + type: "elem", + elem: rule, + shift: midShift + }, { + type: "elem", + elem: numerm, + shift: -numShift + }] + }, options); + } // Since we manually change the style sometimes (with \dfrac or \tfrac), + // account for the possible size change here. + + + newOptions = options.havingStyle(style); + frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier; + frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier; // Rule 15e + + var delimSize; + + if (style.size === Style$1.DISPLAY.size) { + delimSize = options.fontMetrics().delim1; + } else if (style.size === Style$1.SCRIPTSCRIPT.size) { + delimSize = options.havingStyle(Style$1.SCRIPT).fontMetrics().delim2; + } else { + delimSize = options.fontMetrics().delim2; + } + + var leftDelim; + var rightDelim; + + if (group.leftDelim == null) { + leftDelim = makeNullDelimiter(options, ["mopen"]); + } else { + leftDelim = delimiter.customSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]); + } + + if (group.continued) { + rightDelim = buildCommon.makeSpan([]); // zero width for \cfrac + } else if (group.rightDelim == null) { + rightDelim = makeNullDelimiter(options, ["mclose"]); + } else { + rightDelim = delimiter.customSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]); + } + + return buildCommon.makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, buildCommon.makeSpan(["mfrac"], [frac]), rightDelim], options); +}; + +var mathmlBuilder$3 = (group, options) => { + var node = new mathMLTree.MathNode("mfrac", [buildGroup(group.numer, options), buildGroup(group.denom, options)]); + + if (!group.hasBarLine) { + node.setAttribute("linethickness", "0px"); + } else if (group.barSize) { + var ruleWidth = calculateSize(group.barSize, options); + node.setAttribute("linethickness", makeEm(ruleWidth)); + } + + var style = adjustStyle(group.size, options.style); + + if (style.size !== options.style.size) { + node = new mathMLTree.MathNode("mstyle", [node]); + var isDisplay = style.size === Style$1.DISPLAY.size ? "true" : "false"; + node.setAttribute("displaystyle", isDisplay); + node.setAttribute("scriptlevel", "0"); + } + + if (group.leftDelim != null || group.rightDelim != null) { + var withDelims = []; + + if (group.leftDelim != null) { + var leftOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.leftDelim.replace("\\", ""))]); + leftOp.setAttribute("fence", "true"); + withDelims.push(leftOp); + } + + withDelims.push(node); + + if (group.rightDelim != null) { + var rightOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.rightDelim.replace("\\", ""))]); + rightOp.setAttribute("fence", "true"); + withDelims.push(rightOp); + } + + return makeRow(withDelims); + } + + return node; +}; + +defineFunction({ + type: "genfrac", + names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", // can’t be entered directly + "\\\\bracefrac", "\\\\brackfrac" // ditto + ], + props: { + numArgs: 2, + allowedInArgument: true + }, + handler: (_ref, args) => { + var { + parser, + funcName + } = _ref; + var numer = args[0]; + var denom = args[1]; + var hasBarLine; + var leftDelim = null; + var rightDelim = null; + var size = "auto"; + + switch (funcName) { + case "\\dfrac": + case "\\frac": + case "\\tfrac": + hasBarLine = true; + break; + + case "\\\\atopfrac": + hasBarLine = false; + break; + + case "\\dbinom": + case "\\binom": + case "\\tbinom": + hasBarLine = false; + leftDelim = "("; + rightDelim = ")"; + break; + + case "\\\\bracefrac": + hasBarLine = false; + leftDelim = "\\{"; + rightDelim = "\\}"; + break; + + case "\\\\brackfrac": + hasBarLine = false; + leftDelim = "["; + rightDelim = "]"; + break; + + default: + throw new Error("Unrecognized genfrac command"); + } + + switch (funcName) { + case "\\dfrac": + case "\\dbinom": + size = "display"; + break; + + case "\\tfrac": + case "\\tbinom": + size = "text"; + break; + } + + return { + type: "genfrac", + mode: parser.mode, + continued: false, + numer, + denom, + hasBarLine, + leftDelim, + rightDelim, + size, + barSize: null + }; + }, + htmlBuilder: htmlBuilder$4, + mathmlBuilder: mathmlBuilder$3 +}); +defineFunction({ + type: "genfrac", + names: ["\\cfrac"], + props: { + numArgs: 2 + }, + handler: (_ref2, args) => { + var { + parser, + funcName + } = _ref2; + var numer = args[0]; + var denom = args[1]; + return { + type: "genfrac", + mode: parser.mode, + continued: true, + numer, + denom, + hasBarLine: true, + leftDelim: null, + rightDelim: null, + size: "display", + barSize: null + }; + } +}); // Infix generalized fractions -- these are not rendered directly, but replaced +// immediately by one of the variants above. + +defineFunction({ + type: "infix", + names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], + props: { + numArgs: 0, + infix: true + }, + + handler(_ref3) { + var { + parser, + funcName, + token + } = _ref3; + var replaceWith; + + switch (funcName) { + case "\\over": + replaceWith = "\\frac"; + break; + + case "\\choose": + replaceWith = "\\binom"; + break; + + case "\\atop": + replaceWith = "\\\\atopfrac"; + break; + + case "\\brace": + replaceWith = "\\\\bracefrac"; + break; + + case "\\brack": + replaceWith = "\\\\brackfrac"; + break; + + default: + throw new Error("Unrecognized infix genfrac command"); + } + + return { + type: "infix", + mode: parser.mode, + replaceWith, + token + }; + } + +}); +var stylArray = ["display", "text", "script", "scriptscript"]; + +var delimFromValue = function delimFromValue(delimString) { + var delim = null; + + if (delimString.length > 0) { + delim = delimString; + delim = delim === "." ? null : delim; + } + + return delim; +}; + +defineFunction({ + type: "genfrac", + names: ["\\genfrac"], + props: { + numArgs: 6, + allowedInArgument: true, + argTypes: ["math", "math", "size", "text", "math", "math"] + }, + + handler(_ref4, args) { + var { + parser + } = _ref4; + var numer = args[4]; + var denom = args[5]; // Look into the parse nodes to get the desired delimiters. + + var leftNode = normalizeArgument(args[0]); + var leftDelim = leftNode.type === "atom" && leftNode.family === "open" ? delimFromValue(leftNode.text) : null; + var rightNode = normalizeArgument(args[1]); + var rightDelim = rightNode.type === "atom" && rightNode.family === "close" ? delimFromValue(rightNode.text) : null; + var barNode = assertNodeType(args[2], "size"); + var hasBarLine; + var barSize = null; + + if (barNode.isBlank) { + // \genfrac acts differently than \above. + // \genfrac treats an empty size group as a signal to use a + // standard bar size. \above would see size = 0 and omit the bar. + hasBarLine = true; + } else { + barSize = barNode.value; + hasBarLine = barSize.number > 0; + } // Find out if we want displaystyle, textstyle, etc. + + + var size = "auto"; + var styl = args[3]; + + if (styl.type === "ordgroup") { + if (styl.body.length > 0) { + var textOrd = assertNodeType(styl.body[0], "textord"); + size = stylArray[Number(textOrd.text)]; + } + } else { + styl = assertNodeType(styl, "textord"); + size = stylArray[Number(styl.text)]; + } + + return { + type: "genfrac", + mode: parser.mode, + numer, + denom, + continued: false, + hasBarLine, + barSize, + leftDelim, + rightDelim, + size + }; + }, + + htmlBuilder: htmlBuilder$4, + mathmlBuilder: mathmlBuilder$3 +}); // \above is an infix fraction that also defines a fraction bar size. + +defineFunction({ + type: "infix", + names: ["\\above"], + props: { + numArgs: 1, + argTypes: ["size"], + infix: true + }, + + handler(_ref5, args) { + var { + parser, + funcName, + token + } = _ref5; + return { + type: "infix", + mode: parser.mode, + replaceWith: "\\\\abovefrac", + size: assertNodeType(args[0], "size").value, + token + }; + } + +}); +defineFunction({ + type: "genfrac", + names: ["\\\\abovefrac"], + props: { + numArgs: 3, + argTypes: ["math", "size", "math"] + }, + handler: (_ref6, args) => { + var { + parser, + funcName + } = _ref6; + var numer = args[0]; + var barSize = assert(assertNodeType(args[1], "infix").size); + var denom = args[2]; + var hasBarLine = barSize.number > 0; + return { + type: "genfrac", + mode: parser.mode, + numer, + denom, + continued: false, + hasBarLine, + barSize, + leftDelim: null, + rightDelim: null, + size: "auto" + }; + }, + htmlBuilder: htmlBuilder$4, + mathmlBuilder: mathmlBuilder$3 +}); + +// NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but +// also "supsub" since an over/underbrace can affect super/subscripting. +var htmlBuilder$3 = (grp, options) => { + var style = options.style; // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node. + + var supSubGroup; + var group; + + if (grp.type === "supsub") { + // Ref: LaTeX source2e: }}}}\limits} + // i.e. LaTeX treats the brace similar to an op and passes it + // with \limits, so we need to assign supsub style. + supSubGroup = grp.sup ? buildGroup$1(grp.sup, options.havingStyle(style.sup()), options) : buildGroup$1(grp.sub, options.havingStyle(style.sub()), options); + group = assertNodeType(grp.base, "horizBrace"); + } else { + group = assertNodeType(grp, "horizBrace"); + } // Build the base group + + + var body = buildGroup$1(group.base, options.havingBaseStyle(Style$1.DISPLAY)); // Create the stretchy element + + var braceBody = stretchy.svgSpan(group, options); // Generate the vlist, with the appropriate kerns ┏━━━━━━━━┓ + // This first vlist contains the content and the brace: equation + + var vlist; + + if (group.isOver) { + vlist = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: body + }, { + type: "kern", + size: 0.1 + }, { + type: "elem", + elem: braceBody + }] + }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList. + + vlist.children[0].children[0].children[1].classes.push("svg-align"); + } else { + vlist = buildCommon.makeVList({ + positionType: "bottom", + positionData: body.depth + 0.1 + braceBody.height, + children: [{ + type: "elem", + elem: braceBody + }, { + type: "kern", + size: 0.1 + }, { + type: "elem", + elem: body + }] + }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList. + + vlist.children[0].children[0].children[0].classes.push("svg-align"); + } + + if (supSubGroup) { + // To write the supsub, wrap the first vlist in another vlist: + // They can't all go in the same vlist, because the note might be + // wider than the equation. We want the equation to control the + // brace width. + // note long note long note + // ┏━━━━━━━━┓ or ┏━━━┓ not ┏━━━━━━━━━┓ + // equation eqn eqn + var vSpan = buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options); + + if (group.isOver) { + vlist = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: vSpan + }, { + type: "kern", + size: 0.2 + }, { + type: "elem", + elem: supSubGroup + }] + }, options); + } else { + vlist = buildCommon.makeVList({ + positionType: "bottom", + positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth, + children: [{ + type: "elem", + elem: supSubGroup + }, { + type: "kern", + size: 0.2 + }, { + type: "elem", + elem: vSpan + }] + }, options); + } + } + + return buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options); +}; + +var mathmlBuilder$2 = (group, options) => { + var accentNode = stretchy.mathMLnode(group.label); + return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [buildGroup(group.base, options), accentNode]); +}; // Horizontal stretchy braces + + +defineFunction({ + type: "horizBrace", + names: ["\\overbrace", "\\underbrace"], + props: { + numArgs: 1 + }, + + handler(_ref, args) { + var { + parser, + funcName + } = _ref; + return { + type: "horizBrace", + mode: parser.mode, + label: funcName, + isOver: /^\\over/.test(funcName), + base: args[0] + }; + }, + + htmlBuilder: htmlBuilder$3, + mathmlBuilder: mathmlBuilder$2 +}); + +defineFunction({ + type: "href", + names: ["\\href"], + props: { + numArgs: 2, + argTypes: ["url", "original"], + allowedInText: true + }, + handler: (_ref, args) => { + var { + parser + } = _ref; + var body = args[1]; + var href = assertNodeType(args[0], "url").url; + + if (!parser.settings.isTrusted({ + command: "\\href", + url: href + })) { + return parser.formatUnsupportedCmd("\\href"); + } + + return { + type: "href", + mode: parser.mode, + href, + body: ordargument(body) + }; + }, + htmlBuilder: (group, options) => { + var elements = buildExpression$1(group.body, options, false); + return buildCommon.makeAnchor(group.href, [], elements, options); + }, + mathmlBuilder: (group, options) => { + var math = buildExpressionRow(group.body, options); + + if (!(math instanceof MathNode)) { + math = new MathNode("mrow", [math]); + } + + math.setAttribute("href", group.href); + return math; + } +}); +defineFunction({ + type: "href", + names: ["\\url"], + props: { + numArgs: 1, + argTypes: ["url"], + allowedInText: true + }, + handler: (_ref2, args) => { + var { + parser + } = _ref2; + var href = assertNodeType(args[0], "url").url; + + if (!parser.settings.isTrusted({ + command: "\\url", + url: href + })) { + return parser.formatUnsupportedCmd("\\url"); + } + + var chars = []; + + for (var i = 0; i < href.length; i++) { + var c = href[i]; + + if (c === "~") { + c = "\\textasciitilde"; + } + + chars.push({ + type: "textord", + mode: "text", + text: c + }); + } + + var body = { + type: "text", + mode: parser.mode, + font: "\\texttt", + body: chars + }; + return { + type: "href", + mode: parser.mode, + href, + body: ordargument(body) + }; + } +}); + +// In LaTeX, \vcenter can act only on a box, as in +// \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}} +// This function by itself doesn't do anything but prevent a soft line break. + +defineFunction({ + type: "hbox", + names: ["\\hbox"], + props: { + numArgs: 1, + argTypes: ["text"], + allowedInText: true, + primitive: true + }, + + handler(_ref, args) { + var { + parser + } = _ref; + return { + type: "hbox", + mode: parser.mode, + body: ordargument(args[0]) + }; + }, + + htmlBuilder(group, options) { + var elements = buildExpression$1(group.body, options, false); + return buildCommon.makeFragment(elements); + }, + + mathmlBuilder(group, options) { + return new mathMLTree.MathNode("mrow", buildExpression(group.body, options)); + } + +}); + +defineFunction({ + type: "html", + names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"], + props: { + numArgs: 2, + argTypes: ["raw", "original"], + allowedInText: true + }, + handler: (_ref, args) => { + var { + parser, + funcName, + token + } = _ref; + var value = assertNodeType(args[0], "raw").string; + var body = args[1]; + + if (parser.settings.strict) { + parser.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode"); + } + + var trustContext; + var attributes = {}; + + switch (funcName) { + case "\\htmlClass": + attributes.class = value; + trustContext = { + command: "\\htmlClass", + class: value + }; + break; + + case "\\htmlId": + attributes.id = value; + trustContext = { + command: "\\htmlId", + id: value + }; + break; + + case "\\htmlStyle": + attributes.style = value; + trustContext = { + command: "\\htmlStyle", + style: value + }; + break; + + case "\\htmlData": + { + var data = value.split(","); + + for (var i = 0; i < data.length; i++) { + var keyVal = data[i].split("="); + + if (keyVal.length !== 2) { + throw new ParseError("Error parsing key-value for \\htmlData"); + } + + attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); + } + + trustContext = { + command: "\\htmlData", + attributes + }; + break; + } + + default: + throw new Error("Unrecognized html command"); + } + + if (!parser.settings.isTrusted(trustContext)) { + return parser.formatUnsupportedCmd(funcName); + } + + return { + type: "html", + mode: parser.mode, + attributes, + body: ordargument(body) + }; + }, + htmlBuilder: (group, options) => { + var elements = buildExpression$1(group.body, options, false); + var classes = ["enclosing"]; + + if (group.attributes.class) { + classes.push(...group.attributes.class.trim().split(/\s+/)); + } + + var span = buildCommon.makeSpan(classes, elements, options); + + for (var attr in group.attributes) { + if (attr !== "class" && group.attributes.hasOwnProperty(attr)) { + span.setAttribute(attr, group.attributes[attr]); + } + } + + return span; + }, + mathmlBuilder: (group, options) => { + return buildExpressionRow(group.body, options); + } +}); + +defineFunction({ + type: "htmlmathml", + names: ["\\html@mathml"], + props: { + numArgs: 2, + allowedInText: true + }, + handler: (_ref, args) => { + var { + parser + } = _ref; + return { + type: "htmlmathml", + mode: parser.mode, + html: ordargument(args[0]), + mathml: ordargument(args[1]) + }; + }, + htmlBuilder: (group, options) => { + var elements = buildExpression$1(group.html, options, false); + return buildCommon.makeFragment(elements); + }, + mathmlBuilder: (group, options) => { + return buildExpressionRow(group.mathml, options); + } +}); + +var sizeData = function sizeData(str) { + if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { + // str is a number with no unit specified. + // default unit is bp, per graphix package. + return { + number: +str, + unit: "bp" + }; + } else { + var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); + + if (!match) { + throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); + } + + var data = { + number: +(match[1] + match[2]), + // sign + magnitude, cast to number + unit: match[3] + }; + + if (!validUnit(data)) { + throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); + } + + return data; + } +}; + +defineFunction({ + type: "includegraphics", + names: ["\\includegraphics"], + props: { + numArgs: 1, + numOptionalArgs: 1, + argTypes: ["raw", "url"], + allowedInText: false + }, + handler: (_ref, args, optArgs) => { + var { + parser + } = _ref; + var width = { + number: 0, + unit: "em" + }; + var height = { + number: 0.9, + unit: "em" + }; // sorta character sized. + + var totalheight = { + number: 0, + unit: "em" + }; + var alt = ""; + + if (optArgs[0]) { + var attributeStr = assertNodeType(optArgs[0], "raw").string; // Parser.js does not parse key/value pairs. We get a string. + + var attributes = attributeStr.split(","); + + for (var i = 0; i < attributes.length; i++) { + var keyVal = attributes[i].split("="); + + if (keyVal.length === 2) { + var str = keyVal[1].trim(); + + switch (keyVal[0].trim()) { + case "alt": + alt = str; + break; + + case "width": + width = sizeData(str); + break; + + case "height": + height = sizeData(str); + break; + + case "totalheight": + totalheight = sizeData(str); + break; + + default: + throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics."); + } + } + } + } + + var src = assertNodeType(args[0], "url").url; + + if (alt === "") { + // No alt given. Use the file name. Strip away the path. + alt = src; + alt = alt.replace(/^.*[\\/]/, ''); + alt = alt.substring(0, alt.lastIndexOf('.')); + } + + if (!parser.settings.isTrusted({ + command: "\\includegraphics", + url: src + })) { + return parser.formatUnsupportedCmd("\\includegraphics"); + } + + return { + type: "includegraphics", + mode: parser.mode, + alt: alt, + width: width, + height: height, + totalheight: totalheight, + src: src + }; + }, + htmlBuilder: (group, options) => { + var height = calculateSize(group.height, options); + var depth = 0; + + if (group.totalheight.number > 0) { + depth = calculateSize(group.totalheight, options) - height; + } + + var width = 0; + + if (group.width.number > 0) { + width = calculateSize(group.width, options); + } + + var style = { + height: makeEm(height + depth) + }; + + if (width > 0) { + style.width = makeEm(width); + } + + if (depth > 0) { + style.verticalAlign = makeEm(-depth); + } + + var node = new Img(group.src, group.alt, style); + node.height = height; + node.depth = depth; + return node; + }, + mathmlBuilder: (group, options) => { + var node = new mathMLTree.MathNode("mglyph", []); + node.setAttribute("alt", group.alt); + var height = calculateSize(group.height, options); + var depth = 0; + + if (group.totalheight.number > 0) { + depth = calculateSize(group.totalheight, options) - height; + node.setAttribute("valign", makeEm(-depth)); + } + + node.setAttribute("height", makeEm(height + depth)); + + if (group.width.number > 0) { + var width = calculateSize(group.width, options); + node.setAttribute("width", makeEm(width)); + } + + node.setAttribute("src", group.src); + return node; + } +}); + +// Horizontal spacing commands + +defineFunction({ + type: "kern", + names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], + props: { + numArgs: 1, + argTypes: ["size"], + primitive: true, + allowedInText: true + }, + + handler(_ref, args) { + var { + parser, + funcName + } = _ref; + var size = assertNodeType(args[0], "size"); + + if (parser.settings.strict) { + var mathFunction = funcName[1] === 'm'; // \mkern, \mskip + + var muUnit = size.value.unit === 'mu'; + + if (mathFunction) { + if (!muUnit) { + parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " supports only mu units, " + ("not " + size.value.unit + " units")); + } + + if (parser.mode !== "math") { + parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " works only in math mode"); + } + } else { + // !mathFunction + if (muUnit) { + parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " doesn't support mu units"); + } + } + } + + return { + type: "kern", + mode: parser.mode, + dimension: size.value + }; + }, + + htmlBuilder(group, options) { + return buildCommon.makeGlue(group.dimension, options); + }, + + mathmlBuilder(group, options) { + var dimension = calculateSize(group.dimension, options); + return new mathMLTree.SpaceNode(dimension); + } + +}); + +// Horizontal overlap functions +defineFunction({ + type: "lap", + names: ["\\mathllap", "\\mathrlap", "\\mathclap"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref, args) => { + var { + parser, + funcName + } = _ref; + var body = args[0]; + return { + type: "lap", + mode: parser.mode, + alignment: funcName.slice(5), + body + }; + }, + htmlBuilder: (group, options) => { + // mathllap, mathrlap, mathclap + var inner; + + if (group.alignment === "clap") { + // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/ + inner = buildCommon.makeSpan([], [buildGroup$1(group.body, options)]); // wrap, since CSS will center a .clap > .inner > span + + inner = buildCommon.makeSpan(["inner"], [inner], options); + } else { + inner = buildCommon.makeSpan(["inner"], [buildGroup$1(group.body, options)]); + } + + var fix = buildCommon.makeSpan(["fix"], []); + var node = buildCommon.makeSpan([group.alignment], [inner, fix], options); // At this point, we have correctly set horizontal alignment of the + // two items involved in the lap. + // Next, use a strut to set the height of the HTML bounding box. + // Otherwise, a tall argument may be misplaced. + // This code resolved issue #1153 + + var strut = buildCommon.makeSpan(["strut"]); + strut.style.height = makeEm(node.height + node.depth); + + if (node.depth) { + strut.style.verticalAlign = makeEm(-node.depth); + } + + node.children.unshift(strut); // Next, prevent vertical misplacement when next to something tall. + // This code resolves issue #1234 + + node = buildCommon.makeSpan(["thinbox"], [node], options); + return buildCommon.makeSpan(["mord", "vbox"], [node], options); + }, + mathmlBuilder: (group, options) => { + // mathllap, mathrlap, mathclap + var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]); + + if (group.alignment !== "rlap") { + var offset = group.alignment === "llap" ? "-1" : "-0.5"; + node.setAttribute("lspace", offset + "width"); + } + + node.setAttribute("width", "0px"); + return node; + } +}); + +defineFunction({ + type: "styling", + names: ["\\(", "$"], + props: { + numArgs: 0, + allowedInText: true, + allowedInMath: false + }, + + handler(_ref, args) { + var { + funcName, + parser + } = _ref; + var outerMode = parser.mode; + parser.switchMode("math"); + var close = funcName === "\\(" ? "\\)" : "$"; + var body = parser.parseExpression(false, close); + parser.expect(close); + parser.switchMode(outerMode); + return { + type: "styling", + mode: parser.mode, + style: "text", + body + }; + } + +}); // Check for extra closing math delimiters + +defineFunction({ + type: "text", + // Doesn't matter what this is. + names: ["\\)", "\\]"], + props: { + numArgs: 0, + allowedInText: true, + allowedInMath: false + }, + + handler(context, args) { + throw new ParseError("Mismatched " + context.funcName); + } + +}); + +var chooseMathStyle = (group, options) => { + switch (options.style.size) { + case Style$1.DISPLAY.size: + return group.display; + + case Style$1.TEXT.size: + return group.text; + + case Style$1.SCRIPT.size: + return group.script; + + case Style$1.SCRIPTSCRIPT.size: + return group.scriptscript; + + default: + return group.text; + } +}; + +defineFunction({ + type: "mathchoice", + names: ["\\mathchoice"], + props: { + numArgs: 4, + primitive: true + }, + handler: (_ref, args) => { + var { + parser + } = _ref; + return { + type: "mathchoice", + mode: parser.mode, + display: ordargument(args[0]), + text: ordargument(args[1]), + script: ordargument(args[2]), + scriptscript: ordargument(args[3]) + }; + }, + htmlBuilder: (group, options) => { + var body = chooseMathStyle(group, options); + var elements = buildExpression$1(body, options, false); + return buildCommon.makeFragment(elements); + }, + mathmlBuilder: (group, options) => { + var body = chooseMathStyle(group, options); + return buildExpressionRow(body, options); + } +}); + +var assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => { + base = buildCommon.makeSpan([], [base]); + var subIsSingleCharacter = subGroup && utils.isCharacterBox(subGroup); + var sub; + var sup; // We manually have to handle the superscripts and subscripts. This, + // aside from the kern calculations, is copied from supsub. + + if (supGroup) { + var elem = buildGroup$1(supGroup, options.havingStyle(style.sup()), options); + sup = { + elem, + kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth) + }; + } + + if (subGroup) { + var _elem = buildGroup$1(subGroup, options.havingStyle(style.sub()), options); + + sub = { + elem: _elem, + kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - _elem.height) + }; + } // Build the final group as a vlist of the possible subscript, base, + // and possible superscript. + + + var finalGroup; + + if (sup && sub) { + var bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift; + finalGroup = buildCommon.makeVList({ + positionType: "bottom", + positionData: bottom, + children: [{ + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }, { + type: "elem", + elem: sub.elem, + marginLeft: makeEm(-slant) + }, { + type: "kern", + size: sub.kern + }, { + type: "elem", + elem: base + }, { + type: "kern", + size: sup.kern + }, { + type: "elem", + elem: sup.elem, + marginLeft: makeEm(slant) + }, { + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }] + }, options); + } else if (sub) { + var top = base.height - baseShift; // Shift the limits by the slant of the symbol. Note + // that we are supposed to shift the limits by 1/2 of the slant, + // but since we are centering the limits adding a full slant of + // margin will shift by 1/2 that. + + finalGroup = buildCommon.makeVList({ + positionType: "top", + positionData: top, + children: [{ + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }, { + type: "elem", + elem: sub.elem, + marginLeft: makeEm(-slant) + }, { + type: "kern", + size: sub.kern + }, { + type: "elem", + elem: base + }] + }, options); + } else if (sup) { + var _bottom = base.depth + baseShift; + + finalGroup = buildCommon.makeVList({ + positionType: "bottom", + positionData: _bottom, + children: [{ + type: "elem", + elem: base + }, { + type: "kern", + size: sup.kern + }, { + type: "elem", + elem: sup.elem, + marginLeft: makeEm(slant) + }, { + type: "kern", + size: options.fontMetrics().bigOpSpacing5 + }] + }, options); + } else { + // This case probably shouldn't occur (this would mean the + // supsub was sending us a group with no superscript or + // subscript) but be safe. + return base; + } + + var parts = [finalGroup]; + + if (sub && slant !== 0 && !subIsSingleCharacter) { + // A negative margin-left was applied to the lower limit. + // Avoid an overlap by placing a spacer on the left on the group. + var spacer = buildCommon.makeSpan(["mspace"], [], options); + spacer.style.marginRight = makeEm(slant); + parts.unshift(spacer); + } + + return buildCommon.makeSpan(["mop", "op-limits"], parts, options); +}; + +// Limits, symbols +// Most operators have a large successor symbol, but these don't. +var noSuccessor = ["\\smallint"]; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also +// "supsub" since some of them (like \int) can affect super/subscripting. + +var htmlBuilder$2 = (grp, options) => { + // Operators are handled in the TeXbook pg. 443-444, rule 13(a). + var supGroup; + var subGroup; + var hasLimits = false; + var group; + + if (grp.type === "supsub") { + // If we have limits, supsub will pass us its group to handle. Pull + // out the superscript and subscript and set the group to the op in + // its base. + supGroup = grp.sup; + subGroup = grp.sub; + group = assertNodeType(grp.base, "op"); + hasLimits = true; + } else { + group = assertNodeType(grp, "op"); + } + + var style = options.style; + var large = false; + + if (style.size === Style$1.DISPLAY.size && group.symbol && !utils.contains(noSuccessor, group.name)) { + // Most symbol operators get larger in displaystyle (rule 13) + large = true; + } + + var base; + + if (group.symbol) { + // If this is a symbol, create the symbol. + var fontName = large ? "Size2-Regular" : "Size1-Regular"; + var stash = ""; + + if (group.name === "\\oiint" || group.name === "\\oiiint") { + // No font glyphs yet, so use a glyph w/o the oval. + // TODO: When font glyphs are available, delete this code. + stash = group.name.slice(1); + group.name = stash === "oiint" ? "\\iint" : "\\iiint"; + } + + base = buildCommon.makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]); + + if (stash.length > 0) { + // We're in \oiint or \oiiint. Overlay the oval. + // TODO: When font glyphs are available, delete this code. + var italic = base.italic; + var oval = buildCommon.staticSvg(stash + "Size" + (large ? "2" : "1"), options); + base = buildCommon.makeVList({ + positionType: "individualShift", + children: [{ + type: "elem", + elem: base, + shift: 0 + }, { + type: "elem", + elem: oval, + shift: large ? 0.08 : 0 + }] + }, options); + group.name = "\\" + stash; + base.classes.unshift("mop"); // $FlowFixMe + + base.italic = italic; + } + } else if (group.body) { + // If this is a list, compose that list. + var inner = buildExpression$1(group.body, options, true); + + if (inner.length === 1 && inner[0] instanceof SymbolNode) { + base = inner[0]; + base.classes[0] = "mop"; // replace old mclass + } else { + base = buildCommon.makeSpan(["mop"], inner, options); + } + } else { + // Otherwise, this is a text operator. Build the text from the + // operator's name. + var output = []; + + for (var i = 1; i < group.name.length; i++) { + output.push(buildCommon.mathsym(group.name[i], group.mode, options)); + } + + base = buildCommon.makeSpan(["mop"], output, options); + } // If content of op is a single symbol, shift it vertically. + + + var baseShift = 0; + var slant = 0; + + if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) { + // We suppress the shift of the base of \overset and \underset. Otherwise, + // shift the symbol so its center lies on the axis (rule 13). It + // appears that our fonts have the centers of the symbols already + // almost on the axis, so these numbers are very small. Note we + // don't actually apply this here, but instead it is used either in + // the vlist creation or separately when there are no limits. + baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight; // The slant of the symbol is just its italic correction. + // $FlowFixMe + + slant = base.italic; + } + + if (hasLimits) { + return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift); + } else { + if (baseShift) { + base.style.position = "relative"; + base.style.top = makeEm(baseShift); + } + + return base; + } +}; + +var mathmlBuilder$1 = (group, options) => { + var node; + + if (group.symbol) { + // This is a symbol. Just add the symbol. + node = new MathNode("mo", [makeText(group.name, group.mode)]); + + if (utils.contains(noSuccessor, group.name)) { + node.setAttribute("largeop", "false"); + } + } else if (group.body) { + // This is an operator with children. Add them. + node = new MathNode("mo", buildExpression(group.body, options)); + } else { + // This is a text operator. Add all of the characters from the + // operator's name. + node = new MathNode("mi", [new TextNode(group.name.slice(1))]); // Append an . + // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 + + var operator = new MathNode("mo", [makeText("\u2061", "text")]); + + if (group.parentIsSupSub) { + node = new MathNode("mrow", [node, operator]); + } else { + node = newDocumentFragment([node, operator]); + } + } + + return node; +}; + +var singleCharBigOps = { + "\u220F": "\\prod", + "\u2210": "\\coprod", + "\u2211": "\\sum", + "\u22c0": "\\bigwedge", + "\u22c1": "\\bigvee", + "\u22c2": "\\bigcap", + "\u22c3": "\\bigcup", + "\u2a00": "\\bigodot", + "\u2a01": "\\bigoplus", + "\u2a02": "\\bigotimes", + "\u2a04": "\\biguplus", + "\u2a06": "\\bigsqcup" +}; +defineFunction({ + type: "op", + names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220F", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"], + props: { + numArgs: 0 + }, + handler: (_ref, args) => { + var { + parser, + funcName + } = _ref; + var fName = funcName; + + if (fName.length === 1) { + fName = singleCharBigOps[fName]; + } + + return { + type: "op", + mode: parser.mode, + limits: true, + parentIsSupSub: false, + symbol: true, + name: fName + }; + }, + htmlBuilder: htmlBuilder$2, + mathmlBuilder: mathmlBuilder$1 +}); // Note: calling defineFunction with a type that's already been defined only +// works because the same htmlBuilder and mathmlBuilder are being used. + +defineFunction({ + type: "op", + names: ["\\mathop"], + props: { + numArgs: 1, + primitive: true + }, + handler: (_ref2, args) => { + var { + parser + } = _ref2; + var body = args[0]; + return { + type: "op", + mode: parser.mode, + limits: false, + parentIsSupSub: false, + symbol: false, + body: ordargument(body) + }; + }, + htmlBuilder: htmlBuilder$2, + mathmlBuilder: mathmlBuilder$1 +}); // There are 2 flags for operators; whether they produce limits in +// displaystyle, and whether they are symbols and should grow in +// displaystyle. These four groups cover the four possible choices. + +var singleCharIntegrals = { + "\u222b": "\\int", + "\u222c": "\\iint", + "\u222d": "\\iiint", + "\u222e": "\\oint", + "\u222f": "\\oiint", + "\u2230": "\\oiiint" +}; // No limits, not symbols + +defineFunction({ + type: "op", + names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"], + props: { + numArgs: 0 + }, + + handler(_ref3) { + var { + parser, + funcName + } = _ref3; + return { + type: "op", + mode: parser.mode, + limits: false, + parentIsSupSub: false, + symbol: false, + name: funcName + }; + }, + + htmlBuilder: htmlBuilder$2, + mathmlBuilder: mathmlBuilder$1 +}); // Limits, not symbols + +defineFunction({ + type: "op", + names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], + props: { + numArgs: 0 + }, + + handler(_ref4) { + var { + parser, + funcName + } = _ref4; + return { + type: "op", + mode: parser.mode, + limits: true, + parentIsSupSub: false, + symbol: false, + name: funcName + }; + }, + + htmlBuilder: htmlBuilder$2, + mathmlBuilder: mathmlBuilder$1 +}); // No limits, symbols + +defineFunction({ + type: "op", + names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"], + props: { + numArgs: 0 + }, + + handler(_ref5) { + var { + parser, + funcName + } = _ref5; + var fName = funcName; + + if (fName.length === 1) { + fName = singleCharIntegrals[fName]; + } + + return { + type: "op", + mode: parser.mode, + limits: false, + parentIsSupSub: false, + symbol: true, + name: fName + }; + }, + + htmlBuilder: htmlBuilder$2, + mathmlBuilder: mathmlBuilder$1 +}); + +// NOTE: Unlike most `htmlBuilder`s, this one handles not only +// "operatorname", but also "supsub" since \operatorname* can +// affect super/subscripting. +var htmlBuilder$1 = (grp, options) => { + // Operators are handled in the TeXbook pg. 443-444, rule 13(a). + var supGroup; + var subGroup; + var hasLimits = false; + var group; + + if (grp.type === "supsub") { + // If we have limits, supsub will pass us its group to handle. Pull + // out the superscript and subscript and set the group to the op in + // its base. + supGroup = grp.sup; + subGroup = grp.sub; + group = assertNodeType(grp.base, "operatorname"); + hasLimits = true; + } else { + group = assertNodeType(grp, "operatorname"); + } + + var base; + + if (group.body.length > 0) { + var body = group.body.map(child => { + // $FlowFixMe: Check if the node has a string `text` property. + var childText = child.text; + + if (typeof childText === "string") { + return { + type: "textord", + mode: child.mode, + text: childText + }; + } else { + return child; + } + }); // Consolidate function names into symbol characters. + + var expression = buildExpression$1(body, options.withFont("mathrm"), true); + + for (var i = 0; i < expression.length; i++) { + var child = expression[i]; + + if (child instanceof SymbolNode) { + // Per amsopn package, + // change minus to hyphen and \ast to asterisk + child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); + } + } + + base = buildCommon.makeSpan(["mop"], expression, options); + } else { + base = buildCommon.makeSpan(["mop"], [], options); + } + + if (hasLimits) { + return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0); + } else { + return base; + } +}; + +var mathmlBuilder = (group, options) => { + // The steps taken here are similar to the html version. + var expression = buildExpression(group.body, options.withFont("mathrm")); // Is expression a string or has it something like a fraction? + + var isAllString = true; // default + + for (var i = 0; i < expression.length; i++) { + var node = expression[i]; + + if (node instanceof mathMLTree.SpaceNode) ; else if (node instanceof mathMLTree.MathNode) { + switch (node.type) { + case "mi": + case "mn": + case "ms": + case "mspace": + case "mtext": + break; + // Do nothing yet. + + case "mo": + { + var child = node.children[0]; + + if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { + child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); + } else { + isAllString = false; + } + + break; + } + + default: + isAllString = false; + } + } else { + isAllString = false; + } + } + + if (isAllString) { + // Write a single TextNode instead of multiple nested tags. + var word = expression.map(node => node.toText()).join(""); + expression = [new mathMLTree.TextNode(word)]; + } + + var identifier = new mathMLTree.MathNode("mi", expression); + identifier.setAttribute("mathvariant", "normal"); // \u2061 is the same as ⁡ + // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp + + var operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); + + if (group.parentIsSupSub) { + return new mathMLTree.MathNode("mrow", [identifier, operator]); + } else { + return mathMLTree.newDocumentFragment([identifier, operator]); + } +}; // \operatorname +// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ + + +defineFunction({ + type: "operatorname", + names: ["\\operatorname@", "\\operatornamewithlimits"], + props: { + numArgs: 1 + }, + handler: (_ref, args) => { + var { + parser, + funcName + } = _ref; + var body = args[0]; + return { + type: "operatorname", + mode: parser.mode, + body: ordargument(body), + alwaysHandleSupSub: funcName === "\\operatornamewithlimits", + limits: false, + parentIsSupSub: false + }; + }, + htmlBuilder: htmlBuilder$1, + mathmlBuilder +}); +defineMacro("\\operatorname", "\\@ifstar\\operatornamewithlimits\\operatorname@"); + +defineFunctionBuilders({ + type: "ordgroup", + + htmlBuilder(group, options) { + if (group.semisimple) { + return buildCommon.makeFragment(buildExpression$1(group.body, options, false)); + } + + return buildCommon.makeSpan(["mord"], buildExpression$1(group.body, options, true), options); + }, + + mathmlBuilder(group, options) { + return buildExpressionRow(group.body, options, true); + } + +}); + +defineFunction({ + type: "overline", + names: ["\\overline"], + props: { + numArgs: 1 + }, + + handler(_ref, args) { + var { + parser + } = _ref; + var body = args[0]; + return { + type: "overline", + mode: parser.mode, + body + }; + }, + + htmlBuilder(group, options) { + // Overlines are handled in the TeXbook pg 443, Rule 9. + // Build the inner group in the cramped style. + var innerGroup = buildGroup$1(group.body, options.havingCrampedStyle()); // Create the line above the body + + var line = buildCommon.makeLineSpan("overline-line", options); // Generate the vlist, with the appropriate kerns + + var defaultRuleThickness = options.fontMetrics().defaultRuleThickness; + var vlist = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: innerGroup + }, { + type: "kern", + size: 3 * defaultRuleThickness + }, { + type: "elem", + elem: line + }, { + type: "kern", + size: defaultRuleThickness + }] + }, options); + return buildCommon.makeSpan(["mord", "overline"], [vlist], options); + }, + + mathmlBuilder(group, options) { + var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]); + operator.setAttribute("stretchy", "true"); + var node = new mathMLTree.MathNode("mover", [buildGroup(group.body, options), operator]); + node.setAttribute("accent", "true"); + return node; + } + +}); + +defineFunction({ + type: "phantom", + names: ["\\phantom"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref, args) => { + var { + parser + } = _ref; + var body = args[0]; + return { + type: "phantom", + mode: parser.mode, + body: ordargument(body) + }; + }, + htmlBuilder: (group, options) => { + var elements = buildExpression$1(group.body, options.withPhantom(), false); // \phantom isn't supposed to affect the elements it contains. + // See "color" for more details. + + return buildCommon.makeFragment(elements); + }, + mathmlBuilder: (group, options) => { + var inner = buildExpression(group.body, options); + return new mathMLTree.MathNode("mphantom", inner); + } +}); +defineFunction({ + type: "hphantom", + names: ["\\hphantom"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref2, args) => { + var { + parser + } = _ref2; + var body = args[0]; + return { + type: "hphantom", + mode: parser.mode, + body + }; + }, + htmlBuilder: (group, options) => { + var node = buildCommon.makeSpan([], [buildGroup$1(group.body, options.withPhantom())]); + node.height = 0; + node.depth = 0; + + if (node.children) { + for (var i = 0; i < node.children.length; i++) { + node.children[i].height = 0; + node.children[i].depth = 0; + } + } // See smash for comment re: use of makeVList + + + node = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: node + }] + }, options); // For spacing, TeX treats \smash as a math group (same spacing as ord). + + return buildCommon.makeSpan(["mord"], [node], options); + }, + mathmlBuilder: (group, options) => { + var inner = buildExpression(ordargument(group.body), options); + var phantom = new mathMLTree.MathNode("mphantom", inner); + var node = new mathMLTree.MathNode("mpadded", [phantom]); + node.setAttribute("height", "0px"); + node.setAttribute("depth", "0px"); + return node; + } +}); +defineFunction({ + type: "vphantom", + names: ["\\vphantom"], + props: { + numArgs: 1, + allowedInText: true + }, + handler: (_ref3, args) => { + var { + parser + } = _ref3; + var body = args[0]; + return { + type: "vphantom", + mode: parser.mode, + body + }; + }, + htmlBuilder: (group, options) => { + var inner = buildCommon.makeSpan(["inner"], [buildGroup$1(group.body, options.withPhantom())]); + var fix = buildCommon.makeSpan(["fix"], []); + return buildCommon.makeSpan(["mord", "rlap"], [inner, fix], options); + }, + mathmlBuilder: (group, options) => { + var inner = buildExpression(ordargument(group.body), options); + var phantom = new mathMLTree.MathNode("mphantom", inner); + var node = new mathMLTree.MathNode("mpadded", [phantom]); + node.setAttribute("width", "0px"); + return node; + } +}); + +defineFunction({ + type: "raisebox", + names: ["\\raisebox"], + props: { + numArgs: 2, + argTypes: ["size", "hbox"], + allowedInText: true + }, + + handler(_ref, args) { + var { + parser + } = _ref; + var amount = assertNodeType(args[0], "size").value; + var body = args[1]; + return { + type: "raisebox", + mode: parser.mode, + dy: amount, + body + }; + }, + + htmlBuilder(group, options) { + var body = buildGroup$1(group.body, options); + var dy = calculateSize(group.dy, options); + return buildCommon.makeVList({ + positionType: "shift", + positionData: -dy, + children: [{ + type: "elem", + elem: body + }] + }, options); + }, + + mathmlBuilder(group, options) { + var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]); + var dy = group.dy.number + group.dy.unit; + node.setAttribute("voffset", dy); + return node; + } + +}); + +defineFunction({ + type: "internal", + names: ["\\relax"], + props: { + numArgs: 0, + allowedInText: true, + allowedInArgument: true + }, + + handler(_ref) { + var { + parser + } = _ref; + return { + type: "internal", + mode: parser.mode + }; + } + +}); + +defineFunction({ + type: "rule", + names: ["\\rule"], + props: { + numArgs: 2, + numOptionalArgs: 1, + allowedInText: true, + allowedInMath: true, + argTypes: ["size", "size", "size"] + }, + + handler(_ref, args, optArgs) { + var { + parser + } = _ref; + var shift = optArgs[0]; + var width = assertNodeType(args[0], "size"); + var height = assertNodeType(args[1], "size"); + return { + type: "rule", + mode: parser.mode, + shift: shift && assertNodeType(shift, "size").value, + width: width.value, + height: height.value + }; + }, + + htmlBuilder(group, options) { + // Make an empty span for the rule + var rule = buildCommon.makeSpan(["mord", "rule"], [], options); // Calculate the shift, width, and height of the rule, and account for units + + var width = calculateSize(group.width, options); + var height = calculateSize(group.height, options); + var shift = group.shift ? calculateSize(group.shift, options) : 0; // Style the rule to the right size + + rule.style.borderRightWidth = makeEm(width); + rule.style.borderTopWidth = makeEm(height); + rule.style.bottom = makeEm(shift); // Record the height and width + + rule.width = width; + rule.height = height + shift; + rule.depth = -shift; // Font size is the number large enough that the browser will + // reserve at least `absHeight` space above the baseline. + // The 1.125 factor was empirically determined + + rule.maxFontSize = height * 1.125 * options.sizeMultiplier; + return rule; + }, + + mathmlBuilder(group, options) { + var width = calculateSize(group.width, options); + var height = calculateSize(group.height, options); + var shift = group.shift ? calculateSize(group.shift, options) : 0; + var color = options.color && options.getColor() || "black"; + var rule = new mathMLTree.MathNode("mspace"); + rule.setAttribute("mathbackground", color); + rule.setAttribute("width", makeEm(width)); + rule.setAttribute("height", makeEm(height)); + var wrapper = new mathMLTree.MathNode("mpadded", [rule]); + + if (shift >= 0) { + wrapper.setAttribute("height", makeEm(shift)); + } else { + wrapper.setAttribute("height", makeEm(shift)); + wrapper.setAttribute("depth", makeEm(-shift)); + } + + wrapper.setAttribute("voffset", makeEm(shift)); + return wrapper; + } + +}); + +function sizingGroup(value, options, baseOptions) { + var inner = buildExpression$1(value, options, false); + var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize + // manually. Handle nested size changes. + + for (var i = 0; i < inner.length; i++) { + var pos = inner[i].classes.indexOf("sizing"); + + if (pos < 0) { + Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions)); + } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) { + // This is a nested size change: e.g., inner[i] is the "b" in + // `\Huge a \small b`. Override the old size (the `reset-` class) + // but not the new size. + inner[i].classes[pos + 1] = "reset-size" + baseOptions.size; + } + + inner[i].height *= multiplier; + inner[i].depth *= multiplier; + } + + return buildCommon.makeFragment(inner); +} +var sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"]; +var htmlBuilder = (group, options) => { + // Handle sizing operators like \Huge. Real TeX doesn't actually allow + // these functions inside of math expressions, so we do some special + // handling. + var newOptions = options.havingSize(group.size); + return sizingGroup(group.body, newOptions, options); +}; +defineFunction({ + type: "sizing", + names: sizeFuncs, + props: { + numArgs: 0, + allowedInText: true + }, + handler: (_ref, args) => { + var { + breakOnTokenText, + funcName, + parser + } = _ref; + var body = parser.parseExpression(false, breakOnTokenText); + return { + type: "sizing", + mode: parser.mode, + // Figure out what size to use based on the list of functions above + size: sizeFuncs.indexOf(funcName) + 1, + body + }; + }, + htmlBuilder, + mathmlBuilder: (group, options) => { + var newOptions = options.havingSize(group.size); + var inner = buildExpression(group.body, newOptions); + var node = new mathMLTree.MathNode("mstyle", inner); // TODO(emily): This doesn't produce the correct size for nested size + // changes, because we don't keep state of what style we're currently + // in, so we can't reset the size to normal before changing it. Now + // that we're passing an options parameter we should be able to fix + // this. + + node.setAttribute("mathsize", makeEm(newOptions.sizeMultiplier)); + return node; + } +}); + +// smash, with optional [tb], as in AMS +defineFunction({ + type: "smash", + names: ["\\smash"], + props: { + numArgs: 1, + numOptionalArgs: 1, + allowedInText: true + }, + handler: (_ref, args, optArgs) => { + var { + parser + } = _ref; + var smashHeight = false; + var smashDepth = false; + var tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); + + if (tbArg) { + // Optional [tb] argument is engaged. + // ref: amsmath: \renewcommand{\smash}[1][tb]{% + // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% + var letter = ""; + + for (var i = 0; i < tbArg.body.length; ++i) { + var node = tbArg.body[i]; // $FlowFixMe: Not every node type has a `text` property. + + letter = node.text; + + if (letter === "t") { + smashHeight = true; + } else if (letter === "b") { + smashDepth = true; + } else { + smashHeight = false; + smashDepth = false; + break; + } + } + } else { + smashHeight = true; + smashDepth = true; + } + + var body = args[0]; + return { + type: "smash", + mode: parser.mode, + body, + smashHeight, + smashDepth + }; + }, + htmlBuilder: (group, options) => { + var node = buildCommon.makeSpan([], [buildGroup$1(group.body, options)]); + + if (!group.smashHeight && !group.smashDepth) { + return node; + } + + if (group.smashHeight) { + node.height = 0; // In order to influence makeVList, we have to reset the children. + + if (node.children) { + for (var i = 0; i < node.children.length; i++) { + node.children[i].height = 0; + } + } + } + + if (group.smashDepth) { + node.depth = 0; + + if (node.children) { + for (var _i = 0; _i < node.children.length; _i++) { + node.children[_i].depth = 0; + } + } + } // At this point, we've reset the TeX-like height and depth values. + // But the span still has an HTML line height. + // makeVList applies "display: table-cell", which prevents the browser + // from acting on that line height. So we'll call makeVList now. + + + var smashedNode = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: node + }] + }, options); // For spacing, TeX treats \hphantom as a math group (same spacing as ord). + + return buildCommon.makeSpan(["mord"], [smashedNode], options); + }, + mathmlBuilder: (group, options) => { + var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]); + + if (group.smashHeight) { + node.setAttribute("height", "0px"); + } + + if (group.smashDepth) { + node.setAttribute("depth", "0px"); + } + + return node; + } +}); + +defineFunction({ + type: "sqrt", + names: ["\\sqrt"], + props: { + numArgs: 1, + numOptionalArgs: 1 + }, + + handler(_ref, args, optArgs) { + var { + parser + } = _ref; + var index = optArgs[0]; + var body = args[0]; + return { + type: "sqrt", + mode: parser.mode, + body, + index + }; + }, + + htmlBuilder(group, options) { + // Square roots are handled in the TeXbook pg. 443, Rule 11. + // First, we do the same steps as in overline to build the inner group + // and line + var inner = buildGroup$1(group.body, options.havingCrampedStyle()); + + if (inner.height === 0) { + // Render a small surd. + inner.height = options.fontMetrics().xHeight; + } // Some groups can return document fragments. Handle those by wrapping + // them in a span. + + + inner = buildCommon.wrapFragment(inner, options); // Calculate the minimum size for the \surd delimiter + + var metrics = options.fontMetrics(); + var theta = metrics.defaultRuleThickness; + var phi = theta; + + if (options.style.id < Style$1.TEXT.id) { + phi = options.fontMetrics().xHeight; + } // Calculate the clearance between the body and line + + + var lineClearance = theta + phi / 4; + var minDelimiterHeight = inner.height + inner.depth + lineClearance + theta; // Create a sqrt SVG of the required minimum size + + var { + span: img, + ruleWidth, + advanceWidth + } = delimiter.sqrtImage(minDelimiterHeight, options); + var delimDepth = img.height - ruleWidth; // Adjust the clearance based on the delimiter size + + if (delimDepth > inner.height + inner.depth + lineClearance) { + lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2; + } // Shift the sqrt image + + + var imgShift = img.height - inner.height - lineClearance - ruleWidth; + inner.style.paddingLeft = makeEm(advanceWidth); // Overlay the image and the argument. + + var body = buildCommon.makeVList({ + positionType: "firstBaseline", + children: [{ + type: "elem", + elem: inner, + wrapperClasses: ["svg-align"] + }, { + type: "kern", + size: -(inner.height + imgShift) + }, { + type: "elem", + elem: img + }, { + type: "kern", + size: ruleWidth + }] + }, options); + + if (!group.index) { + return buildCommon.makeSpan(["mord", "sqrt"], [body], options); + } else { + // Handle the optional root index + // The index is always in scriptscript style + var newOptions = options.havingStyle(Style$1.SCRIPTSCRIPT); + var rootm = buildGroup$1(group.index, newOptions, options); // The amount the index is shifted by. This is taken from the TeX + // source, in the definition of `\r@@t`. + + var toShift = 0.6 * (body.height - body.depth); // Build a VList with the superscript shifted up correctly + + var rootVList = buildCommon.makeVList({ + positionType: "shift", + positionData: -toShift, + children: [{ + type: "elem", + elem: rootm + }] + }, options); // Add a class surrounding it so we can add on the appropriate + // kerning + + var rootVListWrap = buildCommon.makeSpan(["root"], [rootVList]); + return buildCommon.makeSpan(["mord", "sqrt"], [rootVListWrap, body], options); + } + }, + + mathmlBuilder(group, options) { + var { + body, + index + } = group; + return index ? new mathMLTree.MathNode("mroot", [buildGroup(body, options), buildGroup(index, options)]) : new mathMLTree.MathNode("msqrt", [buildGroup(body, options)]); + } + +}); + +var styleMap = { + "display": Style$1.DISPLAY, + "text": Style$1.TEXT, + "script": Style$1.SCRIPT, + "scriptscript": Style$1.SCRIPTSCRIPT +}; +defineFunction({ + type: "styling", + names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], + props: { + numArgs: 0, + allowedInText: true, + primitive: true + }, + + handler(_ref, args) { + var { + breakOnTokenText, + funcName, + parser + } = _ref; + // parse out the implicit body + var body = parser.parseExpression(true, breakOnTokenText); // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g. + // here and in buildHTML and de-dupe the enumeration of all the styles). + // $FlowFixMe: The names above exactly match the styles. + + var style = funcName.slice(1, funcName.length - 5); + return { + type: "styling", + mode: parser.mode, + // Figure out what style to use by pulling out the style from + // the function name + style, + body + }; + }, + + htmlBuilder(group, options) { + // Style changes are handled in the TeXbook on pg. 442, Rule 3. + var newStyle = styleMap[group.style]; + var newOptions = options.havingStyle(newStyle).withFont(''); + return sizingGroup(group.body, newOptions, options); + }, + + mathmlBuilder(group, options) { + // Figure out what style we're changing to. + var newStyle = styleMap[group.style]; + var newOptions = options.havingStyle(newStyle); + var inner = buildExpression(group.body, newOptions); + var node = new mathMLTree.MathNode("mstyle", inner); + var styleAttributes = { + "display": ["0", "true"], + "text": ["0", "false"], + "script": ["1", "false"], + "scriptscript": ["2", "false"] + }; + var attr = styleAttributes[group.style]; + node.setAttribute("scriptlevel", attr[0]); + node.setAttribute("displaystyle", attr[1]); + return node; + } + +}); + +/** + * Sometimes, groups perform special rules when they have superscripts or + * subscripts attached to them. This function lets the `supsub` group know that + * Sometimes, groups perform special rules when they have superscripts or + * its inner element should handle the superscripts and subscripts instead of + * handling them itself. + */ +var htmlBuilderDelegate = function htmlBuilderDelegate(group, options) { + var base = group.base; + + if (!base) { + return null; + } else if (base.type === "op") { + // Operators handle supsubs differently when they have limits + // (e.g. `\displaystyle\sum_2^3`) + var delegate = base.limits && (options.style.size === Style$1.DISPLAY.size || base.alwaysHandleSupSub); + return delegate ? htmlBuilder$2 : null; + } else if (base.type === "operatorname") { + var _delegate = base.alwaysHandleSupSub && (options.style.size === Style$1.DISPLAY.size || base.limits); + + return _delegate ? htmlBuilder$1 : null; + } else if (base.type === "accent") { + return utils.isCharacterBox(base.base) ? htmlBuilder$a : null; + } else if (base.type === "horizBrace") { + var isSup = !group.sub; + return isSup === base.isOver ? htmlBuilder$3 : null; + } else { + return null; + } +}; // Super scripts and subscripts, whose precise placement can depend on other +// functions that precede them. + + +defineFunctionBuilders({ + type: "supsub", + + htmlBuilder(group, options) { + // Superscript and subscripts are handled in the TeXbook on page + // 445-446, rules 18(a-f). + // Here is where we defer to the inner group if it should handle + // superscripts and subscripts itself. + var builderDelegate = htmlBuilderDelegate(group, options); + + if (builderDelegate) { + return builderDelegate(group, options); + } + + var { + base: valueBase, + sup: valueSup, + sub: valueSub + } = group; + var base = buildGroup$1(valueBase, options); + var supm; + var subm; + var metrics = options.fontMetrics(); // Rule 18a + + var supShift = 0; + var subShift = 0; + var isCharacterBox = valueBase && utils.isCharacterBox(valueBase); + + if (valueSup) { + var newOptions = options.havingStyle(options.style.sup()); + supm = buildGroup$1(valueSup, newOptions, options); + + if (!isCharacterBox) { + supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier; + } + } + + if (valueSub) { + var _newOptions = options.havingStyle(options.style.sub()); + + subm = buildGroup$1(valueSub, _newOptions, options); + + if (!isCharacterBox) { + subShift = base.depth + _newOptions.fontMetrics().subDrop * _newOptions.sizeMultiplier / options.sizeMultiplier; + } + } // Rule 18c + + + var minSupShift; + + if (options.style === Style$1.DISPLAY) { + minSupShift = metrics.sup1; + } else if (options.style.cramped) { + minSupShift = metrics.sup3; + } else { + minSupShift = metrics.sup2; + } // scriptspace is a font-size-independent size, so scale it + // appropriately for use as the marginRight. + + + var multiplier = options.sizeMultiplier; + var marginRight = makeEm(0.5 / metrics.ptPerEm / multiplier); + var marginLeft = null; + + if (subm) { + // Subscripts shouldn't be shifted by the base's italic correction. + // Account for that by shifting the subscript back the appropriate + // amount. Note we only do this when the base is a single symbol. + var isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint"); + + if (base instanceof SymbolNode || isOiint) { + // $FlowFixMe + marginLeft = makeEm(-base.italic); + } + } + + var supsub; + + if (supm && subm) { + supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight); + subShift = Math.max(subShift, metrics.sub2); + var ruleWidth = metrics.defaultRuleThickness; // Rule 18e + + var maxWidth = 4 * ruleWidth; + + if (supShift - supm.depth - (subm.height - subShift) < maxWidth) { + subShift = maxWidth - (supShift - supm.depth) + subm.height; + var psi = 0.8 * metrics.xHeight - (supShift - supm.depth); + + if (psi > 0) { + supShift += psi; + subShift -= psi; + } + } + + var vlistElem = [{ + type: "elem", + elem: subm, + shift: subShift, + marginRight, + marginLeft + }, { + type: "elem", + elem: supm, + shift: -supShift, + marginRight + }]; + supsub = buildCommon.makeVList({ + positionType: "individualShift", + children: vlistElem + }, options); + } else if (subm) { + // Rule 18b + subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight); + var _vlistElem = [{ + type: "elem", + elem: subm, + marginLeft, + marginRight + }]; + supsub = buildCommon.makeVList({ + positionType: "shift", + positionData: subShift, + children: _vlistElem + }, options); + } else if (supm) { + // Rule 18c, d + supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight); + supsub = buildCommon.makeVList({ + positionType: "shift", + positionData: -supShift, + children: [{ + type: "elem", + elem: supm, + marginRight + }] + }, options); + } else { + throw new Error("supsub must have either sup or sub."); + } // Wrap the supsub vlist in a span.msupsub to reset text-align. + + + var mclass = getTypeOfDomTree(base, "right") || "mord"; + return buildCommon.makeSpan([mclass], [base, buildCommon.makeSpan(["msupsub"], [supsub])], options); + }, + + mathmlBuilder(group, options) { + // Is the inner group a relevant horizontal brace? + var isBrace = false; + var isOver; + var isSup; + + if (group.base && group.base.type === "horizBrace") { + isSup = !!group.sup; + + if (isSup === group.base.isOver) { + isBrace = true; + isOver = group.base.isOver; + } + } + + if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) { + group.base.parentIsSupSub = true; + } + + var children = [buildGroup(group.base, options)]; + + if (group.sub) { + children.push(buildGroup(group.sub, options)); + } + + if (group.sup) { + children.push(buildGroup(group.sup, options)); + } + + var nodeType; + + if (isBrace) { + nodeType = isOver ? "mover" : "munder"; + } else if (!group.sub) { + var base = group.base; + + if (base && base.type === "op" && base.limits && (options.style === Style$1.DISPLAY || base.alwaysHandleSupSub)) { + nodeType = "mover"; + } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === Style$1.DISPLAY)) { + nodeType = "mover"; + } else { + nodeType = "msup"; + } + } else if (!group.sup) { + var _base = group.base; + + if (_base && _base.type === "op" && _base.limits && (options.style === Style$1.DISPLAY || _base.alwaysHandleSupSub)) { + nodeType = "munder"; + } else if (_base && _base.type === "operatorname" && _base.alwaysHandleSupSub && (_base.limits || options.style === Style$1.DISPLAY)) { + nodeType = "munder"; + } else { + nodeType = "msub"; + } + } else { + var _base2 = group.base; + + if (_base2 && _base2.type === "op" && _base2.limits && options.style === Style$1.DISPLAY) { + nodeType = "munderover"; + } else if (_base2 && _base2.type === "operatorname" && _base2.alwaysHandleSupSub && (options.style === Style$1.DISPLAY || _base2.limits)) { + nodeType = "munderover"; + } else { + nodeType = "msubsup"; + } + } + + return new mathMLTree.MathNode(nodeType, children); + } + +}); + +defineFunctionBuilders({ + type: "atom", + + htmlBuilder(group, options) { + return buildCommon.mathsym(group.text, group.mode, options, ["m" + group.family]); + }, + + mathmlBuilder(group, options) { + var node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); + + if (group.family === "bin") { + var variant = getVariant(group, options); + + if (variant === "bold-italic") { + node.setAttribute("mathvariant", variant); + } + } else if (group.family === "punct") { + node.setAttribute("separator", "true"); + } else if (group.family === "open" || group.family === "close") { + // Delims built here should not stretch vertically. + // See delimsizing.js for stretchy delims. + node.setAttribute("stretchy", "false"); + } + + return node; + } + +}); + +// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in +// src/symbols.js. +var defaultVariant = { + "mi": "italic", + "mn": "normal", + "mtext": "normal" +}; +defineFunctionBuilders({ + type: "mathord", + + htmlBuilder(group, options) { + return buildCommon.makeOrd(group, options, "mathord"); + }, + + mathmlBuilder(group, options) { + var node = new mathMLTree.MathNode("mi", [makeText(group.text, group.mode, options)]); + var variant = getVariant(group, options) || "italic"; + + if (variant !== defaultVariant[node.type]) { + node.setAttribute("mathvariant", variant); + } + + return node; + } + +}); +defineFunctionBuilders({ + type: "textord", + + htmlBuilder(group, options) { + return buildCommon.makeOrd(group, options, "textord"); + }, + + mathmlBuilder(group, options) { + var text = makeText(group.text, group.mode, options); + var variant = getVariant(group, options) || "normal"; + var node; + + if (group.mode === 'text') { + node = new mathMLTree.MathNode("mtext", [text]); + } else if (/[0-9]/.test(group.text)) { + node = new mathMLTree.MathNode("mn", [text]); + } else if (group.text === "\\prime") { + node = new mathMLTree.MathNode("mo", [text]); + } else { + node = new mathMLTree.MathNode("mi", [text]); + } + + if (variant !== defaultVariant[node.type]) { + node.setAttribute("mathvariant", variant); + } + + return node; + } + +}); + +var cssSpace = { + "\\nobreak": "nobreak", + "\\allowbreak": "allowbreak" +}; // A lookup table to determine whether a spacing function/symbol should be +// treated like a regular space character. If a symbol or command is a key +// in this table, then it should be a regular space character. Furthermore, +// the associated value may have a `className` specifying an extra CSS class +// to add to the created `span`. + +var regularSpace = { + " ": {}, + "\\ ": {}, + "~": { + className: "nobreak" + }, + "\\space": {}, + "\\nobreakspace": { + className: "nobreak" + } +}; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in +// src/symbols.js. + +defineFunctionBuilders({ + type: "spacing", + + htmlBuilder(group, options) { + if (regularSpace.hasOwnProperty(group.text)) { + var className = regularSpace[group.text].className || ""; // Spaces are generated by adding an actual space. Each of these + // things has an entry in the symbols table, so these will be turned + // into appropriate outputs. + + if (group.mode === "text") { + var ord = buildCommon.makeOrd(group, options, "textord"); + ord.classes.push(className); + return ord; + } else { + return buildCommon.makeSpan(["mspace", className], [buildCommon.mathsym(group.text, group.mode, options)], options); + } + } else if (cssSpace.hasOwnProperty(group.text)) { + // Spaces based on just a CSS class. + return buildCommon.makeSpan(["mspace", cssSpace[group.text]], [], options); + } else { + throw new ParseError("Unknown type of space \"" + group.text + "\""); + } + }, + + mathmlBuilder(group, options) { + var node; + + if (regularSpace.hasOwnProperty(group.text)) { + node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); + } else if (cssSpace.hasOwnProperty(group.text)) { + // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored + return new mathMLTree.MathNode("mspace"); + } else { + throw new ParseError("Unknown type of space \"" + group.text + "\""); + } + + return node; + } + +}); + +var pad = () => { + var padNode = new mathMLTree.MathNode("mtd", []); + padNode.setAttribute("width", "50%"); + return padNode; +}; + +defineFunctionBuilders({ + type: "tag", + + mathmlBuilder(group, options) { + var table = new mathMLTree.MathNode("mtable", [new mathMLTree.MathNode("mtr", [pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.body, options)]), pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.tag, options)])])]); + table.setAttribute("width", "100%"); + return table; // TODO: Left-aligned tags. + // Currently, the group and options passed here do not contain + // enough info to set tag alignment. `leqno` is in Settings but it is + // not passed to Options. On the HTML side, leqno is + // set by a CSS class applied in buildTree.js. That would have worked + // in MathML if browsers supported . Since they don't, we + // need to rewrite the way this function is called. + } + +}); + +var textFontFamilies = { + "\\text": undefined, + "\\textrm": "textrm", + "\\textsf": "textsf", + "\\texttt": "texttt", + "\\textnormal": "textrm" +}; +var textFontWeights = { + "\\textbf": "textbf", + "\\textmd": "textmd" +}; +var textFontShapes = { + "\\textit": "textit", + "\\textup": "textup" +}; + +var optionsWithFont = (group, options) => { + var font = group.font; // Checks if the argument is a font family or a font style. + + if (!font) { + return options; + } else if (textFontFamilies[font]) { + return options.withTextFontFamily(textFontFamilies[font]); + } else if (textFontWeights[font]) { + return options.withTextFontWeight(textFontWeights[font]); + } else if (font === "\\emph") { + return options.fontShape === "textit" ? options.withTextFontShape("textup") : options.withTextFontShape("textit"); + } + + return options.withTextFontShape(textFontShapes[font]); +}; + +defineFunction({ + type: "text", + names: [// Font families + "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", // Font weights + "\\textbf", "\\textmd", // Font Shapes + "\\textit", "\\textup", "\\emph"], + props: { + numArgs: 1, + argTypes: ["text"], + allowedInArgument: true, + allowedInText: true + }, + + handler(_ref, args) { + var { + parser, + funcName + } = _ref; + var body = args[0]; + return { + type: "text", + mode: parser.mode, + body: ordargument(body), + font: funcName + }; + }, + + htmlBuilder(group, options) { + var newOptions = optionsWithFont(group, options); + var inner = buildExpression$1(group.body, newOptions, true); + return buildCommon.makeSpan(["mord", "text"], inner, newOptions); + }, + + mathmlBuilder(group, options) { + var newOptions = optionsWithFont(group, options); + return buildExpressionRow(group.body, newOptions); + } + +}); + +defineFunction({ + type: "underline", + names: ["\\underline"], + props: { + numArgs: 1, + allowedInText: true + }, + + handler(_ref, args) { + var { + parser + } = _ref; + return { + type: "underline", + mode: parser.mode, + body: args[0] + }; + }, + + htmlBuilder(group, options) { + // Underlines are handled in the TeXbook pg 443, Rule 10. + // Build the inner group. + var innerGroup = buildGroup$1(group.body, options); // Create the line to go below the body + + var line = buildCommon.makeLineSpan("underline-line", options); // Generate the vlist, with the appropriate kerns + + var defaultRuleThickness = options.fontMetrics().defaultRuleThickness; + var vlist = buildCommon.makeVList({ + positionType: "top", + positionData: innerGroup.height, + children: [{ + type: "kern", + size: defaultRuleThickness + }, { + type: "elem", + elem: line + }, { + type: "kern", + size: 3 * defaultRuleThickness + }, { + type: "elem", + elem: innerGroup + }] + }, options); + return buildCommon.makeSpan(["mord", "underline"], [vlist], options); + }, + + mathmlBuilder(group, options) { + var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]); + operator.setAttribute("stretchy", "true"); + var node = new mathMLTree.MathNode("munder", [buildGroup(group.body, options), operator]); + node.setAttribute("accentunder", "true"); + return node; + } + +}); + +defineFunction({ + type: "vcenter", + names: ["\\vcenter"], + props: { + numArgs: 1, + argTypes: ["original"], + // In LaTeX, \vcenter can act only on a box. + allowedInText: false + }, + + handler(_ref, args) { + var { + parser + } = _ref; + return { + type: "vcenter", + mode: parser.mode, + body: args[0] + }; + }, + + htmlBuilder(group, options) { + var body = buildGroup$1(group.body, options); + var axisHeight = options.fontMetrics().axisHeight; + var dy = 0.5 * (body.height - axisHeight - (body.depth + axisHeight)); + return buildCommon.makeVList({ + positionType: "shift", + positionData: dy, + children: [{ + type: "elem", + elem: body + }] + }, options); + }, + + mathmlBuilder(group, options) { + // There is no way to do this in MathML. + // Write a class as a breadcrumb in case some post-processor wants + // to perform a vcenter adjustment. + return new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)], ["vcenter"]); + } + +}); + +defineFunction({ + type: "verb", + names: ["\\verb"], + props: { + numArgs: 0, + allowedInText: true + }, + + handler(context, args, optArgs) { + // \verb and \verb* are dealt with directly in Parser.js. + // If we end up here, it's because of a failure to match the two delimiters + // in the regex in Lexer.js. LaTeX raises the following error when \verb is + // terminated by end of line (or file). + throw new ParseError("\\verb ended by end of line instead of matching delimiter"); + }, + + htmlBuilder(group, options) { + var text = makeVerb(group); + var body = []; // \verb enters text mode and therefore is sized like \textstyle + + var newOptions = options.havingStyle(options.style.text()); + + for (var i = 0; i < text.length; i++) { + var c = text[i]; + + if (c === '~') { + c = '\\textasciitilde'; + } + + body.push(buildCommon.makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"])); + } + + return buildCommon.makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), buildCommon.tryCombineChars(body), newOptions); + }, + + mathmlBuilder(group, options) { + var text = new mathMLTree.TextNode(makeVerb(group)); + var node = new mathMLTree.MathNode("mtext", [text]); + node.setAttribute("mathvariant", "monospace"); + return node; + } + +}); +/** + * Converts verb group into body string. + * + * \verb* replaces each space with an open box \u2423 + * \verb replaces each space with a no-break space \xA0 + */ + +var makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0'); + +/** Include this to ensure that all functions are defined. */ +var functions = _functions; + +/** + * The Lexer class handles tokenizing the input in various ways. Since our + * parser expects us to be able to backtrack, the lexer allows lexing from any + * given starting point. + * + * Its main exposed function is the `lex` function, which takes a position to + * lex from and a type of token to lex. It defers to the appropriate `_innerLex` + * function. + * + * The various `_innerLex` functions perform the actual lexing of different + * kinds. + */ + +/* The following tokenRegex + * - matches typical whitespace (but not NBSP etc.) using its first group + * - does not match any control character \x00-\x1f except whitespace + * - does not match a bare backslash + * - matches any ASCII character except those just mentioned + * - does not match the BMP private use area \uE000-\uF8FF + * - does not match bare surrogate code units + * - matches any BMP character except for those just described + * - matches any valid Unicode surrogate pair + * - matches a backslash followed by one or more whitespace characters + * - matches a backslash followed by one or more letters then whitespace + * - matches a backslash followed by any BMP character + * Capturing groups: + * [1] regular whitespace + * [2] backslash followed by whitespace + * [3] anything else, which may include: + * [4] left character of \verb* + * [5] left character of \verb + * [6] backslash followed by word, excluding any trailing whitespace + * Just because the Lexer matches something doesn't mean it's valid input: + * If there is no matching function or symbol definition, the Parser will + * still reject the input. + */ +var spaceRegexString = "[ \r\n\t]"; +var controlWordRegexString = "\\\\[a-zA-Z@]+"; +var controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; +var controlWordWhitespaceRegexString = "(" + controlWordRegexString + ")" + spaceRegexString + "*"; +var controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; +var combiningDiacriticalMarkString = "[\u0300-\u036f]"; +var combiningDiacriticalMarksEndRegex = new RegExp(combiningDiacriticalMarkString + "+$"); +var tokenRegexString = "(" + spaceRegexString + "+)|" + ( // whitespace +controlSpaceRegexString + "|") + // \whitespace +"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + ( // single codepoint +combiningDiacriticalMarkString + "*") + // ...plus accents +"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + ( // surrogate pair +combiningDiacriticalMarkString + "*") + // ...plus accents +"|\\\\verb\\*([^]).*?\\4" + // \verb* +"|\\\\verb([^*a-zA-Z]).*?\\5" + ( // \verb unstarred +"|" + controlWordWhitespaceRegexString) + ( // \macroName + spaces +"|" + controlSymbolRegexString + ")"); // \\, \', etc. + +/** Main Lexer class */ + +class Lexer { + // Category codes. The lexer only supports comment characters (14) for now. + // MacroExpander additionally distinguishes active (13). + constructor(input, settings) { + this.input = void 0; + this.settings = void 0; + this.tokenRegex = void 0; + this.catcodes = void 0; + // Separate accents from characters + this.input = input; + this.settings = settings; + this.tokenRegex = new RegExp(tokenRegexString, 'g'); + this.catcodes = { + "%": 14, + // comment character + "~": 13 // active character + + }; + } + + setCatcode(char, code) { + this.catcodes[char] = code; + } + /** + * This function lexes a single token. + */ + + + lex() { + var input = this.input; + var pos = this.tokenRegex.lastIndex; + + if (pos === input.length) { + return new Token("EOF", new SourceLocation(this, pos, pos)); + } + + var match = this.tokenRegex.exec(input); + + if (match === null || match.index !== pos) { + throw new ParseError("Unexpected character: '" + input[pos] + "'", new Token(input[pos], new SourceLocation(this, pos, pos + 1))); + } + + var text = match[6] || match[3] || (match[2] ? "\\ " : " "); + + if (this.catcodes[text] === 14) { + // comment character + var nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex); + + if (nlIndex === -1) { + this.tokenRegex.lastIndex = input.length; // EOF + + this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)"); + } else { + this.tokenRegex.lastIndex = nlIndex + 1; + } + + return this.lex(); + } + + return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); + } + +} + +/** + * A `Namespace` refers to a space of nameable things like macros or lengths, + * which can be `set` either globally or local to a nested group, using an + * undo stack similar to how TeX implements this functionality. + * Performance-wise, `get` and local `set` take constant time, while global + * `set` takes time proportional to the depth of group nesting. + */ +class Namespace { + /** + * Both arguments are optional. The first argument is an object of + * built-in mappings which never change. The second argument is an object + * of initial (global-level) mappings, which will constantly change + * according to any global/top-level `set`s done. + */ + constructor(builtins, globalMacros) { + if (builtins === void 0) { + builtins = {}; + } + + if (globalMacros === void 0) { + globalMacros = {}; + } + + this.current = void 0; + this.builtins = void 0; + this.undefStack = void 0; + this.current = globalMacros; + this.builtins = builtins; + this.undefStack = []; + } + /** + * Start a new nested group, affecting future local `set`s. + */ + + + beginGroup() { + this.undefStack.push({}); + } + /** + * End current nested group, restoring values before the group began. + */ + + + endGroup() { + if (this.undefStack.length === 0) { + throw new ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug"); + } + + var undefs = this.undefStack.pop(); + + for (var undef in undefs) { + if (undefs.hasOwnProperty(undef)) { + if (undefs[undef] == null) { + delete this.current[undef]; + } else { + this.current[undef] = undefs[undef]; + } + } + } + } + /** + * Ends all currently nested groups (if any), restoring values before the + * groups began. Useful in case of an error in the middle of parsing. + */ + + + endGroups() { + while (this.undefStack.length > 0) { + this.endGroup(); + } + } + /** + * Detect whether `name` has a definition. Equivalent to + * `get(name) != null`. + */ + + + has(name) { + return this.current.hasOwnProperty(name) || this.builtins.hasOwnProperty(name); + } + /** + * Get the current value of a name, or `undefined` if there is no value. + * + * Note: Do not use `if (namespace.get(...))` to detect whether a macro + * is defined, as the definition may be the empty string which evaluates + * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or + * `if (namespace.has(...))`. + */ + + + get(name) { + if (this.current.hasOwnProperty(name)) { + return this.current[name]; + } else { + return this.builtins[name]; + } + } + /** + * Set the current value of a name, and optionally set it globally too. + * Local set() sets the current value and (when appropriate) adds an undo + * operation to the undo stack. Global set() may change the undo + * operation at every level, so takes time linear in their number. + * A value of undefined means to delete existing definitions. + */ + + + set(name, value, global) { + if (global === void 0) { + global = false; + } + + if (global) { + // Global set is equivalent to setting in all groups. Simulate this + // by destroying any undos currently scheduled for this name, + // and adding an undo with the *new* value (in case it later gets + // locally reset within this environment). + for (var i = 0; i < this.undefStack.length; i++) { + delete this.undefStack[i][name]; + } + + if (this.undefStack.length > 0) { + this.undefStack[this.undefStack.length - 1][name] = value; + } + } else { + // Undo this set at end of this group (possibly to `undefined`), + // unless an undo is already in place, in which case that older + // value is the correct one. + var top = this.undefStack[this.undefStack.length - 1]; + + if (top && !top.hasOwnProperty(name)) { + top[name] = this.current[name]; + } + } + + if (value == null) { + delete this.current[name]; + } else { + this.current[name] = value; + } + } + +} + +/** + * Predefined macros for KaTeX. + * This can be used to define some commands in terms of others. + */ +var macros = _macros; +// macro tools + +defineMacro("\\noexpand", function (context) { + // The expansion is the token itself; but that token is interpreted + // as if its meaning were ‘\relax’ if it is a control sequence that + // would ordinarily be expanded by TeX’s expansion rules. + var t = context.popToken(); + + if (context.isExpandable(t.text)) { + t.noexpand = true; + t.treatAsRelax = true; + } + + return { + tokens: [t], + numArgs: 0 + }; +}); +defineMacro("\\expandafter", function (context) { + // TeX first reads the token that comes immediately after \expandafter, + // without expanding it; let’s call this token t. Then TeX reads the + // token that comes after t (and possibly more tokens, if that token + // has an argument), replacing it by its expansion. Finally TeX puts + // t back in front of that expansion. + var t = context.popToken(); + context.expandOnce(true); // expand only an expandable token + + return { + tokens: [t], + numArgs: 0 + }; +}); // LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 +// TeX source: \long\def\@firstoftwo#1#2{#1} + +defineMacro("\\@firstoftwo", function (context) { + var args = context.consumeArgs(2); + return { + tokens: args[0], + numArgs: 0 + }; +}); // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 +// TeX source: \long\def\@secondoftwo#1#2{#2} + +defineMacro("\\@secondoftwo", function (context) { + var args = context.consumeArgs(2); + return { + tokens: args[1], + numArgs: 0 + }; +}); // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) +// symbol that isn't a space, consuming any spaces but not consuming the +// first nonspace character. If that nonspace character matches #1, then +// the macro expands to #2; otherwise, it expands to #3. + +defineMacro("\\@ifnextchar", function (context) { + var args = context.consumeArgs(3); // symbol, if, else + + context.consumeSpaces(); + var nextToken = context.future(); + + if (args[0].length === 1 && args[0][0].text === nextToken.text) { + return { + tokens: args[1], + numArgs: 0 + }; + } else { + return { + tokens: args[2], + numArgs: 0 + }; + } +}); // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. +// If it is `*`, then it consumes the symbol, and the macro expands to #1; +// otherwise, the macro expands to #2 (without consuming the symbol). +// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} + +defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode + +defineMacro("\\TextOrMath", function (context) { + var args = context.consumeArgs(2); + + if (context.mode === 'text') { + return { + tokens: args[0], + numArgs: 0 + }; + } else { + return { + tokens: args[1], + numArgs: 0 + }; + } +}); // Lookup table for parsing numbers in base 8 through 16 + +var digitToNumber = { + "0": 0, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7, + "8": 8, + "9": 9, + "a": 10, + "A": 10, + "b": 11, + "B": 11, + "c": 12, + "C": 12, + "d": 13, + "D": 13, + "e": 14, + "E": 14, + "f": 15, + "F": 15 +}; // TeX \char makes a literal character (catcode 12) using the following forms: +// (see The TeXBook, p. 43) +// \char123 -- decimal +// \char'123 -- octal +// \char"123 -- hex +// \char`x -- character that can be written (i.e. isn't active) +// \char`\x -- character that cannot be written (e.g. %) +// These all refer to characters from the font, so we turn them into special +// calls to a function \@char dealt with in the Parser. + +defineMacro("\\char", function (context) { + var token = context.popToken(); + var base; + var number = ''; + + if (token.text === "'") { + base = 8; + token = context.popToken(); + } else if (token.text === '"') { + base = 16; + token = context.popToken(); + } else if (token.text === "`") { + token = context.popToken(); + + if (token.text[0] === "\\") { + number = token.text.charCodeAt(1); + } else if (token.text === "EOF") { + throw new ParseError("\\char` missing argument"); + } else { + number = token.text.charCodeAt(0); + } + } else { + base = 10; + } + + if (base) { + // Parse a number in the given base, starting with first `token`. + number = digitToNumber[token.text]; + + if (number == null || number >= base) { + throw new ParseError("Invalid base-" + base + " digit " + token.text); + } + + var digit; + + while ((digit = digitToNumber[context.future().text]) != null && digit < base) { + number *= base; + number += digit; + context.popToken(); + } + } + + return "\\@char{" + number + "}"; +}); // \newcommand{\macro}[args]{definition} +// \renewcommand{\macro}[args]{definition} +// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition} + +var newcommand = (context, existsOK, nonexistsOK, skipIfExists) => { + var arg = context.consumeArg().tokens; + + if (arg.length !== 1) { + throw new ParseError("\\newcommand's first argument must be a macro name"); + } + + var name = arg[0].text; + var exists = context.isDefined(name); + + if (exists && !existsOK) { + throw new ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand")); + } + + if (!exists && !nonexistsOK) { + throw new ParseError("\\renewcommand{" + name + "} when command " + name + " " + "does not yet exist; use \\newcommand"); + } + + var numArgs = 0; + arg = context.consumeArg().tokens; + + if (arg.length === 1 && arg[0].text === "[") { + var argText = ''; + var token = context.expandNextToken(); + + while (token.text !== "]" && token.text !== "EOF") { + // TODO: Should properly expand arg, e.g., ignore {}s + argText += token.text; + token = context.expandNextToken(); + } + + if (!argText.match(/^\s*[0-9]+\s*$/)) { + throw new ParseError("Invalid number of arguments: " + argText); + } + + numArgs = parseInt(argText); + arg = context.consumeArg().tokens; + } + + if (!(exists && skipIfExists)) { + // Final arg is the expansion of the macro + context.macros.set(name, { + tokens: arg, + numArgs + }); + } + + return ''; +}; + +defineMacro("\\newcommand", context => newcommand(context, false, true, false)); +defineMacro("\\renewcommand", context => newcommand(context, true, false, false)); +defineMacro("\\providecommand", context => newcommand(context, true, true, true)); // terminal (console) tools + +defineMacro("\\message", context => { + var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console + + console.log(arg.reverse().map(token => token.text).join("")); + return ''; +}); +defineMacro("\\errmessage", context => { + var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console + + console.error(arg.reverse().map(token => token.text).join("")); + return ''; +}); +defineMacro("\\show", context => { + var tok = context.popToken(); + var name = tok.text; // eslint-disable-next-line no-console + + console.log(tok, context.macros.get(name), functions[name], symbols.math[name], symbols.text[name]); + return ''; +}); ////////////////////////////////////////////////////////////////////// +// Grouping +// \let\bgroup={ \let\egroup=} + +defineMacro("\\bgroup", "{"); +defineMacro("\\egroup", "}"); // Symbols from latex.ltx: +// \def~{\nobreakspace{}} +// \def\lq{`} +// \def\rq{'} +// \def \aa {\r a} +// \def \AA {\r A} + +defineMacro("~", "\\nobreakspace"); +defineMacro("\\lq", "`"); +defineMacro("\\rq", "'"); +defineMacro("\\aa", "\\r a"); +defineMacro("\\AA", "\\r A"); // Copyright (C) and registered (R) symbols. Use raw symbol in MathML. +// \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}} +// \DeclareTextCommandDefault{\textregistered}{\textcircled{% +// \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}} +// \DeclareRobustCommand{\copyright}{% +// \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi} + +defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}"); +defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}"); +defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}"); // Characters omitted from Unicode range 1D400–1D7FF + +defineMacro("\u212C", "\\mathscr{B}"); // script + +defineMacro("\u2130", "\\mathscr{E}"); +defineMacro("\u2131", "\\mathscr{F}"); +defineMacro("\u210B", "\\mathscr{H}"); +defineMacro("\u2110", "\\mathscr{I}"); +defineMacro("\u2112", "\\mathscr{L}"); +defineMacro("\u2133", "\\mathscr{M}"); +defineMacro("\u211B", "\\mathscr{R}"); +defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur + +defineMacro("\u210C", "\\mathfrak{H}"); +defineMacro("\u2128", "\\mathfrak{Z}"); // Define \Bbbk with a macro that works in both HTML and MathML. + +defineMacro("\\Bbbk", "\\Bbb{k}"); // Unicode middle dot +// The KaTeX fonts do not contain U+00B7. Instead, \cdotp displays +// the dot at U+22C5 and gives it punct spacing. + +defineMacro("\u00b7", "\\cdotp"); // \llap and \rlap render their contents in text mode + +defineMacro("\\llap", "\\mathllap{\\textrm{#1}}"); +defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}"); +defineMacro("\\clap", "\\mathclap{\\textrm{#1}}"); // \mathstrut from the TeXbook, p 360 + +defineMacro("\\mathstrut", "\\vphantom{(}"); // \underbar from TeXbook p 353 + +defineMacro("\\underbar", "\\underline{\\text{#1}}"); // \not is defined by base/fontmath.ltx via +// \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36} +// It's thus treated like a \mathrel, but defined by a symbol that has zero +// width but extends to the right. We use \rlap to get that spacing. +// For MathML we write U+0338 here. buildMathML.js will then do the overlay. + +defineMacro("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'); // Negated symbols from base/fontmath.ltx: +// \def\neq{\not=} \let\ne=\neq +// \DeclareRobustCommand +// \notin{\mathrel{\m@th\mathpalette\c@ncel\in}} +// \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}} + +defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}"); +defineMacro("\\ne", "\\neq"); +defineMacro("\u2260", "\\neq"); +defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}"); +defineMacro("\u2209", "\\notin"); // Unicode stacked relations + +defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}"); +defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}"); +defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}"); +defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}"); +defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}"); +defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}"); +defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}"); // Misc Unicode + +defineMacro("\u27C2", "\\perp"); +defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}"); +defineMacro("\u220C", "\\notni"); +defineMacro("\u231C", "\\ulcorner"); +defineMacro("\u231D", "\\urcorner"); +defineMacro("\u231E", "\\llcorner"); +defineMacro("\u231F", "\\lrcorner"); +defineMacro("\u00A9", "\\copyright"); +defineMacro("\u00AE", "\\textregistered"); +defineMacro("\uFE0F", "\\textregistered"); // The KaTeX fonts have corners at codepoints that don't match Unicode. +// For MathML purposes, use the Unicode code point. + +defineMacro("\\ulcorner", "\\html@mathml{\\@ulcorner}{\\mathop{\\char\"231c}}"); +defineMacro("\\urcorner", "\\html@mathml{\\@urcorner}{\\mathop{\\char\"231d}}"); +defineMacro("\\llcorner", "\\html@mathml{\\@llcorner}{\\mathop{\\char\"231e}}"); +defineMacro("\\lrcorner", "\\html@mathml{\\@lrcorner}{\\mathop{\\char\"231f}}"); ////////////////////////////////////////////////////////////////////// +// LaTeX_2ε +// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ +// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} +// We'll call \varvdots, which gets a glyph from symbols.js. +// The zero-width rule gets us an equivalent to the vertical 6pt kern. + +defineMacro("\\vdots", "{\\varvdots\\rule{0pt}{15pt}}"); +defineMacro("\u22ee", "\\vdots"); ////////////////////////////////////////////////////////////////////// +// amsmath.sty +// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf +// Italic Greek capital letters. AMS defines these with \DeclareMathSymbol, +// but they are equivalent to \mathit{\Letter}. + +defineMacro("\\varGamma", "\\mathit{\\Gamma}"); +defineMacro("\\varDelta", "\\mathit{\\Delta}"); +defineMacro("\\varTheta", "\\mathit{\\Theta}"); +defineMacro("\\varLambda", "\\mathit{\\Lambda}"); +defineMacro("\\varXi", "\\mathit{\\Xi}"); +defineMacro("\\varPi", "\\mathit{\\Pi}"); +defineMacro("\\varSigma", "\\mathit{\\Sigma}"); +defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}"); +defineMacro("\\varPhi", "\\mathit{\\Phi}"); +defineMacro("\\varPsi", "\\mathit{\\Psi}"); +defineMacro("\\varOmega", "\\mathit{\\Omega}"); //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} + +defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); // \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript +// \mkern-\thinmuskip{:}\mskip6muplus1mu\relax} + +defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"); // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} + +defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); // \def\iff{\DOTSB\;\Longleftrightarrow\;} +// \def\implies{\DOTSB\;\Longrightarrow\;} +// \def\impliedby{\DOTSB\;\Longleftarrow\;} + +defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); +defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); +defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); // \def\dddot#1{{\mathop{#1}\limits^{\vbox to-1.4\ex@{\kern-\tw@\ex@ +// \hbox{\normalfont ...}\vss}}}} +// We use \overset which avoids the vertical shift of \mathop. + +defineMacro("\\dddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ...}}{#1}}"); +defineMacro("\\ddddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ....}}{#1}}"); // AMSMath's automatic \dots, based on \mdots@@ macro. + +var dotsByToken = { + ',': '\\dotsc', + '\\not': '\\dotsb', + // \keybin@ checks for the following: + '+': '\\dotsb', + '=': '\\dotsb', + '<': '\\dotsb', + '>': '\\dotsb', + '-': '\\dotsb', + '*': '\\dotsb', + ':': '\\dotsb', + // Symbols whose definition starts with \DOTSB: + '\\DOTSB': '\\dotsb', + '\\coprod': '\\dotsb', + '\\bigvee': '\\dotsb', + '\\bigwedge': '\\dotsb', + '\\biguplus': '\\dotsb', + '\\bigcap': '\\dotsb', + '\\bigcup': '\\dotsb', + '\\prod': '\\dotsb', + '\\sum': '\\dotsb', + '\\bigotimes': '\\dotsb', + '\\bigoplus': '\\dotsb', + '\\bigodot': '\\dotsb', + '\\bigsqcup': '\\dotsb', + '\\And': '\\dotsb', + '\\longrightarrow': '\\dotsb', + '\\Longrightarrow': '\\dotsb', + '\\longleftarrow': '\\dotsb', + '\\Longleftarrow': '\\dotsb', + '\\longleftrightarrow': '\\dotsb', + '\\Longleftrightarrow': '\\dotsb', + '\\mapsto': '\\dotsb', + '\\longmapsto': '\\dotsb', + '\\hookrightarrow': '\\dotsb', + '\\doteq': '\\dotsb', + // Symbols whose definition starts with \mathbin: + '\\mathbin': '\\dotsb', + // Symbols whose definition starts with \mathrel: + '\\mathrel': '\\dotsb', + '\\relbar': '\\dotsb', + '\\Relbar': '\\dotsb', + '\\xrightarrow': '\\dotsb', + '\\xleftarrow': '\\dotsb', + // Symbols whose definition starts with \DOTSI: + '\\DOTSI': '\\dotsi', + '\\int': '\\dotsi', + '\\oint': '\\dotsi', + '\\iint': '\\dotsi', + '\\iiint': '\\dotsi', + '\\iiiint': '\\dotsi', + '\\idotsint': '\\dotsi', + // Symbols whose definition starts with \DOTSX: + '\\DOTSX': '\\dotsx' +}; +defineMacro("\\dots", function (context) { + // TODO: If used in text mode, should expand to \textellipsis. + // However, in KaTeX, \textellipsis and \ldots behave the same + // (in text mode), and it's unlikely we'd see any of the math commands + // that affect the behavior of \dots when in text mode. So fine for now + // (until we support \ifmmode ... \else ... \fi). + var thedots = '\\dotso'; + var next = context.expandAfterFuture().text; + + if (next in dotsByToken) { + thedots = dotsByToken[next]; + } else if (next.slice(0, 4) === '\\not') { + thedots = '\\dotsb'; + } else if (next in symbols.math) { + if (utils.contains(['bin', 'rel'], symbols.math[next].group)) { + thedots = '\\dotsb'; + } + } + + return thedots; +}); +var spaceAfterDots = { + // \rightdelim@ checks for the following: + ')': true, + ']': true, + '\\rbrack': true, + '\\}': true, + '\\rbrace': true, + '\\rangle': true, + '\\rceil': true, + '\\rfloor': true, + '\\rgroup': true, + '\\rmoustache': true, + '\\right': true, + '\\bigr': true, + '\\biggr': true, + '\\Bigr': true, + '\\Biggr': true, + // \extra@ also tests for the following: + '$': true, + // \extrap@ checks for the following: + ';': true, + '.': true, + ',': true +}; +defineMacro("\\dotso", function (context) { + var next = context.future().text; + + if (next in spaceAfterDots) { + return "\\ldots\\,"; + } else { + return "\\ldots"; + } +}); +defineMacro("\\dotsc", function (context) { + var next = context.future().text; // \dotsc uses \extra@ but not \extrap@, instead specially checking for + // ';' and '.', but doesn't check for ','. + + if (next in spaceAfterDots && next !== ',') { + return "\\ldots\\,"; + } else { + return "\\ldots"; + } +}); +defineMacro("\\cdots", function (context) { + var next = context.future().text; + + if (next in spaceAfterDots) { + return "\\@cdots\\,"; + } else { + return "\\@cdots"; + } +}); +defineMacro("\\dotsb", "\\cdots"); +defineMacro("\\dotsm", "\\cdots"); +defineMacro("\\dotsi", "\\!\\cdots"); // amsmath doesn't actually define \dotsx, but \dots followed by a macro +// starting with \DOTSX implies \dotso, and then \extra@ detects this case +// and forces the added `\,`. + +defineMacro("\\dotsx", "\\ldots\\,"); // \let\DOTSI\relax +// \let\DOTSB\relax +// \let\DOTSX\relax + +defineMacro("\\DOTSI", "\\relax"); +defineMacro("\\DOTSB", "\\relax"); +defineMacro("\\DOTSX", "\\relax"); // Spacing, based on amsmath.sty's override of LaTeX defaults +// \DeclareRobustCommand{\tmspace}[3]{% +// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} + +defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} +// TODO: math mode should use \thinmuskip + +defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); // \let\thinspace\, + +defineMacro("\\thinspace", "\\,"); // \def\>{\mskip\medmuskip} +// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} +// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu + +defineMacro("\\>", "\\mskip{4mu}"); +defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); // \let\medspace\: + +defineMacro("\\medspace", "\\:"); // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} +// TODO: math mode should use \thickmuskip = 5mu plus 5mu + +defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); // \let\thickspace\; + +defineMacro("\\thickspace", "\\;"); // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} +// TODO: math mode should use \thinmuskip + +defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); // \let\negthinspace\! + +defineMacro("\\negthinspace", "\\!"); // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} +// TODO: math mode should use \medmuskip + +defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} +// TODO: math mode should use \thickmuskip + +defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); // \def\enspace{\kern.5em } + +defineMacro("\\enspace", "\\kern.5em "); // \def\enskip{\hskip.5em\relax} + +defineMacro("\\enskip", "\\hskip.5em\\relax"); // \def\quad{\hskip1em\relax} + +defineMacro("\\quad", "\\hskip1em\\relax"); // \def\qquad{\hskip2em\relax} + +defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag + +defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); +defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); +defineMacro("\\tag@literal", context => { + if (context.macros.get("\\df@tag")) { + throw new ParseError("Multiple \\tag"); + } + + return "\\gdef\\df@tag{\\text{#1}}"; +}); // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin +// {\operator@font mod}\penalty900 +// \mkern5mu\nonscript\mskip-\medmuskip} +// \newcommand{\pod}[1]{\allowbreak +// \if@display\mkern18mu\else\mkern8mu\fi(#1)} +// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} +// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu +// \else\mkern12mu\fi{\operator@font mod}\,\,#1} +// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu + +defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"); +defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"); +defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); +defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); ////////////////////////////////////////////////////////////////////// +// LaTeX source2e +// \expandafter\let\expandafter\@normalcr +// \csname\expandafter\@gobble\string\\ \endcsname +// \DeclareRobustCommand\newline{\@normalcr\relax} + +defineMacro("\\newline", "\\\\\\relax"); // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} +// TODO: Doesn't normally work in math mode because \@ fails. KaTeX doesn't +// support \@ yet, so that's omitted, and we add \text so that the result +// doesn't look funny in math mode. + +defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}"); // \DeclareRobustCommand{\LaTeX}{L\kern-.36em% +// {\sbox\z@ T% +// \vbox to\ht\z@{\hbox{\check@mathfonts +// \fontsize\sf@size\z@ +// \math@fontsfalse\selectfont +// A}% +// \vss}% +// }% +// \kern-.15em% +// \TeX} +// This code aligns the top of the A with the T (from the perspective of TeX's +// boxes, though visually the A appears to extend above slightly). +// We compute the corresponding \raisebox when A is rendered in \normalsize +// \scriptstyle, which has a scale factor of 0.7 (see Options.js). + +var latexRaiseA = makeEm(fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1]); +defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + ("L\\kern-.36em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{LaTeX}}"); // New KaTeX logo based on tweaking LaTeX logo + +defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + ("K\\kern-.17em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{KaTeX}}"); // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} +// \def\@hspace#1{\hskip #1\relax} +// \def\@hspacer#1{\vrule \@width\z@\nobreak +// \hskip #1\hskip \z@skip} + +defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); +defineMacro("\\@hspace", "\\hskip #1\\relax"); +defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); ////////////////////////////////////////////////////////////////////// +// mathtools.sty +//\providecommand\ordinarycolon{:} + +defineMacro("\\ordinarycolon", ":"); //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}} +//TODO(edemaine): Not yet centered. Fix via \raisebox or #726 + +defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"); // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon} + +defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}"); // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=} + +defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔ +// \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=} + +defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}"); // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} + +defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}"); // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} + +defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}"); // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon} + +defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕ +// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} + +defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}"); // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon} + +defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}"); // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} + +defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}"); // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} + +defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}"); // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} + +defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}"); // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} + +defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}"); // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} + +defineMacro("\\Colonsim", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"2237\\char\"223c}}"); // Some Unicode characters are implemented with macros to mathtools functions. + +defineMacro("\u2237", "\\dblcolon"); // :: + +defineMacro("\u2239", "\\eqcolon"); // -: + +defineMacro("\u2254", "\\coloneqq"); // := + +defineMacro("\u2255", "\\eqqcolon"); // =: + +defineMacro("\u2A74", "\\Coloneqq"); // ::= +////////////////////////////////////////////////////////////////////// +// colonequals.sty +// Alternate names for mathtools's macros: + +defineMacro("\\ratio", "\\vcentcolon"); +defineMacro("\\coloncolon", "\\dblcolon"); +defineMacro("\\colonequals", "\\coloneqq"); +defineMacro("\\coloncolonequals", "\\Coloneqq"); +defineMacro("\\equalscolon", "\\eqqcolon"); +defineMacro("\\equalscoloncolon", "\\Eqqcolon"); +defineMacro("\\colonminus", "\\coloneq"); +defineMacro("\\coloncolonminus", "\\Coloneq"); +defineMacro("\\minuscolon", "\\eqcolon"); +defineMacro("\\minuscoloncolon", "\\Eqcolon"); // \colonapprox name is same in mathtools and colonequals. + +defineMacro("\\coloncolonapprox", "\\Colonapprox"); // \colonsim name is same in mathtools and colonequals. + +defineMacro("\\coloncolonsim", "\\Colonsim"); // Additional macros, implemented by analogy with mathtools definitions: + +defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"); +defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"); +defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"); +defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"); // Present in newtxmath, pxfonts and txfonts + +defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}"); +defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); +defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); ////////////////////////////////////////////////////////////////////// +// From amsopn.sty + +defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); +defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); +defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}"); +defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}"); +defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}"); +defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"); ////////////////////////////////////////////////////////////////////// +// MathML alternates for KaTeX glyphs in the Unicode private area + +defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}"); +defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}"); +defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}"); +defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}"); +defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}"); +defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}"); +defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}"); +defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}"); +defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}"); +defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}"); +defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}"); +defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}"); +defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}"); +defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}"); +defineMacro("\\imath", "\\html@mathml{\\@imath}{\u0131}"); +defineMacro("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"); ////////////////////////////////////////////////////////////////////// +// stmaryrd and semantic +// The stmaryrd and semantic packages render the next four items by calling a +// glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros. + +defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}"); +defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}"); +defineMacro("\u27e6", "\\llbracket"); // blackboard bold [ + +defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ] + +defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}"); +defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}"); +defineMacro("\u2983", "\\lBrace"); // blackboard bold { + +defineMacro("\u2984", "\\rBrace"); // blackboard bold } +// TODO: Create variable sized versions of the last two items. I believe that +// will require new font glyphs. +// The stmaryrd function `\minuso` provides a "Plimsoll" symbol that +// superimposes the characters \circ and \mathminus. Used in chemistry. + +defineMacro("\\minuso", "\\mathbin{\\html@mathml{" + "{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}" + "{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}" + "{\\char`⦵}}"); +defineMacro("⦵", "\\minuso"); ////////////////////////////////////////////////////////////////////// +// texvc.sty +// The texvc package contains macros available in mediawiki pages. +// We omit the functions deprecated at +// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax +// We also omit texvc's \O, which conflicts with \text{\O} + +defineMacro("\\darr", "\\downarrow"); +defineMacro("\\dArr", "\\Downarrow"); +defineMacro("\\Darr", "\\Downarrow"); +defineMacro("\\lang", "\\langle"); +defineMacro("\\rang", "\\rangle"); +defineMacro("\\uarr", "\\uparrow"); +defineMacro("\\uArr", "\\Uparrow"); +defineMacro("\\Uarr", "\\Uparrow"); +defineMacro("\\N", "\\mathbb{N}"); +defineMacro("\\R", "\\mathbb{R}"); +defineMacro("\\Z", "\\mathbb{Z}"); +defineMacro("\\alef", "\\aleph"); +defineMacro("\\alefsym", "\\aleph"); +defineMacro("\\Alpha", "\\mathrm{A}"); +defineMacro("\\Beta", "\\mathrm{B}"); +defineMacro("\\bull", "\\bullet"); +defineMacro("\\Chi", "\\mathrm{X}"); +defineMacro("\\clubs", "\\clubsuit"); +defineMacro("\\cnums", "\\mathbb{C}"); +defineMacro("\\Complex", "\\mathbb{C}"); +defineMacro("\\Dagger", "\\ddagger"); +defineMacro("\\diamonds", "\\diamondsuit"); +defineMacro("\\empty", "\\emptyset"); +defineMacro("\\Epsilon", "\\mathrm{E}"); +defineMacro("\\Eta", "\\mathrm{H}"); +defineMacro("\\exist", "\\exists"); +defineMacro("\\harr", "\\leftrightarrow"); +defineMacro("\\hArr", "\\Leftrightarrow"); +defineMacro("\\Harr", "\\Leftrightarrow"); +defineMacro("\\hearts", "\\heartsuit"); +defineMacro("\\image", "\\Im"); +defineMacro("\\infin", "\\infty"); +defineMacro("\\Iota", "\\mathrm{I}"); +defineMacro("\\isin", "\\in"); +defineMacro("\\Kappa", "\\mathrm{K}"); +defineMacro("\\larr", "\\leftarrow"); +defineMacro("\\lArr", "\\Leftarrow"); +defineMacro("\\Larr", "\\Leftarrow"); +defineMacro("\\lrarr", "\\leftrightarrow"); +defineMacro("\\lrArr", "\\Leftrightarrow"); +defineMacro("\\Lrarr", "\\Leftrightarrow"); +defineMacro("\\Mu", "\\mathrm{M}"); +defineMacro("\\natnums", "\\mathbb{N}"); +defineMacro("\\Nu", "\\mathrm{N}"); +defineMacro("\\Omicron", "\\mathrm{O}"); +defineMacro("\\plusmn", "\\pm"); +defineMacro("\\rarr", "\\rightarrow"); +defineMacro("\\rArr", "\\Rightarrow"); +defineMacro("\\Rarr", "\\Rightarrow"); +defineMacro("\\real", "\\Re"); +defineMacro("\\reals", "\\mathbb{R}"); +defineMacro("\\Reals", "\\mathbb{R}"); +defineMacro("\\Rho", "\\mathrm{P}"); +defineMacro("\\sdot", "\\cdot"); +defineMacro("\\sect", "\\S"); +defineMacro("\\spades", "\\spadesuit"); +defineMacro("\\sub", "\\subset"); +defineMacro("\\sube", "\\subseteq"); +defineMacro("\\supe", "\\supseteq"); +defineMacro("\\Tau", "\\mathrm{T}"); +defineMacro("\\thetasym", "\\vartheta"); // TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}"); + +defineMacro("\\weierp", "\\wp"); +defineMacro("\\Zeta", "\\mathrm{Z}"); ////////////////////////////////////////////////////////////////////// +// statmath.sty +// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf + +defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); +defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); +defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"); ////////////////////////////////////////////////////////////////////// +// braket.sty +// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf + +defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); +defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); +defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); +defineMacro("\\Bra", "\\left\\langle#1\\right|"); +defineMacro("\\Ket", "\\left|#1\\right\\rangle"); + +var braketHelper = one => context => { + var left = context.consumeArg().tokens; + var middle = context.consumeArg().tokens; + var middleDouble = context.consumeArg().tokens; + var right = context.consumeArg().tokens; + var oldMiddle = context.macros.get("|"); + var oldMiddleDouble = context.macros.get("\\|"); + context.macros.beginGroup(); + + var midMacro = double => context => { + if (one) { + // Only modify the first instance of | or \| + context.macros.set("|", oldMiddle); + + if (middleDouble.length) { + context.macros.set("\\|", oldMiddleDouble); + } + } + + var doubled = double; + + if (!double && middleDouble.length) { + // Mimic \@ifnextchar + var nextToken = context.future(); + + if (nextToken.text === "|") { + context.popToken(); + doubled = true; + } + } + + return { + tokens: doubled ? middleDouble : middle, + numArgs: 0 + }; + }; + + context.macros.set("|", midMacro(false)); + + if (middleDouble.length) { + context.macros.set("\\|", midMacro(true)); + } + + var arg = context.consumeArg().tokens; + var expanded = context.expandTokens([...right, ...arg, ...left // reversed + ]); + context.macros.endGroup(); + return { + tokens: expanded.reverse(), + numArgs: 0 + }; +}; + +defineMacro("\\bra@ket", braketHelper(false)); +defineMacro("\\bra@set", braketHelper(true)); +defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); +defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); +defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); // has no support for special || or \| +////////////////////////////////////////////////////////////////////// +// actuarialangle.dtx + +defineMacro("\\angln", "{\\angl n}"); // Custom Khan Academy colors, should be moved to an optional package + +defineMacro("\\blue", "\\textcolor{##6495ed}{#1}"); +defineMacro("\\orange", "\\textcolor{##ffa500}{#1}"); +defineMacro("\\pink", "\\textcolor{##ff00af}{#1}"); +defineMacro("\\red", "\\textcolor{##df0030}{#1}"); +defineMacro("\\green", "\\textcolor{##28ae7b}{#1}"); +defineMacro("\\gray", "\\textcolor{gray}{#1}"); +defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}"); +defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}"); +defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}"); +defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}"); +defineMacro("\\blueD", "\\textcolor{##11accd}{#1}"); +defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}"); +defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}"); +defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}"); +defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}"); +defineMacro("\\tealD", "\\textcolor{##01a995}{#1}"); +defineMacro("\\tealE", "\\textcolor{##208170}{#1}"); +defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}"); +defineMacro("\\greenB", "\\textcolor{##8af281}{#1}"); +defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}"); +defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}"); +defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}"); +defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}"); +defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}"); +defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}"); +defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}"); +defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}"); +defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}"); +defineMacro("\\redB", "\\textcolor{##ff8482}{#1}"); +defineMacro("\\redC", "\\textcolor{##f9685d}{#1}"); +defineMacro("\\redD", "\\textcolor{##e84d39}{#1}"); +defineMacro("\\redE", "\\textcolor{##bc2612}{#1}"); +defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}"); +defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}"); +defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}"); +defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}"); +defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}"); +defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}"); +defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}"); +defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}"); +defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}"); +defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}"); +defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}"); +defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}"); +defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}"); +defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}"); +defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}"); +defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}"); +defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}"); +defineMacro("\\grayE", "\\textcolor{##babec2}{#1}"); +defineMacro("\\grayF", "\\textcolor{##888d93}{#1}"); +defineMacro("\\grayG", "\\textcolor{##626569}{#1}"); +defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}"); +defineMacro("\\grayI", "\\textcolor{##21242c}{#1}"); +defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}"); +defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}"); + +/** + * This file contains the “gullet” where macros are expanded + * until only non-macro tokens remain. + */ +// List of commands that act like macros but aren't defined as a macro, +// function, or symbol. Used in `isDefined`. +var implicitCommands = { + "^": true, + // Parser.js + "_": true, + // Parser.js + "\\limits": true, + // Parser.js + "\\nolimits": true // Parser.js + +}; +class MacroExpander { + constructor(input, settings, mode) { + this.settings = void 0; + this.expansionCount = void 0; + this.lexer = void 0; + this.macros = void 0; + this.stack = void 0; + this.mode = void 0; + this.settings = settings; + this.expansionCount = 0; + this.feed(input); // Make new global namespace + + this.macros = new Namespace(macros, settings.macros); + this.mode = mode; + this.stack = []; // contains tokens in REVERSE order + } + /** + * Feed a new input string to the same MacroExpander + * (with existing macros etc.). + */ + + + feed(input) { + this.lexer = new Lexer(input, this.settings); + } + /** + * Switches between "text" and "math" modes. + */ + + + switchMode(newMode) { + this.mode = newMode; + } + /** + * Start a new group nesting within all namespaces. + */ + + + beginGroup() { + this.macros.beginGroup(); + } + /** + * End current group nesting within all namespaces. + */ + + + endGroup() { + this.macros.endGroup(); + } + /** + * Ends all currently nested groups (if any), restoring values before the + * groups began. Useful in case of an error in the middle of parsing. + */ + + + endGroups() { + this.macros.endGroups(); + } + /** + * Returns the topmost token on the stack, without expanding it. + * Similar in behavior to TeX's `\futurelet`. + */ + + + future() { + if (this.stack.length === 0) { + this.pushToken(this.lexer.lex()); + } + + return this.stack[this.stack.length - 1]; + } + /** + * Remove and return the next unexpanded token. + */ + + + popToken() { + this.future(); // ensure non-empty stack + + return this.stack.pop(); + } + /** + * Add a given token to the token stack. In particular, this get be used + * to put back a token returned from one of the other methods. + */ + + + pushToken(token) { + this.stack.push(token); + } + /** + * Append an array of tokens to the token stack. + */ + + + pushTokens(tokens) { + this.stack.push(...tokens); + } + /** + * Find an macro argument without expanding tokens and append the array of + * tokens to the token stack. Uses Token as a container for the result. + */ + + + scanArgument(isOptional) { + var start; + var end; + var tokens; + + if (isOptional) { + this.consumeSpaces(); // \@ifnextchar gobbles any space following it + + if (this.future().text !== "[") { + return null; + } + + start = this.popToken(); // don't include [ in tokens + + ({ + tokens, + end + } = this.consumeArg(["]"])); + } else { + ({ + tokens, + start, + end + } = this.consumeArg()); + } // indicate the end of an argument + + + this.pushToken(new Token("EOF", end.loc)); + this.pushTokens(tokens); + return start.range(end, ""); + } + /** + * Consume all following space tokens, without expansion. + */ + + + consumeSpaces() { + for (;;) { + var token = this.future(); + + if (token.text === " ") { + this.stack.pop(); + } else { + break; + } + } + } + /** + * Consume an argument from the token stream, and return the resulting array + * of tokens and start/end token. + */ + + + consumeArg(delims) { + // The argument for a delimited parameter is the shortest (possibly + // empty) sequence of tokens with properly nested {...} groups that is + // followed ... by this particular list of non-parameter tokens. + // The argument for an undelimited parameter is the next nonblank + // token, unless that token is ‘{’, when the argument will be the + // entire {...} group that follows. + var tokens = []; + var isDelimited = delims && delims.length > 0; + + if (!isDelimited) { + // Ignore spaces between arguments. As the TeXbook says: + // "After you have said ‘\def\row#1#2{...}’, you are allowed to + // put spaces between the arguments (e.g., ‘\row x n’), because + // TeX doesn’t use single spaces as undelimited arguments." + this.consumeSpaces(); + } + + var start = this.future(); + var tok; + var depth = 0; + var match = 0; + + do { + tok = this.popToken(); + tokens.push(tok); + + if (tok.text === "{") { + ++depth; + } else if (tok.text === "}") { + --depth; + + if (depth === -1) { + throw new ParseError("Extra }", tok); + } + } else if (tok.text === "EOF") { + throw new ParseError("Unexpected end of input in a macro argument" + ", expected '" + (delims && isDelimited ? delims[match] : "}") + "'", tok); + } + + if (delims && isDelimited) { + if ((depth === 0 || depth === 1 && delims[match] === "{") && tok.text === delims[match]) { + ++match; + + if (match === delims.length) { + // don't include delims in tokens + tokens.splice(-match, match); + break; + } + } else { + match = 0; + } + } + } while (depth !== 0 || isDelimited); // If the argument found ... has the form ‘{}’, + // ... the outermost braces enclosing the argument are removed + + + if (start.text === "{" && tokens[tokens.length - 1].text === "}") { + tokens.pop(); + tokens.shift(); + } + + tokens.reverse(); // to fit in with stack order + + return { + tokens, + start, + end: tok + }; + } + /** + * Consume the specified number of (delimited) arguments from the token + * stream and return the resulting array of arguments. + */ + + + consumeArgs(numArgs, delimiters) { + if (delimiters) { + if (delimiters.length !== numArgs + 1) { + throw new ParseError("The length of delimiters doesn't match the number of args!"); + } + + var delims = delimiters[0]; + + for (var i = 0; i < delims.length; i++) { + var tok = this.popToken(); + + if (delims[i] !== tok.text) { + throw new ParseError("Use of the macro doesn't match its definition", tok); + } + } + } + + var args = []; + + for (var _i = 0; _i < numArgs; _i++) { + args.push(this.consumeArg(delimiters && delimiters[_i + 1]).tokens); + } + + return args; + } + /** + * Increment `expansionCount` by the specified amount. + * Throw an error if it exceeds `maxExpand`. + */ + + + countExpansion(amount) { + this.expansionCount += amount; + + if (this.expansionCount > this.settings.maxExpand) { + throw new ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting"); + } + } + /** + * Expand the next token only once if possible. + * + * If the token is expanded, the resulting tokens will be pushed onto + * the stack in reverse order, and the number of such tokens will be + * returned. This number might be zero or positive. + * + * If not, the return value is `false`, and the next token remains at the + * top of the stack. + * + * In either case, the next token will be on the top of the stack, + * or the stack will be empty (in case of empty expansion + * and no other tokens). + * + * Used to implement `expandAfterFuture` and `expandNextToken`. + * + * If expandableOnly, only expandable tokens are expanded and + * an undefined control sequence results in an error. + */ + + + expandOnce(expandableOnly) { + var topToken = this.popToken(); + var name = topToken.text; + var expansion = !topToken.noexpand ? this._getExpansion(name) : null; + + if (expansion == null || expandableOnly && expansion.unexpandable) { + if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { + throw new ParseError("Undefined control sequence: " + name); + } + + this.pushToken(topToken); + return false; + } + + this.countExpansion(1); + var tokens = expansion.tokens; + var args = this.consumeArgs(expansion.numArgs, expansion.delimiters); + + if (expansion.numArgs) { + // paste arguments in place of the placeholders + tokens = tokens.slice(); // make a shallow copy + + for (var i = tokens.length - 1; i >= 0; --i) { + var tok = tokens[i]; + + if (tok.text === "#") { + if (i === 0) { + throw new ParseError("Incomplete placeholder at end of macro body", tok); + } + + tok = tokens[--i]; // next token on stack + + if (tok.text === "#") { + // ## → # + tokens.splice(i + 1, 1); // drop first # + } else if (/^[1-9]$/.test(tok.text)) { + // replace the placeholder with the indicated argument + tokens.splice(i, 2, ...args[+tok.text - 1]); + } else { + throw new ParseError("Not a valid argument number", tok); + } + } + } + } // Concatenate expansion onto top of stack. + + + this.pushTokens(tokens); + return tokens.length; + } + /** + * Expand the next token only once (if possible), and return the resulting + * top token on the stack (without removing anything from the stack). + * Similar in behavior to TeX's `\expandafter\futurelet`. + * Equivalent to expandOnce() followed by future(). + */ + + + expandAfterFuture() { + this.expandOnce(); + return this.future(); + } + /** + * Recursively expand first token, then return first non-expandable token. + */ + + + expandNextToken() { + for (;;) { + if (this.expandOnce() === false) { + // fully expanded + var token = this.stack.pop(); // the token after \noexpand is interpreted as if its meaning + // were ‘\relax’ + + if (token.treatAsRelax) { + token.text = "\\relax"; + } + + return token; + } + } // Flow unable to figure out that this pathway is impossible. + // https://github.com/facebook/flow/issues/4808 + + + throw new Error(); // eslint-disable-line no-unreachable + } + /** + * Fully expand the given macro name and return the resulting list of + * tokens, or return `undefined` if no such macro is defined. + */ + + + expandMacro(name) { + return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; + } + /** + * Fully expand the given token stream and return the resulting list of + * tokens. Note that the input tokens are in reverse order, but the + * output tokens are in forward order. + */ + + + expandTokens(tokens) { + var output = []; + var oldStackLength = this.stack.length; + this.pushTokens(tokens); + + while (this.stack.length > oldStackLength) { + // Expand only expandable tokens + if (this.expandOnce(true) === false) { + // fully expanded + var token = this.stack.pop(); + + if (token.treatAsRelax) { + // the expansion of \noexpand is the token itself + token.noexpand = false; + token.treatAsRelax = false; + } + + output.push(token); + } + } // Count all of these tokens as additional expansions, to prevent + // exponential blowup from linearly many \edef's. + + + this.countExpansion(output.length); + return output; + } + /** + * Fully expand the given macro name and return the result as a string, + * or return `undefined` if no such macro is defined. + */ + + + expandMacroAsText(name) { + var tokens = this.expandMacro(name); + + if (tokens) { + return tokens.map(token => token.text).join(""); + } else { + return tokens; + } + } + /** + * Returns the expanded macro as a reversed array of tokens and a macro + * argument count. Or returns `null` if no such macro. + */ + + + _getExpansion(name) { + var definition = this.macros.get(name); + + if (definition == null) { + // mainly checking for undefined here + return definition; + } // If a single character has an associated catcode other than 13 + // (active character), then don't expand it. + + + if (name.length === 1) { + var catcode = this.lexer.catcodes[name]; + + if (catcode != null && catcode !== 13) { + return; + } + } + + var expansion = typeof definition === "function" ? definition(this) : definition; + + if (typeof expansion === "string") { + var numArgs = 0; + + if (expansion.indexOf("#") !== -1) { + var stripped = expansion.replace(/##/g, ""); + + while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { + ++numArgs; + } + } + + var bodyLexer = new Lexer(expansion, this.settings); + var tokens = []; + var tok = bodyLexer.lex(); + + while (tok.text !== "EOF") { + tokens.push(tok); + tok = bodyLexer.lex(); + } + + tokens.reverse(); // to fit in with stack using push and pop + + var expanded = { + tokens, + numArgs + }; + return expanded; + } + + return expansion; + } + /** + * Determine whether a command is currently "defined" (has some + * functionality), meaning that it's a macro (in the current group), + * a function, a symbol, or one of the special commands listed in + * `implicitCommands`. + */ + + + isDefined(name) { + return this.macros.has(name) || functions.hasOwnProperty(name) || symbols.math.hasOwnProperty(name) || symbols.text.hasOwnProperty(name) || implicitCommands.hasOwnProperty(name); + } + /** + * Determine whether a command is expandable. + */ + + + isExpandable(name) { + var macro = this.macros.get(name); + return macro != null ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable : functions.hasOwnProperty(name) && !functions[name].primitive; + } + +} + +// Helpers for Parser.js handling of Unicode (sub|super)script characters. +var unicodeSubRegEx = /^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/; +var uSubsAndSups = Object.freeze({ + '₊': '+', + '₋': '-', + '₌': '=', + '₍': '(', + '₎': ')', + '₀': '0', + '₁': '1', + '₂': '2', + '₃': '3', + '₄': '4', + '₅': '5', + '₆': '6', + '₇': '7', + '₈': '8', + '₉': '9', + '\u2090': 'a', + '\u2091': 'e', + '\u2095': 'h', + '\u1D62': 'i', + '\u2C7C': 'j', + '\u2096': 'k', + '\u2097': 'l', + '\u2098': 'm', + '\u2099': 'n', + '\u2092': 'o', + '\u209A': 'p', + '\u1D63': 'r', + '\u209B': 's', + '\u209C': 't', + '\u1D64': 'u', + '\u1D65': 'v', + '\u2093': 'x', + '\u1D66': 'β', + '\u1D67': 'γ', + '\u1D68': 'ρ', + '\u1D69': '\u03d5', + '\u1D6A': 'χ', + '⁺': '+', + '⁻': '-', + '⁼': '=', + '⁽': '(', + '⁾': ')', + '⁰': '0', + '¹': '1', + '²': '2', + '³': '3', + '⁴': '4', + '⁵': '5', + '⁶': '6', + '⁷': '7', + '⁸': '8', + '⁹': '9', + '\u1D2C': 'A', + '\u1D2E': 'B', + '\u1D30': 'D', + '\u1D31': 'E', + '\u1D33': 'G', + '\u1D34': 'H', + '\u1D35': 'I', + '\u1D36': 'J', + '\u1D37': 'K', + '\u1D38': 'L', + '\u1D39': 'M', + '\u1D3A': 'N', + '\u1D3C': 'O', + '\u1D3E': 'P', + '\u1D3F': 'R', + '\u1D40': 'T', + '\u1D41': 'U', + '\u2C7D': 'V', + '\u1D42': 'W', + '\u1D43': 'a', + '\u1D47': 'b', + '\u1D9C': 'c', + '\u1D48': 'd', + '\u1D49': 'e', + '\u1DA0': 'f', + '\u1D4D': 'g', + '\u02B0': 'h', + '\u2071': 'i', + '\u02B2': 'j', + '\u1D4F': 'k', + '\u02E1': 'l', + '\u1D50': 'm', + '\u207F': 'n', + '\u1D52': 'o', + '\u1D56': 'p', + '\u02B3': 'r', + '\u02E2': 's', + '\u1D57': 't', + '\u1D58': 'u', + '\u1D5B': 'v', + '\u02B7': 'w', + '\u02E3': 'x', + '\u02B8': 'y', + '\u1DBB': 'z', + '\u1D5D': 'β', + '\u1D5E': 'γ', + '\u1D5F': 'δ', + '\u1D60': '\u03d5', + '\u1D61': 'χ', + '\u1DBF': 'θ' +}); + +/* eslint no-constant-condition:0 */ + +var unicodeAccents = { + "́": { + "text": "\\'", + "math": "\\acute" + }, + "̀": { + "text": "\\`", + "math": "\\grave" + }, + "̈": { + "text": "\\\"", + "math": "\\ddot" + }, + "̃": { + "text": "\\~", + "math": "\\tilde" + }, + "̄": { + "text": "\\=", + "math": "\\bar" + }, + "̆": { + "text": "\\u", + "math": "\\breve" + }, + "̌": { + "text": "\\v", + "math": "\\check" + }, + "̂": { + "text": "\\^", + "math": "\\hat" + }, + "̇": { + "text": "\\.", + "math": "\\dot" + }, + "̊": { + "text": "\\r", + "math": "\\mathring" + }, + "̋": { + "text": "\\H" + }, + "̧": { + "text": "\\c" + } +}; +var unicodeSymbols = { + "á": "á", + "à": "à", + "ä": "ä", + "ǟ": "ǟ", + "ã": "ã", + "ā": "ā", + "ă": "ă", + "ắ": "ắ", + "ằ": "ằ", + "ẵ": "ẵ", + "ǎ": "ǎ", + "â": "â", + "ấ": "ấ", + "ầ": "ầ", + "ẫ": "ẫ", + "ȧ": "ȧ", + "ǡ": "ǡ", + "å": "å", + "ǻ": "ǻ", + "ḃ": "ḃ", + "ć": "ć", + "ḉ": "ḉ", + "č": "č", + "ĉ": "ĉ", + "ċ": "ċ", + "ç": "ç", + "ď": "ď", + "ḋ": "ḋ", + "ḑ": "ḑ", + "é": "é", + "è": "è", + "ë": "ë", + "ẽ": "ẽ", + "ē": "ē", + "ḗ": "ḗ", + "ḕ": "ḕ", + "ĕ": "ĕ", + "ḝ": "ḝ", + "ě": "ě", + "ê": "ê", + "ế": "ế", + "ề": "ề", + "ễ": "ễ", + "ė": "ė", + "ȩ": "ȩ", + "ḟ": "ḟ", + "ǵ": "ǵ", + "ḡ": "ḡ", + "ğ": "ğ", + "ǧ": "ǧ", + "ĝ": "ĝ", + "ġ": "ġ", + "ģ": "ģ", + "ḧ": "ḧ", + "ȟ": "ȟ", + "ĥ": "ĥ", + "ḣ": "ḣ", + "ḩ": "ḩ", + "í": "í", + "ì": "ì", + "ï": "ï", + "ḯ": "ḯ", + "ĩ": "ĩ", + "ī": "ī", + "ĭ": "ĭ", + "ǐ": "ǐ", + "î": "î", + "ǰ": "ǰ", + "ĵ": "ĵ", + "ḱ": "ḱ", + "ǩ": "ǩ", + "ķ": "ķ", + "ĺ": "ĺ", + "ľ": "ľ", + "ļ": "ļ", + "ḿ": "ḿ", + "ṁ": "ṁ", + "ń": "ń", + "ǹ": "ǹ", + "ñ": "ñ", + "ň": "ň", + "ṅ": "ṅ", + "ņ": "ņ", + "ó": "ó", + "ò": "ò", + "ö": "ö", + "ȫ": "ȫ", + "õ": "õ", + "ṍ": "ṍ", + "ṏ": "ṏ", + "ȭ": "ȭ", + "ō": "ō", + "ṓ": "ṓ", + "ṑ": "ṑ", + "ŏ": "ŏ", + "ǒ": "ǒ", + "ô": "ô", + "ố": "ố", + "ồ": "ồ", + "ỗ": "ỗ", + "ȯ": "ȯ", + "ȱ": "ȱ", + "ő": "ő", + "ṕ": "ṕ", + "ṗ": "ṗ", + "ŕ": "ŕ", + "ř": "ř", + "ṙ": "ṙ", + "ŗ": "ŗ", + "ś": "ś", + "ṥ": "ṥ", + "š": "š", + "ṧ": "ṧ", + "ŝ": "ŝ", + "ṡ": "ṡ", + "ş": "ş", + "ẗ": "ẗ", + "ť": "ť", + "ṫ": "ṫ", + "ţ": "ţ", + "ú": "ú", + "ù": "ù", + "ü": "ü", + "ǘ": "ǘ", + "ǜ": "ǜ", + "ǖ": "ǖ", + "ǚ": "ǚ", + "ũ": "ũ", + "ṹ": "ṹ", + "ū": "ū", + "ṻ": "ṻ", + "ŭ": "ŭ", + "ǔ": "ǔ", + "û": "û", + "ů": "ů", + "ű": "ű", + "ṽ": "ṽ", + "ẃ": "ẃ", + "ẁ": "ẁ", + "ẅ": "ẅ", + "ŵ": "ŵ", + "ẇ": "ẇ", + "ẘ": "ẘ", + "ẍ": "ẍ", + "ẋ": "ẋ", + "ý": "ý", + "ỳ": "ỳ", + "ÿ": "ÿ", + "ỹ": "ỹ", + "ȳ": "ȳ", + "ŷ": "ŷ", + "ẏ": "ẏ", + "ẙ": "ẙ", + "ź": "ź", + "ž": "ž", + "ẑ": "ẑ", + "ż": "ż", + "Á": "Á", + "À": "À", + "Ä": "Ä", + "Ǟ": "Ǟ", + "Ã": "Ã", + "Ā": "Ā", + "Ă": "Ă", + "Ắ": "Ắ", + "Ằ": "Ằ", + "Ẵ": "Ẵ", + "Ǎ": "Ǎ", + "Â": "Â", + "Ấ": "Ấ", + "Ầ": "Ầ", + "Ẫ": "Ẫ", + "Ȧ": "Ȧ", + "Ǡ": "Ǡ", + "Å": "Å", + "Ǻ": "Ǻ", + "Ḃ": "Ḃ", + "Ć": "Ć", + "Ḉ": "Ḉ", + "Č": "Č", + "Ĉ": "Ĉ", + "Ċ": "Ċ", + "Ç": "Ç", + "Ď": "Ď", + "Ḋ": "Ḋ", + "Ḑ": "Ḑ", + "É": "É", + "È": "È", + "Ë": "Ë", + "Ẽ": "Ẽ", + "Ē": "Ē", + "Ḗ": "Ḗ", + "Ḕ": "Ḕ", + "Ĕ": "Ĕ", + "Ḝ": "Ḝ", + "Ě": "Ě", + "Ê": "Ê", + "Ế": "Ế", + "Ề": "Ề", + "Ễ": "Ễ", + "Ė": "Ė", + "Ȩ": "Ȩ", + "Ḟ": "Ḟ", + "Ǵ": "Ǵ", + "Ḡ": "Ḡ", + "Ğ": "Ğ", + "Ǧ": "Ǧ", + "Ĝ": "Ĝ", + "Ġ": "Ġ", + "Ģ": "Ģ", + "Ḧ": "Ḧ", + "Ȟ": "Ȟ", + "Ĥ": "Ĥ", + "Ḣ": "Ḣ", + "Ḩ": "Ḩ", + "Í": "Í", + "Ì": "Ì", + "Ï": "Ï", + "Ḯ": "Ḯ", + "Ĩ": "Ĩ", + "Ī": "Ī", + "Ĭ": "Ĭ", + "Ǐ": "Ǐ", + "Î": "Î", + "İ": "İ", + "Ĵ": "Ĵ", + "Ḱ": "Ḱ", + "Ǩ": "Ǩ", + "Ķ": "Ķ", + "Ĺ": "Ĺ", + "Ľ": "Ľ", + "Ļ": "Ļ", + "Ḿ": "Ḿ", + "Ṁ": "Ṁ", + "Ń": "Ń", + "Ǹ": "Ǹ", + "Ñ": "Ñ", + "Ň": "Ň", + "Ṅ": "Ṅ", + "Ņ": "Ņ", + "Ó": "Ó", + "Ò": "Ò", + "Ö": "Ö", + "Ȫ": "Ȫ", + "Õ": "Õ", + "Ṍ": "Ṍ", + "Ṏ": "Ṏ", + "Ȭ": "Ȭ", + "Ō": "Ō", + "Ṓ": "Ṓ", + "Ṑ": "Ṑ", + "Ŏ": "Ŏ", + "Ǒ": "Ǒ", + "Ô": "Ô", + "Ố": "Ố", + "Ồ": "Ồ", + "Ỗ": "Ỗ", + "Ȯ": "Ȯ", + "Ȱ": "Ȱ", + "Ő": "Ő", + "Ṕ": "Ṕ", + "Ṗ": "Ṗ", + "Ŕ": "Ŕ", + "Ř": "Ř", + "Ṙ": "Ṙ", + "Ŗ": "Ŗ", + "Ś": "Ś", + "Ṥ": "Ṥ", + "Š": "Š", + "Ṧ": "Ṧ", + "Ŝ": "Ŝ", + "Ṡ": "Ṡ", + "Ş": "Ş", + "Ť": "Ť", + "Ṫ": "Ṫ", + "Ţ": "Ţ", + "Ú": "Ú", + "Ù": "Ù", + "Ü": "Ü", + "Ǘ": "Ǘ", + "Ǜ": "Ǜ", + "Ǖ": "Ǖ", + "Ǚ": "Ǚ", + "Ũ": "Ũ", + "Ṹ": "Ṹ", + "Ū": "Ū", + "Ṻ": "Ṻ", + "Ŭ": "Ŭ", + "Ǔ": "Ǔ", + "Û": "Û", + "Ů": "Ů", + "Ű": "Ű", + "Ṽ": "Ṽ", + "Ẃ": "Ẃ", + "Ẁ": "Ẁ", + "Ẅ": "Ẅ", + "Ŵ": "Ŵ", + "Ẇ": "Ẇ", + "Ẍ": "Ẍ", + "Ẋ": "Ẋ", + "Ý": "Ý", + "Ỳ": "Ỳ", + "Ÿ": "Ÿ", + "Ỹ": "Ỹ", + "Ȳ": "Ȳ", + "Ŷ": "Ŷ", + "Ẏ": "Ẏ", + "Ź": "Ź", + "Ž": "Ž", + "Ẑ": "Ẑ", + "Ż": "Ż", + "ά": "ά", + "ὰ": "ὰ", + "ᾱ": "ᾱ", + "ᾰ": "ᾰ", + "έ": "έ", + "ὲ": "ὲ", + "ή": "ή", + "ὴ": "ὴ", + "ί": "ί", + "ὶ": "ὶ", + "ϊ": "ϊ", + "ΐ": "ΐ", + "ῒ": "ῒ", + "ῑ": "ῑ", + "ῐ": "ῐ", + "ό": "ό", + "ὸ": "ὸ", + "ύ": "ύ", + "ὺ": "ὺ", + "ϋ": "ϋ", + "ΰ": "ΰ", + "ῢ": "ῢ", + "ῡ": "ῡ", + "ῠ": "ῠ", + "ώ": "ώ", + "ὼ": "ὼ", + "Ύ": "Ύ", + "Ὺ": "Ὺ", + "Ϋ": "Ϋ", + "Ῡ": "Ῡ", + "Ῠ": "Ῠ", + "Ώ": "Ώ", + "Ὼ": "Ὼ" +}; + +/** + * This file contains the parser used to parse out a TeX expression from the + * input. Since TeX isn't context-free, standard parsers don't work particularly + * well. + * + * The strategy of this parser is as such: + * + * The main functions (the `.parse...` ones) take a position in the current + * parse string to parse tokens from. The lexer (found in Lexer.js, stored at + * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When + * individual tokens are needed at a position, the lexer is called to pull out a + * token, which is then used. + * + * The parser has a property called "mode" indicating the mode that + * the parser is currently in. Currently it has to be one of "math" or + * "text", which denotes whether the current environment is a math-y + * one or a text-y one (e.g. inside \text). Currently, this serves to + * limit the functions which can be used in text mode. + * + * The main functions then return an object which contains the useful data that + * was parsed at its given point, and a new position at the end of the parsed + * data. The main functions can call each other and continue the parsing by + * using the returned position as a new starting point. + * + * There are also extra `.handle...` functions, which pull out some reused + * functionality into self-contained functions. + * + * The functions return ParseNodes. + */ +class Parser { + constructor(input, settings) { + this.mode = void 0; + this.gullet = void 0; + this.settings = void 0; + this.leftrightDepth = void 0; + this.nextToken = void 0; + // Start in math mode + this.mode = "math"; // Create a new macro expander (gullet) and (indirectly via that) also a + // new lexer (mouth) for this parser (stomach, in the language of TeX) + + this.gullet = new MacroExpander(input, settings, this.mode); // Store the settings for use in parsing + + this.settings = settings; // Count leftright depth (for \middle errors) + + this.leftrightDepth = 0; + } + /** + * Checks a result to make sure it has the right type, and throws an + * appropriate error otherwise. + */ + + + expect(text, consume) { + if (consume === void 0) { + consume = true; + } + + if (this.fetch().text !== text) { + throw new ParseError("Expected '" + text + "', got '" + this.fetch().text + "'", this.fetch()); + } + + if (consume) { + this.consume(); + } + } + /** + * Discards the current lookahead token, considering it consumed. + */ + + + consume() { + this.nextToken = null; + } + /** + * Return the current lookahead token, or if there isn't one (at the + * beginning, or if the previous lookahead token was consume()d), + * fetch the next token as the new lookahead token and return it. + */ + + + fetch() { + if (this.nextToken == null) { + this.nextToken = this.gullet.expandNextToken(); + } + + return this.nextToken; + } + /** + * Switches between "text" and "math" modes. + */ + + + switchMode(newMode) { + this.mode = newMode; + this.gullet.switchMode(newMode); + } + /** + * Main parsing function, which parses an entire input. + */ + + + parse() { + if (!this.settings.globalGroup) { + // Create a group namespace for the math expression. + // (LaTeX creates a new group for every $...$, $$...$$, \[...\].) + this.gullet.beginGroup(); + } // Use old \color behavior (same as LaTeX's \textcolor) if requested. + // We do this within the group for the math expression, so it doesn't + // pollute settings.macros. + + + if (this.settings.colorIsTextColor) { + this.gullet.macros.set("\\color", "\\textcolor"); + } + + try { + // Try to parse the input + var parse = this.parseExpression(false); // If we succeeded, make sure there's an EOF at the end + + this.expect("EOF"); // End the group namespace for the expression + + if (!this.settings.globalGroup) { + this.gullet.endGroup(); + } + + return parse; // Close any leftover groups in case of a parse error. + } finally { + this.gullet.endGroups(); + } + } + /** + * Fully parse a separate sequence of tokens as a separate job. + * Tokens should be specified in reverse order, as in a MacroDefinition. + */ + + + subparse(tokens) { + // Save the next token from the current job. + var oldToken = this.nextToken; + this.consume(); // Run the new job, terminating it with an excess '}' + + this.gullet.pushToken(new Token("}")); + this.gullet.pushTokens(tokens); + var parse = this.parseExpression(false); + this.expect("}"); // Restore the next token from the current job. + + this.nextToken = oldToken; + return parse; + } + + /** + * Parses an "expression", which is a list of atoms. + * + * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This + * happens when functions have higher precedence han infix + * nodes in implicit parses. + * + * `breakOnTokenText`: The text of the token that the expression should end + * with, or `null` if something else should end the + * expression. + */ + parseExpression(breakOnInfix, breakOnTokenText) { + var body = []; // Keep adding atoms to the body until we can't parse any more atoms (either + // we reached the end, a }, or a \right) + + while (true) { + // Ignore spaces in math mode + if (this.mode === "math") { + this.consumeSpaces(); + } + + var lex = this.fetch(); + + if (Parser.endOfExpression.indexOf(lex.text) !== -1) { + break; + } + + if (breakOnTokenText && lex.text === breakOnTokenText) { + break; + } + + if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { + break; + } + + var atom = this.parseAtom(breakOnTokenText); + + if (!atom) { + break; + } else if (atom.type === "internal") { + // Internal nodes do not appear in parse tree + continue; + } + + body.push(atom); + } + + if (this.mode === "text") { + this.formLigatures(body); + } + + return this.handleInfixNodes(body); + } + /** + * Rewrites infix operators such as \over with corresponding commands such + * as \frac. + * + * There can only be one infix operator per group. If there's more than one + * then the expression is ambiguous. This can be resolved by adding {}. + */ + + + handleInfixNodes(body) { + var overIndex = -1; + var funcName; + + for (var i = 0; i < body.length; i++) { + if (body[i].type === "infix") { + if (overIndex !== -1) { + throw new ParseError("only one infix operator per group", body[i].token); + } + + overIndex = i; + funcName = body[i].replaceWith; + } + } + + if (overIndex !== -1 && funcName) { + var numerNode; + var denomNode; + var numerBody = body.slice(0, overIndex); + var denomBody = body.slice(overIndex + 1); + + if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { + numerNode = numerBody[0]; + } else { + numerNode = { + type: "ordgroup", + mode: this.mode, + body: numerBody + }; + } + + if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { + denomNode = denomBody[0]; + } else { + denomNode = { + type: "ordgroup", + mode: this.mode, + body: denomBody + }; + } + + var node; + + if (funcName === "\\\\abovefrac") { + node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); + } else { + node = this.callFunction(funcName, [numerNode, denomNode], []); + } + + return [node]; + } else { + return body; + } + } + /** + * Handle a subscript or superscript with nice errors. + */ + + + handleSupSubscript(name // For error reporting. + ) { + var symbolToken = this.fetch(); + var symbol = symbolToken.text; + this.consume(); + this.consumeSpaces(); // ignore spaces before sup/subscript argument + // Skip over allowed internal nodes such as \relax + + var group; + + do { + var _group; + + group = this.parseGroup(name); + } while (((_group = group) == null ? void 0 : _group.type) === "internal"); + + if (!group) { + throw new ParseError("Expected group after '" + symbol + "'", symbolToken); + } + + return group; + } + /** + * Converts the textual input of an unsupported command into a text node + * contained within a color node whose color is determined by errorColor + */ + + + formatUnsupportedCmd(text) { + var textordArray = []; + + for (var i = 0; i < text.length; i++) { + textordArray.push({ + type: "textord", + mode: "text", + text: text[i] + }); + } + + var textNode = { + type: "text", + mode: this.mode, + body: textordArray + }; + var colorNode = { + type: "color", + mode: this.mode, + color: this.settings.errorColor, + body: [textNode] + }; + return colorNode; + } + /** + * Parses a group with optional super/subscripts. + */ + + + parseAtom(breakOnTokenText) { + // The body of an atom is an implicit group, so that things like + // \left(x\right)^2 work correctly. + var base = this.parseGroup("atom", breakOnTokenText); // Internal nodes (e.g. \relax) cannot support super/subscripts. + // Instead we will pick up super/subscripts with blank base next round. + + if ((base == null ? void 0 : base.type) === "internal") { + return base; + } // In text mode, we don't have superscripts or subscripts + + + if (this.mode === "text") { + return base; + } // Note that base may be empty (i.e. null) at this point. + + + var superscript; + var subscript; + + while (true) { + // Guaranteed in math mode, so eat any spaces first. + this.consumeSpaces(); // Lex the first token + + var lex = this.fetch(); + + if (lex.text === "\\limits" || lex.text === "\\nolimits") { + // We got a limit control + if (base && base.type === "op") { + var limits = lex.text === "\\limits"; + base.limits = limits; + base.alwaysHandleSupSub = true; + } else if (base && base.type === "operatorname") { + if (base.alwaysHandleSupSub) { + base.limits = lex.text === "\\limits"; + } + } else { + throw new ParseError("Limit controls must follow a math operator", lex); + } + + this.consume(); + } else if (lex.text === "^") { + // We got a superscript start + if (superscript) { + throw new ParseError("Double superscript", lex); + } + + superscript = this.handleSupSubscript("superscript"); + } else if (lex.text === "_") { + // We got a subscript start + if (subscript) { + throw new ParseError("Double subscript", lex); + } + + subscript = this.handleSupSubscript("subscript"); + } else if (lex.text === "'") { + // We got a prime + if (superscript) { + throw new ParseError("Double superscript", lex); + } + + var prime = { + type: "textord", + mode: this.mode, + text: "\\prime" + }; // Many primes can be grouped together, so we handle this here + + var primes = [prime]; + this.consume(); // Keep lexing tokens until we get something that's not a prime + + while (this.fetch().text === "'") { + // For each one, add another prime to the list + primes.push(prime); + this.consume(); + } // If there's a superscript following the primes, combine that + // superscript in with the primes. + + + if (this.fetch().text === "^") { + primes.push(this.handleSupSubscript("superscript")); + } // Put everything into an ordgroup as the superscript + + + superscript = { + type: "ordgroup", + mode: this.mode, + body: primes + }; + } else if (uSubsAndSups[lex.text]) { + // A Unicode subscript or superscript character. + // We treat these similarly to the unicode-math package. + // So we render a string of Unicode (sub|super)scripts the + // same as a (sub|super)script of regular characters. + var isSub = unicodeSubRegEx.test(lex.text); + var subsupTokens = []; + subsupTokens.push(new Token(uSubsAndSups[lex.text])); + this.consume(); // Continue fetching tokens to fill out the string. + + while (true) { + var token = this.fetch().text; + + if (!uSubsAndSups[token]) { + break; + } + + if (unicodeSubRegEx.test(token) !== isSub) { + break; + } + + subsupTokens.unshift(new Token(uSubsAndSups[token])); + this.consume(); + } // Now create a (sub|super)script. + + + var body = this.subparse(subsupTokens); + + if (isSub) { + subscript = { + type: "ordgroup", + mode: "math", + body + }; + } else { + superscript = { + type: "ordgroup", + mode: "math", + body + }; + } + } else { + // If it wasn't ^, _, or ', stop parsing super/subscripts + break; + } + } // Base must be set if superscript or subscript are set per logic above, + // but need to check here for type check to pass. + + + if (superscript || subscript) { + // If we got either a superscript or subscript, create a supsub + return { + type: "supsub", + mode: this.mode, + base: base, + sup: superscript, + sub: subscript + }; + } else { + // Otherwise return the original body + return base; + } + } + /** + * Parses an entire function, including its base and all of its arguments. + */ + + + parseFunction(breakOnTokenText, name // For determining its context + ) { + var token = this.fetch(); + var func = token.text; + var funcData = functions[func]; + + if (!funcData) { + return null; + } + + this.consume(); // consume command token + + if (name && name !== "atom" && !funcData.allowedInArgument) { + throw new ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token); + } else if (this.mode === "text" && !funcData.allowedInText) { + throw new ParseError("Can't use function '" + func + "' in text mode", token); + } else if (this.mode === "math" && funcData.allowedInMath === false) { + throw new ParseError("Can't use function '" + func + "' in math mode", token); + } + + var { + args, + optArgs + } = this.parseArguments(func, funcData); + return this.callFunction(func, args, optArgs, token, breakOnTokenText); + } + /** + * Call a function handler with a suitable context and arguments. + */ + + + callFunction(name, args, optArgs, token, breakOnTokenText) { + var context = { + funcName: name, + parser: this, + token, + breakOnTokenText + }; + var func = functions[name]; + + if (func && func.handler) { + return func.handler(context, args, optArgs); + } else { + throw new ParseError("No function handler for " + name); + } + } + /** + * Parses the arguments of a function or environment + */ + + + parseArguments(func, // Should look like "\name" or "\begin{name}". + funcData) { + var totalArgs = funcData.numArgs + funcData.numOptionalArgs; + + if (totalArgs === 0) { + return { + args: [], + optArgs: [] + }; + } + + var args = []; + var optArgs = []; + + for (var i = 0; i < totalArgs; i++) { + var argType = funcData.argTypes && funcData.argTypes[i]; + var isOptional = i < funcData.numOptionalArgs; + + if (funcData.primitive && argType == null || // \sqrt expands into primitive if optional argument doesn't exist + funcData.type === "sqrt" && i === 1 && optArgs[0] == null) { + argType = "primitive"; + } + + var arg = this.parseGroupOfType("argument to '" + func + "'", argType, isOptional); + + if (isOptional) { + optArgs.push(arg); + } else if (arg != null) { + args.push(arg); + } else { + // should be unreachable + throw new ParseError("Null argument, please report this as a bug"); + } + } + + return { + args, + optArgs + }; + } + /** + * Parses a group when the mode is changing. + */ + + + parseGroupOfType(name, type, optional) { + switch (type) { + case "color": + return this.parseColorGroup(optional); + + case "size": + return this.parseSizeGroup(optional); + + case "url": + return this.parseUrlGroup(optional); + + case "math": + case "text": + return this.parseArgumentGroup(optional, type); + + case "hbox": + { + // hbox argument type wraps the argument in the equivalent of + // \hbox, which is like \text but switching to \textstyle size. + var group = this.parseArgumentGroup(optional, "text"); + return group != null ? { + type: "styling", + mode: group.mode, + body: [group], + style: "text" // simulate \textstyle + + } : null; + } + + case "raw": + { + var token = this.parseStringGroup("raw", optional); + return token != null ? { + type: "raw", + mode: "text", + string: token.text + } : null; + } + + case "primitive": + { + if (optional) { + throw new ParseError("A primitive argument cannot be optional"); + } + + var _group2 = this.parseGroup(name); + + if (_group2 == null) { + throw new ParseError("Expected group as " + name, this.fetch()); + } + + return _group2; + } + + case "original": + case null: + case undefined: + return this.parseArgumentGroup(optional); + + default: + throw new ParseError("Unknown group type as " + name, this.fetch()); + } + } + /** + * Discard any space tokens, fetching the next non-space token. + */ + + + consumeSpaces() { + while (this.fetch().text === " ") { + this.consume(); + } + } + /** + * Parses a group, essentially returning the string formed by the + * brace-enclosed tokens plus some position information. + */ + + + parseStringGroup(modeName, // Used to describe the mode in error messages. + optional) { + var argToken = this.gullet.scanArgument(optional); + + if (argToken == null) { + return null; + } + + var str = ""; + var nextToken; + + while ((nextToken = this.fetch()).text !== "EOF") { + str += nextToken.text; + this.consume(); + } + + this.consume(); // consume the end of the argument + + argToken.text = str; + return argToken; + } + /** + * Parses a regex-delimited group: the largest sequence of tokens + * whose concatenated strings match `regex`. Returns the string + * formed by the tokens plus some position information. + */ + + + parseRegexGroup(regex, modeName // Used to describe the mode in error messages. + ) { + var firstToken = this.fetch(); + var lastToken = firstToken; + var str = ""; + var nextToken; + + while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { + lastToken = nextToken; + str += lastToken.text; + this.consume(); + } + + if (str === "") { + throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); + } + + return firstToken.range(lastToken, str); + } + /** + * Parses a color description. + */ + + + parseColorGroup(optional) { + var res = this.parseStringGroup("color", optional); + + if (res == null) { + return null; + } + + var match = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(res.text); + + if (!match) { + throw new ParseError("Invalid color: '" + res.text + "'", res); + } + + var color = match[0]; + + if (/^[0-9a-f]{6}$/i.test(color)) { + // We allow a 6-digit HTML color spec without a leading "#". + // This follows the xcolor package's HTML color model. + // Predefined color names are all missed by this RegEx pattern. + color = "#" + color; + } + + return { + type: "color-token", + mode: this.mode, + color + }; + } + /** + * Parses a size specification, consisting of magnitude and unit. + */ + + + parseSizeGroup(optional) { + var res; + var isBlank = false; // don't expand before parseStringGroup + + this.gullet.consumeSpaces(); + + if (!optional && this.gullet.future().text !== "{") { + res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); + } else { + res = this.parseStringGroup("size", optional); + } + + if (!res) { + return null; + } + + if (!optional && res.text.length === 0) { + // Because we've tested for what is !optional, this block won't + // affect \kern, \hspace, etc. It will capture the mandatory arguments + // to \genfrac and \above. + res.text = "0pt"; // Enable \above{} + + isBlank = true; // This is here specifically for \genfrac + } + + var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); + + if (!match) { + throw new ParseError("Invalid size: '" + res.text + "'", res); + } + + var data = { + number: +(match[1] + match[2]), + // sign + magnitude, cast to number + unit: match[3] + }; + + if (!validUnit(data)) { + throw new ParseError("Invalid unit: '" + data.unit + "'", res); + } + + return { + type: "size", + mode: this.mode, + value: data, + isBlank + }; + } + /** + * Parses an URL, checking escaped letters and allowed protocols, + * and setting the catcode of % as an active character (as in \hyperref). + */ + + + parseUrlGroup(optional) { + this.gullet.lexer.setCatcode("%", 13); // active character + + this.gullet.lexer.setCatcode("~", 12); // other character + + var res = this.parseStringGroup("url", optional); + this.gullet.lexer.setCatcode("%", 14); // comment character + + this.gullet.lexer.setCatcode("~", 13); // active character + + if (res == null) { + return null; + } // hyperref package allows backslashes alone in href, but doesn't + // generate valid links in such cases; we interpret this as + // "undefined" behaviour, and keep them as-is. Some browser will + // replace backslashes with forward slashes. + + + var url = res.text.replace(/\\([#$%&~_^{}])/g, '$1'); + return { + type: "url", + mode: this.mode, + url + }; + } + /** + * Parses an argument with the mode specified. + */ + + + parseArgumentGroup(optional, mode) { + var argToken = this.gullet.scanArgument(optional); + + if (argToken == null) { + return null; + } + + var outerMode = this.mode; + + if (mode) { + // Switch to specified mode + this.switchMode(mode); + } + + this.gullet.beginGroup(); + var expression = this.parseExpression(false, "EOF"); // TODO: find an alternative way to denote the end + + this.expect("EOF"); // expect the end of the argument + + this.gullet.endGroup(); + var result = { + type: "ordgroup", + mode: this.mode, + loc: argToken.loc, + body: expression + }; + + if (mode) { + // Switch mode back + this.switchMode(outerMode); + } + + return result; + } + /** + * Parses an ordinary group, which is either a single nucleus (like "x") + * or an expression in braces (like "{x+y}") or an implicit group, a group + * that starts at the current position, and ends right before a higher explicit + * group ends, or at EOF. + */ + + + parseGroup(name, // For error reporting. + breakOnTokenText) { + var firstToken = this.fetch(); + var text = firstToken.text; + var result; // Try to parse an open brace or \begingroup + + if (text === "{" || text === "\\begingroup") { + this.consume(); + var groupEnd = text === "{" ? "}" : "\\endgroup"; + this.gullet.beginGroup(); // If we get a brace, parse an expression + + var expression = this.parseExpression(false, groupEnd); + var lastToken = this.fetch(); + this.expect(groupEnd); // Check that we got a matching closing brace + + this.gullet.endGroup(); + result = { + type: "ordgroup", + mode: this.mode, + loc: SourceLocation.range(firstToken, lastToken), + body: expression, + // A group formed by \begingroup...\endgroup is a semi-simple group + // which doesn't affect spacing in math mode, i.e., is transparent. + // https://tex.stackexchange.com/questions/1930/when-should-one- + // use-begingroup-instead-of-bgroup + semisimple: text === "\\begingroup" || undefined + }; + } else { + // If there exists a function with this name, parse the function. + // Otherwise, just return a nucleus + result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); + + if (result == null && text[0] === "\\" && !implicitCommands.hasOwnProperty(text)) { + if (this.settings.throwOnError) { + throw new ParseError("Undefined control sequence: " + text, firstToken); + } + + result = this.formatUnsupportedCmd(text); + this.consume(); + } + } + + return result; + } + /** + * Form ligature-like combinations of characters for text mode. + * This includes inputs like "--", "---", "``" and "''". + * The result will simply replace multiple textord nodes with a single + * character in each value by a single textord node having multiple + * characters in its value. The representation is still ASCII source. + * The group will be modified in place. + */ + + + formLigatures(group) { + var n = group.length - 1; + + for (var i = 0; i < n; ++i) { + var a = group[i]; // $FlowFixMe: Not every node type has a `text` property. + + var v = a.text; + + if (v === "-" && group[i + 1].text === "-") { + if (i + 1 < n && group[i + 2].text === "-") { + group.splice(i, 3, { + type: "textord", + mode: "text", + loc: SourceLocation.range(a, group[i + 2]), + text: "---" + }); + n -= 2; + } else { + group.splice(i, 2, { + type: "textord", + mode: "text", + loc: SourceLocation.range(a, group[i + 1]), + text: "--" + }); + n -= 1; + } + } + + if ((v === "'" || v === "`") && group[i + 1].text === v) { + group.splice(i, 2, { + type: "textord", + mode: "text", + loc: SourceLocation.range(a, group[i + 1]), + text: v + v + }); + n -= 1; + } + } + } + /** + * Parse a single symbol out of the string. Here, we handle single character + * symbols and special functions like \verb. + */ + + + parseSymbol() { + var nucleus = this.fetch(); + var text = nucleus.text; + + if (/^\\verb[^a-zA-Z]/.test(text)) { + this.consume(); + var arg = text.slice(5); + var star = arg.charAt(0) === "*"; + + if (star) { + arg = arg.slice(1); + } // Lexer's tokenRegex is constructed to always have matching + // first/last characters. + + + if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { + throw new ParseError("\\verb assertion failed --\n please report what input caused this bug"); + } + + arg = arg.slice(1, -1); // remove first and last char + + return { + type: "verb", + mode: "text", + body: arg, + star + }; + } // At this point, we should have a symbol, possibly with accents. + // First expand any accented base symbol according to unicodeSymbols. + + + if (unicodeSymbols.hasOwnProperty(text[0]) && !symbols[this.mode][text[0]]) { + // This behavior is not strict (XeTeX-compatible) in math mode. + if (this.settings.strict && this.mode === "math") { + this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus); + } + + text = unicodeSymbols[text[0]] + text.slice(1); + } // Strip off any combining characters + + + var match = combiningDiacriticalMarksEndRegex.exec(text); + + if (match) { + text = text.substring(0, match.index); + + if (text === 'i') { + text = '\u0131'; // dotless i, in math and text mode + } else if (text === 'j') { + text = '\u0237'; // dotless j, in math and text mode + } + } // Recognize base symbol + + + var symbol; + + if (symbols[this.mode][text]) { + if (this.settings.strict && this.mode === 'math' && extraLatin.indexOf(text) >= 0) { + this.settings.reportNonstrict("unicodeTextInMathMode", "Latin-1/Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus); + } + + var group = symbols[this.mode][text].group; + var loc = SourceLocation.range(nucleus); + var s; + + if (ATOMS.hasOwnProperty(group)) { + // $FlowFixMe + var family = group; + s = { + type: "atom", + mode: this.mode, + family, + loc, + text + }; + } else { + // $FlowFixMe + s = { + type: group, + mode: this.mode, + loc, + text + }; + } // $FlowFixMe + + + symbol = s; + } else if (text.charCodeAt(0) >= 0x80) { + // no symbol for e.g. ^ + if (this.settings.strict) { + if (!supportedCodepoint(text.charCodeAt(0))) { + this.settings.reportNonstrict("unknownSymbol", "Unrecognized Unicode character \"" + text[0] + "\"" + (" (" + text.charCodeAt(0) + ")"), nucleus); + } else if (this.mode === "math") { + this.settings.reportNonstrict("unicodeTextInMathMode", "Unicode text character \"" + text[0] + "\" used in math mode", nucleus); + } + } // All nonmathematical Unicode characters are rendered as if they + // are in text mode (wrapped in \text) because that's what it + // takes to render them in LaTeX. Setting `mode: this.mode` is + // another natural choice (the user requested math mode), but + // this makes it more difficult for getCharacterMetrics() to + // distinguish Unicode characters without metrics and those for + // which we want to simulate the letter M. + + + symbol = { + type: "textord", + mode: "text", + loc: SourceLocation.range(nucleus), + text + }; + } else { + return null; // EOF, ^, _, {, }, etc. + } + + this.consume(); // Transform combining characters into accents + + if (match) { + for (var i = 0; i < match[0].length; i++) { + var accent = match[0][i]; + + if (!unicodeAccents[accent]) { + throw new ParseError("Unknown accent ' " + accent + "'", nucleus); + } + + var command = unicodeAccents[accent][this.mode] || unicodeAccents[accent].text; + + if (!command) { + throw new ParseError("Accent " + accent + " unsupported in " + this.mode + " mode", nucleus); + } + + symbol = { + type: "accent", + mode: this.mode, + loc: SourceLocation.range(nucleus), + label: command, + isStretchy: false, + isShifty: true, + // $FlowFixMe + base: symbol + }; + } + } // $FlowFixMe + + + return symbol; + } + +} +Parser.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"]; + +/** + * Provides a single function for parsing an expression using a Parser + * TODO(emily): Remove this + */ + +/** + * Parses an expression using a Parser, then returns the parsed result. + */ +var parseTree = function parseTree(toParse, settings) { + if (!(typeof toParse === 'string' || toParse instanceof String)) { + throw new TypeError('KaTeX can only parse string typed expression'); + } + + var parser = new Parser(toParse, settings); // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors + + delete parser.gullet.macros.current["\\df@tag"]; + var tree = parser.parse(); // Prevent a color definition from persisting between calls to katex.render(). + + delete parser.gullet.macros.current["\\current@color"]; + delete parser.gullet.macros.current["\\color"]; // If the input used \tag, it will set the \df@tag macro to the tag. + // In this case, we separately parse the tag and wrap the tree. + + if (parser.gullet.macros.get("\\df@tag")) { + if (!settings.displayMode) { + throw new ParseError("\\tag works only in display equations"); + } + + tree = [{ + type: "tag", + mode: "text", + body: tree, + tag: parser.subparse([new Token("\\df@tag")]) + }]; + } + + return tree; +}; + +/* eslint no-console:0 */ + +/** + * Parse and build an expression, and place that expression in the DOM node + * given. + */ +var render = function render(expression, baseNode, options) { + baseNode.textContent = ""; + var node = renderToDomTree(expression, options).toNode(); + baseNode.appendChild(node); +}; // KaTeX's styles don't work properly in quirks mode. Print out an error, and +// disable rendering. + + +if (typeof document !== "undefined") { + if (document.compatMode !== "CSS1Compat") { + typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype."); + + render = function render() { + throw new ParseError("KaTeX doesn't work in quirks mode."); + }; + } +} +/** + * Parse and build an expression, and return the markup for that. + */ + + +var renderToString = function renderToString(expression, options) { + var markup = renderToDomTree(expression, options).toMarkup(); + return markup; +}; +/** + * Parse an expression and return the parse tree. + */ + + +var generateParseTree = function generateParseTree(expression, options) { + var settings = new Settings(options); + return parseTree(expression, settings); +}; +/** + * If the given error is a KaTeX ParseError and options.throwOnError is false, + * renders the invalid LaTeX as a span with hover title giving the KaTeX + * error message. Otherwise, simply throws the error. + */ + + +var renderError = function renderError(error, expression, options) { + if (options.throwOnError || !(error instanceof ParseError)) { + throw error; + } + + var node = buildCommon.makeSpan(["katex-error"], [new SymbolNode(expression)]); + node.setAttribute("title", error.toString()); + node.setAttribute("style", "color:" + options.errorColor); + return node; +}; +/** + * Generates and returns the katex build tree. This is used for advanced + * use cases (like rendering to custom output). + */ + + +var renderToDomTree = function renderToDomTree(expression, options) { + var settings = new Settings(options); + + try { + var tree = parseTree(expression, settings); + return buildTree(tree, expression, settings); + } catch (error) { + return renderError(error, expression, settings); + } +}; +/** + * Generates and returns the katex build tree, with just HTML (no MathML). + * This is used for advanced use cases (like rendering to custom output). + */ + + +var renderToHTMLTree = function renderToHTMLTree(expression, options) { + var settings = new Settings(options); + + try { + var tree = parseTree(expression, settings); + return buildHTMLTree(tree, expression, settings); + } catch (error) { + return renderError(error, expression, settings); + } +}; + +var version = "0.16.22"; +var __domTree = { + Span, + Anchor, + SymbolNode, + SvgNode, + PathNode, + LineNode +}; // ESM exports + +var katex = { + /** + * Current KaTeX version + */ + version, + + /** + * Renders the given LaTeX into an HTML+MathML combination, and adds + * it as a child to the specified DOM node. + */ + render, + + /** + * Renders the given LaTeX into an HTML+MathML combination string, + * for sending to the client. + */ + renderToString, + + /** + * KaTeX error, usually during parsing. + */ + ParseError, + + /** + * The schema of Settings + */ + SETTINGS_SCHEMA, + + /** + * Parses the given LaTeX into KaTeX's internal parse tree structure, + * without rendering to HTML or MathML. + * + * NOTE: This method is not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __parse: generateParseTree, + + /** + * Renders the given LaTeX into an HTML+MathML internal DOM tree + * representation, without flattening that representation to a string. + * + * NOTE: This method is not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __renderToDomTree: renderToDomTree, + + /** + * Renders the given LaTeX into an HTML internal DOM tree representation, + * without MathML and without flattening that representation to a string. + * + * NOTE: This method is not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __renderToHTMLTree: renderToHTMLTree, + + /** + * extends internal font metrics object with a new object + * each key in the new object represents a font name + */ + __setFontMetrics: setFontMetrics, + + /** + * adds a new symbol to builtin symbols table + */ + __defineSymbol: defineSymbol, + + /** + * adds a new function to builtin function list, + * which directly produce parse tree elements + * and have their own html/mathml builders + */ + __defineFunction: defineFunction, + + /** + * adds a new macro to builtin macro list + */ + __defineMacro: defineMacro, + + /** + * Expose the dom tree node types, which can be useful for type checking nodes. + * + * NOTE: These methods are not currently recommended for public use. + * The internal tree representation is unstable and is very likely + * to change. Use at your own risk. + */ + __domTree +}; + +export { ParseError, SETTINGS_SCHEMA, defineFunction as __defineFunction, defineMacro as __defineMacro, defineSymbol as __defineSymbol, __domTree, generateParseTree as __parse, renderToDomTree as __renderToDomTree, renderToHTMLTree as __renderToHTMLTree, setFontMetrics as __setFontMetrics, katex as default, render, renderToString, version }; diff --git a/uni_modules/tmx-ui/components/x-markdown/katex.min.css b/uni_modules/tmx-ui/components/x-markdown/katex.min.css new file mode 100644 index 0000000..ae7d00c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/katex.min.css @@ -0,0 +1,1316 @@ +@font-face { + font-family: KaTeX_AMS; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_AMS-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Caligraphic; + font-style: normal; + font-weight: 700; + src: url(https://cdn.tmui.design/fonts/KaTeX_Caligraphic-Bold.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Caligraphic; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Caligraphic-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Fraktur; + font-style: normal; + font-weight: 700; + src: url(https://cdn.tmui.design/fonts/KaTeX_Fraktur-Bold.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Fraktur; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Fraktur-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Main; + font-style: normal; + font-weight: 700; + src: url(https://cdn.tmui.design/fonts/KaTeX_Main-Bold.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Main; + font-style: italic; + font-weight: 700; + src: url(https://cdn.tmui.design/fonts/KaTeX_Main-BoldItalic.woff) format("woff") +} +@font-face { + font-family: KaTeX_Main; + font-style: italic; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Main-Italic.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Main; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Main-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Math; + font-style: italic; + font-weight: 700; + src: url(https://cdn.tmui.design/fonts/KaTeX_Math-BoldItalic.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Math; + font-style: italic; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Math-Italic.woff) format("woff") +} + +@font-face { + font-family: "KaTeX_SansSerif"; + font-style: normal; + font-weight: 700; + src: url(https://cdn.tmui.design/fonts/KaTeX_SansSerif-Bold.woff) format("woff") +} + +@font-face { + font-family: "KaTeX_SansSerif"; + font-style: italic; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_SansSerif-Italic.woff) format("woff") +} + +@font-face { + font-family: "KaTeX_SansSerif"; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_SansSerif-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Script; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Script-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Size1; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Size1-Regular.woff) format("woff") + +} + +@font-face { + font-family: KaTeX_Size2; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Size2-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Size3; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Size3-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Size4; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Size4-Regular.woff) format("woff") +} + +@font-face { + font-family: KaTeX_Typewriter; + font-style: normal; + font-weight: 400; + src: url(https://cdn.tmui.design/fonts/KaTeX_Typewriter-Regular.woff) format("woff") +} + +.katex { + counter-reset: katexEqnNo mmlEqnNo; + font: 1.21em KaTeX_Main, Times New Roman, serif; + line-height: 1.2; + text-indent: 0; + text-rendering: auto +} + +.katex view, +.katex text { + -ms-high-contrast-adjust: none !important; + border-color: currentColor +} + +.katex .katex-version:after { + content: "" +} + +.katex .katex-mathml { + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + padding: 0; + border: 0; + height: 1px; + width: 1px; + overflow: hidden +} + +.katex .katex-html>.newline { + display: block +} + +.katex .base { + position: relative; + display: inline-block; + white-space: nowrap; + width: min-content +} + +.katex .strut { + display: inline-block +} + +.katex .textbf { + font-weight: 700 +} + +.katex .textit { + font-style: italic +} + +.katex .textrm { + font-family: KaTeX_Main +} + +.katex .textsf { + font-family: KaTeX_SansSerif +} + +.katex .texttt { + font-family: KaTeX_Typewriter +} + +.katex .mathnormal { + font-family: KaTeX_Math; + font-style: italic +} + +.katex .mathit { + font-family: KaTeX_Main; + font-style: italic +} + +.katex .mathrm { + font-style: normal +} + +.katex .mathbf { + font-family: KaTeX_Main; + font-weight: 700 +} + +.katex .boldsymbol { + font-family: KaTeX_Math; + font-weight: 700; + font-style: italic +} + +.katex .amsrm, +.katex .mathbb, +.katex .textbb { + font-family: KaTeX_AMS +} + +.katex .mathcal { + font-family: KaTeX_Caligraphic +} + +.katex .mathfrak, +.katex .textfrak { + font-family: KaTeX_Fraktur +} + +.katex .mathboldfrak, +.katex .textboldfrak { + font-family: KaTeX_Fraktur; + font-weight: 700 +} + +.katex .mathtt { + font-family: KaTeX_Typewriter +} + +.katex .mathscr, +.katex .textscr { + font-family: KaTeX_Script +} + +.katex .mathsf, +.katex .textsf { + font-family: KaTeX_SansSerif +} + +.katex .mathboldsf, +.katex .textboldsf { + font-family: KaTeX_SansSerif; + font-weight: 700 +} + +.katex .mathsfit, +.katex .mathitsf, +.katex .textitsf { + font-family: KaTeX_SansSerif; + font-style: italic +} + +.katex .mainrm { + font-family: KaTeX_Main; + font-style: normal +} + +.katex .vlist-t { + display: inline-table; + table-layout: fixed; + border-collapse: collapse +} + +.katex .vlist-r { + display: table-row +} + +.katex .vlist { + display: table-cell; + vertical-align: bottom; + position: relative +} + +.katex .vlist>.katex-span { + display: block; + height: 0; + position: relative +} + +.katex .vlist>.katex-span>.katex-span { + display: inline-block +} + +.katex .vlist>.katex-span>.pstrut { + overflow: hidden; + width: 0 +} + +.katex .vlist-t2 { + margin-right: -2px +} + +.katex .vlist-s { + display: table-cell; + vertical-align: bottom; + font-size: 1px; + width: 2px; + min-width: 2px +} + +.katex .vbox { + display: inline-flex; + flex-direction: column; + align-items: baseline +} + +.katex .hbox { + display: inline-flex; + flex-direction: row; + width: 100% +} + +.katex .thinbox { + display: inline-flex; + flex-direction: row; + width: 0; + max-width: 0 +} + +.katex .msupsub { + text-align: left +} + +.katex .mfrac>.katex-span>.katex-span { + text-align: center +} + +.katex .mfrac .frac-line { + display: inline-block; + width: 100%; + border-bottom-style: solid +} + +.katex .mfrac .frac-line, +.katex .overline .overline-line, +.katex .underline .underline-line, +.katex .hline, +.katex .hdashline, +.katex .rule { + min-height: 1px +} + +.katex .mspace { + display: inline-block +} + +.katex .llap, +.katex .rlap, +.katex .clap { + width: 0; + position: relative +} + +.katex .llap>.inner, +.katex .rlap>.inner, +.katex .clap>.inner { + position: absolute +} + +.katex .llap>.fix, +.katex .rlap>.fix, +.katex .clap>.fix { + display: inline-block +} + +.katex .llap>.inner { + right: 0 +} + +.katex .rlap>.inner, +.katex .clap>.inner { + left: 0 +} + +.katex .clap>.inner>.katex-span { + margin-left: -50%; + margin-right: 50% +} + +.katex .rule { + display: inline-block; + border: solid 0; + position: relative +} + +.katex .overline .overline-line, +.katex .underline .underline-line, +.katex .hline { + display: inline-block; + width: 100%; + border-bottom-style: solid +} + +.katex .hdashline { + display: inline-block; + width: 100%; + border-bottom-style: dashed +} + +.katex .sqrt>.root { + margin-left: .2777777778em; + margin-right: -.5555555556em +} + +.katex .sizing.reset-size1.size1, +.katex .fontsize-ensurer.reset-size1.size1 { + font-size: 1em +} + +.katex .sizing.reset-size1.size2, +.katex .fontsize-ensurer.reset-size1.size2 { + font-size: 1.2em +} + +.katex .sizing.reset-size1.size3, +.katex .fontsize-ensurer.reset-size1.size3 { + font-size: 1.4em +} + +.katex .sizing.reset-size1.size4, +.katex .fontsize-ensurer.reset-size1.size4 { + font-size: 1.6em +} + +.katex .sizing.reset-size1.size5, +.katex .fontsize-ensurer.reset-size1.size5 { + font-size: 1.8em +} + +.katex .sizing.reset-size1.size6, +.katex .fontsize-ensurer.reset-size1.size6 { + font-size: 2em +} + +.katex .sizing.reset-size1.size7, +.katex .fontsize-ensurer.reset-size1.size7 { + font-size: 2.4em +} + +.katex .sizing.reset-size1.size8, +.katex .fontsize-ensurer.reset-size1.size8 { + font-size: 2.88em +} + +.katex .sizing.reset-size1.size9, +.katex .fontsize-ensurer.reset-size1.size9 { + font-size: 3.456em +} + +.katex .sizing.reset-size1.size10, +.katex .fontsize-ensurer.reset-size1.size10 { + font-size: 4.148em +} + +.katex .sizing.reset-size1.size11, +.katex .fontsize-ensurer.reset-size1.size11 { + font-size: 4.976em +} + +.katex .sizing.reset-size2.size1, +.katex .fontsize-ensurer.reset-size2.size1 { + font-size: .8333333333em +} + +.katex .sizing.reset-size2.size2, +.katex .fontsize-ensurer.reset-size2.size2 { + font-size: 1em +} + +.katex .sizing.reset-size2.size3, +.katex .fontsize-ensurer.reset-size2.size3 { + font-size: 1.1666666667em +} + +.katex .sizing.reset-size2.size4, +.katex .fontsize-ensurer.reset-size2.size4 { + font-size: 1.3333333333em +} + +.katex .sizing.reset-size2.size5, +.katex .fontsize-ensurer.reset-size2.size5 { + font-size: 1.5em +} + +.katex .sizing.reset-size2.size6, +.katex .fontsize-ensurer.reset-size2.size6 { + font-size: 1.6666666667em +} + +.katex .sizing.reset-size2.size7, +.katex .fontsize-ensurer.reset-size2.size7 { + font-size: 2em +} + +.katex .sizing.reset-size2.size8, +.katex .fontsize-ensurer.reset-size2.size8 { + font-size: 2.4em +} + +.katex .sizing.reset-size2.size9, +.katex .fontsize-ensurer.reset-size2.size9 { + font-size: 2.88em +} + +.katex .sizing.reset-size2.size10, +.katex .fontsize-ensurer.reset-size2.size10 { + font-size: 3.4566666667em +} + +.katex .sizing.reset-size2.size11, +.katex .fontsize-ensurer.reset-size2.size11 { + font-size: 4.1466666667em +} + +.katex .sizing.reset-size3.size1, +.katex .fontsize-ensurer.reset-size3.size1 { + font-size: .7142857143em +} + +.katex .sizing.reset-size3.size2, +.katex .fontsize-ensurer.reset-size3.size2 { + font-size: .8571428571em +} + +.katex .sizing.reset-size3.size3, +.katex .fontsize-ensurer.reset-size3.size3 { + font-size: 1em +} + +.katex .sizing.reset-size3.size4, +.katex .fontsize-ensurer.reset-size3.size4 { + font-size: 1.1428571429em +} + +.katex .sizing.reset-size3.size5, +.katex .fontsize-ensurer.reset-size3.size5 { + font-size: 1.2857142857em +} + +.katex .sizing.reset-size3.size6, +.katex .fontsize-ensurer.reset-size3.size6 { + font-size: 1.4285714286em +} + +.katex .sizing.reset-size3.size7, +.katex .fontsize-ensurer.reset-size3.size7 { + font-size: 1.7142857143em +} + +.katex .sizing.reset-size3.size8, +.katex .fontsize-ensurer.reset-size3.size8 { + font-size: 2.0571428571em +} + +.katex .sizing.reset-size3.size9, +.katex .fontsize-ensurer.reset-size3.size9 { + font-size: 2.4685714286em +} + +.katex .sizing.reset-size3.size10, +.katex .fontsize-ensurer.reset-size3.size10 { + font-size: 2.9628571429em +} + +.katex .sizing.reset-size3.size11, +.katex .fontsize-ensurer.reset-size3.size11 { + font-size: 3.5542857143em +} + +.katex .sizing.reset-size4.size1, +.katex .fontsize-ensurer.reset-size4.size1 { + font-size: .625em +} + +.katex .sizing.reset-size4.size2, +.katex .fontsize-ensurer.reset-size4.size2 { + font-size: .75em +} + +.katex .sizing.reset-size4.size3, +.katex .fontsize-ensurer.reset-size4.size3 { + font-size: .875em +} + +.katex .sizing.reset-size4.size4, +.katex .fontsize-ensurer.reset-size4.size4 { + font-size: 1em +} + +.katex .sizing.reset-size4.size5, +.katex .fontsize-ensurer.reset-size4.size5 { + font-size: 1.125em +} + +.katex .sizing.reset-size4.size6, +.katex .fontsize-ensurer.reset-size4.size6 { + font-size: 1.25em +} + +.katex .sizing.reset-size4.size7, +.katex .fontsize-ensurer.reset-size4.size7 { + font-size: 1.5em +} + +.katex .sizing.reset-size4.size8, +.katex .fontsize-ensurer.reset-size4.size8 { + font-size: 1.8em +} + +.katex .sizing.reset-size4.size9, +.katex .fontsize-ensurer.reset-size4.size9 { + font-size: 2.16em +} + +.katex .sizing.reset-size4.size10, +.katex .fontsize-ensurer.reset-size4.size10 { + font-size: 2.5925em +} + +.katex .sizing.reset-size4.size11, +.katex .fontsize-ensurer.reset-size4.size11 { + font-size: 3.11em +} + +.katex .sizing.reset-size5.size1, +.katex .fontsize-ensurer.reset-size5.size1 { + font-size: .5555555556em +} + +.katex .sizing.reset-size5.size2, +.katex .fontsize-ensurer.reset-size5.size2 { + font-size: .6666666667em +} + +.katex .sizing.reset-size5.size3, +.katex .fontsize-ensurer.reset-size5.size3 { + font-size: .7777777778em +} + +.katex .sizing.reset-size5.size4, +.katex .fontsize-ensurer.reset-size5.size4 { + font-size: .8888888889em +} + +.katex .sizing.reset-size5.size5, +.katex .fontsize-ensurer.reset-size5.size5 { + font-size: 1em +} + +.katex .sizing.reset-size5.size6, +.katex .fontsize-ensurer.reset-size5.size6 { + font-size: 1.1111111111em +} + +.katex .sizing.reset-size5.size7, +.katex .fontsize-ensurer.reset-size5.size7 { + font-size: 1.3333333333em +} + +.katex .sizing.reset-size5.size8, +.katex .fontsize-ensurer.reset-size5.size8 { + font-size: 1.6em +} + +.katex .sizing.reset-size5.size9, +.katex .fontsize-ensurer.reset-size5.size9 { + font-size: 1.92em +} + +.katex .sizing.reset-size5.size10, +.katex .fontsize-ensurer.reset-size5.size10 { + font-size: 2.3044444444em +} + +.katex .sizing.reset-size5.size11, +.katex .fontsize-ensurer.reset-size5.size11 { + font-size: 2.7644444444em +} + +.katex .sizing.reset-size6.size1, +.katex .fontsize-ensurer.reset-size6.size1 { + font-size: .5em +} + +.katex .sizing.reset-size6.size2, +.katex .fontsize-ensurer.reset-size6.size2 { + font-size: .6em +} + +.katex .sizing.reset-size6.size3, +.katex .fontsize-ensurer.reset-size6.size3 { + font-size: .7em +} + +.katex .sizing.reset-size6.size4, +.katex .fontsize-ensurer.reset-size6.size4 { + font-size: .8em +} + +.katex .sizing.reset-size6.size5, +.katex .fontsize-ensurer.reset-size6.size5 { + font-size: .9em +} + +.katex .sizing.reset-size6.size6, +.katex .fontsize-ensurer.reset-size6.size6 { + font-size: 1em +} + +.katex .sizing.reset-size6.size7, +.katex .fontsize-ensurer.reset-size6.size7 { + font-size: 1.2em +} + +.katex .sizing.reset-size6.size8, +.katex .fontsize-ensurer.reset-size6.size8 { + font-size: 1.44em +} + +.katex .sizing.reset-size6.size9, +.katex .fontsize-ensurer.reset-size6.size9 { + font-size: 1.728em +} + +.katex .sizing.reset-size6.size10, +.katex .fontsize-ensurer.reset-size6.size10 { + font-size: 2.074em +} + +.katex .sizing.reset-size6.size11, +.katex .fontsize-ensurer.reset-size6.size11 { + font-size: 2.488em +} + +.katex .sizing.reset-size7.size1, +.katex .fontsize-ensurer.reset-size7.size1 { + font-size: .4166666667em +} + +.katex .sizing.reset-size7.size2, +.katex .fontsize-ensurer.reset-size7.size2 { + font-size: .5em +} + +.katex .sizing.reset-size7.size3, +.katex .fontsize-ensurer.reset-size7.size3 { + font-size: .5833333333em +} + +.katex .sizing.reset-size7.size4, +.katex .fontsize-ensurer.reset-size7.size4 { + font-size: .6666666667em +} + +.katex .sizing.reset-size7.size5, +.katex .fontsize-ensurer.reset-size7.size5 { + font-size: .75em +} + +.katex .sizing.reset-size7.size6, +.katex .fontsize-ensurer.reset-size7.size6 { + font-size: .8333333333em +} + +.katex .sizing.reset-size7.size7, +.katex .fontsize-ensurer.reset-size7.size7 { + font-size: 1em +} + +.katex .sizing.reset-size7.size8, +.katex .fontsize-ensurer.reset-size7.size8 { + font-size: 1.2em +} + +.katex .sizing.reset-size7.size9, +.katex .fontsize-ensurer.reset-size7.size9 { + font-size: 1.44em +} + +.katex .sizing.reset-size7.size10, +.katex .fontsize-ensurer.reset-size7.size10 { + font-size: 1.7283333333em +} + +.katex .sizing.reset-size7.size11, +.katex .fontsize-ensurer.reset-size7.size11 { + font-size: 2.0733333333em +} + +.katex .sizing.reset-size8.size1, +.katex .fontsize-ensurer.reset-size8.size1 { + font-size: .3472222222em +} + +.katex .sizing.reset-size8.size2, +.katex .fontsize-ensurer.reset-size8.size2 { + font-size: .4166666667em +} + +.katex .sizing.reset-size8.size3, +.katex .fontsize-ensurer.reset-size8.size3 { + font-size: .4861111111em +} + +.katex .sizing.reset-size8.size4, +.katex .fontsize-ensurer.reset-size8.size4 { + font-size: .5555555556em +} + +.katex .sizing.reset-size8.size5, +.katex .fontsize-ensurer.reset-size8.size5 { + font-size: .625em +} + +.katex .sizing.reset-size8.size6, +.katex .fontsize-ensurer.reset-size8.size6 { + font-size: .6944444444em +} + +.katex .sizing.reset-size8.size7, +.katex .fontsize-ensurer.reset-size8.size7 { + font-size: .8333333333em +} + +.katex .sizing.reset-size8.size8, +.katex .fontsize-ensurer.reset-size8.size8 { + font-size: 1em +} + +.katex .sizing.reset-size8.size9, +.katex .fontsize-ensurer.reset-size8.size9 { + font-size: 1.2em +} + +.katex .sizing.reset-size8.size10, +.katex .fontsize-ensurer.reset-size8.size10 { + font-size: 1.4402777778em +} + +.katex .sizing.reset-size8.size11, +.katex .fontsize-ensurer.reset-size8.size11 { + font-size: 1.7277777778em +} + +.katex .sizing.reset-size9.size1, +.katex .fontsize-ensurer.reset-size9.size1 { + font-size: .2893518519em +} + +.katex .sizing.reset-size9.size2, +.katex .fontsize-ensurer.reset-size9.size2 { + font-size: .3472222222em +} + +.katex .sizing.reset-size9.size3, +.katex .fontsize-ensurer.reset-size9.size3 { + font-size: .4050925926em +} + +.katex .sizing.reset-size9.size4, +.katex .fontsize-ensurer.reset-size9.size4 { + font-size: .462962963em +} + +.katex .sizing.reset-size9.size5, +.katex .fontsize-ensurer.reset-size9.size5 { + font-size: .5208333333em +} + +.katex .sizing.reset-size9.size6, +.katex .fontsize-ensurer.reset-size9.size6 { + font-size: .5787037037em +} + +.katex .sizing.reset-size9.size7, +.katex .fontsize-ensurer.reset-size9.size7 { + font-size: .6944444444em +} + +.katex .sizing.reset-size9.size8, +.katex .fontsize-ensurer.reset-size9.size8 { + font-size: .8333333333em +} + +.katex .sizing.reset-size9.size9, +.katex .fontsize-ensurer.reset-size9.size9 { + font-size: 1em +} + +.katex .sizing.reset-size9.size10, +.katex .fontsize-ensurer.reset-size9.size10 { + font-size: 1.2002314815em +} + +.katex .sizing.reset-size9.size11, +.katex .fontsize-ensurer.reset-size9.size11 { + font-size: 1.4398148148em +} + +.katex .sizing.reset-size10.size1, +.katex .fontsize-ensurer.reset-size10.size1 { + font-size: .2410800386em +} + +.katex .sizing.reset-size10.size2, +.katex .fontsize-ensurer.reset-size10.size2 { + font-size: .2892960463em +} + +.katex .sizing.reset-size10.size3, +.katex .fontsize-ensurer.reset-size10.size3 { + font-size: .337512054em +} + +.katex .sizing.reset-size10.size4, +.katex .fontsize-ensurer.reset-size10.size4 { + font-size: .3857280617em +} + +.katex .sizing.reset-size10.size5, +.katex .fontsize-ensurer.reset-size10.size5 { + font-size: .4339440694em +} + +.katex .sizing.reset-size10.size6, +.katex .fontsize-ensurer.reset-size10.size6 { + font-size: .4821600771em +} + +.katex .sizing.reset-size10.size7, +.katex .fontsize-ensurer.reset-size10.size7 { + font-size: .5785920926em +} + +.katex .sizing.reset-size10.size8, +.katex .fontsize-ensurer.reset-size10.size8 { + font-size: .6943105111em +} + +.katex .sizing.reset-size10.size9, +.katex .fontsize-ensurer.reset-size10.size9 { + font-size: .8331726133em +} + +.katex .sizing.reset-size10.size10, +.katex .fontsize-ensurer.reset-size10.size10 { + font-size: 1em +} + +.katex .sizing.reset-size10.size11, +.katex .fontsize-ensurer.reset-size10.size11 { + font-size: 1.1996142719em +} + +.katex .sizing.reset-size11.size1, +.katex .fontsize-ensurer.reset-size11.size1 { + font-size: .2009646302em +} + +.katex .sizing.reset-size11.size2, +.katex .fontsize-ensurer.reset-size11.size2 { + font-size: .2411575563em +} + +.katex .sizing.reset-size11.size3, +.katex .fontsize-ensurer.reset-size11.size3 { + font-size: .2813504823em +} + +.katex .sizing.reset-size11.size4, +.katex .fontsize-ensurer.reset-size11.size4 { + font-size: .3215434084em +} + +.katex .sizing.reset-size11.size5, +.katex .fontsize-ensurer.reset-size11.size5 { + font-size: .3617363344em +} + +.katex .sizing.reset-size11.size6, +.katex .fontsize-ensurer.reset-size11.size6 { + font-size: .4019292605em +} + +.katex .sizing.reset-size11.size7, +.katex .fontsize-ensurer.reset-size11.size7 { + font-size: .4823151125em +} + +.katex .sizing.reset-size11.size8, +.katex .fontsize-ensurer.reset-size11.size8 { + font-size: .578778135em +} + +.katex .sizing.reset-size11.size9, +.katex .fontsize-ensurer.reset-size11.size9 { + font-size: .6945337621em +} + +.katex .sizing.reset-size11.size10, +.katex .fontsize-ensurer.reset-size11.size10 { + font-size: .8336012862em +} + +.katex .sizing.reset-size11.size11, +.katex .fontsize-ensurer.reset-size11.size11 { + font-size: 1em +} + +.katex .delimsizing.size1 { + font-family: KaTeX_Size1 +} + +.katex .delimsizing.size2 { + font-family: KaTeX_Size2 +} + +.katex .delimsizing.size3 { + font-family: KaTeX_Size3 +} + +.katex .delimsizing.size4 { + font-family: KaTeX_Size4 +} + +.katex .delimsizing.mult .delim-size1>.katex-span { + font-family: KaTeX_Size1 +} + +.katex .delimsizing.mult .delim-size4>.katex-span { + font-family: KaTeX_Size4 +} + +.katex .nulldelimiter { + display: inline-block; + width: .12em +} + +.katex .delimcenter, +.katex .op-symbol { + position: relative +} + +.katex .op-symbol.small-op { + font-family: KaTeX_Size1 +} + +.katex .op-symbol.large-op { + font-family: KaTeX_Size2 +} + +.katex .op-limits>.vlist-t { + text-align: center +} + +.katex .accent>.vlist-t { + text-align: center +} + +.katex .accent .accent-body { + position: relative +} + +.katex .accent .accent-body:not(.accent-full) { + width: 0 +} + +.katex .overlay { + display: block +} + +.katex .mtable .vertical-separator { + display: inline-block; + min-width: 1px +} + +.katex .mtable .arraycolsep { + display: inline-block +} + +.katex .mtable .col-align-c>.vlist-t { + text-align: center +} + +.katex .mtable .col-align-l>.vlist-t { + text-align: left +} + +.katex .mtable .col-align-r>.vlist-t { + text-align: right +} + +.katex .svg-align { + text-align: left +} + +.katex .katex-svg { + display: block; + position: absolute; + width: 100%; + height: inherit; + fill: currentColor; + stroke: currentColor; + fill-rule: nonzero; + fill-opacity: 1; + stroke-width: 1; + stroke-linecap: butt; + stroke-linejoin: miter; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-dashoffset: 0; + stroke-opacity: 1 +} + +.katex .katex-svg path { + stroke: none +} + +.katex .katex-img { + border-style: none; + min-width: 0; + min-height: 0; + max-width: none; + max-height: none +} + +.katex .stretchy { + width: 100%; + display: block; + position: relative; + overflow: hidden +} + +.katex .stretchy:before, +.katex .stretchy:after { + content: "" +} + +.katex .hide-tail { + width: 100%; + position: relative; + overflow: hidden +} + +.katex .halfarrow-left { + position: absolute; + left: 0; + width: 50.2%; + overflow: hidden +} + +.katex .halfarrow-right { + position: absolute; + right: 0; + width: 50.2%; + overflow: hidden +} + +.katex .brace-left { + position: absolute; + left: 0; + width: 25.1%; + overflow: hidden +} + +.katex .brace-center { + position: absolute; + left: 25%; + width: 50%; + overflow: hidden +} + +.katex .brace-right { + position: absolute; + right: 0; + width: 25.1%; + overflow: hidden +} + +.katex .x-arrow-pad { + padding: 0 .5em +} + +.katex .cd-arrow-pad { + padding: 0 .55556em 0 .27778em +} + +.katex .x-arrow, +.katex .mover, +.katex .munder { + text-align: center +} + +.katex .boxpad { + padding: 0 .3em +} + +.katex .fbox, +.katex .fcolorbox { + box-sizing: border-box; + border: .04em solid +} + +.katex .cancel-pad { + padding: 0 .2em +} + +.katex .cancel-lap { + margin-left: -.2em; + margin-right: -.2em +} + +.katex .sout { + border-bottom-style: solid; + border-bottom-width: .08em +} + +.katex .angl { + box-sizing: border-box; + border-top: .049em solid; + border-right: .049em solid; + margin-right: .03889em +} + +.katex .anglpad { + padding: 0 .03889em +} + +.katex .eqn-num:before { + counter-increment: katexEqnNo; + content: "(" counter(katexEqnNo) ")" +} + +.katex .mml-eqn-num:before { + counter-increment: mmlEqnNo; + content: "(" counter(mmlEqnNo) ")" +} + +.katex .mtr-glue { + width: 50% +} + +.katex .cd-vert-arrow { + display: inline-block; + position: relative +} + +.katex .cd-label-left { + display: inline-block; + position: absolute; + right: calc(50% + .3em); + text-align: left +} + +.katex .cd-label-right { + display: inline-block; + position: absolute; + left: calc(50% + .3em); + text-align: right +} + +.katex-display { + display: block; + margin: 1em 0; + text-align: center +} + +.katex-display>.katex { + display: block; + text-align: center; + white-space: nowrap +} + +.katex-display>.katex>.katex-html { + display: block; + position: relative +} + +.katex-display>.katex>.katex-html>.tag { + position: absolute; + right: 0 +} + +.katex-display.leqno>.katex>.katex-html>.tag { + left: 0; + right: auto +} + +.katex-display.fleqn>.katex { + text-align: left; + padding-left: 2em +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-markdown/marked-highlight.js b/uni_modules/tmx-ui/components/x-markdown/marked-highlight.js new file mode 100644 index 0000000..9939a07 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/marked-highlight.js @@ -0,0 +1,103 @@ + + export function markedHighlight(options) { + if (typeof options === 'function') { + options = { + highlight: options, + }; + } + + if (!options || typeof options.highlight !== 'function') { + throw new Error('Must provide highlight function'); + } + + if (typeof options.langPrefix !== 'string') { + options.langPrefix = 'language-'; + } + + if (typeof options.emptyLangClass !== 'string') { + options.emptyLangClass = ''; + } + + return { + async: !!options.async, + walkTokens(token) { + if (token.type !== 'code') { + return; + } + + const lang = getLang(token.lang); + + if (options.async) { + return Promise.resolve(options.highlight(token.text, lang, token.lang || '')).then( + updateToken(token)); + } + + const code = options.highlight(token.text, lang, token.lang || ''); + if (code instanceof Promise) { + throw new Error( + 'markedHighlight is not set to async but the highlight function is async. Set the async option to true on markedHighlight to await the async highlight function.' + ); + } + updateToken(token)(code); + }, + useNewRenderer: true, + renderer: { + code(code, infoString, escaped) { + // istanbul ignore next + if (typeof code === 'object') { + escaped = code.escaped; + infoString = code.lang; + code = code.text; + } + const lang = getLang(infoString); + const classValue = lang ? options.langPrefix + escape(lang) : options.emptyLangClass; + const classAttr = classValue ? + ` class="${classValue}"` : + ''; + code = code.replace(/\n$/, ''); + return `
    ${escaped ? code : escape(code, true)}\n
    `; + }, + }, + }; + } + + function getLang(lang) { + return (lang || '').match(/\S*/)[0]; + } + + function updateToken(token) { + return (code) => { + if (typeof code === 'string' && code !== token.text) { + token.escaped = true; + token.text = code; + } + }; + } + + // copied from marked helpers + const escapeTest = /[&<>"']/; + const escapeReplace = new RegExp(escapeTest.source, 'g'); + const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/; + const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, 'g'); + const escapeReplacements = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + }; + const getEscapeReplacement = (ch) => escapeReplacements[ch]; + + function escape(html, encode) { + if (encode) { + if (escapeTest.test(html)) { + return html.replace(escapeReplace, getEscapeReplacement); + } + } else { + if (escapeTestNoEncode.test(html)) { + return html.replace(escapeReplaceNoEncode, getEscapeReplacement); + } + } + + return html; + } diff --git a/uni_modules/tmx-ui/components/x-markdown/marked-katex-extension.js b/uni_modules/tmx-ui/components/x-markdown/marked-katex-extension.js new file mode 100644 index 0000000..4c5df6c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/marked-katex-extension.js @@ -0,0 +1,135 @@ +import { + createClass, + parseLatex, + renderMathInText +} from "./index.js" + +export function treeToHtml(nodes) { + // 如果输入是数组,处理数组中的每个节点 + if (Array.isArray(nodes)) { + return nodes.map(node => treeToHtml(node)).join(''); + } + + // 如果是文本节点 + if (nodes.type === 'text') { + return nodes.text; + } + + // 处理HTML节点 + if (nodes.name) { + // 构建开始标签 + let html = `<${nodes.name}`; + + // 添加属性 + if (nodes.attrs) { + for (const [key, value] of Object.entries(nodes.attrs)) { + html += ` ${key}="${value}"`; + } + } + + html += '>'; + + // 处理子节点 + if (nodes.children) { + html += treeToHtml(nodes.children); + } + + // 添加结束标签 + html += ``; + + return html; + } + + return ''; +} + +export function markedKatex(katex) { + 'use strict'; + + const inlineRule = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n\$]))\1(?=[\s?!\.,:?!。,:]|$)/; + const inlineRuleNonStandard = + /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n\$]))\1/; // Non-standard, even if there are no spaces before and after $ or $$, try to parse + + const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/; + + function index(options = {}) { + return { + extensions: [ + inlineKatex(options, createRenderer(options, false)), + blockKatex(options, createRenderer(options, true)), + ], + }; + } + + function createRenderer(options, newlineAfter) { + + return (token) => katex.renderToString(token.text, { + ...options, + displayMode: token.displayMode + }) + (newlineAfter ? '\n' : ''); + } + + function inlineKatex(options, renderer) { + const nonStandard = options && options.nonStandard; + const ruleReg = nonStandard ? inlineRuleNonStandard : inlineRule; + return { + name: 'inlineKatex', + level: 'inline', + start(src) { + let index; + let indexSrc = src; + + while (indexSrc) { + index = indexSrc.indexOf('$'); + if (index === -1) { + return; + } + const f = nonStandard ? index > -1 : index === 0 || indexSrc.charAt(index - 1) === ' '; + if (f) { + const possibleKatex = indexSrc.substring(index); + + if (possibleKatex.match(ruleReg)) { + return index; + } + } + + indexSrc = indexSrc.substring(index + 1).replace(/^\$+/, ''); + } + }, + tokenizer(src, tokens) { + const match = src.match(ruleReg); + if (match) { + return { + type: 'inlineKatex', + raw: match[0], + text: match[2].trim(), + displayMode: match[1].length === 2, + }; + } + }, + renderer, + }; + } + + function blockKatex(options, renderer) { + return { + name: 'blockKatex', + level: 'block', + tokenizer(src, tokens) { + const match = src.match(blockRule); + if (match) { + return { + type: 'blockKatex', + raw: match[0], + text: match[2].trim(), + displayMode: match[1].length === 2, + }; + } + }, + renderer, + }; + } + + return index; + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-markdown/marked-tables.js b/uni_modules/tmx-ui/components/x-markdown/marked-tables.js new file mode 100644 index 0000000..c541b84 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/marked-tables.js @@ -0,0 +1,242 @@ + + export function extendedTables({ + interruptPatterns = [], + skipEmptyRows = true + } = {}) { + return { + extensions: [{ + name: 'spanTable', + level: 'block', // Is this a block-level or inline-level tokenizer? + start(src) { + return src.match(/\n *([^\n ].*\|.*)\n/m)?.index; + }, // Hint to Marked.js to stop and check for a match + tokenizer(src, tokens) { + // const regex = this.tokenizer.rules.block.table; + let regexString = '^ *([^\\n ].*\\|.*\\n(?: *[^\\s].*\\n)*?)' // Header + + + ' {0,3}(?:\\| *)?(:?-+(?: *(?:100|[1-9][0-9]?%) *-+)?:? *(?:\\| *:?-+(?: *(?:100|[1-9][0-9]?%) *-+)?:? *)*)(?:\\| *)?' // Align + + + '(?:\\n((?:(?! *\\n| {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})' // Cells + + + '(?:\\n+|$)| {0,3}#{1,6}(?:\\s|$)| {0,3}>| {4}[^\\n]| {0,3}(?:`{3,}' + + '(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n| {0,3}(?:[*+-]|1[.)]) |' + + '<\\/?(?:address|article|aside|base|basefont|blockquote|body' + + '|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt' + + '|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]' + + '|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem' + + '|meta|nav|noframes|ol|optgroup|option|p|param|section|source' + + '|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)' + + '(?: +|\\n|\\/?>)|<(?:script|pre|style|textarea|!--)endRegex).*(?:\\n|$))*)\\n*|$)'; // Cells + + regexString = regexString.replace('endRegex', interruptPatterns.map(str => + `|(?:${str})`).join('')); + const widthRegex = / *(?:100|[1-9][0-9]?%) */g; + const regex = new RegExp(regexString); + const cap = regex.exec(src); + + if (cap) { + const item = { + type: 'spanTable', + header: cap[1].replace(/\n$/, '').split('\n'), + align: cap[2].replace(widthRegex, '').replace(/^ *|\| *$/g, '').split( + / *\| */), + rows: cap[3]?.trim() ? cap[3].replace(/\n[ \t]*$/, '').split('\n') : [], + width: cap[2].replace(/:/g, '').replace(/-+| /g, '').split('|') + }; + + // Get first header row to determine how many columns + item.header[0] = splitCells(item.header[0]); + + const colCount = item.header[0].reduce((length, header) => { + return length + header.colspan; + }, 0); + + if (colCount === item.align.length) { + item.raw = cap[0]; + + let i, j, k, row; + + // Get alignment row (:---:) + let l = item.align.length; + + for (i = 0; i < l; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + // Get any remaining header rows + l = item.header.length; + for (i = 1; i < l; i++) { + item.header[i] = splitCells(item.header[i], colCount, item.header[i - + 1], skipEmptyRows); + } + + // Get main table cells + l = item.rows.length; + for (i = 0; i < l; i++) { + item.rows[i] = splitCells(item.rows[i], colCount, item.rows[i - 1], + skipEmptyRows); + } + + // header child tokens + l = item.header.length; + for (j = 0; j < l; j++) { + row = item.header[j]; + for (k = 0; k < row.length; k++) { + row[k].tokens = []; + this.lexer.inline(row[k].text, row[k].tokens); + } + } + + // cell child tokens + l = item.rows.length; + for (j = 0; j < l; j++) { + row = item.rows[j]; + for (k = 0; k < row.length; k++) { + row[k].tokens = []; + this.lexer.inline(row[k].text, row[k].tokens); + } + } + return item; + } + } + }, + renderer(token) { + + let i, j, row, cell, col, text; + let output = ''; + output += ''; + for (i = 0; i < token.header.length; i++) { + row = token.header[i]; + let col = 0; + output += ''; + for (j = 0; j < row.length; j++) { + cell = row[j]; + text = this.parser.parseInline(cell.tokens); + output += getTableCell(text, cell, 'th', token.align[col], token.width[ + col]); + col += cell.colspan; + } + output += ''; + } + output += ''; + if (token.rows.length) { + output += ''; + for (i = 0; i < token.rows.length; i++) { + row = token.rows[i]; + col = 0; + if (!row[0].emptyRow) { + output += ''; + for (j = 0; j < row.length; j++) { + cell = row[j]; + text = this.parser.parseInline(cell.tokens); + output += getTableCell(text, cell, 'td', token.align[col], token + .width[col]); + col += cell.colspan; + } + output += ''; + } + } + output += ''; + } + output += '
    '; + return output; + } + }] + }; + } + + const getTableCell = (text, cell, type, align, width) => { + if (!cell.rowspan) { + return ''; + } + const tag = `<${type} class="${type}"` + + `${cell.colspan > 1 ? ` colspan=${cell.colspan}` : ''}` + + `${cell.rowspan > 1 ? ` rowspan=${cell.rowspan}` : ''}` + + `${align ? ` align=${align}` : ''}` + + `${width ? ` width=${width}` : ''}>`; + return `${tag + text}\n`; + }; + + const splitCells = (tableRow, count, prevRow = [], skipEmptyRows) => { + const cells = [...tableRow.trim().matchAll(/(?:[^|\\]|\\.?)+(?:\|+|$)/g)].map((x) => x[0]); + + // Remove first/last cell in a row if whitespace only and no leading/trailing pipe + if (!cells[0]?.trim()) { + cells.shift(); + } + if (!cells[cells.length - 1]?.trim()) { + cells.pop(); + } + + let numCols = 0; + let i, j, trimmedCell, prevCell, prevCols; + + for (i = 0; i < cells.length; i++) { + trimmedCell = cells[i].split(/\|+$/)[0]; + cells[i] = { + rowspan: 1, + colspan: Math.max(cells[i].length - trimmedCell.length, 1), + text: trimmedCell.trim().replace(/\\\|/g, '|') + // display escaped pipes as normal character + }; + + // Handle Rowspan + if (trimmedCell.slice(-1) === '^' && prevRow.length) { + // Find matching cell in previous row + prevCols = 0; + for (j = 0; j < prevRow.length; j++) { + prevCell = prevRow[j]; + if ((prevCols === numCols) && (prevCell.colspan === cells[i].colspan)) { + // merge into matching cell in previous row (the "target") + cells[i].rowSpanTarget = prevCell.rowSpanTarget ?? prevCell; + cells[i].rowSpanTarget.text += ` ${cells[i].text.slice(0, -1)}`; + cells[i].rowSpanTarget.rowspan += 1; + cells[i].rowspan = 0; + break; + } + prevCols += prevCell.colspan; + if (prevCols > numCols) { + break; + } + } + } + + numCols += cells[i].colspan; + } + + // If all cells have been merged, flag as an empty row + if (cells.length > 0 && skipEmptyRows && cells.length === cells.filter((cell) => { + return cell.rowspan === 0; + }).length) { + cells[0].emptyRow = true; + for (i = 0; i < cells.length; i++) { + cells[i].rowSpanTarget.rowspan -= 1; + } + } + + // Force main cell rows to match header column count + if (numCols > count) { + cells.splice(count); + } else { + while (numCols < count) { + cells.push({ + rowspan: 1, + colspan: 1, + text: '' + }); + numCols += 1; + } + } + return cells; + }; + + + diff --git a/uni_modules/tmx-ui/components/x-markdown/marked.uts b/uni_modules/tmx-ui/components/x-markdown/marked.uts new file mode 100644 index 0000000..b5f4066 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/marked.uts @@ -0,0 +1,2579 @@ +/** + * marked v15.0.7 - a markdown parser + * Copyright (c) 2011-2025, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ + +/** + * DO NOT EDIT THIS FILE + * The code in this file is generated from files in ./src/ + */ + +/** + * Gets the original marked default options. + */ +function _getDefaults() { + return { + async: false, + breaks: false, + extensions: null, + gfm: true, + hooks: null, + pedantic: false, + renderer: null, + silent: false, + tokenizer: null, + walkTokens: null, + }; +} +let _defaults = _getDefaults(); +function changeDefaults(newDefaults) { + _defaults = newDefaults; +} + +const noopTest = { exec: () => null }; +function edit(regex, opt = '') { + let source = typeof regex === 'string' ? regex : regex.source; + const obj = { + replace: (name, val) => { + let valSource = typeof val === 'string' ? val : val.source; + valSource = valSource.replace(other.caret, '$1'); + source = source.replace(name, valSource); + return obj; + }, + getRegex: () => { + return new RegExp(source, opt); + }, + }; + return obj; +} +const other = { + codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, + outputLinkReplace: /\\([\[\]])/g, + indentCodeCompensation: /^(\s+)(?:```)/, + beginningSpace: /^\s+/, + endingHash: /#$/, + startingSpaceChar: /^ /, + endingSpaceChar: / $/, + nonSpaceChar: /[^ ]/, + newLineCharGlobal: /\n/g, + tabCharGlobal: /\t/g, + multipleSpaceGlobal: /\s+/g, + blankLine: /^[ \t]*$/, + doubleBlankLine: /\n[ \t]*\n[ \t]*$/, + blockquoteStart: /^ {0,3}>/, + blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, + blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, + listReplaceTabs: /^\t+/, + listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, + listIsTask: /^\[[ xX]\] /, + listReplaceTask: /^\[[ xX]\] +/, + anyLine: /\n.*\n/, + hrefBrackets: /^<(.*)>$/, + tableDelimiter: /[:|]/, + tableAlignChars: /^\||\| *$/g, + tableRowBlankLine: /\n[ \t]*$/, + tableAlignRight: /^ *-+: *$/, + tableAlignCenter: /^ *:-+: *$/, + tableAlignLeft: /^ *:-+ *$/, + startATag: /^/i, + startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, + endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, + startAngleBracket: /^$/, + pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, + unicodeAlphaNumeric: /[\p{L}\p{N}]/u, + escapeTest: /[&<>"']/, + escapeReplace: /[&<>"']/g, + escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, + escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, + unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, + caret: /(^|[^\[])\^/g, + percentDecode: /%25/g, + findPipe: /\|/g, + splitPipe: / \|/, + slashPipe: /\\\|/g, + carriageReturn: /\r\n|\r/g, + spaceLine: /^ +$/gm, + notSpaceStart: /^\S*/, + endingNewline: /\n$/, + listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`), + nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`), + hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), + fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`), + headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`), + htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'), +}; +/** + * Block-Level Grammar + */ +const newline = /^(?:[ \t]*(?:\n|$))+/; +const blockCode = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/; +const fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/; +const hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/; +const heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/; +const bullet = /(?:[*+-]|\d{1,9}[.)])/; +const lheadingCore = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/; +const lheading = edit(lheadingCore) + .replace(/bull/g, bullet) // lists can interrupt + .replace(/blockCode/g, /(?: {4}| {0,3}\t)/) // indented code blocks can interrupt + .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt + .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt + .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt + .replace(/html/g, / {0,3}<[^\n>]+>\n/) // block html can interrupt + .replace(/\|table/g, '') // table not in commonmark + .getRegex(); +const lheadingGfm = edit(lheadingCore) + .replace(/bull/g, bullet) // lists can interrupt + .replace(/blockCode/g, /(?: {4}| {0,3}\t)/) // indented code blocks can interrupt + .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt + .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt + .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt + .replace(/html/g, / {0,3}<[^\n>]+>\n/) // block html can interrupt + .replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/) // table can interrupt + .getRegex(); +const _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/; +const blockText = /^[^\n]+/; +const _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/; +const def = edit(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/) + .replace('label', _blockLabel) + .replace('title', /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/) + .getRegex(); +const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/) + .replace(/bull/g, bullet) + .getRegex(); +const _tag = 'address|article|aside|base|basefont|blockquote|body|caption' + + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title' + + '|tr|track|ul'; +const _comment = /|$))/; +const html = edit('^ {0,3}(?:' // optional indentation + + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3) + + '|\\n*|$)' // (4) + + '|\\n*|$)' // (5) + + '|)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (6) + + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) closing tag + + ')', 'i') + .replace('comment', _comment) + .replace('tag', _tag) + .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/) + .getRegex(); +const paragraph = edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(); +const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/) + .replace('paragraph', paragraph) + .getRegex(); +/** + * Normal Block Grammar + */ +const blockNormal = { + blockquote, + code: blockCode, + def, + fences, + heading, + hr, + html, + lheading, + list, + newline, + paragraph, + table: noopTest, + text: blockText, +}; +/** + * GFM Block Grammar + */ +const gfmTable = edit('^ *([^\\n ].*)\\n' // Header + + ' {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)' // Align + + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)') // Cells + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('blockquote', ' {0,3}>') + .replace('code', '(?: {4}| {0,3}\t)[^\\n]') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // tables can be interrupted by type (6) html blocks + .getRegex(); +const blockGfm = { + ...blockNormal, + lheading: lheadingGfm, + table: gfmTable, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('table', gfmTable) // interrupt paragraphs with table + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(), +}; +/** + * Pedantic grammar (original John Gruber's loose markdown specification) + */ +const blockPedantic = { + ...blockNormal, + html: edit('^ *(?:comment *(?:\\n|\\s*$)' + + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))') + .replace('comment', _comment) + .replace(/tag/g, '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b') + .getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: noopTest, // fences not supported + lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' *#{1,6} *[^\n]') + .replace('lheading', lheading) + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('|fences', '') + .replace('|list', '') + .replace('|html', '') + .replace('|tag', '') + .getRegex(), +}; +/** + * Inline-Level Grammar + */ +const escape$1 = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/; +const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/; +const br = /^( {2,}|\\)\n(?!\s*$)/; +const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\ +const blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g; +const emStrongLDelimCore = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/; +const emStrongLDelim = edit(emStrongLDelimCore, 'u') + .replace(/punct/g, _punctuation) + .getRegex(); +const emStrongLDelimGfm = edit(emStrongLDelimCore, 'u') + .replace(/punct/g, _punctuationGfmStrongEm) + .getRegex(); +const emStrongRDelimAstCore = '^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)' // Skip orphan inside strong + + '|[^*]+(?=[^*])' // Consume to delim + + '|(?!\\*)punct(\\*+)(?=[\\s]|$)' // (1) #*** can only be a Right Delimiter + + '|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter + + '|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter + + '|[\\s](\\*+)(?!\\*)(?=punct)' // (4) ***# can only be Left Delimiter + + '|(?!\\*)punct(\\*+)(?!\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter + + '|notPunctSpace(\\*+)(?=notPunctSpace)'; // (6) a***a can be either Left or Right Delimiter +const emStrongRDelimAst = edit(emStrongRDelimAstCore, 'gu') + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); +const emStrongRDelimAstGfm = edit(emStrongRDelimAstCore, 'gu') + .replace(/notPunctSpace/g, _notPunctuationOrSpaceGfmStrongEm) + .replace(/punctSpace/g, _punctuationOrSpaceGfmStrongEm) + .replace(/punct/g, _punctuationGfmStrongEm) + .getRegex(); +// (6) Not allowed for _ +const emStrongRDelimUnd = edit('^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)' // Skip orphan inside strong + + '|[^_]+(?=[^_])' // Consume to delim + + '|(?!_)punct(_+)(?=[\\s]|$)' // (1) #___ can only be a Right Delimiter + + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter + + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter + + '|[\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter + + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); +const anyPunctuation = edit(/\\(punct)/, 'gu') + .replace(/punct/g, _punctuation) + .getRegex(); +const autolink = edit(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/) + .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/) + .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/) + .getRegex(); +const _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex(); +const tag = edit('^comment' + + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^') // CDATA section + .replace('comment', _inlineComment) + .replace('attribute', /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/) + .getRegex(); +const _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; +const link = edit(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/) + .replace('label', _inlineLabel) + .replace('href', /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/) + .replace('title', /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/) + .getRegex(); +const reflink = edit(/^!?\[(label)\]\[(ref)\]/) + .replace('label', _inlineLabel) + .replace('ref', _blockLabel) + .getRegex(); +const nolink = edit(/^!?\[(ref)\](?:\[\])?/) + .replace('ref', _blockLabel) + .getRegex(); +const reflinkSearch = edit('reflink|nolink(?!\\()', 'g') + .replace('reflink', reflink) + .replace('nolink', nolink) + .getRegex(); +/** + * Normal Inline Grammar + */ +const inlineNormal = { + _backpedal: noopTest, // only used for GFM url + anyPunctuation, + autolink, + blockSkip, + br, + code: inlineCode, + del: noopTest, + emStrongLDelim, + emStrongRDelimAst, + emStrongRDelimUnd, + escape: escape$1, + link, + nolink, + punctuation, + reflink, + reflinkSearch, + tag, + text: inlineText, + url: noopTest, +}; +/** + * Pedantic Inline Grammar + */ +const inlinePedantic = { + ...inlineNormal, + link: edit(/^!?\[(label)\]\((.*?)\)/) + .replace('label', _inlineLabel) + .getRegex(), + reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/) + .replace('label', _inlineLabel) + .getRegex(), +}; +/** + * GFM Inline Grammar + */ +const inlineGfm = { + ...inlineNormal, + emStrongRDelimAst: emStrongRDelimAstGfm, + emStrongLDelim: emStrongLDelimGfm, + url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, 'i') + .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/) + .getRegex(), + _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\': '>', + '"': '"', + "'": ''', +}; +const getEscapeReplacement = (ch) => escapeReplacements[ch]; +function escape(html, encode) { + if (encode) { + if (other.escapeTest.test(html)) { + return html.replace(other.escapeReplace, getEscapeReplacement); + } + } + else { + if (other.escapeTestNoEncode.test(html)) { + return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement); + } + } + return html; +} +function cleanUrl(href) { + try { + href = encodeURI(href).replace(other.percentDecode, '%'); + } + catch { + return null; + } + return href; +} +function splitCells(tableRow, count) { + // ensure that every cell-delimiting pipe has a space + // before it to distinguish it from an escaped pipe + const row = tableRow.replace(other.findPipe, (match, offset, str) => { + let escaped = false; + let curr = offset; + while (--curr >= 0 && str[curr] === '\\') + escaped = !escaped; + if (escaped) { + // odd number of slashes means | is escaped + // so we leave it alone + return '|'; + } + else { + // add space before unescaped | + return ' |'; + } + }), cells = row.split(other.splitPipe); + let i = 0; + // First/last cell in a row cannot be empty if it has no leading/trailing pipe + if (!cells[0].trim()) { + cells.shift(); + } + if (cells.length > 0 && !cells.at(-1)?.trim()) { + cells.pop(); + } + if (count) { + if (cells.length > count) { + cells.splice(count); + } + else { + while (cells.length < count) + cells.push(''); + } + } + for (; i < cells.length; i++) { + // leading or trailing whitespace is ignored per the gfm spec + cells[i] = cells[i].trim().replace(other.slashPipe, '|'); + } + return cells; +} +/** + * Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). + * /c*$/ is vulnerable to REDOS. + * + * @param str + * @param c + * @param invert Remove suffix of non-c chars instead. Default falsey. + */ +function rtrim(str, c, invert) { + const l = str.length; + if (l === 0) { + return ''; + } + // Length of suffix matching the invert condition. + let suffLen = 0; + // Step left until we fail to match the invert condition. + while (suffLen < l) { + const currChar = str.charAt(l - suffLen - 1); + if (currChar === c && true) { + suffLen++; + } + else { + break; + } + } + return str.slice(0, l - suffLen); +} +function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + let level = 0; + for (let i = 0; i < str.length; i++) { + if (str[i] === '\\') { + i++; + } + else if (str[i] === b[0]) { + level++; + } + else if (str[i] === b[1]) { + level--; + if (level < 0) { + return i; + } + } + } + return -1; +} + +function outputLink(cap, link, raw, lexer, rules) { + const href = link.href; + const title = link.title || null; + const text = cap[1].replace(rules.other.outputLinkReplace, '$1'); + if (cap[0].charAt(0) !== '!') { + lexer.state.inLink = true; + const token = { + type: 'link', + raw, + href, + title, + text, + tokens: lexer.inlineTokens(text), + }; + lexer.state.inLink = false; + return token; + } + return { + type: 'image', + raw, + href, + title, + text, + }; +} +function indentCodeCompensation(raw, text, rules) { + const matchIndentToCode = raw.match(rules.other.indentCodeCompensation); + if (matchIndentToCode === null) { + return text; + } + const indentToCode = matchIndentToCode[1]; + return text + .split('\n') + .map(node => { + const matchIndentInNode = node.match(rules.other.beginningSpace); + if (matchIndentInNode === null) { + return node; + } + const [indentInNode] = matchIndentInNode; + if (indentInNode.length >= indentToCode.length) { + return node.slice(indentToCode.length); + } + return node; + }) + .join('\n'); +} +/** + * Tokenizer + */ +class _Tokenizer { + options; + rules; // set by the lexer + lexer; // set by the lexer + constructor(options) { + this.options = options || _defaults; + } + space(src) { + const cap = this.rules.block.newline.exec(src); + if (cap && cap[0].length > 0) { + return { + type: 'space', + raw: cap[0], + }; + } + } + code(src) { + const cap = this.rules.block.code.exec(src); + if (cap) { + const text = cap[0].replace(this.rules.other.codeRemoveIndent, ''); + return { + type: 'code', + raw: cap[0], + codeBlockStyle: 'indented', + text: !this.options.pedantic + ? rtrim(text, '\n') + : text, + }; + } + } + fences(src) { + const cap = this.rules.block.fences.exec(src); + if (cap) { + const raw = cap[0]; + const text = indentCodeCompensation(raw, cap[3] || '', this.rules); + return { + type: 'code', + raw, + lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2], + text, + }; + } + } + heading(src) { + const cap = this.rules.block.heading.exec(src); + if (cap) { + let text = cap[2].trim(); + // remove trailing #s + if (this.rules.other.endingHash.test(text)) { + const trimmed = rtrim(text, '#'); + if (this.options.pedantic) { + text = trimmed.trim(); + } + else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) { + // CommonMark requires space before trailing #s + text = trimmed.trim(); + } + } + return { + type: 'heading', + raw: cap[0], + depth: cap[1].length, + text, + tokens: this.lexer.inline(text), + }; + } + } + hr(src) { + const cap = this.rules.block.hr.exec(src); + if (cap) { + return { + type: 'hr', + raw: rtrim(cap[0], '\n'), + }; + } + } + blockquote(src) { + const cap = this.rules.block.blockquote.exec(src); + if (cap) { + let lines = rtrim(cap[0], '\n').split('\n'); + let raw = ''; + let text = ''; + const tokens = []; + while (lines.length > 0) { + let inBlockquote = false; + const currentLines = []; + let i; + for (i = 0; i < lines.length; i++) { + // get lines up to a continuation + if (this.rules.other.blockquoteStart.test(lines[i])) { + currentLines.push(lines[i]); + inBlockquote = true; + } + else if (!inBlockquote) { + currentLines.push(lines[i]); + } + else { + break; + } + } + lines = lines.slice(i); + const currentRaw = currentLines.join('\n'); + const currentText = currentRaw + // precede setext continuation with 4 spaces so it isn't a setext + .replace(this.rules.other.blockquoteSetextReplace, '\n $1') + .replace(this.rules.other.blockquoteSetextReplace2, ''); + raw = raw ? `${raw}\n${currentRaw}` : currentRaw; + text = text ? `${text}\n${currentText}` : currentText; + // parse blockquote lines as top level tokens + // merge paragraphs if this is a continuation + const top = this.lexer.state.top; + this.lexer.state.top = true; + this.lexer.blockTokens(currentText, tokens, true); + this.lexer.state.top = top; + // if there is no continuation then we are done + if (lines.length === 0) { + break; + } + const lastToken = tokens.at(-1); + if (lastToken?.type === 'code') { + // blockquote continuation cannot be preceded by a code block + break; + } + else if (lastToken?.type === 'blockquote') { + // include continuation in nested blockquote + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.blockquote(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.text.length) + newToken.text; + break; + } + else if (lastToken?.type === 'list') { + // include continuation in nested list + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.list(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw; + lines = newText.substring(tokens.at(-1).raw.length).split('\n'); + continue; + } + } + return { + type: 'blockquote', + raw, + tokens, + text, + }; + } + } + list(src) { + let cap = this.rules.block.list.exec(src); + if (cap) { + let bull = cap[1].trim(); + const isordered = bull.length > 1; + const list = { + type: 'list', + raw: '', + ordered: isordered, + start: isordered ? +bull.slice(0, -1) : '', + loose: false, + items: [], + }; + bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`; + if (this.options.pedantic) { + bull = isordered ? bull : '[*+-]'; + } + // Get next list item + const itemRegex = this.rules.other.listItemRegex(bull); + let endsWithBlankLine = false; + // Check if current bullet point can start a new List Item + while (src) { + let endEarly = false; + let raw = ''; + let itemContents = ''; + if (!(cap = itemRegex.exec(src))) { + break; + } + if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?) + break; + } + raw = cap[0]; + src = src.substring(raw.length); + let line = cap[2].split('\n', 1)[0].replace(this.rules.other.listReplaceTabs, (t) => ' '.repeat(3 * t.length)); + let nextLine = src.split('\n', 1)[0]; + let blankLine = !line.trim(); + let indent = 0; + if (this.options.pedantic) { + indent = 2; + itemContents = line.trimStart(); + } + else if (blankLine) { + indent = cap[1].length + 1; + } + else { + indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char + indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent + itemContents = line.slice(indent); + indent += cap[1].length; + } + if (blankLine && this.rules.other.blankLine.test(nextLine)) { // Items begin with at most one blank line + raw += nextLine + '\n'; + src = src.substring(nextLine.length + 1); + endEarly = true; + } + if (!endEarly) { + const nextBulletRegex = this.rules.other.nextBulletRegex(indent); + const hrRegex = this.rules.other.hrRegex(indent); + const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent); + const headingBeginRegex = this.rules.other.headingBeginRegex(indent); + const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent); + // Check if following lines should be included in List Item + while (src) { + const rawLine = src.split('\n', 1)[0]; + let nextLineWithoutTabs; + nextLine = rawLine; + // Re-align to follow commonmark nesting rules + if (this.options.pedantic) { + nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' '); + nextLineWithoutTabs = nextLine; + } + else { + nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' '); + } + // End list item if found code fences + if (fencesBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new heading + if (headingBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of html block + if (htmlBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new bullet + if (nextBulletRegex.test(nextLine)) { + break; + } + // Horizontal rule found + if (hrRegex.test(nextLine)) { + break; + } + if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) { // Dedent if possible + itemContents += '\n' + nextLineWithoutTabs.slice(indent); + } + else { + // not enough indentation + if (blankLine) { + break; + } + // paragraph continuation unless last line was a different block level element + if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) { // indented code block + break; + } + if (fencesBeginRegex.test(line)) { + break; + } + if (headingBeginRegex.test(line)) { + break; + } + if (hrRegex.test(line)) { + break; + } + itemContents += '\n' + nextLine; + } + if (!blankLine && !nextLine.trim()) { // Check if current line is blank + blankLine = true; + } + raw += rawLine + '\n'; + src = src.substring(rawLine.length + 1); + line = nextLineWithoutTabs.slice(indent); + } + } + if (!list.loose) { + // If the previous item ended with a blank line, the list is loose + if (endsWithBlankLine) { + list.loose = true; + } + else if (this.rules.other.doubleBlankLine.test(raw)) { + endsWithBlankLine = true; + } + } + let istask = null; + let ischecked; + // Check for task list items + if (this.options.gfm) { + istask = this.rules.other.listIsTask.exec(itemContents); + if (istask) { + ischecked = istask[0] !== '[ ] '; + itemContents = itemContents.replace(this.rules.other.listReplaceTask, ''); + } + } + list.items.push({ + type: 'list_item', + raw, + task: !!istask, + checked: ischecked, + loose: false, + text: itemContents, + tokens: [], + }); + list.raw += raw; + } + // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic + const lastItem = list.items.at(-1); + if (lastItem) { + lastItem.raw = lastItem.raw.trimEnd(); + lastItem.text = lastItem.text.trimEnd(); + } + else { + // not a list since there were no items + return; + } + list.raw = list.raw.trimEnd(); + // Item child tokens handled here at end because we needed to have the final item to trim it first + for (let i = 0; i < list.items.length; i++) { + this.lexer.state.top = false; + list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []); + if (!list.loose) { + // Check if list should be loose + const spacers = list.items[i].tokens.filter(t => t.type === 'space'); + const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw)); + list.loose = hasMultipleLineBreaks; + } + } + // Set all items to loose if list is loose + if (list.loose) { + for (let i = 0; i < list.items.length; i++) { + list.items[i].loose = true; + } + } + return list; + } + } + html(src) { + const cap = this.rules.block.html.exec(src); + if (cap) { + const token = { + type: 'html', + block: true, + raw: cap[0], + pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style', + text: cap[0], + }; + return token; + } + } + def(src) { + const cap = this.rules.block.def.exec(src); + if (cap) { + const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' '); + const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : ''; + const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3]; + return { + type: 'def', + tag, + raw: cap[0], + href, + title, + }; + } + } + table(src) { + const cap = this.rules.block.table.exec(src); + if (!cap) { + return; + } + if (!this.rules.other.tableDelimiter.test(cap[2])) { + // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading + return; + } + const headers = splitCells(cap[1]); + const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|'); + const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : []; + const item = { + type: 'table', + raw: cap[0], + header: [], + align: [], + rows: [], + }; + if (headers.length !== aligns.length) { + // header and align columns must be equal, rows can be different. + return; + } + for (const align of aligns) { + if (this.rules.other.tableAlignRight.test(align)) { + item.align.push('right'); + } + else if (this.rules.other.tableAlignCenter.test(align)) { + item.align.push('center'); + } + else if (this.rules.other.tableAlignLeft.test(align)) { + item.align.push('left'); + } + else { + item.align.push(null); + } + } + for (let i = 0; i < headers.length; i++) { + item.header.push({ + text: headers[i], + tokens: this.lexer.inline(headers[i]), + header: true, + align: item.align[i], + }); + } + for (const row of rows) { + item.rows.push(splitCells(row, item.header.length).map((cell, i) => { + return { + text: cell, + tokens: this.lexer.inline(cell), + header: false, + align: item.align[i], + }; + })); + } + return item; + } + lheading(src) { + const cap = this.rules.block.lheading.exec(src); + if (cap) { + return { + type: 'heading', + raw: cap[0], + depth: cap[2].charAt(0) === '=' ? 1 : 2, + text: cap[1], + tokens: this.lexer.inline(cap[1]), + }; + } + } + paragraph(src) { + const cap = this.rules.block.paragraph.exec(src); + if (cap) { + const text = cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1]; + return { + type: 'paragraph', + raw: cap[0], + text, + tokens: this.lexer.inline(text), + }; + } + } + text(src) { + const cap = this.rules.block.text.exec(src); + if (cap) { + return { + type: 'text', + raw: cap[0], + text: cap[0], + tokens: this.lexer.inline(cap[0]), + }; + } + } + escape(src) { + const cap = this.rules.inline.escape.exec(src); + if (cap) { + return { + type: 'escape', + raw: cap[0], + text: cap[1], + }; + } + } + tag(src) { + const cap = this.rules.inline.tag.exec(src); + if (cap) { + if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) { + this.lexer.state.inLink = true; + } + else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) { + this.lexer.state.inLink = false; + } + if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = true; + } + else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = false; + } + return { + type: 'html', + raw: cap[0], + inLink: this.lexer.state.inLink, + inRawBlock: this.lexer.state.inRawBlock, + block: false, + text: cap[0], + }; + } + } + link(src) { + const cap = this.rules.inline.link.exec(src); + if (cap) { + const trimmedUrl = cap[2].trim(); + if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) { + // commonmark requires matching angle brackets + if (!(this.rules.other.endAngleBracket.test(trimmedUrl))) { + return; + } + // ending angle bracket cannot be escaped + const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\'); + if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) { + return; + } + } + else { + // find closing parenthesis + const lastParenIndex = findClosingBracket(cap[2], '()'); + if (lastParenIndex > -1) { + const start = cap[0].indexOf('!') === 0 ? 5 : 4; + const linkLen = start + cap[1].length + lastParenIndex; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } + } + let href = cap[2]; + let title = ''; + if (this.options.pedantic) { + // split pedantic href and title + const link = this.rules.other.pedanticHrefTitle.exec(href); + if (link) { + href = link[1]; + title = link[3]; + } + } + else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + href = href.trim(); + if (this.rules.other.startAngleBracket.test(href)) { + if (this.options.pedantic && !(this.rules.other.endAngleBracket.test(trimmedUrl))) { + // pedantic allows starting angle bracket without ending angle bracket + href = href.slice(1); + } + else { + href = href.slice(1, -1); + } + } + return outputLink(cap, { + href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href, + title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title, + }, cap[0], this.lexer, this.rules); + } + } + reflink(src, links) { + let cap; + if ((cap = this.rules.inline.reflink.exec(src)) + || (cap = this.rules.inline.nolink.exec(src))) { + const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' '); + const link = links[linkString.toLowerCase()]; + if (!link) { + const text = cap[0].charAt(0); + return { + type: 'text', + raw: text, + text, + }; + } + return outputLink(cap, link, cap[0], this.lexer, this.rules); + } + } + emStrong(src, maskedSrc, prevChar = '') { + let match = this.rules.inline.emStrongLDelim.exec(src); + if (!match) + return; + // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well + if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric)) + return; + const nextChar = match[1] || match[2] || ''; + if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) { + // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below) + const lLength = [...match[0]].length - 1; + let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0; + const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd; + endReg.lastIndex = 0; + // Clip maskedSrc to same section of string as src (move to lexer?) + maskedSrc = maskedSrc.slice(-1 * src.length + lLength); + while ((match = endReg.exec(maskedSrc)) != null) { + rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6]; + if (!rDelim) + continue; // skip single * in __abc*abc__ + rLength = [...rDelim].length; + if (match[3] || match[4]) { // found another Left Delim + delimTotal += rLength; + continue; + } + else if (match[5] || match[6]) { // either Left or Right Delim + if (lLength % 3 && !((lLength + rLength) % 3)) { + midDelimTotal += rLength; + continue; // CommonMark Emphasis Rules 9-10 + } + } + delimTotal -= rLength; + if (delimTotal > 0) + continue; // Haven't found enough closing delimiters + // Remove extra characters. *a*** -> *a* + rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); + // char length can be >1 for unicode characters; + const lastCharLength = [...match[0]][0].length; + const raw = src.slice(0, lLength + match.index + lastCharLength + rLength); + // Create `em` if smallest delimiter has odd char count. *a*** + if (Math.min(lLength, rLength) % 2) { + const text = raw.slice(1, -1); + return { + type: 'em', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + // Create 'strong' if smallest delimiter has even char count. **a*** + const text = raw.slice(2, -2); + return { + type: 'strong', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + } + } + codespan(src) { + const cap = this.rules.inline.code.exec(src); + if (cap) { + let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' '); + const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text); + const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text); + if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { + text = text.substring(1, text.length - 1); + } + return { + type: 'codespan', + raw: cap[0], + text, + }; + } + } + br(src) { + const cap = this.rules.inline.br.exec(src); + if (cap) { + return { + type: 'br', + raw: cap[0], + }; + } + } + del(src) { + const cap = this.rules.inline.del.exec(src); + if (cap) { + return { + type: 'del', + raw: cap[0], + text: cap[2], + tokens: this.lexer.inlineTokens(cap[2]), + }; + } + } + autolink(src) { + const cap = this.rules.inline.autolink.exec(src); + if (cap) { + let text, href; + if (cap[2] === '@') { + text = cap[1]; + href = 'mailto:' + text; + } + else { + text = cap[1]; + href = text; + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + url(src) { + let cap; + if (cap = this.rules.inline.url.exec(src)) { + let text, href; + if (cap[2] === '@') { + text = cap[0]; + href = 'mailto:' + text; + } + else { + // do extended autolink path validation + let prevCapZero; + do { + prevCapZero = cap[0]; + cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? ''; + } while (prevCapZero !== cap[0]); + text = cap[0]; + if (cap[1] === 'www.') { + href = 'http://' + cap[0]; + } + else { + href = cap[0]; + } + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + inlineText(src) { + const cap = this.rules.inline.text.exec(src); + if (cap) { + const escaped = this.lexer.state.inRawBlock; + return { + type: 'text', + raw: cap[0], + text: cap[0], + escaped, + }; + } + } +} + +/** + * Block Lexer + */ +class _Lexer { + tokens; + options; + state; + tokenizer; + inlineQueue; + constructor(options) { + // TokenList cannot be created in one go + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || _defaults; + this.options.tokenizer = this.options.tokenizer || new _Tokenizer(); + this.tokenizer = this.options.tokenizer; + this.tokenizer.options = this.options; + this.tokenizer.lexer = this; + this.inlineQueue = []; + this.state = { + inLink: false, + inRawBlock: false, + top: true, + }; + const rules = { + other, + block: block.normal, + inline: inline.normal, + }; + if (this.options.pedantic) { + rules.block = block.pedantic; + rules.inline = inline.pedantic; + } + else if (this.options.gfm) { + rules.block = block.gfm; + if (this.options.breaks) { + rules.inline = inline.breaks; + } + else { + rules.inline = inline.gfm; + } + } + this.tokenizer.rules = rules; + } + /** + * Expose Rules + */ + static get rules() { + return { + block, + inline, + }; + } + /** + * Static Lex Method + */ + static lex(src, options) { + const lexer = new _Lexer(options); + return lexer.lex(src); + } + /** + * Static Lex Inline Method + */ + static lexInline(src, options) { + const lexer = new _Lexer(options); + return lexer.inlineTokens(src); + } + /** + * Preprocessing + */ + lex(src) { + src = src.replace(other.carriageReturn, '\n'); + this.blockTokens(src, this.tokens); + for (let i = 0; i < this.inlineQueue.length; i++) { + const next = this.inlineQueue[i]; + this.inlineTokens(next.src, next.tokens); + } + this.inlineQueue = []; + return this.tokens; + } + blockTokens(src, tokens = [], lastParagraphClipped = false) { + if (this.options.pedantic) { + src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, ''); + } + while (src) { + let token; + if (this.options.extensions?.block?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // newline + if (token = this.tokenizer.space(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.raw.length === 1 && lastToken !== undefined) { + // if there's a single \n as a spacer, it's terminating the last line, + // so move it there so that we don't get unnecessary paragraph tags + lastToken.raw += '\n'; + } + else { + tokens.push(token); + } + continue; + } + // code + if (token = this.tokenizer.code(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + // An indented code block cannot interrupt a paragraph. + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + // fences + if (token = this.tokenizer.fences(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // heading + if (token = this.tokenizer.heading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // hr + if (token = this.tokenizer.hr(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // blockquote + if (token = this.tokenizer.blockquote(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // list + if (token = this.tokenizer.list(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // html + if (token = this.tokenizer.html(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // def + if (token = this.tokenizer.def(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.raw; + this.inlineQueue.at(-1).src = lastToken.text; + } + else if (!this.tokens.links[token.tag]) { + this.tokens.links[token.tag] = { + href: token.href, + title: token.title, + }; + } + continue; + } + // table (gfm) + if (token = this.tokenizer.table(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // lheading + if (token = this.tokenizer.lheading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // top-level paragraph + // prevent paragraph consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startBlock) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startBlock.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) { + const lastToken = tokens.at(-1); + if (lastParagraphClipped && lastToken?.type === 'paragraph') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + lastParagraphClipped = cutSrc.length !== src.length; + src = src.substring(token.raw.length); + continue; + } + // text + if (token = this.tokenizer.text(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + this.state.top = true; + return tokens; + } + inline(src, tokens = []) { + this.inlineQueue.push({ src, tokens }); + return tokens; + } + /** + * Lexing/Compiling + */ + inlineTokens(src, tokens = []) { + // String with links masked to avoid interference with em and strong + let maskedSrc = src; + let match = null; + // Mask out reflinks + if (this.tokens.links) { + const links = Object.keys(this.tokens.links); + if (links.length > 0) { + while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { + if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) { + maskedSrc = maskedSrc.slice(0, match.index) + + '[' + 'a'.repeat(match[0].length - 2) + ']' + + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); + } + } + } + } + // Mask out other blocks + while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + } + // Mask out escaped characters + while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex); + } + let keepPrevChar = false; + let prevChar = ''; + while (src) { + if (!keepPrevChar) { + prevChar = ''; + } + keepPrevChar = false; + let token; + // extensions + if (this.options.extensions?.inline?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // escape + if (token = this.tokenizer.escape(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // tag + if (token = this.tokenizer.tag(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // link + if (token = this.tokenizer.link(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // reflink, nolink + if (token = this.tokenizer.reflink(src, this.tokens.links)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.type === 'text' && lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + // em & strong + if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // code + if (token = this.tokenizer.codespan(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // br + if (token = this.tokenizer.br(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // del (gfm) + if (token = this.tokenizer.del(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // autolink + if (token = this.tokenizer.autolink(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // url (gfm) + if (!this.state.inLink && (token = this.tokenizer.url(src))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // text + // prevent inlineText consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startInline) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startInline.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (token = this.tokenizer.inlineText(cutSrc)) { + src = src.substring(token.raw.length); + if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started + prevChar = token.raw.slice(-1); + } + keepPrevChar = true; + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + return tokens; + } +} + +/** + * Renderer + */ +class _Renderer { + options; + parser; // set by the parser + constructor(options) { + this.options = options || _defaults; + } + space(token) { + return ''; + } + code({ text, lang, escaped }) { + const langString = (lang || '').match(other.notSpaceStart)?.[0]; + const code = text.replace(other.endingNewline, '') + '\n'; + if (!langString) { + return '
    '
    +                + (escaped ? code : escape(code, true))
    +                + '
    \n'; + } + return '
    '
    +            + (escaped ? code : escape(code, true))
    +            + '
    \n'; + } + blockquote({ tokens }) { + const body = this.parser.parse(tokens); + return `
    \n${body}
    \n`; + } + html({ text }) { + return text; + } + heading({ tokens, depth }) { + return `${this.parser.parseInline(tokens)}\n`; + } + hr(token) { + return '
    \n'; + } + list(token) { + const ordered = token.ordered; + const start = token.start; + let body = ''; + for (let j = 0; j < token.items.length; j++) { + const item = token.items[j]; + body += this.listitem(item); + } + const type = ordered ? 'ol' : 'ul'; + const startAttr = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startAttr + '>\n' + body + '\n'; + } + listitem(item) { + let itemBody = ''; + if (item.task) { + const checkbox = this.checkbox({ checked: !!item.checked }); + if (item.loose) { + if (item.tokens[0]?.type === 'paragraph') { + item.tokens[0].text = checkbox + ' ' + item.tokens[0].text; + if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { + item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text); + item.tokens[0].tokens[0].escaped = true; + } + } + else { + item.tokens.unshift({ + type: 'text', + raw: checkbox + ' ', + text: checkbox + ' ', + escaped: true, + }); + } + } + else { + itemBody += checkbox + ' '; + } + } + itemBody += this.parser.parse(item.tokens, !!item.loose); + return `
  • ${itemBody}
  • \n`; + } + checkbox({ checked }) { + return ''; + } + paragraph({ tokens }) { + return `

    ${this.parser.parseInline(tokens)}

    \n`; + } + table(token) { + let header = ''; + // header + let cell = ''; + for (let j = 0; j < token.header.length; j++) { + cell += this.tablecell(token.header[j]); + } + header += this.tablerow({ text: cell }); + let body = ''; + for (let j = 0; j < token.rows.length; j++) { + const row = token.rows[j]; + cell = ''; + for (let k = 0; k < row.length; k++) { + cell += this.tablecell(row[k]); + } + body += this.tablerow({ text: cell }); + } + if (body) + body = `${body}`; + return '\n' + + '\n' + + header + + '\n' + + body + + '
    \n'; + } + tablerow({ text }) { + return `\n${text}\n`; + } + tablecell(token) { + const content = this.parser.parseInline(token.tokens); + const type = token.header ? 'th' : 'td'; + const tag = token.align + ? `<${type} align="${token.align}">` + : `<${type}>`; + return tag + content + `\n`; + } + /** + * span level renderer + */ + strong({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + em({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + codespan({ text }) { + return `${escape(text, true)}`; + } + br(token) { + return '
    '; + } + del({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + link({ href, title, tokens }) { + const text = this.parser.parseInline(tokens); + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return text; + } + href = cleanHref; + let out = '
    '; + return out; + } + image({ href, title, text }) { + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return escape(text); + } + href = cleanHref; + let out = `${text} { + const tokens = genericToken[childTokens].flat(Infinity); + values = values.concat(this.walkTokens(tokens, callback)); + }); + } + else if (genericToken.tokens) { + values = values.concat(this.walkTokens(genericToken.tokens, callback)); + } + } + } + } + return values; + } + use(...args) { + const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} }; + args.forEach((pack) => { + // copy options to new object + const opts = { ...pack }; + // set async to true if it was set to true before + opts.async = this.defaults.async || opts.async || false; + // ==-- Parse "addon" extensions --== // + if (pack.extensions) { + pack.extensions.forEach((ext) => { + if (!ext.name) { + throw new Error('extension name required'); + } + if ('renderer' in ext) { // Renderer extensions + const prevRenderer = extensions.renderers[ext.name]; + if (prevRenderer) { + // Replace extension with func to run new extension but fall back if false + extensions.renderers[ext.name] = function (...args) { + let ret = ext.renderer.apply(this, args); + if (ret === false) { + ret = prevRenderer.apply(this, args); + } + return ret; + }; + } + else { + extensions.renderers[ext.name] = ext.renderer; + } + } + if ('tokenizer' in ext) { // Tokenizer Extensions + if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) { + throw new Error("extension level must be 'block' or 'inline'"); + } + const extLevel = extensions[ext.level]; + if (extLevel) { + extLevel.unshift(ext.tokenizer); + } + else { + extensions[ext.level] = [ext.tokenizer]; + } + if (ext.start) { // Function to check for start of token + if (ext.level === 'block') { + if (extensions.startBlock) { + extensions.startBlock.push(ext.start); + } + else { + extensions.startBlock = [ext.start]; + } + } + else if (ext.level === 'inline') { + if (extensions.startInline) { + extensions.startInline.push(ext.start); + } + else { + extensions.startInline = [ext.start]; + } + } + } + } + if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens + extensions.childTokens[ext.name] = ext.childTokens; + } + }); + opts.extensions = extensions; + } + // ==-- Parse "overwrite" extensions --== // + if (pack.renderer) { + const renderer = this.defaults.renderer || new _Renderer(this.defaults); + for (const prop in pack.renderer) { + if (!(prop in renderer)) { + throw new Error(`renderer '${prop}' does not exist`); + } + if (['options', 'parser'].includes(prop)) { + // ignore options property + continue; + } + const rendererProp = prop; + const rendererFunc = pack.renderer[rendererProp]; + const prevRenderer = renderer[rendererProp]; + // Replace renderer with func to run extension, but fall back if false + renderer[rendererProp] = (...args) => { + let ret = rendererFunc.apply(renderer, args); + if (ret === false) { + ret = prevRenderer.apply(renderer, args); + } + return ret || ''; + }; + } + opts.renderer = renderer; + } + if (pack.tokenizer) { + const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults); + for (const prop in pack.tokenizer) { + if (!(prop in tokenizer)) { + throw new Error(`tokenizer '${prop}' does not exist`); + } + if (['options', 'rules', 'lexer'].includes(prop)) { + // ignore options, rules, and lexer properties + continue; + } + const tokenizerProp = prop; + const tokenizerFunc = pack.tokenizer[tokenizerProp]; + const prevTokenizer = tokenizer[tokenizerProp]; + // Replace tokenizer with func to run extension, but fall back if false + // @ts-expect-error cannot type tokenizer function dynamically + tokenizer[tokenizerProp] = (...args) => { + let ret = tokenizerFunc.apply(tokenizer, args); + if (ret === false) { + ret = prevTokenizer.apply(tokenizer, args); + } + return ret; + }; + } + opts.tokenizer = tokenizer; + } + // ==-- Parse Hooks extensions --== // + if (pack.hooks) { + const hooks = this.defaults.hooks || new _Hooks(); + for (const prop in pack.hooks) { + if (!(prop in hooks)) { + throw new Error(`hook '${prop}' does not exist`); + } + if (['options', 'block'].includes(prop)) { + // ignore options and block properties + continue; + } + const hooksProp = prop; + const hooksFunc = pack.hooks[hooksProp]; + const prevHook = hooks[hooksProp]; + if (_Hooks.passThroughHooks.has(prop)) { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (arg) => { + if (this.defaults.async) { + return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => { + return prevHook.call(hooks, ret); + }); + } + const ret = hooksFunc.call(hooks, arg); + return prevHook.call(hooks, ret); + }; + } + else { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (...args) => { + let ret = hooksFunc.apply(hooks, args); + if (ret === false) { + ret = prevHook.apply(hooks, args); + } + return ret; + }; + } + } + opts.hooks = hooks; + } + // ==-- Parse WalkTokens extensions --== // + if (pack.walkTokens) { + const walkTokens = this.defaults.walkTokens; + const packWalktokens = pack.walkTokens; + opts.walkTokens = function (token) { + let values = []; + values.push(packWalktokens.call(this, token)); + if (walkTokens) { + values = values.concat(walkTokens.call(this, token)); + } + return values; + }; + } + this.defaults = { ...this.defaults, ...opts }; + }); + return this; + } + setOptions(opt) { + this.defaults = { ...this.defaults, ...opt }; + return this; + } + lexer(src, options) { + return _Lexer.lex(src, options ?? this.defaults); + } + parser(tokens, options) { + return _Parser.parse(tokens, options ?? this.defaults); + } + parseMarkdown(blockType) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const parse = (src, options) => { + const origOpt = { ...options }; + const opt = { ...this.defaults, ...origOpt }; + const throwError = this.onError(!!opt.silent, !!opt.async); + // throw error if an extension set async to true but parse was called with async: false + if (this.defaults.async === true && origOpt.async === false) { + return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.')); + } + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + return throwError(new Error('marked(): input parameter is undefined or null')); + } + if (typeof src !== 'string') { + return throwError(new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected')); + } + if (opt.hooks) { + opt.hooks.options = opt; + opt.hooks.block = blockType; + } + const lexer = opt.hooks ? opt.hooks.provideLexer() : (blockType ? _Lexer.lex : _Lexer.lexInline); + const parser = opt.hooks ? opt.hooks.provideParser() : (blockType ? _Parser.parse : _Parser.parseInline); + if (opt.async) { + return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src) + .then(src => lexer(src, opt)) + .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens) + .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens) + .then(tokens => parser(tokens, opt)) + .then(html => opt.hooks ? opt.hooks.postprocess(html) : html) + .catch(throwError); + } + try { + if (opt.hooks) { + src = opt.hooks.preprocess(src); + } + let tokens = lexer(src, opt); + if (opt.hooks) { + tokens = opt.hooks.processAllTokens(tokens); + } + if (opt.walkTokens) { + this.walkTokens(tokens, opt.walkTokens); + } + let html = parser(tokens, opt); + if (opt.hooks) { + html = opt.hooks.postprocess(html); + } + return html; + } + catch (e) { + return throwError(e); + } + }; + return parse; + } + onError(silent, async) { + return (e) => { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if (silent) { + const msg = '

    An error occurred:

    '
    +                    + escape(e.message + '', true)
    +                    + '
    '; + if (async) { + return Promise.resolve(msg); + } + return msg; + } + if (async) { + return Promise.reject(e); + } + throw e; + }; + } +} + +const markedInstance = new Marked(); +function marked(src, opt) { + return markedInstance.parse(src, opt); +} +/** + * Sets the default options. + * + * @param options Hash of options + */ +marked.options = + marked.setOptions = function (options) { + markedInstance.setOptions(options); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; + }; +/** + * Gets the original marked default options. + */ +marked.getDefaults = _getDefaults; +marked.defaults = _defaults; +/** + * Use Extension + */ +marked.use = function (...args) { + markedInstance.use(...args); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; +}; +/** + * Run callback for every token + */ +marked.walkTokens = function (tokens, callback) { + return markedInstance.walkTokens(tokens, callback); +}; +/** + * Compiles markdown to HTML without enclosing `p` tag. + * + * @param src String of markdown source to be compiled + * @param options Hash of options + * @return String of compiled HTML + */ +marked.parseInline = markedInstance.parseInline; +/** + * Expose + */ +marked.Parser = _Parser; +marked.parser = _Parser.parse; +marked.Renderer = _Renderer; +marked.TextRenderer = _TextRenderer; +marked.Lexer = _Lexer; +marked.lexer = _Lexer.lex; +marked.Tokenizer = _Tokenizer; +marked.Hooks = _Hooks; +marked.parse = marked; +const options = marked.options; +const setOptions = marked.setOptions; +const use = marked.use; +const walkTokens = marked.walkTokens; +const parseInline = marked.parseInline; +const parse = marked; +const parser = _Parser.parse; +const lexer = _Lexer.lex; + +export { _Hooks as Hooks, _Lexer as Lexer, Marked, _Parser as Parser, _Renderer as Renderer, _TextRenderer as TextRenderer, _Tokenizer as Tokenizer, _defaults as defaults, _getDefaults as getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens }; diff --git a/uni_modules/tmx-ui/components/x-markdown/x-markdown.uvue b/uni_modules/tmx-ui/components/x-markdown/x-markdown.uvue new file mode 100644 index 0000000..aead89b --- /dev/null +++ b/uni_modules/tmx-ui/components/x-markdown/x-markdown.uvue @@ -0,0 +1,469 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-mention/x-mention.uvue b/uni_modules/tmx-ui/components/x-mention/x-mention.uvue new file mode 100644 index 0000000..4a5125c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-mention/x-mention.uvue @@ -0,0 +1,310 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-modal/x-modal.uvue b/uni_modules/tmx-ui/components/x-modal/x-modal.uvue new file mode 100644 index 0000000..75794b1 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-modal/x-modal.uvue @@ -0,0 +1,786 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-money/x-money.uvue b/uni_modules/tmx-ui/components/x-money/x-money.uvue new file mode 100644 index 0000000..60b695b --- /dev/null +++ b/uni_modules/tmx-ui/components/x-money/x-money.uvue @@ -0,0 +1,308 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-more/x-more.uvue b/uni_modules/tmx-ui/components/x-more/x-more.uvue new file mode 100644 index 0000000..787045f --- /dev/null +++ b/uni_modules/tmx-ui/components/x-more/x-more.uvue @@ -0,0 +1,273 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-msg-notice/x-msg-notice.uvue b/uni_modules/tmx-ui/components/x-msg-notice/x-msg-notice.uvue new file mode 100644 index 0000000..d385eb4 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-msg-notice/x-msg-notice.uvue @@ -0,0 +1,375 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-navbar/x-navbar.uvue b/uni_modules/tmx-ui/components/x-navbar/x-navbar.uvue new file mode 100644 index 0000000..3073d25 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-navbar/x-navbar.uvue @@ -0,0 +1,426 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-notice/x-notice.uvue b/uni_modules/tmx-ui/components/x-notice/x-notice.uvue new file mode 100644 index 0000000..972f0c5 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-notice/x-notice.uvue @@ -0,0 +1,316 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-overlay/x-overlay.uvue b/uni_modules/tmx-ui/components/x-overlay/x-overlay.uvue new file mode 100644 index 0000000..c472938 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-overlay/x-overlay.uvue @@ -0,0 +1,591 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-pagination/x-pagination.uvue b/uni_modules/tmx-ui/components/x-pagination/x-pagination.uvue new file mode 100644 index 0000000..c760dac --- /dev/null +++ b/uni_modules/tmx-ui/components/x-pagination/x-pagination.uvue @@ -0,0 +1,435 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-city/level.min.uts b/uni_modules/tmx-ui/components/x-picker-city/level.min.uts new file mode 100644 index 0000000..e5d9c2c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-city/level.min.uts @@ -0,0 +1,22503 @@ +let citys = '[]' + +// #ifdef APP || WEB +citys = `[ + { + "title": "北京市", + "id": "110000", + "children": [ + { + "title": "北京市", + "id": "1100001", + "children": [ + { + "title": "东城区", + "id": "110101", + "children": [], + "disabled": false + }, + { + "title": "西城区", + "id": "110102", + "children": [], + "disabled": false + }, + { + "title": "朝阳区", + "id": "110105", + "children": [], + "disabled": false + }, + { + "title": "丰台区", + "id": "110106", + "children": [], + "disabled": false + }, + { + "title": "石景山区", + "id": "110107", + "children": [], + "disabled": false + }, + { + "title": "海淀区", + "id": "110108", + "children": [], + "disabled": false + }, + { + "title": "门头沟区", + "id": "110109", + "children": [], + "disabled": false + }, + { + "title": "房山区", + "id": "110111", + "children": [], + "disabled": false + }, + { + "title": "通州区", + "id": "110112", + "children": [], + "disabled": false + }, + { + "title": "顺义区", + "id": "110113", + "children": [], + "disabled": false + }, + { + "title": "昌平区", + "id": "110114", + "children": [], + "disabled": false + }, + { + "title": "大兴区", + "id": "110115", + "children": [], + "disabled": false + }, + { + "title": "怀柔区", + "id": "110116", + "children": [], + "disabled": false + }, + { + "title": "平谷区", + "id": "110117", + "children": [], + "disabled": false + }, + { + "title": "密云区", + "id": "110118", + "children": [], + "disabled": false + }, + { + "title": "延庆区", + "id": "110119", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "天津市", + "id": "120000", + "children": [ + { + "title": "天津市", + "id": "1200001", + "children": [ + { + "title": "和平区", + "id": "120101", + "children": [], + "disabled": false + }, + { + "title": "河东区", + "id": "120102", + "children": [], + "disabled": false + }, + { + "title": "河西区", + "id": "120103", + "children": [], + "disabled": false + }, + { + "title": "南开区", + "id": "120104", + "children": [], + "disabled": false + }, + { + "title": "河北区", + "id": "120105", + "children": [], + "disabled": false + }, + { + "title": "红桥区", + "id": "120106", + "children": [], + "disabled": false + }, + { + "title": "东丽区", + "id": "120110", + "children": [], + "disabled": false + }, + { + "title": "西青区", + "id": "120111", + "children": [], + "disabled": false + }, + { + "title": "津南区", + "id": "120112", + "children": [], + "disabled": false + }, + { + "title": "北辰区", + "id": "120113", + "children": [], + "disabled": false + }, + { + "title": "武清区", + "id": "120114", + "children": [], + "disabled": false + }, + { + "title": "宝坻区", + "id": "120115", + "children": [], + "disabled": false + }, + { + "title": "滨海新区", + "id": "120116", + "children": [], + "disabled": false + }, + { + "title": "宁河区", + "id": "120117", + "children": [], + "disabled": false + }, + { + "title": "静海区", + "id": "120118", + "children": [], + "disabled": false + }, + { + "title": "蓟州区", + "id": "120119", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "河北省", + "id": "130000", + "children": [ + { + "title": "石家庄市", + "id": "130100", + "children": [ + { + "title": "长安区", + "id": "130102", + "children": [], + "disabled": false + }, + { + "title": "桥西区", + "id": "130104", + "children": [], + "disabled": false + }, + { + "title": "新华区", + "id": "130105", + "children": [], + "disabled": false + }, + { + "title": "井陉矿区", + "id": "130107", + "children": [], + "disabled": false + }, + { + "title": "裕华区", + "id": "130108", + "children": [], + "disabled": false + }, + { + "title": "藁城区", + "id": "130109", + "children": [], + "disabled": false + }, + { + "title": "鹿泉区", + "id": "130110", + "children": [], + "disabled": false + }, + { + "title": "栾城区", + "id": "130111", + "children": [], + "disabled": false + }, + { + "title": "井陉县", + "id": "130121", + "children": [], + "disabled": false + }, + { + "title": "正定县", + "id": "130123", + "children": [], + "disabled": false + }, + { + "title": "行唐县", + "id": "130125", + "children": [], + "disabled": false + }, + { + "title": "灵寿县", + "id": "130126", + "children": [], + "disabled": false + }, + { + "title": "高邑县", + "id": "130127", + "children": [], + "disabled": false + }, + { + "title": "深泽县", + "id": "130128", + "children": [], + "disabled": false + }, + { + "title": "赞皇县", + "id": "130129", + "children": [], + "disabled": false + }, + { + "title": "无极县", + "id": "130130", + "children": [], + "disabled": false + }, + { + "title": "平山县", + "id": "130131", + "children": [], + "disabled": false + }, + { + "title": "元氏县", + "id": "130132", + "children": [], + "disabled": false + }, + { + "title": "赵县", + "id": "130133", + "children": [], + "disabled": false + }, + { + "title": "辛集市", + "id": "130181", + "children": [], + "disabled": false + }, + { + "title": "晋州市", + "id": "130183", + "children": [], + "disabled": false + }, + { + "title": "新乐市", + "id": "130184", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130101", + "children": [], + "disabled": false + }, + { + "title": "石家庄高新技术产业开发区", + "id": "130171", + "children": [], + "disabled": false + }, + { + "title": "石家庄循环化工园区", + "id": "130172", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "唐山市", + "id": "130200", + "children": [ + { + "title": "路南区", + "id": "130202", + "children": [], + "disabled": false + }, + { + "title": "路北区", + "id": "130203", + "children": [], + "disabled": false + }, + { + "title": "古冶区", + "id": "130204", + "children": [], + "disabled": false + }, + { + "title": "开平区", + "id": "130205", + "children": [], + "disabled": false + }, + { + "title": "丰南区", + "id": "130207", + "children": [], + "disabled": false + }, + { + "title": "丰润区", + "id": "130208", + "children": [], + "disabled": false + }, + { + "title": "曹妃甸区", + "id": "130209", + "children": [], + "disabled": false + }, + { + "title": "滦南县", + "id": "130224", + "children": [], + "disabled": false + }, + { + "title": "乐亭县", + "id": "130225", + "children": [], + "disabled": false + }, + { + "title": "迁西县", + "id": "130227", + "children": [], + "disabled": false + }, + { + "title": "玉田县", + "id": "130229", + "children": [], + "disabled": false + }, + { + "title": "遵化市", + "id": "130281", + "children": [], + "disabled": false + }, + { + "title": "迁安市", + "id": "130283", + "children": [], + "disabled": false + }, + { + "title": "滦州市", + "id": "130284", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130201", + "children": [], + "disabled": false + }, + { + "title": "河北唐山芦台经济开发区", + "id": "130271", + "children": [], + "disabled": false + }, + { + "title": "唐山市汉沽管理区", + "id": "130272", + "children": [], + "disabled": false + }, + { + "title": "唐山高新技术产业开发区", + "id": "130273", + "children": [], + "disabled": false + }, + { + "title": "河北唐山海港经济开发区", + "id": "130274", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "秦皇岛市", + "id": "130300", + "children": [ + { + "title": "海港区", + "id": "130302", + "children": [], + "disabled": false + }, + { + "title": "山海关区", + "id": "130303", + "children": [], + "disabled": false + }, + { + "title": "北戴河区", + "id": "130304", + "children": [], + "disabled": false + }, + { + "title": "抚宁区", + "id": "130306", + "children": [], + "disabled": false + }, + { + "title": "青龙满族自治县", + "id": "130321", + "children": [], + "disabled": false + }, + { + "title": "昌黎县", + "id": "130322", + "children": [], + "disabled": false + }, + { + "title": "卢龙县", + "id": "130324", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130301", + "children": [], + "disabled": false + }, + { + "title": "秦皇岛市经济技术开发区", + "id": "130371", + "children": [], + "disabled": false + }, + { + "title": "北戴河新区", + "id": "130372", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "邯郸市", + "id": "130400", + "children": [ + { + "title": "邯山区", + "id": "130402", + "children": [], + "disabled": false + }, + { + "title": "丛台区", + "id": "130403", + "children": [], + "disabled": false + }, + { + "title": "复兴区", + "id": "130404", + "children": [], + "disabled": false + }, + { + "title": "峰峰矿区", + "id": "130406", + "children": [], + "disabled": false + }, + { + "title": "肥乡区", + "id": "130407", + "children": [], + "disabled": false + }, + { + "title": "永年区", + "id": "130408", + "children": [], + "disabled": false + }, + { + "title": "临漳县", + "id": "130423", + "children": [], + "disabled": false + }, + { + "title": "成安县", + "id": "130424", + "children": [], + "disabled": false + }, + { + "title": "大名县", + "id": "130425", + "children": [], + "disabled": false + }, + { + "title": "涉县", + "id": "130426", + "children": [], + "disabled": false + }, + { + "title": "磁县", + "id": "130427", + "children": [], + "disabled": false + }, + { + "title": "邱县", + "id": "130430", + "children": [], + "disabled": false + }, + { + "title": "鸡泽县", + "id": "130431", + "children": [], + "disabled": false + }, + { + "title": "广平县", + "id": "130432", + "children": [], + "disabled": false + }, + { + "title": "馆陶县", + "id": "130433", + "children": [], + "disabled": false + }, + { + "title": "魏县", + "id": "130434", + "children": [], + "disabled": false + }, + { + "title": "曲周县", + "id": "130435", + "children": [], + "disabled": false + }, + { + "title": "武安市", + "id": "130481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130401", + "children": [], + "disabled": false + }, + { + "title": "邯郸经济技术开发区", + "id": "130471", + "children": [], + "disabled": false + }, + { + "title": "邯郸冀南新区", + "id": "130473", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "邢台市", + "id": "130500", + "children": [ + { + "title": "襄都区", + "id": "130502", + "children": [], + "disabled": false + }, + { + "title": "信都区", + "id": "130503", + "children": [], + "disabled": false + }, + { + "title": "任泽区", + "id": "130505", + "children": [], + "disabled": false + }, + { + "title": "南和区", + "id": "130506", + "children": [], + "disabled": false + }, + { + "title": "临城县", + "id": "130522", + "children": [], + "disabled": false + }, + { + "title": "内丘县", + "id": "130523", + "children": [], + "disabled": false + }, + { + "title": "柏乡县", + "id": "130524", + "children": [], + "disabled": false + }, + { + "title": "隆尧县", + "id": "130525", + "children": [], + "disabled": false + }, + { + "title": "宁晋县", + "id": "130528", + "children": [], + "disabled": false + }, + { + "title": "巨鹿县", + "id": "130529", + "children": [], + "disabled": false + }, + { + "title": "新河县", + "id": "130530", + "children": [], + "disabled": false + }, + { + "title": "广宗县", + "id": "130531", + "children": [], + "disabled": false + }, + { + "title": "平乡县", + "id": "130532", + "children": [], + "disabled": false + }, + { + "title": "威县", + "id": "130533", + "children": [], + "disabled": false + }, + { + "title": "清河县", + "id": "130534", + "children": [], + "disabled": false + }, + { + "title": "临西县", + "id": "130535", + "children": [], + "disabled": false + }, + { + "title": "南宫市", + "id": "130581", + "children": [], + "disabled": false + }, + { + "title": "沙河市", + "id": "130582", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130501", + "children": [], + "disabled": false + }, + { + "title": "河北邢台经济开发区", + "id": "130571", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "保定市", + "id": "130600", + "children": [ + { + "title": "竞秀区", + "id": "130602", + "children": [], + "disabled": false + }, + { + "title": "莲池区", + "id": "130606", + "children": [], + "disabled": false + }, + { + "title": "满城区", + "id": "130607", + "children": [], + "disabled": false + }, + { + "title": "清苑区", + "id": "130608", + "children": [], + "disabled": false + }, + { + "title": "徐水区", + "id": "130609", + "children": [], + "disabled": false + }, + { + "title": "涞水县", + "id": "130623", + "children": [], + "disabled": false + }, + { + "title": "阜平县", + "id": "130624", + "children": [], + "disabled": false + }, + { + "title": "定兴县", + "id": "130626", + "children": [], + "disabled": false + }, + { + "title": "唐县", + "id": "130627", + "children": [], + "disabled": false + }, + { + "title": "高阳县", + "id": "130628", + "children": [], + "disabled": false + }, + { + "title": "容城县", + "id": "130629", + "children": [], + "disabled": false + }, + { + "title": "涞源县", + "id": "130630", + "children": [], + "disabled": false + }, + { + "title": "望都县", + "id": "130631", + "children": [], + "disabled": false + }, + { + "title": "安新县", + "id": "130632", + "children": [], + "disabled": false + }, + { + "title": "易县", + "id": "130633", + "children": [], + "disabled": false + }, + { + "title": "曲阳县", + "id": "130634", + "children": [], + "disabled": false + }, + { + "title": "蠡县", + "id": "130635", + "children": [], + "disabled": false + }, + { + "title": "顺平县", + "id": "130636", + "children": [], + "disabled": false + }, + { + "title": "博野县", + "id": "130637", + "children": [], + "disabled": false + }, + { + "title": "雄县", + "id": "130638", + "children": [], + "disabled": false + }, + { + "title": "涿州市", + "id": "130681", + "children": [], + "disabled": false + }, + { + "title": "定州市", + "id": "130682", + "children": [], + "disabled": false + }, + { + "title": "安国市", + "id": "130683", + "children": [], + "disabled": false + }, + { + "title": "高碑店市", + "id": "130684", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130601", + "children": [], + "disabled": false + }, + { + "title": "保定高新技术产业开发区", + "id": "130671", + "children": [], + "disabled": false + }, + { + "title": "保定白沟新城", + "id": "130672", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "张家口市", + "id": "130700", + "children": [ + { + "title": "桥东区", + "id": "130702", + "children": [], + "disabled": false + }, + { + "title": "桥西区", + "id": "130703", + "children": [], + "disabled": false + }, + { + "title": "宣化区", + "id": "130705", + "children": [], + "disabled": false + }, + { + "title": "下花园区", + "id": "130706", + "children": [], + "disabled": false + }, + { + "title": "万全区", + "id": "130708", + "children": [], + "disabled": false + }, + { + "title": "崇礼区", + "id": "130709", + "children": [], + "disabled": false + }, + { + "title": "张北县", + "id": "130722", + "children": [], + "disabled": false + }, + { + "title": "康保县", + "id": "130723", + "children": [], + "disabled": false + }, + { + "title": "沽源县", + "id": "130724", + "children": [], + "disabled": false + }, + { + "title": "尚义县", + "id": "130725", + "children": [], + "disabled": false + }, + { + "title": "蔚县", + "id": "130726", + "children": [], + "disabled": false + }, + { + "title": "阳原县", + "id": "130727", + "children": [], + "disabled": false + }, + { + "title": "怀安县", + "id": "130728", + "children": [], + "disabled": false + }, + { + "title": "怀来县", + "id": "130730", + "children": [], + "disabled": false + }, + { + "title": "涿鹿县", + "id": "130731", + "children": [], + "disabled": false + }, + { + "title": "赤城县", + "id": "130732", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130701", + "children": [], + "disabled": false + }, + { + "title": "张家口经济开发区", + "id": "130771", + "children": [], + "disabled": false + }, + { + "title": "张家口市察北管理区", + "id": "130772", + "children": [], + "disabled": false + }, + { + "title": "张家口市塞北管理区", + "id": "130773", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "承德市", + "id": "130800", + "children": [ + { + "title": "双桥区", + "id": "130802", + "children": [], + "disabled": false + }, + { + "title": "双滦区", + "id": "130803", + "children": [], + "disabled": false + }, + { + "title": "鹰手营子矿区", + "id": "130804", + "children": [], + "disabled": false + }, + { + "title": "承德县", + "id": "130821", + "children": [], + "disabled": false + }, + { + "title": "兴隆县", + "id": "130822", + "children": [], + "disabled": false + }, + { + "title": "滦平县", + "id": "130824", + "children": [], + "disabled": false + }, + { + "title": "隆化县", + "id": "130825", + "children": [], + "disabled": false + }, + { + "title": "丰宁满族自治县", + "id": "130826", + "children": [], + "disabled": false + }, + { + "title": "宽城满族自治县", + "id": "130827", + "children": [], + "disabled": false + }, + { + "title": "围场满族蒙古族自治县", + "id": "130828", + "children": [], + "disabled": false + }, + { + "title": "平泉市", + "id": "130881", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130801", + "children": [], + "disabled": false + }, + { + "title": "承德高新技术产业开发区", + "id": "130871", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "沧州市", + "id": "130900", + "children": [ + { + "title": "新华区", + "id": "130902", + "children": [], + "disabled": false + }, + { + "title": "运河区", + "id": "130903", + "children": [], + "disabled": false + }, + { + "title": "沧县", + "id": "130921", + "children": [], + "disabled": false + }, + { + "title": "青县", + "id": "130922", + "children": [], + "disabled": false + }, + { + "title": "东光县", + "id": "130923", + "children": [], + "disabled": false + }, + { + "title": "海兴县", + "id": "130924", + "children": [], + "disabled": false + }, + { + "title": "盐山县", + "id": "130925", + "children": [], + "disabled": false + }, + { + "title": "肃宁县", + "id": "130926", + "children": [], + "disabled": false + }, + { + "title": "南皮县", + "id": "130927", + "children": [], + "disabled": false + }, + { + "title": "吴桥县", + "id": "130928", + "children": [], + "disabled": false + }, + { + "title": "献县", + "id": "130929", + "children": [], + "disabled": false + }, + { + "title": "孟村回族自治县", + "id": "130930", + "children": [], + "disabled": false + }, + { + "title": "泊头市", + "id": "130981", + "children": [], + "disabled": false + }, + { + "title": "任丘市", + "id": "130982", + "children": [], + "disabled": false + }, + { + "title": "黄骅市", + "id": "130983", + "children": [], + "disabled": false + }, + { + "title": "河间市", + "id": "130984", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "130901", + "children": [], + "disabled": false + }, + { + "title": "河北沧州经济开发区", + "id": "130971", + "children": [], + "disabled": false + }, + { + "title": "沧州高新技术产业开发区", + "id": "130972", + "children": [], + "disabled": false + }, + { + "title": "沧州渤海新区", + "id": "130973", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "廊坊市", + "id": "131000", + "children": [ + { + "title": "安次区", + "id": "131002", + "children": [], + "disabled": false + }, + { + "title": "广阳区", + "id": "131003", + "children": [], + "disabled": false + }, + { + "title": "固安县", + "id": "131022", + "children": [], + "disabled": false + }, + { + "title": "永清县", + "id": "131023", + "children": [], + "disabled": false + }, + { + "title": "香河县", + "id": "131024", + "children": [], + "disabled": false + }, + { + "title": "大城县", + "id": "131025", + "children": [], + "disabled": false + }, + { + "title": "文安县", + "id": "131026", + "children": [], + "disabled": false + }, + { + "title": "大厂回族自治县", + "id": "131028", + "children": [], + "disabled": false + }, + { + "title": "霸州市", + "id": "131081", + "children": [], + "disabled": false + }, + { + "title": "三河市", + "id": "131082", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "131001", + "children": [], + "disabled": false + }, + { + "title": "廊坊经济技术开发区", + "id": "131071", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "衡水市", + "id": "131100", + "children": [ + { + "title": "桃城区", + "id": "131102", + "children": [], + "disabled": false + }, + { + "title": "冀州区", + "id": "131103", + "children": [], + "disabled": false + }, + { + "title": "枣强县", + "id": "131121", + "children": [], + "disabled": false + }, + { + "title": "武邑县", + "id": "131122", + "children": [], + "disabled": false + }, + { + "title": "武强县", + "id": "131123", + "children": [], + "disabled": false + }, + { + "title": "饶阳县", + "id": "131124", + "children": [], + "disabled": false + }, + { + "title": "安平县", + "id": "131125", + "children": [], + "disabled": false + }, + { + "title": "故城县", + "id": "131126", + "children": [], + "disabled": false + }, + { + "title": "景县", + "id": "131127", + "children": [], + "disabled": false + }, + { + "title": "阜城县", + "id": "131128", + "children": [], + "disabled": false + }, + { + "title": "深州市", + "id": "131182", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "131101", + "children": [], + "disabled": false + }, + { + "title": "河北衡水高新技术产业开发区", + "id": "131171", + "children": [], + "disabled": false + }, + { + "title": "衡水滨湖新区", + "id": "131172", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "山西省", + "id": "140000", + "children": [ + { + "title": "太原市", + "id": "140100", + "children": [ + { + "title": "小店区", + "id": "140105", + "children": [], + "disabled": false + }, + { + "title": "迎泽区", + "id": "140106", + "children": [], + "disabled": false + }, + { + "title": "杏花岭区", + "id": "140107", + "children": [], + "disabled": false + }, + { + "title": "尖草坪区", + "id": "140108", + "children": [], + "disabled": false + }, + { + "title": "万柏林区", + "id": "140109", + "children": [], + "disabled": false + }, + { + "title": "晋源区", + "id": "140110", + "children": [], + "disabled": false + }, + { + "title": "清徐县", + "id": "140121", + "children": [], + "disabled": false + }, + { + "title": "阳曲县", + "id": "140122", + "children": [], + "disabled": false + }, + { + "title": "娄烦县", + "id": "140123", + "children": [], + "disabled": false + }, + { + "title": "古交市", + "id": "140181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140101", + "children": [], + "disabled": false + }, + { + "title": "山西转型综合改革示范区", + "id": "140171", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "大同市", + "id": "140200", + "children": [ + { + "title": "新荣区", + "id": "140212", + "children": [], + "disabled": false + }, + { + "title": "平城区", + "id": "140213", + "children": [], + "disabled": false + }, + { + "title": "云冈区", + "id": "140214", + "children": [], + "disabled": false + }, + { + "title": "云州区", + "id": "140215", + "children": [], + "disabled": false + }, + { + "title": "阳高县", + "id": "140221", + "children": [], + "disabled": false + }, + { + "title": "天镇县", + "id": "140222", + "children": [], + "disabled": false + }, + { + "title": "广灵县", + "id": "140223", + "children": [], + "disabled": false + }, + { + "title": "灵丘县", + "id": "140224", + "children": [], + "disabled": false + }, + { + "title": "浑源县", + "id": "140225", + "children": [], + "disabled": false + }, + { + "title": "左云县", + "id": "140226", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140201", + "children": [], + "disabled": false + }, + { + "title": "山西大同经济开发区", + "id": "140271", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阳泉市", + "id": "140300", + "children": [ + { + "title": "城区", + "id": "140302", + "children": [], + "disabled": false + }, + { + "title": "矿区", + "id": "140303", + "children": [], + "disabled": false + }, + { + "title": "郊区", + "id": "140311", + "children": [], + "disabled": false + }, + { + "title": "平定县", + "id": "140321", + "children": [], + "disabled": false + }, + { + "title": "盂县", + "id": "140322", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "长治市", + "id": "140400", + "children": [ + { + "title": "潞州区", + "id": "140403", + "children": [], + "disabled": false + }, + { + "title": "上党区", + "id": "140404", + "children": [], + "disabled": false + }, + { + "title": "屯留区", + "id": "140405", + "children": [], + "disabled": false + }, + { + "title": "潞城区", + "id": "140406", + "children": [], + "disabled": false + }, + { + "title": "襄垣县", + "id": "140423", + "children": [], + "disabled": false + }, + { + "title": "平顺县", + "id": "140425", + "children": [], + "disabled": false + }, + { + "title": "黎城县", + "id": "140426", + "children": [], + "disabled": false + }, + { + "title": "壶关县", + "id": "140427", + "children": [], + "disabled": false + }, + { + "title": "长子县", + "id": "140428", + "children": [], + "disabled": false + }, + { + "title": "武乡县", + "id": "140429", + "children": [], + "disabled": false + }, + { + "title": "沁县", + "id": "140430", + "children": [], + "disabled": false + }, + { + "title": "沁源县", + "id": "140431", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140401", + "children": [], + "disabled": false + }, + { + "title": "山西长治高新技术产业园区", + "id": "140471", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "晋城市", + "id": "140500", + "children": [ + { + "title": "城区", + "id": "140502", + "children": [], + "disabled": false + }, + { + "title": "沁水县", + "id": "140521", + "children": [], + "disabled": false + }, + { + "title": "阳城县", + "id": "140522", + "children": [], + "disabled": false + }, + { + "title": "陵川县", + "id": "140524", + "children": [], + "disabled": false + }, + { + "title": "泽州县", + "id": "140525", + "children": [], + "disabled": false + }, + { + "title": "高平市", + "id": "140581", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "朔州市", + "id": "140600", + "children": [ + { + "title": "朔城区", + "id": "140602", + "children": [], + "disabled": false + }, + { + "title": "平鲁区", + "id": "140603", + "children": [], + "disabled": false + }, + { + "title": "山阴县", + "id": "140621", + "children": [], + "disabled": false + }, + { + "title": "应县", + "id": "140622", + "children": [], + "disabled": false + }, + { + "title": "右玉县", + "id": "140623", + "children": [], + "disabled": false + }, + { + "title": "怀仁市", + "id": "140681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140601", + "children": [], + "disabled": false + }, + { + "title": "山西朔州经济开发区", + "id": "140671", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "晋中市", + "id": "140700", + "children": [ + { + "title": "榆次区", + "id": "140702", + "children": [], + "disabled": false + }, + { + "title": "太谷区", + "id": "140703", + "children": [], + "disabled": false + }, + { + "title": "榆社县", + "id": "140721", + "children": [], + "disabled": false + }, + { + "title": "左权县", + "id": "140722", + "children": [], + "disabled": false + }, + { + "title": "和顺县", + "id": "140723", + "children": [], + "disabled": false + }, + { + "title": "昔阳县", + "id": "140724", + "children": [], + "disabled": false + }, + { + "title": "寿阳县", + "id": "140725", + "children": [], + "disabled": false + }, + { + "title": "祁县", + "id": "140727", + "children": [], + "disabled": false + }, + { + "title": "平遥县", + "id": "140728", + "children": [], + "disabled": false + }, + { + "title": "灵石县", + "id": "140729", + "children": [], + "disabled": false + }, + { + "title": "介休市", + "id": "140781", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "运城市", + "id": "140800", + "children": [ + { + "title": "盐湖区", + "id": "140802", + "children": [], + "disabled": false + }, + { + "title": "临猗县", + "id": "140821", + "children": [], + "disabled": false + }, + { + "title": "万荣县", + "id": "140822", + "children": [], + "disabled": false + }, + { + "title": "闻喜县", + "id": "140823", + "children": [], + "disabled": false + }, + { + "title": "稷山县", + "id": "140824", + "children": [], + "disabled": false + }, + { + "title": "新绛县", + "id": "140825", + "children": [], + "disabled": false + }, + { + "title": "绛县", + "id": "140826", + "children": [], + "disabled": false + }, + { + "title": "垣曲县", + "id": "140827", + "children": [], + "disabled": false + }, + { + "title": "夏县", + "id": "140828", + "children": [], + "disabled": false + }, + { + "title": "平陆县", + "id": "140829", + "children": [], + "disabled": false + }, + { + "title": "芮城县", + "id": "140830", + "children": [], + "disabled": false + }, + { + "title": "永济市", + "id": "140881", + "children": [], + "disabled": false + }, + { + "title": "河津市", + "id": "140882", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "忻州市", + "id": "140900", + "children": [ + { + "title": "忻府区", + "id": "140902", + "children": [], + "disabled": false + }, + { + "title": "定襄县", + "id": "140921", + "children": [], + "disabled": false + }, + { + "title": "五台县", + "id": "140922", + "children": [], + "disabled": false + }, + { + "title": "代县", + "id": "140923", + "children": [], + "disabled": false + }, + { + "title": "繁峙县", + "id": "140924", + "children": [], + "disabled": false + }, + { + "title": "宁武县", + "id": "140925", + "children": [], + "disabled": false + }, + { + "title": "静乐县", + "id": "140926", + "children": [], + "disabled": false + }, + { + "title": "神池县", + "id": "140927", + "children": [], + "disabled": false + }, + { + "title": "五寨县", + "id": "140928", + "children": [], + "disabled": false + }, + { + "title": "岢岚县", + "id": "140929", + "children": [], + "disabled": false + }, + { + "title": "河曲县", + "id": "140930", + "children": [], + "disabled": false + }, + { + "title": "保德县", + "id": "140931", + "children": [], + "disabled": false + }, + { + "title": "偏关县", + "id": "140932", + "children": [], + "disabled": false + }, + { + "title": "原平市", + "id": "140981", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "140901", + "children": [], + "disabled": false + }, + { + "title": "五台山风景名胜区", + "id": "140971", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "临汾市", + "id": "141000", + "children": [ + { + "title": "尧都区", + "id": "141002", + "children": [], + "disabled": false + }, + { + "title": "曲沃县", + "id": "141021", + "children": [], + "disabled": false + }, + { + "title": "翼城县", + "id": "141022", + "children": [], + "disabled": false + }, + { + "title": "襄汾县", + "id": "141023", + "children": [], + "disabled": false + }, + { + "title": "洪洞县", + "id": "141024", + "children": [], + "disabled": false + }, + { + "title": "古县", + "id": "141025", + "children": [], + "disabled": false + }, + { + "title": "安泽县", + "id": "141026", + "children": [], + "disabled": false + }, + { + "title": "浮山县", + "id": "141027", + "children": [], + "disabled": false + }, + { + "title": "吉县", + "id": "141028", + "children": [], + "disabled": false + }, + { + "title": "乡宁县", + "id": "141029", + "children": [], + "disabled": false + }, + { + "title": "大宁县", + "id": "141030", + "children": [], + "disabled": false + }, + { + "title": "隰县", + "id": "141031", + "children": [], + "disabled": false + }, + { + "title": "永和县", + "id": "141032", + "children": [], + "disabled": false + }, + { + "title": "蒲县", + "id": "141033", + "children": [], + "disabled": false + }, + { + "title": "汾西县", + "id": "141034", + "children": [], + "disabled": false + }, + { + "title": "侯马市", + "id": "141081", + "children": [], + "disabled": false + }, + { + "title": "霍州市", + "id": "141082", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "141001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "吕梁市", + "id": "141100", + "children": [ + { + "title": "离石区", + "id": "141102", + "children": [], + "disabled": false + }, + { + "title": "文水县", + "id": "141121", + "children": [], + "disabled": false + }, + { + "title": "交城县", + "id": "141122", + "children": [], + "disabled": false + }, + { + "title": "兴县", + "id": "141123", + "children": [], + "disabled": false + }, + { + "title": "临县", + "id": "141124", + "children": [], + "disabled": false + }, + { + "title": "柳林县", + "id": "141125", + "children": [], + "disabled": false + }, + { + "title": "石楼县", + "id": "141126", + "children": [], + "disabled": false + }, + { + "title": "岚县", + "id": "141127", + "children": [], + "disabled": false + }, + { + "title": "方山县", + "id": "141128", + "children": [], + "disabled": false + }, + { + "title": "中阳县", + "id": "141129", + "children": [], + "disabled": false + }, + { + "title": "交口县", + "id": "141130", + "children": [], + "disabled": false + }, + { + "title": "孝义市", + "id": "141181", + "children": [], + "disabled": false + }, + { + "title": "汾阳市", + "id": "141182", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "141101", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "内蒙古自治区", + "id": "150000", + "children": [ + { + "title": "呼和浩特市", + "id": "150100", + "children": [ + { + "title": "新城区", + "id": "150102", + "children": [], + "disabled": false + }, + { + "title": "回民区", + "id": "150103", + "children": [], + "disabled": false + }, + { + "title": "玉泉区", + "id": "150104", + "children": [], + "disabled": false + }, + { + "title": "赛罕区", + "id": "150105", + "children": [], + "disabled": false + }, + { + "title": "土默特左旗", + "id": "150121", + "children": [], + "disabled": false + }, + { + "title": "托克托县", + "id": "150122", + "children": [], + "disabled": false + }, + { + "title": "和林格尔县", + "id": "150123", + "children": [], + "disabled": false + }, + { + "title": "清水河县", + "id": "150124", + "children": [], + "disabled": false + }, + { + "title": "武川县", + "id": "150125", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150101", + "children": [], + "disabled": false + }, + { + "title": "呼和浩特经济技术开发区", + "id": "150172", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "包头市", + "id": "150200", + "children": [ + { + "title": "东河区", + "id": "150202", + "children": [], + "disabled": false + }, + { + "title": "昆都仑区", + "id": "150203", + "children": [], + "disabled": false + }, + { + "title": "青山区", + "id": "150204", + "children": [], + "disabled": false + }, + { + "title": "石拐区", + "id": "150205", + "children": [], + "disabled": false + }, + { + "title": "白云鄂博矿区", + "id": "150206", + "children": [], + "disabled": false + }, + { + "title": "九原区", + "id": "150207", + "children": [], + "disabled": false + }, + { + "title": "土默特右旗", + "id": "150221", + "children": [], + "disabled": false + }, + { + "title": "固阳县", + "id": "150222", + "children": [], + "disabled": false + }, + { + "title": "达尔罕茂明安联合旗", + "id": "150223", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150201", + "children": [], + "disabled": false + }, + { + "title": "包头稀土高新技术产业开发区", + "id": "150271", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "乌海市", + "id": "150300", + "children": [ + { + "title": "海勃湾区", + "id": "150302", + "children": [], + "disabled": false + }, + { + "title": "海南区", + "id": "150303", + "children": [], + "disabled": false + }, + { + "title": "乌达区", + "id": "150304", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "赤峰市", + "id": "150400", + "children": [ + { + "title": "红山区", + "id": "150402", + "children": [], + "disabled": false + }, + { + "title": "元宝山区", + "id": "150403", + "children": [], + "disabled": false + }, + { + "title": "松山区", + "id": "150404", + "children": [], + "disabled": false + }, + { + "title": "阿鲁科尔沁旗", + "id": "150421", + "children": [], + "disabled": false + }, + { + "title": "巴林左旗", + "id": "150422", + "children": [], + "disabled": false + }, + { + "title": "巴林右旗", + "id": "150423", + "children": [], + "disabled": false + }, + { + "title": "林西县", + "id": "150424", + "children": [], + "disabled": false + }, + { + "title": "克什克腾旗", + "id": "150425", + "children": [], + "disabled": false + }, + { + "title": "翁牛特旗", + "id": "150426", + "children": [], + "disabled": false + }, + { + "title": "喀喇沁旗", + "id": "150428", + "children": [], + "disabled": false + }, + { + "title": "宁城县", + "id": "150429", + "children": [], + "disabled": false + }, + { + "title": "敖汉旗", + "id": "150430", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "通辽市", + "id": "150500", + "children": [ + { + "title": "科尔沁区", + "id": "150502", + "children": [], + "disabled": false + }, + { + "title": "科尔沁左翼中旗", + "id": "150521", + "children": [], + "disabled": false + }, + { + "title": "科尔沁左翼后旗", + "id": "150522", + "children": [], + "disabled": false + }, + { + "title": "开鲁县", + "id": "150523", + "children": [], + "disabled": false + }, + { + "title": "库伦旗", + "id": "150524", + "children": [], + "disabled": false + }, + { + "title": "奈曼旗", + "id": "150525", + "children": [], + "disabled": false + }, + { + "title": "扎鲁特旗", + "id": "150526", + "children": [], + "disabled": false + }, + { + "title": "霍林郭勒市", + "id": "150581", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150501", + "children": [], + "disabled": false + }, + { + "title": "通辽经济技术开发区", + "id": "150571", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "鄂尔多斯市", + "id": "150600", + "children": [ + { + "title": "东胜区", + "id": "150602", + "children": [], + "disabled": false + }, + { + "title": "康巴什区", + "id": "150603", + "children": [], + "disabled": false + }, + { + "title": "达拉特旗", + "id": "150621", + "children": [], + "disabled": false + }, + { + "title": "准格尔旗", + "id": "150622", + "children": [], + "disabled": false + }, + { + "title": "鄂托克前旗", + "id": "150623", + "children": [], + "disabled": false + }, + { + "title": "鄂托克旗", + "id": "150624", + "children": [], + "disabled": false + }, + { + "title": "杭锦旗", + "id": "150625", + "children": [], + "disabled": false + }, + { + "title": "乌审旗", + "id": "150626", + "children": [], + "disabled": false + }, + { + "title": "伊金霍洛旗", + "id": "150627", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "呼伦贝尔市", + "id": "150700", + "children": [ + { + "title": "海拉尔区", + "id": "150702", + "children": [], + "disabled": false + }, + { + "title": "扎赉诺尔区", + "id": "150703", + "children": [], + "disabled": false + }, + { + "title": "阿荣旗", + "id": "150721", + "children": [], + "disabled": false + }, + { + "title": "莫力达瓦达斡尔族自治旗", + "id": "150722", + "children": [], + "disabled": false + }, + { + "title": "鄂伦春自治旗", + "id": "150723", + "children": [], + "disabled": false + }, + { + "title": "鄂温克族自治旗", + "id": "150724", + "children": [], + "disabled": false + }, + { + "title": "陈巴尔虎旗", + "id": "150725", + "children": [], + "disabled": false + }, + { + "title": "新巴尔虎左旗", + "id": "150726", + "children": [], + "disabled": false + }, + { + "title": "新巴尔虎右旗", + "id": "150727", + "children": [], + "disabled": false + }, + { + "title": "满洲里市", + "id": "150781", + "children": [], + "disabled": false + }, + { + "title": "牙克石市", + "id": "150782", + "children": [], + "disabled": false + }, + { + "title": "扎兰屯市", + "id": "150783", + "children": [], + "disabled": false + }, + { + "title": "额尔古纳市", + "id": "150784", + "children": [], + "disabled": false + }, + { + "title": "根河市", + "id": "150785", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "巴彦淖尔市", + "id": "150800", + "children": [ + { + "title": "临河区", + "id": "150802", + "children": [], + "disabled": false + }, + { + "title": "五原县", + "id": "150821", + "children": [], + "disabled": false + }, + { + "title": "磴口县", + "id": "150822", + "children": [], + "disabled": false + }, + { + "title": "乌拉特前旗", + "id": "150823", + "children": [], + "disabled": false + }, + { + "title": "乌拉特中旗", + "id": "150824", + "children": [], + "disabled": false + }, + { + "title": "乌拉特后旗", + "id": "150825", + "children": [], + "disabled": false + }, + { + "title": "杭锦后旗", + "id": "150826", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "乌兰察布市", + "id": "150900", + "children": [ + { + "title": "集宁区", + "id": "150902", + "children": [], + "disabled": false + }, + { + "title": "卓资县", + "id": "150921", + "children": [], + "disabled": false + }, + { + "title": "化德县", + "id": "150922", + "children": [], + "disabled": false + }, + { + "title": "商都县", + "id": "150923", + "children": [], + "disabled": false + }, + { + "title": "兴和县", + "id": "150924", + "children": [], + "disabled": false + }, + { + "title": "凉城县", + "id": "150925", + "children": [], + "disabled": false + }, + { + "title": "察哈尔右翼前旗", + "id": "150926", + "children": [], + "disabled": false + }, + { + "title": "察哈尔右翼中旗", + "id": "150927", + "children": [], + "disabled": false + }, + { + "title": "察哈尔右翼后旗", + "id": "150928", + "children": [], + "disabled": false + }, + { + "title": "四子王旗", + "id": "150929", + "children": [], + "disabled": false + }, + { + "title": "丰镇市", + "id": "150981", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "150901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "兴安盟", + "id": "152200", + "children": [ + { + "title": "乌兰浩特市", + "id": "152201", + "children": [], + "disabled": false + }, + { + "title": "阿尔山市", + "id": "152202", + "children": [], + "disabled": false + }, + { + "title": "科尔沁右翼前旗", + "id": "152221", + "children": [], + "disabled": false + }, + { + "title": "科尔沁右翼中旗", + "id": "152222", + "children": [], + "disabled": false + }, + { + "title": "扎赉特旗", + "id": "152223", + "children": [], + "disabled": false + }, + { + "title": "突泉县", + "id": "152224", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "锡林郭勒盟", + "id": "152500", + "children": [ + { + "title": "二连浩特市", + "id": "152501", + "children": [], + "disabled": false + }, + { + "title": "锡林浩特市", + "id": "152502", + "children": [], + "disabled": false + }, + { + "title": "阿巴嘎旗", + "id": "152522", + "children": [], + "disabled": false + }, + { + "title": "苏尼特左旗", + "id": "152523", + "children": [], + "disabled": false + }, + { + "title": "苏尼特右旗", + "id": "152524", + "children": [], + "disabled": false + }, + { + "title": "东乌珠穆沁旗", + "id": "152525", + "children": [], + "disabled": false + }, + { + "title": "西乌珠穆沁旗", + "id": "152526", + "children": [], + "disabled": false + }, + { + "title": "太仆寺旗", + "id": "152527", + "children": [], + "disabled": false + }, + { + "title": "镶黄旗", + "id": "152528", + "children": [], + "disabled": false + }, + { + "title": "正镶白旗", + "id": "152529", + "children": [], + "disabled": false + }, + { + "title": "正蓝旗", + "id": "152530", + "children": [], + "disabled": false + }, + { + "title": "多伦县", + "id": "152531", + "children": [], + "disabled": false + }, + { + "title": "乌拉盖管委会", + "id": "152571", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阿拉善盟", + "id": "152900", + "children": [ + { + "title": "阿拉善左旗", + "id": "152921", + "children": [], + "disabled": false + }, + { + "title": "阿拉善右旗", + "id": "152922", + "children": [], + "disabled": false + }, + { + "title": "额济纳旗", + "id": "152923", + "children": [], + "disabled": false + }, + { + "title": "内蒙古阿拉善高新技术产业开发区", + "id": "152971", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "辽宁省", + "id": "210000", + "children": [ + { + "title": "沈阳市", + "id": "210100", + "children": [ + { + "title": "和平区", + "id": "210102", + "children": [], + "disabled": false + }, + { + "title": "沈河区", + "id": "210103", + "children": [], + "disabled": false + }, + { + "title": "大东区", + "id": "210104", + "children": [], + "disabled": false + }, + { + "title": "皇姑区", + "id": "210105", + "children": [], + "disabled": false + }, + { + "title": "铁西区", + "id": "210106", + "children": [], + "disabled": false + }, + { + "title": "苏家屯区", + "id": "210111", + "children": [], + "disabled": false + }, + { + "title": "浑南区", + "id": "210112", + "children": [], + "disabled": false + }, + { + "title": "沈北新区", + "id": "210113", + "children": [], + "disabled": false + }, + { + "title": "于洪区", + "id": "210114", + "children": [], + "disabled": false + }, + { + "title": "辽中区", + "id": "210115", + "children": [], + "disabled": false + }, + { + "title": "康平县", + "id": "210123", + "children": [], + "disabled": false + }, + { + "title": "法库县", + "id": "210124", + "children": [], + "disabled": false + }, + { + "title": "新民市", + "id": "210181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "大连市", + "id": "210200", + "children": [ + { + "title": "中山区", + "id": "210202", + "children": [], + "disabled": false + }, + { + "title": "西岗区", + "id": "210203", + "children": [], + "disabled": false + }, + { + "title": "沙河口区", + "id": "210204", + "children": [], + "disabled": false + }, + { + "title": "甘井子区", + "id": "210211", + "children": [], + "disabled": false + }, + { + "title": "旅顺口区", + "id": "210212", + "children": [], + "disabled": false + }, + { + "title": "金州区", + "id": "210213", + "children": [], + "disabled": false + }, + { + "title": "普兰店区", + "id": "210214", + "children": [], + "disabled": false + }, + { + "title": "长海县", + "id": "210224", + "children": [], + "disabled": false + }, + { + "title": "瓦房店市", + "id": "210281", + "children": [], + "disabled": false + }, + { + "title": "庄河市", + "id": "210283", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "鞍山市", + "id": "210300", + "children": [ + { + "title": "铁东区", + "id": "210302", + "children": [], + "disabled": false + }, + { + "title": "铁西区", + "id": "210303", + "children": [], + "disabled": false + }, + { + "title": "立山区", + "id": "210304", + "children": [], + "disabled": false + }, + { + "title": "千山区", + "id": "210311", + "children": [], + "disabled": false + }, + { + "title": "台安县", + "id": "210321", + "children": [], + "disabled": false + }, + { + "title": "岫岩满族自治县", + "id": "210323", + "children": [], + "disabled": false + }, + { + "title": "海城市", + "id": "210381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "抚顺市", + "id": "210400", + "children": [ + { + "title": "新抚区", + "id": "210402", + "children": [], + "disabled": false + }, + { + "title": "东洲区", + "id": "210403", + "children": [], + "disabled": false + }, + { + "title": "望花区", + "id": "210404", + "children": [], + "disabled": false + }, + { + "title": "顺城区", + "id": "210411", + "children": [], + "disabled": false + }, + { + "title": "抚顺县", + "id": "210421", + "children": [], + "disabled": false + }, + { + "title": "新宾满族自治县", + "id": "210422", + "children": [], + "disabled": false + }, + { + "title": "清原满族自治县", + "id": "210423", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "本溪市", + "id": "210500", + "children": [ + { + "title": "平山区", + "id": "210502", + "children": [], + "disabled": false + }, + { + "title": "溪湖区", + "id": "210503", + "children": [], + "disabled": false + }, + { + "title": "明山区", + "id": "210504", + "children": [], + "disabled": false + }, + { + "title": "南芬区", + "id": "210505", + "children": [], + "disabled": false + }, + { + "title": "本溪满族自治县", + "id": "210521", + "children": [], + "disabled": false + }, + { + "title": "桓仁满族自治县", + "id": "210522", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "丹东市", + "id": "210600", + "children": [ + { + "title": "元宝区", + "id": "210602", + "children": [], + "disabled": false + }, + { + "title": "振兴区", + "id": "210603", + "children": [], + "disabled": false + }, + { + "title": "振安区", + "id": "210604", + "children": [], + "disabled": false + }, + { + "title": "宽甸满族自治县", + "id": "210624", + "children": [], + "disabled": false + }, + { + "title": "东港市", + "id": "210681", + "children": [], + "disabled": false + }, + { + "title": "凤城市", + "id": "210682", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "锦州市", + "id": "210700", + "children": [ + { + "title": "古塔区", + "id": "210702", + "children": [], + "disabled": false + }, + { + "title": "凌河区", + "id": "210703", + "children": [], + "disabled": false + }, + { + "title": "太和区", + "id": "210711", + "children": [], + "disabled": false + }, + { + "title": "黑山县", + "id": "210726", + "children": [], + "disabled": false + }, + { + "title": "义县", + "id": "210727", + "children": [], + "disabled": false + }, + { + "title": "凌海市", + "id": "210781", + "children": [], + "disabled": false + }, + { + "title": "北镇市", + "id": "210782", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "营口市", + "id": "210800", + "children": [ + { + "title": "站前区", + "id": "210802", + "children": [], + "disabled": false + }, + { + "title": "西市区", + "id": "210803", + "children": [], + "disabled": false + }, + { + "title": "鲅鱼圈区", + "id": "210804", + "children": [], + "disabled": false + }, + { + "title": "老边区", + "id": "210811", + "children": [], + "disabled": false + }, + { + "title": "盖州市", + "id": "210881", + "children": [], + "disabled": false + }, + { + "title": "大石桥市", + "id": "210882", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阜新市", + "id": "210900", + "children": [ + { + "title": "海州区", + "id": "210902", + "children": [], + "disabled": false + }, + { + "title": "新邱区", + "id": "210903", + "children": [], + "disabled": false + }, + { + "title": "太平区", + "id": "210904", + "children": [], + "disabled": false + }, + { + "title": "清河门区", + "id": "210905", + "children": [], + "disabled": false + }, + { + "title": "细河区", + "id": "210911", + "children": [], + "disabled": false + }, + { + "title": "阜新蒙古族自治县", + "id": "210921", + "children": [], + "disabled": false + }, + { + "title": "彰武县", + "id": "210922", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "210901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "辽阳市", + "id": "211000", + "children": [ + { + "title": "白塔区", + "id": "211002", + "children": [], + "disabled": false + }, + { + "title": "文圣区", + "id": "211003", + "children": [], + "disabled": false + }, + { + "title": "宏伟区", + "id": "211004", + "children": [], + "disabled": false + }, + { + "title": "弓长岭区", + "id": "211005", + "children": [], + "disabled": false + }, + { + "title": "太子河区", + "id": "211011", + "children": [], + "disabled": false + }, + { + "title": "辽阳县", + "id": "211021", + "children": [], + "disabled": false + }, + { + "title": "灯塔市", + "id": "211081", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "211001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "盘锦市", + "id": "211100", + "children": [ + { + "title": "双台子区", + "id": "211102", + "children": [], + "disabled": false + }, + { + "title": "兴隆台区", + "id": "211103", + "children": [], + "disabled": false + }, + { + "title": "大洼区", + "id": "211104", + "children": [], + "disabled": false + }, + { + "title": "盘山县", + "id": "211122", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "211101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "铁岭市", + "id": "211200", + "children": [ + { + "title": "银州区", + "id": "211202", + "children": [], + "disabled": false + }, + { + "title": "清河区", + "id": "211204", + "children": [], + "disabled": false + }, + { + "title": "铁岭县", + "id": "211221", + "children": [], + "disabled": false + }, + { + "title": "西丰县", + "id": "211223", + "children": [], + "disabled": false + }, + { + "title": "昌图县", + "id": "211224", + "children": [], + "disabled": false + }, + { + "title": "调兵山市", + "id": "211281", + "children": [], + "disabled": false + }, + { + "title": "开原市", + "id": "211282", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "211201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "朝阳市", + "id": "211300", + "children": [ + { + "title": "双塔区", + "id": "211302", + "children": [], + "disabled": false + }, + { + "title": "龙城区", + "id": "211303", + "children": [], + "disabled": false + }, + { + "title": "朝阳县", + "id": "211321", + "children": [], + "disabled": false + }, + { + "title": "建平县", + "id": "211322", + "children": [], + "disabled": false + }, + { + "title": "喀喇沁左翼蒙古族自治县", + "id": "211324", + "children": [], + "disabled": false + }, + { + "title": "北票市", + "id": "211381", + "children": [], + "disabled": false + }, + { + "title": "凌源市", + "id": "211382", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "211301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "葫芦岛市", + "id": "211400", + "children": [ + { + "title": "连山区", + "id": "211402", + "children": [], + "disabled": false + }, + { + "title": "龙港区", + "id": "211403", + "children": [], + "disabled": false + }, + { + "title": "南票区", + "id": "211404", + "children": [], + "disabled": false + }, + { + "title": "绥中县", + "id": "211421", + "children": [], + "disabled": false + }, + { + "title": "建昌县", + "id": "211422", + "children": [], + "disabled": false + }, + { + "title": "兴城市", + "id": "211481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "211401", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "吉林省", + "id": "220000", + "children": [ + { + "title": "长春市", + "id": "220100", + "children": [ + { + "title": "南关区", + "id": "220102", + "children": [], + "disabled": false + }, + { + "title": "宽城区", + "id": "220103", + "children": [], + "disabled": false + }, + { + "title": "朝阳区", + "id": "220104", + "children": [], + "disabled": false + }, + { + "title": "二道区", + "id": "220105", + "children": [], + "disabled": false + }, + { + "title": "绿园区", + "id": "220106", + "children": [], + "disabled": false + }, + { + "title": "双阳区", + "id": "220112", + "children": [], + "disabled": false + }, + { + "title": "九台区", + "id": "220113", + "children": [], + "disabled": false + }, + { + "title": "农安县", + "id": "220122", + "children": [], + "disabled": false + }, + { + "title": "榆树市", + "id": "220182", + "children": [], + "disabled": false + }, + { + "title": "德惠市", + "id": "220183", + "children": [], + "disabled": false + }, + { + "title": "公主岭市", + "id": "220184", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220101", + "children": [], + "disabled": false + }, + { + "title": "长春经济技术开发区", + "id": "220171", + "children": [], + "disabled": false + }, + { + "title": "长春净月高新技术产业开发区", + "id": "220172", + "children": [], + "disabled": false + }, + { + "title": "长春高新技术产业开发区", + "id": "220173", + "children": [], + "disabled": false + }, + { + "title": "长春汽车经济技术开发区", + "id": "220174", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "吉林市", + "id": "220200", + "children": [ + { + "title": "昌邑区", + "id": "220202", + "children": [], + "disabled": false + }, + { + "title": "龙潭区", + "id": "220203", + "children": [], + "disabled": false + }, + { + "title": "船营区", + "id": "220204", + "children": [], + "disabled": false + }, + { + "title": "丰满区", + "id": "220211", + "children": [], + "disabled": false + }, + { + "title": "永吉县", + "id": "220221", + "children": [], + "disabled": false + }, + { + "title": "蛟河市", + "id": "220281", + "children": [], + "disabled": false + }, + { + "title": "桦甸市", + "id": "220282", + "children": [], + "disabled": false + }, + { + "title": "舒兰市", + "id": "220283", + "children": [], + "disabled": false + }, + { + "title": "磐石市", + "id": "220284", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220201", + "children": [], + "disabled": false + }, + { + "title": "吉林经济开发区", + "id": "220271", + "children": [], + "disabled": false + }, + { + "title": "吉林高新技术产业开发区", + "id": "220272", + "children": [], + "disabled": false + }, + { + "title": "吉林中国新加坡食品区", + "id": "220273", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "四平市", + "id": "220300", + "children": [ + { + "title": "铁西区", + "id": "220302", + "children": [], + "disabled": false + }, + { + "title": "铁东区", + "id": "220303", + "children": [], + "disabled": false + }, + { + "title": "梨树县", + "id": "220322", + "children": [], + "disabled": false + }, + { + "title": "伊通满族自治县", + "id": "220323", + "children": [], + "disabled": false + }, + { + "title": "双辽市", + "id": "220382", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "辽源市", + "id": "220400", + "children": [ + { + "title": "龙山区", + "id": "220402", + "children": [], + "disabled": false + }, + { + "title": "西安区", + "id": "220403", + "children": [], + "disabled": false + }, + { + "title": "东丰县", + "id": "220421", + "children": [], + "disabled": false + }, + { + "title": "东辽县", + "id": "220422", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "通化市", + "id": "220500", + "children": [ + { + "title": "东昌区", + "id": "220502", + "children": [], + "disabled": false + }, + { + "title": "二道江区", + "id": "220503", + "children": [], + "disabled": false + }, + { + "title": "通化县", + "id": "220521", + "children": [], + "disabled": false + }, + { + "title": "辉南县", + "id": "220523", + "children": [], + "disabled": false + }, + { + "title": "柳河县", + "id": "220524", + "children": [], + "disabled": false + }, + { + "title": "梅河口市", + "id": "220581", + "children": [], + "disabled": false + }, + { + "title": "集安市", + "id": "220582", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "白山市", + "id": "220600", + "children": [ + { + "title": "浑江区", + "id": "220602", + "children": [], + "disabled": false + }, + { + "title": "江源区", + "id": "220605", + "children": [], + "disabled": false + }, + { + "title": "抚松县", + "id": "220621", + "children": [], + "disabled": false + }, + { + "title": "靖宇县", + "id": "220622", + "children": [], + "disabled": false + }, + { + "title": "长白朝鲜族自治县", + "id": "220623", + "children": [], + "disabled": false + }, + { + "title": "临江市", + "id": "220681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "松原市", + "id": "220700", + "children": [ + { + "title": "宁江区", + "id": "220702", + "children": [], + "disabled": false + }, + { + "title": "前郭尔罗斯蒙古族自治县", + "id": "220721", + "children": [], + "disabled": false + }, + { + "title": "长岭县", + "id": "220722", + "children": [], + "disabled": false + }, + { + "title": "乾安县", + "id": "220723", + "children": [], + "disabled": false + }, + { + "title": "扶余市", + "id": "220781", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220701", + "children": [], + "disabled": false + }, + { + "title": "吉林松原经济开发区", + "id": "220771", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "白城市", + "id": "220800", + "children": [ + { + "title": "洮北区", + "id": "220802", + "children": [], + "disabled": false + }, + { + "title": "镇赉县", + "id": "220821", + "children": [], + "disabled": false + }, + { + "title": "通榆县", + "id": "220822", + "children": [], + "disabled": false + }, + { + "title": "洮南市", + "id": "220881", + "children": [], + "disabled": false + }, + { + "title": "大安市", + "id": "220882", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "220801", + "children": [], + "disabled": false + }, + { + "title": "吉林白城经济开发区", + "id": "220871", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "延边朝鲜族自治州", + "id": "222400", + "children": [ + { + "title": "延吉市", + "id": "222401", + "children": [], + "disabled": false + }, + { + "title": "图们市", + "id": "222402", + "children": [], + "disabled": false + }, + { + "title": "敦化市", + "id": "222403", + "children": [], + "disabled": false + }, + { + "title": "珲春市", + "id": "222404", + "children": [], + "disabled": false + }, + { + "title": "龙井市", + "id": "222405", + "children": [], + "disabled": false + }, + { + "title": "和龙市", + "id": "222406", + "children": [], + "disabled": false + }, + { + "title": "汪清县", + "id": "222424", + "children": [], + "disabled": false + }, + { + "title": "安图县", + "id": "222426", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黑龙江省", + "id": "230000", + "children": [ + { + "title": "哈尔滨市", + "id": "230100", + "children": [ + { + "title": "道里区", + "id": "230102", + "children": [], + "disabled": false + }, + { + "title": "南岗区", + "id": "230103", + "children": [], + "disabled": false + }, + { + "title": "道外区", + "id": "230104", + "children": [], + "disabled": false + }, + { + "title": "平房区", + "id": "230108", + "children": [], + "disabled": false + }, + { + "title": "松北区", + "id": "230109", + "children": [], + "disabled": false + }, + { + "title": "香坊区", + "id": "230110", + "children": [], + "disabled": false + }, + { + "title": "呼兰区", + "id": "230111", + "children": [], + "disabled": false + }, + { + "title": "阿城区", + "id": "230112", + "children": [], + "disabled": false + }, + { + "title": "双城区", + "id": "230113", + "children": [], + "disabled": false + }, + { + "title": "依兰县", + "id": "230123", + "children": [], + "disabled": false + }, + { + "title": "方正县", + "id": "230124", + "children": [], + "disabled": false + }, + { + "title": "宾县", + "id": "230125", + "children": [], + "disabled": false + }, + { + "title": "巴彦县", + "id": "230126", + "children": [], + "disabled": false + }, + { + "title": "木兰县", + "id": "230127", + "children": [], + "disabled": false + }, + { + "title": "通河县", + "id": "230128", + "children": [], + "disabled": false + }, + { + "title": "延寿县", + "id": "230129", + "children": [], + "disabled": false + }, + { + "title": "尚志市", + "id": "230183", + "children": [], + "disabled": false + }, + { + "title": "五常市", + "id": "230184", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "齐齐哈尔市", + "id": "230200", + "children": [ + { + "title": "龙沙区", + "id": "230202", + "children": [], + "disabled": false + }, + { + "title": "建华区", + "id": "230203", + "children": [], + "disabled": false + }, + { + "title": "铁锋区", + "id": "230204", + "children": [], + "disabled": false + }, + { + "title": "昂昂溪区", + "id": "230205", + "children": [], + "disabled": false + }, + { + "title": "富拉尔基区", + "id": "230206", + "children": [], + "disabled": false + }, + { + "title": "碾子山区", + "id": "230207", + "children": [], + "disabled": false + }, + { + "title": "梅里斯达斡尔族区", + "id": "230208", + "children": [], + "disabled": false + }, + { + "title": "龙江县", + "id": "230221", + "children": [], + "disabled": false + }, + { + "title": "依安县", + "id": "230223", + "children": [], + "disabled": false + }, + { + "title": "泰来县", + "id": "230224", + "children": [], + "disabled": false + }, + { + "title": "甘南县", + "id": "230225", + "children": [], + "disabled": false + }, + { + "title": "富裕县", + "id": "230227", + "children": [], + "disabled": false + }, + { + "title": "克山县", + "id": "230229", + "children": [], + "disabled": false + }, + { + "title": "克东县", + "id": "230230", + "children": [], + "disabled": false + }, + { + "title": "拜泉县", + "id": "230231", + "children": [], + "disabled": false + }, + { + "title": "讷河市", + "id": "230281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "鸡西市", + "id": "230300", + "children": [ + { + "title": "鸡冠区", + "id": "230302", + "children": [], + "disabled": false + }, + { + "title": "恒山区", + "id": "230303", + "children": [], + "disabled": false + }, + { + "title": "滴道区", + "id": "230304", + "children": [], + "disabled": false + }, + { + "title": "梨树区", + "id": "230305", + "children": [], + "disabled": false + }, + { + "title": "城子河区", + "id": "230306", + "children": [], + "disabled": false + }, + { + "title": "麻山区", + "id": "230307", + "children": [], + "disabled": false + }, + { + "title": "鸡东县", + "id": "230321", + "children": [], + "disabled": false + }, + { + "title": "虎林市", + "id": "230381", + "children": [], + "disabled": false + }, + { + "title": "密山市", + "id": "230382", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "鹤岗市", + "id": "230400", + "children": [ + { + "title": "向阳区", + "id": "230402", + "children": [], + "disabled": false + }, + { + "title": "工农区", + "id": "230403", + "children": [], + "disabled": false + }, + { + "title": "南山区", + "id": "230404", + "children": [], + "disabled": false + }, + { + "title": "兴安区", + "id": "230405", + "children": [], + "disabled": false + }, + { + "title": "东山区", + "id": "230406", + "children": [], + "disabled": false + }, + { + "title": "兴山区", + "id": "230407", + "children": [], + "disabled": false + }, + { + "title": "萝北县", + "id": "230421", + "children": [], + "disabled": false + }, + { + "title": "绥滨县", + "id": "230422", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "双鸭山市", + "id": "230500", + "children": [ + { + "title": "尖山区", + "id": "230502", + "children": [], + "disabled": false + }, + { + "title": "岭东区", + "id": "230503", + "children": [], + "disabled": false + }, + { + "title": "四方台区", + "id": "230505", + "children": [], + "disabled": false + }, + { + "title": "宝山区", + "id": "230506", + "children": [], + "disabled": false + }, + { + "title": "集贤县", + "id": "230521", + "children": [], + "disabled": false + }, + { + "title": "友谊县", + "id": "230522", + "children": [], + "disabled": false + }, + { + "title": "宝清县", + "id": "230523", + "children": [], + "disabled": false + }, + { + "title": "饶河县", + "id": "230524", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "大庆市", + "id": "230600", + "children": [ + { + "title": "萨尔图区", + "id": "230602", + "children": [], + "disabled": false + }, + { + "title": "龙凤区", + "id": "230603", + "children": [], + "disabled": false + }, + { + "title": "让胡路区", + "id": "230604", + "children": [], + "disabled": false + }, + { + "title": "红岗区", + "id": "230605", + "children": [], + "disabled": false + }, + { + "title": "大同区", + "id": "230606", + "children": [], + "disabled": false + }, + { + "title": "肇州县", + "id": "230621", + "children": [], + "disabled": false + }, + { + "title": "肇源县", + "id": "230622", + "children": [], + "disabled": false + }, + { + "title": "林甸县", + "id": "230623", + "children": [], + "disabled": false + }, + { + "title": "杜尔伯特蒙古族自治县", + "id": "230624", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230601", + "children": [], + "disabled": false + }, + { + "title": "大庆高新技术产业开发区", + "id": "230671", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "伊春市", + "id": "230700", + "children": [ + { + "title": "伊美区", + "id": "230717", + "children": [], + "disabled": false + }, + { + "title": "乌翠区", + "id": "230718", + "children": [], + "disabled": false + }, + { + "title": "友好区", + "id": "230719", + "children": [], + "disabled": false + }, + { + "title": "嘉荫县", + "id": "230722", + "children": [], + "disabled": false + }, + { + "title": "汤旺县", + "id": "230723", + "children": [], + "disabled": false + }, + { + "title": "丰林县", + "id": "230724", + "children": [], + "disabled": false + }, + { + "title": "大箐山县", + "id": "230725", + "children": [], + "disabled": false + }, + { + "title": "南岔县", + "id": "230726", + "children": [], + "disabled": false + }, + { + "title": "金林区", + "id": "230751", + "children": [], + "disabled": false + }, + { + "title": "铁力市", + "id": "230781", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "佳木斯市", + "id": "230800", + "children": [ + { + "title": "向阳区", + "id": "230803", + "children": [], + "disabled": false + }, + { + "title": "前进区", + "id": "230804", + "children": [], + "disabled": false + }, + { + "title": "东风区", + "id": "230805", + "children": [], + "disabled": false + }, + { + "title": "郊区", + "id": "230811", + "children": [], + "disabled": false + }, + { + "title": "桦南县", + "id": "230822", + "children": [], + "disabled": false + }, + { + "title": "桦川县", + "id": "230826", + "children": [], + "disabled": false + }, + { + "title": "汤原县", + "id": "230828", + "children": [], + "disabled": false + }, + { + "title": "同江市", + "id": "230881", + "children": [], + "disabled": false + }, + { + "title": "富锦市", + "id": "230882", + "children": [], + "disabled": false + }, + { + "title": "抚远市", + "id": "230883", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "七台河市", + "id": "230900", + "children": [ + { + "title": "新兴区", + "id": "230902", + "children": [], + "disabled": false + }, + { + "title": "桃山区", + "id": "230903", + "children": [], + "disabled": false + }, + { + "title": "茄子河区", + "id": "230904", + "children": [], + "disabled": false + }, + { + "title": "勃利县", + "id": "230921", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "230901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "牡丹江市", + "id": "231000", + "children": [ + { + "title": "东安区", + "id": "231002", + "children": [], + "disabled": false + }, + { + "title": "阳明区", + "id": "231003", + "children": [], + "disabled": false + }, + { + "title": "爱民区", + "id": "231004", + "children": [], + "disabled": false + }, + { + "title": "西安区", + "id": "231005", + "children": [], + "disabled": false + }, + { + "title": "林口县", + "id": "231025", + "children": [], + "disabled": false + }, + { + "title": "绥芬河市", + "id": "231081", + "children": [], + "disabled": false + }, + { + "title": "海林市", + "id": "231083", + "children": [], + "disabled": false + }, + { + "title": "宁安市", + "id": "231084", + "children": [], + "disabled": false + }, + { + "title": "穆棱市", + "id": "231085", + "children": [], + "disabled": false + }, + { + "title": "东宁市", + "id": "231086", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "231001", + "children": [], + "disabled": false + }, + { + "title": "牡丹江经济技术开发区", + "id": "231071", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黑河市", + "id": "231100", + "children": [ + { + "title": "爱辉区", + "id": "231102", + "children": [], + "disabled": false + }, + { + "title": "逊克县", + "id": "231123", + "children": [], + "disabled": false + }, + { + "title": "孙吴县", + "id": "231124", + "children": [], + "disabled": false + }, + { + "title": "北安市", + "id": "231181", + "children": [], + "disabled": false + }, + { + "title": "五大连池市", + "id": "231182", + "children": [], + "disabled": false + }, + { + "title": "嫩江市", + "id": "231183", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "231101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "绥化市", + "id": "231200", + "children": [ + { + "title": "北林区", + "id": "231202", + "children": [], + "disabled": false + }, + { + "title": "望奎县", + "id": "231221", + "children": [], + "disabled": false + }, + { + "title": "兰西县", + "id": "231222", + "children": [], + "disabled": false + }, + { + "title": "青冈县", + "id": "231223", + "children": [], + "disabled": false + }, + { + "title": "庆安县", + "id": "231224", + "children": [], + "disabled": false + }, + { + "title": "明水县", + "id": "231225", + "children": [], + "disabled": false + }, + { + "title": "绥棱县", + "id": "231226", + "children": [], + "disabled": false + }, + { + "title": "安达市", + "id": "231281", + "children": [], + "disabled": false + }, + { + "title": "肇东市", + "id": "231282", + "children": [], + "disabled": false + }, + { + "title": "海伦市", + "id": "231283", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "231201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "大兴安岭地区", + "id": "232700", + "children": [ + { + "title": "漠河市", + "id": "232701", + "children": [], + "disabled": false + }, + { + "title": "呼玛县", + "id": "232721", + "children": [], + "disabled": false + }, + { + "title": "塔河县", + "id": "232722", + "children": [], + "disabled": false + }, + { + "title": "加格达奇区", + "id": "232761", + "children": [], + "disabled": false + }, + { + "title": "松岭区", + "id": "232762", + "children": [], + "disabled": false + }, + { + "title": "新林区", + "id": "232763", + "children": [], + "disabled": false + }, + { + "title": "呼中区", + "id": "232764", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "上海市", + "id": "310000", + "children": [ + { + "title": "上海市", + "id": "3100001", + "children": [ + { + "title": "黄浦区", + "id": "310101", + "children": [], + "disabled": false + }, + { + "title": "徐汇区", + "id": "310104", + "children": [], + "disabled": false + }, + { + "title": "长宁区", + "id": "310105", + "children": [], + "disabled": false + }, + { + "title": "静安区", + "id": "310106", + "children": [], + "disabled": false + }, + { + "title": "普陀区", + "id": "310107", + "children": [], + "disabled": false + }, + { + "title": "虹口区", + "id": "310109", + "children": [], + "disabled": false + }, + { + "title": "杨浦区", + "id": "310110", + "children": [], + "disabled": false + }, + { + "title": "闵行区", + "id": "310112", + "children": [], + "disabled": false + }, + { + "title": "宝山区", + "id": "310113", + "children": [], + "disabled": false + }, + { + "title": "嘉定区", + "id": "310114", + "children": [], + "disabled": false + }, + { + "title": "浦东新区", + "id": "310115", + "children": [], + "disabled": false + }, + { + "title": "金山区", + "id": "310116", + "children": [], + "disabled": false + }, + { + "title": "松江区", + "id": "310117", + "children": [], + "disabled": false + }, + { + "title": "青浦区", + "id": "310118", + "children": [], + "disabled": false + }, + { + "title": "奉贤区", + "id": "310120", + "children": [], + "disabled": false + }, + { + "title": "崇明区", + "id": "310151", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "江苏省", + "id": "320000", + "children": [ + { + "title": "南京市", + "id": "320100", + "children": [ + { + "title": "玄武区", + "id": "320102", + "children": [], + "disabled": false + }, + { + "title": "秦淮区", + "id": "320104", + "children": [], + "disabled": false + }, + { + "title": "建邺区", + "id": "320105", + "children": [], + "disabled": false + }, + { + "title": "鼓楼区", + "id": "320106", + "children": [], + "disabled": false + }, + { + "title": "浦口区", + "id": "320111", + "children": [], + "disabled": false + }, + { + "title": "栖霞区", + "id": "320113", + "children": [], + "disabled": false + }, + { + "title": "雨花台区", + "id": "320114", + "children": [], + "disabled": false + }, + { + "title": "江宁区", + "id": "320115", + "children": [], + "disabled": false + }, + { + "title": "六合区", + "id": "320116", + "children": [], + "disabled": false + }, + { + "title": "溧水区", + "id": "320117", + "children": [], + "disabled": false + }, + { + "title": "高淳区", + "id": "320118", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "无锡市", + "id": "320200", + "children": [ + { + "title": "锡山区", + "id": "320205", + "children": [], + "disabled": false + }, + { + "title": "惠山区", + "id": "320206", + "children": [], + "disabled": false + }, + { + "title": "滨湖区", + "id": "320211", + "children": [], + "disabled": false + }, + { + "title": "梁溪区", + "id": "320213", + "children": [], + "disabled": false + }, + { + "title": "新吴区", + "id": "320214", + "children": [], + "disabled": false + }, + { + "title": "江阴市", + "id": "320281", + "children": [], + "disabled": false + }, + { + "title": "宜兴市", + "id": "320282", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "徐州市", + "id": "320300", + "children": [ + { + "title": "鼓楼区", + "id": "320302", + "children": [], + "disabled": false + }, + { + "title": "云龙区", + "id": "320303", + "children": [], + "disabled": false + }, + { + "title": "贾汪区", + "id": "320305", + "children": [], + "disabled": false + }, + { + "title": "泉山区", + "id": "320311", + "children": [], + "disabled": false + }, + { + "title": "铜山区", + "id": "320312", + "children": [], + "disabled": false + }, + { + "title": "丰县", + "id": "320321", + "children": [], + "disabled": false + }, + { + "title": "沛县", + "id": "320322", + "children": [], + "disabled": false + }, + { + "title": "睢宁县", + "id": "320324", + "children": [], + "disabled": false + }, + { + "title": "新沂市", + "id": "320381", + "children": [], + "disabled": false + }, + { + "title": "邳州市", + "id": "320382", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320301", + "children": [], + "disabled": false + }, + { + "title": "徐州经济技术开发区", + "id": "320371", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "常州市", + "id": "320400", + "children": [ + { + "title": "天宁区", + "id": "320402", + "children": [], + "disabled": false + }, + { + "title": "钟楼区", + "id": "320404", + "children": [], + "disabled": false + }, + { + "title": "新北区", + "id": "320411", + "children": [], + "disabled": false + }, + { + "title": "武进区", + "id": "320412", + "children": [], + "disabled": false + }, + { + "title": "金坛区", + "id": "320413", + "children": [], + "disabled": false + }, + { + "title": "溧阳市", + "id": "320481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "苏州市", + "id": "320500", + "children": [ + { + "title": "虎丘区", + "id": "320505", + "children": [], + "disabled": false + }, + { + "title": "吴中区", + "id": "320506", + "children": [], + "disabled": false + }, + { + "title": "相城区", + "id": "320507", + "children": [], + "disabled": false + }, + { + "title": "姑苏区", + "id": "320508", + "children": [], + "disabled": false + }, + { + "title": "吴江区", + "id": "320509", + "children": [], + "disabled": false + }, + { + "title": "常熟市", + "id": "320581", + "children": [], + "disabled": false + }, + { + "title": "张家港市", + "id": "320582", + "children": [], + "disabled": false + }, + { + "title": "昆山市", + "id": "320583", + "children": [], + "disabled": false + }, + { + "title": "太仓市", + "id": "320585", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320501", + "children": [], + "disabled": false + }, + { + "title": "苏州工业园区", + "id": "320571", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "南通市", + "id": "320600", + "children": [ + { + "title": "通州区", + "id": "320612", + "children": [], + "disabled": false + }, + { + "title": "崇川区", + "id": "320613", + "children": [], + "disabled": false + }, + { + "title": "海门区", + "id": "320614", + "children": [], + "disabled": false + }, + { + "title": "如东县", + "id": "320623", + "children": [], + "disabled": false + }, + { + "title": "启东市", + "id": "320681", + "children": [], + "disabled": false + }, + { + "title": "如皋市", + "id": "320682", + "children": [], + "disabled": false + }, + { + "title": "海安市", + "id": "320685", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320601", + "children": [], + "disabled": false + }, + { + "title": "南通经济技术开发区", + "id": "320671", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "连云港市", + "id": "320700", + "children": [ + { + "title": "连云区", + "id": "320703", + "children": [], + "disabled": false + }, + { + "title": "海州区", + "id": "320706", + "children": [], + "disabled": false + }, + { + "title": "赣榆区", + "id": "320707", + "children": [], + "disabled": false + }, + { + "title": "东海县", + "id": "320722", + "children": [], + "disabled": false + }, + { + "title": "灌云县", + "id": "320723", + "children": [], + "disabled": false + }, + { + "title": "灌南县", + "id": "320724", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320701", + "children": [], + "disabled": false + }, + { + "title": "连云港经济技术开发区", + "id": "320771", + "children": [], + "disabled": false + }, + { + "title": "连云港高新技术产业开发区", + "id": "320772", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "淮安市", + "id": "320800", + "children": [ + { + "title": "淮安区", + "id": "320803", + "children": [], + "disabled": false + }, + { + "title": "淮阴区", + "id": "320804", + "children": [], + "disabled": false + }, + { + "title": "清江浦区", + "id": "320812", + "children": [], + "disabled": false + }, + { + "title": "洪泽区", + "id": "320813", + "children": [], + "disabled": false + }, + { + "title": "涟水县", + "id": "320826", + "children": [], + "disabled": false + }, + { + "title": "盱眙县", + "id": "320830", + "children": [], + "disabled": false + }, + { + "title": "金湖县", + "id": "320831", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320801", + "children": [], + "disabled": false + }, + { + "title": "淮安经济技术开发区", + "id": "320871", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "盐城市", + "id": "320900", + "children": [ + { + "title": "亭湖区", + "id": "320902", + "children": [], + "disabled": false + }, + { + "title": "盐都区", + "id": "320903", + "children": [], + "disabled": false + }, + { + "title": "大丰区", + "id": "320904", + "children": [], + "disabled": false + }, + { + "title": "响水县", + "id": "320921", + "children": [], + "disabled": false + }, + { + "title": "滨海县", + "id": "320922", + "children": [], + "disabled": false + }, + { + "title": "阜宁县", + "id": "320923", + "children": [], + "disabled": false + }, + { + "title": "射阳县", + "id": "320924", + "children": [], + "disabled": false + }, + { + "title": "建湖县", + "id": "320925", + "children": [], + "disabled": false + }, + { + "title": "东台市", + "id": "320981", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "320901", + "children": [], + "disabled": false + }, + { + "title": "盐城经济技术开发区", + "id": "320971", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "扬州市", + "id": "321000", + "children": [ + { + "title": "广陵区", + "id": "321002", + "children": [], + "disabled": false + }, + { + "title": "邗江区", + "id": "321003", + "children": [], + "disabled": false + }, + { + "title": "江都区", + "id": "321012", + "children": [], + "disabled": false + }, + { + "title": "宝应县", + "id": "321023", + "children": [], + "disabled": false + }, + { + "title": "仪征市", + "id": "321081", + "children": [], + "disabled": false + }, + { + "title": "高邮市", + "id": "321084", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "321001", + "children": [], + "disabled": false + }, + { + "title": "扬州经济技术开发区", + "id": "321071", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "镇江市", + "id": "321100", + "children": [ + { + "title": "京口区", + "id": "321102", + "children": [], + "disabled": false + }, + { + "title": "润州区", + "id": "321111", + "children": [], + "disabled": false + }, + { + "title": "丹徒区", + "id": "321112", + "children": [], + "disabled": false + }, + { + "title": "丹阳市", + "id": "321181", + "children": [], + "disabled": false + }, + { + "title": "扬中市", + "id": "321182", + "children": [], + "disabled": false + }, + { + "title": "句容市", + "id": "321183", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "321101", + "children": [], + "disabled": false + }, + { + "title": "镇江新区", + "id": "321171", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "泰州市", + "id": "321200", + "children": [ + { + "title": "海陵区", + "id": "321202", + "children": [], + "disabled": false + }, + { + "title": "高港区", + "id": "321203", + "children": [], + "disabled": false + }, + { + "title": "姜堰区", + "id": "321204", + "children": [], + "disabled": false + }, + { + "title": "兴化市", + "id": "321281", + "children": [], + "disabled": false + }, + { + "title": "靖江市", + "id": "321282", + "children": [], + "disabled": false + }, + { + "title": "泰兴市", + "id": "321283", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "321201", + "children": [], + "disabled": false + }, + { + "title": "泰州医药高新技术产业开发区", + "id": "321271", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宿迁市", + "id": "321300", + "children": [ + { + "title": "宿城区", + "id": "321302", + "children": [], + "disabled": false + }, + { + "title": "宿豫区", + "id": "321311", + "children": [], + "disabled": false + }, + { + "title": "沭阳县", + "id": "321322", + "children": [], + "disabled": false + }, + { + "title": "泗阳县", + "id": "321323", + "children": [], + "disabled": false + }, + { + "title": "泗洪县", + "id": "321324", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "321301", + "children": [], + "disabled": false + }, + { + "title": "宿迁经济技术开发区", + "id": "321371", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "浙江省", + "id": "330000", + "children": [ + { + "title": "杭州市", + "id": "330100", + "children": [ + { + "title": "上城区", + "id": "330102", + "children": [], + "disabled": false + }, + { + "title": "下城区", + "id": "330103", + "children": [], + "disabled": false + }, + { + "title": "江干区", + "id": "330104", + "children": [], + "disabled": false + }, + { + "title": "拱墅区", + "id": "330105", + "children": [], + "disabled": false + }, + { + "title": "西湖区", + "id": "330106", + "children": [], + "disabled": false + }, + { + "title": "滨江区", + "id": "330108", + "children": [], + "disabled": false + }, + { + "title": "萧山区", + "id": "330109", + "children": [], + "disabled": false + }, + { + "title": "余杭区", + "id": "330110", + "children": [], + "disabled": false + }, + { + "title": "富阳区", + "id": "330111", + "children": [], + "disabled": false + }, + { + "title": "临安区", + "id": "330112", + "children": [], + "disabled": false + }, + { + "title": "桐庐县", + "id": "330122", + "children": [], + "disabled": false + }, + { + "title": "淳安县", + "id": "330127", + "children": [], + "disabled": false + }, + { + "title": "建德市", + "id": "330182", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330101", + "children": [], + "disabled": false + }, + { + "title": "临平区", + "id": "330113", + "children": [], + "disabled": false + }, + { + "title": "钱塘区", + "id": "330114", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宁波市", + "id": "330200", + "children": [ + { + "title": "海曙区", + "id": "330203", + "children": [], + "disabled": false + }, + { + "title": "江北区", + "id": "330205", + "children": [], + "disabled": false + }, + { + "title": "北仑区", + "id": "330206", + "children": [], + "disabled": false + }, + { + "title": "镇海区", + "id": "330211", + "children": [], + "disabled": false + }, + { + "title": "鄞州区", + "id": "330212", + "children": [], + "disabled": false + }, + { + "title": "奉化区", + "id": "330213", + "children": [], + "disabled": false + }, + { + "title": "象山县", + "id": "330225", + "children": [], + "disabled": false + }, + { + "title": "宁海县", + "id": "330226", + "children": [], + "disabled": false + }, + { + "title": "余姚市", + "id": "330281", + "children": [], + "disabled": false + }, + { + "title": "慈溪市", + "id": "330282", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "温州市", + "id": "330300", + "children": [ + { + "title": "鹿城区", + "id": "330302", + "children": [], + "disabled": false + }, + { + "title": "龙湾区", + "id": "330303", + "children": [], + "disabled": false + }, + { + "title": "瓯海区", + "id": "330304", + "children": [], + "disabled": false + }, + { + "title": "洞头区", + "id": "330305", + "children": [], + "disabled": false + }, + { + "title": "永嘉县", + "id": "330324", + "children": [], + "disabled": false + }, + { + "title": "平阳县", + "id": "330326", + "children": [], + "disabled": false + }, + { + "title": "苍南县", + "id": "330327", + "children": [], + "disabled": false + }, + { + "title": "文成县", + "id": "330328", + "children": [], + "disabled": false + }, + { + "title": "泰顺县", + "id": "330329", + "children": [], + "disabled": false + }, + { + "title": "瑞安市", + "id": "330381", + "children": [], + "disabled": false + }, + { + "title": "乐清市", + "id": "330382", + "children": [], + "disabled": false + }, + { + "title": "龙港市", + "id": "330383", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330301", + "children": [], + "disabled": false + }, + { + "title": "温州经济技术开发区", + "id": "330371", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "嘉兴市", + "id": "330400", + "children": [ + { + "title": "南湖区", + "id": "330402", + "children": [], + "disabled": false + }, + { + "title": "秀洲区", + "id": "330411", + "children": [], + "disabled": false + }, + { + "title": "嘉善县", + "id": "330421", + "children": [], + "disabled": false + }, + { + "title": "海盐县", + "id": "330424", + "children": [], + "disabled": false + }, + { + "title": "海宁市", + "id": "330481", + "children": [], + "disabled": false + }, + { + "title": "平湖市", + "id": "330482", + "children": [], + "disabled": false + }, + { + "title": "桐乡市", + "id": "330483", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "湖州市", + "id": "330500", + "children": [ + { + "title": "吴兴区", + "id": "330502", + "children": [], + "disabled": false + }, + { + "title": "南浔区", + "id": "330503", + "children": [], + "disabled": false + }, + { + "title": "德清县", + "id": "330521", + "children": [], + "disabled": false + }, + { + "title": "长兴县", + "id": "330522", + "children": [], + "disabled": false + }, + { + "title": "安吉县", + "id": "330523", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "绍兴市", + "id": "330600", + "children": [ + { + "title": "越城区", + "id": "330602", + "children": [], + "disabled": false + }, + { + "title": "柯桥区", + "id": "330603", + "children": [], + "disabled": false + }, + { + "title": "上虞区", + "id": "330604", + "children": [], + "disabled": false + }, + { + "title": "新昌县", + "id": "330624", + "children": [], + "disabled": false + }, + { + "title": "诸暨市", + "id": "330681", + "children": [], + "disabled": false + }, + { + "title": "嵊州市", + "id": "330683", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "金华市", + "id": "330700", + "children": [ + { + "title": "婺城区", + "id": "330702", + "children": [], + "disabled": false + }, + { + "title": "金东区", + "id": "330703", + "children": [], + "disabled": false + }, + { + "title": "武义县", + "id": "330723", + "children": [], + "disabled": false + }, + { + "title": "浦江县", + "id": "330726", + "children": [], + "disabled": false + }, + { + "title": "磐安县", + "id": "330727", + "children": [], + "disabled": false + }, + { + "title": "兰溪市", + "id": "330781", + "children": [], + "disabled": false + }, + { + "title": "义乌市", + "id": "330782", + "children": [], + "disabled": false + }, + { + "title": "东阳市", + "id": "330783", + "children": [], + "disabled": false + }, + { + "title": "永康市", + "id": "330784", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "衢州市", + "id": "330800", + "children": [ + { + "title": "柯城区", + "id": "330802", + "children": [], + "disabled": false + }, + { + "title": "衢江区", + "id": "330803", + "children": [], + "disabled": false + }, + { + "title": "常山县", + "id": "330822", + "children": [], + "disabled": false + }, + { + "title": "开化县", + "id": "330824", + "children": [], + "disabled": false + }, + { + "title": "龙游县", + "id": "330825", + "children": [], + "disabled": false + }, + { + "title": "江山市", + "id": "330881", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "舟山市", + "id": "330900", + "children": [ + { + "title": "定海区", + "id": "330902", + "children": [], + "disabled": false + }, + { + "title": "普陀区", + "id": "330903", + "children": [], + "disabled": false + }, + { + "title": "岱山县", + "id": "330921", + "children": [], + "disabled": false + }, + { + "title": "嵊泗县", + "id": "330922", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "330901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "台州市", + "id": "331000", + "children": [ + { + "title": "椒江区", + "id": "331002", + "children": [], + "disabled": false + }, + { + "title": "黄岩区", + "id": "331003", + "children": [], + "disabled": false + }, + { + "title": "路桥区", + "id": "331004", + "children": [], + "disabled": false + }, + { + "title": "三门县", + "id": "331022", + "children": [], + "disabled": false + }, + { + "title": "天台县", + "id": "331023", + "children": [], + "disabled": false + }, + { + "title": "仙居县", + "id": "331024", + "children": [], + "disabled": false + }, + { + "title": "温岭市", + "id": "331081", + "children": [], + "disabled": false + }, + { + "title": "临海市", + "id": "331082", + "children": [], + "disabled": false + }, + { + "title": "玉环市", + "id": "331083", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "331001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "丽水市", + "id": "331100", + "children": [ + { + "title": "莲都区", + "id": "331102", + "children": [], + "disabled": false + }, + { + "title": "青田县", + "id": "331121", + "children": [], + "disabled": false + }, + { + "title": "缙云县", + "id": "331122", + "children": [], + "disabled": false + }, + { + "title": "遂昌县", + "id": "331123", + "children": [], + "disabled": false + }, + { + "title": "松阳县", + "id": "331124", + "children": [], + "disabled": false + }, + { + "title": "云和县", + "id": "331125", + "children": [], + "disabled": false + }, + { + "title": "庆元县", + "id": "331126", + "children": [], + "disabled": false + }, + { + "title": "景宁畲族自治县", + "id": "331127", + "children": [], + "disabled": false + }, + { + "title": "龙泉市", + "id": "331181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "331101", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "安徽省", + "id": "340000", + "children": [ + { + "title": "合肥市", + "id": "340100", + "children": [ + { + "title": "瑶海区", + "id": "340102", + "children": [], + "disabled": false + }, + { + "title": "庐阳区", + "id": "340103", + "children": [], + "disabled": false + }, + { + "title": "蜀山区", + "id": "340104", + "children": [], + "disabled": false + }, + { + "title": "包河区", + "id": "340111", + "children": [], + "disabled": false + }, + { + "title": "长丰县", + "id": "340121", + "children": [], + "disabled": false + }, + { + "title": "肥东县", + "id": "340122", + "children": [], + "disabled": false + }, + { + "title": "肥西县", + "id": "340123", + "children": [], + "disabled": false + }, + { + "title": "庐江县", + "id": "340124", + "children": [], + "disabled": false + }, + { + "title": "巢湖市", + "id": "340181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340101", + "children": [], + "disabled": false + }, + { + "title": "合肥高新技术产业开发区", + "id": "340171", + "children": [], + "disabled": false + }, + { + "title": "合肥经济技术开发区", + "id": "340172", + "children": [], + "disabled": false + }, + { + "title": "合肥新站高新技术产业开发区", + "id": "340173", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "芜湖市", + "id": "340200", + "children": [ + { + "title": "镜湖区", + "id": "340202", + "children": [], + "disabled": false + }, + { + "title": "鸠江区", + "id": "340207", + "children": [], + "disabled": false + }, + { + "title": "弋江区", + "id": "340209", + "children": [], + "disabled": false + }, + { + "title": "湾沚区", + "id": "340210", + "children": [], + "disabled": false + }, + { + "title": "繁昌区", + "id": "340212", + "children": [], + "disabled": false + }, + { + "title": "南陵县", + "id": "340223", + "children": [], + "disabled": false + }, + { + "title": "无为市", + "id": "340281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340201", + "children": [], + "disabled": false + }, + { + "title": "芜湖经济技术开发区", + "id": "340271", + "children": [], + "disabled": false + }, + { + "title": "安徽芜湖三山经济开发区", + "id": "340272", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "蚌埠市", + "id": "340300", + "children": [ + { + "title": "龙子湖区", + "id": "340302", + "children": [], + "disabled": false + }, + { + "title": "蚌山区", + "id": "340303", + "children": [], + "disabled": false + }, + { + "title": "禹会区", + "id": "340304", + "children": [], + "disabled": false + }, + { + "title": "淮上区", + "id": "340311", + "children": [], + "disabled": false + }, + { + "title": "怀远县", + "id": "340321", + "children": [], + "disabled": false + }, + { + "title": "五河县", + "id": "340322", + "children": [], + "disabled": false + }, + { + "title": "固镇县", + "id": "340323", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340301", + "children": [], + "disabled": false + }, + { + "title": "蚌埠市高新技术开发区", + "id": "340371", + "children": [], + "disabled": false + }, + { + "title": "蚌埠市经济开发区", + "id": "340372", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "淮南市", + "id": "340400", + "children": [ + { + "title": "大通区", + "id": "340402", + "children": [], + "disabled": false + }, + { + "title": "田家庵区", + "id": "340403", + "children": [], + "disabled": false + }, + { + "title": "谢家集区", + "id": "340404", + "children": [], + "disabled": false + }, + { + "title": "八公山区", + "id": "340405", + "children": [], + "disabled": false + }, + { + "title": "潘集区", + "id": "340406", + "children": [], + "disabled": false + }, + { + "title": "凤台县", + "id": "340421", + "children": [], + "disabled": false + }, + { + "title": "寿县", + "id": "340422", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "马鞍山市", + "id": "340500", + "children": [ + { + "title": "花山区", + "id": "340503", + "children": [], + "disabled": false + }, + { + "title": "雨山区", + "id": "340504", + "children": [], + "disabled": false + }, + { + "title": "博望区", + "id": "340506", + "children": [], + "disabled": false + }, + { + "title": "当涂县", + "id": "340521", + "children": [], + "disabled": false + }, + { + "title": "含山县", + "id": "340522", + "children": [], + "disabled": false + }, + { + "title": "和县", + "id": "340523", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "淮北市", + "id": "340600", + "children": [ + { + "title": "杜集区", + "id": "340602", + "children": [], + "disabled": false + }, + { + "title": "相山区", + "id": "340603", + "children": [], + "disabled": false + }, + { + "title": "烈山区", + "id": "340604", + "children": [], + "disabled": false + }, + { + "title": "濉溪县", + "id": "340621", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "铜陵市", + "id": "340700", + "children": [ + { + "title": "铜官区", + "id": "340705", + "children": [], + "disabled": false + }, + { + "title": "义安区", + "id": "340706", + "children": [], + "disabled": false + }, + { + "title": "郊区", + "id": "340711", + "children": [], + "disabled": false + }, + { + "title": "枞阳县", + "id": "340722", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "安庆市", + "id": "340800", + "children": [ + { + "title": "迎江区", + "id": "340802", + "children": [], + "disabled": false + }, + { + "title": "大观区", + "id": "340803", + "children": [], + "disabled": false + }, + { + "title": "宜秀区", + "id": "340811", + "children": [], + "disabled": false + }, + { + "title": "怀宁县", + "id": "340822", + "children": [], + "disabled": false + }, + { + "title": "太湖县", + "id": "340825", + "children": [], + "disabled": false + }, + { + "title": "宿松县", + "id": "340826", + "children": [], + "disabled": false + }, + { + "title": "望江县", + "id": "340827", + "children": [], + "disabled": false + }, + { + "title": "岳西县", + "id": "340828", + "children": [], + "disabled": false + }, + { + "title": "桐城市", + "id": "340881", + "children": [], + "disabled": false + }, + { + "title": "潜山市", + "id": "340882", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "340801", + "children": [], + "disabled": false + }, + { + "title": "安徽安庆经济开发区", + "id": "340871", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黄山市", + "id": "341000", + "children": [ + { + "title": "屯溪区", + "id": "341002", + "children": [], + "disabled": false + }, + { + "title": "黄山区", + "id": "341003", + "children": [], + "disabled": false + }, + { + "title": "徽州区", + "id": "341004", + "children": [], + "disabled": false + }, + { + "title": "歙县", + "id": "341021", + "children": [], + "disabled": false + }, + { + "title": "休宁县", + "id": "341022", + "children": [], + "disabled": false + }, + { + "title": "黟县", + "id": "341023", + "children": [], + "disabled": false + }, + { + "title": "祁门县", + "id": "341024", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "滁州市", + "id": "341100", + "children": [ + { + "title": "琅琊区", + "id": "341102", + "children": [], + "disabled": false + }, + { + "title": "南谯区", + "id": "341103", + "children": [], + "disabled": false + }, + { + "title": "来安县", + "id": "341122", + "children": [], + "disabled": false + }, + { + "title": "全椒县", + "id": "341124", + "children": [], + "disabled": false + }, + { + "title": "定远县", + "id": "341125", + "children": [], + "disabled": false + }, + { + "title": "凤阳县", + "id": "341126", + "children": [], + "disabled": false + }, + { + "title": "天长市", + "id": "341181", + "children": [], + "disabled": false + }, + { + "title": "明光市", + "id": "341182", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341101", + "children": [], + "disabled": false + }, + { + "title": "中新苏滁高新技术产业开发区", + "id": "341171", + "children": [], + "disabled": false + }, + { + "title": "滁州经济技术开发区", + "id": "341172", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阜阳市", + "id": "341200", + "children": [ + { + "title": "颍州区", + "id": "341202", + "children": [], + "disabled": false + }, + { + "title": "颍东区", + "id": "341203", + "children": [], + "disabled": false + }, + { + "title": "颍泉区", + "id": "341204", + "children": [], + "disabled": false + }, + { + "title": "临泉县", + "id": "341221", + "children": [], + "disabled": false + }, + { + "title": "太和县", + "id": "341222", + "children": [], + "disabled": false + }, + { + "title": "阜南县", + "id": "341225", + "children": [], + "disabled": false + }, + { + "title": "颍上县", + "id": "341226", + "children": [], + "disabled": false + }, + { + "title": "界首市", + "id": "341282", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341201", + "children": [], + "disabled": false + }, + { + "title": "阜阳合肥现代产业园区", + "id": "341271", + "children": [], + "disabled": false + }, + { + "title": "阜阳经济技术开发区", + "id": "341272", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宿州市", + "id": "341300", + "children": [ + { + "title": "埇桥区", + "id": "341302", + "children": [], + "disabled": false + }, + { + "title": "砀山县", + "id": "341321", + "children": [], + "disabled": false + }, + { + "title": "萧县", + "id": "341322", + "children": [], + "disabled": false + }, + { + "title": "灵璧县", + "id": "341323", + "children": [], + "disabled": false + }, + { + "title": "泗县", + "id": "341324", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341301", + "children": [], + "disabled": false + }, + { + "title": "宿州马鞍山现代产业园区", + "id": "341371", + "children": [], + "disabled": false + }, + { + "title": "宿州经济技术开发区", + "id": "341372", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "六安市", + "id": "341500", + "children": [ + { + "title": "金安区", + "id": "341502", + "children": [], + "disabled": false + }, + { + "title": "裕安区", + "id": "341503", + "children": [], + "disabled": false + }, + { + "title": "叶集区", + "id": "341504", + "children": [], + "disabled": false + }, + { + "title": "霍邱县", + "id": "341522", + "children": [], + "disabled": false + }, + { + "title": "舒城县", + "id": "341523", + "children": [], + "disabled": false + }, + { + "title": "金寨县", + "id": "341524", + "children": [], + "disabled": false + }, + { + "title": "霍山县", + "id": "341525", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "亳州市", + "id": "341600", + "children": [ + { + "title": "谯城区", + "id": "341602", + "children": [], + "disabled": false + }, + { + "title": "涡阳县", + "id": "341621", + "children": [], + "disabled": false + }, + { + "title": "蒙城县", + "id": "341622", + "children": [], + "disabled": false + }, + { + "title": "利辛县", + "id": "341623", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "池州市", + "id": "341700", + "children": [ + { + "title": "贵池区", + "id": "341702", + "children": [], + "disabled": false + }, + { + "title": "东至县", + "id": "341721", + "children": [], + "disabled": false + }, + { + "title": "石台县", + "id": "341722", + "children": [], + "disabled": false + }, + { + "title": "青阳县", + "id": "341723", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宣城市", + "id": "341800", + "children": [ + { + "title": "宣州区", + "id": "341802", + "children": [], + "disabled": false + }, + { + "title": "郎溪县", + "id": "341821", + "children": [], + "disabled": false + }, + { + "title": "泾县", + "id": "341823", + "children": [], + "disabled": false + }, + { + "title": "绩溪县", + "id": "341824", + "children": [], + "disabled": false + }, + { + "title": "旌德县", + "id": "341825", + "children": [], + "disabled": false + }, + { + "title": "宁国市", + "id": "341881", + "children": [], + "disabled": false + }, + { + "title": "广德市", + "id": "341882", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "341801", + "children": [], + "disabled": false + }, + { + "title": "宣城市经济开发区", + "id": "341871", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "福建省", + "id": "350000", + "children": [ + { + "title": "福州市", + "id": "350100", + "children": [ + { + "title": "鼓楼区", + "id": "350102", + "children": [], + "disabled": false + }, + { + "title": "台江区", + "id": "350103", + "children": [], + "disabled": false + }, + { + "title": "仓山区", + "id": "350104", + "children": [], + "disabled": false + }, + { + "title": "马尾区", + "id": "350105", + "children": [], + "disabled": false + }, + { + "title": "晋安区", + "id": "350111", + "children": [], + "disabled": false + }, + { + "title": "长乐区", + "id": "350112", + "children": [], + "disabled": false + }, + { + "title": "闽侯县", + "id": "350121", + "children": [], + "disabled": false + }, + { + "title": "连江县", + "id": "350122", + "children": [], + "disabled": false + }, + { + "title": "罗源县", + "id": "350123", + "children": [], + "disabled": false + }, + { + "title": "闽清县", + "id": "350124", + "children": [], + "disabled": false + }, + { + "title": "永泰县", + "id": "350125", + "children": [], + "disabled": false + }, + { + "title": "平潭县", + "id": "350128", + "children": [], + "disabled": false + }, + { + "title": "福清市", + "id": "350181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "厦门市", + "id": "350200", + "children": [ + { + "title": "思明区", + "id": "350203", + "children": [], + "disabled": false + }, + { + "title": "海沧区", + "id": "350205", + "children": [], + "disabled": false + }, + { + "title": "湖里区", + "id": "350206", + "children": [], + "disabled": false + }, + { + "title": "集美区", + "id": "350211", + "children": [], + "disabled": false + }, + { + "title": "同安区", + "id": "350212", + "children": [], + "disabled": false + }, + { + "title": "翔安区", + "id": "350213", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "莆田市", + "id": "350300", + "children": [ + { + "title": "城厢区", + "id": "350302", + "children": [], + "disabled": false + }, + { + "title": "涵江区", + "id": "350303", + "children": [], + "disabled": false + }, + { + "title": "荔城区", + "id": "350304", + "children": [], + "disabled": false + }, + { + "title": "秀屿区", + "id": "350305", + "children": [], + "disabled": false + }, + { + "title": "仙游县", + "id": "350322", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "三明市", + "id": "350400", + "children": [ + { + "title": "梅列区", + "id": "350402", + "children": [], + "disabled": false + }, + { + "title": "三元区", + "id": "350403", + "children": [], + "disabled": false + }, + { + "title": "明溪县", + "id": "350421", + "children": [], + "disabled": false + }, + { + "title": "清流县", + "id": "350423", + "children": [], + "disabled": false + }, + { + "title": "宁化县", + "id": "350424", + "children": [], + "disabled": false + }, + { + "title": "大田县", + "id": "350425", + "children": [], + "disabled": false + }, + { + "title": "尤溪县", + "id": "350426", + "children": [], + "disabled": false + }, + { + "title": "沙县", + "id": "350427", + "children": [], + "disabled": false + }, + { + "title": "将乐县", + "id": "350428", + "children": [], + "disabled": false + }, + { + "title": "泰宁县", + "id": "350429", + "children": [], + "disabled": false + }, + { + "title": "建宁县", + "id": "350430", + "children": [], + "disabled": false + }, + { + "title": "永安市", + "id": "350481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350401", + "children": [], + "disabled": false + }, + { + "title": "三元区", + "id": "350404", + "children": [], + "disabled": false + }, + { + "title": "沙县区", + "id": "350405", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "泉州市", + "id": "350500", + "children": [ + { + "title": "鲤城区", + "id": "350502", + "children": [], + "disabled": false + }, + { + "title": "丰泽区", + "id": "350503", + "children": [], + "disabled": false + }, + { + "title": "洛江区", + "id": "350504", + "children": [], + "disabled": false + }, + { + "title": "泉港区", + "id": "350505", + "children": [], + "disabled": false + }, + { + "title": "惠安县", + "id": "350521", + "children": [], + "disabled": false + }, + { + "title": "安溪县", + "id": "350524", + "children": [], + "disabled": false + }, + { + "title": "永春县", + "id": "350525", + "children": [], + "disabled": false + }, + { + "title": "德化县", + "id": "350526", + "children": [], + "disabled": false + }, + { + "title": "金门县", + "id": "350527", + "children": [], + "disabled": false + }, + { + "title": "石狮市", + "id": "350581", + "children": [], + "disabled": false + }, + { + "title": "晋江市", + "id": "350582", + "children": [], + "disabled": false + }, + { + "title": "南安市", + "id": "350583", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "漳州市", + "id": "350600", + "children": [ + { + "title": "芗城区", + "id": "350602", + "children": [], + "disabled": false + }, + { + "title": "龙文区", + "id": "350603", + "children": [], + "disabled": false + }, + { + "title": "云霄县", + "id": "350622", + "children": [], + "disabled": false + }, + { + "title": "漳浦县", + "id": "350623", + "children": [], + "disabled": false + }, + { + "title": "诏安县", + "id": "350624", + "children": [], + "disabled": false + }, + { + "title": "长泰县", + "id": "350625", + "children": [], + "disabled": false + }, + { + "title": "东山县", + "id": "350626", + "children": [], + "disabled": false + }, + { + "title": "南靖县", + "id": "350627", + "children": [], + "disabled": false + }, + { + "title": "平和县", + "id": "350628", + "children": [], + "disabled": false + }, + { + "title": "华安县", + "id": "350629", + "children": [], + "disabled": false + }, + { + "title": "龙海市", + "id": "350681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350601", + "children": [], + "disabled": false + }, + { + "title": "龙海区", + "id": "350604", + "children": [], + "disabled": false + }, + { + "title": "长泰区", + "id": "350605", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "南平市", + "id": "350700", + "children": [ + { + "title": "延平区", + "id": "350702", + "children": [], + "disabled": false + }, + { + "title": "建阳区", + "id": "350703", + "children": [], + "disabled": false + }, + { + "title": "顺昌县", + "id": "350721", + "children": [], + "disabled": false + }, + { + "title": "浦城县", + "id": "350722", + "children": [], + "disabled": false + }, + { + "title": "光泽县", + "id": "350723", + "children": [], + "disabled": false + }, + { + "title": "松溪县", + "id": "350724", + "children": [], + "disabled": false + }, + { + "title": "政和县", + "id": "350725", + "children": [], + "disabled": false + }, + { + "title": "邵武市", + "id": "350781", + "children": [], + "disabled": false + }, + { + "title": "武夷山市", + "id": "350782", + "children": [], + "disabled": false + }, + { + "title": "建瓯市", + "id": "350783", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "龙岩市", + "id": "350800", + "children": [ + { + "title": "新罗区", + "id": "350802", + "children": [], + "disabled": false + }, + { + "title": "永定区", + "id": "350803", + "children": [], + "disabled": false + }, + { + "title": "长汀县", + "id": "350821", + "children": [], + "disabled": false + }, + { + "title": "上杭县", + "id": "350823", + "children": [], + "disabled": false + }, + { + "title": "武平县", + "id": "350824", + "children": [], + "disabled": false + }, + { + "title": "连城县", + "id": "350825", + "children": [], + "disabled": false + }, + { + "title": "漳平市", + "id": "350881", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宁德市", + "id": "350900", + "children": [ + { + "title": "蕉城区", + "id": "350902", + "children": [], + "disabled": false + }, + { + "title": "霞浦县", + "id": "350921", + "children": [], + "disabled": false + }, + { + "title": "古田县", + "id": "350922", + "children": [], + "disabled": false + }, + { + "title": "屏南县", + "id": "350923", + "children": [], + "disabled": false + }, + { + "title": "寿宁县", + "id": "350924", + "children": [], + "disabled": false + }, + { + "title": "周宁县", + "id": "350925", + "children": [], + "disabled": false + }, + { + "title": "柘荣县", + "id": "350926", + "children": [], + "disabled": false + }, + { + "title": "福安市", + "id": "350981", + "children": [], + "disabled": false + }, + { + "title": "福鼎市", + "id": "350982", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "350901", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "江西省", + "id": "360000", + "children": [ + { + "title": "南昌市", + "id": "360100", + "children": [ + { + "title": "东湖区", + "id": "360102", + "children": [], + "disabled": false + }, + { + "title": "西湖区", + "id": "360103", + "children": [], + "disabled": false + }, + { + "title": "青云谱区", + "id": "360104", + "children": [], + "disabled": false + }, + { + "title": "青山湖区", + "id": "360111", + "children": [], + "disabled": false + }, + { + "title": "新建区", + "id": "360112", + "children": [], + "disabled": false + }, + { + "title": "红谷滩区", + "id": "360113", + "children": [], + "disabled": false + }, + { + "title": "南昌县", + "id": "360121", + "children": [], + "disabled": false + }, + { + "title": "安义县", + "id": "360123", + "children": [], + "disabled": false + }, + { + "title": "进贤县", + "id": "360124", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "景德镇市", + "id": "360200", + "children": [ + { + "title": "昌江区", + "id": "360202", + "children": [], + "disabled": false + }, + { + "title": "珠山区", + "id": "360203", + "children": [], + "disabled": false + }, + { + "title": "浮梁县", + "id": "360222", + "children": [], + "disabled": false + }, + { + "title": "乐平市", + "id": "360281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "萍乡市", + "id": "360300", + "children": [ + { + "title": "安源区", + "id": "360302", + "children": [], + "disabled": false + }, + { + "title": "湘东区", + "id": "360313", + "children": [], + "disabled": false + }, + { + "title": "莲花县", + "id": "360321", + "children": [], + "disabled": false + }, + { + "title": "上栗县", + "id": "360322", + "children": [], + "disabled": false + }, + { + "title": "芦溪县", + "id": "360323", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "九江市", + "id": "360400", + "children": [ + { + "title": "濂溪区", + "id": "360402", + "children": [], + "disabled": false + }, + { + "title": "浔阳区", + "id": "360403", + "children": [], + "disabled": false + }, + { + "title": "柴桑区", + "id": "360404", + "children": [], + "disabled": false + }, + { + "title": "武宁县", + "id": "360423", + "children": [], + "disabled": false + }, + { + "title": "修水县", + "id": "360424", + "children": [], + "disabled": false + }, + { + "title": "永修县", + "id": "360425", + "children": [], + "disabled": false + }, + { + "title": "德安县", + "id": "360426", + "children": [], + "disabled": false + }, + { + "title": "都昌县", + "id": "360428", + "children": [], + "disabled": false + }, + { + "title": "湖口县", + "id": "360429", + "children": [], + "disabled": false + }, + { + "title": "彭泽县", + "id": "360430", + "children": [], + "disabled": false + }, + { + "title": "瑞昌市", + "id": "360481", + "children": [], + "disabled": false + }, + { + "title": "共青城市", + "id": "360482", + "children": [], + "disabled": false + }, + { + "title": "庐山市", + "id": "360483", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "新余市", + "id": "360500", + "children": [ + { + "title": "渝水区", + "id": "360502", + "children": [], + "disabled": false + }, + { + "title": "分宜县", + "id": "360521", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "鹰潭市", + "id": "360600", + "children": [ + { + "title": "月湖区", + "id": "360602", + "children": [], + "disabled": false + }, + { + "title": "余江区", + "id": "360603", + "children": [], + "disabled": false + }, + { + "title": "贵溪市", + "id": "360681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "赣州市", + "id": "360700", + "children": [ + { + "title": "章贡区", + "id": "360702", + "children": [], + "disabled": false + }, + { + "title": "南康区", + "id": "360703", + "children": [], + "disabled": false + }, + { + "title": "赣县区", + "id": "360704", + "children": [], + "disabled": false + }, + { + "title": "信丰县", + "id": "360722", + "children": [], + "disabled": false + }, + { + "title": "大余县", + "id": "360723", + "children": [], + "disabled": false + }, + { + "title": "上犹县", + "id": "360724", + "children": [], + "disabled": false + }, + { + "title": "崇义县", + "id": "360725", + "children": [], + "disabled": false + }, + { + "title": "安远县", + "id": "360726", + "children": [], + "disabled": false + }, + { + "title": "定南县", + "id": "360728", + "children": [], + "disabled": false + }, + { + "title": "全南县", + "id": "360729", + "children": [], + "disabled": false + }, + { + "title": "宁都县", + "id": "360730", + "children": [], + "disabled": false + }, + { + "title": "于都县", + "id": "360731", + "children": [], + "disabled": false + }, + { + "title": "兴国县", + "id": "360732", + "children": [], + "disabled": false + }, + { + "title": "会昌县", + "id": "360733", + "children": [], + "disabled": false + }, + { + "title": "寻乌县", + "id": "360734", + "children": [], + "disabled": false + }, + { + "title": "石城县", + "id": "360735", + "children": [], + "disabled": false + }, + { + "title": "瑞金市", + "id": "360781", + "children": [], + "disabled": false + }, + { + "title": "龙南市", + "id": "360783", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "吉安市", + "id": "360800", + "children": [ + { + "title": "吉州区", + "id": "360802", + "children": [], + "disabled": false + }, + { + "title": "青原区", + "id": "360803", + "children": [], + "disabled": false + }, + { + "title": "吉安县", + "id": "360821", + "children": [], + "disabled": false + }, + { + "title": "吉水县", + "id": "360822", + "children": [], + "disabled": false + }, + { + "title": "峡江县", + "id": "360823", + "children": [], + "disabled": false + }, + { + "title": "新干县", + "id": "360824", + "children": [], + "disabled": false + }, + { + "title": "永丰县", + "id": "360825", + "children": [], + "disabled": false + }, + { + "title": "泰和县", + "id": "360826", + "children": [], + "disabled": false + }, + { + "title": "遂川县", + "id": "360827", + "children": [], + "disabled": false + }, + { + "title": "万安县", + "id": "360828", + "children": [], + "disabled": false + }, + { + "title": "安福县", + "id": "360829", + "children": [], + "disabled": false + }, + { + "title": "永新县", + "id": "360830", + "children": [], + "disabled": false + }, + { + "title": "井冈山市", + "id": "360881", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宜春市", + "id": "360900", + "children": [ + { + "title": "袁州区", + "id": "360902", + "children": [], + "disabled": false + }, + { + "title": "奉新县", + "id": "360921", + "children": [], + "disabled": false + }, + { + "title": "万载县", + "id": "360922", + "children": [], + "disabled": false + }, + { + "title": "上高县", + "id": "360923", + "children": [], + "disabled": false + }, + { + "title": "宜丰县", + "id": "360924", + "children": [], + "disabled": false + }, + { + "title": "靖安县", + "id": "360925", + "children": [], + "disabled": false + }, + { + "title": "铜鼓县", + "id": "360926", + "children": [], + "disabled": false + }, + { + "title": "丰城市", + "id": "360981", + "children": [], + "disabled": false + }, + { + "title": "樟树市", + "id": "360982", + "children": [], + "disabled": false + }, + { + "title": "高安市", + "id": "360983", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "360901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "抚州市", + "id": "361000", + "children": [ + { + "title": "临川区", + "id": "361002", + "children": [], + "disabled": false + }, + { + "title": "东乡区", + "id": "361003", + "children": [], + "disabled": false + }, + { + "title": "南城县", + "id": "361021", + "children": [], + "disabled": false + }, + { + "title": "黎川县", + "id": "361022", + "children": [], + "disabled": false + }, + { + "title": "南丰县", + "id": "361023", + "children": [], + "disabled": false + }, + { + "title": "崇仁县", + "id": "361024", + "children": [], + "disabled": false + }, + { + "title": "乐安县", + "id": "361025", + "children": [], + "disabled": false + }, + { + "title": "宜黄县", + "id": "361026", + "children": [], + "disabled": false + }, + { + "title": "金溪县", + "id": "361027", + "children": [], + "disabled": false + }, + { + "title": "资溪县", + "id": "361028", + "children": [], + "disabled": false + }, + { + "title": "广昌县", + "id": "361030", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "361001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "上饶市", + "id": "361100", + "children": [ + { + "title": "信州区", + "id": "361102", + "children": [], + "disabled": false + }, + { + "title": "广丰区", + "id": "361103", + "children": [], + "disabled": false + }, + { + "title": "广信区", + "id": "361104", + "children": [], + "disabled": false + }, + { + "title": "玉山县", + "id": "361123", + "children": [], + "disabled": false + }, + { + "title": "铅山县", + "id": "361124", + "children": [], + "disabled": false + }, + { + "title": "横峰县", + "id": "361125", + "children": [], + "disabled": false + }, + { + "title": "弋阳县", + "id": "361126", + "children": [], + "disabled": false + }, + { + "title": "余干县", + "id": "361127", + "children": [], + "disabled": false + }, + { + "title": "鄱阳县", + "id": "361128", + "children": [], + "disabled": false + }, + { + "title": "万年县", + "id": "361129", + "children": [], + "disabled": false + }, + { + "title": "婺源县", + "id": "361130", + "children": [], + "disabled": false + }, + { + "title": "德兴市", + "id": "361181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "361101", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "山东省", + "id": "370000", + "children": [ + { + "title": "济南市", + "id": "370100", + "children": [ + { + "title": "历下区", + "id": "370102", + "children": [], + "disabled": false + }, + { + "title": "市中区", + "id": "370103", + "children": [], + "disabled": false + }, + { + "title": "槐荫区", + "id": "370104", + "children": [], + "disabled": false + }, + { + "title": "天桥区", + "id": "370105", + "children": [], + "disabled": false + }, + { + "title": "历城区", + "id": "370112", + "children": [], + "disabled": false + }, + { + "title": "长清区", + "id": "370113", + "children": [], + "disabled": false + }, + { + "title": "章丘区", + "id": "370114", + "children": [], + "disabled": false + }, + { + "title": "济阳区", + "id": "370115", + "children": [], + "disabled": false + }, + { + "title": "莱芜区", + "id": "370116", + "children": [], + "disabled": false + }, + { + "title": "钢城区", + "id": "370117", + "children": [], + "disabled": false + }, + { + "title": "平阴县", + "id": "370124", + "children": [], + "disabled": false + }, + { + "title": "商河县", + "id": "370126", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370101", + "children": [], + "disabled": false + }, + { + "title": "济南高新技术产业开发区", + "id": "370171", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "青岛市", + "id": "370200", + "children": [ + { + "title": "市南区", + "id": "370202", + "children": [], + "disabled": false + }, + { + "title": "市北区", + "id": "370203", + "children": [], + "disabled": false + }, + { + "title": "黄岛区", + "id": "370211", + "children": [], + "disabled": false + }, + { + "title": "崂山区", + "id": "370212", + "children": [], + "disabled": false + }, + { + "title": "李沧区", + "id": "370213", + "children": [], + "disabled": false + }, + { + "title": "城阳区", + "id": "370214", + "children": [], + "disabled": false + }, + { + "title": "即墨区", + "id": "370215", + "children": [], + "disabled": false + }, + { + "title": "胶州市", + "id": "370281", + "children": [], + "disabled": false + }, + { + "title": "平度市", + "id": "370283", + "children": [], + "disabled": false + }, + { + "title": "莱西市", + "id": "370285", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370201", + "children": [], + "disabled": false + }, + { + "title": "青岛高新技术产业开发区", + "id": "370271", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "淄博市", + "id": "370300", + "children": [ + { + "title": "淄川区", + "id": "370302", + "children": [], + "disabled": false + }, + { + "title": "张店区", + "id": "370303", + "children": [], + "disabled": false + }, + { + "title": "博山区", + "id": "370304", + "children": [], + "disabled": false + }, + { + "title": "临淄区", + "id": "370305", + "children": [], + "disabled": false + }, + { + "title": "周村区", + "id": "370306", + "children": [], + "disabled": false + }, + { + "title": "桓台县", + "id": "370321", + "children": [], + "disabled": false + }, + { + "title": "高青县", + "id": "370322", + "children": [], + "disabled": false + }, + { + "title": "沂源县", + "id": "370323", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "枣庄市", + "id": "370400", + "children": [ + { + "title": "市中区", + "id": "370402", + "children": [], + "disabled": false + }, + { + "title": "薛城区", + "id": "370403", + "children": [], + "disabled": false + }, + { + "title": "峄城区", + "id": "370404", + "children": [], + "disabled": false + }, + { + "title": "台儿庄区", + "id": "370405", + "children": [], + "disabled": false + }, + { + "title": "山亭区", + "id": "370406", + "children": [], + "disabled": false + }, + { + "title": "滕州市", + "id": "370481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "东营市", + "id": "370500", + "children": [ + { + "title": "东营区", + "id": "370502", + "children": [], + "disabled": false + }, + { + "title": "河口区", + "id": "370503", + "children": [], + "disabled": false + }, + { + "title": "垦利区", + "id": "370505", + "children": [], + "disabled": false + }, + { + "title": "利津县", + "id": "370522", + "children": [], + "disabled": false + }, + { + "title": "广饶县", + "id": "370523", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370501", + "children": [], + "disabled": false + }, + { + "title": "东营经济技术开发区", + "id": "370571", + "children": [], + "disabled": false + }, + { + "title": "东营港经济开发区", + "id": "370572", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "烟台市", + "id": "370600", + "children": [ + { + "title": "芝罘区", + "id": "370602", + "children": [], + "disabled": false + }, + { + "title": "福山区", + "id": "370611", + "children": [], + "disabled": false + }, + { + "title": "牟平区", + "id": "370612", + "children": [], + "disabled": false + }, + { + "title": "莱山区", + "id": "370613", + "children": [], + "disabled": false + }, + { + "title": "蓬莱区", + "id": "370614", + "children": [], + "disabled": false + }, + { + "title": "龙口市", + "id": "370681", + "children": [], + "disabled": false + }, + { + "title": "莱阳市", + "id": "370682", + "children": [], + "disabled": false + }, + { + "title": "莱州市", + "id": "370683", + "children": [], + "disabled": false + }, + { + "title": "招远市", + "id": "370685", + "children": [], + "disabled": false + }, + { + "title": "栖霞市", + "id": "370686", + "children": [], + "disabled": false + }, + { + "title": "海阳市", + "id": "370687", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370601", + "children": [], + "disabled": false + }, + { + "title": "烟台高新技术产业开发区", + "id": "370671", + "children": [], + "disabled": false + }, + { + "title": "烟台经济技术开发区", + "id": "370672", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "潍坊市", + "id": "370700", + "children": [ + { + "title": "潍城区", + "id": "370702", + "children": [], + "disabled": false + }, + { + "title": "寒亭区", + "id": "370703", + "children": [], + "disabled": false + }, + { + "title": "坊子区", + "id": "370704", + "children": [], + "disabled": false + }, + { + "title": "奎文区", + "id": "370705", + "children": [], + "disabled": false + }, + { + "title": "临朐县", + "id": "370724", + "children": [], + "disabled": false + }, + { + "title": "昌乐县", + "id": "370725", + "children": [], + "disabled": false + }, + { + "title": "青州市", + "id": "370781", + "children": [], + "disabled": false + }, + { + "title": "诸城市", + "id": "370782", + "children": [], + "disabled": false + }, + { + "title": "寿光市", + "id": "370783", + "children": [], + "disabled": false + }, + { + "title": "安丘市", + "id": "370784", + "children": [], + "disabled": false + }, + { + "title": "高密市", + "id": "370785", + "children": [], + "disabled": false + }, + { + "title": "昌邑市", + "id": "370786", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370701", + "children": [], + "disabled": false + }, + { + "title": "潍坊滨海经济技术开发区", + "id": "370772", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "济宁市", + "id": "370800", + "children": [ + { + "title": "任城区", + "id": "370811", + "children": [], + "disabled": false + }, + { + "title": "兖州区", + "id": "370812", + "children": [], + "disabled": false + }, + { + "title": "微山县", + "id": "370826", + "children": [], + "disabled": false + }, + { + "title": "鱼台县", + "id": "370827", + "children": [], + "disabled": false + }, + { + "title": "金乡县", + "id": "370828", + "children": [], + "disabled": false + }, + { + "title": "嘉祥县", + "id": "370829", + "children": [], + "disabled": false + }, + { + "title": "汶上县", + "id": "370830", + "children": [], + "disabled": false + }, + { + "title": "泗水县", + "id": "370831", + "children": [], + "disabled": false + }, + { + "title": "梁山县", + "id": "370832", + "children": [], + "disabled": false + }, + { + "title": "曲阜市", + "id": "370881", + "children": [], + "disabled": false + }, + { + "title": "邹城市", + "id": "370883", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370801", + "children": [], + "disabled": false + }, + { + "title": "济宁高新技术产业开发区", + "id": "370871", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "泰安市", + "id": "370900", + "children": [ + { + "title": "泰山区", + "id": "370902", + "children": [], + "disabled": false + }, + { + "title": "岱岳区", + "id": "370911", + "children": [], + "disabled": false + }, + { + "title": "宁阳县", + "id": "370921", + "children": [], + "disabled": false + }, + { + "title": "东平县", + "id": "370923", + "children": [], + "disabled": false + }, + { + "title": "新泰市", + "id": "370982", + "children": [], + "disabled": false + }, + { + "title": "肥城市", + "id": "370983", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "370901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "威海市", + "id": "371000", + "children": [ + { + "title": "环翠区", + "id": "371002", + "children": [], + "disabled": false + }, + { + "title": "文登区", + "id": "371003", + "children": [], + "disabled": false + }, + { + "title": "荣成市", + "id": "371082", + "children": [], + "disabled": false + }, + { + "title": "乳山市", + "id": "371083", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "371001", + "children": [], + "disabled": false + }, + { + "title": "威海火炬高技术产业开发区", + "id": "371071", + "children": [], + "disabled": false + }, + { + "title": "威海经济技术开发区", + "id": "371072", + "children": [], + "disabled": false + }, + { + "title": "威海临港经济技术开发区", + "id": "371073", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "日照市", + "id": "371100", + "children": [ + { + "title": "东港区", + "id": "371102", + "children": [], + "disabled": false + }, + { + "title": "岚山区", + "id": "371103", + "children": [], + "disabled": false + }, + { + "title": "五莲县", + "id": "371121", + "children": [], + "disabled": false + }, + { + "title": "莒县", + "id": "371122", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "371101", + "children": [], + "disabled": false + }, + { + "title": "日照经济技术开发区", + "id": "371171", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "临沂市", + "id": "371300", + "children": [ + { + "title": "兰山区", + "id": "371302", + "children": [], + "disabled": false + }, + { + "title": "罗庄区", + "id": "371311", + "children": [], + "disabled": false + }, + { + "title": "河东区", + "id": "371312", + "children": [], + "disabled": false + }, + { + "title": "沂南县", + "id": "371321", + "children": [], + "disabled": false + }, + { + "title": "郯城县", + "id": "371322", + "children": [], + "disabled": false + }, + { + "title": "沂水县", + "id": "371323", + "children": [], + "disabled": false + }, + { + "title": "兰陵县", + "id": "371324", + "children": [], + "disabled": false + }, + { + "title": "费县", + "id": "371325", + "children": [], + "disabled": false + }, + { + "title": "平邑县", + "id": "371326", + "children": [], + "disabled": false + }, + { + "title": "莒南县", + "id": "371327", + "children": [], + "disabled": false + }, + { + "title": "蒙阴县", + "id": "371328", + "children": [], + "disabled": false + }, + { + "title": "临沭县", + "id": "371329", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "371301", + "children": [], + "disabled": false + }, + { + "title": "临沂高新技术产业开发区", + "id": "371371", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "德州市", + "id": "371400", + "children": [ + { + "title": "德城区", + "id": "371402", + "children": [], + "disabled": false + }, + { + "title": "陵城区", + "id": "371403", + "children": [], + "disabled": false + }, + { + "title": "宁津县", + "id": "371422", + "children": [], + "disabled": false + }, + { + "title": "庆云县", + "id": "371423", + "children": [], + "disabled": false + }, + { + "title": "临邑县", + "id": "371424", + "children": [], + "disabled": false + }, + { + "title": "齐河县", + "id": "371425", + "children": [], + "disabled": false + }, + { + "title": "平原县", + "id": "371426", + "children": [], + "disabled": false + }, + { + "title": "夏津县", + "id": "371427", + "children": [], + "disabled": false + }, + { + "title": "武城县", + "id": "371428", + "children": [], + "disabled": false + }, + { + "title": "乐陵市", + "id": "371481", + "children": [], + "disabled": false + }, + { + "title": "禹城市", + "id": "371482", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "371401", + "children": [], + "disabled": false + }, + { + "title": "德州经济技术开发区", + "id": "371471", + "children": [], + "disabled": false + }, + { + "title": "德州运河经济开发区", + "id": "371472", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "聊城市", + "id": "371500", + "children": [ + { + "title": "东昌府区", + "id": "371502", + "children": [], + "disabled": false + }, + { + "title": "茌平区", + "id": "371503", + "children": [], + "disabled": false + }, + { + "title": "阳谷县", + "id": "371521", + "children": [], + "disabled": false + }, + { + "title": "莘县", + "id": "371522", + "children": [], + "disabled": false + }, + { + "title": "东阿县", + "id": "371524", + "children": [], + "disabled": false + }, + { + "title": "冠县", + "id": "371525", + "children": [], + "disabled": false + }, + { + "title": "高唐县", + "id": "371526", + "children": [], + "disabled": false + }, + { + "title": "临清市", + "id": "371581", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "371501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "滨州市", + "id": "371600", + "children": [ + { + "title": "滨城区", + "id": "371602", + "children": [], + "disabled": false + }, + { + "title": "沾化区", + "id": "371603", + "children": [], + "disabled": false + }, + { + "title": "惠民县", + "id": "371621", + "children": [], + "disabled": false + }, + { + "title": "阳信县", + "id": "371622", + "children": [], + "disabled": false + }, + { + "title": "无棣县", + "id": "371623", + "children": [], + "disabled": false + }, + { + "title": "博兴县", + "id": "371625", + "children": [], + "disabled": false + }, + { + "title": "邹平市", + "id": "371681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "371601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "菏泽市", + "id": "371700", + "children": [ + { + "title": "牡丹区", + "id": "371702", + "children": [], + "disabled": false + }, + { + "title": "定陶区", + "id": "371703", + "children": [], + "disabled": false + }, + { + "title": "曹县", + "id": "371721", + "children": [], + "disabled": false + }, + { + "title": "单县", + "id": "371722", + "children": [], + "disabled": false + }, + { + "title": "成武县", + "id": "371723", + "children": [], + "disabled": false + }, + { + "title": "巨野县", + "id": "371724", + "children": [], + "disabled": false + }, + { + "title": "郓城县", + "id": "371725", + "children": [], + "disabled": false + }, + { + "title": "鄄城县", + "id": "371726", + "children": [], + "disabled": false + }, + { + "title": "东明县", + "id": "371728", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "371701", + "children": [], + "disabled": false + }, + { + "title": "菏泽经济技术开发区", + "id": "371771", + "children": [], + "disabled": false + }, + { + "title": "菏泽高新技术开发区", + "id": "371772", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "河南省", + "id": "410000", + "children": [ + { + "title": "郑州市", + "id": "410100", + "children": [ + { + "title": "中原区", + "id": "410102", + "children": [], + "disabled": false + }, + { + "title": "二七区", + "id": "410103", + "children": [], + "disabled": false + }, + { + "title": "管城回族区", + "id": "410104", + "children": [], + "disabled": false + }, + { + "title": "金水区", + "id": "410105", + "children": [], + "disabled": false + }, + { + "title": "上街区", + "id": "410106", + "children": [], + "disabled": false + }, + { + "title": "惠济区", + "id": "410108", + "children": [], + "disabled": false + }, + { + "title": "中牟县", + "id": "410122", + "children": [], + "disabled": false + }, + { + "title": "巩义市", + "id": "410181", + "children": [], + "disabled": false + }, + { + "title": "荥阳市", + "id": "410182", + "children": [], + "disabled": false + }, + { + "title": "新密市", + "id": "410183", + "children": [], + "disabled": false + }, + { + "title": "新郑市", + "id": "410184", + "children": [], + "disabled": false + }, + { + "title": "登封市", + "id": "410185", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410101", + "children": [], + "disabled": false + }, + { + "title": "郑州经济技术开发区", + "id": "410171", + "children": [], + "disabled": false + }, + { + "title": "郑州高新技术产业开发区", + "id": "410172", + "children": [], + "disabled": false + }, + { + "title": "郑州航空港经济综合实验区", + "id": "410173", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "开封市", + "id": "410200", + "children": [ + { + "title": "龙亭区", + "id": "410202", + "children": [], + "disabled": false + }, + { + "title": "顺河回族区", + "id": "410203", + "children": [], + "disabled": false + }, + { + "title": "鼓楼区", + "id": "410204", + "children": [], + "disabled": false + }, + { + "title": "禹王台区", + "id": "410205", + "children": [], + "disabled": false + }, + { + "title": "祥符区", + "id": "410212", + "children": [], + "disabled": false + }, + { + "title": "杞县", + "id": "410221", + "children": [], + "disabled": false + }, + { + "title": "通许县", + "id": "410222", + "children": [], + "disabled": false + }, + { + "title": "尉氏县", + "id": "410223", + "children": [], + "disabled": false + }, + { + "title": "兰考县", + "id": "410225", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "洛阳市", + "id": "410300", + "children": [ + { + "title": "老城区", + "id": "410302", + "children": [], + "disabled": false + }, + { + "title": "西工区", + "id": "410303", + "children": [], + "disabled": false + }, + { + "title": "瀍河回族区", + "id": "410304", + "children": [], + "disabled": false + }, + { + "title": "涧西区", + "id": "410305", + "children": [], + "disabled": false + }, + { + "title": "吉利区", + "id": "410306", + "children": [], + "disabled": false + }, + { + "title": "洛龙区", + "id": "410311", + "children": [], + "disabled": false + }, + { + "title": "孟津县", + "id": "410322", + "children": [], + "disabled": false + }, + { + "title": "新安县", + "id": "410323", + "children": [], + "disabled": false + }, + { + "title": "栾川县", + "id": "410324", + "children": [], + "disabled": false + }, + { + "title": "嵩县", + "id": "410325", + "children": [], + "disabled": false + }, + { + "title": "汝阳县", + "id": "410326", + "children": [], + "disabled": false + }, + { + "title": "宜阳县", + "id": "410327", + "children": [], + "disabled": false + }, + { + "title": "洛宁县", + "id": "410328", + "children": [], + "disabled": false + }, + { + "title": "伊川县", + "id": "410329", + "children": [], + "disabled": false + }, + { + "title": "偃师市", + "id": "410381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410301", + "children": [], + "disabled": false + }, + { + "title": "偃师区", + "id": "410307", + "children": [], + "disabled": false + }, + { + "title": "孟津区", + "id": "410308", + "children": [], + "disabled": false + }, + { + "title": "洛阳高新技术产业开发区", + "id": "410371", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "平顶山市", + "id": "410400", + "children": [ + { + "title": "新华区", + "id": "410402", + "children": [], + "disabled": false + }, + { + "title": "卫东区", + "id": "410403", + "children": [], + "disabled": false + }, + { + "title": "石龙区", + "id": "410404", + "children": [], + "disabled": false + }, + { + "title": "湛河区", + "id": "410411", + "children": [], + "disabled": false + }, + { + "title": "宝丰县", + "id": "410421", + "children": [], + "disabled": false + }, + { + "title": "叶县", + "id": "410422", + "children": [], + "disabled": false + }, + { + "title": "鲁山县", + "id": "410423", + "children": [], + "disabled": false + }, + { + "title": "郏县", + "id": "410425", + "children": [], + "disabled": false + }, + { + "title": "舞钢市", + "id": "410481", + "children": [], + "disabled": false + }, + { + "title": "汝州市", + "id": "410482", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410401", + "children": [], + "disabled": false + }, + { + "title": "平顶山高新技术产业开发区", + "id": "410471", + "children": [], + "disabled": false + }, + { + "title": "平顶山市城乡一体化示范区", + "id": "410472", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "安阳市", + "id": "410500", + "children": [ + { + "title": "文峰区", + "id": "410502", + "children": [], + "disabled": false + }, + { + "title": "北关区", + "id": "410503", + "children": [], + "disabled": false + }, + { + "title": "殷都区", + "id": "410505", + "children": [], + "disabled": false + }, + { + "title": "龙安区", + "id": "410506", + "children": [], + "disabled": false + }, + { + "title": "安阳县", + "id": "410522", + "children": [], + "disabled": false + }, + { + "title": "汤阴县", + "id": "410523", + "children": [], + "disabled": false + }, + { + "title": "滑县", + "id": "410526", + "children": [], + "disabled": false + }, + { + "title": "内黄县", + "id": "410527", + "children": [], + "disabled": false + }, + { + "title": "林州市", + "id": "410581", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410501", + "children": [], + "disabled": false + }, + { + "title": "安阳高新技术产业开发区", + "id": "410571", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "鹤壁市", + "id": "410600", + "children": [ + { + "title": "鹤山区", + "id": "410602", + "children": [], + "disabled": false + }, + { + "title": "山城区", + "id": "410603", + "children": [], + "disabled": false + }, + { + "title": "淇滨区", + "id": "410611", + "children": [], + "disabled": false + }, + { + "title": "浚县", + "id": "410621", + "children": [], + "disabled": false + }, + { + "title": "淇县", + "id": "410622", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410601", + "children": [], + "disabled": false + }, + { + "title": "鹤壁经济技术开发区", + "id": "410671", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "新乡市", + "id": "410700", + "children": [ + { + "title": "红旗区", + "id": "410702", + "children": [], + "disabled": false + }, + { + "title": "卫滨区", + "id": "410703", + "children": [], + "disabled": false + }, + { + "title": "凤泉区", + "id": "410704", + "children": [], + "disabled": false + }, + { + "title": "牧野区", + "id": "410711", + "children": [], + "disabled": false + }, + { + "title": "新乡县", + "id": "410721", + "children": [], + "disabled": false + }, + { + "title": "获嘉县", + "id": "410724", + "children": [], + "disabled": false + }, + { + "title": "原阳县", + "id": "410725", + "children": [], + "disabled": false + }, + { + "title": "延津县", + "id": "410726", + "children": [], + "disabled": false + }, + { + "title": "封丘县", + "id": "410727", + "children": [], + "disabled": false + }, + { + "title": "卫辉市", + "id": "410781", + "children": [], + "disabled": false + }, + { + "title": "辉县市", + "id": "410782", + "children": [], + "disabled": false + }, + { + "title": "长垣市", + "id": "410783", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410701", + "children": [], + "disabled": false + }, + { + "title": "新乡高新技术产业开发区", + "id": "410771", + "children": [], + "disabled": false + }, + { + "title": "新乡经济技术开发区", + "id": "410772", + "children": [], + "disabled": false + }, + { + "title": "新乡市平原城乡一体化示范区", + "id": "410773", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "焦作市", + "id": "410800", + "children": [ + { + "title": "解放区", + "id": "410802", + "children": [], + "disabled": false + }, + { + "title": "中站区", + "id": "410803", + "children": [], + "disabled": false + }, + { + "title": "马村区", + "id": "410804", + "children": [], + "disabled": false + }, + { + "title": "山阳区", + "id": "410811", + "children": [], + "disabled": false + }, + { + "title": "修武县", + "id": "410821", + "children": [], + "disabled": false + }, + { + "title": "博爱县", + "id": "410822", + "children": [], + "disabled": false + }, + { + "title": "武陟县", + "id": "410823", + "children": [], + "disabled": false + }, + { + "title": "温县", + "id": "410825", + "children": [], + "disabled": false + }, + { + "title": "沁阳市", + "id": "410882", + "children": [], + "disabled": false + }, + { + "title": "孟州市", + "id": "410883", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410801", + "children": [], + "disabled": false + }, + { + "title": "焦作城乡一体化示范区", + "id": "410871", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "濮阳市", + "id": "410900", + "children": [ + { + "title": "华龙区", + "id": "410902", + "children": [], + "disabled": false + }, + { + "title": "清丰县", + "id": "410922", + "children": [], + "disabled": false + }, + { + "title": "南乐县", + "id": "410923", + "children": [], + "disabled": false + }, + { + "title": "范县", + "id": "410926", + "children": [], + "disabled": false + }, + { + "title": "台前县", + "id": "410927", + "children": [], + "disabled": false + }, + { + "title": "濮阳县", + "id": "410928", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "410901", + "children": [], + "disabled": false + }, + { + "title": "河南濮阳工业园区", + "id": "410971", + "children": [], + "disabled": false + }, + { + "title": "濮阳经济技术开发区", + "id": "410972", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "许昌市", + "id": "411000", + "children": [ + { + "title": "魏都区", + "id": "411002", + "children": [], + "disabled": false + }, + { + "title": "建安区", + "id": "411003", + "children": [], + "disabled": false + }, + { + "title": "鄢陵县", + "id": "411024", + "children": [], + "disabled": false + }, + { + "title": "襄城县", + "id": "411025", + "children": [], + "disabled": false + }, + { + "title": "禹州市", + "id": "411081", + "children": [], + "disabled": false + }, + { + "title": "长葛市", + "id": "411082", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411001", + "children": [], + "disabled": false + }, + { + "title": "许昌经济技术开发区", + "id": "411071", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "漯河市", + "id": "411100", + "children": [ + { + "title": "源汇区", + "id": "411102", + "children": [], + "disabled": false + }, + { + "title": "郾城区", + "id": "411103", + "children": [], + "disabled": false + }, + { + "title": "召陵区", + "id": "411104", + "children": [], + "disabled": false + }, + { + "title": "舞阳县", + "id": "411121", + "children": [], + "disabled": false + }, + { + "title": "临颍县", + "id": "411122", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411101", + "children": [], + "disabled": false + }, + { + "title": "漯河经济技术开发区", + "id": "411171", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "三门峡市", + "id": "411200", + "children": [ + { + "title": "湖滨区", + "id": "411202", + "children": [], + "disabled": false + }, + { + "title": "陕州区", + "id": "411203", + "children": [], + "disabled": false + }, + { + "title": "渑池县", + "id": "411221", + "children": [], + "disabled": false + }, + { + "title": "卢氏县", + "id": "411224", + "children": [], + "disabled": false + }, + { + "title": "义马市", + "id": "411281", + "children": [], + "disabled": false + }, + { + "title": "灵宝市", + "id": "411282", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411201", + "children": [], + "disabled": false + }, + { + "title": "河南三门峡经济开发区", + "id": "411271", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "南阳市", + "id": "411300", + "children": [ + { + "title": "宛城区", + "id": "411302", + "children": [], + "disabled": false + }, + { + "title": "卧龙区", + "id": "411303", + "children": [], + "disabled": false + }, + { + "title": "南召县", + "id": "411321", + "children": [], + "disabled": false + }, + { + "title": "方城县", + "id": "411322", + "children": [], + "disabled": false + }, + { + "title": "西峡县", + "id": "411323", + "children": [], + "disabled": false + }, + { + "title": "镇平县", + "id": "411324", + "children": [], + "disabled": false + }, + { + "title": "内乡县", + "id": "411325", + "children": [], + "disabled": false + }, + { + "title": "淅川县", + "id": "411326", + "children": [], + "disabled": false + }, + { + "title": "社旗县", + "id": "411327", + "children": [], + "disabled": false + }, + { + "title": "唐河县", + "id": "411328", + "children": [], + "disabled": false + }, + { + "title": "新野县", + "id": "411329", + "children": [], + "disabled": false + }, + { + "title": "桐柏县", + "id": "411330", + "children": [], + "disabled": false + }, + { + "title": "邓州市", + "id": "411381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411301", + "children": [], + "disabled": false + }, + { + "title": "南阳高新技术产业开发区", + "id": "411371", + "children": [], + "disabled": false + }, + { + "title": "南阳市城乡一体化示范区", + "id": "411372", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "商丘市", + "id": "411400", + "children": [ + { + "title": "梁园区", + "id": "411402", + "children": [], + "disabled": false + }, + { + "title": "睢阳区", + "id": "411403", + "children": [], + "disabled": false + }, + { + "title": "民权县", + "id": "411421", + "children": [], + "disabled": false + }, + { + "title": "睢县", + "id": "411422", + "children": [], + "disabled": false + }, + { + "title": "宁陵县", + "id": "411423", + "children": [], + "disabled": false + }, + { + "title": "柘城县", + "id": "411424", + "children": [], + "disabled": false + }, + { + "title": "虞城县", + "id": "411425", + "children": [], + "disabled": false + }, + { + "title": "夏邑县", + "id": "411426", + "children": [], + "disabled": false + }, + { + "title": "永城市", + "id": "411481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411401", + "children": [], + "disabled": false + }, + { + "title": "豫东综合物流产业聚集区", + "id": "411471", + "children": [], + "disabled": false + }, + { + "title": "河南商丘经济开发区", + "id": "411472", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "信阳市", + "id": "411500", + "children": [ + { + "title": "浉河区", + "id": "411502", + "children": [], + "disabled": false + }, + { + "title": "平桥区", + "id": "411503", + "children": [], + "disabled": false + }, + { + "title": "罗山县", + "id": "411521", + "children": [], + "disabled": false + }, + { + "title": "光山县", + "id": "411522", + "children": [], + "disabled": false + }, + { + "title": "新县", + "id": "411523", + "children": [], + "disabled": false + }, + { + "title": "商城县", + "id": "411524", + "children": [], + "disabled": false + }, + { + "title": "固始县", + "id": "411525", + "children": [], + "disabled": false + }, + { + "title": "潢川县", + "id": "411526", + "children": [], + "disabled": false + }, + { + "title": "淮滨县", + "id": "411527", + "children": [], + "disabled": false + }, + { + "title": "息县", + "id": "411528", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411501", + "children": [], + "disabled": false + }, + { + "title": "信阳高新技术产业开发区", + "id": "411571", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "周口市", + "id": "411600", + "children": [ + { + "title": "川汇区", + "id": "411602", + "children": [], + "disabled": false + }, + { + "title": "淮阳区", + "id": "411603", + "children": [], + "disabled": false + }, + { + "title": "扶沟县", + "id": "411621", + "children": [], + "disabled": false + }, + { + "title": "西华县", + "id": "411622", + "children": [], + "disabled": false + }, + { + "title": "商水县", + "id": "411623", + "children": [], + "disabled": false + }, + { + "title": "沈丘县", + "id": "411624", + "children": [], + "disabled": false + }, + { + "title": "郸城县", + "id": "411625", + "children": [], + "disabled": false + }, + { + "title": "太康县", + "id": "411627", + "children": [], + "disabled": false + }, + { + "title": "鹿邑县", + "id": "411628", + "children": [], + "disabled": false + }, + { + "title": "项城市", + "id": "411681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411601", + "children": [], + "disabled": false + }, + { + "title": "河南周口经济开发区", + "id": "411671", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "驻马店市", + "id": "411700", + "children": [ + { + "title": "驿城区", + "id": "411702", + "children": [], + "disabled": false + }, + { + "title": "西平县", + "id": "411721", + "children": [], + "disabled": false + }, + { + "title": "上蔡县", + "id": "411722", + "children": [], + "disabled": false + }, + { + "title": "平舆县", + "id": "411723", + "children": [], + "disabled": false + }, + { + "title": "正阳县", + "id": "411724", + "children": [], + "disabled": false + }, + { + "title": "确山县", + "id": "411725", + "children": [], + "disabled": false + }, + { + "title": "泌阳县", + "id": "411726", + "children": [], + "disabled": false + }, + { + "title": "汝南县", + "id": "411727", + "children": [], + "disabled": false + }, + { + "title": "遂平县", + "id": "411728", + "children": [], + "disabled": false + }, + { + "title": "新蔡县", + "id": "411729", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "411701", + "children": [], + "disabled": false + }, + { + "title": "河南驻马店经济开发区", + "id": "411771", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "河南省-省直辖县级行政区划", + "id": "419000", + "children": [ + { + "title": "济源市", + "id": "419001", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "湖北省", + "id": "420000", + "children": [ + { + "title": "武汉市", + "id": "420100", + "children": [ + { + "title": "江岸区", + "id": "420102", + "children": [], + "disabled": false + }, + { + "title": "江汉区", + "id": "420103", + "children": [], + "disabled": false + }, + { + "title": "硚口区", + "id": "420104", + "children": [], + "disabled": false + }, + { + "title": "汉阳区", + "id": "420105", + "children": [], + "disabled": false + }, + { + "title": "武昌区", + "id": "420106", + "children": [], + "disabled": false + }, + { + "title": "青山区", + "id": "420107", + "children": [], + "disabled": false + }, + { + "title": "洪山区", + "id": "420111", + "children": [], + "disabled": false + }, + { + "title": "东西湖区", + "id": "420112", + "children": [], + "disabled": false + }, + { + "title": "汉南区", + "id": "420113", + "children": [], + "disabled": false + }, + { + "title": "蔡甸区", + "id": "420114", + "children": [], + "disabled": false + }, + { + "title": "江夏区", + "id": "420115", + "children": [], + "disabled": false + }, + { + "title": "黄陂区", + "id": "420116", + "children": [], + "disabled": false + }, + { + "title": "新洲区", + "id": "420117", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黄石市", + "id": "420200", + "children": [ + { + "title": "黄石港区", + "id": "420202", + "children": [], + "disabled": false + }, + { + "title": "西塞山区", + "id": "420203", + "children": [], + "disabled": false + }, + { + "title": "下陆区", + "id": "420204", + "children": [], + "disabled": false + }, + { + "title": "铁山区", + "id": "420205", + "children": [], + "disabled": false + }, + { + "title": "阳新县", + "id": "420222", + "children": [], + "disabled": false + }, + { + "title": "大冶市", + "id": "420281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "十堰市", + "id": "420300", + "children": [ + { + "title": "茅箭区", + "id": "420302", + "children": [], + "disabled": false + }, + { + "title": "张湾区", + "id": "420303", + "children": [], + "disabled": false + }, + { + "title": "郧阳区", + "id": "420304", + "children": [], + "disabled": false + }, + { + "title": "郧西县", + "id": "420322", + "children": [], + "disabled": false + }, + { + "title": "竹山县", + "id": "420323", + "children": [], + "disabled": false + }, + { + "title": "竹溪县", + "id": "420324", + "children": [], + "disabled": false + }, + { + "title": "房县", + "id": "420325", + "children": [], + "disabled": false + }, + { + "title": "丹江口市", + "id": "420381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宜昌市", + "id": "420500", + "children": [ + { + "title": "西陵区", + "id": "420502", + "children": [], + "disabled": false + }, + { + "title": "伍家岗区", + "id": "420503", + "children": [], + "disabled": false + }, + { + "title": "点军区", + "id": "420504", + "children": [], + "disabled": false + }, + { + "title": "猇亭区", + "id": "420505", + "children": [], + "disabled": false + }, + { + "title": "夷陵区", + "id": "420506", + "children": [], + "disabled": false + }, + { + "title": "远安县", + "id": "420525", + "children": [], + "disabled": false + }, + { + "title": "兴山县", + "id": "420526", + "children": [], + "disabled": false + }, + { + "title": "秭归县", + "id": "420527", + "children": [], + "disabled": false + }, + { + "title": "长阳土家族自治县", + "id": "420528", + "children": [], + "disabled": false + }, + { + "title": "五峰土家族自治县", + "id": "420529", + "children": [], + "disabled": false + }, + { + "title": "宜都市", + "id": "420581", + "children": [], + "disabled": false + }, + { + "title": "当阳市", + "id": "420582", + "children": [], + "disabled": false + }, + { + "title": "枝江市", + "id": "420583", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "襄阳市", + "id": "420600", + "children": [ + { + "title": "襄城区", + "id": "420602", + "children": [], + "disabled": false + }, + { + "title": "樊城区", + "id": "420606", + "children": [], + "disabled": false + }, + { + "title": "襄州区", + "id": "420607", + "children": [], + "disabled": false + }, + { + "title": "南漳县", + "id": "420624", + "children": [], + "disabled": false + }, + { + "title": "谷城县", + "id": "420625", + "children": [], + "disabled": false + }, + { + "title": "保康县", + "id": "420626", + "children": [], + "disabled": false + }, + { + "title": "老河口市", + "id": "420682", + "children": [], + "disabled": false + }, + { + "title": "枣阳市", + "id": "420683", + "children": [], + "disabled": false + }, + { + "title": "宜城市", + "id": "420684", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "鄂州市", + "id": "420700", + "children": [ + { + "title": "梁子湖区", + "id": "420702", + "children": [], + "disabled": false + }, + { + "title": "华容区", + "id": "420703", + "children": [], + "disabled": false + }, + { + "title": "鄂城区", + "id": "420704", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "荆门市", + "id": "420800", + "children": [ + { + "title": "东宝区", + "id": "420802", + "children": [], + "disabled": false + }, + { + "title": "掇刀区", + "id": "420804", + "children": [], + "disabled": false + }, + { + "title": "沙洋县", + "id": "420822", + "children": [], + "disabled": false + }, + { + "title": "钟祥市", + "id": "420881", + "children": [], + "disabled": false + }, + { + "title": "京山市", + "id": "420882", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "孝感市", + "id": "420900", + "children": [ + { + "title": "孝南区", + "id": "420902", + "children": [], + "disabled": false + }, + { + "title": "孝昌县", + "id": "420921", + "children": [], + "disabled": false + }, + { + "title": "大悟县", + "id": "420922", + "children": [], + "disabled": false + }, + { + "title": "云梦县", + "id": "420923", + "children": [], + "disabled": false + }, + { + "title": "应城市", + "id": "420981", + "children": [], + "disabled": false + }, + { + "title": "安陆市", + "id": "420982", + "children": [], + "disabled": false + }, + { + "title": "汉川市", + "id": "420984", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "420901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "荆州市", + "id": "421000", + "children": [ + { + "title": "沙市区", + "id": "421002", + "children": [], + "disabled": false + }, + { + "title": "荆州区", + "id": "421003", + "children": [], + "disabled": false + }, + { + "title": "公安县", + "id": "421022", + "children": [], + "disabled": false + }, + { + "title": "江陵县", + "id": "421024", + "children": [], + "disabled": false + }, + { + "title": "石首市", + "id": "421081", + "children": [], + "disabled": false + }, + { + "title": "洪湖市", + "id": "421083", + "children": [], + "disabled": false + }, + { + "title": "松滋市", + "id": "421087", + "children": [], + "disabled": false + }, + { + "title": "监利市", + "id": "421088", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "421001", + "children": [], + "disabled": false + }, + { + "title": "荆州经济技术开发区", + "id": "421071", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黄冈市", + "id": "421100", + "children": [ + { + "title": "黄州区", + "id": "421102", + "children": [], + "disabled": false + }, + { + "title": "团风县", + "id": "421121", + "children": [], + "disabled": false + }, + { + "title": "红安县", + "id": "421122", + "children": [], + "disabled": false + }, + { + "title": "罗田县", + "id": "421123", + "children": [], + "disabled": false + }, + { + "title": "英山县", + "id": "421124", + "children": [], + "disabled": false + }, + { + "title": "浠水县", + "id": "421125", + "children": [], + "disabled": false + }, + { + "title": "蕲春县", + "id": "421126", + "children": [], + "disabled": false + }, + { + "title": "黄梅县", + "id": "421127", + "children": [], + "disabled": false + }, + { + "title": "麻城市", + "id": "421181", + "children": [], + "disabled": false + }, + { + "title": "武穴市", + "id": "421182", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "421101", + "children": [], + "disabled": false + }, + { + "title": "龙感湖管理区", + "id": "421171", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "咸宁市", + "id": "421200", + "children": [ + { + "title": "咸安区", + "id": "421202", + "children": [], + "disabled": false + }, + { + "title": "嘉鱼县", + "id": "421221", + "children": [], + "disabled": false + }, + { + "title": "通城县", + "id": "421222", + "children": [], + "disabled": false + }, + { + "title": "崇阳县", + "id": "421223", + "children": [], + "disabled": false + }, + { + "title": "通山县", + "id": "421224", + "children": [], + "disabled": false + }, + { + "title": "赤壁市", + "id": "421281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "421201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "随州市", + "id": "421300", + "children": [ + { + "title": "曾都区", + "id": "421303", + "children": [], + "disabled": false + }, + { + "title": "随县", + "id": "421321", + "children": [], + "disabled": false + }, + { + "title": "广水市", + "id": "421381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "421301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "恩施土家族苗族自治州", + "id": "422800", + "children": [ + { + "title": "恩施市", + "id": "422801", + "children": [], + "disabled": false + }, + { + "title": "利川市", + "id": "422802", + "children": [], + "disabled": false + }, + { + "title": "建始县", + "id": "422822", + "children": [], + "disabled": false + }, + { + "title": "巴东县", + "id": "422823", + "children": [], + "disabled": false + }, + { + "title": "宣恩县", + "id": "422825", + "children": [], + "disabled": false + }, + { + "title": "咸丰县", + "id": "422826", + "children": [], + "disabled": false + }, + { + "title": "来凤县", + "id": "422827", + "children": [], + "disabled": false + }, + { + "title": "鹤峰县", + "id": "422828", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "湖北省-自治区直辖县级行政区划", + "id": "429000", + "children": [ + { + "title": "仙桃市", + "id": "429004", + "children": [], + "disabled": false + }, + { + "title": "潜江市", + "id": "429005", + "children": [], + "disabled": false + }, + { + "title": "天门市", + "id": "429006", + "children": [], + "disabled": false + }, + { + "title": "神农架林区", + "id": "429021", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "湖南省", + "id": "430000", + "children": [ + { + "title": "长沙市", + "id": "430100", + "children": [ + { + "title": "芙蓉区", + "id": "430102", + "children": [], + "disabled": false + }, + { + "title": "天心区", + "id": "430103", + "children": [], + "disabled": false + }, + { + "title": "岳麓区", + "id": "430104", + "children": [], + "disabled": false + }, + { + "title": "开福区", + "id": "430105", + "children": [], + "disabled": false + }, + { + "title": "雨花区", + "id": "430111", + "children": [], + "disabled": false + }, + { + "title": "望城区", + "id": "430112", + "children": [], + "disabled": false + }, + { + "title": "长沙县", + "id": "430121", + "children": [], + "disabled": false + }, + { + "title": "浏阳市", + "id": "430181", + "children": [], + "disabled": false + }, + { + "title": "宁乡市", + "id": "430182", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "株洲市", + "id": "430200", + "children": [ + { + "title": "荷塘区", + "id": "430202", + "children": [], + "disabled": false + }, + { + "title": "芦淞区", + "id": "430203", + "children": [], + "disabled": false + }, + { + "title": "石峰区", + "id": "430204", + "children": [], + "disabled": false + }, + { + "title": "天元区", + "id": "430211", + "children": [], + "disabled": false + }, + { + "title": "渌口区", + "id": "430212", + "children": [], + "disabled": false + }, + { + "title": "攸县", + "id": "430223", + "children": [], + "disabled": false + }, + { + "title": "茶陵县", + "id": "430224", + "children": [], + "disabled": false + }, + { + "title": "炎陵县", + "id": "430225", + "children": [], + "disabled": false + }, + { + "title": "醴陵市", + "id": "430281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430201", + "children": [], + "disabled": false + }, + { + "title": "云龙示范区", + "id": "430271", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "湘潭市", + "id": "430300", + "children": [ + { + "title": "雨湖区", + "id": "430302", + "children": [], + "disabled": false + }, + { + "title": "岳塘区", + "id": "430304", + "children": [], + "disabled": false + }, + { + "title": "湘潭县", + "id": "430321", + "children": [], + "disabled": false + }, + { + "title": "湘乡市", + "id": "430381", + "children": [], + "disabled": false + }, + { + "title": "韶山市", + "id": "430382", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430301", + "children": [], + "disabled": false + }, + { + "title": "湖南湘潭高新技术产业园区", + "id": "430371", + "children": [], + "disabled": false + }, + { + "title": "湘潭昭山示范区", + "id": "430372", + "children": [], + "disabled": false + }, + { + "title": "湘潭九华示范区", + "id": "430373", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "衡阳市", + "id": "430400", + "children": [ + { + "title": "珠晖区", + "id": "430405", + "children": [], + "disabled": false + }, + { + "title": "雁峰区", + "id": "430406", + "children": [], + "disabled": false + }, + { + "title": "石鼓区", + "id": "430407", + "children": [], + "disabled": false + }, + { + "title": "蒸湘区", + "id": "430408", + "children": [], + "disabled": false + }, + { + "title": "南岳区", + "id": "430412", + "children": [], + "disabled": false + }, + { + "title": "衡阳县", + "id": "430421", + "children": [], + "disabled": false + }, + { + "title": "衡南县", + "id": "430422", + "children": [], + "disabled": false + }, + { + "title": "衡山县", + "id": "430423", + "children": [], + "disabled": false + }, + { + "title": "衡东县", + "id": "430424", + "children": [], + "disabled": false + }, + { + "title": "祁东县", + "id": "430426", + "children": [], + "disabled": false + }, + { + "title": "耒阳市", + "id": "430481", + "children": [], + "disabled": false + }, + { + "title": "常宁市", + "id": "430482", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430401", + "children": [], + "disabled": false + }, + { + "title": "衡阳综合保税区", + "id": "430471", + "children": [], + "disabled": false + }, + { + "title": "湖南衡阳高新技术产业园区", + "id": "430472", + "children": [], + "disabled": false + }, + { + "title": "湖南衡阳松木经济开发区", + "id": "430473", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "邵阳市", + "id": "430500", + "children": [ + { + "title": "双清区", + "id": "430502", + "children": [], + "disabled": false + }, + { + "title": "大祥区", + "id": "430503", + "children": [], + "disabled": false + }, + { + "title": "北塔区", + "id": "430511", + "children": [], + "disabled": false + }, + { + "title": "新邵县", + "id": "430522", + "children": [], + "disabled": false + }, + { + "title": "邵阳县", + "id": "430523", + "children": [], + "disabled": false + }, + { + "title": "隆回县", + "id": "430524", + "children": [], + "disabled": false + }, + { + "title": "洞口县", + "id": "430525", + "children": [], + "disabled": false + }, + { + "title": "绥宁县", + "id": "430527", + "children": [], + "disabled": false + }, + { + "title": "新宁县", + "id": "430528", + "children": [], + "disabled": false + }, + { + "title": "城步苗族自治县", + "id": "430529", + "children": [], + "disabled": false + }, + { + "title": "武冈市", + "id": "430581", + "children": [], + "disabled": false + }, + { + "title": "邵东市", + "id": "430582", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "岳阳市", + "id": "430600", + "children": [ + { + "title": "岳阳楼区", + "id": "430602", + "children": [], + "disabled": false + }, + { + "title": "云溪区", + "id": "430603", + "children": [], + "disabled": false + }, + { + "title": "君山区", + "id": "430611", + "children": [], + "disabled": false + }, + { + "title": "岳阳县", + "id": "430621", + "children": [], + "disabled": false + }, + { + "title": "华容县", + "id": "430623", + "children": [], + "disabled": false + }, + { + "title": "湘阴县", + "id": "430624", + "children": [], + "disabled": false + }, + { + "title": "平江县", + "id": "430626", + "children": [], + "disabled": false + }, + { + "title": "汨罗市", + "id": "430681", + "children": [], + "disabled": false + }, + { + "title": "临湘市", + "id": "430682", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430601", + "children": [], + "disabled": false + }, + { + "title": "岳阳市屈原管理区", + "id": "430671", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "常德市", + "id": "430700", + "children": [ + { + "title": "武陵区", + "id": "430702", + "children": [], + "disabled": false + }, + { + "title": "鼎城区", + "id": "430703", + "children": [], + "disabled": false + }, + { + "title": "安乡县", + "id": "430721", + "children": [], + "disabled": false + }, + { + "title": "汉寿县", + "id": "430722", + "children": [], + "disabled": false + }, + { + "title": "澧县", + "id": "430723", + "children": [], + "disabled": false + }, + { + "title": "临澧县", + "id": "430724", + "children": [], + "disabled": false + }, + { + "title": "桃源县", + "id": "430725", + "children": [], + "disabled": false + }, + { + "title": "石门县", + "id": "430726", + "children": [], + "disabled": false + }, + { + "title": "津市市", + "id": "430781", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430701", + "children": [], + "disabled": false + }, + { + "title": "常德市西洞庭管理区", + "id": "430771", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "张家界市", + "id": "430800", + "children": [ + { + "title": "永定区", + "id": "430802", + "children": [], + "disabled": false + }, + { + "title": "武陵源区", + "id": "430811", + "children": [], + "disabled": false + }, + { + "title": "慈利县", + "id": "430821", + "children": [], + "disabled": false + }, + { + "title": "桑植县", + "id": "430822", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "益阳市", + "id": "430900", + "children": [ + { + "title": "资阳区", + "id": "430902", + "children": [], + "disabled": false + }, + { + "title": "赫山区", + "id": "430903", + "children": [], + "disabled": false + }, + { + "title": "南县", + "id": "430921", + "children": [], + "disabled": false + }, + { + "title": "桃江县", + "id": "430922", + "children": [], + "disabled": false + }, + { + "title": "安化县", + "id": "430923", + "children": [], + "disabled": false + }, + { + "title": "沅江市", + "id": "430981", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "430901", + "children": [], + "disabled": false + }, + { + "title": "益阳市大通湖管理区", + "id": "430971", + "children": [], + "disabled": false + }, + { + "title": "湖南益阳高新技术产业园区", + "id": "430972", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "郴州市", + "id": "431000", + "children": [ + { + "title": "北湖区", + "id": "431002", + "children": [], + "disabled": false + }, + { + "title": "苏仙区", + "id": "431003", + "children": [], + "disabled": false + }, + { + "title": "桂阳县", + "id": "431021", + "children": [], + "disabled": false + }, + { + "title": "宜章县", + "id": "431022", + "children": [], + "disabled": false + }, + { + "title": "永兴县", + "id": "431023", + "children": [], + "disabled": false + }, + { + "title": "嘉禾县", + "id": "431024", + "children": [], + "disabled": false + }, + { + "title": "临武县", + "id": "431025", + "children": [], + "disabled": false + }, + { + "title": "汝城县", + "id": "431026", + "children": [], + "disabled": false + }, + { + "title": "桂东县", + "id": "431027", + "children": [], + "disabled": false + }, + { + "title": "安仁县", + "id": "431028", + "children": [], + "disabled": false + }, + { + "title": "资兴市", + "id": "431081", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "431001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "永州市", + "id": "431100", + "children": [ + { + "title": "零陵区", + "id": "431102", + "children": [], + "disabled": false + }, + { + "title": "冷水滩区", + "id": "431103", + "children": [], + "disabled": false + }, + { + "title": "祁阳县", + "id": "431121", + "children": [], + "disabled": false + }, + { + "title": "东安县", + "id": "431122", + "children": [], + "disabled": false + }, + { + "title": "双牌县", + "id": "431123", + "children": [], + "disabled": false + }, + { + "title": "道县", + "id": "431124", + "children": [], + "disabled": false + }, + { + "title": "江永县", + "id": "431125", + "children": [], + "disabled": false + }, + { + "title": "宁远县", + "id": "431126", + "children": [], + "disabled": false + }, + { + "title": "蓝山县", + "id": "431127", + "children": [], + "disabled": false + }, + { + "title": "新田县", + "id": "431128", + "children": [], + "disabled": false + }, + { + "title": "江华瑶族自治县", + "id": "431129", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "431101", + "children": [], + "disabled": false + }, + { + "title": "永州经济技术开发区", + "id": "431171", + "children": [], + "disabled": false + }, + { + "title": "永州市回龙圩管理区", + "id": "431173", + "children": [], + "disabled": false + }, + { + "title": "祁阳市", + "id": "431181", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "怀化市", + "id": "431200", + "children": [ + { + "title": "鹤城区", + "id": "431202", + "children": [], + "disabled": false + }, + { + "title": "中方县", + "id": "431221", + "children": [], + "disabled": false + }, + { + "title": "沅陵县", + "id": "431222", + "children": [], + "disabled": false + }, + { + "title": "辰溪县", + "id": "431223", + "children": [], + "disabled": false + }, + { + "title": "溆浦县", + "id": "431224", + "children": [], + "disabled": false + }, + { + "title": "会同县", + "id": "431225", + "children": [], + "disabled": false + }, + { + "title": "麻阳苗族自治县", + "id": "431226", + "children": [], + "disabled": false + }, + { + "title": "新晃侗族自治县", + "id": "431227", + "children": [], + "disabled": false + }, + { + "title": "芷江侗族自治县", + "id": "431228", + "children": [], + "disabled": false + }, + { + "title": "靖州苗族侗族自治县", + "id": "431229", + "children": [], + "disabled": false + }, + { + "title": "通道侗族自治县", + "id": "431230", + "children": [], + "disabled": false + }, + { + "title": "洪江市", + "id": "431281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "431201", + "children": [], + "disabled": false + }, + { + "title": "怀化市洪江管理区", + "id": "431271", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "娄底市", + "id": "431300", + "children": [ + { + "title": "娄星区", + "id": "431302", + "children": [], + "disabled": false + }, + { + "title": "双峰县", + "id": "431321", + "children": [], + "disabled": false + }, + { + "title": "新化县", + "id": "431322", + "children": [], + "disabled": false + }, + { + "title": "冷水江市", + "id": "431381", + "children": [], + "disabled": false + }, + { + "title": "涟源市", + "id": "431382", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "431301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "湘西土家族苗族自治州", + "id": "433100", + "children": [ + { + "title": "吉首市", + "id": "433101", + "children": [], + "disabled": false + }, + { + "title": "泸溪县", + "id": "433122", + "children": [], + "disabled": false + }, + { + "title": "凤凰县", + "id": "433123", + "children": [], + "disabled": false + }, + { + "title": "花垣县", + "id": "433124", + "children": [], + "disabled": false + }, + { + "title": "保靖县", + "id": "433125", + "children": [], + "disabled": false + }, + { + "title": "古丈县", + "id": "433126", + "children": [], + "disabled": false + }, + { + "title": "永顺县", + "id": "433127", + "children": [], + "disabled": false + }, + { + "title": "龙山县", + "id": "433130", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "广东省", + "id": "440000", + "children": [ + { + "title": "广州市", + "id": "440100", + "children": [ + { + "title": "荔湾区", + "id": "440103", + "children": [], + "disabled": false + }, + { + "title": "越秀区", + "id": "440104", + "children": [], + "disabled": false + }, + { + "title": "海珠区", + "id": "440105", + "children": [], + "disabled": false + }, + { + "title": "天河区", + "id": "440106", + "children": [], + "disabled": false + }, + { + "title": "白云区", + "id": "440111", + "children": [], + "disabled": false + }, + { + "title": "黄埔区", + "id": "440112", + "children": [], + "disabled": false + }, + { + "title": "番禺区", + "id": "440113", + "children": [], + "disabled": false + }, + { + "title": "花都区", + "id": "440114", + "children": [], + "disabled": false + }, + { + "title": "南沙区", + "id": "440115", + "children": [], + "disabled": false + }, + { + "title": "从化区", + "id": "440117", + "children": [], + "disabled": false + }, + { + "title": "增城区", + "id": "440118", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "韶关市", + "id": "440200", + "children": [ + { + "title": "武江区", + "id": "440203", + "children": [], + "disabled": false + }, + { + "title": "浈江区", + "id": "440204", + "children": [], + "disabled": false + }, + { + "title": "曲江区", + "id": "440205", + "children": [], + "disabled": false + }, + { + "title": "始兴县", + "id": "440222", + "children": [], + "disabled": false + }, + { + "title": "仁化县", + "id": "440224", + "children": [], + "disabled": false + }, + { + "title": "翁源县", + "id": "440229", + "children": [], + "disabled": false + }, + { + "title": "乳源瑶族自治县", + "id": "440232", + "children": [], + "disabled": false + }, + { + "title": "新丰县", + "id": "440233", + "children": [], + "disabled": false + }, + { + "title": "乐昌市", + "id": "440281", + "children": [], + "disabled": false + }, + { + "title": "南雄市", + "id": "440282", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "深圳市", + "id": "440300", + "children": [ + { + "title": "罗湖区", + "id": "440303", + "children": [], + "disabled": false + }, + { + "title": "福田区", + "id": "440304", + "children": [], + "disabled": false + }, + { + "title": "南山区", + "id": "440305", + "children": [], + "disabled": false + }, + { + "title": "宝安区", + "id": "440306", + "children": [], + "disabled": false + }, + { + "title": "龙岗区", + "id": "440307", + "children": [], + "disabled": false + }, + { + "title": "盐田区", + "id": "440308", + "children": [], + "disabled": false + }, + { + "title": "龙华区", + "id": "440309", + "children": [], + "disabled": false + }, + { + "title": "坪山区", + "id": "440310", + "children": [], + "disabled": false + }, + { + "title": "光明区", + "id": "440311", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "珠海市", + "id": "440400", + "children": [ + { + "title": "香洲区", + "id": "440402", + "children": [], + "disabled": false + }, + { + "title": "斗门区", + "id": "440403", + "children": [], + "disabled": false + }, + { + "title": "金湾区", + "id": "440404", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "汕头市", + "id": "440500", + "children": [ + { + "title": "龙湖区", + "id": "440507", + "children": [], + "disabled": false + }, + { + "title": "金平区", + "id": "440511", + "children": [], + "disabled": false + }, + { + "title": "濠江区", + "id": "440512", + "children": [], + "disabled": false + }, + { + "title": "潮阳区", + "id": "440513", + "children": [], + "disabled": false + }, + { + "title": "潮南区", + "id": "440514", + "children": [], + "disabled": false + }, + { + "title": "澄海区", + "id": "440515", + "children": [], + "disabled": false + }, + { + "title": "南澳县", + "id": "440523", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "佛山市", + "id": "440600", + "children": [ + { + "title": "禅城区", + "id": "440604", + "children": [], + "disabled": false + }, + { + "title": "南海区", + "id": "440605", + "children": [], + "disabled": false + }, + { + "title": "顺德区", + "id": "440606", + "children": [], + "disabled": false + }, + { + "title": "三水区", + "id": "440607", + "children": [], + "disabled": false + }, + { + "title": "高明区", + "id": "440608", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "江门市", + "id": "440700", + "children": [ + { + "title": "蓬江区", + "id": "440703", + "children": [], + "disabled": false + }, + { + "title": "江海区", + "id": "440704", + "children": [], + "disabled": false + }, + { + "title": "新会区", + "id": "440705", + "children": [], + "disabled": false + }, + { + "title": "台山市", + "id": "440781", + "children": [], + "disabled": false + }, + { + "title": "开平市", + "id": "440783", + "children": [], + "disabled": false + }, + { + "title": "鹤山市", + "id": "440784", + "children": [], + "disabled": false + }, + { + "title": "恩平市", + "id": "440785", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "湛江市", + "id": "440800", + "children": [ + { + "title": "赤坎区", + "id": "440802", + "children": [], + "disabled": false + }, + { + "title": "霞山区", + "id": "440803", + "children": [], + "disabled": false + }, + { + "title": "坡头区", + "id": "440804", + "children": [], + "disabled": false + }, + { + "title": "麻章区", + "id": "440811", + "children": [], + "disabled": false + }, + { + "title": "遂溪县", + "id": "440823", + "children": [], + "disabled": false + }, + { + "title": "徐闻县", + "id": "440825", + "children": [], + "disabled": false + }, + { + "title": "廉江市", + "id": "440881", + "children": [], + "disabled": false + }, + { + "title": "雷州市", + "id": "440882", + "children": [], + "disabled": false + }, + { + "title": "吴川市", + "id": "440883", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "茂名市", + "id": "440900", + "children": [ + { + "title": "茂南区", + "id": "440902", + "children": [], + "disabled": false + }, + { + "title": "电白区", + "id": "440904", + "children": [], + "disabled": false + }, + { + "title": "高州市", + "id": "440981", + "children": [], + "disabled": false + }, + { + "title": "化州市", + "id": "440982", + "children": [], + "disabled": false + }, + { + "title": "信宜市", + "id": "440983", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "440901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "肇庆市", + "id": "441200", + "children": [ + { + "title": "端州区", + "id": "441202", + "children": [], + "disabled": false + }, + { + "title": "鼎湖区", + "id": "441203", + "children": [], + "disabled": false + }, + { + "title": "高要区", + "id": "441204", + "children": [], + "disabled": false + }, + { + "title": "广宁县", + "id": "441223", + "children": [], + "disabled": false + }, + { + "title": "怀集县", + "id": "441224", + "children": [], + "disabled": false + }, + { + "title": "封开县", + "id": "441225", + "children": [], + "disabled": false + }, + { + "title": "德庆县", + "id": "441226", + "children": [], + "disabled": false + }, + { + "title": "四会市", + "id": "441284", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "441201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "惠州市", + "id": "441300", + "children": [ + { + "title": "惠城区", + "id": "441302", + "children": [], + "disabled": false + }, + { + "title": "惠阳区", + "id": "441303", + "children": [], + "disabled": false + }, + { + "title": "博罗县", + "id": "441322", + "children": [], + "disabled": false + }, + { + "title": "惠东县", + "id": "441323", + "children": [], + "disabled": false + }, + { + "title": "龙门县", + "id": "441324", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "441301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "梅州市", + "id": "441400", + "children": [ + { + "title": "梅江区", + "id": "441402", + "children": [], + "disabled": false + }, + { + "title": "梅县区", + "id": "441403", + "children": [], + "disabled": false + }, + { + "title": "大埔县", + "id": "441422", + "children": [], + "disabled": false + }, + { + "title": "丰顺县", + "id": "441423", + "children": [], + "disabled": false + }, + { + "title": "五华县", + "id": "441424", + "children": [], + "disabled": false + }, + { + "title": "平远县", + "id": "441426", + "children": [], + "disabled": false + }, + { + "title": "蕉岭县", + "id": "441427", + "children": [], + "disabled": false + }, + { + "title": "兴宁市", + "id": "441481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "441401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "汕尾市", + "id": "441500", + "children": [ + { + "title": "城区", + "id": "441502", + "children": [], + "disabled": false + }, + { + "title": "海丰县", + "id": "441521", + "children": [], + "disabled": false + }, + { + "title": "陆河县", + "id": "441523", + "children": [], + "disabled": false + }, + { + "title": "陆丰市", + "id": "441581", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "441501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "河源市", + "id": "441600", + "children": [ + { + "title": "源城区", + "id": "441602", + "children": [], + "disabled": false + }, + { + "title": "紫金县", + "id": "441621", + "children": [], + "disabled": false + }, + { + "title": "龙川县", + "id": "441622", + "children": [], + "disabled": false + }, + { + "title": "连平县", + "id": "441623", + "children": [], + "disabled": false + }, + { + "title": "和平县", + "id": "441624", + "children": [], + "disabled": false + }, + { + "title": "东源县", + "id": "441625", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "441601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阳江市", + "id": "441700", + "children": [ + { + "title": "江城区", + "id": "441702", + "children": [], + "disabled": false + }, + { + "title": "阳东区", + "id": "441704", + "children": [], + "disabled": false + }, + { + "title": "阳西县", + "id": "441721", + "children": [], + "disabled": false + }, + { + "title": "阳春市", + "id": "441781", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "441701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "清远市", + "id": "441800", + "children": [ + { + "title": "清城区", + "id": "441802", + "children": [], + "disabled": false + }, + { + "title": "清新区", + "id": "441803", + "children": [], + "disabled": false + }, + { + "title": "佛冈县", + "id": "441821", + "children": [], + "disabled": false + }, + { + "title": "阳山县", + "id": "441823", + "children": [], + "disabled": false + }, + { + "title": "连山壮族瑶族自治县", + "id": "441825", + "children": [], + "disabled": false + }, + { + "title": "连南瑶族自治县", + "id": "441826", + "children": [], + "disabled": false + }, + { + "title": "英德市", + "id": "441881", + "children": [], + "disabled": false + }, + { + "title": "连州市", + "id": "441882", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "441801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "东莞市", + "id": "441900", + "children": [], + "disabled": false + }, + { + "title": "中山市", + "id": "442000", + "children": [], + "disabled": false + }, + { + "title": "潮州市", + "id": "445100", + "children": [ + { + "title": "湘桥区", + "id": "445102", + "children": [], + "disabled": false + }, + { + "title": "潮安区", + "id": "445103", + "children": [], + "disabled": false + }, + { + "title": "饶平县", + "id": "445122", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "445101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "揭阳市", + "id": "445200", + "children": [ + { + "title": "榕城区", + "id": "445202", + "children": [], + "disabled": false + }, + { + "title": "揭东区", + "id": "445203", + "children": [], + "disabled": false + }, + { + "title": "揭西县", + "id": "445222", + "children": [], + "disabled": false + }, + { + "title": "惠来县", + "id": "445224", + "children": [], + "disabled": false + }, + { + "title": "普宁市", + "id": "445281", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "445201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "云浮市", + "id": "445300", + "children": [ + { + "title": "云城区", + "id": "445302", + "children": [], + "disabled": false + }, + { + "title": "云安区", + "id": "445303", + "children": [], + "disabled": false + }, + { + "title": "新兴县", + "id": "445321", + "children": [], + "disabled": false + }, + { + "title": "郁南县", + "id": "445322", + "children": [], + "disabled": false + }, + { + "title": "罗定市", + "id": "445381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "445301", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "广西壮族自治区", + "id": "450000", + "children": [ + { + "title": "南宁市", + "id": "450100", + "children": [ + { + "title": "兴宁区", + "id": "450102", + "children": [], + "disabled": false + }, + { + "title": "青秀区", + "id": "450103", + "children": [], + "disabled": false + }, + { + "title": "江南区", + "id": "450105", + "children": [], + "disabled": false + }, + { + "title": "西乡塘区", + "id": "450107", + "children": [], + "disabled": false + }, + { + "title": "良庆区", + "id": "450108", + "children": [], + "disabled": false + }, + { + "title": "邕宁区", + "id": "450109", + "children": [], + "disabled": false + }, + { + "title": "武鸣区", + "id": "450110", + "children": [], + "disabled": false + }, + { + "title": "隆安县", + "id": "450123", + "children": [], + "disabled": false + }, + { + "title": "马山县", + "id": "450124", + "children": [], + "disabled": false + }, + { + "title": "上林县", + "id": "450125", + "children": [], + "disabled": false + }, + { + "title": "宾阳县", + "id": "450126", + "children": [], + "disabled": false + }, + { + "title": "横县", + "id": "450127", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450101", + "children": [], + "disabled": false + }, + { + "title": "横州市", + "id": "450181", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "柳州市", + "id": "450200", + "children": [ + { + "title": "城中区", + "id": "450202", + "children": [], + "disabled": false + }, + { + "title": "鱼峰区", + "id": "450203", + "children": [], + "disabled": false + }, + { + "title": "柳南区", + "id": "450204", + "children": [], + "disabled": false + }, + { + "title": "柳北区", + "id": "450205", + "children": [], + "disabled": false + }, + { + "title": "柳江区", + "id": "450206", + "children": [], + "disabled": false + }, + { + "title": "柳城县", + "id": "450222", + "children": [], + "disabled": false + }, + { + "title": "鹿寨县", + "id": "450223", + "children": [], + "disabled": false + }, + { + "title": "融安县", + "id": "450224", + "children": [], + "disabled": false + }, + { + "title": "融水苗族自治县", + "id": "450225", + "children": [], + "disabled": false + }, + { + "title": "三江侗族自治县", + "id": "450226", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "桂林市", + "id": "450300", + "children": [ + { + "title": "秀峰区", + "id": "450302", + "children": [], + "disabled": false + }, + { + "title": "叠彩区", + "id": "450303", + "children": [], + "disabled": false + }, + { + "title": "象山区", + "id": "450304", + "children": [], + "disabled": false + }, + { + "title": "七星区", + "id": "450305", + "children": [], + "disabled": false + }, + { + "title": "雁山区", + "id": "450311", + "children": [], + "disabled": false + }, + { + "title": "临桂区", + "id": "450312", + "children": [], + "disabled": false + }, + { + "title": "阳朔县", + "id": "450321", + "children": [], + "disabled": false + }, + { + "title": "灵川县", + "id": "450323", + "children": [], + "disabled": false + }, + { + "title": "全州县", + "id": "450324", + "children": [], + "disabled": false + }, + { + "title": "兴安县", + "id": "450325", + "children": [], + "disabled": false + }, + { + "title": "永福县", + "id": "450326", + "children": [], + "disabled": false + }, + { + "title": "灌阳县", + "id": "450327", + "children": [], + "disabled": false + }, + { + "title": "龙胜各族自治县", + "id": "450328", + "children": [], + "disabled": false + }, + { + "title": "资源县", + "id": "450329", + "children": [], + "disabled": false + }, + { + "title": "平乐县", + "id": "450330", + "children": [], + "disabled": false + }, + { + "title": "恭城瑶族自治县", + "id": "450332", + "children": [], + "disabled": false + }, + { + "title": "荔浦市", + "id": "450381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "梧州市", + "id": "450400", + "children": [ + { + "title": "万秀区", + "id": "450403", + "children": [], + "disabled": false + }, + { + "title": "长洲区", + "id": "450405", + "children": [], + "disabled": false + }, + { + "title": "龙圩区", + "id": "450406", + "children": [], + "disabled": false + }, + { + "title": "苍梧县", + "id": "450421", + "children": [], + "disabled": false + }, + { + "title": "藤县", + "id": "450422", + "children": [], + "disabled": false + }, + { + "title": "蒙山县", + "id": "450423", + "children": [], + "disabled": false + }, + { + "title": "岑溪市", + "id": "450481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "北海市", + "id": "450500", + "children": [ + { + "title": "海城区", + "id": "450502", + "children": [], + "disabled": false + }, + { + "title": "银海区", + "id": "450503", + "children": [], + "disabled": false + }, + { + "title": "铁山港区", + "id": "450512", + "children": [], + "disabled": false + }, + { + "title": "合浦县", + "id": "450521", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "防城港市", + "id": "450600", + "children": [ + { + "title": "港口区", + "id": "450602", + "children": [], + "disabled": false + }, + { + "title": "防城区", + "id": "450603", + "children": [], + "disabled": false + }, + { + "title": "上思县", + "id": "450621", + "children": [], + "disabled": false + }, + { + "title": "东兴市", + "id": "450681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "钦州市", + "id": "450700", + "children": [ + { + "title": "钦南区", + "id": "450702", + "children": [], + "disabled": false + }, + { + "title": "钦北区", + "id": "450703", + "children": [], + "disabled": false + }, + { + "title": "灵山县", + "id": "450721", + "children": [], + "disabled": false + }, + { + "title": "浦北县", + "id": "450722", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "贵港市", + "id": "450800", + "children": [ + { + "title": "港北区", + "id": "450802", + "children": [], + "disabled": false + }, + { + "title": "港南区", + "id": "450803", + "children": [], + "disabled": false + }, + { + "title": "覃塘区", + "id": "450804", + "children": [], + "disabled": false + }, + { + "title": "平南县", + "id": "450821", + "children": [], + "disabled": false + }, + { + "title": "桂平市", + "id": "450881", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "玉林市", + "id": "450900", + "children": [ + { + "title": "玉州区", + "id": "450902", + "children": [], + "disabled": false + }, + { + "title": "福绵区", + "id": "450903", + "children": [], + "disabled": false + }, + { + "title": "容县", + "id": "450921", + "children": [], + "disabled": false + }, + { + "title": "陆川县", + "id": "450922", + "children": [], + "disabled": false + }, + { + "title": "博白县", + "id": "450923", + "children": [], + "disabled": false + }, + { + "title": "兴业县", + "id": "450924", + "children": [], + "disabled": false + }, + { + "title": "北流市", + "id": "450981", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "450901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "百色市", + "id": "451000", + "children": [ + { + "title": "右江区", + "id": "451002", + "children": [], + "disabled": false + }, + { + "title": "田阳区", + "id": "451003", + "children": [], + "disabled": false + }, + { + "title": "田东县", + "id": "451022", + "children": [], + "disabled": false + }, + { + "title": "德保县", + "id": "451024", + "children": [], + "disabled": false + }, + { + "title": "那坡县", + "id": "451026", + "children": [], + "disabled": false + }, + { + "title": "凌云县", + "id": "451027", + "children": [], + "disabled": false + }, + { + "title": "乐业县", + "id": "451028", + "children": [], + "disabled": false + }, + { + "title": "田林县", + "id": "451029", + "children": [], + "disabled": false + }, + { + "title": "西林县", + "id": "451030", + "children": [], + "disabled": false + }, + { + "title": "隆林各族自治县", + "id": "451031", + "children": [], + "disabled": false + }, + { + "title": "靖西市", + "id": "451081", + "children": [], + "disabled": false + }, + { + "title": "平果市", + "id": "451082", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "451001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "贺州市", + "id": "451100", + "children": [ + { + "title": "八步区", + "id": "451102", + "children": [], + "disabled": false + }, + { + "title": "平桂区", + "id": "451103", + "children": [], + "disabled": false + }, + { + "title": "昭平县", + "id": "451121", + "children": [], + "disabled": false + }, + { + "title": "钟山县", + "id": "451122", + "children": [], + "disabled": false + }, + { + "title": "富川瑶族自治县", + "id": "451123", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "451101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "河池市", + "id": "451200", + "children": [ + { + "title": "金城江区", + "id": "451202", + "children": [], + "disabled": false + }, + { + "title": "宜州区", + "id": "451203", + "children": [], + "disabled": false + }, + { + "title": "南丹县", + "id": "451221", + "children": [], + "disabled": false + }, + { + "title": "天峨县", + "id": "451222", + "children": [], + "disabled": false + }, + { + "title": "凤山县", + "id": "451223", + "children": [], + "disabled": false + }, + { + "title": "东兰县", + "id": "451224", + "children": [], + "disabled": false + }, + { + "title": "罗城仫佬族自治县", + "id": "451225", + "children": [], + "disabled": false + }, + { + "title": "环江毛南族自治县", + "id": "451226", + "children": [], + "disabled": false + }, + { + "title": "巴马瑶族自治县", + "id": "451227", + "children": [], + "disabled": false + }, + { + "title": "都安瑶族自治县", + "id": "451228", + "children": [], + "disabled": false + }, + { + "title": "大化瑶族自治县", + "id": "451229", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "451201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "来宾市", + "id": "451300", + "children": [ + { + "title": "兴宾区", + "id": "451302", + "children": [], + "disabled": false + }, + { + "title": "忻城县", + "id": "451321", + "children": [], + "disabled": false + }, + { + "title": "象州县", + "id": "451322", + "children": [], + "disabled": false + }, + { + "title": "武宣县", + "id": "451323", + "children": [], + "disabled": false + }, + { + "title": "金秀瑶族自治县", + "id": "451324", + "children": [], + "disabled": false + }, + { + "title": "合山市", + "id": "451381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "451301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "崇左市", + "id": "451400", + "children": [ + { + "title": "江州区", + "id": "451402", + "children": [], + "disabled": false + }, + { + "title": "扶绥县", + "id": "451421", + "children": [], + "disabled": false + }, + { + "title": "宁明县", + "id": "451422", + "children": [], + "disabled": false + }, + { + "title": "龙州县", + "id": "451423", + "children": [], + "disabled": false + }, + { + "title": "大新县", + "id": "451424", + "children": [], + "disabled": false + }, + { + "title": "天等县", + "id": "451425", + "children": [], + "disabled": false + }, + { + "title": "凭祥市", + "id": "451481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "451401", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "海南省", + "id": "460000", + "children": [ + { + "title": "海口市", + "id": "460100", + "children": [ + { + "title": "秀英区", + "id": "460105", + "children": [], + "disabled": false + }, + { + "title": "龙华区", + "id": "460106", + "children": [], + "disabled": false + }, + { + "title": "琼山区", + "id": "460107", + "children": [], + "disabled": false + }, + { + "title": "美兰区", + "id": "460108", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "460101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "三亚市", + "id": "460200", + "children": [ + { + "title": "海棠区", + "id": "460202", + "children": [], + "disabled": false + }, + { + "title": "吉阳区", + "id": "460203", + "children": [], + "disabled": false + }, + { + "title": "天涯区", + "id": "460204", + "children": [], + "disabled": false + }, + { + "title": "崖州区", + "id": "460205", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "460201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "三沙市", + "id": "460300", + "children": [ + { + "title": "西沙群岛", + "id": "460321", + "children": [], + "disabled": false + }, + { + "title": "南沙群岛", + "id": "460322", + "children": [], + "disabled": false + }, + { + "title": "中沙群岛的岛礁及其海域", + "id": "460323", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "儋州市", + "id": "460400", + "children": [], + "disabled": false + }, + { + "title": "海南省-自治区直辖县级行政区划", + "id": "469000", + "children": [ + { + "title": "五指山市", + "id": "469001", + "children": [], + "disabled": false + }, + { + "title": "琼海市", + "id": "469002", + "children": [], + "disabled": false + }, + { + "title": "文昌市", + "id": "469005", + "children": [], + "disabled": false + }, + { + "title": "万宁市", + "id": "469006", + "children": [], + "disabled": false + }, + { + "title": "东方市", + "id": "469007", + "children": [], + "disabled": false + }, + { + "title": "定安县", + "id": "469021", + "children": [], + "disabled": false + }, + { + "title": "屯昌县", + "id": "469022", + "children": [], + "disabled": false + }, + { + "title": "澄迈县", + "id": "469023", + "children": [], + "disabled": false + }, + { + "title": "临高县", + "id": "469024", + "children": [], + "disabled": false + }, + { + "title": "白沙黎族自治县", + "id": "469025", + "children": [], + "disabled": false + }, + { + "title": "昌江黎族自治县", + "id": "469026", + "children": [], + "disabled": false + }, + { + "title": "乐东黎族自治县", + "id": "469027", + "children": [], + "disabled": false + }, + { + "title": "陵水黎族自治县", + "id": "469028", + "children": [], + "disabled": false + }, + { + "title": "保亭黎族苗族自治县", + "id": "469029", + "children": [], + "disabled": false + }, + { + "title": "琼中黎族苗族自治县", + "id": "469030", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "重庆市", + "id": "500000", + "children": [ + { + "title": "重庆市", + "id": "5000001", + "children": [ + { + "title": "万州区", + "id": "500101", + "children": [], + "disabled": false + }, + { + "title": "涪陵区", + "id": "500102", + "children": [], + "disabled": false + }, + { + "title": "渝中区", + "id": "500103", + "children": [], + "disabled": false + }, + { + "title": "大渡口区", + "id": "500104", + "children": [], + "disabled": false + }, + { + "title": "江北区", + "id": "500105", + "children": [], + "disabled": false + }, + { + "title": "沙坪坝区", + "id": "500106", + "children": [], + "disabled": false + }, + { + "title": "九龙坡区", + "id": "500107", + "children": [], + "disabled": false + }, + { + "title": "南岸区", + "id": "500108", + "children": [], + "disabled": false + }, + { + "title": "北碚区", + "id": "500109", + "children": [], + "disabled": false + }, + { + "title": "綦江区", + "id": "500110", + "children": [], + "disabled": false + }, + { + "title": "大足区", + "id": "500111", + "children": [], + "disabled": false + }, + { + "title": "渝北区", + "id": "500112", + "children": [], + "disabled": false + }, + { + "title": "巴南区", + "id": "500113", + "children": [], + "disabled": false + }, + { + "title": "黔江区", + "id": "500114", + "children": [], + "disabled": false + }, + { + "title": "长寿区", + "id": "500115", + "children": [], + "disabled": false + }, + { + "title": "江津区", + "id": "500116", + "children": [], + "disabled": false + }, + { + "title": "合川区", + "id": "500117", + "children": [], + "disabled": false + }, + { + "title": "永川区", + "id": "500118", + "children": [], + "disabled": false + }, + { + "title": "南川区", + "id": "500119", + "children": [], + "disabled": false + }, + { + "title": "璧山区", + "id": "500120", + "children": [], + "disabled": false + }, + { + "title": "铜梁区", + "id": "500151", + "children": [], + "disabled": false + }, + { + "title": "潼南区", + "id": "500152", + "children": [], + "disabled": false + }, + { + "title": "荣昌区", + "id": "500153", + "children": [], + "disabled": false + }, + { + "title": "开州区", + "id": "500154", + "children": [], + "disabled": false + }, + { + "title": "梁平区", + "id": "500155", + "children": [], + "disabled": false + }, + { + "title": "武隆区", + "id": "500156", + "children": [], + "disabled": false + }, + { + "title": "城口县", + "id": "500229", + "children": [], + "disabled": false + }, + { + "title": "丰都县", + "id": "500230", + "children": [], + "disabled": false + }, + { + "title": "垫江县", + "id": "500231", + "children": [], + "disabled": false + }, + { + "title": "忠县", + "id": "500233", + "children": [], + "disabled": false + }, + { + "title": "云阳县", + "id": "500235", + "children": [], + "disabled": false + }, + { + "title": "奉节县", + "id": "500236", + "children": [], + "disabled": false + }, + { + "title": "巫山县", + "id": "500237", + "children": [], + "disabled": false + }, + { + "title": "巫溪县", + "id": "500238", + "children": [], + "disabled": false + }, + { + "title": "石柱土家族自治县", + "id": "500240", + "children": [], + "disabled": false + }, + { + "title": "秀山土家族苗族自治县", + "id": "500241", + "children": [], + "disabled": false + }, + { + "title": "酉阳土家族苗族自治县", + "id": "500242", + "children": [], + "disabled": false + }, + { + "title": "彭水苗族土家族自治县", + "id": "500243", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "四川省", + "id": "510000", + "children": [ + { + "title": "成都市", + "id": "510100", + "children": [ + { + "title": "锦江区", + "id": "510104", + "children": [], + "disabled": false + }, + { + "title": "青羊区", + "id": "510105", + "children": [], + "disabled": false + }, + { + "title": "金牛区", + "id": "510106", + "children": [], + "disabled": false + }, + { + "title": "武侯区", + "id": "510107", + "children": [], + "disabled": false + }, + { + "title": "成华区", + "id": "510108", + "children": [], + "disabled": false + }, + { + "title": "龙泉驿区", + "id": "510112", + "children": [], + "disabled": false + }, + { + "title": "青白江区", + "id": "510113", + "children": [], + "disabled": false + }, + { + "title": "新都区", + "id": "510114", + "children": [], + "disabled": false + }, + { + "title": "温江区", + "id": "510115", + "children": [], + "disabled": false + }, + { + "title": "双流区", + "id": "510116", + "children": [], + "disabled": false + }, + { + "title": "郫都区", + "id": "510117", + "children": [], + "disabled": false + }, + { + "title": "新津区", + "id": "510118", + "children": [], + "disabled": false + }, + { + "title": "金堂县", + "id": "510121", + "children": [], + "disabled": false + }, + { + "title": "大邑县", + "id": "510129", + "children": [], + "disabled": false + }, + { + "title": "蒲江县", + "id": "510131", + "children": [], + "disabled": false + }, + { + "title": "都江堰市", + "id": "510181", + "children": [], + "disabled": false + }, + { + "title": "彭州市", + "id": "510182", + "children": [], + "disabled": false + }, + { + "title": "邛崃市", + "id": "510183", + "children": [], + "disabled": false + }, + { + "title": "崇州市", + "id": "510184", + "children": [], + "disabled": false + }, + { + "title": "简阳市", + "id": "510185", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "自贡市", + "id": "510300", + "children": [ + { + "title": "自流井区", + "id": "510302", + "children": [], + "disabled": false + }, + { + "title": "贡井区", + "id": "510303", + "children": [], + "disabled": false + }, + { + "title": "大安区", + "id": "510304", + "children": [], + "disabled": false + }, + { + "title": "沿滩区", + "id": "510311", + "children": [], + "disabled": false + }, + { + "title": "荣县", + "id": "510321", + "children": [], + "disabled": false + }, + { + "title": "富顺县", + "id": "510322", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "攀枝花市", + "id": "510400", + "children": [ + { + "title": "东区", + "id": "510402", + "children": [], + "disabled": false + }, + { + "title": "西区", + "id": "510403", + "children": [], + "disabled": false + }, + { + "title": "仁和区", + "id": "510411", + "children": [], + "disabled": false + }, + { + "title": "米易县", + "id": "510421", + "children": [], + "disabled": false + }, + { + "title": "盐边县", + "id": "510422", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "泸州市", + "id": "510500", + "children": [ + { + "title": "江阳区", + "id": "510502", + "children": [], + "disabled": false + }, + { + "title": "纳溪区", + "id": "510503", + "children": [], + "disabled": false + }, + { + "title": "龙马潭区", + "id": "510504", + "children": [], + "disabled": false + }, + { + "title": "泸县", + "id": "510521", + "children": [], + "disabled": false + }, + { + "title": "合江县", + "id": "510522", + "children": [], + "disabled": false + }, + { + "title": "叙永县", + "id": "510524", + "children": [], + "disabled": false + }, + { + "title": "古蔺县", + "id": "510525", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "德阳市", + "id": "510600", + "children": [ + { + "title": "旌阳区", + "id": "510603", + "children": [], + "disabled": false + }, + { + "title": "罗江区", + "id": "510604", + "children": [], + "disabled": false + }, + { + "title": "中江县", + "id": "510623", + "children": [], + "disabled": false + }, + { + "title": "广汉市", + "id": "510681", + "children": [], + "disabled": false + }, + { + "title": "什邡市", + "id": "510682", + "children": [], + "disabled": false + }, + { + "title": "绵竹市", + "id": "510683", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "绵阳市", + "id": "510700", + "children": [ + { + "title": "涪城区", + "id": "510703", + "children": [], + "disabled": false + }, + { + "title": "游仙区", + "id": "510704", + "children": [], + "disabled": false + }, + { + "title": "安州区", + "id": "510705", + "children": [], + "disabled": false + }, + { + "title": "三台县", + "id": "510722", + "children": [], + "disabled": false + }, + { + "title": "盐亭县", + "id": "510723", + "children": [], + "disabled": false + }, + { + "title": "梓潼县", + "id": "510725", + "children": [], + "disabled": false + }, + { + "title": "北川羌族自治县", + "id": "510726", + "children": [], + "disabled": false + }, + { + "title": "平武县", + "id": "510727", + "children": [], + "disabled": false + }, + { + "title": "江油市", + "id": "510781", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "广元市", + "id": "510800", + "children": [ + { + "title": "利州区", + "id": "510802", + "children": [], + "disabled": false + }, + { + "title": "昭化区", + "id": "510811", + "children": [], + "disabled": false + }, + { + "title": "朝天区", + "id": "510812", + "children": [], + "disabled": false + }, + { + "title": "旺苍县", + "id": "510821", + "children": [], + "disabled": false + }, + { + "title": "青川县", + "id": "510822", + "children": [], + "disabled": false + }, + { + "title": "剑阁县", + "id": "510823", + "children": [], + "disabled": false + }, + { + "title": "苍溪县", + "id": "510824", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "遂宁市", + "id": "510900", + "children": [ + { + "title": "船山区", + "id": "510903", + "children": [], + "disabled": false + }, + { + "title": "安居区", + "id": "510904", + "children": [], + "disabled": false + }, + { + "title": "蓬溪县", + "id": "510921", + "children": [], + "disabled": false + }, + { + "title": "大英县", + "id": "510923", + "children": [], + "disabled": false + }, + { + "title": "射洪市", + "id": "510981", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "510901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "内江市", + "id": "511000", + "children": [ + { + "title": "市中区", + "id": "511002", + "children": [], + "disabled": false + }, + { + "title": "东兴区", + "id": "511011", + "children": [], + "disabled": false + }, + { + "title": "威远县", + "id": "511024", + "children": [], + "disabled": false + }, + { + "title": "资中县", + "id": "511025", + "children": [], + "disabled": false + }, + { + "title": "隆昌市", + "id": "511083", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511001", + "children": [], + "disabled": false + }, + { + "title": "内江经济开发区", + "id": "511071", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "乐山市", + "id": "511100", + "children": [ + { + "title": "市中区", + "id": "511102", + "children": [], + "disabled": false + }, + { + "title": "沙湾区", + "id": "511111", + "children": [], + "disabled": false + }, + { + "title": "五通桥区", + "id": "511112", + "children": [], + "disabled": false + }, + { + "title": "金口河区", + "id": "511113", + "children": [], + "disabled": false + }, + { + "title": "犍为县", + "id": "511123", + "children": [], + "disabled": false + }, + { + "title": "井研县", + "id": "511124", + "children": [], + "disabled": false + }, + { + "title": "夹江县", + "id": "511126", + "children": [], + "disabled": false + }, + { + "title": "沐川县", + "id": "511129", + "children": [], + "disabled": false + }, + { + "title": "峨边彝族自治县", + "id": "511132", + "children": [], + "disabled": false + }, + { + "title": "马边彝族自治县", + "id": "511133", + "children": [], + "disabled": false + }, + { + "title": "峨眉山市", + "id": "511181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "南充市", + "id": "511300", + "children": [ + { + "title": "顺庆区", + "id": "511302", + "children": [], + "disabled": false + }, + { + "title": "高坪区", + "id": "511303", + "children": [], + "disabled": false + }, + { + "title": "嘉陵区", + "id": "511304", + "children": [], + "disabled": false + }, + { + "title": "南部县", + "id": "511321", + "children": [], + "disabled": false + }, + { + "title": "营山县", + "id": "511322", + "children": [], + "disabled": false + }, + { + "title": "蓬安县", + "id": "511323", + "children": [], + "disabled": false + }, + { + "title": "仪陇县", + "id": "511324", + "children": [], + "disabled": false + }, + { + "title": "西充县", + "id": "511325", + "children": [], + "disabled": false + }, + { + "title": "阆中市", + "id": "511381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "眉山市", + "id": "511400", + "children": [ + { + "title": "东坡区", + "id": "511402", + "children": [], + "disabled": false + }, + { + "title": "彭山区", + "id": "511403", + "children": [], + "disabled": false + }, + { + "title": "仁寿县", + "id": "511421", + "children": [], + "disabled": false + }, + { + "title": "洪雅县", + "id": "511423", + "children": [], + "disabled": false + }, + { + "title": "丹棱县", + "id": "511424", + "children": [], + "disabled": false + }, + { + "title": "青神县", + "id": "511425", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宜宾市", + "id": "511500", + "children": [ + { + "title": "翠屏区", + "id": "511502", + "children": [], + "disabled": false + }, + { + "title": "南溪区", + "id": "511503", + "children": [], + "disabled": false + }, + { + "title": "叙州区", + "id": "511504", + "children": [], + "disabled": false + }, + { + "title": "江安县", + "id": "511523", + "children": [], + "disabled": false + }, + { + "title": "长宁县", + "id": "511524", + "children": [], + "disabled": false + }, + { + "title": "高县", + "id": "511525", + "children": [], + "disabled": false + }, + { + "title": "珙县", + "id": "511526", + "children": [], + "disabled": false + }, + { + "title": "筠连县", + "id": "511527", + "children": [], + "disabled": false + }, + { + "title": "兴文县", + "id": "511528", + "children": [], + "disabled": false + }, + { + "title": "屏山县", + "id": "511529", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "广安市", + "id": "511600", + "children": [ + { + "title": "广安区", + "id": "511602", + "children": [], + "disabled": false + }, + { + "title": "前锋区", + "id": "511603", + "children": [], + "disabled": false + }, + { + "title": "岳池县", + "id": "511621", + "children": [], + "disabled": false + }, + { + "title": "武胜县", + "id": "511622", + "children": [], + "disabled": false + }, + { + "title": "邻水县", + "id": "511623", + "children": [], + "disabled": false + }, + { + "title": "华蓥市", + "id": "511681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "达州市", + "id": "511700", + "children": [ + { + "title": "通川区", + "id": "511702", + "children": [], + "disabled": false + }, + { + "title": "达川区", + "id": "511703", + "children": [], + "disabled": false + }, + { + "title": "宣汉县", + "id": "511722", + "children": [], + "disabled": false + }, + { + "title": "开江县", + "id": "511723", + "children": [], + "disabled": false + }, + { + "title": "大竹县", + "id": "511724", + "children": [], + "disabled": false + }, + { + "title": "渠县", + "id": "511725", + "children": [], + "disabled": false + }, + { + "title": "万源市", + "id": "511781", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511701", + "children": [], + "disabled": false + }, + { + "title": "达州经济开发区", + "id": "511771", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "雅安市", + "id": "511800", + "children": [ + { + "title": "雨城区", + "id": "511802", + "children": [], + "disabled": false + }, + { + "title": "名山区", + "id": "511803", + "children": [], + "disabled": false + }, + { + "title": "荥经县", + "id": "511822", + "children": [], + "disabled": false + }, + { + "title": "汉源县", + "id": "511823", + "children": [], + "disabled": false + }, + { + "title": "石棉县", + "id": "511824", + "children": [], + "disabled": false + }, + { + "title": "天全县", + "id": "511825", + "children": [], + "disabled": false + }, + { + "title": "芦山县", + "id": "511826", + "children": [], + "disabled": false + }, + { + "title": "宝兴县", + "id": "511827", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "巴中市", + "id": "511900", + "children": [ + { + "title": "巴州区", + "id": "511902", + "children": [], + "disabled": false + }, + { + "title": "恩阳区", + "id": "511903", + "children": [], + "disabled": false + }, + { + "title": "通江县", + "id": "511921", + "children": [], + "disabled": false + }, + { + "title": "南江县", + "id": "511922", + "children": [], + "disabled": false + }, + { + "title": "平昌县", + "id": "511923", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "511901", + "children": [], + "disabled": false + }, + { + "title": "巴中经济开发区", + "id": "511971", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "资阳市", + "id": "512000", + "children": [ + { + "title": "雁江区", + "id": "512002", + "children": [], + "disabled": false + }, + { + "title": "安岳县", + "id": "512021", + "children": [], + "disabled": false + }, + { + "title": "乐至县", + "id": "512022", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "512001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阿坝藏族羌族自治州", + "id": "513200", + "children": [ + { + "title": "马尔康市", + "id": "513201", + "children": [], + "disabled": false + }, + { + "title": "汶川县", + "id": "513221", + "children": [], + "disabled": false + }, + { + "title": "理县", + "id": "513222", + "children": [], + "disabled": false + }, + { + "title": "茂县", + "id": "513223", + "children": [], + "disabled": false + }, + { + "title": "松潘县", + "id": "513224", + "children": [], + "disabled": false + }, + { + "title": "九寨沟县", + "id": "513225", + "children": [], + "disabled": false + }, + { + "title": "金川县", + "id": "513226", + "children": [], + "disabled": false + }, + { + "title": "小金县", + "id": "513227", + "children": [], + "disabled": false + }, + { + "title": "黑水县", + "id": "513228", + "children": [], + "disabled": false + }, + { + "title": "壤塘县", + "id": "513230", + "children": [], + "disabled": false + }, + { + "title": "阿坝县", + "id": "513231", + "children": [], + "disabled": false + }, + { + "title": "若尔盖县", + "id": "513232", + "children": [], + "disabled": false + }, + { + "title": "红原县", + "id": "513233", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "甘孜藏族自治州", + "id": "513300", + "children": [ + { + "title": "康定市", + "id": "513301", + "children": [], + "disabled": false + }, + { + "title": "泸定县", + "id": "513322", + "children": [], + "disabled": false + }, + { + "title": "丹巴县", + "id": "513323", + "children": [], + "disabled": false + }, + { + "title": "九龙县", + "id": "513324", + "children": [], + "disabled": false + }, + { + "title": "雅江县", + "id": "513325", + "children": [], + "disabled": false + }, + { + "title": "道孚县", + "id": "513326", + "children": [], + "disabled": false + }, + { + "title": "炉霍县", + "id": "513327", + "children": [], + "disabled": false + }, + { + "title": "甘孜县", + "id": "513328", + "children": [], + "disabled": false + }, + { + "title": "新龙县", + "id": "513329", + "children": [], + "disabled": false + }, + { + "title": "德格县", + "id": "513330", + "children": [], + "disabled": false + }, + { + "title": "白玉县", + "id": "513331", + "children": [], + "disabled": false + }, + { + "title": "石渠县", + "id": "513332", + "children": [], + "disabled": false + }, + { + "title": "色达县", + "id": "513333", + "children": [], + "disabled": false + }, + { + "title": "理塘县", + "id": "513334", + "children": [], + "disabled": false + }, + { + "title": "巴塘县", + "id": "513335", + "children": [], + "disabled": false + }, + { + "title": "乡城县", + "id": "513336", + "children": [], + "disabled": false + }, + { + "title": "稻城县", + "id": "513337", + "children": [], + "disabled": false + }, + { + "title": "得荣县", + "id": "513338", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "凉山彝族自治州", + "id": "513400", + "children": [ + { + "title": "西昌市", + "id": "513401", + "children": [], + "disabled": false + }, + { + "title": "木里藏族自治县", + "id": "513422", + "children": [], + "disabled": false + }, + { + "title": "盐源县", + "id": "513423", + "children": [], + "disabled": false + }, + { + "title": "德昌县", + "id": "513424", + "children": [], + "disabled": false + }, + { + "title": "会理县", + "id": "513425", + "children": [], + "disabled": false + }, + { + "title": "会东县", + "id": "513426", + "children": [], + "disabled": false + }, + { + "title": "宁南县", + "id": "513427", + "children": [], + "disabled": false + }, + { + "title": "普格县", + "id": "513428", + "children": [], + "disabled": false + }, + { + "title": "布拖县", + "id": "513429", + "children": [], + "disabled": false + }, + { + "title": "金阳县", + "id": "513430", + "children": [], + "disabled": false + }, + { + "title": "昭觉县", + "id": "513431", + "children": [], + "disabled": false + }, + { + "title": "喜德县", + "id": "513432", + "children": [], + "disabled": false + }, + { + "title": "冕宁县", + "id": "513433", + "children": [], + "disabled": false + }, + { + "title": "越西县", + "id": "513434", + "children": [], + "disabled": false + }, + { + "title": "甘洛县", + "id": "513435", + "children": [], + "disabled": false + }, + { + "title": "美姑县", + "id": "513436", + "children": [], + "disabled": false + }, + { + "title": "雷波县", + "id": "513437", + "children": [], + "disabled": false + }, + { + "title": "会理市", + "id": "513402", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "贵州省", + "id": "520000", + "children": [ + { + "title": "贵阳市", + "id": "520100", + "children": [ + { + "title": "南明区", + "id": "520102", + "children": [], + "disabled": false + }, + { + "title": "云岩区", + "id": "520103", + "children": [], + "disabled": false + }, + { + "title": "花溪区", + "id": "520111", + "children": [], + "disabled": false + }, + { + "title": "乌当区", + "id": "520112", + "children": [], + "disabled": false + }, + { + "title": "白云区", + "id": "520113", + "children": [], + "disabled": false + }, + { + "title": "观山湖区", + "id": "520115", + "children": [], + "disabled": false + }, + { + "title": "开阳县", + "id": "520121", + "children": [], + "disabled": false + }, + { + "title": "息烽县", + "id": "520122", + "children": [], + "disabled": false + }, + { + "title": "修文县", + "id": "520123", + "children": [], + "disabled": false + }, + { + "title": "清镇市", + "id": "520181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "520101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "六盘水市", + "id": "520200", + "children": [ + { + "title": "钟山区", + "id": "520201", + "children": [], + "disabled": false + }, + { + "title": "六枝特区", + "id": "520203", + "children": [], + "disabled": false + }, + { + "title": "水城区", + "id": "520204", + "children": [], + "disabled": false + }, + { + "title": "盘州市", + "id": "520281", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "遵义市", + "id": "520300", + "children": [ + { + "title": "红花岗区", + "id": "520302", + "children": [], + "disabled": false + }, + { + "title": "汇川区", + "id": "520303", + "children": [], + "disabled": false + }, + { + "title": "播州区", + "id": "520304", + "children": [], + "disabled": false + }, + { + "title": "桐梓县", + "id": "520322", + "children": [], + "disabled": false + }, + { + "title": "绥阳县", + "id": "520323", + "children": [], + "disabled": false + }, + { + "title": "正安县", + "id": "520324", + "children": [], + "disabled": false + }, + { + "title": "道真仡佬族苗族自治县", + "id": "520325", + "children": [], + "disabled": false + }, + { + "title": "务川仡佬族苗族自治县", + "id": "520326", + "children": [], + "disabled": false + }, + { + "title": "凤冈县", + "id": "520327", + "children": [], + "disabled": false + }, + { + "title": "湄潭县", + "id": "520328", + "children": [], + "disabled": false + }, + { + "title": "余庆县", + "id": "520329", + "children": [], + "disabled": false + }, + { + "title": "习水县", + "id": "520330", + "children": [], + "disabled": false + }, + { + "title": "赤水市", + "id": "520381", + "children": [], + "disabled": false + }, + { + "title": "仁怀市", + "id": "520382", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "520301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "安顺市", + "id": "520400", + "children": [ + { + "title": "西秀区", + "id": "520402", + "children": [], + "disabled": false + }, + { + "title": "平坝区", + "id": "520403", + "children": [], + "disabled": false + }, + { + "title": "普定县", + "id": "520422", + "children": [], + "disabled": false + }, + { + "title": "镇宁布依族苗族自治县", + "id": "520423", + "children": [], + "disabled": false + }, + { + "title": "关岭布依族苗族自治县", + "id": "520424", + "children": [], + "disabled": false + }, + { + "title": "紫云苗族布依族自治县", + "id": "520425", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "520401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "毕节市", + "id": "520500", + "children": [ + { + "title": "七星关区", + "id": "520502", + "children": [], + "disabled": false + }, + { + "title": "大方县", + "id": "520521", + "children": [], + "disabled": false + }, + { + "title": "黔西县", + "id": "520522", + "children": [], + "disabled": false + }, + { + "title": "金沙县", + "id": "520523", + "children": [], + "disabled": false + }, + { + "title": "织金县", + "id": "520524", + "children": [], + "disabled": false + }, + { + "title": "纳雍县", + "id": "520525", + "children": [], + "disabled": false + }, + { + "title": "威宁彝族回族苗族自治县", + "id": "520526", + "children": [], + "disabled": false + }, + { + "title": "赫章县", + "id": "520527", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "520501", + "children": [], + "disabled": false + }, + { + "title": "黔西市", + "id": "520581", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "铜仁市", + "id": "520600", + "children": [ + { + "title": "碧江区", + "id": "520602", + "children": [], + "disabled": false + }, + { + "title": "万山区", + "id": "520603", + "children": [], + "disabled": false + }, + { + "title": "江口县", + "id": "520621", + "children": [], + "disabled": false + }, + { + "title": "玉屏侗族自治县", + "id": "520622", + "children": [], + "disabled": false + }, + { + "title": "石阡县", + "id": "520623", + "children": [], + "disabled": false + }, + { + "title": "思南县", + "id": "520624", + "children": [], + "disabled": false + }, + { + "title": "印江土家族苗族自治县", + "id": "520625", + "children": [], + "disabled": false + }, + { + "title": "德江县", + "id": "520626", + "children": [], + "disabled": false + }, + { + "title": "沿河土家族自治县", + "id": "520627", + "children": [], + "disabled": false + }, + { + "title": "松桃苗族自治县", + "id": "520628", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "520601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黔西南布依族苗族自治州", + "id": "522300", + "children": [ + { + "title": "兴义市", + "id": "522301", + "children": [], + "disabled": false + }, + { + "title": "兴仁市", + "id": "522302", + "children": [], + "disabled": false + }, + { + "title": "普安县", + "id": "522323", + "children": [], + "disabled": false + }, + { + "title": "晴隆县", + "id": "522324", + "children": [], + "disabled": false + }, + { + "title": "贞丰县", + "id": "522325", + "children": [], + "disabled": false + }, + { + "title": "望谟县", + "id": "522326", + "children": [], + "disabled": false + }, + { + "title": "册亨县", + "id": "522327", + "children": [], + "disabled": false + }, + { + "title": "安龙县", + "id": "522328", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黔东南苗族侗族自治州", + "id": "522600", + "children": [ + { + "title": "凯里市", + "id": "522601", + "children": [], + "disabled": false + }, + { + "title": "黄平县", + "id": "522622", + "children": [], + "disabled": false + }, + { + "title": "施秉县", + "id": "522623", + "children": [], + "disabled": false + }, + { + "title": "三穗县", + "id": "522624", + "children": [], + "disabled": false + }, + { + "title": "镇远县", + "id": "522625", + "children": [], + "disabled": false + }, + { + "title": "岑巩县", + "id": "522626", + "children": [], + "disabled": false + }, + { + "title": "天柱县", + "id": "522627", + "children": [], + "disabled": false + }, + { + "title": "锦屏县", + "id": "522628", + "children": [], + "disabled": false + }, + { + "title": "剑河县", + "id": "522629", + "children": [], + "disabled": false + }, + { + "title": "台江县", + "id": "522630", + "children": [], + "disabled": false + }, + { + "title": "黎平县", + "id": "522631", + "children": [], + "disabled": false + }, + { + "title": "榕江县", + "id": "522632", + "children": [], + "disabled": false + }, + { + "title": "从江县", + "id": "522633", + "children": [], + "disabled": false + }, + { + "title": "雷山县", + "id": "522634", + "children": [], + "disabled": false + }, + { + "title": "麻江县", + "id": "522635", + "children": [], + "disabled": false + }, + { + "title": "丹寨县", + "id": "522636", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黔南布依族苗族自治州", + "id": "522700", + "children": [ + { + "title": "都匀市", + "id": "522701", + "children": [], + "disabled": false + }, + { + "title": "福泉市", + "id": "522702", + "children": [], + "disabled": false + }, + { + "title": "荔波县", + "id": "522722", + "children": [], + "disabled": false + }, + { + "title": "贵定县", + "id": "522723", + "children": [], + "disabled": false + }, + { + "title": "瓮安县", + "id": "522725", + "children": [], + "disabled": false + }, + { + "title": "独山县", + "id": "522726", + "children": [], + "disabled": false + }, + { + "title": "平塘县", + "id": "522727", + "children": [], + "disabled": false + }, + { + "title": "罗甸县", + "id": "522728", + "children": [], + "disabled": false + }, + { + "title": "长顺县", + "id": "522729", + "children": [], + "disabled": false + }, + { + "title": "龙里县", + "id": "522730", + "children": [], + "disabled": false + }, + { + "title": "惠水县", + "id": "522731", + "children": [], + "disabled": false + }, + { + "title": "三都水族自治县", + "id": "522732", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "云南省", + "id": "530000", + "children": [ + { + "title": "昆明市", + "id": "530100", + "children": [ + { + "title": "五华区", + "id": "530102", + "children": [], + "disabled": false + }, + { + "title": "盘龙区", + "id": "530103", + "children": [], + "disabled": false + }, + { + "title": "官渡区", + "id": "530111", + "children": [], + "disabled": false + }, + { + "title": "西山区", + "id": "530112", + "children": [], + "disabled": false + }, + { + "title": "东川区", + "id": "530113", + "children": [], + "disabled": false + }, + { + "title": "呈贡区", + "id": "530114", + "children": [], + "disabled": false + }, + { + "title": "晋宁区", + "id": "530115", + "children": [], + "disabled": false + }, + { + "title": "富民县", + "id": "530124", + "children": [], + "disabled": false + }, + { + "title": "宜良县", + "id": "530125", + "children": [], + "disabled": false + }, + { + "title": "石林彝族自治县", + "id": "530126", + "children": [], + "disabled": false + }, + { + "title": "嵩明县", + "id": "530127", + "children": [], + "disabled": false + }, + { + "title": "禄劝彝族苗族自治县", + "id": "530128", + "children": [], + "disabled": false + }, + { + "title": "寻甸回族彝族自治县", + "id": "530129", + "children": [], + "disabled": false + }, + { + "title": "安宁市", + "id": "530181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "曲靖市", + "id": "530300", + "children": [ + { + "title": "麒麟区", + "id": "530302", + "children": [], + "disabled": false + }, + { + "title": "沾益区", + "id": "530303", + "children": [], + "disabled": false + }, + { + "title": "马龙区", + "id": "530304", + "children": [], + "disabled": false + }, + { + "title": "陆良县", + "id": "530322", + "children": [], + "disabled": false + }, + { + "title": "师宗县", + "id": "530323", + "children": [], + "disabled": false + }, + { + "title": "罗平县", + "id": "530324", + "children": [], + "disabled": false + }, + { + "title": "富源县", + "id": "530325", + "children": [], + "disabled": false + }, + { + "title": "会泽县", + "id": "530326", + "children": [], + "disabled": false + }, + { + "title": "宣威市", + "id": "530381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "玉溪市", + "id": "530400", + "children": [ + { + "title": "红塔区", + "id": "530402", + "children": [], + "disabled": false + }, + { + "title": "江川区", + "id": "530403", + "children": [], + "disabled": false + }, + { + "title": "通海县", + "id": "530423", + "children": [], + "disabled": false + }, + { + "title": "华宁县", + "id": "530424", + "children": [], + "disabled": false + }, + { + "title": "易门县", + "id": "530425", + "children": [], + "disabled": false + }, + { + "title": "峨山彝族自治县", + "id": "530426", + "children": [], + "disabled": false + }, + { + "title": "新平彝族傣族自治县", + "id": "530427", + "children": [], + "disabled": false + }, + { + "title": "元江哈尼族彝族傣族自治县", + "id": "530428", + "children": [], + "disabled": false + }, + { + "title": "澄江市", + "id": "530481", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "保山市", + "id": "530500", + "children": [ + { + "title": "隆阳区", + "id": "530502", + "children": [], + "disabled": false + }, + { + "title": "施甸县", + "id": "530521", + "children": [], + "disabled": false + }, + { + "title": "龙陵县", + "id": "530523", + "children": [], + "disabled": false + }, + { + "title": "昌宁县", + "id": "530524", + "children": [], + "disabled": false + }, + { + "title": "腾冲市", + "id": "530581", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "昭通市", + "id": "530600", + "children": [ + { + "title": "昭阳区", + "id": "530602", + "children": [], + "disabled": false + }, + { + "title": "鲁甸县", + "id": "530621", + "children": [], + "disabled": false + }, + { + "title": "巧家县", + "id": "530622", + "children": [], + "disabled": false + }, + { + "title": "盐津县", + "id": "530623", + "children": [], + "disabled": false + }, + { + "title": "大关县", + "id": "530624", + "children": [], + "disabled": false + }, + { + "title": "永善县", + "id": "530625", + "children": [], + "disabled": false + }, + { + "title": "绥江县", + "id": "530626", + "children": [], + "disabled": false + }, + { + "title": "镇雄县", + "id": "530627", + "children": [], + "disabled": false + }, + { + "title": "彝良县", + "id": "530628", + "children": [], + "disabled": false + }, + { + "title": "威信县", + "id": "530629", + "children": [], + "disabled": false + }, + { + "title": "水富市", + "id": "530681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "丽江市", + "id": "530700", + "children": [ + { + "title": "古城区", + "id": "530702", + "children": [], + "disabled": false + }, + { + "title": "玉龙纳西族自治县", + "id": "530721", + "children": [], + "disabled": false + }, + { + "title": "永胜县", + "id": "530722", + "children": [], + "disabled": false + }, + { + "title": "华坪县", + "id": "530723", + "children": [], + "disabled": false + }, + { + "title": "宁蒗彝族自治县", + "id": "530724", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "普洱市", + "id": "530800", + "children": [ + { + "title": "思茅区", + "id": "530802", + "children": [], + "disabled": false + }, + { + "title": "宁洱哈尼族彝族自治县", + "id": "530821", + "children": [], + "disabled": false + }, + { + "title": "墨江哈尼族自治县", + "id": "530822", + "children": [], + "disabled": false + }, + { + "title": "景东彝族自治县", + "id": "530823", + "children": [], + "disabled": false + }, + { + "title": "景谷傣族彝族自治县", + "id": "530824", + "children": [], + "disabled": false + }, + { + "title": "镇沅彝族哈尼族拉祜族自治县", + "id": "530825", + "children": [], + "disabled": false + }, + { + "title": "江城哈尼族彝族自治县", + "id": "530826", + "children": [], + "disabled": false + }, + { + "title": "孟连傣族拉祜族佤族自治县", + "id": "530827", + "children": [], + "disabled": false + }, + { + "title": "澜沧拉祜族自治县", + "id": "530828", + "children": [], + "disabled": false + }, + { + "title": "西盟佤族自治县", + "id": "530829", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "临沧市", + "id": "530900", + "children": [ + { + "title": "临翔区", + "id": "530902", + "children": [], + "disabled": false + }, + { + "title": "凤庆县", + "id": "530921", + "children": [], + "disabled": false + }, + { + "title": "云县", + "id": "530922", + "children": [], + "disabled": false + }, + { + "title": "永德县", + "id": "530923", + "children": [], + "disabled": false + }, + { + "title": "镇康县", + "id": "530924", + "children": [], + "disabled": false + }, + { + "title": "双江拉祜族佤族布朗族傣族自治县", + "id": "530925", + "children": [], + "disabled": false + }, + { + "title": "耿马傣族佤族自治县", + "id": "530926", + "children": [], + "disabled": false + }, + { + "title": "沧源佤族自治县", + "id": "530927", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "530901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "楚雄彝族自治州", + "id": "532300", + "children": [ + { + "title": "楚雄市", + "id": "532301", + "children": [], + "disabled": false + }, + { + "title": "双柏县", + "id": "532322", + "children": [], + "disabled": false + }, + { + "title": "牟定县", + "id": "532323", + "children": [], + "disabled": false + }, + { + "title": "南华县", + "id": "532324", + "children": [], + "disabled": false + }, + { + "title": "姚安县", + "id": "532325", + "children": [], + "disabled": false + }, + { + "title": "大姚县", + "id": "532326", + "children": [], + "disabled": false + }, + { + "title": "永仁县", + "id": "532327", + "children": [], + "disabled": false + }, + { + "title": "元谋县", + "id": "532328", + "children": [], + "disabled": false + }, + { + "title": "武定县", + "id": "532329", + "children": [], + "disabled": false + }, + { + "title": "禄丰县", + "id": "532331", + "children": [], + "disabled": false + }, + { + "title": "禄丰市", + "id": "532302", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "红河哈尼族彝族自治州", + "id": "532500", + "children": [ + { + "title": "个旧市", + "id": "532501", + "children": [], + "disabled": false + }, + { + "title": "开远市", + "id": "532502", + "children": [], + "disabled": false + }, + { + "title": "蒙自市", + "id": "532503", + "children": [], + "disabled": false + }, + { + "title": "弥勒市", + "id": "532504", + "children": [], + "disabled": false + }, + { + "title": "屏边苗族自治县", + "id": "532523", + "children": [], + "disabled": false + }, + { + "title": "建水县", + "id": "532524", + "children": [], + "disabled": false + }, + { + "title": "石屏县", + "id": "532525", + "children": [], + "disabled": false + }, + { + "title": "泸西县", + "id": "532527", + "children": [], + "disabled": false + }, + { + "title": "元阳县", + "id": "532528", + "children": [], + "disabled": false + }, + { + "title": "红河县", + "id": "532529", + "children": [], + "disabled": false + }, + { + "title": "金平苗族瑶族傣族自治县", + "id": "532530", + "children": [], + "disabled": false + }, + { + "title": "绿春县", + "id": "532531", + "children": [], + "disabled": false + }, + { + "title": "河口瑶族自治县", + "id": "532532", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "文山壮族苗族自治州", + "id": "532600", + "children": [ + { + "title": "文山市", + "id": "532601", + "children": [], + "disabled": false + }, + { + "title": "砚山县", + "id": "532622", + "children": [], + "disabled": false + }, + { + "title": "西畴县", + "id": "532623", + "children": [], + "disabled": false + }, + { + "title": "麻栗坡县", + "id": "532624", + "children": [], + "disabled": false + }, + { + "title": "马关县", + "id": "532625", + "children": [], + "disabled": false + }, + { + "title": "丘北县", + "id": "532626", + "children": [], + "disabled": false + }, + { + "title": "广南县", + "id": "532627", + "children": [], + "disabled": false + }, + { + "title": "富宁县", + "id": "532628", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "西双版纳傣族自治州", + "id": "532800", + "children": [ + { + "title": "景洪市", + "id": "532801", + "children": [], + "disabled": false + }, + { + "title": "勐海县", + "id": "532822", + "children": [], + "disabled": false + }, + { + "title": "勐腊县", + "id": "532823", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "大理白族自治州", + "id": "532900", + "children": [ + { + "title": "大理市", + "id": "532901", + "children": [], + "disabled": false + }, + { + "title": "漾濞彝族自治县", + "id": "532922", + "children": [], + "disabled": false + }, + { + "title": "祥云县", + "id": "532923", + "children": [], + "disabled": false + }, + { + "title": "宾川县", + "id": "532924", + "children": [], + "disabled": false + }, + { + "title": "弥渡县", + "id": "532925", + "children": [], + "disabled": false + }, + { + "title": "南涧彝族自治县", + "id": "532926", + "children": [], + "disabled": false + }, + { + "title": "巍山彝族回族自治县", + "id": "532927", + "children": [], + "disabled": false + }, + { + "title": "永平县", + "id": "532928", + "children": [], + "disabled": false + }, + { + "title": "云龙县", + "id": "532929", + "children": [], + "disabled": false + }, + { + "title": "洱源县", + "id": "532930", + "children": [], + "disabled": false + }, + { + "title": "剑川县", + "id": "532931", + "children": [], + "disabled": false + }, + { + "title": "鹤庆县", + "id": "532932", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "德宏傣族景颇族自治州", + "id": "533100", + "children": [ + { + "title": "瑞丽市", + "id": "533102", + "children": [], + "disabled": false + }, + { + "title": "芒市", + "id": "533103", + "children": [], + "disabled": false + }, + { + "title": "梁河县", + "id": "533122", + "children": [], + "disabled": false + }, + { + "title": "盈江县", + "id": "533123", + "children": [], + "disabled": false + }, + { + "title": "陇川县", + "id": "533124", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "怒江傈僳族自治州", + "id": "533300", + "children": [ + { + "title": "泸水市", + "id": "533301", + "children": [], + "disabled": false + }, + { + "title": "福贡县", + "id": "533323", + "children": [], + "disabled": false + }, + { + "title": "贡山独龙族怒族自治县", + "id": "533324", + "children": [], + "disabled": false + }, + { + "title": "兰坪白族普米族自治县", + "id": "533325", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "迪庆藏族自治州", + "id": "533400", + "children": [ + { + "title": "香格里拉市", + "id": "533401", + "children": [], + "disabled": false + }, + { + "title": "德钦县", + "id": "533422", + "children": [], + "disabled": false + }, + { + "title": "维西傈僳族自治县", + "id": "533423", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "西藏自治区", + "id": "540000", + "children": [ + { + "title": "拉萨市", + "id": "540100", + "children": [ + { + "title": "城关区", + "id": "540102", + "children": [], + "disabled": false + }, + { + "title": "堆龙德庆区", + "id": "540103", + "children": [], + "disabled": false + }, + { + "title": "达孜区", + "id": "540104", + "children": [], + "disabled": false + }, + { + "title": "林周县", + "id": "540121", + "children": [], + "disabled": false + }, + { + "title": "当雄县", + "id": "540122", + "children": [], + "disabled": false + }, + { + "title": "尼木县", + "id": "540123", + "children": [], + "disabled": false + }, + { + "title": "曲水县", + "id": "540124", + "children": [], + "disabled": false + }, + { + "title": "墨竹工卡县", + "id": "540127", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "540101", + "children": [], + "disabled": false + }, + { + "title": "格尔木藏青工业园区", + "id": "540171", + "children": [], + "disabled": false + }, + { + "title": "拉萨经济技术开发区", + "id": "540172", + "children": [], + "disabled": false + }, + { + "title": "西藏文化旅游创意园区", + "id": "540173", + "children": [], + "disabled": false + }, + { + "title": "达孜工业园区", + "id": "540174", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "日喀则市", + "id": "540200", + "children": [ + { + "title": "桑珠孜区", + "id": "540202", + "children": [], + "disabled": false + }, + { + "title": "南木林县", + "id": "540221", + "children": [], + "disabled": false + }, + { + "title": "江孜县", + "id": "540222", + "children": [], + "disabled": false + }, + { + "title": "定日县", + "id": "540223", + "children": [], + "disabled": false + }, + { + "title": "萨迦县", + "id": "540224", + "children": [], + "disabled": false + }, + { + "title": "拉孜县", + "id": "540225", + "children": [], + "disabled": false + }, + { + "title": "昂仁县", + "id": "540226", + "children": [], + "disabled": false + }, + { + "title": "谢通门县", + "id": "540227", + "children": [], + "disabled": false + }, + { + "title": "白朗县", + "id": "540228", + "children": [], + "disabled": false + }, + { + "title": "仁布县", + "id": "540229", + "children": [], + "disabled": false + }, + { + "title": "康马县", + "id": "540230", + "children": [], + "disabled": false + }, + { + "title": "定结县", + "id": "540231", + "children": [], + "disabled": false + }, + { + "title": "仲巴县", + "id": "540232", + "children": [], + "disabled": false + }, + { + "title": "亚东县", + "id": "540233", + "children": [], + "disabled": false + }, + { + "title": "吉隆县", + "id": "540234", + "children": [], + "disabled": false + }, + { + "title": "聂拉木县", + "id": "540235", + "children": [], + "disabled": false + }, + { + "title": "萨嘎县", + "id": "540236", + "children": [], + "disabled": false + }, + { + "title": "岗巴县", + "id": "540237", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "昌都市", + "id": "540300", + "children": [ + { + "title": "卡若区", + "id": "540302", + "children": [], + "disabled": false + }, + { + "title": "江达县", + "id": "540321", + "children": [], + "disabled": false + }, + { + "title": "贡觉县", + "id": "540322", + "children": [], + "disabled": false + }, + { + "title": "类乌齐县", + "id": "540323", + "children": [], + "disabled": false + }, + { + "title": "丁青县", + "id": "540324", + "children": [], + "disabled": false + }, + { + "title": "察雅县", + "id": "540325", + "children": [], + "disabled": false + }, + { + "title": "八宿县", + "id": "540326", + "children": [], + "disabled": false + }, + { + "title": "左贡县", + "id": "540327", + "children": [], + "disabled": false + }, + { + "title": "芒康县", + "id": "540328", + "children": [], + "disabled": false + }, + { + "title": "洛隆县", + "id": "540329", + "children": [], + "disabled": false + }, + { + "title": "边坝县", + "id": "540330", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "林芝市", + "id": "540400", + "children": [ + { + "title": "巴宜区", + "id": "540402", + "children": [], + "disabled": false + }, + { + "title": "工布江达县", + "id": "540421", + "children": [], + "disabled": false + }, + { + "title": "米林县", + "id": "540422", + "children": [], + "disabled": false + }, + { + "title": "墨脱县", + "id": "540423", + "children": [], + "disabled": false + }, + { + "title": "波密县", + "id": "540424", + "children": [], + "disabled": false + }, + { + "title": "察隅县", + "id": "540425", + "children": [], + "disabled": false + }, + { + "title": "朗县", + "id": "540426", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "山南市", + "id": "540500", + "children": [ + { + "title": "乃东区", + "id": "540502", + "children": [], + "disabled": false + }, + { + "title": "扎囊县", + "id": "540521", + "children": [], + "disabled": false + }, + { + "title": "贡嘎县", + "id": "540522", + "children": [], + "disabled": false + }, + { + "title": "桑日县", + "id": "540523", + "children": [], + "disabled": false + }, + { + "title": "琼结县", + "id": "540524", + "children": [], + "disabled": false + }, + { + "title": "曲松县", + "id": "540525", + "children": [], + "disabled": false + }, + { + "title": "措美县", + "id": "540526", + "children": [], + "disabled": false + }, + { + "title": "洛扎县", + "id": "540527", + "children": [], + "disabled": false + }, + { + "title": "加查县", + "id": "540528", + "children": [], + "disabled": false + }, + { + "title": "隆子县", + "id": "540529", + "children": [], + "disabled": false + }, + { + "title": "错那县", + "id": "540530", + "children": [], + "disabled": false + }, + { + "title": "浪卡子县", + "id": "540531", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "540501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "那曲市", + "id": "540600", + "children": [ + { + "title": "色尼区", + "id": "540602", + "children": [], + "disabled": false + }, + { + "title": "嘉黎县", + "id": "540621", + "children": [], + "disabled": false + }, + { + "title": "比如县", + "id": "540622", + "children": [], + "disabled": false + }, + { + "title": "聂荣县", + "id": "540623", + "children": [], + "disabled": false + }, + { + "title": "安多县", + "id": "540624", + "children": [], + "disabled": false + }, + { + "title": "申扎县", + "id": "540625", + "children": [], + "disabled": false + }, + { + "title": "索县", + "id": "540626", + "children": [], + "disabled": false + }, + { + "title": "班戈县", + "id": "540627", + "children": [], + "disabled": false + }, + { + "title": "巴青县", + "id": "540628", + "children": [], + "disabled": false + }, + { + "title": "尼玛县", + "id": "540629", + "children": [], + "disabled": false + }, + { + "title": "双湖县", + "id": "540630", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阿里地区", + "id": "542500", + "children": [ + { + "title": "普兰县", + "id": "542521", + "children": [], + "disabled": false + }, + { + "title": "札达县", + "id": "542522", + "children": [], + "disabled": false + }, + { + "title": "噶尔县", + "id": "542523", + "children": [], + "disabled": false + }, + { + "title": "日土县", + "id": "542524", + "children": [], + "disabled": false + }, + { + "title": "革吉县", + "id": "542525", + "children": [], + "disabled": false + }, + { + "title": "改则县", + "id": "542526", + "children": [], + "disabled": false + }, + { + "title": "措勤县", + "id": "542527", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "陕西省", + "id": "610000", + "children": [ + { + "title": "西安市", + "id": "610100", + "children": [ + { + "title": "新城区", + "id": "610102", + "children": [], + "disabled": false + }, + { + "title": "碑林区", + "id": "610103", + "children": [], + "disabled": false + }, + { + "title": "莲湖区", + "id": "610104", + "children": [], + "disabled": false + }, + { + "title": "灞桥区", + "id": "610111", + "children": [], + "disabled": false + }, + { + "title": "未央区", + "id": "610112", + "children": [], + "disabled": false + }, + { + "title": "雁塔区", + "id": "610113", + "children": [], + "disabled": false + }, + { + "title": "阎良区", + "id": "610114", + "children": [], + "disabled": false + }, + { + "title": "临潼区", + "id": "610115", + "children": [], + "disabled": false + }, + { + "title": "长安区", + "id": "610116", + "children": [], + "disabled": false + }, + { + "title": "高陵区", + "id": "610117", + "children": [], + "disabled": false + }, + { + "title": "鄠邑区", + "id": "610118", + "children": [], + "disabled": false + }, + { + "title": "蓝田县", + "id": "610122", + "children": [], + "disabled": false + }, + { + "title": "周至县", + "id": "610124", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "铜川市", + "id": "610200", + "children": [ + { + "title": "王益区", + "id": "610202", + "children": [], + "disabled": false + }, + { + "title": "印台区", + "id": "610203", + "children": [], + "disabled": false + }, + { + "title": "耀州区", + "id": "610204", + "children": [], + "disabled": false + }, + { + "title": "宜君县", + "id": "610222", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宝鸡市", + "id": "610300", + "children": [ + { + "title": "渭滨区", + "id": "610302", + "children": [], + "disabled": false + }, + { + "title": "金台区", + "id": "610303", + "children": [], + "disabled": false + }, + { + "title": "陈仓区", + "id": "610304", + "children": [], + "disabled": false + }, + { + "title": "凤翔县", + "id": "610322", + "children": [], + "disabled": false + }, + { + "title": "岐山县", + "id": "610323", + "children": [], + "disabled": false + }, + { + "title": "扶风县", + "id": "610324", + "children": [], + "disabled": false + }, + { + "title": "眉县", + "id": "610326", + "children": [], + "disabled": false + }, + { + "title": "陇县", + "id": "610327", + "children": [], + "disabled": false + }, + { + "title": "千阳县", + "id": "610328", + "children": [], + "disabled": false + }, + { + "title": "麟游县", + "id": "610329", + "children": [], + "disabled": false + }, + { + "title": "凤县", + "id": "610330", + "children": [], + "disabled": false + }, + { + "title": "太白县", + "id": "610331", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610301", + "children": [], + "disabled": false + }, + { + "title": "凤翔区", + "id": "610305", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "咸阳市", + "id": "610400", + "children": [ + { + "title": "秦都区", + "id": "610402", + "children": [], + "disabled": false + }, + { + "title": "杨陵区", + "id": "610403", + "children": [], + "disabled": false + }, + { + "title": "渭城区", + "id": "610404", + "children": [], + "disabled": false + }, + { + "title": "三原县", + "id": "610422", + "children": [], + "disabled": false + }, + { + "title": "泾阳县", + "id": "610423", + "children": [], + "disabled": false + }, + { + "title": "乾县", + "id": "610424", + "children": [], + "disabled": false + }, + { + "title": "礼泉县", + "id": "610425", + "children": [], + "disabled": false + }, + { + "title": "永寿县", + "id": "610426", + "children": [], + "disabled": false + }, + { + "title": "长武县", + "id": "610428", + "children": [], + "disabled": false + }, + { + "title": "旬邑县", + "id": "610429", + "children": [], + "disabled": false + }, + { + "title": "淳化县", + "id": "610430", + "children": [], + "disabled": false + }, + { + "title": "武功县", + "id": "610431", + "children": [], + "disabled": false + }, + { + "title": "兴平市", + "id": "610481", + "children": [], + "disabled": false + }, + { + "title": "彬州市", + "id": "610482", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "渭南市", + "id": "610500", + "children": [ + { + "title": "临渭区", + "id": "610502", + "children": [], + "disabled": false + }, + { + "title": "华州区", + "id": "610503", + "children": [], + "disabled": false + }, + { + "title": "潼关县", + "id": "610522", + "children": [], + "disabled": false + }, + { + "title": "大荔县", + "id": "610523", + "children": [], + "disabled": false + }, + { + "title": "合阳县", + "id": "610524", + "children": [], + "disabled": false + }, + { + "title": "澄城县", + "id": "610525", + "children": [], + "disabled": false + }, + { + "title": "蒲城县", + "id": "610526", + "children": [], + "disabled": false + }, + { + "title": "白水县", + "id": "610527", + "children": [], + "disabled": false + }, + { + "title": "富平县", + "id": "610528", + "children": [], + "disabled": false + }, + { + "title": "韩城市", + "id": "610581", + "children": [], + "disabled": false + }, + { + "title": "华阴市", + "id": "610582", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "延安市", + "id": "610600", + "children": [ + { + "title": "宝塔区", + "id": "610602", + "children": [], + "disabled": false + }, + { + "title": "安塞区", + "id": "610603", + "children": [], + "disabled": false + }, + { + "title": "延长县", + "id": "610621", + "children": [], + "disabled": false + }, + { + "title": "延川县", + "id": "610622", + "children": [], + "disabled": false + }, + { + "title": "志丹县", + "id": "610625", + "children": [], + "disabled": false + }, + { + "title": "吴起县", + "id": "610626", + "children": [], + "disabled": false + }, + { + "title": "甘泉县", + "id": "610627", + "children": [], + "disabled": false + }, + { + "title": "富县", + "id": "610628", + "children": [], + "disabled": false + }, + { + "title": "洛川县", + "id": "610629", + "children": [], + "disabled": false + }, + { + "title": "宜川县", + "id": "610630", + "children": [], + "disabled": false + }, + { + "title": "黄龙县", + "id": "610631", + "children": [], + "disabled": false + }, + { + "title": "黄陵县", + "id": "610632", + "children": [], + "disabled": false + }, + { + "title": "子长市", + "id": "610681", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "汉中市", + "id": "610700", + "children": [ + { + "title": "汉台区", + "id": "610702", + "children": [], + "disabled": false + }, + { + "title": "南郑区", + "id": "610703", + "children": [], + "disabled": false + }, + { + "title": "城固县", + "id": "610722", + "children": [], + "disabled": false + }, + { + "title": "洋县", + "id": "610723", + "children": [], + "disabled": false + }, + { + "title": "西乡县", + "id": "610724", + "children": [], + "disabled": false + }, + { + "title": "勉县", + "id": "610725", + "children": [], + "disabled": false + }, + { + "title": "宁强县", + "id": "610726", + "children": [], + "disabled": false + }, + { + "title": "略阳县", + "id": "610727", + "children": [], + "disabled": false + }, + { + "title": "镇巴县", + "id": "610728", + "children": [], + "disabled": false + }, + { + "title": "留坝县", + "id": "610729", + "children": [], + "disabled": false + }, + { + "title": "佛坪县", + "id": "610730", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "榆林市", + "id": "610800", + "children": [ + { + "title": "榆阳区", + "id": "610802", + "children": [], + "disabled": false + }, + { + "title": "横山区", + "id": "610803", + "children": [], + "disabled": false + }, + { + "title": "府谷县", + "id": "610822", + "children": [], + "disabled": false + }, + { + "title": "靖边县", + "id": "610824", + "children": [], + "disabled": false + }, + { + "title": "定边县", + "id": "610825", + "children": [], + "disabled": false + }, + { + "title": "绥德县", + "id": "610826", + "children": [], + "disabled": false + }, + { + "title": "米脂县", + "id": "610827", + "children": [], + "disabled": false + }, + { + "title": "佳县", + "id": "610828", + "children": [], + "disabled": false + }, + { + "title": "吴堡县", + "id": "610829", + "children": [], + "disabled": false + }, + { + "title": "清涧县", + "id": "610830", + "children": [], + "disabled": false + }, + { + "title": "子洲县", + "id": "610831", + "children": [], + "disabled": false + }, + { + "title": "神木市", + "id": "610881", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "安康市", + "id": "610900", + "children": [ + { + "title": "汉滨区", + "id": "610902", + "children": [], + "disabled": false + }, + { + "title": "汉阴县", + "id": "610921", + "children": [], + "disabled": false + }, + { + "title": "石泉县", + "id": "610922", + "children": [], + "disabled": false + }, + { + "title": "宁陕县", + "id": "610923", + "children": [], + "disabled": false + }, + { + "title": "紫阳县", + "id": "610924", + "children": [], + "disabled": false + }, + { + "title": "岚皋县", + "id": "610925", + "children": [], + "disabled": false + }, + { + "title": "平利县", + "id": "610926", + "children": [], + "disabled": false + }, + { + "title": "镇坪县", + "id": "610927", + "children": [], + "disabled": false + }, + { + "title": "旬阳县", + "id": "610928", + "children": [], + "disabled": false + }, + { + "title": "白河县", + "id": "610929", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "610901", + "children": [], + "disabled": false + }, + { + "title": "旬阳市", + "id": "610981", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "商洛市", + "id": "611000", + "children": [ + { + "title": "商州区", + "id": "611002", + "children": [], + "disabled": false + }, + { + "title": "洛南县", + "id": "611021", + "children": [], + "disabled": false + }, + { + "title": "丹凤县", + "id": "611022", + "children": [], + "disabled": false + }, + { + "title": "商南县", + "id": "611023", + "children": [], + "disabled": false + }, + { + "title": "山阳县", + "id": "611024", + "children": [], + "disabled": false + }, + { + "title": "镇安县", + "id": "611025", + "children": [], + "disabled": false + }, + { + "title": "柞水县", + "id": "611026", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "611001", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "甘肃省", + "id": "620000", + "children": [ + { + "title": "兰州市", + "id": "620100", + "children": [ + { + "title": "城关区", + "id": "620102", + "children": [], + "disabled": false + }, + { + "title": "七里河区", + "id": "620103", + "children": [], + "disabled": false + }, + { + "title": "西固区", + "id": "620104", + "children": [], + "disabled": false + }, + { + "title": "安宁区", + "id": "620105", + "children": [], + "disabled": false + }, + { + "title": "红古区", + "id": "620111", + "children": [], + "disabled": false + }, + { + "title": "永登县", + "id": "620121", + "children": [], + "disabled": false + }, + { + "title": "皋兰县", + "id": "620122", + "children": [], + "disabled": false + }, + { + "title": "榆中县", + "id": "620123", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620101", + "children": [], + "disabled": false + }, + { + "title": "兰州新区", + "id": "620171", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "嘉峪关市", + "id": "620200", + "children": [ + { + "title": "市辖区", + "id": "620201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "金昌市", + "id": "620300", + "children": [ + { + "title": "金川区", + "id": "620302", + "children": [], + "disabled": false + }, + { + "title": "永昌县", + "id": "620321", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "白银市", + "id": "620400", + "children": [ + { + "title": "白银区", + "id": "620402", + "children": [], + "disabled": false + }, + { + "title": "平川区", + "id": "620403", + "children": [], + "disabled": false + }, + { + "title": "靖远县", + "id": "620421", + "children": [], + "disabled": false + }, + { + "title": "会宁县", + "id": "620422", + "children": [], + "disabled": false + }, + { + "title": "景泰县", + "id": "620423", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "天水市", + "id": "620500", + "children": [ + { + "title": "秦州区", + "id": "620502", + "children": [], + "disabled": false + }, + { + "title": "麦积区", + "id": "620503", + "children": [], + "disabled": false + }, + { + "title": "清水县", + "id": "620521", + "children": [], + "disabled": false + }, + { + "title": "秦安县", + "id": "620522", + "children": [], + "disabled": false + }, + { + "title": "甘谷县", + "id": "620523", + "children": [], + "disabled": false + }, + { + "title": "武山县", + "id": "620524", + "children": [], + "disabled": false + }, + { + "title": "张家川回族自治县", + "id": "620525", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620501", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "武威市", + "id": "620600", + "children": [ + { + "title": "凉州区", + "id": "620602", + "children": [], + "disabled": false + }, + { + "title": "民勤县", + "id": "620621", + "children": [], + "disabled": false + }, + { + "title": "古浪县", + "id": "620622", + "children": [], + "disabled": false + }, + { + "title": "天祝藏族自治县", + "id": "620623", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620601", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "张掖市", + "id": "620700", + "children": [ + { + "title": "甘州区", + "id": "620702", + "children": [], + "disabled": false + }, + { + "title": "肃南裕固族自治县", + "id": "620721", + "children": [], + "disabled": false + }, + { + "title": "民乐县", + "id": "620722", + "children": [], + "disabled": false + }, + { + "title": "临泽县", + "id": "620723", + "children": [], + "disabled": false + }, + { + "title": "高台县", + "id": "620724", + "children": [], + "disabled": false + }, + { + "title": "山丹县", + "id": "620725", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620701", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "平凉市", + "id": "620800", + "children": [ + { + "title": "崆峒区", + "id": "620802", + "children": [], + "disabled": false + }, + { + "title": "泾川县", + "id": "620821", + "children": [], + "disabled": false + }, + { + "title": "灵台县", + "id": "620822", + "children": [], + "disabled": false + }, + { + "title": "崇信县", + "id": "620823", + "children": [], + "disabled": false + }, + { + "title": "庄浪县", + "id": "620825", + "children": [], + "disabled": false + }, + { + "title": "静宁县", + "id": "620826", + "children": [], + "disabled": false + }, + { + "title": "华亭市", + "id": "620881", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620801", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "酒泉市", + "id": "620900", + "children": [ + { + "title": "肃州区", + "id": "620902", + "children": [], + "disabled": false + }, + { + "title": "金塔县", + "id": "620921", + "children": [], + "disabled": false + }, + { + "title": "瓜州县", + "id": "620922", + "children": [], + "disabled": false + }, + { + "title": "肃北蒙古族自治县", + "id": "620923", + "children": [], + "disabled": false + }, + { + "title": "阿克塞哈萨克族自治县", + "id": "620924", + "children": [], + "disabled": false + }, + { + "title": "玉门市", + "id": "620981", + "children": [], + "disabled": false + }, + { + "title": "敦煌市", + "id": "620982", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "620901", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "庆阳市", + "id": "621000", + "children": [ + { + "title": "西峰区", + "id": "621002", + "children": [], + "disabled": false + }, + { + "title": "庆城县", + "id": "621021", + "children": [], + "disabled": false + }, + { + "title": "环县", + "id": "621022", + "children": [], + "disabled": false + }, + { + "title": "华池县", + "id": "621023", + "children": [], + "disabled": false + }, + { + "title": "合水县", + "id": "621024", + "children": [], + "disabled": false + }, + { + "title": "正宁县", + "id": "621025", + "children": [], + "disabled": false + }, + { + "title": "宁县", + "id": "621026", + "children": [], + "disabled": false + }, + { + "title": "镇原县", + "id": "621027", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "621001", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "定西市", + "id": "621100", + "children": [ + { + "title": "安定区", + "id": "621102", + "children": [], + "disabled": false + }, + { + "title": "通渭县", + "id": "621121", + "children": [], + "disabled": false + }, + { + "title": "陇西县", + "id": "621122", + "children": [], + "disabled": false + }, + { + "title": "渭源县", + "id": "621123", + "children": [], + "disabled": false + }, + { + "title": "临洮县", + "id": "621124", + "children": [], + "disabled": false + }, + { + "title": "漳县", + "id": "621125", + "children": [], + "disabled": false + }, + { + "title": "岷县", + "id": "621126", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "621101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "陇南市", + "id": "621200", + "children": [ + { + "title": "武都区", + "id": "621202", + "children": [], + "disabled": false + }, + { + "title": "成县", + "id": "621221", + "children": [], + "disabled": false + }, + { + "title": "文县", + "id": "621222", + "children": [], + "disabled": false + }, + { + "title": "宕昌县", + "id": "621223", + "children": [], + "disabled": false + }, + { + "title": "康县", + "id": "621224", + "children": [], + "disabled": false + }, + { + "title": "西和县", + "id": "621225", + "children": [], + "disabled": false + }, + { + "title": "礼县", + "id": "621226", + "children": [], + "disabled": false + }, + { + "title": "徽县", + "id": "621227", + "children": [], + "disabled": false + }, + { + "title": "两当县", + "id": "621228", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "621201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "临夏回族自治州", + "id": "622900", + "children": [ + { + "title": "临夏市", + "id": "622901", + "children": [], + "disabled": false + }, + { + "title": "临夏县", + "id": "622921", + "children": [], + "disabled": false + }, + { + "title": "康乐县", + "id": "622922", + "children": [], + "disabled": false + }, + { + "title": "永靖县", + "id": "622923", + "children": [], + "disabled": false + }, + { + "title": "广河县", + "id": "622924", + "children": [], + "disabled": false + }, + { + "title": "和政县", + "id": "622925", + "children": [], + "disabled": false + }, + { + "title": "东乡族自治县", + "id": "622926", + "children": [], + "disabled": false + }, + { + "title": "积石山保安族东乡族撒拉族自治县", + "id": "622927", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "甘南藏族自治州", + "id": "623000", + "children": [ + { + "title": "合作市", + "id": "623001", + "children": [], + "disabled": false + }, + { + "title": "临潭县", + "id": "623021", + "children": [], + "disabled": false + }, + { + "title": "卓尼县", + "id": "623022", + "children": [], + "disabled": false + }, + { + "title": "舟曲县", + "id": "623023", + "children": [], + "disabled": false + }, + { + "title": "迭部县", + "id": "623024", + "children": [], + "disabled": false + }, + { + "title": "玛曲县", + "id": "623025", + "children": [], + "disabled": false + }, + { + "title": "碌曲县", + "id": "623026", + "children": [], + "disabled": false + }, + { + "title": "夏河县", + "id": "623027", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "青海省", + "id": "630000", + "children": [ + { + "title": "西宁市", + "id": "630100", + "children": [ + { + "title": "城东区", + "id": "630102", + "children": [], + "disabled": false + }, + { + "title": "城中区", + "id": "630103", + "children": [], + "disabled": false + }, + { + "title": "城西区", + "id": "630104", + "children": [], + "disabled": false + }, + { + "title": "城北区", + "id": "630105", + "children": [], + "disabled": false + }, + { + "title": "湟中区", + "id": "630106", + "children": [], + "disabled": false + }, + { + "title": "大通回族土族自治县", + "id": "630121", + "children": [], + "disabled": false + }, + { + "title": "湟源县", + "id": "630123", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "630101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "海东市", + "id": "630200", + "children": [ + { + "title": "乐都区", + "id": "630202", + "children": [], + "disabled": false + }, + { + "title": "平安区", + "id": "630203", + "children": [], + "disabled": false + }, + { + "title": "民和回族土族自治县", + "id": "630222", + "children": [], + "disabled": false + }, + { + "title": "互助土族自治县", + "id": "630223", + "children": [], + "disabled": false + }, + { + "title": "化隆回族自治县", + "id": "630224", + "children": [], + "disabled": false + }, + { + "title": "循化撒拉族自治县", + "id": "630225", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "海北藏族自治州", + "id": "632200", + "children": [ + { + "title": "门源回族自治县", + "id": "632221", + "children": [], + "disabled": false + }, + { + "title": "祁连县", + "id": "632222", + "children": [], + "disabled": false + }, + { + "title": "海晏县", + "id": "632223", + "children": [], + "disabled": false + }, + { + "title": "刚察县", + "id": "632224", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "黄南藏族自治州", + "id": "632300", + "children": [ + { + "title": "同仁市", + "id": "632301", + "children": [], + "disabled": false + }, + { + "title": "尖扎县", + "id": "632322", + "children": [], + "disabled": false + }, + { + "title": "泽库县", + "id": "632323", + "children": [], + "disabled": false + }, + { + "title": "河南蒙古族自治县", + "id": "632324", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "海南藏族自治州", + "id": "632500", + "children": [ + { + "title": "共和县", + "id": "632521", + "children": [], + "disabled": false + }, + { + "title": "同德县", + "id": "632522", + "children": [], + "disabled": false + }, + { + "title": "贵德县", + "id": "632523", + "children": [], + "disabled": false + }, + { + "title": "兴海县", + "id": "632524", + "children": [], + "disabled": false + }, + { + "title": "贵南县", + "id": "632525", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "果洛藏族自治州", + "id": "632600", + "children": [ + { + "title": "玛沁县", + "id": "632621", + "children": [], + "disabled": false + }, + { + "title": "班玛县", + "id": "632622", + "children": [], + "disabled": false + }, + { + "title": "甘德县", + "id": "632623", + "children": [], + "disabled": false + }, + { + "title": "达日县", + "id": "632624", + "children": [], + "disabled": false + }, + { + "title": "久治县", + "id": "632625", + "children": [], + "disabled": false + }, + { + "title": "玛多县", + "id": "632626", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "玉树藏族自治州", + "id": "632700", + "children": [ + { + "title": "玉树市", + "id": "632701", + "children": [], + "disabled": false + }, + { + "title": "杂多县", + "id": "632722", + "children": [], + "disabled": false + }, + { + "title": "称多县", + "id": "632723", + "children": [], + "disabled": false + }, + { + "title": "治多县", + "id": "632724", + "children": [], + "disabled": false + }, + { + "title": "囊谦县", + "id": "632725", + "children": [], + "disabled": false + }, + { + "title": "曲麻莱县", + "id": "632726", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "海西蒙古族藏族自治州", + "id": "632800", + "children": [ + { + "title": "格尔木市", + "id": "632801", + "children": [], + "disabled": false + }, + { + "title": "德令哈市", + "id": "632802", + "children": [], + "disabled": false + }, + { + "title": "茫崖市", + "id": "632803", + "children": [], + "disabled": false + }, + { + "title": "乌兰县", + "id": "632821", + "children": [], + "disabled": false + }, + { + "title": "都兰县", + "id": "632822", + "children": [], + "disabled": false + }, + { + "title": "天峻县", + "id": "632823", + "children": [], + "disabled": false + }, + { + "title": "大柴旦行政委员会", + "id": "632857", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "宁夏回族自治区", + "id": "640000", + "children": [ + { + "title": "银川市", + "id": "640100", + "children": [ + { + "title": "兴庆区", + "id": "640104", + "children": [], + "disabled": false + }, + { + "title": "西夏区", + "id": "640105", + "children": [], + "disabled": false + }, + { + "title": "金凤区", + "id": "640106", + "children": [], + "disabled": false + }, + { + "title": "永宁县", + "id": "640121", + "children": [], + "disabled": false + }, + { + "title": "贺兰县", + "id": "640122", + "children": [], + "disabled": false + }, + { + "title": "灵武市", + "id": "640181", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "640101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "石嘴山市", + "id": "640200", + "children": [ + { + "title": "大武口区", + "id": "640202", + "children": [], + "disabled": false + }, + { + "title": "惠农区", + "id": "640205", + "children": [], + "disabled": false + }, + { + "title": "平罗县", + "id": "640221", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "640201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "吴忠市", + "id": "640300", + "children": [ + { + "title": "利通区", + "id": "640302", + "children": [], + "disabled": false + }, + { + "title": "红寺堡区", + "id": "640303", + "children": [], + "disabled": false + }, + { + "title": "盐池县", + "id": "640323", + "children": [], + "disabled": false + }, + { + "title": "同心县", + "id": "640324", + "children": [], + "disabled": false + }, + { + "title": "青铜峡市", + "id": "640381", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "640301", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "固原市", + "id": "640400", + "children": [ + { + "title": "原州区", + "id": "640402", + "children": [], + "disabled": false + }, + { + "title": "西吉县", + "id": "640422", + "children": [], + "disabled": false + }, + { + "title": "隆德县", + "id": "640423", + "children": [], + "disabled": false + }, + { + "title": "泾源县", + "id": "640424", + "children": [], + "disabled": false + }, + { + "title": "彭阳县", + "id": "640425", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "640401", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "中卫市", + "id": "640500", + "children": [ + { + "title": "沙坡头区", + "id": "640502", + "children": [], + "disabled": false + }, + { + "title": "中宁县", + "id": "640521", + "children": [], + "disabled": false + }, + { + "title": "海原县", + "id": "640522", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "640501", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "新疆维吾尔自治区", + "id": "650000", + "children": [ + { + "title": "乌鲁木齐市", + "id": "650100", + "children": [ + { + "title": "天山区", + "id": "650102", + "children": [], + "disabled": false + }, + { + "title": "沙依巴克区", + "id": "650103", + "children": [], + "disabled": false + }, + { + "title": "新市区", + "id": "650104", + "children": [], + "disabled": false + }, + { + "title": "水磨沟区", + "id": "650105", + "children": [], + "disabled": false + }, + { + "title": "头屯河区", + "id": "650106", + "children": [], + "disabled": false + }, + { + "title": "达坂城区", + "id": "650107", + "children": [], + "disabled": false + }, + { + "title": "米东区", + "id": "650109", + "children": [], + "disabled": false + }, + { + "title": "乌鲁木齐县", + "id": "650121", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "650101", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "克拉玛依市", + "id": "650200", + "children": [ + { + "title": "独山子区", + "id": "650202", + "children": [], + "disabled": false + }, + { + "title": "克拉玛依区", + "id": "650203", + "children": [], + "disabled": false + }, + { + "title": "白碱滩区", + "id": "650204", + "children": [], + "disabled": false + }, + { + "title": "乌尔禾区", + "id": "650205", + "children": [], + "disabled": false + }, + { + "title": "市辖区", + "id": "650201", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "吐鲁番市", + "id": "650400", + "children": [ + { + "title": "高昌区", + "id": "650402", + "children": [], + "disabled": false + }, + { + "title": "鄯善县", + "id": "650421", + "children": [], + "disabled": false + }, + { + "title": "托克逊县", + "id": "650422", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "哈密市", + "id": "650500", + "children": [ + { + "title": "伊州区", + "id": "650502", + "children": [], + "disabled": false + }, + { + "title": "巴里坤哈萨克自治县", + "id": "650521", + "children": [], + "disabled": false + }, + { + "title": "伊吾县", + "id": "650522", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "昌吉回族自治州", + "id": "652300", + "children": [ + { + "title": "昌吉市", + "id": "652301", + "children": [], + "disabled": false + }, + { + "title": "阜康市", + "id": "652302", + "children": [], + "disabled": false + }, + { + "title": "呼图壁县", + "id": "652323", + "children": [], + "disabled": false + }, + { + "title": "玛纳斯县", + "id": "652324", + "children": [], + "disabled": false + }, + { + "title": "奇台县", + "id": "652325", + "children": [], + "disabled": false + }, + { + "title": "吉木萨尔县", + "id": "652327", + "children": [], + "disabled": false + }, + { + "title": "木垒哈萨克自治县", + "id": "652328", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "博尔塔拉蒙古自治州", + "id": "652700", + "children": [ + { + "title": "博乐市", + "id": "652701", + "children": [], + "disabled": false + }, + { + "title": "阿拉山口市", + "id": "652702", + "children": [], + "disabled": false + }, + { + "title": "精河县", + "id": "652722", + "children": [], + "disabled": false + }, + { + "title": "温泉县", + "id": "652723", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "巴音郭楞蒙古自治州", + "id": "652800", + "children": [ + { + "title": "库尔勒市", + "id": "652801", + "children": [], + "disabled": false + }, + { + "title": "轮台县", + "id": "652822", + "children": [], + "disabled": false + }, + { + "title": "尉犁县", + "id": "652823", + "children": [], + "disabled": false + }, + { + "title": "若羌县", + "id": "652824", + "children": [], + "disabled": false + }, + { + "title": "且末县", + "id": "652825", + "children": [], + "disabled": false + }, + { + "title": "焉耆回族自治县", + "id": "652826", + "children": [], + "disabled": false + }, + { + "title": "和静县", + "id": "652827", + "children": [], + "disabled": false + }, + { + "title": "和硕县", + "id": "652828", + "children": [], + "disabled": false + }, + { + "title": "博湖县", + "id": "652829", + "children": [], + "disabled": false + }, + { + "title": "库尔勒经济技术开发区", + "id": "652871", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阿克苏地区", + "id": "652900", + "children": [ + { + "title": "阿克苏市", + "id": "652901", + "children": [], + "disabled": false + }, + { + "title": "库车市", + "id": "652902", + "children": [], + "disabled": false + }, + { + "title": "温宿县", + "id": "652922", + "children": [], + "disabled": false + }, + { + "title": "沙雅县", + "id": "652924", + "children": [], + "disabled": false + }, + { + "title": "新和县", + "id": "652925", + "children": [], + "disabled": false + }, + { + "title": "拜城县", + "id": "652926", + "children": [], + "disabled": false + }, + { + "title": "乌什县", + "id": "652927", + "children": [], + "disabled": false + }, + { + "title": "阿瓦提县", + "id": "652928", + "children": [], + "disabled": false + }, + { + "title": "柯坪县", + "id": "652929", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "克孜勒苏柯尔克孜自治州", + "id": "653000", + "children": [ + { + "title": "阿图什市", + "id": "653001", + "children": [], + "disabled": false + }, + { + "title": "阿克陶县", + "id": "653022", + "children": [], + "disabled": false + }, + { + "title": "阿合奇县", + "id": "653023", + "children": [], + "disabled": false + }, + { + "title": "乌恰县", + "id": "653024", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "喀什地区", + "id": "653100", + "children": [ + { + "title": "喀什市", + "id": "653101", + "children": [], + "disabled": false + }, + { + "title": "疏附县", + "id": "653121", + "children": [], + "disabled": false + }, + { + "title": "疏勒县", + "id": "653122", + "children": [], + "disabled": false + }, + { + "title": "英吉沙县", + "id": "653123", + "children": [], + "disabled": false + }, + { + "title": "泽普县", + "id": "653124", + "children": [], + "disabled": false + }, + { + "title": "莎车县", + "id": "653125", + "children": [], + "disabled": false + }, + { + "title": "叶城县", + "id": "653126", + "children": [], + "disabled": false + }, + { + "title": "麦盖提县", + "id": "653127", + "children": [], + "disabled": false + }, + { + "title": "岳普湖县", + "id": "653128", + "children": [], + "disabled": false + }, + { + "title": "伽师县", + "id": "653129", + "children": [], + "disabled": false + }, + { + "title": "巴楚县", + "id": "653130", + "children": [], + "disabled": false + }, + { + "title": "塔什库尔干塔吉克自治县", + "id": "653131", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "和田地区", + "id": "653200", + "children": [ + { + "title": "和田市", + "id": "653201", + "children": [], + "disabled": false + }, + { + "title": "和田县", + "id": "653221", + "children": [], + "disabled": false + }, + { + "title": "墨玉县", + "id": "653222", + "children": [], + "disabled": false + }, + { + "title": "皮山县", + "id": "653223", + "children": [], + "disabled": false + }, + { + "title": "洛浦县", + "id": "653224", + "children": [], + "disabled": false + }, + { + "title": "策勒县", + "id": "653225", + "children": [], + "disabled": false + }, + { + "title": "于田县", + "id": "653226", + "children": [], + "disabled": false + }, + { + "title": "民丰县", + "id": "653227", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "伊犁哈萨克自治州", + "id": "654000", + "children": [ + { + "title": "伊宁市", + "id": "654002", + "children": [], + "disabled": false + }, + { + "title": "奎屯市", + "id": "654003", + "children": [], + "disabled": false + }, + { + "title": "霍尔果斯市", + "id": "654004", + "children": [], + "disabled": false + }, + { + "title": "伊宁县", + "id": "654021", + "children": [], + "disabled": false + }, + { + "title": "察布查尔锡伯自治县", + "id": "654022", + "children": [], + "disabled": false + }, + { + "title": "霍城县", + "id": "654023", + "children": [], + "disabled": false + }, + { + "title": "巩留县", + "id": "654024", + "children": [], + "disabled": false + }, + { + "title": "新源县", + "id": "654025", + "children": [], + "disabled": false + }, + { + "title": "昭苏县", + "id": "654026", + "children": [], + "disabled": false + }, + { + "title": "特克斯县", + "id": "654027", + "children": [], + "disabled": false + }, + { + "title": "尼勒克县", + "id": "654028", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "塔城地区", + "id": "654200", + "children": [ + { + "title": "塔城市", + "id": "654201", + "children": [], + "disabled": false + }, + { + "title": "乌苏市", + "id": "654202", + "children": [], + "disabled": false + }, + { + "title": "额敏县", + "id": "654221", + "children": [], + "disabled": false + }, + { + "title": "沙湾县", + "id": "654223", + "children": [], + "disabled": false + }, + { + "title": "托里县", + "id": "654224", + "children": [], + "disabled": false + }, + { + "title": "裕民县", + "id": "654225", + "children": [], + "disabled": false + }, + { + "title": "和布克赛尔蒙古自治县", + "id": "654226", + "children": [], + "disabled": false + }, + { + "title": "沙湾市", + "id": "654203", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "阿勒泰地区", + "id": "654300", + "children": [ + { + "title": "阿勒泰市", + "id": "654301", + "children": [], + "disabled": false + }, + { + "title": "布尔津县", + "id": "654321", + "children": [], + "disabled": false + }, + { + "title": "富蕴县", + "id": "654322", + "children": [], + "disabled": false + }, + { + "title": "福海县", + "id": "654323", + "children": [], + "disabled": false + }, + { + "title": "哈巴河县", + "id": "654324", + "children": [], + "disabled": false + }, + { + "title": "青河县", + "id": "654325", + "children": [], + "disabled": false + }, + { + "title": "吉木乃县", + "id": "654326", + "children": [], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "新疆维吾尔自治区-自治区直辖县级行政区划", + "id": "659000", + "children": [ + { + "title": "石河子市", + "id": "659001", + "children": [], + "disabled": false + }, + { + "title": "阿拉尔市", + "id": "659002", + "children": [], + "disabled": false + }, + { + "title": "图木舒克市", + "id": "659003", + "children": [], + "disabled": false + }, + { + "title": "五家渠市", + "id": "659004", + "children": [], + "disabled": false + }, + { + "title": "北屯市", + "id": "659005", + "children": [], + "disabled": false + }, + { + "title": "铁门关市", + "id": "659006", + "children": [], + "disabled": false + }, + { + "title": "双河市", + "id": "659007", + "children": [], + "disabled": false + }, + { + "title": "可克达拉市", + "id": "659008", + "children": [], + "disabled": false + }, + { + "title": "昆玉市", + "id": "659009", + "children": [], + "disabled": false + }, + { + "title": "胡杨河市", + "id": "659010", + "children": [], + "disabled": false + }, + { + "title": "新星市", + "id": "659011", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "香港特别行政区", + "id": "810000", + "children": [ + { + "title": "香港特别行政区", + "id": "81000011", + "children": [ + { + "title": "中西区", + "id": "810001", + "children": [], + "disabled": false + }, + { + "title": "湾仔区", + "id": "810002", + "children": [], + "disabled": false + }, + { + "title": "东区", + "id": "810003", + "children": [], + "disabled": false + }, + { + "title": "南区", + "id": "810004", + "children": [], + "disabled": false + }, + { + "title": "油尖旺区", + "id": "810005", + "children": [], + "disabled": false + }, + { + "title": "深水埗区", + "id": "810006", + "children": [], + "disabled": false + }, + { + "title": "九龙城区", + "id": "810007", + "children": [], + "disabled": false + }, + { + "title": "黄大仙区", + "id": "810008", + "children": [], + "disabled": false + }, + { + "title": "观塘区", + "id": "810009", + "children": [], + "disabled": false + }, + { + "title": "荃湾区", + "id": "810010", + "children": [], + "disabled": false + }, + { + "title": "屯门区", + "id": "810011", + "children": [], + "disabled": false + }, + { + "title": "元朗区", + "id": "810012", + "children": [], + "disabled": false + }, + { + "title": "北区", + "id": "810013", + "children": [], + "disabled": false + }, + { + "title": "大埔区", + "id": "810014", + "children": [], + "disabled": false + }, + { + "title": "西贡区", + "id": "810015", + "children": [], + "disabled": false + }, + { + "title": "沙田区", + "id": "810016", + "children": [], + "disabled": false + }, + { + "title": "葵青区", + "id": "810017", + "children": [], + "disabled": false + }, + { + "title": "离岛区", + "id": "810018", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + }, + { + "title": "澳门特别行政区", + "id": "820000", + "children": [ + { + "title": "澳门特别行政区", + "id": "82000011", + "children": [ + { + "title": "花地玛堂区", + "id": "820001", + "children": [], + "disabled": false + }, + { + "title": "花王堂区", + "id": "820002", + "children": [], + "disabled": false + }, + { + "title": "望德堂区", + "id": "820003", + "children": [], + "disabled": false + }, + { + "title": "大堂区", + "id": "820004", + "children": [], + "disabled": false + }, + { + "title": "风顺堂区", + "id": "820005", + "children": [], + "disabled": false + }, + { + "title": "嘉模堂区", + "id": "820006", + "children": [], + "disabled": false + }, + { + "title": "路凼填海区", + "id": "820007", + "children": [], + "disabled": false + }, + { + "title": "圣方济各堂区", + "id": "820008", + "children": [], + "disabled": false + } + ], + "disabled": false + } + ], + "disabled": false + } +]` +// #endif + +export default citys \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-city/level.minxxx.uts b/uni_modules/tmx-ui/components/x-picker-city/level.minxxx.uts new file mode 100644 index 0000000..d0f10be --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-city/level.minxxx.uts @@ -0,0 +1,22497 @@ +export default [ + { + "title": "北京市", + "id": "110000", + "children": [ + { + "title": "北京市", + "id": "1100001", + "children": [ + { + "title": "东城区", + "id": "110101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西城区", + "id": "110102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "朝阳区", + "id": "110105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰台区", + "id": "110106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石景山区", + "id": "110107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海淀区", + "id": "110108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "门头沟区", + "id": "110109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "房山区", + "id": "110111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通州区", + "id": "110112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "顺义区", + "id": "110113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌平区", + "id": "110114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大兴区", + "id": "110115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀柔区", + "id": "110116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平谷区", + "id": "110117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "密云区", + "id": "110118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "延庆区", + "id": "110119", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天津市", + "id": "120000", + "children": [ + { + "title": "天津市", + "id": "1200001", + "children": [ + { + "title": "和平区", + "id": "120101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河东区", + "id": "120102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河西区", + "id": "120103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南开区", + "id": "120104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河北区", + "id": "120105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红桥区", + "id": "120106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东丽区", + "id": "120110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西青区", + "id": "120111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "津南区", + "id": "120112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北辰区", + "id": "120113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武清区", + "id": "120114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝坻区", + "id": "120115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滨海新区", + "id": "120116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁河区", + "id": "120117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "静海区", + "id": "120118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蓟州区", + "id": "120119", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河北省", + "id": "130000", + "children": [ + { + "title": "石家庄市", + "id": "130100", + "children": [ + { + "title": "长安区", + "id": "130102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桥西区", + "id": "130104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新华区", + "id": "130105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "井陉矿区", + "id": "130107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "裕华区", + "id": "130108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "藁城区", + "id": "130109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹿泉区", + "id": "130110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "栾城区", + "id": "130111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "井陉县", + "id": "130121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "正定县", + "id": "130123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "行唐县", + "id": "130125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵寿县", + "id": "130126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高邑县", + "id": "130127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "深泽县", + "id": "130128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赞皇县", + "id": "130129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "无极县", + "id": "130130", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平山县", + "id": "130131", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "元氏县", + "id": "130132", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赵县", + "id": "130133", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辛集市", + "id": "130181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晋州市", + "id": "130183", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新乐市", + "id": "130184", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石家庄高新技术产业开发区", + "id": "130171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石家庄循环化工园区", + "id": "130172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "唐山市", + "id": "130200", + "children": [ + { + "title": "路南区", + "id": "130202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "路北区", + "id": "130203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "古冶区", + "id": "130204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开平区", + "id": "130205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰南区", + "id": "130207", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰润区", + "id": "130208", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曹妃甸区", + "id": "130209", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滦南县", + "id": "130224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐亭县", + "id": "130225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "迁西县", + "id": "130227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉田县", + "id": "130229", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "遵化市", + "id": "130281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "迁安市", + "id": "130283", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滦州市", + "id": "130284", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河北唐山芦台经济开发区", + "id": "130271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "唐山市汉沽管理区", + "id": "130272", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "唐山高新技术产业开发区", + "id": "130273", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河北唐山海港经济开发区", + "id": "130274", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秦皇岛市", + "id": "130300", + "children": [ + { + "title": "海港区", + "id": "130302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山海关区", + "id": "130303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北戴河区", + "id": "130304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "抚宁区", + "id": "130306", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青龙满族自治县", + "id": "130321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌黎县", + "id": "130322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卢龙县", + "id": "130324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秦皇岛市经济技术开发区", + "id": "130371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北戴河新区", + "id": "130372", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邯郸市", + "id": "130400", + "children": [ + { + "title": "邯山区", + "id": "130402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丛台区", + "id": "130403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "复兴区", + "id": "130404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "峰峰矿区", + "id": "130406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肥乡区", + "id": "130407", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永年区", + "id": "130408", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临漳县", + "id": "130423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "成安县", + "id": "130424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大名县", + "id": "130425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涉县", + "id": "130426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "磁县", + "id": "130427", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邱县", + "id": "130430", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鸡泽县", + "id": "130431", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广平县", + "id": "130432", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "馆陶县", + "id": "130433", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "魏县", + "id": "130434", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲周县", + "id": "130435", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武安市", + "id": "130481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邯郸经济技术开发区", + "id": "130471", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邯郸冀南新区", + "id": "130473", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邢台市", + "id": "130500", + "children": [ + { + "title": "襄都区", + "id": "130502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "信都区", + "id": "130503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "任泽区", + "id": "130505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南和区", + "id": "130506", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临城县", + "id": "130522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "内丘县", + "id": "130523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柏乡县", + "id": "130524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆尧县", + "id": "130525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁晋县", + "id": "130528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巨鹿县", + "id": "130529", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新河县", + "id": "130530", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广宗县", + "id": "130531", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平乡县", + "id": "130532", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威县", + "id": "130533", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清河县", + "id": "130534", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临西县", + "id": "130535", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南宫市", + "id": "130581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙河市", + "id": "130582", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河北邢台经济开发区", + "id": "130571", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保定市", + "id": "130600", + "children": [ + { + "title": "竞秀区", + "id": "130602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莲池区", + "id": "130606", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "满城区", + "id": "130607", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清苑区", + "id": "130608", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "徐水区", + "id": "130609", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涞水县", + "id": "130623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜平县", + "id": "130624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定兴县", + "id": "130626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "唐县", + "id": "130627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高阳县", + "id": "130628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "容城县", + "id": "130629", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涞源县", + "id": "130630", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "望都县", + "id": "130631", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安新县", + "id": "130632", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "易县", + "id": "130633", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲阳县", + "id": "130634", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蠡县", + "id": "130635", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "顺平县", + "id": "130636", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博野县", + "id": "130637", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雄县", + "id": "130638", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涿州市", + "id": "130681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定州市", + "id": "130682", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安国市", + "id": "130683", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高碑店市", + "id": "130684", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保定高新技术产业开发区", + "id": "130671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保定白沟新城", + "id": "130672", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张家口市", + "id": "130700", + "children": [ + { + "title": "桥东区", + "id": "130702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桥西区", + "id": "130703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宣化区", + "id": "130705", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "下花园区", + "id": "130706", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万全区", + "id": "130708", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇礼区", + "id": "130709", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张北县", + "id": "130722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "康保县", + "id": "130723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沽源县", + "id": "130724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尚义县", + "id": "130725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蔚县", + "id": "130726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳原县", + "id": "130727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀安县", + "id": "130728", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀来县", + "id": "130730", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涿鹿县", + "id": "130731", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赤城县", + "id": "130732", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张家口经济开发区", + "id": "130771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张家口市察北管理区", + "id": "130772", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张家口市塞北管理区", + "id": "130773", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "承德市", + "id": "130800", + "children": [ + { + "title": "双桥区", + "id": "130802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双滦区", + "id": "130803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹰手营子矿区", + "id": "130804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "承德县", + "id": "130821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴隆县", + "id": "130822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滦平县", + "id": "130824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆化县", + "id": "130825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰宁满族自治县", + "id": "130826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宽城满族自治县", + "id": "130827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "围场满族蒙古族自治县", + "id": "130828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平泉市", + "id": "130881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "承德高新技术产业开发区", + "id": "130871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沧州市", + "id": "130900", + "children": [ + { + "title": "新华区", + "id": "130902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "运河区", + "id": "130903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沧县", + "id": "130921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青县", + "id": "130922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东光县", + "id": "130923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海兴县", + "id": "130924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐山县", + "id": "130925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肃宁县", + "id": "130926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南皮县", + "id": "130927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吴桥县", + "id": "130928", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "献县", + "id": "130929", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孟村回族自治县", + "id": "130930", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泊头市", + "id": "130981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "任丘市", + "id": "130982", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄骅市", + "id": "130983", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河间市", + "id": "130984", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "130901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河北沧州经济开发区", + "id": "130971", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沧州高新技术产业开发区", + "id": "130972", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沧州渤海新区", + "id": "130973", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "廊坊市", + "id": "131000", + "children": [ + { + "title": "安次区", + "id": "131002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广阳区", + "id": "131003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "固安县", + "id": "131022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永清县", + "id": "131023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "香河县", + "id": "131024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大城县", + "id": "131025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文安县", + "id": "131026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大厂回族自治县", + "id": "131028", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霸州市", + "id": "131081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三河市", + "id": "131082", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "131001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "廊坊经济技术开发区", + "id": "131071", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡水市", + "id": "131100", + "children": [ + { + "title": "桃城区", + "id": "131102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "冀州区", + "id": "131103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "枣强县", + "id": "131121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武邑县", + "id": "131122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武强县", + "id": "131123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "饶阳县", + "id": "131124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安平县", + "id": "131125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "故城县", + "id": "131126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "景县", + "id": "131127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜城县", + "id": "131128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "深州市", + "id": "131182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "131101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河北衡水高新技术产业开发区", + "id": "131171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡水滨湖新区", + "id": "131172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山西省", + "id": "140000", + "children": [ + { + "title": "太原市", + "id": "140100", + "children": [ + { + "title": "小店区", + "id": "140105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "迎泽区", + "id": "140106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杏花岭区", + "id": "140107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尖草坪区", + "id": "140108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万柏林区", + "id": "140109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晋源区", + "id": "140110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清徐县", + "id": "140121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳曲县", + "id": "140122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "娄烦县", + "id": "140123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "古交市", + "id": "140181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山西转型综合改革示范区", + "id": "140171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大同市", + "id": "140200", + "children": [ + { + "title": "新荣区", + "id": "140212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平城区", + "id": "140213", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云冈区", + "id": "140214", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云州区", + "id": "140215", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳高县", + "id": "140221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天镇县", + "id": "140222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广灵县", + "id": "140223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵丘县", + "id": "140224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浑源县", + "id": "140225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "左云县", + "id": "140226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山西大同经济开发区", + "id": "140271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳泉市", + "id": "140300", + "children": [ + { + "title": "城区", + "id": "140302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "矿区", + "id": "140303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郊区", + "id": "140311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平定县", + "id": "140321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盂县", + "id": "140322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长治市", + "id": "140400", + "children": [ + { + "title": "潞州区", + "id": "140403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上党区", + "id": "140404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "屯留区", + "id": "140405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潞城区", + "id": "140406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "襄垣县", + "id": "140423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平顺县", + "id": "140425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黎城县", + "id": "140426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "壶关县", + "id": "140427", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长子县", + "id": "140428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武乡县", + "id": "140429", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沁县", + "id": "140430", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沁源县", + "id": "140431", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山西长治高新技术产业园区", + "id": "140471", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晋城市", + "id": "140500", + "children": [ + { + "title": "城区", + "id": "140502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沁水县", + "id": "140521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳城县", + "id": "140522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陵川县", + "id": "140524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泽州县", + "id": "140525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高平市", + "id": "140581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "朔州市", + "id": "140600", + "children": [ + { + "title": "朔城区", + "id": "140602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平鲁区", + "id": "140603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山阴县", + "id": "140621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "应县", + "id": "140622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "右玉县", + "id": "140623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀仁市", + "id": "140681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山西朔州经济开发区", + "id": "140671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晋中市", + "id": "140700", + "children": [ + { + "title": "榆次区", + "id": "140702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太谷区", + "id": "140703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "榆社县", + "id": "140721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "左权县", + "id": "140722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和顺县", + "id": "140723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昔阳县", + "id": "140724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "寿阳县", + "id": "140725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祁县", + "id": "140727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平遥县", + "id": "140728", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵石县", + "id": "140729", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "介休市", + "id": "140781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "运城市", + "id": "140800", + "children": [ + { + "title": "盐湖区", + "id": "140802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临猗县", + "id": "140821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万荣县", + "id": "140822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "闻喜县", + "id": "140823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "稷山县", + "id": "140824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新绛县", + "id": "140825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绛县", + "id": "140826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "垣曲县", + "id": "140827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "夏县", + "id": "140828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平陆县", + "id": "140829", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芮城县", + "id": "140830", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永济市", + "id": "140881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河津市", + "id": "140882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "忻州市", + "id": "140900", + "children": [ + { + "title": "忻府区", + "id": "140902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定襄县", + "id": "140921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五台县", + "id": "140922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "代县", + "id": "140923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "繁峙县", + "id": "140924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁武县", + "id": "140925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "静乐县", + "id": "140926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "神池县", + "id": "140927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五寨县", + "id": "140928", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岢岚县", + "id": "140929", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河曲县", + "id": "140930", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保德县", + "id": "140931", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "偏关县", + "id": "140932", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "原平市", + "id": "140981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "140901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五台山风景名胜区", + "id": "140971", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临汾市", + "id": "141000", + "children": [ + { + "title": "尧都区", + "id": "141002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲沃县", + "id": "141021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "翼城县", + "id": "141022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "襄汾县", + "id": "141023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洪洞县", + "id": "141024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "古县", + "id": "141025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安泽县", + "id": "141026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浮山县", + "id": "141027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉县", + "id": "141028", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乡宁县", + "id": "141029", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大宁县", + "id": "141030", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隰县", + "id": "141031", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永和县", + "id": "141032", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒲县", + "id": "141033", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汾西县", + "id": "141034", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "侯马市", + "id": "141081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霍州市", + "id": "141082", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "141001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吕梁市", + "id": "141100", + "children": [ + { + "title": "离石区", + "id": "141102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文水县", + "id": "141121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "交城县", + "id": "141122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴县", + "id": "141123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临县", + "id": "141124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柳林县", + "id": "141125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石楼县", + "id": "141126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岚县", + "id": "141127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "方山县", + "id": "141128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中阳县", + "id": "141129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "交口县", + "id": "141130", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孝义市", + "id": "141181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汾阳市", + "id": "141182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "141101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "内蒙古自治区", + "id": "150000", + "children": [ + { + "title": "呼和浩特市", + "id": "150100", + "children": [ + { + "title": "新城区", + "id": "150102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "回民区", + "id": "150103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉泉区", + "id": "150104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赛罕区", + "id": "150105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "土默特左旗", + "id": "150121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "托克托县", + "id": "150122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和林格尔县", + "id": "150123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清水河县", + "id": "150124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武川县", + "id": "150125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "呼和浩特经济技术开发区", + "id": "150172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "包头市", + "id": "150200", + "children": [ + { + "title": "东河区", + "id": "150202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昆都仑区", + "id": "150203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青山区", + "id": "150204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石拐区", + "id": "150205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白云鄂博矿区", + "id": "150206", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "九原区", + "id": "150207", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "土默特右旗", + "id": "150221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "固阳县", + "id": "150222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达尔罕茂明安联合旗", + "id": "150223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "包头稀土高新技术产业开发区", + "id": "150271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌海市", + "id": "150300", + "children": [ + { + "title": "海勃湾区", + "id": "150302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海南区", + "id": "150303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌达区", + "id": "150304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赤峰市", + "id": "150400", + "children": [ + { + "title": "红山区", + "id": "150402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "元宝山区", + "id": "150403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松山区", + "id": "150404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿鲁科尔沁旗", + "id": "150421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴林左旗", + "id": "150422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴林右旗", + "id": "150423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "林西县", + "id": "150424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "克什克腾旗", + "id": "150425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "翁牛特旗", + "id": "150426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "喀喇沁旗", + "id": "150428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁城县", + "id": "150429", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "敖汉旗", + "id": "150430", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通辽市", + "id": "150500", + "children": [ + { + "title": "科尔沁区", + "id": "150502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "科尔沁左翼中旗", + "id": "150521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "科尔沁左翼后旗", + "id": "150522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开鲁县", + "id": "150523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "库伦旗", + "id": "150524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奈曼旗", + "id": "150525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扎鲁特旗", + "id": "150526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霍林郭勒市", + "id": "150581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通辽经济技术开发区", + "id": "150571", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄂尔多斯市", + "id": "150600", + "children": [ + { + "title": "东胜区", + "id": "150602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "康巴什区", + "id": "150603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达拉特旗", + "id": "150621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "准格尔旗", + "id": "150622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄂托克前旗", + "id": "150623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄂托克旗", + "id": "150624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杭锦旗", + "id": "150625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌审旗", + "id": "150626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伊金霍洛旗", + "id": "150627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "呼伦贝尔市", + "id": "150700", + "children": [ + { + "title": "海拉尔区", + "id": "150702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扎赉诺尔区", + "id": "150703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿荣旗", + "id": "150721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莫力达瓦达斡尔族自治旗", + "id": "150722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄂伦春自治旗", + "id": "150723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄂温克族自治旗", + "id": "150724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陈巴尔虎旗", + "id": "150725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新巴尔虎左旗", + "id": "150726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新巴尔虎右旗", + "id": "150727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "满洲里市", + "id": "150781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "牙克石市", + "id": "150782", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扎兰屯市", + "id": "150783", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "额尔古纳市", + "id": "150784", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "根河市", + "id": "150785", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴彦淖尔市", + "id": "150800", + "children": [ + { + "title": "临河区", + "id": "150802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五原县", + "id": "150821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "磴口县", + "id": "150822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌拉特前旗", + "id": "150823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌拉特中旗", + "id": "150824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌拉特后旗", + "id": "150825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杭锦后旗", + "id": "150826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌兰察布市", + "id": "150900", + "children": [ + { + "title": "集宁区", + "id": "150902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卓资县", + "id": "150921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "化德县", + "id": "150922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "商都县", + "id": "150923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴和县", + "id": "150924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凉城县", + "id": "150925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "察哈尔右翼前旗", + "id": "150926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "察哈尔右翼中旗", + "id": "150927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "察哈尔右翼后旗", + "id": "150928", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "四子王旗", + "id": "150929", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰镇市", + "id": "150981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "150901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴安盟", + "id": "152200", + "children": [ + { + "title": "乌兰浩特市", + "id": "152201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿尔山市", + "id": "152202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "科尔沁右翼前旗", + "id": "152221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "科尔沁右翼中旗", + "id": "152222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扎赉特旗", + "id": "152223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "突泉县", + "id": "152224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "锡林郭勒盟", + "id": "152500", + "children": [ + { + "title": "二连浩特市", + "id": "152501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "锡林浩特市", + "id": "152502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿巴嘎旗", + "id": "152522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苏尼特左旗", + "id": "152523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苏尼特右旗", + "id": "152524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东乌珠穆沁旗", + "id": "152525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西乌珠穆沁旗", + "id": "152526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太仆寺旗", + "id": "152527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镶黄旗", + "id": "152528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "正镶白旗", + "id": "152529", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "正蓝旗", + "id": "152530", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "多伦县", + "id": "152531", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌拉盖管委会", + "id": "152571", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿拉善盟", + "id": "152900", + "children": [ + { + "title": "阿拉善左旗", + "id": "152921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿拉善右旗", + "id": "152922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "额济纳旗", + "id": "152923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "内蒙古阿拉善高新技术产业开发区", + "id": "152971", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辽宁省", + "id": "210000", + "children": [ + { + "title": "沈阳市", + "id": "210100", + "children": [ + { + "title": "和平区", + "id": "210102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沈河区", + "id": "210103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大东区", + "id": "210104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "皇姑区", + "id": "210105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁西区", + "id": "210106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苏家屯区", + "id": "210111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浑南区", + "id": "210112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沈北新区", + "id": "210113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "于洪区", + "id": "210114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辽中区", + "id": "210115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "康平县", + "id": "210123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "法库县", + "id": "210124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新民市", + "id": "210181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大连市", + "id": "210200", + "children": [ + { + "title": "中山区", + "id": "210202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西岗区", + "id": "210203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙河口区", + "id": "210204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘井子区", + "id": "210211", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "旅顺口区", + "id": "210212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金州区", + "id": "210213", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普兰店区", + "id": "210214", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长海县", + "id": "210224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瓦房店市", + "id": "210281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庄河市", + "id": "210283", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鞍山市", + "id": "210300", + "children": [ + { + "title": "铁东区", + "id": "210302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁西区", + "id": "210303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "立山区", + "id": "210304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "千山区", + "id": "210311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "台安县", + "id": "210321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岫岩满族自治县", + "id": "210323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海城市", + "id": "210381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "抚顺市", + "id": "210400", + "children": [ + { + "title": "新抚区", + "id": "210402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东洲区", + "id": "210403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "望花区", + "id": "210404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "顺城区", + "id": "210411", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "抚顺县", + "id": "210421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新宾满族自治县", + "id": "210422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清原满族自治县", + "id": "210423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "本溪市", + "id": "210500", + "children": [ + { + "title": "平山区", + "id": "210502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "溪湖区", + "id": "210503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "明山区", + "id": "210504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南芬区", + "id": "210505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "本溪满族自治县", + "id": "210521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桓仁满族自治县", + "id": "210522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹东市", + "id": "210600", + "children": [ + { + "title": "元宝区", + "id": "210602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "振兴区", + "id": "210603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "振安区", + "id": "210604", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宽甸满族自治县", + "id": "210624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东港市", + "id": "210681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤城市", + "id": "210682", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "锦州市", + "id": "210700", + "children": [ + { + "title": "古塔区", + "id": "210702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凌河区", + "id": "210703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太和区", + "id": "210711", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黑山县", + "id": "210726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "义县", + "id": "210727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凌海市", + "id": "210781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北镇市", + "id": "210782", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "营口市", + "id": "210800", + "children": [ + { + "title": "站前区", + "id": "210802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西市区", + "id": "210803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鲅鱼圈区", + "id": "210804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "老边区", + "id": "210811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盖州市", + "id": "210881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大石桥市", + "id": "210882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜新市", + "id": "210900", + "children": [ + { + "title": "海州区", + "id": "210902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新邱区", + "id": "210903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太平区", + "id": "210904", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清河门区", + "id": "210905", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "细河区", + "id": "210911", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜新蒙古族自治县", + "id": "210921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彰武县", + "id": "210922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "210901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辽阳市", + "id": "211000", + "children": [ + { + "title": "白塔区", + "id": "211002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文圣区", + "id": "211003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宏伟区", + "id": "211004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "弓长岭区", + "id": "211005", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太子河区", + "id": "211011", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辽阳县", + "id": "211021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灯塔市", + "id": "211081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "211001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盘锦市", + "id": "211100", + "children": [ + { + "title": "双台子区", + "id": "211102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴隆台区", + "id": "211103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大洼区", + "id": "211104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盘山县", + "id": "211122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "211101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁岭市", + "id": "211200", + "children": [ + { + "title": "银州区", + "id": "211202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清河区", + "id": "211204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁岭县", + "id": "211221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西丰县", + "id": "211223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌图县", + "id": "211224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "调兵山市", + "id": "211281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开原市", + "id": "211282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "211201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "朝阳市", + "id": "211300", + "children": [ + { + "title": "双塔区", + "id": "211302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙城区", + "id": "211303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "朝阳县", + "id": "211321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建平县", + "id": "211322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "喀喇沁左翼蒙古族自治县", + "id": "211324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北票市", + "id": "211381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凌源市", + "id": "211382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "211301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "葫芦岛市", + "id": "211400", + "children": [ + { + "title": "连山区", + "id": "211402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙港区", + "id": "211403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南票区", + "id": "211404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥中县", + "id": "211421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建昌县", + "id": "211422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴城市", + "id": "211481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "211401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉林省", + "id": "220000", + "children": [ + { + "title": "长春市", + "id": "220100", + "children": [ + { + "title": "南关区", + "id": "220102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宽城区", + "id": "220103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "朝阳区", + "id": "220104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "二道区", + "id": "220105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绿园区", + "id": "220106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双阳区", + "id": "220112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "九台区", + "id": "220113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "农安县", + "id": "220122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "榆树市", + "id": "220182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德惠市", + "id": "220183", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "公主岭市", + "id": "220184", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长春经济技术开发区", + "id": "220171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长春净月高新技术产业开发区", + "id": "220172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长春高新技术产业开发区", + "id": "220173", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长春汽车经济技术开发区", + "id": "220174", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉林市", + "id": "220200", + "children": [ + { + "title": "昌邑区", + "id": "220202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙潭区", + "id": "220203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "船营区", + "id": "220204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰满区", + "id": "220211", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永吉县", + "id": "220221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蛟河市", + "id": "220281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桦甸市", + "id": "220282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "舒兰市", + "id": "220283", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "磐石市", + "id": "220284", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉林经济开发区", + "id": "220271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉林高新技术产业开发区", + "id": "220272", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉林中国新加坡食品区", + "id": "220273", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "四平市", + "id": "220300", + "children": [ + { + "title": "铁西区", + "id": "220302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁东区", + "id": "220303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梨树县", + "id": "220322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伊通满族自治县", + "id": "220323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双辽市", + "id": "220382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辽源市", + "id": "220400", + "children": [ + { + "title": "龙山区", + "id": "220402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西安区", + "id": "220403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东丰县", + "id": "220421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东辽县", + "id": "220422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通化市", + "id": "220500", + "children": [ + { + "title": "东昌区", + "id": "220502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "二道江区", + "id": "220503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通化县", + "id": "220521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辉南县", + "id": "220523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柳河县", + "id": "220524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梅河口市", + "id": "220581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "集安市", + "id": "220582", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白山市", + "id": "220600", + "children": [ + { + "title": "浑江区", + "id": "220602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江源区", + "id": "220605", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "抚松县", + "id": "220621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "靖宇县", + "id": "220622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长白朝鲜族自治县", + "id": "220623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临江市", + "id": "220681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松原市", + "id": "220700", + "children": [ + { + "title": "宁江区", + "id": "220702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "前郭尔罗斯蒙古族自治县", + "id": "220721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长岭县", + "id": "220722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乾安县", + "id": "220723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扶余市", + "id": "220781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉林松原经济开发区", + "id": "220771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白城市", + "id": "220800", + "children": [ + { + "title": "洮北区", + "id": "220802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇赉县", + "id": "220821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通榆县", + "id": "220822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洮南市", + "id": "220881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大安市", + "id": "220882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "220801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉林白城经济开发区", + "id": "220871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "延边朝鲜族自治州", + "id": "222400", + "children": [ + { + "title": "延吉市", + "id": "222401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "图们市", + "id": "222402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "敦化市", + "id": "222403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "珲春市", + "id": "222404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙井市", + "id": "222405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和龙市", + "id": "222406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汪清县", + "id": "222424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安图县", + "id": "222426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黑龙江省", + "id": "230000", + "children": [ + { + "title": "哈尔滨市", + "id": "230100", + "children": [ + { + "title": "道里区", + "id": "230102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南岗区", + "id": "230103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "道外区", + "id": "230104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平房区", + "id": "230108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松北区", + "id": "230109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "香坊区", + "id": "230110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "呼兰区", + "id": "230111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿城区", + "id": "230112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双城区", + "id": "230113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "依兰县", + "id": "230123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "方正县", + "id": "230124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宾县", + "id": "230125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴彦县", + "id": "230126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "木兰县", + "id": "230127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通河县", + "id": "230128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "延寿县", + "id": "230129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尚志市", + "id": "230183", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五常市", + "id": "230184", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "齐齐哈尔市", + "id": "230200", + "children": [ + { + "title": "龙沙区", + "id": "230202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建华区", + "id": "230203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁锋区", + "id": "230204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昂昂溪区", + "id": "230205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富拉尔基区", + "id": "230206", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "碾子山区", + "id": "230207", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梅里斯达斡尔族区", + "id": "230208", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙江县", + "id": "230221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "依安县", + "id": "230223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰来县", + "id": "230224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘南县", + "id": "230225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富裕县", + "id": "230227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "克山县", + "id": "230229", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "克东县", + "id": "230230", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "拜泉县", + "id": "230231", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "讷河市", + "id": "230281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鸡西市", + "id": "230300", + "children": [ + { + "title": "鸡冠区", + "id": "230302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "恒山区", + "id": "230303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滴道区", + "id": "230304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梨树区", + "id": "230305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城子河区", + "id": "230306", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麻山区", + "id": "230307", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鸡东县", + "id": "230321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "虎林市", + "id": "230381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "密山市", + "id": "230382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹤岗市", + "id": "230400", + "children": [ + { + "title": "向阳区", + "id": "230402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "工农区", + "id": "230403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南山区", + "id": "230404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴安区", + "id": "230405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东山区", + "id": "230406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴山区", + "id": "230407", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "萝北县", + "id": "230421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥滨县", + "id": "230422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双鸭山市", + "id": "230500", + "children": [ + { + "title": "尖山区", + "id": "230502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岭东区", + "id": "230503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "四方台区", + "id": "230505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝山区", + "id": "230506", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "集贤县", + "id": "230521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "友谊县", + "id": "230522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝清县", + "id": "230523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "饶河县", + "id": "230524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大庆市", + "id": "230600", + "children": [ + { + "title": "萨尔图区", + "id": "230602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙凤区", + "id": "230603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "让胡路区", + "id": "230604", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红岗区", + "id": "230605", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大同区", + "id": "230606", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肇州县", + "id": "230621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肇源县", + "id": "230622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "林甸县", + "id": "230623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杜尔伯特蒙古族自治县", + "id": "230624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大庆高新技术产业开发区", + "id": "230671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伊春市", + "id": "230700", + "children": [ + { + "title": "伊美区", + "id": "230717", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌翠区", + "id": "230718", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "友好区", + "id": "230719", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉荫县", + "id": "230722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汤旺县", + "id": "230723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰林县", + "id": "230724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大箐山县", + "id": "230725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南岔县", + "id": "230726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金林区", + "id": "230751", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁力市", + "id": "230781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "佳木斯市", + "id": "230800", + "children": [ + { + "title": "向阳区", + "id": "230803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "前进区", + "id": "230804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东风区", + "id": "230805", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郊区", + "id": "230811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桦南县", + "id": "230822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桦川县", + "id": "230826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汤原县", + "id": "230828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "同江市", + "id": "230881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富锦市", + "id": "230882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "抚远市", + "id": "230883", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "七台河市", + "id": "230900", + "children": [ + { + "title": "新兴区", + "id": "230902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桃山区", + "id": "230903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "茄子河区", + "id": "230904", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "勃利县", + "id": "230921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "230901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "牡丹江市", + "id": "231000", + "children": [ + { + "title": "东安区", + "id": "231002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳明区", + "id": "231003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "爱民区", + "id": "231004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西安区", + "id": "231005", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "林口县", + "id": "231025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥芬河市", + "id": "231081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海林市", + "id": "231083", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁安市", + "id": "231084", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "穆棱市", + "id": "231085", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东宁市", + "id": "231086", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "231001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "牡丹江经济技术开发区", + "id": "231071", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黑河市", + "id": "231100", + "children": [ + { + "title": "爱辉区", + "id": "231102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "逊克县", + "id": "231123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孙吴县", + "id": "231124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北安市", + "id": "231181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五大连池市", + "id": "231182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嫩江市", + "id": "231183", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "231101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥化市", + "id": "231200", + "children": [ + { + "title": "北林区", + "id": "231202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "望奎县", + "id": "231221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兰西县", + "id": "231222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青冈县", + "id": "231223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庆安县", + "id": "231224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "明水县", + "id": "231225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥棱县", + "id": "231226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安达市", + "id": "231281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肇东市", + "id": "231282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海伦市", + "id": "231283", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "231201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大兴安岭地区", + "id": "232700", + "children": [ + { + "title": "漠河市", + "id": "232701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "呼玛县", + "id": "232721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "塔河县", + "id": "232722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "加格达奇区", + "id": "232761", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松岭区", + "id": "232762", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新林区", + "id": "232763", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "呼中区", + "id": "232764", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上海市", + "id": "310000", + "children": [ + { + "title": "上海市", + "id": "3100001", + "children": [ + { + "title": "黄浦区", + "id": "310101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "徐汇区", + "id": "310104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长宁区", + "id": "310105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "静安区", + "id": "310106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普陀区", + "id": "310107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "虹口区", + "id": "310109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杨浦区", + "id": "310110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "闵行区", + "id": "310112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝山区", + "id": "310113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉定区", + "id": "310114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浦东新区", + "id": "310115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金山区", + "id": "310116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松江区", + "id": "310117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青浦区", + "id": "310118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奉贤区", + "id": "310120", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇明区", + "id": "310151", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江苏省", + "id": "320000", + "children": [ + { + "title": "南京市", + "id": "320100", + "children": [ + { + "title": "玄武区", + "id": "320102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秦淮区", + "id": "320104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建邺区", + "id": "320105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鼓楼区", + "id": "320106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浦口区", + "id": "320111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "栖霞区", + "id": "320113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雨花台区", + "id": "320114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江宁区", + "id": "320115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "六合区", + "id": "320116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "溧水区", + "id": "320117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高淳区", + "id": "320118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "无锡市", + "id": "320200", + "children": [ + { + "title": "锡山区", + "id": "320205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠山区", + "id": "320206", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滨湖区", + "id": "320211", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梁溪区", + "id": "320213", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新吴区", + "id": "320214", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江阴市", + "id": "320281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜兴市", + "id": "320282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "徐州市", + "id": "320300", + "children": [ + { + "title": "鼓楼区", + "id": "320302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云龙区", + "id": "320303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贾汪区", + "id": "320305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泉山区", + "id": "320311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铜山区", + "id": "320312", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰县", + "id": "320321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沛县", + "id": "320322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "睢宁县", + "id": "320324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新沂市", + "id": "320381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邳州市", + "id": "320382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "徐州经济技术开发区", + "id": "320371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "常州市", + "id": "320400", + "children": [ + { + "title": "天宁区", + "id": "320402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "钟楼区", + "id": "320404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新北区", + "id": "320411", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武进区", + "id": "320412", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金坛区", + "id": "320413", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "溧阳市", + "id": "320481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苏州市", + "id": "320500", + "children": [ + { + "title": "虎丘区", + "id": "320505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吴中区", + "id": "320506", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "相城区", + "id": "320507", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "姑苏区", + "id": "320508", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吴江区", + "id": "320509", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "常熟市", + "id": "320581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张家港市", + "id": "320582", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昆山市", + "id": "320583", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太仓市", + "id": "320585", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苏州工业园区", + "id": "320571", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南通市", + "id": "320600", + "children": [ + { + "title": "通州区", + "id": "320612", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇川区", + "id": "320613", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海门区", + "id": "320614", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "如东县", + "id": "320623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "启东市", + "id": "320681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "如皋市", + "id": "320682", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海安市", + "id": "320685", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南通经济技术开发区", + "id": "320671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连云港市", + "id": "320700", + "children": [ + { + "title": "连云区", + "id": "320703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海州区", + "id": "320706", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赣榆区", + "id": "320707", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东海县", + "id": "320722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灌云县", + "id": "320723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灌南县", + "id": "320724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连云港经济技术开发区", + "id": "320771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连云港高新技术产业开发区", + "id": "320772", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮安市", + "id": "320800", + "children": [ + { + "title": "淮安区", + "id": "320803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮阴区", + "id": "320804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清江浦区", + "id": "320812", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洪泽区", + "id": "320813", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涟水县", + "id": "320826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盱眙县", + "id": "320830", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金湖县", + "id": "320831", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮安经济技术开发区", + "id": "320871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐城市", + "id": "320900", + "children": [ + { + "title": "亭湖区", + "id": "320902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐都区", + "id": "320903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大丰区", + "id": "320904", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "响水县", + "id": "320921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滨海县", + "id": "320922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜宁县", + "id": "320923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "射阳县", + "id": "320924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建湖县", + "id": "320925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东台市", + "id": "320981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "320901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐城经济技术开发区", + "id": "320971", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扬州市", + "id": "321000", + "children": [ + { + "title": "广陵区", + "id": "321002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邗江区", + "id": "321003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江都区", + "id": "321012", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝应县", + "id": "321023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仪征市", + "id": "321081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高邮市", + "id": "321084", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "321001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扬州经济技术开发区", + "id": "321071", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇江市", + "id": "321100", + "children": [ + { + "title": "京口区", + "id": "321102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "润州区", + "id": "321111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹徒区", + "id": "321112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹阳市", + "id": "321181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扬中市", + "id": "321182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "句容市", + "id": "321183", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "321101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇江新区", + "id": "321171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰州市", + "id": "321200", + "children": [ + { + "title": "海陵区", + "id": "321202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高港区", + "id": "321203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "姜堰区", + "id": "321204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴化市", + "id": "321281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "靖江市", + "id": "321282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰兴市", + "id": "321283", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "321201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰州医药高新技术产业开发区", + "id": "321271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宿迁市", + "id": "321300", + "children": [ + { + "title": "宿城区", + "id": "321302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宿豫区", + "id": "321311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沭阳县", + "id": "321322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泗阳县", + "id": "321323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泗洪县", + "id": "321324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "321301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宿迁经济技术开发区", + "id": "321371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浙江省", + "id": "330000", + "children": [ + { + "title": "杭州市", + "id": "330100", + "children": [ + { + "title": "上城区", + "id": "330102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "下城区", + "id": "330103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江干区", + "id": "330104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "拱墅区", + "id": "330105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西湖区", + "id": "330106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滨江区", + "id": "330108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "萧山区", + "id": "330109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "余杭区", + "id": "330110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富阳区", + "id": "330111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临安区", + "id": "330112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桐庐县", + "id": "330122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淳安县", + "id": "330127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建德市", + "id": "330182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临平区", + "id": "330113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "钱塘区", + "id": "330114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁波市", + "id": "330200", + "children": [ + { + "title": "海曙区", + "id": "330203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江北区", + "id": "330205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北仑区", + "id": "330206", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇海区", + "id": "330211", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄞州区", + "id": "330212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奉化区", + "id": "330213", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "象山县", + "id": "330225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁海县", + "id": "330226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "余姚市", + "id": "330281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "慈溪市", + "id": "330282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "温州市", + "id": "330300", + "children": [ + { + "title": "鹿城区", + "id": "330302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙湾区", + "id": "330303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瓯海区", + "id": "330304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洞头区", + "id": "330305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永嘉县", + "id": "330324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平阳县", + "id": "330326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苍南县", + "id": "330327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文成县", + "id": "330328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰顺县", + "id": "330329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瑞安市", + "id": "330381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐清市", + "id": "330382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙港市", + "id": "330383", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "温州经济技术开发区", + "id": "330371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉兴市", + "id": "330400", + "children": [ + { + "title": "南湖区", + "id": "330402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秀洲区", + "id": "330411", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉善县", + "id": "330421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海盐县", + "id": "330424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海宁市", + "id": "330481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平湖市", + "id": "330482", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桐乡市", + "id": "330483", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖州市", + "id": "330500", + "children": [ + { + "title": "吴兴区", + "id": "330502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南浔区", + "id": "330503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德清县", + "id": "330521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长兴县", + "id": "330522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安吉县", + "id": "330523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绍兴市", + "id": "330600", + "children": [ + { + "title": "越城区", + "id": "330602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柯桥区", + "id": "330603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上虞区", + "id": "330604", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新昌县", + "id": "330624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "诸暨市", + "id": "330681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嵊州市", + "id": "330683", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金华市", + "id": "330700", + "children": [ + { + "title": "婺城区", + "id": "330702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金东区", + "id": "330703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武义县", + "id": "330723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浦江县", + "id": "330726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "磐安县", + "id": "330727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兰溪市", + "id": "330781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "义乌市", + "id": "330782", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东阳市", + "id": "330783", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永康市", + "id": "330784", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衢州市", + "id": "330800", + "children": [ + { + "title": "柯城区", + "id": "330802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衢江区", + "id": "330803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "常山县", + "id": "330822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开化县", + "id": "330824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙游县", + "id": "330825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江山市", + "id": "330881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "舟山市", + "id": "330900", + "children": [ + { + "title": "定海区", + "id": "330902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普陀区", + "id": "330903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岱山县", + "id": "330921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嵊泗县", + "id": "330922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "330901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "台州市", + "id": "331000", + "children": [ + { + "title": "椒江区", + "id": "331002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄岩区", + "id": "331003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "路桥区", + "id": "331004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三门县", + "id": "331022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天台县", + "id": "331023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仙居县", + "id": "331024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "温岭市", + "id": "331081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临海市", + "id": "331082", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉环市", + "id": "331083", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "331001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丽水市", + "id": "331100", + "children": [ + { + "title": "莲都区", + "id": "331102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青田县", + "id": "331121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "缙云县", + "id": "331122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "遂昌县", + "id": "331123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松阳县", + "id": "331124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云和县", + "id": "331125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庆元县", + "id": "331126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "景宁畲族自治县", + "id": "331127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙泉市", + "id": "331181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "331101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安徽省", + "id": "340000", + "children": [ + { + "title": "合肥市", + "id": "340100", + "children": [ + { + "title": "瑶海区", + "id": "340102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庐阳区", + "id": "340103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蜀山区", + "id": "340104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "包河区", + "id": "340111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长丰县", + "id": "340121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肥东县", + "id": "340122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肥西县", + "id": "340123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庐江县", + "id": "340124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巢湖市", + "id": "340181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合肥高新技术产业开发区", + "id": "340171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合肥经济技术开发区", + "id": "340172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合肥新站高新技术产业开发区", + "id": "340173", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芜湖市", + "id": "340200", + "children": [ + { + "title": "镜湖区", + "id": "340202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鸠江区", + "id": "340207", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "弋江区", + "id": "340209", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湾沚区", + "id": "340210", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "繁昌区", + "id": "340212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南陵县", + "id": "340223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "无为市", + "id": "340281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芜湖经济技术开发区", + "id": "340271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安徽芜湖三山经济开发区", + "id": "340272", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蚌埠市", + "id": "340300", + "children": [ + { + "title": "龙子湖区", + "id": "340302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蚌山区", + "id": "340303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "禹会区", + "id": "340304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮上区", + "id": "340311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀远县", + "id": "340321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五河县", + "id": "340322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "固镇县", + "id": "340323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蚌埠市高新技术开发区", + "id": "340371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蚌埠市经济开发区", + "id": "340372", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮南市", + "id": "340400", + "children": [ + { + "title": "大通区", + "id": "340402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "田家庵区", + "id": "340403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "谢家集区", + "id": "340404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "八公山区", + "id": "340405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潘集区", + "id": "340406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤台县", + "id": "340421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "寿县", + "id": "340422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "马鞍山市", + "id": "340500", + "children": [ + { + "title": "花山区", + "id": "340503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雨山区", + "id": "340504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博望区", + "id": "340506", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "当涂县", + "id": "340521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "含山县", + "id": "340522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和县", + "id": "340523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮北市", + "id": "340600", + "children": [ + { + "title": "杜集区", + "id": "340602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "相山区", + "id": "340603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "烈山区", + "id": "340604", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "濉溪县", + "id": "340621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铜陵市", + "id": "340700", + "children": [ + { + "title": "铜官区", + "id": "340705", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "义安区", + "id": "340706", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郊区", + "id": "340711", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "枞阳县", + "id": "340722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安庆市", + "id": "340800", + "children": [ + { + "title": "迎江区", + "id": "340802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大观区", + "id": "340803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜秀区", + "id": "340811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀宁县", + "id": "340822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太湖县", + "id": "340825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宿松县", + "id": "340826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "望江县", + "id": "340827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳西县", + "id": "340828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桐城市", + "id": "340881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潜山市", + "id": "340882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "340801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安徽安庆经济开发区", + "id": "340871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄山市", + "id": "341000", + "children": [ + { + "title": "屯溪区", + "id": "341002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄山区", + "id": "341003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "徽州区", + "id": "341004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "歙县", + "id": "341021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "休宁县", + "id": "341022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黟县", + "id": "341023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祁门县", + "id": "341024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滁州市", + "id": "341100", + "children": [ + { + "title": "琅琊区", + "id": "341102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南谯区", + "id": "341103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "来安县", + "id": "341122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "全椒县", + "id": "341124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定远县", + "id": "341125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤阳县", + "id": "341126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天长市", + "id": "341181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "明光市", + "id": "341182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中新苏滁高新技术产业开发区", + "id": "341171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滁州经济技术开发区", + "id": "341172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜阳市", + "id": "341200", + "children": [ + { + "title": "颍州区", + "id": "341202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "颍东区", + "id": "341203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "颍泉区", + "id": "341204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临泉县", + "id": "341221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太和县", + "id": "341222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜南县", + "id": "341225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "颍上县", + "id": "341226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "界首市", + "id": "341282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜阳合肥现代产业园区", + "id": "341271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜阳经济技术开发区", + "id": "341272", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宿州市", + "id": "341300", + "children": [ + { + "title": "埇桥区", + "id": "341302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "砀山县", + "id": "341321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "萧县", + "id": "341322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵璧县", + "id": "341323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泗县", + "id": "341324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宿州马鞍山现代产业园区", + "id": "341371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宿州经济技术开发区", + "id": "341372", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "六安市", + "id": "341500", + "children": [ + { + "title": "金安区", + "id": "341502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "裕安区", + "id": "341503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "叶集区", + "id": "341504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霍邱县", + "id": "341522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "舒城县", + "id": "341523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金寨县", + "id": "341524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霍山县", + "id": "341525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "亳州市", + "id": "341600", + "children": [ + { + "title": "谯城区", + "id": "341602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涡阳县", + "id": "341621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒙城县", + "id": "341622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "利辛县", + "id": "341623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "池州市", + "id": "341700", + "children": [ + { + "title": "贵池区", + "id": "341702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东至县", + "id": "341721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石台县", + "id": "341722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青阳县", + "id": "341723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宣城市", + "id": "341800", + "children": [ + { + "title": "宣州区", + "id": "341802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郎溪县", + "id": "341821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泾县", + "id": "341823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绩溪县", + "id": "341824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "旌德县", + "id": "341825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁国市", + "id": "341881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广德市", + "id": "341882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "341801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宣城市经济开发区", + "id": "341871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福建省", + "id": "350000", + "children": [ + { + "title": "福州市", + "id": "350100", + "children": [ + { + "title": "鼓楼区", + "id": "350102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "台江区", + "id": "350103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仓山区", + "id": "350104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "马尾区", + "id": "350105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晋安区", + "id": "350111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长乐区", + "id": "350112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "闽侯县", + "id": "350121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连江县", + "id": "350122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗源县", + "id": "350123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "闽清县", + "id": "350124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永泰县", + "id": "350125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平潭县", + "id": "350128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福清市", + "id": "350181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "厦门市", + "id": "350200", + "children": [ + { + "title": "思明区", + "id": "350203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海沧区", + "id": "350205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖里区", + "id": "350206", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "集美区", + "id": "350211", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "同安区", + "id": "350212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "翔安区", + "id": "350213", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莆田市", + "id": "350300", + "children": [ + { + "title": "城厢区", + "id": "350302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涵江区", + "id": "350303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荔城区", + "id": "350304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秀屿区", + "id": "350305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仙游县", + "id": "350322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三明市", + "id": "350400", + "children": [ + { + "title": "梅列区", + "id": "350402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三元区", + "id": "350403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "明溪县", + "id": "350421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清流县", + "id": "350423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁化县", + "id": "350424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大田县", + "id": "350425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尤溪县", + "id": "350426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙县", + "id": "350427", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "将乐县", + "id": "350428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰宁县", + "id": "350429", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建宁县", + "id": "350430", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永安市", + "id": "350481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三元区", + "id": "350404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙县区", + "id": "350405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泉州市", + "id": "350500", + "children": [ + { + "title": "鲤城区", + "id": "350502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰泽区", + "id": "350503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛江区", + "id": "350504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泉港区", + "id": "350505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠安县", + "id": "350521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安溪县", + "id": "350524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永春县", + "id": "350525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德化县", + "id": "350526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金门县", + "id": "350527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石狮市", + "id": "350581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晋江市", + "id": "350582", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南安市", + "id": "350583", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "漳州市", + "id": "350600", + "children": [ + { + "title": "芗城区", + "id": "350602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙文区", + "id": "350603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云霄县", + "id": "350622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "漳浦县", + "id": "350623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "诏安县", + "id": "350624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长泰县", + "id": "350625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东山县", + "id": "350626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南靖县", + "id": "350627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平和县", + "id": "350628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华安县", + "id": "350629", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙海市", + "id": "350681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙海区", + "id": "350604", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长泰区", + "id": "350605", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南平市", + "id": "350700", + "children": [ + { + "title": "延平区", + "id": "350702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建阳区", + "id": "350703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "顺昌县", + "id": "350721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浦城县", + "id": "350722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "光泽县", + "id": "350723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松溪县", + "id": "350724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "政和县", + "id": "350725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邵武市", + "id": "350781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武夷山市", + "id": "350782", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建瓯市", + "id": "350783", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙岩市", + "id": "350800", + "children": [ + { + "title": "新罗区", + "id": "350802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永定区", + "id": "350803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长汀县", + "id": "350821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上杭县", + "id": "350823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武平县", + "id": "350824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连城县", + "id": "350825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "漳平市", + "id": "350881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁德市", + "id": "350900", + "children": [ + { + "title": "蕉城区", + "id": "350902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霞浦县", + "id": "350921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "古田县", + "id": "350922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "屏南县", + "id": "350923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "寿宁县", + "id": "350924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "周宁县", + "id": "350925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柘荣县", + "id": "350926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福安市", + "id": "350981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福鼎市", + "id": "350982", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "350901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江西省", + "id": "360000", + "children": [ + { + "title": "南昌市", + "id": "360100", + "children": [ + { + "title": "东湖区", + "id": "360102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西湖区", + "id": "360103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青云谱区", + "id": "360104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青山湖区", + "id": "360111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新建区", + "id": "360112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红谷滩区", + "id": "360113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南昌县", + "id": "360121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安义县", + "id": "360123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "进贤县", + "id": "360124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "景德镇市", + "id": "360200", + "children": [ + { + "title": "昌江区", + "id": "360202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "珠山区", + "id": "360203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浮梁县", + "id": "360222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐平市", + "id": "360281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "萍乡市", + "id": "360300", + "children": [ + { + "title": "安源区", + "id": "360302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘东区", + "id": "360313", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莲花县", + "id": "360321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上栗县", + "id": "360322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芦溪县", + "id": "360323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "九江市", + "id": "360400", + "children": [ + { + "title": "濂溪区", + "id": "360402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浔阳区", + "id": "360403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柴桑区", + "id": "360404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武宁县", + "id": "360423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "修水县", + "id": "360424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永修县", + "id": "360425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德安县", + "id": "360426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "都昌县", + "id": "360428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖口县", + "id": "360429", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彭泽县", + "id": "360430", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瑞昌市", + "id": "360481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "共青城市", + "id": "360482", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庐山市", + "id": "360483", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新余市", + "id": "360500", + "children": [ + { + "title": "渝水区", + "id": "360502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "分宜县", + "id": "360521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹰潭市", + "id": "360600", + "children": [ + { + "title": "月湖区", + "id": "360602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "余江区", + "id": "360603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贵溪市", + "id": "360681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赣州市", + "id": "360700", + "children": [ + { + "title": "章贡区", + "id": "360702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南康区", + "id": "360703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赣县区", + "id": "360704", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "信丰县", + "id": "360722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大余县", + "id": "360723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上犹县", + "id": "360724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇义县", + "id": "360725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安远县", + "id": "360726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定南县", + "id": "360728", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "全南县", + "id": "360729", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁都县", + "id": "360730", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "于都县", + "id": "360731", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴国县", + "id": "360732", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "会昌县", + "id": "360733", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "寻乌县", + "id": "360734", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石城县", + "id": "360735", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瑞金市", + "id": "360781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙南市", + "id": "360783", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉安市", + "id": "360800", + "children": [ + { + "title": "吉州区", + "id": "360802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青原区", + "id": "360803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉安县", + "id": "360821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉水县", + "id": "360822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "峡江县", + "id": "360823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新干县", + "id": "360824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永丰县", + "id": "360825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰和县", + "id": "360826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "遂川县", + "id": "360827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万安县", + "id": "360828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安福县", + "id": "360829", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永新县", + "id": "360830", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "井冈山市", + "id": "360881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜春市", + "id": "360900", + "children": [ + { + "title": "袁州区", + "id": "360902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奉新县", + "id": "360921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万载县", + "id": "360922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上高县", + "id": "360923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜丰县", + "id": "360924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "靖安县", + "id": "360925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铜鼓县", + "id": "360926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰城市", + "id": "360981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "樟树市", + "id": "360982", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高安市", + "id": "360983", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "360901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "抚州市", + "id": "361000", + "children": [ + { + "title": "临川区", + "id": "361002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东乡区", + "id": "361003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南城县", + "id": "361021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黎川县", + "id": "361022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南丰县", + "id": "361023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇仁县", + "id": "361024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐安县", + "id": "361025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜黄县", + "id": "361026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金溪县", + "id": "361027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "资溪县", + "id": "361028", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广昌县", + "id": "361030", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "361001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上饶市", + "id": "361100", + "children": [ + { + "title": "信州区", + "id": "361102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广丰区", + "id": "361103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广信区", + "id": "361104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉山县", + "id": "361123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铅山县", + "id": "361124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "横峰县", + "id": "361125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "弋阳县", + "id": "361126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "余干县", + "id": "361127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄱阳县", + "id": "361128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万年县", + "id": "361129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "婺源县", + "id": "361130", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德兴市", + "id": "361181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "361101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山东省", + "id": "370000", + "children": [ + { + "title": "济南市", + "id": "370100", + "children": [ + { + "title": "历下区", + "id": "370102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市中区", + "id": "370103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "槐荫区", + "id": "370104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天桥区", + "id": "370105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "历城区", + "id": "370112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长清区", + "id": "370113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "章丘区", + "id": "370114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "济阳区", + "id": "370115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莱芜区", + "id": "370116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "钢城区", + "id": "370117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平阴县", + "id": "370124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "商河县", + "id": "370126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "济南高新技术产业开发区", + "id": "370171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青岛市", + "id": "370200", + "children": [ + { + "title": "市南区", + "id": "370202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市北区", + "id": "370203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄岛区", + "id": "370211", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崂山区", + "id": "370212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "李沧区", + "id": "370213", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城阳区", + "id": "370214", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "即墨区", + "id": "370215", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "胶州市", + "id": "370281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平度市", + "id": "370283", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莱西市", + "id": "370285", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青岛高新技术产业开发区", + "id": "370271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淄博市", + "id": "370300", + "children": [ + { + "title": "淄川区", + "id": "370302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张店区", + "id": "370303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博山区", + "id": "370304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临淄区", + "id": "370305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "周村区", + "id": "370306", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桓台县", + "id": "370321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高青县", + "id": "370322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沂源县", + "id": "370323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "枣庄市", + "id": "370400", + "children": [ + { + "title": "市中区", + "id": "370402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "薛城区", + "id": "370403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "峄城区", + "id": "370404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "台儿庄区", + "id": "370405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山亭区", + "id": "370406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滕州市", + "id": "370481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东营市", + "id": "370500", + "children": [ + { + "title": "东营区", + "id": "370502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河口区", + "id": "370503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "垦利区", + "id": "370505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "利津县", + "id": "370522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广饶县", + "id": "370523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东营经济技术开发区", + "id": "370571", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东营港经济开发区", + "id": "370572", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "烟台市", + "id": "370600", + "children": [ + { + "title": "芝罘区", + "id": "370602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福山区", + "id": "370611", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "牟平区", + "id": "370612", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莱山区", + "id": "370613", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蓬莱区", + "id": "370614", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙口市", + "id": "370681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莱阳市", + "id": "370682", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莱州市", + "id": "370683", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "招远市", + "id": "370685", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "栖霞市", + "id": "370686", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海阳市", + "id": "370687", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "烟台高新技术产业开发区", + "id": "370671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "烟台经济技术开发区", + "id": "370672", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潍坊市", + "id": "370700", + "children": [ + { + "title": "潍城区", + "id": "370702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "寒亭区", + "id": "370703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "坊子区", + "id": "370704", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奎文区", + "id": "370705", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临朐县", + "id": "370724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌乐县", + "id": "370725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青州市", + "id": "370781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "诸城市", + "id": "370782", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "寿光市", + "id": "370783", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安丘市", + "id": "370784", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高密市", + "id": "370785", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌邑市", + "id": "370786", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潍坊滨海经济技术开发区", + "id": "370772", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "济宁市", + "id": "370800", + "children": [ + { + "title": "任城区", + "id": "370811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兖州区", + "id": "370812", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "微山县", + "id": "370826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鱼台县", + "id": "370827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金乡县", + "id": "370828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉祥县", + "id": "370829", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汶上县", + "id": "370830", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泗水县", + "id": "370831", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梁山县", + "id": "370832", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲阜市", + "id": "370881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邹城市", + "id": "370883", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "济宁高新技术产业开发区", + "id": "370871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泰安市", + "id": "370900", + "children": [ + { + "title": "泰山区", + "id": "370902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岱岳区", + "id": "370911", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁阳县", + "id": "370921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东平县", + "id": "370923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新泰市", + "id": "370982", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肥城市", + "id": "370983", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "370901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威海市", + "id": "371000", + "children": [ + { + "title": "环翠区", + "id": "371002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文登区", + "id": "371003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荣成市", + "id": "371082", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乳山市", + "id": "371083", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "371001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威海火炬高技术产业开发区", + "id": "371071", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威海经济技术开发区", + "id": "371072", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威海临港经济技术开发区", + "id": "371073", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "日照市", + "id": "371100", + "children": [ + { + "title": "东港区", + "id": "371102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岚山区", + "id": "371103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五莲县", + "id": "371121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莒县", + "id": "371122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "371101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "日照经济技术开发区", + "id": "371171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临沂市", + "id": "371300", + "children": [ + { + "title": "兰山区", + "id": "371302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗庄区", + "id": "371311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河东区", + "id": "371312", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沂南县", + "id": "371321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郯城县", + "id": "371322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沂水县", + "id": "371323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兰陵县", + "id": "371324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "费县", + "id": "371325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平邑县", + "id": "371326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莒南县", + "id": "371327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒙阴县", + "id": "371328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临沭县", + "id": "371329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "371301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临沂高新技术产业开发区", + "id": "371371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德州市", + "id": "371400", + "children": [ + { + "title": "德城区", + "id": "371402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陵城区", + "id": "371403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁津县", + "id": "371422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庆云县", + "id": "371423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临邑县", + "id": "371424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "齐河县", + "id": "371425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平原县", + "id": "371426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "夏津县", + "id": "371427", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武城县", + "id": "371428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐陵市", + "id": "371481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "禹城市", + "id": "371482", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "371401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德州经济技术开发区", + "id": "371471", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德州运河经济开发区", + "id": "371472", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "聊城市", + "id": "371500", + "children": [ + { + "title": "东昌府区", + "id": "371502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "茌平区", + "id": "371503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳谷县", + "id": "371521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莘县", + "id": "371522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东阿县", + "id": "371524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "冠县", + "id": "371525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高唐县", + "id": "371526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临清市", + "id": "371581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "371501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滨州市", + "id": "371600", + "children": [ + { + "title": "滨城区", + "id": "371602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沾化区", + "id": "371603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠民县", + "id": "371621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳信县", + "id": "371622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "无棣县", + "id": "371623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博兴县", + "id": "371625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邹平市", + "id": "371681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "371601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "菏泽市", + "id": "371700", + "children": [ + { + "title": "牡丹区", + "id": "371702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定陶区", + "id": "371703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曹县", + "id": "371721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "单县", + "id": "371722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "成武县", + "id": "371723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巨野县", + "id": "371724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郓城县", + "id": "371725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄄城县", + "id": "371726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东明县", + "id": "371728", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "371701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "菏泽经济技术开发区", + "id": "371771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "菏泽高新技术开发区", + "id": "371772", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南省", + "id": "410000", + "children": [ + { + "title": "郑州市", + "id": "410100", + "children": [ + { + "title": "中原区", + "id": "410102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "二七区", + "id": "410103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "管城回族区", + "id": "410104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金水区", + "id": "410105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上街区", + "id": "410106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠济区", + "id": "410108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中牟县", + "id": "410122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巩义市", + "id": "410181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荥阳市", + "id": "410182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新密市", + "id": "410183", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新郑市", + "id": "410184", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "登封市", + "id": "410185", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郑州经济技术开发区", + "id": "410171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郑州高新技术产业开发区", + "id": "410172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郑州航空港经济综合实验区", + "id": "410173", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开封市", + "id": "410200", + "children": [ + { + "title": "龙亭区", + "id": "410202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "顺河回族区", + "id": "410203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鼓楼区", + "id": "410204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "禹王台区", + "id": "410205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祥符区", + "id": "410212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杞县", + "id": "410221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通许县", + "id": "410222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尉氏县", + "id": "410223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兰考县", + "id": "410225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛阳市", + "id": "410300", + "children": [ + { + "title": "老城区", + "id": "410302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西工区", + "id": "410303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瀍河回族区", + "id": "410304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涧西区", + "id": "410305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉利区", + "id": "410306", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛龙区", + "id": "410311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孟津县", + "id": "410322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新安县", + "id": "410323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "栾川县", + "id": "410324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嵩县", + "id": "410325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汝阳县", + "id": "410326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜阳县", + "id": "410327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛宁县", + "id": "410328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伊川县", + "id": "410329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "偃师市", + "id": "410381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "偃师区", + "id": "410307", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孟津区", + "id": "410308", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛阳高新技术产业开发区", + "id": "410371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平顶山市", + "id": "410400", + "children": [ + { + "title": "新华区", + "id": "410402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卫东区", + "id": "410403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石龙区", + "id": "410404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湛河区", + "id": "410411", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝丰县", + "id": "410421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "叶县", + "id": "410422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鲁山县", + "id": "410423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郏县", + "id": "410425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "舞钢市", + "id": "410481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汝州市", + "id": "410482", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平顶山高新技术产业开发区", + "id": "410471", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平顶山市城乡一体化示范区", + "id": "410472", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安阳市", + "id": "410500", + "children": [ + { + "title": "文峰区", + "id": "410502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北关区", + "id": "410503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "殷都区", + "id": "410505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙安区", + "id": "410506", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安阳县", + "id": "410522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汤阴县", + "id": "410523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "滑县", + "id": "410526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "内黄县", + "id": "410527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "林州市", + "id": "410581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安阳高新技术产业开发区", + "id": "410571", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹤壁市", + "id": "410600", + "children": [ + { + "title": "鹤山区", + "id": "410602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山城区", + "id": "410603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淇滨区", + "id": "410611", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浚县", + "id": "410621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淇县", + "id": "410622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹤壁经济技术开发区", + "id": "410671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新乡市", + "id": "410700", + "children": [ + { + "title": "红旗区", + "id": "410702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卫滨区", + "id": "410703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤泉区", + "id": "410704", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "牧野区", + "id": "410711", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新乡县", + "id": "410721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "获嘉县", + "id": "410724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "原阳县", + "id": "410725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "延津县", + "id": "410726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "封丘县", + "id": "410727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卫辉市", + "id": "410781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辉县市", + "id": "410782", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长垣市", + "id": "410783", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新乡高新技术产业开发区", + "id": "410771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新乡经济技术开发区", + "id": "410772", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新乡市平原城乡一体化示范区", + "id": "410773", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "焦作市", + "id": "410800", + "children": [ + { + "title": "解放区", + "id": "410802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中站区", + "id": "410803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "马村区", + "id": "410804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山阳区", + "id": "410811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "修武县", + "id": "410821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博爱县", + "id": "410822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武陟县", + "id": "410823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "温县", + "id": "410825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沁阳市", + "id": "410882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孟州市", + "id": "410883", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "焦作城乡一体化示范区", + "id": "410871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "濮阳市", + "id": "410900", + "children": [ + { + "title": "华龙区", + "id": "410902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清丰县", + "id": "410922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南乐县", + "id": "410923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "范县", + "id": "410926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "台前县", + "id": "410927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "濮阳县", + "id": "410928", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "410901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南濮阳工业园区", + "id": "410971", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "濮阳经济技术开发区", + "id": "410972", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "许昌市", + "id": "411000", + "children": [ + { + "title": "魏都区", + "id": "411002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建安区", + "id": "411003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄢陵县", + "id": "411024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "襄城县", + "id": "411025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "禹州市", + "id": "411081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长葛市", + "id": "411082", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "许昌经济技术开发区", + "id": "411071", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "漯河市", + "id": "411100", + "children": [ + { + "title": "源汇区", + "id": "411102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郾城区", + "id": "411103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "召陵区", + "id": "411104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "舞阳县", + "id": "411121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临颍县", + "id": "411122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "漯河经济技术开发区", + "id": "411171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三门峡市", + "id": "411200", + "children": [ + { + "title": "湖滨区", + "id": "411202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陕州区", + "id": "411203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渑池县", + "id": "411221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卢氏县", + "id": "411224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "义马市", + "id": "411281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵宝市", + "id": "411282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南三门峡经济开发区", + "id": "411271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南阳市", + "id": "411300", + "children": [ + { + "title": "宛城区", + "id": "411302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卧龙区", + "id": "411303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南召县", + "id": "411321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "方城县", + "id": "411322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西峡县", + "id": "411323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇平县", + "id": "411324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "内乡县", + "id": "411325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淅川县", + "id": "411326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "社旗县", + "id": "411327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "唐河县", + "id": "411328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新野县", + "id": "411329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桐柏县", + "id": "411330", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邓州市", + "id": "411381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南阳高新技术产业开发区", + "id": "411371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南阳市城乡一体化示范区", + "id": "411372", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "商丘市", + "id": "411400", + "children": [ + { + "title": "梁园区", + "id": "411402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "睢阳区", + "id": "411403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "民权县", + "id": "411421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "睢县", + "id": "411422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁陵县", + "id": "411423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柘城县", + "id": "411424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "虞城县", + "id": "411425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "夏邑县", + "id": "411426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永城市", + "id": "411481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "豫东综合物流产业聚集区", + "id": "411471", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南商丘经济开发区", + "id": "411472", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "信阳市", + "id": "411500", + "children": [ + { + "title": "浉河区", + "id": "411502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平桥区", + "id": "411503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗山县", + "id": "411521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "光山县", + "id": "411522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新县", + "id": "411523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "商城县", + "id": "411524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "固始县", + "id": "411525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潢川县", + "id": "411526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮滨县", + "id": "411527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "息县", + "id": "411528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "信阳高新技术产业开发区", + "id": "411571", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "周口市", + "id": "411600", + "children": [ + { + "title": "川汇区", + "id": "411602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淮阳区", + "id": "411603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扶沟县", + "id": "411621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西华县", + "id": "411622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "商水县", + "id": "411623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沈丘县", + "id": "411624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郸城县", + "id": "411625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太康县", + "id": "411627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹿邑县", + "id": "411628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "项城市", + "id": "411681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南周口经济开发区", + "id": "411671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "驻马店市", + "id": "411700", + "children": [ + { + "title": "驿城区", + "id": "411702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西平县", + "id": "411721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上蔡县", + "id": "411722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平舆县", + "id": "411723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "正阳县", + "id": "411724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "确山县", + "id": "411725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泌阳县", + "id": "411726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汝南县", + "id": "411727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "遂平县", + "id": "411728", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新蔡县", + "id": "411729", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "411701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南驻马店经济开发区", + "id": "411771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南省-省直辖县级行政区划", + "id": "419000", + "children": [ + { + "title": "济源市", + "id": "419001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖北省", + "id": "420000", + "children": [ + { + "title": "武汉市", + "id": "420100", + "children": [ + { + "title": "江岸区", + "id": "420102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江汉区", + "id": "420103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "硚口区", + "id": "420104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汉阳区", + "id": "420105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武昌区", + "id": "420106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青山区", + "id": "420107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洪山区", + "id": "420111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东西湖区", + "id": "420112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汉南区", + "id": "420113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蔡甸区", + "id": "420114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江夏区", + "id": "420115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄陂区", + "id": "420116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新洲区", + "id": "420117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄石市", + "id": "420200", + "children": [ + { + "title": "黄石港区", + "id": "420202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西塞山区", + "id": "420203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "下陆区", + "id": "420204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁山区", + "id": "420205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳新县", + "id": "420222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大冶市", + "id": "420281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "十堰市", + "id": "420300", + "children": [ + { + "title": "茅箭区", + "id": "420302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张湾区", + "id": "420303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郧阳区", + "id": "420304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郧西县", + "id": "420322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "竹山县", + "id": "420323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "竹溪县", + "id": "420324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "房县", + "id": "420325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹江口市", + "id": "420381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜昌市", + "id": "420500", + "children": [ + { + "title": "西陵区", + "id": "420502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伍家岗区", + "id": "420503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "点军区", + "id": "420504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "猇亭区", + "id": "420505", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "夷陵区", + "id": "420506", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "远安县", + "id": "420525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴山县", + "id": "420526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秭归县", + "id": "420527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长阳土家族自治县", + "id": "420528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五峰土家族自治县", + "id": "420529", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜都市", + "id": "420581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "当阳市", + "id": "420582", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "枝江市", + "id": "420583", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "襄阳市", + "id": "420600", + "children": [ + { + "title": "襄城区", + "id": "420602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "樊城区", + "id": "420606", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "襄州区", + "id": "420607", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南漳县", + "id": "420624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "谷城县", + "id": "420625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保康县", + "id": "420626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "老河口市", + "id": "420682", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "枣阳市", + "id": "420683", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜城市", + "id": "420684", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄂州市", + "id": "420700", + "children": [ + { + "title": "梁子湖区", + "id": "420702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华容区", + "id": "420703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄂城区", + "id": "420704", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荆门市", + "id": "420800", + "children": [ + { + "title": "东宝区", + "id": "420802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "掇刀区", + "id": "420804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙洋县", + "id": "420822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "钟祥市", + "id": "420881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "京山市", + "id": "420882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孝感市", + "id": "420900", + "children": [ + { + "title": "孝南区", + "id": "420902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孝昌县", + "id": "420921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大悟县", + "id": "420922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云梦县", + "id": "420923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "应城市", + "id": "420981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安陆市", + "id": "420982", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汉川市", + "id": "420984", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "420901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荆州市", + "id": "421000", + "children": [ + { + "title": "沙市区", + "id": "421002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荆州区", + "id": "421003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "公安县", + "id": "421022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江陵县", + "id": "421024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石首市", + "id": "421081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洪湖市", + "id": "421083", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松滋市", + "id": "421087", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "监利市", + "id": "421088", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "421001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荆州经济技术开发区", + "id": "421071", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄冈市", + "id": "421100", + "children": [ + { + "title": "黄州区", + "id": "421102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "团风县", + "id": "421121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红安县", + "id": "421122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗田县", + "id": "421123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "英山县", + "id": "421124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浠水县", + "id": "421125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蕲春县", + "id": "421126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄梅县", + "id": "421127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麻城市", + "id": "421181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武穴市", + "id": "421182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "421101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙感湖管理区", + "id": "421171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "咸宁市", + "id": "421200", + "children": [ + { + "title": "咸安区", + "id": "421202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉鱼县", + "id": "421221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通城县", + "id": "421222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇阳县", + "id": "421223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通山县", + "id": "421224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赤壁市", + "id": "421281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "421201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "随州市", + "id": "421300", + "children": [ + { + "title": "曾都区", + "id": "421303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "随县", + "id": "421321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广水市", + "id": "421381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "421301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "恩施土家族苗族自治州", + "id": "422800", + "children": [ + { + "title": "恩施市", + "id": "422801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "利川市", + "id": "422802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建始县", + "id": "422822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴东县", + "id": "422823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宣恩县", + "id": "422825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "咸丰县", + "id": "422826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "来凤县", + "id": "422827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹤峰县", + "id": "422828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖北省-自治区直辖县级行政区划", + "id": "429000", + "children": [ + { + "title": "仙桃市", + "id": "429004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潜江市", + "id": "429005", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天门市", + "id": "429006", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "神农架林区", + "id": "429021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖南省", + "id": "430000", + "children": [ + { + "title": "长沙市", + "id": "430100", + "children": [ + { + "title": "芙蓉区", + "id": "430102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天心区", + "id": "430103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳麓区", + "id": "430104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开福区", + "id": "430105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雨花区", + "id": "430111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "望城区", + "id": "430112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长沙县", + "id": "430121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浏阳市", + "id": "430181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁乡市", + "id": "430182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "株洲市", + "id": "430200", + "children": [ + { + "title": "荷塘区", + "id": "430202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芦淞区", + "id": "430203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石峰区", + "id": "430204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天元区", + "id": "430211", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渌口区", + "id": "430212", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "攸县", + "id": "430223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "茶陵县", + "id": "430224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "炎陵县", + "id": "430225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "醴陵市", + "id": "430281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云龙示范区", + "id": "430271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘潭市", + "id": "430300", + "children": [ + { + "title": "雨湖区", + "id": "430302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳塘区", + "id": "430304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘潭县", + "id": "430321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘乡市", + "id": "430381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "韶山市", + "id": "430382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖南湘潭高新技术产业园区", + "id": "430371", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘潭昭山示范区", + "id": "430372", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘潭九华示范区", + "id": "430373", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡阳市", + "id": "430400", + "children": [ + { + "title": "珠晖区", + "id": "430405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雁峰区", + "id": "430406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石鼓区", + "id": "430407", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒸湘区", + "id": "430408", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南岳区", + "id": "430412", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡阳县", + "id": "430421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡南县", + "id": "430422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡山县", + "id": "430423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡东县", + "id": "430424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祁东县", + "id": "430426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "耒阳市", + "id": "430481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "常宁市", + "id": "430482", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "衡阳综合保税区", + "id": "430471", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖南衡阳高新技术产业园区", + "id": "430472", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖南衡阳松木经济开发区", + "id": "430473", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邵阳市", + "id": "430500", + "children": [ + { + "title": "双清区", + "id": "430502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大祥区", + "id": "430503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北塔区", + "id": "430511", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新邵县", + "id": "430522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邵阳县", + "id": "430523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆回县", + "id": "430524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洞口县", + "id": "430525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥宁县", + "id": "430527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新宁县", + "id": "430528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城步苗族自治县", + "id": "430529", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武冈市", + "id": "430581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邵东市", + "id": "430582", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳阳市", + "id": "430600", + "children": [ + { + "title": "岳阳楼区", + "id": "430602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云溪区", + "id": "430603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "君山区", + "id": "430611", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳阳县", + "id": "430621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华容县", + "id": "430623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘阴县", + "id": "430624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平江县", + "id": "430626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汨罗市", + "id": "430681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临湘市", + "id": "430682", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳阳市屈原管理区", + "id": "430671", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "常德市", + "id": "430700", + "children": [ + { + "title": "武陵区", + "id": "430702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鼎城区", + "id": "430703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安乡县", + "id": "430721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汉寿县", + "id": "430722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "澧县", + "id": "430723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临澧县", + "id": "430724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桃源县", + "id": "430725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石门县", + "id": "430726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "津市市", + "id": "430781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "常德市西洞庭管理区", + "id": "430771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张家界市", + "id": "430800", + "children": [ + { + "title": "永定区", + "id": "430802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武陵源区", + "id": "430811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "慈利县", + "id": "430821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桑植县", + "id": "430822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "益阳市", + "id": "430900", + "children": [ + { + "title": "资阳区", + "id": "430902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赫山区", + "id": "430903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南县", + "id": "430921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桃江县", + "id": "430922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安化县", + "id": "430923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沅江市", + "id": "430981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "430901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "益阳市大通湖管理区", + "id": "430971", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湖南益阳高新技术产业园区", + "id": "430972", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郴州市", + "id": "431000", + "children": [ + { + "title": "北湖区", + "id": "431002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苏仙区", + "id": "431003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桂阳县", + "id": "431021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜章县", + "id": "431022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永兴县", + "id": "431023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉禾县", + "id": "431024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临武县", + "id": "431025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汝城县", + "id": "431026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桂东县", + "id": "431027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安仁县", + "id": "431028", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "资兴市", + "id": "431081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "431001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永州市", + "id": "431100", + "children": [ + { + "title": "零陵区", + "id": "431102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "冷水滩区", + "id": "431103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祁阳县", + "id": "431121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东安县", + "id": "431122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双牌县", + "id": "431123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "道县", + "id": "431124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江永县", + "id": "431125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁远县", + "id": "431126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蓝山县", + "id": "431127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新田县", + "id": "431128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江华瑶族自治县", + "id": "431129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "431101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永州经济技术开发区", + "id": "431171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永州市回龙圩管理区", + "id": "431173", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祁阳市", + "id": "431181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀化市", + "id": "431200", + "children": [ + { + "title": "鹤城区", + "id": "431202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中方县", + "id": "431221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沅陵县", + "id": "431222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "辰溪县", + "id": "431223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "溆浦县", + "id": "431224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "会同县", + "id": "431225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麻阳苗族自治县", + "id": "431226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新晃侗族自治县", + "id": "431227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芷江侗族自治县", + "id": "431228", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "靖州苗族侗族自治县", + "id": "431229", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通道侗族自治县", + "id": "431230", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洪江市", + "id": "431281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "431201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀化市洪江管理区", + "id": "431271", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "娄底市", + "id": "431300", + "children": [ + { + "title": "娄星区", + "id": "431302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双峰县", + "id": "431321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新化县", + "id": "431322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "冷水江市", + "id": "431381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涟源市", + "id": "431382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "431301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湘西土家族苗族自治州", + "id": "433100", + "children": [ + { + "title": "吉首市", + "id": "433101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泸溪县", + "id": "433122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤凰县", + "id": "433123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "花垣县", + "id": "433124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保靖县", + "id": "433125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "古丈县", + "id": "433126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永顺县", + "id": "433127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙山县", + "id": "433130", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广东省", + "id": "440000", + "children": [ + { + "title": "广州市", + "id": "440100", + "children": [ + { + "title": "荔湾区", + "id": "440103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "越秀区", + "id": "440104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海珠区", + "id": "440105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天河区", + "id": "440106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白云区", + "id": "440111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄埔区", + "id": "440112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "番禺区", + "id": "440113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "花都区", + "id": "440114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南沙区", + "id": "440115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "从化区", + "id": "440117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "增城区", + "id": "440118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "韶关市", + "id": "440200", + "children": [ + { + "title": "武江区", + "id": "440203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浈江区", + "id": "440204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲江区", + "id": "440205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "始兴县", + "id": "440222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仁化县", + "id": "440224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "翁源县", + "id": "440229", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乳源瑶族自治县", + "id": "440232", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新丰县", + "id": "440233", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐昌市", + "id": "440281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南雄市", + "id": "440282", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "深圳市", + "id": "440300", + "children": [ + { + "title": "罗湖区", + "id": "440303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福田区", + "id": "440304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南山区", + "id": "440305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝安区", + "id": "440306", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙岗区", + "id": "440307", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐田区", + "id": "440308", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙华区", + "id": "440309", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "坪山区", + "id": "440310", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "光明区", + "id": "440311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "珠海市", + "id": "440400", + "children": [ + { + "title": "香洲区", + "id": "440402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "斗门区", + "id": "440403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金湾区", + "id": "440404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汕头市", + "id": "440500", + "children": [ + { + "title": "龙湖区", + "id": "440507", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金平区", + "id": "440511", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "濠江区", + "id": "440512", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潮阳区", + "id": "440513", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潮南区", + "id": "440514", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "澄海区", + "id": "440515", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南澳县", + "id": "440523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "佛山市", + "id": "440600", + "children": [ + { + "title": "禅城区", + "id": "440604", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南海区", + "id": "440605", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "顺德区", + "id": "440606", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三水区", + "id": "440607", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高明区", + "id": "440608", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江门市", + "id": "440700", + "children": [ + { + "title": "蓬江区", + "id": "440703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江海区", + "id": "440704", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新会区", + "id": "440705", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "台山市", + "id": "440781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开平市", + "id": "440783", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹤山市", + "id": "440784", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "恩平市", + "id": "440785", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湛江市", + "id": "440800", + "children": [ + { + "title": "赤坎区", + "id": "440802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霞山区", + "id": "440803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "坡头区", + "id": "440804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麻章区", + "id": "440811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "遂溪县", + "id": "440823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "徐闻县", + "id": "440825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "廉江市", + "id": "440881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雷州市", + "id": "440882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吴川市", + "id": "440883", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "茂名市", + "id": "440900", + "children": [ + { + "title": "茂南区", + "id": "440902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "电白区", + "id": "440904", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高州市", + "id": "440981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "化州市", + "id": "440982", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "信宜市", + "id": "440983", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "440901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肇庆市", + "id": "441200", + "children": [ + { + "title": "端州区", + "id": "441202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鼎湖区", + "id": "441203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高要区", + "id": "441204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广宁县", + "id": "441223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怀集县", + "id": "441224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "封开县", + "id": "441225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德庆县", + "id": "441226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "四会市", + "id": "441284", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "441201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠州市", + "id": "441300", + "children": [ + { + "title": "惠城区", + "id": "441302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠阳区", + "id": "441303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博罗县", + "id": "441322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠东县", + "id": "441323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙门县", + "id": "441324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "441301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梅州市", + "id": "441400", + "children": [ + { + "title": "梅江区", + "id": "441402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梅县区", + "id": "441403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大埔县", + "id": "441422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰顺县", + "id": "441423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五华县", + "id": "441424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平远县", + "id": "441426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蕉岭县", + "id": "441427", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴宁市", + "id": "441481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "441401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汕尾市", + "id": "441500", + "children": [ + { + "title": "城区", + "id": "441502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海丰县", + "id": "441521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陆河县", + "id": "441523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陆丰市", + "id": "441581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "441501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河源市", + "id": "441600", + "children": [ + { + "title": "源城区", + "id": "441602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "紫金县", + "id": "441621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙川县", + "id": "441622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连平县", + "id": "441623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和平县", + "id": "441624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东源县", + "id": "441625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "441601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳江市", + "id": "441700", + "children": [ + { + "title": "江城区", + "id": "441702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳东区", + "id": "441704", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳西县", + "id": "441721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳春市", + "id": "441781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "441701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清远市", + "id": "441800", + "children": [ + { + "title": "清城区", + "id": "441802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清新区", + "id": "441803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "佛冈县", + "id": "441821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳山县", + "id": "441823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连山壮族瑶族自治县", + "id": "441825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连南瑶族自治县", + "id": "441826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "英德市", + "id": "441881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "连州市", + "id": "441882", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "441801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东莞市", + "id": "441900", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中山市", + "id": "442000", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潮州市", + "id": "445100", + "children": [ + { + "title": "湘桥区", + "id": "445102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潮安区", + "id": "445103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "饶平县", + "id": "445122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "445101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "揭阳市", + "id": "445200", + "children": [ + { + "title": "榕城区", + "id": "445202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "揭东区", + "id": "445203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "揭西县", + "id": "445222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠来县", + "id": "445224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普宁市", + "id": "445281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "445201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云浮市", + "id": "445300", + "children": [ + { + "title": "云城区", + "id": "445302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云安区", + "id": "445303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新兴县", + "id": "445321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郁南县", + "id": "445322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗定市", + "id": "445381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "445301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广西壮族自治区", + "id": "450000", + "children": [ + { + "title": "南宁市", + "id": "450100", + "children": [ + { + "title": "兴宁区", + "id": "450102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青秀区", + "id": "450103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江南区", + "id": "450105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西乡塘区", + "id": "450107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "良庆区", + "id": "450108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邕宁区", + "id": "450109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武鸣区", + "id": "450110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆安县", + "id": "450123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "马山县", + "id": "450124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上林县", + "id": "450125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宾阳县", + "id": "450126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "横县", + "id": "450127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "横州市", + "id": "450181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柳州市", + "id": "450200", + "children": [ + { + "title": "城中区", + "id": "450202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鱼峰区", + "id": "450203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柳南区", + "id": "450204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柳北区", + "id": "450205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柳江区", + "id": "450206", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柳城县", + "id": "450222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹿寨县", + "id": "450223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "融安县", + "id": "450224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "融水苗族自治县", + "id": "450225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三江侗族自治县", + "id": "450226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桂林市", + "id": "450300", + "children": [ + { + "title": "秀峰区", + "id": "450302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "叠彩区", + "id": "450303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "象山区", + "id": "450304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "七星区", + "id": "450305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雁山区", + "id": "450311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临桂区", + "id": "450312", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阳朔县", + "id": "450321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵川县", + "id": "450323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "全州县", + "id": "450324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴安县", + "id": "450325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永福县", + "id": "450326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灌阳县", + "id": "450327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙胜各族自治县", + "id": "450328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "资源县", + "id": "450329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平乐县", + "id": "450330", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "恭城瑶族自治县", + "id": "450332", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荔浦市", + "id": "450381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梧州市", + "id": "450400", + "children": [ + { + "title": "万秀区", + "id": "450403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长洲区", + "id": "450405", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙圩区", + "id": "450406", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苍梧县", + "id": "450421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "藤县", + "id": "450422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒙山县", + "id": "450423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岑溪市", + "id": "450481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北海市", + "id": "450500", + "children": [ + { + "title": "海城区", + "id": "450502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "银海区", + "id": "450503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁山港区", + "id": "450512", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合浦县", + "id": "450521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "防城港市", + "id": "450600", + "children": [ + { + "title": "港口区", + "id": "450602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "防城区", + "id": "450603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "上思县", + "id": "450621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东兴市", + "id": "450681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "钦州市", + "id": "450700", + "children": [ + { + "title": "钦南区", + "id": "450702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "钦北区", + "id": "450703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵山县", + "id": "450721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浦北县", + "id": "450722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贵港市", + "id": "450800", + "children": [ + { + "title": "港北区", + "id": "450802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "港南区", + "id": "450803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "覃塘区", + "id": "450804", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平南县", + "id": "450821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桂平市", + "id": "450881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉林市", + "id": "450900", + "children": [ + { + "title": "玉州区", + "id": "450902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福绵区", + "id": "450903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "容县", + "id": "450921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陆川县", + "id": "450922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博白县", + "id": "450923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴业县", + "id": "450924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北流市", + "id": "450981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "450901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "百色市", + "id": "451000", + "children": [ + { + "title": "右江区", + "id": "451002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "田阳区", + "id": "451003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "田东县", + "id": "451022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德保县", + "id": "451024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "那坡县", + "id": "451026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凌云县", + "id": "451027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐业县", + "id": "451028", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "田林县", + "id": "451029", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西林县", + "id": "451030", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆林各族自治县", + "id": "451031", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "靖西市", + "id": "451081", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平果市", + "id": "451082", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "451001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贺州市", + "id": "451100", + "children": [ + { + "title": "八步区", + "id": "451102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平桂区", + "id": "451103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昭平县", + "id": "451121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "钟山县", + "id": "451122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富川瑶族自治县", + "id": "451123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "451101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河池市", + "id": "451200", + "children": [ + { + "title": "金城江区", + "id": "451202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜州区", + "id": "451203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南丹县", + "id": "451221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天峨县", + "id": "451222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤山县", + "id": "451223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东兰县", + "id": "451224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗城仫佬族自治县", + "id": "451225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "环江毛南族自治县", + "id": "451226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴马瑶族自治县", + "id": "451227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "都安瑶族自治县", + "id": "451228", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大化瑶族自治县", + "id": "451229", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "451201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "来宾市", + "id": "451300", + "children": [ + { + "title": "兴宾区", + "id": "451302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "忻城县", + "id": "451321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "象州县", + "id": "451322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武宣县", + "id": "451323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金秀瑶族自治县", + "id": "451324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合山市", + "id": "451381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "451301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇左市", + "id": "451400", + "children": [ + { + "title": "江州区", + "id": "451402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扶绥县", + "id": "451421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁明县", + "id": "451422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙州县", + "id": "451423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大新县", + "id": "451424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天等县", + "id": "451425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凭祥市", + "id": "451481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "451401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海南省", + "id": "460000", + "children": [ + { + "title": "海口市", + "id": "460100", + "children": [ + { + "title": "秀英区", + "id": "460105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙华区", + "id": "460106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "琼山区", + "id": "460107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "美兰区", + "id": "460108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "460101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三亚市", + "id": "460200", + "children": [ + { + "title": "海棠区", + "id": "460202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉阳区", + "id": "460203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天涯区", + "id": "460204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崖州区", + "id": "460205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "460201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三沙市", + "id": "460300", + "children": [ + { + "title": "西沙群岛", + "id": "460321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南沙群岛", + "id": "460322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中沙群岛的岛礁及其海域", + "id": "460323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "儋州市", + "id": "460400", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海南省-自治区直辖县级行政区划", + "id": "469000", + "children": [ + { + "title": "五指山市", + "id": "469001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "琼海市", + "id": "469002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文昌市", + "id": "469005", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万宁市", + "id": "469006", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东方市", + "id": "469007", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定安县", + "id": "469021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "屯昌县", + "id": "469022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "澄迈县", + "id": "469023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临高县", + "id": "469024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白沙黎族自治县", + "id": "469025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌江黎族自治县", + "id": "469026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐东黎族自治县", + "id": "469027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陵水黎族自治县", + "id": "469028", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保亭黎族苗族自治县", + "id": "469029", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "琼中黎族苗族自治县", + "id": "469030", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "重庆市", + "id": "500000", + "children": [ + { + "title": "重庆市", + "id": "5000001", + "children": [ + { + "title": "万州区", + "id": "500101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "涪陵区", + "id": "500102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渝中区", + "id": "500103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大渡口区", + "id": "500104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江北区", + "id": "500105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙坪坝区", + "id": "500106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "九龙坡区", + "id": "500107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南岸区", + "id": "500108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北碚区", + "id": "500109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "綦江区", + "id": "500110", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大足区", + "id": "500111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渝北区", + "id": "500112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴南区", + "id": "500113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黔江区", + "id": "500114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长寿区", + "id": "500115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江津区", + "id": "500116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合川区", + "id": "500117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永川区", + "id": "500118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南川区", + "id": "500119", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "璧山区", + "id": "500120", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铜梁区", + "id": "500151", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潼南区", + "id": "500152", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荣昌区", + "id": "500153", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开州区", + "id": "500154", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梁平区", + "id": "500155", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武隆区", + "id": "500156", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城口县", + "id": "500229", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丰都县", + "id": "500230", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "垫江县", + "id": "500231", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "忠县", + "id": "500233", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云阳县", + "id": "500235", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奉节县", + "id": "500236", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巫山县", + "id": "500237", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巫溪县", + "id": "500238", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石柱土家族自治县", + "id": "500240", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秀山土家族苗族自治县", + "id": "500241", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "酉阳土家族苗族自治县", + "id": "500242", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彭水苗族土家族自治县", + "id": "500243", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "四川省", + "id": "510000", + "children": [ + { + "title": "成都市", + "id": "510100", + "children": [ + { + "title": "锦江区", + "id": "510104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青羊区", + "id": "510105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金牛区", + "id": "510106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武侯区", + "id": "510107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "成华区", + "id": "510108", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙泉驿区", + "id": "510112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青白江区", + "id": "510113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新都区", + "id": "510114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "温江区", + "id": "510115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双流区", + "id": "510116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "郫都区", + "id": "510117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新津区", + "id": "510118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金堂县", + "id": "510121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大邑县", + "id": "510129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒲江县", + "id": "510131", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "都江堰市", + "id": "510181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彭州市", + "id": "510182", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邛崃市", + "id": "510183", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇州市", + "id": "510184", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "简阳市", + "id": "510185", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "自贡市", + "id": "510300", + "children": [ + { + "title": "自流井区", + "id": "510302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贡井区", + "id": "510303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大安区", + "id": "510304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沿滩区", + "id": "510311", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荣县", + "id": "510321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富顺县", + "id": "510322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "攀枝花市", + "id": "510400", + "children": [ + { + "title": "东区", + "id": "510402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西区", + "id": "510403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仁和区", + "id": "510411", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "米易县", + "id": "510421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐边县", + "id": "510422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泸州市", + "id": "510500", + "children": [ + { + "title": "江阳区", + "id": "510502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "纳溪区", + "id": "510503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙马潭区", + "id": "510504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泸县", + "id": "510521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合江县", + "id": "510522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "叙永县", + "id": "510524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "古蔺县", + "id": "510525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德阳市", + "id": "510600", + "children": [ + { + "title": "旌阳区", + "id": "510603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗江区", + "id": "510604", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中江县", + "id": "510623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广汉市", + "id": "510681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "什邡市", + "id": "510682", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绵竹市", + "id": "510683", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绵阳市", + "id": "510700", + "children": [ + { + "title": "涪城区", + "id": "510703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "游仙区", + "id": "510704", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安州区", + "id": "510705", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三台县", + "id": "510722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐亭县", + "id": "510723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梓潼县", + "id": "510725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北川羌族自治县", + "id": "510726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平武县", + "id": "510727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江油市", + "id": "510781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广元市", + "id": "510800", + "children": [ + { + "title": "利州区", + "id": "510802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昭化区", + "id": "510811", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "朝天区", + "id": "510812", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "旺苍县", + "id": "510821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青川县", + "id": "510822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "剑阁县", + "id": "510823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "苍溪县", + "id": "510824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "遂宁市", + "id": "510900", + "children": [ + { + "title": "船山区", + "id": "510903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安居区", + "id": "510904", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蓬溪县", + "id": "510921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大英县", + "id": "510923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "射洪市", + "id": "510981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "510901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "内江市", + "id": "511000", + "children": [ + { + "title": "市中区", + "id": "511002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东兴区", + "id": "511011", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威远县", + "id": "511024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "资中县", + "id": "511025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆昌市", + "id": "511083", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "内江经济开发区", + "id": "511071", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐山市", + "id": "511100", + "children": [ + { + "title": "市中区", + "id": "511102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙湾区", + "id": "511111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五通桥区", + "id": "511112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金口河区", + "id": "511113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "犍为县", + "id": "511123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "井研县", + "id": "511124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "夹江县", + "id": "511126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沐川县", + "id": "511129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "峨边彝族自治县", + "id": "511132", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "马边彝族自治县", + "id": "511133", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "峨眉山市", + "id": "511181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南充市", + "id": "511300", + "children": [ + { + "title": "顺庆区", + "id": "511302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高坪区", + "id": "511303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉陵区", + "id": "511304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南部县", + "id": "511321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "营山县", + "id": "511322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蓬安县", + "id": "511323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仪陇县", + "id": "511324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西充县", + "id": "511325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阆中市", + "id": "511381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "眉山市", + "id": "511400", + "children": [ + { + "title": "东坡区", + "id": "511402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彭山区", + "id": "511403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仁寿县", + "id": "511421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洪雅县", + "id": "511423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹棱县", + "id": "511424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青神县", + "id": "511425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜宾市", + "id": "511500", + "children": [ + { + "title": "翠屏区", + "id": "511502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南溪区", + "id": "511503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "叙州区", + "id": "511504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江安县", + "id": "511523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长宁县", + "id": "511524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高县", + "id": "511525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "珙县", + "id": "511526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "筠连县", + "id": "511527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴文县", + "id": "511528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "屏山县", + "id": "511529", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广安市", + "id": "511600", + "children": [ + { + "title": "广安区", + "id": "511602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "前锋区", + "id": "511603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳池县", + "id": "511621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武胜县", + "id": "511622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "邻水县", + "id": "511623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华蓥市", + "id": "511681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达州市", + "id": "511700", + "children": [ + { + "title": "通川区", + "id": "511702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达川区", + "id": "511703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宣汉县", + "id": "511722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开江县", + "id": "511723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大竹县", + "id": "511724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渠县", + "id": "511725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万源市", + "id": "511781", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达州经济开发区", + "id": "511771", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雅安市", + "id": "511800", + "children": [ + { + "title": "雨城区", + "id": "511802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "名山区", + "id": "511803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荥经县", + "id": "511822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汉源县", + "id": "511823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石棉县", + "id": "511824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天全县", + "id": "511825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芦山县", + "id": "511826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝兴县", + "id": "511827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴中市", + "id": "511900", + "children": [ + { + "title": "巴州区", + "id": "511902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "恩阳区", + "id": "511903", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通江县", + "id": "511921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南江县", + "id": "511922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平昌县", + "id": "511923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "511901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴中经济开发区", + "id": "511971", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "资阳市", + "id": "512000", + "children": [ + { + "title": "雁江区", + "id": "512002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安岳县", + "id": "512021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乐至县", + "id": "512022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "512001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿坝藏族羌族自治州", + "id": "513200", + "children": [ + { + "title": "马尔康市", + "id": "513201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汶川县", + "id": "513221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "理县", + "id": "513222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "茂县", + "id": "513223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松潘县", + "id": "513224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "九寨沟县", + "id": "513225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金川县", + "id": "513226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "小金县", + "id": "513227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黑水县", + "id": "513228", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "壤塘县", + "id": "513230", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿坝县", + "id": "513231", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "若尔盖县", + "id": "513232", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红原县", + "id": "513233", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘孜藏族自治州", + "id": "513300", + "children": [ + { + "title": "康定市", + "id": "513301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泸定县", + "id": "513322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹巴县", + "id": "513323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "九龙县", + "id": "513324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雅江县", + "id": "513325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "道孚县", + "id": "513326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "炉霍县", + "id": "513327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘孜县", + "id": "513328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新龙县", + "id": "513329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德格县", + "id": "513330", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白玉县", + "id": "513331", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石渠县", + "id": "513332", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "色达县", + "id": "513333", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "理塘县", + "id": "513334", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴塘县", + "id": "513335", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乡城县", + "id": "513336", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "稻城县", + "id": "513337", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "得荣县", + "id": "513338", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凉山彝族自治州", + "id": "513400", + "children": [ + { + "title": "西昌市", + "id": "513401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "木里藏族自治县", + "id": "513422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐源县", + "id": "513423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德昌县", + "id": "513424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "会理县", + "id": "513425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "会东县", + "id": "513426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁南县", + "id": "513427", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普格县", + "id": "513428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "布拖县", + "id": "513429", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金阳县", + "id": "513430", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昭觉县", + "id": "513431", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "喜德县", + "id": "513432", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "冕宁县", + "id": "513433", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "越西县", + "id": "513434", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘洛县", + "id": "513435", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "美姑县", + "id": "513436", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雷波县", + "id": "513437", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "会理市", + "id": "513402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贵州省", + "id": "520000", + "children": [ + { + "title": "贵阳市", + "id": "520100", + "children": [ + { + "title": "南明区", + "id": "520102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云岩区", + "id": "520103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "花溪区", + "id": "520111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌当区", + "id": "520112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白云区", + "id": "520113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "观山湖区", + "id": "520115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开阳县", + "id": "520121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "息烽县", + "id": "520122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "修文县", + "id": "520123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清镇市", + "id": "520181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "520101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "六盘水市", + "id": "520200", + "children": [ + { + "title": "钟山区", + "id": "520201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "六枝特区", + "id": "520203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "水城区", + "id": "520204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盘州市", + "id": "520281", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "遵义市", + "id": "520300", + "children": [ + { + "title": "红花岗区", + "id": "520302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汇川区", + "id": "520303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "播州区", + "id": "520304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桐梓县", + "id": "520322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥阳县", + "id": "520323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "正安县", + "id": "520324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "道真仡佬族苗族自治县", + "id": "520325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "务川仡佬族苗族自治县", + "id": "520326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤冈县", + "id": "520327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湄潭县", + "id": "520328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "余庆县", + "id": "520329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "习水县", + "id": "520330", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赤水市", + "id": "520381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仁怀市", + "id": "520382", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "520301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安顺市", + "id": "520400", + "children": [ + { + "title": "西秀区", + "id": "520402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平坝区", + "id": "520403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普定县", + "id": "520422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇宁布依族苗族自治县", + "id": "520423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "关岭布依族苗族自治县", + "id": "520424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "紫云苗族布依族自治县", + "id": "520425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "520401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "毕节市", + "id": "520500", + "children": [ + { + "title": "七星关区", + "id": "520502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大方县", + "id": "520521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黔西县", + "id": "520522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金沙县", + "id": "520523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "织金县", + "id": "520524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "纳雍县", + "id": "520525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威宁彝族回族苗族自治县", + "id": "520526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "赫章县", + "id": "520527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "520501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黔西市", + "id": "520581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铜仁市", + "id": "520600", + "children": [ + { + "title": "碧江区", + "id": "520602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "万山区", + "id": "520603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江口县", + "id": "520621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉屏侗族自治县", + "id": "520622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石阡县", + "id": "520623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "思南县", + "id": "520624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "印江土家族苗族自治县", + "id": "520625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德江县", + "id": "520626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沿河土家族自治县", + "id": "520627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "松桃苗族自治县", + "id": "520628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "520601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黔西南布依族苗族自治州", + "id": "522300", + "children": [ + { + "title": "兴义市", + "id": "522301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴仁市", + "id": "522302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普安县", + "id": "522323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晴隆县", + "id": "522324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贞丰县", + "id": "522325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "望谟县", + "id": "522326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "册亨县", + "id": "522327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安龙县", + "id": "522328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黔东南苗族侗族自治州", + "id": "522600", + "children": [ + { + "title": "凯里市", + "id": "522601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄平县", + "id": "522622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "施秉县", + "id": "522623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三穗县", + "id": "522624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇远县", + "id": "522625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岑巩县", + "id": "522626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天柱县", + "id": "522627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "锦屏县", + "id": "522628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "剑河县", + "id": "522629", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "台江县", + "id": "522630", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黎平县", + "id": "522631", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "榕江县", + "id": "522632", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "从江县", + "id": "522633", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雷山县", + "id": "522634", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麻江县", + "id": "522635", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹寨县", + "id": "522636", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黔南布依族苗族自治州", + "id": "522700", + "children": [ + { + "title": "都匀市", + "id": "522701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福泉市", + "id": "522702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荔波县", + "id": "522722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贵定县", + "id": "522723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瓮安县", + "id": "522725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "独山县", + "id": "522726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平塘县", + "id": "522727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗甸县", + "id": "522728", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长顺县", + "id": "522729", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙里县", + "id": "522730", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠水县", + "id": "522731", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三都水族自治县", + "id": "522732", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云南省", + "id": "530000", + "children": [ + { + "title": "昆明市", + "id": "530100", + "children": [ + { + "title": "五华区", + "id": "530102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盘龙区", + "id": "530103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "官渡区", + "id": "530111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西山区", + "id": "530112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东川区", + "id": "530113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "呈贡区", + "id": "530114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "晋宁区", + "id": "530115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富民县", + "id": "530124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜良县", + "id": "530125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石林彝族自治县", + "id": "530126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嵩明县", + "id": "530127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "禄劝彝族苗族自治县", + "id": "530128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "寻甸回族彝族自治县", + "id": "530129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安宁市", + "id": "530181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲靖市", + "id": "530300", + "children": [ + { + "title": "麒麟区", + "id": "530302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沾益区", + "id": "530303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "马龙区", + "id": "530304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陆良县", + "id": "530322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "师宗县", + "id": "530323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "罗平县", + "id": "530324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富源县", + "id": "530325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "会泽县", + "id": "530326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宣威市", + "id": "530381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉溪市", + "id": "530400", + "children": [ + { + "title": "红塔区", + "id": "530402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江川区", + "id": "530403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通海县", + "id": "530423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华宁县", + "id": "530424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "易门县", + "id": "530425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "峨山彝族自治县", + "id": "530426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新平彝族傣族自治县", + "id": "530427", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "元江哈尼族彝族傣族自治县", + "id": "530428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "澄江市", + "id": "530481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "保山市", + "id": "530500", + "children": [ + { + "title": "隆阳区", + "id": "530502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "施甸县", + "id": "530521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "龙陵县", + "id": "530523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌宁县", + "id": "530524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "腾冲市", + "id": "530581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昭通市", + "id": "530600", + "children": [ + { + "title": "昭阳区", + "id": "530602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鲁甸县", + "id": "530621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巧家县", + "id": "530622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐津县", + "id": "530623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大关县", + "id": "530624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永善县", + "id": "530625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥江县", + "id": "530626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇雄县", + "id": "530627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彝良县", + "id": "530628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "威信县", + "id": "530629", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "水富市", + "id": "530681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丽江市", + "id": "530700", + "children": [ + { + "title": "古城区", + "id": "530702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉龙纳西族自治县", + "id": "530721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永胜县", + "id": "530722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华坪县", + "id": "530723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁蒗彝族自治县", + "id": "530724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "普洱市", + "id": "530800", + "children": [ + { + "title": "思茅区", + "id": "530802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁洱哈尼族彝族自治县", + "id": "530821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "墨江哈尼族自治县", + "id": "530822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "景东彝族自治县", + "id": "530823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "景谷傣族彝族自治县", + "id": "530824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇沅彝族哈尼族拉祜族自治县", + "id": "530825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江城哈尼族彝族自治县", + "id": "530826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "孟连傣族拉祜族佤族自治县", + "id": "530827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "澜沧拉祜族自治县", + "id": "530828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西盟佤族自治县", + "id": "530829", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临沧市", + "id": "530900", + "children": [ + { + "title": "临翔区", + "id": "530902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤庆县", + "id": "530921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云县", + "id": "530922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永德县", + "id": "530923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇康县", + "id": "530924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双江拉祜族佤族布朗族傣族自治县", + "id": "530925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "耿马傣族佤族自治县", + "id": "530926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沧源佤族自治县", + "id": "530927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "530901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "楚雄彝族自治州", + "id": "532300", + "children": [ + { + "title": "楚雄市", + "id": "532301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双柏县", + "id": "532322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "牟定县", + "id": "532323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南华县", + "id": "532324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "姚安县", + "id": "532325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大姚县", + "id": "532326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永仁县", + "id": "532327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "元谋县", + "id": "532328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武定县", + "id": "532329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "禄丰县", + "id": "532331", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "禄丰市", + "id": "532302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红河哈尼族彝族自治州", + "id": "532500", + "children": [ + { + "title": "个旧市", + "id": "532501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "开远市", + "id": "532502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒙自市", + "id": "532503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "弥勒市", + "id": "532504", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "屏边苗族自治县", + "id": "532523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "建水县", + "id": "532524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石屏县", + "id": "532525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泸西县", + "id": "532527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "元阳县", + "id": "532528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红河县", + "id": "532529", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金平苗族瑶族傣族自治县", + "id": "532530", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绿春县", + "id": "532531", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河口瑶族自治县", + "id": "532532", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文山壮族苗族自治州", + "id": "532600", + "children": [ + { + "title": "文山市", + "id": "532601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "砚山县", + "id": "532622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西畴县", + "id": "532623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麻栗坡县", + "id": "532624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "马关县", + "id": "532625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丘北县", + "id": "532626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广南县", + "id": "532627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富宁县", + "id": "532628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西双版纳傣族自治州", + "id": "532800", + "children": [ + { + "title": "景洪市", + "id": "532801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "勐海县", + "id": "532822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "勐腊县", + "id": "532823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大理白族自治州", + "id": "532900", + "children": [ + { + "title": "大理市", + "id": "532901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "漾濞彝族自治县", + "id": "532922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祥云县", + "id": "532923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宾川县", + "id": "532924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "弥渡县", + "id": "532925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南涧彝族自治县", + "id": "532926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巍山彝族回族自治县", + "id": "532927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永平县", + "id": "532928", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "云龙县", + "id": "532929", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洱源县", + "id": "532930", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "剑川县", + "id": "532931", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鹤庆县", + "id": "532932", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德宏傣族景颇族自治州", + "id": "533100", + "children": [ + { + "title": "瑞丽市", + "id": "533102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芒市", + "id": "533103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "梁河县", + "id": "533122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盈江县", + "id": "533123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陇川县", + "id": "533124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "怒江傈僳族自治州", + "id": "533300", + "children": [ + { + "title": "泸水市", + "id": "533301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福贡县", + "id": "533323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贡山独龙族怒族自治县", + "id": "533324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兰坪白族普米族自治县", + "id": "533325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "迪庆藏族自治州", + "id": "533400", + "children": [ + { + "title": "香格里拉市", + "id": "533401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德钦县", + "id": "533422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "维西傈僳族自治县", + "id": "533423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西藏自治区", + "id": "540000", + "children": [ + { + "title": "拉萨市", + "id": "540100", + "children": [ + { + "title": "城关区", + "id": "540102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "堆龙德庆区", + "id": "540103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达孜区", + "id": "540104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "林周县", + "id": "540121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "当雄县", + "id": "540122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尼木县", + "id": "540123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲水县", + "id": "540124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "墨竹工卡县", + "id": "540127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "540101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "格尔木藏青工业园区", + "id": "540171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "拉萨经济技术开发区", + "id": "540172", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西藏文化旅游创意园区", + "id": "540173", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达孜工业园区", + "id": "540174", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "日喀则市", + "id": "540200", + "children": [ + { + "title": "桑珠孜区", + "id": "540202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南木林县", + "id": "540221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江孜县", + "id": "540222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定日县", + "id": "540223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "萨迦县", + "id": "540224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "拉孜县", + "id": "540225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昂仁县", + "id": "540226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "谢通门县", + "id": "540227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白朗县", + "id": "540228", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仁布县", + "id": "540229", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "康马县", + "id": "540230", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定结县", + "id": "540231", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "仲巴县", + "id": "540232", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "亚东县", + "id": "540233", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉隆县", + "id": "540234", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "聂拉木县", + "id": "540235", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "萨嘎县", + "id": "540236", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岗巴县", + "id": "540237", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌都市", + "id": "540300", + "children": [ + { + "title": "卡若区", + "id": "540302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "江达县", + "id": "540321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贡觉县", + "id": "540322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "类乌齐县", + "id": "540323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丁青县", + "id": "540324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "察雅县", + "id": "540325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "八宿县", + "id": "540326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "左贡县", + "id": "540327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "芒康县", + "id": "540328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛隆县", + "id": "540329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "边坝县", + "id": "540330", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "林芝市", + "id": "540400", + "children": [ + { + "title": "巴宜区", + "id": "540402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "工布江达县", + "id": "540421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "米林县", + "id": "540422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "墨脱县", + "id": "540423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "波密县", + "id": "540424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "察隅县", + "id": "540425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "朗县", + "id": "540426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山南市", + "id": "540500", + "children": [ + { + "title": "乃东区", + "id": "540502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扎囊县", + "id": "540521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贡嘎县", + "id": "540522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "桑日县", + "id": "540523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "琼结县", + "id": "540524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲松县", + "id": "540525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "措美县", + "id": "540526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛扎县", + "id": "540527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "加查县", + "id": "540528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆子县", + "id": "540529", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "错那县", + "id": "540530", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "浪卡子县", + "id": "540531", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "540501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "那曲市", + "id": "540600", + "children": [ + { + "title": "色尼区", + "id": "540602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉黎县", + "id": "540621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "比如县", + "id": "540622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "聂荣县", + "id": "540623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安多县", + "id": "540624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "申扎县", + "id": "540625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "索县", + "id": "540626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "班戈县", + "id": "540627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴青县", + "id": "540628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尼玛县", + "id": "540629", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双湖县", + "id": "540630", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿里地区", + "id": "542500", + "children": [ + { + "title": "普兰县", + "id": "542521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "札达县", + "id": "542522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "噶尔县", + "id": "542523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "日土县", + "id": "542524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "革吉县", + "id": "542525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "改则县", + "id": "542526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "措勤县", + "id": "542527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陕西省", + "id": "610000", + "children": [ + { + "title": "西安市", + "id": "610100", + "children": [ + { + "title": "新城区", + "id": "610102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "碑林区", + "id": "610103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莲湖区", + "id": "610104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灞桥区", + "id": "610111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "未央区", + "id": "610112", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "雁塔区", + "id": "610113", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阎良区", + "id": "610114", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临潼区", + "id": "610115", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长安区", + "id": "610116", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高陵区", + "id": "610117", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄠邑区", + "id": "610118", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蓝田县", + "id": "610122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "周至县", + "id": "610124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铜川市", + "id": "610200", + "children": [ + { + "title": "王益区", + "id": "610202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "印台区", + "id": "610203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "耀州区", + "id": "610204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜君县", + "id": "610222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宝鸡市", + "id": "610300", + "children": [ + { + "title": "渭滨区", + "id": "610302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金台区", + "id": "610303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陈仓区", + "id": "610304", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤翔县", + "id": "610322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岐山县", + "id": "610323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "扶风县", + "id": "610324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "眉县", + "id": "610326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陇县", + "id": "610327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "千阳县", + "id": "610328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麟游县", + "id": "610329", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤县", + "id": "610330", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "太白县", + "id": "610331", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "凤翔区", + "id": "610305", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "咸阳市", + "id": "610400", + "children": [ + { + "title": "秦都区", + "id": "610402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杨陵区", + "id": "610403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渭城区", + "id": "610404", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "三原县", + "id": "610422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泾阳县", + "id": "610423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乾县", + "id": "610424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "礼泉县", + "id": "610425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永寿县", + "id": "610426", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "长武县", + "id": "610428", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "旬邑县", + "id": "610429", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "淳化县", + "id": "610430", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武功县", + "id": "610431", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴平市", + "id": "610481", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彬州市", + "id": "610482", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渭南市", + "id": "610500", + "children": [ + { + "title": "临渭区", + "id": "610502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华州区", + "id": "610503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "潼关县", + "id": "610522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大荔县", + "id": "610523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合阳县", + "id": "610524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "澄城县", + "id": "610525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "蒲城县", + "id": "610526", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白水县", + "id": "610527", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富平县", + "id": "610528", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "韩城市", + "id": "610581", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华阴市", + "id": "610582", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "延安市", + "id": "610600", + "children": [ + { + "title": "宝塔区", + "id": "610602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安塞区", + "id": "610603", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "延长县", + "id": "610621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "延川县", + "id": "610622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "志丹县", + "id": "610625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吴起县", + "id": "610626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘泉县", + "id": "610627", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富县", + "id": "610628", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛川县", + "id": "610629", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宜川县", + "id": "610630", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄龙县", + "id": "610631", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄陵县", + "id": "610632", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "子长市", + "id": "610681", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汉中市", + "id": "610700", + "children": [ + { + "title": "汉台区", + "id": "610702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南郑区", + "id": "610703", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城固县", + "id": "610722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洋县", + "id": "610723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西乡县", + "id": "610724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "勉县", + "id": "610725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁强县", + "id": "610726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "略阳县", + "id": "610727", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇巴县", + "id": "610728", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "留坝县", + "id": "610729", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "佛坪县", + "id": "610730", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "榆林市", + "id": "610800", + "children": [ + { + "title": "榆阳区", + "id": "610802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "横山区", + "id": "610803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "府谷县", + "id": "610822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "靖边县", + "id": "610824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定边县", + "id": "610825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "绥德县", + "id": "610826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "米脂县", + "id": "610827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "佳县", + "id": "610828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吴堡县", + "id": "610829", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清涧县", + "id": "610830", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "子洲县", + "id": "610831", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "神木市", + "id": "610881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安康市", + "id": "610900", + "children": [ + { + "title": "汉滨区", + "id": "610902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "汉阴县", + "id": "610921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石泉县", + "id": "610922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁陕县", + "id": "610923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "紫阳县", + "id": "610924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岚皋县", + "id": "610925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平利县", + "id": "610926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇坪县", + "id": "610927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "旬阳县", + "id": "610928", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白河县", + "id": "610929", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "610901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "旬阳市", + "id": "610981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "商洛市", + "id": "611000", + "children": [ + { + "title": "商州区", + "id": "611002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛南县", + "id": "611021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "丹凤县", + "id": "611022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "商南县", + "id": "611023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山阳县", + "id": "611024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇安县", + "id": "611025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柞水县", + "id": "611026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "611001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘肃省", + "id": "620000", + "children": [ + { + "title": "兰州市", + "id": "620100", + "children": [ + { + "title": "城关区", + "id": "620102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "七里河区", + "id": "620103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西固区", + "id": "620104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "安宁区", + "id": "620105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红古区", + "id": "620111", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永登县", + "id": "620121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "皋兰县", + "id": "620122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "榆中县", + "id": "620123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兰州新区", + "id": "620171", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉峪关市", + "id": "620200", + "children": [ + { + "title": "市辖区", + "id": "620201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金昌市", + "id": "620300", + "children": [ + { + "title": "金川区", + "id": "620302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永昌县", + "id": "620321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白银市", + "id": "620400", + "children": [ + { + "title": "白银区", + "id": "620402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平川区", + "id": "620403", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "靖远县", + "id": "620421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "会宁县", + "id": "620422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "景泰县", + "id": "620423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天水市", + "id": "620500", + "children": [ + { + "title": "秦州区", + "id": "620502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麦积区", + "id": "620503", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "清水县", + "id": "620521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "秦安县", + "id": "620522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘谷县", + "id": "620523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武山县", + "id": "620524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张家川回族自治县", + "id": "620525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "武威市", + "id": "620600", + "children": [ + { + "title": "凉州区", + "id": "620602", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "民勤县", + "id": "620621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "古浪县", + "id": "620622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天祝藏族自治县", + "id": "620623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620601", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "张掖市", + "id": "620700", + "children": [ + { + "title": "甘州区", + "id": "620702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肃南裕固族自治县", + "id": "620721", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "民乐县", + "id": "620722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临泽县", + "id": "620723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "高台县", + "id": "620724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "山丹县", + "id": "620725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平凉市", + "id": "620800", + "children": [ + { + "title": "崆峒区", + "id": "620802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泾川县", + "id": "620821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵台县", + "id": "620822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "崇信县", + "id": "620823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庄浪县", + "id": "620825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "静宁县", + "id": "620826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华亭市", + "id": "620881", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "酒泉市", + "id": "620900", + "children": [ + { + "title": "肃州区", + "id": "620902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金塔县", + "id": "620921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "瓜州县", + "id": "620922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "肃北蒙古族自治县", + "id": "620923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿克塞哈萨克族自治县", + "id": "620924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉门市", + "id": "620981", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "敦煌市", + "id": "620982", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "620901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庆阳市", + "id": "621000", + "children": [ + { + "title": "西峰区", + "id": "621002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "庆城县", + "id": "621021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "环县", + "id": "621022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "华池县", + "id": "621023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "合水县", + "id": "621024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "正宁县", + "id": "621025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁县", + "id": "621026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "镇原县", + "id": "621027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "621001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "定西市", + "id": "621100", + "children": [ + { + "title": "安定区", + "id": "621102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "通渭县", + "id": "621121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陇西县", + "id": "621122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "渭源县", + "id": "621123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临洮县", + "id": "621124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "漳县", + "id": "621125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岷县", + "id": "621126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "621101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "陇南市", + "id": "621200", + "children": [ + { + "title": "武都区", + "id": "621202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "成县", + "id": "621221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "文县", + "id": "621222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宕昌县", + "id": "621223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "康县", + "id": "621224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西和县", + "id": "621225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "礼县", + "id": "621226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "徽县", + "id": "621227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "两当县", + "id": "621228", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "621201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临夏回族自治州", + "id": "622900", + "children": [ + { + "title": "临夏市", + "id": "622901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临夏县", + "id": "622921", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "康乐县", + "id": "622922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永靖县", + "id": "622923", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "广河县", + "id": "622924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和政县", + "id": "622925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东乡族自治县", + "id": "622926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "积石山保安族东乡族撒拉族自治县", + "id": "622927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘南藏族自治州", + "id": "623000", + "children": [ + { + "title": "合作市", + "id": "623001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "临潭县", + "id": "623021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "卓尼县", + "id": "623022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "舟曲县", + "id": "623023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "迭部县", + "id": "623024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玛曲县", + "id": "623025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "碌曲县", + "id": "623026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "夏河县", + "id": "623027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青海省", + "id": "630000", + "children": [ + { + "title": "西宁市", + "id": "630100", + "children": [ + { + "title": "城东区", + "id": "630102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城中区", + "id": "630103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城西区", + "id": "630104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "城北区", + "id": "630105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湟中区", + "id": "630106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大通回族土族自治县", + "id": "630121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湟源县", + "id": "630123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "630101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海东市", + "id": "630200", + "children": [ + { + "title": "乐都区", + "id": "630202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平安区", + "id": "630203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "民和回族土族自治县", + "id": "630222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "互助土族自治县", + "id": "630223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "化隆回族自治县", + "id": "630224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "循化撒拉族自治县", + "id": "630225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海北藏族自治州", + "id": "632200", + "children": [ + { + "title": "门源回族自治县", + "id": "632221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "祁连县", + "id": "632222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海晏县", + "id": "632223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "刚察县", + "id": "632224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄南藏族自治州", + "id": "632300", + "children": [ + { + "title": "同仁市", + "id": "632301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尖扎县", + "id": "632322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泽库县", + "id": "632323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "河南蒙古族自治县", + "id": "632324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海南藏族自治州", + "id": "632500", + "children": [ + { + "title": "共和县", + "id": "632521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "同德县", + "id": "632522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贵德县", + "id": "632523", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "兴海县", + "id": "632524", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贵南县", + "id": "632525", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "果洛藏族自治州", + "id": "632600", + "children": [ + { + "title": "玛沁县", + "id": "632621", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "班玛县", + "id": "632622", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "甘德县", + "id": "632623", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达日县", + "id": "632624", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "久治县", + "id": "632625", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玛多县", + "id": "632626", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玉树藏族自治州", + "id": "632700", + "children": [ + { + "title": "玉树市", + "id": "632701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "杂多县", + "id": "632722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "称多县", + "id": "632723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "治多县", + "id": "632724", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "囊谦县", + "id": "632725", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "曲麻莱县", + "id": "632726", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海西蒙古族藏族自治州", + "id": "632800", + "children": [ + { + "title": "格尔木市", + "id": "632801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "德令哈市", + "id": "632802", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "茫崖市", + "id": "632803", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌兰县", + "id": "632821", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "都兰县", + "id": "632822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "天峻县", + "id": "632823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大柴旦行政委员会", + "id": "632857", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "宁夏回族自治区", + "id": "640000", + "children": [ + { + "title": "银川市", + "id": "640100", + "children": [ + { + "title": "兴庆区", + "id": "640104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西夏区", + "id": "640105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "金凤区", + "id": "640106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "永宁县", + "id": "640121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "贺兰县", + "id": "640122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "灵武市", + "id": "640181", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "640101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "石嘴山市", + "id": "640200", + "children": [ + { + "title": "大武口区", + "id": "640202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "惠农区", + "id": "640205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "平罗县", + "id": "640221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "640201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吴忠市", + "id": "640300", + "children": [ + { + "title": "利通区", + "id": "640302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "红寺堡区", + "id": "640303", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "盐池县", + "id": "640323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "同心县", + "id": "640324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青铜峡市", + "id": "640381", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "640301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "固原市", + "id": "640400", + "children": [ + { + "title": "原州区", + "id": "640402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西吉县", + "id": "640422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "隆德县", + "id": "640423", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泾源县", + "id": "640424", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "彭阳县", + "id": "640425", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "640401", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中卫市", + "id": "640500", + "children": [ + { + "title": "沙坡头区", + "id": "640502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "中宁县", + "id": "640521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "海原县", + "id": "640522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "640501", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新疆维吾尔自治区", + "id": "650000", + "children": [ + { + "title": "乌鲁木齐市", + "id": "650100", + "children": [ + { + "title": "天山区", + "id": "650102", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙依巴克区", + "id": "650103", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新市区", + "id": "650104", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "水磨沟区", + "id": "650105", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "头屯河区", + "id": "650106", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "达坂城区", + "id": "650107", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "米东区", + "id": "650109", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌鲁木齐县", + "id": "650121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "650101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "克拉玛依市", + "id": "650200", + "children": [ + { + "title": "独山子区", + "id": "650202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "克拉玛依区", + "id": "650203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "白碱滩区", + "id": "650204", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌尔禾区", + "id": "650205", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "市辖区", + "id": "650201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吐鲁番市", + "id": "650400", + "children": [ + { + "title": "高昌区", + "id": "650402", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "鄯善县", + "id": "650421", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "托克逊县", + "id": "650422", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "哈密市", + "id": "650500", + "children": [ + { + "title": "伊州区", + "id": "650502", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴里坤哈萨克自治县", + "id": "650521", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伊吾县", + "id": "650522", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昌吉回族自治州", + "id": "652300", + "children": [ + { + "title": "昌吉市", + "id": "652301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阜康市", + "id": "652302", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "呼图壁县", + "id": "652323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "玛纳斯县", + "id": "652324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奇台县", + "id": "652325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉木萨尔县", + "id": "652327", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "木垒哈萨克自治县", + "id": "652328", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博尔塔拉蒙古自治州", + "id": "652700", + "children": [ + { + "title": "博乐市", + "id": "652701", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿拉山口市", + "id": "652702", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "精河县", + "id": "652722", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "温泉县", + "id": "652723", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴音郭楞蒙古自治州", + "id": "652800", + "children": [ + { + "title": "库尔勒市", + "id": "652801", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "轮台县", + "id": "652822", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尉犁县", + "id": "652823", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "若羌县", + "id": "652824", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "且末县", + "id": "652825", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "焉耆回族自治县", + "id": "652826", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和静县", + "id": "652827", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和硕县", + "id": "652828", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "博湖县", + "id": "652829", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "库尔勒经济技术开发区", + "id": "652871", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿克苏地区", + "id": "652900", + "children": [ + { + "title": "阿克苏市", + "id": "652901", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "库车市", + "id": "652902", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "温宿县", + "id": "652922", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙雅县", + "id": "652924", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新和县", + "id": "652925", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "拜城县", + "id": "652926", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌什县", + "id": "652927", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿瓦提县", + "id": "652928", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "柯坪县", + "id": "652929", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "克孜勒苏柯尔克孜自治州", + "id": "653000", + "children": [ + { + "title": "阿图什市", + "id": "653001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿克陶县", + "id": "653022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿合奇县", + "id": "653023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌恰县", + "id": "653024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "喀什地区", + "id": "653100", + "children": [ + { + "title": "喀什市", + "id": "653101", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "疏附县", + "id": "653121", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "疏勒县", + "id": "653122", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "英吉沙县", + "id": "653123", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "泽普县", + "id": "653124", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "莎车县", + "id": "653125", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "叶城县", + "id": "653126", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "麦盖提县", + "id": "653127", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "岳普湖县", + "id": "653128", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伽师县", + "id": "653129", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巴楚县", + "id": "653130", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "塔什库尔干塔吉克自治县", + "id": "653131", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和田地区", + "id": "653200", + "children": [ + { + "title": "和田市", + "id": "653201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和田县", + "id": "653221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "墨玉县", + "id": "653222", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "皮山县", + "id": "653223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "洛浦县", + "id": "653224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "策勒县", + "id": "653225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "于田县", + "id": "653226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "民丰县", + "id": "653227", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伊犁哈萨克自治州", + "id": "654000", + "children": [ + { + "title": "伊宁市", + "id": "654002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "奎屯市", + "id": "654003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霍尔果斯市", + "id": "654004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "伊宁县", + "id": "654021", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "察布查尔锡伯自治县", + "id": "654022", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "霍城县", + "id": "654023", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "巩留县", + "id": "654024", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新源县", + "id": "654025", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昭苏县", + "id": "654026", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "特克斯县", + "id": "654027", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "尼勒克县", + "id": "654028", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "塔城地区", + "id": "654200", + "children": [ + { + "title": "塔城市", + "id": "654201", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "乌苏市", + "id": "654202", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "额敏县", + "id": "654221", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙湾县", + "id": "654223", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "托里县", + "id": "654224", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "裕民县", + "id": "654225", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "和布克赛尔蒙古自治县", + "id": "654226", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙湾市", + "id": "654203", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿勒泰地区", + "id": "654300", + "children": [ + { + "title": "阿勒泰市", + "id": "654301", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "布尔津县", + "id": "654321", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "富蕴县", + "id": "654322", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "福海县", + "id": "654323", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "哈巴河县", + "id": "654324", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "青河县", + "id": "654325", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "吉木乃县", + "id": "654326", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新疆维吾尔自治区-自治区直辖县级行政区划", + "id": "659000", + "children": [ + { + "title": "石河子市", + "id": "659001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "阿拉尔市", + "id": "659002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "图木舒克市", + "id": "659003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "五家渠市", + "id": "659004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北屯市", + "id": "659005", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "铁门关市", + "id": "659006", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "双河市", + "id": "659007", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "可克达拉市", + "id": "659008", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "昆玉市", + "id": "659009", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "胡杨河市", + "id": "659010", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "新星市", + "id": "659011", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "香港特别行政区", + "id": "810000", + "children": [ + { + "title": "香港特别行政区", + "id": "81000011", + "children": [ + { + "title": "中西区", + "id": "810001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "湾仔区", + "id": "810002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "东区", + "id": "810003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "南区", + "id": "810004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "油尖旺区", + "id": "810005", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "深水埗区", + "id": "810006", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "九龙城区", + "id": "810007", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "黄大仙区", + "id": "810008", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "观塘区", + "id": "810009", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "荃湾区", + "id": "810010", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "屯门区", + "id": "810011", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "元朗区", + "id": "810012", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "北区", + "id": "810013", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大埔区", + "id": "810014", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "西贡区", + "id": "810015", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "沙田区", + "id": "810016", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "葵青区", + "id": "810017", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "离岛区", + "id": "810018", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "澳门特别行政区", + "id": "820000", + "children": [ + { + "title": "澳门特别行政区", + "id": "82000011", + "children": [ + { + "title": "花地玛堂区", + "id": "820001", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "花王堂区", + "id": "820002", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "望德堂区", + "id": "820003", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "大堂区", + "id": "820004", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "风顺堂区", + "id": "820005", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "嘉模堂区", + "id": "820006", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "路凼填海区", + "id": "820007", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject, + { + "title": "圣方济各堂区", + "id": "820008", + "children": [] as UTSJSONObject[] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } + ] as UTSJSONObject[], + "disabled": false + } as UTSJSONObject +] as UTSJSONObject[] \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-city/x-picker-city.uvue b/uni_modules/tmx-ui/components/x-picker-city/x-picker-city.uvue new file mode 100644 index 0000000..0836fc0 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-city/x-picker-city.uvue @@ -0,0 +1,376 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-date/x-picker-date.uvue b/uni_modules/tmx-ui/components/x-picker-date/x-picker-date.uvue new file mode 100644 index 0000000..c7890e9 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-date/x-picker-date.uvue @@ -0,0 +1,683 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-item/x-picker-item.uvue b/uni_modules/tmx-ui/components/x-picker-item/x-picker-item.uvue new file mode 100644 index 0000000..6e2e5ed --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-item/x-picker-item.uvue @@ -0,0 +1,409 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-selected/x-picker-selected.uvue b/uni_modules/tmx-ui/components/x-picker-selected/x-picker-selected.uvue new file mode 100644 index 0000000..33be670 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-selected/x-picker-selected.uvue @@ -0,0 +1,757 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-time/x-picker-time.uvue b/uni_modules/tmx-ui/components/x-picker-time/x-picker-time.uvue new file mode 100644 index 0000000..217d15a --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-time/x-picker-time.uvue @@ -0,0 +1,612 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-view/interface.uts b/uni_modules/tmx-ui/components/x-picker-view/interface.uts new file mode 100644 index 0000000..aa317d6 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-view/interface.uts @@ -0,0 +1,9 @@ + /** + * 项目结构 + */ + export type X_PICKER_X_ITEM = { + id : string, + title : string, + children : X_PICKER_X_ITEM[], + disabled : boolean, + } \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-view/util.uts b/uni_modules/tmx-ui/components/x-picker-view/util.uts new file mode 100644 index 0000000..a66cafc --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-view/util.uts @@ -0,0 +1,129 @@ +import { X_PICKER_X_ITEM } from "./interface.uts" +/** + * 当前树有多少个被选中了。 + */ +export function getTreeSelectedNum(item : X_PICKER_X_ITEM[], target : Set) : number { + let inx = 0; + function jshz(tree : X_PICKER_X_ITEM[]) { + for (let i = 0; i < tree.length; i++) { + let item = tree[i] + if (item.children.length > 0) { + jshz(item.children) + } else if (target.has(item.id)) { + inx += 1 + } + } + } + jshz(item) + return inx; +} + +/** + * 根据目标节点,过滤掉父节点。 + * @param item + * @param target + */ +export function filterParentNode(item : X_PICKER_X_ITEM[], target : Set) : string[] { + function jshz(tree : X_PICKER_X_ITEM[]) : string[] { + let arr = [] as string[] + for (let i = 0; i < tree.length; i++) { + let item = tree[i] + if (item.children.length > 0) { + arr = arr.concat(jshz(item.children)) + } else if (target.has(item.id)) { + arr.push(item.id) + } + } + return arr; + } + return jshz(item) +} + +/** + * 根据给定的长度值,赋值默认值 + */ +export function setDefaultByValueAr(list : X_PICKER_X_ITEM[], value : string[], maxLen : number) : string[] { + let v = value; + let pr = [] as string[]; + for (let j = 0; j < maxLen; j++) { + pr.push("") + } + v = v.concat(pr).slice(0, maxLen) + let defaultAr = [] as string[]; + function setvalue(item : X_PICKER_X_ITEM[]) { + if (item.length > 0) { + defaultAr.push(item[0].id); + if (item[0].children.length > 0) { + setvalue(item[0].children) + } + } + } + + setvalue(list); + + for (let i = 0; i < maxLen; i++) { + if (defaultAr.length - 1 >= i && v[i] == "") { + v[i] = defaultAr[i] + } + } + + + return v; +} + + + +// 通过 ID 查找节点的函数 +export function findNodeById(TreeNode : X_PICKER_X_ITEM[], id : string) : X_PICKER_X_ITEM | null { + let newnode = null as X_PICKER_X_ITEM | null + for (let i = 0; i < TreeNode.length; i++) { + let node = TreeNode[i] + if (node.id === id) { + newnode = node; + break; + } + if (node.children.length > 0) { + const foundNode = findNodeById(node.children, id); + if (foundNode != null) { + newnode = foundNode; + break; + } + } + + } + + return newnode; +} + + +// 查找节点的上级节点 +export function findParentNode(nodes: X_PICKER_X_ITEM[], targetNodeId: string ): X_PICKER_X_ITEM | null { + function search(node: X_PICKER_X_ITEM): X_PICKER_X_ITEM | null { + if (node.children.length>0) { + for (let i = 0; i < node.children.length; i++) { + const child = node.children[i]; + if (child.id === targetNodeId) { + return node; + } else { + const foundParent = search(child); + if (foundParent !=null) { + return foundParent; + } + } + } + } + + return null; + } + + // 使用for循环遍历根节点数组 + for (let i = 0; i < nodes.length; i++) { + const root = nodes[i]; + const parentNode = search(root); + if (parentNode!=null) { + return parentNode; + } + } + + return null; // 如果未找到目标节点的父节点,则返回undefined +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-view/x-picker-view - 4.04sdk备用.uvue b/uni_modules/tmx-ui/components/x-picker-view/x-picker-view - 4.04sdk备用.uvue new file mode 100644 index 0000000..8e622d5 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-view/x-picker-view - 4.04sdk备用.uvue @@ -0,0 +1,483 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker-view/x-picker-view.uvue b/uni_modules/tmx-ui/components/x-picker-view/x-picker-view.uvue new file mode 100644 index 0000000..2d66c43 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker-view/x-picker-view.uvue @@ -0,0 +1,334 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-picker/x-picker.uvue b/uni_modules/tmx-ui/components/x-picker/x-picker.uvue new file mode 100644 index 0000000..121a949 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-picker/x-picker.uvue @@ -0,0 +1,422 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-popover/x-popover.uvue b/uni_modules/tmx-ui/components/x-popover/x-popover.uvue new file mode 100644 index 0000000..172a1e8 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-popover/x-popover.uvue @@ -0,0 +1,628 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-progress/x-progress.uvue b/uni_modules/tmx-ui/components/x-progress/x-progress.uvue new file mode 100644 index 0000000..54b1a07 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-progress/x-progress.uvue @@ -0,0 +1,290 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-pull-refresh/x-pull-refresh.uvue b/uni_modules/tmx-ui/components/x-pull-refresh/x-pull-refresh.uvue new file mode 100644 index 0000000..4cc2a0a --- /dev/null +++ b/uni_modules/tmx-ui/components/x-pull-refresh/x-pull-refresh.uvue @@ -0,0 +1,419 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-qrcoder/drawQrcoder.uts b/uni_modules/tmx-ui/components/x-qrcoder/drawQrcoder.uts new file mode 100644 index 0000000..4a2eade --- /dev/null +++ b/uni_modules/tmx-ui/components/x-qrcoder/drawQrcoder.uts @@ -0,0 +1,306 @@ +import { GenerateFrameResult, XQrcoderProps } from "./interface.uts" +import { generateFrame } from "./qrcode.uts" + +// 绘制圆形定位点模式的函数 +function drawRoundedPositionPattern(ctx: CanvasRenderingContext2D, x: number, y: number, px: number, pdColor: string, bgColor: string) { + // 外层黑色圆形 (7x7) + ctx.fillStyle = pdColor + ctx.beginPath() + ctx.arc(x + px * 3.5, y + px * 3.5, px * 3.5, 0, 2 * Math.PI) + ctx.fill() + ctx.closePath() + + // 中层白色圆形 (5x5) + ctx.fillStyle = bgColor + ctx.beginPath() + ctx.arc(x + px * 3.5, y + px * 3.5, px * 2.5, 0, 2 * Math.PI) + ctx.fill() + ctx.closePath() + + // 内层黑色圆形 (3x3) + ctx.fillStyle = pdColor + ctx.beginPath() + ctx.arc(x + px * 3.5, y + px * 3.5, px * 1.5, 0, 2 * Math.PI) + ctx.fill() + ctx.closePath() +} + +// 绘制星形图案的函数 +function drawStar(ctx: CanvasRenderingContext2D, x: number, y: number, px: number) { + const centerX = x + px / 2 + const centerY = y + px / 2 + const outerRadius = px * 0.4 // 外圆半径 + const innerRadius = px * 0.15 // 内圆半径 + const spikes = 4 // 四个尖角 + + ctx.beginPath() + + for (let i = 0; i < spikes * 2; i++) { + const angle = (i * Math.PI) / spikes + const radius = i % 2 === 0 ? outerRadius : innerRadius + const starX = centerX + Math.cos(angle) * radius + const starY = centerY + Math.sin(angle) * radius + + if (i === 0) { + ctx.moveTo(starX, starY) + } else { + ctx.lineTo(starX, starY) + } + } + + ctx.closePath() + ctx.fill() +} + +// 兼容的圆角矩形绘制函数 +function drawRoundedRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number) { + ctx.beginPath() + + // 如果圆角半径太大,限制为宽度或高度的一半 + const maxRadius = Math.min(width, height) / 2 + radius = Math.min(radius, maxRadius) + + // 绘制圆角矩形路径 + ctx.moveTo(x + radius, y) + ctx.lineTo(x + width - radius, y) + ctx.arc(x + width - radius, y + radius, radius, -Math.PI / 2, 0) + ctx.lineTo(x + width, y + height - radius) + ctx.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2) + ctx.lineTo(x + radius, y + height) + ctx.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI) + ctx.lineTo(x, y + radius) + ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2) + ctx.closePath() +} + +export function drawQrcode(opts : XQrcoderProps, img : any | null = null) { + let fo = generateFrame(opts.text, opts.ecc) + let points = fo.frameBuffer + let width = fo.width + let px = opts.size / width + let borderWidth = 0 + const ctx = opts.ctx; + + // 绘制背景 + ctx.fillStyle = opts.background + ctx.fillRect(0, 0, opts.size, opts.size) + + // 判断是否是定位点的函数 + function isPositionDetectionPattern(i : number, j : number, width : number) : boolean { + // 左上角 + if (i < 7 && j < 7) return true; + // 右上角 + if (i > width - 8 && j < 7) return true; + // 左下角 + if (i < 7 && j > width - 8) return true; + return false; + } + let dot = px * 0.1 + let pdColor = opts?.pdColor??opts.foreground + + // 先绘制定位点区域(如果需要圆角) + if ((opts?.pdRounded??false)) { + // 绘制三个定位点的同心圆角矩形结构 + // 左上角 + drawRoundedPositionPattern(ctx, borderWidth, borderWidth, px, pdColor, opts.background) + + // 右上角 + drawRoundedPositionPattern(ctx, borderWidth + px * (width - 7), borderWidth, px, pdColor, opts.background) + + // 左下角 + drawRoundedPositionPattern(ctx, borderWidth, borderWidth + px * (width - 7), px, pdColor, opts.background) + } + + for (let i = 0; i < width; i++) { + for (let j = 0; j < width; j++) { + if (points[j * width + i] > 0) { + // 设置颜色,如果是定位点则使用pdColor,否则使用foreground + const isPostion = isPositionDetectionPattern(i, j, width); + ctx.fillStyle = opts.foreground; + + if (isPostion) { + // 如果启用了圆角,定位点区域已经整体绘制过了,跳过单个方块的绘制 + if (!(opts?.pdRounded??false)) { + ctx.fillStyle = pdColor + ctx.fillRect(borderWidth + px * i, borderWidth + px * j, px, px) + } + } else { + if (opts.mode == 'line') { + ctx.fillRect(borderWidth + px * i, borderWidth + px * j, px, px / 2) + } else if (opts.mode == 'circular') { + ctx.beginPath() + let rx = borderWidth + px * i + px / 2 - dot + let ry = borderWidth + px * j + px / 2 - dot + ctx.arc(rx, ry, px / 2 - dot, 0, 2 * Math.PI) + ctx.fill() + ctx.closePath() + } else if (opts.mode == 'rectSmall') { + + ctx.fillRect(borderWidth + px * i + dot, borderWidth + px * j + dot, px - dot*2, px - dot*2) + } else if (opts.mode == 'xing') { + // 绘制星形 + drawStar(ctx, borderWidth + px * i, borderWidth + px * j, px) + } else if (opts.mode == 'vertical') { + continue + } else { + ctx.fillRect(borderWidth + px * i, borderWidth + px * j, px, px) + } + } + + + + + + } + } + } + + // 对于vertical模式,需要特殊处理垂直方向的连续点 + if (opts.mode == 'vertical') { + // 创建已处理标记数组 + let processed:boolean[] = [] as boolean[] + for(let km=0;km 0 && !processed[index]) { + const isPostion = isPositionDetectionPattern(i, j, width); + + if (isPostion) { + // 定位点跳过,已经处理过了 + continue + } + + // 分析垂直方向的连续点 + let verticalLength = 1 + let startJ = j + + // 向上查找连续点 + while (startJ > 0 && points[(startJ - 1) * width + i] > 0 && + !isPositionDetectionPattern(i, startJ - 1, width)) { + startJ-- + verticalLength++ + } + + // 向下查找连续点 + let endJ = j + while (endJ < width - 1 && points[(endJ + 1) * width + i] > 0 && + !isPositionDetectionPattern(i, endJ + 1, width)) { + endJ++ + verticalLength++ + } + + // 标记这些点为已处理 + for (let k = startJ; k <= endJ; k++) { + processed[k * width + i] = true + } + + // 根据长度决定绘制方式 + ctx.fillStyle = opts.foreground + + if (verticalLength == 1) { + // 单个点:绘制圆点 + ctx.beginPath() + let centerX = borderWidth + px * i + px / 2 + let centerY = borderWidth + px * j + px / 2 + ctx.arc(centerX, centerY, px * 0.25, 0, 2 * Math.PI) // 稍微减小圆点半径 + ctx.fill() + ctx.closePath() + } else if (verticalLength <= 3) { + // 2-3个点:绘制连续线条 + let x = borderWidth + px * i + px / 2 + let y = borderWidth + px * startJ + px * 0.2 // 减少上下间距 + let lineWidth = px * 0.5 // 减少线条宽度 + let lineHeight = px * (endJ - startJ + 1) * 0.8 // 增加线条高度 + // 圆角半径适中,不完全半圆 + let radius = px * 0.5 + drawRoundedRect(ctx, x - lineWidth / 2, y, lineWidth, lineHeight, radius) + ctx.fill() + } else { + // 超过3个点:分段绘制,每3个点一段 + let segments = Math.ceil(verticalLength / 3) + for (let seg = 0; seg < segments; seg++) { + let segStart = startJ + seg * 3 + let segEnd = Math.min(startJ + (seg + 1) * 3 - 1, endJ) + let segLength = segEnd - segStart + 1 + + let x = borderWidth + px * i + px / 2 + let y = borderWidth + px * segStart + px * 0.2 // 减少上下间距 + let lineWidth = px * 0.5 // 减少线条宽度 + let lineHeight = px * segLength * 0.8 // 增加线条高度 + // 圆角半径适中,不完全半圆 + let radius = px * 0.5 + drawRoundedRect(ctx, x - lineWidth / 2, y, lineWidth, lineHeight, radius) + ctx.fill() + } + } + } + } + } + } + + if (opts.logo != '') { + // #ifdef APP-ANDROID||APP-IOS||WEB + let images = new Image(opts.logoSize, opts.logoSize) + images.src = opts.logo + console.log(opts.logo) + images.onload = () => { + + uni.getImageInfo({ + src: opts.logo, + success: (res) => { + ctx.save() + ctx.fillStyle = opts.logoBgColor + let centerx = (opts.size - opts.logoSize) / 2; + ctx.fillRect(centerx, centerx, opts.logoSize, opts.logoSize) + ctx.drawImage(images, 0, 0, res.width, res.height, centerx + 3, centerx + 3, opts.logoSize - 6, opts.logoSize - 6) + ctx.restore() + } + }) + } + // #endif + // #ifdef MP-WEIXIN||APP-HARMONY + img.src = opts.logo + img.onload = () => { + uni.getImageInfo({ + src: opts.logo, + success: (res) => { + ctx.save() + ctx.fillStyle = opts.logoBgColor + let centerx = (opts.size - opts.logoSize) / 2; + ctx.fillRect(centerx, centerx, opts.logoSize, opts.logoSize) + + // #ifdef MP + ctx.drawImage( + img, + 0, + 0, + res.width, + res.height, + centerx + 3, + centerx + 3, + opts.logoSize - 6, + opts.logoSize - 6 + ) + // #endif + // #ifdef APP-HARMONY + let dpr = uni.getWindowInfo().pixelRatio + ctx.drawImage( + img, + centerx + 3, + centerx + 3, + opts.logoSize - 6, + opts.logoSize - 6 + ) + // #endif + ctx.restore() + } + }) + } + // #endif + + + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-qrcoder/interface.uts b/uni_modules/tmx-ui/components/x-qrcoder/interface.uts new file mode 100644 index 0000000..62afc92 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-qrcoder/interface.uts @@ -0,0 +1,58 @@ +export type GenerateFrameResult = { + frameBuffer: number[], + width: number +} +export type XQrcoderProps = { + ctx: CanvasRenderingContext2D, + /** + * 容错等级 + */ + ecc:string, + /** + * 二维码内容 + */ + text: string, + /** + * 二维码大小 + */ + size: number, + /** + * 二维码前景色 + */ + foreground: string, + /** + * 二维码背景色 + */ + background: string, + padding: number, + /** + * 二维码logo + */ + logo: string, + /** + * 二维码logo的背景色 + */ + logoBgColor:string, + /** + * 二维码logo大小 + */ + logoSize: number, + /** + * 绘制的样式目前提供 + * rect :普通码矩形 + * circular :小圆点 + * line :横向线条 + * rectSmall :小方格 + * xing :星形 + * vertical :竖向线条带圆角 + */ + mode:String, + /** + * 定位点的颜色 + */ + pdColor?: string, + /** + * 定位点是否使用圆角 + */ + pdRounded?: boolean +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-qrcoder/qrcode.uts b/uni_modules/tmx-ui/components/x-qrcoder/qrcode.uts new file mode 100644 index 0000000..13e77ac --- /dev/null +++ b/uni_modules/tmx-ui/components/x-qrcoder/qrcode.uts @@ -0,0 +1,1062 @@ +import { GenerateFrameResult } from "./interface.uts" +/** + * 二维码生成器 + * @author https://tmui.design + * @description 由tmui改进,并重写为uts版本,不得分发给其它人。 + * @version 1.0.0 + */ +const ALIGNMENT_DELTA = [ + 0, 11, 15, 19, 23, 27, 31, + 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, + 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28 +] as number[] + +// There are four elements per version. The first two indicate the number of blocks, then the +// data width, and finally the ECC width. +const ECC_BLOCKS = [ + 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, + 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28, + 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, + 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16, + 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, + 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, + 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26, + 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, + 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24, + 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, + 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, + 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28, + 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, + 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24, + 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, + 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30, + 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28, + 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28, + 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26, + 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28, + 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, + 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24, + 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30, + 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30, + 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30, + 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, + 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30, + 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30, + 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30, + 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30, + 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30, + 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30, + 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30, + 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30, + 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30, + 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30, + 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30, + 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30, + 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30, + 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30 +] as number[] + +// Map of human-readable ECC levels. +const ECC_LEVELS = new Map([ + ['L', 1], + ['M', 0], + ['Q', 3], + ['H', 2] +]) + + +// Final format bits with mask (level << 3 | mask). +const FINAL_FORMAT = [ + 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, /* L */ + 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, /* M */ + 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, /* Q */ + 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b /* H */ +] + +// Galois field exponent table. +const GALOIS_EXPONENT = [ + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, + 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, + 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, + 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, + 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, + 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, + 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, + 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, + 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, + 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, + 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, + 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, + 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, + 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, + 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, + 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00 +] + +// Galois field log table. +const GALOIS_LOG = [ + 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, + 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, + 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, + 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, + 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, + 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, + 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, + 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, + 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, + 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, + 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, + 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, + 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, + 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, + 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, + 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf +] + +// *Badness* coefficients. +const N1 = 3 +const N2 = 3 +const N3 = 40 +const N4 = 10 + +// Version pattern. +const VERSION_BLOCK = [ + 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532, + 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5, + 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69 +] + + +// Generate the encoded QR image for the string provided. +export function generateFrame(_str : string | null = null, ecc : string | null = null) : GenerateFrameResult { + let i = 0 + let t = 0 + let j = 0 + let k = 0 + let m = 0 + let v = 0 + let x = 0 + let y = 0 + let version = 0 + let str = _str == null ? '' : (_str) + let width = 0 + let eccLevel = ECC_LEVELS.get(ecc == null ? 'L' : (ecc))! + + + // Run lengths for badness. + var badBuffer = [] as number[] + + + // Data block. + var dataBlock = 0 + var eccBlock = 0 + var neccBlock1 = 0 + var neccBlock2 = 0 + // ECC buffer. + var eccBuffer = [] as number[] + + // Image buffer. + var frameBuffer = [] as number[] + + // Fixed part of the image. + var frameMask = [] as number[] + + // Generator polynomial. + var polynomial = [] as number[] + + // Data input buffer. + var stringBuffer = [] as number[] + + + // functions + + // Set bit to indicate cell in frame is immutable (symmetric around diagonal). + function setMask(_x : number, _y : number) { + let bit = 0 + let x = _x + let y = _y + + if (x > y) { + bit = x + x = y + y = bit + } + + bit = y + bit *= y + bit += y + bit >>= 1 + bit += x + + frameMask[bit] = 1 + } + + // Enter alignment pattern. Foreground colour to frame, background to mask. Frame will be merged + // with mask later. + function addAlignment(_x : number, _y : number) { + let i = 0 + let x = _x + let y = _y + + frameBuffer[x + width * y] = 1 + + for (i = -2; i < 2; i++) { + frameBuffer[(x + i) + width * (y - 2)] = 1 + frameBuffer[(x - 2) + width * (y + i + 1)] = 1 + frameBuffer[(x + 2) + width * (y + i)] = 1 + frameBuffer[(x + i + 1) + width * (y + 2)] = 1 + } + + for (i = 0; i < 2; i++) { + setMask(x - 1, y + i) + setMask(x + 1, y - i) + setMask(x - i, y - 1) + setMask(x + i, y + 1) + } + } + + // Exponentiation mod N. + function modN(_x : number) : number { + var x = _x + while (x >= 255) { + x -= 255 + x = (x >> 8) + (x & 255) + } + + return x + } + + // Calculate and append `ecc` data to the `data` block. If block is in the string buffer the + // indices to buffers are used. + function appendData(_data : number, _dataLength : number, _ecc : number, _eccLength : number) { + let bit = 0 + let i = 0 + let j = 0 + let data = _data + let dataLength = _dataLength + let ecc = _ecc + let eccLength = _eccLength + + + for (i = 0; i < eccLength; i++) { + stringBuffer[ecc + i] = 0 + } + + for (i = 0; i < dataLength; i++) { + bit = GALOIS_LOG[stringBuffer[data + i] ^ stringBuffer[ecc]] + + if (bit !== 255) { + for (j = 1; j < eccLength; j++) { + stringBuffer[ecc + j - 1] = stringBuffer[ecc + j] ^ + GALOIS_EXPONENT[modN(bit + polynomial[eccLength - j])] + } + } else { + for (j = ecc; j < ecc + eccLength; j++) { + stringBuffer[j] = stringBuffer[j + 1] + } + } + + stringBuffer[ecc + eccLength - 1] = bit == 255 ? 0 : + GALOIS_EXPONENT[modN(bit + polynomial[0])] + } + } + + // Check mask since symmetricals use half. + function isMasked(_x : number, _y : number) : boolean { + let bit = 0 + let x = _x + let y = _y + + + if (x > y) { + bit = x + x = y + y = bit + } + + bit = y + bit += y * y + bit >>= 1 + bit += x + return frameMask[bit] == 1 + } + + // Apply the selected mask out of the 8 options. + function applyMask(_mask : number) { + let x = 0; + let y = 0; + let r3x = 0; + let r3y = 0; + let mask = _mask; + + if (mask == 0) { + for (y = 0; y < width; y++) { + for (x = 0; x < width; x++) { + if (((x + y) & 1) == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + } + } + } + + + if (mask == 1) { + for (y = 0; y < width; y++) { + for (x = 0; x < width; x++) { + if ((y & 1) == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + } + } + } + + + if (mask == 2) { + for (y = 0; y < width; y++) { + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + if (r3x == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + } + } + + + if (mask == 3) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = r3y + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + if (r3x == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + + r3y++ + } + } + + if (mask == 4) { + for (y = 0; y < width; y++) { + r3y = ((y >> 1) & 1) + x = 0 + for (r3x = 0; x < width; x++) { + if (r3x == 3) { + r3x = 0 + } + + if (r3x == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + } + } + + + if (mask == 5) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + // 定义变量来存储中间结果 + let bitwiseAndResult = x & y & 1; // 计算 x, y 与 1 的按位与结果 + let notR3x = r3x == 0 ? 1 : 0; // 将 r3x 转换为数字,如果 r3x 是 0,则为 1,否则为 0 + let notR3y = r3y == 0 ? 1 : 0; // 将 r3y 转换为数字,如果 r3y 是 0,则为 1,否则为 0 + let orResult = notR3x | notR3y; // 计算 notR3x 和 notR3y 的按位或结果 + let notOrResult = orResult == 0 ? 1 : 0; // 取逻辑非,如果 orResult 是 0,则为 1,否则为 0 + + // 计算括号内的结果 + let bracketResult = bitwiseAndResult + notOrResult; // 将两个数字相加 + + // 计算最终结果 + let finalResult = bracketResult == 0 ? true : false; // 如果 bracketResult 是 0,则为 1,否则为 + + // !((x & y & 1) + !(!r3x | !r3y)) + if (finalResult && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + + r3x++ + } + r3y++ + } + } + + + if (mask == 6) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + // 定义变量来存储中间结果 + let bitwiseAndResult = x & y & 1; // 计算 x, y 与 1 的按位与结果 + let r3xEqualsR3y = r3x === r3y; // 检查 r3x 是否等于 r3y + let r3xAndResult = r3x > 0 && r3xEqualsR3y; // 计算 r3x 与 r3xEqualsR3y 的逻辑与结果 + + // 将逻辑与结果转换为数字(true 转换为 1,false 转换为 0) + let r3xAndResultAsNumber = r3xAndResult ? 1 : 0; + + // 计算括号内的加法结果 + let additionResult = bitwiseAndResult + r3xAndResultAsNumber; + + // 计算加法结果与 1 的按位与 + let bitwiseAndWithOne = additionResult & 1; + + // 计算最终结果,即对按位与结果取逻辑非 + let finalResult = bitwiseAndWithOne == 0 ? true : false; + + // !(((x & y & 1) + (r3x && (r3x == r3y))) & 1) + if (finalResult && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + + r3x++ + } + r3y++ + } + } + + + if (mask == 7) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + // 定义变量来存储中间结果 + let r3xEqualsR3y = r3x === r3y; // 检查 r3x 是否等于 r3y + let r3xAndResult = r3x > 0 && r3xEqualsR3y; // 计算 r3x 与 r3xEqualsR3y 的逻辑与结果 + + // 将逻辑与结果转换为数字(true 转换为 1,false 转换为 0) + let r3xAndResultAsNumber = r3xAndResult ? 1 : 0; + + // 计算 x 和 y 的和 + let sumOfXAndY = x + y; + + // 计算 x 和 y 之和与 1 的按位与结果 + let bitwiseAndWithOne = sumOfXAndY & 1; + + // 计算括号内的加法结果 + let additionResult = r3xAndResultAsNumber + bitwiseAndWithOne; + + // 计算加法结果与 1 的按位与 + let bitwiseAndOfAddition = additionResult & 1; + + // 计算最终结果,即对按位与结果取逻辑非 + let finalResult = bitwiseAndOfAddition === 0 ? true : false; + + // !(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) + if (finalResult && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + + r3y++ + } + } + + + + } + + // Using the table for the length of each run, calculate the amount of bad image. Long runs or + // those that look like finders are called twice once for X and Y. + function getBadRuns(_length : number) : number { + let badRuns = 0 + let i = 0 + let length = _length + + for (i = 0; i <= length; i++) { + if (badBuffer[i] >= 5) { + badRuns += N1 + badBuffer[i] - 5 + } + } + + // FBFFFBF as in finder. + for (i = 3; i < length - 1; i += 2) { + if (badBuffer[i - 2] == badBuffer[i + 2] && + badBuffer[i + 2] == badBuffer[i - 1] && + badBuffer[i - 1] == badBuffer[i + 1] && + badBuffer[i - 1] * 3 == badBuffer[i] && + // Background around the foreground pattern? Not part of the specs. + (badBuffer[i - 3] == 0 || i + 3 > length || + badBuffer[i - 3] * 3 >= badBuffer[i] * 4 || + badBuffer[i + 3] * 3 >= badBuffer[i] * 4)) { + badRuns += N3 + } + } + + return badRuns + } + + // Calculate how bad the masked image is (e.g. blocks, imbalance, runs, or finders). + function checkBadness() { + let b = 0 + let b1 = 0 + let bad = 0 + let big = 0 + let bw = 0 + let count = 0 + let h = 0 + let x = 0 + let y = 0 + + + // Blocks of same colour. + for (y = 0; y < width - 1; y++) { + for (x = 0; x < width - 1; x++) { + // All foreground colour. + if ((frameBuffer[x + width * y] > 0 && + frameBuffer[(x + 1) + width * y] > 0 && + frameBuffer[x + width * (y + 1)] > 0 && + frameBuffer[(x + 1) + width * (y + 1)] > 0) || + // All background colour. + !(frameBuffer[x + width * y] > 0 || + frameBuffer[(x + 1) + width * y] > 0 || + frameBuffer[x + width * (y + 1)] > 0 || + frameBuffer[(x + 1) + width * (y + 1)] > 0)) { + bad += N2 + } + } + } + + for (y = 0; y < width; y++) { + badBuffer.push(0) + } + for (y = 0; y < width; y++) { + badBuffer[0] = 0 + h = 0 + b = 0 + for (x = 0; x < width; x++) { + b1 = frameBuffer[x + width * y] + if (b1 == b) { + badBuffer[h]++ + } else { + badBuffer[++h] = 1 + } + + b = b1 + bw += b > 0 ? 1 : -1 + } + + bad += getBadRuns(h) + } + + if (bw < 0) bw = -bw + + big = bw + big += big << 2 + big <<= 1 + + while (big > width * width) { + big -= width * width + count++ + } + + bad += count * N4 + + // Y runs. + for (x = 0; x < width; x++) { + badBuffer[0] = 0 + h = 0 + b = 0 + for (y = 0; y < width; y++) { + b1 = frameBuffer[x + width * y] + if (b1 == b) { + badBuffer[h]++ + } else { + badBuffer[++h] = 1 + } + + b = b1 + } + + bad += getBadRuns(h) + } + + return bad + } + function toUtf8(str : string) : string { + let out = '' + let i = 0 + let len = 0 + let c = 0 + len = str.length; + for (i = 0; i < len; i++) { + c = str.charCodeAt(i)!; + if ((c >= 0x0001) && (c <= 0x007F)) { + out += str.charAt(i); + } else if (c > 0x07FF) { + out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); + out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); + out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); + } else { + out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); + out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); + } + } + return out; + } + + //end functions + + // Find the smallest version that fits the string. + str = toUtf8(str) + t = str.length + + + version = 0 + + do { + version++ + k = (eccLevel - 1) * 4 + (version - 1) * 16 + neccBlock1 = ECC_BLOCKS[k++] + neccBlock2 = ECC_BLOCKS[k++] + dataBlock = ECC_BLOCKS[k++] + eccBlock = ECC_BLOCKS[k] + + k = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 - 3 + (version <= 9?1:0) + + if (t <= k) break + } while (version < 40) + + // FIXME: Ensure that it fits insted of being truncated. + width = 17 + 4 * version + + // Allocate, clear and setup data structures. + v = dataBlock + (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2 + + for (t = 0; t < v; t++) { + eccBuffer.push(0) + } + + // -------------------------------------------------------------------------------------- + let stringBufferLength = str.length + let stringBack = str.slice(0) + + + + // -------------------------------------------------------------------------------------- + + for (t = 0; t < width * width; t++) { + frameBuffer.push(0) + } + + for (t = 0; t < (width * (width + 1) + 1) / 2; t++) { + frameMask.push(0) + } + + // Insert finders: Foreground colour to frame and background to mask. + for (t = 0; t < 3; t++) { + k=0 + y=0 + if (t == 1) k = (width - 7) + if (t == 2) y = (width - 7) + + frameBuffer[(y + 3) + width * (k + 3)] = 1 + + for (x = 0; x < 6; x++) { + frameBuffer[(y + x) + width * k] = 1 + frameBuffer[y + width * (k + x + 1)] = 1 + frameBuffer[(y + 6) + width * (k + x)] = 1 + frameBuffer[(y + x + 1) + width * (k + 6)] = 1 + } + + for (x = 1; x < 5; x++) { + setMask(y + x, k + 1) + setMask(y + 1, k + x + 1) + setMask(y + 5, k + x) + setMask(y + x + 1, k + 5) + } + + for (x = 2; x < 4; x++) { + frameBuffer[(y + x) + width * (k + 2)] = 1 + frameBuffer[(y + 2) + width * (k + x + 1)] = 1 + frameBuffer[(y + 4) + width * (k + x)] = 1 + frameBuffer[(y + x + 1) + width * (k + 4)] = 1 + } + } + + // Alignment blocks. + if (version > 1) { + t = ALIGNMENT_DELTA[version] + y = width - 7 + + for (; ;) { + x = width - 7 + + while (x > t - 3) { + addAlignment(x, y) + + if (x < t) break + + x -= t + } + + if (y <= t + 9) break + + y -= t + + addAlignment(6, y) + addAlignment(y, 6) + } + } + + // Single foreground cell. + frameBuffer[8 + width * (width - 8)] = 1 + + // Timing gap (mask only). + for (y = 0; y < 7; y++) { + setMask(7, y) + setMask(width - 8, y) + setMask(7, y + width - 7) + } + + for (x = 0; x < 8; x++) { + setMask(x, 7) + setMask(x + width - 8, 7) + setMask(x, width - 8) + } + + // Reserve mask, format area. + for (x = 0; x < 9; x++) { + setMask(x, 8) + } + + for (x = 0; x < 8; x++) { + setMask(x + width - 8, 8) + setMask(8, x) + } + + for (y = 0; y < 7; y++) { + setMask(8, y + width - 7) + } + + // Timing row/column. + for (x = 0; x < width - 14; x++) { + if ((x & 1)>0) { + setMask(8 + x, 6) + setMask(6, 8 + x) + } else { + frameBuffer[(8 + x) + width * 6] = 1 + frameBuffer[6 + width * (8 + x)] = 1 + } + } + + // Version block. + if (version > 6) { + t = VERSION_BLOCK[version - 7] + k = 17 + + for (x = 0; x < 6; x++) { + for (y = 0; y < 3; y++) { + if ((1 & (k > 11 ? version >> (k - 12) : t >> k))>0) { + frameBuffer[(5 - x) + width * (2 - y + width - 11)] = 1 + frameBuffer[(2 - y + width - 11) + width * (5 - x)] = 1 + } else { + setMask(5 - x, 2 - y + width - 11) + setMask(2 - y + width - 11, 5 - x) + } + k-- + } + } + } + + // Sync mask bits. Only set above for background cells, so now add the foreground. + for (y = 0; y < width; y++) { + for (x = 0; x <= y; x++) { + if (frameBuffer[x + width * y]>0) { + setMask(x, y) + } + } + } + + // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanum, or kanji + // not supported). + v = stringBufferLength + + // stringBuffer = str.slice(0) + + // String to array. + for (i = 0; i < v; i++) { + // #ifdef APP-ANDROID + eccBuffer[i.toInt()] = stringBack.charCodeAt(i)! + // #endif + // #ifndef APP-ANDROID + eccBuffer[i] = stringBack.charCodeAt(i)! + // #endif + } + + //++++++++++++++++++++===================== + + stringBuffer = eccBuffer.slice(0) + + // Calculate max string length. + x = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 + + if (v >= x - 2) { + v = x - 2 + + if (version > 9) v-- + } + + + // Shift and re-pack to insert length prefix. + i = v + + if (version > 9) { + stringBuffer[i + 2] = 0 + stringBuffer[i + 3] = 0 + + while ((i--)>0) { + t = stringBuffer[i] + + stringBuffer[i + 3] |= 255 & (t << 4) + stringBuffer[i + 2] = t >> 4 + } + + stringBuffer[2] |= 255 & (v << 4) + stringBuffer[1] = v >> 4 + stringBuffer[0] = 0x40 | (v >> 12) + } else { + stringBuffer[i + 1] = 0 + stringBuffer[i + 2] = 0 + + while ((i--)>0) { + t = stringBuffer[i] + + stringBuffer[i + 2] |= 255 & (t << 4) + stringBuffer[i + 1] = t >> 4 + } + + stringBuffer[1] |= 255 & (v << 4) + stringBuffer[0] = 0x40 | (v >> 4) + } + + + // Fill to end with pad pattern. + i = v + 3 - (version < 10?1:0) + + while (i < x) { + stringBuffer[i++] = 0xec + stringBuffer[i++] = 0x11 + } + + // Calculate generator polynomial. + for (i = 0; i <= eccBlock; i++) { + polynomial.push(0) + } + polynomial[0] = 1 + + for (i = 0; i < eccBlock; i++) { + polynomial[i + 1] = 1 + + for (j = i; j > 0; j--) { + polynomial[j] = polynomial[j]>0 ? polynomial[j - 1] ^ + GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[j]] + i)] : polynomial[j - 1] + } + + polynomial[0] = GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[0]] + i)] + } + + + + // Use logs for generator polynomial to save calculation step. + for (i = 0; i < eccBlock; i++) { + polynomial[i] = GALOIS_LOG[polynomial[i]] + } + + + // Append ECC to data buffer. + k = x + y = 0 + + for (i = 0; i < neccBlock1; i++) { + appendData(y, dataBlock, k, eccBlock) + + y += dataBlock + k += eccBlock + } + + for (i = 0; i < neccBlock2; i++) { + appendData(y, dataBlock + 1, k, eccBlock) + + y += dataBlock + 1 + k += eccBlock + } + + // Interleave blocks. + y = 0 + + for (i = 0; i < dataBlock; i++) { + for (j = 0; j < neccBlock1; j++) { + eccBuffer[y++] = stringBuffer[i + j * dataBlock] + } + + for (j = 0; j < neccBlock2; j++) { + eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))] + } + } + + for (j = 0; j < neccBlock2; j++) { + eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))] + } + + for (i = 0; i < eccBlock; i++) { + for (j = 0; j < neccBlock1 + neccBlock2; j++) { + eccBuffer[y++] = stringBuffer[x + i + j * eccBlock] + } + } + + stringBuffer = eccBuffer + + // Pack bits into frame avoiding masked area. + x = width - 1 + y = width - 1 + k = 1 + v = 1 + + + + // inteleaved data and ECC codes. + m = (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2 + + for (i = 0; i < m; i++) { + t = stringBuffer[i] + + for (j = 0; j < 8; j++) { + if ((0x80 & t)>0) { + frameBuffer[x + width * y] = 1 + } + + // Find next fill position. + do { + if (v>0) { + x-- + } else { + x++ + + if (k>0) { + if (y !== 0) { + y-- + } else { + x -= 2 + k = k==0?1:0 + + if (x == 6) { + x-- + y = 9 + } + } + } else { + if (y !== width - 1) { + y++ + } else { + x -= 2 + k = k==0?1:0 + + if (x == 6) { + x-- + y -= 8 + } + } + } + } + + v = v==0?1:0 + } while (isMasked(x, y)) + t <<= 1 + } + } + + // Save pre-mask copy of frame. + stringBuffer = frameBuffer.slice(0) + + + + + + + t = 0 + y = 30000 + + // Using `for` instead of `while` since in original Arduino code if an early mask was *good + // enough* it wouldn't try for a better one since they get more complex and take longer. + for (k = 0; k < 8; k++) { + // Returns foreground-background imbalance. + applyMask(k) + + x = checkBadness() + + // Is current mask better than previous best? + if (x < y) { + y = x + t = k + } + + // Don't increment `i` to a void redoing mask. + if (t == 7) break + + // Reset for next pass. + frameBuffer = stringBuffer.slice(0) + } + + // Redo best mask as none were *good enough* (i.e. last wasn't `t`). + if (t !== k) { + applyMask(t) + } + + // Add in final mask/ECC level bytes. + y = FINAL_FORMAT[t + ((eccLevel - 1) << 3)] + + // Low byte. + for (k = 0; k < 8; k++) { + if ((y & 1)>0) { + frameBuffer[(width - 1 - k) + width * 8] = 1 + + if (k < 6) { + frameBuffer[8 + width * k] = 1 + } else { + frameBuffer[8 + width * (k + 1)] = 1 + } + } + y >>= 1 + } + + // High byte. + for (k = 0; k < 7; k++) { + if ((y & 1)>0) { + frameBuffer[8 + width * (width - 7 + k)] = 1 + + if (k>0) { + frameBuffer[(6 - k) + width * 8] = 1 + } else { + frameBuffer[7 + width * 8] = 1 + } + } + y >>= 1 + } + + // Finally, return the image data. + return { + frameBuffer: frameBuffer + , width: width + } as GenerateFrameResult +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-qrcoder/x-qrcoder.uvue b/uni_modules/tmx-ui/components/x-qrcoder/x-qrcoder.uvue new file mode 100644 index 0000000..96671c6 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-qrcoder/x-qrcoder.uvue @@ -0,0 +1,361 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-radio-button/x-radio-button.uvue b/uni_modules/tmx-ui/components/x-radio-button/x-radio-button.uvue new file mode 100644 index 0000000..4caf5ce --- /dev/null +++ b/uni_modules/tmx-ui/components/x-radio-button/x-radio-button.uvue @@ -0,0 +1,379 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-radio-group/x-radio-group.uvue b/uni_modules/tmx-ui/components/x-radio-group/x-radio-group.uvue new file mode 100644 index 0000000..12910ed --- /dev/null +++ b/uni_modules/tmx-ui/components/x-radio-group/x-radio-group.uvue @@ -0,0 +1,171 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-radio/x-radio.uvue b/uni_modules/tmx-ui/components/x-radio/x-radio.uvue new file mode 100644 index 0000000..f641078 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-radio/x-radio.uvue @@ -0,0 +1,404 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-rate/x-rate.uvue b/uni_modules/tmx-ui/components/x-rate/x-rate.uvue new file mode 100644 index 0000000..ad7ed82 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-rate/x-rate.uvue @@ -0,0 +1,569 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-rolling-number/x-rolling-number.uvue b/uni_modules/tmx-ui/components/x-rolling-number/x-rolling-number.uvue new file mode 100644 index 0000000..367a1b4 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-rolling-number/x-rolling-number.uvue @@ -0,0 +1,323 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-row/x-row.uvue b/uni_modules/tmx-ui/components/x-row/x-row.uvue new file mode 100644 index 0000000..6ee90c9 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-row/x-row.uvue @@ -0,0 +1,73 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-scrollx/x-scrollx.uvue b/uni_modules/tmx-ui/components/x-scrollx/x-scrollx.uvue new file mode 100644 index 0000000..db6fbd4 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-scrollx/x-scrollx.uvue @@ -0,0 +1,215 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-search/x-search.uvue b/uni_modules/tmx-ui/components/x-search/x-search.uvue new file mode 100644 index 0000000..41018bc --- /dev/null +++ b/uni_modules/tmx-ui/components/x-search/x-search.uvue @@ -0,0 +1,290 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-sheet/x-sheet.uvue b/uni_modules/tmx-ui/components/x-sheet/x-sheet.uvue new file mode 100644 index 0000000..b762b15 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-sheet/x-sheet.uvue @@ -0,0 +1,246 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-sign-board/x-sign-board.uvue b/uni_modules/tmx-ui/components/x-sign-board/x-sign-board.uvue new file mode 100644 index 0000000..20898e0 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-sign-board/x-sign-board.uvue @@ -0,0 +1,427 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-skeleton/x-skeleton.uvue b/uni_modules/tmx-ui/components/x-skeleton/x-skeleton.uvue new file mode 100644 index 0000000..c052762 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-skeleton/x-skeleton.uvue @@ -0,0 +1,129 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slide-verify/x-slide-verify.uvue b/uni_modules/tmx-ui/components/x-slide-verify/x-slide-verify.uvue new file mode 100644 index 0000000..7990ba7 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slide-verify/x-slide-verify.uvue @@ -0,0 +1,675 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider-children/x-slider-children.uvue b/uni_modules/tmx-ui/components/x-slider-children/x-slider-children.uvue new file mode 100644 index 0000000..76a6e14 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider-children/x-slider-children.uvue @@ -0,0 +1,346 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider-double/x-slider-double.uvue b/uni_modules/tmx-ui/components/x-slider-double/x-slider-double.uvue new file mode 100644 index 0000000..50d25bf --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider-double/x-slider-double.uvue @@ -0,0 +1,862 @@ + + + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider-double/xfs.wxs b/uni_modules/tmx-ui/components/x-slider-double/xfs.wxs new file mode 100644 index 0000000..503a91f --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider-double/xfs.wxs @@ -0,0 +1,117 @@ +var _x = 0 +var _realx = 0 +var _y = 0 +var isMoving = false +var leftPos = 0 +var opts = { + disabled: false, + max: 0, + min: 0, + step: 1, + _step: 0, + btnSize: 0, + boxwidth: 0, + boxLeft:[0,0] +} +var btnIndex = 0 +function isLeftOrRight(a, b, c, diffX) { + if (diffX > 0) { + return c; + } else if (diffX < 0) { + return a; + } + return b; +} + +function mStart(evt, ins,lindex) { + if (opts.disabled) return false; + btnIndex = lindex; + _realx = evt.changedTouches[0].clientX; + var ele1 = ins.selectComponent('.xSliderBtn') + var ele2 = ins.selectComponent('.xSliderBtn2') + var ele = lindex == 0 ? ele1 : ele2 + opts = ele.getDataset().opts; + + leftPos = parseFloat(ele.getComputedStyle(['left']).left) + _x = evt.changedTouches[0].clientX - leftPos; + _y = evt.changedTouches[0].clientY; + isMoving = false + ins.callMethod('setOpts', { + isMoveIndex: btnIndex + }) + return false +} + +function mMove(evt, ins) { + var ele1 = ins.selectComponent('.xSliderBtn') + var ele2 = ins.selectComponent('.xSliderBtn2') + var ele = btnIndex == 0 ? ele1 : ele2 + var bgid = ele.getDataset().bgid; + if (opts.disabled) return false; + isMoving = true + + var x = evt.changedTouches[0].clientX - _x + var diffX = evt.changedTouches[0].clientX - _realx + var maxX = opts.boxwidth - opts.btnSize; + + if (opts.step > 0) { + var step = opts._step; + var distanceToMove = Math.abs(diffX); + + // 优化:提高步值对齐精度 + var qz = Math.round(x / step) * step; + + if (distanceToMove > 1) { + x = isLeftOrRight(qz - step, x, qz + step, diffX); + } + + } + + x = Math.max(Math.min(maxX,x),0) + + ele.setStyle({ + 'left': x + 'px' + }) + + var bgNode = ins.selectComponent('#'+bgid) + opts.boxLeft[btnIndex] = x + var minwidth = Math.abs(opts.boxLeft[0] - opts.boxLeft[1])+5 + var minleft = Math.min(opts.boxLeft[0], opts.boxLeft[1])+5 + bgNode.setStyle({ + 'left': minleft + 'px', + 'width': minwidth + 'px', + }) + + ins.callMethod('setOpts', { + x: x, + index:btnIndex, + isMoveIndex:btnIndex, + boxLeft:opts.boxLeft + }) + ins.callMethod('setMoveChanges', { + x: x, + index:btnIndex + }) + + + + return false +} + +function mEnd(evt, ins) { + if (opts.disabled) return false; + var ele1 = ins.selectComponent('.xSliderBtn') + var ele2 = ins.selectComponent('.xSliderBtn2') + var ele = btnIndex == 0 ? ele1 : ele2 + ins.callMethod('setMoveEnd') + return false +} + +module.exports = { + mStart: function(evt, ins){mStart(evt, ins,0)}, + mMove: function(evt, ins){mMove(evt, ins,0)}, + mEnd: function(evt, ins){mEnd(evt, ins,0)}, + mStart2: function(evt, ins){mStart(evt, ins,1)}, + mMove2: function(evt, ins){mMove(evt, ins,1)}, + mEnd2: function(evt, ins){mEnd(evt, ins,1)}, +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider-menu/x-slider-menu.uvue b/uni_modules/tmx-ui/components/x-slider-menu/x-slider-menu.uvue new file mode 100644 index 0000000..6c1e5e9 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider-menu/x-slider-menu.uvue @@ -0,0 +1,587 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider-tree/interface.uts b/uni_modules/tmx-ui/components/x-slider-tree/interface.uts new file mode 100644 index 0000000..d2fc209 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider-tree/interface.uts @@ -0,0 +1,13 @@ + /** + * 侧边分类数据 + */ + export type SLIDER_TREE_ITEM = { + id : string, + title : string, + children : SLIDER_TREE_ITEM[], + disabled : boolean, + /** 当前选中的id数组 */ + selected : string[], + //左侧小图标. + icon:string + } \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider-tree/util.uts b/uni_modules/tmx-ui/components/x-slider-tree/util.uts new file mode 100644 index 0000000..0409054 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider-tree/util.uts @@ -0,0 +1,40 @@ +import { SLIDER_TREE_ITEM } from "./interface.uts" +/** + * 当前树有多少个被选中了。 + */ +export function getTreeSelectedNum(item: SLIDER_TREE_ITEM[],target:Set):number{ + let inx = 0; + function jshz(tree : SLIDER_TREE_ITEM[]) { + for (let i = 0; i < tree.length; i++) { + let item = tree[i] + if (item.children.length > 0) { + jshz(item.children) + } else if (target.has(item.id)) { + inx += 1 + } + } + } + jshz(item) + return inx; +} + +/** + * 根据目标节点,过滤掉父节点。 + * @param item + * @param target + */ +export function filterParentNode(item: SLIDER_TREE_ITEM[],target:Set):string[]{ + function jshz(tree : SLIDER_TREE_ITEM[]):string[] { + let arr = [] as string[] + for (let i = 0; i < tree.length; i++) { + let items = tree[i] + if (items.children.length > 0) { + arr = arr.concat(jshz(items.children)) + }else if (target.has(items.id)) { + arr.push(items.id) + } + } + return arr; + } + return jshz(item) +} diff --git a/uni_modules/tmx-ui/components/x-slider-tree/x-slider-tree.uvue b/uni_modules/tmx-ui/components/x-slider-tree/x-slider-tree.uvue new file mode 100644 index 0000000..740815d --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider-tree/x-slider-tree.uvue @@ -0,0 +1,416 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider/x-slider.uvue b/uni_modules/tmx-ui/components/x-slider/x-slider.uvue new file mode 100644 index 0000000..ca4ae88 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider/x-slider.uvue @@ -0,0 +1,723 @@ + + + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-slider/xfs.wxs b/uni_modules/tmx-ui/components/x-slider/xfs.wxs new file mode 100644 index 0000000..497554e --- /dev/null +++ b/uni_modules/tmx-ui/components/x-slider/xfs.wxs @@ -0,0 +1,92 @@ +var _x = 0 +var _realx = 0 +var _y = 0 +var isMoving = false +var leftPos = 0 +var opts = { + disabled: false, + max: 0, + min: 0, + step: 1, + _step: 0, + btnSize: 0, + boxwidth: 0 +} + +function isLeftOrRight(a, b, c, diffX) { + if (diffX > 0) { + return c; + } else if (diffX < 0) { + return a; + } + return b; +} + +function mStart(evt, ins) { + if (opts.disabled) return false; + + _realx = evt.changedTouches[0].clientX; + + var ele = ins.selectComponent('.xSliderBtn') + opts = ele.getDataset().opts; + leftPos = parseFloat(ele.getComputedStyle(['left']).left) + _x = evt.changedTouches[0].clientX - leftPos; + _y = evt.changedTouches[0].clientY; + isMoving = false + ins.callMethod('setOpts', { + isMoving: isMoving + }) + return false +} + +function mMove(evt, ins) { + var ele = ins.selectComponent('.xSliderBtn') + if (opts.disabled) return false; + isMoving = true + ins.callMethod('setOpts', { + isMoving: isMoving + }) + var x = evt.changedTouches[0].clientX - _x + var diffX = evt.changedTouches[0].clientX - _realx + var maxX = opts.boxwidth - opts.btnSize; + + if (opts.step > 0) { + var step = opts._step; + var distanceToMove = Math.abs(diffX); + + // 优化:提高步值对齐精度 + var qz = Math.round(x / step) * step; + + if (distanceToMove > 1) { + x = isLeftOrRight(qz - step, x, qz + step, diffX); + } + + } + + x = Math.max(Math.min(maxX,x),0) + + ele.setStyle({ + 'left': x + 'px' + }) + ins.callMethod('setMoveChanges', { + x: x + }) + + var bgNode = ins.selectComponent('.xSliderBg') + bgNode.setStyle({ + 'width': (x+4) + 'px', + }) + return false +} + +function mEnd(evt, ins) { + if (opts.disabled) return false; + ins.callMethod('setEnd') + return false +} + +module.exports = { + mStart: mStart, + mMove: mMove, + mEnd: mEnd +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-snackbar-item/x-snackbar-item.uvue b/uni_modules/tmx-ui/components/x-snackbar-item/x-snackbar-item.uvue new file mode 100644 index 0000000..6294001 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-snackbar-item/x-snackbar-item.uvue @@ -0,0 +1,196 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-snackbar/interface.uts b/uni_modules/tmx-ui/components/x-snackbar/interface.uts new file mode 100644 index 0000000..8953ba5 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-snackbar/interface.uts @@ -0,0 +1 @@ +export type positionType = "top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right" \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-snackbar/x-snackbar.uvue b/uni_modules/tmx-ui/components/x-snackbar/x-snackbar.uvue new file mode 100644 index 0000000..f6c8a9f --- /dev/null +++ b/uni_modules/tmx-ui/components/x-snackbar/x-snackbar.uvue @@ -0,0 +1,252 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-stepper/x-stepper.uvue b/uni_modules/tmx-ui/components/x-stepper/x-stepper.uvue new file mode 100644 index 0000000..4132ed9 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-stepper/x-stepper.uvue @@ -0,0 +1,410 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-steps-item/x-steps-item.uvue b/uni_modules/tmx-ui/components/x-steps-item/x-steps-item.uvue new file mode 100644 index 0000000..c6b8c1c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-steps-item/x-steps-item.uvue @@ -0,0 +1,424 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-steps/interface.uts b/uni_modules/tmx-ui/components/x-steps/interface.uts new file mode 100644 index 0000000..48c25d6 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-steps/interface.uts @@ -0,0 +1,4 @@ +export type CHIDREN_ITEM = { + id:string, + ele:XStepsItemComponentPublicInstance +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-steps/x-steps.uvue b/uni_modules/tmx-ui/components/x-steps/x-steps.uvue new file mode 100644 index 0000000..c8e345a --- /dev/null +++ b/uni_modules/tmx-ui/components/x-steps/x-steps.uvue @@ -0,0 +1,213 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-sticky/x-sticky.uvue b/uni_modules/tmx-ui/components/x-sticky/x-sticky.uvue new file mode 100644 index 0000000..8c1c7c3 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-sticky/x-sticky.uvue @@ -0,0 +1,182 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-swiper-item/x-swiper-item.uvue b/uni_modules/tmx-ui/components/x-swiper-item/x-swiper-item.uvue new file mode 100644 index 0000000..bf9ae51 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-swiper-item/x-swiper-item.uvue @@ -0,0 +1,580 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-swiper/interface.uts b/uni_modules/tmx-ui/components/x-swiper/interface.uts new file mode 100644 index 0000000..553157b --- /dev/null +++ b/uni_modules/tmx-ui/components/x-swiper/interface.uts @@ -0,0 +1,13 @@ +export type SWIPER_ITEM = { + id : string, + order:number, + ele : XSwiperItemComponentPublicInstance +} +export type POSITON = { + x : number, + y : number +} +export type SIZE = { + width : number, + height : number +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-swiper/x-swiper.uvue b/uni_modules/tmx-ui/components/x-swiper/x-swiper.uvue new file mode 100644 index 0000000..627fc28 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-swiper/x-swiper.uvue @@ -0,0 +1,1149 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-switch-slider/x-switch-slider.uvue b/uni_modules/tmx-ui/components/x-switch-slider/x-switch-slider.uvue new file mode 100644 index 0000000..b48834a --- /dev/null +++ b/uni_modules/tmx-ui/components/x-switch-slider/x-switch-slider.uvue @@ -0,0 +1,670 @@ + + + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-switch-slider/xfs.wxs b/uni_modules/tmx-ui/components/x-switch-slider/xfs.wxs new file mode 100644 index 0000000..414db79 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-switch-slider/xfs.wxs @@ -0,0 +1,167 @@ +var _x = 0 +var _realx = 0 +var _y = 0 +var isMoving = false +var leftPos = 0 +var menuwidth = 0 +var opts = { + disabled: false, + slideX:0, + duration:0, + animationFun:"cubic-bezier(.42,.38,.15,.93)", + threshold:10, + opened:false +} +var dirs = "right" +var newDirs = "right" +var dateTime = 0 +var isSwiper = 'none'; +var _diff_x = 0 + +function mStart(evt, ins) { + ins.callMethod('callEmits', {name:"start"}) + dateTime = Date.now() + _realx = evt.changedTouches[0].clientX; + _diff_x = evt.changedTouches[0].clientX; + var ele = ins.selectComponent('.xSwitchSilderWrap') + var itemMenuele = ins.selectComponent('.xSwitchSilderItems') + menuwidth = itemMenuele.getBoundingClientRect().width + opts = ele.getDataset().opts; + if (opts.disabled) return false; + leftPos = parseFloat(ele.getComputedStyle(['left']).left) + dirs = opts.opened ? "left" : "right" + newDirs = dirs + ele.setStyle({ + 'left': leftPos + 'px', + 'transition-duration':'0ms', + 'transition-timing-function':opts.animationFun + }) + + _x = evt.changedTouches[0].clientX - leftPos; + _y = evt.changedTouches[0].clientY; + isMoving = true + isSwiper = 'none'; + ins.callMethod('setOpts', { + isMove: isMoving, + isSwiper:isSwiper + }) + +z} + +function mMove(evt, ins) { + ins.callMethod('callEmits', {name:"move"}) + var ele = ins.selectComponent('.xSwitchSilderWrap') + if (opts.disabled) return true; + var x = evt.changedTouches[0].clientX - _x + var dreal_iff_x = evt.changedTouches[0].clientX - _diff_x + var diffx = Math.abs(evt.changedTouches[0].clientX - _realx) + var diffy = Math.abs(evt.changedTouches[0].clientY - _y) + // 判断是否有明显的方向 + var hasDirection = Math.max(diffx, diffy) > 10 + // 判断是否为水平方向 + var isHorizontal = diffx > diffy + if(hasDirection && isSwiper == 'none'){ + if (isHorizontal) { + // 水平滑动,启用左滑并阻止页面滚动 + isSwiper = 'swiper' + // evt.preventDefault() + // evt.stopPropagation() + } else { + // 垂直滑动,禁用左滑 + isSwiper = 'off' + } + + } + + ins.callMethod('setOpts', { + isSwiper:isSwiper + }) + + if(isSwiper == 'swiper'){ + x = Math.min(0, x) + x = Math.max(-menuwidth, x) + + ele.setStyle({ + 'left': x + 'px' + }) + + if (Math.abs(x) > opts.threshold) { + + if (dreal_iff_x > 0) { + newDirs = "right" + } else { + newDirs = "left" + } + } + + _diff_x = evt.changedTouches[0].clientX + + return true; + } + +} + +function mEnd(evt, ins) { + ins.callMethod('callEmits', {name:"end"}) + + var diffdate = Date.now() - dateTime + var diffx = evt.changedTouches[0].clientX - _realx + var diffy = evt.changedTouches[0].clientY - _y + if(Math.abs(diffx) == Math.abs(diffy) && diffx==0 && diffdate>50&&diffdate<=250){ + ins.callMethod('callEmits', {name:"click"}) + } + if (opts.disabled || isSwiper=='off') return false; + var ele = ins.selectComponent('.xSwitchSilderWrap') + var event = evt.changedTouches[0]; + + var diffX = evt.changedTouches[0].clientX - _realx + + var x = 0; + if(newDirs == 'left'){ + x = -menuwidth + } + + ele.setStyle({ + 'left': x + 'px', + 'transition-duration':opts.duration+'ms', + 'transition-timing-function':opts.animationFun + }) + if(diffX==0||dirs == newDirs){ + return; + } + dirs = newDirs + var opened = x>=0?false:true + ins.callMethod('setOpts', { + isMove: isMoving, + isSwiper:isSwiper, + opened:opened + }) + if(opts.opened!=opened){ + ins.callMethod('callEmits', {name:opened?'open':"close"}) + } + + opts.opened = opened +} +function setTatus(status,instance){ + var ele = instance.selectComponent('.xSwitchSilderWrap') + var itemMenuele = instance.selectComponent('.xSwitchSilderItems') + menuwidth = itemMenuele.getBoundingClientRect().width + var x = opts.opened?-menuwidth:0 + ele.setStyle({ + 'left': x + 'px', + 'transition-duration':opts.duration+'ms', + 'transition-timing-function':opts.animationFun + }) +} +module.exports = { + mStart: mStart, + mMove: mMove, + mEnd: mEnd, + propObserver: function(newValue, oldValue, ownerInstance, instance) { + var ele = ownerInstance.selectComponent('.xSwitchSilderWrap') + opts = ele.getDataset().opts; + if(newValue!=undefined&&oldValue!=undefined&&newValue!=oldValue){ + setTatus(newValue,ownerInstance) + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-switch/x-switch.uvue b/uni_modules/tmx-ui/components/x-switch/x-switch.uvue new file mode 100644 index 0000000..80a0b25 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-switch/x-switch.uvue @@ -0,0 +1,322 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tabbar/interface.uts b/uni_modules/tmx-ui/components/x-tabbar/interface.uts new file mode 100644 index 0000000..026a0ce --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tabbar/interface.uts @@ -0,0 +1,11 @@ +export type xTabbarCanvasDrawProps = { + bgColor:string, + bgLigth:string[], + listCount:number, + img:string, + /** 1正常背景,2渐变,3背景图 */ + bgType:1|2|3, + active:number, + /** 1 向下凹陷,2向上凸起 */ + tuqiType:1|2 +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tabbar/x-tabbar.uvue b/uni_modules/tmx-ui/components/x-tabbar/x-tabbar.uvue new file mode 100644 index 0000000..40a820c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tabbar/x-tabbar.uvue @@ -0,0 +1,777 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tabbar/xTabbarCanvas.uts b/uni_modules/tmx-ui/components/x-tabbar/xTabbarCanvas.uts new file mode 100644 index 0000000..232d2fa --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tabbar/xTabbarCanvas.uts @@ -0,0 +1,210 @@ +import { xTabbarCanvasDrawProps } from "./interface.uts" +export default class xTabbarCanvas { + dom : UniCanvasElement + ctx : CanvasRenderingContext2D + tuqiSize : number = 60 + toQiSafeTop : number = 25 + dpr : number = 0; + loadimgs : Image | null = null; + callback:()=>void = ()=>{}; + domWidth=0 + domHeight=0 + domOffsetWidth=0 + domOffsetHeight=0 + imgObj = null as any|null; + safeHeight = 0 + constructor(dom : UniCanvasElement,content:CanvasRenderingContext2D, safeHeight : number,w : number,h : number,ofw : number,ofh : number,imamp:any|null) { + const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1; + this.domWidth = w; + this.domHeight = h; + this.safeHeight = safeHeight + this.domOffsetWidth = ofw; + this.domOffsetHeight = ofh; + this.imgObj = imamp; + this.dpr = dpr; + this.dom = dom + this.ctx = content + + } + addRestoredListener(fun:()=>void){ + this.callback = fun + } + + /** 绘制图片背景 */ + fillBgImage(color : string, activeIndex : number) { + let ctx = this.ctx; + ctx.save() + ctx.fillStyle = color + ctx.fillRect(0, activeIndex > -1 ? this.toQiSafeTop : 0, this.domWidth, this.domHeight) + ctx.restore() + } + + setTuQi(count : number, activeIndex : number) { + let t = this; + if (activeIndex == -1) return; + let width = this.dom.offsetWidth; + + let height = this.domHeight; + let itemwidth = width / count; + + let ctx = this.ctx; + ctx.globalCompositeOperation = 'destination-out' + let space = 2 + // ctx.fillStyle = "#ff0000" + + let size = this.tuqiSize + space * 2; + let r = size / 2; + + + if (this.loadimgs != null) { + this.loadimgs?.remove() + } + // #ifdef APP||WEB + this.loadimgs = new Image(164, 70) + // #endif + // #ifdef MP-WEIXIN + this.loadimgs = this.imgObj + // #endif + + this.loadimgs!.src = '/static/tmui4xLibs/static/tabaarMasker.png' + let x = itemwidth * (activeIndex + 1) - itemwidth / 2 + + this.loadimgs!.onload = () => { + + // #ifdef WEB + ctx.drawImage(t.loadimgs!, x - 82 / 2, this.toQiSafeTop, 82, 38) + // #endif + + // #ifdef APP-IOS + ctx.drawImage(t.loadimgs!, x - 84 / 2, this.toQiSafeTop, 85, 38) + // #endif + + // #ifdef APP-ANDROID + ctx.drawImage(t.loadimgs!, x - 85 / 2, this.toQiSafeTop, 86, 38) + // #endif + + } + + } + setTuQiTop(color : string[], count : number, activeIndex : number) { + let t = this; + if (this.loadimgs != null) { + this.loadimgs = null; + } + if (activeIndex == -1) return; + let width = this.dom.offsetWidth; + + let height = this.domHeight; + let itemwidth = width / count; + + let ctx = this.ctx; + // ctx.save() + // ctx.fillStyle = 'red' + ctx.globalCompositeOperation = 'source-over' + ctx.clearRect(0, 0, this.domWidth, this.domHeight) + // ctx.fillRect(0,0,100,25) + + + + let space = 2 + let size = this.tuqiSize + space * 2; + let r = size / 2; + // ctx.globalCompositeOperation = 'source-atop' + // #ifdef APP||WEB + this.loadimgs = new Image(152, 50) + // #endif + // #ifdef MP-WEIXIN + this.loadimgs = this.imgObj + // #endif + this.loadimgs!.src = '/static/tmui4xLibs/static/tabaarMaskerTop.png' + let x = itemwidth * (activeIndex + 1) - itemwidth / 2 + + this.loadimgs!.onload = () => { + ctx.save() + ctx.drawImage(t.loadimgs!, x - 76 / 2, 0, 76, 25) + ctx.restore() + ctx.globalCompositeOperation = 'source-atop' + if(color.length==1){ + ctx.fillStyle = color[0] + }else{ + let liner = ctx.createLinearGradient(0, this.toQiSafeTop / 2, this.domWidth, this.toQiSafeTop / 2) + liner.addColorStop(0, color[1]) + liner.addColorStop(0.5, color[2]) + ctx.fillStyle = liner + } + ctx.fillRect(0, 0, this.domWidth, this.toQiSafeTop) + } + } + + draw(props:xTabbarCanvasDrawProps){ + let ctx = this.ctx; + ctx.globalCompositeOperation = 'source-over' + // 向上凸起。 + //先绘制背景。如果有凸起 + if(props.active>-1){ + + // 凸起类型。 + if(props.tuqiType==1){ + + if(props.bgType==1){ + ctx.fillStyle = props.bgColor + ctx.fillRect(0, this.toQiSafeTop, this.domWidth, this.domHeight) + }else if(props.bgType == 2){ + let liner = ctx.createLinearGradient(0,this.domHeight / 2 + this.toQiSafeTop, this.domWidth, this.domHeight / 2 + this.toQiSafeTop) + liner.addColorStop(0, props.bgLigth[1]) + liner.addColorStop(0.5, props.bgLigth[2]) + ctx.fillStyle = liner + ctx.fillRect(0, this.toQiSafeTop, this.domWidth, this.domHeight+this.safeHeight) + }else if(props.bgType==3){ + //图片 + } + + + // 绘制镂空。 + this.setTuQi(props.listCount,props.active) + }else if(props.tuqiType==2){ + + if(props.bgType==1){ + // 绘制镂空。 + this.setTuQiTop([props.bgColor] as string[],props.listCount,props.active) + ctx.globalCompositeOperation = 'source-over' + ctx.fillStyle = props.bgColor + ctx.fillRect(0, this.toQiSafeTop, this.domWidth, this.domHeight) + }else if(props.bgType == 2){ + // 绘制镂空。 + this.setTuQiTop(props.bgLigth,props.listCount,props.active) + ctx.globalCompositeOperation = 'source-over' + let liner = ctx.createLinearGradient(0,this.domHeight / 2, this.domWidth, this.domHeight / 2) + liner.addColorStop(0, props.bgLigth[1]) + liner.addColorStop(0.5, props.bgLigth[2]) + ctx.fillStyle = liner + ctx.fillRect(0, this.toQiSafeTop, this.domWidth, this.domHeight) + }else if(props.bgType==3){ + //图片 + } + + } + + }else{ + //绘制背景类型。 + if(props.bgType==1){ + ctx.fillStyle = props.bgColor + ctx.fillRect(0, 0, this.domWidth, this.domHeight) + } + else if(props.bgType==2){ + let liner = ctx.createLinearGradient(0,this.domHeight / 2, this.domWidth, this.domHeight / 2) + liner.addColorStop(0, props.bgLigth[1]) + liner.addColorStop(0.5, props.bgLigth[2]) + ctx.fillStyle = liner + ctx.fillRect(0, 0, this.domWidth, this.domHeight) + } + else if(props.bgType==3){ + //图片 + } + } + } + destory() { + + this.loadimgs = null; + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-table/x-table.uvue b/uni_modules/tmx-ui/components/x-table/x-table.uvue new file mode 100644 index 0000000..94048e8 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-table/x-table.uvue @@ -0,0 +1,1184 @@ + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tabs/tabs-item.uvue b/uni_modules/tmx-ui/components/x-tabs/tabs-item.uvue new file mode 100644 index 0000000..b7e45c5 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tabs/tabs-item.uvue @@ -0,0 +1,49 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tabs/x-tabs.uvue b/uni_modules/tmx-ui/components/x-tabs/x-tabs.uvue new file mode 100644 index 0000000..3d925c0 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tabs/x-tabs.uvue @@ -0,0 +1,660 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tag/x-tag.uvue b/uni_modules/tmx-ui/components/x-tag/x-tag.uvue new file mode 100644 index 0000000..e90c95c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tag/x-tag.uvue @@ -0,0 +1,302 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-text-cloud/x-text-cloud.uvue b/uni_modules/tmx-ui/components/x-text-cloud/x-text-cloud.uvue new file mode 100644 index 0000000..7bbf981 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-text-cloud/x-text-cloud.uvue @@ -0,0 +1,281 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-text/x-text.uvue b/uni_modules/tmx-ui/components/x-text/x-text.uvue new file mode 100644 index 0000000..d64b6c9 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-text/x-text.uvue @@ -0,0 +1,308 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tree-flat/draw.uts b/uni_modules/tmx-ui/components/x-tree-flat/draw.uts new file mode 100644 index 0000000..f907254 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tree-flat/draw.uts @@ -0,0 +1,707 @@ +import { XTREEFLAT_CONFIG, XTREEFLAT_CHILDREN, XTREEFLAT_LAYOUT } from "./interface.uts" +import { hexToRgb } from "../../core/util/xCoreColorUtil.uts" +import { XTREEFLAT_NODES } from "../../interface.uts" +type XTREE_NODES_FLAT = { + node : XTREEFLAT_CHILDREN; + x : number; + y : number; + width : number; + height : number; + level : number; + parent ?: XTREEFLAT_CHILDREN; +} + +type XTREEFLAT_CONFIG_REAL = { + width : number, + height : number, + bgColor : string, + nodeBgColor : string, + fontColor : string, + fontSize : number, + /** 统一连线颜色,不配置取节点的背景,如果节点背景也没设置取#333 */ + lineColor : string, + /** 画板对象,必填写 **/ + canvas : CanvasContext, + nodeInfo : NodeInfo, + /** 绘制文本时的内边跑 */ + padding : number, + /** 绘制项目是连接线上下项目或者左右项目的间距 */ + gutter : number, + /** 父级与子级之间的连续长度 */ + parentLineGutter : number, + /** 连线宽 */ + lineWidth : number, + enbleOpenChildren : boolean, + nodeRadius : number, + /** 布局方式 */ + layout : XTREEFLAT_LAYOUT +} +type calculateNodeSize_return = { width : number, height : number } +type xCalcListDataFun = (list : XTREEFLAT_NODES[]) => XTREEFLAT_CHILDREN[] +type traverseFun = (node : XTREEFLAT_CHILDREN, level : number) => void +type drawRealRect = { x : number, y : number, width : number, height : number } + +export class OrgChartRenderer { + private ctx : CanvasRenderingContext2D; + private nodes = [] as Array; + private offsetX = 0; + private offsetY = 0; + private config : XTREEFLAT_CONFIG_REAL + private pixelRatio = 1; + private levelMaxWidth = {} as UTSJSONObject + private data = [] as XTREEFLAT_CHILDREN[] + public scaleXY = 1.0; + private nowSelectedNodes = null as null | XTREEFLAT_CHILDREN + private nodesClick = (item : XTREEFLAT_CHILDREN) => { } + constructor(xconfig : XTREEFLAT_CONFIG) { + this.config = { + width: xconfig?.width ?? 1000, + height: xconfig?.height ?? 1000, + bgColor: xconfig?.bgColor ?? 'rgba(0,0,0,0)', + fontColor: xconfig?.fontColor ?? '#2f2943', + lineColor: xconfig?.lineColor ?? 'rgb(220, 215, 255)', + nodeBgColor: xconfig?.nodeBgColor ?? 'rgb(220, 215, 255)', + padding: xconfig?.padding ?? 10, + gutter: xconfig?.gutter ?? 12, + nodeRadius: xconfig?.nodeRadius ?? 8, + parentLineGutter: xconfig?.parentLineGutter ?? 30, + enbleOpenChildren: xconfig?.enbleOpenChildren ?? true, + lineWidth: xconfig?.lineWidth ?? 1.5, + canvas: xconfig.canvas, + nodeInfo: xconfig.nodeInfo, + fontSize: xconfig?.fontSize ?? 13, + layout: (xconfig?.layout ?? 'horizontal') as XTREEFLAT_LAYOUT, + } as XTREEFLAT_CONFIG_REAL + + const canvasContext = this.config.canvas.getContext('2d')!; + const canvas = canvasContext.canvas; + // 处理高清屏逻辑 + const dpr = uni.getWindowInfo().pixelRatio; + canvas.width = canvas.offsetWidth * dpr; + canvas.height = canvas.offsetHeight * dpr; + canvasContext.scale(dpr, dpr); + this.ctx = canvasContext; + this.pixelRatio = dpr; + + } + + public getDrawBounds() : drawRealRect { + if (this.nodes.length === 0) { + return { + x: 0, + y: 0, + width: 0, + height: 0 + } as drawRealRect + } + + let minX = Infinity, minY = Infinity; + let maxX = -Infinity, maxY = -Infinity; + + this.nodes.forEach(({ x, y, width, height }) => { + // #ifndef APP-ANDROID + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, (x + width)); + maxY = Math.max(maxY, (y + height)); + // #endif + // #ifdef APP-ANDROID + minX = Math.min(minX.toDouble(), x.toDouble()).toDouble(); + minY = Math.min(minY.toDouble(), y.toDouble()).toDouble(); + maxX = Math.max(maxX.toDouble(), (x + width).toDouble()).toDouble(); + maxY = Math.max(maxY.toDouble(), (y + height).toDouble()).toDouble(); + // #endif + }); + + // 加上偏移量得到实际绘制位置 + return { + x: minX + this.offsetX, + y: minY + this.offsetY, + width: maxX - minX, + height: maxY - minY + } as drawRealRect + } + + private wrapText(text : string, fontSize : number) : string[] { + this.ctx.font = `${fontSize}px Arial`; + const words = text.split(''); + const lines : string[] = []; + let currentLine = ''; + // 每行最多8个字符 + const maxCharsPerLine = 8; + for (let i = 0; i < words.length; i++) { + if (currentLine.length >= maxCharsPerLine) { + lines.push(currentLine); + currentLine = ''; + } + currentLine += words[i]; + } + if (currentLine != '') { + lines.push(currentLine); + } + return lines; + } + private calcMeasureText(text : string, fontSize : number) : number { + let totalWidth = 0; + // #ifdef APP-HARMONY + for (let i = 0; i < text.length; i++) { + const char = text.charAt(i); + const charCode = char.charCodeAt(0); + + // 判断是否为中文字符(包括中文标点符号) + // 中文字符的Unicode范围:0x4e00-0x9fff(基本汉字) + // 中文标点符号:0x3000-0x303f, 0xff00-0xffef + if ((charCode >= 0x4e00 && charCode <= 0x9fff) || + (charCode >= 0x3000 && charCode <= 0x303f) || + (charCode >= 0xff00 && charCode <= 0xffef)) { + // 中文字符时取字号大小 + totalWidth += fontSize; + } else { + // 非中文符号时取字符数量*字号大小的一半 + totalWidth += fontSize * 0.5; + } + } + // #endif + return totalWidth; + } + private calculateNodeSize(node : XTREEFLAT_CHILDREN) : calculateNodeSize_return { + const lines = this.wrapText(node.title, node.fontSize); + this.ctx.font = `${node.fontSize}px Arial`; + // 计算最宽的行的宽度 + let linesWidths : number[] = lines.map((line) : number => { + let w = this.ctx.measureText(line).width; + // #ifdef APP-HARMONY + w = this.calcMeasureText(line,node.fontSize); + // #endif + return w; + }); + const maxWidth = Math.max(...linesWidths); + // 高度需要考虑行数和行间距 + const lineHeight = node.fontSize * 1.2; // 添加1.2倍行高 + const textHeight = lineHeight * lines.length; + return { + width: maxWidth + node.padding * 2, // 两侧添加padding + height: textHeight + node.padding * 2 // 上下添加padding + } as calculateNodeSize_return; + } + // 计算节点及其子树需要的总高度 + private calculateSubtreeHeight(node : XTREEFLAT_CHILDREN) : number { + const nodeSize = this.calculateNodeSize(node); + if (!node.opened || node.children.length == 0) { + return nodeSize.height; + } + // 计算所有子节点的高度总和(包括间距) + const childrenHeight = node.children.reduce((total, child, index) => { + const childHeight = this.calculateSubtreeHeight(child); + return total + childHeight + (index < node.children.length - 1 ? node.gutter : 0); + }, 0); + // 返回较大的值:节点自身高度,或子节点总高度 + return Math.max(nodeSize.height, childrenHeight); + } + // 收集各层级的最大宽度 + private collectLevelMaxWidth() { + this.levelMaxWidth = {} as UTSJSONObject; + let traverse = null as traverseFun | null; + traverse = (node : XTREEFLAT_CHILDREN, level : number) => { + const size = this.calculateNodeSize(node); + const currentWidth = size.width; + if (this.levelMaxWidth.get(level.toString()) == null) { + this.levelMaxWidth.set(level.toString(), currentWidth) + } + let maxwidth = this.levelMaxWidth.get(level.toString())! as number; + if (currentWidth > maxwidth) { + this.levelMaxWidth.set(level.toString(), currentWidth) + } + if (node.opened && node.children.length > 0) { + node.children.forEach(child => traverse!(child, level + 1)); + } + }; + this.data.forEach(root => traverse!(root, 0)); + } + + private layoutNode( + node : XTREEFLAT_CHILDREN, + parentX : number, + parentY : number, + level : number, + parent : XTREEFLAT_CHILDREN | null = null + ) { + const size = this.calculateNodeSize(node); + const nodeWidth = (this.levelMaxWidth.getNumber(level.toString()))!; + const subtreeHeight = this.calculateSubtreeHeight(node); + // 将节点添加到nodes数组,注意这里y坐标的计算 + this.nodes.push({ + node, + x: parentX, + y: parentY - size.height / 2, // 修改:直接使用节点自身高度居中 + width: nodeWidth, + height: size.height, + level, + parent + } as XTREE_NODES_FLAT); + if (node.opened && node.children.length > 0) { + // 计算所有子节点的总高度 + const totalChildrenHeight = node.children.reduce((total, child) => { + return total + this.calculateSubtreeHeight(child); + }, 0); + // 添加子节点之间的间距 + const totalGutterHeight = (node.children.length - 1) * node.gutter; + const totalHeight = totalChildrenHeight + totalGutterHeight; + // 修改:计算子节点的起始y坐标,使其相对父节点居中 + let childY = parentY - totalHeight / 2; + // 为每个子节点布局 + node.children.forEach((child, index) => { + const childSubtreeHeight = this.calculateSubtreeHeight(child); + // 修改:将子节点放置在计算好的位置上 + this.layoutNode( + child, + (parentX + nodeWidth + node.parentLineGutter), + (childY + childSubtreeHeight / 2), // 修改:确保子节点在其分配空间内居中 + level + 1, + node + ); + // 更新下一个子节点的y坐标 + childY += childSubtreeHeight + node.gutter; + }); + } + } + + // 计算节点及其子树需要的总宽(用于垂直布局) + private calculateSubtreeWidth(node : XTREEFLAT_CHILDREN) : number { + const nodeSize = this.calculateNodeSize(node); + if (!node.opened || node.children.length == 0) { + return nodeSize.width; + } + const childrenWidth = node.children.reduce((total, child, index) => { + const childWidth = this.calculateSubtreeWidth(child); + return total + childWidth + (index < node.children.length - 1 ? node.gutter : 0); + }, 0); + return Math.max(nodeSize.width, childrenWidth); + } + + // 垂直布局:同级左右排列,次级向下 + private layoutNodeVertical( + node : XTREEFLAT_CHILDREN, + parentCenterX : number, + parentTopY : number, + level : number, + parent : XTREEFLAT_CHILDREN | null = null + ) { + const size = this.calculateNodeSize(node); + const nodeLeftX = parentCenterX - size.width / 2; + this.nodes.push({ + node, + x: nodeLeftX, + y: parentTopY, + width: size.width, + height: size.height, + level, + parent + } as XTREE_NODES_FLAT); + + if (node.opened && node.children.length > 0) { + const totalChildrenWidth = node.children.reduce((total, child) => { + return total + this.calculateSubtreeWidth(child); + }, 0); + const totalGutterWidth = (node.children.length - 1) * node.gutter; + const totalWidth = totalChildrenWidth + totalGutterWidth; + let childLeft = parentCenterX - totalWidth / 2; + node.children.forEach((child) => { + const childSubtreeWidth = this.calculateSubtreeWidth(child); + const childCenterX = childLeft + childSubtreeWidth / 2; + this.layoutNodeVertical( + child, + childCenterX, + parentTopY + size.height + node.parentLineGutter, + level + 1, + node + ); + childLeft += childSubtreeWidth + node.gutter; + }); + } + } + + + private calculateLayout() { + this.nodes = []; + if (this.config.layout == 'horizontal') { + this.collectLevelMaxWidth(); + const totalHeight = this.data.reduce((total, root, index) => { + const subtreeHeight = this.calculateSubtreeHeight(root); + return total + subtreeHeight + (index < this.data.length - 1 ? root.gutter : 0); + }, 0); + let startY = -totalHeight / 2; + this.data.forEach((root) => { + const subtreeHeight = this.calculateSubtreeHeight(root); + this.layoutNode( + root, + 0, + startY + subtreeHeight / 2, + 0, + null + ); + startY += subtreeHeight + root.gutter; + }); + } else { + + const totalWidth = this.data.reduce((total, root, index) => { + const subtreeWidth = this.calculateSubtreeWidth(root); + return total + subtreeWidth + (index < this.data.length - 1 ? root.gutter : 0); + }, 0); + let startX = -totalWidth / 2; + this.data.forEach((root) => { + const subtreeWidth = this.calculateSubtreeWidth(root); + const rootCenterX = startX + subtreeWidth / 2; + this.layoutNodeVertical( + root, + rootCenterX, + 0, + 0, + null + ); + startX += subtreeWidth + root.gutter; + }); + } + + // 计算边界框并设置偏移 + + let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; + + this.nodes.forEach(({ x, y, width, height }) => { + // #ifndef APP-ANDROID + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, (x + width)); + maxY = Math.max(maxY, (y + height)); + // #endif + // #ifdef APP-ANDROID + minX = Math.min(minX.toDouble(), x.toDouble()).toDouble(); + minY = Math.min(minY.toDouble(), y.toDouble()).toDouble(); + maxX = Math.max(maxX.toDouble(), (x + width).toDouble()).toDouble(); + maxY = Math.max(maxY.toDouble(), (y + height).toDouble()).toDouble(); + // #endif + }); + + // 计算居中偏移 + this.offsetX = (this.config.width - (maxX - minX)) / 2 - minX; + this.offsetY = (this.config.height - (maxY - minY)) / 2 - minY; + } + + private drawConnections(nodeMeta : XTREE_NODES_FLAT) { + const node = nodeMeta.node + const x = nodeMeta.x + const y = nodeMeta.y + const width = nodeMeta.width + const height = nodeMeta.height + const level = nodeMeta.level + const parent = nodeMeta.parent + // 设置连接线样式 + this.ctx.strokeStyle = nodeMeta.node.bgColor; + this.ctx.lineWidth = this.config.lineWidth; + // 如果有父节点,绘制到父节点的连接(根据布局切换) + if (parent != null && this.config.layout == 'horizontal') { + const parentMetas = this.nodes.find((n) : boolean => n.node.id == parent.id); + + if (parentMetas != null) { + const parentMeta = parentMetas! + const startX = x; + const startY = y + height / 2; + const endX = parentMeta.x + parentMeta.width; + const endY = parentMeta.y + parentMeta.height / 2; + + this.ctx.beginPath(); + this.ctx.moveTo(startX, startY); + this.ctx.lineTo(startX - node.parentLineGutter / 2, startY); + this.ctx.lineTo(startX - node.parentLineGutter / 2, endY); + this.ctx.lineTo(endX, endY); + + this.ctx.stroke(); + } + } + // vertical 模式下不需要在子节点中绘制到父节点的连接线 + // 父节点会负责绘制到所有子节点的连接线 + + // 绘制同级节点之间的连接线 + if (this.config.layout == 'horizontal' && level == 0) { + // 查找所有根节点 + const rootNodes = this.nodes.filter(n => n.level === 0); + if (rootNodes.length > 1) { + const index = rootNodes.findIndex(n => n.node === node); + if (index > 0) { + const prevNode = rootNodes[index - 1]!; + const midY = (prevNode.y + prevNode.height / 2 + y + height / 2) / 2; + + this.ctx.beginPath(); + + this.ctx.moveTo(prevNode.x + prevNode.width / 2, prevNode.y + prevNode.height / 2); + this.ctx.lineTo(prevNode.x + prevNode.width / 2, midY); + this.ctx.lineTo(x + width / 2, midY); + this.ctx.lineTo(x + width / 2, y + height / 2); + this.ctx.stroke(); + } + } + } + + // 绘制同级节点之间的连接线(垂直布局) + if (this.config.layout == 'vertical' && level == 0) { + // 查找所有根节点 + const rootNodes = this.nodes.filter(n => n.level === 0); + if (rootNodes.length > 1) { + const index = rootNodes.findIndex(n => n.node === node); + if (index > 0) { + const prevNode = rootNodes[index - 1]!; + const midX = (prevNode.x + prevNode.width / 2 + x + width / 2) / 2; + + this.ctx.beginPath(); + + this.ctx.moveTo(prevNode.x + prevNode.width / 2, prevNode.y + prevNode.height / 2); + this.ctx.lineTo(midX, prevNode.y + prevNode.height / 2); + this.ctx.lineTo(midX, y + height / 2); + this.ctx.lineTo(x + width / 2, y + height / 2); + this.ctx.stroke(); + } + } + } + + // 如果节点展开且有子节点,绘制子节点连接线 + if (node.opened && node.children.length > 0 && this.config.layout == 'horizontal') { + const childNodes = this.nodes.filter(n => n.parent === node); + if (childNodes.length > 0) { + // 绘制垂直连接线 + const firstChild = childNodes[0]!; + const lastChild = childNodes[childNodes.length - 1]!; + const lineX = x + width + node.parentLineGutter / 2; + + this.ctx.beginPath(); + + this.ctx.moveTo(lineX, firstChild.y + firstChild.height / 2); + this.ctx.lineTo(lineX, lastChild.y + lastChild.height / 2); + this.ctx.stroke(); + + // 绘制到每个子节点的水平连接线 + + childNodes.forEach(child => { + this.ctx.beginPath(); + this.ctx.moveTo(lineX, child.y + child.height / 2); + this.ctx.lineTo(child.x, child.y + child.height / 2); + this.ctx.stroke(); + }); + } + } + if (node.children.length > 0 && this.config.layout == 'vertical') { + const childNodes = this.nodes.filter(n => n.parent === node); + if (childNodes.length > 0) { + const firstChild = childNodes[0]!; + const lastChild = childNodes[childNodes.length - 1]!; + const midY = y + height + node.parentLineGutter / 2; + // 父竖线 + const parentCenterX = x + width / 2; + this.ctx.beginPath(); + this.ctx.moveTo(parentCenterX, y + height); + this.ctx.lineTo(parentCenterX, midY); + this.ctx.stroke(); + // 水平干线 + this.ctx.beginPath(); + this.ctx.moveTo(firstChild.x + firstChild.width / 2, midY); + this.ctx.lineTo(lastChild.x + lastChild.width / 2, midY); + this.ctx.stroke(); + // 子竖线 + childNodes.forEach(child => { + const childCenterX = child.x + child.width / 2; + this.ctx.beginPath(); + this.ctx.moveTo(childCenterX, child.y); + this.ctx.lineTo(childCenterX, midY); + this.ctx.stroke(); + }); + } + } + } + drawRoundedRect(x : number, y : number, width : number, height : number, radius : number) { + const ctx = this.ctx; + ctx.beginPath(); + // 左上角开始 + ctx.moveTo(x + radius, y); + // 上边 + 右上角圆弧 + ctx.arcTo(x + width, y, x + width, y + height, radius); + // 右边 + 右下角圆弧 + ctx.arcTo(x + width, y + height, x, y + height, radius); + // 下边 + 左下角圆弧 + ctx.arcTo(x, y + height, x, y, radius); + // 左边 + 左上角圆弧 + ctx.arcTo(x, y, x + width, y, radius); + ctx.closePath(); + ctx.fill(); // 或使用 stroke() 绘制边框 + } + private draw() { + this.ctx.clearRect(0, 0, this.config.width, this.config.height); + this.ctx.fillStyle = this.config.bgColor; + this.ctx.fillRect(0, 0, this.config.width, this.config.height); + this.ctx.save(); + + this.ctx.translate(this.offsetX, this.offsetY); + // 先绘制连接线 + this.nodes.forEach(nodeMeta => this.drawConnections(nodeMeta)); + // 再绘制节点(确保节点在连接线上层) + this.nodes.forEach(nodeMeta => { + const { node, x, y, width, height } = nodeMeta; + + // 绘制选中状态 + if (node.selected) { + this.ctx.fillStyle = node.lineColor; + this.drawRoundedRect(x - 5, y - 5, width + 10, height + 10, this.config.nodeRadius) + } + + // 绘制背景 + this.ctx.fillStyle = node.bgColor; + this.drawRoundedRect(x, y, width, height, this.config.nodeRadius) + + // 绘制文本(使用换行) + const lines = this.wrapText(node.title, node.fontSize); + this.ctx.fillStyle = node.fontColor; + this.ctx.font = `${node.fontSize}px Arial`; + this.ctx.textBaseline = 'middle'; + + const lineHeight = node.fontSize * 1.2; + + const totalTextHeight = lineHeight * lines.length; + const textStartY = y + (height - totalTextHeight) / 2; + + lines.forEach((line, index) => { + + const lineY = textStartY + lineHeight * index + lineHeight / 2; + let textWidth = this.ctx.measureText(line).width; + // #ifdef APP-HARMONY + textWidth = this.calcMeasureText(line,node.fontSize); + // #endif + const textX = x + (width - textWidth) / 2; + this.ctx.fillText(line, textX, lineY); + + }); + + + }); + + this.ctx.restore(); + } + + + // 处理数据 + private updateData(list : XTREEFLAT_NODES[]) { + let calcListData = null as xCalcListDataFun | null; + let _this = this; + calcListData = (datas : XTREEFLAT_NODES[]) : XTREEFLAT_CHILDREN[] => { + if (datas.length == 0) return [] as XTREEFLAT_CHILDREN[]; + let tem = [] as XTREEFLAT_CHILDREN[] + let calcfun = calcListData! + for (let i = 0; i < datas.length; i++) { + let item = datas[i]; + let children = item?.children ?? ([] as XTREEFLAT_NODES[]) + + let bgcolor = item?.bgColor ?? _this.config.nodeBgColor + let rgba = hexToRgb(bgcolor) + let lineColor = `rgba(${rgba.getNumber('r')},${rgba.getNumber('g')},${rgba.getNumber('b')},0.4)` + tem.push({ + title: item.title, + id: item?.id ?? ("xTreeFlatNodes-" + Math.random().toString(16).substring(4, 20)), + fontColor: item?.fontColor ?? _this.config.fontColor, + bgColor: bgcolor, + lineColor: lineColor, + padding: item?.padding ?? _this.config.padding, + gutter: item?.gutter ?? _this.config.gutter, + parentLineGutter: item?.parentLineGutter ?? _this.config.parentLineGutter, + opened: item?.opened ?? true, + disabled: item?.disabled ?? _this.config.enbleOpenChildren, + selected: item?.selected ?? false, + fontSize: item?.fontSize ?? _this.config.fontSize, + children: calcfun(children) + } as XTREEFLAT_CHILDREN) + } + return tem; + } + let calcfun = calcListData! + this.data = calcfun(list) + } + + // 计算自动缩放比例 + private calculateAutoScale() : number { + const bounds = this.getDrawBounds(); + if (bounds.width === 0 || bounds.height === 0) return 1.0; + + // 考虑边距,留出10%的空间 + const padding = 0.1; + const containerWidth = this.config.nodeInfo.width! * (1 - padding); + const containerHeight = this.config.nodeInfo.height! * (1 - padding); + + // 计算水平和垂直方向的缩放比例 + const scaleX = containerWidth / bounds.width; + const scaleY = containerHeight / bounds.height; + + // 取较小的缩放比例,确保完整显示 + return Math.min(scaleX, scaleY); + } + + // 设置缩放比例的公共方法 + public setScale(scale : number | null = null) { + // 如果没有提供缩放比例,则自动计算 + this.scaleXY = scale == null ? this.calculateAutoScale() : (scale!); + this.draw(); + } + public addEventClick(e : UniPointerEvent, scrollTop : number, scrollLeft : number) { + if (this.nodes.length == 0) return; + let wintop = uni.getWindowInfo().windowTop; + const containerX = e.clientX - (this.config.nodeInfo.left ?? 0) + const containerY = e.clientY - (this.config.nodeInfo.top ?? 0) - wintop + + const canvasX = (containerX) + scrollLeft - this.offsetX; + const canvasY = (containerY) + scrollTop - this.offsetY; + //是否命中了节点.0未操作,1命中, + let isHit = false + //检测点击的节点 + for (let i = 0; i < this.nodes.length; i++) { + const meta = this.nodes[i]; + if (canvasX >= meta.x && canvasX <= meta.x + meta.width && + canvasY >= meta.y && canvasY <= meta.y + meta.height) { + if (!meta.node.disabled) { + meta.node.opened = !meta.node.opened; + this.calculateLayout(); + } + // 更新选中状态 + this.nodes.forEach(m => { + m.node.selected = false + if (m.node.id == meta.node.id) { + m.node.selected = true; + } + }); + this.draw(); + isHit = true; + this.nowSelectedNodes = meta.node + //命中的情况下触发选中事件. + this.nodesClick(meta.node) + break; + } + } + // 点击空白时,如果有选中的项目就清除所有选中,而且必须是未命中的情况 + if (this.nowSelectedNodes != null && !isHit) { + this.nodes.forEach(m => { + m.node.selected = false + }); + + this.draw(); + } + + if (!isHit) { + this.nowSelectedNodes = null + } + + } + public onListen(call : (item : XTREEFLAT_CHILDREN) => void) { + this.nodesClick = call; + } + + public setData(newData : XTREEFLAT_NODES[]) { + this.updateData(newData) + this.calculateLayout(); + this.draw(); + // this.setScale() + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tree-flat/interface.uts b/uni_modules/tmx-ui/components/x-tree-flat/interface.uts new file mode 100644 index 0000000..750d183 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tree-flat/interface.uts @@ -0,0 +1,79 @@ + +export type XTREEFLAT_LAYOUT = 'horizontal' | 'vertical' + +export type XTREEFLAT_CONFIG = { + /** 不填写默认为1000 */ + width?:number, + /** 不填写默认为1000 */ + height?:number, + /** 不填写默认为透明,即不绘制背景 */ + bgColor?:string, + nodeBgColor?:string, + /** 不填写默认为#333 */ + fontColor?:string, + /** 不填写默认为14,如果子节点设置了以子节点为准 */ + fontSize ?: number, + /** 统一连线颜色,不配置取节点的背景,如果节点背景也没设置取#333 */ + lineColor?:string, + /** 连线宽 */ + lineWidth?:number, + /** 画板对象,必填写 **/ + canvas:CanvasContext, + /** 节点布局信息 **/ + nodeInfo:NodeInfo, + /** 绘制文本时的内边跑 */ + padding ?: number, + /** 绘制项目是连接线上下项目或者左右项目的间距 */ + gutter ?: number, + /** 父级与子级之间的连续长度 */ + parentLineGutter ?: number, + /** 点击有子节点的父级时,是否允许关闭和展开,默认关闭 */ + enbleOpenChildren ?:boolean, + /** 节点圆角,默认为8 */ + nodeRadius ?: number, + /** 布局方式:horizontal 水平(默认),vertical 垂直 */ + layout?: XTREEFLAT_LAYOUT +} + + +export type XTREEFLAT_CHILDREN = { + /** 唯一标识,如果不填写内部自动填写 */ + id : string | number, + /** 标题 */ + title : string, + /** 文本颜色 */ + fontColor : string, + /** 文本背景颜色 */ + bgColor : string, + /** 绘制文本时的内边跑 */ + padding : number, + /** 绘制项目是连接线上下项目或者左右项目的间距 */ + gutter : number, + /** 父级与子级之间的连续长度 */ + parentLineGutter : number, + /** 是否展开了子级 */ + opened : boolean, + /** 是否禁用展开子级 */ + disabled : boolean, + /** 当前项目是否选中 */ + selected : boolean, + /** 绘制文本的字号大小 */ + fontSize : number, + /** 子级数据,可以为空数组代表无子级不绘制下级 */ + children : Array, + lineColor : string +} + +export type propsTypeAsSelef = { + /** 画板宽,总宽不要小于节点展开后的宽,可以尽量设置大点 */ + canvasWidth:number, + /** 画板高,总高不要小于节点展开后的高,可以尽量设置大点 */ + canvasHeight:number, + /** 组件宽 */ + width:string, + /** 组件高,不能为auto */ + height:string, + /** 动态数据 */ + list:XTREEFLAT_NODES[], + opts:XTreeFlatOpts|null +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tree-flat/x-tree-flat.uvue b/uni_modules/tmx-ui/components/x-tree-flat/x-tree-flat.uvue new file mode 100644 index 0000000..1def473 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tree-flat/x-tree-flat.uvue @@ -0,0 +1,275 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tree-item/x-tree-item.vue b/uni_modules/tmx-ui/components/x-tree-item/x-tree-item.vue new file mode 100644 index 0000000..0930cc8 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tree-item/x-tree-item.vue @@ -0,0 +1,645 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-tree/util.uts b/uni_modules/tmx-ui/components/x-tree/util.uts new file mode 100644 index 0000000..50768c3 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tree/util.uts @@ -0,0 +1,172 @@ + +export function findParentIds(nodes : UTSJSONObject[], targetId : string, idkey : string) : string[] { + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] as UTSJSONObject + + if (node.getString(idkey) == targetId) { + return [node.getString(idkey!)!] as string[]; + } + if (node.getArray("children") != null) { + let children = node.getArray("children") as UTSJSONObject[] | null; + children = children == null ? ([] as UTSJSONObject[]) : children! + + if (children.length > 0) { + let childResult = findParentIds(children as UTSJSONObject[], targetId, idkey); + // console.log(childResult) + + if (childResult.length > 0) { + return childResult.concat([node.getString(idkey!)!] as string[]) as string[]; + } + } + + } + + } + + return [] as string[]; +} + +export function flatChildrensId(list : UTSJSONObject, idkey : string) : string[] { + let seleds = [] as string[]; + let nodes = list.getArray("children") as UTSJSONObject[] | null; + nodes = nodes == null ? ([] as UTSJSONObject[]) : nodes! + if (nodes.length == 0) { + return seleds + } + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] as UTSJSONObject + let disabled = node.getBoolean('disabled'); + disabled = disabled == null ? false : disabled! + if (!disabled) { + seleds.push(node.getString(idkey!)!) + } + let childResult = flatChildrensId(node, idkey); + seleds = seleds.concat(childResult) + } + return seleds; +} + +/** + * unix在安卓上,二级以下直接赋值修改,不会影响整体list数据。无奈。只有一级一级反推修改。 + */ +export function setChildrenByid(nodesess : UTSJSONObject[], targetId : string, idkey : string, targetChildren : UTSJSONObject[]) : UTSJSONObject[] { + let nodes = nodesess + + function setlist(nodes : UTSJSONObject[]) { + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] as UTSJSONObject + if (node.getString(idkey) == targetId) { + nodes[i].set('children', targetChildren) + break; + } + if (node.getArray("children") != null) { + let children = node.getArray("children") as UTSJSONObject[] | null; + if (children != null) { + setlist(children!); + } + } + } + } + setlist(nodes) + + return nodes; +} + + +export function findParentNode(tree : UTSJSONObject[], targetId : string, idkey : string,parent:UTSJSONObject|null=null) : null | UTSJSONObject { + + for (let i = 0; i < tree.length; i++) { + const node = tree[i]; + if (node.getString(idkey) == targetId) { + return parent; // 没有父级,因为它是根节点 + } + let children = node.getArray('children') as null | UTSJSONObject[] + if (children !=null) { + const parent = findParentNode(children!,targetId,idkey,node); + if (parent !=null) { + return parent; + } + } + } + return null; // 没有找到具有该ID的节点或其父级 +} + +export function getAllParentIds(nodes : UTSJSONObject[],idkey : string) : string[] { + let parentIds = [] as string[]; + + function traverseTree(nodeList : UTSJSONObject[]) { + for (let i = 0; i < nodeList.length; i++) { + let node = nodeList[i] as UTSJSONObject; + let children = node.getArray("children") as UTSJSONObject[] | null; + + if (children != null && children.length > 0) { + // 只有当节点有子节点时,才将其ID添加到父节点列表中 + parentIds.push(node.getString(idkey!)!); + // 递归遍历子节点 + traverseTree(children!); + } + } + } + + traverseTree(nodes); + return parentIds; +} + +export function findNode(nodes : UTSJSONObject[],targetId : string,idkey : string) : UTSJSONObject|null { + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i] as UTSJSONObject + + if (node.getString(idkey) == targetId) { + return node; // 找到匹配ID的节点,直接返回 + } + + if (node.getArray("children") != null) { + let children = node.getArray("children") as UTSJSONObject[] | null; + if (children != null && children.length > 0) { + let result = findNode(children!, targetId, idkey); + if (result != null) { + return result; // 在子节点中找到匹配的节点,返回结果 + } + } + } + } + + return null; +} + +export function findNodeIndeterminate(nodes : UTSJSONObject[],targetIds : string[],idkey : string) : string[] { + let indeterminateIds = [] as string[]; + + function traverseTree(nodeList : UTSJSONObject[]) { + for (let i = 0; i < nodeList.length; i++) { + let node = nodeList[i] as UTSJSONObject; + let nodeId = node.getString(idkey!)!; + let children = node.getArray("children") as UTSJSONObject[] | null; + + // 检查当前节点是否在targetIds中 + let currentNodeSelected = targetIds.includes(nodeId) + if(currentNodeSelected){ + continue; + } + if (children != null && children.length > 0) { + + let childrenIds = flatChildrensId(node,idkey) + // 检查子节点是否部分选中 + let hasSelected = childrenIds.some((id:string):boolean => targetIds.includes(id)) + + + // 如果子节点部分选中(有选中但不是全部选中),则添加当前节点ID到结果中 + if (hasSelected) { + indeterminateIds.push(nodeId); + } + + // 递归检查子节点 + traverseTree(children!); + } + } + } + + traverseTree(nodes); + return indeterminateIds; +} + diff --git a/uni_modules/tmx-ui/components/x-tree/x-tree.uvue b/uni_modules/tmx-ui/components/x-tree/x-tree.uvue new file mode 100644 index 0000000..6e8d66c --- /dev/null +++ b/uni_modules/tmx-ui/components/x-tree/x-tree.uvue @@ -0,0 +1,340 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-upload-file/x-upload-file.uvue b/uni_modules/tmx-ui/components/x-upload-file/x-upload-file.uvue new file mode 100644 index 0000000..a3bd58d --- /dev/null +++ b/uni_modules/tmx-ui/components/x-upload-file/x-upload-file.uvue @@ -0,0 +1,707 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-upload-media/x-upload-media.uvue b/uni_modules/tmx-ui/components/x-upload-media/x-upload-media.uvue new file mode 100644 index 0000000..fd666cb --- /dev/null +++ b/uni_modules/tmx-ui/components/x-upload-media/x-upload-media.uvue @@ -0,0 +1,875 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-view-tofull/x-view-tofull.uvue b/uni_modules/tmx-ui/components/x-view-tofull/x-view-tofull.uvue new file mode 100644 index 0000000..c480c1f --- /dev/null +++ b/uni_modules/tmx-ui/components/x-view-tofull/x-view-tofull.uvue @@ -0,0 +1,270 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-virtual-list/x-virtual-list.uvue b/uni_modules/tmx-ui/components/x-virtual-list/x-virtual-list.uvue new file mode 100644 index 0000000..ed23079 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-virtual-list/x-virtual-list.uvue @@ -0,0 +1,799 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-waterfall-item/x-waterfall-item.uvue b/uni_modules/tmx-ui/components/x-waterfall-item/x-waterfall-item.uvue new file mode 100644 index 0000000..3d63560 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-waterfall-item/x-waterfall-item.uvue @@ -0,0 +1,194 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-waterfall/back b/uni_modules/tmx-ui/components/x-waterfall/back new file mode 100644 index 0000000..b1fccbe --- /dev/null +++ b/uni_modules/tmx-ui/components/x-waterfall/back @@ -0,0 +1,316 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-waterfall/x-waterfall.uvue b/uni_modules/tmx-ui/components/x-waterfall/x-waterfall.uvue new file mode 100644 index 0000000..c17c515 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-waterfall/x-waterfall.uvue @@ -0,0 +1,349 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-watermark/x-watermark.uvue b/uni_modules/tmx-ui/components/x-watermark/x-watermark.uvue new file mode 100644 index 0000000..e888821 --- /dev/null +++ b/uni_modules/tmx-ui/components/x-watermark/x-watermark.uvue @@ -0,0 +1,337 @@ + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/components/x-weekbar/x-weekbar.uvue b/uni_modules/tmx-ui/components/x-weekbar/x-weekbar.uvue new file mode 100644 index 0000000..f19e4ba --- /dev/null +++ b/uni_modules/tmx-ui/components/x-weekbar/x-weekbar.uvue @@ -0,0 +1,608 @@ + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/config/observeAppTheme.uts b/uni_modules/tmx-ui/config/observeAppTheme.uts new file mode 100644 index 0000000..1842277 --- /dev/null +++ b/uni_modules/tmx-ui/config/observeAppTheme.uts @@ -0,0 +1,197 @@ +import { xProvitae, xConfig } from "./xConfig.uts" +import { xPageStyle} from "../interface.uts" + +/** + * 获取当前缓存的暗黑主题设置。 + */ +export function getDarkMode() : 'light' | 'dark' { + let dark = getOsTheme(); + + let model = "light" as 'light' | 'dark' + if (dark == 'dark' || dark == 'light') { + model = dark + } + + let customSetings = uni.getStorageSync('tmuiXuiOsThemeSet'); + if (customSetings != null && customSetings != 'auto' && customSetings!='') { + let dsd = customSetings as string; + if (dark == 'dark' || dark == 'light') { + model = dsd as 'light' | 'dark' + } + } + + + return model; +} +/** + * 是否设置过暗黑主题,即是否有缓存。 + */ +export function isCustomTheme() : boolean { + + let issettheme = false + let customSetings = uni.getStorageSync('tmuiXuiOsThemeSet'); + if (customSetings != null) { + let str = customSetings as string; + if (str == 'dark' || str == 'light' || str == 'auto') { + issettheme = true + } + } + return issettheme; +} + +export function getOsTheme() : 'dark' | 'light' { + + let defaultModel = 'light' as 'dark' | 'light' + // #ifdef WEB + const mq = window.matchMedia('(prefers-color-scheme: dark)'); + + if (mq.matches) { + defaultModel = 'dark' + } + + // #endif + // #ifdef APP + let str = uni.getSystemInfoSync().osTheme + if (str != null) { + defaultModel = str + } + // #endif + + return defaultModel; + +} + +export function WebObserveTheme() { + // #ifdef WEB + const mq = window.matchMedia('(prefers-color-scheme: dark)'); + const listener = (e) => { + + let customSetings = uni.getStorageSync('tmuiXuiOsThemeSet'); + if (customSetings != 'auto') return; + if (e.matches) { + // 系统设置了主题为暗黑 + xConfig.dark = 'dark' + } else { + // 系统设置了主题为非暗黑 + xConfig.dark = 'light' + } + + setThemeDarkModel() + }; + // 添加监听器 + mq.onchange = listener + // #endif + // #ifdef APP + uni.onOsThemeChange((res : OsThemeChangeResult) => { + let customSetings = uni.getStorageSync('tmuiXuiOsThemeSet'); + if (customSetings != 'auto') return; + xConfig.dark = res.osTheme + setThemeDarkModel() + }) + // #endif +} + +export function setThemeDarkModel(){ + setBgBodyColor(); +} + +export function setBgBodyColor(){ + let dark = xConfig.dark + + + // #ifdef WEB + + let pages = getCurrentPages() + let page = pages[pages.length-1] + if(!page?.$getPageStyle||!page) return; + let pageJson = page.$getPageStyle() + let newpages = {} as UTSJSONObject + if(!xProvitae.pageStyle.has(page.route)){ + let oldNavbgColor = "" + let oldNavTxtColor = "" + let oldbgColor = "" + // #ifdef WEB + oldNavbgColor = pageJson.navigationBarBackgroundColor||"" + oldNavTxtColor = pageJson.navigationBarTextStyle||"" + //h5无法获取背景色 sdk有bug + oldbgColor = pageJson.backgroundColorContent||"" + // oldbgColor = document.body.style.getPropertyValue("--background-color-content")||"" + // #endif + xProvitae.pageStyle.set(page.route,{ + path:page.route, + backgroundColorContent:oldbgColor==null?"":oldbgColor, + navigationBarBackgroundColor:oldNavbgColor==null?"":oldNavbgColor, + navigationBarTextStyle:oldNavTxtColor==null?"":oldNavTxtColor + } as xPageStyle ) + } + + let pageStyles = xProvitae.pageStyle.get(page.route) as xPageStyle + + document.body.style.setProperty('--header-bg-color',`#ffffff`) + document.body.style.setProperty('--header-title-color','black') + let header = document.body.querySelector("style") + + if(!header){ + let cssNode = document.createElement("style") + cssNode.id="xTmui4.0BodyCssId" + cssNode.type = 'text/css' + cssNode.innerHTML = ".uni-page-head{background-color:var(--header-bg-color) !important;color:var(--header-title-color) !important;}" + document.body.appendChild(cssNode) + + } + if(dark=='light'){ + let pageBgColor = pageStyles!.backgroundColorContent==""?xConfig.backgroundColorContentLight:pageStyles!.backgroundColorContent + let navBgColor = pageStyles!.navigationBarBackgroundColor==""?xConfig.navigationBarBackgroundColorLight:pageStyles!.navigationBarBackgroundColor + let navTextColor = pageStyles!.navigationBarTextStyle==""?xConfig.navigationBarTextStyleLight:pageStyles!.navigationBarTextStyle + + pageJson.backgroundColorContent = pageBgColor + pageJson.navigationBarBackgroundColor = navBgColor + pageJson.navigationBarTextStyle = navTextColor + if(pageBgColor){ + document.body.style.setProperty('background-color',pageBgColor) + document.body.style.setProperty('--background-color-content',pageBgColor) + } + + document.body.style.setProperty('--header-bg-color',navBgColor) + document.body.style.setProperty('--header-title-color',navTextColor) + + } + if(dark=='dark'){ + pageJson.backgroundColorContent = xConfig.backgroundColorContentDark + pageJson.navigationBarBackgroundColor = xConfig.navigationBarBackgroundColorDark + pageJson.navigationBarTextStyle = xConfig.navigationBarTextStyleDark + + document.body.style.setProperty('background-color',xConfig.backgroundColorContentDark) + + document.body.style.setProperty('--background-color-content',xConfig.backgroundColorContentDark) + document.body.style.setProperty('--header-bg-color',xConfig.navigationBarBackgroundColorDark) + document.body.style.setProperty('--header-title-color',xConfig.navigationBarTextStyleDark) + + } + + uni.setTabBarStyle({ + backgroundColor:dark=='dark'?xConfig.tabarBackgroundColorDark:xConfig.tabarBackgroundColorLight, + borderStyle:dark=='dark'?xConfig.tabarBackgroundColorDark:xConfig.tabarBackgroundColorLight, + fail:(result)=>{} + } as SetTabBarStyleOptions) + uni.setNavigationBarColor({ + frontColor:dark=='dark'?'#ffffff':'#000000', + backgroundColor:pageJson.navigationBarBackgroundColor + } as SetNavigationBarColorOptions) + page.$setPageStyle(newpages) + // #endif + // #ifdef APP + uni.setAppTheme({ + theme:dark, + success(_: SetAppThemeSuccessResult){ + // console.log(uni.getSystemInfoSync().osTheme,'****') + }, + fail(result: IAppThemeFail){ + console.log(result) + } + }) + + // #endif + +} + diff --git a/uni_modules/tmx-ui/config/xConfig.uts b/uni_modules/tmx-ui/config/xConfig.uts new file mode 100644 index 0000000..cd3a834 --- /dev/null +++ b/uni_modules/tmx-ui/config/xConfig.uts @@ -0,0 +1,358 @@ +import { getDefaultColor } from "../core/util/xCoreColorUtil.uts" +import { TABBAR_ITEM_INFO, xPageStyle, XPRIVATECONFIG, XTABBARCONFIG, XCONFIG } from "../interface.uts" +import { getDarkMode, isCustomTheme, WebObserveTheme, setThemeDarkModel } from "./observeAppTheme.uts" +import { mergeI18nOpts,$i18n,createI18n} from "@/uni_modules/x-vuei18n-s/index.uts" +import { Tmui4xI18nTml} from "@/uni_modules/x-vuei18n-s/interface.uts" +import {Tmui4xOptions} from "@/uni_modules/tmx-ui/interface.uts" + +import en from "@/uni_modules/tmx-ui/localLanuage/en.json" +import zhHans from "@/uni_modules/tmx-ui/localLanuage/zh-Hans.json" +import zhHant from "@/uni_modules/tmx-ui/localLanuage/zh-Hant.json" +import ko from "@/uni_modules/tmx-ui/localLanuage/ko.json" +import ja from "@/uni_modules/tmx-ui/localLanuage/ja.json" +/** + * 下方是组件的语言包,以及你自己定义的语言包与组件合并即可。共用一个实例。 + */ +const messages : UTSJSONObject = { + "en":en, + "zh-Hans":zhHans, + "zh-Hant":zhHant, + "ko":ko, + "ja":ja +} +/** + * 内部组件私有 + */ +export const xProvitae = reactive({ + /** + * 供给需要页面滚动参数时组件使用。 + */ + scrollTop: -1, + windowInnerWidth: 0, + windowInnerHeight: 0, + windowWidth: 0, + windowHeight: 0, + pageStyle: new Map(), + pageReady:false + +} as XPRIVATECONFIG) + + +/** + * x-ui配置 + */ +export const xConfig = reactive({ + theme:new Map([]), + i18n:createI18n({messages,locale:'zh-Hans'}), + /** 全局的主题色 */ + color: "#0088ff", + /** 主题配置,auto,dark,light */ + dark: 'auto', + /** 设计基准默认是375,如果修改会影响组件的尺寸,比如你设置为414,那么假设12号最终计算过程是414/375*12=13.248px,如果你小于375则不计算。 */ + designSize: 375, + /** 当屏幕宽大于或者等于667时再直接采用以375为基座,按照designSize比例来的原始尺寸,即尺寸不会变大也不会变小了 */ + maximumCalculatedSize:667, + /** 设计单位px,rpx */ + unit: 'px', + /** 语言 */ + language: "zh-Hans", + /** 如果你使用unit为rpx时,fontScale不要去设置,如果unit为px时,可以设置此值来缩放大小。 */ + fontScale: 1, + /** x-text默认的字号,如果你使用unit为rpx时,fontScale不要去设置 */ + fontSize: "16", + /** 全局默认的文本x-text色 */ + fontColor:"#1d1d1f", + /** 全局默认的文本x-text暗黑字体色 */ + fontDarkColor:"#f5f5f7", + navigationBarTextStyleDark: "#ffffff", + /** 注意局部的page.json节点配置会覆盖这里 */ + navigationBarTextStyleLight: "#000000", + + navigationBarBackgroundColorDark: "#000000", + /** 注意局部的page.json节点配置会覆盖这里 */ + navigationBarBackgroundColorLight: "#f5f5f5", + + backgroundColorContentDark: "#000000", + /** 注意局部的page.json节点配置会覆盖这里 */ + backgroundColorContentLight: "#f5f5f5", + + tabarBackgroundColorDark: "#0a0a0a", + tabarBackgroundColorLight: "#FFFFFF", + + + /** 一般容器sheet的暗黑背景 */ + sheetDarkColor: '#141414', + sheetDarkBorderColor: ["#232323"], + + /** 输入框暗黑背景 */ + inputDarkColor: '#1E1E1F', + /** 输入框默认的亮系背景色方便统一设计稿 */ + inputBgColor: '#f2f2f7', + /** 输入框默认的统一提示placeholderStyle方便统一设计稿 */ + placeholderStyle: 'color:#aeaeb2', + borderDarkColor: '#1c1c1c', + + /** l输入框的圆角 */ + inputRadius: "12", + inputFocusBorder:[], + /** 按钮的圆角 */ + buttonRadius: "12", + /** 统一的标签圆角 */ + tagRadius: "5", + /** 列表cell组件为card时的圆角 */ + cellRadius: "12", + /** 列表为cellCard组件时的边距 */ + cellMargin:['12px','0','12px','6px'], + + /** 容器的全局圆角 */ + sheetRadius: ["12"], + /** 容器的全局间隙 */ + sheetMargin: ["14", "0", "14", "14"], + /** 容器的全局内间隙 */ + sheetPadding: ["14"], + /** + * 影响: + * 抽屉打开方向为上和下时的圆角 + * 浮动面板 + * 动作菜单 + * */ + drawerRadius: "26", + /** 对话框modal的圆角 */ + modalRadius: "18", + /** 开关的圆角 */ + switchRadius: "32", + /**进度条的圆角 */ + progressRadius: "32", + /** 未选中时的颜色 */ + unRadioAndCheckBoxColor: "#aeaeb2", + /** 单选按钮组的圆角 */ + radioButtonRadius: "12", + /** 弹窗,弹层,对话框等等所有的动画类型。 */ + animationFun: 'cubic-bezier(.42,.38,.15,.93)', + /** 卡片的圆角 */ + cardRound: '12', + closeIcon:"close-circle-fill" + +} as XCONFIG) + +/** + * 获取当前的主题配色。 + */ +export const getThemePrimary = () : string => { + return getDefaultColor(xConfig.color) as string +} +/** + * 设置全局主题色 + */ +export const setThemePrimary = (scolor : string) : string => { + xConfig.color = getDefaultColor(scolor) + return xConfig.color as string +} + +/** + * 设置暗黑主题配置 + * @param {string} value - auto,dark,light + */ +export const setDarkModel = (value : 'dark' | 'auto' | 'light') => { + uni.setStorageSync('tmuiXuiOsThemeSet', value) + let darkmodl = getDarkMode(); + xConfig.dark = darkmodl + setThemeDarkModel(); +} +/** + * 获取当前的主题 + */ +export const getDarkModel = () : 'dark' | 'auto' | 'light' => { + let darkmodl = uni.getStorageSync('tmuiXuiOsThemeSet'); + let m = darkmodl == null ? 'dark' : darkmodl + return m as 'dark' | 'auto' | 'light' +} + + +/** + * 全局的tabbar配置。 + */ +export const xTabbarConfig = reactive({ + tabbarActiveIndex: 0, + tabaarHeight:60, + list: [] as TABBAR_ITEM_INFO[] +} as XTABBARCONFIG) + +/** + * 处理xConfig配置表 + */ +export const setConfig = (configs:Tmui4xOptions|null)=>{ + let localLang = uni.getStorageSync("language") as string|null; + if(configs != null && configs?.i18nOptions != null){ + let opts = configs.i18nOptions; + xConfig.i18n = createI18n(opts) + } + if(configs != null && configs?.config != null){ + const config = configs.config + let cfg = config! as UTSJSONObject + if(cfg.getString('color')!=null&&cfg.getString('color')!=''){ + xConfig.color = cfg.getString('color')! + + } + + if(cfg.getAny('theme')!=null){ + let theme = cfg.getAny('theme')! as Map + xConfig.theme = theme + } + if(cfg.getString('dark')!=null&&cfg.getString('dark')!=''){ + xConfig.dark = cfg.getString('dark')! as "auto" | "dark" | "light" + setDarkModel(xConfig.dark) + } + if(cfg.getNumber('designSize')!=null){ + xConfig.designSize = cfg.getNumber('designSize')! + } + if(cfg.getNumber('maximumCalculatedSize')!=null){ + xConfig.maximumCalculatedSize = cfg.getNumber('maximumCalculatedSize')! + } + + if(cfg.getString('unit')!=null&&cfg.getString('unit')!=''){ + xConfig.unit = cfg.getString('unit')! as "px"|"rpx" + } + + if(cfg.getString('language')!=null&&cfg.getString('language')!=''){ + + if(localLang=='' || localLang == null){ + xConfig.language = cfg.getString('language')! + xConfig.i18n.setLocale(xConfig.language ) + }else{ + xConfig.language = localLang! + xConfig.i18n.setLocale(localLang!) + } + } + + if(cfg.getString('language')==null||cfg.getString('language')==''){ + if(localLang!=''&& typeof localLang == 'string'){ + xConfig.language = localLang! + xConfig.i18n.setLocale(localLang!) + } + } + + + + if(cfg.getNumber('fontScale')!=null){ + xConfig.fontScale = cfg.getNumber('fontScale')! + } + if(cfg.getString('fontSize')!=null&&cfg.getString('fontSize')!=''){ + xConfig.fontSize = cfg.getString('fontSize')! + } + + if(cfg.getString('navigationBarTextStyleDark')!=null){ + xConfig.navigationBarTextStyleDark = cfg.getString('navigationBarTextStyleDark')! + } + if(cfg.getString('navigationBarTextStyleLight')!=null){ + xConfig.navigationBarTextStyleLight = cfg.getString('navigationBarTextStyleLight')! + } + if(cfg.getString('navigationBarBackgroundColorDark')!=null){ + xConfig.navigationBarBackgroundColorDark = cfg.getString('navigationBarBackgroundColorDark')! + } + if(cfg.getString('navigationBarBackgroundColorLight')!=null){ + xConfig.navigationBarBackgroundColorLight = cfg.getString('navigationBarBackgroundColorLight')! + } + if(cfg.getString('backgroundColorContentDark')!=null){ + xConfig.backgroundColorContentDark = cfg.getString('backgroundColorContentDark')! + } + if(cfg.getString('backgroundColorContentLight')!=null){ + xConfig.backgroundColorContentLight = cfg.getString('backgroundColorContentLight')! + } + if(cfg.getString('tabarBackgroundColorDark')!=null){ + xConfig.tabarBackgroundColorDark = cfg.getString('tabarBackgroundColorDark')! + } + if(cfg.getString('tabarBackgroundColorLight')!=null){ + xConfig.tabarBackgroundColorLight = cfg.getString('tabarBackgroundColorLight')! + } + if(cfg.getString('sheetDarkColor')!=null){ + xConfig.sheetDarkColor = cfg.getString('sheetDarkColor')! + } + if(cfg.getString('fontColor')!=null){ + xConfig.fontColor = cfg.getString('fontColor')! + } + if(cfg.getString('fontDarkColor')!=null){ + xConfig.fontDarkColor = cfg.getString('fontDarkColor')! + } + + if(cfg.getArray('sheetDarkBorderColor')!=null){ + xConfig.sheetDarkBorderColor = cfg.getArray('sheetDarkBorderColor')! + } + if(cfg.getString('inputDarkColor')!=null){ + xConfig.inputDarkColor = cfg.getString('inputDarkColor')! + } + if(cfg.getString('sheetDarkColor')!=null){ + xConfig.borderDarkColor = cfg.getString('borderDarkColor')! + } + if(cfg.getString('inputRadius')!=null){ + xConfig.inputRadius = cfg.getString('inputRadius')! + } + if(cfg.getArray('inputFocusBorder')!=null){ + xConfig.inputFocusBorder = cfg.getArray('inputFocusBorder')! + } + + if(cfg.getString('buttonRadius')!=null){ + xConfig.buttonRadius = cfg.getString('buttonRadius')! + } + if(cfg.getString('tagRadius')!=null){ + xConfig.tagRadius = cfg.getString('tagRadius')! + } + if(cfg.getString('cellRadius')!=null){ + xConfig.cellRadius = cfg.getString('cellRadius')! + } + + if(cfg.getArray('sheetRadius')!=null){ + xConfig.sheetRadius = cfg.getArray('sheetRadius')! + } + if(cfg.getArray('sheetMargin')!=null){ + xConfig.sheetMargin = cfg.getArray('sheetMargin')! + } + if(cfg.getArray('sheetPadding')!=null){ + xConfig.sheetPadding = cfg.getArray('sheetPadding')! + } + + + if(cfg.getString('drawerRadius')!=null){ + xConfig.drawerRadius = cfg.getString('drawerRadius')! + } + if(cfg.getString('modalRadius')!=null){ + xConfig.modalRadius = cfg.getString('modalRadius')! + } + if(cfg.getString('switchRadius')!=null){ + xConfig.switchRadius = cfg.getString('switchRadius')! + } + if(cfg.getString('progressRadius')!=null){ + xConfig.progressRadius = cfg.getString('progressRadius')! + } + if(cfg.getString('unRadioAndCheckBoxColor')!=null){ + xConfig.unRadioAndCheckBoxColor = cfg.getString('unRadioAndCheckBoxColor')! + } + if(cfg.getString('radioButtonRadius')!=null){ + xConfig.radioButtonRadius = cfg.getString('radioButtonRadius')! + } + if(cfg.getString('animationFun')!=null){ + xConfig.animationFun = cfg.getString('animationFun')! + } + if(cfg.getString('cardRound')!=null){ + xConfig.cardRound = cfg.getString('cardRound')! + } + if(cfg.getString('closeIcon')!=null){ + xConfig.closeIcon = cfg.getString('closeIcon')! + } + if(cfg.getString('inputBgColor')!=null){ + xConfig.inputBgColor = cfg.getString('inputBgColor')! + } + if(cfg.getString('placeholderStyle')!=null){ + xConfig.placeholderStyle = cfg.getString('placeholderStyle')! + } + return; + } + + + xConfig.language = xConfig.i18n.ops.locale +} + +export const getI18n = () : Tmui4xI18nTml => { + + return xConfig.i18n +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/config/xui.uts b/uni_modules/tmx-ui/config/xui.uts new file mode 100644 index 0000000..7b0f891 --- /dev/null +++ b/uni_modules/tmx-ui/config/xui.uts @@ -0,0 +1,82 @@ +import { xProvitae, xConfig ,setConfig} from "./xConfig.uts" +import { Tmui4xI18nTml} from "@/uni_modules/x-vuei18n-s/interface.uts" +import { getDarkMode, isCustomTheme, WebObserveTheme, setThemeDarkModel } from "./observeAppTheme.uts" +import {Tmui4xOptions} from "@/uni_modules/tmx-ui/interface.uts" +const xui = definePlugin({ + install(app:VueApp,config:Tmui4xOptions|null) { + setConfig(config) + + /** + * 组合式代码中使用 + */ + app.config.globalProperties.$i18n = xConfig.i18n + let darkModel = getDarkMode(); + if (isCustomTheme()) { + xConfig.dark = darkModel + } else { + if (xConfig.dark == 'auto') { + uni.setStorageSync('tmuiXuiOsThemeSet', darkModel) + xConfig.dark = darkModel + } else { + uni.setStorageSync('tmuiXuiOsThemeSet', xConfig.dark) + } + } + WebObserveTheme() + setThemeDarkModel() + app.mixin({ + data() { + return { + /** + * 模板vue内及选项式this.i18n可调用使用 + */ + i18n: xConfig.i18n as Tmui4xI18nTml + } + }, + computed:{ + // #ifdef MP + xThemeConfigBgColor():string{ + return xConfig.dark=='dark'?xConfig.backgroundColorContentDark:xConfig.backgroundColorContentLight + }, + xThemeConfigNavBgColor():string{ + return xConfig.dark=='dark'?xConfig.navigationBarBackgroundColorDark:xConfig.navigationBarBackgroundColorLight + }, + xThemeConfigNavFontColor():string{ + return xConfig.dark=='dark'?xConfig.navigationBarTextStyleDark:xConfig.navigationBarTextStyleLight + }, + xThemeConfigIsDark():boolean{ + return xConfig.dark=='dark' + } + // #endif + }, + onPageScroll(e) { + xProvitae.scrollTop = e.scrollTop + uni.$emit('onPageScroll', e.scrollTop) + }, + onResize() { + uni.$emit('onResize', function () { }) + }, + onLoad() { + + }, + onHide() { + uni.$emit('onHide', function () { }) + }, + onReady(){ + uni.$emit('onReady', function () { }) + xProvitae.pageReady = true; + }, + onShow() { + // #ifdef WEB + this.$nextTick(()=>{ + setThemeDarkModel() + }) + // #endif + uni.$emit('onShow', function () { }) + } + }) + } +}) + + + +export default xui \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/android/button.uts b/uni_modules/tmx-ui/core/android/button.uts new file mode 100644 index 0000000..c06c8b2 --- /dev/null +++ b/uni_modules/tmx-ui/core/android/button.uts @@ -0,0 +1,259 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +import { ref} from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import Typeface from 'android.graphics.Typeface'; +import {hexToRgb,getDefaultColor,toFillMarginAr,colorGetHover,colorGetThint} from "../util/xCoreColorUtil.uts" +import {getUid,dp2px} from "../util/xCoreUtil.uts" + +import xLinearView from "./linearView.uts"; +import xCardView from "./cardView.uts"; +import xIcon from "./icon.uts"; +import xText from "./text.uts"; + +class xButton { + view:xLinearView; + textLayer:xText; + iconLayer:xIcon; + bgLayer:xCardView; + wrapLinear:xLinearView; + width:number = 180; + heigth:number = 64; + private _backgroundColor = "primary"; + status = 'default';//default,success,warn,danger + type = 'primary';//normal,primary,secondary,dashed,outlin,text + + constructor(context : Context){ + let boxLinear = new xLinearView(context) + let wrapLinear = new xLinearView(context) + let bgView = new xCardView(context) + let iconView = new xIcon(context) + let laberView = new xText(context) + + boxLinear.setLayoutParams(this.width.toInt(),this.heigth.toInt(),0) + boxLinear.setAlign(Gravity.CENTER) + + + + wrapLinear.setLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT,0) + wrapLinear.setAlign(Gravity.CENTER_VERTICAL|Gravity.CENTER) + + bgView.setRadius(6); + + iconView.setFontColor("white").setFontSize(18) + laberView.setBackgroundColor('transparent').setFontColor("white").setFontSize(16) + laberView.setLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,0) + + + wrapLinear.append(iconView.getView(),laberView.getView()) + bgView.append(wrapLinear.getView() as View) + boxLinear.append(bgView.getView() as View) + + this.textLayer = laberView; + this.wrapLinear = wrapLinear; + this.bgLayer = bgView; + this.iconLayer = iconView; + this.view = boxLinear; + this._setBackgroundColor('','up') + bgView.setTouchStart((event : MotionEvent):void=>{ + this._setBackgroundColor('','down') + }).setTouchEnd((event : MotionEvent):void=>{ + this._setBackgroundColor('','up') + }) + + } + /** + * type: + * auto:按钮宽度自动为内容宽,w宽度失效。 + * block:按钮宽度自动为父级宽,w宽度失效。 + * '':空值,取w,h为按钮宽和高。 + * 'mini':44,24,10 + * 'small':64,32,12 + * 'medium':180,64,15 + * 'large':220,76,16 + */ + setSize(w:number,h:number,type= ''):xButton{ + if(type =='auto'){ + this.width = w; + this.heigth = h; + this.view.setLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,this.heigth.toInt(),0) + }else if(type =='mini'){ + this.heigth = 28; + this.view.setLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,this.heigth.toInt(),0) + // this.bgLayer.setLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,this.heigth.toInt(),0) + + + + this.setFontSize(10) + }else if(type =='small'){ + this.width = 64; + this.heigth = 32; + this.view.setLayoutParams(this.width.toInt(),this.heigth.toInt(),0) + }else if(type =='medium'||type==''){ + this.width = 180; + this.heigth = 64; + this.view.setLayoutParams(this.width.toInt(),this.heigth.toInt(),0) + }else if(type =='large'){ + this.width = 220; + this.heigth = 76; + this.view.setLayoutParams(this.width.toInt(),this.heigth.toInt(),0) + } + + return this; + } + //primary,secondary,dashed,outlin,text + setType(str:string):xButton{ + this.type = str; + this._setBackgroundColor('','up') + return this; + } + //primary,secondary,dashed,outlin,text + setStatus(str:string):xButton{ + this.status = str; + this._setBackgroundColor('','up') + return this; + } + setDisabled(dis:boolean) : xButton{ + this.bgLayer.setDisabled(dis); + this._setBackgroundColor("#A5A5A5",'down') + return this; + } + setLabel(str:string):xButton{ + let label = this.textLayer as xText; + label.setText(str); + return this; + } + setRadius(radius:number):xButton{ + let bgView = this.bgLayer as xCardView; + bgView.setRadius(radius); + return this; + } + + setClick(fun?:(event: MotionEvent)=>void) : xButton{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setClick(fun) + } + return this; + } + + setIcon(name:string):xButton{ + let iconLayer = this.iconLayer as xIcon; + let label = this.textLayer as xText; + iconLayer.setIcon(name); + label.setPadding([10,0,0,0]) + return this; + } + setFontSize(size:number):xButton{ + let label = this.textLayer as xText; + let iconLayer = this.iconLayer as xIcon; + label.setFontSize(size.toInt()) + iconLayer.setFontSize(size.toInt()) + return this; + } + + setFontColor(str:string):xButton{ + let label = this.textLayer as xText; + let iconLayer = this.iconLayer as xIcon; + label.setFontColor(str) + iconLayer.setFontColor(str) + return this; + } + setBorder(w?:number,colorStr?:string,dashed?:boolean):xButton{ + this.bgLayer.setBorder(w,colorStr,dashed) + return this; + } + private _setBackgroundColor(str:string,clickStatus:string):xButton{ + let cr = this._backgroundColor; + + let fontColor = "" + if(str !=''){ + cr = str; + }else{ + if(this.status==""||this.status=="default"){ + cr = 'primary' + }else if(this.status == 'success'){ + cr = 'green' + }else if(this.status == 'warn'){ + cr = 'orange' + }else if(this.status == 'danger'){ + cr = 'red' + }else if(this.status == 'normal'){ + cr = '#D8D8D8' + fontColor = '#333333' + } + } + + + let lightColor = colorGetThint(cr); + let defaultColor = colorGetHover(cr); + + if(clickStatus=='down'){ + if(this.type == 'primary' || this.type==""){ + this.bgLayer.setBackgroundColor(defaultColor.getString("hover")!); + + }else if(this.type == 'secondary'){ + this.setFontColor(cr) + this.bgLayer.setBackgroundColor(lightColor.getString("hover")!); + }else if(this.type == 'outline'){ + this.setFontColor(cr) + this.bgLayer.setBackgroundColor('transparent'); + this.setBorder(1,cr,false) + }else if(this.type == 'dashed'){ + this.setFontColor(cr) + this.bgLayer.setBackgroundColor(lightColor.getString("hover")!); + this.setBorder(1,cr,true) + }else if(this.type == 'text'){ + this.setFontColor(defaultColor.getString("hover")!) + this.bgLayer.setBackgroundColor('transparent'); + } + }else if(clickStatus=='up'){ + if(this.type == 'primary' || this.type==""){ + this.bgLayer.setBackgroundColor(defaultColor.getString("default")!); + }else if(this.type == 'secondary'){ + this.setFontColor(cr) + this.bgLayer.setBackgroundColor(lightColor.getString("default")!); + }else if(this.type == 'outline'){ + this.setFontColor(cr) + this.bgLayer.setBackgroundColor('transparent'); + this.setBorder(1,cr,false) + }else if(this.type == 'dashed'){ + this.setFontColor(cr) + this.bgLayer.setBackgroundColor(lightColor.getString("default")!); + this.setBorder(1,cr,true) + }else if(this.type == 'text'){ + this.setFontColor(cr) + this.bgLayer.setBackgroundColor('transparent'); + } + } + + if(fontColor!=''){ + this.setFontColor(fontColor) + } + + + return this; + } + + setBackgroundColor(str:string):xButton{ + this.bgLayer.setBackgroundColor(str); + this._backgroundColor = str; + return this; + } + + getView():View{ + return this.view.getView() as View; + } + + +} + +export default xButton; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/android/cardView.uts b/uni_modules/tmx-ui/core/android/cardView.uts new file mode 100644 index 0000000..6d29808 --- /dev/null +++ b/uni_modules/tmx-ui/core/android/cardView.uts @@ -0,0 +1,242 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +// import CardView from 'androidx.cardview.widget.CardView'; +import { ref, } from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; + +import {hexToRgb,getDefaultColor} from "../util/xCoreColorUtil.uts" +import {getUid, dp2px} from "../util/xCoreUtil.uts" + +import xView from "./view.uts"; + + +class xCardView extends xView { + override view:any; + bgLayer:xView; + contentView:any + wrap:RelativeLayout + contentParams:LinearLayout.LayoutParams + constructor(context : Context){ + super(context); + let box = new LinearLayout(context); + box.setOrientation(LinearLayout.VERTICAL) + box.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + (0).toInt(), + (0).toFloat() + )) + let wrap = new RelativeLayout(context); + let content = new LinearLayout(context); + + let RLay = new RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + wrap.setLayoutParams(RLay) + + + + this.bgLayer = new xView(context); + + + content.setBackground(this.bgLayer.bgView); + content.setClipToOutline(true); + this.contentParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + content.setLayoutParams(this.contentParams) + content.setOrientation(LinearLayout.VERTICAL) + this.contentView = content; + this.wrap =wrap; + wrap.addView(this.bgLayer.getView()) + wrap.addView(content as View) + box.addView(wrap as View) + + this.view = box; + } + override getView():LinearLayout{ + return this.view as LinearLayout; + } + + override setBackgroundColor(colorStr : string) : xCardView { + + + this.bgLayer.setBackgroundColor(colorStr) + return this; + } + + override setRadius(radius:any) : xCardView{ + this.bgLayer.setRadius(radius) + return this; + } + + override setBorder(w?:number,colorStr?:string,dashed?:boolean):xCardView{ + this.bgLayer.setBorder(w,colorStr,dashed) + return this; + } + + override setHeight(height : number) : xCardView { + console.error("不支持,请通过linerView设置,并将本CardView加入其中来设置高度。") + + return this; + } + + override setPadding(n:any):xCardView{ + let view = this.contentView as ViewGroup; + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = dp2px(rds).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = dp2px(rd[0]).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + view.setPadding(dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt(),dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + view.setPadding(dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt(),dp2px(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + view.setPadding(dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt(),dp2px(rd[2]).toInt(),dp2px(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = dp2px(rd).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + } + + return this; + } + + override setDisabled(dis:boolean) : xCardView{ + this.bgLayer.setDisabled(dis) + return this; + } + + override setSwiper(fun?:(event: MotionEvent,detail?:UTSJSONObject)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setSwiper(fun) + } + return this; + } + override setDoubleClick(fun?:(event: MotionEvent)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setDoubleClick(fun) + } + return this; + } + override setClick(fun?:(event: MotionEvent)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setClick(fun) + } + return this; + } + override setTouchStart(fun?:(event: MotionEvent)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setTouchStart(fun) + } + return this; + } + override setTouchMove(fun?:(event: MotionEvent)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setTouchMove(fun) + } + return this; + } + override setTouchEnd(fun?:(event: MotionEvent)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setTouchEnd(fun) + } + return this; + } + override setTouchCancel(fun?:(event: MotionEvent)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setTouchCancel(fun) + } + return this; + } + override setTouchLongPress(fun?:(event: MotionEvent)=>void) : xCardView{ + if(typeof fun !== 'undefined'){ + this.bgLayer.setTouchCancel(fun) + } + + return this; + } + + + setAlign(cr:Int) : xCardView{ + let view = this.contentView as LinearLayout; + view.setGravity(cr) + return this; + } + setLayoutParams(width?:number,height?:number,layouWidth?:number):xCardView{ + let view = this.contentView as LinearLayout; + let w = (0).toInt(); + let h = ViewGroup.LayoutParams.WRAP_CONTENT; + let flex = (1).toFloat(); + + if(typeof width =='number'){ + let tw = width!; + w = tw.toInt(); + } + if(typeof height =='number'){ + let th = height!; + h = th.toInt(); + } + if(typeof layouWidth =='number'&&layouWidth!=-1){ + let tf = layouWidth!; + flex = tf.toFloat(); + console.log('null',layouWidth) + let layoutParams_crd = new LinearLayout.LayoutParams( + w, + h, + flex + ) + this.contentParams = layoutParams_crd + }else{ + console.log('null') + let layoutParams_crd = new LinearLayout.LayoutParams( + w, + h + ) + this.contentParams = layoutParams_crd + } + + + + + // 未知原因设置这个会闪退。 + // view.setLayoutParams(layoutParams_crd); + return this; + } + + append(children : View,...args: View[]):xCardView{ + let view = this.contentView as ViewGroup; + view.addView(children) + args.forEach((el)=>view.addView(el)) + + return this; + } + appendChild(children : View):xCardView { + let view = this.contentView as ViewGroup; + view.addView(children) + + return this; + } +} + +export default xCardView; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/android/icon.uts b/uni_modules/tmx-ui/core/android/icon.uts new file mode 100644 index 0000000..2c972ed --- /dev/null +++ b/uni_modules/tmx-ui/core/android/icon.uts @@ -0,0 +1,68 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +import { ref} from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import Typeface from 'android.graphics.Typeface'; +import {hexToRgb,getDefaultColor,toFillMarginAr} from "../util/xCoreColorUtil.uts" +import {getUid,dp2px} from "../util/xCoreUtil.uts" + + +class xIcon { + view:any + constructor(context : Context,name:string=""){ + let view = new TextView(context); + let layoutParams_crd = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + + view.setGravity(Gravity.CENTER) + view.setLayoutParams(layoutParams_crd); + this.view = view; + + this._setCodeStr(name) + } + getView():View{ + return this.view as View; + } + setIcon(name:string=""):xIcon{ + this._setCodeStr(name) + return this; + } + + setFontSize(n:number):xIcon{ + let view = this.view as TextView; + view.setTextSize(dp2px(n).toFloat()) + return this; + } + setFontColor(str:string):xIcon{ + let view = this.view as TextView; + view.setTextColor(Color.parseColor(getDefaultColor(str))) + return this; + } + + private _setCodeStr(code:string){ + let view = this.view as TextView; + let assetManager = view.getContext()!.getAssets(); + let typeface = Typeface.createFromAsset(assetManager, "remixicon.ttf") + view.setTypeface(typeface) + if(!TextUtils.isEmpty(code)){ + let codePoint = Integer.parseInt(code, 16); + let charArray = Character.toChars(codePoint); + let text = new String(charArray); + view.setText(text); + } + } + +} + +export default xIcon; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/android/linearView.uts b/uni_modules/tmx-ui/core/android/linearView.uts new file mode 100644 index 0000000..ddb0371 --- /dev/null +++ b/uni_modules/tmx-ui/core/android/linearView.uts @@ -0,0 +1,130 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +// import CardView from 'androidx.cardview.widget.CardView'; +import { ref, } from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; + +import {hexToRgb,getDefaultColor} from "../util/xCoreColorUtil.uts" +import {getUid, dp2px} from "../util/xCoreUtil.uts" + +import xView from "./view.uts"; + +class xLinearView extends xView { + override view:any; + contentParams:LinearLayout.LayoutParams + constructor(context : Context){ + super(context); + let box = new LinearLayout(context); + this.contentParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + ) + box.setLayoutParams(this.contentParams) + + this.view = box; + } + override getView():LinearLayout{ + return this.view as LinearLayout; + } + + override setBackgroundColor(colorStr : string) : xLinearView { + console.error("不支持,请通过cardView设置") + return this; + } + + override setRadius(radius:any) : xLinearView{ + console.error("不支持,请通过cardView设置") + return this; + } + + override setBorder(w?:number,colorStr?:string,dashed?:boolean):xLinearView{ + console.error("不支持,请通过cardView设置") + return this; + } + + override setHeight(height : number) : xLinearView { + console.error("不支持,请通过linerView设置,并将本CardView加入其中来设置高度。") + + return this; + } + + //让内容的对齐方向, + //https://developer.android.google.cn/reference/kotlin/android/view/Gravity + //只有tmxTextView,有这个属性。 + setAlign(cr:Int) : xLinearView{ + let view = this.view as LinearLayout; + view.setGravity(cr) + return this; + } + + setLayoutParams(width?:number,height?:number,layouWidth?:number) : xLinearView{ + let view = this.view as LinearLayout; + let w = (0).toInt(); + let h = ViewGroup.LayoutParams.WRAP_CONTENT; + let flex = (1).toFloat(); + + if(typeof width =='number'){ + w = width!.toInt(); + } + if(typeof height =='number'){ + h = height!.toInt(); + } + if(typeof layouWidth =='number'&&layouWidth!=-1){ + let tf = layouWidth!; + flex = tf.toFloat(); + console.log('null',layouWidth) + let layoutParams_crd = new LinearLayout.LayoutParams( + w, + h, + flex + ) + this.contentParams = layoutParams_crd + }else{ + console.log('null') + let layoutParams_crd = new LinearLayout.LayoutParams( + w, + h + ) + this.contentParams = layoutParams_crd + } + + return this; + } + + //内容的排版方向:vertical,horizontal + setLayoutDirection(dir:string) : xLinearView{ + let view = this.view as LinearLayout; + if(dir=='VERTICAL'){ + view.setOrientation(LinearLayout.VERTICAL) + }else if(dir=='HORIZONTAL'){ + view.setOrientation(LinearLayout.HORIZONTAL) + } + + return this + } + + append(children : View,...args: View[]) : xLinearView { + let view = this.view as ViewGroup; + view.addView(children) + args.forEach((el)=>view.addView(el)) + + return this; + } + appendChild(children : View) : xLinearView { + let view = this.view as ViewGroup; + view.addView(children) + return this; + } +} + +export default xLinearView; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/android/text.uts b/uni_modules/tmx-ui/core/android/text.uts new file mode 100644 index 0000000..ca165d0 --- /dev/null +++ b/uni_modules/tmx-ui/core/android/text.uts @@ -0,0 +1,301 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +// import CardView from 'androidx.cardview.widget.CardView'; +import { ref, } from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import Typeface from 'android.graphics.Typeface'; +import {hexToRgb,getDefaultColor,toFillMarginAr} from "../util/xCoreColorUtil.uts" +import {getUid,dp2px} from "../util/xCoreUtil.uts" + +import xView from "./view.uts"; + +class xText extends xView { + override view:any + constructor(context : Context,str:string=""){ + super(context); + let view = new TextView(context); + let layoutParams_crd = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + (1).toFloat() + ) + view.setText(str); + view.setLayoutParams(layoutParams_crd); + + this.bgView = new GradientDrawable(); + this.bgView.setShape(0x00000000) + this.bgView.setColor(Color.WHITE) + this.bgView.mutate() + view.setBackground(this.bgView) + + this.view = view; + } + override getView():View{ + + return this.view as View; + } + override setBackgroundColor(colorStr : string) : xText { + this.bgView.mutate() + if(colorStr == 'transparent'){ + this.bgView.setColor(Color.TRANSPARENT) + }else{ + this.bgView.setColor(Color.parseColor(getDefaultColor(colorStr))) + } + + return this; + } + override setBorder(w?:number,colorStr?:string,dashed?:boolean) : xText { + this.bgView.mutate() + + let tw:number = 1; + let tcolor = 'transparent'; + let tdashed = false; + if(typeof tw !== 'undefined'){ + tw = w as number; + } + if(typeof tw !== 'undefined'){ + tcolor = colorStr as string; + } + + if(typeof dashed !== 'undefined'){ + tdashed = dashed as boolean; + } + + let colorNum = Color.TRANSPARENT; + if(tcolor != 'transparent'){ + colorNum = Color.parseColor(getDefaultColor(tcolor)); + } + if(dashed == true){ + let dashedWidth = dp2px(6) + let dashedGap = dp2px(4) + this.bgView.setStroke(dp2px(tw).toInt(),colorNum,dashedWidth.toFloat(),dashedGap.toFloat()) + }else{ + this.bgView.setStroke(dp2px(tw).toInt(),colorNum) + } + + + return this; + } + override setRadius(radius:any) : xText{ + let x =0 + let y =0 + this.bgView.mutate() + if(Array.isArray(radius)){ + let rd = radius as number[]; + if(rd.length==0){ + let rdfs = 0; + this.bgView.setCornerRadius(dp2px(rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==1){ + let rdfs = rd[0]; + this.bgView.setCornerRadius(dp2px(rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==2){ + let tl = [ + dp2px(rd[0]).toFloat(),dp2px(rd[0]).toFloat(), + dp2px(rd[1]).toFloat(),dp2px(rd[1]).toFloat(), + x.toFloat(),x.toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==3){ + let tl = [ + dp2px(rd[0]).toFloat(),dp2px(rd[0]).toFloat(), + dp2px(rd[1]).toFloat(),dp2px(rd[1]).toFloat(), + dp2px(rd[2]).toFloat(),dp2px(rd[2]).toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==4){ + let tl = [ + dp2px(rd[0]).toFloat(),dp2px(rd[0]).toFloat(), + dp2px(rd[1]).toFloat(),dp2px(rd[1]).toFloat(), + dp2px(rd[2]).toFloat(),dp2px(rd[2]).toFloat(), + dp2px(rd[3]).toFloat(),dp2px(rd[3]).toFloat(), + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + } + }else{ + + let rd = radius as number; + + this.bgView.setCornerRadius(dp2px(rd).toFloat()); + } + + + return this; + } + + setFontSize(n:number):xText{ + let view = this.view as TextView; + view.setTextSize(dp2px(n).toFloat()) + return this; + } + setFontColor(str:string):xText{ + let view = this.view as TextView; + view.setTextColor(Color.parseColor(getDefaultColor(str))) + + return this; + } + //是否允许复制。 + setTextIsSelectable(isSelectet:boolean):xText{ + let view = this.view as TextView; + view.setTextIsSelectable(isSelectet) + return this; + } + //bold,normal,ligth + setFontWeight(str:string):xText{ + let view = this.view as TextView; + if(str=='bold'){ + view.setTypeface(null,Typeface.BOLD) + }else{ + view.setTypeface(null,Typeface.NORMAL) + } + return this; + } + setFontStyle(str:string):xText{ + let view = this.view as TextView; + if(str=='italtc'){ + view.setTypeface(null,Typeface.ITALIC) + }else if(str=='italtc-bold'){ + view.setTypeface(null,Typeface.BOLD_ITALIC) + } + return this; + } + setText(str:string):xText{ + let view = this.view as TextView; + view.setText(str) + + return this; + } + override setPadding(n:any):xText{ + let view = this.view as TextView; + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = dp2px(rds).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = dp2px(rd[0]).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + view.setPadding(dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt(),dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + view.setPadding(dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt(),dp2px(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + view.setPadding(dp2px(rd[0]).toInt(),dp2px(rd[1]).toInt(),dp2px(rd[2]).toInt(),dp2px(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = dp2px(rd).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + } + + return this; + } + + //让内容的对齐方向, + //https://developer.android.google.cn/reference/kotlin/android/view/Gravity + //只有xTextView,有这个属性。 + setAlign(cr:Int) : xText{ + let view = this.view as TextView; + view.setGravity(cr) + return this; + } + //追加文本 + //start,end不填写就追加到末尾。 + setIcon(code:string,start:number=0,end:number=0) : xText{ + let view = this.view as TextView; + let nowText = view.getText().toString(); + + let assetManager = view.getContext()!.getAssets(); + let typeface = Typeface.createFromAsset(assetManager, "remixicon.ttf") + view.setTypeface(typeface) + + if(!TextUtils.isEmpty(code)){ + let codePoint = Integer.parseInt(code, 16); + let charArray = Character.toChars(codePoint); + let text = new String(charArray); + view.setText(text+" "+nowText); + } + + return this; + } + setLayoutParams(width?:number,height?:number,layouWidth?:number) : xText{ + let view = this.view as TextView; + let w = (0).toInt(); + let h = ViewGroup.LayoutParams.WRAP_CONTENT; + let flex = (1).toFloat(); + + if(typeof width =='number'){ + w = width!.toInt(); + } + if(typeof height =='number'){ + h = height!.toInt(); + } + if(typeof layouWidth =='number'){ + flex = layouWidth!.toFloat(); + } + + let layoutParams_crd = new LinearLayout.LayoutParams( + w, + h, + flex + ) + view.setLayoutParams(layoutParams_crd); + + return this; + } + + setLineHeight(line:number) : xText{ + let view = this.view as TextView; + view.setLineHeight(line.toInt()) + return this; + } + setLetterSpacing(space:number) : xText{ + let view = this.view as TextView; + view.setLineHeight(space.toInt()) + return this; + } + setHighlightColor(color:string) : xText{ + let view = this.view as TextView; + if(!TextUtils.isEmpty(color)){ + view.setHighlightColor(Color.parseColor(getDefaultColor(color))) + } + + return this; + } + + + // 设置文字的省略情况,0表示不显示省略号,数字表示几行显示省略号。 + setEllipsis(lines:number=0) : xText{ + let view = this.view as TextView; + if(lines>0){ + view.setMaxLines(lines.toInt()) + view.setEllipsize(TextUtils.TruncateAt.END) + }else{ + view.setMaxLines((1).toInt()) + view.setEllipsize(null) + } + return this; + } + +} + +export default xText; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/android/view.uts b/uni_modules/tmx-ui/core/android/view.uts new file mode 100644 index 0000000..155ba52 --- /dev/null +++ b/uni_modules/tmx-ui/core/android/view.uts @@ -0,0 +1,486 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +// import CardView from 'androidx.cardview.widget.CardView'; +import { ref, } from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import ColorStateList from 'android.content.res.ColorStateList'; +import attr from 'android.R.attr' +import {hexToRgb,getDefaultColor} from "../util/xCoreColorUtil.uts" + + +/** + * 数字转16进制 + */ +function toHex(numbers : number) : string { + let i = 0 as number + if (numbers === i) { + return '00'; + } + let hex = ''; + const hexChars = '0123456789abcdef'; + while (numbers > 0) { + const remainder = numbers % 16; + hex = hexChars[remainder] + hex; + numbers = Math.floor(numbers / 16); + } + return hex; +} + +/** + * 随机一个uid + * @param rdix 随机因子 + * @param length 取的长度 + * @param isAddStr 是否限制随机结果中的长度,不允许输出长度 + * @returns String + */ +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifndef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length); + // #endif + + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} + +class MyClickListener implements View.OnClickListener { + callbackFun:()=>void; + constructor(cal?:()=>void){ + this.callbackFun = cal as ()=>void; + } + override onClick(v?:View):void { + if(typeof this.callbackFun !='underfinde'){ + this.callbackFun(); + } + } +} +class MyTouchListener implements View.OnTouchListener { + //down,up,move,cancel,longClick + callbackFun:(types:string,event : MotionEvent,detail:UTSJSONObject)=>void; + dubleTime = 0; + tid = 56; + _x = 0; + _y = 0; + // 判断方向的差值 + swipe_mindiff = 40 + // 滑动时,一定时间内只能触发一次事件。不能连续触发。 + tid_siper = 100; + swipeDirection = "" + constructor(call:(types:string,event : MotionEvent,detail?:UTSJSONObject)=>void) { + this.callbackFun = call; + } + override onTouch(view : View, event : MotionEvent) : Boolean { + + if(event.action == MotionEvent.ACTION_DOWN ){ + this._x = event.getX(); + this._y = event.getY(); + this.swipeDirection = "" + this.callbackFun('down',event,{}); + let difftime = new Date().getTime() - this.dubleTime; + if(difftime >0 && difftime<=300){ + this.callbackFun('doubleClick',event ,{}); + } + this.dubleTime = new Date().getTime(); + clearTimeout(this.tid) + tid = setTimeout(function() { + this.callbackFun('longPress',event,{}); + }, 800); + } + if(event.action == MotionEvent.ACTION_UP ){ + clearTimeout(this.tid) + this.callbackFun('up',event,{}); + if(new Date().getTime() - this.dubleTime > 50){ + this.callbackFun('click',event,{}); + } + } + if(event.action == MotionEvent.ACTION_CANCEL || event.action== MotionEvent.ACTION_OUTSIDE ){ + this.callbackFun('cancel',event,{}); + clearTimeout(this.tid) + + } + + if(event.action == MotionEvent.ACTION_MOVE ){ + let x = event.getX(); + let y = event.getY(); + let deltaX = Math.abs(x - this._x); + let deltaY = Math.abs(y - this._y); + if(deltaX > deltaY && deltaX > this.swipe_mindiff){ + this.swipeDirection = (this._x > x) ? "left" : "right"; + }else if(deltaY > deltaX && deltaY > this.swipe_mindiff){ + this.swipeDirection = (this._y < y) ? "down" : "up"; + } + if(this.swipeDirection !=""){ + this.callbackFun('swiper',event,{x,y,diffX:deltaX,diffY:deltaY,direction:this.swipeDirection}); + } + // this._x = x; + // this._y = y; + this.callbackFun('move',event,{}); + clearTimeout(this.tid) + } + + + return true; + } +} + +class xView { + public view : any; + public tagId:string = 'x_view_id_'+getUid(); + public bgView:GradientDrawable + private _onclickFun= (_event : MotionEvent):void=>{}; + private _onTouchStart= (_event : MotionEvent):void=>{}; + private _onTouchEnd= (_event : MotionEvent):void=>{}; + private _onTouchCancel= (_event : MotionEvent):void=>{}; + private _onTouchMove= (_event : MotionEvent):void=>{}; + private _onTouchLongPress= (_event : MotionEvent):void=>{}; + private _onTouchDubleClick= (_event : MotionEvent):void=>{}; + private _onTouchSwiper= (_event : MotionEvent,detail?:UTSJSONObject):void=>{}; + // 设置禁用,不会触发上面的事件。 + private _disabled = false; + constructor(context : Context) { + let view = new View(context); + + view.setTag(this.tagId) + let layoutParams_crd = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + view.setLayoutParams(layoutParams_crd); + this.bgView = new GradientDrawable(); + + // let statuesInts= [[attr.state_enabled].toKotlinList().toIntArray(),[attr.state_pressed].toKotlinList().toIntArray(),[-attr.state_enabled].toKotlinList().toIntArray()] + // let statuesColors= [Color.WHITE,Color.RED,Color.RED] + // let states = new ColorStateList(statuesInts.toKotlinList().toTypedArray(),statuesColors.toKotlinList().toIntArray()) + + this.bgView.setShape(GradientDrawable.RECTANGLE) + this.bgView.setColor(Color.WHITE) + this.bgView.mutate() + view.setBackground(this.bgView) + + this.view = view; + + // view.setOnClickListener(new MyClickListener(():void=>{ + // this._onclickFun() + // })); + view.setOnTouchListener(new MyTouchListener((types:string,event : MotionEvent,detail?:UTSJSONObject):void=>{ + + if(this._disabled == false){ + if(types=='down'){ + this._onTouchStart(event) + } + if(types=='up'){ + this._onTouchEnd(event); + } + if(types=='click'){ + this._onclickFun(event); + } + if(types=='move'){ + this._onTouchMove(event) + } + if(types=='cancel'){ + this._onTouchCancel(event) + } + if(types=='longPress'){ + this._onTouchLongPress(event) + } + if(types=='doubleClick'){ + this._onTouchDubleClick(event) + } + if(types=='swiper'){ + this._onTouchSwiper(event,detail) + } + } + })); + + + } + getView():View{ + return this.view as View; + } + setDisabled(dis:boolean) : xView{ + this._disabled = dis; + return this; + } + + /** + * 触发距离是大于50时触发并判断方向 + * x,y当前坐标,diffX滑动时距离开始时按下的横向x距离,diffY表示竖向。Direction为方向:left,right,up,dowon + *detail: + *{x,y,diffX,diffY,direction} + */ + setSwiper(fun?:(event: MotionEvent,detail?:UTSJSONObject)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchSwiper = fun; + } + return this; + } + setDoubleClick(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchDubleClick = fun; + } + return this; + } + setClick(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onclickFun = fun; + } + return this; + } + setTouchStart(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchStart = fun; + } + return this; + } + setTouchMove(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchMove = fun; + } + return this; + } + setTouchEnd(fun?:(event: MotionEvent)=>void) : xView{ + + if(typeof fun !== 'undefined'){ + this._onTouchEnd = fun; + } + return this; + } + setTouchCancel(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchCancel = fun; + } + return this; + } + setTouchLongPress(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchLongPress = fun; + } + return this; + } + + + setBackgroundColor(colorStr : string) : xView { + this.bgView.mutate() + if(colorStr == 'transparent'){ + this.bgView.setColor(Color.TRANSPARENT) + }else{ + this.bgView.setColor(Color.parseColor(getDefaultColor(colorStr))) + } + + return this; + } + + setBorder(w?:number,colorStr?:string,dashed?:boolean) : xView { + this.bgView.mutate() + + let tw:number = 1; + let tcolor = 'transparent'; + let tdashed = false; + if(typeof tw !== 'undefined'){ + tw = w as number; + } + if(typeof tw !== 'undefined'){ + tcolor = colorStr as string; + } + + if(typeof dashed !== 'undefined'){ + tdashed = dashed as boolean; + } + + let colorNum = Color.TRANSPARENT; + if(tcolor != 'transparent'){ + colorNum = Color.parseColor(getDefaultColor(tcolor)); + } + if(dashed == true){ + let dashedWidth = 8 + let dashedGap = 5 + this.bgView.setStroke(tw.toInt(),colorNum,dashedWidth.toFloat(),dashedGap.toFloat()) + }else{ + this.bgView.setStroke(tw.toInt(),colorNum) + } + + + return this; + } + setMargin(n:any):xView{ + let view = this.view as View; + let selfPrams = view.getLayoutParams() + let params = new LinearLayout.LayoutParams( + selfPrams.width, + selfPrams.height + ) + + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = (rds).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = (rd[0]).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + let rds = 0; + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[0]).toInt(),(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = (rd).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + } + + view.setLayoutParams(params); + return this; + } + + setPadding(n:any):xView{ + let view = this.view as View; + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = (rds).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = (rd[0]).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[0]).toInt(),(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = (rd).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + } + + return this; + } + setRadius(radius:any) : xView{ + let x =0 + let y =0 + this.bgView.mutate() + if(Array.isArray(radius)){ + let rd = radius as number[]; + if(rd.length==0){ + let rdfs = 0; + this.bgView.setCornerRadius((rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==1){ + let rdfs = rd[0]; + this.bgView.setCornerRadius((rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==2){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + x.toFloat(),x.toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==3){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + (rd[2]).toFloat(),(rd[2]).toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==4){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + (rd[2]).toFloat(),(rd[2]).toFloat(), + (rd[3]).toFloat(),(rd[3]).toFloat(), + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + } + }else{ + + let rd = radius as number; + + this.bgView.setCornerRadius((rd).toFloat()); + } + + + return this; + } + /** 设置当前宽和高为父级的相对宽和高 + *w,h有效值为:auto|100% + */ + setSizeBy(w:string="100%",h:string = "auto"){ + let view = this.view as View; + let ww = ViewGroup.LayoutParams.MATCH_PARENT; + let hh = ViewGroup.LayoutParams.MATCH_PARENT; + if(w=="auto"){ + ww = ViewGroup.LayoutParams.WRAP_CONTENT + } + if(h=="auto"){ + hh = ViewGroup.LayoutParams.WRAP_CONTENT + } + + let layoutParams_crd = new LinearLayout.LayoutParams(ww,hh) + view.setLayoutParams(layoutParams_crd); + } + setSize(width : number, height : number) : xView { + let view = this.view as View; + let layoutParams_crd = new LinearLayout.LayoutParams( + (width).toInt(), + (height).toInt() + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + setWidth(width : number) : xView { + let view = this.view as View; + let lpar = view.getLayoutParams(); + let layoutParams_crd = new LinearLayout.LayoutParams( + (width).toInt(), + (lpar.height).toInt(), + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + setHeight(height : number) : xView { + let view = this.view as View; + let lpar = view.getLayoutParams(); + let layoutParams_crd = new LinearLayout.LayoutParams( + (lpar.width).toInt(), + (height).toInt(), + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + + + +} + +export default xView; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/android/xLog.uts b/uni_modules/tmx-ui/core/android/xLog.uts new file mode 100644 index 0000000..9acdde8 --- /dev/null +++ b/uni_modules/tmx-ui/core/android/xLog.uts @@ -0,0 +1,17 @@ +import Dialog from "android.app.Dialog" +import Context from 'android.content.Context' +import { UTSAndroid } from "io.dcloud.uts"; +import FrameLayout from "android.widget.FrameLayout"; +class xOverflay { + + static show(){ + let d = new Dialog(UTSAndroid.getUniActivity() as Context); + + let decorView = UTSAndroid.getUniActivity()!.window.decorView; + let frameContent = decorView.findViewById(android.R.id.content) as FrameLayout + // test + d.show(); + } +} + +export default xOverflay; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/ICanvas.uts b/uni_modules/tmx-ui/core/canvas/ICanvas.uts new file mode 100644 index 0000000..99c003d --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/ICanvas.uts @@ -0,0 +1,839 @@ +import { ShapeType, ICanvasEvent, ICanvasDomEvent, IEventListener, CanvasEventType, ICanvasOptional, IcanvasDomEventDetail } from './interface.uts'; +// import { Shape } from './lib/shape.uts'; +import { Shape } from '@/uni_modules/tmx-ui/core/canvas/lib/shape.uts'; +export class ICanvas { + canvas : CanvasContext | null = null; + ctx : CanvasRenderingContext2D | null = null; + canvasNode : NodeInfo | null = null + + width : number = 0; + height : number = 0; + boxWidth : number = 0; + boxHeight : number = 0; + dpr : number = 1; + /** + * 命中检测事件范围,默认只对clik点击进行命中测试,如果全放开会有性能风险 + * 相当于是事件过滤。比如['click']那么元素只会触发click事件,其它事件不会响应 + * 空数组响应所有事件 + */ + checkPointInHitEvents = ['click'] as CanvasEventType[] + + //点击时的位置 + private touch_x = 0 + private touch_y = 0 + //移动时的位置 + private touch_move_x = 0 + private touch_move_y = 0 + //结束时的位置 + private touch_end_x = 0 + private touch_end_y = 0 + //结束时相对起始时之间的位置距离 + private touch_end_len_x = 0 + private touch_end_len_y = 0 + //移动时相对上一次移动的距离 + private touch_move_len_x = 0 + private touch_move_len_y = 0 + //点击时的时间 + private touchStartTime = 0 + //点击抬起时的结束时间. + private touchEndTime = 0 + + private touchTimeTid = 0 + + + id = Math.random().toString(16).substring(4) + + gaptimeId = 23 + + private shapes : ShapeType[] = []; + private eventListeners : Map = new Map(); + + component : any | null = null; + canvasId : string; + + + constructor(config : ICanvasOptional) { + this.canvasId = config.canvasId; + this.component = config.component + } + init() : Promise { + const _this = this; + return new Promise((res) => { + uni.createSelectorQuery() + .in(_this.component) + .select("#" + _this.canvasId) + .boundingClientRect() + .exec(result => { + if (result.length == 0) return; + let node = result[0]! as NodeInfo + uni.createCanvasContextAsync({ + id: _this.canvasId, + component: _this.component as ComponentPublicInstance | null, + success: (context : CanvasContext) => { + _this.canvasNode = node + _this.canvas = context; + + const dpr = uni.getWindowInfo().pixelRatio ?? 1; + const canvasContext = context.getContext('2d')!; + // #ifdef APP + canvasContext.resetTransform() + // #endif + const canvas = canvasContext.canvas; + canvas.width = canvas.offsetWidth * dpr; + canvas.height = canvas.offsetHeight * dpr; + canvasContext.scale(dpr, dpr); + _this.ctx = canvasContext as CanvasRenderingContext2D; + + _this.dpr = dpr; + + _this.ctx!.globalAlpha = 1; + _this.width = node.width!; + _this.height = node.height!; + _this.boxWidth = canvas.offsetWidth; + _this.boxHeight = canvas.offsetHeight; + res(_this) + } + }) + }) + }) + + } + + private _resizePos() { + const _this = this; + uni.createSelectorQuery() + .in(_this.component) + .select("#" + _this.canvasId) + .boundingClientRect() + .exec(result => { + if (result.length == 0) return; + let node = result[0]! as NodeInfo + _this.canvasNode = node + }) + } + + clear() : ICanvas { + this.ctx!.clearRect(0, 0, this.width, this.height) + return this; + } + + addShape(shape : ShapeType|ShapeType[]) : ICanvas { + if(Array.isArray(shape)){ + let _this = this; + shape.forEach((el)=>{ + _this.shapes.push(el); + }) + }else{ + this.shapes.push(shape); + } + this.shapes.sort((a, b ) : number => { + let ela = a as Shape + let elb = b as Shape + return ela.zIndex - elb.zIndex + }) + return this; + } + + removeShape(shape : ShapeType) : ICanvas { + for (let i = 0; i < this.shapes.length; i++) { + let itemshape = this.shapes[i] + if (itemshape instanceof Shape && shape instanceof Shape) { + if (itemshape.id == shape.id) { + this.shapes.splice(i, 1); + break; + } + } + } + return this; + } + + render() : ICanvas { + this.clear(); + for (let i = 0; i < this.shapes.length; i++) { + const shape = this.shapes[i]; + if (shape instanceof Shape) { + shape.draw(this.ctx!); + } + } + return this; + } + + update() : ICanvas { + + let needsRender = false; + for (let i = 0; i < this.shapes.length; i++) { + const shape = this.shapes[i]; + if (shape instanceof Shape) { + if (shape.needsUpdate) { + needsRender = true; + shape.update() + } + } + } + if (needsRender) { + this.render(); + } + return this; + } + + getImage():Promise{ + return new Promise((res,_rej)=>{ + // #ifdef WEB||H5 + try { + this.ctx.canvas.toBlob((blob)=>{ + res(URL.createObjectURL(blob)) + },'images/png',1) + } catch (error) { + console.error(error,'注意画布中的图片要同域') + res('') + } + // #endif + + // #ifdef APP + let ele = uni.getElementById(this.canvasId) as UniElement + ele!.takeSnapshot({ + success(result){ + res(result.tempFilePath) + }, + fail(){ + res('') + } + }) + // #endif + + // #ifdef MP + uni.canvasToTempFilePath({ + canvasId:this.canvasId, + success(result){ + res(result.tempFilePath) + }, + fail(){ + res('') + } + },this.component) + // #endif + }) + } + /** 将外部事件绑定到对象上,实现事件分发. **/ + bindEvent(eventType : any | null) { + + let _this = this; + clearTimeout(this.touchTimeTid) + if (eventType == null || this.canvasNode == null) return; + const winTop = uni.getWindowInfo().windowTop + const offsetTop = this.canvasNode!.top! + 0 + const offsetLeft = this.canvasNode!.left! + //防止触摸和鼠标事件同时触发。 + let isTouch = false; + + // 移动端 + // #ifdef APP-ANDROID||H5 + if (eventType instanceof TouchEvent) { + // #endif + // #ifdef APP-IOS||APP-HARMONY + if (eventType instanceof UniTouchEvent) { + // #endif + // #ifdef MP + if (true) { + // #endif + + eventType.stopPropagation() + eventType.preventDefault() + + isTouch = true; + let changedTouches = eventType.changedTouches + // #ifndef APP + changedTouches = Array.from(changedTouches) + // #endif + const clientX = changedTouches[0].clientX - offsetLeft + const clientY = changedTouches[0].clientY - offsetTop + + if (eventType.type == 'touchstart') { + this.touch_x = clientX + this.touch_y = clientY + this.touch_move_x = clientX + this.touch_move_y = clientY + this.touch_end_x = clientX + this.touch_end_y = clientY + + + this.touch_end_len_x = 0 + this.touch_end_len_y = 0 + this.touch_move_len_x = 0 + this.touch_move_len_y = 0 + + + this.touchStartTime = Date.now() + this.buildEvents('down', { + type: 'down', + x: changedTouches[0].clientX - offsetLeft, + y: changedTouches[0].clientY - offsetTop, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: changedTouches.map((el) : ICanvasDomEvent => { + return { + type: 'down', + x: el.clientX - offsetLeft, + y: el.clientY - offsetTop, + touches: [], + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + } as ICanvasDomEvent + }) + } as ICanvasDomEvent) + this.touchTimeTid = setTimeout(() => { + _this.buildEvents('longpress', { + type: 'longpress', + x: changedTouches[0].clientX - offsetLeft, + y: changedTouches[0].clientY - offsetTop, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: changedTouches.map((el) : ICanvasDomEvent => { + return { + type: 'longpress', + x: el.clientX - offsetLeft, + y: el.clientY - offsetTop, + touches: [], + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + } as ICanvasDomEvent + }) + } as ICanvasDomEvent) + }, 500) + } else if (eventType.type == 'touchmove') { + + this.touch_move_len_x = this.touch_move_x - clientX + this.touch_move_len_y = this.touch_move_y - clientY + + this.touch_end_len_x = clientX - this.touch_x + this.touch_end_len_y = clientY - this.touch_y + + this.touch_move_x = clientX + this.touch_move_y = clientY + + this.buildEvents('move', { + type: 'move', + x: changedTouches[0].clientX - offsetLeft, + y: changedTouches[0].clientY - offsetTop, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: changedTouches.map((el) : ICanvasDomEvent => { + return { + type: 'move', + x: el.clientX - offsetLeft, + y: el.clientY - offsetTop, + touches: [], + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + } as ICanvasDomEvent + }) + } as ICanvasDomEvent) + + } else if (eventType.type == 'touchend') { + this.touch_end_x = clientX + this.touch_end_y = clientY + this.touch_end_len_x = this.touch_end_x - this.touch_x + this.touch_end_len_y = this.touch_end_y - this.touch_y + + let nowTIme = Date.now() + this.buildEvents('up', { + type: 'up', + x: changedTouches[0].clientX - offsetLeft, + y: changedTouches[0].clientY - offsetTop, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: changedTouches.map((el) : ICanvasDomEvent => { + return { + type: 'up', + x: el.clientX - offsetLeft, + y: el.clientY - offsetTop, + touches: [], + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + } as ICanvasDomEvent + }) + } as ICanvasDomEvent) + // 判断是不是单击 + const difftime = nowTIme - this.touchStartTime + if (difftime > 50 && difftime < 250) { + this.buildEvents('click', { + type: 'click', + x: changedTouches[0].clientX - offsetLeft, + y: changedTouches[0].clientY - offsetTop, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: changedTouches.map((el) : ICanvasDomEvent => { + return { + type: 'click', + x: el.clientX - offsetLeft, + y: el.clientY - offsetTop, + touches: [], + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + } as ICanvasDomEvent + }) + } as ICanvasDomEvent) + } + // 判断是不是双击 + const diffEndtime = nowTIme - this.touchEndTime + if (diffEndtime > 100 && diffEndtime < 280) { + this.buildEvents('dbclick', { + type: 'dbclick', + x: changedTouches[0].clientX - offsetLeft, + y: changedTouches[0].clientY - offsetTop, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: [] as ICanvasDomEvent[] + }) + } + this.touchEndTime = nowTIme + } else if (eventType.type == 'touchcancel') { + this.touch_end_x = clientX + this.touch_end_y = clientY + this.touch_end_len_x = this.touch_end_x - this.touch_x + this.touch_end_len_y = this.touch_end_y - this.touch_y + const touchesList = changedTouches.map((el) : ICanvasDomEvent => { + return { + type: 'cancel', + x: el.clientX - offsetLeft, + y: el.clientY - offsetTop, + touches: [], + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + } as IcanvasDomEventDetail ] as IcanvasDomEventDetail[], + } as ICanvasDomEvent + }) + this.buildEvents('cancel', { + type: 'cancel', + x: changedTouches[0].clientX - offsetLeft, + y: changedTouches[0].clientY - offsetTop, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + } as IcanvasDomEventDetail ] as IcanvasDomEventDetail[], + touches: touchesList as ICanvasDomEvent[] + } as ICanvasDomEvent) + } + } + // 兼容PC + // #ifdef WEB + + if (eventType instanceof MouseEvent && !(eventType instanceof PointerEvent) && !isTouch) { + eventType.stopPropagation() + const clientX = eventType.layerX + const clientY = eventType.layerY + + if (eventType.type == 'mousedown') { + this.touch_x = clientX + this.touch_y = clientY + this.touch_move_x = clientX + this.touch_move_y = clientY + this.touch_end_x = clientX + this.touch_end_y = clientY + + + this.touch_end_len_x = 0 + this.touch_end_len_y = 0 + this.touch_move_len_x = 0 + this.touch_move_len_y = 0 + + this.touchStartTime = Date.now() + window.ICnavansId = this.id + this.buildEvents('down', { + type: 'down', + x: clientX, + y: clientY, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: [] as ICanvasDomEvent[] + }) + + this.touchTimeTid = setTimeout(() => { + _this.buildEvents('longpress', { + type: 'longpress', + x: clientX, + y: clientY, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: [] as ICanvasDomEvent[] + } as ICanvasDomEvent) + }, 500) + } + if (eventType.type == 'mousemove' && window.ICnavansId === this.id) { + this.touch_move_len_x = this.touch_move_x - clientX + this.touch_move_len_y = this.touch_move_y - clientY + + this.touch_end_len_x = clientX - this.touch_x + this.touch_end_len_y = clientY - this.touch_y + + this.touch_move_x = clientX + this.touch_move_y = clientY + + this.buildEvents('move', { + type: 'move', + x: clientX, + y: clientY, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: [] as ICanvasDomEvent[] + }) + } + if ((eventType.type == 'mouseup') && window.ICnavansId === this.id) { + this.touch_end_x = clientX + this.touch_end_y = clientY + this.touch_end_len_x = this.touch_end_x - this.touch_x + this.touch_end_len_y = this.touch_end_y - this.touch_y + + let nowTIme = Date.now() + window.ICnavansId = "" + + this.buildEvents('up', { + type: 'up', + x: clientX, + y: clientY, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: [] as ICanvasDomEvent[] + }) + + // 判断是不是单击 + const difftime = nowTIme - this.touchStartTime + if (difftime > 50 && difftime < 250) { + this.buildEvents('click', { + type: 'click', + x: clientX, + y: clientY, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: [] as ICanvasDomEvent[] + } as ICanvasDomEvent) + } + + // 判断是不是双击 + const diffEndtime = nowTIme - this.touchEndTime + if (diffEndtime > 100 && diffEndtime < 280) { + this.buildEvents('dbclick', { + type: 'dbclick', + x: clientX, + y: clientY, + detail: [], + touches: [] as ICanvasDomEvent[] + }) + } + this.touchEndTime = nowTIme + } + if ((eventType.type == 'mouseleave') && window.ICnavansId === this.id) { + this.touch_end_x = clientX + this.touch_end_y = clientY + this.touch_end_len_x = this.touch_end_x - this.touch_x + this.touch_end_len_y = this.touch_end_y - this.touch_y + + window.ICnavansId = "" + this.buildEvents('cancel', { + type: 'cancel', + x: clientX, + y: clientY, + detail: [{ + startX: this.touch_x, + startY: this.touch_y, + endX: this.touch_end_x, + endY: this.touch_end_y, + moveX: this.touch_move_x, + moveY: this.touch_move_y, + moveLenX: this.touch_move_len_x, + moveLenY: this.touch_move_len_y, + endLenX: this.touch_end_len_x, + endLenY: this.touch_end_len_y + }], + touches: [] as ICanvasDomEvent[] + }) + } + + } + // #endif + + + } + + addEventListener(eventName : CanvasEventType, listener : IEventListener) : ICanvas { + if (!this.eventListeners.has(eventName)) { + this.eventListeners.set(eventName, []); + } + this.eventListeners.get(eventName)!.push(listener); + return this; + } + + removeEventListener(eventName : CanvasEventType, listener : IEventListener) : ICanvas { + const listeners = this.eventListeners.get(eventName); + if (listeners == null) return this; + const index = listeners.indexOf(listener); + if (index != -1) { + listeners.splice(index, 1); + } + return this; + } + + private getTargetShape(eventName : CanvasEventType, x : number, y : number) : ShapeType[] { + let shapes = [] as ShapeType[] + // 只针对开命中事件进行检测 + if (!this.checkPointInHitEvents.includes(eventName) && this.checkPointInHitEvents.length > 0) return shapes; + for (let i = this.shapes.length - 1; i >= 0; i--) { + const shape = this.shapes[i]; + if (shape instanceof Shape) { + if (shape.isPointInPath(x, y, shape.id)) { + shapes.push(shape) + if (!shape.bubbleEvent) { + return shapes; + } + } + } + } + return shapes; + } + + private buildEvents(eventName : CanvasEventType, eventDetail : ICanvasDomEvent) { + this._resizePos() + const listeners = this.eventListeners.get(eventName); + const target = this.getTargetShape(eventName, eventDetail.x, eventDetail.y); + + + const event : ICanvasEvent = { + type: eventName, + x: eventDetail.x, + y: eventDetail.y, + target: target, + detail: eventDetail.detail, + touches: eventDetail.touches.map((el : ICanvasDomEvent) : ICanvasEvent => { + return { + type: eventName, + x: el.x, + y: el.y, + target: target, + detail: el.detail, + touches: [] as ICanvasEvent[] + } as ICanvasEvent + }) + }; + if (listeners != null) { + for (let i = 0; i < listeners.length; i++) { + let children = listeners[i] + //执行画布的监听事件 + children(event); + } + } + + for (let i = 0; i < this.shapes.length; i++) { + const shape = this.shapes[i]; + if (shape instanceof Shape) { + if (event.detail.length == 0) continue; + let startX = event.detail[0].startX + let startY = event.detail[0].startY + if (shape.isPointInPath(startX, startY, shape.id) && shape.draggable && eventName == 'down') { + shape.draggableing = true; + } + if (shape.draggable && (eventName == 'up' || eventName == 'cancel') && shape.draggableing) { + shape.draggableing = false; + } + if (shape.draggableing && eventName == 'move') { + shape.drag(eventName, event) + } + } + } + + if (target.length > 0) { + let isUpdate = false; + for (let i = 0; i < target.length; i++) { + const shape = target[i]; + if (shape instanceof Shape) { + shape.buildEvents(eventName, event) + if(shape.draggable&&!isUpdate){ + isUpdate = true; + } + } + } + if(isUpdate){ + this.render() + } + } + + } + + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/interface.uts b/uni_modules/tmx-ui/core/canvas/interface.uts new file mode 100644 index 0000000..00b6cc8 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/interface.uts @@ -0,0 +1,255 @@ +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +export type ShapeType = any; +/** 旋转元素时的中心点,默认是topLeft左顶,center表示元素的中间 */ +export type ITextAlignType = 'left' | 'center' | 'right'; +export type ITextBaselineType = 'top' | 'middle' | 'bottom'; +export type ILineJoinType = "round" | "bevel" | "miter"; +export type ILineCapType = "butt" | "round" | "square"; +export type CanvasRotateCenter = "topLeft"|"center"|"topRight"|"bottomLeft"|"bottomRight" +export type DirectionEventType = 'down' | 'move' | 'up'; + +export type InteractionEventType = 'click' | 'longpress' | 'dbclick' | 'cancel'; +export type CanvasEventType = DirectionEventType | InteractionEventType; +export type ShapeSetAttrType = string | number | boolean | Array +export type IShapeVector2d = { + x:number, + y:number +} +export type ICanvasEvent = { + type: CanvasEventType; + /** 在画布上的坐标X */ + x: number; + /** 在画布上的坐标Y */ + y: number; + detail:IcanvasDomEventDetail[], + touches:ICanvasEvent[]; + target: ShapeType[]; +} +export type IcanvasDomEventDetail = { + startX:number, + startY:number, + endX:number, + endY:number, + moveX:number, + moveY:number, + /** 相对上一次移动的距离*/ + moveLenX:number, + /** 相对上一次移动的距离*/ + moveLenY:number, + /** 相对起始时到当前位置移动的距离*/ + endLenX:number, + /** 相对起始时到当前位置移动的距离*/ + endLenY:number + // /** 多点触摸时,两点之间的距离 */ + // touchesLenX:number, + // /** 多点触摸时,两点之间的距离 */ + // touchesLenY:number +} +export type ICanvasDomEvent = { + type: CanvasEventType; + x: number; + y: number; + detail:IcanvasDomEventDetail[], + touches:ICanvasDomEvent[]; +} + +export type IEventListener = (event: ICanvasEvent) => void; + +export type IEventShape = { + type: CanvasEventType; + x: number; + y: number; + /** 元素本身内的坐标X */ + layerX:number; + /** 元素本身内的坐标Y */ + layerY:number; + touches:IEventShape[]; + target:ShapeType +} +export type IEventShapeListener = (event: IEventShape) => void; + +export type IEventMap = Map; +export type ICanvasOptional = { + /** 选式时传递当前组件this,组合式传递 getCurrentInstance()?.proxy ?? null */ + component:any|null, + /** 画布id */ + canvasId:string, +} +export type IShapeOptional = { + x?: number; + y?: number; + width?: number; + height?: number; + fill?: string; + stroke?: string; + strokeWidth?: number; + opacity?: number; + visible?: boolean; + rotation?: number; + scaleX?: number; + scaleY?: number; + /** 元素相对舞台x坐标系的坐标,就是x,y为起始点,如果x,y为0就相当于是舞台的顶左 **/ + offsetX?: number; + /** 元素相对舞台y坐标系的坐标,就是x,y为起始点,如果x,y为0就相当于是舞台的顶左 **/ + offsetY?: number; + draggable?: boolean; + // 元素之间上下重叠时,是否允许穿透冒泡逐层触发,默认不允许 + bubbleEvent?: boolean; + rotateCenter?:CanvasRotateCenter; + + // 线条样式 + lineJoin?: ILineJoinType; + lineDashOffset?: number; + lineDash ?:number[] ; + lineCap?: ILineCapType; + + src?:string; + // 二维码的前景块的颜色。 + foreground?:string; + // 二维码内容。 + qrcodeText?:string; + + text?: string; + fontSize?: number; + fontFamily?: string; + textAlign?: ITextAlignType; + textBaseline?: ITextBaselineType; + padding?: number; + lineHeight?: number; + + innerRadius ?: number; + outerRadius ?: number; + startAngle ?: number; + endAngle ?: number; + + radius ?:number; + + sides ?:number; + //多边形线的点 + points ?:number[]; + //多边形线是否自动闭合 + closed ?:boolean; + // 多边线将连接线曲线化 + tension ?:number + //将曲线平滑化 + bezier ?:boolean; + // 椭圆的小径 + radiusX ?:number + //椭圆的大径 + radiusY ?:number + //星的角数量,默认5角星 + numPoints ?: number; + + pointStart?:IShapeVector2d; + pointEnd?:IShapeVector2d; + + strokeGradient?:string[]; + fillGradient?:string[]; + clip?:boolean; + zIndex?:number; + textBgColor?:string; +} +export type IShapeBoundRect = { + x : number, + y : number, + height : number, + width : number +} + +export type QrGenerateFrameResult = { + frameBuffer: number[], + width: number +} +export interface IShape { + canvas : ICanvas, + x: number; + y: number; + width: number; + height: number; + fill: string; + stroke: string; + strokeWidth: number; + opacity: number; + visible: boolean; + rotation: number; + scaleX: number; + scaleY: number; + /** 元素相对舞台x坐标系的坐标,就是x,y为起始点,如果x,y为0就相当于是舞台的顶左 **/ + offsetX: number; + /** 元素相对舞台y坐标系的坐标,就是x,y为起始点,如果x,y为0就相当于是舞台的顶左 **/ + offsetY: number; + draggable: boolean; + // 元素之间上下重叠时,是否允许穿透冒泡逐层触发,默认不允许 + bubbleEvent: boolean; + rotateCenter:CanvasRotateCenter; + /**toggle方法中的选中状态 */ + toggleStatus:boolean; + + + + // 线条样式 + lineJoin: ILineJoinType; + lineDashOffset: number; + lineDash:number[] + lineCap: ILineCapType; + + // text数据 + + text : string; + fontSize : number; + fontFamily : string ; + textAlign : ITextAlignType; + textBaseline : ITextBaselineType; + padding : number; + lineHeight : number; + + //ring数据 + + innerRadius : number; + outerRadius : number; + startAngle : number; + endAngle : number; + + radius :number; + sides: number; + + src:string; + + // 二维码的前景块的颜色。 + foreground:string; + // 二维码内容。 + qrcodeText:string; + + points :number[]; + //多边形线是否自动闭合 + closed :boolean; + // 多边线将连接线曲线化 + tension:number + bezier :boolean; + + // 椭圆的小径 + radiusX :number; + //椭圆的大径 + radiusY :number; + + //星的角数量,默认5角星 + numPoints: number; + + pointStart:IShapeVector2d; + pointEnd:IShapeVector2d; + + strokeGradient:string[]; + fillGradient:string[]; + + clip:boolean; + zIndex:number; + textBgColor:string; + drag : (eventName : CanvasEventType, parentEventDetail : ICanvasEvent) => void + + draw(ctx: CanvasRenderingContext2D): void; + isPointInPath(x: number, y: number,shapeId:string): boolean; + getBoundRect() : IShapeBoundRect; + setAttr(key:string,value:any):void; + getAttr(key: string): any | null; + toggle(call:(status:boolean,target:any)=>void):void; +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/animation/tween.uts b/uni_modules/tmx-ui/core/canvas/lib/animation/tween.uts new file mode 100644 index 0000000..a100f35 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/animation/tween.uts @@ -0,0 +1,348 @@ +import { Shape } from '../shape.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; + +export type EasingFunction = (t: number) => number; +type UpdateCall = (t: number) => void; +type AnimationConfig = { + props: UTSJSONObject; + duration: number; + easing?: EasingFunction; + startValues: Map; +} + +export class Tween { + private target: Shape; + private startValues: Map = new Map(); + private endValues: Map = new Map(); + private duration: number; + private startTime: number = 0; + private isPlaying: boolean = false; + private easing: EasingFunction; + private onUpdateFun: ((progress:number) => void) | null = null; + private onCompleteFun: (() => void) | null = null; + private canvas: CanvasContext; + private parentICanvas: ICanvas; + private requestAnimationFrameId = 0; + private loop: number = 0; // 循环次数,0表示不循环,-1表示无限循环 + private currentLoop: number = 0; // 当前已完成的循环次数 + private yoyo: boolean = false; // 是否开启往返播放 + private isReverse: boolean = false; // 当前是否为反向播放 + private animationQueue: AnimationConfig[] = []; // 动画队列 + private currentAnimationIndex: number = -1; // 当前执行的动画索引 + private delayDur = 0 + private delayDurTid = 12 + constructor(target: Shape, canvas: ICanvas) { + this.target = target; + this.canvas = canvas.canvas!; + this.parentICanvas = canvas; + this.duration = 1000; + this.easing = Easing.linear as EasingFunction; + } + + to(props: UTSJSONObject, duration: number = 1000): Tween { + return this.addTo(props, duration); + } + + addTo(props: UTSJSONObject, duration: number = 1000, easing: EasingFunction = this.easing): Tween { + const startValues = new Map(); + for (const key in props) { + let keyValue = props[key]; + if (typeof keyValue == 'number') { + let startValue = this.target.getAttr(key); + if(typeof startValue == 'number'){ + startValues.set(key, startValue); + } + } + } + this.animationQueue.push({ + props: props, + duration: duration, + easing: easing, + startValues: startValues + }); + return this; + } + + // 在队列中插入一个仅用于延时的动画段 + delay(ms: number): Tween { + this.delayDur = ms; + return this; + } + + clearAnimations(): Tween { + this.stop(); + this.canvas.cancelAnimationFrame(this.requestAnimationFrameId); + this.requestAnimationFrameId = 0; + this.animationQueue = []; + this.currentAnimationIndex = -1; + this.startValues.clear(); + this.endValues.clear(); + return this; + } + + + start(): Tween { + let _this = this; + if (this.isPlaying) { + return this; + } + if(this.delayDur>0){ + _this.delayDurTid = setTimeout(function() { + if (_this.requestAnimationFrameId != 0) { + _this.canvas.cancelAnimationFrame(_this.requestAnimationFrameId); + _this.requestAnimationFrameId = 0; + } + + _this.update(); + }, _this.delayDur); + }else{ + if (this.requestAnimationFrameId != 0) { + this.canvas.cancelAnimationFrame(this.requestAnimationFrameId); + this.requestAnimationFrameId = 0; + } + + this.update(); + } + + + this.isPlaying = true; + return this; + } + + stop(): Tween { + clearTimeout(this.delayDurTid) + this.isPlaying = false; + if (this.requestAnimationFrameId != 0) { + this.canvas.cancelAnimationFrame(this.requestAnimationFrameId); + this.requestAnimationFrameId = 0; + } + return this; + } + + private update(): void { + const selftThis = this; + let updateSelf = null as null|UpdateCall; + selftThis.currentLoop = 1; + selftThis.isReverse = false; + // 开始执行队列中的第一个动画 + if (selftThis.currentAnimationIndex == -1 && selftThis.animationQueue.length > 0) { + selftThis.currentAnimationIndex = 0; + const currentAnimation = selftThis.animationQueue[selftThis.currentAnimationIndex]; + selftThis.duration = currentAnimation.duration; + selftThis.easing = currentAnimation.easing ?? selftThis.easing; + selftThis.startValues.clear(); + selftThis.endValues.clear(); + for (const key in currentAnimation.props) { + let keyValue = currentAnimation.props[key]; + if (typeof keyValue == 'number') { + let startValue = currentAnimation.startValues?.get(key); + if(typeof startValue == 'number'){ + selftThis.startValues.set(key, startValue!); + selftThis.endValues.set(key, keyValue); + } + } + } + } + + updateSelf = (time:number)=>{ + + if (!selftThis.isPlaying) return; + const currentTime = time; + let elapsed = currentTime - selftThis.startTime; + + if (elapsed > selftThis.duration) { + + if (selftThis.yoyo && !selftThis.isReverse && (selftThis.currentLoop < selftThis.loop||selftThis.loop==-1)) { + // 开启yoyo且当前为正向播放,切换为反向播放 + selftThis.isReverse = true; + + if (selftThis.isPlaying) { + selftThis.requestAnimationFrameId = selftThis.canvas.requestAnimationFrame((t) => { + selftThis.startTime = t; + updateSelf!(t) + }); + return; + } + } else { + if(this.yoyo){ + selftThis.isReverse = false; + } + // 检查是否还有下一个动画 + if (selftThis.currentAnimationIndex < selftThis.animationQueue.length - 1) { + selftThis.currentAnimationIndex++; + + const nextAnimation = selftThis.animationQueue[selftThis.currentAnimationIndex]; + selftThis.duration = nextAnimation.duration; + selftThis.easing = nextAnimation.easing ?? selftThis.easing; + selftThis.startValues.clear(); + selftThis.endValues.clear(); + for (const key in nextAnimation.props) { + let keyValue = nextAnimation.props[key]; + if (typeof keyValue == 'number') { + let startValue = selftThis.target.getAttr(key); + if(typeof startValue == 'number'){ + selftThis.startValues.set(key, nextAnimation.startValues.get(key)!); + selftThis.endValues.set(key, keyValue); + + } + } + } + selftThis.requestAnimationFrameId = selftThis.canvas.requestAnimationFrame((t) => { + selftThis.startTime = t; + updateSelf!(t); + }); + return; + } else if (selftThis.loop == -1 || selftThis.currentLoop < selftThis.loop) { + // 重置动画索引,开始新一轮循环 + selftThis.currentAnimationIndex = 0; + selftThis.currentLoop++; + if(selftThis.animationQueue.length>0){ + const nextAnimation = selftThis.animationQueue[selftThis.currentAnimationIndex]; + selftThis.duration = nextAnimation.duration; + selftThis.easing = nextAnimation.easing ?? selftThis.easing; + selftThis.startValues.clear(); + selftThis.endValues.clear(); + + for (const key in nextAnimation.props) { + let keyValue = nextAnimation.props[key]; + if (typeof keyValue == 'number') { + let startValue = selftThis.target.getAttr(key); + if(typeof startValue == 'number'){ + selftThis.startValues.set(key, nextAnimation.startValues.get(key)!); + selftThis.endValues.set(key, keyValue); + + } + } + } + selftThis.requestAnimationFrameId = selftThis.canvas.requestAnimationFrame((t) => { + selftThis.startTime = t; + updateSelf!(t); + }); + }else{ + selftThis.duration = currentTime; + selftThis.easing = selftThis.easing; + selftThis.startValues.clear(); + selftThis.endValues.clear(); + selftThis.requestAnimationFrameId = selftThis.canvas.requestAnimationFrame((t) => { + selftThis.startTime = t; + updateSelf!(t); + }); + } + return; + } + selftThis.isPlaying = false; + selftThis.currentAnimationIndex = -1; // 重置动画索引 + selftThis.canvas.cancelAnimationFrame(selftThis.requestAnimationFrameId); + selftThis.requestAnimationFrameId = 0; + selftThis.animationQueue = []; + selftThis.startValues.clear(); + selftThis.endValues.clear(); + } + } + + let progress = selftThis.easing(elapsed / selftThis.duration); + if (selftThis.isReverse) { + progress = 1 - progress; + } + + selftThis.startValues.forEach((startValue, key) => { + const endValue = selftThis.endValues.get(key)!; + const value = startValue + (endValue - startValue) * progress; + selftThis.target.setAttr(key,value); + }); + + selftThis.target.needsUpdate = true; + + if (selftThis.onUpdateFun!=null) { + selftThis.onUpdateFun!(progress); + } + selftThis.parentICanvas.update(); + if (!selftThis.isPlaying && selftThis.onCompleteFun!=null) { + selftThis.onCompleteFun!(); + return; + } + if (selftThis.isPlaying) { + selftThis.requestAnimationFrameId = selftThis.canvas.requestAnimationFrame((t) => updateSelf!(t)); + } + } + selftThis.requestAnimationFrameId = selftThis.canvas.requestAnimationFrame((t) => { + selftThis.startTime = t; + updateSelf!(t); + }); + } + + destroy(): void { + this.stop(); + this.animationQueue = []; + this.currentAnimationIndex = -1; + this.startValues.clear(); + this.endValues.clear(); + this.onUpdateFun = null; + this.onCompleteFun = null; + this.loop = 0; + this.yoyo = false; + + } + + setEasing(easingFunction: EasingFunction): Tween { + this.easing = easingFunction; + return this; + } + + onUpdate(callback: (progress:number) => void): Tween { + this.onUpdateFun = callback; + return this; + } + + onComplete(callback: () => void): Tween { + this.onCompleteFun = callback; + return this; + } + + setLoop(count: number): Tween { + this.loop = count; + return this; + } + + setYoyo(value: boolean): Tween { + this.yoyo = value; + return this; + } +} + +export const Easing = { + linear: (t: number): number => t, + + easeInQuad: (t: number): number => t * t, + + easeOutQuad: (t: number): number => t * (2 - t), + + easeInOutQuad: (t: number): number => { + return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; + }, + + easeInCubic: (t: number): number => t * t * t, + + easeOutCubic: (t: number): number => (t-1) * t * t + 1, + + easeInOutCubic: (t: number): number => { + return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; + }, + + easeInElastic: (t: number): number => { + const c4 = (2 * Math.PI) / 3; + return t === 0 ? 0 : t === 1 ? 1 : -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * c4); + }, + + easeOutElastic: (t: number): number => { + const c4 = (2 * Math.PI) / 3; + return t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1; + }, + + easeInOutElastic: (t: number): number => { + const c5 = (2 * Math.PI) / 4.5; + return t === 0 ? 0 : t === 1 ? 1 : t < 0.5 + ? -(Math.pow(2, 20 * t - 10) * Math.sin((20 * t - 11.125) * c5)) / 2 + : (Math.pow(2, -20 * t + 10) * Math.sin((20 * t - 11.125) * c5)) / 2 + 1; + } +}; \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/arc.uts b/uni_modules/tmx-ui/core/canvas/lib/arc.uts new file mode 100644 index 0000000..3768aca --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/arc.uts @@ -0,0 +1,200 @@ +import { Shape } from './shape.uts'; +import { CanvasRotateCenter, ShapeSetAttrType, IShapeBoundRect, IShapeOptional } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +export class IArc extends Shape { + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.radius = config?.radius ?? 30; + this.startAngle = config?.startAngle ?? 0; + this.endAngle = config?.endAngle ?? 90; + this.type = "IArc" + } + + setRadius(value : number) : IArc { + this.radius = value; + this.needsUpdate = true; + return this; + } + + override getBoundRect() : IShapeBoundRect { + // 计算精确的弧段/扇形包围盒 + const centerX = this.x; + const centerY = this.y; + const r = Math.max(0, this.radius); + const d2r = Math.PI / 180; + + // 角度标准化到 [0, 360) + const normalize = (deg:number):number => { + let a = deg % 360; + if (a < 0) a += 360; + return a; + }; + + let start = normalize(this.startAngle); + let end = normalize(this.endAngle); + if (end < start) end += 360; // 保证 end >= start(顺时针绘制) + + const withinSweep = (deg:number):boolean => { + let a = normalize(deg); + if (a < start) a += 360; + return a >= start && a <= end; + }; + + const candidatesX:number[] = []; + const candidatesY:number[] = []; + + // 起止点 + const sx = centerX + r * Math.cos(start * d2r); + const sy = centerY + r * Math.sin(start * d2r); + const ex = centerX + r * Math.cos(end * d2r); + const ey = centerY + r * Math.sin(end * d2r); + candidatesX.push(sx, ex); + candidatesY.push(sy, ey); + + // 若为扇形(有填充),中心点也参与包围盒 + const isFilled = (this.fill != "" || this.fillGradient.length > 0); + if (isFilled) { + candidatesX.push(centerX); + candidatesY.push(centerY); + } + + // 检查跨越极值角(0, 90, 180, 270) + const extrema = [0, 90, 180, 270]; + for (const deg of extrema) { + if (withinSweep(deg)) { + const rad = deg * d2r; + candidatesX.push(centerX + r * Math.cos(rad)); + candidatesY.push(centerY + r * Math.sin(rad)); + } + } + + let minX = candidatesX.length>0?candidatesX[0]:centerX; + let maxX = candidatesX.length>0?candidatesX[0]:centerX; + let minY = candidatesY.length>0?candidatesY[0]:centerY; + let maxY = candidatesY.length>0?candidatesY[0]:centerY; + for (let i=1;i maxX) maxX = vx; + } + } + for (let i=1;i maxY) maxY = vy; + } + } + + // 描边扩张 + const hasStroke = (this.stroke != "" || this.strokeGradient.length > 0); + const pad = hasStroke ? this.strokeWidth : 0; + minX -= pad; + minY -= pad; + maxX += pad; + maxY += pad; + + return { + x: minX, + y: minY, + width: Math.max(0, maxX - minX), + height: Math.max(0, maxY - minY) + } as IShapeBoundRect; + } + + override setWidth(value : number) : IArc { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + override setHeight(value : number) : IArc { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + setStartAngle(angle:number):IArc{ + this.startAngle = angle; + this.needsUpdate = true; + return this; + } + setEndAngle(angle:number):IArc{ + this.endAngle = angle; + this.needsUpdate = true; + return this; + } + + + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + ctx.beginPath(); + // 将角度转换为弧度 + const startRad = this.startAngle * Math.PI / 180; + const endRad = this.endAngle * Math.PI / 180; + // 如果有填充色,先移动到圆心,绘制扇形 + if (this.fill != ""||this.fillGradient.length>0) { + ctx.moveTo(this.x, this.y); + } + // 绘制圆弧 + ctx.arc(this.x, this.y, this.radius, startRad, endRad, false); + + if (this.fill != ""||this.fillGradient.length>0) { + ctx.closePath(); + ctx.fill(); + } + if (this.stroke != ""||this.strokeGradient.length>0) { + ctx.stroke(); + } + + ctx.restore(); + } + override isPointInPath(x: number, y: number, shapeId: string): boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + const realX = x - (this.offsetX) - this.x; + const realY = y - (this.offsetY) - this.y; + + // 计算点到圆心的距离 + const dx = realX; + const dy = realY; + const distance = Math.sqrt(dx * dx + dy * dy); + + // 计算点相对于圆心的角度(弧度) + const angle = Math.atan2(dy, dx); + // 将角度转换为0-360度范围 + let degrees = angle * 180 / Math.PI; + if (degrees < 0) degrees += 360; + + // 将起始角度和结束角度标准化到0-360度范围 + let start = this.startAngle % 360; + if (start < 0) start += 360; + let end = this.endAngle % 360; + if (end < 0) end += 360; + // 确保end大于start + if (end < start) end += 360; + + // 检查点的角度是否在弧的范围内 + const inAngle = degrees >= start && degrees <= end; + + if (this.fill !== "") { + // 填充模式:检查是否在扇形内 + return inAngle && distance <= this.radius; + } else if (this.stroke !== "") { + // 非填充模式:检查是否在圆弧线附近 + // 考虑整个线宽作为检测范围 + const tolerance = this.strokeWidth; + const distanceFromArc = Math.abs(distance - this.radius); + return inAngle && distanceFromArc <= tolerance; + } + + + return false; + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/circle.uts b/uni_modules/tmx-ui/core/canvas/lib/circle.uts new file mode 100644 index 0000000..c2b93a7 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/circle.uts @@ -0,0 +1,133 @@ +import { Shape } from './shape.uts'; +import { CanvasRotateCenter, IShapeBoundRect, IShapeOptional } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; + +export class ICircle extends Shape { + override type = 'ICircle' + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.radius = config?.radius ?? 30; + } + + setRadius(value : number) : ICircle { + this.radius = value; + this.needsUpdate = true; + return this; + } + + override getBoundRect() : IShapeBoundRect { + const r = Math.max(0, this.radius); + const pad = (this.stroke != "" ? this.strokeWidth / 2 : 0); + const d = r * 2 + pad * 2; + return { + x: this.x - r - pad, + y: this.y - r - pad, + width: d, + height: d + } as IShapeBoundRect; + } + + override setWidth(value : number) : ICircle { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + override setHeight(value : number) : ICircle { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); + ctx.closePath(); + if (this.fill != ""||this.fillGradient.length>0) { + ctx.fill(); + } + if (this.stroke != "") { + ctx.stroke(); + } + + ctx.restore(); + } + + override isPointInPath(x: number, y: number, shapeId: string): boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + // 计算点击位置相对于圆心的实际坐标 + let realX = x - this.offsetX - this.x; + let realY = y - this.offsetY - this.y; + + // 如果有旋转,需要将坐标转换回未旋转状态 + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + realX = centerX + dx * cos - dy * sin; + realY = centerY + dx * sin + dy * cos; + } + + // 计算点到圆心的距离 + const distance = Math.sqrt(realX * realX + realY * realY); + + // 考虑缩放因素 + const scaledRadius = this.radius * Math.min(this.scaleX, this.scaleY); + + // 如果只有描边模式,检查点是否在圆形线条附近 + if (this.stroke != "" && this.fill == ""&&this.fillGradient.length==0) { + const strokeWidth = this.strokeWidth / 2; + return Math.abs(distance - scaledRadius) <= strokeWidth; + } + + // 如果同时有描边和填充,或者只有填充 + if (this.fill != ""||this.fillGradient.length>0) { + // 如果有描边,扩大检测范围到描边外缘 + if (this.stroke != "") { + return distance <= (scaledRadius + this.strokeWidth / 2); + } + + // 只有填充时,检查点是否在圆内 + return distance <= scaledRadius; + } + + return false; + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/ellipse.uts b/uni_modules/tmx-ui/core/canvas/lib/ellipse.uts new file mode 100644 index 0000000..ea504c3 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/ellipse.uts @@ -0,0 +1,141 @@ +import { Shape } from './shape.uts'; +import { CanvasRotateCenter, IShapeBoundRect, IShapeOptional } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; + +export class IEllipse extends Shape { + override type = 'IEllipse' + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.radiusX = config?.radiusX ?? 80; + this.radiusY = config?.radiusY ?? 20; + } + + setRadiusX(value : number) : IEllipse { + this.radiusX = value; + this.needsUpdate = true; + return this; + } + + setRadiusY(value : number) : IEllipse { + this.radiusY = value; + this.needsUpdate = true; + return this; + } + + override getBoundRect() : IShapeBoundRect { + const rx = Math.max(0, this.radiusX); + const ry = Math.max(0, this.radiusY); + const pad = (this.stroke != "" ? this.strokeWidth / 2 : 0); + return { + x: this.x - rx - pad, + y: this.y - ry - pad, + width: rx * 2 + pad * 2, + height: ry * 2 + pad * 2 + } as IShapeBoundRect; + } + + override setWidth(value : number) : IEllipse { + this.width = value; + this.radiusX = value / 2; + this.needsUpdate = true; + return this; + } + + override setHeight(value : number) : IEllipse { + this.height = value; + this.radiusY = value / 2; + this.needsUpdate = true; + return this; + } + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + ctx.beginPath(); + ctx.ellipse(this.x, this.y, this.radiusX, this.radiusY, 0, 0, Math.PI * 2, false); + ctx.closePath(); + if (this.fill != "") { + ctx.fill(); + } + if (this.stroke != "") { + ctx.stroke(); + } + ctx.restore(); + } + + override isPointInPath(x: number, y: number, shapeId: string): boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + // 计算点击位置相对于椭圆中心的实际坐标 + let realX = x - this.offsetX - this.x; + let realY = y - this.offsetY - this.y; + + // 如果有旋转,需要将坐标转换回未旋转状态 + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + realX = centerX + dx * cos - dy * sin; + realY = centerY + dx * sin + dy * cos; + } + + // 考虑缩放因素 + const scaledRadiusX = this.radiusX * Math.abs(this.scaleX); + const scaledRadiusY = this.radiusY * Math.abs(this.scaleY); + + // 计算点是否在椭圆内(标准椭圆方程) + const normalizedX = realX / scaledRadiusX; + const normalizedY = realY / scaledRadiusY; + const distance = normalizedX * normalizedX + normalizedY * normalizedY; + + // 如果只有描边模式,检查点是否在椭圆线条附近 + if (this.stroke != "" && this.fill == "") { + const strokeWidth = this.strokeWidth / 2; + const outerDistance = Math.sqrt(distance); + return Math.abs(outerDistance - 1) * Math.min(scaledRadiusX, scaledRadiusY) <= strokeWidth; + } + + // 如果同时有描边和填充,或者只有填充 + if (this.fill != "") { + // 如果有描边,扩大检测范围到描边外缘 + if (this.stroke != "") { + const strokeOffset = this.strokeWidth / (2 * Math.min(scaledRadiusX, scaledRadiusY)); + return distance <= (1 + strokeOffset) * (1 + strokeOffset); + } + // 只有填充时,检查点是否在椭圆内 + return distance <= 1; + } + + return false; + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/image.uts b/uni_modules/tmx-ui/core/canvas/lib/image.uts new file mode 100644 index 0000000..7f2b686 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/image.uts @@ -0,0 +1,205 @@ +import { Shape } from './shape.uts'; +import { IShapeBoundRect, IShapeOptional, ShapeSetAttrType } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; + +/** + * 图片 + * @description 注意创建添加完图片后。要通过方法setSrc(xx)来设置加载图片 + * @version 1.0.0 + * @date 2025/2/6 + * @copright 不允许外发给别人,只可在tmui4x是使用 + */ +export class ImageShape extends Shape { + override type = 'ImageShape' + private image : any | null = null; + loaded : boolean = false; + private srcWidth : number = 0; + private srcHeight : number = 0; + private cropX : number = 0; + private cropY : number = 0; + private cropWidth : number = 0; + private cropHeight : number = 0; + private useCrop : boolean = false; + private canvasContext : CanvasContext; + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.canvasContext = canvas.canvas! + this.type = 'ImageShape'; + if(this.src!=''){ + this.setSrc(this.src) + } + } + + setSrc(src : string) : ImageShape { + if (!this.visible) return this; + this.src = src; + this.loaded = false; + if (this.src != '') { + this.loadImage(); + } + return this; + } + + private loadImage() : void { + if (this.loaded) return; + const image = this.canvasContext.createImage(); + image.src = this.src; + let _this = this; + image.onload = () => { + _this.image = image; + _this.loaded = true; + if (_this.width == 0) _this.width = image.width; + if (_this.height == 0) _this.height = image.height; + _this.srcWidth = image.width; + _this.srcHeight = image.height; + _this.needsUpdate = true; + _this.canvas.update() + + }; + + + } + + crop(x : number, y : number, width : number, height : number) : ImageShape { + this.cropX = x; + this.cropY = y; + this.cropWidth = width; + this.cropHeight = height; + this.useCrop = true; + this.needsUpdate = true; + return this; + } + + resetCrop() : ImageShape { + this.useCrop = false; + this.needsUpdate = true; + return this; + } + + override draw(ctx : CanvasRenderingContext2D) : void { + + if (!this.loaded || this.image == null) return; + super.draw(ctx); + + // #ifdef APP||WEB + if (this.useCrop) { + ctx.drawImage( + this.image! as Image, + this.cropX, + this.cropY, + this.cropWidth, + this.cropHeight, + this.x, + this.y, + this.width, + this.height + ); + } else { + ctx.drawImage( + this.image! as Image, + this.x, + this.y, + this.width, + this.height + ); + } + // #endif + // #ifdef MP + if (this.useCrop) { + ctx.drawImage( + this.image!, + this.cropX, + this.cropY, + this.cropWidth, + this.cropHeight, + this.x, + this.y, + this.width, + this.height + ); + } else { + ctx.drawImage( + this.image!, + this.x, + this.y, + this.width, + this.height + ); + } + // #endif + + ctx.restore() + } + + override isPointInPath(x : number, y : number, shapeId : string) : boolean { + if (!this.visible || !this.loaded || (shapeId != "" && shapeId != this.id)) return false; + + const realX = x - this.x - this.offsetX; + const realY = y - this.y - this.offsetY; + + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + const rotatedX = centerX + dx * cos - dy * sin; + const rotatedY = centerY + dx * sin + dy * cos; + return rotatedX >= 0 && rotatedX <= this.width * this.scaleX && rotatedY >= 0 && rotatedY <= this.height * this.scaleY; + } + + return realX >= 0 && realX <= this.width * this.scaleX && realY >= 0 && realY <= this.height * this.scaleY; + } + + override getBoundRect() : IShapeBoundRect { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height + } as IShapeBoundRect; + } + + override getAttr(key: string): any | null { + const superValue = super.getAttr(key); + if(superValue!=null) return superValue; + switch (key) { + case 'src': return this.src; + case 'cropX': return this.cropX; + case 'cropY': return this.cropY; + case 'cropWidth': return this.cropWidth; + case 'cropHeight': return this.cropHeight; + case 'useCrop': return this.useCrop; + default: return null; + } + } + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/layout.uts b/uni_modules/tmx-ui/core/canvas/lib/layout.uts new file mode 100644 index 0000000..c0d0382 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/layout.uts @@ -0,0 +1,355 @@ +import { Shape } from '@/uni_modules/tmx-ui/core/canvas/lib/shape.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +type LayoutDirection = 'horizontal'|'vertical' +type LayoutAnchor = 'top'|'bottom' +type LayoutMode = 'left'|'right'|'between'|'center';//左对齐,右对齐,两边对齐均分,中间对齐 +type CurSizeType = {width:number,height:number} +type RoysType = {items:Shape[], sizes:CurSizeType[], rowWidth:number, rowHeight:number} +type CoysType = {items:Shape[], sizes:CurSizeType[], colWidth:number, colHeight:number} +export class ILayout { + x:number = 0 + y:number = 0 + width:number = 0; + height:number = 0; + shapeList:Shape[] = []; + colSpace:number = 10 + rowSpace:number = 10 + direction:LayoutDirection = 'horizontal' + mode:LayoutMode = 'left' + anchor:LayoutAnchor = 'top';//是以顶开始往排,还是以容器底往上排 + // 自动断行 + wrap:boolean = false + icanvas:ICanvas; + /** + * 创建布局容器 + * @param ic 画布实例(默认用于初始化容器宽高) + */ + constructor(ic:ICanvas){ + this.icanvas = ic; + this.width = ic.width + this.height = ic.height + } + /** + * 添加需要参与布局的元素(按 id 去重) + * @param shapes 形状列表 + */ + addShape(shapes:Shape[]){ + let ids = this.shapeList.map((el:Shape):string => el.id) + let realShapes = shapes.filter((el:Shape):boolean => !ids.includes(el.id)) + this.shapeList.push(...realShapes) + } + /** + * 设置容器 X 偏移 + * @param val X 坐标 + */ + setsX(val:number){ + this.x = val + } + /** + * 设置容器 Y 偏移 + * @param val Y 坐标 + */ + setsY(val:number){ + this.y = val + } + /** + * 设置容器位置 + * @param x X 坐标 + * @param y Y 坐标 + */ + setsPosition(x:number,y:number){ + this.x = x + this.y = y + } + /** + * 设置容器尺寸 + * @param w 宽度 + * @param h 高度 + */ + setsSize(w:number,h:number){ + this.width = w; + this.height = h; + } + /** + * 设置容器宽度 + * @param w 宽度 + */ + setsWidth(w:number){ + this.width = w; + } + /** + * 设置容器高度 + * @param h 高度 + */ + setsHeight(h:number){ + this.height = h; + } + /** + * 设置列间距(横向相邻元素间距) + * @param val 间距像素 + */ + setsSpaceCol(val:number){ + this.colSpace = val; + } + /** + * 设置行间距(纵向相邻元素间距) + * @param val 间距像素 + */ + setsSpaceRow(val:number){ + this.rowSpace = val + } + /** + * 同时设置列/行间距 + * @param col 列间距 + * @param row 行间距 + */ + setsSpace(col:number,row:number){ + this.colSpace = col; + this.rowSpace = row + } + /** + * 设置主轴方向 + * @param val 'horizontal' | 'vertical' + */ + setsLayoutDirection(val:LayoutDirection){ + this.direction = val; + } + /** + * 设置主轴对齐模式 + * @param val 'left' | 'right' | 'between' | 'center' + */ + setsMode(val:LayoutMode){ + this.mode = val; + } + /** + * 设置交叉轴锚点(顶/底对齐) + * @param val 'top' | 'bottom' + */ + setsAnchor(val:LayoutAnchor){ + this.anchor = val; + } + /** + * 设置是否自动换行/换列 + * @param val true 开启 + */ + setsWrap(val:boolean){ + this.wrap = val; + } + /** + * 执行布局:根据 direction / mode / anchor / wrap / spacing 将 shapeList 定位 + */ + render(){ + const items = this.shapeList.filter((s:Shape)=> s.visible); + if(items.length==0) return; + if(this.direction=='horizontal'){ + this.layoutHorizontal(items); + }else{ + this.layoutVertical(items); + } + items.forEach((el) => { + el.needsUpdate = true + }) + } + + /** + * 获取元素参与布局的尺寸(来自元素 getBoundRect) + * @param shape 形状 + * @returns width/height + */ + private getItemSize(shape:Shape):CurSizeType{ + const rect = shape.getBoundRect(); + const w = Math.max(0, rect.width); + const h = Math.max(0, rect.height); + return {width:w,height:h}; + } + + /** + * 横向布局:按主轴水平排列,支持均分与换行 + * @param items 待布局元素 + */ + private layoutHorizontal(items:Shape[]){ + if(!this.wrap){ + // single row + const sizes = items.map(s=> this.getItemSize(s)); + const totalWidth = sizes.reduce((acc,it)=> acc + it.width, 0); + const gaps = Math.max(0, items.length-1); + let spacing = this.colSpace; + let startX = this.x; + if(this.mode=='between' && gaps>0){ + spacing = Math.max(0, (this.width - totalWidth) / gaps); + startX = this.x; + }else if(this.mode=='center'){ + startX = this.x + Math.max(0, (this.width - (totalWidth + spacing*gaps)) / 2); + }else if(this.mode=='right'){ + startX = this.x + Math.max(0, this.width - (totalWidth + spacing*gaps)); + }else{ + startX = this.x; + } + let x = startX; + for(let i=0;i0? this.colSpace:0) + sz.width; + if(curItems.length>0 && curWidth + addWidth > this.width){ + rows.push({items:curItems, sizes:curSizes, rowWidth:curWidth, rowHeight:curHeight}); + curItems = []; + curSizes = []; + curWidth = 0; + curHeight = 0; + } + if(curItems.length>0){ + curWidth += this.colSpace; + } + curItems.push(s); + curSizes.push(sz); + curWidth += sz.width; + curHeight = Math.max(curHeight, sz.height); + } + if(curItems.length>0){ + rows.push({items:curItems, sizes:curSizes, rowWidth:curWidth, rowHeight:curHeight}); + } + // total height with row spaces + const totalRowsHeight = rows.reduce((acc,r)=> acc + r.rowHeight, 0); + const totalRowSpaces = this.rowSpace * Math.max(0, rows.length-1); + let startY = this.anchor=='top' ? this.y : this.y + Math.max(0, this.height - (totalRowsHeight + totalRowSpaces)); + let y = startY; + for(let r=0;r0){ + spacing = Math.max(0, (this.width - row.rowWidth + this.colSpace*gaps) / gaps); + startX = this.x; + }else if(this.mode=='center'){ + startX = this.x + Math.max(0, (this.width - (row.rowWidth + this.colSpace*gaps)) / 2); + }else if(this.mode=='right'){ + startX = this.x + Math.max(0, this.width - (row.rowWidth + this.colSpace*gaps)); + }else{ + startX = this.x; + } + let x = startX; + for(let i=0;i this.getItemSize(s)); + const totalHeight = sizes.reduce((acc,it)=> acc + it.height, 0); + const gaps = Math.max(0, items.length-1); + let spacing = this.rowSpace; + let startY = this.y; + if(this.mode=='between' && gaps>0){ + spacing = Math.max(0, (this.height - totalHeight) / gaps); + startY = this.y; + }else if(this.anchor=='top'){ + startY = this.y; + }else{ + startY = this.y + Math.max(0, this.height - (totalHeight + spacing*gaps)); + } + let y = startY; + for(let i=0;i0? this.rowSpace:0) + sz.height; + if(curItems.length>0 && curHeight + addHeight > this.height){ + cols.push({items:curItems, sizes:curSizes, colWidth:curWidth, colHeight:curHeight}); + curItems = []; + curSizes = []; + curHeight = 0; + curWidth = 0; + } + if(curItems.length>0){ + curHeight += this.rowSpace; + } + curItems.push(s); + curSizes.push(sz); + curHeight += sz.height; + curWidth = Math.max(curWidth, sz.width); + } + if(curItems.length>0){ + cols.push({items:curItems, sizes:curSizes, colWidth:curWidth, colHeight:curHeight}); + } + const totalColsWidth = cols.reduce((acc,c)=> acc + c.colWidth, 0); + const totalColSpaces = this.colSpace * Math.max(0, cols.length-1); + let startX = this.x; + if(this.mode=='between' && cols.length>1){ + // distribute columns + startX = this.x; + }else if(this.mode=='center'){ + startX = this.x + Math.max(0, (this.width - (totalColsWidth + totalColSpaces))/2); + }else if(this.mode=='right'){ + startX = this.x + Math.max(0, this.width - (totalColsWidth + totalColSpaces)); + }else{ + startX = this.x; + } + let x = startX; + let betweenSpacing = this.colSpace; + if(this.mode=='between' && cols.length>1){ + betweenSpacing = Math.max(0, (this.width - totalColsWidth) / (cols.length-1)); + } + for(let c=0;c0 ? this.strokeWidth / 2 : 0; + return { + x: this.x - pad, + y: this.y - pad, + width: this.width + pad * 2, + height: this.height + pad * 2 + } as IShapeBoundRect; + } + + override draw(ctx: CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + + ctx.beginPath(); + ctx.moveTo(this.pointStart.x, this.pointStart.y); + ctx.lineTo(this.pointEnd.x, this.pointEnd.y); + + if (this.stroke != ""||this.strokeGradient.length>0) { + ctx.stroke(); + } + ctx.restore() + } + + override setHeight(value : number) : Shape { + // 计算线条的中心点 + const centerX = (this.pointStart.x + this.pointEnd.x) / 2; + const centerY = (this.pointStart.y + this.pointEnd.y) / 2; + + // 计算当前线条的宽度(保持不变) + const currentWidth = Math.abs(this.pointEnd.x - this.pointStart.x); + + // 根据新的高度重新计算起点和终点的Y坐标 + // 保持线条的水平方向不变,只改变垂直方向 + if (this.pointStart.x <= this.pointEnd.x) { + // 从左到右的线条 + this.pointStart.x = centerX - currentWidth / 2; + this.pointEnd.x = centerX + currentWidth / 2; + } else { + // 从右到左的线条 + this.pointStart.x = centerX + currentWidth / 2; + this.pointEnd.x = centerX - currentWidth / 2; + } + + // 根据新高度设置Y坐标 + if (this.pointStart.y <= this.pointEnd.y) { + // 从上到下的线条 + this.pointStart.y = centerY - value / 2; + this.pointEnd.y = centerY + value / 2; + } else { + // 从下到上的线条 + this.pointStart.y = centerY + value / 2; + this.pointEnd.y = centerY - value / 2; + } + + this.updateDimensions(); + this.needsUpdate = true; + return this; + } + + override setWidth(value : number) : Shape { + // 计算线条的中心点 + const centerX = (this.pointStart.x + this.pointEnd.x) / 2; + const centerY = (this.pointStart.y + this.pointEnd.y) / 2; + + // 计算当前线条的高度(保持不变) + const currentHeight = Math.abs(this.pointEnd.y - this.pointStart.y); + + // 根据新的宽度重新计算起点和终点的X坐标 + // 保持线条的垂直方向不变,只改变水平方向 + if (this.pointStart.y <= this.pointEnd.y) { + // 从上到下的线条 + this.pointStart.y = centerY - currentHeight / 2; + this.pointEnd.y = centerY + currentHeight / 2; + } else { + // 从下到上的线条 + this.pointStart.y = centerY + currentHeight / 2; + this.pointEnd.y = centerY - currentHeight / 2; + } + + // 根据新宽度设置X坐标 + if (this.pointStart.x <= this.pointEnd.x) { + // 从左到右的线条 + this.pointStart.x = centerX - value / 2; + this.pointEnd.x = centerX + value / 2; + } else { + // 从右到左的线条 + this.pointStart.x = centerX + value / 2; + this.pointEnd.x = centerX - value / 2; + } + + this.updateDimensions(); + this.needsUpdate = true; + return this; + } + + // 获取两点之间的角度,以起点为基准,水平向右为0度,顺时针为正,逆时针为负 + getAngle(): number { + // 直接使用起点和终点计算角度 + const angle = Math.atan2(this.pointEnd.y - this.pointStart.y, this.pointEnd.x - this.pointStart.x); + + // 将弧度转换为角度,顺时针为正 + return angle * (180 / Math.PI); + } + getAngleByPoints(start:IShapeVector2d,end:IShapeVector2d): number { + // 直接使用起点和终点计算角度 + const angle = Math.atan2(start.y - end.y, end.x - start.x); + + // 将弧度转换为角度,顺时针为正,逆时针为负 + return angle * (180 / Math.PI); + } + + // 计算线条绕指定锚点的旋转角度 + getAngleByAnchor(anchorX: number, anchorY: number, startX: number, startY: number, endX: number, endY: number): number { + // 计算向量1:从锚点到起点的向量 + const vector1X = startX - anchorX; + const vector1Y = startY - anchorY; + + // 计算向量2:从锚点到终点的向量 + const vector2X = endX - anchorX; + const vector2Y = endY - anchorY; + + // 使用向量的点积和叉积计算角度 + const dotProduct = vector1X * vector2X + vector1Y * vector2Y; + const crossProduct = vector1X * vector2Y - vector1Y * vector2X; + + // 计算角度(弧度) + const angle = Math.atan2(crossProduct, dotProduct); + + // 将弧度转换为角度,并确保角度范围在-180到180度之间 + return angle * (180 / Math.PI); + } + + override isPointInPath(x: number, y: number, shapeId: string): boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + // 计算点到线段的距离 + const lineLength = Math.sqrt( + Math.pow(this.pointEnd.x - this.pointStart.x, 2) + + Math.pow(this.pointEnd.y - this.pointStart.y, 2) + ); + + if (lineLength === 0) return false; + + const distance = Math.abs( + (this.pointEnd.y - this.pointStart.y) * x - + (this.pointEnd.x - this.pointStart.x) * y + + this.pointEnd.x * this.pointStart.y - + this.pointEnd.y * this.pointStart.x + ) / lineLength; + + // 判断点是否在线段的范围内 + const dotProduct = + ((x - this.pointStart.x) * (this.pointEnd.x - this.pointStart.x) + + (y - this.pointStart.y) * (this.pointEnd.y - this.pointStart.y)) / lineLength; + + return distance <= this.strokeWidth && dotProduct >= 0 && dotProduct <= lineLength; + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/linePolygon.uts b/uni_modules/tmx-ui/core/canvas/lib/linePolygon.uts new file mode 100644 index 0000000..310effc --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/linePolygon.uts @@ -0,0 +1,314 @@ +import { Shape } from './shape.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +import { IShapeBoundRect, IShapeOptional } from '../interface.uts'; + +function getControlPoints(x0 : number, y0 : number, x1 : number, y1 : number, x2 : number, y2 : number, t : number) : number[] { + const d01 = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2)), + d12 = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)), + fa = (t * d01) / (d01 + d12), + fb = (t * d12) / (d01 + d12), + p1x = x1 - fa * (x2 - x0), + p1y = y1 - fa * (y2 - y0), + p2x = x1 + fb * (x2 - x0), + p2y = y1 + fb * (y2 - y0); + + return [p1x, p1y, p2x, p2y]; +} + +function expandPoints(p : number[], tension : number) : number[] { + const len = p.length + const allPoints : Array = []; + + for (let n = 2; n < len - 2; n += 2) { + const cp = getControlPoints( + p[n - 2], + p[n - 1], + p[n], + p[n + 1], + p[n + 2], + p[n + 3], + tension + ); + if (isNaN(cp[0])) { + continue; + } + allPoints.push(cp[0]); + allPoints.push(cp[1]); + allPoints.push(p[n]); + allPoints.push(p[n + 1]); + allPoints.push(cp[2]); + allPoints.push(cp[3]); + } + + return allPoints; +} + +export class ILinePolygon extends Shape { + override type = 'ILinePolygon' + constructor(config : IShapeOptional, canvas : ICanvas) { + super(config, canvas); + } + + override getBoundRect() : IShapeBoundRect { + let points = this.points; + if (points.length < 4) { + let cp = [] as number[] + for(let i=0;i<(4-points.length);i++){ + cp.push(0) + } + points = points.concat(cp) + return { + x: points[0], + y: points[1], + width: 0, + height: 0, + }; + } + if (this.tension !== 0) { + points = [ + points[0], + points[1], + ...this._getTensionPoints(false), + points[points.length - 2], + points[points.length - 1], + ]; + } else { + points = this.points; + } + let minX = this.points[0] + this.x; + let maxX = this.points[0] + this.x; + let minY = this.points[1] + this.y; + let maxY = this.points[1] + this.y; + let x=0 + let y =0; + for (let i = 0; i < points.length / 2; i++) { + x = points[i * 2] + this.x; + y = points[i * 2 + 1] + this.y; + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + minY = Math.min(minY, y); + maxY = Math.max(maxY, y); + } + let borderWidth = (this.stroke!='' ? this.strokeWidth / 2 : 0); + return { + x: minX - borderWidth, + y: minY - borderWidth, + width: maxX - minX + borderWidth*2, + height: maxY - minY + borderWidth*2, + } as IShapeBoundRect; + + + } + + private getTensionPoints() { + return this._getTensionPoints(); + } + private _getTensionPoints(isXYOffset:boolean = true) { + + if (this.closed) { + return this._getTensionPointsClosed(isXYOffset); + } else { + return expandPoints(isXYOffset?this._getPoints():this.points, this.tension); + } + } + private _getTensionPointsClosed(isXYOffset:boolean = true) { + const p = isXYOffset?this._getPoints():this.points + const len = p.length; + const tension = this.tension; + const firstControlPoints = getControlPoints( + p[len - 2], + p[len - 1], + p[0], + p[1], + p[2], + p[3], + tension + ); + const lastControlPoints = getControlPoints( + p[len - 4], + p[len - 3], + p[len - 2], + p[len - 1], + p[0], + p[1], + tension + ); + const middle = expandPoints(p, tension); + const tp = [firstControlPoints[2], firstControlPoints[3]] + .concat(middle) + .concat([ + lastControlPoints[0], + lastControlPoints[1], + p[len - 2], + p[len - 1], + lastControlPoints[2], + lastControlPoints[3], + firstControlPoints[0], + firstControlPoints[1], + p[0], + p[1], + ]); + + return tp; + } + + private _getPoints():number[]{ + return this.points.map((el:number,index:number)=>{ + return (index+1)%2 == 0 ?el+this.y:el+this.x; + }) + } + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false || this.points.length < 4) return; + super.draw(ctx); + ctx.beginPath(); + + let points = this._getPoints() + let length = points.length + let tension = this.tension + let closed = this.closed + let bezier = this.bezier + let tp = [] as number[] + let len = 0 + let n = 0; + + if (length==0) { + return; + } + + ctx.beginPath(); + ctx.moveTo(points[0], points[1]); + + + if (tension !== 0 && length > 4) { + tp = this.getTensionPoints(); + len = tp.length; + n = closed ? 0 : 4; + + if (!closed) { + ctx.quadraticCurveTo(tp[0], tp[1], tp[2], tp[3]); + } + + while (n < len - 2) { + + // #ifdef APP-ANDROID + ctx.bezierCurveTo( + tp[(n++).toInt()], + tp[(n++).toInt()], + tp[(n++).toInt()], + tp[(n++).toInt()], + tp[(n++).toInt()], + tp[(n++).toInt()] + ); + // #endif + // #ifndef APP-ANDROID + ctx.bezierCurveTo( + tp[n++], + tp[n++], + tp[n++], + tp[n++], + tp[n++], + tp[n++] + ); + // #endif + } + + if (!closed) { + ctx.quadraticCurveTo( + tp[len - 2], + tp[len - 1], + points[length - 2], + points[length - 1] + ); + } + } else if (bezier) { + + n = 2; + while (n < length) { + + // #ifdef APP-ANDROID + ctx.bezierCurveTo( + points[(n++).toInt()], + points[(n++).toInt()], + points[(n++).toInt()], + points[(n++).toInt()], + points[(n++).toInt()], + points[(n++).toInt()] + ); + // #endif + // #ifndef APP-ANDROID + ctx.bezierCurveTo( + points[n++], + points[n++], + points[n++], + points[n++], + points[n++], + points[n++] + ); + // #endif + } + } else { + for (n = 2; n < length; n += 2) { + ctx.lineTo(points[n], points[n + 1]); + } + } + + if (closed&&this.fill!='') { + ctx.closePath(); + ctx.fill(); + } else if(this.stroke!='') { + ctx.stroke(); + } + + ctx.restore(); + } + + override isPointInPath(x : number, y : number, shapeId : string) : boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + const rect = this.getBoundRect() + const realX = x - (this.offsetX) - this.x - this.points[0]; + const realY = y - (this.offsetY) - this.y - this.points[1]; + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + const rotatedX = centerX + dx * cos - dy * sin; + const rotatedY = centerY + dx * sin + dy * cos; + return rotatedX >= 0 && rotatedX <= rect.width* this.scaleX && rotatedY >= 0 && rotatedY <= rect.height* this.scaleY; + } + let isInRect = realX >= 0 && realX <= rect.width* this.scaleX && realY >= 0 && realY <= rect.height* this.scaleY; + + return isInRect + } + + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/path2d.uts b/uni_modules/tmx-ui/core/canvas/lib/path2d.uts new file mode 100644 index 0000000..6008302 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/path2d.uts @@ -0,0 +1,1869 @@ +import { Shape } from './shape.uts'; +import { IShapeOptional, ShapeSetAttrType,IShapeBoundRect } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +type Vector2d = { + x : number; + y : number; +} +type CommandType = 'm' | 'M' | 'l' | 'L' | 'v' | 'V' | 'h' | 'H' | 'z' | 'Z' | 'c' | 'C' | 'q' | 'Q' | 't' | 'T' | 's' | 'S' | 'a' | 'A' +type PathSegment = { + command : CommandType; + start : Vector2d | null; + points : number[]; + pathLength : number; +} + +type GetDerivativeType = (derivative : number, t : number, vs : number[]) => number + + +export const tValues : number[][] = [ + [], + [], + [ + -0.5773502691896257645091487805019574556476, + 0.5773502691896257645091487805019574556476, + ], + [ + 0, -0.7745966692414833770358530799564799221665, + 0.7745966692414833770358530799564799221665, + ], + [ + -0.3399810435848562648026657591032446872005, + 0.3399810435848562648026657591032446872005, + -0.8611363115940525752239464888928095050957, + 0.8611363115940525752239464888928095050957, + ], + [ + 0, -0.5384693101056830910363144207002088049672, + 0.5384693101056830910363144207002088049672, + -0.9061798459386639927976268782993929651256, + 0.9061798459386639927976268782993929651256, + ], + [ + 0.6612093864662645136613995950199053470064, + -0.6612093864662645136613995950199053470064, + -0.2386191860831969086305017216807119354186, + 0.2386191860831969086305017216807119354186, + -0.9324695142031520278123015544939946091347, + 0.9324695142031520278123015544939946091347, + ], + [ + 0, 0.4058451513773971669066064120769614633473, + -0.4058451513773971669066064120769614633473, + -0.7415311855993944398638647732807884070741, + 0.7415311855993944398638647732807884070741, + -0.9491079123427585245261896840478512624007, + 0.9491079123427585245261896840478512624007, + ], + [ + -0.1834346424956498049394761423601839806667, + 0.1834346424956498049394761423601839806667, + -0.5255324099163289858177390491892463490419, + 0.5255324099163289858177390491892463490419, + -0.7966664774136267395915539364758304368371, + 0.7966664774136267395915539364758304368371, + -0.9602898564975362316835608685694729904282, + 0.9602898564975362316835608685694729904282, + ], + [ + 0, -0.8360311073266357942994297880697348765441, + 0.8360311073266357942994297880697348765441, + -0.9681602395076260898355762029036728700494, + 0.9681602395076260898355762029036728700494, + -0.3242534234038089290385380146433366085719, + 0.3242534234038089290385380146433366085719, + -0.6133714327005903973087020393414741847857, + 0.6133714327005903973087020393414741847857, + ], + [ + -0.1488743389816312108848260011297199846175, + 0.1488743389816312108848260011297199846175, + -0.4333953941292471907992659431657841622, + 0.4333953941292471907992659431657841622, + -0.6794095682990244062343273651148735757692, + 0.6794095682990244062343273651148735757692, + -0.8650633666889845107320966884234930485275, + 0.8650633666889845107320966884234930485275, + -0.9739065285171717200779640120844520534282, + 0.9739065285171717200779640120844520534282, + ], + [ + 0, -0.2695431559523449723315319854008615246796, + 0.2695431559523449723315319854008615246796, + -0.5190961292068118159257256694586095544802, + 0.5190961292068118159257256694586095544802, + -0.7301520055740493240934162520311534580496, + 0.7301520055740493240934162520311534580496, + -0.8870625997680952990751577693039272666316, + 0.8870625997680952990751577693039272666316, + -0.9782286581460569928039380011228573907714, + 0.9782286581460569928039380011228573907714, + ], + [ + -0.1252334085114689154724413694638531299833, + 0.1252334085114689154724413694638531299833, + -0.3678314989981801937526915366437175612563, + 0.3678314989981801937526915366437175612563, + -0.587317954286617447296702418940534280369, + 0.587317954286617447296702418940534280369, + -0.7699026741943046870368938332128180759849, + 0.7699026741943046870368938332128180759849, + -0.9041172563704748566784658661190961925375, + 0.9041172563704748566784658661190961925375, + -0.9815606342467192506905490901492808229601, + 0.9815606342467192506905490901492808229601, + ], + [ + 0, -0.2304583159551347940655281210979888352115, + 0.2304583159551347940655281210979888352115, + -0.4484927510364468528779128521276398678019, + 0.4484927510364468528779128521276398678019, + -0.6423493394403402206439846069955156500716, + 0.6423493394403402206439846069955156500716, + -0.8015780907333099127942064895828598903056, + 0.8015780907333099127942064895828598903056, + -0.9175983992229779652065478365007195123904, + 0.9175983992229779652065478365007195123904, + -0.9841830547185881494728294488071096110649, + 0.9841830547185881494728294488071096110649, + ], + [ + -0.1080549487073436620662446502198347476119, + 0.1080549487073436620662446502198347476119, + -0.3191123689278897604356718241684754668342, + 0.3191123689278897604356718241684754668342, + -0.5152486363581540919652907185511886623088, + 0.5152486363581540919652907185511886623088, + -0.6872929048116854701480198030193341375384, + 0.6872929048116854701480198030193341375384, + -0.8272013150697649931897947426503949610397, + 0.8272013150697649931897947426503949610397, + -0.928434883663573517336391139377874264477, + 0.928434883663573517336391139377874264477, + -0.986283808696812338841597266704052801676, + 0.986283808696812338841597266704052801676, + ], + [ + 0, -0.2011940939974345223006283033945962078128, + 0.2011940939974345223006283033945962078128, + -0.3941513470775633698972073709810454683627, + 0.3941513470775633698972073709810454683627, + -0.5709721726085388475372267372539106412383, + 0.5709721726085388475372267372539106412383, + -0.7244177313601700474161860546139380096308, + 0.7244177313601700474161860546139380096308, + -0.8482065834104272162006483207742168513662, + 0.8482065834104272162006483207742168513662, + -0.9372733924007059043077589477102094712439, + 0.9372733924007059043077589477102094712439, + -0.9879925180204854284895657185866125811469, + 0.9879925180204854284895657185866125811469, + ], + [ + -0.0950125098376374401853193354249580631303, + 0.0950125098376374401853193354249580631303, + -0.281603550779258913230460501460496106486, + 0.281603550779258913230460501460496106486, + -0.45801677765722738634241944298357757354, + 0.45801677765722738634241944298357757354, + -0.6178762444026437484466717640487910189918, + 0.6178762444026437484466717640487910189918, + -0.7554044083550030338951011948474422683538, + 0.7554044083550030338951011948474422683538, + -0.8656312023878317438804678977123931323873, + 0.8656312023878317438804678977123931323873, + -0.9445750230732325760779884155346083450911, + 0.9445750230732325760779884155346083450911, + -0.9894009349916499325961541734503326274262, + 0.9894009349916499325961541734503326274262, + ], + [ + 0, -0.1784841814958478558506774936540655574754, + 0.1784841814958478558506774936540655574754, + -0.3512317634538763152971855170953460050405, + 0.3512317634538763152971855170953460050405, + -0.5126905370864769678862465686295518745829, + 0.5126905370864769678862465686295518745829, + -0.6576711592166907658503022166430023351478, + 0.6576711592166907658503022166430023351478, + -0.7815140038968014069252300555204760502239, + 0.7815140038968014069252300555204760502239, + -0.8802391537269859021229556944881556926234, + 0.8802391537269859021229556944881556926234, + -0.9506755217687677612227169578958030214433, + 0.9506755217687677612227169578958030214433, + -0.9905754753144173356754340199406652765077, + 0.9905754753144173356754340199406652765077, + ], + [ + -0.0847750130417353012422618529357838117333, + 0.0847750130417353012422618529357838117333, + -0.2518862256915055095889728548779112301628, + 0.2518862256915055095889728548779112301628, + -0.4117511614628426460359317938330516370789, + 0.4117511614628426460359317938330516370789, + -0.5597708310739475346078715485253291369276, + 0.5597708310739475346078715485253291369276, + -0.6916870430603532078748910812888483894522, + 0.6916870430603532078748910812888483894522, + -0.8037049589725231156824174550145907971032, + 0.8037049589725231156824174550145907971032, + -0.8926024664975557392060605911271455154078, + 0.8926024664975557392060605911271455154078, + -0.9558239495713977551811958929297763099728, + 0.9558239495713977551811958929297763099728, + -0.9915651684209309467300160047061507702525, + 0.9915651684209309467300160047061507702525, + ], + [ + 0, -0.1603586456402253758680961157407435495048, + 0.1603586456402253758680961157407435495048, + -0.3165640999636298319901173288498449178922, + 0.3165640999636298319901173288498449178922, + -0.4645707413759609457172671481041023679762, + 0.4645707413759609457172671481041023679762, + -0.6005453046616810234696381649462392798683, + 0.6005453046616810234696381649462392798683, + -0.7209661773352293786170958608237816296571, + 0.7209661773352293786170958608237816296571, + -0.8227146565371428249789224867127139017745, + 0.8227146565371428249789224867127139017745, + -0.9031559036148179016426609285323124878093, + 0.9031559036148179016426609285323124878093, + -0.960208152134830030852778840687651526615, + 0.960208152134830030852778840687651526615, + -0.9924068438435844031890176702532604935893, + 0.9924068438435844031890176702532604935893, + ], + [ + -0.0765265211334973337546404093988382110047, + 0.0765265211334973337546404093988382110047, + -0.227785851141645078080496195368574624743, + 0.227785851141645078080496195368574624743, + -0.3737060887154195606725481770249272373957, + 0.3737060887154195606725481770249272373957, + -0.5108670019508270980043640509552509984254, + 0.5108670019508270980043640509552509984254, + -0.6360536807265150254528366962262859367433, + 0.6360536807265150254528366962262859367433, + -0.7463319064601507926143050703556415903107, + 0.7463319064601507926143050703556415903107, + -0.8391169718222188233945290617015206853296, + 0.8391169718222188233945290617015206853296, + -0.9122344282513259058677524412032981130491, + 0.9122344282513259058677524412032981130491, + -0.963971927277913791267666131197277221912, + 0.963971927277913791267666131197277221912, + -0.9931285991850949247861223884713202782226, + 0.9931285991850949247861223884713202782226, + ], + [ + 0, -0.1455618541608950909370309823386863301163, + 0.1455618541608950909370309823386863301163, + -0.288021316802401096600792516064600319909, + 0.288021316802401096600792516064600319909, + -0.4243421202074387835736688885437880520964, + 0.4243421202074387835736688885437880520964, + -0.551618835887219807059018796724313286622, + 0.551618835887219807059018796724313286622, + -0.667138804197412319305966669990339162597, + 0.667138804197412319305966669990339162597, + -0.7684399634756779086158778513062280348209, + 0.7684399634756779086158778513062280348209, + -0.8533633645833172836472506385875676702761, + 0.8533633645833172836472506385875676702761, + -0.9200993341504008287901871337149688941591, + 0.9200993341504008287901871337149688941591, + -0.9672268385663062943166222149076951614246, + 0.9672268385663062943166222149076951614246, + -0.9937521706203895002602420359379409291933, + 0.9937521706203895002602420359379409291933, + ], + [ + -0.0697392733197222212138417961186280818222, + 0.0697392733197222212138417961186280818222, + -0.2078604266882212854788465339195457342156, + 0.2078604266882212854788465339195457342156, + -0.3419358208920842251581474204273796195591, + 0.3419358208920842251581474204273796195591, + -0.4693558379867570264063307109664063460953, + 0.4693558379867570264063307109664063460953, + -0.5876404035069115929588769276386473488776, + 0.5876404035069115929588769276386473488776, + -0.6944872631866827800506898357622567712673, + 0.6944872631866827800506898357622567712673, + -0.7878168059792081620042779554083515213881, + 0.7878168059792081620042779554083515213881, + -0.8658125777203001365364256370193787290847, + 0.8658125777203001365364256370193787290847, + -0.9269567721871740005206929392590531966353, + 0.9269567721871740005206929392590531966353, + -0.9700604978354287271239509867652687108059, + 0.9700604978354287271239509867652687108059, + -0.994294585482399292073031421161298980393, + 0.994294585482399292073031421161298980393, + ], + [ + 0, -0.1332568242984661109317426822417661370104, + 0.1332568242984661109317426822417661370104, + -0.264135680970344930533869538283309602979, + 0.264135680970344930533869538283309602979, + -0.390301038030290831421488872880605458578, + 0.390301038030290831421488872880605458578, + -0.5095014778460075496897930478668464305448, + 0.5095014778460075496897930478668464305448, + -0.6196098757636461563850973116495956533871, + 0.6196098757636461563850973116495956533871, + -0.7186613631319501944616244837486188483299, + 0.7186613631319501944616244837486188483299, + -0.8048884016188398921511184069967785579414, + 0.8048884016188398921511184069967785579414, + -0.8767523582704416673781568859341456716389, + 0.8767523582704416673781568859341456716389, + -0.9329710868260161023491969890384229782357, + 0.9329710868260161023491969890384229782357, + -0.9725424712181152319560240768207773751816, + 0.9725424712181152319560240768207773751816, + -0.9947693349975521235239257154455743605736, + 0.9947693349975521235239257154455743605736, + ], + [ + -0.0640568928626056260850430826247450385909, + 0.0640568928626056260850430826247450385909, + -0.1911188674736163091586398207570696318404, + 0.1911188674736163091586398207570696318404, + -0.3150426796961633743867932913198102407864, + 0.3150426796961633743867932913198102407864, + -0.4337935076260451384870842319133497124524, + 0.4337935076260451384870842319133497124524, + -0.5454214713888395356583756172183723700107, + 0.5454214713888395356583756172183723700107, + -0.6480936519369755692524957869107476266696, + 0.6480936519369755692524957869107476266696, + -0.7401241915785543642438281030999784255232, + 0.7401241915785543642438281030999784255232, + -0.8200019859739029219539498726697452080761, + 0.8200019859739029219539498726697452080761, + -0.8864155270044010342131543419821967550873, + 0.8864155270044010342131543419821967550873, + -0.9382745520027327585236490017087214496548, + 0.9382745520027327585236490017087214496548, + -0.9747285559713094981983919930081690617411, + 0.9747285559713094981983919930081690617411, + -0.9951872199970213601799974097007368118745, + 0.9951872199970213601799974097007368118745, + ], +]; + +// Legendre-Gauss weights (wi values, defined by a function linked to in the Bezier primer article) +export const cValues : number[][] = [ + [], + [], + [1.0, 1.0], + [ + 0.8888888888888888888888888888888888888888, + 0.5555555555555555555555555555555555555555, + 0.5555555555555555555555555555555555555555, + ], + [ + 0.6521451548625461426269360507780005927646, + 0.6521451548625461426269360507780005927646, + 0.3478548451374538573730639492219994072353, + 0.3478548451374538573730639492219994072353, + ], + [ + 0.5688888888888888888888888888888888888888, + 0.4786286704993664680412915148356381929122, + 0.4786286704993664680412915148356381929122, + 0.2369268850561890875142640407199173626432, + 0.2369268850561890875142640407199173626432, + ], + [ + 0.3607615730481386075698335138377161116615, + 0.3607615730481386075698335138377161116615, + 0.4679139345726910473898703439895509948116, + 0.4679139345726910473898703439895509948116, + 0.1713244923791703450402961421727328935268, + 0.1713244923791703450402961421727328935268, + ], + [ + 0.4179591836734693877551020408163265306122, + 0.3818300505051189449503697754889751338783, + 0.3818300505051189449503697754889751338783, + 0.2797053914892766679014677714237795824869, + 0.2797053914892766679014677714237795824869, + 0.1294849661688696932706114326790820183285, + 0.1294849661688696932706114326790820183285, + ], + [ + 0.3626837833783619829651504492771956121941, + 0.3626837833783619829651504492771956121941, + 0.3137066458778872873379622019866013132603, + 0.3137066458778872873379622019866013132603, + 0.2223810344533744705443559944262408844301, + 0.2223810344533744705443559944262408844301, + 0.1012285362903762591525313543099621901153, + 0.1012285362903762591525313543099621901153, + ], + [ + 0.3302393550012597631645250692869740488788, + 0.1806481606948574040584720312429128095143, + 0.1806481606948574040584720312429128095143, + 0.0812743883615744119718921581105236506756, + 0.0812743883615744119718921581105236506756, + 0.3123470770400028400686304065844436655987, + 0.3123470770400028400686304065844436655987, + 0.2606106964029354623187428694186328497718, + 0.2606106964029354623187428694186328497718, + ], + [ + 0.295524224714752870173892994651338329421, + 0.295524224714752870173892994651338329421, + 0.2692667193099963550912269215694693528597, + 0.2692667193099963550912269215694693528597, + 0.2190863625159820439955349342281631924587, + 0.2190863625159820439955349342281631924587, + 0.1494513491505805931457763396576973324025, + 0.1494513491505805931457763396576973324025, + 0.0666713443086881375935688098933317928578, + 0.0666713443086881375935688098933317928578, + ], + [ + 0.272925086777900630714483528336342189156, + 0.2628045445102466621806888698905091953727, + 0.2628045445102466621806888698905091953727, + 0.2331937645919904799185237048431751394317, + 0.2331937645919904799185237048431751394317, + 0.1862902109277342514260976414316558916912, + 0.1862902109277342514260976414316558916912, + 0.1255803694649046246346942992239401001976, + 0.1255803694649046246346942992239401001976, + 0.0556685671161736664827537204425485787285, + 0.0556685671161736664827537204425485787285, + ], + [ + 0.2491470458134027850005624360429512108304, + 0.2491470458134027850005624360429512108304, + 0.2334925365383548087608498989248780562594, + 0.2334925365383548087608498989248780562594, + 0.2031674267230659217490644558097983765065, + 0.2031674267230659217490644558097983765065, + 0.160078328543346226334652529543359071872, + 0.160078328543346226334652529543359071872, + 0.1069393259953184309602547181939962242145, + 0.1069393259953184309602547181939962242145, + 0.047175336386511827194615961485017060317, + 0.047175336386511827194615961485017060317, + ], + [ + 0.2325515532308739101945895152688359481566, + 0.2262831802628972384120901860397766184347, + 0.2262831802628972384120901860397766184347, + 0.2078160475368885023125232193060527633865, + 0.2078160475368885023125232193060527633865, + 0.1781459807619457382800466919960979955128, + 0.1781459807619457382800466919960979955128, + 0.1388735102197872384636017768688714676218, + 0.1388735102197872384636017768688714676218, + 0.0921214998377284479144217759537971209236, + 0.0921214998377284479144217759537971209236, + 0.0404840047653158795200215922009860600419, + 0.0404840047653158795200215922009860600419, + ], + [ + 0.2152638534631577901958764433162600352749, + 0.2152638534631577901958764433162600352749, + 0.2051984637212956039659240656612180557103, + 0.2051984637212956039659240656612180557103, + 0.1855383974779378137417165901251570362489, + 0.1855383974779378137417165901251570362489, + 0.1572031671581935345696019386238421566056, + 0.1572031671581935345696019386238421566056, + 0.1215185706879031846894148090724766259566, + 0.1215185706879031846894148090724766259566, + 0.0801580871597602098056332770628543095836, + 0.0801580871597602098056332770628543095836, + 0.0351194603317518630318328761381917806197, + 0.0351194603317518630318328761381917806197, + ], + [ + 0.2025782419255612728806201999675193148386, + 0.1984314853271115764561183264438393248186, + 0.1984314853271115764561183264438393248186, + 0.1861610000155622110268005618664228245062, + 0.1861610000155622110268005618664228245062, + 0.1662692058169939335532008604812088111309, + 0.1662692058169939335532008604812088111309, + 0.1395706779261543144478047945110283225208, + 0.1395706779261543144478047945110283225208, + 0.1071592204671719350118695466858693034155, + 0.1071592204671719350118695466858693034155, + 0.0703660474881081247092674164506673384667, + 0.0703660474881081247092674164506673384667, + 0.0307532419961172683546283935772044177217, + 0.0307532419961172683546283935772044177217, + ], + [ + 0.1894506104550684962853967232082831051469, + 0.1894506104550684962853967232082831051469, + 0.1826034150449235888667636679692199393835, + 0.1826034150449235888667636679692199393835, + 0.1691565193950025381893120790303599622116, + 0.1691565193950025381893120790303599622116, + 0.1495959888165767320815017305474785489704, + 0.1495959888165767320815017305474785489704, + 0.1246289712555338720524762821920164201448, + 0.1246289712555338720524762821920164201448, + 0.0951585116824927848099251076022462263552, + 0.0951585116824927848099251076022462263552, + 0.0622535239386478928628438369943776942749, + 0.0622535239386478928628438369943776942749, + 0.0271524594117540948517805724560181035122, + 0.0271524594117540948517805724560181035122, + ], + [ + 0.1794464703562065254582656442618856214487, + 0.1765627053669926463252709901131972391509, + 0.1765627053669926463252709901131972391509, + 0.1680041021564500445099706637883231550211, + 0.1680041021564500445099706637883231550211, + 0.1540457610768102880814315948019586119404, + 0.1540457610768102880814315948019586119404, + 0.1351363684685254732863199817023501973721, + 0.1351363684685254732863199817023501973721, + 0.1118838471934039710947883856263559267358, + 0.1118838471934039710947883856263559267358, + 0.0850361483171791808835353701910620738504, + 0.0850361483171791808835353701910620738504, + 0.0554595293739872011294401653582446605128, + 0.0554595293739872011294401653582446605128, + 0.0241483028685479319601100262875653246916, + 0.0241483028685479319601100262875653246916, + ], + [ + 0.1691423829631435918406564701349866103341, + 0.1691423829631435918406564701349866103341, + 0.1642764837458327229860537764659275904123, + 0.1642764837458327229860537764659275904123, + 0.1546846751262652449254180038363747721932, + 0.1546846751262652449254180038363747721932, + 0.1406429146706506512047313037519472280955, + 0.1406429146706506512047313037519472280955, + 0.1225552067114784601845191268002015552281, + 0.1225552067114784601845191268002015552281, + 0.1009420441062871655628139849248346070628, + 0.1009420441062871655628139849248346070628, + 0.0764257302548890565291296776166365256053, + 0.0764257302548890565291296776166365256053, + 0.0497145488949697964533349462026386416808, + 0.0497145488949697964533349462026386416808, + 0.0216160135264833103133427102664524693876, + 0.0216160135264833103133427102664524693876, + ], + [ + 0.1610544498487836959791636253209167350399, + 0.1589688433939543476499564394650472016787, + 0.1589688433939543476499564394650472016787, + 0.152766042065859666778855400897662998461, + 0.152766042065859666778855400897662998461, + 0.1426067021736066117757461094419029724756, + 0.1426067021736066117757461094419029724756, + 0.1287539625393362276755157848568771170558, + 0.1287539625393362276755157848568771170558, + 0.1115666455473339947160239016817659974813, + 0.1115666455473339947160239016817659974813, + 0.0914900216224499994644620941238396526609, + 0.0914900216224499994644620941238396526609, + 0.0690445427376412265807082580060130449618, + 0.0690445427376412265807082580060130449618, + 0.0448142267656996003328381574019942119517, + 0.0448142267656996003328381574019942119517, + 0.0194617882297264770363120414644384357529, + 0.0194617882297264770363120414644384357529, + ], + [ + 0.1527533871307258506980843319550975934919, + 0.1527533871307258506980843319550975934919, + 0.1491729864726037467878287370019694366926, + 0.1491729864726037467878287370019694366926, + 0.1420961093183820513292983250671649330345, + 0.1420961093183820513292983250671649330345, + 0.1316886384491766268984944997481631349161, + 0.1316886384491766268984944997481631349161, + 0.118194531961518417312377377711382287005, + 0.118194531961518417312377377711382287005, + 0.1019301198172404350367501354803498761666, + 0.1019301198172404350367501354803498761666, + 0.0832767415767047487247581432220462061001, + 0.0832767415767047487247581432220462061001, + 0.0626720483341090635695065351870416063516, + 0.0626720483341090635695065351870416063516, + 0.040601429800386941331039952274932109879, + 0.040601429800386941331039952274932109879, + 0.0176140071391521183118619623518528163621, + 0.0176140071391521183118619623518528163621, + ], + [ + 0.1460811336496904271919851476833711882448, + 0.1445244039899700590638271665537525436099, + 0.1445244039899700590638271665537525436099, + 0.1398873947910731547221334238675831108927, + 0.1398873947910731547221334238675831108927, + 0.132268938633337461781052574496775604329, + 0.132268938633337461781052574496775604329, + 0.1218314160537285341953671771257335983563, + 0.1218314160537285341953671771257335983563, + 0.1087972991671483776634745780701056420336, + 0.1087972991671483776634745780701056420336, + 0.0934444234560338615532897411139320884835, + 0.0934444234560338615532897411139320884835, + 0.0761001136283793020170516533001831792261, + 0.0761001136283793020170516533001831792261, + 0.0571344254268572082836358264724479574912, + 0.0571344254268572082836358264724479574912, + 0.0369537897708524937999506682993296661889, + 0.0369537897708524937999506682993296661889, + 0.0160172282577743333242246168584710152658, + 0.0160172282577743333242246168584710152658, + ], + [ + 0.1392518728556319933754102483418099578739, + 0.1392518728556319933754102483418099578739, + 0.1365414983460151713525738312315173965863, + 0.1365414983460151713525738312315173965863, + 0.1311735047870623707329649925303074458757, + 0.1311735047870623707329649925303074458757, + 0.1232523768105124242855609861548144719594, + 0.1232523768105124242855609861548144719594, + 0.1129322960805392183934006074217843191142, + 0.1129322960805392183934006074217843191142, + 0.1004141444428809649320788378305362823508, + 0.1004141444428809649320788378305362823508, + 0.0859416062170677274144436813727028661891, + 0.0859416062170677274144436813727028661891, + 0.0697964684245204880949614189302176573987, + 0.0697964684245204880949614189302176573987, + 0.0522933351526832859403120512732112561121, + 0.0522933351526832859403120512732112561121, + 0.0337749015848141547933022468659129013491, + 0.0337749015848141547933022468659129013491, + 0.0146279952982722006849910980471854451902, + 0.0146279952982722006849910980471854451902, + ], + [ + 0.1336545721861061753514571105458443385831, + 0.132462039404696617371642464703316925805, + 0.132462039404696617371642464703316925805, + 0.1289057221880821499785953393997936532597, + 0.1289057221880821499785953393997936532597, + 0.1230490843067295304675784006720096548158, + 0.1230490843067295304675784006720096548158, + 0.1149966402224113649416435129339613014914, + 0.1149966402224113649416435129339613014914, + 0.1048920914645414100740861850147438548584, + 0.1048920914645414100740861850147438548584, + 0.0929157660600351474770186173697646486034, + 0.0929157660600351474770186173697646486034, + 0.0792814117767189549228925247420432269137, + 0.0792814117767189549228925247420432269137, + 0.0642324214085258521271696151589109980391, + 0.0642324214085258521271696151589109980391, + 0.0480376717310846685716410716320339965612, + 0.0480376717310846685716410716320339965612, + 0.0309880058569794443106942196418845053837, + 0.0309880058569794443106942196418845053837, + 0.0134118594871417720813094934586150649766, + 0.0134118594871417720813094934586150649766, + ], + [ + 0.1279381953467521569740561652246953718517, + 0.1279381953467521569740561652246953718517, + 0.1258374563468282961213753825111836887264, + 0.1258374563468282961213753825111836887264, + 0.121670472927803391204463153476262425607, + 0.121670472927803391204463153476262425607, + 0.1155056680537256013533444839067835598622, + 0.1155056680537256013533444839067835598622, + 0.1074442701159656347825773424466062227946, + 0.1074442701159656347825773424466062227946, + 0.0976186521041138882698806644642471544279, + 0.0976186521041138882698806644642471544279, + 0.086190161531953275917185202983742667185, + 0.086190161531953275917185202983742667185, + 0.0733464814110803057340336152531165181193, + 0.0733464814110803057340336152531165181193, + 0.0592985849154367807463677585001085845412, + 0.0592985849154367807463677585001085845412, + 0.0442774388174198061686027482113382288593, + 0.0442774388174198061686027482113382288593, + 0.0285313886289336631813078159518782864491, + 0.0285313886289336631813078159518782864491, + 0.0123412297999871995468056670700372915759, + 0.0123412297999871995468056670700372915759, + ], +]; +export const binomialCoefficients = [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]; +let getDerivative = null as GetDerivativeType | null +getDerivative = (derivative : number, t : number, vs : number[]) : number => { + // the derivative of any 't'-less function is zero. + const n = vs.length - 1; + let _vs = [] as number[]; + let value = 0; + + if (n === 0) { + return 0; + } + + // direct values? compute! + if (derivative === 0) { + value = 0; + for (let k = 0; k <= n; k++) { + value += + binomialCoefficients[n][k] * + Math.pow(1 - t, n - k) * + Math.pow(t, k) * + vs[k]; + } + return value; + } else { + // Still some derivative? go down one order, then try + // for the lower order curve's. + _vs = [] as number[]; + for (let k = 0; k < n; k++) { + _vs.push(0) + } + for (let k = 0; k < n; k++) { + _vs[k] = n * (vs[k + 1] - vs[k]); + } + + let vz = getDerivative!(derivative - 1, t, _vs) as number + return vz as number; + } + +}; + +function BFunc(xs : number[], ys : number[], t : number) { + const xbase = getDerivative!(1, t, xs); + const ybase = getDerivative!(1, t, ys); + const combined = xbase * xbase + ybase * ybase; + return Math.sqrt(combined); +} +export const t2length = ( + length : number, + totalLength : number, + func : (t : number) => number +) : number => { + let error = 1; + let t = length / totalLength; + let step = (length - func(t)) / totalLength; + + let numIterations = 0; + while (error > 0.001) { + const increasedTLength = func(t + step); + const increasedTError = Math.abs(length - increasedTLength) / totalLength; + if (increasedTError < error) { + error = increasedTError; + t += step; + } else { + const decreasedTLength = func(t - step); + const decreasedTError = Math.abs(length - decreasedTLength) / totalLength; + if (decreasedTError < error) { + error = decreasedTError; + t -= step; + } else { + step /= 2; + } + } + + numIterations++; + if (numIterations > 500) { + break; + } + } + + return t; +}; +export const getCubicArcLength = (xs : number[], ys : number[], t : number) => { + let sum : number = 0; + let correctedT : number = 0; + + /*if (xs.length >= tValues.length) { + throw new Error('too high n bezier'); + }*/ + + const n = 20; + + const z = t / 2; + sum = 0; + for (let i = 0; i < n; i++) { + correctedT = z * tValues[n][i] + z; + sum += cValues[n][i] * BFunc(xs, ys, correctedT); + } + return z * sum; +}; + +export const getQuadraticArcLength = ( + xs : number[], + ys : number[], + t : number +) => { + if (t == null) { + t = 1; + } + const ax = xs[0] - 2 * xs[1] + xs[2]; + const ay = ys[0] - 2 * ys[1] + ys[2]; + const bx = 2 * xs[1] - 2 * xs[0]; + const by = 2 * ys[1] - 2 * ys[0]; + + const A = 4 * (ax * ax + ay * ay); + const B = 4 * (ax * bx + ay * by); + const C = bx * bx + by * by; + + if (A === 0) { + return ( + t * Math.sqrt(Math.pow(xs[2] - xs[0], 2) + Math.pow(ys[2] - ys[0], 2)) + ); + } + const b = B / (2 * A); + const c = C / A; + const u = t + b; + const k = c - b * b; + + const uuk = u * u + k > 0 ? Math.sqrt(u * u + k) : 0; + const bbk = b * b + k > 0 ? Math.sqrt(b * b + k) : 0; + const term = + b + Math.sqrt(b * b + k) !== 0 + ? k * Math.log(Math.abs((u + uuk) / (b + bbk))) + : 0; + + return (Math.sqrt(A) / 2) * (u * uuk - b * bbk + term); +}; + +/** + * Path2dSvg解析器 + * 注意事项: + * 1,x,y,width,height无法通过属性设置,内容被解析后会 + * 自动更新上述信息,为只读 + * 真实坐标是x+offsetX,外部如果设置渲染位置要用offsetX来设置,因为SVG解析后的坐标是绝对的,不受外部属性设置影响。 + * @version 1.0.0 + * @date 2025/2/6 + * @copright 不允许外发给别人,只可在tmui4x是使用 + */ +export class Path2DShape extends Shape { + svgPath:string = "" + private path : any; + private commands : string[] = []; + private dataArray : PathSegment[] = []; + private pathLength = 0; + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.type = 'Path2DShape'; + this.path = canvas.canvas!.createPath2D(); + } + + moveTo(x : number, y : number) : Path2DShape { + // #ifdef APP|WEB + let pathObj = this.path as Path2D; + // #endif + // #ifdef MP + let pathObj = this.path; + // #endif + this.commands.push(`M ${x} ${y}`); + pathObj.moveTo(x, y); + this.needsUpdate = true; + return this; + } + + lineTo(x : number, y : number) : Path2DShape { + // #ifdef APP|WEB + let pathObj = this.path as Path2D; + // #endif + // #ifdef MP + let pathObj = this.path; + // #endif + this.commands.push(`L ${x} ${y}`); + pathObj.lineTo(x, y); + this.needsUpdate = true; + return this; + } + + bezierCurveTo(cp1x : number, cp1y : number, cp2x : number, cp2y : number, x : number, y : number) : Path2DShape { + // #ifdef APP|WEB + let pathObj = this.path as Path2D; + // #endif + // #ifdef MP + let pathObj = this.path; + // #endif + this.commands.push(`C ${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x} ${y}`); + pathObj.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + this.needsUpdate = true; + return this; + } + + quadraticCurveTo(cpx : number, cpy : number, x : number, y : number) : Path2DShape { + // #ifdef APP|WEB + let pathObj = this.path as Path2D; + // #endif + // #ifdef MP + let pathObj = this.path; + // #endif + this.commands.push(`Q ${cpx} ${cpy} ${x} ${y}`); + pathObj.quadraticCurveTo(cpx, cpy, x, y); + this.needsUpdate = true; + return this; + } + + arc(x : number, y : number, radius : number, startAngle : number, endAngle : number, counterclockwise : boolean = false) : Path2DShape { + // #ifdef APP|WEB + let pathObj = this.path as Path2D; + // #endif + // #ifdef MP + let pathObj = this.path; + // #endif + this.commands.push(`A ${x} ${y} ${radius} ${startAngle} ${endAngle} ${counterclockwise ? 1 : 0}`); + pathObj.arc(x, y, radius, startAngle, endAngle, counterclockwise); + this.needsUpdate = true; + return this; + } + + closePath() : Path2DShape { + // #ifdef APP|WEB + let pathObj = this.path as Path2D; + // #endif + // #ifdef MP + let pathObj = this.path; + // #endif + this.commands.push('Z'); + pathObj.closePath(); + this.needsUpdate = true; + return this; + } + + clear() : Path2DShape { + + this.commands = []; + this.path = this.canvas.canvas!.createPath2D(); + this.needsUpdate = true; + return this; + } + convertEndpointToCenterParameterization( + x1 : number, + y1 : number, + x2 : number, + y2 : number, + fa : number, + fs : number, + rxs : number, + rys : number, + psiDeg : number + ) { + let rx = rxs + let ry = rys + // Derived from: http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes + const psi = psiDeg * (Math.PI / 180.0); + const xp = + (Math.cos(psi) * (x1 - x2)) / 2.0 + (Math.sin(psi) * (y1 - y2)) / 2.0; + const yp = + (-1 * Math.sin(psi) * (x1 - x2)) / 2.0 + + (Math.cos(psi) * (y1 - y2)) / 2.0; + + const lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); + + if (lambda > 1) { + rx = rx * Math.sqrt(lambda); + ry = ry * Math.sqrt(lambda); + } + + let f = Math.sqrt( + (rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) / + (rx * rx * (yp * yp) + ry * ry * (xp * xp)) + ); + + if (fa == fs) { + f *= -1; + } + if (isNaN(f)) { + f = 0; + } + + const cxp = (f * rx * yp) / ry; + const cyp = (f * -ry * xp) / rx; + + const cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; + const cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; + + const vMag = function (v : number[]) : number { + return Math.sqrt(v[0] * v[0] + v[1] * v[1]); + }; + const vRatio = function (u : number[], v : number[]) : number { + return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); + }; + const vAngle = function (u : number[], v : number[]) : number { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v)); + }; + const theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]); + const u = [(xp - cxp) / rx, (yp - cyp) / ry]; + const v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; + let dTheta = vAngle(u, v); + + if (vRatio(u, v) <= -1) { + dTheta = Math.PI; + } + if (vRatio(u, v) >= 1) { + dTheta = 0; + } + if (fs === 0 && dTheta > 0) { + dTheta = dTheta - 2 * Math.PI; + } + if (fs === 1 && dTheta < 0) { + dTheta = dTheta + 2 * Math.PI; + } + return [cx, cy, rx, ry, theta, dTheta, psi, fs]; + } + parsePathData(data : string) : PathSegment[] { + if (data == "") { + return []; + } + + // command string + let cs = data; + this.svgPath = data; + // command chars + const cc = [ + 'm', + 'M', + 'l', + 'L', + 'v', + 'V', + 'h', + 'H', + 'z', + 'Z', + 'c', + 'C', + 'q', + 'Q', + 't', + 'T', + 's', + 'S', + 'a', + 'A', + ]; + // convert white spaces to commas + cs = cs.replace(new RegExp(' ', 'g'), ','); + // create pipes so that we can split the data + for (let n = 0; n < cc.length; n++) { + cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]); + } + // create array + const arr = cs.split('|'); + const ca : PathSegment[] = []; + let coords : string[] = []; + // init context point + let cpx = 0; + let cpy = 0; + + const re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi; + let n = 0 + for (n = 1; n < arr.length; n++) { + let str = arr[n]; + let c = str.charAt(0) + str = str.slice(1); + // match = re.exec(str); + + coords = [] as string[]; + let match = str.match(re); + if (match != null) { + match.forEach((el : string | null) => { + if (el != null) { + let estr = el!; + coords.push(estr); + } + }) + } + + const p : number[] = []; + + for (let j = 0, jlen = coords.length; j < jlen; j++) { + // extra case for merged flags + if (coords[j] == '00') { + p.push(0, 0); + continue; + } + const parsed = parseFloat(coords[j]); + if (!isNaN(parsed)) { + p.push(parsed); + } else { + p.push(0); + } + } + + while (p.length > 0) { + if (isNaN(p[0])) { + // case for a trailing comma before next command + break; + } + + let cmd : string = ''; + let points : number[] = []; + const startX = cpx; + const startY = cpy; + let prevCmd = null as PathSegment | null; + let ctlPtx = 0; + let ctlPty = 0; + + let rx = 0; + let ry = 0; + let psi = 0; + let fa = 0; + let fs = 0; + let x1 = 0; + let y1 = 0; + // convert l, H, h, V, and v to L + switch (c) { + // Note: Keep the lineTo's above the moveTo's in this switch + case 'l': + cpx += p.shift()!; + cpy += p.shift()!; + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'L': + cpx = p.shift()!; + cpy = p.shift()!; + points.push(cpx, cpy); + break; + // Note: lineTo handlers need to be above this point + case 'm': + var dx = p.shift()!; + var dy = p.shift()!; + cpx += dx; + cpy += dy; + cmd = 'M'; + // After closing the path move the current position + // to the the first point of the path (if any). + if (ca.length > 2 && ca[ca.length - 1].command === 'z') { + for (let idx = ca.length - 2; idx >= 0; idx--) { + if (ca[idx].command === 'M') { + cpx = ca[idx].points[0] + dx; + cpy = ca[idx].points[1] + dy; + break; + } + } + } + points.push(cpx, cpy); + c = 'l'; + // subsequent points are treated as relative lineTo + break; + case 'M': + cpx = p.shift()!; + cpy = p.shift()!; + cmd = 'M'; + points.push(cpx, cpy); + c = 'L'; + // subsequent points are treated as absolute lineTo + break; + + case 'h': + cpx += p.shift()!; + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'H': + cpx = p.shift()!; + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'v': + cpy += p.shift()!; + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'V': + cpy = p.shift()!; + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'C': + points.push(p.shift()!, p.shift()!, p.shift()!, p.shift()!); + cpx = p.shift()!; + cpy = p.shift()!; + points.push(cpx, cpy); + break; + case 'c': + points.push( + cpx + p.shift()!, + cpy + p.shift()!, + cpx + p.shift()!, + cpy + p.shift()! + ); + cpx += p.shift()!; + cpy += p.shift()!; + cmd = 'C'; + points.push(cpx, cpy); + break; + case 'S': + ctlPtx = cpx; + ctlPty = cpy; + prevCmd = ca[ca.length - 1]; + if (prevCmd?.command == 'C') { + ctlPtx = cpx + (cpx - prevCmd!.points[2]); + ctlPty = cpy + (cpy - prevCmd!.points[3]); + } + points.push(ctlPtx, ctlPty, p.shift()!, p.shift()!); + cpx = p.shift()!; + cpy = p.shift()!; + cmd = 'C'; + points.push(cpx, cpy); + break; + case 's': + ctlPtx = cpx; + ctlPty = cpy; + prevCmd = ca[ca.length - 1]; + if (prevCmd?.command == 'C') { + ctlPtx = cpx + (cpx - prevCmd!.points[2]); + ctlPty = cpy + (cpy - prevCmd!.points[3]); + } + points.push(ctlPtx, ctlPty, cpx + p.shift()!, cpy + p.shift()!); + cpx += p.shift()!; + cpy += p.shift()!; + cmd = 'C'; + points.push(cpx, cpy); + break; + case 'Q': + points.push(p.shift()!, p.shift()!); + cpx = p.shift()!; + cpy = p.shift()!; + points.push(cpx, cpy); + break; + case 'q': + points.push(cpx + p.shift()!, cpy + p.shift()!); + cpx += p.shift()!; + cpy += p.shift()!; + cmd = 'Q'; + points.push(cpx, cpy); + break; + case 'T': + ctlPtx = cpx; + ctlPty = cpy; + prevCmd = ca[ca.length - 1]; + if (prevCmd?.command == 'Q') { + ctlPtx = cpx + (cpx - prevCmd!.points[0]); + ctlPty = cpy + (cpy - prevCmd!.points[1]); + } + cpx = p.shift()!; + cpy = p.shift()!; + cmd = 'Q'; + points.push(ctlPtx, ctlPty, cpx, cpy); + break; + case 't': + ctlPtx = cpx; + ctlPty = cpy; + prevCmd = ca[ca.length - 1]; + if (prevCmd?.command == 'Q') { + ctlPtx = cpx + (cpx - prevCmd!.points[0]); + ctlPty = cpy + (cpy - prevCmd!.points[1]); + } + cpx += p.shift()!; + cpy += p.shift()!; + cmd = 'Q'; + points.push(ctlPtx, ctlPty, cpx, cpy); + break; + case 'A': + rx = p.shift()!; + ry = p.shift()!; + psi = p.shift()!; + fa = p.shift()!; + fs = p.shift()!; + x1 = cpx; + y1 = cpy; + cpx = p.shift()!; + cpy = p.shift()!; + cmd = 'A'; + points = this.convertEndpointToCenterParameterization( + x1, + y1, + cpx, + cpy, + fa, + fs, + rx, + ry, + psi + ); + break; + case 'a': + rx = p.shift()!; + ry = p.shift()!; + psi = p.shift()!; + fa = p.shift()!; + fs = p.shift()!; + x1 = cpx; + y1 = cpy; + cpx += p.shift()!; + cpy += p.shift()!; + cmd = 'A'; + points = this.convertEndpointToCenterParameterization( + x1, + y1, + cpx, + cpy, + fa, + fs, + rx, + ry, + psi + ); + break; + } + + let cReal = (cmd == '' ? c : cmd) as CommandType + ca.push({ + command: cReal, + points: points, + start: { + x: startX, + y: startY, + }, + pathLength: this.calcLength(startX, startY, cReal, points), + }); + + } + + if (c === 'z' || c === 'Z') { + ca.push({ + command: 'z', + points: [], + start: null, + pathLength: 0, + }); + } + } + + + this.pathLength = ca.length; + this.dataArray = ca; + const rect = this.getBoundRect() + this.width = rect.width; + this.height = rect.height; + this.x = rect.x + this.y = rect.y + return ca; + } + getPointOnCubicBezier(pct : number, P1x : number, P1y : number, P2x : number, P2y : number, P3x : number, P3y : number, P4x : number, P4y : number) { + function CB1(t : number) : number { + return t * t * t; + } + function CB2(t : number) : number { + return 3 * t * t * (1 - t); + } + function CB3(t : number) : number { + return 3 * t * (1 - t) * (1 - t); + } + function CB4(t : number) : number { + return (1 - t) * (1 - t) * (1 - t); + } + const x = P4x * CB1(pct) + P3x * CB2(pct) + P2x * CB3(pct) + P1x * CB4(pct); + const y = P4y * CB1(pct) + P3y * CB2(pct) + P2y * CB3(pct) + P1y * CB4(pct); + + return { + x: x, + y: y, + } as Vector2d; + } + override getBoundRect() : IShapeBoundRect { + let points : Array = []; + let _this = this; + this.dataArray.forEach(function (data) { + if (data.command === 'A') { + // Approximates by breaking curve into line segments + const start = data.points[4]; + // 4 = theta + const dTheta = data.points[5]; + // 5 = dTheta + const end = data.points[4] + dTheta; + let inc = Math.PI / 180.0; + // 1 degree resolution + if (Math.abs(start - end) < inc) { + // #ifdef APP-ANDROID + inc = Math.abs((start - end)).toDouble(); + // #endif + // #ifndef APP-ANDROID + inc = Math.abs(start - end); + // #endif + } + if (dTheta < 0) { + // clockwise + for (let t = start - inc; t > end; t -= inc) { + const point = _this.getPointOnEllipticalArc( + data.points[0], + data.points[1], + data.points[2], + data.points[3], + t, + 0 + ); + points.push(point.x, point.y); + + } + } else { + // counter-clockwise + for (let t = start + inc; t < end; t += inc) { + const point = _this.getPointOnEllipticalArc( + data.points[0], + data.points[1], + data.points[2], + data.points[3], + t, + 0 + ); + points.push(point.x, point.y); + } + } + } else if (data.command == 'C') { + // Approximates by breaking curve into 100 line segments + for (let t = 0.0; t <= 1; t += 0.01) { + if (data.start == null) continue; + const point = _this.getPointOnCubicBezier( + t, + data.start!.x, + data.start!.y, + data.points[0], + data.points[1], + data.points[2], + data.points[3], + data.points[4], + data.points[5] + ); + points.push(point.x, point.y); + } + } else { + // TODO: how can we calculate bezier curves better? + points = points.concat(data.points); + + } + }); + let minX = points[0]; + let maxX = points[0]; + let minY = points[1]; + let maxY = points[1]; + let x = 0; + let y = 0; + for (let i = 0; i < points.length / 2; i++) { + x = points[i * 2]; + y = points[i * 2 + 1]; + + // skip bad values + if (!isNaN(x)) { + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + } + if (!isNaN(y)) { + minY = Math.min(minY, y); + maxY = Math.max(maxY, y); + } + } + // include stroke padding if any + const pad = (this.stroke!='' ? this.strokeWidth/2 : 0); + return { + x: minX - pad, + y: minY - pad, + width: (maxX - minX) + pad*2, + height: (maxY - minY) + pad*2, + } as IShapeBoundRect; + } + getLineLength(x1 : number, y1 : number, x2 : number, y2 : number) : number { + return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + } + getPointOnQuadraticBezier(pct : number, P1x : number, P1y : number, P2x : number, P2y : number, P3x : number, P3y : number) : Vector2d { + function QB1(t : number) : number { + return t * t; + } + function QB2(t : number) : number { + return 2 * t * (1 - t); + } + function QB3(t : number) : number { + return (1 - t) * (1 - t); + } + const x = P3x * QB1(pct) + P2x * QB2(pct) + P1x * QB3(pct); + const y = P3y * QB1(pct) + P2y * QB2(pct) + P1y * QB3(pct); + + return { + x: x, + y: y, + } as Vector2d; + } + getPointAtLengthOfDataArray(lengths : number, dataArray : PathSegment[]) : Vector2d | null { + let points : number[] = [] + let i = 0 + let ii = dataArray.length; + let length = lengths + if (ii == 0) { + return null; + } + + while (i < ii && length > dataArray[i].pathLength) { + length -= dataArray[i].pathLength; + ++i; + } + + if (i === ii) { + points = dataArray[i - 1].points.slice(-2); + return { + x: points[0], + y: points[1], + } as Vector2d; + } + + if (length < 0.01) { + points = dataArray[i].points.slice(0, 2); + return { + x: points[0], + y: points[1], + } as Vector2d; + } + + const cp = dataArray[i]; + const p = cp.points; + let _this = this; + switch (cp.command) { + case 'L': + if (cp.start == null) return null; + return this.getPointOnLine(length, cp.start!.x, cp.start!.y, p[0], p[1]); + case 'C': + if (cp.start == null) return null; + return this.getPointOnCubicBezier( + t2length(length, _this.getPathLength(dataArray), (i) => { + return getCubicArcLength( + [cp.start!.x, p[0], p[2], p[4]], + [cp.start!.y, p[1], p[3], p[5]], + i + ); + }), + cp.start!.x, + cp.start!.y, + p[0], + p[1], + p[2], + p[3], + p[4], + p[5] + ); + case 'Q': + if (cp.start == null) return null; + return this.getPointOnQuadraticBezier( + t2length(length, _this.getPathLength(dataArray), (i) => { + return getQuadraticArcLength( + [cp.start!.x, p[0], p[2]], + [cp.start!.y, p[1], p[3]], + i + ); + }), + cp.start!.x, + cp.start!.y, + p[0], + p[1], + p[2], + p[3] + ); + case 'A': + var cx = p[0], + cy = p[1], + rx = p[2], + ry = p[3], + theta = p[4], + dTheta = p[5], + psi = p[6]; + theta += (dTheta * length) / cp.pathLength; + return _this.getPointOnEllipticalArc(cx, cy, rx, ry, theta, psi); + } + + return null; + } + getPathLength(dataArray : PathSegment[]) : number { + let pathLength = 0; + for (let i = 0; i < dataArray.length; ++i) { + pathLength += dataArray[i].pathLength; + } + return pathLength; + } + getPointOnLine( + dist : number, + P1x : number, + P1y : number, + P2x : number, + P2y : number, + fromXs : number | null = null, + fromYs : number | null = null + ) : Vector2d { + let fromX = fromXs == null ? P1x : fromXs!; + let fromY = fromYs == null ? P1y : fromYs!; + + const len = this.getLineLength(P1x, P1y, P2x, P2y); + if (len < 1e-10) { + return { x: P1x, y: P1y }; + } + if (P2x === P1x) { + // Vertical line + return { x: fromX, y: fromY + (P2y > P1y ? dist : -dist) }; + } + + const m = (P2y - P1y) / (P2x - P1x); + const run = Math.sqrt((dist * dist) / (1 + m * m)) * (P2x < P1x ? -1 : 1); + const rise = m * run; + + if (Math.abs(fromY - P1y - m * (fromX - P1x)) < 1e-10) { + return { x: fromX + run, y: fromY + rise }; + } + + const u = + ((fromX - P1x) * (P2x - P1x) + (fromY - P1y) * (P2y - P1y)) / (len * len); + const ix = P1x + u * (P2x - P1x); + const iy = P1y + u * (P2y - P1y); + const pRise = this.getLineLength(fromX, fromY, ix, iy); + const pRun = Math.sqrt(dist * dist - pRise * pRise); + const adjustedRun = + Math.sqrt((pRun * pRun) / (1 + m * m)) * (P2x < P1x ? -1 : 1); + const adjustedRise = m * adjustedRun; + + return { x: ix + adjustedRun, y: iy + adjustedRise } as Vector2d; + + } + calcLength(x : number, y : number, cmd : CommandType, points : number[]) { + let len = 0; + let p1 = { x: 0, y: 0 } as Vector2d; + let p2 = { x: 0, y: 0 } as Vector2d; + let t = 0; + // #ifdef APP|WEB + let path = this.path as Path2D; + // #endif + // #ifdef MP + let path = this.path; + // #endif + switch (cmd) { + case 'L': + return this.getLineLength(x, y, points[0], points[1]); + case 'C': + return getCubicArcLength( + [x, points[0], points[2], points[4]], + [y, points[1], points[3], points[5]], + 1 + ); + case 'Q': + return getQuadraticArcLength( + [x, points[0], points[2]], + [y, points[1], points[3]], + 1 + ); + case 'A': + len = 0.0; + var start = points[4]; + + var dTheta = points[5]; + + var end = points[4] + dTheta; + var inc = Math.PI / 180.0; + + if (Math.abs(start - end) < inc) { + // #ifdef APP-ANDROID + inc = Math.abs(start - end).toDouble() + // #endif + // #ifndef APP-ANDROID + inc = Math.abs(start - end); + // #endif + } + p1 = this.getPointOnEllipticalArc( + points[0], + points[1], + points[2], + points[3], + start, + 0 + ); + if (dTheta < 0) { + // clockwise + for (t = start - inc; t > end; t -= inc) { + p2 = this.getPointOnEllipticalArc( + points[0], + points[1], + points[2], + points[3], + t, + 0 + ); + len += this.getLineLength(p1.x, p1.y, p2.x, p2.y); + p1 = p2; + } + } else { + // counter-clockwise + for (t = start + inc; t < end; t += inc) { + p2 = this.getPointOnEllipticalArc( + points[0], + points[1], + points[2], + points[3], + t, + 0 + ); + len += this.getLineLength(p1.x, p1.y, p2.x, p2.y); + p1 = p2; + } + } + p2 = this.getPointOnEllipticalArc( + points[0], + points[1], + points[2], + points[3], + end, + 0 + ); + len += this.getLineLength(p1.x, p1.y, p2.x, p2.y); + + return len; + } + + return 0; + } + + getPointOnEllipticalArc( + cx : number, + cy : number, + rx : number, + ry : number, + theta : number, + psi : number + ) : Vector2d { + const cosPsi = Math.cos(psi), + sinPsi = Math.sin(psi); + const pt = { + x: rx * Math.cos(theta), + y: ry * Math.sin(theta), + } as Vector2d; + return { + x: cx + (pt.x * cosPsi - pt.y * sinPsi), + y: cy + (pt.x * sinPsi + pt.y * cosPsi), + } as Vector2d; + } + override draw(ctx : CanvasRenderingContext2D) : void { + super.draw(ctx); + // #ifdef APP|WEB + let pathObj = this.path as Path2D; + // #endif + // #ifdef MP + let pathObj = this.path; + // #endif + + + const ca = this.dataArray; + + ctx.beginPath(); + + for (let n = 0; n < ca.length; n++) { + const c = ca[n].command.toUpperCase(); + const p = ca[n].points; + switch (c) { + case 'L': + ctx.lineTo(p[0], p[1]); + break; + case 'M': + ctx.moveTo(p[0], p[1]); + break; + case 'C': + ctx.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]); + break; + case 'Q': + ctx.quadraticCurveTo(p[0], p[1], p[2], p[3]); + break; + case 'A': + var cx = p[0], + cy = p[1], + rx = p[2], + ry = p[3], + theta = p[4], + dTheta = p[5], + psi = p[6], + fs = p[7]; + + var r = rx > ry ? rx : ry; + var scaleX = rx > ry ? 1 : rx / ry; + var scaleY = rx > ry ? ry / rx : 1; + + ctx.translate(cx, cy); + ctx.rotate(psi); + ctx.scale(scaleX, scaleY); + ctx.arc(0, 0, Math.abs(r), theta, theta + dTheta, 1 - fs == 1); + ctx.scale(1 / scaleX, 1 / scaleY); + ctx.rotate(-psi); + ctx.translate(-cx, -cy); + + break; + case 'Z': + break; + } + } + + + + if (this.fill != '') { + ctx.fill(); + ctx.closePath(); + } + if (this.stroke != '') { + ctx.stroke(); + } + + ctx.restore() + } + + override isPointInPath(x : number, y : number, shapeId : string) : boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + const rect = this.getBoundRect() + const realX = x - (this.offsetX) - this.x; + const realY = y - (this.offsetY) - this.y; + + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + const dx = realX - centerX; + const dy = realY - centerY; + const rotatedX = centerX + dx * cos - dy * sin; + const rotatedY = centerY + dx * sin + dy * cos; + return rotatedX >= 0 && rotatedX <= rect.width* this.scaleX && rotatedY >= 0 && rotatedY <= rect.height* this.scaleY; + } + let isInRect = realX >= 0 && realX <= rect.width* this.scaleX && realY >= 0 && realY <= rect.height* this.scaleY; + + return isInRect + } + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/qrcode.uts b/uni_modules/tmx-ui/core/canvas/lib/qrcode.uts new file mode 100644 index 0000000..0065a53 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/qrcode.uts @@ -0,0 +1,105 @@ +import { Shape } from './shape.uts'; +import { IShapeBoundRect, IShapeOptional } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +import { generateFrame } from "./qrcode/qrcode.uts" +export class IQrcode extends Shape { + override type = 'IQrcode' + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + } + + override getBoundRect() : IShapeBoundRect { + const pad = (this.stroke!='' ? this.strokeWidth/2 : 0); + return { + x: this.x - pad, + y: this.y - pad, + width: this.width + pad*2, + height: this.height + pad*2 + } as IShapeBoundRect; + } + + setRadius(value : number) : IQrcode { + this.radius = value; + this.needsUpdate = true; + return this; + } + + // 根据新高度调整矩形,以左上角 (x,y) 为起点 + override setHeight(value : number) : Shape { + const originalY = this.y; + if (value >= 0) { + this.y = originalY; + this.height = value; + } else { + this.y = originalY + value; // value 为负,向上扩展 + this.height = Math.abs(value); + } + this.needsUpdate = true; + return this; + } + + // 根据新宽度调整矩形,以左上角 (x,y) 为起点 + override setWidth(value : number) : Shape { + const originalX = this.x; + if (value >= 0) { + this.x = originalX; + this.width = value; + } else { + this.x = originalX + value; // value 为负,向左扩展 + this.width = Math.abs(value); + } + this.needsUpdate = true; + return this; + } + + // 设置二维码图片图片。 + setQrcodeLabel(text:string){ + this.qrcodeText = text; + this.needsUpdate = true; + } + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + + ctx.beginPath(); + if (this.radius > 0) { + let radiuss = Math.min(this.radius, this.width / 2, this.height / 2); + const radius = Math.max(radiuss, 0) + ctx.moveTo(this.x + radius, this.y); + ctx.lineTo(this.x + this.width - radius, this.y); + ctx.arcTo(this.x + this.width, this.y, this.x + this.width, this.y + radius, radius); + ctx.lineTo(this.x + this.width, this.y + this.height - radius); + ctx.arcTo(this.x + this.width, this.y + this.height, this.x + this.width - radius, this.y + this.height, radius); + ctx.lineTo(this.x + radius, this.y + this.height); + ctx.arcTo(this.x, this.y + this.height, this.x, this.y + this.height - radius, radius); + ctx.lineTo(this.x, this.y + radius); + ctx.arcTo(this.x, this.y, this.x + radius, this.y, radius); + } else { + ctx.beginPath(); + ctx.rect(this.x, this.y, this.width, this.height); + } + ctx.closePath(); + if (this.fill != "") { + ctx.fill(); + } + if (this.stroke != "") { + ctx.stroke(); + } + + let fo = generateFrame(this.qrcodeText, "H") + let points = fo.frameBuffer + let width = fo.width + let px = this.width / width + let borderWidth = 0 + for (let i = 0; i < width; i++) { + for (let j = 0; j < width; j++) { + if (points[j * width + i] > 0) { + ctx.fillStyle = this.foreground; + ctx.fillRect( borderWidth + px * i + this.x, borderWidth + px * j + this.y, px, px) + } + } + } + + ctx.restore() + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/qrcode/qrcode.uts b/uni_modules/tmx-ui/core/canvas/lib/qrcode/qrcode.uts new file mode 100644 index 0000000..30bd531 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/qrcode/qrcode.uts @@ -0,0 +1,1062 @@ +import { QrGenerateFrameResult } from '../../interface.uts'; +/** + * 二维码生成器 + * @author https://tmui.design + * @description 由tmui改进,并重写为uts版本,不得分发给其它人。 + * @version 1.0.0 + */ +const ALIGNMENT_DELTA = [ + 0, 11, 15, 19, 23, 27, 31, + 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, + 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28 +] as number[] + +// There are four elements per version. The first two indicate the number of blocks, then the +// data width, and finally the ECC width. +const ECC_BLOCKS = [ + 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, + 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28, + 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, + 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16, + 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, + 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, + 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26, + 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, + 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24, + 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, + 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, + 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28, + 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, + 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24, + 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, + 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30, + 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28, + 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28, + 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26, + 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28, + 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, + 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24, + 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30, + 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30, + 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30, + 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, + 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30, + 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30, + 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30, + 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30, + 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30, + 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30, + 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30, + 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30, + 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30, + 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30, + 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30, + 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30, + 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30, + 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30 +] as number[] + +// Map of human-readable ECC levels. +const ECC_LEVELS = new Map([ + ['L', 1], + ['M', 0], + ['Q', 3], + ['H', 2] +]) + + +// Final format bits with mask (level << 3 | mask). +const FINAL_FORMAT = [ + 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, /* L */ + 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, /* M */ + 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, /* Q */ + 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b /* H */ +] + +// Galois field exponent table. +const GALOIS_EXPONENT = [ + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, + 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, + 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, + 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, + 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, + 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, + 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, + 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, + 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, + 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, + 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, + 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, + 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, + 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, + 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, + 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00 +] + +// Galois field log table. +const GALOIS_LOG = [ + 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, + 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, + 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, + 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, + 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, + 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, + 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, + 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, + 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, + 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, + 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, + 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, + 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, + 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, + 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, + 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf +] + +// *Badness* coefficients. +const N1 = 3 +const N2 = 3 +const N3 = 40 +const N4 = 10 + +// Version pattern. +const VERSION_BLOCK = [ + 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532, + 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5, + 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69 +] + + +// Generate the encoded QR image for the string provided. +export function generateFrame(_str : string | null = null, ecc : string | null = null) : QrGenerateFrameResult { + let i = 0 + let t = 0 + let j = 0 + let k = 0 + let m = 0 + let v = 0 + let x = 0 + let y = 0 + let version = 0 + let str = _str == null ? '' : (_str) + let width = 0 + let eccLevel = ECC_LEVELS.get(ecc == null ? 'L' : (ecc))! + + + // Run lengths for badness. + var badBuffer = [] as number[] + + + // Data block. + var dataBlock = 0 + var eccBlock = 0 + var neccBlock1 = 0 + var neccBlock2 = 0 + // ECC buffer. + var eccBuffer = [] as number[] + + // Image buffer. + var frameBuffer = [] as number[] + + // Fixed part of the image. + var frameMask = [] as number[] + + // Generator polynomial. + var polynomial = [] as number[] + + // Data input buffer. + var stringBuffer = [] as number[] + + + // functions + + // Set bit to indicate cell in frame is immutable (symmetric around diagonal). + function setMask(_x : number, _y : number) { + let bit = 0 + let x = _x + let y = _y + + if (x > y) { + bit = x + x = y + y = bit + } + + bit = y + bit *= y + bit += y + bit >>= 1 + bit += x + + frameMask[bit] = 1 + } + + // Enter alignment pattern. Foreground colour to frame, background to mask. Frame will be merged + // with mask later. + function addAlignment(_x : number, _y : number) { + let i = 0 + let x = _x + let y = _y + + frameBuffer[x + width * y] = 1 + + for (i = -2; i < 2; i++) { + frameBuffer[(x + i) + width * (y - 2)] = 1 + frameBuffer[(x - 2) + width * (y + i + 1)] = 1 + frameBuffer[(x + 2) + width * (y + i)] = 1 + frameBuffer[(x + i + 1) + width * (y + 2)] = 1 + } + + for (i = 0; i < 2; i++) { + setMask(x - 1, y + i) + setMask(x + 1, y - i) + setMask(x - i, y - 1) + setMask(x + i, y + 1) + } + } + + // Exponentiation mod N. + function modN(_x : number) : number { + var x = _x + while (x >= 255) { + x -= 255 + x = (x >> 8) + (x & 255) + } + + return x + } + + // Calculate and append `ecc` data to the `data` block. If block is in the string buffer the + // indices to buffers are used. + function appendData(_data : number, _dataLength : number, _ecc : number, _eccLength : number) { + let bit = 0 + let i = 0 + let j = 0 + let data = _data + let dataLength = _dataLength + let ecc = _ecc + let eccLength = _eccLength + + + for (i = 0; i < eccLength; i++) { + stringBuffer[ecc + i] = 0 + } + + for (i = 0; i < dataLength; i++) { + bit = GALOIS_LOG[stringBuffer[data + i] ^ stringBuffer[ecc]] + + if (bit !== 255) { + for (j = 1; j < eccLength; j++) { + stringBuffer[ecc + j - 1] = stringBuffer[ecc + j] ^ + GALOIS_EXPONENT[modN(bit + polynomial[eccLength - j])] + } + } else { + for (j = ecc; j < ecc + eccLength; j++) { + stringBuffer[j] = stringBuffer[j + 1] + } + } + + stringBuffer[ecc + eccLength - 1] = bit == 255 ? 0 : + GALOIS_EXPONENT[modN(bit + polynomial[0])] + } + } + + // Check mask since symmetricals use half. + function isMasked(_x : number, _y : number) : boolean { + let bit = 0 + let x = _x + let y = _y + + + if (x > y) { + bit = x + x = y + y = bit + } + + bit = y + bit += y * y + bit >>= 1 + bit += x + return frameMask[bit] == 1 + } + + // Apply the selected mask out of the 8 options. + function applyMask(_mask : number) { + let x = 0; + let y = 0; + let r3x = 0; + let r3y = 0; + let mask = _mask; + + if (mask == 0) { + for (y = 0; y < width; y++) { + for (x = 0; x < width; x++) { + if (((x + y) & 1) == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + } + } + } + + + if (mask == 1) { + for (y = 0; y < width; y++) { + for (x = 0; x < width; x++) { + if ((y & 1) == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + } + } + } + + + if (mask == 2) { + for (y = 0; y < width; y++) { + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + if (r3x == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + } + } + + + if (mask == 3) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = r3y + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + if (r3x == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + + r3y++ + } + } + + if (mask == 4) { + for (y = 0; y < width; y++) { + r3y = ((y >> 1) & 1) + x = 0 + for (r3x = 0; x < width; x++) { + if (r3x == 3) { + r3x = 0 + } + + if (r3x == 0 && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + } + } + + + if (mask == 5) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + // 定义变量来存储中间结果 + let bitwiseAndResult = x & y & 1; // 计算 x, y 与 1 的按位与结果 + let notR3x = r3x == 0 ? 1 : 0; // 将 r3x 转换为数字,如果 r3x 是 0,则为 1,否则为 0 + let notR3y = r3y == 0 ? 1 : 0; // 将 r3y 转换为数字,如果 r3y 是 0,则为 1,否则为 0 + let orResult = notR3x | notR3y; // 计算 notR3x 和 notR3y 的按位或结果 + let notOrResult = orResult == 0 ? 1 : 0; // 取逻辑非,如果 orResult 是 0,则为 1,否则为 0 + + // 计算括号内的结果 + let bracketResult = bitwiseAndResult + notOrResult; // 将两个数字相加 + + // 计算最终结果 + let finalResult = bracketResult == 0 ? true : false; // 如果 bracketResult 是 0,则为 1,否则为 + + // !((x & y & 1) + !(!r3x | !r3y)) + if (finalResult && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + + r3x++ + } + r3y++ + } + } + + + if (mask == 6) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + // 定义变量来存储中间结果 + let bitwiseAndResult = x & y & 1; // 计算 x, y 与 1 的按位与结果 + let r3xEqualsR3y = r3x === r3y; // 检查 r3x 是否等于 r3y + let r3xAndResult = r3x > 0 && r3xEqualsR3y; // 计算 r3x 与 r3xEqualsR3y 的逻辑与结果 + + // 将逻辑与结果转换为数字(true 转换为 1,false 转换为 0) + let r3xAndResultAsNumber = r3xAndResult ? 1 : 0; + + // 计算括号内的加法结果 + let additionResult = bitwiseAndResult + r3xAndResultAsNumber; + + // 计算加法结果与 1 的按位与 + let bitwiseAndWithOne = additionResult & 1; + + // 计算最终结果,即对按位与结果取逻辑非 + let finalResult = bitwiseAndWithOne == 0 ? true : false; + + // !(((x & y & 1) + (r3x && (r3x == r3y))) & 1) + if (finalResult && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + + r3x++ + } + r3y++ + } + } + + + if (mask == 7) { + r3y = 0 + for (y = 0; y < width; y++) { + if (r3y == 3) r3y = 0 + r3x = 0 + for (x = 0; x < width; x++) { + if (r3x == 3) r3x = 0 + + // 定义变量来存储中间结果 + let r3xEqualsR3y = r3x === r3y; // 检查 r3x 是否等于 r3y + let r3xAndResult = r3x > 0 && r3xEqualsR3y; // 计算 r3x 与 r3xEqualsR3y 的逻辑与结果 + + // 将逻辑与结果转换为数字(true 转换为 1,false 转换为 0) + let r3xAndResultAsNumber = r3xAndResult ? 1 : 0; + + // 计算 x 和 y 的和 + let sumOfXAndY = x + y; + + // 计算 x 和 y 之和与 1 的按位与结果 + let bitwiseAndWithOne = sumOfXAndY & 1; + + // 计算括号内的加法结果 + let additionResult = r3xAndResultAsNumber + bitwiseAndWithOne; + + // 计算加法结果与 1 的按位与 + let bitwiseAndOfAddition = additionResult & 1; + + // 计算最终结果,即对按位与结果取逻辑非 + let finalResult = bitwiseAndOfAddition === 0 ? true : false; + + // !(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) + if (finalResult && !isMasked(x, y)) { + frameBuffer[x + y * width] ^= 1 + } + r3x++ + } + + r3y++ + } + } + + + + } + + // Using the table for the length of each run, calculate the amount of bad image. Long runs or + // those that look like finders are called twice once for X and Y. + function getBadRuns(_length : number) : number { + let badRuns = 0 + let i = 0 + let length = _length + + for (i = 0; i <= length; i++) { + if (badBuffer[i] >= 5) { + badRuns += N1 + badBuffer[i] - 5 + } + } + + // FBFFFBF as in finder. + for (i = 3; i < length - 1; i += 2) { + if (badBuffer[i - 2] == badBuffer[i + 2] && + badBuffer[i + 2] == badBuffer[i - 1] && + badBuffer[i - 1] == badBuffer[i + 1] && + badBuffer[i - 1] * 3 == badBuffer[i] && + // Background around the foreground pattern? Not part of the specs. + (badBuffer[i - 3] == 0 || i + 3 > length || + badBuffer[i - 3] * 3 >= badBuffer[i] * 4 || + badBuffer[i + 3] * 3 >= badBuffer[i] * 4)) { + badRuns += N3 + } + } + + return badRuns + } + + // Calculate how bad the masked image is (e.g. blocks, imbalance, runs, or finders). + function checkBadness() { + let b = 0 + let b1 = 0 + let bad = 0 + let big = 0 + let bw = 0 + let count = 0 + let h = 0 + let x = 0 + let y = 0 + + + // Blocks of same colour. + for (y = 0; y < width - 1; y++) { + for (x = 0; x < width - 1; x++) { + // All foreground colour. + if ((frameBuffer[x + width * y] > 0 && + frameBuffer[(x + 1) + width * y] > 0 && + frameBuffer[x + width * (y + 1)] > 0 && + frameBuffer[(x + 1) + width * (y + 1)] > 0) || + // All background colour. + !(frameBuffer[x + width * y] > 0 || + frameBuffer[(x + 1) + width * y] > 0 || + frameBuffer[x + width * (y + 1)] > 0 || + frameBuffer[(x + 1) + width * (y + 1)] > 0)) { + bad += N2 + } + } + } + + for (y = 0; y < width; y++) { + badBuffer.push(0) + } + for (y = 0; y < width; y++) { + badBuffer[0] = 0 + h = 0 + b = 0 + for (x = 0; x < width; x++) { + b1 = frameBuffer[x + width * y] + if (b1 == b) { + badBuffer[h]++ + } else { + badBuffer[++h] = 1 + } + + b = b1 + bw += b > 0 ? 1 : -1 + } + + bad += getBadRuns(h) + } + + if (bw < 0) bw = -bw + + big = bw + big += big << 2 + big <<= 1 + + while (big > width * width) { + big -= width * width + count++ + } + + bad += count * N4 + + // Y runs. + for (x = 0; x < width; x++) { + badBuffer[0] = 0 + h = 0 + b = 0 + for (y = 0; y < width; y++) { + b1 = frameBuffer[x + width * y] + if (b1 == b) { + badBuffer[h]++ + } else { + badBuffer[++h] = 1 + } + + b = b1 + } + + bad += getBadRuns(h) + } + + return bad + } + function toUtf8(str : string) : string { + let out = '' + let i = 0 + let len = 0 + let c = 0 + len = str.length; + for (i = 0; i < len; i++) { + c = str.charCodeAt(i)!; + if ((c >= 0x0001) && (c <= 0x007F)) { + out += str.charAt(i); + } else if (c > 0x07FF) { + out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); + out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); + out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); + } else { + out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); + out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); + } + } + return out; + } + + //end functions + + // Find the smallest version that fits the string. + str = toUtf8(str) + t = str.length + + + version = 0 + + do { + version++ + k = (eccLevel - 1) * 4 + (version - 1) * 16 + neccBlock1 = ECC_BLOCKS[k++] + neccBlock2 = ECC_BLOCKS[k++] + dataBlock = ECC_BLOCKS[k++] + eccBlock = ECC_BLOCKS[k] + + k = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 - 3 + (version <= 9?1:0) + + if (t <= k) break + } while (version < 40) + + // FIXME: Ensure that it fits insted of being truncated. + width = 17 + 4 * version + + // Allocate, clear and setup data structures. + v = dataBlock + (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2 + + for (t = 0; t < v; t++) { + eccBuffer.push(0) + } + + // -------------------------------------------------------------------------------------- + let stringBufferLength = str.length + let stringBack = str.slice(0) + + + + // -------------------------------------------------------------------------------------- + + for (t = 0; t < width * width; t++) { + frameBuffer.push(0) + } + + for (t = 0; t < (width * (width + 1) + 1) / 2; t++) { + frameMask.push(0) + } + + // Insert finders: Foreground colour to frame and background to mask. + for (t = 0; t < 3; t++) { + k=0 + y=0 + if (t == 1) k = (width - 7) + if (t == 2) y = (width - 7) + + frameBuffer[(y + 3) + width * (k + 3)] = 1 + + for (x = 0; x < 6; x++) { + frameBuffer[(y + x) + width * k] = 1 + frameBuffer[y + width * (k + x + 1)] = 1 + frameBuffer[(y + 6) + width * (k + x)] = 1 + frameBuffer[(y + x + 1) + width * (k + 6)] = 1 + } + + for (x = 1; x < 5; x++) { + setMask(y + x, k + 1) + setMask(y + 1, k + x + 1) + setMask(y + 5, k + x) + setMask(y + x + 1, k + 5) + } + + for (x = 2; x < 4; x++) { + frameBuffer[(y + x) + width * (k + 2)] = 1 + frameBuffer[(y + 2) + width * (k + x + 1)] = 1 + frameBuffer[(y + 4) + width * (k + x)] = 1 + frameBuffer[(y + x + 1) + width * (k + 4)] = 1 + } + } + + // Alignment blocks. + if (version > 1) { + t = ALIGNMENT_DELTA[version] + y = width - 7 + + for (; ;) { + x = width - 7 + + while (x > t - 3) { + addAlignment(x, y) + + if (x < t) break + + x -= t + } + + if (y <= t + 9) break + + y -= t + + addAlignment(6, y) + addAlignment(y, 6) + } + } + + // Single foreground cell. + frameBuffer[8 + width * (width - 8)] = 1 + + // Timing gap (mask only). + for (y = 0; y < 7; y++) { + setMask(7, y) + setMask(width - 8, y) + setMask(7, y + width - 7) + } + + for (x = 0; x < 8; x++) { + setMask(x, 7) + setMask(x + width - 8, 7) + setMask(x, width - 8) + } + + // Reserve mask, format area. + for (x = 0; x < 9; x++) { + setMask(x, 8) + } + + for (x = 0; x < 8; x++) { + setMask(x + width - 8, 8) + setMask(8, x) + } + + for (y = 0; y < 7; y++) { + setMask(8, y + width - 7) + } + + // Timing row/column. + for (x = 0; x < width - 14; x++) { + if ((x & 1)>0) { + setMask(8 + x, 6) + setMask(6, 8 + x) + } else { + frameBuffer[(8 + x) + width * 6] = 1 + frameBuffer[6 + width * (8 + x)] = 1 + } + } + + // Version block. + if (version > 6) { + t = VERSION_BLOCK[version - 7] + k = 17 + + for (x = 0; x < 6; x++) { + for (y = 0; y < 3; y++) { + if ((1 & (k > 11 ? version >> (k - 12) : t >> k))>0) { + frameBuffer[(5 - x) + width * (2 - y + width - 11)] = 1 + frameBuffer[(2 - y + width - 11) + width * (5 - x)] = 1 + } else { + setMask(5 - x, 2 - y + width - 11) + setMask(2 - y + width - 11, 5 - x) + } + k-- + } + } + } + + // Sync mask bits. Only set above for background cells, so now add the foreground. + for (y = 0; y < width; y++) { + for (x = 0; x <= y; x++) { + if (frameBuffer[x + width * y]>0) { + setMask(x, y) + } + } + } + + // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanum, or kanji + // not supported). + v = stringBufferLength + + // stringBuffer = str.slice(0) + + // String to array. + for (i = 0; i < v; i++) { + // #ifdef APP-ANDROID + eccBuffer[i.toInt()] = stringBack.charCodeAt(i)! + // #endif + // #ifndef APP-ANDROID + eccBuffer[i] = stringBack.charCodeAt(i)! + // #endif + } + + //++++++++++++++++++++===================== + + stringBuffer = eccBuffer.slice(0) + + // Calculate max string length. + x = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 + + if (v >= x - 2) { + v = x - 2 + + if (version > 9) v-- + } + + + // Shift and re-pack to insert length prefix. + i = v + + if (version > 9) { + stringBuffer[i + 2] = 0 + stringBuffer[i + 3] = 0 + + while ((i--)>0) { + t = stringBuffer[i] + + stringBuffer[i + 3] |= 255 & (t << 4) + stringBuffer[i + 2] = t >> 4 + } + + stringBuffer[2] |= 255 & (v << 4) + stringBuffer[1] = v >> 4 + stringBuffer[0] = 0x40 | (v >> 12) + } else { + stringBuffer[i + 1] = 0 + stringBuffer[i + 2] = 0 + + while ((i--)>0) { + t = stringBuffer[i] + + stringBuffer[i + 2] |= 255 & (t << 4) + stringBuffer[i + 1] = t >> 4 + } + + stringBuffer[1] |= 255 & (v << 4) + stringBuffer[0] = 0x40 | (v >> 4) + } + + + // Fill to end with pad pattern. + i = v + 3 - (version < 10?1:0) + + while (i < x) { + stringBuffer[i++] = 0xec + stringBuffer[i++] = 0x11 + } + + // Calculate generator polynomial. + for (i = 0; i <= eccBlock; i++) { + polynomial.push(0) + } + polynomial[0] = 1 + + for (i = 0; i < eccBlock; i++) { + polynomial[i + 1] = 1 + + for (j = i; j > 0; j--) { + polynomial[j] = polynomial[j]>0 ? polynomial[j - 1] ^ + GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[j]] + i)] : polynomial[j - 1] + } + + polynomial[0] = GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[0]] + i)] + } + + + + // Use logs for generator polynomial to save calculation step. + for (i = 0; i < eccBlock; i++) { + polynomial[i] = GALOIS_LOG[polynomial[i]] + } + + + // Append ECC to data buffer. + k = x + y = 0 + + for (i = 0; i < neccBlock1; i++) { + appendData(y, dataBlock, k, eccBlock) + + y += dataBlock + k += eccBlock + } + + for (i = 0; i < neccBlock2; i++) { + appendData(y, dataBlock + 1, k, eccBlock) + + y += dataBlock + 1 + k += eccBlock + } + + // Interleave blocks. + y = 0 + + for (i = 0; i < dataBlock; i++) { + for (j = 0; j < neccBlock1; j++) { + eccBuffer[y++] = stringBuffer[i + j * dataBlock] + } + + for (j = 0; j < neccBlock2; j++) { + eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))] + } + } + + for (j = 0; j < neccBlock2; j++) { + eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))] + } + + for (i = 0; i < eccBlock; i++) { + for (j = 0; j < neccBlock1 + neccBlock2; j++) { + eccBuffer[y++] = stringBuffer[x + i + j * eccBlock] + } + } + + stringBuffer = eccBuffer + + // Pack bits into frame avoiding masked area. + x = width - 1 + y = width - 1 + k = 1 + v = 1 + + + + // inteleaved data and ECC codes. + m = (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2 + + for (i = 0; i < m; i++) { + t = stringBuffer[i] + + for (j = 0; j < 8; j++) { + if ((0x80 & t)>0) { + frameBuffer[x + width * y] = 1 + } + + // Find next fill position. + do { + if (v>0) { + x-- + } else { + x++ + + if (k>0) { + if (y !== 0) { + y-- + } else { + x -= 2 + k = k==0?1:0 + + if (x == 6) { + x-- + y = 9 + } + } + } else { + if (y !== width - 1) { + y++ + } else { + x -= 2 + k = k==0?1:0 + + if (x == 6) { + x-- + y -= 8 + } + } + } + } + + v = v==0?1:0 + } while (isMasked(x, y)) + t <<= 1 + } + } + + // Save pre-mask copy of frame. + stringBuffer = frameBuffer.slice(0) + + + + + + + t = 0 + y = 30000 + + // Using `for` instead of `while` since in original Arduino code if an early mask was *good + // enough* it wouldn't try for a better one since they get more complex and take longer. + for (k = 0; k < 8; k++) { + // Returns foreground-background imbalance. + applyMask(k) + + x = checkBadness() + + // Is current mask better than previous best? + if (x < y) { + y = x + t = k + } + + // Don't increment `i` to a void redoing mask. + if (t == 7) break + + // Reset for next pass. + frameBuffer = stringBuffer.slice(0) + } + + // Redo best mask as none were *good enough* (i.e. last wasn't `t`). + if (t !== k) { + applyMask(t) + } + + // Add in final mask/ECC level bytes. + y = FINAL_FORMAT[t + ((eccLevel - 1) << 3)] + + // Low byte. + for (k = 0; k < 8; k++) { + if ((y & 1)>0) { + frameBuffer[(width - 1 - k) + width * 8] = 1 + + if (k < 6) { + frameBuffer[8 + width * k] = 1 + } else { + frameBuffer[8 + width * (k + 1)] = 1 + } + } + y >>= 1 + } + + // High byte. + for (k = 0; k < 7; k++) { + if ((y & 1)>0) { + frameBuffer[8 + width * (width - 7 + k)] = 1 + + if (k>0) { + frameBuffer[(6 - k) + width * 8] = 1 + } else { + frameBuffer[7 + width * 8] = 1 + } + } + y >>= 1 + } + + // Finally, return the image data. + return { + frameBuffer: frameBuffer + , width: width + } as QrGenerateFrameResult +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/rect.uts b/uni_modules/tmx-ui/core/canvas/lib/rect.uts new file mode 100644 index 0000000..2e56ff7 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/rect.uts @@ -0,0 +1,86 @@ +import { Shape } from './shape.uts'; +import { CanvasRotateCenter, IShapeBoundRect, IShapeOptional, ShapeSetAttrType } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +export class IRect extends Shape { + override type = 'IRect' + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + } + + override getBoundRect() : IShapeBoundRect { + const pad = (this.stroke!='' ? this.strokeWidth/2 : 0); + return { + x: this.x - pad, + y: this.y - pad, + width: this.width + pad*2, + height: this.height + pad*2 + } as IShapeBoundRect; + } + + setRadius(value : number) : IRect { + this.radius = value; + this.needsUpdate = true; + return this; + } + + // 根据新高度调整矩形,以左上角 (x,y) 为起点 + override setHeight(value : number) : Shape { + const originalY = this.y; + if (value >= 0) { + this.y = originalY; + this.height = value; + } else { + this.y = originalY + value; // value 为负,向上扩展 + this.height = Math.abs(value); + } + this.needsUpdate = true; + return this; + } + + // 根据新宽度调整矩形,以左上角 (x,y) 为起点 + override setWidth(value : number) : Shape { + const originalX = this.x; + if (value >= 0) { + this.x = originalX; + this.width = value; + } else { + this.x = originalX + value; // value 为负,向左扩展 + this.width = Math.abs(value); + } + this.needsUpdate = true; + return this; + } + + + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + + ctx.beginPath(); + if (this.radius > 0) { + let radiuss = Math.min(this.radius, this.width / 2, this.height / 2); + const radius = Math.max(radiuss, 0) + ctx.moveTo(this.x + radius, this.y); + ctx.lineTo(this.x + this.width - radius, this.y); + ctx.arcTo(this.x + this.width, this.y, this.x + this.width, this.y + radius, radius); + ctx.lineTo(this.x + this.width, this.y + this.height - radius); + ctx.arcTo(this.x + this.width, this.y + this.height, this.x + this.width - radius, this.y + this.height, radius); + ctx.lineTo(this.x + radius, this.y + this.height); + ctx.arcTo(this.x, this.y + this.height, this.x, this.y + this.height - radius, radius); + ctx.lineTo(this.x, this.y + radius); + ctx.arcTo(this.x, this.y, this.x + radius, this.y, radius); + } else { + ctx.beginPath(); + ctx.rect(this.x, this.y, this.width, this.height); + } + ctx.closePath(); + if (this.fill != "") { + ctx.fill(); + } + if (this.stroke != "") { + ctx.stroke(); + } + ctx.restore() + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/regularPolygon.uts b/uni_modules/tmx-ui/core/canvas/lib/regularPolygon.uts new file mode 100644 index 0000000..21f3603 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/regularPolygon.uts @@ -0,0 +1,189 @@ +import { Shape } from './shape.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +import { IShapeBoundRect, IShapeOptional, IShapeVector2d } from '../interface.uts'; + +export class IRegularPolygon extends Shape { + override type = 'IRegularPolygon' + constructor(config : IShapeOptional, canvas : ICanvas) { + super(config, canvas); + this.radius = config?.radius ?? 30; + this.sides = config?.sides ?? 3; + } + + setRadius(value : number) : IRegularPolygon { + this.radius = value; + this.needsUpdate = true; + return this; + } + + setSides(value : number) : IRegularPolygon { + this.sides = value; + this.needsUpdate = true; + return this; + } + + override getBoundRect() : IShapeBoundRect { + const points = this.getPointsVec(); + let minX = points[0].x; + let maxX = points[0].x; + let minY = points[0].y; + let maxY = points[0].y; + points.forEach((point) => { + minX = Math.min(minX, point.x); + maxX = Math.max(maxX, point.x); + minY = Math.min(minY, point.y); + maxY = Math.max(maxY, point.y); + }); + let borderWidth = (this.stroke!='' ? this.strokeWidth/2 : 0) + return { + x: minX-borderWidth, + y: minY-borderWidth, + width: maxX - minX+borderWidth*2, + height: maxY - minY+borderWidth*2, + } as IShapeBoundRect; + + } + + override setWidth(value : number) : IRegularPolygon { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + override setHeight(value : number) : IRegularPolygon { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + private getPointsVec() : IShapeVector2d[] { + const sides = this.sides as number; + const radius = this.radius; + const points : IShapeVector2d[] = []; + for (let n = 0; n < sides; n++) { + points.push({ + x: this.x + radius * Math.sin((n * 2 * Math.PI) / sides), + y: this.y + (-1 * radius * Math.cos((n * 2 * Math.PI) / sides)), + }); + } + return points; + } + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + ctx.beginPath(); + const points = this.getPointsVec(); + ctx.moveTo(points[0].x, points[0].y); + for (let n = 1; n < points.length; n++) { + ctx.lineTo(points[n].x, points[n].y); + } + ctx.closePath(); + if (this.fill != "") { + ctx.fill(); + } + if (this.stroke != "") { + ctx.stroke(); + } + ctx.restore(); + } + + override isPointInPath(x : number, y : number, shapeId : string) : boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + // 计算相对于图形原点的坐标 + let realX = x - this.offsetX - this.x; + let realY = y - this.offsetY - this.y; + + // 处理旋转 + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + realX = centerX + dx * cos - dy * sin; + realY = centerY + dx * sin + dy * cos; + } + + // 获取多边形的顶点 + const points = this.getPointsVec(); + const n = points.length; + let inside = false; + + // 使用射线法判断点是否在多边形内部 + for (let i = 0, j = n - 1; i < n; j = i++) { + const xi = points[i].x - this.x; + const yi = points[i].y - this.y; + const xj = points[j].x - this.x; + const yj = points[j].y - this.y; + + if (((yi > realY) != (yj > realY)) && + (realX < (xj - xi) * (realY - yi) / (yj - yi) + xi)) { + inside = !inside; + } + } + + // 如果有描边,检查点是否在描边范围内 + if (!inside && this.stroke != "") { + for (let i = 0, j = n - 1; i < n; j = i++) { + const xi = points[i].x - this.x; + const yi = points[i].y - this.y; + const xj = points[j].x - this.x; + const yj = points[j].y - this.y; + + // 计算点到线段的距离 + const dx = xj - xi; + const dy = yj - yi; + const len = Math.sqrt(dx * dx + dy * dy); + if (len > 0) { + const t = ((realX - xi) * dx + (realY - yi) * dy) / (len * len); + if (t >= 0 && t <= 1) { + const px = xi + t * dx; + const py = yi + t * dy; + const distance = Math.sqrt((realX - px) * (realX - px) + (realY - py) * (realY - py)); + if (distance <= this.strokeWidth / 2) { + return true; + } + } + } + } + } + + return inside; + } + + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/ring.uts b/uni_modules/tmx-ui/core/canvas/lib/ring.uts new file mode 100644 index 0000000..266002c --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/ring.uts @@ -0,0 +1,153 @@ +import { Shape } from './shape.uts'; +import { CanvasRotateCenter, ShapeSetAttrType, IShapeBoundRect, IShapeOptional } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; + + +export class IRing extends Shape { + override type = 'IRing' + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.width = this.outerRadius * 2 + this.height = this.outerRadius * 2 + } + + setInnerRadius(value : number) : IRing { + this.innerRadius = value; + this.needsUpdate = true; + return this; + } + setOuterRadius(value : number) : IRing { + this.outerRadius = value; + this.needsUpdate = true; + return this; + } + override getBoundRect() : IShapeBoundRect { + const r = Math.max(0, this.outerRadius); + const pad = (this.stroke != "" ? this.strokeWidth / 2 : 0); + const d = r * 2 + pad * 2; + return { + x: this.x - r - pad, + y: this.y - r - pad, + width: d, + height: d + } as IShapeBoundRect; + } + + override setWidth(value : number) : IRing { + this.height = value; + this.width = value; + this.outerRadius = value / 2 + this.needsUpdate = true; + return this; + } + + override setHeight(value : number) : IRing { + this.height = value; + this.width = value; + this.outerRadius = value / 2 + this.needsUpdate = true; + return this; + } + + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + ctx.beginPath(); + // 将角度转换为弧度 + const startRad = this.startAngle * Math.PI / 180; + const endRad = this.endAngle * Math.PI / 180; + // 绘制外圆弧 + ctx.arc(this.x, this.y, this.outerRadius, startRad, endRad, false); + // 绘制内圆弧(反方向) + ctx.arc(this.x, this.y, this.innerRadius, endRad, startRad, true); + ctx.closePath(); + if (this.fill != "") { + ctx.fill(); + + } + if (this.stroke != "") { + ctx.stroke(); + } + ctx.restore(); + } + + override isPointInPath(x : number, y : number, shapeId : string) : boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + // 计算点击位置相对于圆心的实际坐标 + let realX = x - this.offsetX - this.x; + let realY = y - this.offsetY - this.y; + + // 如果有旋转,需要将坐标转换回未旋转状态 + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + realX = centerX + dx * cos - dy * sin; + realY = centerY + dx * sin + dy * cos; + } + + // 计算点到圆心的距离 + const distance = Math.sqrt(realX * realX + realY * realY); + + // 考虑缩放因素 + const scaledInnerRadius = this.innerRadius * Math.min(this.scaleX, this.scaleY); + const scaledOuterRadius = this.outerRadius * Math.min(this.scaleX, this.scaleY); + + // 检查距离是否在内径和外径之间 + if (distance < scaledInnerRadius || distance > scaledOuterRadius) { + return false; + } + + // 计算点击位置的角度(弧度) + let angle = Math.atan2(realY, realX); + // 将角度转换为0-2π范围 + if (angle < 0) angle += 2 * Math.PI; + // 将角度转换为度数 + angle = angle * 180 / Math.PI; + + // 将起始角度和结束角度标准化到0-360度范围 + let start = this.startAngle % 360; + if (start < 0) start += 360; + let end = this.endAngle % 360; + if (end < 0) end += 360; + + // 处理跨越0度线的情况 + if (start <= end) { + return angle >= start && angle <= end; + } else { + return angle >= start || angle <= end; + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/sector.uts b/uni_modules/tmx-ui/core/canvas/lib/sector.uts new file mode 100644 index 0000000..4d7fc67 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/sector.uts @@ -0,0 +1,184 @@ +import { Shape } from './shape.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +import { IShapeBoundRect, IShapeOptional } from '../interface.uts'; + +export class ISector extends Shape { + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.radius = config?.radius ?? 30; + this.startAngle = config?.startAngle ?? 0; + this.endAngle = config?.endAngle ?? 90; + this.type = "ISector" + } + + setRadius(value : number) : ISector { + this.radius = value; + this.needsUpdate = true; + return this; + } + + override getBoundRect() : IShapeBoundRect { + // 与 IArc 相同的严谨包围盒逻辑:扇形需包含圆心 + const centerX = this.x; + const centerY = this.y; + const r = Math.max(0, this.radius); + const d2r = Math.PI / 180; + const normalize = (deg:number):number => { let a = deg % 360; if (a < 0) a += 360; return a; }; + let start = normalize(this.startAngle); + let end = normalize(this.endAngle); + if (end < start) end += 360; + const withinSweep = (deg:number):boolean => { let a = normalize(deg); if (a < start) a += 360; return a >= start && a <= end; }; + const candidatesX:number[] = [centerX]; + const candidatesY:number[] = [centerY]; + const sx = centerX + r * Math.cos(start * d2r); + const sy = centerY + r * Math.sin(start * d2r); + const ex = centerX + r * Math.cos(end * d2r); + const ey = centerY + r * Math.sin(end * d2r); + candidatesX.push(sx, ex); + candidatesY.push(sy, ey); + const extrema = [0, 90, 180, 270]; + for (const deg of extrema) { + if (withinSweep(deg)) { + const rad = deg * d2r; + candidatesX.push(centerX + r * Math.cos(rad)); + candidatesY.push(centerY + r * Math.sin(rad)); + } + } + let minX = candidatesX.length>0?candidatesX[0]:centerX; + let maxX = candidatesX.length>0?candidatesX[0]:centerX; + let minY = candidatesY.length>0?candidatesY[0]:centerY; + let maxY = candidatesY.length>0?candidatesY[0]:centerY; + for (let i=1;i maxX) maxX = vx; + } + } + for (let i=1;i maxY) maxY = vy; + } + } + const pad = (this.stroke != "" ? this.strokeWidth / 2 : 0); + minX -= pad; minY -= pad; maxX += pad; maxY += pad; + return { x: minX, y: minY, width: Math.max(0, maxX - minX), height: Math.max(0, maxY - minY) } as IShapeBoundRect; + } + + override setWidth(value : number) : ISector { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + override setHeight(value : number) : ISector { + this.height = value; + this.width = value; + this.radius = value / 2 + this.needsUpdate = true; + return this; + } + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + ctx.beginPath(); + // 将角度转换为弧度 + const startRad = this.startAngle * Math.PI / 180; + const endRad = this.endAngle * Math.PI / 180; + // 如果有填充色,先移动到圆心,绘制扇形 + if (this.fill !== "") { + ctx.moveTo(this.x, this.y); + } + // 绘制圆弧 + ctx.arc(this.x, this.y, this.radius, startRad, endRad, false); + // 如果有填充色,连接回圆心形成扇形 + if (this.fill != "") { + ctx.lineTo(this.x, this.y); + } + ctx.closePath(); + if (this.fill != "") { + ctx.fill(); + } + if (this.stroke != "") { + ctx.stroke(); + } + ctx.restore(); + } + + override isPointInPath(x: number, y: number, shapeId: string): boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + // 计算实际点击位置(考虑偏移量) + const realX = x - (this.offsetX) - this.x; + const realY = y - (this.offsetY) - this.y; + + // 如果有旋转,先进行反向旋转变换 + let finalX = realX; + let finalY = realY; + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + finalX = centerX + dx * cos - dy * sin; + finalY = centerY + dx * sin + dy * cos; + } + + // 计算点到圆心的距离 + const distance = Math.sqrt(finalX * finalX + finalY * finalY); + + // 如果点击位置超出半径范围,则不在扇形内 + if (distance > this.radius * this.scaleX) return false; + + // 计算点击位置的角度(弧度) + let angle = Math.atan2(finalY, finalX) * 180 / Math.PI; + // 将角度转换为0-360度范围 + angle = (angle + 360) % 360; + + // 将起始角度和结束角度标准化到0-360度范围 + let start = (this.startAngle + 360) % 360; + let end = (this.endAngle + 360) % 360; + + // 处理跨越0度线的情况 + if (end < start) { + return angle >= start || angle <= end; + } + + // 判断点击角度是否在扇形角度范围内 + return angle >= start && angle <= end; + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/shape.uts b/uni_modules/tmx-ui/core/canvas/lib/shape.uts new file mode 100644 index 0000000..0d24e52 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/shape.uts @@ -0,0 +1,857 @@ +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; +// import { Path2DShape } from '@/uni_modules/tmx-ui/core/canvas/lib/path2d.uts'; + +import { + IShape, IShapeVector2d, + ILineJoinType, ILineCapType, + IShapeOptional, IShapeBoundRect, ICanvasEvent, CanvasEventType, IEventShapeListener, IEventShape, CanvasRotateCenter, ShapeSetAttrType, ITextAlignType, ITextBaselineType +} from '../interface.uts'; +// #ifdef APP-ANDROID +import { IArc } from './arc.uts'; +import { ICircle } from './circle.uts'; +import { IEllipse } from './ellipse.uts'; +import { ImageShape } from './image.uts'; +import { ILine } from './line.uts'; +import { ILinePolygon } from './linePolygon.uts'; +import { Path2DShape } from './path2d.uts'; +import { IRect } from './rect.uts'; +import { IRegularPolygon } from './regularPolygon.uts'; +import { IRing } from './ring.uts'; +import { ISector } from './sector.uts'; +import { IStar } from './star.uts'; +import { IText } from './text.uts'; +// #endif + +type CloneCallActions = (el:Shape,index:number) => void +export class Shape implements IShape { + canvas : ICanvas + x : number = 0; + y : number = 0; + width : number = 0; + height : number = 0; + fill : string = ""; + stroke : string = ""; + strokeWidth : number = 0; + opacity : number = 1; + visible : boolean = true; + rotation : number = 0; + scaleX : number = 1; + scaleY : number = 1; + offsetX : number = 0; + offsetY : number = 0; + draggable : boolean = false; + draggableing : boolean = false; + // 元素之间上下重叠时,是否允许穿透冒泡逐层触发,默认不允许 + bubbleEvent = false; + toggleStatus = false; + + // 线条样式 + lineJoin : ILineJoinType = "round"; + lineDashOffset : number = 0; + lineDash : number[] = [] + lineCap : ILineCapType = "butt"; + + text : string = ""; + fontSize : number = 12; + fontFamily : string = "Arial"; + textAlign : 'left' | 'center' | 'right' = 'left'; + textBaseline : 'top' | 'middle' | 'bottom' = 'top'; + padding : number = 0; + lineHeight : number = 1.2; + + innerRadius : number = 10; + outerRadius : number = 20; + startAngle : number = 0; + endAngle : number = 360; + + src:string = ""; + + foreground:string = 'rgba(0,0,0,1)' + qrcodeText:string = 'TMUI4x Great' + + radius : number = 0; + + sides : number = 3; + + points : number[] = []; + //多边形线是否自动闭合 + closed : boolean = true; + tension : number = 0 + bezier : boolean = false; + + radiusX : number = 20; + radiusY : number = 80; + //星的角数量,默认5角星 + numPoints : number = 5 + + + pointStart : IShapeVector2d = { x: 0, y: 0 }; + pointEnd : IShapeVector2d = { x: 0, y: 0 }; + + clip : boolean = false; + zIndex : number = 0; + textBgColor : string = ''; + + + id : string = "shape-" + (Math.random()).toString(8).substring(4, 20) + type : string = '' + /** 旋转元素时的中心点,默认是topLeft左顶,center表示元素的中间 */ + rotateCenter : CanvasRotateCenter = "topLeft" + + + strokeGradient = [] as string[] + fillGradient = [] as string[] + + needsUpdate = false + private toggleListener = (status : boolean, target : any) => { } + private eventListeners : Map = new Map(); + + + drag : (eventName : CanvasEventType, parentEventDetail : ICanvasEvent) => void = (eventName : CanvasEventType, parentEventDetail : ICanvasEvent) => { + if (!this.draggable) return + this.x -= parentEventDetail.detail[0].moveLenX + this.y -= parentEventDetail.detail[0].moveLenY + + } + constructor(config : IShapeOptional, canvas : ICanvas) { + this.canvas = canvas + this.x = config?.x ?? this.x; + this.y = config?.y ?? this.y; + this.width = config?.width ?? this.width; + this.height = config?.height ?? this.height; + this.fill = config?.fill ?? this.fill; + this.stroke = config?.stroke ?? this.stroke; + this.strokeWidth = config?.strokeWidth ?? this.strokeWidth; + this.opacity = config?.opacity ?? this.opacity; + this.visible = config?.visible ?? this.visible; + this.rotation = config?.rotation ?? this.rotation; + this.scaleX = config?.scaleX ?? this.scaleX; + this.scaleY = config?.scaleY ?? this.scaleY; + this.offsetX = config?.offsetX ?? this.offsetX; + this.offsetY = config?.offsetY ?? this.offsetY; + this.draggable = config?.draggable ?? this.draggable; + this.bubbleEvent = config?.bubbleEvent ?? this.bubbleEvent; + this.rotateCenter = config?.rotateCenter ?? this.rotateCenter; + + this.lineJoin = config?.lineJoin ?? this.lineJoin; + this.lineDashOffset = config?.lineDashOffset ?? this.lineDashOffset; + this.lineDash = config?.lineDash ?? this.lineDash; + this.lineCap = config?.lineCap ?? this.lineCap; + + this.text = config?.text ?? this.text; + this.fontSize = config?.fontSize ?? this.fontSize; + this.fontFamily = config?.fontFamily ?? this.fontFamily; + this.textAlign = config?.textAlign ?? this.textAlign; + this.textBaseline = config?.textBaseline ?? this.textBaseline; + this.padding = config?.padding ?? this.padding; + this.lineHeight = config?.lineHeight ?? this.lineHeight; + + this.innerRadius = config?.innerRadius ?? this.innerRadius; + this.outerRadius = config?.outerRadius ?? this.outerRadius; + this.startAngle = config?.startAngle ?? this.startAngle; + this.endAngle = config?.endAngle ?? this.endAngle; + + this.radius = config?.radius ?? this.radius; + this.sides = config?.sides ?? this.sides; + + this.points = config?.points ?? this.points; + this.closed = config?.closed ?? this.closed; + + this.tension = config?.tension ?? this.tension; + this.bezier = config?.bezier ?? this.bezier; + + this.src = config?.src ?? this.src; + + this.foreground = config?.foreground ?? this.foreground; + this.qrcodeText = config?.qrcodeText ?? this.qrcodeText; + + + this.radiusX = config?.radiusX ?? this.radiusX; + this.radiusY = config?.radiusY ?? this.radiusY; + this.numPoints = config?.numPoints ?? this.numPoints; + this.pointStart = config?.pointStart ?? this.pointStart; + this.pointEnd = config?.pointEnd ?? this.pointEnd; + + this.strokeGradient = config?.strokeGradient ?? this.strokeGradient; + this.fillGradient = config?.fillGradient ?? this.fillGradient; + this.clip = config?.clip ?? this.clip; + this.zIndex = config?.zIndex ?? this.zIndex; + this.textBgColor = config?.textBgColor ?? this.textBgColor; + + + } + + draw(ctx : CanvasRenderingContext2D) : void { + if (this.visible == false) return; + ctx.save(); + ctx.globalAlpha = this.opacity; + ctx.translate(this.x + this.offsetX, this.y + this.offsetY); + if (this.rotation != 0) { + if (this.rotateCenter == 'topLeft') { + ctx.rotate(this.rotation * Math.PI / 180); + } else if (this.rotateCenter == 'center') { + ctx.translate(this.width / 2, this.height / 2); + ctx.rotate(this.rotation * Math.PI / 180); + ctx.translate(-this.width / 2, -this.height / 2); + } else if (this.rotateCenter == 'topRight') { + ctx.translate(this.width, 0); + ctx.rotate(this.rotation * Math.PI / 180); + ctx.translate(-this.width, 0); + } else if (this.rotateCenter == 'bottomLeft') { + ctx.translate(0, this.height); + ctx.rotate(this.rotation * Math.PI / 180); + ctx.translate(0, -this.height); + } else if (this.rotateCenter == 'bottomRight') { + ctx.translate(this.width, this.height); + ctx.rotate(this.rotation * Math.PI / 180); + ctx.translate(-this.width, -this.height); + } + } + if (this.scaleX != 1 || this.scaleY != 1) { + + if (this.rotateCenter == 'topLeft') { + ctx.scale(this.scaleX, this.scaleY); + } else if (this.rotateCenter == 'center') { + ctx.translate(this.width / 2, this.height / 2); + ctx.scale(this.scaleX, this.scaleY); + ctx.translate(-this.width / 2, -this.height / 2); + } else if (this.rotateCenter == 'topRight') { + ctx.translate(this.width, 0); + ctx.scale(this.scaleX, this.scaleY); + ctx.translate(-this.width, 0); + } else if (this.rotateCenter == 'bottomLeft') { + ctx.translate(0, this.height); + ctx.scale(this.scaleX, this.scaleY); + ctx.translate(0, -this.height); + } else if (this.rotateCenter == 'bottomRight') { + ctx.translate(this.width, this.height); + ctx.scale(this.scaleX, this.scaleY); + ctx.translate(-this.width, -this.height); + } + + } + ctx.translate(-this.x, -this.y); + if (this.clip) { + ctx.clip() + } + if (this.fill != "" || this.fillGradient.length > 0) { + if (this.fillGradient.length > 0) { + const gradient = this.createLinearGradient(ctx, this.fillGradient); + ctx.fillStyle = gradient; + } else if (this.fill != "") { + ctx.fillStyle = this.fill; + } + } + if (this.stroke != "" || this.strokeGradient.length > 0) { + if (this.strokeGradient.length > 0) { + const gradient = this.createLinearGradient(ctx, this.strokeGradient); + ctx.strokeStyle = gradient; + } else { + ctx.strokeStyle = this.stroke + } + ctx.lineWidth = this.strokeWidth; + ctx.lineJoin = this.lineJoin; + ctx.lineCap = this.lineCap; + ctx.lineDashOffset = this.lineDashOffset; + if (this.lineDash.length > 0) { + ctx.setLineDash(this.lineDash) + } + } + + } + + isPointInPath(x : number, y : number, shapeId : string) : boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + const realX = x - (this.offsetX) - this.x; + const realY = y - (this.offsetY) - this.y; + + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + if (this.rotateCenter == 'topLeft') { + centerX = 0; + centerY = 0; + } else if (this.rotateCenter == 'center') { + centerX = this.width / 2; + centerY = this.height / 2; + } else if (this.rotateCenter == 'topRight') { + centerX = this.width; + centerY = 0; + } else if (this.rotateCenter == 'bottomLeft') { + centerX = 0; + centerY = this.height; + } else if (this.rotateCenter == 'bottomRight') { + centerX = this.width; + centerY = this.height; + } + + const dx = realX - centerX; + const dy = realY - centerY; + const rotatedX = centerX + dx * cos - dy * sin; + const rotatedY = centerY + dx * sin + dy * cos; + return rotatedX >= 0 && rotatedX <= this.width * this.scaleX && rotatedY >= 0 && rotatedY <= this.height * this.scaleY; + } + + return realX >= 0 && realX <= this.width * this.scaleX && + realY >= 0 && realY <= this.height * this.scaleY; + } + + addEventListener(eventName : CanvasEventType, listener : IEventShapeListener) : Shape { + if (!this.eventListeners.has(eventName)) { + this.eventListeners.set(eventName, []); + } + + this.eventListeners.get(eventName)!.push(listener); + return this; + } + + removeEventListener(eventName : CanvasEventType, listener : IEventShapeListener) : Shape { + const listeners = this.eventListeners.get(eventName); + if (listeners == null) return this; + const index = listeners.indexOf(listener); + if (index != -1) { + listeners.splice(index, 1); + } + return this; + } + + buildEvents(eventName : CanvasEventType, parentEventDetail : ICanvasEvent) { + const listeners = this.eventListeners.get(eventName); + + if (eventName == 'click') { + this.toggleStatus = !this.toggleStatus + this.toggleListener(this.toggleStatus, this) + } + + if (listeners == null) return; + let layerX = parentEventDetail.x - ((this.offsetX * this.scaleX) + this.x); + let layerY = parentEventDetail.y - ((this.offsetY * this.scaleY) + this.y); + const events = { + type: eventName, + x: parentEventDetail.x, + y: parentEventDetail.y, + /** 元素本身内的坐标X */ + layerX: layerX, + /** 元素本身内的坐标Y */ + layerY: layerY, + target: this, + touches: parentEventDetail.touches.map((el : ICanvasEvent) : IEventShape => { + let layerX_self = el.x - ((this.offsetX * this.scaleX) + this.x); + let layerY_self = el.y - ((this.offsetY * this.scaleY) + this.y); + return { + touches: [] as IEventShape[], + type: eventName, + x: el.x, + y: el.y, + layerX: layerX_self, + layerY: layerY_self, + target: this + } as IEventShape + }) + } as IEventShape + + for (let i = 0; i < listeners.length; i++) { + let children = listeners[i] + //执行画布的监听事件 + children(events); + } + } + + setRotateCenter(center : CanvasRotateCenter) : Shape { + this.rotateCenter = center; + return this; + } + setX(value : number) : Shape { + this.x = value; + this.needsUpdate = true; + return this; + } + + setY(value : number) : Shape { + this.y = value; + this.needsUpdate = true; + return this; + } + + setWidth(value : number) : Shape { + if( + this.type=='ILinePolygon'|| + this.type=='ILayout'|| + this.type=='Path2DShape'|| + this.type=='IRegularPolygon' + ){ + console.warn(`所在图形:${this.type}不支持本方法`) + return this; + } + this.width = value; + this.needsUpdate = true; + return this; + } + + setHeight(value : number) : Shape { + if( + this.type=='ILinePolygon'|| + this.type=='ILayout'|| + this.type=='Path2DShape'|| + this.type=='IRegularPolygon' + ){ + console.warn(`所在图形:${this.type}不支持本方法`) + return this; + } + this.height = value; + this.needsUpdate = true; + return this; + } + + setFill(value : string) : Shape { + this.fill = value; + this.needsUpdate = true; + return this; + } + + setStroke(value : string) : Shape { + this.stroke = value; + this.needsUpdate = true; + return this; + } + + setStrokeWidth(value : number) : Shape { + this.strokeWidth = value; + this.needsUpdate = true; + return this; + } + + setOpacity(value : number) : Shape { + this.opacity = value; + this.needsUpdate = true; + return this; + } + + setVisible(value : boolean) : Shape { + this.visible = value; + this.needsUpdate = true; + return this; + } + + setRotation(value : number) : Shape { + this.rotation = value; + this.needsUpdate = true; + return this; + } + + setScaleX(value : number) : Shape { + this.scaleX = value; + this.needsUpdate = true; + return this; + } + + setScaleY(value : number) : Shape { + this.scaleY = value; + this.needsUpdate = true; + return this; + } + + setOffsetX(value : number) : Shape { + this.offsetX = value; + this.needsUpdate = true; + return this; + } + + setOffsetY(value : number) : Shape { + this.offsetY = value; + this.needsUpdate = true; + return this; + } + setLineDash(value : number[]) : Shape { + this.lineDash = value; + this.needsUpdate = true; + return this; + } + + setDraggable(value : boolean) : Shape { + this.draggable = value; + this.needsUpdate = true; + return this; + } + + setBubbleEvent(value : boolean) : Shape { + this.bubbleEvent = value; + this.needsUpdate = true; + return this; + } + setZindex(value : number) : Shape { + this.zIndex = value; + this.needsUpdate = true; + return this; + } + setClip(value : boolean) : Shape { + this.clip = value; + this.needsUpdate = true; + return this; + } + setTextBgColor(value : string) : Shape { + this.textBgColor = value; + this.needsUpdate = true; + return this; + } + + setAttr(key : string, value : any) { + this.needsUpdate = true; + switch (key) { + case 'x': { this.x = value as number; break; } + case 'y': { this.y = value as number; break; } + case 'width': { this.width = value as number; break; } + case 'height': { this.height = value as number; break; } + case 'fill': { this.fill = value as string; break; } + case 'stroke': { this.stroke = value as string; break; } + case 'strokeWidth': { this.strokeWidth = value as number; break; } + case 'opacity': { this.opacity = value as number; break; } + case 'visible': { this.visible = value as boolean; break; } + case 'rotation': { this.rotation = value as number; break; } + case 'scaleX': { this.scaleX = value as number; break; } + case 'scaleY': { this.scaleY = value as number; break; } + case 'offsetX': { this.offsetX = value as number; break; } + case 'offsetY': { this.offsetY = value as number; break; } + case 'draggable': { this.draggable = value as boolean; break; } + case 'bubbleEvent': { this.bubbleEvent = value as boolean; break; } + case 'lineJoin': { this.lineJoin = value as ILineJoinType; break; } + case 'lineDashOffset': { this.lineDashOffset = value as number; break; } + case 'lineDash': { this.lineDash = value as number[]; break; } + case 'lineCap': { this.lineCap = value as ILineCapType; break; } + case 'text': this.text = value as string; + case 'src': this.src = value as string; + case 'fontSize': this.fontSize = value as number; + case 'fontFamily': this.fontFamily = value as string; + case 'textAlign': this.textAlign = value as ITextAlignType; + case 'textBaseline': this.textBaseline = value as ITextBaselineType; + case 'padding': this.padding = value as number; + case 'lineHeight': this.lineHeight = value as number; + case 'innerRadius': { this.innerRadius = value as number; break; } + case 'outerRadius': { this.outerRadius = value as number; break; } + case 'startAngle': { this.startAngle = value as number; break; } + case 'endAngle': { this.endAngle = value as number; break; } + case 'radius': { this.radius = value as number; break; } + case 'sides': { this.sides = value as number; break; } + case 'points': { this.points = value as number[]; break; } + case 'closed': { this.closed = value as boolean; break; } + case 'tension': { this.tension = value as number; break; } + case 'bezier': { this.bezier = value as boolean; break; } + case 'radiusX': { this.radiusX = value as number; break; } + case 'radiusY': { this.radiusY = value as number; break; } + case 'numPoints': { this.numPoints = value as number; break; } + case 'pointStart': { this.pointStart = value as IShapeVector2d; break; } + case 'pointEnd': { this.pointEnd = value as IShapeVector2d; break; } + case 'clip': { this.clip = value as boolean; break; } + case 'zIndex': { this.zIndex = value as number; break; } + case 'textBgColor': { this.textBgColor = value as string; break; } + case 'foreground': { this.foreground = value as string; break; } + case 'qrcodeText': { this.qrcodeText = value as string; break; } + + default: return; + } + } + + getAttr(key : string) : any | null { + switch (key) { + case 'x': return this.x; + case 'y': return this.y; + case 'src': return this.src; + case 'width': return this.width; + case 'height': return this.height; + case 'fill': return this.fill; + case 'stroke': return this.stroke; + case 'strokeWidth': return this.strokeWidth; + case 'opacity': return this.opacity; + case 'visible': return this.visible; + case 'rotation': return this.rotation; + case 'scaleX': return this.scaleX; + case 'scaleY': return this.scaleY; + case 'offsetX': return this.offsetX; + case 'offsetY': return this.offsetY; + case 'draggable': return this.draggable; + case 'bubbleEvent': return this.bubbleEvent; + case 'lineJoin': return this.lineJoin; + case 'lineDashOffset': return this.lineDashOffset; + case 'lineDash': return this.lineDash; + case 'lineCap': return this.lineCap; + case 'text': return this.text; + case 'fontSize': return this.fontSize; + case 'fontFamily': return this.fontFamily; + case 'textAlign': return this.textAlign; + case 'textBaseline': return this.textBaseline; + case 'padding': return this.padding; + case 'lineHeight': return this.lineHeight; + case 'innerRadius': return this.innerRadius; + case 'outerRadius': return this.outerRadius; + case 'startAngle': return this.startAngle; + case 'endAngle': return this.endAngle; + case 'radius': return this.radius; + case 'sides': return this.sides; + case 'closed': return this.closed; + case 'points': return this.points; + case 'tension': return this.tension; + case 'bezier': return this.bezier; + case 'radiusX': return this.radiusX; + case 'radiusY': return this.radiusY; + case 'numPoints': return this.numPoints; + case 'pointStart': return this.pointStart; + case 'pointEnd': return this.pointEnd; + case 'clip': return this.pointEnd; + case 'zIndex': return this.zIndex; + case 'textBgColor': return this.textBgColor; + case 'foreground': return this.foreground; + case 'qrcodeText': return this.qrcodeText; + default: return null; + } + } + + getBoundRect() : IShapeBoundRect { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height + } as IShapeBoundRect; + } + + + toggle(call : (status : boolean, target : any) => void) : void { + this.toggleListener = call; + } + + + update() : Shape { + if (!this.needsUpdate) return this; + this.needsUpdate = false; + return this; + } + + /** + * 克隆当前图形 + * @param count 要克隆的数量,默认 1 + * @returns 克隆出来的新图形数组(长度为 count) + */ + clone(count : number = 1,callActons:CloneCallActions|null = null) : Shape[] { + const clones : Shape[] = []; + + const baseConfig = { + x: this.x, + y: this.y, + width: this.width, + height: this.height, + fill: this.fill, + stroke: this.stroke, + strokeWidth: this.strokeWidth, + opacity: this.opacity, + visible: this.visible, + rotation: this.rotation, + scaleX: this.scaleX, + scaleY: this.scaleY, + offsetX: this.offsetX, + offsetY: this.offsetY, + draggable: this.draggable, + bubbleEvent: this.bubbleEvent, + rotateCenter: this.rotateCenter, + lineJoin: this.lineJoin, + lineDashOffset: this.lineDashOffset, + lineDash: this.lineDash.slice(), + lineCap: this.lineCap, + text: this.text, + fontSize: this.fontSize, + fontFamily: this.fontFamily, + textAlign: this.textAlign, + textBaseline: this.textBaseline, + padding: this.padding, + lineHeight: this.lineHeight, + innerRadius: this.innerRadius, + outerRadius: this.outerRadius, + startAngle: this.startAngle, + endAngle: this.endAngle, + radius: this.radius, + sides: this.sides, + points: this.points.slice(), + closed: this.closed, + tension: this.tension, + bezier: this.bezier, + radiusX: this.radiusX, + radiusY: this.radiusY, + numPoints: this.numPoints, + pointStart: { x: this.pointStart.x, y: this.pointStart.y }, + pointEnd: { x: this.pointEnd.x, y: this.pointEnd.y }, + strokeGradient: this.strokeGradient.slice(), + fillGradient: this.fillGradient.slice(), + clip: this.clip, + zIndex: this.zIndex, + textBgColor: this.textBgColor, + src: this.src, + } as IShapeOptional; + + for (let i = 0; i < Math.max(1, count); i++) { + + let shape:any|null = null; + + // #ifdef APP-ANDROID + switch(this.type){ + case 'IArc':{ + shape = new IArc(baseConfig,this.canvas) + break; + } + case 'ICircle':{ + shape = new ICircle(baseConfig,this.canvas) + break; + } + case 'IEllipse':{ + shape = new IEllipse(baseConfig,this.canvas) + break; + } + case 'ImageShape':{ + shape = new ImageShape(baseConfig,this.canvas) + break; + } + case 'ILine':{ + shape = new ILine(baseConfig,this.canvas) + break; + } + case 'ILinePolygon':{ + shape = new ILinePolygon(baseConfig,this.canvas) + break; + } + case 'Path2DShape':{ + shape = new Path2DShape(baseConfig,this.canvas) + break; + } + case 'IRect':{ + shape = new IRect(baseConfig,this.canvas) + break; + } + case 'IRegularPolygon':{ + shape = new IRegularPolygon(baseConfig,this.canvas) + break; + } + case 'IRing':{ + shape = new IRing(baseConfig,this.canvas) + break; + } + case 'ISector':{ + shape = new ISector(baseConfig,this.canvas) + break; + } + case 'IStar':{ + shape = new IStar(baseConfig,this.canvas) + break; + } + case 'IText':{ + shape = new IText(baseConfig,this.canvas) + break; + } + default:{ + break; + } + + } + + // #endif + + // #ifndef APP-ANDROID + const Ctor = (this as any).constructor; + shape = new Ctor(baseConfig,this.canvas) as any + // #endif + + + if(shape!=null){ + const cloned : Shape = shape! as Shape; + cloned.needsUpdate = true; + if(callActons!=null){ + callActons!(cloned!,i) + } + clones.push(cloned); + } + + } + return clones; + } + + private createLinearGradient(ctx : CanvasRenderingContext2D, gradientArray : string[]) : CanvasGradient { + if (gradientArray.length < 2) return ctx.createLinearGradient(0, 0, 0, 0); + // 解析角度 + let angle = 0; + const firstItem = gradientArray[0]; + if (firstItem.includes('deg')) { + angle = parseFloat(firstItem); + gradientArray = gradientArray.slice(1); + } + + // 计算渐变的起点和终点 + const radian = angle * Math.PI / 180; + const length = Math.max(this.width, this.height); + let startX = this.x; + let startY = this.y; + let endX = this.x; + let endY = this.y; + + if (this.type == 'ICircle') { + // 对于圆形,使用半径计算 + const dx = Math.cos(radian) * this.radius; + const dy = Math.sin(radian) * this.radius; + startX = this.x - dx; + startY = this.y - dy; + endX = this.x + dx; + endY = this.y + dy; + } else if (this.type == 'IEllipse') { + // 对于椭圆,使用radiusX和radiusY计算 + const dx = Math.cos(radian) * this.radiusX; + const dy = Math.sin(radian) * this.radiusY; + startX = this.x - dx; + startY = this.y - dy; + endX = this.x + dx; + endY = this.y + dy; + } else if (this.type == 'IStar') { + // 对于星形,使用外接圆半径计算 + const radius = this.outerRadius; + const dx = Math.cos(radian) * radius; + const dy = Math.sin(radian) * radius; + startX = this.x - dx; + startY = this.y - dy; + endX = this.x + dx; + endY = this.y + dy; + } else if (this.type == 'IText') { + // 对于文本,使用文本框的宽高计算 + const dx = Math.cos(radian) * this.width; + const dy = Math.sin(radian) * this.height; + endX = startX + dx; + endY = startY + dy; + } else if (this.type == 'IArc' || this.type == 'ISector') { + // 对于圆弧和扇形,使用半径计算 + const dx = Math.cos(radian) * this.radius; + const dy = Math.sin(radian) * this.radius; + startX = this.x - dx; + startY = this.y - dy; + endX = this.x + dx; + endY = this.y + dy; + } else { + // 默认使用矩形的宽高计算 + const dx = Math.cos(radian) * length; + const dy = Math.sin(radian) * length; + endX = startX + dx; + endY = startY + dy; + } + + const gradient = ctx.createLinearGradient(startX, startY, endX, endY); + // 添加渐变色停止点 + gradientArray.forEach(item => { + const ar = item.split(' '); + const color = ar[0]; + const stop = ar[1]; + const offset = parseFloat(stop) / 100; + + gradient.addColorStop(offset, color); + }); + + return gradient; + } + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/star.uts b/uni_modules/tmx-ui/core/canvas/lib/star.uts new file mode 100644 index 0000000..327e79e --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/star.uts @@ -0,0 +1,170 @@ +import { Shape } from './shape.uts'; +import { CanvasRotateCenter, IShapeBoundRect, IShapeOptional } from '../interface.uts'; +import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; + +export class IStar extends Shape { + override type = 'IStar' + constructor(config: IShapeOptional, canvas: ICanvas) { + super(config, canvas); + this.numPoints = config?.numPoints ?? 5; + this.innerRadius = config?.innerRadius ?? 16; + this.outerRadius = config?.outerRadius ?? 30; + this.width = this.outerRadius * 2; + this.height = this.outerRadius * 2; + } + + setInnerRadius(value: number): IStar { + this.innerRadius = value; + this.needsUpdate = true; + return this; + } + + setOuterRadius(value: number): IStar { + this.outerRadius = value; + this.width = value * 2; + this.height = value * 2; + this.needsUpdate = true; + return this; + } + + setNumPoints(value: number): IStar { + this.numPoints = value; + this.needsUpdate = true; + return this; + } + + override getBoundRect(): IShapeBoundRect { + // 估算星形的外接矩形(以中心为圆心,外半径为界) + const r = Math.max(0, this.outerRadius); + const pad = (this.stroke != "" ? this.strokeWidth/2 : 0); + const d = r*2 + pad*2; + return { + x: this.x - r - pad, + y: this.y - r - pad, + width: d, + height: d + } as IShapeBoundRect; + } + + override setWidth(value: number): IStar { + this.height = value; + this.width = value; + this.outerRadius = value / 2; + this.needsUpdate = true; + return this; + } + + override setHeight(value: number): IStar { + this.height = value; + this.width = value; + this.outerRadius = value / 2; + this.needsUpdate = true; + return this; + } + + override draw(ctx: CanvasRenderingContext2D) { + if (this.visible == false) return; + super.draw(ctx); + ctx.beginPath(); + + // 计算每个角的角度增量 + const angleStep = Math.PI * 2 / this.numPoints; + // 起始角度(使星形垂直向上) + const startAngle = -Math.PI / 2; + + // 绘制第一个点(外部点) + let x = this.x + Math.cos(startAngle) * this.outerRadius; + let y = this.y + Math.sin(startAngle) * this.outerRadius; + ctx.moveTo(x, y); + + // 绘制其余的点 + for (let i = 1; i <= this.numPoints * 2; i++) { + const angle = startAngle + angleStep * i / 2; + const radius = i % 2 === 0 ? this.outerRadius : this.innerRadius; + x = this.x + Math.cos(angle) * radius; + y = this.y + Math.sin(angle) * radius; + ctx.lineTo(x, y); + } + + ctx.closePath(); + if (this.fill != "") { + ctx.fill(); + } + if (this.stroke != "") { + ctx.stroke(); + } + ctx.restore(); + } + + override isPointInPath(x: number, y: number, shapeId: string): boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + + // 计算点击位置相对于星形中心的实际坐标 + let realX = x - this.offsetX - this.x; + let realY = y - this.offsetY - this.y; + + // 如果有旋转,需要将坐标转换回未旋转状态 + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = this.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = this.height; + break; + case 'bottomRight': + centerX = this.width; + centerY = this.height; + break; + case 'center': + default: + centerX = this.width/2; + centerY = this.height/2; + break; + } + const dx = realX - centerX; + const dy = realY - centerY; + realX = centerX + dx * cos - dy * sin; + realY = centerY + dx * sin + dy * cos; + } + + // 计算点到中心的距离 + const distance = Math.sqrt(realX * realX + realY * realY); + + // 如果点击位置超出外半径,则不在星形内 + if (distance > this.outerRadius * Math.max(this.scaleX, this.scaleY)) return false; + + // 计算点击位置的角度 + let angle = Math.atan2(realY, realX); + if (angle < 0) angle += Math.PI * 2; + + // 调整角度使其从垂直向上开始计算 + angle = (angle + Math.PI / 2) % (Math.PI * 2); + + // 计算点所在的扇区 + const angleStep = Math.PI * 2 / this.numPoints; + const sector = Math.floor(angle / angleStep); + const sectorAngle = angle - sector * angleStep; + + // 计算该角度对应的半径 + const ratio = sectorAngle / angleStep; + const radius = this.innerRadius + (this.outerRadius - this.innerRadius) * Math.abs(0.5 - ratio) * 2; + // 考虑缩放因素 + const scaledRadius = radius * Math.max(this.scaleX, this.scaleY); + // 如果点击位置在计算出的半径内,则在星形内 + return distance <= scaledRadius; + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/canvas/lib/text.uts b/uni_modules/tmx-ui/core/canvas/lib/text.uts new file mode 100644 index 0000000..eb23143 --- /dev/null +++ b/uni_modules/tmx-ui/core/canvas/lib/text.uts @@ -0,0 +1,226 @@ +import { Shape } from './shape.uts'; +import { ShapeSetAttrType, ITextBaselineType, ITextAlignType, CanvasRotateCenter, IShapeBoundRect, IShapeOptional } from '../interface.uts'; + import { ICanvas } from '@/uni_modules/tmx-ui/core/canvas/ICanvas.uts'; + + + +export class IText extends Shape { + + constructor(config : IShapeOptional,canvas:ICanvas) { + super(config,canvas); + this.type = 'IText' + } + + private wrapText(ctx : CanvasRenderingContext2D, text : string, maxWidth : number) : string[] { + // 首先处理所有类型的换行符,统一转换为\n + text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); + // 按换行符分割文本 + const paragraphs = text.split('\n'); + const lines : string[] = []; + + // 处理每个段落 + for (let i = 0; i < paragraphs.length; i++) { + let paragraph = paragraphs[i] + if (paragraph == '') { + // 保留空行 + lines.push(''); + continue; + } + + const words = paragraph.split(''); + let currentLine = ''; + + for (let i = 0; i < words.length; i++) { + const testLine = currentLine + words[i]; + const metrics = ctx.measureText(testLine); + const testWidth = metrics.width; + + if (testWidth > maxWidth && i > 0) { + lines.push(currentLine); + currentLine = words[i]; + } else { + currentLine = testLine; + } + } + lines.push(currentLine); + } + return lines; + } + + override draw(ctx : CanvasRenderingContext2D) { + if (this.visible == false) return; + + ctx.font = `${this.fontSize}px ${this.fontFamily}`; + ctx.textAlign = this.textAlign; + ctx.textBaseline = this.textBaseline; + const maxWidth = this.width > 0 ? this.width - this.padding * 2 : ctx.canvas.offsetWidth - this.x - this.padding * 2; + const lines = this.wrapText(ctx, this.text, maxWidth); + const lineHeightPixels = this.fontSize * this.lineHeight; + + this.width = maxWidth + this.padding * 2; + this.height = lineHeightPixels * lines.length + this.padding * 2; + if(this.textBgColor!=''){ + ctx.fillStyle = this.textBgColor + // ctx.fillRect(this.x,this.y,this.width,this.height) + ctx.beginPath(); + if (this.radius > 0) { + let radiuss = Math.min(this.radius, this.width / 2, this.height / 2); + const radius = Math.max(radiuss, 0) + ctx.moveTo(this.x + radius, this.y); + ctx.lineTo(this.x + this.width - radius, this.y); + ctx.arcTo(this.x + this.width, this.y, this.x + this.width, this.y + radius, radius); + ctx.lineTo(this.x + this.width, this.y + this.height - radius); + ctx.arcTo(this.x + this.width, this.y + this.height, this.x + this.width - radius, this.y + this.height, radius); + ctx.lineTo(this.x + radius, this.y + this.height); + ctx.arcTo(this.x, this.y + this.height, this.x, this.y + this.height - radius, radius); + ctx.lineTo(this.x, this.y + radius); + ctx.arcTo(this.x, this.y, this.x + radius, this.y, radius); + } else { + ctx.beginPath(); + ctx.rect(this.x, this.y, this.width, this.height); + } + ctx.closePath(); + ctx.fill() + ctx.fillStyle = this.fill + } + + for (let i = 0; i < lines.length; i++) { + const y = this.y + this.padding + i * lineHeightPixels; + let adjustedY = y; + + // 根据textBaseline调整y坐标 + if (this.textBaseline === 'middle') { + adjustedY = y + this.fontSize / 2; + } else if (this.textBaseline === 'bottom') { + adjustedY = y + this.fontSize; + } + + let x = this.x + this.padding; + if (this.textAlign === 'center') { + x = this.x + this.width / 2; + } else if (this.textAlign === 'right') { + x = this.x + this.width - this.padding; + } + if (this.fill != "") { + ctx.fillStyle = this.fill; + ctx.fillText(lines[i], x, adjustedY); + } + if (this.stroke != "") { + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + ctx.strokeText(lines[i], x, adjustedY); + } + } + + ctx.restore() + } + + setText(value : string) : IText { + this.text = value; + this.needsUpdate = true; + return this; + } + + setFontSize(value : number) : IText { + this.fontSize = value; + this.needsUpdate = true; + return this; + } + + setFontFamily(value : string) : IText { + this.fontFamily = value; + this.needsUpdate = true; + return this; + } + + setTextAlign(value : 'left' | 'center' | 'right') : IText { + this.textAlign = value; + this.needsUpdate = true; + return this; + } + + setTextBaseline(value : 'top' | 'middle' | 'bottom') : IText { + this.textBaseline = value; + this.needsUpdate = true; + return this; + } + + setPadding(value : number) : IText { + this.padding = value; + this.needsUpdate = true; + return this; + } + + setLineHeight(value : number) : IText { + this.lineHeight = value; + this.needsUpdate = true; + return this; + } + + override getBoundRect() : IShapeBoundRect { + const ctx = this.canvas.ctx! + ctx.font = `${this.fontSize}px ${this.fontFamily}`; + const maxWidth = this.width > 0 ? this.width - this.padding * 2 : ctx.canvas.offsetWidth - this.x - this.padding * 2; + const lines = this.wrapText(ctx, this.text, maxWidth); + const lineHeightPixels = this.fontSize * this.lineHeight; + const measuredWidth = Math.max(...lines.map(line => ctx.measureText(line).width), 0); + const effectiveWidth = (this.width > 0 ? Math.min(measuredWidth, maxWidth) : measuredWidth) + this.padding * 2; + const width = effectiveWidth; + const height = lineHeightPixels * lines.length + this.padding * 2; + return { + x: this.x, + y: this.y, + width: width, + height: height + } as IShapeBoundRect; + } + + override isPointInPath(x : number, y : number, shapeId : string) : boolean { + if (!this.visible || (shapeId != "" && shapeId != this.id)) return false; + const textBounds = this.getBoundRect(); + const realX = x - textBounds.x - this.offsetX; + const realY = y - textBounds.y - this.offsetY; + + if (this.rotation != 0) { + const angle = -this.rotation * Math.PI / 180; + const cos = Math.cos(angle); + const sin = Math.sin(angle); + let centerX = 0; + let centerY = 0; + + // 根据不同的旋转中心点设置centerX和centerY + switch(this.rotateCenter) { + case 'topLeft': + centerX = 0; + centerY = 0; + break; + case 'topRight': + centerX = textBounds.width; + centerY = 0; + break; + case 'bottomLeft': + centerX = 0; + centerY = textBounds.height; + break; + case 'bottomRight': + centerX = textBounds.width; + centerY = textBounds.height; + break; + case 'center': + default: + centerX = textBounds.width/2; + centerY = textBounds.height/2; + break; + } + + const dx = realX - centerX; + const dy = realY - centerY; + const rotatedX = centerX + dx * cos - dy * sin; + const rotatedY = centerY + dx * sin + dy * cos; + return rotatedX >= 0 && rotatedX <= textBounds.width * this.scaleX && rotatedY >= 0 && rotatedY <= textBounds.height * this.scaleY; + } + + return realX >= 0 && realX <= textBounds.width * this.scaleX && realY >= 0 && realY <= textBounds.height * this.scaleY; + } + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/bezier.uts b/uni_modules/tmx-ui/core/util/bezier.uts new file mode 100644 index 0000000..327844b --- /dev/null +++ b/uni_modules/tmx-ui/core/util/bezier.uts @@ -0,0 +1,78 @@ +type callbackFunType = (x:number)=>number +let kSplineTableSize = 11; +let kSampleStepSize = 1.0 / (kSplineTableSize - 1.0); + +function A(aA1:number, aA2:number):number { return 1.0 - 3.0 * aA2 + 3.0 * aA1 } +function B(aA1:number, aA2:number):number { return 3.0 * aA2 - 6.0 * aA1 } +function C(aA1:number):number { return 3.0 * aA1 } + +function calcBezier(aT:number, aA1:number, aA2:number):number { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT } +function getSlope(aT:number, aA1:number, aA2:number):number { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1) } + +function binarySubdivide(aX:number, aA:number, aB:number, mX1:number, mX2:number):number { + let currentX = 0; + let currentT = 0; + let i = 0; + do { + currentT = aA + (aB - aA) / 2.0; + currentX = calcBezier(currentT, mX1, mX2) - aX; + if (currentX > 0.0) { aB = currentT; } else { aA = currentT; } + } while (Math.abs(currentX) > 0.0000001 && ++i < 10); + return currentT; +} + +function newtonRaphsonIterate(aX:number, aGuessT:number, mX1:number, mX2:number):number { + let pat = aGuessT; + for (let i = 0; i < 4; ++i) { + let currentSlope = getSlope(aGuessT, mX1, mX2); + if (currentSlope == 0.0) { return aGuessT; } + let currentX = calcBezier(aGuessT, mX1, mX2) - aX; + pat -= currentX / currentSlope; + } + return pat; +} + +function bezier(mX1:number, mY1:number, mX2:number, mY2:number):callbackFunType|null { + + if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { return null; } + let sampleValues:number[] = []; + + if (mX1 != mY1 || mX2 != mY2) { + for (let i = 0; i < kSplineTableSize; ++i) { + sampleValues.push(calcBezier(i * kSampleStepSize, mX1, mX2)) + } + } + + function getTForX(aX:number):number { + + let intervalStart = 0; + let currentSample = 1; + let lastSample = kSplineTableSize - 1; + + for (; currentSample != lastSample && sampleValues[currentSample] <= aX; ++currentSample) { + intervalStart += kSampleStepSize; + } + + --currentSample; + + let dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]); + let guessForT:number = intervalStart + dist * kSampleStepSize; + let initialSlope = getSlope(guessForT, mX1, mX2); + + if (initialSlope >= 0.001) { + return newtonRaphsonIterate(aX, guessForT, mX1, mX2); + } else if (initialSlope == 0.0) { + return guessForT; + } + return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2); + } + + return function (x:number):number { + if (mX1 == mY1 && mX2 == mY2) { return x; } + if (x == 0 || x == 1) { return x; } + return calcBezier(getTForX(x), mY1, mY2); + } + +} + +export default bezier \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/config.uts b/uni_modules/tmx-ui/core/util/config.uts new file mode 100644 index 0000000..8fe04e3 --- /dev/null +++ b/uni_modules/tmx-ui/core/util/config.uts @@ -0,0 +1,20 @@ +import {xRequestHistoryType,X_REQUEST_PRIVATE_CALL_FUN_TYPE} from "../../interface.uts" + + +/** + * 内部组件私有 + */ +export const xRequestCall = reactive({ + history:[] as xRequestHistoryType[], + authPass:true, + hostUrl:"", + dev:false, + header:null, + /** 请求前是否显示loading遮罩 */ + showLoadToast:true, + /** 请求成功后是否提示,否则不提示 */ + showSuccessToast:true, + /** 出错时,是否显示提示,否则不提示 */ + showErrorToast:true +} as X_REQUEST_PRIVATE_CALL_FUN_TYPE) + diff --git a/uni_modules/tmx-ui/core/util/xAnimate.uts b/uni_modules/tmx-ui/core/util/xAnimate.uts new file mode 100644 index 0000000..cfa5bff --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xAnimate.uts @@ -0,0 +1,850 @@ +/** + * xAnimate + * @author tmzdy + * @copyright tmui4.0附带核心基类 + * @version 1.0.0 + * @description 通过nodeElement元素来控制属性动画变得更为简单方便 + * + */ +import { XANIMATE_OPIONS } from "../../interface.uts" +import { getUid } from "./xCoreUtil.uts"; +import { hexToRgb,getDefaultColor,rgbToHex } from "./xCoreColorUtil.uts"; +import bezier from "./bezier.uts" +// #ifdef APP-ANDROID +import Choreographer from "android.view.Choreographer"; +import FrameCallback from "android.view.Choreographer.FrameCallback"; +// #endif + +// #ifdef APP-IOS +// import * as UIKit from 'UIKit'; +// #endif + +type ATTRGERTS = { + from : string, + to : string, + unit : string, + now : string, + progress : number, + name : string +} +type callbackFunType = (x:number)=>number +type easingFunType = { + x:number, + y:number, + m:number, + n:number, +} + +export class xAnimate { + easingList = new Map([ + ["linear",[0.250, 0.250, 0.750, 0.750]], + ["ease",[0.250, 0.100, 0.250, 1.000]], + ["easeIn",[0.420, 0.000, 1.000, 1.000]], + ["easeOut",[0.000, 0.000, 0.580, 1.000]], + ["easeInOut",[0.420, 0.000, 0.580, 1.000]], + ["easeInQuad", [0.550, 0.085, 0.680, 0.530]], + ["easeOutQuad", [0.250, 0.460, 0.450, 0.940]], + ["easeInOutQuad", [0.455, 0.030, 0.515, 0.955]], + ["easeInCubic", [0.550, 0.055, 0.675, 0.190]], + ["easeOutCubic", [0.215, 0.610, 0.355, 1.000]], + ["easeInOutCubic", [0.645, 0.045, 0.355, 1.000]], + ["easeInQuart", [0.895, 0.030, 0.685, 0.220]], + ["easeOutQuart", [0.165, 0.840, 0.440, 1.000]], + ["easeInOutQuart", [0.770, 0.000, 0.175, 1.000]], + ["easeInQuint", [0.755, 0.050, 0.855, 0.060]], + ["easeOutQuint", [0.230, 1.000, 0.320, 1.000]], + ["easeInOutQuint", [0.860, 0.000, 0.070, 1.000]], + ["easeInSine", [0.470, 0.000, 0.745, 0.715]], + ["easeOutSine", [0.390, 0.575, 0.565, 1.000]], + ["easeInOutSine", [0.445, 0.050, 0.550, 0.950]], + ["easeInExpo", [0.950, 0.050, 0.795, 0.035]], + ["easeOutExpo", [0.190, 1.000, 0.220, 1.000]], + ["easeInOutExpo", [1.000, 0.000, 0.000, 1.000]], + ["easeInCirc", [0.600, 0.040, 0.980, 0.335]], + ["easeOutCirc", [0.075, 0.820, 0.165, 1.000]], + ["easeInOutBack", [0.680, -0.550, 0.265, 1.550]], + ]); + private tid = null as null | number; + element = null as null|UniElement; + // 当前播放的动画函数 + timingFunction = 'linear'; + //当前设置的播放时间 + duration = 500; + //元素id + ele = ""; + // 当前是否播放中 + running = false + //当前是否暂停中 + pauseing = false + //当前的播放进度 + progress = 0 + reverse = false; + //设置true时,loop>1播放时会来回播放动画,而不是从起始开始而是 + // 始-终-始这样的模式播放。 + tyty = false; + _tyty = false; + // 循环播放次数-1表示无限循环. + loop = 1 + // 播放计数 + private _loop = 0 + + // 是否停止动画。 + private _isStopping = true + private attrIndex = 0; + + private completeCallBack = () => { } + private startCallBack = () => { } + private doCallBack = (propress:number) => { } + + private tagetsAttr = [] as ATTRGERTS[] + + private startTime = 0 + private easing = null as null | callbackFunType; + /** 是否让动画顺序挨过按attr添加的属性顺序执行动画,而不是统一一起执行。 */ + private isDescPlay = false + + private enterCallFun = ()=>{} + // #ifdef APP-ANDROID + private ChoreographerDemo = null as Choreographer|null + private FrameCallbackCallFun = null as FrameCallback|null + // #endif + + // #ifdef APP-IOS + // private CADisplayLink = null as UIKit.CADisplayLink|null + private dhid = 0 + // #endif + + + // #ifdef WEB || APP-IOS + private canFrameIds:number|null = null + // #endif + + /** + * 创建xAnimate动画实例 + * @param ele 元素UniElement + * @param options 动画参数 XANIMATE_OPIONS + */ + constructor(ele:UniElement|null,options : XANIMATE_OPIONS) { + + // this.element = uni.getElementById(options.ele); + this.element = ele; + + this.duration = options.duration == null?this.duration:options.duration! + this.loop = options.loop == null?this.loop:options.loop! + this.tyty = options.tyty == null?this.tyty:options.tyty! + this.isDescPlay = options.isDescPlay == null?this.isDescPlay:options.isDescPlay! + + + let easingName = options.timingFunction == null?'linear':options.timingFunction! + let ecall = this.easingList.get(easingName); + if(ecall!=null){ + let ecallps = ecall! + this.easing = bezier(ecallps[0],ecallps[1],ecallps[2],ecallps[3]); + } + if(options.bezier!=null){ + let ecallps = options.bezier! + this.easing = bezier(ecallps[0],ecallps[1],ecallps[2],ecallps[3]); + } + if(options.complete!=null){ + this.completeCallBack = options.complete! + } + if(options.start!=null){ + this.startCallBack = options.start! + } + if(options.frame!=null){ + this.doCallBack = options.frame! + } + + + + + } + + private getUnit(n ?: string) : string { + if (n == null) return 'px'; + let unit = n.replace(/[\d|\-|\+]/g, ''); + if(unit=="."){ + unit = "" + } + return unit; + } + /** + * 添加自定义动画 + */ + addTimingFunction(name:string,nubs:number[]){ + this.easingList.set(name,nubs) + } + /** + * 设置动画反转状态 + */ + setAniReverse(n:boolean|null=null){ + if(n!=null){ + this.reverse = n! + }else{ + this.reverse = !this.reverse + } + } + /** + * 设置播放动画的次数 + */ + setLoops(n:number|null = null){ + if(n!=null){ + this.loop = n!; + } + } + /** + * 设置单次动画播放的持续时间 + */ + setDurations(n:number|null = null){ + if(n!=null){ + this.duration = n!; + } + } + /** + * 连续播放的模式切换 + */ + setTytys(n:boolean|null = null){ + if(n!=null){ + this.tyty = n!; + } + } + /** + * 添加动画属性 + * @param {string} name 属性名,目前支持官方的css属性,相同的name会被覆盖 + * @param {string} from 起始值,允许数字字符,带单位2px,20%这样的,但必须和to相同单位 + * @param {string} to 结束值,允许数字字符,带单位2px,20%这样的,但必须和from相同单位 + * @param {boolean} only 是否让其是唯一性,重复添加相同的name会被最后一次替换。 + */ + attr(name:string,from : string, to : string ,only:boolean = true):xAnimate { + let unit = this.isColorStyle(name)?'':this.getUnit(from); + let from_n = this.isColorStyle(name)?getDefaultColor(from):parseFloat(from).toString() + let to_n = this.isColorStyle(name)?getDefaultColor(to):parseFloat(to).toString() + let index = this.tagetsAttr.findIndex((item:ATTRGERTS):boolean => item.name == name); + if(!only){ + index=-1; + } + if(index==-1){ + this.tagetsAttr.push({ + from: from_n.toString(), + to: to_n.toString(), + unit, + progress: 0, + now: from_n, + name: name + } as ATTRGERTS) + }else{ + this.tagetsAttr[index] = { + from: from_n.toString(), + to: to_n.toString(), + unit, + progress: 0, + now: from_n, + name: name + } as ATTRGERTS + } + + return this; + } + private interpolate(startValue:number, endValue:number, progress:number):number { + return startValue + (endValue - startValue) * progress; + } + private isColorStyle(val:string):boolean{ + return val.indexOf('background')>-1||val.indexOf('color')>-1; + } + private _setAttr(name:string,current:number,unit:string,progress:number,item:ATTRGERTS){ + if(this.element==null) return + + if(name=='scaleX'){ + this.element!.style!.setProperty("transform",`scaleX(${current})`) + }else if(name=='scaleY'){ + this.element!.style!.setProperty("transform",`scaleY(${current})`) + }else if(name=='scale'){ + this.element!.style!.setProperty("transform",`scale(${current})`) + }else if(name=='rotateX'){ + this.element!.style!.setProperty("transform",`rotateX(${(current).toString()+unit})`) + }else if(name=='rotateY'){ + this.element!.style!.setProperty("transform",`rotateY(${(current).toString()+unit})`) + }else if(name=='rotate'){ + this.element!.style!.setProperty("transform",`rotate(${(current).toString()+unit})`) + }else if(name=='translateX'){ + this.element!.style!.setProperty("transform",`translateX(${(current).toString()+unit})`) + }else if(name=='translateY'){ + this.element!.style!.setProperty("transform",`translateY(${(current).toString()+unit})`) + }else if(name=='translate'){ + this.element!.style!.setProperty("transform",`translate(${(current).toString()+unit},${(current).toString()+unit})`) + }else if(this.isColorStyle(name)){ + let startRgba = hexToRgb(item.from) + let dndRgba = hexToRgb(item.to) + let r = this.interpolate(startRgba.getNumber('r')!,dndRgba.getNumber('r')!,progress); + let g = this.interpolate(startRgba.getNumber('g')!,dndRgba.getNumber('g')!,progress); + let b = this.interpolate(startRgba.getNumber('b')!,dndRgba.getNumber('b')!,progress); + let a = this.interpolate(startRgba.getNumber('a')!,dndRgba.getNumber('a')!,progress); + this.element!.style! + .setProperty(name,`rgba(${r.toFixed(0)},${g.toFixed(0)},${b.toFixed(0)},${a.toFixed(1)})`) + }else{ + + this.element!.style!.setProperty(name,current.toFixed(2)+unit) + } + + } + private _run_web() { + + // #ifdef H5 || APP-IOS || APP-HARMONY + + let _this = this; + _this.startTime = 0 + + if(_this.canFrameIds!=null){ + cancelAnimationFrame(_this.canFrameIds) + } + function run(){ + if (_this.startTime<=0) { + _this.startTime = Date.now(); // 记录动画开始时间 + } + const progress = Math.min((Date.now() - _this.startTime) / _this.duration + _this.progress, 1); // 计算当前进度 + if(_this.element!=null){ + if(!_this.isDescPlay){ + for(let i=0;i<_this.tagetsAttr.length;i++){ + let item = _this.tagetsAttr[i] + item.progress = progress + if(!_this.isColorStyle(item.name)){ + let fromN = parseFloat(item.from) + let toN = parseFloat(item.to) + let easeInt = 1 + if(_this.easing!=null){ + let eas = _this.easing! + easeInt = eas(progress) + } + + let current = fromN + (toN - fromN) * (easeInt==1?progress:easeInt); // 根据进度计算当前值 + if(_this.reverse||_this._tyty ){ + current = toN + (fromN - toN) * (easeInt==1?progress:easeInt); + } + if(_this.element!=null){ + _this._setAttr(item.name,current,item.unit,progress,item) + } + }else{ + if(_this.element!=null){ + + _this._setAttr(item.name,0,item.unit,progress,item) + } + } + } + }else{ + if(_this.attrIndex<_this.tagetsAttr.length){ + let item = _this.tagetsAttr[_this.attrIndex] + item.progress = progress + + if(!_this.isColorStyle(item.name)){ + let fromN = parseFloat(item.from) + let toN = parseFloat(item.to) + let easeInt = 1 + if(_this.easing!=null){ + let eas = _this.easing! + easeInt = eas(progress) + } + + let current = fromN + (toN - fromN) * (easeInt==1?progress:easeInt); // 根据进度计算当前值 + if(_this.reverse||_this._tyty ){ + current = toN + (fromN - toN) * (easeInt==1?progress:easeInt); + } + if(_this.element!=null){ + _this._setAttr(item.name,current,item.unit,progress,item) + } + }else{ + if(_this.element!=null){ + _this._setAttr(item.name,0,item.unit,progress,item) + } + } + + } + } + + } + + + if(_this.pauseing){ + if(_this.canFrameIds!=null){ + cancelAnimationFrame(_this.canFrameIds) + } + _this.running = false + console.log(_this.pauseing,"动画暂停") + _this.progress = progress + return; + } + + // console.log(_this.running,"动画结束") + if(progress>=1||_this._isStopping){ + + if(_this.isDescPlay&&_this.attrIndex<_this.tagetsAttr.length){ + _this.attrIndex +=1; + _this.progress = 0 + _this._run_web(); + return; + } + + if(_this.canFrameIds!=null) { + cancelAnimationFrame(_this.canFrameIds) + } + _this.attrIndex = 0; + _this.progress = 0 + if(_this.tyty){ + _this._tyty = !_this._tyty + } + if(_this.loop==-1){ + _this._run_web(); + return; + }else{ + _this._loop+=1; + if(_this._loop<_this.loop){ + _this._run_web(); + return; + } + } + + _this.running = false + _this.completeCallBack() + return; + } + + if (progress < 1 && _this.running) { + _this.doCallBack(progress) + _this.canFrameIds = requestAnimationFrame(run) + } + } + _this.startCallBack() + + run() + // #endif + } + + private _run_weapp() { + // #ifdef MP + let _this = this; + _this.startTime = 0 + clearTimeout(_this.dhid) + function run(){ + if (_this.startTime<=0) { + _this.startTime = Date.now(); // 记录动画开始时间 + } + const progress = Math.min((Date.now() - _this.startTime) / _this.duration + _this.progress, 1); // 计算当前进度 + if(_this.element!=null){ + if(!_this.isDescPlay){ + for(let i=0;i<_this.tagetsAttr.length;i++){ + let item = _this.tagetsAttr[i] + item.progress = progress + if(!_this.isColorStyle(item.name)){ + let fromN = parseFloat(item.from) + let toN = parseFloat(item.to) + let easeInt = 1 + if(_this.easing!=null){ + let eas = _this.easing! + easeInt = eas(progress) + } + + let current = fromN + (toN - fromN) * (easeInt==1?progress:easeInt); // 根据进度计算当前值 + if(_this.reverse||_this._tyty ){ + current = toN + (fromN - toN) * (easeInt==1?progress:easeInt); + } + if(_this.element!=null){ + _this._setAttr(item.name,current,item.unit,progress,item) + } + }else{ + if(_this.element!=null){ + + _this._setAttr(item.name,0,item.unit,progress,item) + } + } + } + }else{ + if(_this.attrIndex<_this.tagetsAttr.length){ + let item = _this.tagetsAttr[_this.attrIndex] + item.progress = progress + + if(!_this.isColorStyle(item.name)){ + let fromN = parseFloat(item.from) + let toN = parseFloat(item.to) + let easeInt = 1 + if(_this.easing!=null){ + let eas = _this.easing! + easeInt = eas(progress) + } + + let current = fromN + (toN - fromN) * (easeInt==1?progress:easeInt); // 根据进度计算当前值 + if(_this.reverse||_this._tyty ){ + current = toN + (fromN - toN) * (easeInt==1?progress:easeInt); + } + if(_this.element!=null){ + _this._setAttr(item.name,current,item.unit,progress,item) + } + }else{ + if(_this.element!=null){ + _this._setAttr(item.name,0,item.unit,progress,item) + } + } + + } + } + + } + + + if(_this.pauseing){ + clearTimeout(_this.dhid) + _this.running = false + console.log(_this.pauseing,"动画暂停") + _this.progress = progress + return; + } + + // console.log(_this.running,"动画结束") + if(progress>=1||_this._isStopping){ + + if(_this.isDescPlay&&_this.attrIndex<_this.tagetsAttr.length){ + _this.attrIndex +=1; + _this.progress = 0 + _this._run_weapp(); + return; + } + + clearTimeout(_this.dhid) + _this.attrIndex = 0; + _this.progress = 0 + if(_this.tyty){ + _this._tyty = !_this._tyty + } + if(_this.loop==-1){ + _this._run_weapp(); + return; + }else{ + _this._loop+=1; + if(_this._loop<_this.loop){ + _this._run_weapp(); + return; + } + } + + _this.running = false + _this.completeCallBack() + return; + } + + + if (progress < 1 && _this.running) { + _this.dhid = setTimeout(()=>{ + _this.doCallBack(progress) + run() + }, 6); // 递归调用自身,实现动画效果 + } + + } + _this.startCallBack() + run() + + // #endif + + } + + private _run_andriod() { + // #ifdef APP-ANDROID + let _this = this; + _this.startTime = 0 + let dhid = 0 + if(this.ChoreographerDemo==null){ + this.ChoreographerDemo = Choreographer.getInstance(); + }else{ + if(this.FrameCallbackCallFun!=null){ + _this.ChoreographerDemo!.removeFrameCallback(this.FrameCallbackCallFun!) + } + } + class frameCallback extends Choreographer.FrameCallback { + override doFrame(frameTimeNanos:Long) { + + if (_this.startTime<=0) { + _this.startTime = Date.now(); // 记录动画开始时间 + } + const progress = Math.min((Date.now() - _this.startTime) / _this.duration + _this.progress, 1); // 计算当前进度 + if(_this.element!=null){ + + if(!_this.isDescPlay){ + for(let i=0;i<_this.tagetsAttr.length;i++){ + let item = _this.tagetsAttr[i] + if(!_this.isColorStyle(item.name)){ + let fromN = parseFloat(item.from) + let toN = parseFloat(item.to) + let easeInt = 1 + if(_this.easing!=null){ + let eas = _this.easing! + easeInt = eas(progress) + } + + let current = fromN + (toN - fromN) * (easeInt==1?progress:easeInt); // 根据进度计算当前值 + if(_this.reverse||_this._tyty ){ + current = toN + (fromN - toN) * (easeInt==1?progress:easeInt); + } + if(_this.element!=null){ + _this._setAttr(item.name,current,item.unit,progress,item) + } + }else{ + if(_this.element!=null){ + _this._setAttr(item.name,0,item.unit,progress,item) + } + } + } + }else{ + if(_this.attrIndex<_this.tagetsAttr.length){ + let item = _this.tagetsAttr[_this.attrIndex] + item.progress = progress + + if(!_this.isColorStyle(item.name)){ + let fromN = parseFloat(item.from) + let toN = parseFloat(item.to) + let easeInt = 1 + if(_this.easing!=null){ + let eas = _this.easing! + easeInt = eas(progress) + } + + let current = fromN + (toN - fromN) * (easeInt==1?progress:easeInt); // 根据进度计算当前值 + if(_this.reverse||_this._tyty ){ + current = toN + (fromN - toN) * (easeInt==1?progress:easeInt); + } + if(_this.element!=null){ + _this._setAttr(item.name,current,item.unit,progress,item) + } + }else{ + if(_this.element!=null){ + _this._setAttr(item.name,0,item.unit,progress,item) + } + } + + } + } + + + } + + + + if(progress>=1||_this._isStopping){ + + if(_this.isDescPlay&&_this.attrIndex<_this.tagetsAttr.length){ + _this.attrIndex +=1; + _this.progress = 0 + _this._run_andriod(); + return; + } + + + _this.progress = 0 + if(_this.tyty){ + _this._tyty = !_this._tyty + } + if(_this.loop==-1){ + _this._run_andriod(); + return; + }else{ + _this._loop+=1; + if(_this._loop<_this.loop){ + _this._run_andriod(); + return; + } + } + _this.running = false + _this.completeCallBack() + return; + } + + if(_this.pauseing){ + _this.running = false + console.log(_this.pauseing,"动画暂停") + _this.progress = progress + return; + } + + + if (progress < 1 && _this.running) { + _this.doCallBack(progress) + _this.ChoreographerDemo!.postFrameCallback(this); + } + + + } + }; + + _this.startCallBack() + this.FrameCallbackCallFun = new frameCallback() + _this.ChoreographerDemo!.postFrameCallback(this.FrameCallbackCallFun!); + + // #endif + + } + + private __run_web() { + // #ifdef H5 + let _this = this; + if(_this.canFrameIds!=null) { + cancelAnimationFrame(_this.canFrameIds) + } + function run(){ + _this.enterCallFun() + if(_this._isStopping){ + _this.running = false + + if(_this.canFrameIds!=null) { + cancelAnimationFrame(_this.canFrameIds) + } + return; + } + if (_this.running) { + _this.canFrameIds = requestAnimationFrame(run) + } + } + run() + // #endif + } + + private __run_andriod() { + // #ifdef APP-ANDROID + let _this = this; + + if(this.ChoreographerDemo==null){ + this.ChoreographerDemo = Choreographer.getInstance(); + }else{ + if(this.FrameCallbackCallFun!=null){ + _this.ChoreographerDemo!.removeFrameCallback(this.FrameCallbackCallFun!) + } + } + class frameCallback extends Choreographer.FrameCallback { + override doFrame(frameTimeNanos:Long) { + _this.enterCallFun() + if(_this._isStopping){ + _this.running = false + return; + } + if (_this.running) { + _this.ChoreographerDemo!.postFrameCallback(this); + } + } + }; + this.FrameCallbackCallFun = new frameCallback() + _this.ChoreographerDemo!.postFrameCallback(this.FrameCallbackCallFun!); + + // #endif + + } + + + private __run_weapp(){ + // #ifdef MP + let _this = this; + clearTimeout(_this.dhid) + function run(){ + _this.enterCallFun() + if(_this._isStopping){ + _this.running = false + clearTimeout(_this.dhid) + return; + } + if (_this.running) { + _this.dhid = setTimeout(run, 6); + } + } + run() + // #endif + } + /** + * 启动动画 + */ + play():xAnimate { + if(this.running) return this; + this.running = true; + // 开始动画 + this._isStopping = false; + this.pauseing = false; + this._loop = 0 + this.attrIndex =0; + // #ifdef H5 || APP-IOS || APP-HARMONY + this._run_web(); + // #endif + // #ifdef APP-ANDROID + this._run_andriod(); + // #endif + // #ifdef MP + this._run_weapp(); + // #endif + + return this; + } + + /** + * 停止,会让动画直接结束,把目标值直接前进到结束的地方。 + */ + stop():xAnimate { + let _this = this; + this._isStopping = true; + this.progress = 0 + this.attrIndex = _this.tagetsAttr.length + + // #ifdef WEB || APP-IOS + if(_this.canFrameIds!=null){ + cancelAnimationFrame(_this.canFrameIds) + } + // #endif + + // #ifdef APP-ANDROID + + if(this.ChoreographerDemo==null){ + this.ChoreographerDemo = Choreographer.getInstance(); + }else{ + if(this.FrameCallbackCallFun!=null){ + this.ChoreographerDemo!.removeFrameCallback(this.FrameCallbackCallFun!) + } + } + // #endif + + // #ifdef MP + clearTimeout(_this.dhid) + // setTimeout(function(){ + // for(let i=0;i<_this.tagetsAttr.length;i++){ + // let item = _this.tagetsAttr[i] + // item.now = item.to; + // if(_this.element!=null){ + // _this.element!.style!.setProperty(item.name,(_this.reverse?item.from:item.to)+item.unit) + // } + // } + // _this.reverse = false; + // },10) + // _this.running = false; + // #endif + return this; + } + /** + * 暂停,会保留当前的动画效果,不会直接结束。 + */ + pause():xAnimate { + this.pauseing = true; + return this; + } + /** + * 刷新回调函数 + */ + enterFrame(evt:()=>void){ + this.stop() + this.enterCallFun=evt; + this.running = true; + this._isStopping = false + // #ifdef WEB || APP-IOS + this.__run_web() + // #endif + // #ifdef APP-ANDROID + this.__run_andriod(); + // #endif + + // #ifdef MP + this.__run_weapp(); + // #endif + + } + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xCoreColorUtil.uts b/uni_modules/tmx-ui/core/util/xCoreColorUtil.uts new file mode 100644 index 0000000..07febcc --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xCoreColorUtil.uts @@ -0,0 +1,726 @@ +import { toHex } from "./xCoreUtil.uts"; +import { xConfig } from "../../config/xConfig.uts"; +/** + * 颜色值列表 + */ + +export const colors = new Map([ + ['primary', '#0088ff'], + ['success', '#34c759'], + ['danger', '#ff8d28'], + ['warn', '#F3BF12'], + ['error', '#ff383c'], + ['info', '#f2f2f7'], + + ['kleinblue', '#002FA7'], // 克莱因蓝 + ['chinesered', '#FF0000'], // 中国红 + ['internationalorange', '#FF4F00'], // 国际橙 + ['egyptianvlue', '#1034A6'], // 埃及艳蓝 + ['parisviolet', '#6C3082'], // 巴黎紫 + ['moroccanblue', '#1256A7'], // 摩洛哥蓝 + ['brazilgreen', '#009B3A'], // 巴西绿 + ['britishracinggreen', '#004225'], // 英国赛车绿 + ['indianyellow', '#E3A857'], // 印度黄 + ['australiangold', '#FFDF00'], // 澳大利亚金 + ['venetianred', '#C80815'], // 威尼斯红 + ['majorelleblue', '#6050DC'], // 马若雷蓝 + ['tuscanred', '#7C3030'], // 托斯卡红 + ['naplesyellow', '#FADA5E'], // 那不勒斯黄 + ['capumortuum', '#592720'], // 死者之首 + ['mayablue', '#73C2FB'], // 玛雅蓝 + ['persianrose', '#FE28A2'], // 波斯玫瑰 + ['tyrianpurple', '#66023C'], // 泰尔紫 + ['saharasand', '#F1E788'], // 撒哈拉沙 + ['burmeseruby', '#B00A0A'], // 缅甸红宝石 + + ['transparent', 'rgba(0,0,0,0)'], + ['aliceblue', '#F0F8FF'], + ['antiquewhite', '#FAEBD7'], + ['aqua', '#00FFFF'], + ['aquamarine', '#7FFFD4'], + ['azure', '#F0FFFF'], + ['beige', '#F5F5DC'], + ['bisque', '#FFE4C4'], + ['black', '#000000'], + ['blanchedalmond', '#FFEBCD'], + ['blue', '#0000FF'], + ['blueviolet', '#8A2BE2'], + ['brown', '#A52A2A'], + ['burlywood', '#DEB887'], + ['cadetblue', '#5F9EA0'], + ['chartreuse', '#7FFF00'], + ['chocolate', '#D2691E'], + ['coral', '#FF7F50'], + ['cornflowerblue', '#6495ED'], + ['cornsilk', '#FFF8DC'], + ['crimson', '#DC143C'], + ['cyan', '#00FFFF'], + ['darkblue', '#00008B'], + ['darkcyan', '#008B8B'], + ['darkgoldenrod', '#B8860B'], + ['darkgray', '#A9A9A9'], + ['darkgreen', '#006400'], + ['darkkhaki', '#BDB76B'], + ['darkmagenta', '#8B008B'], + ['darkolivegreen', '#556B2F'], + ['darkorange', '#FF8C00'], + ['darkorchid', '#9932CC'], + ['darkred', '#8B0000'], + ['darksalmon', '#E9967A'], + ['darkseagreen', '#8FBC8F'], + ['darkslateblue', '#483D8B'], + ['darkslategray', '#2F4F4F'], + ['darkturquoise', '#00CED1'], + ['darkviolet', '#9400D3'], + ['deeppink', '#FF1493'], + ['deepskyblue', '#00BFFF'], + ['dimgray', '#696969'], + ['dodgerblue', '#1E90FF'], + ['firebrick', '#B22222'], + ['floralwhite', '#FFFAF0'], + ['forestgreen', '#228B22'], + ['fuchsia', '#FF00FF'], + ['gainsboro', '#DCDCDC'], + ['ghostwhite', '#F8F8FF'], + ['gold', '#FFD700'], + ['goldenrod', '#DAA520'], + ['gray', '#808080'], + ['green', '#008000'], + ['greenyellow', '#ADFF2F'], + ['honeydew', '#F0FFF0'], + ['hotpink', '#FF69B4'], + ['indianred', '#CD5C5C'], + ['indigo', '#4B0082'], + ['ivory', '#FFFFF0'], + ['khaki', '#F0E68C'], + ['lavender', '#E6E6FA'], + ['lavenderblush', '#FFF0F5'], + ['lawngreen', '#7CFC00'], + ['lemonchiffon', '#FFFACD'], + ['lightblue', '#ADD8E6'], + ['lightcoral', '#F08080'], + ['lightcyan', '#E0FFFF'], + ['lightgoldenrodyellow', '#FAFAD2'], + ['lightgray', '#D3D3D3'], + ['lightgreen', '#90EE90'], + ['lightpink', '#FFB6C1'], + ['lightsalmon', '#FFA07A'], + ['lightseagreen', '#20B2AA'], + ['lightskyblue', '#87CEFA'], + ['lightslategray', '#778899'], + ['lightsteelblue', '#B0C4DE'], + ['lightyellow', '#FFFFE0'], + ['lime', '#00FF00'], + ['limegreen', '#32CD32'], + ['linen', '#FAF0E6'], + ['magenta', '#FF00FF'], + ['maroon', '#800000'], + ['mediumaquamarine', '#66CDAA'], + ['mediumblue', '#0000CD'], + ['mediumorchid', '#BA55D3'], + ['mediumpurple', '#9370DB'], + ['mediumseagreen', '#3CB371'], + ['mediumslateblue', '#7B68EE'], + ['mediumspringgreen', '#00FA9A'], + ['mediumturquoise', '#48D1CC'], + ['mediumvioletred', '#C71585'], + ['midnightblue', '#191970'], + ['mintcream', '#F5FFFA'], + ['mistyrose', '#FFE4E1'], + ['moccasin', '#FFE4B5'], + ['navajowhite', '#FFDEAD'], + ['navy', '#000080'], + ['oldlace', '#FDF5E6'], + ['olive', '#808000'], + ['olivedrab', '#6B8E23'], + ['orange', '#FFA500'], + ['orangered', '#FF4500'], + ['orchid', '#DA70D6'], + ['palegoldenrod', '#EEE8AA'], + ['palegreen', '#98FB98'], + ['paleturquoise', '#AFEEEE'], + ['palevioletred', '#DB7093'], + ['papayawhip', '#FFEFD5'], + ['peachpuff', '#FFDAB9'], + ['peru', '#CD853F'], + ['pink', '#FFC0CB'], + ['plum', '#DDA0DD'], + ['powderblue', '#B0E0E6'], + ['purple', '#800080'], + ['rebeccapurple', '#663399'], + ['red', '#FF0000'], + ['rosybrown', '#BC8F8F'], + ['royalblue', '#4169E1'], + ['saddlebrown', '#8B4513'], + ['salmon', '#FA8072'], + ['sandybrown', '#F4A460'], + ['seagreen', '#2E8B57'], + ['seashell', '#FFF5EE'], + ['sienna', '#A0522D'], + ['silver', '#C0C0C0'], + ['skyblue', '#87CEEB'], + ['slateblue', '#6A5ACD'], + ['slategray', '#708090'], + ['snow', '#FFFAFA'], + ['springgreen', '#00FF7F'], + ['steelblue', '#4682B4'], + ['tan', '#D2B48C'], + ['teal', '#008080'], + ['thistle', '#D8BFD8'], + ['tomato', '#FF6347'], + ['turquoise', '#40E0D0'], + ['violet', '#EE82EE'], + ['wheat', '#F5DEB3'], + ['white', '#FFFFFF'], + ['whitesmoke', '#F5F5F5'], + ['yellow', '#FFFF00'], + ['yellowgreen', '#9ACD32'] + +]) + +export function isValidColor(color : string) : boolean { + // return chroma.valid(color); + const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + const rgbRegex = /^rgb\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\)$/; + const rgbaRegex = /^rgba\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*((1(\.0{1,2})?)|(0(\.\d{1,2})?))\)$/; + const hslRegex = /^hsl\((\d{1,3}), (\d{1,3})%, (\d{1,3})%\)$/; + const hslaRegex = /^hsla\(\s*((\d{1,2}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)\s*,\s*((\d{1,2}|\d{0,1}\d{1}\d{1}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)%\s*,\s*((\d{1,2}|\d{0,1}\d{1}\d{1}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)%\s*,\s*((1|0(\.\d{1,2})?|(\.\d{1,2})))\)$/i; + + + if (color == '') { + return false; // 颜色值为空 + } else if (color === 'inherit' || color === 'transparent') { + return false; // 特殊颜色值 + } else if (color === 'currentColor') { + return false; // currentColor 不是有效的颜色值 + } else if (hexRegex.test(color) || rgbRegex.test(color) || rgbaRegex.test(color) || hslRegex.test(color) || hslaRegex.test(color)) { + return true; // 符合颜色值的格式 + } + return false; +} +/** + * 获取默认的颜色值 + * @param [string] 颜色名称或者16进制颜色值 + */ +export function getDefaultColor(sColor : string) : string { + if (sColor == "") return "" + let sc = sColor.toLocaleLowerCase().trim().replace(" ", ""); + + if (isValidColor(sc)) { + // 如果符合所有颜色值,进行转换为16进制。css方便统一解析。 + return sc; + } + let colorhtme = xConfig.theme.get(sc) + // 检测是否是颜色名称。 + let sco = colorhtme==null?colors.get(sc):colorhtme; + if (typeof sco == 'string') return sco as string; + return colors.get("primary")!; +} + +/** + * 16进制转rgb + */ +export function hexToRgb(sColors : string) : UTSJSONObject { + if (sColors == "") { + return { r: 0, g: 0, b: 0, a: 0 } + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + + let p : number[] = arr.map((val : string) : number => parseInt(val)); + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } + } + if (p.length == 3) { + arr.push('1') + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: parseFloat(arr[3]) + } + } else { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } + } +} +/** + * rgb转hsl + */ +export function rgbToHsl(rgb : UTSJSONObject) : UTSJSONObject { + let r = rgb.getNumber("r") + r = r as number / 255 + let g = rgb.getNumber("g") + g = g as number / 255 + let b = rgb.getNumber("b") + b = b as number / 255 + let a = rgb.getNumber("a") + + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + let maxmindiff = max - min; + let maxmindiffAdd = max + min; + // #ifdef APP-ANDROID && uniVersion >=4.31 + maxmindiff = maxmindiff.toDouble() + maxmindiffAdd = maxmindiffAdd.toDouble() + // #endif + let h = 60 * (4 + (r - g) / maxmindiff); + let sdy = 2 - max - min + // #ifdef APP-ANDROID && uniVersion >=4.31 + sdy = sdy.toDouble() + // #endif + let s = (max - min) / sdy; + let l = (max + min) / 2; + + if (max === r) { + h = (60 * (g - b)) / maxmindiff; + } else if (max === g) { + h = 60 * (2 + (b - r) / maxmindiff); + } + + if (h < 0) { + h += 360; + } + + + if (max === min) { + s = 0; + } else if (l < 0.5) { + s = (max - min) / maxmindiffAdd; + } + + return { h: h, s: s * 100, l: l * 100, a: a }; +} + +/** + * hsl转rgb + */ +export function hslToRgb(hsl : UTSJSONObject) : UTSJSONObject { + let h = hsl.getNumber("h")! + let s = hsl.getNumber("s")! + let l = hsl.getNumber("l")! + let a = hsl.getNumber("a")! + + h = h / 360; + s = s / 100; + l = l / 100; + let r = l; + let g = l; + let b = l; + + function hue2rgb(pxx : number, q : number, txs : number) : number { + let t = txs; + let p = pxx; + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + + + if (s > 0) { + let q = l * (1 + s); + if (l >= 0.5) { + q = l + s - l * s; + } + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + + } + + r = Math.round(r * 255); + g = Math.round(g * 255); + b = Math.round(b * 255); + return { r, g, b, a }; +} + +/** + * rgb转16进制 + */ +export function rgbToHex(rgb : UTSJSONObject) : string { + let r = rgb.getNumber("r")! + let g = rgb.getNumber("g")! + let b = rgb.getNumber("b")! + let a = rgb.getNumber("a")! + return "#" + toHex(r) + toHex(g) + toHex(b) + toHex(a * 255) +} +/** + * rgb转16进制 + */ +export function rgbToHexNoAlpha(rgb : UTSJSONObject) : string { + let r = rgb.getNumber("r")! + let g = rgb.getNumber("g")! + let b = rgb.getNumber("b")! + + return "#" + toHex(r) + toHex(g) + toHex(b) +} +export function hslaToCss(hsl : UTSJSONObject) : string { + + let rgb = hslToRgb(hsl) + + return rgbToHex(rgb) +} + +export function hslaToRgbCss(hsl : UTSJSONObject) : string { + + let rgb = hslToRgb(hsl) + let r = rgb.getNumber("r")! + let g = rgb.getNumber("g")! + let b = rgb.getNumber("b")! + let a = rgb.getNumber("a")! + return `rgba(${r},${g},${b},${a})` +} + +// 根据 HSLA 颜色计算亮度 +export function getLuminance(color : UTSJSONObject, type = "rgba") : number { + + + let colordefault : UTSJSONObject = type == 'rgba' ? color : hslToRgb(color); + const r = colordefault.getNumber("r")! + const g = colordefault.getNumber("g")! + const b = colordefault.getNumber("b")! + const rs = r / 255 + const gs = g / 255 + const bs = b / 255 + const rl = Math.pow(rs <= 0.03928 ? rs / 12.92 : ((rs + 0.055) / 1.055), 2.4); + const gl = Math.pow(gs <= 0.03928 ? gs / 12.92 : ((gs + 0.055) / 1.055), 2.4); + const bl = Math.pow(bs <= 0.03928 ? bs / 12.92 : ((bs + 0.055) / 1.055), 2.4); + + return 0.2126 * rl + 0.7152 * gl + 0.0722 * bl; +} + +/** + * 对颜色加深 + */ +export function colorAddDeepen(sColor : string) : string { + + let rgb = hexToRgb(getDefaultColor(sColor)); + + let hsl = rgbToHsl(rgb); + + let l = hsl.getNumber("l")! - 5; + l = Math.max(0, Math.min(l, 100)) + + return hslaToRgbCss({ h: hsl.getNumber("h"), s: hsl.getNumber("s"), l, a: hsl.getNumber("a")! }) +} +/** + * 对颜色提亮 + */ +export function colorAddBrighten(sColor : string) : string { + let rgb = hexToRgb(getDefaultColor(sColor)); + let hsl = rgbToHsl(rgb); + let l = hsl.getNumber("l")! + 10; + l = Math.max(0, Math.min(l, 100)) + return rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s: hsl.getNumber("s"), l, a: hsl.getNumber("a")! })) +} + + + + +/** + * 获取浅色系主题,根据颜色值计算。返回正常值和hover值。 + */ +export function colorGetThint(sColor : string) { + let rgb = hexToRgb(getDefaultColor(sColor)); + let hsl = rgbToHsl(rgb); + let s = hsl.getNumber("s")!; + // let l = hsl.getNumber("l"); + if (Math.ceil(s) > 0) { + s = 45 + } + return { + default: rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s, l: 93, a: hsl.getNumber("a")! })), + hover: rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s, l: 85, a: hsl.getNumber("a")! })) + } +} +/** + * 获取正常主题,根据颜色值计算。返回正常值和hover值。 + */ +export function colorGetHover(sColor : string) { + + return { + default: sColor, + hover: colorAddDeepen(sColor) + } +} + + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getDefaultColorObj(color : string, hoverColor : string) : UTSJSONObject { + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + let shadow = hslaToRgbCss({ h: hsla.getNumber("h")!, s: (hsla.getNumber("s")!) == 0 ? 0 : 60, l: 40, a: 0.4 }); + let shadowHOver = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: (hoverHsla.getNumber("s")!) == 0 ? 0 : 60, l: 40, a: 0.4 }); + if ((hsla.getNumber("h")!) == 0 && (hsla.getNumber("s")!) == 0) { + shadow = "transparent" + } + if ((hoverHsla.getNumber("h")!) == 0 && (hoverHsla.getNumber("s")!) == 0) { + shadowHOver = "transparent" + } + let lightnum = getLuminance(hoverHsla, 'hsla'); + let h = hsla.getNumber('h')!; + let maxLightNum = 0.55 + if(h>=31&&h<=90){ + maxLightNum = 0.60 + } + let o = { + default: { + background: hslaToRgbCss(hsla), + borderColor: hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: Math.min(Math.max(0, hsla.getNumber("l")! - 3), hsla.getNumber("l")!) }), + fontColor: lightnum < maxLightNum && hsla.getNumber("a")! > 0.1 ? '#ffffff' : '#000000', + shadow: shadow + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: Math.min(Math.max(0, hoverHsla.getNumber("l")! - 5), hoverHsla.getNumber("l")!) }), + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: Math.max(Math.max(0, hoverHsla.getNumber("l")! - 10), hoverHsla.getNumber("l")!) }), + fontColor: lightnum < maxLightNum && hoverHsla.getNumber("a")! > 0.1 ? '#ffffff' : '#000000', + shadow: shadowHOver + } + } as UTSJSONObject + + return o; +} +const hslColorMap = new Map([ + ['红色', [331, 360]], // 0-30度 + ['红色', [0, 30]], // 0-30度 + ['橙色', [31, 60]], // 30-60度 + ['黄色', [61, 90]], // 60-90度 + ['绿色', [91, 150]], // 90-150度 + ['青色', [151, 210]], // 150-210度 + ['蓝色', [211, 270]], // 210-270度 + ['紫色', [271, 330]] // 270-330度 +]); + + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getTextColorObj(color : string, hoverColor : string, isCoverDark ?: boolean) : UTSJSONObject { + let dark = isCoverDark == null ? false : isCoverDark + // #ifdef WEB + dark = isCoverDark == undefined ? false : dark + // #endif + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hsla2 : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // let fontcolor = getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l:30 }) + // let bordercolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark==true?21:92 }) + let bgcolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark == true ? 20 : 95 }) + + if (dark) { + let p = hsla2; + // p.set('l',90) + // fontcolor = hslaToRgbCss(p) + p.set('l', 20) + p.set('s', (p.getNumber('s')) != 0 ? 0 : 20) + bgcolor = hslaToRgbCss(p) + // p.set('l',22) + // bordercolor = hslaToRgbCss(p) + } + let lightnum = getLuminance(hoverHsla, 'hsla'); + let h = hsla.getNumber('h')!; + let maxLightNum = 0.3 + // if(h>=31&&h<=90){ + // maxLightNum = 1 + // } + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let o = { + default: { + background: "transparent", + borderColor: "transparent", + fontColor: lightnum < maxLightNum && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + }, + active: { + background: bgcolor, + borderColor: "transparent", + fontColor: lightnum < maxLightNum && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getThinColorObj(color : string, hoverColor : string, isCoverDark ?: boolean) : UTSJSONObject { + let dark = isCoverDark == null ? false : isCoverDark + // #ifdef WEB + dark = isCoverDark == undefined ? false : dark + // #endif + + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let fontcolor = getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: 30 }) + let bordercolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark == true ? 21 : 92 }) + let bgcolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark == true ? 20 : 95 }) + let lightnum = getLuminance(hoverHsla, 'hsla'); + if (dark) { + let p = hsla; + p.set('l', 98) + fontcolor = hslaToRgbCss(p) + p.set('l', 20) + p.set('s', (p.getNumber('s')) != 0 ? 5 : 20) + bgcolor = hslaToRgbCss(p) + p.set('l', 22) + bordercolor = hslaToRgbCss(p) + } + let o = { + default: { + background: bgcolor, + borderColor: bordercolor, + fontColor: fontcolor, + shadow: "transparent", + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: dark ? 10 : 50, a: hoverHsla.getNumber("a")!, l: dark == true ? 15 : 88 }), + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: 0, l: dark == true ? 18 : 80 }), + fontColor: lightnum < 0.3 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 64 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getOutlineColorObj(color : string, hoverColor : string, isCoverDark ?: boolean) : UTSJSONObject { + let dark = isCoverDark == null ? false : isCoverDark + // #ifdef WEB + dark = isCoverDark == undefined ? false : dark + // #endif + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let lightnum = getLuminance(hoverHsla, 'hsla'); + let h = hsla.getNumber('h')!; + let borderLight = 70; + // let maxLightNum = 0.55 + if(dark){ + borderLight = 50 + } + let o = { + default: { + background: 'transparent', + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: 1, l: borderLight+5 }), + fontColor: lightnum < 0.6 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + }, + + active: { + background: 'transparent', + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: 1, l: borderLight }), + fontColor: lightnum < 0.6 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 设置颜色的亮度值。29 + * isCoverDark:是根据亮度值,是否要设置n的值,如果n超过了 + * 指定的30就不操作。 + */ +export function setTextColorLightByDark(color : string) : string { + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let l = hsla.getNumber('l')! + let s = hsla.getNumber('s')! + if (l < 30) { + if (s > 0) { + hsla.set('l', 50) + } else { + hsla.set('l', 100) + } + + } + + return hslaToRgbCss(hsla) +} +/** + * 变动的颜色是否需要变深。如果不需要返回原始颜色 + * 如果果需要自动加深。 + */ +export function setBgColorLightByDark(color : string) : string { + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let l = hsla.getNumber('l')! + let s = hsla.getNumber('s')! + if (s == 0 && l > 50) { + hsla.set('l', 100 - l) + } + if (s > 0) { + if (l > 50) { + hsla.set('l', 100 - l) + } + } + return hslaToRgbCss(hsla) +} + +export function isBlackAndWhite(color : string) : boolean { + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let s = hsla.getNumber('s')! + return s == 0 +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xCoreUtil.uts b/uni_modules/tmx-ui/core/util/xCoreUtil.uts new file mode 100644 index 0000000..53e391e --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xCoreUtil.uts @@ -0,0 +1,333 @@ +import { getDefaultColor } from "./xCoreColorUtil.uts"; +import { xConfig } from "../../config/xConfig.uts" +/** + * 数字转16进制 + */ +function toHex(numbers : number) : string { + // let i = 0 as number + // if (numbers === i) { + // return '00'; + // } + // let hex = ''; + // const hexChars = '0123456789abcdef'; + // while (numbers > 0) { + // const remainder = numbers % 16; + // hex = hexChars[remainder] + hex; + // numbers = Math.floor(numbers / 16); + // } + let n = numbers.toString(16) as string; + if(n.length==1){ + n = '0'+n + } + return n; +} + +/** + * 随机一个uid + * @param rdix 随机因子 + * @param length 取的长度 + * @param isAddStr 是否限制随机结果中的长度,不允许输出长度 + * @returns String + */ +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifndef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length); + // #endif + + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} + + +/** + * 给定一个值,来填充边距所需要的数组值 + * @param val any + * @returns [左,上,右,下] + */ +function toFillMarginAr(val : number[]) : number[] { + + let ar : number[] = []; + + if (val.length == 1) { + let firstEl = val[0]; + ar = [firstEl, firstEl, firstEl, firstEl] + + } else if (val.length == 2) { + ar = [val[0], val[1], val[0], val[1]] + + } else if (val.length == 3) { + ar = [val[0], val[1], val[2], 0] + } + + + return ar; +} + + +function rpx2px(n : number, _w = 750) : number { + let r = n + // #ifdef APP + r = uni.rpx2px(n); + // #endif + // #ifdef H5 + + function getLayoutRatio() : number { + const devicePixelRatio = window.devicePixelRatio || 1; + const screenWidth = window.innerWidth + + if (screenWidth <= 950) { + // 小屏幕设备 + return screenWidth / 750; + } else { + return 0.5 + } + } + + if (uni?.rpx2px) { + r = uni.rpx2px(n) + } else { + r = getLayoutRatio() * n + } + // #endif + + return r +} + +function px2dp(n : number) : number { + let w = n; + // #ifdef APP + + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + // 屏幕逻辑像素的宽度 + let width = mets.widthPixels; + // 屏幕宽度 + let screenWidth = uni.getWindowInfo().screenWidth + w = n / (width / screenWidth); + // #endif + return w +} + +function checkIsCssUnit(str : string|number, unit : string) : string { + if(typeof str != 'string'){ + return (str as number).toString() + unit; + } + let s = str as string; + if (s.indexOf("px") > -1 || s.indexOf("%") > -1 || s.indexOf("auto") > -1 || s.indexOf("vw") > -1 || s.indexOf("vh") > -1) { + return s; + } + + return s + (unit==''?'px':unit) +} + +// function checkIsCssUnit(str : string|number, unit : string) : string { +// let screenWidth = uni.getWindowInfo().windowWidth; +// let base = 0; +// let baseUnit = unit == ''?xConfig.unit:unit; +// if(typeof str != 'string'){ +// base = str as number; +// }else if(typeof str == 'string'){ +// let s = str as string; +// if ( +// s.indexOf("px") > -1 || +// s.indexOf("rpx") > -1 || +// s.indexOf("%") > -1 || +// s.indexOf("auto") > -1 || +// s.indexOf("vw") > -1 || +// s.indexOf("rem") > -1 || +// s.indexOf("em") > -1 || +// s.indexOf("in") > -1 || +// s.indexOf("vh") > -1) +// { +// return s; +// } +// base = parseFloat(s); +// base = isNaN(base)?0:base +// } + +// if(baseUnit=='rpx'){ +// let baseDesize = Math.max(xConfig.designSize,375) +// let baseMaxWidth = Math.max(xConfig.maximumCalculatedSize,375) +// let origSize = 375; +// let ratio = 1 - baseDesize / origSize; +// let maxRatio = screenWidth / baseMaxWidth; +// let baseSize = base - (ratio*base) +// // 说明超过了设定缩放的最大屏幕尺寸。 +// if(maxRatio>=1){ +// base = baseSize; +// }else{ +// const calcRatio = Math.max(screenWidth/baseDesize,1) +// base = calcRatio*baseSize ; +// } +// let baseunitReal = 'px' +// // #ifdef H5 +// if(base<12){ +// base = base/16 +// baseunitReal = "rem" +// } +// // #endif +// return base + baseunitReal +// } + +// return base + baseUnit +// } + +function fillArrayCssValue(val : Array) : string[] { + let ar : string[] = val.map((el : string) : string => { + return checkIsCssUnit(el, xConfig.unit) + }) + if (ar.length == 0) return []; + if (ar.length == 1) return [ar[0], ar[0], ar[0], ar[0]] + if (ar.length == 2) { + return [ar[1], ar[0], ar[1], ar[0]] + } + if (ar.length == 3) return [ar[1], ar[2], '0px', ar[0]] + return [ar[1], ar[2], ar[3], ar[0]]; +} +function fillArrayCssValueByround(val : Array) : string[] { + let ar : string[] = val.map((el : string) : string => { + return checkIsCssUnit(el, xConfig.unit) + }) + if (ar.length == 0) return []; + if (ar.length == 1) return [ar[0], ar[0], ar[0], ar[0]] + if (ar.length == 2) { + return [ar[1], ar[0], ar[1], ar[0]] + } + if (ar.length == 3) return [ar[0], ar[1], ar[0], '0px'] + return [ar[0], ar[1], ar[2], ar[3]]; +} +function fillArrayCssValueBycolor(val : Array) : string[] { + let ar : string[] = val.map((el : string) : string => { + return getDefaultColor(el) + }) + if (ar.length == 0) return []; + if (ar.length == 1) return [ar[0], ar[0], ar[0], ar[0]] + if (ar.length == 2) { + return [ar[1], ar[0], ar[1], ar[0]] + } + if (ar.length == 3) return [ar[1], ar[2], '0px', ar[0]] + return [ar[1], ar[2], ar[3], ar[0]]; +} + +/** + * 对数组进行分组。按数量分组 + */ +function splitArray(target : Array, value : number) : Array> { + var result = [] as Array>; + for (var i = 0; i < target.length; i += value) { + let ml = target.slice(i, i + value); + result.push(ml); + } + return result; +} +/** + * 对数组进行分组。按指定组数量 + */ +function splitArrayByGroup(target : Array, group : number) : Array> { + var groupSize = Math.ceil(target.length / group); + var result = [] as Array>; + for (var i = 0; i < target.length; i += groupSize) { + result.push(target.slice(i, i + groupSize)); + } + return result; +} + +/** + * 获取字符的css单位。 + */ +function getUnit(n ?: string) : string { + if (n == null || n == '') return xConfig.unit; + let unit = n.replace(/[\d|\-|\+|\.]/g, ''); + if (unit == "") { + unit = xConfig.unit; + } + return unit; +} + +/** + * 设置当前页面是否刷新。 + */ +function setPagePullRefresh(enbledpull : boolean) { + // #ifdef APP + let pages = getCurrentPages() + let page = pages[pages.length - 1] + // let pageJson = page.$getPageStyle() + // pageJson.set("enablePullDownRefresh",enbledpull) + page.$setPageStyle({ "enablePullDownRefresh": enbledpull } as UTSJSONObject) + // #endif +} + +/** + * 获取当前的下拉状态。 + */ +function getPagePullRefresh() : boolean { + // #ifdef APP + let pages = getCurrentPages() + let page = pages[pages.length - 1] + let pageJson = page.$getPageStyle() + + let enb = pageJson.get("enablePullDownRefresh") as boolean|null; + if(enb==null) return false; + return enb as boolean; + // #endif + return false; +} + +/** + * 防抖 + */ +function debounce( + func : (args : any) => void, + wait : number, + immediate ?: boolean +) : (args : any) => number | null { + let timeout : number | null = null; + let callNow = immediate == null ? true : (immediate! as boolean); + + // 返回的函数是实际被调用的防抖函数 + return (args : any) : number | null => { + if (timeout != null && callNow == true) { + return timeout; + } + if (timeout != null) { + clearTimeout(timeout! as number); + timeout = null; + } + + // 决定是否立即执行函数 + if (callNow == true) { + + func(args) + timeout = setTimeout(() => { + timeout = null; + }, wait); + return timeout; + } + // 否则,设置定时器以稍后执行函数 + timeout = setTimeout(() => { + func(args) + + }, wait); + return timeout + } +} +export { + toHex, + toFillMarginAr, + getUid, + checkIsCssUnit, + px2dp, + rpx2px, + splitArray, + splitArrayByGroup, + fillArrayCssValue, + fillArrayCssValueByround, + fillArrayCssValueBycolor, + getUnit, + setPagePullRefresh, + getPagePullRefresh, + debounce + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xDate.md b/uni_modules/tmx-ui/core/util/xDate.md new file mode 100644 index 0000000..5ce8757 --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xDate.md @@ -0,0 +1,545 @@ +# xDate + +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +日期处理库 + +### 说明 +这是tmui4.0|XUI的日期处理库,提供了丰富的日期操作功能。简单好上手,单库只有14kb,能满足大部分日期处理需求。库采用类Jq式的链式调用,使用灵活方便。 + +### 兼容性 + +| IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | + +### 导入使用 +在页面中直接使用快捷导入即可使用,它是class类,需要new +```ts +import {xDate, createDate} from "@/uni_modules/tmx-ui/index.uts" +// 打印当前 +console.log(new xDate().date) +// 辅助函数用来创建系统的Date对象时间 +console.log(createDate('2023-3-1')) +``` + +### 创建实例 +支持string, number, Date, null四种类型 +```ts +import {xDate, createDate} from "@/uni_modules/tmx-ui/index.uts" +// 为空,默认是现在 +const now = new xDate() +// 传递字符串的毫秒数 +const date1 = new xDate('15888888') +// 传递字符串的时间 +const date2 = new xDate('2023-2-3') +const date3 = new xDate('2023/2/3') +// 传递Date对象 +const date4 = new xDate(new Date()) +``` +### 实例方法 +| 名称 | 参数 | 介绍 | +| --- | --- | --- | +| format | s: string \| null = null | 格式化日期,默认格式为YYYY/MM/DD hh:mm:ss | +| getYear | 无 | 获取当前年份 | +| getMonth | 无 | 获取当前月份(0-11,0代表1月) | +| getMonthName | useShort: boolean = false | 获取当前月份的名称(支持国际化) | +| getDate | 无 | 获取当前日(1-31) | +| getHours | 无 | 获取当前小时(0-23) | +| getMinutes | 无 | 获取当前分钟(0-59) | +| getSeconds | 无 | 获取当前秒(0-59) | +| getDateOf | d: xDateTypeTime = 'd' | 获取指定类型的数据,d可为'y'年,'m'月,'d'日,'h'时,'M'分,'s'秒,'ms'毫秒,'w'周 | +| setDateOf | n: number, d: xDateTypeTime = 'd' | 设定日期,支持链式调用 | +| getTime | d: xDateTypeTime | 获取时间戳,可指定单位 | +| getClone | 无 | 获取当前时间的副本 | +| getWeek | 无 | 获取本年的第几周 | +| getDateStartOf | d: 'm' \| 'w' \| 'y' = 'm' | 获取时间的第一天(月/周/年) | +| getDateEndOf | d: 'm' \| 'w' \| 'y' = 'm' | 获取时间的最后一天(月/周/年) | +| getWeekDay | 无 | 获取星期几(0-6,0表示星期天) | +| getWeekDayCn | model: string[] \| null = null, useShort: boolean = true | 获取星期名称(支持国际化) | +| getMonthCountDay | 无 | 获取当前月份的最大天数 | +| getDateInfo | str: string \| null = null | 获取日期详细信息 | +| getDaysOf | d: 'm' \| 'w' = 'm' | 获取日期数组(月/周) | +| add | count: number, d: xDateTypeTime = 'd' | 日期加法操作,支持链式调用 | +| subtraction | count: number, d: xDateTypeTime = 'd' | 日期减法操作,支持链式调用 | +| isBetween | start: xDate, end: xDate, type: xDateTypeTime = 'ms', d: '()' \| '[]' \| '(]' \| '[)' = '[]' | 判断日期是否在区间内 | +| isBetweenOf | targetDate: xDate, d: '>' \| '>=' \| '<' \| '<=' \| '=' = '>', type: xDateTypeTime = 'ms' | 与目标日期比较 | +| fromBetweenLongTime | target: any, model: Map \| null, format: string \| null | 计算与目标时间过了多久(支持国际化) | +| diffTime | target: any, type: xDateTypeTime = 's' | 计算与目标时间相差多少个单位 | +| getQuarter | type: string = '' | 获取季度信息 | +| setDateLocale | locale: xDateLanguage | 设置xDate的语言 | +| getDateLocale | 无 | 获取当前xDate使用的语言 | + + +### 类型定义 + +```ts +// 日期时间单位类型 +export type xDateTypeTime = 'y' | 'm' | 'd' | 'h' | 'M' | 's' | 'ms' | 'w' + +// 季度信息类型 +export type xDateTypeQuarter = { + quarter : number, + start : string, + end : string +} + +// 日期格式类型 +export type DateFormat = 'RFC2822' | 'ISO8601' | 'CUSTOM'; + +// 日期信息类型 +export type xDateDayInfoType = { + year: number, + month: number, + day: number, + hours: number, + minutes: number, + seconds: number, + week: number, + weeks: number, + weekCn: string, + date: string +} + +// 支持的语言类型 +export type xDateLanguage = 'zh-Hans' | 'en' | 'ja' | 'ko' | 'zh-Hant' | 'fr' | 'ru'; + +// 国际化相对时间配置类型 +export type xDateI18nTypeRelativeTime = { + future: string, + past: string, + s: string, + m: string, + mm: string, + h: string, + hh: string, + d: string, + dd: string, + M: string, + MM: string, + y: string, + yy: string +} + +// 国际化配置类型 +export type xDateI18nType = { + weekdays: string[], + weekdaysShort: string[], + months: string[], + monthsShort: string[], + meridiem: (hour: number, minute: number, isLowercase: boolean) => string, + relativeTime: xDateI18nTypeRelativeTime +} +``` + +### 国际化相关API + +```ts +// 设置xDate的语言 +setDateLocale(locale: xDateLanguage): void + +// 获取当前xDate使用的语言 +getDateLocale(): xDateLanguage + +// 获取当前月份的名称 +getMonthName(useShort: boolean = false): string + +// 获取星期名称(支持国际化) +getWeekDayCn(model: string[] | null = null, useShort: boolean = true): string +``` +``` + +### API说明 + +#### 辅助函数 + +##### createDate +```ts +function createDate(dateStrs: string): Date +``` +- 描述:用来解析非标准时间以及各种奇怪的时间格式 +- 参数: + - dateStrs: 日期字符串,支持多种格式如YYYY、YYYY-MM、YYYY-MM-DD等 +- 返回值:Date对象 + +##### dateCovertXdate +```ts +function dateCovertXdate(date: Date): xDate +``` +- 描述:将一个日期转换为xDate对象 +- 参数: + - date: Date对象 +- 返回值:xDate对象 + +#### xDate类方法 + +##### 构造函数 +```ts +constructor(dateStr: string | number | Date | null = null) +``` +- 描述:创建xDate实例 +- 参数: + - dateStr: 可以是字符串、数字、Date对象或null(默认为当前时间) + +##### detectDateFormat +```ts +detectDateFormat(dateStr: string): DateFormat +``` +- 描述:检测字符串的日期格式类型 +- 参数: + - dateStr: 日期字符串 +- 返回值:日期格式类型('RFC2822'、'ISO8601'或'CUSTOM') + +##### format +```ts +format(s: string | null = null): string +``` +- 描述:格式化日期 +- 参数: + - s: 模板,比如YYYY/MM/DD hh:mm:ss,默认为YYYY/MM/DD hh:mm:ss +- 返回值:格式化后的日期字符串 + +##### getYear +```ts +getYear(): number +``` +- 描述:获取当前年 +- 返回值:根据当地时间,返回一个对应于给定日期的年份数字 + +##### getMonth +```ts +getMonth(): number +``` +- 描述:获取当前月(0-11,0代表1月) +- 返回值:一个0到11的整数值 + +##### getMonthName +```ts +getMonthName(useShort: boolean = false): string +``` +- 描述:获取当前月份的名称(支持国际化) +- 参数: + - useShort: 是否使用短名称,默认为false +- 返回值:返回当前语言环境下的月份名称 + +##### getDate +```ts +getDate(): number +``` +- 描述:获取当前天 +- 返回值:返回一个1到31的整数值 + +##### getHours +```ts +getHours(): number +``` +- 描述:获取当前小时 +- 返回值:返回一个0到23之间的整数值 + +##### getMinutes +```ts +getMinutes(): number +``` +- 描述:获取当前分钟 +- 返回值:返回一个0到59的整数值 + +##### getSeconds +```ts +getSeconds(): number +``` +- 描述:获取当前秒 +- 返回值:返回一个0到59的整数值 + +##### getDateOf +```ts +getDateOf(d: xDateTypeTime = 'd'): number +``` +- 描述:获取指定类型的数据 +- 参数: + - d: 'y'年 'm'月 'd'日 'h'时 'M'分 's'秒 'ms'毫秒 'w'周 +- 返回值:指定类型的数值 + +##### setDateOf +```ts +setDateOf(n: number, d: xDateTypeTime = 'd'): xDate +``` +- 描述:设定日期 +- 参数: + - n: 设定的数据 + - d: 比如d=y,那么就是设置本日期的年份数据 +- 返回值:xDate对象实例(支持链式调用) + +##### getTime +```ts +getTime(d: xDateTypeTime): number +``` +- 描述:获取时间戳 +- 参数: + - d: 'y'年 'm'月 'd'日 'h'时 'M'分 's'秒 'ms'毫秒 +- 返回值:返回从UTC时间1970年1月1日午夜开始以毫秒为单位存储的时间值 +- 注意:如果不提供d就默认返回毫秒,比如设置d=m那么后面的h,M,s,ms会被设置为0 + +##### getClone +```ts +getClone(): xDate +``` +- 描述:当前时间的副本 +- 返回值:新的xDate对象 + +##### getWeek +```ts +getWeek(): number +``` +- 描述:本年的第几周 +- 返回值:周次 + +##### getDateStartOf +```ts +getDateStartOf(d: 'm' | 'w' | 'y' = 'm'): xDate +``` +- 描述:取时间的第一天 +- 参数: + - d: 'm'表示取本月的第一天,'w'取本周的第一天,'y'表示本年的第一天 +- 返回值:返回xDate对象 + +##### getDateEndOf +```ts +getDateEndOf(d: 'm' | 'w' | 'y' = 'm'): xDate +``` +- 描述:取时间的最后一天 +- 参数: + - d: 'm'表示取本月的最后一天,'w'取本周的最后一天,'y'表示本年的最后一天 +- 返回值:返回xDate对象 + +##### getWeekDay +```ts +getWeekDay(): number +``` +- 描述:根据本地时间,返回一个具体日期中一周的第几天,0表示星期天 +- 返回值:根据本地时间,返回一个0到6之间的整数值 + +##### getWeekDayCn +```ts +getWeekDayCn(model: string[] | null = null, useShort: boolean = true): string +``` +- 描述:获取星期名称(支持国际化) +- 参数: + - model: 具有星期的中文模板,请按照顺序放置如["周日","周一","周二","周三","周四","周五","周六"] + - useShort: 是否使用短名称,默认为true +- 返回值:返回当前语言环境下的星期名称 + +##### getMonthCountDay +```ts +getMonthCountDay(): number +``` +- 描述:返回当前日期本月的最大天数 +- 返回值:当前月份的最大天数 + +##### getDateInfo +```ts +getDateInfo(str: string | null = null): xDateDayInfoType +``` +- 描述:返回当日的信息 +- 参数: + - str: 日期字符串,为null时使用当前xDate实例 +- 返回值:返回一个包含年月日周次,星期,农历等的对象 + +##### getDaysOf +```ts +getDaysOf(d: 'm' | 'w' = 'm'): xDateDayInfoType[] +``` +- 描述:返回日期数组 +- 参数: + - d: 'm'表示返回本月的日期数据,'w'表示返回本周的日期数据 +- 返回值:返回一个日期数组 + +##### add +```ts +add(count: number, d: xDateTypeTime = 'd'): xDate +``` +- 描述:为当前日期进行加操作 +- 参数: + - count: 要增加的数量 + - d: 'y'年 'm'月 'd'日 'h'时 'M'分 's'秒 'w'周 +- 返回值:xDate对象(支持链式调用) + +##### subtraction +```ts +subtraction(count: number, d: xDateTypeTime = 'd'): xDate +``` +- 描述:为当前日期进行减操作 +- 参数: + - count: 要减少的数量 + - d: 'y'年 'm'月 'd'日 'h'时 'M'分 's'秒 'w'周 +- 返回值:xDate对象(支持链式调用) + +##### isBetween +```ts +isBetween(start: xDate, end: xDate, type: xDateTypeTime = 'ms', d: '()' | '[]' | '(]' | '[)' = '[]'): boolean +``` +- 描述:日期是否在一个区间内 +- 参数: + - start: 开始日期 + - end: 结束日期 + - type: 要比较的单位,默认为ms + - d: 区间类型,'()'不含起始'[]'包含起始'(]'不包含开始但包含结束'[)'包含开始但不包含结束 +- 返回值:是否在区间内 + +##### isBetweenOf +```ts +isBetweenOf(targetDate: xDate, d: '>' | '>=' | '<' | '<=' | '=' = '>', type: xDateTypeTime = 'ms'): boolean +``` +- 描述:与目标日期比较 +- 参数: + - targetDate: 要比较的日期 + - d: 比较类型,'>'大于目标日期,'>='大于等于目标'<'小于目标,'<='小于等于目标,'='全等 + - type: 要比较的单位 +- 返回值:比较结果 + +##### fromBetweenLongTime +```ts +fromBetweenLongTime(target: any, model: Map | null, format: string | null): string +``` +- 描述:与目标时间过了多久(支持国际化) +- 参数: + - target: 要对比的相对时间,如果填写null就表示当前时间以来的的多久 + - model: 如果为null或者为空的map采用默认值,map格式key表示以秒为单位的时间,value为对应的文本 + - format: 超过最大值最使用格式化日期,如果为null默认为YYYY-MM-DD +- 返回值:返回对应的时间文本 + +##### diffTime +```ts +diffTime(target: any, type: xDateTypeTime = 's'): number +``` +- 描述:与目标时间相差多少个单位 +- 参数: + - target: 目标时间 + - type: 相差的单位,默认:s秒 +- 返回值:返回以xDateTypeTime为单位相关的时间数 + +##### getQuarter +```ts +getQuarter(type: string = ''): xDateTypeQuarter[] +``` +- 描述:获取季度 +- 参数: + - type: 'y'表示获取本年的4个季度,空值表示获取当前时间所在的季度 +- 返回值:返回一个季度数组{quarter:number,start:string,end:string} + +##### setDateLocale +```ts +setDateLocale(locale: xDateLanguage): void +``` +- 描述:设置xDate的语言 +- 参数: + - locale: 语言代码,支持'zh-Hans'(中文简体)、'en'(英文)、'ja'(日文)、'ko'(韩文)、'zh-Hant'(繁体中文)、'fr'(法语)、'ru'(俄语) +- 返回值:无 + +##### getDateLocale +```ts +getDateLocale(): xDateLanguage +``` +- 描述:获取当前xDate使用的语言 +- 返回值:当前语言代码 + +### 使用示例 + +#### 基本使用 +```ts +import {xDate, createDate} from "@/uni_modules/tmx-ui/index.uts" + +// 创建日期实例 +const date = new xDate('2023-05-15') + +// 格式化日期 +console.log(date.format('YYYY年MM月DD日')) // 输出: 2023年05月15日 + +// 获取年月日 +console.log(date.getYear()) // 输出: 2023 +console.log(date.getMonth()) // 输出: 4 (5月) +console.log(date.getDate()) // 输出: 15 + +// 链式调用 +const nextWeek = date.getClone().add(1, 'w') +console.log(nextWeek.format()) // 输出下周同一天的日期 + +// 获取月份天数 +console.log(date.getMonthCountDay()) // 输出: 31 (5月有31天) + +// 获取日期信息 +const info = date.getDateInfo() +console.log(info.weekCn) // 输出: 周一 (假设5月15日是周一) + +// 日期比较 +const date1 = new xDate('2023-01-01') +const date2 = new xDate('2023-12-31') +console.log(date.isBetween(date1, date2)) // 输出: true +``` + +#### 高级用法 +```ts +import {xDate} from "@/uni_modules/tmx-ui/index.uts" + +// 获取本月所有日期 +const currentDate = new xDate() +const daysInMonth = currentDate.getDaysOf('m') +console.log(`本月共有 ${daysInMonth.length} 天`) + +// 获取本周日期 +const daysInWeek = currentDate.getDaysOf('w') +console.log(`本周的第一天是 ${daysInWeek[0].date}`) + +// 获取季度信息 +const quarters = currentDate.getQuarter('y') +console.log(`今年第一季度: ${quarters[0].start} 至 ${quarters[0].end}`) + +// 计算两个日期之间的差距 +const birthday = new xDate('1990-01-01') +const daysDiff = currentDate.diffTime(birthday, 'd') +console.log(`距离生日已经过去了 ${daysDiff} 天`) + +// 友好的时间显示 +const pastTime = new xDate().subtraction(3, 'h') +const timeText = currentDate.fromBetweenLongTime(pastTime, null, null) +console.log(timeText) // 输出: 3小时前 +``` + +#### 国际化使用示例 +```ts +import {xDate} from "@/uni_modules/tmx-ui/index.uts" + +// 创建日期实例 +const date = new xDate('2023-05-15') + +// 默认使用中文简体 +console.log(date.getWeekDayCn()) // 输出: 周一 (假设5月15日是周一) +console.log(date.getMonthName()) // 输出: 五月 + +// 切换到英文 +date.setDateLocale('en') +console.log(date.getWeekDayCn()) // 输出: Mon +console.log(date.getMonthName()) // 输出: May +console.log(date.getMonthName(false)) // 输出: May (完整名称) + +// 切换到日文 +date.setDateLocale('ja') +console.log(date.getWeekDayCn()) // 输出: 月 +console.log(date.getMonthName()) // 输出: 5月 + +// 相对时间显示也会根据语言环境变化 +const currentDate = new xDate() +const pastTime = new xDate().subtraction(3, 'h') + +// 中文环境 +currentDate.setDateLocale('zh-Hans') +console.log(currentDate.fromBetweenLongTime(pastTime, null, null)) // 输出: 3小时前 + +// 英文环境 +currentDate.setDateLocale('en') +console.log(currentDate.fromBetweenLongTime(pastTime, null, null)) // 输出: 3 hours ago + +// 获取当前语言设置 +console.log(currentDate.getDateLocale()) // 输出: en +``` \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xDate.uts b/uni_modules/tmx-ui/core/util/xDate.uts new file mode 100644 index 0000000..3d118d8 --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xDate.uts @@ -0,0 +1,873 @@ +import { xDateDayInfoType } from "../../interface.uts" +import { getCurrentLocale, getLocaleData, setLocale, xDateLanguage } from "./xDateI18n.uts" +export type xDateTypeTime = 'y' | 'm' | 'd' | 'h' | 'M' | 's' | 'ms' | 'w' +export type xDateTypeQuarter = { + quarter : number, + start : string, + end : string +} +export type DateFormat = 'RFC2822' | 'ISO8601' | 'CUSTOM'; + +/** + * 用来解析非标准时间以及各种奇怪的时间格式。 + */ +export function createDate(dateStrs : string) : Date { + const dateStr = dateStrs.replace(/\//g, '-') + const result = new Date(); + + // YYYY,YYYY-MM,YYYY-MM-DD,YYYY-MM-DD HH,YYYY-MM-DD HH:mm,YYYY-MM-DD HH:mm:ss + + let regxyy = /^(\d{4})$/ + let regxyymm = /^(\d{4})[-/](\d{1,2})$/ + let regxyymmdd = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2})$/ + let regxyymmddhh = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2}) (\d{1,2})$/ + let regxyymmddhhmm = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2}) (\d{1,2}):(\d{1,2})$/ + let regxyymmddhhmmss = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/ + + let year = result.getFullYear(); + let month = result.getMonth() - 1 + let day = result.getDate() + let hour = result.getHours() + let minute = result.getMinutes() + let second = result.getSeconds() + + result.setSeconds(59); + result.setMinutes(59); + result.setHours(59); + result.setDate(1); + if (regxyymmddhhmmss.test(dateStr)) { + const match = dateStr.match(regxyymmddhhmmss)!; + year = (parseInt(match[1] as string)); + month = (parseInt(match[2] as string) - 1); + day = (parseInt(match[3] as string)); + hour = (parseInt(match[4] as string)); + minute = (parseInt(match[5] as string)); + second = (parseInt(match[6] as string)); + } else if (regxyymmddhhmm.test(dateStr)) { + const match = dateStr.match(regxyymmddhhmm)!; + year = (parseInt(match[1] as string)); + month = (parseInt(match[2] as string) - 1); + day = (parseInt(match[3] as string)); + hour = (parseInt(match[4] as string)); + minute = (parseInt(match[5] as string)); + + } else if (regxyymmddhh.test(dateStr)) { + const match = dateStr.match(regxyymmddhh)!; + year = (parseInt(match[1] as string)); + month = (parseInt(match[2] as string) - 1); + day = (parseInt(match[3] as string)); + hour = (parseInt(match[4] as string)); + } else if (regxyymmdd.test(dateStr)) { + const match = dateStr.match(regxyymmdd)!; + year = (parseInt(match[1] as string)); + month = (parseInt(match[2] as string) - 1); + day = (parseInt(match[3] as string)); + + } else if (regxyymm.test(dateStr)) { + const match = dateStr.match(regxyymm)!; + year = (parseInt(match[1] as string)); + month = (parseInt(match[2] as string) - 1); + } else if (regxyy.test(dateStr)) { + const match = dateStr.match(regxyy)!; + year = (parseInt(match[1] as string)); + } + + result.setSeconds(second); + result.setMinutes(minute); + result.setHours(hour); + result.setFullYear(year); + result.setMonth(month); + result.setDate(day); + return result; +} + +/** + * 日期库 xDate + */ +export class xDate { + date : Date; + /** + * dateStr,可能是数字,字符串,Date对象 + */ + constructor(dateStr : string | number | Date | null = null) { + this.date = this.checkDate(dateStr) + } + private checkDate(dateStr : string | number | Date | null = null) : Date { + let tempDate = new Date(); + if (dateStr == null) { + return tempDate; + } + if (typeof dateStr == 'number') { + return new Date(dateStr! as number); + } else if (typeof dateStr == 'string') { + if (dateStr == '') { + return tempDate; + } + const dateformatStr = this.detectDateFormat(dateStr!) + + if (dateformatStr == 'CUSTOM') { + let str = dateStr! as string; + str = str.replace(/-/g, '/') + let isNumberStr = /^\d+$/.test(str) + if (!isNumberStr) { + return createDate(dateStr!) + } else { + return new Date(parseInt(str!)); + } + + } else { + return new Date(dateStr! as string); + } + + } else if (dateStr instanceof Date) { + return dateStr! as Date; + } + + return tempDate; + } + /** + * 检测字符串的日期格式类型 + * @param dateStr - 日期字符串 + * @returns 日期格式类型 + */ + detectDateFormat(dateStr : string) : DateFormat { + // RFC2822 格式检测 + if (/^(?:\w{3},\s)?(?:\d{1,2}\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}(?::\d{2})?(?:\sGMT)?)|(?:\w{3}\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{1,2}\s\d{2}:\d{2}(?::\d{2})?\s\d{4})/.test(dateStr)) { + return 'RFC2822'; + } + + // ISO8601 格式检测 + if (/^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?$/.test(dateStr)) { + return 'ISO8601'; + } + + return 'CUSTOM'; + } + /** + * 给数字添加前缀0 + */ + translateFullDate(d : number, w : number) : string { + let dstr = d.toString(); + if (dstr.length < w) { + let dar : number[] = new Array(w - dstr.length).fill(0); + dstr = dar.join('') + dstr + } + return dstr; + } + /** + * 格式化日期 + * @param {string} s 模板,比如YYYY/MM/DD hh:mm:ss + * @returns {string} 格式化后的日期字符串 + */ + format(s : string | null = null) : string { + let str = "YYYY/MM/DD hh:mm:ss" + if (s != null) { + str = s; + } + str = str.replace(/YYYY/g, this.translateFullDate(this.date.getFullYear(), 2)) + str = str.replace(/MM/g, this.translateFullDate(this.date.getMonth() + 1, 2)) + str = str.replace(/DD/g, this.translateFullDate(this.date.getDate(), 2)) + str = str.replace(/hh/g, this.translateFullDate(this.date.getHours(), 2)) + str = str.replace(/mm/g, this.translateFullDate(this.date.getMinutes(), 2)) + str = str.replace(/ss/g, this.translateFullDate(this.date.getSeconds(), 2)) + return str; + } + /** + * 获取当前年 + * @return — 根据当地时间,返回一个对应于给定日期的年份数字。 + */ + getYear() : number { + return this.date.getFullYear() + } + /** + * 获取当前月 + * @description 是从0开始,1-11月 + * @return — 一个 0 到 11 的整数值:0 代表一月份,1 代表二月份,2 代表三月份,依次类推 + */ + getMonth() : number { + return this.date.getMonth() + } + + /** + * 获取当前月份的名称 + * @param {boolean} useShort - 是否使用短名称 + * @return — 返回当前语言环境下的月份名称 + */ + getMonthName(useShort : boolean = false) : string { + const monthIndex = this.date.getMonth(); + return useShort ? + getLocaleData().monthsShort[monthIndex] : + getLocaleData().months[monthIndex]; + } + /** + * 获取当前天 + * @return — 返回一个 1 到 31 的整数值。 + */ + getDate() : number { + return this.date.getDate() + } + /** + * 获取当前小时 + * @return — 返回一个 0 到 23 之间的整数值。 + */ + getHours() : number { + return this.date.getHours() + } + /** + * 获取当前分钟 + * @return — 返回一个 0 到 59 的整数值。 + */ + getMinutes() : number { + return this.date.getMinutes() + } + /** + * 获取当前秒 + * @return — 返回一个 0 到 59 的整数值。 + */ + getSeconds() : number { + return this.date.getSeconds() + } + /** + * 获取指定是数据 + * @param {xDateTypeTime} d - 'y' 年 'm' 月 'd' 日 'h' 时 'M' 分 's' 秒 'ms' 毫秒 + * @returns - 指定类型的数值 + */ + getDateOf(d : xDateTypeTime = 'd') : number { + if (d == 'y') { + return this.date.getFullYear() + } + else if (d == 'm') { + return this.date.getMonth() + } + else if (d == 'd') { + return this.date.getDate() + } + else if (d == 'h') { + return this.date.getHours() + } + else if (d == 'M') { + return this.date.getMinutes() + } + else if (d == 's') { + return this.date.getSeconds() + } + return this.date.getMilliseconds() + } + /** + * 设定日期 + * @param {number} n - 设定的数据, + * @param {string} d - 比如d=y,那么就是设置本日期的年份数据,'y' 年 'm' 月 'd' 日 'h' 时 'M' 分 's' 秒 'ms' 毫秒 + * @returns - xDate对象实例 + */ + setDateOf(n : number, d : xDateTypeTime = 'd') : xDate { + if (d == 'y') { + this.date.setFullYear(n) + } + else if (d == 'm') { + this.date.setMonth(n) + } + else if (d == 'd') { + this.date.setDate(n) + } + else if (d == 'h') { + this.date.setHours(n) + } + else if (d == 'M') { + this.date.setMinutes(n) + } + else if (d == 's') { + this.date.setSeconds(n) + } + else if (d == 'ms') { + this.date.setMilliseconds(n) + } + return this; + } + + /** + * @param {string} - d:'y' 年 'm' 月 'd' 日 'h' 时 'M' 分 's' 秒 'ms' 毫秒 + * @returns - 返回从UTC时间1970年1月1日午夜开始以毫秒为单位存储的时间值。 + * @description 注意,如果不提供d就默认返回毫秒,比如设置d=m那么后面的h,M,s,ms会被设置为0 + */ + getTime(d : xDateTypeTime) : number { + let date = new Date(this.date.getTime()) + + if (d == 'y') { + date.setMonth(0) + date.setDate(1) + date.setHours(0) + date.setMinutes(0) + date.setSeconds(0) + date.setMilliseconds(0) + return date.getTime() + } + else if (d == 'm') { + date.setDate(1) + date.setHours(0) + date.setMinutes(0) + date.setSeconds(0) + date.setMilliseconds(0) + return date.getTime() + } + else if (d == 'd') { + date.setHours(0) + date.setMinutes(0) + date.setSeconds(0) + date.setMilliseconds(0) + return date.getTime() + } + else if (d == 'h') { + date.setMinutes(0) + date.setSeconds(0) + date.setMilliseconds(0) + return date.getTime() + } + else if (d == 'M') { + date.setSeconds(0) + date.setMilliseconds(0) + return date.getTime() + } + else if (d == 's') { + date.setMilliseconds(0) + return date.getTime() + } + return date.getTime() + } + + /** + * 当前时间的副本 + */ + getClone() : xDate { + + return new xDate(this.format()); + } + /** + * 本年的第几周 + * @return 周次 + */ + getWeek() : number { + let target = new Date(this.format()) + target.setDate(target.getDate() - (target.getDay() == 0 ? 7 : target.getDay())); + let firstDayOfYear = new Date(target.getFullYear(), 0, 1); + firstDayOfYear.setDate(firstDayOfYear.getDate() - (firstDayOfYear.getDay() == 0 ? 7 : firstDayOfYear.getDay())); + return Math.ceil((((target.getTime() - firstDayOfYear.getTime()) / 86400000) + 1) / 7); + } + /** + * 取时间的第一天 + * @param {m,w,y} - m表示取本月的第一天,w取本周的第一天,y表示本年的第一天 + * @returns {xDate} - 返回xDate对象 + */ + getDateStartOf(d : 'm' | 'w' | 'y' = 'm') : xDate { + // 获取当前日期对象 + let now = new Date(this.format()) + if (d == 'w') { + // 将日期设置为所在周的周一(遵循ISO 8601标准,周一开始于周一) + let dayOfWeek = now.getDay(); + if (dayOfWeek === 0) { // 如果是星期日,则向前推一天至上周的周一 + now.setDate(now.getDate() - 7); + } + now.setDate(now.getDate() - dayOfWeek + 1); + } + if (d == 'm' || d == 'y') { + now.setDate(1); + } + if (d == 'y') { + now.setMonth(0); + } + now.setHours(0); + now.setMinutes(0); + now.setSeconds(0); + return dateCovertXdate(now); + } + + /** + * 取时间的最后一天 + * @param {string} - m,w,y m表示取本月的最后一天,w取本周的最后一天,y表示本年的最后一天 + * @returns {xDate} - 返回xDate对象 + */ + getDateEndOf(d : 'm' | 'w' | 'y' = 'm') : xDate { + // 获取当前日期对象 + let now = new Date(this.format()) + if (d == 'w') { + // 将日期设置为所在周的周一(遵循ISO 8601标准,周一开始于周一) + let dayOfWeek = now.getDay(); + if (dayOfWeek === 0) { // 如果是星期日,则向前推一天至上周的周一 + return dateCovertXdate(now); + } + now.setDate(now.getDate() + (7 - dayOfWeek)); + } + if (d == 'm') { + now.setDate(this.getMonthCountDay()); + } + if (d == 'y') { + // 先设置月份为12月,再设置为该月的最后一天 + now.setMonth(11); + // 设置为12月的最后一天 + now.setDate(31); + } + now.setHours(23); + now.setMinutes(59); + now.setSeconds(59); + return dateCovertXdate(now); + } + + + /** + * 根据本地时间,返回一个具体日期中一周的第几天,0 表示星期天。 + * @return — 根据本地时间,返回一个 0 到 6 之间的整数值,代表星期几:0 代表星期日,1 代表星期一,2 代表星期二,依次类推。 + */ + getWeekDay() : number { + return this.date.getDay() + } + /** + * 根据本地时间,返回一个具体日期中一周的第几天,0 表示星期天。 + * @param {string[]} model 具有星期的中文模板,请按照顺序放置如["周日","周一","周二","周三","周四","周五","周六"] + * @param {boolean} useShort 是否使用短名称 + * @return — 返回一个当前语言环境下的星期名称 + */ + getWeekDayCn(model : string[] | null = null, useShort : boolean = true) : string { + let ml = useShort ? getLocaleData().weekdaysShort : getLocaleData().weekdays; + if (model != null && model?.length == 7) { + ml = model!; + } + return ml[this.getWeekDay()]! + } + /** + * 返回当前日期本月的最大天数 + * @returns - 当前月份的最大天数 + */ + getMonthCountDay() : number { + let nextDate = new Date(this.format()) + // 先设置为1号,避免后面设置月份时超过月的天数。 + nextDate.setDate(1) + nextDate.setMonth(this.getMonth() + 1) + // 设置为上月的最后一天。 + nextDate.setDate(0) + return nextDate.getDate() + } + + /** + * 返回当日的信息 + * @returns - 返回一个包含年月日周次,星期,农历等的对象 + */ + getDateInfo(str : string | null = null) : xDateDayInfoType { + let date = this as xDate + if (str != null) { + date = new xDate(str) + } + let info = { + year: date.getYear(), + month: date.getMonth(), + day: date.getDate(), + hours: date.getHours(), + minutes: date.getMinutes(), + seconds: date.getSeconds(), + week: date.getWeekDay(), + weeks: date.getWeek(), + weekCn: date.getWeekDayCn(), + date: "" + } as xDateDayInfoType + info.date = info.year + '/' + (info.month + 1) + '/' + info.day + return info + } + + /** + * 返回日期数组 + * @param {string} - m,w,m表示返回本月的日期数据,w表示返回本周的日期数据 + * @returns - 返回一个日期数组 + */ + getDaysOf(d : 'm' | 'w' = 'm') : xDateDayInfoType[] { + let dates = [] as xDateDayInfoType[] + if (d == 'w') { + let first = this.getDateStartOf('w') + + for (let i = 0; i < 7; i++) { + let date = first.getClone() + date.date.setDate(date.date.getDate() + i) + dates.push(date.getDateInfo()) + } + } + if (d == 'm') { + let first = this.getDateStartOf('m') + let maxDay = this.getMonthCountDay() + for (let i = 1; i <= maxDay; i++) { + let date = first.getClone() + date.date.setDate(i) + dates.push(date.getDateInfo()) + } + + } + + return dates; + } + /** + * 按指定天数返回日期数组 + * @param {string} d - 返回多少天的日期数组 + * @param {string} type - after表示返回当前日期之后的日期,before表示返回当前日期之前的日期 + */ + getDaysOfNum(d : number = 0, type : 'after' | 'before') : xDateDayInfoType[] { + let ar = [] as xDateDayInfoType[]; + let nowdate = this.getClone() + if (type == 'after') { + for (let i = 0; i < d; i++) { + nowdate.add(1, 'd') + ar.push(nowdate.getDateInfo()) + } + } else if (type == 'before') { + for (let i = 0; i < d; i++) { + nowdate.subtraction(1, 'd') + ar.push(nowdate.getDateInfo()) + } + ar.reverse() + } + + return ar; + } + + /** + * 为当前日期进行加操作 + * @param {string} - y,m,d,h,M,s,w,代表的是年份,月份,日期,小时,分钟,秒数,周 + */ + add(count : number, d : xDateTypeTime = 'd') : xDate { + if (d == 'y') { + this.date.setFullYear(this.getYear() + count) + } + else if (d == 'm') { + this.date.setMonth(this.getMonth() + count) + } + else if (d == 'd') { + this.date.setDate(this.getDate() + count) + } + else if (d == 'h') { + this.date.setHours(this.getHours() + count) + } + else if (d == 'M') { + this.date.setMinutes(this.getMinutes() + count) + } + else if (d == 's') { + this.date.setSeconds(this.getSeconds() + count) + } + // 添加一周 + else if (d == 'w') { + this.date.setDate(this.getDate() + count * 7) + + } + + return this; + } + /** + * 为当前日期进行减操作 + * @param {string} - y,m,d,h,M,s,w,代表的是年份,月份,日期,小时,分钟,秒数,周 + */ + subtraction(count : number, d : xDateTypeTime = 'd') : xDate { + if (d == 'y') { + this.date.setFullYear(this.getYear() - count) + } + else if (d == 'm') { + this.date.setMonth(this.getMonth() - count) + } + else if (d == 'd') { + this.date.setDate(this.getDate() - count) + } + else if (d == 'h') { + this.date.setHours(this.getHours() - count) + } + else if (d == 'M') { + this.date.setMinutes(this.getMinutes() - count) + } + else if (d == 's') { + this.date.setSeconds(this.getSeconds() - count) + } + // 添加一周 + else if (d == 'w') { + this.date.setDate(this.getDate() - count * 7) + } + + return this; + } + + + /** + * 日期是否在一个区间内 + * @param {xDate} start 开始日期 + * @param {xDate} end 结束日期 + * @param {string} - type要比较的单位,默认为ms,'y' 年 'm' 月 'd' 日 'h' 时 'M' 分 's' 秒 'ms' 毫秒 + * @param {string} - d,默认为[] 区间类型,'()'不含起始'[]'包含起始'(]'不包含开始,但包含结束'[)'包含开始,但不包含结束 + * @returns {boolean} 是否在区间内 + */ + isBetween(start : xDate, end : xDate, type : xDateTypeTime = 'ms', d : '()' | '[]' | '(]' | '[)' = '[]') : boolean { + let startTime = start.getTime(type) + + // new Date('1970-1-1 8:0:0').getTime() + let endTime = end.getTime(type) + let nowTime = this.getTime(type) + if (d == '()') { + return nowTime > startTime && nowTime < endTime + } + else if (d == '[]') { + return nowTime >= startTime && nowTime <= endTime + } + else if (d == '(]') { + return nowTime > startTime && nowTime <= endTime + } + else if (d == '[)') { + return nowTime >= startTime && nowTime < endTime + } + return nowTime >= startTime && nowTime <= endTime + } + + /** + * 与目标日期比较 + * @param {xDate} targetDate 要比较的日期 + * @param {string} - d,默认为> 比较类型,'>'大于目标日期,'>='大于等于目标'<'小于目标,'<='小于等于目标,'='全等 + * @param {string} - type要比较的单位,默认为ms,'y' 年 'm' 月 'd' 日 'h' 时 'M' 分 's' 秒 'ms' 毫秒 + * @returns {boolean} 比较结果 + */ + isBetweenOf(targetDate : xDate, d : '>' | '>=' | '<' | '<=' | '=' = '>', type : xDateTypeTime = 'ms') : boolean { + let startTime = targetDate.getTime(type) + let nowTime = this.getTime(type) + if (d == '>') { + return nowTime > startTime + } + else if (d == '>=') { + return nowTime >= startTime + } + else if (d == '<') { + return nowTime < startTime + } + else if (d == '<=') { + return nowTime <= startTime + } + else if (d == '=') { + return nowTime == startTime + } + return nowTime > startTime + } + /** + * 与目标时间过了多久 + * @param {string|xDate|null} target 要对比的相对时间,如果填写null就表示当前时间以来的的多久 + * @param {Map} model 如果为null或者为空的map采用默认值,map格式key表示以秒为单位的时间,value为对应的文本 + * 比如60,1分钟前 + * @param {string} format 超过最大值最使用格式化日期,如果为null默认为YYYY-MM-DD + * @returns {string} 返回对应的时间文本 + */ + fromBetweenLongTime(target : any, model : Map | null, format : string | null) : string { + let bijiaodate : xDate = new xDate() + if (target instanceof xDate) { + bijiaodate = (target as xDate) + } else if (typeof target == 'string') { + bijiaodate = new xDate(target as string) + } else if (target == null) { + bijiaodate = new xDate() + } + + // 使用国际化相对时间配置 + let relativeTime = getLocaleData().relativeTime; + let mapmodel = new Map([ + [30, relativeTime.s], + [60, relativeTime.m], + [60 * 5, '5' + relativeTime.mm.replace('%d', '')], + [60 * 10, '10' + relativeTime.mm.replace('%d', '')], + [60 * 30, '30' + relativeTime.mm.replace('%d', '')], + [60 * 60, relativeTime.h], + [60 * 60 * 2, '2' + relativeTime.hh.replace('%d', '')], + [60 * 60 * 3, '3' + relativeTime.hh.replace('%d', '')], + [60 * 60 * 5, '5' + relativeTime.hh.replace('%d', '')], + [60 * 60 * 23, '23' + relativeTime.hh.replace('%d', '')], + [60 * 60 * 24 * 1, relativeTime.d], + [60 * 60 * 24 * 2, '2' + relativeTime.dd.replace('%d', '')], + [60 * 60 * 24 * 7, '7' + relativeTime.dd.replace('%d', '')], + [60 * 60 * 24 * 30, relativeTime.M], + [60 * 60 * 24 * 30 * 2, '2' + relativeTime.MM.replace('%d', '')], + [60 * 60 * 24 * 30 * 3, '3' + relativeTime.MM.replace('%d', '')], + [60 * 60 * 24 * 30 * 4, '4' + relativeTime.MM.replace('%d', '')], + [60 * 60 * 24 * 30 * 5, '5' + relativeTime.MM.replace('%d', '')], + [60 * 60 * 24 * 30 * 6, '6' + relativeTime.MM.replace('%d', '')], + [60 * 60 * 24 * 30 * 12, relativeTime.y], + [60 * 60 * 24 * 30 * 12 + 60 * 60 * 24 * 30, ''] + ]) + let fmt = format == null ? 'YYYY-MM-DD' : (format!) + + if (model != null) { + if (model!.size > 0) { + mapmodel = model! + } + } + let str = "" + let fanzhumap = [] as number[]; + mapmodel.forEach((value : string, key : number) => { + fanzhumap.push(key) + }) + fanzhumap.reverse() + + try { + let startTime = bijiaodate.getTime('s') + let nowTime = this.getTime('s') + let diff = (nowTime - startTime) / 1000 + + + if (diff > 0) { + for (let i = 0; i < fanzhumap.length; i++) { + let key = fanzhumap[i]; + + if (diff >= key) { + console.log(diff, key, 5 * 60 * 60, '---', fanzhumap) + str = mapmodel.get(key)! + break; + } + } + + } else { + str = mapmodel.get(fanzhumap[fanzhumap.length - 1])! + } + if (str == '') { + str = bijiaodate.format(fmt) + } + + + } catch (e) { + //TODO handle the exception + } + + + + return str + } + /** + * 与目标时间相差多少个单位 + * @param {string|xDate|null} target 目标时间 + * @param {xDateTypeTime} type 相差的单位,默认:s秒 + * @returns {string} 反返回以xDateTypeTime为单位相关的时间数 + */ + diffTime(target : any, type : xDateTypeTime = 's') : number { + let startTime = 0 + let typed : xDateTypeTime = (type == 'w' ? 'd' : type) + if (target instanceof xDate) { + startTime = (target as xDate).getTime(typed) + } else if (typeof target == 'string') { + startTime = new xDate(target as string).getTime(typed) + + } else if (target == null) { + startTime = new xDate().getTime(typed) + } + + let nowTime = this.getTime(typed) + let diff = Math.abs(nowTime - startTime); + let d = 0 + if (type == 's') { + d = diff + } else if (type == 'M') { + d = diff / 60 / 1000 + } else if (type == 'h') { + d = diff / 60 / 60 / 1000 + } else if (type == 'd') { + d = diff / 60 / 60 / 24 / 1000 + } else if (type == 'm') { + d = diff / 60 / 60 / 24 / 30 / 1000 + } else if (type == 'y') { + d = diff / 60 / 60 / 24 / 30 / 12 / 1000 + } else if (type == 'w') { + let ondate = (1000 * 60 * 60 * 24 * 7); + d = diff / ondate + } + + return Math.floor(d) + } + /** + * 获取季度 + * @param {string} type y表示获取本年的4个季度,空值表示获取当前时间所在的季度 + * @returns {xDateTypeQuarter[]} 返回一个季度数组{quarter:number,start:string,end:string} + */ + getQuarter(type : string = '') : xDateTypeQuarter[] { + let q1 = [1, 2, 3] + let q2 = [4, 5, 6] + let q3 = [7, 8, 9] + let q4 = [10, 11, 12] + let nowMonth = this.getMonth() + 1 + let qall = [q1, q2, q3, q4] as number[][] + let qmap = [] as xDateTypeQuarter[] + if (type == 'y') { + for (let i = 0; i < qall.length; i++) { + let item = qall[i] + let sdate = new xDate(this.getYear() + '/' + item[0] + '/1') + let edate = new xDate(this.getYear() + '/' + item[item.length - 1] + '/1') + let start = sdate.format('YYYY/MM/DD') + let end = edate.getDateEndOf('m').format('YYYY/MM/DD') + qmap.push({ + quarter: i, + start, + end + } as xDateTypeQuarter) + } + } else { + for (let i = 0; i < qall.length; i++) { + let item = qall[i] + if (item.includes(nowMonth)) { + let sdate = new xDate(this.getYear() + '/' + item[0] + '/1') + let edate = new xDate(this.getYear() + '/' + item[item.length - 1] + '/1') + let start = sdate.format('YYYY/MM/DD') + let end = edate.getDateEndOf('m').format('YYYY/MM/DD') + qmap.push({ + quarter: i, + start, + end + } as xDateTypeQuarter) + break; + } + } + } + return qmap; + } + + /** + * 设置xDate的语言 + * @param {xDateLanguage} locale - 语言代码 + */ + setDateLocale(locale : xDateLanguage) : void { + setLocale(locale); + } + + /** + * 获取当前xDate使用的语言 + * @returns {xDateLanguage} - 当前语言代码 + */ + getDateLocale() : xDateLanguage { + return getCurrentLocale(); + } + /** + * 根据开始和结束时间取之间的时间(含起始) + * @param {string|xDate|null} start 目标时间 + * @param {string|xDate|null} end 目标时间 + */ + getBetweenDate(start : string | number | Date, end : string | number | Date, minx : 'min' | 'max' | 'auto' = 'auto') : Date { + let _start = this.checkDate(start); + let _end = this.checkDate(end); + let startDiff = _start.getTime() + let endDiff = _end.getTime() + let nowDiff = this.getTime('ms') + if(nowDiff>=startDiff&&nowDiff<=endDiff){ + return this.date; + } + if (minx == 'min') { + return _start; + } + if (minx == 'max') { + return _end; + } + if (startDiff < endDiff) { + return _end; + } + return _start; + } + +} + + + + +/** + * 将一个日期转换为xDate对象 + */ +export const dateCovertXdate = function (date : Date) : xDate { + return new xDate(date) +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xDateI18n.uts b/uni_modules/tmx-ui/core/util/xDateI18n.uts new file mode 100644 index 0000000..65922eb --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xDateI18n.uts @@ -0,0 +1,258 @@ +/** + * xDate国际化支持 + * 支持中文、英文、日文、韩文、繁体中文、法语和俄语 + */ + +export type xDateLanguage = 'zh-Hans' | 'en' | 'ja' | 'ko' | 'zh-Hant' | 'fr' | 'ru'; +export type xDateI18nTypeRelativeTime = { + future: string, + past: string, + s: string, + m: string, + mm: string, + h: string, + hh: string, + d: string, + dd: string, + M: string, + MM: string, + y: string, + yy: string + } +export type xDateI18nType = { + weekdays: string[], + weekdaysShort: string[], + months: string[], + monthsShort: string[], + meridiem: (hour: number, minute: number, isLowercase: boolean) => string, + relativeTime: xDateI18nTypeRelativeTime +} + +// 中文简体 +const zhHans: xDateI18nType = { + weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], + weekdaysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], + months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + meridiem: (hour: number, minute: number, isLowercase: boolean): string => { + return hour < 12 ? '上午' : '下午'; + }, + relativeTime: { + future: '%s内', + past: '%s前', + s: '几秒', + m: '1分钟', + mm: '%d分钟', + h: '1小时', + hh: '%d小时', + d: '1天', + dd: '%d天', + M: '1个月', + MM: '%d个月', + y: '1年', + yy: '%d年' + } +}; + +// 英文 +const en: xDateI18nType = { + weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + meridiem: (hour: number, minute: number, isLowercase: boolean): string => { + return hour < 12 ? (isLowercase ? 'am' : 'AM') : (isLowercase ? 'pm' : 'PM'); + }, + relativeTime: { + future: 'in %s', + past: '%s ago', + s: 'a few seconds', + m: 'a minute', + mm: '%d minutes', + h: 'an hour', + hh: '%d hours', + d: 'a day', + dd: '%d days', + M: 'a month', + MM: '%d months', + y: 'a year', + yy: '%d years' + } +}; + +// 日文 +const ja: xDateI18nType = { + weekdays: ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'], + weekdaysShort: ['日', '月', '火', '水', '木', '金', '土'], + months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + meridiem: (hour: number, minute: number, isLowercase: boolean): string => { + return hour < 12 ? '午前' : '午後'; + }, + relativeTime: { + future: '%s後', + past: '%s前', + s: '数秒', + m: '1分', + mm: '%d分', + h: '1時間', + hh: '%d時間', + d: '1日', + dd: '%d日', + M: '1ヶ月', + MM: '%dヶ月', + y: '1年', + yy: '%d年' + } +}; + +// 韩文 +const ko: xDateI18nType = { + weekdays: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'], + weekdaysShort: ['일', '월', '화', '수', '목', '금', '토'], + months: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'], + monthsShort: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'], + meridiem: (hour: number, minute: number, isLowercase: boolean): string => { + return hour < 12 ? '오전' : '오후'; + }, + relativeTime: { + future: '%s 후', + past: '%s 전', + s: '몇 초', + m: '1분', + mm: '%d분', + h: '1시간', + hh: '%d시간', + d: '1일', + dd: '%d일', + M: '1개월', + MM: '%d개월', + y: '1년', + yy: '%d년' + } +}; + +// 繁体中文 +const zhHant: xDateI18nType = { + weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], + weekdaysShort: ['週日', '週一', '週二', '週三', '週四', '週五', '週六'], + months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + meridiem: (hour: number, minute: number, isLowercase: boolean): string => { + return hour < 12 ? '上午' : '下午'; + }, + relativeTime: { + future: '%s內', + past: '%s前', + s: '幾秒', + m: '1分鐘', + mm: '%d分鐘', + h: '1小時', + hh: '%d小時', + d: '1天', + dd: '%d天', + M: '1個月', + MM: '%d個月', + y: '1年', + yy: '%d年' + } +}; + +// 法语 +const fr: xDateI18nType = { + weekdays: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'], + weekdaysShort: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'], + months: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'], + monthsShort: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'], + meridiem: (hour: number, minute: number, isLowercase: boolean): string => { + return ''; + }, + relativeTime: { + future: 'dans %s', + past: 'il y a %s', + s: 'quelques secondes', + m: 'une minute', + mm: '%d minutes', + h: 'une heure', + hh: '%d heures', + d: 'un jour', + dd: '%d jours', + M: 'un mois', + MM: '%d mois', + y: 'un an', + yy: '%d ans' + } +}; + +// 俄语 +const ru: xDateI18nType = { + weekdays: ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'], + weekdaysShort: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'], + months: ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'], + monthsShort: ['янв.', 'февр.', 'март', 'апр.', 'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.', 'нояб.', 'дек.'], + meridiem: (hour: number, minute: number, isLowercase: boolean): string => { + return ''; + }, + relativeTime: { + future: 'через %s', + past: '%s назад', + s: 'несколько секунд', + m: 'минута', + mm: '%d минут', + h: 'час', + hh: '%d часов', + d: 'день', + dd: '%d дней', + M: 'месяц', + MM: '%d месяцев', + y: 'год', + yy: '%d лет' + } +}; + +// 语言映射表 +export const locales: Map = new Map([ + ['zh-Hans', zhHans], + ['en', en], + ['ja', ja], + ['ko', ko], + ['zh-Hant', zhHant], + ['fr', fr], + ['ru', ru] +]); + +// 默认语言 +let currentLocale: xDateLanguage = 'zh-Hans'; + +/** + * 获取当前语言设置 + */ +export function getCurrentLocale(): xDateLanguage { + return currentLocale; +} + +/** + * 设置当前语言 + * @param locale 语言代码 + */ +export function setLocale(locale: xDateLanguage): void { + + if (locales.has(locale)) { + currentLocale = locale; + } +} + +/** + * 获取当前语言的本地化数据 + */ +export function getLocaleData(): xDateI18nType { + return locales.get(currentLocale)!; +} + +/** + * 获取指定语言的本地化数据 + * @param locale 语言代码 + */ +export function getLocaleDataByCode(locale: xDateLanguage): xDateI18nType | null { + return locales.has(locale) ? locales.get(locale)! : null; +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xRequest.uts b/uni_modules/tmx-ui/core/util/xRequest.uts new file mode 100644 index 0000000..a82a8c3 --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xRequest.uts @@ -0,0 +1,676 @@ +import { xRequestCall } from "./config.uts" +import { xRequestOptions, xRequestOptionsCallBack, xRequestResult, xRequestHistoryType, xRequestMethond } from "../../interface.uts" +import { xConfig } from "../../config/xConfig.uts" +const i18n = xConfig.i18n; +/** + * 请求库xRequest + * @version 1.0.0 + * @author tmzdy + * @host https://xui.tmui.design + * @description 异常简便,没有繁杂的配置选项,只有快速的开发部署。 + */ +/** + * auth 表示全局设置了全限auth为false,后面的所有请求都被中止请求,从而触发此事件。 + * 如果此时返回true,将继续请求。 + * before 如果返回true,将继续请求。返回false被中断请求。 + * after 可以返回请求的后台数据格式化并返回到最终的请求结果中。 + * + * auth,before监听函数请务必返回Promise.resolve(boolean),其中函数内得到的arg为xRequestOptionsCallBack类型(请求参数配置数据) + * 除了auth,before 函数体内arg 得到的参数全是xRequestResult(请求结果数据), 返回随意,因为内部不采用。 + * after,需要返回 Promise.resolve(xRequestResult),会覆盖success请求后的数据,相当于你在此hook事件中修改和格式化服务器,并返回到最终结果中。 + */ +type xRequestEventType = "before" | "after" | "abort" | "timeout" | "error" | "auth" | "success" | "complete" +type funType = (arg : any) => Promise; +type funCall = { + fun : funType, + type : xRequestEventType +} + +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifndef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length); + // #endif + + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} + +// 缓存管理器 +class xCacheManager { + private cache : UTSJSONObject = {}; + + constructor() { + let cs = uni.getStorageSync('xCacheManager'); + if (cs instanceof UTSJSONObject) { + this.cache = cs! as UTSJSONObject + } + } + + // 生成缓存键 + generateCacheKey(config : xRequestOptionsCallBack) : string { + const url = config.url; + const method = config.method; + let keyQ = (url?.split('?')?.[0] ?? url) as string; + // 简化缓存键生成,避免复杂对象序列化可能导致的不一致 + let key = `${method}_${keyQ}`; + // 对data进行类似处理 + if (config.data != null) { + // 如果是简单类型,直接使用 + if (!(config.data instanceof UTSJSONObject)) { + key += `_d:${config.data}`; + } else if (config.data instanceof UTSJSONObject) { + let _data = config.data as UTSJSONObject; + let _keys = [] as string[] + for (const key in _data) { + _keys.push(key) + } + // 对于对象,只使用键名作为缓存键的一部分 + const dataKeys = _keys.sort() + key += `_d:${dataKeys.join(',')}`; + } + } + + return key; + } + + // 设置缓存 + set(config : xRequestOptionsCallBack, response : any) : void { + const key = this.generateCacheKey(config); + this.cache.set(key, { + data: response, + timestamp: Date.now() + } as UTSJSONObject) + + try { + uni.setStorageSync('xCacheManager', this.cache); + } catch (error) { + // 如果存储失败,可能是缓存太大,清理一部分 + this.pruneCache(); + try { + uni.setStorageSync('xCacheManager', this.cache); + } catch (e) { + console.error('二次缓存设置失败'); + } + } + } + + // 获取缓存 + get(config : xRequestOptionsCallBack) : any | null { + const key = this.generateCacheKey(config); + const cacheItem = this.cache.getJSON(key) + + if (cacheItem == null) return null; + + const cacheTime = config.cacheTime == 0 ? 60000 : config.cacheTime + const now = Date.now(); + const timestamp = cacheItem.getNumber("timestamp")! + // 检查缓存是否过期 + if (now - timestamp > cacheTime) { + let allkeys = {} as UTSJSONObject; + for (const keySelf in this.cache) { + if (keySelf != key) { + allkeys.set(keySelf, this.cache[keySelf]) + } + } + this.cache = allkeys + uni.setStorageSync('xCacheManager', allkeys); + return null; + } + + // console.log('命中缓存:', key); + return cacheItem.getAny('data'); + } + + // 清除缓存 + clear() : void { + this.cache = {}; + uni.removeStorageSync('xCacheManager'); + } + + + + // 清理部分缓存 + private pruneCache() : void { + + const _keys = [] as string[] + for (const key in this.cache) { + _keys.push(key) + } + + if (_keys.length > 20) { // 如果缓存项超过20个 + // 按时间戳排序,删除最旧的一半 + const sortedKeys = _keys.sort((a : string, b : string) : number => { + let ad = this.cache[a]! as UTSJSONObject + let bd = this.cache[b]! as UTSJSONObject + return ad.getNumber('timestamp')! - bd.getNumber('timestamp')! + }); + + const toRemove = sortedKeys.slice(0, Math.floor(_keys.length / 2)); + let allkeys = {} as UTSJSONObject; + for (let i = 0; i < sortedKeys.length; i++) { + let key = sortedKeys[i] + allkeys.set(key, this.cache[key]) + } + this.cache = allkeys + uni.setStorageSync('xCacheManager', allkeys); + console.log(`已清理${toRemove.length}个旧缓存项`); + } + } +} + +export class xRequest { + private auth = true; + private cacheManager : xCacheManager; + private selfOpts = { + useCache: false, + cacheTime: 60 * 1000, + hostUrl: xRequestCall.hostUrl, + successStatusCode: 200, + url: "", + data: {} as UTSJSONObject, + header: { + 'content-type': 'application/json' + } as UTSJSONObject, + method: "GET", + timeout: 6000, + firstIpv4: false, + /** 请求前是否显示loading遮罩 */ + showLoadToast: xRequestCall.showLoadToast, + /** 请求成功后是否提示,否则不提示 */ + showSuccessToast: xRequestCall.showSuccessToast, + /** 出错时,是否显示提示,否则不提示 */ + showErrorToast: xRequestCall.showErrorToast, + loadToastText: i18n.t("tmui4x.xRequest.loading"), + successToastText: i18n.t("tmui4x.xRequest.success"), + errorToastText: "" + } as xRequestOptionsCallBack + + private _lisentEventList = [] as funCall[] + + private status = null as xRequestEventType | null + + + private result = { + data: null, + statusCode: 0, + header: {} as any, + cookies: [] as string[], + } as xRequestResult + + private reqtask = null as null | RequestTask + constructor(opts : xRequestOptions | null = null) { + this.setOptions(opts) + this.cacheManager = new xCacheManager() + } + /** + * 设置当前请求的参数 + * 只影响本次的实例请求,不影响其它请求。 + * 但配置中的header,data会与全局的合并。 + */ + setOptions(opts : xRequestOptions | null = null) : xRequestOptionsCallBack { + + if (opts == null) return this.selfOpts; + let headerTmep = opts.header + headerTmep = opts.header == null ? this.selfOpts.header : opts.header! + // #ifdef WEB + headerTmep = opts.header == undefined ? this.selfOpts.header : opts.header + // #endif + + + let dataTmep = opts?.data ?? ({} as UTSJSONObject) + + if (xRequestCall.header != null) { + let obj = xRequestCall.header as UTSJSONObject; + let newObj = headerTmep! as UTSJSONObject; + for (let key in newObj) { + obj.set(key, newObj.get(key)) + } + headerTmep = obj; + } + let firstIpv4 = (opts?.firstIpv4 ?? false) as boolean; + let method = (opts?.method ?? this.selfOpts.method) as xRequestMethond + let timeout = (opts?.timeout ?? this.selfOpts.timeout) as number + let successStatusCode = (opts?.successStatusCode ?? this.selfOpts.successStatusCode) as number + let url = (opts?.url ?? this.selfOpts.url) as string + let showLoadToast = (opts?.showLoadToast ?? this.selfOpts.showSuccessToast) as boolean + let showSuccessToast = (opts?.showSuccessToast ?? this.selfOpts.showSuccessToast) as boolean + let showErrorToast = (opts?.showErrorToast ?? this.selfOpts.showErrorToast) as boolean + let hostUrl = (opts?.hostUrl ?? xRequestCall.hostUrl) as string + let cacheTime = (opts?.cacheTime ?? this.selfOpts.cacheTime) as number + let useCache = (opts?.useCache ?? this.selfOpts.useCache) as boolean + let loadToastText = (opts?.loadToastText ?? this.selfOpts!.loadToastText) as string + let successToastText = (opts?.successToastText ?? this.selfOpts!.successToastText) as string + let errorToastText = (opts?.errorToastText ?? this.selfOpts!.errorToastText) as string + + this.selfOpts.firstIpv4 = firstIpv4! + this.selfOpts.method = method! as xRequestMethond; + this.selfOpts.timeout = timeout! + this.selfOpts.cacheTime = cacheTime! + this.selfOpts.useCache = useCache! + this.selfOpts.successStatusCode = successStatusCode! + this.selfOpts.data = dataTmep! + this.selfOpts.header = headerTmep! + this.selfOpts.url = url! as string + this.selfOpts.showLoadToast = showLoadToast! as boolean; + this.selfOpts.showSuccessToast = showSuccessToast! as boolean + this.selfOpts.showErrorToast = showErrorToast! as boolean + this.selfOpts.responseType = opts.responseType + this.selfOpts.dataType = opts.dataType + this.selfOpts.hostUrl = hostUrl + this.selfOpts!.loadToastText = loadToastText + this.selfOpts!.successToastText = successToastText + this.selfOpts!.errorToastText = errorToastText + + return this.selfOpts; + } + /** + * 添加事件监听 + * 可以重复添加,被添加的函数会被按顺序执行。 + * 相当于Hooks + */ + addEventListener(event : xRequestEventType = "success", fun : (arg : any) => Promise) : xRequest { + this._lisentEventList.push({ + type: event, + fun + } as funCall) + + return this; + } + /** + * 中断当前的事件 + * @returns {boolean} true表示中断成功,false表示失败 + */ + abort() : boolean { + if (this.reqtask != null) { + this.reqtask!.abort() + return true; + } + + return false + } + /** + * 设置请求授权失败还是通过 + * 如果设置了false + * 接下来的所有请求全部会被中断掉。哪怕你异步或者跨页面发起请求。 + */ + static setAuth(isPass : boolean) { + xRequestCall.authPass = isPass + } + /** + * 设置的头数据是会被所有请求共享 + * 包括跨页面。 + * 同时新增的数据会与旧的数据合并,如果之前不存在则新增。 + */ + static setHeader(header : UTSJSONObject | null = null) : UTSJSONObject | null { + if (xRequestCall.header == null) { + xRequestCall.header = header; + } else { + let obj = xRequestCall.header as UTSJSONObject; + let newObj = header! as UTSJSONObject; + for (let key in newObj) { + obj.set(key, newObj.get(key)) + } + xRequestCall.header = obj; + } + + return xRequestCall.header + } + /** + * 设置请求的主域名地址 + * 所有的请求共享,包括跨页面。 + */ + static setHostUrl(url : string | null) { + xRequestCall.hostUrl = url == null ? "" : url!; + } + static setDev(dev : boolean = false) { + xRequestCall.dev = dev; + if (dev) { + console.warn('tmui4.0提醒:' + `你开启了请求调试模式`) + } else { + console.warn('tmui4.0提醒:' + `你关闭了请求调试模式`) + } + } + /** + * 获取整个应用运行期间的所有请求日志列表 + */ + static getHistory() : xRequestHistoryType[] { + return xRequestCall.history.slice(0) + } + static setShowToast(showLoadToast : boolean = true, showSuccessToast : boolean = true, showErrorToast : boolean = true) { + xRequestCall.showLoadToast = showLoadToast + xRequestCall.showSuccessToast = showSuccessToast + xRequestCall.showErrorToast = showErrorToast + } + /** + * 执行Hooks函数。 + */ + private _callFun_build() : Promise { + if (this.status == null) return Promise.resolve([true] as any[]); + // "before"|"after"|"abort"|"timeout"|"error"|"auth"|"success"|"complete" + let fun = this._lisentEventList.filter((el) : boolean => el.type == this.status!) + let funCalls = fun.map((el) : funType => el.fun) + + if (funCalls.length == 0) { + if (this.status == 'auth' || this.status == 'before') { + return Promise.resolve([true] as any[]); + } + return Promise.resolve([this.result] as any[]); + } + + return this._buildPromise(funCalls) + } + /** + * 递归执行异步函数 + * 由于官方的Promise.all,不知道是bug还是什么,始终无法执行成功 + * 因此自己写了个。 + */ + private _buildPromise(lst : funType[]) : Promise { + let _this = this; + let len = lst.length; + let i = 0; + let p = [] as any[] + async function customPromiseAll(evt : funType) : Promise { + if (i >= len) return Promise.resolve(p); + let arg : any = _this.selfOpts + // 非这两事件,全部传递结果集给监听事件中。 + if (_this.status != 'auth' && _this.status != 'before') { + arg = _this.result as xRequestResult + } + let v = await evt(arg); + // 如果这两事件中返回的不是boolean,则强制转换为true通过。 + if ((_this.status == 'auth') && typeof v != 'boolean') { + v = true; + } + if ((_this.status == 'before') && typeof v != 'boolean') { + + let beforeOpts = JSON.stringify(v) + _this.setOptions(JSON.parse(beforeOpts!)!) + v = true; + } + // before中按顺序中断了前面的,后面的不要再执行,直接结束。 + if ((_this.status == 'before') && typeof v == 'boolean') { + let iabort = v as boolean; + if (!iabort) { + p.push(v); + return Promise.resolve(p); + } + } + + // 请后,与事件中返回的修改后的数据覆盖原本的。 + if ((_this.status == 'after') && typeof v == 'object') { + _this.result = v as xRequestResult + + } + // 其它事件则全部结果集。 + if (_this.status == 'success' || _this.status == 'timeout' || _this.status == 'error' || _this.status == 'abort' || _this.status == 'complete') { + v = _this.result + } + + i += 1; + p.push(v); + if (i >= len) return Promise.resolve(p); + return await customPromiseAll(lst[i]); + } + return new Promise((res, rej) => { + + customPromiseAll(lst[i]).then(() => { + res(p) + }) + }) + + } + + + /** + * 请置指定请求的状态值。 + */ + private _setDevReqStatus(id : string) { + if (!xRequestCall.dev) return; + let eventType = this.status; + let index = -1; + for (let i = 0; i < xRequestCall.history.length; i++) { + let item = xRequestCall.history[i]; + if (id == item.id) { + index = i; + break; + } + } + if (index > -1 && eventType != null) { + xRequestCall.history[index].status = eventType; + if (eventType == 'complete' || eventType == 'abort' || eventType == 'auth') { + xRequestCall.history[index].loaded = true; + xRequestCall.history[index].loading = false; + } + if (eventType == 'before') { + xRequestCall.history[index].loading = true; + } + if (eventType == 'success') { + xRequestCall.history[index].time = Date.now() - xRequestCall.history[index].time; + } + if (eventType == 'complete' || eventType == 'success') { + xRequestCall.history[index].result = this.result; + } + } + + } + async request(opts : xRequestOptions | null = null) : Promise { + let _this = this; + + let _thisOpts = this.setOptions(opts) + + let requestId = getUid() + + if (xRequestCall.dev) { + xRequestCall.history.push({ + id: requestId, + loading: true, + loaded: false, + status: "", + time: Date.now(), + api: _thisOpts.url, + result: {} as any + } as xRequestHistoryType) + } + + if (_thisOpts.showLoadToast) { + uni.showLoading({ title: _thisOpts!.loadToastText!, mask: true }) + } + + const url = _thisOpts.hostUrl + _thisOpts.url; + + if (url == "" || _thisOpts.hostUrl == "") { + this.status = 'error'; + this._setDevReqStatus(requestId); + await this._callFun_build() + console.warn("未填写请求接口") + if (_thisOpts.showLoadToast) { + uni.hideLoading() + } + if (_thisOpts.showErrorToast) { + return new Promise((tres, trej) => { + uni.showToast({ title: i18n.t("tmui4x.xRequest.hostFailEmpty"), icon: 'error', mask: true, complete() { trej(_this.result) } }) + }) + } + return Promise.reject(_this.result) + } + + + if (xRequestCall.authPass == false) { + this.status = 'auth' + console.warn("授权失败,中断请求") + this._setDevReqStatus(requestId); + await this._callFun_build() + if (_thisOpts.showLoadToast) { + uni.hideLoading() + } + return Promise.reject(_thisOpts) + } + + // 检查是否使用缓存,只针对post及get方式进行缓存. + if (_thisOpts.useCache && (_thisOpts.method == 'GET' || _thisOpts.method == 'POST')) { + // 尝试从缓存获取响应 + const cachedResponse = this.cacheManager.get(_thisOpts); + + if (cachedResponse != null) { + if (process.env.NODE_ENV == 'development') { + console.log('缓存接口:', _thisOpts.url) + } + const cachedata = cachedResponse as UTSJSONObject + const _cookies = cachedata.getArray('cookies'); + const cacheResult = { + data: cachedata.getAny('data'), + statusCode: cachedata.getNumber('statusCode')!, + header: cachedata.getAny('header')!, + cookies: _cookies == null ? ([] as string[]) : _cookies!, + } as xRequestResult + if (_thisOpts.showLoadToast) { + uni.hideLoading() + } + return Promise.resolve(cacheResult); + } + } + + + this.status = 'before'; + this._setDevReqStatus(requestId); + let jg2 = await this._callFun_build() + let isAbor = (jg2 as boolean[]).some((el) : boolean => !el) + + // 是否中断请求 + if (isAbor) { + console.warn("事件before中断了请求") + this.status = 'abort'; + this._setDevReqStatus(requestId); + await this._callFun_build() + if (_thisOpts.showLoadToast) { + uni.hideLoading() + } + return Promise.reject(this.result) + } + + + // "before" | "after" | "abort" | "timeout" | "error" | "auth" | "success" | "complete" + return new Promise((res, rej) => { + _this.reqtask = uni.request({ + url: url, + data: _thisOpts.data, + header: _thisOpts.header, + method: _thisOpts.method, + timeout: _thisOpts.timeout, + firstIpv4: _thisOpts.firstIpv4, + sslVerify: false, + withCredentials: false, + dataType: _thisOpts.dataType, + responseType: _thisOpts.responseType, + success(rst) { + if (process.env.NODE_ENV == 'development') { + console.log('请求接口成功:', _thisOpts.url, rst) + } + _this.result = { + data: rst.data, + statusCode: rst.statusCode, + header: rst.header, + cookies: rst.cookies as string[], + } as xRequestResult + + _this.status = 'after'; + _this._setDevReqStatus(requestId); + _this._callFun_build() + .then((v) => { + if (_thisOpts.successStatusCode != rst.statusCode) { + _this.status = 'error'; + _this.result.statusCode = rst.statusCode + _this._setDevReqStatus(requestId); + _this._callFun_build() + .then(() => { + if (_thisOpts.showLoadToast) { + uni.hideLoading() + } + if (_thisOpts.showErrorToast) { + let msg = _thisOpts!.errorToastText + msg = msg==""?(i18n.t("tmui4x.xRequest.error")+rst.statusCode.toString()):msg + uni.showToast({ title: msg!, mask: true, icon: 'error', complete() { rej(_this.result) } }) + } else { + rej(_this.result) + } + }) + return; + } + let jgtss = v as xRequestResult[] + let formartv = _this.result as xRequestResult + if (jgtss.length > 0) { + formartv = jgtss[jgtss.length - 1] + } + _this.result = formartv; + + _this.status = 'success'; + _this._setDevReqStatus(requestId); + _this._callFun_build() + .then(() => { + if (_thisOpts.showLoadToast) { + uni.hideLoading() + } + _this.cacheManager.set(_thisOpts, _this.result); + if (_thisOpts.showSuccessToast) { + //默认读取data下的msg字段。 + let d = formartv.data; + let msg = _thisOpts!.successToastText + if (typeof d == 'object' && d != null && !Array.isArray(d)&&msg=="") { + try { + let s = d as UTSJSONObject; + msg = s.getString('msg') != null ? s.getString('msg')! : msg + } catch (e) { + //TODO handle the exception + console.error("服务没有返回msg字段") + } + + } + msg = msg==""?i18n.t("tmui4x.xRequest.success"):msg + uni.showToast({ title: msg!, icon: 'none', mask: true, complete() { res(_this.result) } }) + } else { + res(_this.result) + } + + }) + + }) + + }, + fail(er) { + if (process.env.NODE_ENV == 'development') { + console.error(er) + } + if (er.errCode == 5) { + _this.status = 'timeout'; + } else { + _this.status = 'error'; + } + + _this.result.statusCode = er.errCode + _this._setDevReqStatus(requestId); + _this._callFun_build() + .then(() => { + if (_thisOpts.showLoadToast) { + uni.hideLoading() + } + if (_thisOpts.showErrorToast) { + uni.showToast({ title: i18n.t("tmui4x.xRequest.error") + er.errCode.toString(), mask: true, icon: 'error', complete() { rej(_this.result) } }) + } else { + rej(_this.result) + } + }) + }, + complete() { + _this.status = 'complete'; + _this._setDevReqStatus(requestId); + _this._callFun_build() + + } + }) + + }) + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xTween.uts b/uni_modules/tmx-ui/core/util/xTween.uts new file mode 100644 index 0000000..8521f55 --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xTween.uts @@ -0,0 +1,435 @@ +/** + * 动画过渡函数 + * @version 1.0.0 + * @author tmzdy + * @host https://xui.tmui.design + * @description 异常简便,没有繁杂的配置选项,只有快速的开发部署。 + */ +import bezier from "./bezier.uts" +import { xTweenStatus, xTweenCallbackFunType, xTweenAnimate, xTweenEventCallFunType, xTweenEventCall } from "../../interface.uts" +import { getUid } from "./xCoreUtil.uts"; + +type FrameRequestCallback = (time:number)=>void; + +export class xTween { + private frameId : null | number = null; + //当前全局动画是否在执行中,只要有一个动画在执行就会是true + isRuning : boolean = false; + //所有动画是否结束 + isStoping : boolean = true; + //刷新率,不会立即得出结题,需要有至少执行16ms才可能计算出帖率 + frmae = 0 + // 舞台是否在执行中 + isRendering = false; + + private _callListFun : xTweenEventCallFunType[] = [] + + private _frema_starttimes = 0 + + private enters : (listAni : xTweenEventCallFunType[], tims : number) => void = (listAni : xTweenEventCallFunType[], tims : number) => { } + private complete : () => void = () => { } + + private lastTime = 0 + private nextHandle = 0 + // 存储回调函数的映射 + private callbacks : Map = new Map(); + + private easingList = new Map([ + ["linear", [0.250, 0.250, 0.750, 0.750]], + ["ease", [0.250, 0.100, 0.250, 1.000]], + ["easeIn", [0.420, 0.000, 1.000, 1.000]], + ["easeOut", [0.000, 0.000, 0.580, 1.000]], + ["easeInOut", [0.420, 0.000, 0.580, 1.000]], + ["easeInQuad", [0.550, 0.085, 0.680, 0.530]], + ["easeOutQuad", [0.250, 0.460, 0.450, 0.940]], + ["easeInOutQuad", [0.455, 0.030, 0.515, 0.955]], + ["easeInCubic", [0.550, 0.055, 0.675, 0.190]], + ["easeOutCubic", [0.215, 0.610, 0.355, 1.000]], + ["easeInOutCubic", [0.645, 0.045, 0.355, 1.000]], + ["easeInQuart", [0.895, 0.030, 0.685, 0.220]], + ["easeOutQuart", [0.165, 0.840, 0.440, 1.000]], + ["easeInOutQuart", [0.770, 0.000, 0.175, 1.000]], + ["easeInQuint", [0.755, 0.050, 0.855, 0.060]], + ["easeOutQuint", [0.230, 1.000, 0.320, 1.000]], + ["easeInOutQuint", [0.860, 0.000, 0.070, 1.000]], + ["easeInSine", [0.470, 0.000, 0.745, 0.715]], + ["easeOutSine", [0.390, 0.575, 0.565, 1.000]], + ["easeInOutSine", [0.445, 0.050, 0.550, 0.950]], + ["easeInExpo", [0.950, 0.050, 0.795, 0.035]], + ["easeOutExpo", [0.190, 1.000, 0.220, 1.000]], + ["easeInOutExpo", [1.000, 0.000, 0.000, 1.000]], + ["easeInCirc", [0.600, 0.040, 0.980, 0.335]], + ["easeOutCirc", [0.075, 0.820, 0.165, 1.000]], + ["easeInOutBack", [0.680, -0.550, 0.265, 1.550]], + ["tmxEase", [0.42, 0.38, 0.15, 0.93]] + ]); + + constructor() { + + } + private customRequestAnimationFrame(callback : FrameRequestCallback) : number { + const currTime : number = Date.now(); + const timeToCall : number = Math.max(0, 16 - (currTime - this.lastTime)); + const handle : number = this.nextHandle++; + + this.callbacks.set(handle, callback); + + const id = setTimeout(() => { + callback(currTime + timeToCall); + }, timeToCall); + + this.lastTime = currTime + timeToCall; + return handle; + } + + private customCancelAnimationFrame(handle : number) { + if (this.callbacks.has(handle)) { + this.callbacks.delete(handle); + clearTimeout(handle); + } + } + + /** + * 启动渲染,并非执行动画,执行动画需要使用play + * 但如果不启动渲染,play中的动画都无法执行. + */ + startRender() : xTween { + this.isRendering = true; + if (this.frameId == null) { + this._run(this) + } + return this; + } + /** + * 销毁渲染. + */ + destroy() { + if (this.frameId != null) { + // #ifdef APP||WEB + cancelAnimationFrame(this.frameId!) + // #endif + // #ifdef MP + this.customCancelAnimationFrame(this.frameId!) + // #endif + } + this.frameId = null; + this.isRendering = false; + + } + getFrame() : number { + return this.frmae + } + /** + * 所有事件动画执行完毕 + */ + setComplete(call : () => void) : xTween { + this.complete = call + return this; + } + + /** + * 设置帖动画,舞台渲染执行帖函数 + * 它不是animate动画,没有进度,只会不停的执行.直接舞台渲染被注销. + */ + setEnter(call : (listAni : xTweenEventCallFunType[], tims : number) => void) : xTween { + this.enters = call + return this; + } + /** + * 添加一个动画,可以重复加达到多个动画联合执行的效果 + * 并且 每一个动画都是独立存在,这样可以细微的控制每个动画 + * 来达到联合处理的效果. + */ + addAnimate(opts : xTweenAnimate) : string { + let uid = getUid(); + let call : xTweenEventCall = (item : xTweenEventCallFunType) => { }; + + this._callListFun.push({ + id: uid, + ease: this._getEasing(opts?.ease ?? 'linear'), + duration: opts.duration, + status: 1, + progress: 0, + oldProgeress: 0, + startTime: 0, + autoRemove: opts?.autoRemove != null ? (opts!.autoRemove as boolean) : true, + complete: opts?.complete != null ? (opts!.complete!) : call, + enter: opts?.enter != null ? (opts!.enter!) : call, + start: opts?.start != null ? (opts!.start!) : call, + pause: opts?.pause != null ? (opts!.pause!) : call, + loop: opts?.loop != null ? (opts!.loop!) : 1, + tyty: opts?.tyty != null ? (opts!.tyty!) : false, + step: opts?.step != null ? (opts!.step!) : 1, + _finishLoop: 0, + reverse: false + } as xTweenEventCallFunType) + return uid; + } + /** + * 删除一个事件. + * @param {string} uid 如果为null表示删除所有. + */ + removeAnimate(uid : string | null = null) : xTween { + if (uid == null) { + this._callListFun = [] as xTweenEventCallFunType[] + } else { + let index = this._getCallIndex(uid as string); + if (index > -1) { + this._callListFun.splice(index, 1) + } + } + return this; + } + /** + * 播放动画。 + * @param {string|null} uid 动画id,如果不填写或者为null表示播放所有动画 + */ + play(uid : string | null = null) { + if (uid != null && uid != '') { + let index = this._getCallIndex(uid! as string) + if (index > -1) { + let item = this._callListFun[index] + if (item.status == 1) { + this._by_run_set_status(item, 1) + this._by_run_item_callFun(item, 0) + + } + // 马上要执行运行 + this._by_run_set_status(item, 4) + } + } else { + for (let i = 0; i < this._callListFun.length; i++) { + let item = this._callListFun[i] + if (item.status == 1) { + this._by_run_set_status(item, 1) + this._by_run_item_callFun(item, 0) + } + + this._by_run_set_status(item, 4) + + } + } + this._setGlobaleStatus(1) + } + getAnimationListLen() : number { + return this._callListFun.length; + } + /** + * 暂停动画。 + * @param {string|null} uid 动画id,如果不填写或者为null表示暂停所有动画 + */ + pause(uid : string | null = null) : xTween { + if (uid != null && uid != '') { + let index = this._getCallIndex(uid! as string) + if (index > -1) { + let item = this._callListFun[index] + + this._by_run_set_status(item, this._isLoopPauseing(item) ? 6 : 3) + this._by_run_item_callFun(item, item.progress) + } + } else { + for (let i = 0; i < this._callListFun.length; i++) { + let item = this._callListFun[i] + this._by_run_set_status(item, this._isLoopPauseing(item) ? 6 : 3) + this._by_run_item_callFun(item, item.progress) + } + this._setGlobaleStatus(2) + } + return this; + } + /** + * 结束动画。 + * @param {string|null} uid 动画id,如果不填写或者为null表示结束所有动画 + */ + stop(uid : string | null = null) : xTween { + + if (uid != null && uid != '') { + let index = this._getCallIndex(uid! as string) + if (index > -1) { + let item = this._callListFun[index] + this._by_run_set_status(item, 2) + this._by_run_item_callFun(item, 1) + } + } else { + for (let i = 0; i < this._callListFun.length; i++) { + let item = this._callListFun[i] + this._by_run_set_status(item, 2) + this._by_run_item_callFun(item, 1) + } + this._callListFun = this._callListFun.filter((el : xTweenEventCallFunType) : boolean => !el.autoRemove) + this.enters(this._callListFun, 0) + } + return this; + } + + private _getEasing(args : any) : xTweenCallbackFunType | null { + let fun : xTweenCallbackFunType | null = (x : number) : number => x; + if (typeof args == 'string') { + let animateNumber = this.easingList.get(args as string) + if (animateNumber != null) { + let ease = animateNumber! as number[] + fun = bezier(ease[0], ease[1], ease[2], ease[3]) + } + } else if (Array.isArray(args)) { + let argsar = args as number[] + if (argsar.length == 4) { + fun = bezier(argsar[0], argsar[1], argsar[2], argsar[3]) + } + } else { + let animateNumber = this.easingList.get('linear') + if (animateNumber != null) { + let ease = animateNumber! as number[] + fun = bezier(ease[0], ease[1], ease[2], ease[3]) + } + } + + return fun; + } + private _getCallIndex(uid : string) : number { + let index = -1; + for (let i = 0; i < this._callListFun.length; i++) { + let item = this._callListFun[i] + if (item.id == uid) { + index = i; + break; + } + } + return index; + } + + private _isLoopPauseing(item : xTweenEventCallFunType) : boolean { + if (item.loop == -1) return true; + if (item._finishLoop < item.loop) return true; + return false; + } + private _by_run_set_status(item : xTweenEventCallFunType, status : xTweenStatus) { + + if (status == 1) { + item.progress = 0 + item.startTime = 0 + item._finishLoop = 0 + } else if (status == 2) { + item.progress = 1; + item.oldProgeress = 0; + item.startTime = 0 + item._finishLoop = item.loop + } else if (status == 3) { + item.startTime = 0 + item.oldProgeress = item.progress + } else if (status == 5) { + item.progress = 0 + item.oldProgeress = 0 + item.startTime = 0 + } else if (status == 6) { + item.oldProgeress = item.progress + item.startTime = 0 + } + item.status = status; + } + + private _by_run_item_callFun(item : xTweenEventCallFunType, progress : number) { + if (item.status == 1) { + item.start(item) + } + if (item.status == 2) { + item.enter(item) + item.complete(item) + if (item.autoRemove) { + let index = this._getCallIndex(item.id) + if (index > -1) { + this._callListFun.splice(index, 1) + } + } + } + if (item.status == 3) { + item.pause(item) + } + if (item.status == 4 || item.status == 5) { + item.enter(item) + } + } + + /** + * 1:执行中 + * 2:未在执行动画。 + */ + private _setGlobaleStatus(type : number) { + if (type == 1) { + this.isRuning = true; + this.isStoping = false + } else if (type == 2) { + this.isRuning = false; + this.isStoping = true + } + } + + private _run(_this : xTween) { + if (!_this.isRendering) { + return; + } + function actions(times:number){ + _this.enters(_this._callListFun, times) + if (_this._frema_starttimes == 0) { + _this._frema_starttimes = times + } + let isAllCompelted = true; + for (let i = 0; i < _this._callListFun.length; i++) { + let item = _this._callListFun[i] + let isFinishStatus = 1 + if (item.status == 4 || item.status == 5) { + if (item.startTime == 0) { + item.startTime = times + } + // 计算当前进度 + if (_this.frmae > 0) { + let progress = Math.min((times - (item.startTime)) / item.duration + item.oldProgeress, 1); + + let eas = item.ease! + item.progress = eas(progress) + + if (progress == isFinishStatus) { + item._finishLoop += 1 + if (item.loop > 0) { + if (item.loop == item._finishLoop) { + _this._by_run_set_status(item, 2) + _this._by_run_item_callFun(item, isFinishStatus) + + } else { + _this._by_run_set_status(item, 5) + } + } else if (item.loop == -1) { + _this._by_run_set_status(item, 5) + } + if (item.tyty) { + item.reverse = !item.reverse + } + } + _this._by_run_item_callFun(item, item.progress) + } + + } + if (item.progress != 2) { + isAllCompelted = false; + } + } + if (isAllCompelted && _this.isRuning) { + _this.complete() + _this._setGlobaleStatus(2) + } + _this.frmae = Math.ceil(1000 / (times - _this._frema_starttimes)) + _this._frema_starttimes = times + _this._run(_this) + } + // #ifdef APP||WEB + _this.frameId = requestAnimationFrame((times : number) => { + actions(times) + }) + // #endif + // #ifdef MP + _this.frameId = this.customRequestAnimationFrame((times : number) => { + actions(times) + }) + // #endif + } + +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/core/util/xUploadFileMedia.uts b/uni_modules/tmx-ui/core/util/xUploadFileMedia.uts new file mode 100644 index 0000000..a0fca42 --- /dev/null +++ b/uni_modules/tmx-ui/core/util/xUploadFileMedia.uts @@ -0,0 +1,528 @@ +import { XUPLOADFILE_INFO, XUPLOADFILE_FILE_VALUE, XUPLOADFILE_FILE_INFO, XUPLOADFILE_EVENT_NAME } from "../../interface.uts" +import { getUid } from "./xCoreUtil.uts" +import { xConfig } from "../../config/xConfig.uts" +type CONFIG = { + count : number, + sourceType : Array, + sizeType : Array, + hostUrl : string, + name : string, + header : UTSJSONObject, + formData : UTSJSONObject, + multipart : boolean, + autoUpload : boolean, + statusCode : number, + compress:boolean, + quality:number|null, + compressedHeight:number|null, + compressedWidth:number|null + + +} + +/** + * 媒体文件上传 + */ +export class xUploadMedia { + model = 'photo' + videoOps={ + pageOrientation:'auto', + albumMode:'system', + sourceType:['album', 'camera'] as string[], + compressed:true, + maxDuration:60, + camera:'back' + } as UTSJSONObject + config = { + count: 9, + sourceType: ['album', 'camera'], + sizeType: ['original', 'compressed'], + hostUrl: "", + name: "file", + header: {} as UTSJSONObject, + multipart: false, + formData:{} as UTSJSONObject, + autoUpload: true, + statusCode: 200, + compress:true, + quality:80, + compressedHeight:null, + compressedWidth:null + } as CONFIG + fileList : Array = [] + currentIndex = 0; + uploading = false; + uploadObj = null as null | UploadTask + systemError = xConfig.i18n.t("tmui4x.uploadMedia.systemError") + limitMaxCount = xConfig.i18n.t("tmui4x.uploadMedia.limitMaxCount") + constructor(opts : XUPLOADFILE_INFO = {} as XUPLOADFILE_INFO) { + this.chuliConfigArgs(opts) + } + chooseBefore = (res : string[]) : Promise => Promise.resolve(res) + complete = (res : XUPLOADFILE_FILE_INFO[]) : Promise => Promise.resolve(res) + change = (res : XUPLOADFILE_FILE_INFO[]) : Promise => Promise.resolve(res) + beforeComplete = (res : XUPLOADFILE_FILE_INFO) :XUPLOADFILE_FILE_INFO => res + myChangeSync = function (res : XUPLOADFILE_FILE_INFO[]) { } + beforeUpload = (res : XUPLOADFILE_FILE_INFO) : Promise => Promise.resolve(res) + events:Map Promise> = new Map(); + + + /** + * 处理配置参数 + * @param opts 配置参数 + */ + private chuliConfigArgs(opts : XUPLOADFILE_INFO) : CONFIG { + this.config = { + count: opts.count == null ? this.config.count : opts.count as number, + statusCode: opts.statusCode == null ? this.config.statusCode : opts.statusCode as number, + sourceType: opts.sourceType == null ? this.config.sourceType : opts.sourceType as string[], + sizeType: opts.sizeType == null ? this.config.sizeType : opts.sizeType as string[], + hostUrl: opts.hostUrl == null ? this.config.hostUrl : opts.hostUrl as string, + name: opts.name == null ? this.config.name : opts.name as string, + header: opts.header == null ? this.config.header : opts.header as UTSJSONObject, + formData: opts.formData == null ? this.config.formData : opts.formData as UTSJSONObject, + multipart: opts.multipart == null ? this.config.multipart : opts.multipart as boolean, + autoUpload: opts.autoUpload == null ? this.config.autoUpload : opts.autoUpload as boolean, + compress: opts.compress == null ? this.config.compress : opts.compress as boolean, + quality: opts.quality == null ? this.config.quality : opts.quality as number, + compressedHeight: opts.compressedHeight, + compressedWidth: opts.compressedWidth, + } as CONFIG + return this.config + } + + stop() { + if (this.uploadObj == null) return + this.currentIndex = 0; + this.uploading = false; + this.uploadObj!.abort() + this.uploadObj = null; + console.info("xUploadMedia:中断上传") + } + chooseMedia() { + if (this.fileList.length == this.config.count) { + // "已超最大上传数量" + uni.showToast({ title: this.limitMaxCount, mask: true, icon: 'none' }) + console.warn("xUploadMedia:已经超过最大上传数量") + return; + } + if(this.model == 'photo'){ + uni.chooseImage({ + count: Math.max(this.config.count - this.fileList.length, 0), + sourceType: this.config.sourceType, + sizeType: this.config.sizeType, + success: (res) => { + + let temps = [] as UTSJSONObject[] + // #ifdef uniVersion >= 4.31 + let items = res.tempFiles; + for(let i=0;i { + + this.addNewFile(temps) + + if (this.config.autoUpload && !this.uploading){ + this.start() + } + }).catch(er => { + console.error(er) + uni.showModal({ + title:this.systemError, + content:er as string, + showCancel:false + }) + }) + + } else { + // @ts-ignore + let tps = res.tempFilePaths as UTSJSONObject + chooseBefore([tps] as UTSJSONObject[]).then(() => { + this.addNewFile(temps) + if (this.config.autoUpload && !this.uploading){ + this.start() + } + }).catch(er => { + console.error(er) + uni.showModal({ + title:this.systemError, + content:er as string, + showCancel:false + }) + }) + } + }else{ + + if (Array.isArray(temps)) { + this.addNewFile(temps) + if (this.config.autoUpload && !this.uploading){ + this.start() + } + }else{ + // @ts-ignore + let tps = res.tempFilePaths as UTSJSONObject + this.addNewFile([tps] as UTSJSONObject[]) + if (this.config.autoUpload && !this.uploading){ + this.start() + } + } + + } + + + + }, + fail: (err) => { + this.chooseBefore([] as string[]) + console.warn("xUploadMedia:", err) + } + }) + }else if(this.model == 'video'){ + let pageOrientation = this.videoOps.getString('pageOrientation') + pageOrientation = pageOrientation==null?'auto':pageOrientation + let albumMode = this.videoOps.getString('albumMode') + albumMode = albumMode==null?'system':albumMode + let sourceType = this.videoOps.getArray('sourceType') + sourceType = sourceType==null?(['album', 'camera'] as string[]):sourceType + let compressed = this.videoOps.getBoolean('compressed') + compressed = compressed==null?true:compressed + let maxDuration = this.videoOps.getNumber('maxDuration') + maxDuration = maxDuration==null?60:maxDuration + let camera = this.videoOps.getString('camera') + camera = camera==null?'back':camera + uni.chooseVideo({ + pageOrientation, + albumMode, + sourceType, + compressed, + maxDuration, + camera, + success: (res) => { + + let temps = [ + {path:res.tempFilePath,size:res.size} as UTSJSONObject + ] as UTSJSONObject[] + + let chooseBefore = this.events.get('chooseBefore') + if(chooseBefore!=null){ + chooseBefore([res.tempFilePath] as string[]).then(() => { + this.addNewFile(temps) + if (this.config.autoUpload && !this.uploading){ + this.start() + } + }).catch(er => { + console.error(er) + uni.showModal({ + title:this.systemError, + content:er as string, + showCancel:false + }) + }) + }else{ + this.addNewFile(temps) + if (this.config.autoUpload && !this.uploading){ + this.start() + } + } + + }, + fail: (err) => { + this.chooseBefore([] as string[]) + console.warn("xUploadMedia:", err) + } + } as ChooseVideoOptions) + } + + } + + /** + * 增加事件监听 + * @param eventName 事件名称 + * @param callback(res : T) => Promise 回调,注意如果是chooseBefore,外部回调时res是string[],其它为 XUPLOADFILE_FILE_INFO[] + */ + addListenEvent(eventName : XUPLOADFILE_EVENT_NAME, callback : (res : any) => Promise) { + this.events.set(eventName,callback) + // if (eventName == 'chooseBefore') { + // this.chooseBefore = (res2 : string[]) : Promise => callback(res2 as unknown[] as T) as Promise + // } else if (eventName == 'complete') { + // this.complete = (res2 : XUPLOADFILE_FILE_INFO[]) : Promise => callback(res2 as unknown[] as T) as Promise + // } else if (eventName == 'change') { + // this.change = (res2 : XUPLOADFILE_FILE_INFO[]) : Promise => callback(res2 as unknown[] as T) as Promise + // } + + } + + /** + * 增加事件监听 + * @param eventName 事件名称 + * @param callback(res : T) => Promise 回调,注意如果是chooseBefore,外部回调时res是string[],其它为 XUPLOADFILE_FILE_INFO[] + */ + addListenEventsss(eventName : XUPLOADFILE_EVENT_NAME, callback : (res : T) => Promise) { + if (eventName == 'chooseBefore') { + this.chooseBefore = (res2 : string[]) : Promise => callback(res2 as unknown[] as T) as Promise + } else if (eventName == 'complete') { + this.complete = (res2 : XUPLOADFILE_FILE_INFO[]) : Promise => callback(res2 as unknown[] as T) as Promise + } else if (eventName == 'change') { + this.change = (res2 : XUPLOADFILE_FILE_INFO[]) : Promise => callback(res2 as unknown[] as T) as Promise + } + + } + /** + * 设置上传的配置参数 + * @param opts 配置参数-XUPLOADFILE_INFO + */ + setConfig(opts : XUPLOADFILE_INFO) { + this.chuliConfigArgs(opts) + } + + setVideoOps(config:UTSJSONObject,model:string){ + this.videoOps = config + this.model = model; + } + setChangeSync(callBack : (res : XUPLOADFILE_FILE_INFO[]) => void) { + this.myChangeSync = function (res2 : XUPLOADFILE_FILE_INFO[]) { + callBack(res2) + } + } + delFile(id : string) : boolean { + let index = this.fileList.findIndex((item : XUPLOADFILE_FILE_INFO) : boolean => item.id == id) + if (index >= 0) { + let item = this.fileList[index]; + if (item.status == 1) { + item.status = 4 + item.statusText = "取消上传" + this.stop() + } + this.fileList.splice(index, 1) + this.myChangeSync(this.fileList) + return true; + } + return false + } + clear(){ + this.fileList = [] as XUPLOADFILE_FILE_INFO[] + this.myChangeSync(this.fileList) + } + /** + * 添加新选择的未上传文件 + */ + private addNewFile(files : UTSJSONObject[]) { + if (files.length == 0) return; + let t = this; + // #ifdef APP-ANDROID||APP-IOS + if(this.model == 'photo'){ + let i=0; + function compress(){ + if(i>=files.length) return; + let item = files[i]! as UTSJSONObject; + uni.compressImage({ + src: item.getString('path')!, + quality: t.config.quality, + compressedHeight: t.config.compressedHeight, + compressedWidth: t.config.compressedWidth, + success: (res:CompressImageSuccess) => { + item.set("path",res.tempFilePath) + i+=1; + compress() + }, + fail: (err) => { + i+=1; + compress() + } + }) + } + if(this.config.compress){ + compress() + } + } + // #endif + + + files.forEach((item : UTSJSONObject) => { + let id = getUid(); + let name = ""; + let size = 0 + // #ifdef APP + let items = item as UTSJSONObject + name = items.getString('path')! + size = items.getNumber('size')! + // #endif + + // #ifndef APP + name = item.path! + size = item.size! + // #endif + + this.fileList.push({ + id: id, + type: "", + size: size, + extension: name.substring(name.lastIndexOf(".") + 1), + statusText: '待上传', + status: 0, + path: name, + progress: 0, + response: "", + name: name.substring(name.lastIndexOf("/") + 1), + model:this.model + } as XUPLOADFILE_FILE_INFO) + }) + + this.myChangeSync(this.fileList) + + } + addFile(files:XUPLOADFILE_FILE_VALUE[]){ + let ids = this.fileList.map((el:XUPLOADFILE_FILE_INFO):string=>el.id) + let i=0; + files.forEach((el:XUPLOADFILE_FILE_VALUE)=>{ + let oldId = el.id == null?"":el.id! as string; + if(!ids.includes(oldId)){ + let id = getUid(); + let name = el.url + let status = el?.status??2; + this.fileList.push({ + id: id, + type: "", + size: 0, + extension: name.substring(name.lastIndexOf(".") + 1), + statusText: status==2?'上传成功':'待上传', + status: el?.status??2, + path: name, + progress: status==2?100:0, + response: el.response == null ?"":el.response! as string, + name: name.substring(name.lastIndexOf("/") + 1) + } as XUPLOADFILE_FILE_INFO) + ++i; + } + }) + + if(i>0){ + this.myChangeSync(this.fileList) + } + + } + _addFilesByself(files:XUPLOADFILE_FILE_INFO[]){ + this.fileList = files.slice(0) + } + + /** + * 获取待上传的文件数量。 + */ + private getWaitUploadFilesNumber() : number { + let num = 0; + this.fileList.forEach((item : XUPLOADFILE_FILE_INFO) => { + if (item.status == 0 || item.status == 3 || item.status == 4) { + num += 1; + } + }) + return num; + } + start() { + if (this.uploading) return; + this.uploading = true; + this.currentIndex = 0 + this.uploadFile(); + } + private uploadFile() { + // if (!this.config.autoUpload) return; + + // if (this.fileList.length == 0 || this.getWaitUploadFilesNumber() == 0) { + // this.uploadObj = null + // this.uploading = false; + // console.warn("xUploadMedia:上传结束了") + // return; + // } + + + + if (this.currentIndex >= this.fileList.length) { + this.uploadObj = null; + this.uploading = false; + + this.complete(this.fileList) + this.myChangeSync(this.fileList) + let complete = this.events.get('complete') + + if(complete!=null){ + complete(this.fileList.slice(0)) + } + return; + } + + this.beforeUpload(this.fileList[this.currentIndex]).then((beforeUploadFileRes:XUPLOADFILE_FILE_INFO)=>{ + this.fileList[this.currentIndex] = beforeUploadFileRes; + let nowitemStatus = this.fileList[this.currentIndex].status + if (nowitemStatus == 1 || nowitemStatus == 2 || nowitemStatus == 5) { + this.uploadObj = null + this.uploading = false; + this.currentIndex += 1; + this.uploadFile(); + return; + } + this.fileList[this.currentIndex].status = 1; + this.fileList[this.currentIndex].statusText = "上传中"; + this.myChangeSync(this.fileList) + this.uploadObj = uni.uploadFile({ + url: this.config.hostUrl, + filePath: this.fileList[this.currentIndex].path, + name: this.config.name, + formData: this.config.formData, + header:this.config.header, + success: (uploadFileRes) => { + if (uploadFileRes.statusCode != 200) { + this.fileList[this.currentIndex].status = 3; + this.fileList[this.currentIndex].statusText = "上传失败"; + this.currentIndex += 1; + this.uploadFile(); + this.myChangeSync(this.fileList) + return; + } + this.fileList[this.currentIndex].status = 2; + this.fileList[this.currentIndex].response = uploadFileRes.data; + this.fileList[this.currentIndex].statusText = "上传成功"; + let itemtemp = this.fileList.slice(0)[this.currentIndex] + let calllItem = this.beforeComplete(itemtemp) + this.fileList[this.currentIndex] = calllItem + this.currentIndex += 1; + this.uploadFile(); + this.myChangeSync(this.fileList) + + }, + fail: (err) => { + console.error("上传失败了,请检查配置:",err) + this.fileList[this.currentIndex].status = 3; + this.fileList[this.currentIndex].statusText = "上传失败"; + this.currentIndex += 1; + this.uploadFile(); + }, + complete: () => { + this.myChangeSync(this.fileList) + } + }) + + this.uploadObj?.onProgressUpdate((res) => { + + this.fileList[this.currentIndex].progress = res.progress; + // if(res.progress == 100){ + // this.fileList[this.currentIndex].status = 1; + // this.fileList[this.currentIndex].statusText = "上传中"; + // }else{ + // this.fileList[this.currentIndex].status = 1; + // this.fileList[this.currentIndex].statusText = "上传中"; + // } + this.myChangeSync(this.fileList) + }) + + }) + + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/index.uts b/uni_modules/tmx-ui/index.uts new file mode 100644 index 0000000..9e61cb6 --- /dev/null +++ b/uni_modules/tmx-ui/index.uts @@ -0,0 +1,74 @@ +import * as xStorex from "./config/xConfig.uts" +import * as uToll from "./core/util/xCoreUtil.uts" +import * as xColor from "./core/util/xCoreColorUtil.uts" +import * as xComponentsStore from "./core/util/config.uts" + +import { xTween } from "./core/util/xTween.uts" +import { xDate, createDate } from "./core/util/xDate.uts" +import { xRequest } from "./core/util/xRequest.uts" +import { xRequestCall } from "./core/util/config.uts" +import { xAnimate } from "./core/util/xAnimate.uts" +import { xUploadMedia } from "./core/util/xUploadFileMedia.uts" +import xui from "./config/xui.uts" +export { + xRequest, + xRequestCall, + xDate, + createDate, + xColor, + xAnimate, + xUploadMedia, + xTween, + xui + +} +export class xStore { + public static xConfig = xStorex.xConfig; + public static setConfig = xStorex.setConfig; + public static getDarkModel = xStorex.getDarkModel + public static setDarkModel = xStorex.setDarkModel + public static getThemePrimary = xStorex.getThemePrimary + public static setThemePrimary = xStorex.setThemePrimary + public static xProvitae = xStorex.xProvitae + public static xTabbarConfig = xStorex.xTabbarConfig +} +export class tool { + /** + * 防抖 + * @description 使用方法 + * let debounce = tool.debounce((args:any)=>{ + console.log(args,'---') + },0,true) + debounce(88) + */ + public static debounce(func : (args : any) => void, wait : number, immediate ?: boolean) : (args : any) => number | null { + let timeout : number | null = null; + let callNow = immediate == null ? true : (immediate! as boolean); + // 返回的函数是实际被调用的防抖函数 + return (args : any) : number | null => { + if (timeout != null && callNow == true) { + return timeout; + } + if (timeout != null) { + clearTimeout(timeout! as number); + timeout = null; + } + + // 决定是否立即执行函数 + if (callNow == true) { + + func(args) + timeout = setTimeout(() => { + timeout = null; + }, wait); + return timeout; + } + // 否则,设置定时器以稍后执行函数 + timeout = setTimeout(() => { + func(args) + + }, wait); + return timeout + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/interface.uts b/uni_modules/tmx-ui/interface.uts new file mode 100644 index 0000000..3eb1e41 --- /dev/null +++ b/uni_modules/tmx-ui/interface.uts @@ -0,0 +1,996 @@ +import { I18nOptions,Tmui4xI18nTml} from "@/uni_modules/x-vuei18n-s/interface.uts" +export type NAVIGATE_TYPE = "navigate" | "redirect" | "switchTab" | "reLaunch" | "navigateBack"; +/** + * 下拉菜单类型子项目信息 + */ +export type XDROPDOWN_LISTITEM_INFO_TYPE = { + /** 下拉列表项的唯一标识符 */ + id : string, + /** 下拉列表项的标题 */ + title : string, + /** 下拉列表项的键名 */ + keyName : string, + /** 下拉列表项的图标 */ + icon : string, + /** 下拉列表项激活状态下的图标 */ + activeIcon : string, + /** 下拉列表项的字体颜色 */ + fontColor : string, + /** 下拉列表项激活状态下的字体颜色 */ + activeFontColor : string, + /** 下拉列表项的字体大小 */ + fontSize : string, + /** 是否是按钮类型的下拉列表项 */ + isBtn : boolean +} + +/** + * 节点的信息 + */ +export type NODE_INFO = { + /** 节点左边界的位置 */ + left : number, + /** 节点的宽度 */ + width : number, + /** 节点的高度 */ + height : number, + /** 节点底部的位置 */ + bottom : number, + /** 节点右边界的位置 */ + right : number, + /** 节点顶部的位置 */ + top : number +} +/** + * 消息条的数据类型 + */ +export type SNACKBAR_INFO = { + /** + * 可选的背景颜色 + */ + background ?: string, + /** + * 可选的文字颜色属性 + */ + color ?: string, + /** + * 可选的字体大小属性 + */ + fontSize ?: string, + /** + * 必需的内容属性 + */ + content : string, + /** + * 必需的id属性 + */ + id : number, + /** + * 图标 + */ + icon ?: string +} +/** + * 消息条的数据类型 + */ +export type SNACKBAR_ITEM = { + background : string, + color : string, + fontSize : string, + content : string, + id : number, + icon : string +} + +/** + * 多选,选项组的子节点属性。 + */ +export type CHECKBOX_ITEM_INFO = { + id : string, + /** 当前选中的值 */ + nowvalue :string|number|boolean, + /** 选中的值 */ + value :string|number|boolean, + /** 未选中的值 */ + unvalue : string|number|boolean +} +/** + * 单选,选项组的子节点属性。 + */ +export type RADIO_ITEM_INFO = { + id : string, + /** 当前选中的值 */ + nowvalue : string|number|boolean, + /** 选中的值 */ + value : string|number|boolean, + /** 未选中的值 */ + unvalue : string|number|boolean +} +/** + * 单选按钮组件类型 + */ +export type RADIO_BUTTON = { + id : string, + icon ?: string, + title : string, + /** 是否禁用 */ + disabled ?: boolean +} +/** + * 宫格项目类型 + */ +export type XGRID_ITEM_INFO = { + iconSize : string, + fontSize : string, + iconColor : string, + fontColor : string, + fontDarkColor:string, + darkIconColor : string +} +/** + * 动作菜单项目类型 + */ +export type XACTION_MENU_ITEM_INFO = { + iconSize ?: string, + fontSize ?: string, + iconColor ?: string, + fontColor ?: string, + icon ?: string, + disabled ?: boolean, + id : string, + text : string, +} + +/** + * 词云项目类型 + */ +export type TEXTCLOUD_ITEM_INFO = { + /** 文本 **/ + text : string, + /** 权重 **/ + weight : number, + /** 颜色值 **/ + color ?: string +} +/** + * tabs组件项目类型 + */ +export type TABS_ITEM_INFO = { + /** 标题 **/ + title : string, + /** 是否禁用 **/ + disabled ?: boolean, + /** 唯一标识,如果不提供,会当作idnex索引取代 **/ + id ?: string, + /** 角标类型,dot,label,"",空时不显示 */ + dotType ?: "" | "dot" | "label", + /** 角标背景颜色 */ + dotColor ?: string, + /** 角标文本,只有dotType="number"时有效 */ + dotText ?: string, +} + +export type TABS_ITEM = { + /** 标题 **/ + title : string, + /** 是否禁用 **/ + disabled : boolean, + /** 唯一标识,如果不提供,会当作idnex索引取代 **/ + id : string, + /** 角标类型,dot,number,"",空时不显示 */ + dotType : string, + /** 角标背景颜色 */ + dotColor : string, + /** 角标文本,只有dotType="number"时有效 */ + dotText : string, +} + +/** + * 侧边分类数据 + */ +export type SLIDER_TREE_ITEM_INFO = { + id : string, + title : string, + children ?: SLIDER_TREE_ITEM_INFO[], + disabled ?: boolean, + //菜单左侧小图标 + icon ?: string, + /** 选中的子级值 */ + selected ?: string[], +} +/** + * 底部导航项目信息tabbar + */ +export type TABBAR_ITEM_INFO = { + /** + * 标题 + * @type {string} + */ + title ?: string; + /** + * 图标 + * @type {string} + */ + icon ?: string; + /** + * 被选中时的图标 + * @type {string} + */ + selectedIcon ?: string; + /** + * 是否禁用 + * @type {boolean} + */ + disabled ?: boolean; + + /** + * 默认颜色 + * @type {string} + */ + color ?: string; + /** + * 选中时的颜色 + * @type {string} + */ + selectedColor ?: string; + + /** + * 打开方式 + * @type {NAVIGATE_TYPE} + */ + openType ?: NAVIGATE_TYPE; + /** + * 链接地址 + * @type {string} + */ + url ?: string; + /** + * 是否显示角标。如果为dot,dotLabel不为空优先展示文本角标 + * dot, + * label + */ + dotType ?: string, + /** + * 文本角标。空不展示。 + */ + dotLabel ?: string +} + +export type TABBAR_ITEM = { + title : string, + icon : string, + selectedIcon : string, + disabled : boolean, + color : string, + selectedColor : string, + openType : string, + url : string, + /** + * 是否显示角标。如果为dot,dotLabel不为空优先展示文本角标 + * dot, + * label + */ + dotType ?: string, + /** + * 文本角标。空不展示。 + */ + dotLabel ?: string +} + +/** + * xUploadMedia组件参数配置表类型 + */ +export type XUPLOADFILE_INFO = { + /** 最大上传数量 */ + count ?: number, + sourceType ?: Array, + sizeType ?: Array, + /** 上传地址 */ + hostUrl ?: string, + /** 上传的文件字段名 */ + name ?: string, + header ?: UTSJSONObject, + formData ?: UTSJSONObject, + /** + * 开启多文件同时上传。 + * 开启后注意:多个文件中的字段名name都是file + */ + multipart ?: boolean, + autoUpload ?: boolean, + /** 开发者服务器返回code,默认是200,非200表示上传失败。 */ + statusCode ?: number, + compress ?: boolean, + quality ?: number | null, + compressedHeight ?: number | null, + compressedWidth ?: number | null + +} +/** + * 0未上传,1上传中,2上传成功,3上传失败(网络错误),4已取消(终止,上到一半取消了),5超过大小 + */ +export type XUPLOADFILE_FILE_STATUS = 0 | 1 | 2 | 3 | 4 | 5 + +/** + * 上传的文件类型 + */ +export type XUPLOADFILE_FILE_INFO = { + id : string, + /** 文件类型 */ + type : string, + /** 文件大小 */ + size : number, + /** 文件路径 */ + path : string, + /** 文件名 */ + name : string, + /** 文件扩展名 */ + extension : string, + progress : number, + statusText : string, + status : XUPLOADFILE_FILE_STATUS, + response : string, + /** 文件类型,photo,video */ + model ?: string +} +/** + * 选择前|选择结束|上传前|成功|失败|完成前|完成|任何变动触发 + * chooseBefore|chooseAfter|beforeUpload|success|fail|beforeComplete|complete|change + */ +export type XUPLOADFILE_EVENT_NAME = "chooseBefore" | "chooseAfter" | "beforeUpload" | "success" | "fail" | "beforeComplete" | "complete" | "change" + +/** + * 文件上传双向绑定的对象类型 + */ +export type XUPLOADFILE_FILE_VALUE = { + id ?: string, + response ?: string, + url : string, + /** 可选字段状态值,如果你自己添加的文件路径错误,再上传时安卓是直接引发io错误,uni.upload是捕捉不到的,请小心使用状态值,默认为2即用户添加的代表上传成功,其它值:0等待,1失败,2成功,3上传中,4超过大小。 */ + status ?: number +} + + +/** + * picker数据结构 + */ +export type PICKER_ITEM_INFO = { + title : string, + id ?: string, + children ?: PICKER_ITEM_INFO[], + disabled ?: boolean +} + +/** + * picker数据结构项目结构 + */ +export type X_PICKER_X_ITEM = { + id : string, + title : string, + children : X_PICKER_X_ITEM[], + disabled : boolean, +} + + +/** + * 极联器数据 + */ +export type CASCADER_ITEM_INFO = { + id : string, + title : string, + children ?: CASCADER_ITEM_INFO[], + disabled ?: boolean, + /** 选中的子级值 */ + selected ?: string[], +} + +export type CALLFUN_T_BOOLEAN = (val : any) => boolean; +export type FORM_RULE_TYPE = '' | 'string' | 'number' | 'array' | 'UTSJSON' | 'phone' | 'email' | 'boolean' | 'date' +/** +* 表单校验对象 +*/ +export type FORM_RULE = { + /** + * 字段类型,空值为自动判断 ,不填写默认为空,自动判断. + */ + type ?: FORM_RULE_TYPE, + /** + * 校验函数。默认根据泛型判断字段值,如果不填写默认为自带的校验函数校验. + */ + valid ?: (val : any | null) => boolean, + /** + * 错误信息,默认为自动根据类型编写提示 + */ + errorMessage ?: string, + /** + * 最大值,如果为空值或者为-1表示不限制大小,(数组和字符串是长度,数字是值,utsjson是key字段数量) + * 如果type=date时.max是以毫秒值的时间值可以通过Date.getTime()或者通过我的xDate来取值 + */ + max ?: number, + /** + * 最小值,如果为空默认为1,(数组,字符,utsjson为1,长不能小于1) + * * 如果type=date时,默认1不作判断请提供大于的值,此时只会校验val是不是合法的date值 + */ + min ?: number, + /** + * 触发时机,只针对input有效,其它默认全是change + * change变化时触发,blur失焦时触发(如果你配置在非input组件上,会导致无法校验,因为只有input才有blur事件.) + */ + trigger ?: "change" | "blur" +}; +export type FORM_SUBMIT_OBJECT = { + errorMessage : string, + valid : boolean, + key : string, + value : any | null +} +/** + * 提交表单时的验证结果 + */ +export type FORM_SUBMIT_RESULT = { + /** + * 是否验证通过 + */ + valid : boolean, + /** + * 首次(验证失败的第一个字段,并非你字段中的顺序,是按渲染顺序来)验证失败的字段 错误信息 + */ + errorMessage : string, + /** + * 首次(验证失败的第一个字段,并非你字段中的顺序,是按渲染顺序来)验证失败的字段 key + */ + key : string, + + formData : FORM_SUBMIT_OBJECT[] +} + +export type CASCADER_TREE_ITEM = { + id : string, + title : string, + children : CASCADER_TREE_ITEM[], + disabled : boolean, + /** 当前选中的id数组 */ + selected : string[], + checked:boolean +} + +export type CASCADER_PATH_MENU_TYPE = { + indexPath:number[], + ids:string[], + pathData:CASCADER_TREE_ITEM[] +} + +/** + * xAnimate类型 + */ +export type XANIMATE_OPIONS = { + /** 元素id */ + ele ?: string, + /** 时间 */ + duration ?: number, + /** 动画类型 */ + timingFunction ?: string, + /** -1表示无限循环播放,0表示不会播放,大于0表示播放该次数后停止播放 */ + loop ?: number, + /** 表示循环播放时,是否左右来回播放,而不是始终从开始到结束这样的状态播放 */ + tyty ?: boolean, + /** 是否让动画顺序挨过按attr添加的属性顺序执行动画,而不是统一一起执行。 */ + isDescPlay ?: boolean, + /** 四位数数组的动画映射值,优先级高于timingFunction */ + bezier ?: number[], + /** 动画结束后的回调函数 */ + complete ?: () => void, + /** 动画开始 */ + start ?: () => void, + /** 动画运行中执行 */ + frame ?: (propress : number) => void +} + +/** + * 日期的对象属性 + */ +export type xDateDayInfoType = { + /** 年 */ + year : number, + /** 月0-11 */ + month : number, + /** 天 */ + day : number, + /** 小时0-23 */ + hours : number, + /** 分钟0-59 */ + minutes : number, + /** 秒0-59 */ + seconds : number, + /** 本年的第几周 */ + weeks : number, + /** 本周星期几 */ + week : number, + /** 本周星期几,中文名称 */ + weekCn : string, + /** 格式化的日期字符串 */ + date : string, + /** 是否渲染显示 */ + isRender ?: boolean +} + +/** + * 日历单个日期的样式对象 + */ +export type xCalendarDateStyle_type = { + /** 是否显示右角标 */ + dot ?: boolean, + /** 右角标背景颜色 */ + dotColor ?: string, + /** 右角标文字颜色 */ + dotLabelColor ?: string, + /** 注意如果dot为true,此内容为空就会显示小圆点。如果有内容优先显示本文本 */ + dotLabel ?: string, + /** 底部文本 */ + label ?: string, + /** 背景颜色 */ + color ?: string, + /** 日期文字颜色 */ + fontColor ?: string, + /** 设置的日期 */ + date : string +} + +export type xCalendarDateStyleStatus = { + date:string, + color:string +} + +export type xCalendarDateStyleBetweenStatus = { + /** 指定了start和end,那么处于这两个日期(含起始)之间的会显示状态点 */ + start?:string, + /** 指定了start和end,那么处于这两个日期(含起始)之间的会显示状态点 */ + end?:string, + /** start和end间条件达成时的状态颜色 */ + color?:string, + /* 区间内排除的指定日期 */ + notDate?:string[], +} +/** + * 状态结构对象 + */ +export type xCalendarDateStyleStatusType = { + /** 启用日期区间设置连续性的状态,它与下面的参数不冲突,如果日期不在区间内,但又在指定的日期内,也会启用状态显示。 */ + between?:xCalendarDateStyleBetweenStatus, + /** 指定单独的日期状态,高于between优先权 */ + date?:xCalendarDateStyleStatus[] +} + +export type xRequestMethond = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS" + +/** + * xReuest请求配置表 + */ +export type xRequestOptions = { + /** + * 是否新增访问前缀域名。如果提供了,在请求时会覆盖函数设置的setHostUrl如果不提供就使用全局设置的域名。 + */ + hostUrl?:string, + /** 定义服务器成功的状态码,如果不为此值会让请求进入失败状态。 */ + successStatusCode ?: number, + /** string|null */ + url ?: string, + /** 如果请求时提供了缓存时间将对接口进行缓存,一定时间内请求直接返回上次结果,不会真正请求 */ + cacheTime?:number, + /** 是否启用缓存 */ + useCache?:boolean, + /** UTSJSONObject|string|null */ + data ?: any, + /** UTSJSONObject|string|null */ + header ?: UTSJSONObject, + method ?: xRequestMethond, + timeout ?: number, + firstIpv4 ?: boolean, + /** 请求前是否显示loading遮罩 */ + showLoadToast ?: boolean, + /** 请求成功后是否提示,否则不提示 */ + showSuccessToast ?: boolean, + /** 出错时,是否显示提示,否则不提示 */ + showErrorToast ?: boolean, + dataType ?: string | null, + responseType ?: string | null, + /** 显示loading是的提示文本。 */ + loadToastText ?:string, + /** + * 成功后的提示文件,注意你不提供它会先偿试读取你返回结果中msg字段,如果没有返回系统的错误字段,如果还没有就是最终的默认错误信息了 + * 如果你提供了,不会展示其它可能的错误信息,以提供的为准。 + */ + successToastText ?:string, + /** + * 失败后的提示文件,注意你不提供它会先偿试读取你返回结果中msg字段,如果没有默认的则提示:操作成功字样 + * 如果你提供了,不会展示其它信息,以提供的为准。 + */ + errorToastText ?:string, +} +/** + * 在监事事件中返回的参数类型 + */ +export type xRequestOptionsCallBack = { + /** + * 是否新增访问前缀域名。如果提供了,在请求时会覆盖函数设置的setHostUrl如果不提供就使用全局设置的域名。 + */ + hostUrl:string, + /** 定义服务器成功的状态码,如果不为此值会让请求进入失败状态。 */ + successStatusCode : number, + /** 是否启用缓存 */ + useCache:boolean, + /** 如果请求时提供了缓存时间将对接口进行缓存,一定时间内请求直接返回上次结果,不会真正请求 */ + cacheTime:number, + /** string|null */ + url : string, + /** UTSJSONObject|string|null */ + data : any, + /** UTSJSONObject|string|null */ + header : UTSJSONObject, + method : xRequestMethond, + timeout : number, + firstIpv4 : boolean, + /** 请求前是否显示loading遮罩 */ + showLoadToast : boolean, + /** 请求成功后是否提示,否则不提示 */ + showSuccessToast : boolean, + /** 出错时,是否显示提示,否则不提示 */ + showErrorToast : boolean, + dataType ?: string | null, + responseType ?: string | null, + /** 显示loading是的提示文本。 */ + loadToastText ?:string, + /** + * 成功后的提示文件,注意你不提供它会先偿试读取你返回结果中msg字段,如果没有返回系统的错误字段,如果还没有就是最终的默认错误信息了 + * 如果你提供了,不会展示其它可能的错误信息,以提供的为准。 + */ + successToastText ?:string, + /** + * 失败后的提示文件,注意你不提供它会先偿试读取你返回结果中msg字段,如果没有默认的则提示:操作成功字样 + * 如果你提供了,不会展示其它信息,以提供的为准。 + */ + errorToastText ?:string, +} +/** + * 请求成功后听结果 + */ +export type xRequestResult = { + data : any | null, + statusCode : number, + header : any, + cookies : string[], +} +/** + * 请求的历史记录类型列表 + */ +export type xRequestHistoryType = { + id : string, + loading : boolean, + loaded : boolean, + /** 状态标志 */ + status : string, + /** 请求总时间ms为单位 */ + time : number, + /** 请求的接口api名称 */ + api : string, + /** 请求成功后的数据集 */ + result : any +}; + +export type xTableColumns = { + title : string, + /** 需要对应源数据中值的key字段名称 */ + key : string, + style ?: UTSJSONObject, + /** 升序,降序,只针对数字或者数字字符串 */ + desc ?: boolean, + /** 单列宽,0px或者auto为自动宽其实就是flex-1值。 + 允许auto,%,prx,px等,多列时,不要全部写一个宽, + 你要让剩下的一个自动。不然会出现大于或者小于容器宽的。 + excel表格宽就懂了,总要有一个是最大的自动宽。 + */ + width ?: string, + /** 单元格合并配置 */ + colspan ?: number, + /** 行合并配置,暂无法实现 */ + rowspan ?: number +} +export type XTABBARCONFIG = { + /** + * 底部导航栏选中项索引值。 + */ + tabbarActiveIndex : number, + /** + * 底部导航的高 + */ + tabaarHeight : number, + /** + * 导航栏数据。 + */ + list : TABBAR_ITEM_INFO[] +} + +export type X_REQUEST_PRIVATE_CALL_FUN_TYPE = { + history : xRequestHistoryType[], + /** + * 设置为false时表示需要登录授权的请求不会被发起 + * 比如第一次请求发现没有登录或者登录失败,设置此值为false后 + * 后面所有再它后面请求的请求会部会被阻止请求。 + */ + authPass : boolean, + hostUrl : string, + header : UTSJSONObject | null, + /** + * 开了调试模式后,你能查看所有的请求日志并统计当前的 + * 请求总数,及每次请求的时间 + * 及请求的状态值。 + */ + dev : boolean, + showLoadToast : boolean, + /** 请求成功后是否提示,否则不提示 */ + showSuccessToast : boolean, + /** 出错时,是否显示提示,否则不提示 */ + showErrorToast : boolean +} + +export type xPageStyle = { + path : string, + backgroundColorContent : string, + navigationBarBackgroundColor : string, + navigationBarTextStyle : string +} +export type XPRIVATECONFIG = { + scrollTop : number, + windowInnerWidth : number, + windowInnerHeight : number, + windowWidth : number, + windowHeight : number, + pageStyle : Map, + pageReady : boolean +} + +export type XCONFIG = { + i18n:Tmui4xI18nTml, + /** 默认颜色主题名称的配置 */ + theme : Map, + /** 全局的主题色 **/ + color : string, + /** 全局默认的文本x-text色 */ + fontColor:string, + /** 全局默认的文本x-text暗黑字体色 */ + fontDarkColor:string, + /** 主题配置,auto,dark,light */ + dark : 'dark' | 'light' | 'auto', + /** 设计基准默认是375,如果修改会影响组件的尺寸,比如你设置为414,那么假设12号最终计算过程是414/375*12=13.248px,如果你小于375则不计算。 */ + designSize: number, + /** 当屏幕宽大于或者等于667时再直接采用以375为基座,按照designSize比例来的原始尺寸,即尺寸不会变大也不会变小了 */ + maximumCalculatedSize:number, + /** 设计单位px,rpx */ + unit : 'px' | 'rpx', + /** 语言 */ + language : string, + /** 所有组件的文字统一缩放的倍数,如果你使用unit为rpx时,fontScale不要去设置,如果unit为px时,可以设置此值来缩放大小。 */ + fontScale: number, + /** x-text默认的字号,如果你使用unit为rpx时,fontScale不要去设置 */ + fontSize: string, + /** 在web时的系统导航文本色 **/ + navigationBarTextStyleDark : string, + /** 注意局部的page.json节点配置会覆盖这里 */ + navigationBarTextStyleLight : string, + /** 在web时的系统导航背景色 **/ + navigationBarBackgroundColorDark : string, + /** 注意局部的page.json节点配置会覆盖这里 */ + navigationBarBackgroundColorLight : string, + /** 在web时的页面暗黑本色 **/ + backgroundColorContentDark : string, + /** 注意局部的page.json节点配置会覆盖这里 */ + backgroundColorContentLight : string, + /** 在web时的底部导航暗黑背景色 **/ + tabarBackgroundColorDark : string, + /** 在web时的底部导航亮系背景色 **/ + tabarBackgroundColorLight : string, + + /** 一般容器sheet的暗黑背景 */ + sheetDarkColor : string, + /** 一般容器边线颜色如果你布局自己写了默认的边线色,但忘记填写组件上的暗黑线时,会取这里的值 */ + sheetDarkBorderColor : string[], + + /** 输入框,表单,常规灰背景待统一的二级暗黑背景 */ + inputDarkColor : string, + /** 输入框默认的亮系背景色方便统一设计稿 */ + inputBgColor: string, + /** 输入框默认的统一提示placeholderStyle方便统一设计稿 */ + placeholderStyle: string, + /** 一般的表单,列表底的暗黑统一边线颜色 */ + borderDarkColor : string, + + + /** 统一的输入框圆角 */ + inputRadius : string, + /** + * 输入框统一的聚集样式 + * 第3表示默认的边颜色(如果为空表示默认边颜色不生效.),第4表示聚焦时的颜色(空表示取全局color,transparent为不生效就是没有聚集样式) + * ['2px','solid','',''] + */ + inputFocusBorder : string[], + /** 统一的按钮圆角 */ + buttonRadius : string, + /** 统一的标签圆角 */ + tagRadius : string, + /** + * 统一列表的圆角 + */ + cellRadius : string, + /** + * 列表为cellCard组件时的边距 + * [x]全部,[x,x]左右,上下,[x,x,x]左上右,[x,x,x,x]左上右下 + */ + cellMargin : string[], + /** 容器的全局圆角 */ + sheetRadius : string[], + /** 容器的全局间隙 */ + sheetMargin : string[], + /** 容器的全局内间隙 */ + sheetPadding : string[], + /** + * 影响: + * 抽屉打开方向为上和下时的圆角 + * 浮动面板 + * 动作菜单 + * */ + drawerRadius : string, + /** 对话框modal的圆角 */ + modalRadius : string, + /** 开关的圆角 */ + switchRadius : string, + /**进度条的圆角 */ + progressRadius : string, + /** 未选中时的颜色 */ + unRadioAndCheckBoxColor : string, + /** 单选按钮组的圆角 */ + radioButtonRadius : string, + /** 弹窗,弹层,对话框等等所有的动画类型。 */ + animationFun : string, + /** 卡片的圆角 */ + cardRound : string, + /**各种弹层右上角的关闭按钮图标名称,可以根据自己设计稿更换**/ + closeIcon : string + +} + +export type xWaterfallDataItemType = { + top : number, + left : number, + width : number, + height : number, + id : string, + col : number, + isRender : boolean, + order : number +} + +/** + * 1:从未执行过动画 + * 2:已完成/结束 + * 3:暂停中 + * 6:循环中被暂停。 + * 4:执行动画中 + * 5:重置并继续 + */ +export type xTweenStatus = 1 | 2 | 3 | 4 | 5 | 6 +export type xTweenEventListenerName = 'enter' | 'complete' | 'start' | 'stop' | 'pause' +export type xTweenCallbackFunType = (x : number) => number +export type xTweenEventCallFunType = { + id : string, + ease : xTweenCallbackFunType | null, + status : xTweenStatus, + duration : number, + progress : number, + oldProgeress : number, + startTime : number, + autoRemove : boolean, + complete : xTweenEventCall, + enter : xTweenEventCall, + start : xTweenEventCall, + pause : xTweenEventCall, + loop : number, + tyty : boolean, + step : number, + //已执行的次数。 + _finishLoop : number, + //是否允许在下次播放时反向(loop>1或者loop -1才生效) + reverse : boolean, + +} +export type xTweenEventCall = (item : xTweenEventCallFunType) => void; +export type xTweenAnimate = { + //结束完成时都被执行 + complete ?: xTweenEventCall, + //运行中执行,会不停的执行回调函数 + enter ?: xTweenEventCall, + //开始时执行 + start ?: xTweenEventCall + //暂停时执行. + pause ?: xTweenEventCall, + /** + * string|number[]|null + * 动画名称或者动画差值number[]长度为4 + * args为string时,应该是ease名称,只能是内置的名称. + */ + ease ?: any, + /** + * 动画持续的时间. + */ + duration : number, + /** + * 执行完动画后,是否自动删除本动画 + * 删除后,如果再点play不再有动画.如果需要执行就需要再次 + * addAnimate来添加执行的动画. + */ + autoRemove ?: boolean, + // 动画循环的次数,默认为1即执行一次,-1表示永久循环执行 + loop ?: number, + //动画被执行后,如果loop=-1或者loop>1将在下一次动画执行时,将从反向开始播放.进度也会反向值.1-0 + tyty ?: boolean, + // [未实现]按步骤帖执行动画,比如在指定duration时间内以这个步骤数完成 + step ?: number, +} + +/** 思维导图数据类型 */ +export type XTREEFLAT_NODES = { + /** 标题,必填写,其它字段全部为非必填 */ + title : string, + /** 唯一标识,如果不填写内部自动填写 */ + id ?: string | number, + /** 文本颜色 */ + fontColor ?: string, + /** 文本背景颜色 */ + bgColor ?: string, + /** 绘制文本时的内边跑 */ + padding ?: number, + /** 绘制项目是连接线上下项目或者左右项目的间距 */ + gutter ?: number, + /** 父级与子级之间的连续长度 */ + parentLineGutter ?: number, + /** 是否展开了子级 */ + opened ?: boolean, + /** 是否禁用展开子级 */ + disabled ?: boolean, + /** 当前项目是否选中 */ + selected ?: boolean, + /** 绘制文本的字号大小 */ + fontSize ?: number, + /** 子级数据,可以为空数组代表无子级不绘制下级 */ + children ?: Array +} + +/** 思维导图组件配置项 */ +export type XTreeFlatOpts = { + /** 不填写默认为透明,即不绘制背景 */ + bgColor ?: string, + nodeBgColor ?: string, + /** 不填写默认为#333 */ + fontColor ?: string, + /** 不填写默认为14,如果子节点设置了以子节点为准 */ + fontSize ?: number, + /** 统一连线颜色,不配置取节点的背景,如果节点背景也没设置取#333 */ + lineColor ?: string, + /** 连线宽 */ + lineWidth ?: number, + /** 绘制文本时的内边跑 */ + padding ?: number, + /** 绘制项目是连接线上下项目或者左右项目的间距 */ + gutter ?: number, + /** 父级与子级之间的连续长度 */ + parentLineGutter ?: number, + /** 点击有子节点的父级时,是否允许关闭和展开,默认关闭 */ + enbleOpenChildren ?: boolean + /** 节点圆角,默认为8 */ + nodeRadius ?: number, + /** 布局方式:horizontal 水平(默认),vertical 垂直 */ + layout ?: 'horizontal' | 'vertical' +} + +export type Tmui4xOptions = { + config:UTSJSONObject|null, + i18nOptions:I18nOptions|null +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/localLanuage/en.json b/uni_modules/tmx-ui/localLanuage/en.json new file mode 100644 index 0000000..108b6d9 --- /dev/null +++ b/uni_modules/tmx-ui/localLanuage/en.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "Cancel", + "confirm": "Confirm", + "success": "Success", + "fail": "Failed", + "warn": "Warning", + "info": "Info", + "clear":"Clear", + "pickerTitle":"Please select", + "calendar":{ + "year": "Year", + "month": "Month", + "day": "Day", + "hour": "Hour", + "minute": "Minute", + "second": "Second", + "titleCurrentMonth":"{0} {1}", + "monthCountSelected":"{count} months", + "selectedStatus":"{count} days selected | No date selected | Selected | End date not selected", + "rangStatus":"Start | End | Today", + "tips":"Max {count} days", + "currentMonthTitle":"This month", + "week":"Mon | Tue | Wed | Thu | Fri | Sat | Sun" + }, + "betweentTime": { + "start": "Start time", + "end": "End time", + "quiakListTitle":"Today | This week | This month | This year | This quarter", + "quiakListTitle2":"Last {count} days", + "quiakListTitle3":"Previous {count} years", + "title":"Please select time", + "splite":"to" + }, + "uploadFile":{ + "title":"Select file", + "uploadStatus":"Pending upload | Uploading... | Upload failed | Upload successful | Exceeds size", + "tips1":"Deletion prohibited during upload", + "tips2":"Deletion prohibited for uploaded files" + }, + "pickerSelected":{ + "placeholder":"Please enter keywords", + "search":"Search", + "selected":"{count} items selected", + "claer":"Clear selection", + "selectedMode":"Currently in single selection mode", + "selectedALl":"Select all" + }, + "tree":{ + "changeTitle":"Modify content", + "addTitle":"Add subordinate", + "inputTitle":"Title", + "inputId":"Identifier ID", + "inputTips1":"Do not repeat, auto-generate when empty" + }, + "input":{ + "placeholder":"Please select or fill in" + }, + "inputTag":{ + "placeholder": "Please enter and press Enter", + "tips": "Cannot be empty", + "tips2": "Exceeds maximum limit: {count}", + "btnText": "Add Tag" + }, + "keyboard":{ + "placeholder":"Safe keyboard for secure input", + "space":"Space", + "confirm":"Confirm" + }, + "pickerTime":{ + "hour":"Hour", + "minute":"Minute", + "second":"Second" + }, + "cascader":{ + "placeholder":"Please select", + "currentPlaceholder":"Select current" + }, + "pickerDate":{ + "placeholder":"Please select time", + "year":"Year", + "month":"Month", + "day":"Day", + "hour":"Hour", + "minute":"Minute", + "second":"Second" + }, + "uploadMedia":{ + "tips1":"Dragging sort not allowed during upload", + "videoPreview":"Video preview", + "close":"Close", + "systemError":"System error", + "limitMaxCount":"Exceeded max upload count", + "uploadStatus":"Pending upload | Uploading... | Upload failed | Upload successful | Exceeds size" + }, + "checkbox":{ + "tips":"Exceeds maximum selection" + }, + "weekbar":{ + "week":"Mon | Tue | Wed | Thu | Fri | Sat | Sun" + }, + "pagination":{ + "prev": "Previous", + "next": "Next" + }, + "search":{ + "placeholder":"Enter keywords", + "cancel":"Cancel" + }, + "xmore":{ + "off": "Expand more", + "on": "Collapse more" + }, + "empty":{ + "moreLabel": "No more data", + "errorLabel": "Error~", + "btnLabel": "Retry", + "title":"No data" + }, + "xloading":{ + "label":"Loading..." + }, + "actionModal":{ + "title":"Reminder", + "btnText":"Confirm" + }, + "actionMenu":{ + "title":"Please select", + "btnText":"Confirm" + }, + "pullRefresh":{ + "status_1":"Refreshing", + "status_2":"Pull down more", + "status_3":"Release to refresh", + "status_4":"Refresh done", + "status_5":"Refresh failed" + }, + "virtualList":{ + "status_0":"Pull down more", + "status_1":"Release to refresh", + "status_2":"Refreshing", + "status_3":"Cancel refresh", + "status_4":"Refresh timeout, retry", + "status_5":"Refresh done" + }, + "imageResize":{ + "ok":"Done", + "cancel":"Cancel", + "reset":"Reset" + }, + "colorView":{ + "rgb":"RGB", + "hub":"Spectrum", + "grid":"Palette", + "alpha":"Alpha", + "hex":"HEX", + "r":"Red", + "g":"Green", + "b":"Blue" + }, + "modal": { + "title": "Title" + }, + "mention": { + "placeholder": "Enter content, @select friend, press confirm" + }, + "slideVerify": { + "tipsText": "Drag to position", + "tipsTextSuccess": "Verified", + "tipsTextFail": "Verification failed" + }, + "xRequest":{ + "error":"Server error:", + "success":"Success", + "hostFailEmpty":"Domain empty", + "loading":"Loading" + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/localLanuage/ja.json b/uni_modules/tmx-ui/localLanuage/ja.json new file mode 100644 index 0000000..6b6195b --- /dev/null +++ b/uni_modules/tmx-ui/localLanuage/ja.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "キャンセル", + "confirm": "確認", + "success": "成功", + "fail": "失敗", + "warn": "警告", + "info": "情報", + "clear":"クリア", + "pickerTitle":"選択してください", + "calendar":{ + "year": "年", + "month": "月", + "day": "日", + "hour": "時", + "minute": "分", + "second": "秒", + "titleCurrentMonth":"{0}年{1}月", + "monthCountSelected":"{count}ヶ月", + "selectedStatus":"選択済み{count}日 | 日付未選択 | 選択済み | 終了日未選択", + "rangStatus":"開始 | 終了 | 本日", + "tips":"最大選択{count}日", + "currentMonthTitle":"今月", + "week":"月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日 | 日曜日" + }, + "betweentTime": { + "start": "開始時間", + "end": "終了時間", + "quiakListTitle":"本日 | 今週 | 今月 | 今年 | 今四半期", + "quiakListTitle2":"最近{count}日", + "quiakListTitle3":"前{count}年", + "title":"時間を選択してください", + "splite":"から" + }, + "uploadFile":{ + "title":"ファイルを選択", + "uploadStatus":"アップロード待機 | アップロード中... | アップロード失敗 | アップロード成功 | サイズ超過", + "tips1":"アップロード中は削除禁止", + "tips2":"アップロード済みファイルは削除禁止" + }, + "pickerSelected":{ + "placeholder":"キーワードを入力してください", + "search":"検索", + "selected":"選択済み{count}項目", + "claer":"選択をクリア", + "selectedMode":"現在は単一選択モード", + "selectedALl":"すべて選択" + }, + "tree":{ + "changeTitle":"内容を変更", + "addTitle":"下位を追加", + "inputTitle":"タイトル", + "inputId":"識別ID", + "inputTips1":"重複しないでください、空の場合は自動生成" + }, + "input":{ + "placeholder":"選択または入力してください" + }, + "inputTag":{ + "placeholder":"入力してEnterを押してください", + "tips":"空にできません", + "tips2":"制限最大数を超過:{count}", + "btnText":"タグを追加" + }, + "keyboard":{ + "placeholder":"安全キーボードで安心入力", + "space":"スペース", + "confirm":"確認" + }, + "pickerTime":{ + "hour":"時間", + "minute":"分", + "second":"秒数" + }, + "cascader":{ + "placeholder":"選択してください", + "currentPlaceholder":"本級を選択" + }, + "pickerDate":{ + "placeholder":"時間を選択してください", + "year":"年", + "month":"月", + "day":"日", + "hour":"時", + "minute":"分", + "second":"秒" + }, + "uploadMedia":{ + "tips1":"アップロード中はドラッグソート禁止", + "videoPreview":"ビデオプレビュー", + "close":"閉じる", + "systemError":"システム異常", + "limitMaxCount":"最大アップロード数を超過", + "uploadStatus":"アップロード待機 | アップロード中... | アップロード失敗 | アップロード成功 | サイズ超過" + }, + "checkbox":{ + "tips":"最大選択数を超過" + }, + "weekbar":{ + "week":"月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日 | 日曜日" + }, + "pagination":{ + "prev": "前のページ", + "next": "次のページ" + }, + "search":{ + "placeholder":"キーワードを入力", + "cancel":"キャンセル" + }, + "xmore":{ + "off": "もっと展開", + "on": "もっと収納" + }, + "empty":{ + "moreLabel": "データなし", + "errorLabel": "エラー", + "btnLabel": "リトライ", + "title":"データなし" + }, + "xloading":{ + "label":"ロード中..." + }, + "actionModal":{ + "title":"リマインダー", + "btnText":"確認" + }, + "actionMenu":{ + "title":"選択してください", + "btnText":"確認" + }, + "pullRefresh":{ + "status_1":"リフレッシュ中", + "status_2":"さらに下に引っ張る", + "status_3":"離してリフレッシュ", + "status_4":"リフレッシュ完了", + "status_5":"リフレッシュ失敗" + }, + "virtualList":{ + "status_0":"さらに下に引っ張る", + "status_1":"離してリフレッシュ", + "status_2":"リフレッシュ中", + "status_3":"リフレッシュキャンセル", + "status_4":"リフレッシュタイムアウト、リトライ", + "status_5":"リフレッシュ完了" + }, + "imageResize":{ + "ok":"完了", + "cancel":"キャンセル", + "reset":"リセット" + }, + "colorView":{ + "rgb":"RGB", + "hub":"スペクトル", + "grid":"カラーパレット", + "alpha":"透明度", + "hex":"HEX", + "r":"赤", + "g":"緑", + "b":"青" + }, + "modal": { + "title": "タイトル" + }, + "mention": { + "placeholder": "内容を入力、@で友達選択、確認押す" + }, + "slideVerify": { + "tipsText": "指定位置にドラッグ", + "tipsTextSuccess": "検証成功", + "tipsTextFail": "検証失敗" + }, + "xRequest":{ + "error":"サーバーエラー:", + "success":"操作成功", + "hostFailEmpty":"リクエストドメイン未入力", + "loading":"ロード中" + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/localLanuage/ko.json b/uni_modules/tmx-ui/localLanuage/ko.json new file mode 100644 index 0000000..5689303 --- /dev/null +++ b/uni_modules/tmx-ui/localLanuage/ko.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "취소", + "confirm": "확인", + "success": "성공", + "fail": "실패", + "warn": "경고", + "info": "정보", + "clear":"지우기", + "pickerTitle":"선택하세요", + "calendar":{ + "year": "년", + "month": "월", + "day": "일", + "hour": "시", + "minute": "분", + "second": "초", + "titleCurrentMonth":"{0}년{1}월", + "monthCountSelected":"{count}개월", + "selectedStatus":"선택됨{count}일 | 날짜 미선택 | 선택됨 | 종료일 미선택", + "rangStatus":"시작 | 종료 | 오늘", + "tips":"최대선택{count}일", + "currentMonthTitle":"이번 달", + "week":"월요일 | 화요일 | 수요일 | 목요일 | 금요일 | 토요일 | 일요일" + }, + "betweentTime": { + "start": "시작 시간", + "end": "종료 시간", + "quiakListTitle":"오늘 | 이번 주 | 이번 달 | 올해 | 이번 분기", + "quiakListTitle2":"최근 {count}일", + "quiakListTitle3":"이전 {count}년", + "title":"시간을 선택하세요", + "splite":"부터" + }, + "uploadFile":{ + "title":"파일 선택", + "uploadStatus":"업로드 대기 | 업로드 중... | 업로드 실패 | 업로드 성공 | 크기 초과", + "tips1":"업로드 중 삭제 금지", + "tips2":"업로드된 파일 삭제 금지" + }, + "pickerSelected":{ + "placeholder":"키워드를 입력하세요", + "search":"검색", + "selected":"선택됨{count}개", + "claer":"선택 지우기", + "selectedMode":"현재 단일 선택 모드", + "selectedALl":"모두 선택" + }, + "tree":{ + "changeTitle":"내용 수정", + "addTitle":"하위 추가", + "inputTitle":"제목", + "inputId":"식별 ID", + "inputTips1":"중복하지 마세요, 비어있으면 자동 생성" + }, + "input":{ + "placeholder":"선택하거나 입력하세요" + }, + "inputTag":{ + "placeholder":"입력 후 엔터를 누르세요", + "tips":"비워둘 수 없습니다", + "tips2":"최대 수 초과:{count}", + "btnText":"태그 추가" + }, + "keyboard":{ + "placeholder":"안전한 키보드로 안심 입력", + "space":"스페이스", + "confirm":"확인" + }, + "pickerTime":{ + "hour":"시간", + "minute":"분", + "second":"초수" + }, + "cascader":{ + "placeholder":"선택하세요", + "currentPlaceholder":"본급 선택" + }, + "pickerDate":{ + "placeholder":"시간을 선택하세요", + "year":"년", + "month":"월", + "day":"일", + "hour":"시", + "minute":"분", + "second":"초" + }, + "uploadMedia":{ + "tips1":"업로드 중 드래그 정렬 금지", + "videoPreview":"비디오 미리보기", + "close":"닫기", + "systemError":"시스템 이상", + "limitMaxCount":"최대 업로드 수 초과", + "uploadStatus":"업로드 대기 | 업로드 중... | 업로드 실패 | 업로드 성공 | 크기 초과" + }, + "checkbox":{ + "tips":"최대 선택 수 초과" + }, + "weekbar":{ + "week":"월요일 | 화요일 | 수요일 | 목요일 | 금요일 | 토요일 | 일요일" + }, + "pagination":{ + "prev": "이전 페이지", + "next": "다음 페이지" + }, + "search":{ + "placeholder":"키워드 입력", + "cancel":"취소" + }, + "xmore":{ + "off": "더 펼치기", + "on": "더 접기" + }, + "empty":{ + "moreLabel": "데이터 없음", + "errorLabel": "오류", + "btnLabel": "재시도", + "title":"데이터 없음" + }, + "xloading":{ + "label":"로드 중..." + }, + "actionModal":{ + "title":"리마인더", + "btnText":"확인" + }, + "actionMenu":{ + "title":"선택하세요", + "btnText":"확인" + }, + "pullRefresh":{ + "status_1":"새로고침 중", + "status_2":"더 아래로 끌기", + "status_3":"놓아서 새로고침", + "status_4":"새로고침 완료", + "status_5":"새로고침 실패" + }, + "virtualList":{ + "status_0":"더 아래로 끌기", + "status_1":"놓아서 새로고침", + "status_2":"새로고침 중", + "status_3":"새로고침 취소", + "status_4":"새로고침 타임아웃, 재시도", + "status_5":"새로고침 완료" + }, + "imageResize":{ + "ok":"완료", + "cancel":"취소", + "reset":"리셋" + }, + "colorView":{ + "rgb":"RGB", + "hub":"스펙트럼", + "grid":"팔레트", + "alpha":"투명도", + "hex":"HEX", + "r":"빨강", + "g":"녹색", + "b":"파랑" + }, + "modal": { + "title": "제목" + }, + "mention": { + "placeholder": "내용 입력, @로 친구 선택, 확인 누르기" + }, + "slideVerify": { + "tipsText": "지정 위치로 드래그", + "tipsTextSuccess": "검증 성공", + "tipsTextFail": "검증 실패" + }, + "xRequest":{ + "error":"서버 오류:", + "success":"작업 성공", + "hostFailEmpty":"요청 도메인 미입력", + "loading":"로드 중" + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/localLanuage/zh-Hans.json b/uni_modules/tmx-ui/localLanuage/zh-Hans.json new file mode 100644 index 0000000..82d5e43 --- /dev/null +++ b/uni_modules/tmx-ui/localLanuage/zh-Hans.json @@ -0,0 +1,181 @@ +{ + "tmui4x": { + "cancel": "取消", + "confirm": "确认", + "success": "成功", + "fail": "失败", + "warn": "警告", + "info": "提醒", + "clear":"清空", + "pickerTitle":"请选择", + "calendar":{ + "year": "年", + "month": "月", + "day": "日", + "hour": "时", + "minute": "分", + "second": "秒", + "titleCurrentMonth":"{0}年{1}月", + "monthCountSelected":"{count}月", + "selectedStatus":"已选择{count}日 | 未选择日期 | 已选择 | 未选择结束日期", + "rangStatus":"开始 | 结束 | 本日", + "tips":"最大选择{count}日", + "currentMonthTitle":"本月", + "week":"周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日" + }, + "betweentTime": { + "start": "开始时间", + "end": "结束时间", + "quiakListTitle":"本日 | 本周 | 本月 | 本年 | 本季度", + "quiakListTitle2":"最近{count}天", + "quiakListTitle3":"前{count}年", + "title":"请选择时间", + "splite":"至" + }, + "uploadFile":{ + "title":"选择文件", + "uploadStatus":"待上传 | 上传中... | 上传失败 | 上传成功 | 超过大小", + "tips1":"上传中禁止删除", + "tips2":"已上传文件禁止删除" + }, + "pickerSelected":{ + "placeholder":"请输入关键词", + "search":"搜索", + "selected":"已选择{count}项", + "claer":"清空选择", + "selectedMode":"当前为单选模式", + "selectedALl":"选择所有" + }, + "tree":{ + "changeTitle":"修改内容", + "addTitle":"添加下级", + "inputTitle":"标题", + "inputId":"标识ID", + "inputTips1":"不要重复,空时自动生成" + }, + "input":{ + "placeholder":"请选择或者填写" + }, + + "inputTag":{ + "placeholder":"请输入并回车", + "tips":"不能为空", + "tips2":"超过限制最大数:{count}", + "btnText":"添加标签" + }, + "keyboard":{ + "placeholder":"安全键盘放心输入", + "space":"空格", + "confirm":"确认" + }, + "pickerTime":{ + "hour":"小时", + "minute":"分钟", + "second":"秒数" + }, + "cascader":{ + "placeholder":"请选择", + "currentPlaceholder":"选择本级" + }, + "pickerDate":{ + "placeholder":"请选择时间", + "year":"年", + "month":"月", + "day":"日", + "hour":"时", + "minute":"分", + "second":"秒" + }, + + "uploadMedia":{ + "tips1":"上传中不允许拖动排序", + "videoPreview":"视频预览", + "close":"关闭", + "systemError":"系统异常", + "limitMaxCount":"已超最大上传数量", + "uploadStatus":"待上传 | 上传中... | 上传失败 | 上传成功 | 超过大小" + }, + "checkbox":{ + "tips":"超过最大选择" + }, + "weekbar":{ + "week": "周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日" + }, + "pagination":{ + "prev": "上一页", + "next": "下一页" + }, + "search":{ + "placeholder":"请输入关键词", + "cancel":"取消" + }, + "xmore":{ + "off": "展开更多", + "on": "收起更多" + }, + "empty":{ + "moreLabel": "没有更多数据啦", + "errorLabel": "出错啦~", + "btnLabel": "点击重试", + "title":"当前没有数据" + }, + "xloading":{ + "label":"加载中..." + }, + "actionModal":{ + "title":"提醒", + "btnText":"确认" + }, + "actionMenu":{ + "title":"请选择", + "btnText":"确认" + }, + "pullRefresh":{ + "status_1":"正在刷新", + "status_2":"继续下拉", + "status_3":"松开刷新", + "status_4":"刷新完成", + "status_5":"刷新失败" + }, + "virtualList":{ + "status_0":"继续下拉", + "status_1":"松开刷新", + "status_2":"刷新中", + "status_3":"取消刷新", + "status_4":"刷新超时,点击重试", + "status_5":"刷新完成" + }, + "imageResize":{ + "ok":"完成", + "cancel":"取消", + "reset":"还原" + }, + "colorView":{ + "rgb":"RGB", + "hub":"光谱", + "grid":"色卡", + "alpha":"透明度", + "hex":"HEX", + "r":"红色", + "g":"绿色", + "b":"蓝色" + }, + "modal": { + "title": "标题" + }, + "mention": { + "placeholder": "请输入内容,@选择朋友,按确认完成" + }, + "slideVerify": { + "tipsText": "请拖动到指定位置", + "tipsTextSuccess": "验证成功", + "tipsTextFail": "验证失败" + }, + "xRequest":{ + "error":"服务器错误:", + "success":"操作成功", + "hostFailEmpty":"未填请求域名", + "loading":"加载中" + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/localLanuage/zh-Hant.json b/uni_modules/tmx-ui/localLanuage/zh-Hant.json new file mode 100644 index 0000000..9831a40 --- /dev/null +++ b/uni_modules/tmx-ui/localLanuage/zh-Hant.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "取消", + "confirm": "確認", + "success": "成功", + "fail": "失敗", + "warn": "警告", + "info": "提醒", + "clear":"清空", + "pickerTitle":"請選擇", + "calendar":{ + "year": "年", + "month": "月", + "day": "日", + "hour": "時", + "minute": "分", + "second": "秒", + "titleCurrentMonth":"{0}年{1}月", + "monthCountSelected":"{count}月", + "selectedStatus":"已選擇{count}日 | 未選擇日期 | 已選擇 | 未選擇結束日期", + "rangStatus":"開始 | 結束 | 本日", + "tips":"最大選擇{count}日", + "currentMonthTitle":"本月", + "week":"週一 | 週二 | 週三 | 週四 | 週五 | 週六 | 週日" + }, + "betweentTime": { + "start": "開始時間", + "end": "結束時間", + "quiakListTitle":"本日 | 本週 | 本月 | 本年 | 本季度", + "quiakListTitle2":"最近{count}天", + "quiakListTitle3":"前{count}年", + "title":"請選擇時間", + "splite":"至" + }, + "uploadFile":{ + "title":"選擇檔案", + "uploadStatus":"待上傳 | 上傳中... | 上傳失敗 | 上傳成功 | 超過大小", + "tips1":"上傳中禁止刪除", + "tips2":"已上傳檔案禁止刪除" + }, + "pickerSelected":{ + "placeholder":"請輸入關鍵詞", + "search":"搜尋", + "selected":"已選擇{count}項", + "claer":"清空選擇", + "selectedMode":"當前為單選模式", + "selectedALl":"選擇所有" + }, + "tree":{ + "changeTitle":"修改內容", + "addTitle":"添加下級", + "inputTitle":"標題", + "inputId":"標識ID", + "inputTips1":"不要重複,空時自動生成" + }, + "input":{ + "placeholder":"請選擇或者填寫" + }, + "inputTag":{ + "placeholder":"請輸入並回車", + "tips":"不能為空", + "tips2":"超過限制最大數:{count}", + "btnText":"添加標籤" + }, + "keyboard":{ + "placeholder":"安全鍵盤放心輸入", + "space":"空格", + "confirm":"確認" + }, + "pickerTime":{ + "hour":"小時", + "minute":"分鐘", + "second":"秒數" + }, + "cascader":{ + "placeholder":"請選擇", + "currentPlaceholder":"選擇本級" + }, + "pickerDate":{ + "placeholder":"請選擇時間", + "year":"年", + "month":"月", + "day":"日", + "hour":"時", + "minute":"分", + "second":"秒" + }, + "uploadMedia":{ + "tips1":"上傳中不允许拖動排序", + "videoPreview":"視頻預覽", + "close":"關閉", + "systemError":"系統異常", + "limitMaxCount":"已超最大上傳數量", + "uploadStatus":"待上傳 | 上傳中... | 上傳失敗 | 上傳成功 | 超過大小" + }, + "checkbox":{ + "tips":"超過最大選擇" + }, + "weekbar":{ + "week":"週一 | 週二 | 週三 | 週四 | 週五 | 週六 | 週日" + }, + "pagination":{ + "prev": "上一頁", + "next": "下一頁" + }, + "search":{ + "placeholder":"請輸入關鍵詞", + "cancel":"取消" + }, + "xmore":{ + "off": "展開更多", + "on": "收起更多" + }, + "empty":{ + "moreLabel": "沒有更多數據啦", + "errorLabel": "出錯啦~", + "btnLabel": "點擊重試", + "title":"當前沒有數據" + }, + "xloading":{ + "label":"加載中..." + }, + "actionModal":{ + "title":"提醒", + "btnText":"確認" + }, + "actionMenu":{ + "title":"請選擇", + "btnText":"確認" + }, + "pullRefresh":{ + "status_1":"正在刷新", + "status_2":"繼續下拉", + "status_3":"鬆開刷新", + "status_4":"刷新完成", + "status_5":"刷新失敗" + }, + "virtualList":{ + "status_0":"繼續下拉", + "status_1":"鬆開刷新", + "status_2":"刷新中", + "status_3":"取消刷新", + "status_4":"刷新超時,點擊重試", + "status_5":"刷新完成" + }, + "imageResize":{ + "ok":"完成", + "cancel":"取消", + "reset":"還原" + }, + "colorView":{ + "rgb":"RGB", + "hub":"光譜", + "grid":"色卡", + "alpha":"透明度", + "hex":"HEX", + "r": "紅色", + "g": "綠色", + "b": "藍色" + }, + "modal": { + "title": "標題" + }, + "mention": { + "placeholder": "請輸入內容,@選擇朋友,按確認完成" + }, + "slideVerify": { + "tipsText": "請拖動到指定位置", + "tipsTextSuccess": "驗證成功", + "tipsTextFail": "驗證失敗" + }, + "xRequest":{ + "error":"服務器錯誤:", + "success":"操作成功", + "hostFailEmpty":"未填請求域名", + "loading":"加載中" + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/package.json b/uni_modules/tmx-ui/package.json new file mode 100644 index 0000000..8728a47 --- /dev/null +++ b/uni_modules/tmx-ui/package.json @@ -0,0 +1,115 @@ +{ + "id": "tmx-ui", + "displayName": "TM-UI-4.0原生应用开发解决方案套装【官方赛事一等奖排名第一】", + "version": "1.1.17", + "description": "高质量uniappx UI组件库,原生Uts插件,原生组件基类,让开发原生级应用流畅性高度保持一致", + "keywords": [ + "ios,安卓,鸿蒙,小程序,web,tmui4.0" +], + "repository": "", + "engines": { + "HBuilderX": "^4.55", + "uni-app": "", + "uni-app-x": "^4.76" + }, + "dcloudext": { + "type": "component-uts", + "sale": { + "regular": { + "price": "599.00" + }, + "sourcecode": { + "price": "599.01" + } + }, + "contact": { + "qq": "369986563" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "√", + "i18n": "√", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": { + "extVersion": "1.1.17", + "minVersion": "103" + }, + "chrome": { + "extVersion": "1.1.17", + "minVersion": "103" + } + }, + "app": { + "android": { + "extVersion": "1.1.17", + "minVersion": "21" + }, + "ios": { + "extVersion": "1.1.17", + "minVersion": "12" + }, + "harmony": { + "extVersion": "1.1.17", + "minVersion": "12" + } + }, + "mp": { + "weixin": { + "extVersion": "1.1.17", + "minVersion": "3.0.0" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/readme.md b/uni_modules/tmx-ui/readme.md new file mode 100644 index 0000000..bcdbdbf --- /dev/null +++ b/uni_modules/tmx-ui/readme.md @@ -0,0 +1,104 @@ +![tmui4.0|xui](https://cdn.tmui.design/xui/tmui4.0banner1.jpg) + +---- + +# TMUI4.0x + +---- + +## 设计 + +一款好的UI/UX,不止是功能,它还应该要有设计感,层次感。注重细微及用户的反馈体验。同时要保留它的高度可扩展性及性能。 +功能的堆叠不是我所追求,也不是我的目标。我追求的是细致,可扩展,精美。不管是IOS,安卓,WEB/H5三端我都朝着这个方向。 +让UNIAPPX 开发的商业应用更像商业应用。为让市场的组件审美提高一个档次而做出应有的贡献。 +**官方赛事一等奖第一名** + +---- + +**丢掉市场劣质应用风与我一道让你的审美更上一层楼** + +- 可全局配置风格 +- 可全局适应暗黑 +- 精致化设计 +- 三端适配 +- 层次分明,颜色统一且协调 + +## 行业交流 + +**你不仅仅是付费买应用开发解决方案,进来的都是各行大佬(技术牛人或老板),交流,经验多,互通有余,畅聊行业,素质高。** + +**[tmui4.0文档](https://xui.tmui.design/)** + +## 微信端 +![2](https://store.tmui.design/api/weChatQr) +## 电脑端 +[电脑端](https://x-ui.design) +## 鸿蒙Next +进入链接后选择Harmony开头的下载即可,请务必使用鸿蒙真机并且是Next鸿蒙系统 +[Harmony](https://gitee.com/LYTB/tmui4.0/releases) +## 安卓端 +进入链接后选择android开头的下载即可,请务必使用安卓5.0(含)以上系统 +[Android](https://gitee.com/LYTB/tmui4.0/releases) +## Ios端 +不提供,需要自行使用demo源码,通过自己的ios证书构建安装包。 + +---- + +**目前VIP源码用户含以下原生插件** + +| Harmony | H5 | PC | android | IOS | 小程序 | UTS | UNIAPP-X SDK | version | +| --- | --- | ---| --- | --- | --- | --- | --- | --- | +| ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️| ☑️ | 4.75+ | 1.1.16+ | + +| 名称 | 介绍 | Harmony | H5/WEB | Android | Ios | UNIAPP-X | UNIAPP | 小程序 | 链接 | 文档 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| 中文转拼音 | x-chinesetopinyin-s | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | 见代码仓库 | 见链接 | +| 文本转语音播报 | x-texttovoice-s | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | x | 见代码仓库 | 见链接 | +| Ocr识别 | 离线识别,支持拍照相册识别x-ocr-s | ☑ | ☑ | ☑ | ☑ | ☑ | - | x | [查看](https://ext.dcloud.net.cn/plugin?id=17557) | 见链接 | +| 多码识别(api版本) | 可同时识别多个码x-mlkit-scannig-s | - | ☑ | ☑ | ☑ | ☑ | - | ☑ | [查看](https://ext.dcloud.net.cn/plugin?id=16468) | 见链接 | +| 多码识别(嵌入版本) | x-mlkit-scannig-u | - | ☑ | ☑ | ☑ | ☑ | - | ☑ | [查看](https://ext.dcloud.net.cn/plugin?id=16468) | 见链接 | +| 文件选择器 | 可以任意选择本地文件单选及多选x-file-s | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | [查看](https://ext.dcloud.net.cn/plugin?id=17624) | 见链接 | +| 分享 | 可以分享任意文件到其它应用x-share-s | ☑ | x | ☑ | ☑ | ☑ | ☑ | x | [查看](https://ext.dcloud.net.cn/plugin?id=18494) | 见链接 | +| 手机震动 | 让手机产生震动x-vibrate-s | ☑ | x | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | 见仓库 | +| 全屏加载 | 平替官方uni.showLoading | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | x | [查看](https://ext.dcloud.net.cn/plugin?id=19697) | 见链接 | +| 消息提醒 | 平替官方uni.showToast | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | [查看](https://ext.dcloud.net.cn/plugin?id=19698) | 见链接 | +| 对话框 | 平替官方uni.showModal | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | [查看](https://ext.dcloud.net.cn/plugin?id=19699) | 见链接 | +| 拨打电话 | x-call-phone | ☑ | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | 见仓库 | +| 打开外链 | x-openweb | ☑ | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | 见仓库 | +| 启动图界面 | x-runstart-logo | ☑ | ☑ | ☑ | ☑ | ☑ | - | x | [查看](https://ext.dcloud.net.cn/plugin?id=19700) | 见链接 | +| 网络状态变化 | x-network-change | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | 见代码仓库 | 见链接 | +| 数据加密 | x-crypto-s | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | 见代码仓库 | 见链接 | +| MQTT | x-mqtt-s | ☑ | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | 见链接 | +| app页面变灰 | x-window-grey | - | ☑ | ☑ | ☑ | ☑ | ☑ | ☑ | 见代码仓库 | 见链接 | +| 模糊视图 | xd-blur | ☑ | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | - | +| 相机 | x-camrea-u | - | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | - | +| base64转图片文件 | x-base642file-s | ☑ | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | - | +| 截图(节点或者窗口) | x-screenshot-s | ☑ | x | ☑ | ☑ | ☑ | - | x | 见代码仓库 | - | +| svg | x-screenshot-s | ☑ | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | - | +| zip解压缩 | x-zip-s | ☑ | x | ☑ | ☑ | ☑ | - | x | 见代码仓库 | - | +| 翻译 | x-translate-s | - | x | ☑ | ☑ | ☑ | - | x | 见代码仓库 | - | +| 剪切板 | x-clipboard-s | - | ☑ | ☑ | ☑ | ☑ | - | ☑ | 见代码仓库 | - | +| SSE客户端 | x-sse-s | ☑ | ☑ | ☑ | ☑ | ☑ | - | x | 见代码仓库 | - | +| 数据库 | x-sqlite-s | - | ☑ | ☑ | ☑ | ☑ | - | x | 见代码仓库 | - | +| 人脸检测 | x-facedetection | ☑ | x | ☑ | - | ☑ | x | x | 见代码仓库 | - | + +---- + +### 义务和免责声明 + +付费用户享受组件的免费使用,我有义务修复bug和提供的稳定版本 + +但我没义务免费为你24小时服务,我在有限的时间内解答你的所有问题,和开发帮助(力所能及范围内)。不接受即问即答模式,我不是专职。 + + +### bug提交 + +请进入内部VIP专属仓库提交需求和bug + +### 安装和使用 + +支付费用后请通过市场上方的群聊联系我。 + + +![1](https://cdn.tmui.design//xui/shoots/fmpg.jpg) +![7](https://cdn.tmui.design//xui/shoots/7.gif) \ No newline at end of file diff --git a/uni_modules/tmx-ui/scss/remixicon.css b/uni_modules/tmx-ui/scss/remixicon.css new file mode 100644 index 0000000..46b2550 --- /dev/null +++ b/uni_modules/tmx-ui/scss/remixicon.css @@ -0,0 +1,666 @@ +@font-face { + font-family: "remixicon"; + src: url("data:application/font-woff;base64,d09GRgABAAAAAN5YAAsAAAAB3twAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADsAAABUIIslek9TLzIAAAFEAAAAQwAAAFZCwlnmY21hcAAAAYgAABb7AAAvEKYEuDZnbHlmAAAYhAAArZQAAXAo1EY5v2hlYWQAAMYYAAAAMAAAADYsoe/QaGhlYQAAxkgAAAAfAAAAJAjHBrxobXR4AADGaAAAAB8AAAo0b5gAAGxvY2EAAMaIAAAFHAAABRx6vdUibWF4cAAAy6QAAAAfAAAAIAOjANJuYW1lAADLxAAAAagAAAMqHA3lNnBvc3QAAM1sAAAQ6wAAK0LWJjZpeJxjYGRgYOBiMGCwY2BycfMJYeDLSSzJY5BiYGGAAJA8MpsxJzM9kYEDxgPKsYBpDiBmg4gCACY7BUgAeJxjYGR5wDiBgZWBgeknswcDA8MKCM3kwGDFaAqkGViZGbCCgDTXFAaHV4xfnzD/+e/DkMP8h2ELUJgRJAcAJLYOOQB4nO3Ye7jOZdYH8LXW82whyaEo58gxaVANiQ4ORRJN02AQJbEVUTkVoZNyCINJiWim0blpmkaYkiY1JarBhE4TU/zOh2dPjZp6v/f+ulzzx/z7Xu/7x7ivT+uZvWf/nt9z/9a97nU/IlImIgVoD0WRWkVRvJKa3+OnWvnzglSv/Hmx5ociNsZEqsoYz7zjvNpeXa+xd5rX0mvjtfc6eed653s9vAu9Xl4/b4A32BvmjfRGe2O9Cd5k71ZvmjfDm+Xd693vLfCWeiu8R7zV3jpvi7fD+8Db7e33/u5966tfzT/Nb+G39Dv4nf2u/iX+IH+UP9G/xZ/qT/dn+vf49/sL/SX+L/2V/hr/Sf9Ff6P/jv+x/4UfBRZUD2oGdYJ6QYOgSdAu6BB0Cs4P+gRXBoODocGIYHQwJigPZgRzg4XBiuDRYG3wePBU8Gzwh2BT8EawO0iDivDEsEXYOewaXhoODUeF5eHN4fxwYbg83BS+G+4Md4d/DfeHB0I/jMPvorLo+Kh21DhqFZ0ZnRNdHg2KhkRjovHRxGhSNDN6PHoyejHaFG2JtkXbow+jXdHH0afRl1ESfRdbXD1uEDeLW8at4w5xt7hH3CceEF8Zj4rHxZPj6fGqeHP8Vvx+vCc+HAdJWVItaZm0Tc5Muibdku7JBclFSe+kXzIwGZnMSBYlK5I1yXvJ7mRf8nlyMImSr9NCWjWtkZ6SNkqbpa3SHunQdFg6Pp2Tzkvnpw+ma9Jfp0+nz6eb09fSt9K96efpN9lxWf2sYXZW1i3rlQ3IBmajstHZ5GxaNiubmy3NVmfrsheyl7KXsw3ZxmxztiXbmu3IdmefZAezr7LDed28ft40b5G3zjvnF+Q986H5Dfn4fGJ+Sz4/X5Qvzh/O1+ZP51vzw3le0lLdUpNSu9JZpR6l3qUxpRmlpaWHShtKe0r7Sn5F7YomFe0qelX0ryivOPjDDyKeelW8GsizBl4z5Flr7wyvI/KsW2We9fT6ev2RZ0ORZ9d6N3g3epOQZ1OQZzO9uyrzbIm33Ft5NM+2I892eR95B70jvvhVj+VZR7+L38cf4I/0J/iT/SnIs9v92f59yLPF/jLk2Sp/vf9b/xXk2X7/b36IPKsWnBDUDk4OTg0aB20r86xr0Ptong2vzLNxwfTgzmBBsCRYFTyGPHsCefYi8mxrsCuIglJYM2wedgy7IM+GVObZxMo8WxZuRJ7tqMyzfeEX4ZdhFB6JClHVqFbUCHnWNjo76hcNjK5CnpVX5tkd0bpoPfJsQ/Rq9Gb052jnsTw7FP0z1rhaXD9u+m951jO+PB4Uj4zHIs9ui1ciz7bEO+PdR/OsatI8aZO0T7ocy7NeSd/kimR4Mj1ZmCxPVifbk13J3uSz5EASJhXJ98iz49P6acO0KfKse2Welaez03uRZ4vSVemvjuXZtvQj5NnXWTGrlzXIOhzLs+HIs0nZ1GxmNiebnz2Src2e/Q95tjc78G951jxvlXfKeyDPhuTX5OX5BOTZ3ZV59lC+On8ifz0/lGclKdUpNS61LnUodUeeXX8sz3aV9pYOVdSqaFzRFnnWt2JcxQGXZ//9999//8v/FHvnWCu3WzFm2B0Ys2y2zcW4u3Lca/NsAcZijGW2wh62VRiPYayz9ZXjKXvGXjg6XsJ42Tbbq7bFttqfjo237R3bbh/aLttjH9k+jE/tkKFoWWQljCP2nX1fwKZesEKxUAWjaqF6oUahZqFWoU7hpMrRoNDo6GhSOZoVmhfaFNoVzi6cW+iCcSFGP4z+hQGFqwpXFwYXhhZGFEZiXFs5RleOMYWxGOWV48bChMK0wozCrMLcwrzCA4UFGMsKKwqrCqsL6zGeqhzPFJ4rvIDxcmFjYXNha+HtY+OjwqeFzwtfFA4VvH8bSSErlAr/KHxT+AbtSRWMk4r1iqccHQ2KzYrNi6cXWx0bbYrtiu2LnYpnF88tdimeVzy/2KN4YfHiYq9in2K/4lUYVxcHF4cWh2GMqBwji9cWx2CMLU4o3nxsTC7eijGleEdxVnF2ce6x8QDGguKi4uLi0uJjxSeK64vP/YfxcnHDv42Nxc3FV4tbMLYWPyzuKu7BOFg5DhWj4jfFI8Xvit+XSZmVFcuql9Uoq4lR69g4qaxeWaOyJmXNyppjtClrhzTrpT2tlp1ojayhbtHX9E3dpjv0B/3eyqxoP7ErtboNs+E2V6+QDnKmDpSN8opeqT/R5/RZu9luFJPj5Tg5XU6zSXYTUqWe1JCqNtHGoyOsLlVsgpXLyegWq6F7fEG+ln/IZXqi9JHe0l+v0np6svxUrpKfyU8wrpZ9+lP5RJ6Rp+0q+UG+l3/KN6poLYfIYPm1PCG/ksfRZZ4hw2WoDNMlulh/oUt1rs6xbnae3C13yVyZI0tliSyQ+bJIFspyWaHb9V35k7yhW/V13ayv6h91kw3S93WnXi25ZPKq/FHf1rf0PblILpYL5QJ5U97UHtrdbrHJ8o6erZ1litymDfRUeV7elrfkBhkjf5eD8qF8oF/pl3pAv9CD+nfZqT+TB2Wx9tfL7ALrYdfqbt0lW+Q1HaKD5Sl5UmfrnfKwrJR1staaWVM7zZpbK2tpp1sLfVqfst7WS4fquXqO/kjP0g56pmaaaqKx5hrpz+Ur+VJSSSSWSHzx5F/ynYQS2HFWRT5GXbhHRskIHa4FNa2mVfU4rWKDbYhu0D/oxXqRjpDr5Fq9RkfKAfnCmlhj1JnrbLRdj4pzg7wuW2W37NHadrUu12U2x2ZrP+2rA/RyaSOtpZVNsanSUtpJW7leRus9erf0kO7SS3pqDT1B/6Rv6EZ9RUfptfZT+5F11Pt1nnW1LtbZztJaUm4j9HgbZ6P0QV1kx2NUtarqq6eH9ZCGGuhf9SPdK+/Kdtkgf5DzpKt0kU5yvnSTc+RsOVc6y4+lo96sE3WyTtIpeps8JmtkgFxubfQZfUbmyX1yr9yjD+lK/aWu0E7aUbvoj+1M66Av6m/1BX1e1+pj+rius06yXn4jL8pv5SX5nbwsv9c79Hb9jT4hO+Q9vUt/rb/SU7S+NtKGcqOMl0vlEr1Vb9HRslf+Kh/ZJdZHVskj+o7+2brb+XqedpUJcpPO0pk6TafK3+RzrdCSnWs/lptlouySv+jL+nsbaFfov/Q7/VaP6Gf6qX6iH+t+3aef69+0iTbWZtpUm+tpsl9Wy6PyZ73e+tqlMlkm6Us2wAbo76ydtdUL9QJ9UtfLj+Qs+7l+YO3tDKmQkp1jZ8v7sk22WcHMFGewb+WIbJZNerq20BtsqO7Rv1gdq2017SQ72U6wU62BnWL1ZZn8QhfqAm2jrbWdttWW2krb6xn6iD6sj+oqXaOr9SStq+drNx2nY3W8luuN8ql8Zq11gt6k3+jX+k/9hzSURtJcWsip0kA/lGbSVJpIY7vILrTqVk2vs9vsVq0jdeVEOUlqSR2pKbXlBOxqd8kv5SEdI9NkqsySmXKH3C4zZLr83H5m12hNG6kzdLpdZv2kn/S16TZNbpVb3MqWK2SgjJOxdp/N0/v0XutpF8uVMkgv1UvkOXlWy7Rod8hhOWQz5RSpr4N0mD1g92MHnS+z5U673PprH+2t8/UBeUDutxoyUq6xulbPbsf+e6fNQq2s8n/dFPw/+FfD/adpDf4PW+7OXKS9EI20J2IVslqIx5GdiFiDrBHiCWQNEWuSbkE8kfQ1xFqkbyLWJt2GWJd0B2IDUncGbEj6PWIjsjLExmRFxGZkP0E8jexKxJak1RFbkw1DbEM2HPEMsrmI7Ql7o3gdCbukeJ1IzkQ8l7BziteNsIeKdz7JK4g9SN09XEjq7q0n6XOIvUifRexLdjNiP8JOLF5/EvccLifszuINIHHPYTBhxxZvKImbg5+TTUIcRtjPxRtJ7nsf71rCHi/edeQywhtNUhXxBrKJiGMJvYB4N5L7nsi7idx3Rd4EEpcvk8jczyYTugfxbiX0EeJNIff9kzeV0FuIN43cd1TeDEK/Id5MQuch3ixCDyLeXSSXId5N6vLuHkKHIt69hF5FvPtJ3BwvIL0KcQmpm5OlpO4+lxO6G/FWkLj//0pCxyPewyTuWT9Cla9XE/oh8daR7EPcQuquuZ3QLYn3HqFvEm8HydOIH5C5991F4tbIbhK3Rj4idFri7SX5BnEfuebL20/uKz7vIKEjE+/vJC6njhC6NPG+JfRraFEInZv4SujhxK9K7rtEvxqhrxP/NEKHJ34LQq8nfksS5KXfgRTz7nckXYzYifQXiJ1J8Tz8LqRYs35X0jmIfciwJv1LCF2k+AMI/aT4VxA6S/EHkrjrDCJx1xlJ4t5rFIm7twmEXlT8iYSuVPzJhP5U/FsInar4Uwg9q/hTSZA3/nRSPG//dkJHK/4dhB1Q/JmEvVD82aRbEeeQvo44l3Qz4l2kryLeTfpHxHtINyHeR+Y+6zzS9xHvJ92JuJDQSYu/mNBTi7+E0F2Lv4zEvddyEvdeK0jfRvwl6VuIKwn9uPirCJ25+I8SenTxVxO6dfHXEPp28dcTOnjxn6TK178lRZ31XyTtjvgKmXsOG8nc83mHxMX9pGcjfkzq8utvJO65fUFyG2JIij3JjwgnBzTphDOEBNUIpwkJqhPOFRKcQDhhSFCTcNaQoDbh1CFBHcL5Q4KTCScRCeqRYM0Hp5J+hdiA9EvExqQHEJuQ4r6DtqTumu1I3Xt1IMGzDjoRzjgSdCWcdiQ4jwTPPuhGijoZnE+KGhv0JsMzCvqQ4VkEV5JhXwkGk6I2BUMJpycJhhPOURKMIEFvEIwmRS0KxpC6a4wjnLckKCdBHgTTSbE2ghmE05gER+FcJsFswglNgjmEs5oEc0nWIi4gQw8RLCRririEDPUrWErWHPEXZK0Ql5GhlgXLybAXByvIUO+CVaSo4cGjpO6zPEbm5nItGXqC4HFSN2dPkKLnCH5Deg7ietIfIT5JehbiU6TuOT9Lir4leJEU6zf4HWmK+BJpgvh70hjxZVKs/eAPpMj7YBPh5CrBVhKXk2+QuJzcReKuv5vEXT8icdc/StzPEnIbS5ASTsISlAhnYgkqCKdjCWsSzskSnkgSIDYnQ18UtiCcoiXsSIJ1HnYiQx8QdiacsSXsQjhtS9iVBHkZXkqKfA2HkKJ3CoeSO46Fo0ix/sNyUuyF4URSdz83kzt1hPPJkNvhQjJ37WWkGxCXk2Lew42kqJPhJlLUz/BdUnefO0jQw4U7SbAGw92k1yD+lRR7W7iPBHUj3E+CuhEeZagj4QEy1JfwSzL0f+FXZO69DpFh3YaHya5H9MiwhkOfDDUwjEiwf4UxCXIoPELi7vdbkj2I35GiVkYFMuxNUZEUcxSVkWLuoqpkWOdRNTKs/6g6KXrr6HhS9NxRLVL0B1FtUvTZUSMSnBOixiQ4P0StSFxsS4b9ImpHhj0+OoMENSFqT+J+fyaJ+7uzSTBX0TkkmMOoHylyMrqMFHt51J8ENTa6nAT7XTSQBHUjGkSCM0Z0FSn6+einpNiHoqtJ0WNEPyPFuo0GkyLPoiGk2EejMaTI76icFHkVjSdz155IhloUTSLDeovuIEVvEc0kRc8RrSPDGoseJ8Pai9aTYU1GT5KhpkUvkrpntYHE3csrZMj/aCOpe7abyLBnRK+Suft/jRR7XLSFFD1b9CaZ+9ttVPn6z2Qup96hytfvkiKno+2kyPVoJynWQPQ+KdZG9AEp6lX0ISnqVbSLFGsy+pgUvXv0KSl69+hLEveeh0jcex4mcfPhkaBWRD4J9u8oIHHzHJK4eY5IUAejmAT7epSQYL+P/knicvMIicvZb0mwH0XfkeB5xUryY0QjQQ7E1UhR++LqpMiVuD4perP4FFLkTXwqKdZU3IAUPVjclAT7ZdyMBD1i3JIE6zduTYK1EXcgw/qNu5HiPBX3oMrXPUmQk3EvEvTHcW8S7BFxHxKsx/hy0ocQB5Cir4gHkaLfja8kxd4fjyTFPMejSN2cjCXFs4jHkbp5m0yGGhHfRuY+xxRSrIF4Kil633gaKc7F8XRS9KLxSlL0E/HDpG7eHiHFeotXkWIdxpvJ3H1uIcE6jF8nQc8RbyVx9/AGibuHP5Ggh4jfJEFvEW8jQQ8Rv0WC3iLeSYq6EL9PivNPvJvUvdceUvQ98WES7G1xQIJzRFJGijNPUpUUZ9WkGinOp0lzUuRW0oIUOZecTor6nrQkbYjYhuRGxLYkqHFJexL0AcmZJDhbJl1Ib0XsSopzR9KNFPU86U6CtZxcQIL1nlxEgvWe9CJz1+xNhpxL+pLgOSX9SPD8kitIUY+SgaSoU8lwMveeI8iwrpNrSFETkpGk7n6nk+BMm8wguQlxIeksxEWkqN3JclLkXLKCFLmYrCbB2SlZQ/I54nZS9G3Je6To55JdZKghyW4y5H+ylwS1ItlHglqRfEbi/u5zkr8gHiBFjiUHSZFjSUjm5iYic3NWQYp+MvkHKepX8jUp6lryPSnqXfID6WeVrWwlRV1OlfQTRCNF7U4LpOil0qqk+Azp8aS477QGKeYqrU+KXis9hRR9RtqQFDUubUSK2pcepcjptBkpziZpKxL3vt1J8DzSHiQ4b6RDSZAn6TBS9B5pORnyLB1PhjxPZ5OgHqVzSFCf03tJsd7T+8hQB9N5VPl6PinqQLqIDP1P+iAZ1lW6ivRCxEdJsTbS1aTY+9M1pKhF6a9I0GOkvyZBb5A+TYbzSPo8KfbadDMZ1m36Ghl6snQbCfIgfYsEOZl+RIb9Lt1Lhv0u/ZwEdSr9msRd4xtyr7MiGZ59VkaGnMiqkCFXsuPIbYtZPRLkW1afBPmWNSDBfWcNSdDHZB1IUbOys0hRy7JupOirs15keMbZAFLU0GwgKdZLNpysDuIIMvS72TVkOFNlI8lOQhxFdjLiaDL0kNkkMuzT2WQyd+9TyZDH2TQy9/lmkqA/z2aR4PyczSFFrcnmkuIcns0nRS3OFpBiX88WkiKXskWkyKXsQVLU8WwxKdZDtoQUOZAtJUUOZI+QuriKFHtk9iipi6tJ3e/XkiIXs3Wk7vfPkrq5eo60LuLzpKi92Quk7lm9RIr9PnuZFH1AtoEUay/bSIo1mW0mxX6UbSFB/cm2kqAuZTvI3PzsJkU9z/aSop5n+0iRr9l+UuRx9jEp+rzsE1LUxOwAicvBgySoQdlXJKg/2WES5GFelwT5kNcnQT7kTUnR7+bNSVCz8hYk7vetSFAD89YkqIF5JzLskXlnMtSKvAcZ+sj8AjLs93lPUpxJ8yFk6J/yoWTYo/NrSJH/+UgSd++jSE5EvJYEzzS/jgTnjnw0ifvb60mwXvIxJFhH+Q0kWCN5ORnObvl4MvQq+QQS9Ir5RBL0k/ktpO56d5Ng/eT3kGBd5feSYP3k95FgXeXzSNBT5feToKfKHyDBvp7PJ8F+ny8iQc3MF5PhHJg/RObmaSWp+4wPk7k5W03qrrmG1F3zMTKcV/O1ZOhX8idI3OvfkGCvydeTub99ksx93qdI3PN6msTNzevkvhvPt5L7bjw/RIL9PT9MgnqXZyRYa3lOMray1FcyzF1JyTB3pTqk7ud1STHXpcZkyK1SE7KLEVuToNcvtSHBGaDUlhR7aKkdKfq6UgcS1IjSWSSoHaXupNgzSj1IsZeUepPhmZauJ8FnK40hwWcuzSBDDpSWkqD2lh4iwTosbSB197aLFHt/aTcZ8qO0hwx5U9pLhppb2keGvCkdIkFPUDpMcieiR4ZzUckn64/ttRYp+tiK2qT4PBWNSXHNiiakuIeKtiTudTsS3E9FLzL0TBV9SZCHFf1IkKsVl5HhmVX0J8P+WjGODGuhopwM81VxgAz3X3GQbNb/ADMmlN4AeJykfQlgW9WVqO57kp7lRbIsPcmbZMuy9LzFi9bEjpfEtpR9X+zsCS+BOAk4CWsWAmUrgdD8QkVoh0ADpaGlhBQG2pK2NN0E0ynQms4UflvSlg4dWmA+mQl1rcc/5973tHgJSceypKe33HPOveeee865556rIzr40xO+Xpen05lI1EQk4gnzs5WP4uQOZX+cFKUeIb8ihXFlP/4qlOF2+gz/P3wIn/ERJzxGrEHusay7fkmK4JjcEVc+4jbrtGc0OMQjeohgIk7yKLcZylfvJb+SlfMAFg5zYRCr10okExG4x9J3cNelHuE2a2iq9z/DXakzwP0CvXn3hTjpIl1x8usLMdKlnI2lcQ9xf6D3SUgv94R6mTx+Ia6cVc7G0/dp5UWRRiyPXibXXIgpZ0nXxPKcSBQ3U72M5VEE0vc9zLXrOKxnD7ebNKVOcu3KiHZN4F5j16y8oIyQx5URbmCy5/A8MZOmic+Rt0gTeRzL1eEZuHaSexnwMiFmQKmTh3rndn8YU15RXonN5AZSJ8k1H8ZJRHklzs2T1WcS3FvqMwJQLfig7rmZmbvI4x/GSIREYjMB/YEJcCSoAcnmCVM4mfvIrz+MK6+QSDz1/EQ4UWitqMEatHJPZO5COBk81Wce5o7reJ2RcZCBeEg/JaIJ64Q7LstYmxrtO6Be2L1AAQ+1ugOvc68hOsoIq13d+HJ9gLmPePiH2V1Yl1+TZajscWX6AFsb1PgNePFGhgSteLjvk9/rr+C3Ad9aKScCdEGKwkHUCQ9Fuatjh+RDsQvcexcu4BF3TfxQahd3/6H4hdTeCxfih7j7U7sO0XK+qQ/yCbUcJzwPuElwAKTDL34m3kyfVE6rT8UvkC+rpbYzKGq/C3Bxyp8GwWeQgPVealauVq5u5uLvD7zxxkCmf2r3+SSDT8jcR0j6PloP+ga+UJevK2Z166FcL/BOwSkQfb2s/OzHMeUHpDv24y/GP/4Yugz5ROkiG34So33hxyAlLnwMxxPKskH1eCjPOW1QlJN8WyahH8dIt/IDtSgoYIqi1Pb5LuWpAirJpKjE00/iI9HYBx/EKoGxPgRGfhyY6kOVueB7kmcRuo1+8t9VXqbPAvPTZ4GhP1QZW3v2k1/zJ/lr1Gc5Z9RpgC4ADfRVFULqTfV2bjrtRB9+eI4y+YcfMrw/+T3/MPALhzVvMvAPM+akn+3I2vjC7q7W18w0nhxQZ6PYkt+oJZ5TIXBvjgeefj5I5QXC4jwmQt7CwvGFfYOBUmXLJ6f1C/gHddXY22oEo2C0Ox1ORxDYr0byS/5QNBKNBD3A1kDrEeWhpbG+uvr6ur7YUnJW6dq1fk04Gg2vWb+LXAl8eSHO7aqX+mKP4U0ynN/w6/Vrw5FD8Y8vxCisl/Uyfwhh+STBGZUEawhhULAi8AUFFkD4It8OfP1x/FAkvHb9rzcAFBmBQsFS/WcppEPkygx0YJezGcwYXUkNFrHaEQAlJwycTAkMIKiwFZFw8u1TIc299KkUj6tD7MHQeSkRFKwX+jMFRkn1kpWfhj23a0rKKR+9qg/xN4G0cEAt2qH4GiAqFCVQbwSqzQojhD7oEsfeFl02ctRcYyZHbbJyQjnBiS6XyBWVWUg0P1952VKm+MgPSbHyodJJadDKnaTUCQVOKEvl8W/pH+SP6iy6Up3OQIvw0hKgzo2+IKIWtAb5V1N9oivB6S1+C6dPuJTvjyJDjspxl0jOkjeKipRGpUt0yeQvxKp8oNiZXE6XbYOyNQzV4nFU0ROXmFOw0iWLiKZWpqz2L57yYQh4Qw916EcpD4gZJhBtCNrdJNBFwkG7mdQ0E/5VrEW+elxVpPrkuv5l/XVy797P7u2dRn5G7MpflFCA1pADaqijoED5saXszvr+urr++r69vb17KT0MB6vOk0VPBrgK28tghye0QKqPwmOwDROAUTB9DKRK8z9D/X1BZ4e2qdTpotZQJOqLAJO6iMFNoPOJnnDQYzUQq2Q9VWIhf8i38RyZabHJf38uSTYA+5wZLeMeKi43PKM35ev1H283VBQrrbLM/c8tqcPkqRWKOr588jzAeYByZ9CaKToNT+R2y6SnyArlysVmcqvJrucquMN3G8ssyjQo7kuWMuPX9UK+3ohijI6zx/grdaKuStejW4FSys0FA1EzBzXWTCRHEKrJ4Jc80NUEj98ZiDpEu1GwesKhZgI15SIeK9RfKOoIRKIeNxHUW2GUDkUCDhHGaj+5jnxsbJvfWFaqb1sIw3vTwjZ9aVnj/DZyoaFU+WJpQ0EB5yh4q66GRKcpJyqaI80VyolpUVKztN/OfdPev8rlTD3jdFmKXYnrnrgu4SrmtzX0S0LTnPr6OU2C1H/E19zsM+Xl/dlmyg+tFJUfyhXNFfAvk05xZSjfZKuvqamfZXU6rSbBrLy7/LrrlpNSs6CNGyr94clpJ8YaIAm4RDKKdocTCe8iATclHBgoNCVxvIT4pxbZ+5ciYaSJshJpmhYdh77yAEUwjTzjKhV5xlvPQJs/pCvTNermo7xlLY7V3g1DeNATcFQR2ixGLyALuOKHt0aygn1gBE4PQtt0EYcTeF47QNJCLUQfDIyVBpoj1XcJTjP3hNkp3FUd+XxhUcuKquoVG/CjpaiQO5PacVNJzYwaqduc55fyzN2LtAMJzpbcRLYpT4MKt6xqS3t36L3CoqLC/wx3t2/pI7UeTy2+ifJLvvqXrv4ZNY21dovFXtuofdfM6Hf/graDRuMM4Oyp6LN+Kj1bJ5LTnBIuir19EtSrlKcvirDKO88A7xyD/g4ygMDA7iFRB2heVo8Vxj9rWuhEgj5gGCZpgHn4QoMh9V1y05inWXle2clXlwXKQPocQCHD305bfxl+8CG4oDz7+7pS5d+JnHqW/A2ee4PeVQ3iW70LPjSZm+BvAentQPkDQwLiIWoIQBWKoFDxMHhGnfqQrFyr7CTnU2/a3W47f7voGkuQm8i1ZafjQ6fjZJAsUx5GiDID5RIDyrNk4djTp2NwWZeWGw+CvsXkXRVABAgqyZ3QNUzQeJGgDRoyKnrDPg+0DBaEVPK3K8NKoUscVYZHR/lfpArJPn4bE78AiZurHCNn54uu1ElZHoV/5SlG33P6rSD3rIw+myrHM5UMPdPqs/nQxLyb/LywshA+GDyZr1aGeWLqUb6lPNPD3UAcgqD8p2BO3U7F+gHz9NTbXPWHqb/9boHyHhEXqm2rwXNOBg3qEtT1cYD4NuUnyvd7yGfI/kmgdCkfkuIFyrfIHEYPyh2t/nS2sNpIWVVIfEHRK0IbnkK+yK691MnRUXJUGeb+PJ+eztTcOTkh5/BmuU6CtgFJlsOPHirLDEgD40nGn/z9ofayNC9ynzNUuZRPGEXfy/Al5ynL4sOysublnt8yyq6enCexxWoAC7+XaaLQUbLYktakZFM5szVENTVr6mWNNRWL8tIsrNNZ1Yw991mpHhdq1bhTuUWt2AVjf2EsqsnMY7Q/1EzZH2xYw96wNxwMB/XBdK9gPVHrFfMTCRn+wWqpnqxbpK7Hq4ksmEhv3afRmwM5Q7UGGqhmnDT7DhX8/VOTnXqOoUBxeFF/L3/k0+gGNRoUaVbn3bKyV9nF+VMnGXC7e+wLZB+5duNQbGgoTv9jZBuVCVtT35ShVbKI78Ob1Puy4V9SHeRg0RZchjp4ug7sbqwD1vIPZaNylxXNiWXBNg0TqAjrQuXbZM781Gdy0KFy6hz0421g6VkAp3K0INIdIQqdzEPEoCAFQUIJHj2R0xJj7G2QGicSyWSC3J5aF+Dz+G3J1PW0WxxOgj5dSM4m4W9UpjRrMEpQL7N5MiBAwxS9zqhN8gjn+Gq1eM4vQ8FnAlhuplTlBBZINsgyq8dHgZdOgnzw6eagBBIkLJLaWNBfo6BxSTa76BTMRMQREWwgYrRRs8hF3JxoF6QIqmhQ/VIkqB50kZf578S2hmYohZTfgmvbSx77b31s5rzIugg5by5KfcSNbly2uLm1fW2wbp4Zzkq18/qXgKq7eFZ82tX8ibFYfKtI+bBn7wq7tT38mPK+0TivTLyqB27mOLOZLGltXrxso9W+Ym/Pkv55tVJ0bcQ8rw4U5mnxWr8ul7Yq3bQpaCMBJ6WCRHg4Ik7gI+MUBHB/DrYhvsqV/V9bEu/fYm+c1rm79aOp0FUxIw/VkQ01nuvn53urP0LEmE17DGyGZvhRAxUrOLtAHWR4UEszB0W02xlq/I4VC+dd49ogrtjdTVGhEDMo0gphmHF31FRfv8A7YyBA0chYpRQ/WvUUJ1WGM3xqdL04vma17aTYOEEdz2YIUIiw2bHaOOQAbrfWtJPhBw2UZgT4gP9Z2+0b7SuundW7lz+UadPJUAbbrG91KeOByLqd6yILOqs7NoSgyEvsg04qC8lkfXA4CZKNK5+6D5Kzk/TBHAhCUAQpa8spnRzFcg9PLPaEWiTlh2f0FSDPO1HnZuaOmOPdCOZ4PrK8K1bVrMQ7wDDiztBaaWqct+CZBfMam+T26ZvkP8mbprdjRZ7AGm1ZsmlJi9zU1QTal43Vv/LXAbwZnxogbym+vfgAPrmX2DKtoPy1dUlLy5JWYlP+WtXUpI39QdClLdSmyRn3Aw7UywLAR4hXJ9GMOGYOdxKvyDDX7GE21qROuhpc8E9H9iy7mN+maa3wmbqQxGP2wWyYJDOTR0fpT+AFgeo926Cd0M/g1FWABPBSDSWQrV1FggbgCgmUR9SlDcAbklcM+uBbH9T0IIC6DBlE1jzXyaSMrZpRJamWnOqjp9E3AQeynETxir7nSfDQ2XKVMFBdGQbIPwK8USE7mK2MJZnPWgaeUQplmQ9l1LFRDSyFCVCZzqz1A4Sq81lhXAAOAaAR7AcwcngMMFjrt8pjb8uqDnIAO0IX93hg7GOuHAu0A5syhuU6FDDOoHydTtMpM+WPK90Jr3Elf4cW+j5WX6ZMnlfLY3y0Ffg/Tv0CGVci82CC6eWkFqcEprI/BHYYcj/IQ2QuND+ZEUrVy2DA4WRdIewDfmPcBrynJ+igezPtqescbovOjMUXbFs/eI9fkvz3DK7/GT0EBm9aWOpdH2Ic1bCgGvuKMpzRSsnjaYcfLc9bvbxedGQVQQ+3zYfeUl9bW0+5uLyU9pmqc+P11jv0hP+Brhr6z2ysR2CHmhYwPWk3p0I309VBAhgy/sdM/URzFOsdlnzBODJishv0Mak+jWS9pLyU7son0n1aE6ORdR8rTxaY+UOHDAaTUSCrpy9Zvn4Xek/Reblr/fIlTWnfZcbFGlm3a104DB8RynMJoOWbMNa6dbW6Bm0cycgtNnRYiFOIOtHZHxQFfwsRYdQIc7tzq5Q20ewHdpTdfnvZjgeKR/tWbZI3rerjXsi5gx6culPcfn9///3bRa4lMWNa/rFj+dNmJCg+D/Lv86d1Jl0R2FYiSmqDYJPg38fjLAi8cSzgdg+Rktd73nuv53VSskHmBsCu4XYojmeV85/7HCl81sH1olcX36OjjFef1O/kH9F16/pR6zQTCzFaiJmrIg44chP4roKxs5tE4KiLwHc36eJaiB+Omgl8t5BmDu6U+KiTOAlXVBNvL64XzIs99YUFFQZDRUFhvWexWagvbo/XrLRYVn7K9QvxI6Qirhzn77/MB8dfV6bH7yMVMeW41sc1Om/QHfzfUSp04b1w1sEewYLgyMjKwzvhyM8ewGLgCIqKRHknkYj0v66hU3k1JSuam1eU1OTVOxoXF5sNlRZLpcFcvLjRUX+Ra1UjZEtceefI/7pm118yyNxryh8Bg5jyzn2abhMEmcvD2CbqXKj9hz0E3iDHg2GPNpIQGEmQu88xrYa+nyYbQN1n4wWo/8MJ7gzPycoIjhfooHeJaAxQrzo/Dk4aCr7T46Ynq/TUmzgDxQonTaxc/GflnlXHwJf1C0C/xDLTY5ItaPXim4z7TsjQBWUwXfALBzv4IvfgPKJygjucuh7sxzf558fmwaj8tDq+blXxzZSNup765qF6cK4Sp3MP0hH8DJ2mO4GfozK+yB5lGIvmbx87AMN3EkzzPu7MKHb6nPGOwcgpnZZINmR9QllYDpan+SaCadp1GqX4PgUDeTXQOMwIpBgAYTrdpz2XTHJnklSDHP8cyqfjIIefBDlchn5mVcmokXwGNqqEIqDy+AzExp0RXThYKAklkSca9C7uETYtzp+E1uzNt+j/8Acjjgb8d0G9GRv77nfVeQGt/MlLn6TgyQpU9XU27qNe5EELDbkXdKBcHa2DhGk70hk53osMDoLbI3oxgEJOZvS0JHcYOfLj2IXT8aFzCb46gZzIHwOlKEdVU7qgZe+OXzgdGyJ/TCQCgcA4XCRdEHBBMDVGUVVsABN/I55DXKiihv0uKHoMzihOpVMHA3mL4cMUt6QMnAqdJCEDnomxt4lf8y3APx8ahxXO7XVxZwCbQOKBrBvH4Vala7x4PRGoHNun15LSNRq4SBUVKsO0JxxFbVem/SwbB69aR5+Ch0d9k0/HJ3VSBikE/0rXp6El0z8NNXUObgP0lWI6zgdQV+JtDmq7il4rVfH1wH/8s88ajCaDMPZVmZ+ZquP+/XP8IWBUg/JT5aegMPGj/PMAYVTrR0/rQ/yX4MiCto0HdSwnjF20TGDy7algZZ2Fry4mlY5Uicz9LXWOu89eyZtTsywNVUm1r7AyCtn4KVqBaQIRv0Q4S12lzL3vqCTF/BEzX2kfiyWrGiw6dW6d0QJyZhwpd/LfzaUiF33V7mHtVAqtVAu8EtBFdV06nWGi9mxHz4MRVDOvm7M5nJGox2sUujhfMBI1c4agXzJGQZlu5rjdE7Rkevjv8/N/kr/wprUFq1cXkMaf5M+bd9PCsQ9/kj9//k0LiedHcPqVefSOJeOfZIfXHT+16LObSfS548efO3Xcsfmz36Sfi+D3Q/SSOnb8s/4K/n7Q42ww6km6Vpy3sXlAtXQiQRLOy0RxIrCegASSkDCwFoAy0DajniBe8dPbIlF85hApEfy+Wde8MKO9sLB9xgvXzPL5Be4XyvsTzypf+R9jdVUkUlVt1L7Jnpv2XLPFenDDppHhTRsOWrdcs+emiWeu3Lxx5cqNm/9F/b5SlXUJ/YOgH5tVO5Day4LBh8Y79gswP31WtMnwpQ/mCcpCZaGQJ+sXwJi0gWyAcfYoMD+8+UWp6rxC/gc/4AvzuLdlObX0S1/iTrG+wGfBYf6JXCjYYXHSKwdAqoQVPb5gHJiYGUvL/SLw1dO6duAmtFUo90hQ92h5dWLv6CDYINSfFaTzlmCPNBJ2NYvtRAEkgQ9kp35rlXtnb/W0eY79bBr1/sLhlQPJgZXDhfezEwl4ZzGMnEhdn/h+rHvmSssmISSVN1cm4YbNjza3tDQ/uhkOk5XN5XB2dOv6NYf9dXX+w2vWbx1FZ2dSm9PWaPjf4H/ZeF8uyml+uRnslxpdi65PNw/Ho6AmbV3Eq0lTVPbSTneSbfIaMrZjxgiLis6oFEZBS2WwTOVsAvSWE9QtdSZjECrHc0xFejC6N7aSXyhTqTxKnQ2pPnWOQulSn4OP5ERL8z++vie26laNPxldUervyoyxaXs3iEhrw60nTMbZkJQkn0oIHUjI7Q1OJzUaY7O6QzjwopY3EX/lBBJwWh1TQt2zYtTudDobCB2B5VTJRNRv+A2g/qw6Jjyl387/E+gq6CdFNAQ0YkCIIucAbk4zGERoBqEtYwDuauaoiQNWj0Crn9o1EcpHgpF7It5b6nSW9pb0rhsYXHcnPY631tRsuvWW1hL4bo2TB3N/xyc+wW2L9a4bHFwL5/DnnesGB9ZBKbfcugkesLbdcmtr/E+5P2MTH8D+YUiPHTi6h0HOdtLR1EXUAb6RiNqkoTc91CPbAQeCThxUpxbhfhz78Sy/Q3QlsIUSLlEpzByDQQ3yJkk9ROQ8es9OJjg/lUHHoPnYzTLerN4AzZwqobfQeJwAGiykKaHqRtsAZ55KVR/GhIoeH3aNrGkg1E4IiByeoucBRMkN5LxSyA0AA2cUNlDVAggtddL1NbALRhlshg05jyoHYJ9A5ZXF5m3lQzqrzg0wTURUpYOdDjdeqYM4nHAEPCw4ud1KITnPRlEuuvXK/dfK8g0bB6cvWjIof/ihnRwlR0eZ18hu397Tq5f13lk+330vvaTGeSKcknFQkOMaSU7Jvn0LFq2Uc4oT5+xyVam8+zX9NfyXQRcpxphJM5F4nz8SBaNcKCI2/XblA6No+qPSbiN2/jt2+72ph0n5MX7fWMzO2chPnxfsAukSbIf+ZbfymipLv6a/Gsozw2jsD9FyaKEmco+NlmBUPjTa854D2TLMzRRK6OOg59iJjTyADktVxi2BsaoEpEEQ5IHOB9RBZyfQ20EYY28xEHbKpP22kazfGGUF6Pv0hpkmg4E3KvMKKwuVefR4JoB5QD3dqrRq58rJ87nnyPOFlWbl5yRAAudrjXaTgVf+JghEMMChvvYj8lv15J+JUz3FfU/5Gz1U/pM46EUiCDtf+Na3NPmGNFkoTbrx6E9C4QSK0tRkoZ0mJZfCSakhv5uAct4klPFPTkKGOvZ8HXjun0AOdOuW6UA4EPTgpKUA9dyg01UCvSKKqgVKAh4DZNC7I8CBxDcT5tSBO7xWAsOqAShHH5ATTVmgXjBEI/Q6N+Qb9L+2EjvaAs7j+aR0urNibqXyictiKbG7xAtnaqoWzq+4y1NQOlog6H9jqrIcqFviNouFphXkQqG7UPkvS35F0YHmtZVn53ndpaknlhJSm6cvuMtcz3+mlJTeDh24S3TV9toeAlns5J2vOPqrzA1OcgMMW0vcFZZS9wO1mxsSgqOARIry9f4Cu8tin1GuvEh+nWd6zpwv6H3mKkn5L7KhWLkh/kqXubrwCxaOtvUr+oX8QZA7jToMVk3XUJp66GE+6v2CFnY4DQ6U/5RoGxv2nFqlWYiDjhvIFVrFRaL8BS8Vgq/ZOqsOlEdsFqvBTsxlHWWvFab6l5RAVyIl0wq8xYLjroplsVdEV8kK79rV1Xf5CyurxWbbb2ymImhjS96BlvU1lgpzZTV3zm3HsZ7UlttNvrwiu6W4xfxcMSm+PU/ZHLe0WF4xm+xdlT2lX3AbyPNw72eryudVlVR6H2jYHZiRpy+8vaCxhOw2GnmfuRSKnBcT1XiErfxDIIFbqVe0WVNEIlFJC0YKAPkhKa1hGe1UkAWoYuWbTFXh4549d6ET/q49npX2/qXoN1/abyd7J7cmxg5MdA5zvuhs6n+fHQ3VSMz37lk4uTWzbaILOmduolTXRn3aGcsp26JyTkpwFOdCpwDXN5G0lZ49/LHJqRudQEYoOjvtJxoEe7GFauY6Hxo57BVEp0UXKrVUl0JLyIj6ipdNL7pB4XUGbWgY4VSDZDWge+n5EltLa1/HvBm9jQG7y9NIGqrdYltD34x5HX2tLT6mrlYEA7Lc1fHU0NBTHd3KG8nkD3neVGgVy6tqG2DMbDGFY2ETaRFdDbVV5aK10GQETVcZgY9R7ktFJYG5qZvnBkqKyCIrrgDh0jQ4cfwmaWytOVT4stG26s2AVu+hdXv3rjvUq2I69lIaO86N4GeHfOWpP5X7QrM1rE5kEHlfx+xLEHgP8mGoSRuNr4ug1hNFl8G4OToS8tcYcWYpmg6wAyuBZ9EC0NgwIvuikiAJzlPo/0O9+F2qVJRCdzvK5jWzYukStd1lMb88vNUfL+0h1ydjX1kTe/RGboDqNxj/jFqSiA+5xMzkk/L1itKYv7HRHyutmJWMPT4Y+zLqbSoNGK/tAz6dDmNyrufKOzn2JI16jRHEDgbIHKTqEMU8df0ErJX30zjP6eZ+nPQ+GlvzFT6kYYyuP2VkItY3ajhXkNpk7Zdjg48zX8WEuqc8/A/WPjp58XX51f8rUP0vq+rJBvSWq3Hoxgn1H6Y+istuAZ9KwGU0AVkv42zwpdf/QoY29rvJeH/2P1z7BDlfcAIHSdF/oAP8ZM2a2OBgjH5eXlNcpT0Gn1l9IU9tC7Rh7MYaPwYjkPFNMmVfyLh0o+QthjozkdVmeXOq9vgoQ0aMy2OYE2du+0zeMRoyZMTGtQ1aNnU4/uDMAz+OCPQZOTFqIZsYAYWlJ9RMaFMEMpgrXXTaY3RUubtmRt+MGvpxsHVJC9nQsoSutjuTjSwa+cka9baaGa+3LGmFe3U5Mgfxq6XxVeO5Box3ATELNWc8E2nM5mfzBzdAmgKTI8VzGV7AWaFkNkJHVISyx+lWnQ4sGvQljPd1gtqJ8QS5k+iiHYxzcqdyoaNjwiB980bPgJyrGLRYq8UOYtp184Rx/XFrS+4MtjzguV+nxfcw3KbGbCoMpgCm6iZnwPa9F1qgHEZ+QfLkmryCR8K5Co+T+8v+fcq3Mnau8u0wmTf2NpkX23nqlMvOfRdDYLGGyVaMM9nKcD4DON9L7c4JJUvjS8RygGHUctxEi90+B/jhmgcfSBfKIWwVmhq8pEaWGTDmCThGHd+DJCh6aQRMfV1vbBk5Sn0yqT76xd+OAUvDLHAJpwKUEVnm2pfFetWQhtRJ+pVkwWVro8oI3nhUzvgxNZzK6CzqpBj51OmdyTDgBtAxOhlImQExpOuuiPpgy6mHQMiuPh+2C5IpqaSSdb/TqjJl5JLQNhuo7xUR33mKfzhdsTI00BbyuKzC0mfBslKaxkEidJKKvbOB9NEScoomZ2WtWMpbh/XH+O/pCml0rwNdihztwzarERd8CFYP6L4eFEZRjyOiJxmptrYsUJaaPsCtNxhSu0XX77h/gw7+ebgBFF32mXqT/NRgUHbEuOOlwTK3feyKU8Q9Hm5VLlynGlmO5EUxrtxNsoHWYzx5qv53NJy8d28uPNmgzBBdSKyLlJWxcMG03cJkRs8/IDVs41aWXZYUuT57udnliBQynL0CLddGqbsIFfy4pWhTYXsgK/BuCrzI+UnWpWV4vmZSfp9QW+N5PpFdI5NxfX1/fX0u3RpM1wS+H09sNu9nETiuB2hkIRyNHx+Dce4rQFXFZJLQi25OqxfO8JvvvVcZ06YqcVjDuEHZtZyKRnoq9bbo4pfJqTe5AbuL1plWdhnWmWFC4ZoATwPh3siBoYy1Ei7VR7h1qZMM2rocYDI5o/Tt5TdrICnMU5RXynQBtBPIOE43pJnHmeHzaA7/C2IQsMkxbLcdvDrNS8yQBga/P5vrO5LKSI5x25HFWXKat6uzGD4xKpMNahtoOFddFGOv1RP2TonYMZk0JafEYVQ5IWfzsQASCCOIo1ZJVGM9rM4cFuPeSCSUE2AKyMi8+9P8xXl2KyPDw6BndSHburM5TDeOb8UJfBsGQGGnNYtfcbUq2ZDI5dR/VmFMiKOg8aU+/2RTvV4PrtvFNbYeeBNL/yRuCYx1xjEVhtbZsUkcEThRzw0kssyfrHmDUl0zcBVacTiuTgQfBbRsngmS1FFF0CfIq+EtBydB6vOA638RPleIdk6Pn0iPkuTxCVLq80CA8qtcAbrk/ulx7r7USXJWM4PSa5gegnG6SeUvFp4m0hlA0GJDUnpyCs2EkF+KMl8VeUseWDFcNGw0FG7BhaBKV5c6FcX96wqfJPlWNJXCH3+sZdojm0/ni8aGz+P84LdXL0rPPo29FY0e+uyhaLR3weInFi/QxiWGT5jONKGfKb28hQbne8JBGkaNrlafOmkGWHMCXeyDfrZcPPmrioZXqN3R6WzogkYGPLYUGoxj/0aVl3mfWZHPLVyYHF1RXcPfm4U6N3PzI9Na0pNri1Z/G2c3P99gFPMPUn2o78a5jptqRhIr9w1Jm5RHcolhsVMYT6ZnUZi+IJGIwRMmkQDUsV0gHgIWI7HFyesxpZmvHjvAPWpuMN9nsaR+xC1QPo7DH3k9rjR/bQQumO8zN1hSP+Y2wll1TS2WbcQ5DZz3CRMnH2UlWwj5Dw7nzj8YOTLEShyKyyPwk1QMsYKGNNkSojHsGB1upGEDETD7IhhU4HOqXjPBG41or6BRINeWFM7dsm7JosY5N3qkf73nNnIyUB7tWLxyUzIg8057TVv3mu2f+/Lr8+eTrpaGcGHh9OiSuTd5VlbffKMUWNg3pzlQWDZqO7z86J6j227smXNuvjY/fYrG05fRdSFph11QA41YRfTB17/8ue1ruttq7E5eDiQ3rlo0M1o+PyBJjfyxOT03boNClx+2jZYVzggsnrs4EJA6Z1M639M38OuhRXBFN6bnQW+PVldg7BJvmGwl34grK8jWeHzwiKXegvU0GI8r4ZFl5Km4spx8BBfuM5uH4NoRdkHtP6xsHPt1JKtQEhWcUC73m0xpyvF4/A1l/wj3UqYgsiU+8oZyYCQzPj2k84O9i7PewOG0P+K8txO9leFs0QG9wYYz9zYUKryXR4/hVJEuXFHIWGsvtPGhWmuFvr9PqkuLhjqpr19fYa2VS0pmd84+C++Sksn9tuSD5+12I28rfH6+aFU+nL54+bpM/od1yxdPJ8VWURnmjBXEpFyoMHLy5A5dXTatqLcFLxKjE5WofQSswJaEkGCY3gknpvIvP9gE9CjfA0Kbwj2z7pvVo4wkQ4C2vdYYmiIe53tPWUXR+lSjs7TUSTbPfx5qymi3P0/b91/08/iD0LpOzJGDQ2HuqmNsZH6OrJRxZ2TQ5lnA1vSYEo7zS2TQT/5DTt3GtBa7uymmhOLaOMjKpXFbJmhiMkmpyj0j5PrxhSqHR8h1k5SJdfqv+gegTCeMQrMwwxEwC9YhfdHlBFi7IBgj2ryLgOFC1O6TItGslwFuiEoCXyME++N3XWHjOcEmNq5eu2le59WLi23+h//H4jd/wcwVvuQsc0TDX/jqtg3rBnvmSNWFeXreUN43e806UmgwzNi/+hGOF9psNt/WufmueaEZwRpRDK2bGb/37ZcKOSjBb76wYf2ynu5+B05aR4KNTRWtkm1Lf195xfV6w4xHVu+ndcXoqqFrwC8Ze+75y8DymcvC5xTY0Q+BnuQBeYKJewRJ8GX6Psp2nOT0s1QY/O6hR04PnX5kiJhA9JpPWyxH9lssygFLg1mxWizkDjg5pt4CssdyGkX2AfhQ4DbyAUhrcrvFovYZBreAzvarkE1EILZLgL5FWX2EnAx/Kg6KlTx5nzLAvTE1Lno6b7GUv4X66HzUP4fhVTTGQAuUCEVsLCQC1PdgmJ4KGqLQt81cMxcZ5c6kSlRzAfn7JtIkugLJAPpwZW7+wECp1dra09NqtfIViQRG3dAVPxhu4xKpEgbn5LsHB0vpTXBrek4I8bKwqFrbZWCUvDRsDl0aKpRPrtP38j+C0d+LsgN6IRVsVMYBz/Io0lggohpDw+2+0IdxKXetHRxcexce9V0gXavd8PeN6/fsuf4beLSaj3zcm76B3tpL7lDOrqJ3VLlcVfTeVdq4ynAowSxK4+GRIGanGl8+dwfmmJtQHE/Lup3/JdRtBa5y8WVF/2DaMJImMNJNJKCwBVOJ0cwR/FdWXzs8vOdrVVUVlcteifG/jaUCXaK9tPS2wVWrB/u+tQQOZ1+4Ln6GdPXUeDjzssqKqqon9w4PX7v6ldhYTYz7177B1asGbysttYtdW5bA4ayPr4u/qJztXr74G+m6Zrg5abY8XO+aRq+bUCwEUk9hH8sg81sVops7TAEdy0D+o1r8EtXOeFF/A9gtxbpO3ULdetSV3aAkY3XSgauLkHHDMxO7dhyWAywCM4gBm2EUV36c7sYlW27OzMFvB0qyZg4ZI+qGgS2yLmLpvtrfstBZEVlHVhWmo7IK6/2xOoksjfctXhrzu1z+2NLFffGlRKqL+ZX/KiPllStawhtCJLJ+qMW7p8TorNgwtD5CQi1eyb+Lr4Ny62uF7pAxXNe8c11E+WN9Y2aVY2N9vqMOCz4CEOrFqiqxHso9ggDqHMquGYc6/PVQ7sYQqbD/qXFDXTOUu3FofYXdENT6XlI/TPteNXqiSUTNX4P+KmcX4SnNDmcbEI1imyCv0NnkZoKU86tE6p3o2NbddNfGauKpHT4Q7ZhF+vbe0dGs3N10x6Iy06xoxx17+8isjmauujXMXBbdV/cLPQsVZ/8X48GIvqrm2juun11TTl7oXiTM2D9UVTP7+juurSnP8hUVUl8hCx2kyQHAMMQMVw7M8+MVeQFjJjAdwHllGKdgEomvydQBn0iVjHLvyzgJgpkAdLr8dJnZazAyKy4xXwaLmffim1e/yfjfT5KjNCLrJF0+mYA/fhl+JvA3txOjw+TUSb46kepL8NXUCUtdsewMq/v9+i/xLwMOzOealmomkj0gSE4Tx/9gkImzWSCsFBsXhoFgALRR+ICBYOi0cpxsIZtXZokz/p7UKzgGrDabyZNwAHc9oxzH+3TjYbsuBpt4Ph0298NPh0ztbqY/YpzOHN1S3Zq0d4Qt3W7ECS87JrTJWTxpo8Gu6B0bp0o7nH6ezZTZjR7twKcdaKqm39fds2CLt7WhrSZL92xsWxHY0rqsNQKK8FuoEbe1Ll+5teyJqqamrqYm8hj7/kTHvvlj3pr9i5evWTCry+dv81a1Vte0ZQdzvBlYEWhd2gYWVnMrVa2vXLM6Mt3URK7Ap7X/BPtSZZNWF01gNXddWk3wgQib2fRoB5J2cHFq96tknWPfZy+JKqVwUuQNNAfMMP8A9Bk3jNg+mhdA8rM8WwTEogHjgVAX6ySAfNQQ5CXBWUF8vGBEqeEmRtJmziu2kdds/jxSlme1KW12v2BIiq6v2qx5RLrmGnn58pXnyZ6PfmvzFxdLfksxt6MWbjkjFNtSc9WDAs4lFvXl+W2biFV6tZaMpZ5IcGv+nkfv9/u1OR2GK+Y0rNDV6nRonHRjPBMIElsWxsDvEadWm7/uBTw2frRedJFxSCr/kVd8ks2Tzq0A2O8pS10iaSVHclDjXrD7j7rq3e565jf9Eeg3d4Kc6dH14doKXDPbAo2Nml8VjarDqFtJW1NIw25pMFZEXYjo1JYi0gBeXMHDF3qM9rvrmh9y5TnmfbG5esdse8O911xjKC0w6E8LBZ8UFnOE22/kWjlzodGg5Jv+kF9q5ImH5L1oIia94d18b3wkxlmqm784z5Hneqi57m7oRLvvbbDP/vq7hXkGXv9iHvFw9kKj/g+mfKXQzhPSyhn3G4UCg/GTAuG0qTRfz12jH4q/oeapZDQ24SjiEy6XGvPlYv63y0aSzaXdoa5t92etB1MtOJopKUqXbYWpyBFp6BG3IRNV64qTo6m+tfGRkfhaGMWSuJ6fa1evsdBglPsiu+PWPuq2r2f1c05/CGAX02yNNLVKFgznOFTIBsywokEYzUKAyxsdldVyA9mAKX0f6Wv4tXS9JdIXYQqUgNGP0A5gi0dCElBo4UDXchIcw0HLCrdc4asvruCcsdS7gb0NtQ7rsKOryUESj8YGBodiQ8rZmHLBUl/JFej5eVZHbcPeQOrdGOesKK73XdEy7GjqcpQMxB4pGYrtUH4QU/7HXOm36NUx5j/1jbwMtU17Hom4OYpNMzceF0HFpanlirkOK+ceSv2eHjFMHnwkNjAwFB9Snhm64Ohu4G0GfrnVMfeKltTvhzg3PVLRiD9iRYxHhj52NLY7DOk2v5LO8vhprmXWvs2kkYTRCSkaJkmxwP+etSDmasBkDSyYQq1sGgxO3lPbuJ7OAPUFxjGB1uY3A+zsNp8aLv8utvlkEGmbTwYH8xt/8mWA8VWdkUpinLVuS8fCG2hQCJ9eg0F1GhoOH8bg9w6Cce/RrLcn6817yLov7Fg9dM02eZQuZUviF9p0uMiVLWlr0v5v/ZfGbwW+tYP7L7ieTMANmOcBja0R6vBOqrke6HStKcv/7hqHNdQSW57ns0WdnlxU7YLkuwi+3BsMIHfNYOrfVUzJUW7L2NvjseVeg2vK3aeUXTu+qOE57YU84ckfTURWtVMS+h66Nr+MZhnE2nQYvTxdb+OXMPUhDH4e/saE3UXc4t+Iyw5DGVHOFBUQO+kH26yJ5v/Q4lQ2mZ3GL6ux11hueTrXB5bbSKzpgrEGYOD3GTyCiJMgwahXDOrNuWDeF0F1KyJW0q/84nekn6LPn6bGrpa+xSXeYC4VPisP+3GlcCKRm8eiFK3uqVfcTZbFYco40YlhqVO47+SJ8a/jYk8MLNp2YhTuVMCngKTT1j88yBu1HMwSTUaPmaX1DyrHY6RCeSeWeozmEyBbYuRx5XicVNBEBco7cVCtt8TVMnr4CMsrzsrAmU5uvvJIHEuIk824SoOMKI/E6NOpHnW955f579A+WgQk2gResJECeJaP2rhf3fLeLT9cys16564HlD/VHbqLrFROrCIb9/Ge1M+V75Hr7MSm3LhYuYfVzZP8Y/wjNOs4K4V7+EtHvvTaPK6U3KmsDpInj3N/Tv23FivAv0ptHBvNe0itmnGDDGrJqC3j4hKccaXTsKjckFlMw+FDNJNMJgkjLmth4WVaHOw2uua7gsXhEZGu+QqPnxem6+/J2SQIEWU4E4Xz35w/dT1bnsUdtrsxfNDuziqXrjv0iU5MljihTKQI+jwYVGqkG1sS8zRf/X9kXJScUyh3mC2OZ/M7D9K18RiBorNhvWilejD5OeJ6QE0EUxrQL/j7czwHleMP0LL6AmmZcE4fAtkuUa8tcCU6/nG8Rc9VOvsLnentwDg9eIGyE/VLXpExcQd6FQSqIYFyRP7q3drVVOCz7thnqyi31dUdP3rPrzo69ZzL9jt7JWfqMOUVn9lYZ7k9HHzxppvvLtu0uq9e4ufe2EAc5E9dW71dxXlwD1dp/53Nxek7O351z9HjdXW28grbvh1WX0FB3+pNZXfffNOLwfDtlrqNxQ7ScONcXqI8xeiox5qeDPMqwlDXSES9TR+ssHnExx44+pvObg5QPJ1vJrxlml4v7Gz75t6FhuK8jdsrTUU/PQ3IcN2dvzn6wGOix1ZRZKrcvjGv2LBw7zfbdgp6/TQLT8zq/OFCOl/OxuisBdqdJLvdBZxtxh+oqvHP06VQyFCMqTAAELMebcAFV03cTpWZxYAWfjCaTPWhb0DGRUgqXHKpfQT3ArgeQajBfWTvJfQR5nMN8beATtao66VrU+xONUErvDqJunzAoH6L2VeB2pzcWem1Bup1lMkY/qlJZTchthLRH7rv+H0hv1jSvWb9a+vXdHNn1IOsS2Nvd87ctv389m0zO9MH5Oxiei3rNnpIHi8qsdvKXa5ym72kaJfkcDod0ij72pV9iZzvDAfcVVXuQLhTKUwfk+fo5fLMnewwkzcC68dJ143qiJihspNkcooZstKLZd0SJuPWWdJL+uBE6sYOTEbxvpzfeMC1JzJUZA6/O9nJTmLDr33ab3pA7WMtJ4nmWdJhPIZvXMYxHs9p3iQbdybVpyX5TufogpMn0aVEfkWaApkrLqVeGUnK5LwWU8fgmbS12jYmzjDKJ50FJYrrCeF9DgsACefib2fA0HWFycEwagO6UiETpximcJ4qQKyfBNV4jYbxdhOG2uAwHQ7ZEILqwMAky0Al90vSrPnny8rYqB2QUzz1kWAEHK6fZB2HfJ5jGkRZar0sc2fKyqgqwZMjoOfq0zgYwHqjMSOki4t6yqBevZT/+fEdl1bq4IObCpSvcGfGCrs6N1/x1azJAq4DCPx1waYHB5Ue5VG++rorNnd2caU53bhP1uJF2Lw96g5WdTU8Xcvso+ELBN2RYj0ueKZrS3kBVytjA3EDSRBImLlGGcHAZn7bKKaLGR07AB+jCXJUq19WPnojbWqWZzozI3p8qoKrD8IzQMfbtJjbcSEzf/v/hTISoL/CB5RTmC7HokaLTrAIfJhXVaQZVkVUrA3Uk0ozrEHbRdVv7bcvy+uJ3/yMREIOUE0auGPsAK7ClzHnBn7B+E6/ydlEgrlEkX2+FqDe0EQgiU3KcnTI7EsZVn/KGMFDnaPaGgtcP5rrm01n35nsfRA03gDixVLxJOAYODqUzic04a3pvrgOl8b5EmfapchEDErWKMtillk6hQE1GJFElrUvnpaJ+2qZtrh9y4z2LIWzfQZZLPNdy6avyIoo2yUPrJi+rH/HroM58V67dihfR6WR8dmT+j7Q70w6u65ZN5+OFjAmW4gUiYaloIgprTAFgA3NR286RaGRnaUZL9VkmHb6TCfLTUdTXaIMdQItYvpSNMLvb20pXD1gTMp8f3fBovZuPsA8C0v76zsiBXOa2vi+PX37rwLR6BY2uXma7LJ9R9Ocjvhc5YN4dS3nF1a7+PJyclPgqp+sFdseeWFu4q2rfrDU3B07uZY8Bg/XYWhiXWLFFzsL+5uv6/kKnEp2dWzbvi9xaH9F+a7drsTGpYtbWn2eeEt5+ZNzGrZGhlfOswSC7RZ50Vw1XzH/A2gnM/Q8zOGDmzoIEgkT3O/GRKxRPipx7/5aeUd+M048yu/ib8qoih+BP/I4nCaL8Hwr8cTfJIuUd5S3lHfuI74j92m5ur9K+wvmWw0Al0EtVUMN4proakzWrw4rgmr7pH/TUdcJx0LHDffdT2bef98N3dsP3aa8e9uh7RtXXjn0x6ErV3bNXT14dnD13I2h7tn3zu4OddVtGtpUt7F+qH4Dd3xTMBwOblq0EhMrrLy23+f3+/oXtVfDX/t1jY7SUkfjomqvt/paj+c6zY/5bcD1c8AlVbo6XQT6MgCXIjiPrKWAjUq0ndVPInkZ6rxGAU15y+0O12/YUK9s56+NKanmtvCmuq7W62d9ZudA19Ite1bN644tGuY+t6dgD1JwxYXjKmX3zupZuX2J57rrPHzX2L0x0Pa81YukZv4z7vjC2b699TMXTa8fVu7Z4/f3L1xM7lZpK1hZrsWwB3nc68pOPbCUfa2qv9vLeDTrJw0fOxVZF0kOb7viWEOjjOPyvhe+euJvfXGZaZNfw6S6/saGY1dsG97HhvJ4399OfPUFppNmwbTQ/H4627jixVzoIkXpFIOR6Jjx6l33PMSAJ2jfRWT4bQzEQ/fc9eqMjiQDTrt3Ei5nx2fX6+bqFkCHTuvR6VwcLIvHBHM6OkGHkXC2Q52Iw3hDD7l54bVVniwh46m6dmHT2sj0tByaHlk7rVeqS0871km90xraaIaLtoZdCWXE2njnslXrsqXPulXL7mxcE1q74S1NSr21YW1osK6vP5OIor+vbk3FYIitYAgNVlQrIxqtKD850JxjwI02jy2d13Ec+k7+kiuC2w142qI9dE6xJ9prtdFdL2zWZyehvndJcyuKpO9hqt3W5iX/VxkhVTW778QJxjt313zWXOdk+U2cdWbl2OTE35V5nh3k5iSapusArXShbpVu40VX06b9IhlfiRO9nainYssaNDPCox1E1e9AVDtzGS6V5SbRwhkfL0bvaCVGPaC9kfqAfd9tcde7XPVPq+bJFCt0J3G/fNXIWUTTO8XoSq2sYiYM+3/OQqcylmpmTVZ+rVI1x9FsugPHVDUERi6tIlY/fidbnRfye7SDqLpgLxTVzkxVHWRBnmj6dSUiWfy4kfOrxP+YfW+0IO3uoxcnXvl/Amc8VonVV/yOSXwqh1Yznbe5Ok0r0xVCQGsRame2HPUXBZnHegrMTb+mWpINo9wZbidNMqjm4x3FxGoZnxvGTNLRzEYXxeVorlHxFDYo8/hjcaM4v5ApjDuDeT0z/a8AtLxampdGpOtmQMPjMWKaOk21GXI0oolXJDaaMj9BE4OMsnlyZQTT+nMXHuGP0XT6ibF56OAexTWQstueelMZcRHL8Zz1JwUAUcqF6Uxr/bjUjxo4uNjP4yBCWAU7mk7TT84zipRpVnJ+VAPM0vBYlWmYmJHVQGvqidHRTMw26v+Z2Xp1p6esYHRctKFmpKJZqUiWxRRP9SW0jFT4XpKdrpjm1OYOy+l8xLmwJkDCGGuD+s6Bkro/AyMHAve+5lhW58GDKj9p9mGObWhDX72HqNtcsAxbmmXI+ZOjmHgv9WYiTRC3kzl66QYJJ0YztGTqzaruqFE9HhY2GFgZBprKWSUpDYy1FLCKBotr13ZDYCt35dHRNGGqXGBrH3DOB705DTg7bPDUsLQbQTVgw24mksgybQtWikK64dDQeDWFS3XUJZ11/WuhIyZTJ9GtoxI8OroENEtmzqVO0jkyln4nwVenSjBtaIb+DD5qhMfFsMm0LNiyk6CR6kujMAUGaPakKyRjO6M9hlZr1n4m6fxEYc2l5UMfv4fcACCpMzbBXFhuewBMhBHokEoh91pCc0ElspxeGFpSmN5zMg2z6iIQO8hU0EanhKTB4NMy0abyL64/HDeh5aRpi0UPzRZ+AzmfSBvfYgKsQUyWSpom5JVEpwetPS4LhlPN3TgOQhR3eu0H2jMlU3OUDyWTOYUm02NWKIcXaG7KifkgRRVzW9ZcE8sPNQkNanZHDCnkj+XSkqTEYF46ZpqSJlmTZRpd6gqYyaizgXgNq2+8Po7SURXyhon0pq6neWJBVCQ1unNlp3cK6ZklcVD6jJegaO3jBAe+wXSfRIaeoVNnnF++RJlNs1ypfQ69U7nSdLMGbxwsvjqZVKcWcRWoFpvO5FwZ9vGoNcQ2yFJrtJkYwlTZCLJMNij4vFZJOAWdWHXqrm9d0gLS43OY+PxUUnR567jd8qlTG7nHqBBAuC1LKjAMBt10qb9bMb2XLI+D7c7IlwwCkgbbClarnlBQGuC4CvHUqSUtS1qzgMkMFE23e1S1AQ8CnFegLjXenci6dAKGTvayZHvpHI3jeDe9FvlM6qTWpnSLgLT7S1bnQdFnksxaj6zhwPr9FBhocnQiVJV9zk8ApqVv5LL4pnQSjmHJ0CVhHKsAJaNQh7lbQrHMsZl5XNbvLNSTMM4ba6Btk7u9Q9+pUzlbOcSxLG0eibU55nBDD5KHZQwIejR+yzCAet5TI/lolFoQRvNUHzNNaPqC65lxxR0WXWNv48mB1MlIM/e+NnvLh6gVhD/xtgH4gKdK4E5yvmI/aqlcFj7ei2MjfCoOgYvCTSK8jC5YDqM8xhWjkzJTmc6szidZWQYfr5UGP1hxl206X0OamhZVVi5qogaMGBjFBWmY6sYuq0kaa6ura1l7QOPCFRzm8KsvC34R40MYOVmUIIVZTzRuDLCNIL36oDIMPQ6DwFMXGHjcfEOW7dz7rMelWx1uS5XImt8C82hbaY+bEC8U9Bhwtatk03yqoAdzd5JvaOwHFO5Vvg8MuFaOUw2X57TEENpIB6P2CbaNlTanyOC5JoNmy6jb3vFwXKyUXAjArWz7K3XPHG3PsUyuF1QznagGoK4u2XBXWulmXLUJfbSLlMrkcQyVWC6Pnf44fnoIw+jV1sD06xswz/bfT1+AK7ocGKUoBcEWZKV60gkz2YpEnkLhjy/tp0UrRxAeZ6C7eG2icMg9deROKJxBU/cAUz5QIbF1dHugnmjUrFOrHqdHjXKR0AzgzcQLn57HRLdbJHtkcsDuukI5Iit/ns8vu1ZfUVKbOjifu82ttgUKJ7ZjSsAq0nR/dG6UwXFMgKJByC597JTMz8CSs8oEQXcUS8zMGW+l8whONvPskYITWvkcZZj7cpuX5yizZDeuOnfL+GUSbhnPIbmsoY4nfweZsTDta9fZaGZMGCvUb5YYB2em5PQRv1AG9YLlvqa6RW4ZTFeDZzFVhKi+NeWePInJ30dplHRilGbHx2TwIflgIgkv8hYoLVRvyC2zhGGGmWOJ+m2IsrxJNAX+UW0AU4aT2ejNP6Wc0F1aeRYyWXnJccXR9d3oHxrV96TLK6NjcQujWnv5tNQ2HHCJM9DFaSllgqjl4DJ57plsc1R5keYCizaXk4rmShJZFybqdiWReYlR3EsAMEGdLkBFMv2QMylsufehowOxhK55aOAP4w5HJkIdLoSmdcVsl24uQuP+shaTdMFJeq0Zr/Fm5R2zq8FMKlx2e/vChS7lHZrO9dZWUh5X3smsYOklFa233rrJ42lV3nEtXNhut7tIBXeF8idLvdsCT7NT8DS7CeNq3unF5bl3YhF98LTHg8XC0wwQqaDyluWrxbngIO7VHVUz0tKFpGoWWguXvUYEt/WiKWxtTiLxp+Ja+lnMPJtJUjuS/SOeuckbVx6JfxTX0s1q6WpZTtqR7B/xzE3kX/ApTQ4R6H9ME4p6w8FoUKBv0Uvf3ih9hz3BqJccF3/xm/KtFUl4P/vdrGNS81Pxp6QnCaY0GNPaF5M/7+mj/IDuSrrSly43IVnrejGqRDSqKX0FlqpXzUasJvrFtStudTEhXXJHNyrpJtoz6LChaX6j2nnOMrs71p4v+YpMnfN6Y73t7vJqkGiCiZit7foZJYKhdjW3ps5bbrNV2p08Z8yr4ESjWF5QV2vKb6ovr6h22fMFjisq48uMxOQdJGslb7m9xGUr4TneUGybYZherC8IcLvmbbzqWluRTSrZd7W8eEGjs9BiKy4pqwrP+nLBw11ltspV3GBVZYHJ7qwr8zasFuIVjoaSfEddyZwqm8FoLrCbSxy9S0xLawWhcrV6a4nL6vS29xwverjTnOfLzelj1TLojNdYgx4a94G6KroeHk5khCZoYH3UqhkIJBLccS2ehA6tI9QsoVprTp6eQm1HjywoKGwwhy9m6OGf18oPcO+Pve3idiUyAcT8siSAT70pyzm4W3Ln9bMmuTEcBtOkA+anMnqvi7+STXSi4ZS77xeddT1Prafc/EImVXKnS/d5NMcBocnPVZX63bFSzc+U5PK0UFS2QQLO+7Iy/0l/E/+ULh8wx7gag01bT2LieeDhLg6XUPm5XvJBXAmZ1eWMHyj7yUlyR1i5YDOb/cGQHz5DQf6puGJVwmwho5lsUfYrA+QOUKwu2LRb4FMbXzW4zhyoPjeAbAaQjlyQ3GB2GbmQarORyGqLKiqbojh+azaJKtjTNcfymUfpRAg0PAwEkWiY7jKGr4Os+mhOsBpWqfR49vT+/ul8NX6OvT2qpb3jPMRGo5z+SjOIKX+l9W2jPxZW7vrMrsoHHmBf1ETjs/Ckvq5Pw9Kn2mlTYUVmMkwuhkcZs9tYu4eg/nFdfZW2O3C6E2Avs2Zv/nWKPFHkLiJPpJVK3OO8Qh3fuMOkPC9P+ZMaM3tX6uvcyj8rt2dGP7W9Gbzy8dDUpPKM6FxA5OxUUMCayhSvxueG+G+C3PDR8T29w/kUni5qdEe1HeBFcgOdxhrvMqJmt7rrObdcZuvhZE24oCuO2sjU/NYSFunTuJTTFUPT2VrGCZh0UBxxt0JMfhj2aQe2Gpz6p5hJ3O6+XKR695Iu2VVXyYMsw6+E1FvPkyZ/j8SfnoAahqYXBkRXmc0YYF/kLNy5S8aHqD6YpLGb6Gmu1dVpuLKwBBSwZkwN4Jd4GthNM5SAqomB6NoOAXwOrlT3T7b7OZctNdPm4vztSTQUyBOpVR7uKkVhgSaJ8GCUJ0eDq0P8ITrNEJCVdnt5uZ38RA4w86GLhZvQvWTPwo0zA/iMOreQi3PoUzBGQ4xuvAjvS8L2tnTal9FPRTT1JsWRO5yNI/Lig/ob+NPAi37UjaK4CJIGednYHI9dUPG0ZXcxT/aPV2Vode5qOfV57mk4OKivsKZmQJNmdYfOzPF/M3vjJGDtEo1GpdAKMv+FTAfJ7ioT8SOe6Di8whrGU+JHgty3y8YjByhPjh90nQxiIkV2rHQK9NRYD9xX3KZGRel8aqwynZvGOQhQr0hWDFAn8ajJ7rjHRlMnR7c8Oq2Fr26Z9qjSk55iH3talvl3ZfkbV8rylbirhozSUh5YOczNzewqsZTt6MFn4aBGNk+CweQwU7GLAILCUVf8uf6H/D6coURb0Imb8GhZ220gEoq4ZKFD+L6BGFNJwZ6X+qmRGL4vOPibCvKV0TyrkHooT+CuEqx5xJhfQGWrVl7p5CU6cafqqYr13Uv+jfzbvZOXLr+kcER5SdM/zuqP8HeD5MCdQ3QVIA2EAg6zpGCulCguFhPSPRDXkOVszJ7s4X7Rkzx37r1fvF5YbxUMr//CWl9QwC/jKm1jI7ZKbhlfbreRt7K4Zm7qN5z3TtKh/JiI9xKfVSg0CMpb9xbkWS0lqX5bWZmNe9Hu4TilMJuDuDSemNlUZ7sYftkjz1cuGa9/v2Rk+Ky4+3y0/XEWxOqsIFEQBsBGQgE5iGoa2hFjpTJf/fV33pkGX6dIv/LiKejQx5SfkdCNpEH5VU4Mf35OSVlF4MO458pIInVSl71HLNq/ZuoB9LNnMUlDAee1BW04Lx5kbeSVxCBO6NPUc7RY9NkfW79+6AtyggzK6p64sqzG78MNMRn3/SNHPwHGVvaQ+zDB11E6YCZlV4MLPQ9aXKa2V2054NA8iYZsDVobiSABTr4ga5lGONeJAyfcla00k6/Ie4bmz9/+GZncM58pQqfk+fkWS/44FfqvGCn7858rj29hutCJZMBit2Tt7VFKo8mil7umhofRT7SGnZ7wZYSCHCFncT740hfZQOUlyNnEaFr/13B20Zx+U2GMG9lJvBPE1ZTIJXHP0dHkFKhwh+VR5cRoIg33pP4A/yjNUz+IawOpecoin7SU8Lh8jRjpIdushtmwYLBK0SpC10A3quKAzjuAOMVplg5VODRSrYL/vd8aDK3esHP72sD8r68cXHT17B6TKdT7mim1fqortxEbtjtL3FsTkA8qf839TUxrfrhsRSBKSGh1Y5XFMq1n51X7D+6RrvkLKZnqylvAJJRhAgE5c5jdBhXAMxhnlN5BnQVT80E1jJNuxJG9QiMStXnVTYejuALt0mqE+HtXrNrAGrHU0XTXQRritnz+3Ci3faorSvDTqoQvn+lhEVrbFs2b00XclFerq2ek9uZcUH6vXXh28grhc/pR3+X2Ipvmikc/eRCThjnRF3MZXeoRFiVzK9vQ8NbEZfUt+AvI7Ek5O864FEe3qXsXYsuy8WtO0+BFuloogxziOgWC5Gwak0BW/t1M3WJc+OXWLi6fFZzRy6jOXRfgb2ho6NKrkbuLPTGUU3+VF6u/i6E0MjIylUxKwrWJ8mjOPyCPnIbJ+e4fET9EHseB/4i4+dE4VhwnZxb943JGmpzSf0Ss/GUcoZcvRF4ZT+Y4+TH/H5EfbhLA5sWt9iQgsYtDX6vgrzFeBtsXXriQ17/Wu7J6VeuMLV1CMCh0bZnRuqp6pXdt/2VIlLNy4wz3jBopvHa6PH1tWKqBX7lyJXKxfgGKMm7rgjOwmNrezeH29JIRlNWppctPp8Q778JUHck/EctGOTtOqAgsw3q6M1MUrHyaWwjq1IzLnHGhs9U4fgaL+23/vkCqL7Cv39re115ROHvZ7MKbt3Nntqf2Zy/jsVt62x5+uK3X4qqpudXf1uYvW5D6hCMLyKvZ4QW58/82Gr1Is0DVGDEVlObpLCMafDdhq/C6iD44+9QV1vZYu/WKU7PTyZIBdvzk+sJZy2YVrj/J/XK+XOL2et0l8vz7qZfs96kvUo/JtpmLiv0tLf7iRTo1F5eWW6z+0rKLGYJ82Gu7tBxjZPjguYPnLjHT2JvKi+dIf27OsxK09SZmHDOgZ9w2ed4xMgwgJ08+9uY5BoKnBvgxPgQSPJAVJewi6ZzIyANqfLiNrYJ0qNIG2QVXd9XQ6Q92GnstTRYLL243C9Nn0fj337x/3gI9O777xusW9HV2L1m5/sahLfv0C6678e71K5d0d/bRk9/JHPKhUsfyyPTOZOf0yHJHaZ1/dt/i19lx6qS3pr3CG3e5rSXuijUtNR01XnK+xOp2xWP0ZNahuj4c6aygHiQxl7zsDaSmjJPWPziBkLcpfak3s+h8O3NIHpez0N7Fjik95F/p177MGXao6gAhGsdr0aJ4qPcSE+wFBdA8DON+kycTaowuLu9iRzyndCWoJTE6msgcZvezAuqHzyor51gtk5zXQhfUQpRh9UC18V6GOj2kc1MrM4h576kyiyNOWlqAjMZsbkEaeMJr252rqw+CYWAVH3R0NEOj6Kjjhci6SMUf1PgC+Q8V8JOGovwTurpZKB+a3BURaUdbLXFJ7bwM74pm/lBk3c5mOT3rgfnYMEgFUSZnlS7ufdxJFe72TTcSeDgiCRXUAaXPoaNFN/PTqYBK4i+fgumynLw8xAv56smRzuiKTp1H10R3SqP58zDFLy7Jp7mSRC+gTLcWt2LD+nAMFanawFyoTi/L3mAUMAt7UIQBl9sNFn+pY+MRZeTbFrbJDlmJ7u7UyXopNn+3u5qcPzS8oz9WtBVdXS8ProrepozIsSuHyJ66/vqq6eI6edU3LeoeO8kksAtpCqxfvmT6TY13LFuxlpzvbN921UF0nrU2L5VJ08H14chEevr+F/RQHcnpsTovnxx57dLF03coI/tim+XLpkfy9e4gTfuWTGvR5gSC/GmdQGd7qNeVeZ4E5iCbGJGL8YC5uxqEcX/zrH0MsiYGAtwZpTDrEvdC1kYOfdnb7rAA5Oyrusz8CcMP509UrDwTtqlnWNsmYMY2LBpOpMP8cLIivRdCLlbZ+FAclPO5CKEseQza/ys6l65Dt0a3TfcZxAnanK2hhGEGDmgUeIhNpod9F79Kkz0IdMdcuvuyn66qxG0R8SbiyaxTl2gxKPSxP3vwBhT3nTiKkSeBaXiBWPPM6QPOP/Gc8qLoMudZicDDKfVA2clXp3XFgOiSfJ8dwMA60TXwWZ8ElbbX7nZDQxoEUmwuc7exZlV/BS5yTSYusc1dZi4mgoGDggnc6VJ/Bu1uxbdr/dpwJBJeu/51tz2wdd3gYakek6W57A3S4cF1WwN2F1Hl3mP6rbTOZ+gGdNd/Wo0T1MRYvdLFqkbBgxtasw6YW9/Gmtz6FsYX7CbZBU9Sy8oI0w5ZreFyBqw1ZLTx9fyziQ9ftGqVFwG6a7KKge6WW7OunIqFenPlFEqyYLCx9Q2oz73Q33tpxiAtYyBWi2aOUlUqiMIKw+1YKgmcn8KM3BIzBtT8iXAHv2z+zbX+SPPK2WuDy0tLlwfXzl7ZHPHX3jx/Vk+koSHSs7svvKd9ZvOStrpl1fF49bK61iUtM9v3hPvE8nJ+76Le2Mprd6xdMbvb22Y2t3m7Z69Yu+PalbHeRaSqvKGhvHrso8aGtZvkne3rAkTCAqTQ2vad8qa1DY1FFoua71aj6dIo+jSMLwErVT59Q38z/yXqRce8w7gnHN3HVLKRKG6DraY+ycQh+VswqRp6BP6ZfzD+4ivKQMBbG9z5LNl4m+Kudjj4iumi3RNaFltcI1bOvUKWenvLqnf3HGhrT8xdwH9xbHv8zCvk5Iyj/ye6S4krj95G/uDbsIEEps+fm2hfGlsiXbFlbqXDO3Oms2h3nr8p5LGLrM01PMtysDQw9CZFiX+aYZL67qTQtzCQXG8ajMpbN0M7+OnusJO1RAsJO9XGCLDGcOYyVTdxRjHySaK539ktGv/xO3LabXV4Y9+qpvWdBVktNyuLx4p2XZlo+eNT8LG//QbKbaLKiePbN+ibHVuzicgkEMQmrqYtLKeZLRAgT40ukr8xupDIGynXFaVZMof/mqfiP0pVGKgSvBdlRUbSey2JK5/6I3z8suAiTKkivXD0G/Ki0afagjnMmYlvxpwxu+gOKdQjowWAOWkSxUjUw5wwYZqsh3kOMW18dlrjtONmSi8BGrqa48dIZyJOn4hNj/YsjixvNOiLxfq2+cGG8nBpZbHy8hfPnCHwyMJk8jFHk/TTslxX3+aVy5ULk3sVlHfDW5u6gtHINHeZkc8rqPA8N8fTV11bF6v3VnhLRMGQbyzJC7ZXRWsW63nj+promgVFnb1zcj0rTQ3fmcLZWd453W02l9orbGJlsV2Xvc6GBztnmi6i62Z5WKxZaWRt6qLrqFNgOXY0ZYnmx7ZNyC6La8K4M+lVx/0d8bn/NDfeMTc2p6WsnClO5WUtc2I/E9WtFNXvPcoJcnajttB4I9kEt9Mb50IJizS9fBEtSjmTvR5VtZ8f5DktLpJkdpaVvFpsfwfmWaXR7tTPL+BkV5hF3BNP2ENsLL4/GUiwoP9EgGxIHybVi4Akrp7icM863IcOQwNIE8bly9pGtDLdx45uapde46OtlY6AdX/l5a6TJjSsEQZpm5POyTXSBNM4mUqdD24YfpEutmwBqJT8dAtqKPAynHHKecnkcZny3G1/37fDWlpqnVlnMrmrTceKCck3VVhMeadvsVcKJuUwXtx+Z0OeyeUxlZSYPJexfjr1cr/ZZPWYg8VE+kVpTWnM7LGazCSvoqrcKT6W57EoPy+XrHDhz3MtcMVSXW0xqePQjfow/6ouqjuow0RvfqMQseBUO6ZQ9bLdIKg07SJUmQmwLFzqPiuaD9ov4T1GrQ9rx/RVI2lWWFYsKAyrEdYuabcKvGgKdn+0i4s6BCPfb613c8Ymaaa/wOycJjYuLK0iJNRS6xStxZa8Olf1/KpKn8liMZltotdenJ8fKK8kJF5e0VYfa7TYvA43If6KplKLsajM4y6prKj2ljrNIUt5R2VxZWmR6KjxVLptVcEqL2mu3R+r8NhqywpLSkvyy5rKGmxVjc1NxhLrzLUNBquF20hMBYS3FhXxRpOVtNRHly16si9Y5iB6gbcK8FfMC3piE0Ou6jxT68ye+deuz9/GF1d25xVXSZGu+e31LqtBdM9oa3J4rHZi1Dv1gmAozNcbCRFLvM6muRuv2nz1ku75wBMGcwFvNOhNJcaCAZ9Yqp/W1hhrIc1t09j89xv6Iv4a6I3bdAd09+m+pDuN+TiCqlymS9xp20k0vRt6rqA5o/+ftjcBjKu67ofnvmXe7PubRdLMaGY0mzTaZrVka7OlGVu7d9nyhjPebZAwYAK2IcQ0wSxxQiqgLCEmBJP0A5wF0gSS1ElaFbJAEBQobXFS2oYSSIJbqOJ5/d/lvZk32myRfLZme9s999ztnHPP+Z1mZabYOl6Ebk+w1ZCzLmkUfAdurZbS1gJpoozUUkEbb5eaEFnmibsvSqCFLyCYA5wyKPeSIFcT/2BpNwPO+ncbjPGGlQPByvq6ZoMGaBk21BRprKbMIZ/OtiRooyhAUzYvF1KyZrWWAfvq+kMejU6jV6poxlbd3dzu5R1uT1040+axmu3WCouD09c7G9SMwWP1OyydwUiwFqpxaksyYrcoGb21sdpu0XDC76NmA0v5eEe0xsoweiPvFN7ha3i+pha9vRyucmo1LM1wGoO52Wkz6ilWZegEGpOaVUEi7ZYKE8dWR2ubG+hKm87m76o2Q1IZyupW1XldOiUNwIG2XMCu0Zt4e1Wlrzph1nGwNWEzq/QAMEqt0ekOdy4PRFSs1mULhLy1sD52nmJirnoAzPpKs7uhImQxOq1H2YC7wZ40mjU1zQ6Xs9JgtnsSbQm3G755/k1lt9ZUu4xWk0NvZk16J2+p9bRinWcK6pnXQHk2DdfvYYRaA9e9OMr0UZyiS1FZS9H8mI4DHzLwmJG5x4esPFAxZkkeDJIFwyf/AW4+/dBp5Gs/uhdKSo3DTYXryOfeUaMnSvUUrnPX0WE3R52En7GCmGIZPCrCIuw6fdrgjhpHG1c3CmPkRnAK/hg1Rt3Cu5EqThjz1NLhKhU45Y1NeGwkshnF6UjfFPK5H2Weq4Wz1zDCkQ8gRxglATkURb9wAIlUYTjhE78YNHnF0wAHiYlyh3XeLEjeK4wd+9yPRGqjn/+HPRvWNsdtfxuq3gDMeLvYBEyt3UuEozuqDnWBvsyGTbs2DvX/Ye5loeqxjhSoXLNl+7rV4xWqTGbj5r2dbS3dHakkVYWT8y6votx+H9jz2JKe1Q1NNYGLP7pkLqR7FTa47l0l5b+asbSF54XDQLJliktwmUAGqathabqAyiredYM/0GD3FqcBpORi0Gxx8FLjc2y0zgOYkQN6n8c0cLdvGV/lU6o0BqPNptHSjHXZYHfO6mhSUoDlLK6tG5d01S7ldAYjHEBKduv+7iUp3m80MRSdnL3YzZMnSlgGqjJxUPXjWzdxWgoOS5XGqtGpdJxKQ9MdfqWSYliV1WLmjTxnqG3w0DRDRRtcNovaYDDZOAnr4Q+QtxvE+BqC+0Q7rLQv4wvSASvwAdpHB7kEeOv9jb+7D/zLiOAD//q7J38nPAi2gOwThWufBBe6bqF+IFxxD3hIaLo3D993UlThBeFlUP/ImEKO8aJTVEJ9J6VYrhiAsznOXYczL0Hh2gFEIVuUjqVvYQOw4ogJIpPDRmfRUXQbXJSxhR/N46id5uvVjIKOBGwVK7fpNeyB48JKg7E5Yh7pdJhTXStWBoSHGzM3XVObsNsGr8r4Gq65i9ZrT9zXlXE6wIcqvStwamfUlbhh+eBXWwf1bt/afp9D/dt52v5v2q5s5B3LIpUOg84MxqyOXM4TSFutMadLmAKszt3b73OHPyP0NTUeaQCV9pBBmevq+OtYU35bcldtNBRdW39slYrRabZsD74273AQdWk3/VeQk19QnEYol2IOAwxLieovLjx+0oXTqTRmTSNoaib9HRkFAVk54f+SpILHBQZ5LMa9OEpLp7R4wivxwEFIzCgyRlLhJFi3RDxNo1gYBwJAUIbCzQ2ACrr5J3QGv15fuaZeZaZNq4LNtXoToJ0VlnSAob2U0aQzBz5XEVVTBl6jAUsqKaqqoqomuVmp1pmszsqupZ0xtVZr1Bo4zfLWaF+A90eaoFSjUj8Qtkec1epqGmiNy+o6fF4QDwZCVU5fTGfnWI5W29RGpcpgdvLBfmV1tIqiae2gjqaoQzaPUbt1RaUOztLAogx6DRY4cADDaiobGtNff8RgUkLlyMX6XCzQ6AvqqnBlq81BK306k86qMVC0zd4Al02nOxBp2jOytK7Hp7dpVGats5Lj9E530//3rd1DV3XUm1XAZmn3e9Jmp92oV0OxiWaVGotGa1RrzeA3cNA7TYySpVRKipX2CJ/EtvMmxSo4yxPAR3k2Dshac9FBGmuoCNmedoMEF6DnndwfQUZtGZLewzvzeZbR2oLujCvs8vstWvqYKx+fu3M7sDldDrC3fkwHovm1jRV2W9BmZCjldkZjrfCtzQtj8/ddtF4fhQz4uQJpWDimFHBWBFql5GgWTudB+NWIxWcrZ6WBlQX/fjh93a1K3kKdBKPOVicY3Uq5tbft5zxc35uPvQem2oR/pgZfB8NawGhYre7ik6+bTK9Th41qzYm/1+uF30+BJYUPwY+Fbc9I+9L0tzG2pRrtl6lBQA0SIEyH7xTeBpXozXxn4YUc+HfhbXSA+lnh+RyxW3ybCdF3I50hiMaJowFZYsSBFsIjhMxYsFVCRbsBbIG0JPNzZKDYeQ41ihLl50hlkghVlsiKODUn1Ama8VD0Y0FSiS8kW7QeEkaGrd/oSrxdC9bbHA4KmJ1am8UQslbZeThweIPKHKVUh1uWJS1+lYOFAlx9avnJrlR9tFrJ2tU+S6qt5bAGGHmacfCVDRVApzbRLr6/oamxQcOyRk0kZXW0f6bdbktFNEaW1dQ3NNUP8E7KpFKqXPVVNidD2Q09e/RVlQzF2xkuFDZzaqvFR9EVJqWWqaqs6hs6uWVl/zo7B+DMZ/CbTH6DjoVCIb+uP7f15FBfVXXwszRvtAUY1hJ2PegKqAwRL61yVuwYysY1bn1Nva5Gr7RYlPoabaxG79bEs0M7Kpwq2hsxcBbe/qArbGEZv81op+Msbp9fM1F6F8q0Bnx2jK7MlSd0Sciw+WSmGnjKR90Ivk5nO1t6BzZtGO6/IdjUFLyhf3jDyGDvslWxlqXLS8aEDat6NmuFZ8Arbs/ux5emKt3VnrFVO6Z2rBrzVHs9S1bVOZxFg0Uk/Nn14hr7JSZDfxWvrg6cyQVh5JFoQZQvgnjPckFgRkkxM8CROa/X0dUWrVapu/iWJaLh3OCbbwG3sBGE3hwa+qxAvbWMflQpNGkiFh360Fq0Bvoh3l34zvlHweOFb4HQEPwHIueXFWVHlBdPh1GfNyg+Q+waZAsIGauJ6kLUmKCIlWYP+kkcJH6TuiB+S8QlHQl32xCGRiZvcQecc2iHnYezDpx3aNgGUBqDzUDDWsKGgE1Bw6YgG3lSena8a/RZ9AZuCyaC8E/43pbldekab6POAOUaQFEGXaO3Jh3t2i4e1xpnHN9Z46nN7u6P0OgwHenfna1zh87NdZBqFcstbmvhN30FKjg4djmFyYnLX6I42UEpzjAp+lFjpLuZXtRo3xBAWTUhjnsSMIp+i+sxQhWFp7B7mEOJcuskO1AqMdivjfA65EoFDxXNaedlHjw56tnCY+FlllMtrFqtNFhNvCHYZvmUyeLxeUNOl8rJmDVqndZftTIUZl2Mk09ZmtYbrUlvMLTB4fM1VleXu2djACFh6SPZd3ijRk3DhU1v9tyfHQo4Kyuqmqvco0a1Q6P36XfXBmzWLXqTvWLwHzp8NdEaG6jxNfjgH5FnIGO+QVcpTFCHy6G8eYFi0krsMxeUPFTQDrA4fsVxTJXOhItRtiKjmGY+ubyjfsjvcVpWDnYsWdoghEzmdYmtV3c2hG2+TG7j1cd3a3Q67a7jV2/MZXy2cEPn1VsT68y1Hv9QfcfyJF/RsHRJx+BKy9SKocx9yxNB+8bhtb9/yOM73XFN1N+2F3jzNx7Vm836ozfmhfN72/zRazpO+z+VWH5fZmjF0O/XDm+0F9fzSjj+Vio+jbI3yRZztxgwLJoymm1yqxJJioerJnIj5ZAdsIpCF6yxxDBimipGGadKOJduIJPg7PRfwBZKtnylJVnpDJjVRpahKVbrMeitfDBs08DOyyaibSmPJ9UWTbCw52ps4SBvNZh0FhVL0QxcIQJ6q9FldlQ39S9b1t9U7TBD3Vxv10ScGhZO+RUaS1U42jf86nBfNFxl0VQAwLEaZ0QDTm6uWr1iVbShIbpqxeqqzfWeeNhrNQEQ5flwtMGnM3JqJaOG0hkU09CbmlGqOaPO1xAN8y4TD4DJ6g3HvcLnHXoNx9C0Ukkj64XeEY6pa0w2p3fZBl/zSs3hLduSmUxy25bDmlWN/g3LvE6bqUYdk+SrnzF5+kbFCsVP0B5pCslXIbyvwpHdOq4k69odvLgBgPRoMe7bITMFpjMNIBjHnTAkSWREbIbLPS/2TTJuSSi4ATiaiTztAaXdDyXKUhUqfvcXhXGsshYF8xSRzCEdRT0WH6IraMrudHVEV9dX8AxdwTC822QwuYxmvSoSdrvsfq2zqt7j0PrtLk8oQqm0JqPHqWc9DprW6QoFjdFq1nCswxz0NaQ6rxuusdpZpcpoUrNqncOodZoqAK8xazQqg7sm0arW6tRGfyelZBiLxgQa68wWvZ0J2EOjNbyfs+st5pqYyaQyMjRHtdcYNVqtenWb1w40Ssas5hne6DbpteD/oGoZa6putjsdscqG6voNEY9KlV7ms7sqLUadETAqVqd1qUxarZlzaXWwpVm91mD2RW2GtgzkU9ClVNObmlobAjV+K9/rjzQsybXTNMdQlEmnt5m1Kqhaq528xR7z1GqAAc5sas6koSuMZgrQQM3RGg6KPRqTSe1kTZyG5lSwz9EmfRWtMXGojnrK2F3TQNn0WjWrpJRqi13DK5miTSIN5UiPohNJ6cAsFyvEoDb7UmBGmwZtgEt4KAcP28tcXGfFdFSiH0aATNb+ENXlqd46PICwigeGvwu/NKzeHI83DjZ8a71m6eiSvu7BrqtOXLV8+VXL9fpYXyzWN9JXdz6YrKlJBul7hR8oG+sHh743NFjfiL5s+64fOBtWN8Xzma3tmtXa+qTwxeVjXV1jnx7rGo71buqNxXrrXXjdI+OiwOyhexQBxRpx54OzoV6JxFAphZhd2mNE/Y8l3roJdBAn8xTVwwaAEw6Lc1IyQ7o7nQgvj1AW3Zp7P2evrT2wUcvCFh3uXXJkZFNj3GxzB4V/BcvHlsc3+00eqycE28uVbR/fddNQftsjvnTL1hQXr2711YG2m27x2/U89VaoKzykswCt7cgNoyMrMhyce5hWRutcvmL/VZ8zOtwW+x1dV3WGAoDhHD2VQf+3T94wlHWZ1OpMgNHbQ2y1J9m1fs+NX/hiCs6AlKRb/5q5m84r3IoRbGtKYqhv0Q8JzQ6IEQ5sIIKDGk68kD9oiOJtFWyCJpMAcfYm/t5oSHtR6jsluRj1CTbtSJNlm+TbsZF1jLK0HepWr2nv6lvds2IwqbJXUBVtXpvDWRUPhz0eR5Vrh1Zv5oEKaHW6YDid3LzlQH7juiu1605GotVujY1SAjPsrgO8w+p0Lj+yCWTrItpqNtjanLwh2dwKP9osFhACVNuhfmPr9qoqX/WVnavaVY6WapOWpemtHMMwxhY4h7tMm8zVen3t7syWoYH6hkj4tnVM77K2XGyNX8NX5fQ2KNk36GiarhswKo111craZGwIJQgf2gQ/KCzrPM9cQR9TqPCe/3rUp2bu8SE1BrNS9DIlPBYTWEtclfkllOu0mPsceL4yGEyHQiBRGQqlg0FhaY0nG6jweg9u3bRv36atr8GPYEDjcTPVBjNfAeBUYFQrG5yucPC2TVue37LptmAYf90VClYFveCfg/Ah0p9wE1z34DzXELv37D318N89mxI7arXeNXX3qCnKy4/zUaOGS3d2ZUeGB4744L8jA8NPoq9+llFaxT71X8y99FaFVzGsOIDsNSLx4uRNNhvIMoNWHqIGNkjIIfhnEm9WGIAkiifiReEbLj8ErATt+wf8ygYgW4EYbSR0+8jWTxydau9aN5i7t2NFpKa/pc3jMy/11/yLgVEZVFy9LxDRqDi3zQi1OyXHO6ojm6Kd3TvXrN853N+zJN1eHzYZwAgbiPJKZXpLmo8EVHbe48VBt6C+fWnrqKtyoDu3aeUD/T1rWSZU02JXq2vru5y19fXGGltAp2Y5zsRQgDHrAxanF2o9QGdaGm37ZDyzrdLNW/zVg+HKOh3LbbbxmhqbqwKWonZEAgyHY3rDeG4ifQlHsKmltofsi5PuEwwVR6jYe2Q9K5W83L5EvyrY4TpgU28Dah170GBQq8BDmdXrrzhY7ERA1rsKay+nR1Gjwn9QtPl5iuXUTJ+KfrojEJR1JEOxh430Fr53Wb2KLtqIeEWT4kYoM8tt4WQh8iIe4OlodlVDYWs8QdQ5AvNDskSSP/igRHPaEfdKTmBkTw1+BpQBmdghCkPgRM3W18vs1Wm++nPdvsCsveLum1pWQhFCqYVrIathVRYo4DG0zWupqdOzDKPiQoDTscwnGCWglYxBrVRrrXbGpHIfXKe2sMurzVUUXNCVqu18usxI/vrWmus/91HLTd2zbFcBH3U/FD2ZREJnVGtsDKviWJ/HXG1RQhWNa+QAFaM4BqjVDoPKwLGsUgMntapeFSwtF/Q3BikVq6YZMoafZzrp43BtrEU2hiAXJk4rogkOB+jgZAAO5H2LA8vYDM6jTvvMAS4coD637kB1X1Uwlq33OZsrK5m/n4wlhpIH6ndqDb86duwasG3J+sngbeDUxLF431+kz+za7A9Ec7XV7taO5b35ye1NGzp/am+szU/mL8QQXhY1UuiWcG+h/rSbTinCcGxsIXb1EEmqQPazbZLqbq8ubnHCjoKTbnBFJZ+0LdHkYRMX90Ex9BMRV4GZpX9LGzTO/n3Ca/v6nRqo4LMqFcuRYyAiO7bZoKQBxSg16mRN6vF1vcNbcztDNUk1lAGRekxOhHbmtg6LZwqTIEY9pDVJjzRpnUsGvzO4xDn7UPOSwy2NybZELhJMa4ykHK0mHYzkEm1J6bhWKgieEVxg25PiXHyCWUG/jONCmhQKFki7uSLkFQbKx0zAXEGCTxmKAjUunJsZmJGbFTBSCja/EbTPDNbIzYwZ+QjcPgNrRaIRZapWzyQxKI96p58Uzs2iSDhQIuBHwrlZJJyYib1S4kmUxKqVc4CfxSWAPczpvbNqPps7wgWEgAQ0s2p952zWgPY8xn0r8QDj9wGErpqyzuIE9UgexLrnYAAFpoXTeXRiVhn42X/HDNG34Nw9aC0JG6kwF86EO6iwwwjgMkF9FZzJ1kwFclMfZT+cyp2dqtn/mztBT9U79KeEkVzN1Nnc1IfZj6ZyAXjinSrhe3f+RvRtk56rKHtohhksf1oOvF7+lKxopyN1tkPps1GxBEcBzGgLMSsKiwLN/Err7HaRsio75J2WvqrTzjsIINxfOB28vTOyovuh7hXCtd/+tuuK6654YI5WO0f2r/mSnQ6YV2we2bj5VtSEt27eOLJ5RWcI/jv57W8nOjqE2+dozTHiVpWPdhODW3e0bAzaFREUFTtPHenZlbucOr06V10uWQkhOQf5ull038s00E9AqlcpNiDdAFEnhnQ6PKW80gGfv+hShLYurRkC0eoFmTAR1FB1UWWRsQGuImUeJMBaH/vS7t1fitVrr1DSzDHWpqbpq4y8IPDGq1Q2FUUdY2jlFdreKA8LpzwZPtqcsZhYtdc73tc37vWqWZMlA3pKUwA4fuzqKx+rq3vsyquPtS0dVZpV/6ZWsoAeMxjGOI5i/k1lVo4uFd6P8A4HH9mcsDS5EokdIxtui0Zv2zCyI5FwNVkSF2ZidNzL1GNepNCOSOqyeJEpm7pAwCTV1LQLqoI3wppS9Bip6RiqKbiRpZXgm6WavLuy79j4lY/FYo9dOX6sb+UmpUX1M6iaw1nZaBznOJr6mcqifLccj4bF+Cq9UHasg7R2wJb7hEJhLe5VSjY2bFQT9VooSBLvIGyJy2AzD7LM4ZBBtC+TlhbK4saCvSwEDbLDA55vaFu2e++Ne7f1ZILegLNCrVKqowackaklvWZ51B+udKrVNJtnAK031hosKerLLKU06v0GU8N9XT2rbsuk/P6drc0pnLfJaFn1lXB0+5qhxkZ136+pjdv23rhv17K2ejdLq9XOyrA/unxNuuUGeKzdEIVSkrrCGfAGM36Twa83KinWV/iW2VBr1NOAiQJ/KnPbqp6u+CqLsalxaPX2VHPrzrXqRvh1RyRy5NfSXt0PmVX0UYVGkVC0KXrJSEXcgEwRnSOIwxMSCMkOc3HI4k19EUUSXQs5hnbuMx7aAW8AJk5VU+e0+l00EvXYEEup1E0BT82SrGNg3frTHe01Wg8D69Xk9wQ711iuHr/mr72e9RU1ZrPBV0GDQvvaao8rcv3dD/SNHRqnvq9WBSo5QLv8BmGtWr2ms8YTaFKrKNatrWnv+PKGtQPO7JKgx9+E2B1SV3m8X792/IPaGiPkfIXPmlk3fuiq3gfuvj7q9FQTrEn6GYwF6MJ4PMVkh3XAHLCaRWyTAIiBbSXgoel8fpq4dtK7i6BFwhQCFcewoZd8Lj/3c1GiauI7WvZc6tlJ2fp9D5T/noWrWRj5rFrNGTZjxnA5vJkNsmSHieXCM+ZTFrvaGyi743wBxD7s0lgZSjgtTAk/Qd9QvH6rDf47PNTfP3QYfRP+cGe4snJgz56Bysow9VThpoMT+6lPVTEqNcsWlkxMfAZ/w4H+LcWb8O033xXCd8F7Q/I97i9jLBmyAswkOINFDysXJiCGSnrvcpeDP1ZO5QMmp6vzw7NnzxKQ0x0+H3isa/OGkdQsolasW7uu4yPQDi/F18Gr5XmZDyhOEOTP4ryQLvkDidvsRVeIZg9FYmrT0mRedP8MNxfnDdGGLAnUkurZTFxx53UQX51ye/Ae+/AqGip7lu06CrCAUqp4e72jUqPUKrU6zmzxGODhWrvD67ky12WgoPakNansfnOVmoE6jFLPsRTL0KxPYzarbKBKx7M0gOIwLMAx9xY/9TeZ7KohvMXvcVWZTbV5vVHrY00qrUrN0ZwWLhtmlZJTm3mzpkpZ6Ux2dGZX96680huz0hqb2gyFbZpRuvS8k3eZVBa1iqXpkNrIUgxQMpxGBYnmtTajrqBY2LdF8nHuwBFM87p1NTWjOQcfN4pAEZDh2O4KW4SC7YCCvP3YUQj2q2YxCIc0oOQvJ+2VwDHRbC/Cvc6fD6lBq9RUOurq1EqaYhjtdgtHK5VbujSAMngsZk6n/fn6wb4WI2wayAyW11UBm8ps1vhYmoHNwenhqgsYdZXZb1eZtJyKoYwrh+bzei68ZVZqIeNNGpXRVOnS5Wst1urKYF91SFmlgY2g5pQqM/ipz7dUU23T8rB0lYaDqjNDsUZ1iKZZldqiMrlgc+hdSgY2PmVW2zQU3xRQiHlTd8G5iGSoiOFV3MdjTyI49qxEYHFYzeIRK8ZvDvvm9tJ383HefVQX91BLPHHdUfwzjmFRf0MbDhQm1d5YrD0GVW3ymY0TF3zgq/L5qoR/FV3yT02DbdOFN9AV0l8JV3aXiP0bwdr3ApQCH+2zSlKwT/pSpPK4NuGl4t6E9jj+WXDRlrHCz5UigT1lBJ4DQ+6aGrdwVmgXf8dmkEdyqPdj30QFYPmg2cGHuVTGzKaCZsQfnnoWuflPnD8/gUC24D1UWyF/XLiwti8e71sLdMfzBWBCSSlE3DyCsYXyBwVlSOjiFjFt9pnVtK9MDn6ymDGBjyMUWgQeJtxH3V04UxKbPHIsBbi8XCh0gwtCDl56Hzg1UxckNHBQ76rBMRwI61MNZFRgzE85CSg7BHgJQcaqpXTeBBACxzOIz0ew6vAig/A/VLgU94oAQmXCGlMc/zzUgdI47g7Zs4DogS3lZ7apcRrRgN8xX956a3GjBdJIv3sOwdDesSIYLkUQ/AR0PZ3ZsGn35s3zAP+UKAOBc5DwO5YMrR4tuUAtF16DT1jT2DSPeybOnyA+o3xu4xUNiqXz1Qx87BoJYx+3IoOXUwPSP4/DOYNRqBRajFWI/EOtjgQNB124zEqS/C449cd/B9sev+Wd9wQ/uPKZJzF4Ffb9BfeBTMFCnRQm3wM/ELrA2pfFE/BNIfVBVA7COLXCyYq2qilfGdYmXf0eHFcFCxyQZ2RP9oBvgxb46FDhDeqk/KElXAySqVcBgmkpBskfDspzQ+Fe7jBzCKmaPgBYFY8colRK4Y/yqOdJlG5ohGp6WklDUbvwFY2RffqX0kk3L5y6Ayy7A1SgWG0FsQ0Uy79E2fOXOW9pEs8kvxJYP+uM8YrAClkH2cKTPI4S8Sfl8wICBd56gaMZmr7AmVhap1LSydJIRQDd1LNfP82aOJo+zdIcVLuyKp2EzU7K9s0umXibmlEf7iA+p2WlgmOsUqWj4VMv0LBorqzIFYxOJXxXyXI0e5qGKyErrgeytsT40AD568/LVRYBVMSlDUyp9izHO+gWSMBc3D6JGk44oWRf5xiGZl7H/KCempykk27+l3M2A8po8QJzErPnJMtwLAvsKh24o+YOIu8WaW6+JL0kOAHyi0L8aqRC89EJDJyW4gxK5nXYaIBlXmfnp+/3GiUjvMNqWZo6SdNKA0ufZGRrK4fRNpE1hsMAy+GgzzEL8LhsDIblujzF5H9AV/8gLxRQPu4SrPvkdN/x3t7jE+itD0c/7EBvNEVgDPJ5eQcvXCdeCd/y4pXwrYidvgvjuRIq56JuLoipTJlp5Z9mUlfUs4pJWFenxTwP6S307nLyussuxF9keSEkW8PnmRP0Mwq9ogqOwyTCUGGLFIYzgEM5lcIE7wpt/jmgwoE92dkwZHqAC2dIzdg0Dl+xIa2NfvfijxAR7kNZ+l+yFz8Yoh47VLOxEXLWW7XS2zjclK4Hn8//IP+GMVdPKlj4D4sVnqaurYh7CPFXZi/6s7SucOZQlRc2RePGmlx9GjaI9/o8eCZvzNbDqiYpeMZquTZeIcldUl2CJKf5jJpIoe0Y56pUJSAzoxSrA1ew8moUNgQJv1v2RnOVK4KQ7S4ndfvzFD5otTwkVkXYGGoxyitBfS26t4W0WzDndMH7gisqhbuet1jxQepBVJVHjS0hsd8gvOmbFUsUyzCeDfGhTmBAbxy9SUKD5PlyzdLxNuKnQfQ1PoHS7qXEYBApnBPBuZQWTPEI+sCRkPQEuDBBV+JVFmVbIufANnlqXBGIHZ/EjxZ00xjbBxRpRwj4i6cY1/T8ZRFK4M9uv2wS0T24fxyH/eN5rEFEFe1oFxJ1C7FDO0T32wDRzSDv0ig5MRtOZxLKRowXgferEeofqRw9+D5qYOBccbi7xj+QHdjY33uFbpd2SXr9yJ786CPNWY5iV4Y1u3RTA0ykJ9o0YOrzId/Nm99DPUr4j6Huwys0g9XIVWHPyPr0Eu0LL2iAj8s2v7uyY9XViUGzBQHgZup6WxBMyeQy3D+kOmDc+SCcegMpoqonEG9hRcJK4sQDYOVoTH0YlEgeHs2Tsnbprujt3wip9tcg4Pb/RCSNEmqFVYTMes0LL5DarLstHKke1EAqhoALV/oaTCJ4RiINr6sTzBb6rMKEJXEpmk2KZSPmViwtOiTtGOPNiz6twuadlrE167+/fs2YZaf9zt3739u/+06MMi9MEZwWEIOfhetto3dH6+qid4/arn4mmUoln5HwZEjZPjzfSnHQUqhz+PLImdPLd27KBuA1whTBkQGxKHbOvQxSMa0FppLuh7Mvwb1D6HuOcECaq4JpTCqkKBMmLhMZEXiAOvm1b33raz9HWx38OaBW8TqjlXsnV1ObqFvZUu1zV1F33z55e5igvLyupIzqi/+uNbDfW1m1pim1uXJlbUfnqu62Vsl3CtFgRcgawcsoGzw7f7FvXrpEqd5PivUOLlRv4ODwXhSCjwT/jer8sx+hCMMfARUs3GDjwM/P5s6ezeK/3NyVBl8+m33qKXQJfJdseKR8K84Kd6lyIwsUOavCM0pjcFn3iHWthauRAmTM4UCKTrB2jGzUADhWxDoK2sRtXDQNInZz6AuHc4Qgsw/4xNe+9q04ZDxnNep4lfAhagimMd48kutFvas3N9Icn/Z6UisjDQ2RlSmPl1LdLvhvnxSmXkexyhVqI6V8nYDYTH7y0P6BXMfG0edHN3bkBvYf+mS2o612ZeXG/EbYWG0dxXa6B/OpBucT+Bg0H1sMuW9+HDIxnSehHP99uN67kVU2WIbeQCC5eATpgP3b6CJ0lFUG0gC23bBv97K2i0fblu3ed8Oxaax/PQS2bF8DhTkozq3ZDn7cDk/dKHSCH96IL+3zt/r9rT7cn0j5OBflvOVR43MUQX9/nqeSvnMjnON/hnOlYORynBuyA8AnYzkGtoAvU3TLDouAK3YeiEXS3y2EoSxtq38SCy5VNsr89TwSU77cs6ppvA0viYUPCCG1RquyEpzdufHJ3EV/jvp1skUYuyr/3JpsdzgaXunzIxinQ4U3sM5KeC7R5kT5osspo8ElaFlW+MLCBID11JUzCpXbWOsRTsdiUYlnapGLwIaIlOuXi4ApXjFL8aRk9ahdCJd1lgI6H8FfL1dF58NffWy2VsqU8fRjYD3TCXPACl+L4GUUJzpZBAtDJM3RTDs7zlM+P/fMCfx/PsIu5uelgTpJCgSxGX2uefFo/WbfYjiDSl0cYxSKsv60IP41nJLm5QaILcgMhULKEb2Lvg/Oc17s59GF9laDGKTXx/swTm8gBfDvBB/Av30p64zzrGTaBrO/DBoHdwwaQUGg8ZeXQIF8voQ/BPqlmee3iaAFXeRT+A35vD62ZEksj9/Atrm/54mLh3C6/FPWx6R6LrqGi67GZZBb9JdL0Ekx5l1hleWSLCamxK8kTgMJL1dhTNEB+iaMrRxSxOG82afYiDwJiCIQIGaGhDVVNIkkHDjbvXjCUfT1h4qElCEA+ZZbi2YUN0ISkiLxUhm+GJ8XAAdadrZMte5sgR/jnmRb0uNJesBUy87D+BDwogPwKHiwBR1ohWdaPeKx/Cv4GLwyL91J3wQPvYKPCd8bly6cJAXILvSOUeP4AHqE8D3p9vFJseDWsTGp5CLuKuFRBdmJnsEbOT/KeEDL6i2va6mKlKFYs/uLFZLVo/BBkXpKX6S58IFEaandwfvYH70CZ+ZFgIjJkG/Wl2lxP+gX5FPYTz7B+/LdH3EPSHwupcLxlaEZsZW+eX8AqywlzZdL34XPyI6r5sqyVO7fgm2/1LP0bqleQKoFPesLNU4q4i37oHeTqhQs5BMckXbfyLNfgc+eq270vD+o8VIdKuf8Su8u1QIlxy7uUGyb6Wd0K/PX9I9wzkRFkLWCYCVggRU4wplGYIQKBjUufGlI+EfwhccfB18Q/nFI+NJU4zf/sHv3H77Z2Pd34E5gaQJXCZ9vEt4TDoMlR95/1P3P/+x+9H3RX096tuzJM5838yG4n3+a+QL9E9jHM4pujN+XQW7oiTgOs7MZAd6dhCpwI4rFbEOrCArGSyccPOeAKlomkYLiZiDMzW9PBS982lBr+PR3ePctRuMtbv475T/jR48+Jf0dLRks0zL+Jue8sfgz/5TsEYKuZMbMz+S/VNfk5dcTLKIqYFvJRnApogtvlEJ3Z8gUi5e4ECg9WBSyWRd4xFhjE7YaaxYhXNwqbLXVGMEjtpoZMsZCUpdI27x5NoR3xWca5xM3fiNSavvTZVOc5WVxsunS/Pxi4VxMOokyNS5aLg3z8ydWuHcBuRQLwpNS/tTzUBYg+2aueaKxwxkHcMyIoxbGpnJ3gsrcHAHRhTemcneByqxCykNOns/PfjrK6hbm5E8Gh8HOnPD2nTOeW7gO7MwKb9+VU8ykeWb+W4lmKMvMjPw+g8IG5grgJvlpqbLnznqqlfel5E/8OrgwM91tXpbnVnqOdx76cMIkktpkFmfzk5P5yTkJRScm8+W0zpWrV0rqAx9fzl3ygFmEo8PlehHCmkK+dKWt+RLCNJBvy8u3661hLsw5zs+RWuTUPBpn7uId2V+Cr8weQdQV84A+3Z67eHv25RlzCZS/2Pn8BtSo/847k4AjwnO/zN5xcb6xclh47uXs7RdnjM2PpcPxi9Hh7kSddVG5WxSL0OEAP3/iN+FhcGHemQN2cXkZNQtncSt2wnlnKdIf5y9O7Jgl3mthmcj6KRs/8+K5zdkOVAd+6PRltwR4lRBZeOOyW2NGX2lZ9IqTcXCS6Xgx2a/uzN0p/S2i6/yj7LYZfWjB9oVDnXPAoQWpnJfIS1NELS0vfgbvWhfLu7IN78Uwr7Q/c/m8myjhp5TxLbgQ38r8BuYjsCTUzpdxLSbbeif+NRXUS2gHXg0caig6ceCn2cJ7wrkslOp/miv8FnRkRV3tL+F1SoVGYUJokfhi2IxGCn40Uzuy4ExWsAjncmc/zH30cg7enwN9WfBYTrDAJwQ+yn00lYNfsqRM+inq18iGAMp67Ie5D6U/8F+yH+I9v6ApfA8UYVASUBTbBEclzjILJZNXpS+xvEx2c+GcLDGcGbvoYFMH5H4jUYCOwmcih5cg2XQ5gpxZsKuDmy9cx7s9PFS5t/HuicIbyJkRikLfO5vbP5WjHiJZ5eElk8QDBrsxnaZC04U38mez+1+Z0TcRPZHLooYGaFVciBIXlKOm9i9AQ6EbXvHKfonnvwCvIkrQJI42H8CrWPAgAfy/oA5iu44CiBYdgiKNXtTBvCQ7/AOUHVAeVp2YSxW2AQirAYfNP+BCXngRdgPYEerz1IeFl6hG4cUcOCOM5KQ1Zsb9pMfB9hTvB01ZYUQYyYKmfH0efAY05YQRcCYnvEg1KsScsvfA+yugTrVUlDFKo0QcJywaPWw7lQw1Ug0UHC1GCo8YL/DRCS4MF5a+2mhWf9X6kcmR9Vfps9HaSOS2tYJu7W2RCO1s3Z5paY4oNes+NfGpdRplpLkls71VBaa+g8IJ8sCwoXdl7IqHEUrEw1fEVvZ+bVVusxJwm3Or7mDa89fu8roae4/09BzpbXR5d12bb2cA2DY9PfnnoB0tWRnHx6I9D4n/OKTHJienp8X5KYFz0iDcORTB6OMD5pn+aikHl0IdK0+NFM7kJR875AYEYtPTwhgwTNPV02i7UnIjAhcwV4trxz2wDCWKLsV9MJyhE0WQolLWv0ARJMJeihwCPchbeHo6/pn0ip6+kotmX8+K9Geye/Z/Uu6W8cn9e2DXh0ULuiZXZXFOrnQ1bU2lZTNlOiWjK4qjXmfhogVm4aIhPwdOaYWs8KUcVMeMgrPzEPg28nKeHi4rfets6kAMpbUi/DrOJOnnFWbkGWkNsmTrmGOD2K0A6go2u4MNIqeD4KvgfnC/2Z7rEH4s/LgjZx9srIVTO1vbKJymrxodZarMgr7/RO3LL9ee6AcfmKvWC6nESNUTT1SNJMALg9jeI5U1R0kznz7nI6U5sERz9FJU0zJJbYEaxHGmr8uoh/AVksPr0ryTa0EzSwY3iJnA5ipQeBATM6uuKGfIzEIyelCqLOdAugY1XlaUGdwvnJYqelNWOAcVZ/r52aUy2kF5Rb+dQ1feVd5HHHNRgJJ0OMDMUqkbProzNwXa5yxK+MNHd6GTM9vTg2ycc3BSLrJwPjylzeLoX5f8kL8Pfsi177x6Z/vc7D1Qck2eXjKaSo2KvlQSn2sV8Uv1qrKYdDjTwi+OBXpXiTRBIJRxl9PVrp5J6JIyH32EZRhW1OG5tCy1miQUOOAMS8t9QOCKTR+YFr0q89Mo6IN3x5Er6NsjuRHpT3gBxKgX80gQQFJAHuekmi6cATHZReABuOrTMloCONOkWLR7BkmAJPzF8jqWG46Qsou0UEtnEYCLnSiRIYzJLqH6kdBRzgsvHiHz8AKIG6lz8wAZT7DMN6vewpi0i4oyHivkWOBSmeGFWwCIe8v0/NwX2vFm8uQ8fD9HSEBmOsm+8wXsi+skMSKl5TMM4KqCYFFpK4IxLAnF4E7qZbyO1uvtnPDfKhXQcvbwb35DfUY4LVOAJMuMTgNO6T16cEqjywunoQz4rPCbGXoSJaPDOzcVQKaizUkAGF64bOHW8kKVCikPHIkjiEINDfmfz/JFlod0sMj3HrYPyuUbhC9pj9AN6AfzJW/3fNGpuHAdtoKhFgGn8vk41nGotZD2M7hlRmCryQJEBR24MIkMrvDqOAlBjYv9RKIVjVKSz2RBSrkiZVbR3RW95qGSuD5P5BG4Qyw/L3lxiSR4XV5MjS3Lp4f42EgsGnK0wpnZ9LBKU5zykJMm7ROJ5UFPiaaZ8QrCmEPcEXHkJ8ApkZNy8uRk5wXdKwZp+8MwDi6ItIv+kITeOuwPuSAfkbNwccWwg0u1t3A6L1EJzAs3ttA3Pl6kEFwra25xLkTybQ3UzGLlI0JOIwHCFdNIcWLnBEeIuiWmI8Rgt7vWr41tqr5+ZffhFSg4pH1yklLBCUlMoAPpwri46eTG+vb+FYe7cYTbhMwOJ9FyeZSgLncJKiYWJgD1MMkH/y76Gew3W6/owijaRTRgKPKKzutcmX8vpMgRFp3xkY+yCPkWFoV0JYgTF2z6nq5V/cMnrhu/32Ha0PUA9ghjEz0mx02j2/Zet2dXpqttT1vg3dNquOY6wcO5uA2f6Vg6tGMfvstReJfj4DWZqN2+rPVnN43cv+xB7Nf+x4Yj3fmHYw2tuwPwdFfm3dN2J3zIvpUrN6DD5qEQuvw42A7PGqS4yLvg/GeBM1EcZ1zCpCJlolqsatqKzcJFmzDOgDx/FMc4ofD+8euEj6RvJ/ZuG73JgSrxovRlL6Sgbc8N6K2tJFrQuxF9N/2sdZn0efGthtjDeUS89HlMvA2+5WUBWnSxLkgGgxKFFdFeLa8NKye0rArrEJVAVUY5pSyZs7pl6B9fkZMHP28sGbDysr1FYk/6HPUK9uYNZ0JoEYNMLPdxdiAQKPTmD4N3d4Q3rTqYPVC/TL/Tenzrjjd2bD1u3alfVn8ge3DVpvCOSMO2hmsq7q5uO5g7mP5U1rL38cbm5sbH91qyn0rDQ23Vd1fcrVKVYsU+R72IoqmgbFsqXARwKi+askVKRdfvP3YzsNx8bH99WclAd7frbp9YtKo/Wlsb7VeJBfvgKZU0f0jjxo/mOCsaJ2HZwAHFkSINFCCNDi4sws9xf8RD4quyQUJ1rfL6YRsYe6OwMfqEd6WBMPi3NDxgsVIv4wHwaHFACMt6jZGeqN+7qqMPtiM1QXr+3r+1WuBPmtB6hjlEP6yw4TVY9BYtbdHg6WXOgCAWco3KYBdS5EB6Yd/upe0Yk6MI8v196QvF3QVVlYfR2Qtl1198q+w6/IW5EyorlIwu5zxUgXkIoPzzlfYmerSszhUk6i3okFpHerQERKLk0pk509JlkEWCvufV3KtLs72DN0hF4/IqXF9srKgoq9j2bGd7k9CNbBI/gfc0uirKWTbYm7U3tXdmy1lXUdEI6vMz6O34mPTKtOfF0v0G1mIXS7ioXStkbYkxKhagXq5oz0uk0EGePB89wCQq3fJyPQuXiwT6+corPA5OLVCWZFvup+9TNCvaFX2KETTTGYreWnG7AwEaS5MswgzkYFdGiYRKzlrJckAf+Q9r2cJy7pdV/bVEWKntr/qlUnJYwT+UxZPwoBhsRNyfuub0HXr8arcfX+t3X40DwIo/4k7pFAone1LmVhSTuRudKXOgInFWSfpmtKdZD8o4EJzBARZygC3nAPX6/ymcnQGS2SnQ6QQKRgxdRL/+T8EwoHgeHn7gDmcl/lLpvMNikY6iHzUW6RS81SJhpOzCMhSa4XgJMEpKW5CQ5zggAhULwiCQ8pkDVIeU7YOk6tilz/YcGLuJWPFQimuqQxjLgVNvQwWDnthVyu6B8oIc27u7tY2Y+nAy7QfwpVD/LaOpbhE0hX3mS1IEBOFsDgw/Ck5dkqA3hadyYOhRYUyKuTzHXE3/BV4LGsncyM4YLngOnte7xZwIQlUVjTQxuEAcMeTLHCvD5yem84Wfnc2dpTXwDV2197+lAfbfe+F9+cZGePnqYXT58OrvI9AmqL6DbRueyp798KncWVEHkuiuwLnq56aaTkH6UmABAlfmpwuZBYgB5xAaHhgulY3m5q8y99CPKKqJRxCU0AnYJ43TpYlSejydwbmwPACFw1tTKI8agTmmlRykivoAdMJhqforpct48WkklT+hs8NLWYtqNBzUChuphruEH1Yn7Kp6ilP5/st6cz5PNcM79tkswmcNZiLFazXgFhXL1tuG64SfC6Ng076aVu9ZtYkxCd+oCOJGRv3uW8y99F8q1Di6PWEWo42CIn3GOSpwbAIZMODJTqWVq7MY2dYStYVf8W5KVzhDKOiCl1DKakOt/ddy4qgVvMirRyGvTpd4RSItMyL2CNn78iuRToEAoDOQVzSP6EHANF6UwArSC94XfiiVTvdKvBLeF3kFHi/88i7QWc4r4CDkgOsROUjv0WqE4yKvQBw8KjxW5BUYrAiCUyKvvgnp/SLhFYDtRGhkRfo65qgAswszS/iV8EOJWSVyKQ/vBsuoEUJCF7ykjFmEusJzvOTb3gbnB7NomcLacsYsW7jMCbhsJcozwyLLCOzcaBRa0dTLI4Ww5EcTv3h0ghop6svTkDPP5PbnCi74tpcI+DYQK+1GIEUQxEpaMzUyoYGXBuBLeLsbi/pR0Y5GaJWsOXNQak0gglKYUDmd5dShVK2rZ9E2B1Eo0yuiieKKJBX3FAF9k4JTaNDOMGcGKbyxSL0yiUDECiPACf9vQsaWU+BcPi9sAV8ha5d0n0KNboG3UnoMOzY1CTbhK9uJg5cSz931OA8b8uVNKDoVAyIWgZTr0FqW+BBBEyI4aTjk7WU/WNKRyNAD8h/UuAgbKQYU/J1GY7nFEuG16L1wsxZ/2vAx6ouaCPzU8uhdUziIf2ls+Bh9r5sn5lfeXbCUvoMLloimT6utwe/CEfmvz1m02j5NpAa/g13yX7J1q5LgRaAtL7T1zkuw0SgonIjnNk4StxJwJU2kimtbOkWN79q0IfNpEMuX9uKwVwQo4CbGZyG3S2fpZFPDatjsx6QtOeJ5IYzhD3ROmCqdK/pQ3AdbKCHSyfnM3EJUZnzmTBmN29evWXIdiF2Vze+5ZjaN+KwwJTtLJ+uiq9ANG5vjs2lE5+DlxXO4z/0K+97hWNvyjUO8wqYSM1QeZOehn8w1dXTlytfSfPlCu2XtaupXueaKqnJpvnzFCwQUIu4Sak8os1lnO+IF+BmaFxZFeORvgSSUY5fwhym1C/jKLP+UcjeYQ7IeIcVNA/qswqGIIaumQzadBOTRlHPLJzKRuTS/lAyFILamh8xpPV+RvqwpecrsK002pbkPnCu7HH8pQ61Afe4eTLMWedzKKZ6TyhJhwthscmQ0zFWyQsIeS2C7vQOjebQjPwK8FJUlbEWYNUDKAoTy4iDI2xnGKzHiCUr6ldSzRElA0QSVeerZwuuN0ab+odFNA31N0frA/mOHHisBkDSJkQ+U7B78DOwscsjmXlUXq41kPfamJUtfKkGR5EsxH8U6INyUOenP+EhzZ+TNOovSM1R7U+/AU/1978jhUcrJivcgFn67DBJFtKH3w3Yz49kc2f94cSzCvkbGXfiS/UyuYVMnm5K45+A+fiiRWLC7gZ1YYwUVe824p+GWjy/Y24Sponot4lYi+tVQ+q1Fq55vIaodZYQKunlJfEMkSzg2H0WTEhXlNPgvSQOL/EYXKhtMCWMLlTxd8pE+wWTpH+Nyay5ZLnKIDGeobUJ7JjW69WBFRXF8P4ICi6Ph7uyLZ3MfQf0pLVxzcOsoKjuMT8quEr6KL5H6Dimf9J2Wj9l3CFmnSr0GEpdIzCZuTWZLKrXlEO41I4TQ+n0W3GvmozYvXn9oS0pYLhE+s89nPibduBkX09epLahdF9HRT+OGRvTexnTRP/gTx6jcu3CiOYGjyfM4qjtBfpTxj0AYHUIsB3+5P7sf/eXgH4jsM+PWOAR5no6XtdAj4pbeIbGhhGfQLeK94jjpuuyxypYRLOjmJRXo5fQtMHC+ia8gf2T8nGLa6e9gesKXnjvCuKfCieO+BYj5aDQ7NZUd/SaoltEBT69Ap1eQ6yZHc1NTuVFx75/QQNp22cds2xJpi2rYm4vE4l7Zs2Y+isum3yL1ZB0+DmWoFxROuIJ1KQYVo/CgaLeRgQvZcPoP2u6lUPi8KO4VV2Wct7Qo1tjswfk3lxRXPhVPyASpRPypK8f/N7upqr29avuqps7lK/u6u450rN2wHcqB7TWhopxRC3bPGeNmdt25a8+1cs+0a/fsutM1DrxLeGVHh9Le0VxV5fFYlwchzR3xIx0yzMOjd8wT8ib6A+2mn4d8Qe2qYLnw3FwBosA7xzJP/Wp8fHZ1C/+zZGj106uHlrQPrH5i9cBvSxtT5vHxOSsDAusampsb1rV6q6u9j8h2qKT9/ZuKsma3Yt2fIm+yuFr4HisCHoPKRqqdQog1+cVLomAqe8DtyTc3DXP925Yf7qntCadjH0c8/RvvVdlVw5v7VtVQn/OeXJ/7ZL9yl7K5ry6xzl6SgY6Lsmst8pa/pPyKK+rAFSW7Dh6Kx+ZdvHy9jqZGYWz2Ega8/UeDIeVEwP+VjkAgvmRLcsXhbtMlxN0x686e3Oodm9Y/vaR/aOO+zdrcnmXdh1fIfHiQj3+bIqsYWjxihIjGJAKDZGYh8y4m2iYvS4caF4OdxVjhRURSkFBOgvR0Zi4cX6nOCMV3ociGYlo80coengXoO3/0jmwzV6rJkwvWBJzrLm0TR/ML0Y0w/RouEVcUvHxaf4l21i6PxlP5/EQ5ZeV9CPFzxceJyUr9Kf1mVFaBxXeXWH56BrP/DOMiTFYfOJMR7yD6TxoXc3SmRddzQt69QOxPGRfBhFi7BKldZhHjYq4hvnCnm5YN5/8sI7vUTk1Q7skphlFWNlBcGsNz7OUiDEA0y8ox3OH1BgrBuGeCcZSbG4MvhUkizGTaJ32R6qTdVG562bFeZ7JXtX46K6sy+HHOqteHkklrFeUS3kvvCDR2THQ0BnZ8UqzyMVHzv1eMM0puMpe3e53V6DAEgjI+FL6UtSaTIb3eWjXkDtSF61wu+Daz7zKyvbG4Yilcj2UcCTVSGKXeAzLKciB7q19pBA4oTHmxm84sKAqp8imlQZnLKZ10pSnK94xu+5ms4yZGA6rGjr4VLQZY0bfFinaUV/TIfruZy2Y592CV0Qhy4Yi8gteF/eo6l42do1rYPrSL/k/61wov8ioLlnb2ZHlPipp5olwM6hj9Yl1dIr5+4083ro8n6uq+ODo9nZ+ejpdQYT/S7Rtes3U3Oo2u2711zfA+3R4co1hCg5XomIS6303YQ1oBMnijM8VJWXTl5kZ7eZDZ786ifc6zwUiRElxUxzXfLNFB7T+bF8bePtt0TUeRGHxppPBQGSF0GSYFMkZaWdoaZK10MANbks7AvzBXvjinqPGXwd63tcKXhC9p3wZ7X/7LwpdV//sR9+XC/2Kxk0g89I+EF/YLrwm3HT8OjoDI/hNv9L0k/O/ICOBe6vsWsQRlRtPp0UwZLkalnAJrgBScwUsn2rKeUfJVsKgDmzJ0HgGCttIzixT+B5YQH0lq4OlUGO1FQFn4HigL24r+rmgPDKHBdsG+cEmpkuyu8gGkwaKXGeo6yAEGzs8pH3xR4wsi8DLIYVQ4mT2Qo1K5/dns/lzhhdyBLP3ziYtvTVy/IBwv9R66hv5s8Z5h+BT4bX8WfBG7oapldSNoA8RvsgkhXcxZM/pjVObTi6wBveYSZMts39UzM5ZkZu++U2tbPL5k8/qRXcMrsylVtvvK8U/v2rr5ZCjS2XbgIH1vKrtyeNfI+uakz9Nyy8EDbZ2R0MnNW3d9evzK7qzkx4nyTPrRugRKJfGzU3IsRcTILinlQoLHKT025a9c3tE8a91l45VVwhSe0sd3bE0kktjgr9vRspR6CO8XVFXG2VnLWnPHcuH7eOpe2rJDh/cPkonE1h0l2yKyaaM9yNWwPRPIeohzGZK8qXKdVcoKwidSwZlw/JyY16WEvdtG4HUpXSKfYB22sMFNV/uL7eevpt2GsM2hnBTytQ5HcVVxOGo5Pmxyw3E1CV9uU5j//PR0XTRYZ/TQkR3JkkaU3BFmPMa6YPRz8fh0sqMrW1Ixsl0dSTUfddaGjpHp4Fio1hnlSTv9gUnTgwSlRw2I+QW9PDjleAOFqm23kow/HipNNYPP5nJHczfm9uf2H/Iaa2pJWpym2isPm9w2W+vAQCt+Bz8Bt8ELszfCHrn/yqarr6xt8vt33PypptqgUXjUPTDYwvMtgwPwXYrBZO6hXiRrBShlxJIlRfaRpYJHGGbyWfpLunUdnatKjFjV2bFOBz7CA2hMpltenT1c7Ssy3Fd9OAtXi8nJCdmmxp8F8wT56i9CVnwJBXAsBvUEXIBUE7mB9FW0Yz6gWIt66yV6aoBPzEocMW9PBQk6FbBSuufn760/n7x0dwWfOHb+2PnPX6LLgthldVlAo/3ponzxDeZ+egKuZEEJYwihCxUdxjGuEDrK+mCfNvvMmTD1/i3GqHHKaHyOOMo/Z4Q/osZbQFD4xtG7ngEXnrmLZm8xGNDB54Q0dhh//jl0i8FwS/7oXU8L7eDc03eJ/rbF8hcsfb4y5y9IzI2wC/s1I0mBF9N9wXWExF4GRfdZJUeGSRtgdsXqevtHjuWBcnNu1brC3/b3LN/paPEH2ASeC6mHjo3099bFpsG2OIqXnfR6DvU0L+8ZwPPrhJQLApWJohNTkhSaRhO0rHypPOx8jwIuYF8LBpBb71IcsAB6NvSt+oS+vnXZ8vMiRXlMAH3iWNueNvQqdCOIZviid4dDn1lb73JJpJ0ixAhT8CoXfJ2PQyUCvWTx0zdD+lplPMFGU8nKRlBPM2nWT7o0SsuE2YSw5uHSgvPvMYk1/bef+PqzurzZTEalpzPpSTQvFc7iDtiQXbElflX3ysCX7/nXZR10PNnYHvPQN+X/85F7B/u61+xef8VXyejWqCiGZtfhDptc2b40uaEz13fFiZtvfZalaDVHi34WiOaojOJ2Cg0/ku9rLuJF+razob72Kp1GY7y/b4CeSatET/+1uzMum1mv3vKpW89ZZtIm+m+QfXdWoYWSpx3KLGjHiseBzGZfKpECVpRCIGB1cAkaTbIokQOUyYEV+ZCcgCNOmHrz4LKfLjv4Zrz96NRknj6RnwSGSQI9MAnOFd6YmKBCpx4A51AoGLw+L+HL4XJpWK4B29rNbIBOZBKOBHAEmAQOmScPFv7QfpTejeATJ9DDwMQDYq7qK+j7cJwC2mly2A0U7IPhDI+dFhpB0BrG0xvsoNj5sgOEUSLqDJSoUSfFeZah3ktf7HeChtWNe6an99jMlSbjQOEPFQcTmrrq++5rGm50JA5SG6OO5MFK4V141FK5zDiwccC5eiv4zq3Rrasbjz355DGNaVnFrX8nvNix2WzzxvKNw9sjm9vB087opg7hxU+1b7JojKbKE/ETtQ2Y7meZDfQdkNdhbN2HKwaUqcOIcJx3qJGSCIe08tyclFOQcor+fb+zYQ2mm2NVShoMCImKDUlaq2YJ5cmNVBekfEOF8F8bk7RSZVbS/bf0I9L/GpHeBHY9+eQnAMOY1cytvxRejG9ScmoDAGACNA1vi26Kg3MO+A5rAM/QLM0xt/bdGm0AZJ+a/kUJKwrMEVeFQvLpB3FsHAk5CqGIsnx+FgITMkKJcXfiM52zn1hCH5Q9EgUaIn+gmcBLElgoiV36B+yLhXG/rGE1AmXgzKJm1wisvGhtT7GArQfnJ6kRlEBEm83v+c89+aw2v2Rg6KmhgSXClHAl+AL4Anz/ybVgm3Ba2AiuWip8Q7+xOR5v3qgHtt91BILBQMfvngTb3nnnHdE36B9g/1SiyHA1QhZjS4VR4yhAEvLjojO7Z/8f9u/JCmP0vSgmEdQInwePnz+/NZVOp7ae/00R++qvIG+CiqXYJiLOXwYKripwZbYnfHGU+QCuKFAaEdNkWA2UG+BwtnCq6EdA8ziIk3gR4tONINROwPfgSP8nvPqGEnqjiY956TXeGG8y6hMhvB5P1vaEhbFwD3Kqxi5nE/k6rzNsUJkqL75VaVIZwk5vXZ7kk1xtsfSsr6trbbsFZSG7pa21rm59j8WCHy/8km3ujfX3x3qbWYp4bwun47/y1rkbnHW9Q/v2DfXWORvcdd5fxaU8QPfQe6AMOoC9JJF4lSZRUz5csbgDo2SFyJJDlCYSNSKmEmnGwX9FLpF8fGgPguaEqVVd7et0Gi1cTsAp+KbV6Na1d/1ap/e3+KGAmIcfel1di5LWGpQakoVMozRoaWVLHb3b57s6B+BNfX3o9tzVPp/wMAXvOB+Pn4cftKqn3mbTu2qckUbia9YYcda49DZbfY9K8WfAd85g1fH/Twy96Ty4sFgMPRTcuQC28wIYeigWGZzCkMYzedP3cXiTQT0B9hU4b5CUIBRJf7MYYy1mmJtH3bgyqtypiq+shXNrdjEsfLq6j3fH2mP+CmukM9g43LR0ywx+phfmZxtoB6RLoyAtPFxRgic4gBPzczmThSXVroyrdiqjlYh8ONsuwPc15i1LYcWCnRFrhR8S6+b7JJ13khmAMgpHEPzgDAp88MX6OLPDlzGzKPYnDezCO8J1wjvADnYIz7/5Jki/WfhbZManbyqeOAns+TfJyX35ku2NPFtbejKOKJc9kQanyp8ibCz5uxAeGnBeP/iEYsQP2k5Wl9sxQLqcsRLD0+Ao1Ryx2wleVWc7eKbwC9nPwpvZOVgGVfW3Cr9ItHd24y5jtxd2UM2yn9Tf9cxuFPhVjidHMKwVwWK+V0y1UaRajCNNZ+gLabeHdM9Na4a7cmW/9nYNr9lEuoDHnc6V/ZL246V+1qjoUnSjWXQO30biBwqUslzTUDbGBthEygFSgeLePFYKg3yCljYHZvk9SmChMnZEXovHJ18T/if9e9lB4efuIdGsPNshkuwvbJM1ROK19LH8UC/QpH8vO7rKDayiWZkp8tWiqIWzRnoWbzmQ4MMz+RvmEbRBwBFIWcnOQNw+g+VgSXpCOF926LXJePybbhcpubwRhMm0CnjLDr02lD92zA26SG2lPkBsrSzsBYogRh42y/CCMd5wOWjwcxhouHBkLuzg40w//TyW4TFOGhxL8C/ImtmgGSwQmQv+SQgKQfh+GzgCjgi3zY36+7zw28Ibwm8hWaEvvS4Mvv46+IawfW5PB0pGi0WiA8xdqAyiV1aCsFHukFCODRa6LGwwFH2+EDLYNBVaEJmMCpG1+RXm0/QRKL0RSy6six0ND1QcQaOww+lKst5SD4B/1mgtWsPFlbxbCb9HLDphPa0TboijBYTedPHvzREt57FB2aHFotVwF6eoRwof5MG5aVxHqSwe4cXOLgkvqgiYdo5iNs75/MJ+uJZuQym/CD4d/RCdVKgVFdgvUEwKXgdwCBqU1smyyHlAkPdJ8PCPn8dR2P7z4AIUb2AP6YEfPneiDQryVnIKvIojrYUgPENXw7fYsNezt5PkDBFx1Q7AcrUoB0kqYcXCGZ2ActfYF/bfC07BN1seCdyFM6LN5I9QBxiQcOywqgk/6QP5vKCD9XkfbLv4BF5W1ginRZ3fK8U3sAGQAAHal/HRoPEgOJoHRw9eLxyMgO7TGfrpi70glgcT0rpBsNbQfUj39HH4Xi2FI1mtwrPDB9HVsYPX33CD8B0Mv7ZpknoPpQYFceHnUC4U91jh22lYP/QcPO5KTwqmIP0ppTj2yneO1gvP5g+CzjzoPHjHDTfQTD7fQMaSbNBhQLCLb4FtqEBHpTBWWSl6W5X5FZViPBzY0lTMppUwy/zUzWhPHjxORmtpXwMVAJfWdiKEg3NCu9yF5uITecn2ivIaWLFHnJ3HqSVTaOqEuoMPNmjQh9cLtDogTzVk7HHQh80P3n7j9Vcf+QGoVhZ+RJ8QrhHe1+mq7/jClbs2H/hu1/YM6Aw37hpvGV9+ZaNPmc9P6Ay1S7fe0nwweZ23sYrH4++PsNwBMZ+CkWRUMMteGBYP+VYXPwfyhevyOCKuiAcyxzPQixY/8TMm0c2TxW9lj1EV6y89wyoi5BSxAKX/AFKVQeNU/KQ6ENosRtkRP4UxbBMhZhA4aJN5DMeSx3E1yB6NP7BNpsC00H2yMl3IJhNIheGISMjKbCQwVU9MQGIn0MCQXlfnHt2Ue5j6j4mJPNQpt+GUE9/PfmVT9stYJoB1ytBduPdbFHbkfQICHJ/Bq30gIysgmGyn0NxgRFhAqQxe8o1wcliWXBXvmGyfwllxxZfwQFVza3OVvXvd5FHO4rIA0Et32QYNX+3rO48JeMPdXAXcze6aqqG+JXepnVazzijaoAqQx30Y+9BeRB+CxXPFhODSF84sfZMybIDHqZOF656cKwfBKXQGveh43lXXEYt11Amn6zrq4B8QzpAD4JVPTO8S+3kjNQ0lSZRFubgHHSbZ2+HK2UARddPOLnSSfititYWDn90cG4BCpVFti1fU99Y1rm4M9wrBeU9RP6hrSq3cMDx4HOrXmVg61KRRUWzTQD08W125wDlFcX/kIJ5nURwj6iPi3Mniid1I4ZgzpPPi1oOU/hOS+YXTebolsSEeUj3698Lp3/OJXJwC+cQGOon6DJp8hNN09WR8Y7wzrnkuPwh4V3Uw0eDn4BFZuUvh6ojwWHiOuPghaxsCtRAVL+yHGpQRxWw/3jYQ35CoH0xB5aSpuiaRqOGtXXe/XnhDpIq6On/KtKsTkhbO1lo9kcTKpGbw8fyknCwp98btuN52NEKC0oIBy2LNxHkA1tvBJajj6LF4UJ/r68sLv5123XmnjTwIPXQSQ2WtAGcf/KBUry7YE3E8coBLO8RwbWUI16ydktJMWstr9pqzooJsp3fvt+xQp/xkf8IRNWxeUjgjVe+T+RMcQB7RKbCmo6o6CioaMg2VNks9aJ+zjldDWvRirgwu7qFIwpNMWdni4oIpY+puycBnY6/eyu8V3MXGrmqowEVVNlCfPC/5ZTeAnrJSCx9UomsIUcV2HsB8tszkcsDMpTLUs0X2nsrnj8kZCyv9TuVelDJNZmumcW2CIsoGHMNhpGlgrAMzfsd6B08HpB9Qdigb7RPxiTgUrCbyeSReocCL4khPwp/wXLzwxjFXHP4Jv4274pNxcA4n3SnHQU4WvWlmbzzPifNhJUCji7AffAlhaYruMrN0pItH50J1n8Q7eHJalbAnIloRiihUUxZFMjWOnrcIYG4C5nru8ikup/Xj8ZWAzy6Gr5jMRTP2z0Ir7JyLgxBHLbAoUs+hXiO3FSBavQtRmghzCX5+c9CC3BJ0mDOXXRYamwvAky9UW6Gd1Oyyy0Jb+vMnGrh3odGFq7WosjhHav7kH7sXrJYI1sspSjnFq+B8XQtlqzi27xE1tUOuvwYT5jBnhv0eASryaIuYz5CZD+uUCNoP7YPxbvMzImJw4W5czjSIFc5YDdNmAn6HhEiPmwfX240P/1pCOsuDxieeEF6ahDLtfv0bRnsvgvK7kBflS0KjSuahpChSA+YgFYHPcaISiuD7wD9hQqiRMvKE32NyULCyWLowNZMuRIOIQSjixTyKMSN0ChPUtN1I++UTJJwfIVTA5c0HuWEVgS5hrwOxyfgfvxWfJHojmv5hJ6BPC1PXYx3xwvWFLyIJmFpReA6tQ9SKSVEXkJfjxOtYIKXGu9ZQzoVl+BCgAnwx98Qh3VAWjzP9UAnCCipa3jTw2UhyJ+UgQRs+Xhyj34HPPgUldbjQsUXETJCOO6CsnEH+MWi7ESp1lN3BAIKVOUExxpCRYiaEsTN2ozHW2sqr1Xxra8xotPN4f+sceEWvF+qEqTPwcJ3JhM6bTHXwQjyHSWXakFwws1QaG4Bgke0U2jpsBx5Kyc0qOo/qCWKXKH8MvAvMwvuCLT+bkOL+1G56j4KH9Sc4a6jfOKzyTbyMtRRcoAUkGx9s5F8xlRbqWUslkwcE+Ro8N/geNv68N7jaffTeo+6v09V0h9luNwvtSlY4jSnbxirBrcJp0ft5m9C+Yu3aFcjYIflGEFpQ1jKOxrlw0eYPpCJMQ7nNKkUABKw+YBXLRls7IA+pCUnFUwfp3bNKPWe2C+1SuQoxv+x99A+hzjKEpDMDCCHgAvRKd4B2gF52BGKAXrATGADyACq53sAZRx7ejrEDigbYNP2BnrFaGb2pNRjScJymJrTUpGOtVlZnWhqqQUdCwdbCa5OTWHFft2n9XXlZ+OHRvsPDOxJL/19jxxbbRhH0+vxInPjss+988St+nX1p6iSN7fj8SPNS48R5NG3SkrSorySkSChNEFRFTWlaoFKLVFQENVC1gOgHIKiQisQPEaDSD3/0A1XtR6mEVF4CIfWLL0NO7OydnTQpVRTv7eYeuzNzc7szu7MzJPLLHo+pqsrkiWQYRsfa9VamXfTB8z6xnbHq7ayOYTI/Tjdg1X90z4XurV0LK/sov4iFU1vzTx16gezwexTn3o3hbIxJ3OPwy2rVCfoNIZpIbFmL12yRIdsnN4TfVwzzGITUHZuqTbKui/pV00piMEKA1xADOhPOAWgl5jws4pJ45RFYgancgPNV/hPUP6If8oyyTKl4f1LXLknGad+poactHD1NB/2bPPGgX2hoTKTfXhyAcyShD4id5dP5vlR8czic9lbX2Dn/aFcgEzTTxlyz2ElbbcF0kKxYUosWkxxGx0wWyLNCUJ9/cTieDoVt7MDJQfQpnC+hC+TyPLpvsiwrNtJOZ6xpW2bXa8N1kp3VGtqQHyqLZqOCHhc8FD5UbDbexeNGDZbeiX9g6DqJJ6GAPqh+ZuRfPblCvrhICMvshQK6UCjABAf5kKIlDEVJdXcv36G0y9twN7s0XQTPxDB0RckgoizxqzHr36O+xPyWBGsqhcMqPEc4DFKF55Jh0HMNDh45YhLEYJACbdTvT2YuKzDgcmstZyzUaGvRDUvUgm4MyFPy4hGsc2zxhrNWzFmsTuEszGuEs+AMY82GvbiWN2uqi7RglmsZBv3dIyfR529V1rnK8HdvEH4wySNWeUmJdxiMCLxBNpPH4gHHhlDBpBY8m20MIwqjXj1GSe7AKMkdtdqagpGrRZd0G0LqlN9aa98UabDbTB5DBTuzQBera6oV3O7q5qgTxE8WmTcxGKvBXxFIVLCTkwfHLg6+GpVHQQkPSgadOcWxgQQEtEgEWG5+MF/IZAr5oeVc2MMF0QF0IMh58pPTkdt953XioQOUSxrKX8xCxIvsxfzQHDwMD54MT06J8ofooDg1mcdP3s69QfltXjKXDHCdJDNnK1ApH6SRl0JxAG0NGKnuvROjN/vuIASwrGlT6rYxwZt9d+HGVTJlTjOOZQlBTEqKthoC1lOEOC5gMCr9gGJECVMiuH3wOmEIrV/v5VjFVVfFiS2NdP3yg5ao42qxOIyZAC0tXUKS1VPX5mqMD7Zu4qw6/eax5EiXlJp42Pvc3OI6wXV5bzLgrqmiDM76pqQU74g+8++4dWivFNxnoHQjQcmXiVfZDCa9kbOF3KFNuQbBv63x8EymfZ3wO/4qa/VwdjdbR9P1qa3l+dWzuqt4HIC1YZ7I1j7MyC1IonjIOpEdwmli8UMvQtaJqNM9Cws9PSdO/FMqnTmD02fz2fa5ufastnZs7MqVsbHL1Hcn4HpPj/wbueFMST6dnZ/P4vQ+3IBTWeZY3XalZb2ao7UtyqeU6kraW2ubCiiwYIGi0gIZ46g/qG80QQ1GVu9QbEZE4lSSvFMHvFHLyhKzHSKYk3eclGit4tKUmNvCTiPSyb7cPcDafZ7h7uMmX13Cm65L1fthQ8i50ZSN6baZpXAsZdl+pHPw5EBToxjgDx5F0PfPxPsX0CtTh3YODnSOHh7v7QjFuLbe/pGZid2tceql3OKOgef9fS3Im9mfyC8Opp8VQ17XjLqe8jr1J8YhUvYCB6MugQkjQUYyDDIRPyTV1leF1V+fqkt7E3U+0/HcTrc3KMwKfENjPOMEeI/GAaqR/t42Lhbq6B2f2ZnbuWN83+SsrqquPt0fJ4Dh9mEvxHndMPU1fj+iZosmrenRDGp2afZpMHQgpVZiEeDerRx3gY+QcYTXO8jgIdojqulXuFzAHUkiAi6ww45kAnclrMPOGppRIlmPxHJBKhe0nXySR8d4t5uXz+EiPuDihNnp5pEPjg9tMUGICfItJUfbHX5/k88nUzaXS3A6/3KFXPh3DcpCOaOumc336Ga3vN3dTN9Tyug6Ls9WWWj5uqvF/LGRtqBhfAaJJhb8VplMbD3L1ssGsxS3u6SE7XsT3RhlcZJ/4Wg22ojTyLrCozQMYG0SPAL0arbjPufgE2jYSs6GmTAiBMIDir1MK7FckMoFpK7jx0R1Z1ysQuHHUy+Genk3rBbL9xV6nLYBjVyXFZJ9q2SozybEBSH+k5KhtELY/6Xd+BKcPXsPXb8nd3KENCwt/1Am0951BTRgApKy7Uom767FZHXitKKTKHONdtAqw1jFFtdG5QHbBmNbiBMh4hOWQRQLQlVP3Q+zB8Wcdim2yv/7RAH03kJlbuZnXYLYLDpJ5OdVikYkpK/U/qBsmwi+7kitj5osllYq3RDcdgls9WHG7DFwl0hVxcKjgJNtAcXiRuBGldpXwb38iVrtGmPLj5Rq/wP55JMYeJxjYGRgYADi8psfLeP5bb4ycLNsAIowPIm5moug/6eynGR+AuRyMDCBRAFwYA0BeJxjYGRgYP7z34eBgeURAxCwnGRgZEABTL0AbAAEjwB4nO3DQQ0AAAgAoXvYP6RJTGAD2KiaVVXV/wHf4knnAAAAAAAAGgA0AEwAZAB4AIwAoAC0AMIA0ADeAOwBBgEgAToBVAFqAYABlAGoAcwB8AIEAhgCPgJkAoICoALAAtYC9gMMA0IDeAOuA+QEEAQyBGAEhgTIBQAFNAVcBdwGLgagBvoHQAd4B7AH6AgYCEgIigjICQIJRAmECcwJ/gooCpYK4gsqC44LwAvqDEYMlAzYDRINQg1qDeYOTA6UDsAPNA/8EDAQWhCIELoQ2BD0ERARQBFmEawR+hI8EooStBLWEvATEBN4E9wUEBQ8FJ4U9BVgFb4WLhaIFsQW+BccF0QXZhfQGDIYxhlKGbgaCBpqGqgbChtmG8ocJhyQHPQdRB2MHdoeBh40HlYeoB7SHwgfNB9wH6YgCiBMIIYguCDmISAheiGwIeIiCiJKIqoi8iNYI4YjqCPuJBwkSiRwJOYlOiVmJZAl/CZEJoAmxicSJ1gnmifAKA4oPijQKSApSimOKcwqBiqMKuorQCuCK/QsRiyELLYs/i1ALX4tsC4KLmIuji7OLxgvRC9mL4Ivpi+8L+4wGjBIMGww0DESMU4xgDIQMnoysjLiMyQzYjOSM7Y0GDRMNJY1IDVONaQ2AjY8NnY27DdaN+w4YjiIOKw45jkkOVo5ijnAOfg6QDqAOro67DseO0Y7ijvCO/48NDxyPKY86D0aPUY9bD20Pew+LD5ePpY+xD72Pyo/Xj+GP64/zj/wQBpAQkBqQLhBFkFuQZ5CQEJ0Qp5C0EL6QzZDZEO4Q/ZELkReRKRE+EVSRaRF9EZERoZGtEbcRxBHZEeqR9BH6kguSHZI0EkMSZJKGkqASshLIEtUS8ZMOkysTQBNRk2GTdJOAk52TspO+k8gT4RP3lBGUK5Q/lFGUgBSqFMSU05TolPWVFJUnFU+VaJV8FaSV2pYeljuWWxaGlpMWvRb5FxSXJJcrl1+XcxeDF7SX1xfzGCUYbZiIGKiY0hjzGRuZPZlrmX8ZpJm5GccZ2ZnlGfAZ+BoVGiwaTZpjGooaqRq0Gr8a1ZrmmxibRZtbG26beBuIm5ibtBvMG9kb45vzm/+cDxwdHDOcRpxbnHCcihyinLoczhzmnPodCZ0fHS+dPh1OHVudcx2IHZgdox22ncUd3h3vngWeE54oHjUeUh5lHmuekB6kHq8evx7Kntqe5h7tHwqfHh80n0MfWJ9mn3KffR+IH5EfnZ+on74fzB/gn+0f+6ARoCkgOSBQIF+gZKBuIHSgeqCMoJygoCClIK0gtSDMoOQg8KEDoRahJCEtIT4hSqFbIWchd6GNIZ6hrqG9Ic0h3iHsogIiFaIrokAiUaJhIn4il6KporkiyCLdovCi/CMSIyojOSNGI2cjeiOMo58jtiPFo9uj6yQBJBCkJiQ3pD6kRCRjpHikjSSdpLCkxyTVJO2k/iUWJSalNaVFpVylcqWLpZ2lriXGJekl/iYepjWmVCZrJn4mmKa3Js2m8CcLJxwnLSc9p0qnZid9J4qnoae/p9Cn4af3KBcoJygyqEEoVShrqHwoiyiTKKoowqjNKNeo5yjwqRApK6lBKU8paymAKYupk6mqqbgp1anrKfSqBioQKh8qLKo4qkeqTapTqlqqY6p0KoAqjyqXqqAqrqq6qsyq3Sr0qwOrE6seqzArQKtJq1orb6uFK5qrsCu9q8sr2KvmK/qsDCwZLCSsMyxErFYsZCyCrJ2swazQrOitBC0XLSMtQ61TLV8td62HrbAt1y3jre4t+q4FHicY2BkYGDqZTjGwMMAAkxAzAWEDAz/wXwGACvLAngAeJxtkb1u2zAUhY8cJ2lioIMLBEiniw5ZCssdggxZCnTL6iE7LVOOAIo0SCqIHqvv0Gfo2KlDn6BzDynWKJBKEPWdc/9ICcASP1Bhui74TFyRLwrPcM6siU/oXheekz8UPsUCHwuf0b8rfAmPz4UXeIev7FDN05wlvhWuyN8Lz/AWvwqf0P9deI5l9abwKa6q94XP6H8qfImf1ZfCC9zMbja6714eGmd9go6w0fvBKH/UR3jUPnTOym19908yQVK9dEGUBB3FteIO2q6CG3yjxeohemVWIY5GSxhD1D1f/daZINqorfMqajNK41Ub9U5a52WnQ7e3HCjK7qietWFPH2p5ivFwv163zrLIuLpxPTbQ6NHhBQ9o4GD5Rf86XXFSzh4DDBSjr+OvnUc6HoE6KcEtav6z/3eeHDnOF+rAVfEJjEe+Hdq8HqgtVvQd9+NZoelbrgPzPGtMjkaMJJ07jFmnOZPqsWW1yTN0PlPSqTZmPdJvsm6zs6Nuc4aQdT7VPs/0ZZ8256TYc+4w7TNFa/pP7BLp3GPNu81nnCalzDqfuv8DluGfuHicdVoFeBy3Es6M0sZsB5q0SZnpCk7KzMzM3bvdu9t6b3Ve8MUpM/dx+5iZmZmZmZmZ+T1pRlppbdff5++b/19pVjAk7S3DZfw3tmzJP3wYEAQsh61ga1gBQzAMIzAKYzAOEzAJU7ASVsFqWAPbwFpYB9vCdrAeNsD2sAPsCDvBzrAL7Aq7we6wB+wJe8HesA/sC/vB/tCAA+BAOAgOhmnYCJvgEDgUDoPD4Qg4Eo6Co+EYOBaOg+PhBDgRToKT4RQ4FU6D0+EMOBPOgrPhHDgXzoPz4QK4EC6Ci+ESuBQug8vhCrgSroKr4Rq4Fq6D6yGAJrQghAja0IEuxHADzEACPUhBQh9mIYMcCihhDgawGeZhC9wIN8HNcAvcCrfB7XAH3Al3wd1wD9wL98H98AA8CA/Bw/AIPAGeCE+CJ8NT4KnwNHgUHoOnwzPgmfAseDY8B54Lz4PnwwvghfAieDG8BF4KL4OXwyvglfAqeDW8Bl4Lr4PXwxvgjfAmeDO8Bd4Kb4O3wzvgnfAueDe8B94L74P3wwfgg/Ah+DB8BD4KH4OPwyfgk/Ap+DR8Bj4Ln4PPwxfgi/Al+DJ8Bb4KX4Ovwzfgm/At+DZ8B74L34Pvww/gh/Aj+DH8BH4KP4Ofwy/gl/Ar+DX8Bn4Lv4Pfwx/gj/An+DP8Bf4Kf4O/wz/gn/Av+Df8B/4L/8NlCIgocDluhVvjChzCYRzBURzDcZzASZzClbgKV+Ma3AbX4jrcFrfD9bgBt8cdcEfcCXfGXXBX3A13xz1wT9wL98Z9cF/cD/fHBh6AB+JBeDBO40bchIfgoXgYHo5H4JF4FB6Nx+CxeBwejyfgiXgSnoyn4Kl4Gp6OZ+CZeBaejefguXgeno8X4IV4EV6Ml+CleBlejlfglXgVXo3X4LV4HV6PATaxhSFG2MYOdjHGG3AGE+xhihL7OIsZ5lhgiXM4wM04j1vwRrwJb8Zb8Fa8DW/HO/BOvAvvxnvwXrwP78cH8EF8CB/GR/AJ+ER8Ej4Zn4JPxafho/gYPh2fgc/EZ+Gz8Tn4XHwePh9fgC/EF+GL8SX4UnwZvhxfga/EV+Gr8TX4Wnwdvh7fgG/EN+Gb8S34Vnwbvh3fge/Ed+G78T34Xnwfvh8/gB/ED+GH8SP4UfwYfhw/gZ/ET+Gn8TP4Wfwcfh6/gF/EL+GX8Sv4Vfwafh2/gd/Eb+G38Tv4Xfwefh9/gD/EH+GP8Sf4U/wZ/hx/gb/EX+Gv8Tf4W/wd/h7/gH/EP+Gf8S/4V/wb/h3/gf/Ef+G/8T/4X/yfWCZAoBBiudhKbC1WiCExLEbEqBgT42JCTIopsVKsEqvFGrGNWCvWiW3FdmK92CC2FzuIHcVOYmexi9hV7CZ2F3uIPcVeYm+xj9hX7Cf2Fw1xgDhQHCQOFtNio9gkDhGHisPE4eIIcaQ4ShwtjhHHiuPE8eIEcaI4SZwsThGnitPE6eIMcaY4S5wtzhHnivPE+eICcaG4SFwsLhGXisvE5eIKcaW4SlwtrhHXiuvE9SIQTdESoYhEW3REV8TiBjEjEtETqZCiL2ZFJnJRiFLMiYHYLObFFnGjuEncLG4Rt4rbxO3iDnGnuEvcLe4R94r7xP3iAfGgeEg8LB5ZNhVkmRw0srjTLRpJnEaTTIRykPo4idr8fJxx2fefKpQTXuWrY2qlp7DGkMp8kZp2nCQL1GiqrsZjjBrNjOUzcb8aGgE3sQnC1bwYVtOqumo9fleNva4OUldvsKWnfBtvaG4EruEgDiOi1nizqsj1LZmlUUYT0RpCWTYTfrTBPWK93rO13ks9ep2/lobXw14dbe4HaVgb90JOt1truAWTWYLWrc3MO7LRltkgyEJ/mkWZpY1m0JrxB0ak33hVpaJqOtyVvciT9JtGSdpErJXJLEjOe7Ga5zTbW42hDW6WcRLGace08DGbVtqKo7RodIIiMjbrM2xshczsKyqgn0z1gjhplGkWBTyjSSJa3chMZ4JwHqWhB2U/ShdCsjbXeJFymounXONxwkHIuh3y2iYyj/yBESZTjtOm3NwIslY3nuMmCygakepQhg3ZbvN4HdRPRxh6IlkAqylTX/ciksYYFEXQ6vb0YnNscJjWvZ/JdmyMuwI0LquG98SD+umKgPWNBGRpNL5eFAYJa2WRm66ei7K4HUehssCwEy3JGUvlN+SFtdQFFDlQM8jU/gSZMp5Mlv2IV2TK0dOLCZqPI2g+DtI+N6Wc6QUZv9chGmwrSJTBUHtrdB5X7b/jorlqvSuOhzXaTgLrJ2uKLA7STpmop0QvSZJ3ml4kdxLZVItL2oxsPDiVZWY9mGSKIa1SuVNPhbk8yubiFo91MUuLW402V1MNSxsLF9O04erZTG4tJ06LKKsDapRF/WSebYVFzgnaA/tJkBrX8TD1cjYw4vZ+Ku8GM1GjqyIlv7ZGsDPJ/ryXpRxk5486QV+tTWRCQwVpTP0gzxtzQRKbOONhCmOEVSCh0EZhrMa4NiqYx5kxzDpDzqH0tWx4rgBtobLHorGRt9DIjp/2+Gk7nzwPlPtstPOxsPZ0uv7UhFXS44XVGkFzIaIW+msMrZnHsLk7THMN41xZWl4HTlc31qF+fgmGtM+pJC4bxJN2D7u3z0lrvj5m0+lHwYwxKBJpBaMwrlbTyLResyptJY0qcTionw7lMVdCJNCu6ABhyiMrUyghnToUUyipEA2jmZV5lwfHIi0Mi9N1QJvSD5QrNVyvGqGbD4eZ5DGwxMEsUc5vM4pDvKsykeSa1l3rDOlsWZ2qlCyaUtsnj2eEX++JnERUfCgKm0QMME/SwvpbBThbBJ24xZpY5OovLWIVUVszgzi3aaFGUd9CyoTNyIg2kXr9Jup9JsJMhdBqsTzIwTPo9czsrczeFmctY9tW5hWSprwcV4vWi1MbkFtllsusJnO8UwZSuNAz3pK9fml3YKgX8EqMKUGnHrPAVfMRF6VGw6gK4qNFoOpP4xthoFCQW1/1MfXTcd7Oysg0sq7e3TCrCgYPsxvoqB+ktjSz0IJqIcZUQq3ARN4tC1cJT7VVgIwyygsm+yZlpLauYKseHqhigBeGJGu6Q5mJFiSQG3b6htECBbIwyLtsoxwGawRnTxfCrKz5NbkyrJn5RiqVtdoSbxFJxmNKpNyM3kH3tIg2+08J0vhc4412MRzh+utU5fUnaMw67vN0jFlbyNtaqq2cN9vKMjmeMrfYWm4FaDxkYDpeVaWTR5BxFzKUvC8kuVn4vXyCRkJqTPIyMtddWnb1uINkbm2ZhMoU7fL7mMKVwa7yqjM8Nmaqd9QItgAm2AJY5lVK4k7aaEW6XBmhLSG1k3Ea6goujFoqHeaRxXFqMDXVpDLsuFAL7Krq6eW6LFrRVUZYBJ3hfCYqVA2bdkYHQWKd1cqmLk1nXEHgQZqb8hnl7UqTtR6f4OJAVcEyNSGHZdLrGpJeB2ld867s93XZ0jQN6gz7h2P0NIx/LCApbFdky9bXCygaaaHCbdfYqpFpjnP6PiAOetKeynyCJq0JlZQGNgzVCJqtI2i2DlLUmLPJey62SXqzKhZSc/RwiOZdoVAmug6neS8kqbZWI1QO10rVv0sUi1kuuNR6aLuVsbFSn6A9qV6hu9Ke1Biq0Fl3VGbSf+USNHmXrjn7qny2ScLDNKZBQDk/CWx54RMm0ZnhDlfjVBW5dMW5NF443InN7Q9LtMrTmxpddRDhkO0Qnapq9sY3Dws50tuUA06uLJHfdiNtVOwRFbA1ZhLPmLhnAc2Vm/XLxBQINYLsU0WDfjBvQmaqioPY3qEkcVMl04Y7gU8E/X6DryloHRQ0WzHSDOKwNJVXrDqqf1u5Z/biZVyfGKpzxIhLt+NKbDbtbdO4OkhmlInIBNtBK6Lw6e38eFsdLCjP07DbSVnYsmK0ExfdsmlkKTumy5SR1XHLZJw4VYesThb0WGWczsV5bGLKcC8qApJWzM7y8zwN+lVRPlrEM4UpWcaKQexeP4iqRuNGNlXkIIqbnGEmzQO77uMDhXK9uNRwSzfu8lqOzcuyKJv25Bb0G8pOqqNNBcmPLCxis9x1hgtTVUD3jWlXoNa7zG2BXGPIUjJZ+ZSViacTrOGNbMrgbMbudgXIQzKpjlv6BTT7CpGfafs0hwUWKZa1TEQigdq5c/RI3As6NZGmxKJnNXWGAmiiD9GtoG9W2EEaJp+8jEk4RK9nRO9kkdw2sSbNEqeqQBXWgfEGlvncxrIt+3xMY1OeGnrndgdpcXvq8GC7VoDPGApM+yLnDpmUvcirTn2C8w8TvdJ4Xo3gdMOEOf55kNZbuawqY1tBYZ2ozlDqqDF2+ItZLgK0p3rbVyPafO+gjLO2wzWGtKhw1a9p8QmaVTRbqlC3xdi9B2lHVXnDvjis/DP3JH5qYyFLfEJ2d7pWprYq2vArWOITkjo0Kq/I7fnFw6aEy5omHluZZhWnCvXcUtcIsl0q6arzeIX0sw0V0sWcOcoV9uvA0s+4cFT1qVVZASoeql7eSi8idcvt6mq95ks/oVXSr3ocTLvOt5GPy5CtZEEYy0ZTJQprnTWG3MWrt1n0voGMuCvPIVu3r61m2CuTIrbJcAmatiQvm0UWtMxNAtkZ72zZT6S5kBrX/lih1RVySXilae2l5UR2VKC2O7NKQZU2altRp+yBuBtHSViTTZVMsqok7bVVjam1cStWY9j1mKkSSI2gPmGkDgRRo1kltTpDm+0xCzHN1mJ9Xzq9FEW1ur4WaehbyYG034jqFLkbUcZ1jUwDJ7lME1sB1ghyjWg+cgd4DSqBY4wSnAF5sNaZrSTS9/9mFA7Rsy1S9hp6I8kDCdlsbkG9HVeu3cBWbCyaHdSi7zQ1hnoGqubvmVqPRNKu6qte02YBh2h3GLlPvx6mfWA1gyBLbWWwgKI3tPlabtoWewaZPQrsqXYykdL/Putj0mPacp09lUUqvHrNhytDHHY2GrTUcTJ1V5k1gpRS2+rjWIVo+oRUBCvNNQ3rVWcnOVhM0JC9HrQahMvUa7KAcmpov8LFhO60zg5bl3DeJi/F01bTdyXeahZpu6KepJTSVSmPa9UFFB1qLJXqFJQsyVEUslyZOn2LSJqOJXN7T+8TNN6BOlWwjQ1ZYZLyqncv72EqIvPS9NCCyd/SlziaagNplgmfIUZm1BGTDXFoxt45KdeytxprXHN3ohwr1F7E5lKgAsa9ozCpDL1CXDNGQduTdIv1+mudyhlqd7OoJTtpXOX8x3lEEUUR89VFmAU0z1Cam1qWaK/UISgsuXZomaJ8IccVjGwHpoLREltIlik1NYeuUzTP2TLKq4E7RA6d99URzFyhGZl8qZ/JrjpIFpH9MuUw1Rx+yWND7yKSoi/ZQTdI2jammiKrjnTT7Ren7mai76ZMDIyywhd1l+VNmYRbx4UqGlsrdJGur73aUn8lCJTpzY+QTJ8bhknMVXE5XKpiJ+P3F5k6rRfqmFx2uiN8N6d/ETHKIoWrMXdL15j2wcYJAiqBRdrzpxmWqSEmTQEzW6rjdN7IhMok6n+j+t+k/g9R/4eq/4PHfC1rqt+Y1OKG9xMQ/w7G+/XJYpp+2eHXIQtV6wVcSjXd+ixW7dG+atrkluz1SuUD5nTvIBtZqyulKbeMTEZGv+vgO5GFmHyHf14wXQfkYnSCD/iWowJkEPrL7Gic9in/qoJnzL/VG/Pv/MwtjlFvgX8tw3WTPjwn7rcmNYI8U9+HsGeSxJ5uvxCyRNvSVlobXZnFW5Ql0o8VHocmDyN6LtL36FXbRaRuuWzZ/wFvvfvjAA==") format("woff"); +} + +.ri-arrow-right-line:before { content: "\ea6c"; } +.ri-arrow-down-line:before { content: "\ea4c"; } +.ri-arrow-left-line:before { content: "\ea60"; } +.ri-arrow-up-line:before { content: "\ea76"; } +.ri-arrow-up-s-line:before { content: "\ea78"; } +.ri-arrow-right-s-line:before { content: "\ea6e"; } +.ri-arrow-down-s-line:before { content: "\ea4e"; } +.ri-arrow-left-s-line:before { content: "\ea64"; } +.ri-arrow-up-s-fill:before { content: "\ea77"; } +.ri-arrow-right-s-fill:before { content: "\ea6d"; } +.ri-arrow-down-s-fill:before { content: "\ea4d"; } +.ri-arrow-left-s-fill:before { content: "\ea63"; } +.ri-skip-up-line:before { content: "\f367"; } +.ri-skip-right-line:before { content: "\f365"; } +.ri-skip-down-line:before { content: "\f361"; } +.ri-skip-left-line:before { content: "\f363"; } +.ri-skip-up-fill:before { content: "\f366"; } +.ri-skip-right-fill:before { content: "\f364"; } +.ri-skip-down-fill:before { content: "\f360"; } +.ri-skip-left-fill:before { content: "\f362"; } +.ri-arrow-up-down-line:before { content: "\ea74"; } +.ri-arrow-left-right-line:before { content: "\ea62"; } +.ri-arrow-up-wide-line:before { content: "\f498"; } +.ri-arrow-down-wide-line:before { content: "\f492"; } +.ri-corner-up-left-double-line:before { content: "\f313"; } +.ri-corner-up-right-double-line:before { content: "\f317"; } +.ri-arrow-left-double-line:before { content: "\f2e3"; } +.ri-arrow-right-double-fill:before { content: "\f2e4"; } +.ri-expand-up-down-line:before { content: "\f327"; } +.ri-expand-up-down-fill:before { content: "\f326"; } +.ri-expand-left-right-line:before { content: "\f323"; } +.ri-expand-left-right-fill:before { content: "\f322"; } +.ri-arrow-go-forward-line:before { content: "\ea5a"; } +.ri-arrow-turn-back-line:before { content: "\f2e7"; } +.ri-arrow-turn-forward-line:before { content: "\f2e9"; } +.ri-arrow-go-back-line:before { content: "\ea58"; } +.ri-home-line:before { content: "\ee2b"; } +.ri-home-fill:before { content: "\ee26"; } +.ri-home-4-line:before { content: "\ee1d"; } +.ri-home-4-fill:before { content: "\ee1c"; } +.ri-home-smile-2-line:before { content: "\ee2d"; } +.ri-home-smile-2-fill:before { content: "\ee2c"; } +.ri-building-2-line:before { content: "\eb09"; } +.ri-building-2-fill:before { content: "\eb08"; } +.ri-ancient-gate-line:before { content: "\ea32"; } +.ri-ancient-gate-fill:before { content: "\ea31"; } +.ri-store-2-line:before { content: "\f1a5"; } +.ri-store-2-fill:before { content: "\f1a4"; } +.ri-mail-unread-line:before { content: "\ef02"; } +.ri-mail-check-line:before { content: "\eeee"; } +.ri-mail-send-line:before { content: "\eefc"; } +.ri-mail-open-line:before { content: "\eefa"; } +.ri-mail-open-fill:before { content: "\eef9"; } +.ri-mail-send-fill:before { content: "\eefb"; } +.ri-mail-unread-fill:before { content: "\ef01"; } +.ri-mail-check-fill:before { content: "\eeed"; } +.ri-mail-add-line:before { content: "\eeec"; } +.ri-mail-add-fill:before { content: "\eeeb"; } +.ri-mail-close-line:before { content: "\eef0"; } +.ri-mail-close-fill:before { content: "\eeef"; } +.ri-inbox-archive-line:before { content: "\ee4d"; } +.ri-inbox-archive-fill:before { content: "\ee4c"; } +.ri-cloud-off-line:before { content: "\eb9f"; } +.ri-cloud-off-fill:before { content: "\eb9e"; } +.ri-cloud-fill:before { content: "\eb9c"; } +.ri-cloud-line:before { content: "\eb9d"; } +.ri-inbox-unarchive-line:before { content: "\ee51"; } +.ri-inbox-unarchive-fill:before { content: "\ee50"; } +.ri-attachment-line:before { content: "\ea86"; } +.ri-attachment-fill:before { content: "\ea85"; } +.ri-profile-line:before { content: "\f02d"; } +.ri-profile-fill:before { content: "\f02c"; } +.ri-archive-2-line:before { content: "\f3a7"; } +.ri-archive-2-fill:before { content: "\f3a6"; } +.ri-at-line:before { content: "\ea83"; } +.ri-award-fill:before { content: "\ea89"; } +.ri-medal-fill:before { content: "\ef27"; } +.ri-medal-2-fill:before { content: "\ef25"; } +.ri-verified-badge-fill:before { content: "\f3e8"; } +.ri-verified-badge-line:before { content: "\f3e9"; } +.ri-archive-stack-line:before { content: "\f428"; } +.ri-archive-stack-fill:before { content: "\f427"; } +.ri-bar-chart-grouped-line:before { content: "\ea9b"; } +.ri-bar-chart-grouped-fill:before { content: "\ea9a"; } +.ri-bar-chart-2-line:before { content: "\ea96"; } +.ri-bar-chart-2-fill:before { content: "\ea95"; } +.ri-bar-chart-line:before { content: "\ea9e"; } +.ri-bar-chart-fill:before { content: "\ea99"; } +.ri-bookmark-line:before { content: "\eae5"; } +.ri-bookmark-fill:before { content: "\eae4"; } +.ri-calendar-check-line:before { content: "\eb23"; } +.ri-calendar-close-line:before { content: "\f38e"; } +.ri-calendar-event-line:before { content: "\eb25"; } +.ri-calendar-2-line:before { content: "\eb21"; } +.ri-flag-2-line:before { content: "\ed39"; } +.ri-triangular-flag-line:before { content: "\f54a"; } +.ri-triangular-flag-fill:before { content: "\f549"; } +.ri-flag-2-fill:before { content: "\ed38"; } +.ri-global-line:before { content: "\edcf"; } +.ri-global-fill:before { content: "\edce"; } +.ri-honour-line:before { content: "\ee35"; } +.ri-honour-fill:before { content: "\ee34"; } +.ri-customer-service-line:before { content: "\ec0e"; } +.ri-customer-service-fill:before { content: "\ec0d"; } +.ri-calendar-schedule-line:before { content: "\f3f3"; } +.ri-calendar-schedule-fill:before { content: "\f3f2"; } +.ri-links-line:before { content: "\eeb8"; } +.ri-printer-line:before { content: "\f029"; } +.ri-printer-fill:before { content: "\f028"; } +.ri-reply-line:before { content: "\f07a"; } +.ri-reply-fill:before { content: "\f079"; } +.ri-send-plane-line:before { content: "\f0da"; } +.ri-send-plane-fill:before { content: "\f0d9"; } +.ri-stack-line:before { content: "\f181"; } +.ri-stack-fill:before { content: "\f180"; } +.ri-shake-hands-line:before { content: "\f3ab"; } +.ri-shake-hands-fill:before { content: "\f3aa"; } +.ri-copyright-line:before { content: "\ebe2"; } +.ri-copyright-fill:before { content: "\ebe1"; } +.ri-megaphone-line:before { content: "\f385"; } +.ri-megaphone-fill:before { content: "\f384"; } +.ri-pass-valid-line:before { content: "\f38b"; } +.ri-pass-valid-fill:before { content: "\f38a"; } +.ri-pass-pending-line:before { content: "\f389"; } +.ri-pass-pending-fill:before { content: "\f388"; } +.ri-pass-expired-line:before { content: "\f387"; } +.ri-pass-expired-fill:before { content: "\f386"; } +.ri-id-card-line:before { content: "\f4e9"; } +.ri-id-card-fill:before { content: "\f4e8"; } +.ri-chat-3-line:before { content: "\eb51"; } +.ri-chat-3-fill:before { content: "\eb50"; } +.ri-chat-2-line:before { content: "\eb4f"; } +.ri-chat-2-fill:before { content: "\eb4e"; } +.ri-message-3-line:before { content: "\ef46"; } +.ri-message-3-fill:before { content: "\ef45"; } +.ri-message-2-line:before { content: "\ef44"; } +.ri-message-2-fill:before { content: "\ef43"; } +.ri-chat-unread-line:before { content: "\f52a"; } +.ri-chat-unread-fill:before { content: "\f529"; } +.ri-chat-smile-2-line:before { content: "\eb6f"; } +.ri-chat-smile-2-fill:before { content: "\eb6e"; } +.ri-chat-smile-line:before { content: "\eb73"; } +.ri-chat-smile-fill:before { content: "\eb72"; } +.ri-discuss-fill:before { content: "\ec39"; } +.ri-discuss-line:before { content: "\ec3a"; } +.ri-chat-history-line:before { content: "\eb61"; } +.ri-chat-history-fill:before { content: "\eb60"; } +.ri-video-chat-line:before { content: "\f27e"; } +.ri-video-chat-fill:before { content: "\f27d"; } +.ri-chat-voice-fill:before { content: "\eb76"; } +.ri-chat-voice-line:before { content: "\eb77"; } +.ri-speak-fill:before { content: "\f36e"; } +.ri-speak-line:before { content: "\f36f"; } +.ri-edit-2-line:before { content: "\ec80"; } +.ri-edit-2-fill:before { content: "\ec7f"; } +.ri-quill-pen-line:before { content: "\f04a"; } +.ri-quill-pen-fill:before { content: "\f049"; } +.ri-sip-line:before { content: "\f13e"; } +.ri-sip-fill:before { content: "\f13d"; } +.ri-markup-line:before { content: "\ef20"; } +.ri-markup-fill:before { content: "\ef1f"; } +.ri-edit-box-line:before { content: "\ec82"; } +.ri-edit-box-fill:before { content: "\ec81"; } +.ri-brush-line:before { content: "\eb01"; } +.ri-brush-fill:before { content: "\eb00"; } +.ri-brush-2-fill:before { content: "\eafa"; } +.ri-brush-2-line:before { content: "\eafb"; } +.ri-paint-brush-line:before { content: "\efc1"; } +.ri-paint-brush-fill:before { content: "\efc0"; } +.ri-drop-line:before { content: "\ec6a"; } +.ri-drop-fill:before { content: "\ec69"; } +.ri-blur-off-line:before { content: "\eace"; } +.ri-blur-off-fill:before { content: "\eacd"; } +.ri-color-filter-line:before { content: "\f42f"; } +.ri-color-filter-fill:before { content: "\f42e"; } +.ri-crop-line:before { content: "\ec02"; } +.ri-artboard-2-line:before { content: "\ea7a"; } +.ri-paint-line:before { content: "\efc3"; } +.ri-paint-fill:before { content: "\efc2"; } +.ri-palette-line:before { content: "\efc5"; } +.ri-palette-fill:before { content: "\efc4"; } +.ri-pantone-line:before { content: "\efc7"; } +.ri-pantone-fill:before { content: "\efc6"; } +.ri-magic-line:before { content: "\eeea"; } +.ri-magic-fill:before { content: "\eee9"; } +.ri-anticlockwise-line:before { content: "\ea3c"; } +.ri-anticlockwise-fill:before { content: "\ea3b"; } +.ri-tools-line:before { content: "\f21b"; } +.ri-tools-fill:before { content: "\f21a"; } +.ri-clockwise-line:before { content: "\eb95"; } +.ri-clockwise-fill:before { content: "\eb94"; } +.ri-drag-drop-line:before { content: "\ec5e"; } +.ri-drag-drop-fill:before { content: "\ec5d"; } +.ri-hammer-fill:before { content: "\edee"; } +.ri-hammer-line:before { content: "\edef"; } +.ri-circle-line:before { content: "\f3c2"; } +.ri-circle-fill:before { content: "\f3c1"; } +.ri-code-line:before { content: "\eba9"; } +.ri-code-fill:before { content: "\eba8"; } +.ri-terminal-line:before { content: "\f1f8"; } +.ri-terminal-fill:before { content: "\f1f7"; } +.ri-cursor-line:before { content: "\ec0a"; } +.ri-cursor-fill:before { content: "\ec09"; } +.ri-smartphone-line:before { content: "\f15a"; } +.ri-computer-line:before { content: "\ebca"; } +.ri-mac-line:before { content: "\eee6"; } +.ri-macbook-line:before { content: "\eee8"; } +.ri-phone-line:before { content: "\efec"; } +.ri-phone-fill:before { content: "\efe9"; } +.ri-device-line:before { content: "\ec2e"; } +.ri-tablet-line:before { content: "\f1e0"; } +.ri-database-2-line:before { content: "\ec16"; } +.ri-database-2-fill:before { content: "\ec15"; } +.ri-server-line:before { content: "\f0e0"; } +.ri-server-fill:before { content: "\f0df"; } +.ri-hard-drive-fill:before { content: "\edfa"; } +.ri-hard-drive-line:before { content: "\edfb"; } +.ri-qr-scan-2-line:before { content: "\f03f"; } +.ri-qr-scan-line:before { content: "\f041"; } +.ri-qr-code-line:before { content: "\f03d"; } +.ri-barcode-line:before { content: "\eaa2"; } +.ri-shut-down-line:before { content: "\f126"; } +.ri-fingerprint-line:before { content: "\ed31"; } +.ri-bluetooth-line:before { content: "\eacc"; } +.ri-wifi-line:before { content: "\f2c0"; } +.ri-wifi-off-line:before { content: "\f2c2"; } +.ri-rss-line:before { content: "\f09f"; } +.ri-rss-fill:before { content: "\f09e"; } +.ri-gps-line:before { content: "\eddb"; } +.ri-gps-fill:before { content: "\edda"; } +.ri-dashboard-3-line:before { content: "\ec12"; } +.ri-dashboard-3-fill:before { content: "\ec11"; } +.ri-file-2-line:before { content: "\ecc3"; } +.ri-file-2-fill:before { content: "\ecc2"; } +.ri-sticky-note-add-line:before { content: "\f466"; } +.ri-sticky-note-add-fill:before { content: "\f465"; } +.ri-file-list-line:before { content: "\ecf1"; } +.ri-file-list-fill:before { content: "\ecf0"; } +.ri-file-text-line:before { content: "\ed0f"; } +.ri-file-text-fill:before { content: "\ed0e"; } +.ri-file-list-3-line:before { content: "\ecef"; } +.ri-file-list-3-fill:before { content: "\ecee"; } +.ri-file-copy-line:before { content: "\ecd5"; } +.ri-file-copy-fill:before { content: "\ecd4"; } +.ri-clipboard-line:before { content: "\eb91"; } +.ri-clipboard-fill:before { content: "\eb90"; } +.ri-survey-line:before { content: "\f1c7"; } +.ri-survey-fill:before { content: "\f1c6"; } +.ri-article-line:before { content: "\ea7e"; } +.ri-article-fill:before { content: "\ea7d"; } +.ri-book-marked-line:before { content: "\ead9"; } +.ri-book-marked-fill:before { content: "\ead8"; } +.ri-todo-line:before { content: "\f217"; } +.ri-todo-fill:before { content: "\f216"; } +.ri-file-marked-line:before { content: "\ecf5"; } +.ri-file-marked-fill:before { content: "\ecf4"; } +.ri-book-3-line:before { content: "\ead5"; } +.ri-book-3-fill:before { content: "\ead4"; } +.ri-book-open-line:before { content: "\eadb"; } +.ri-book-open-fill:before { content: "\eada"; } +.ri-folder-add-line:before { content: "\ed5a"; } +.ri-folder-add-fill:before { content: "\ed59"; } +.ri-folder-check-line:before { content: "\f43e"; } +.ri-folder-check-fill:before { content: "\f43d"; } +.ri-folder-open-line:before { content: "\ed70"; } +.ri-folder-open-fill:before { content: "\ed6f"; } +.ri-folder-line:before { content: "\ed6a"; } +.ri-folder-fill:before { content: "\ed61"; } +.ri-align-center:before { content: "\ea25"; } +.ri-list-check:before { content: "\eeba"; } +.ri-indent-decrease:before { content: "\ee54"; } +.ri-indent-increase:before { content: "\ee55"; } +.ri-list-indefinite:before { content: "\f399"; } +.ri-attachment-2:before { content: "\ea84"; } +.ri-link:before { content: "\eeb2"; } +.ri-hashtag:before { content: "\edfc"; } +.ri-sketching:before { content: "\f35f"; } +.ri-wallet-line:before { content: "\f2ae"; } +.ri-wallet-fill:before { content: "\f2ad"; } +.ri-bank-card-line:before { content: "\ea92"; } +.ri-bank-card-fill:before { content: "\ea91"; } +.ri-price-tag-3-line:before { content: "\f023"; } +.ri-price-tag-3-fill:before { content: "\f022"; } +.ri-coupon-line:before { content: "\ebee"; } +.ri-coupon-fill:before { content: "\ebed"; } +.ri-price-tag-line:before { content: "\f025"; } +.ri-price-tag-fill:before { content: "\f024"; } +.ri-shopping-bag-line:before { content: "\f118"; } +.ri-shopping-bag-fill:before { content: "\f117"; } +.ri-shopping-basket-line:before { content: "\f11c"; } +.ri-shopping-basket-fill:before { content: "\f11b"; } +.ri-shopping-cart-line:before { content: "\f120"; } +.ri-shopping-cart-fill:before { content: "\f11f"; } +.ri-trophy-line:before { content: "\f22f"; } +.ri-trophy-fill:before { content: "\f22e"; } +.ri-vip-diamond-fill:before { content: "\f28f"; } +.ri-vip-diamond-line:before { content: "\f290"; } +.ri-vip-crown-2-line:before { content: "\f28c"; } +.ri-vip-crown-2-fill:before { content: "\f28b"; } +.ri-vip-crown-line:before { content: "\f28e"; } +.ri-vip-crown-fill:before { content: "\f28d"; } +.ri-vip-line:before { content: "\f292"; } +.ri-vip-fill:before { content: "\f291"; } +.ri-exchange-line:before { content: "\ecad"; } +.ri-exchange-fill:before { content: "\ecaa"; } +.ri-exchange-dollar-line:before { content: "\eca9"; } +.ri-exchange-dollar-fill:before { content: "\eca8"; } +.ri-money-cny-circle-line:before { content: "\ef61"; } +.ri-money-cny-circle-fill:before { content: "\ef60"; } +.ri-copper-coin-line:before { content: "\ebdc"; } +.ri-copper-coin-fill:before { content: "\ebdb"; } +.ri-exchange-cny-line:before { content: "\eca7"; } +.ri-exchange-cny-fill:before { content: "\eca6"; } +.ri-money-euro-circle-line:before { content: "\ef69"; } +.ri-money-euro-circle-fill:before { content: "\ef68"; } +.ri-red-packet-line:before { content: "\f060"; } +.ri-red-packet-fill:before { content: "\f05f"; } +.ri-water-flash-line:before { content: "\f2b0"; } +.ri-water-flash-fill:before { content: "\f2af"; } +.ri-coin-line:before { content: "\ebb2"; } +.ri-coin-fill:before { content: "\ebb1"; } +.ri-stock-line:before { content: "\f19d"; } +.ri-stock-fill:before { content: "\f19c"; } +.ri-gift-line:before { content: "\edbb"; } +.ri-gift-fill:before { content: "\edba"; } +.ri-24-hours-line:before { content: "\ea02"; } +.ri-24-hours-fill:before { content: "\ea01"; } +.ri-shopping-bag-4-line:before { content: "\f511"; } +.ri-shopping-bag-4-fill:before { content: "\f510"; } +.ri-bowl-line:before { content: "\f42a"; } +.ri-bowl-fill:before { content: "\f429"; } +.ri-heart-3-line:before { content: "\ee0b"; } +.ri-heart-3-fill:before { content: "\ee0a"; } +.ri-dislike-line:before { content: "\ec3c"; } +.ri-dislike-fill:before { content: "\ec3b"; } +.ri-heart-pulse-line:before { content: "\ee11"; } +.ri-heart-pulse-fill:before { content: "\ee10"; } +.ri-alipay-line:before { content: "\ea2c"; } +.ri-android-line:before { content: "\ea36"; } +.ri-alibaba-cloud-line:before { content: "\f4b8"; } +.ri-app-store-line:before { content: "\ea3e"; } +.ri-apple-line:before { content: "\ea40"; } +.ri-baidu-line:before { content: "\ea8c"; } +.ri-bilibili-line:before { content: "\eac0"; } +.ri-chrome-line:before { content: "\eb8d"; } +.ri-dingding-line:before { content: "\ec32"; } +.ri-drive-line:before { content: "\ec66"; } +.ri-dribbble-line:before { content: "\ec64"; } +.ri-evernote-line:before { content: "\eca3"; } +.ri-facebook-circle-line:before { content: "\ecbb"; } +.ri-firebase-line:before { content: "\f4d4"; } +.ri-flutter-line:before { content: "\ed48"; } +.ri-github-line:before { content: "\edcb"; } +.ri-google-line:before { content: "\edd5"; } +.ri-google-play-line:before { content: "\edd7"; } +.ri-instagram-line:before { content: "\ee66"; } +.ri-invision-line:before { content: "\ee6a"; } +.ri-meta-line:before { content: "\f343"; } +.ri-qq-line:before { content: "\f03b"; } +.ri-snapchat-line:before { content: "\f15c"; } +.ri-tiktok-line:before { content: "\f373"; } +.ri-twitter-line:before { content: "\f23b"; } +.ri-wechat-line:before { content: "\f2b6"; } +.ri-wechat-2-line:before { content: "\f2b4"; } +.ri-weibo-line:before { content: "\f2ba"; } +.ri-wechat-pay-line:before { content: "\f2b8"; } +.ri-whatsapp-line:before { content: "\f2bc"; } +.ri-zhihu-line:before { content: "\f2d9"; } +.ri-youtube-line:before { content: "\f2d5"; } +.ri-map-pin-2-line:before { content: "\ef0a"; } +.ri-map-pin-2-fill:before { content: "\ef09"; } +.ri-map-pin-time-line:before { content: "\ef18"; } +.ri-map-pin-time-fill:before { content: "\ef17"; } +.ri-pushpin-line:before { content: "\f039"; } +.ri-pushpin-fill:before { content: "\f038"; } +.ri-map-pin-user-line:before { content: "\ef1a"; } +.ri-map-pin-user-fill:before { content: "\ef19"; } +.ri-rocket-line:before { content: "\f096"; } +.ri-rocket-fill:before { content: "\f095"; } +.ri-planet-line:before { content: "\f39f"; } +.ri-planet-fill:before { content: "\f39e"; } +.ri-parking-line:before { content: "\efd0"; } +.ri-parking-fill:before { content: "\efcf"; } +.ri-road-map-line:before { content: "\f08e"; } +.ri-road-map-fill:before { content: "\f08d"; } +.ri-earth-line:before { content: "\ec7a"; } +.ri-earth-fill:before { content: "\ec79"; } +.ri-car-line:before { content: "\eb39"; } +.ri-car-fill:before { content: "\eb38"; } +.ri-plane-line:before { content: "\f005"; } +.ri-image-line:before { content: "\ee4b"; } +.ri-image-fill:before { content: "\ee4a"; } +.ri-image-circle-line:before { content: "\f413"; } +.ri-image-circle-fill:before { content: "\f412"; } +.ri-landscape-line:before { content: "\ee7d"; } +.ri-landscape-fill:before { content: "\ee7c"; } +.ri-video-on-line:before { content: "\f51e"; } +.ri-video-on-fill:before { content: "\f51d"; } +.ri-video-line:before { content: "\f282"; } +.ri-video-fill:before { content: "\f281"; } +.ri-live-line:before { content: "\eec0"; } +.ri-live-fill:before { content: "\eebf"; } +.ri-camera-line:before { content: "\eb31"; } +.ri-camera-fill:before { content: "\eb2e"; } +.ri-camera-off-line:before { content: "\eb33"; } +.ri-camera-off-fill:before { content: "\eb32"; } +.ri-headphone-line:before { content: "\ee05"; } +.ri-headphone-fill:before { content: "\ee04"; } +.ri-mic-off-line:before { content: "\ef52"; } +.ri-mic-off-fill:before { content: "\ef51"; } +.ri-mic-2-fill:before { content: "\ef4d"; } +.ri-mic-2-line:before { content: "\ef4e"; } +.ri-volume-down-line:before { content: "\f29c"; } +.ri-volume-down-fill:before { content: "\f29b"; } +.ri-volume-mute-line:before { content: "\f29e"; } +.ri-volume-mute-fill:before { content: "\f29d"; } +.ri-volume-up-line:before { content: "\f2a2"; } +.ri-volume-up-fill:before { content: "\f2a1"; } +.ri-notification-line:before { content: "\ef9a"; } +.ri-notification-fill:before { content: "\ef99"; } +.ri-notification-off-line:before { content: "\ef9c"; } +.ri-notification-off-fill:before { content: "\ef9b"; } +.ri-play-circle-line:before { content: "\f009"; } +.ri-play-circle-fill:before { content: "\f008"; } +.ri-pause-circle-line:before { content: "\efd6"; } +.ri-pause-circle-fill:before { content: "\efd5"; } +.ri-stop-circle-line:before { content: "\f19f"; } +.ri-stop-circle-fill:before { content: "\f19e"; } +.ri-equalizer-line:before { content: "\ec9d"; } +.ri-equalizer-fill:before { content: "\ec9c"; } +.ri-menu-line:before { content: "\ef3e"; } +.ri-menu-fill:before { content: "\ef3b"; } +.ri-apps-line:before { content: "\ea44"; } +.ri-apps-fill:before { content: "\ea43"; } +.ri-more-line:before { content: "\ef79"; } +.ri-more-fill:before { content: "\ef78"; } +.ri-more-2-line:before { content: "\ef77"; } +.ri-more-2-fill:before { content: "\ef76"; } +.ri-star-line:before { content: "\f18b"; } +.ri-star-fill:before { content: "\f186"; } +.ri-settings-2-line:before { content: "\f0e4"; } +.ri-settings-2-fill:before { content: "\f0e3"; } +.ri-forbid-line:before { content: "\ed95"; } +.ri-forbid-fill:before { content: "\ed94"; } +.ri-information-line:before { content: "\ee59"; } +.ri-information-fill:before { content: "\ee58"; } +.ri-checkbox-blank-circle-line:before { content: "\eb7d"; } +.ri-checkbox-blank-circle-fill:before { content: "\eb7c"; } +.ri-checkbox-line:before { content: "\eb85"; } +.ri-checkbox-fill:before { content: "\eb82"; } +.ri-checkbox-indeterminate-line:before { content: "\eb84"; } +.ri-checkbox-indeterminate-fill:before { content: "\eb83"; } +.ri-add-box-line:before { content: "\ea0f"; } +.ri-add-box-fill:before { content: "\ea0e"; } +.ri-checkbox-circle-line:before { content: "\eb81"; } +.ri-checkbox-circle-fill:before { content: "\eb80"; } +.ri-indeterminate-circle-line:before { content: "\ee57"; } +.ri-indeterminate-circle-fill:before { content: "\ee56"; } +.ri-add-circle-fill:before { content: "\ea10"; } +.ri-add-circle-line:before { content: "\ea11"; } +.ri-close-circle-line:before { content: "\eb97"; } +.ri-close-circle-fill:before { content: "\eb96"; } +.ri-radio-button-line:before { content: "\f050"; } +.ri-radio-button-fill:before { content: "\f04f"; } +.ri-check-line:before { content: "\eb7b"; } +.ri-check-double-line:before { content: "\eb79"; } +.ri-close-line:before { content: "\eb99"; } +.ri-add-line:before { content: "\ea13"; } +.ri-checkbox-multiple-line:before { content: "\eb89"; } +.ri-checkbox-multiple-fill:before { content: "\eb88"; } +.ri-subtract-line:before { content: "\f1af"; } +.ri-equal-line:before { content: "\f31f"; } +.ri-upload-line:before { content: "\f250"; } +.ri-download-line:before { content: "\ec5a"; } +.ri-download-cloud-line:before { content: "\ec58"; } +.ri-upload-cloud-line:before { content: "\f24e"; } +.ri-login-box-line:before { content: "\eed4"; } +.ri-logout-circle-line:before { content: "\eedc"; } +.ri-logout-circle-r-line:before { content: "\eede"; } +.ri-shield-line:before { content: "\f108"; } +.ri-shield-fill:before { content: "\f103"; } +.ri-shield-cross-line:before { content: "\f102"; } +.ri-shield-cross-fill:before { content: "\f101"; } +.ri-shield-check-line:before { content: "\f100"; } +.ri-shield-check-fill:before { content: "\f0ff"; } +.ri-shield-user-fill:before { content: "\f10b"; } +.ri-shield-user-line:before { content: "\f10c"; } +.ri-delete-bin-2-line:before { content: "\ec1e"; } +.ri-delete-bin-2-fill:before { content: "\ec1d"; } +.ri-delete-bin-fill:before { content: "\ec29"; } +.ri-delete-bin-line:before { content: "\ec2a"; } +.ri-delete-back-2-line:before { content: "\ec1a"; } +.ri-delete-back-2-fill:before { content: "\ec19"; } +.ri-lock-password-line:before { content: "\eed0"; } +.ri-lock-password-fill:before { content: "\eecf"; } +.ri-lock-2-line:before { content: "\eecc"; } +.ri-lock-2-fill:before { content: "\eecb"; } +.ri-lock-unlock-line:before { content: "\eed2"; } +.ri-lock-unlock-fill:before { content: "\eed1"; } +.ri-eye-off-line:before { content: "\ecb7"; } +.ri-eye-line:before { content: "\ecb5"; } +.ri-eye-fill:before { content: "\ecb4"; } +.ri-eye-close-line:before { content: "\ecb3"; } +.ri-eye-close-fill:before { content: "\ecb2"; } +.ri-eye-off-fill:before { content: "\ecb6"; } +.ri-search-2-line:before { content: "\f0cd"; } +.ri-search-2-fill:before { content: "\f0cc"; } +.ri-zoom-out-line:before { content: "\f2dd"; } +.ri-zoom-in-line:before { content: "\f2db"; } +.ri-zoom-in-fill:before { content: "\f2da"; } +.ri-zoom-out-fill:before { content: "\f2dc"; } +.ri-share-line:before { content: "\f0fe"; } +.ri-share-fill:before { content: "\f0f7"; } +.ri-share-circle-line:before { content: "\f0f6"; } +.ri-share-circle-fill:before { content: "\f0f5"; } +.ri-alarm-line:before { content: "\ea1b"; } +.ri-alarm-fill:before { content: "\ea1a"; } +.ri-thumb-up-line:before { content: "\f207"; } +.ri-thumb-up-fill:before { content: "\f206"; } +.ri-thumb-down-line:before { content: "\f205"; } +.ri-thumb-down-fill:before { content: "\f204"; } +.ri-alarm-warning-line:before { content: "\ea1d"; } +.ri-alarm-warning-fill:before { content: "\ea1c"; } +.ri-filter-2-line:before { content: "\ed23"; } +.ri-filter-2-fill:before { content: "\ed22"; } +.ri-loader-line:before { content: "\eeca"; } +.ri-loader-fill:before { content: "\eec9"; } +.ri-loop-right-line:before { content: "\f33f"; } +.ri-loop-right-fill:before { content: "\f33e"; } +.ri-loader-4-line:before { content: "\eec6"; } +.ri-loader-4-fill:before { content: "\eec5"; } +.ri-reset-right-line:before { content: "\f544"; } +.ri-user-line:before { content: "\f264"; } +.ri-user-fill:before { content: "\f25f"; } +.ri-account-box-line:before { content: "\ea07"; } +.ri-account-box-fill:before { content: "\ea06"; } +.ri-user-add-line:before { content: "\f25e"; } +.ri-user-add-fill:before { content: "\f25d"; } +.ri-user-minus-fill:before { content: "\f54b"; } +.ri-user-follow-fill:before { content: "\f260"; } +.ri-user-follow-line:before { content: "\f261"; } +.ri-user-minus-line:before { content: "\f54c"; } +.ri-user-unfollow-line:before { content: "\f278"; } +.ri-user-unfollow-fill:before { content: "\f277"; } +.ri-user-shared-fill:before { content: "\f271"; } +.ri-user-shared-line:before { content: "\f272"; } +.ri-account-pin-circle-line:before { content: "\ea0d"; } +.ri-account-pin-circle-fill:before { content: "\ea0c"; } +.ri-group-line:before { content: "\ede3"; } +.ri-group-fill:before { content: "\ede2"; } +.ri-emotion-happy-line:before { content: "\ec8d"; } +.ri-emotion-happy-fill:before { content: "\ec8c"; } +.ri-emotion-normal-fill:before { content: "\ec91"; } +.ri-emotion-normal-line:before { content: "\ec92"; } +.ri-emotion-unhappy-line:before { content: "\ec96"; } +.ri-emotion-unhappy-fill:before { content: "\ec95"; } +.ri-emotion-sad-line:before { content: "\ec94"; } +.ri-emotion-sad-fill:before { content: "\ec93"; } +.ri-women-line:before { content: "\f2ce"; } +.ri-men-line:before { content: "\ef2e"; } +.ri-star-smile-line:before { content: "\f18f"; } +.ri-star-smile-fill:before { content: "\f18e"; } +.ri-sun-line:before { content: "\f1bf"; } +.ri-sun-fill:before { content: "\f1bc"; } +.ri-moon-fill:before { content: "\ef72"; } +.ri-moon-line:before { content: "\ef75"; } +.ri-lightbulb-line:before { content: "\eea9"; } +.ri-key-2-line:before { content: "\ee6f"; } +.ri-key-line:before { content: "\ee71"; } +.ri-outlet-line:before { content: "\efbc"; } +.ri-lightbulb-flash-line:before { content: "\eea8"; } +.ri-t-shirt-line:before { content: "\f1d9"; } +.ri-t-shirt-fill:before { content: "\f1d8"; } +.ri-seedling-fill:before { content: "\f0d4"; } +.ri-seedling-line:before { content: "\f0d5"; } +.ri-leaf-line:before { content: "\eea3"; } +.ri-leaf-fill:before { content: "\eea2"; } +.ri-character-recognition-line:before { content: "\eb47"; } +.ri-character-recognition-fill:before { content: "\eb46"; } +.ri-recycle-line:before { content: "\f05e"; } +.ri-recycle-fill:before { content: "\f05d"; } +.ri-door-line:before { content: "\ec46"; } +.ri-door-fill:before { content: "\ec45"; } +.ri-graduation-cap-line:before { content: "\f333"; } +.ri-graduation-cap-fill:before { content: "\f332"; } +.ri-sofa-line:before { content: "\f41e"; } +.ri-sofa-fill:before { content: "\f41d"; } +.ri-error-warning-line:before { content: "\eca1"; } +.ri-error-warning-fill:before { content: "\eca0"; } +.ri-question-line:before { content: "\f045"; } +.ri-question-fill:before { content: "\f044"; } +.ri-spam-3-line:before { content: "\f16b"; } +.ri-spam-3-fill:before { content: "\f16a"; } +.ri-prohibited-line:before { content: "\f3a1"; } +.ri-prohibited-fill:before { content: "\f3a0"; } +.ri-information-off-line:before { content: "\f4eb"; } +.ri-information-off-fill:before { content: "\f4ea"; } +.ri-star-half-line:before { content: "\f188"; } +.ri-star-half-fill:before { content: "\f187"; } +.ri-settings-line:before { content: "\f0ee"; } +.ri-settings-fill:before { content: "\f0ed"; } +.ri-checkbox-multiple-blank-line:before { content: "\eb87"; } +.ri-alert-line:before { content: "\ea21"; } +.ri-alert-fill:before { content: "\ea20"; } +.ri-bold:before { content: "\ead1"; } +.ri-italic:before { content: "\ee6b"; } +.ri-heading:before { content: "\ee03"; } +.ri-font-family:before { content: "\f390"; } +.ri-font-color:before { content: "\ed8b"; } +.ri-font-size:before { content: "\ed8d"; } +.ri-underline:before { content: "\f244"; } +.ri-strikethrough:before { content: "\f1ab"; } +.ri-align-left:before { content: "\ea27"; } +.ri-align-right:before { content: "\ea28"; } +.ri-list-check-2:before { content: "\eeb9"; } +.ri-list-check-3:before { content: "\f398"; } +.ri-list-ordered-2:before { content: "\f39a"; } +.ri-list-unordered:before { content: "\eebe"; } +.ri-double-quotes-r:before { content: "\ec52"; } +.ri-h-2:before { content: "\ede7"; } +.ri-h-3:before { content: "\ede8"; } +.ri-h-4:before { content: "\ede9"; } +.ri-h-5:before { content: "\edea"; } +.ri-h-6:before { content: "\edeb"; } +.ri-h-1:before { content: "\ede6"; } +.ri-list-ordered:before { content: "\eebb"; } +.ri-arrow-up-circle-line:before { content: "\ea72"; } +.ri-arrow-right-circle-line:before { content: "\ea68"; } +.ri-arrow-down-circle-line:before { content: "\ea4a"; } +.ri-arrow-left-circle-line:before { content: "\ea5c"; } +.ri-arrow-up-circle-fill:before { content: "\ea71"; } +.ri-arrow-right-circle-fill:before { content: "\ea67"; } +.ri-arrow-down-circle-fill:before { content: "\ea49"; } +.ri-arrow-left-circle-fill:before { content: "\ea5b"; } +.ri-community-line:before { content: "\ebba"; } +.ri-community-fill:before { content: "\ebb9"; } +.ri-school-line:before { content: "\f35a"; } +.ri-school-fill:before { content: "\f359"; } +.ri-home-heart-fill:before { content: "\ee29"; } +.ri-home-heart-line:before { content: "\ee2a"; } +.ri-inbox-2-line:before { content: "\f3a9"; } +.ri-inbox-2-fill:before { content: "\f3a8"; } +.ri-chat-ai-line:before { content: "\f56a"; } +.ri-chat-ai-fill:before { content: "\f569"; } +.ri-hand:before { content: "\f445"; } +.ri-input-field:before { content: "\f47a"; } +.ri-diamond-line:before { content: "\f5e4"; } +.ri-diamond-fill:before { content: "\f5e3"; } +.ri-heart-2-line:before { content: "\ee09"; } +.ri-heart-2-fill:before { content: "\ee08"; } +.ri-alipay-fill:before { content: "\ea2b"; } +.ri-sparkling-2-line:before { content: "\f36b"; } +.ri-sparkling-2-fill:before { content: "\f36a"; } +.ri-fire-line:before { content: "\ed33"; } +.ri-fire-fill:before { content: "\ed32"; } +.ri-dice-fill:before { content: "\f400"; } +.ri-dice-line:before { content: "\f401"; } +.ri-flip-horizontal-2-line:before { content: "\f4d6"; } +.ri-flip-horizontal-2-fill:before { content: "\f4d5"; } +.ri-flip-vertical-2-line:before { content: "\f4da"; } +.ri-flip-vertical-2-fill:before { content: "\f4d9"; } diff --git a/uni_modules/tmx-ui/scss/remixicon.min.css b/uni_modules/tmx-ui/scss/remixicon.min.css new file mode 100644 index 0000000..033210b --- /dev/null +++ b/uni_modules/tmx-ui/scss/remixicon.min.css @@ -0,0 +1 @@ +@font-face{font-family:remixicon;src:url(data:application/font-woff;base64,d09GRgABAAAAAN5YAAsAAAAB3twAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADsAAABUIIslek9TLzIAAAFEAAAAQwAAAFZCwlnmY21hcAAAAYgAABb7AAAvEKYEuDZnbHlmAAAYhAAArZQAAXAo1EY5v2hlYWQAAMYYAAAAMAAAADYsoe/QaGhlYQAAxkgAAAAfAAAAJAjHBrxobXR4AADGaAAAAB8AAAo0b5gAAGxvY2EAAMaIAAAFHAAABRx6vdUibWF4cAAAy6QAAAAfAAAAIAOjANJuYW1lAADLxAAAAagAAAMqHA3lNnBvc3QAAM1sAAAQ6wAAK0LWJjZpeJxjYGRgYOBiMGCwY2BycfMJYeDLSSzJY5BiYGGAAJA8MpsxJzM9kYEDxgPKsYBpDiBmg4gCACY7BUgAeJxjYGR5wDiBgZWBgeknswcDA8MKCM3kwGDFaAqkGViZGbCCgDTXFAaHV4xfnzD/+e/DkMP8h2ELUJgRJAcAJLYOOQB4nO3Ye7jOZdYH8LXW82whyaEo58gxaVANiQ4ORRJN02AQJbEVUTkVoZNyCINJiWim0blpmkaYkiY1JarBhE4TU/zOh2dPjZp6v/f+ulzzx/z7Xu/7x7ivT+uZvWf/nt9z/9a97nU/IlImIgVoD0WRWkVRvJKa3+OnWvnzglSv/Hmx5ociNsZEqsoYz7zjvNpeXa+xd5rX0mvjtfc6eed653s9vAu9Xl4/b4A32BvmjfRGe2O9Cd5k71ZvmjfDm+Xd693vLfCWeiu8R7zV3jpvi7fD+8Db7e33/u5966tfzT/Nb+G39Dv4nf2u/iX+IH+UP9G/xZ/qT/dn+vf49/sL/SX+L/2V/hr/Sf9Ff6P/jv+x/4UfBRZUD2oGdYJ6QYOgSdAu6BB0Cs4P+gRXBoODocGIYHQwJigPZgRzg4XBiuDRYG3wePBU8Gzwh2BT8EawO0iDivDEsEXYOewaXhoODUeF5eHN4fxwYbg83BS+G+4Md4d/DfeHB0I/jMPvorLo+Kh21DhqFZ0ZnRNdHg2KhkRjovHRxGhSNDN6PHoyejHaFG2JtkXbow+jXdHH0afRl1ESfRdbXD1uEDeLW8at4w5xt7hH3CceEF8Zj4rHxZPj6fGqeHP8Vvx+vCc+HAdJWVItaZm0Tc5Muibdku7JBclFSe+kXzIwGZnMSBYlK5I1yXvJ7mRf8nlyMImSr9NCWjWtkZ6SNkqbpa3SHunQdFg6Pp2Tzkvnpw+ma9Jfp0+nz6eb09fSt9K96efpN9lxWf2sYXZW1i3rlQ3IBmajstHZ5GxaNiubmy3NVmfrsheyl7KXsw3ZxmxztiXbmu3IdmefZAezr7LDed28ft40b5G3zjvnF+Q986H5Dfn4fGJ+Sz4/X5Qvzh/O1+ZP51vzw3le0lLdUpNSu9JZpR6l3qUxpRmlpaWHShtKe0r7Sn5F7YomFe0qelX0ryivOPjDDyKeelW8GsizBl4z5Flr7wyvI/KsW2We9fT6ev2RZ0ORZ9d6N3g3epOQZ1OQZzO9uyrzbIm33Ft5NM+2I892eR95B70jvvhVj+VZR7+L38cf4I/0J/iT/SnIs9v92f59yLPF/jLk2Sp/vf9b/xXk2X7/b36IPKsWnBDUDk4OTg0aB20r86xr0Ptong2vzLNxwfTgzmBBsCRYFTyGPHsCefYi8mxrsCuIglJYM2wedgy7IM+GVObZxMo8WxZuRJ7tqMyzfeEX4ZdhFB6JClHVqFbUCHnWNjo76hcNjK5CnpVX5tkd0bpoPfJsQ/Rq9Gb052jnsTw7FP0z1rhaXD9u+m951jO+PB4Uj4zHIs9ui1ciz7bEO+PdR/OsatI8aZO0T7ocy7NeSd/kimR4Mj1ZmCxPVifbk13J3uSz5EASJhXJ98iz49P6acO0KfKse2Welaez03uRZ4vSVemvjuXZtvQj5NnXWTGrlzXIOhzLs+HIs0nZ1GxmNiebnz2Src2e/Q95tjc78G951jxvlXfKeyDPhuTX5OX5BOTZ3ZV59lC+On8ifz0/lGclKdUpNS61LnUodUeeXX8sz3aV9pYOVdSqaFzRFnnWt2JcxQGXZ//9999//8v/FHvnWCu3WzFm2B0Ys2y2zcW4u3Lca/NsAcZijGW2wh62VRiPYayz9ZXjKXvGXjg6XsJ42Tbbq7bFttqfjo237R3bbh/aLttjH9k+jE/tkKFoWWQljCP2nX1fwKZesEKxUAWjaqF6oUahZqFWoU7hpMrRoNDo6GhSOZoVmhfaFNoVzi6cW+iCcSFGP4z+hQGFqwpXFwYXhhZGFEZiXFs5RleOMYWxGOWV48bChMK0wozCrMLcwrzCA4UFGMsKKwqrCqsL6zGeqhzPFJ4rvIDxcmFjYXNha+HtY+OjwqeFzwtfFA4VvH8bSSErlAr/KHxT+AbtSRWMk4r1iqccHQ2KzYrNi6cXWx0bbYrtiu2LnYpnF88tdimeVzy/2KN4YfHiYq9in2K/4lUYVxcHF4cWh2GMqBwji9cWx2CMLU4o3nxsTC7eijGleEdxVnF2ce6x8QDGguKi4uLi0uJjxSeK64vP/YfxcnHDv42Nxc3FV4tbMLYWPyzuKu7BOFg5DhWj4jfFI8Xvit+XSZmVFcuql9Uoq4lR69g4qaxeWaOyJmXNyppjtClrhzTrpT2tlp1ojayhbtHX9E3dpjv0B/3eyqxoP7ErtboNs+E2V6+QDnKmDpSN8opeqT/R5/RZu9luFJPj5Tg5XU6zSXYTUqWe1JCqNtHGoyOsLlVsgpXLyegWq6F7fEG+ln/IZXqi9JHe0l+v0np6svxUrpKfyU8wrpZ9+lP5RJ6Rp+0q+UG+l3/KN6poLYfIYPm1PCG/ksfRZZ4hw2WoDNMlulh/oUt1rs6xbnae3C13yVyZI0tliSyQ+bJIFspyWaHb9V35k7yhW/V13ayv6h91kw3S93WnXi25ZPKq/FHf1rf0PblILpYL5QJ5U97UHtrdbrHJ8o6erZ1litymDfRUeV7elrfkBhkjf5eD8qF8oF/pl3pAv9CD+nfZqT+TB2Wx9tfL7ALrYdfqbt0lW+Q1HaKD5Sl5UmfrnfKwrJR1staaWVM7zZpbK2tpp1sLfVqfst7WS4fquXqO/kjP0g56pmaaaqKx5hrpz+Ur+VJSSSSWSHzx5F/ynYQS2HFWRT5GXbhHRskIHa4FNa2mVfU4rWKDbYhu0D/oxXqRjpDr5Fq9RkfKAfnCmlhj1JnrbLRdj4pzg7wuW2W37NHadrUu12U2x2ZrP+2rA/RyaSOtpZVNsanSUtpJW7leRus9erf0kO7SS3pqDT1B/6Rv6EZ9RUfptfZT+5F11Pt1nnW1LtbZztJaUm4j9HgbZ6P0QV1kx2NUtarqq6eH9ZCGGuhf9SPdK+/Kdtkgf5DzpKt0kU5yvnSTc+RsOVc6y4+lo96sE3WyTtIpeps8JmtkgFxubfQZfUbmyX1yr9yjD+lK/aWu0E7aUbvoj+1M66Av6m/1BX1e1+pj+rius06yXn4jL8pv5SX5nbwsv9c79Hb9jT4hO+Q9vUt/rb/SU7S+NtKGcqOMl0vlEr1Vb9HRslf+Kh/ZJdZHVskj+o7+2brb+XqedpUJcpPO0pk6TafK3+RzrdCSnWs/lptlouySv+jL+nsbaFfov/Q7/VaP6Gf6qX6iH+t+3aef69+0iTbWZtpUm+tpsl9Wy6PyZ73e+tqlMlkm6Us2wAbo76ydtdUL9QJ9UtfLj+Qs+7l+YO3tDKmQkp1jZ8v7sk22WcHMFGewb+WIbJZNerq20BtsqO7Rv1gdq2017SQ72U6wU62BnWL1ZZn8QhfqAm2jrbWdttWW2krb6xn6iD6sj+oqXaOr9SStq+drNx2nY3W8luuN8ql8Zq11gt6k3+jX+k/9hzSURtJcWsip0kA/lGbSVJpIY7vILrTqVk2vs9vsVq0jdeVEOUlqSR2pKbXlBOxqd8kv5SEdI9NkqsySmXKH3C4zZLr83H5m12hNG6kzdLpdZv2kn/S16TZNbpVb3MqWK2SgjJOxdp/N0/v0XutpF8uVMkgv1UvkOXlWy7Rod8hhOWQz5RSpr4N0mD1g92MHnS+z5U673PprH+2t8/UBeUDutxoyUq6xulbPbsf+e6fNQq2s8n/dFPw/+FfD/adpDf4PW+7OXKS9EI20J2IVslqIx5GdiFiDrBHiCWQNEWuSbkE8kfQ1xFqkbyLWJt2GWJd0B2IDUncGbEj6PWIjsjLExmRFxGZkP0E8jexKxJak1RFbkw1DbEM2HPEMsrmI7Ql7o3gdCbukeJ1IzkQ8l7BziteNsIeKdz7JK4g9SN09XEjq7q0n6XOIvUifRexLdjNiP8JOLF5/EvccLifszuINIHHPYTBhxxZvKImbg5+TTUIcRtjPxRtJ7nsf71rCHi/edeQywhtNUhXxBrKJiGMJvYB4N5L7nsi7idx3Rd4EEpcvk8jczyYTugfxbiX0EeJNIff9kzeV0FuIN43cd1TeDEK/Id5MQuch3ixCDyLeXSSXId5N6vLuHkKHIt69hF5FvPtJ3BwvIL0KcQmpm5OlpO4+lxO6G/FWkLj//0pCxyPewyTuWT9Cla9XE/oh8daR7EPcQuquuZ3QLYn3HqFvEm8HydOIH5C5991F4tbIbhK3Rj4idFri7SX5BnEfuebL20/uKz7vIKEjE+/vJC6njhC6NPG+JfRraFEInZv4SujhxK9K7rtEvxqhrxP/NEKHJ34LQq8nfksS5KXfgRTz7nckXYzYifQXiJ1J8Tz8LqRYs35X0jmIfciwJv1LCF2k+AMI/aT4VxA6S/EHkrjrDCJx1xlJ4t5rFIm7twmEXlT8iYSuVPzJhP5U/FsInar4Uwg9q/hTSZA3/nRSPG//dkJHK/4dhB1Q/JmEvVD82aRbEeeQvo44l3Qz4l2kryLeTfpHxHtINyHeR+Y+6zzS9xHvJ92JuJDQSYu/mNBTi7+E0F2Lv4zEvddyEvdeK0jfRvwl6VuIKwn9uPirCJ25+I8SenTxVxO6dfHXEPp28dcTOnjxn6TK178lRZ31XyTtjvgKmXsOG8nc83mHxMX9pGcjfkzq8utvJO65fUFyG2JIij3JjwgnBzTphDOEBNUIpwkJqhPOFRKcQDhhSFCTcNaQoDbh1CFBHcL5Q4KTCScRCeqRYM0Hp5J+hdiA9EvExqQHEJuQ4r6DtqTumu1I3Xt1IMGzDjoRzjgSdCWcdiQ4jwTPPuhGijoZnE+KGhv0JsMzCvqQ4VkEV5JhXwkGk6I2BUMJpycJhhPOURKMIEFvEIwmRS0KxpC6a4wjnLckKCdBHgTTSbE2ghmE05gER+FcJsFswglNgjmEs5oEc0nWIi4gQw8RLCRririEDPUrWErWHPEXZK0Ql5GhlgXLybAXByvIUO+CVaSo4cGjpO6zPEbm5nItGXqC4HFSN2dPkKLnCH5Deg7ietIfIT5JehbiU6TuOT9Lir4leJEU6zf4HWmK+BJpgvh70hjxZVKs/eAPpMj7YBPh5CrBVhKXk2+QuJzcReKuv5vEXT8icdc/StzPEnIbS5ASTsISlAhnYgkqCKdjCWsSzskSnkgSIDYnQ18UtiCcoiXsSIJ1HnYiQx8QdiacsSXsQjhtS9iVBHkZXkqKfA2HkKJ3CoeSO46Fo0ix/sNyUuyF4URSdz83kzt1hPPJkNvhQjJ37WWkGxCXk2Lew42kqJPhJlLUz/BdUnefO0jQw4U7SbAGw92k1yD+lRR7W7iPBHUj3E+CuhEeZagj4QEy1JfwSzL0f+FXZO69DpFh3YaHya5H9MiwhkOfDDUwjEiwf4UxCXIoPELi7vdbkj2I35GiVkYFMuxNUZEUcxSVkWLuoqpkWOdRNTKs/6g6KXrr6HhS9NxRLVL0B1FtUvTZUSMSnBOixiQ4P0StSFxsS4b9ImpHhj0+OoMENSFqT+J+fyaJ+7uzSTBX0TkkmMOoHylyMrqMFHt51J8ENTa6nAT7XTSQBHUjGkSCM0Z0FSn6+einpNiHoqtJ0WNEPyPFuo0GkyLPoiGk2EejMaTI76icFHkVjSdz155IhloUTSLDeovuIEVvEc0kRc8RrSPDGoseJ8Pai9aTYU1GT5KhpkUvkrpntYHE3csrZMj/aCOpe7abyLBnRK+Suft/jRR7XLSFFD1b9CaZ+9ttVPn6z2Qup96hytfvkiKno+2kyPVoJynWQPQ+KdZG9AEp6lX0ISnqVbSLFGsy+pgUvXv0KSl69+hLEveeh0jcex4mcfPhkaBWRD4J9u8oIHHzHJK4eY5IUAejmAT7epSQYL+P/knicvMIicvZb0mwH0XfkeB5xUryY0QjQQ7E1UhR++LqpMiVuD4perP4FFLkTXwqKdZU3IAUPVjclAT7ZdyMBD1i3JIE6zduTYK1EXcgw/qNu5HiPBX3oMrXPUmQk3EvEvTHcW8S7BFxHxKsx/hy0ocQB5Cir4gHkaLfja8kxd4fjyTFPMejSN2cjCXFs4jHkbp5m0yGGhHfRuY+xxRSrIF4Kil633gaKc7F8XRS9KLxSlL0E/HDpG7eHiHFeotXkWIdxpvJ3H1uIcE6jF8nQc8RbyVx9/AGibuHP5Ggh4jfJEFvEW8jQQ8Rv0WC3iLeSYq6EL9PivNPvJvUvdceUvQ98WES7G1xQIJzRFJGijNPUpUUZ9WkGinOp0lzUuRW0oIUOZecTor6nrQkbYjYhuRGxLYkqHFJexL0AcmZJDhbJl1Ib0XsSopzR9KNFPU86U6CtZxcQIL1nlxEgvWe9CJz1+xNhpxL+pLgOSX9SPD8kitIUY+SgaSoU8lwMveeI8iwrpNrSFETkpGk7n6nk+BMm8wguQlxIeksxEWkqN3JclLkXLKCFLmYrCbB2SlZQ/I54nZS9G3Je6To55JdZKghyW4y5H+ylwS1ItlHglqRfEbi/u5zkr8gHiBFjiUHSZFjSUjm5iYic3NWQYp+MvkHKepX8jUp6lryPSnqXfID6WeVrWwlRV1OlfQTRCNF7U4LpOil0qqk+Azp8aS477QGKeYqrU+KXis9hRR9RtqQFDUubUSK2pcepcjptBkpziZpKxL3vt1J8DzSHiQ4b6RDSZAn6TBS9B5pORnyLB1PhjxPZ5OgHqVzSFCf03tJsd7T+8hQB9N5VPl6PinqQLqIDP1P+iAZ1lW6ivRCxEdJsTbS1aTY+9M1pKhF6a9I0GOkvyZBb5A+TYbzSPo8KfbadDMZ1m36Ghl6snQbCfIgfYsEOZl+RIb9Lt1Lhv0u/ZwEdSr9msRd4xtyr7MiGZ59VkaGnMiqkCFXsuPIbYtZPRLkW1afBPmWNSDBfWcNSdDHZB1IUbOys0hRy7JupOirs15keMbZAFLU0GwgKdZLNpysDuIIMvS72TVkOFNlI8lOQhxFdjLiaDL0kNkkMuzT2WQyd+9TyZDH2TQy9/lmkqA/z2aR4PyczSFFrcnmkuIcns0nRS3OFpBiX88WkiKXskWkyKXsQVLU8WwxKdZDtoQUOZAtJUUOZI+QuriKFHtk9iipi6tJ3e/XkiIXs3Wk7vfPkrq5eo60LuLzpKi92Quk7lm9RIr9PnuZFH1AtoEUay/bSIo1mW0mxX6UbSFB/cm2kqAuZTvI3PzsJkU9z/aSop5n+0iRr9l+UuRx9jEp+rzsE1LUxOwAicvBgySoQdlXJKg/2WES5GFelwT5kNcnQT7kTUnR7+bNSVCz8hYk7vetSFAD89YkqIF5JzLskXlnMtSKvAcZ+sj8AjLs93lPUpxJ8yFk6J/yoWTYo/NrSJH/+UgSd++jSE5EvJYEzzS/jgTnjnw0ifvb60mwXvIxJFhH+Q0kWCN5ORnObvl4MvQq+QQS9Ir5RBL0k/ktpO56d5Ng/eT3kGBd5feSYP3k95FgXeXzSNBT5feToKfKHyDBvp7PJ8F+ny8iQc3MF5PhHJg/RObmaSWp+4wPk7k5W03qrrmG1F3zMTKcV/O1ZOhX8idI3OvfkGCvydeTub99ksx93qdI3PN6msTNzevkvhvPt5L7bjw/RIL9PT9MgnqXZyRYa3lOMray1FcyzF1JyTB3pTqk7ud1STHXpcZkyK1SE7KLEVuToNcvtSHBGaDUlhR7aKkdKfq6UgcS1IjSWSSoHaXupNgzSj1IsZeUepPhmZauJ8FnK40hwWcuzSBDDpSWkqD2lh4iwTosbSB197aLFHt/aTcZ8qO0hwx5U9pLhppb2keGvCkdIkFPUDpMcieiR4ZzUckn64/ttRYp+tiK2qT4PBWNSXHNiiakuIeKtiTudTsS3E9FLzL0TBV9SZCHFf1IkKsVl5HhmVX0J8P+WjGODGuhopwM81VxgAz3X3GQbNb/ADMmlN4AeJykfQlgW9WVqO57kp7lRbIsPcmbZMuy9LzFi9bEjpfEtpR9X+zsCS+BOAk4CWsWAmUrgdD8QkVoh0ADpaGlhBQG2pK2NN0E0ynQms4UflvSlg4dWmA+mQl1rcc/5973tHgJSceypKe33HPOveeee865556rIzr40xO+Xpen05lI1EQk4gnzs5WP4uQOZX+cFKUeIb8ihXFlP/4qlOF2+gz/P3wIn/ERJzxGrEHusay7fkmK4JjcEVc+4jbrtGc0OMQjeohgIk7yKLcZylfvJb+SlfMAFg5zYRCr10okExG4x9J3cNelHuE2a2iq9z/DXakzwP0CvXn3hTjpIl1x8usLMdKlnI2lcQ9xf6D3SUgv94R6mTx+Ia6cVc7G0/dp5UWRRiyPXibXXIgpZ0nXxPKcSBQ3U72M5VEE0vc9zLXrOKxnD7ebNKVOcu3KiHZN4F5j16y8oIyQx5URbmCy5/A8MZOmic+Rt0gTeRzL1eEZuHaSexnwMiFmQKmTh3rndn8YU15RXonN5AZSJ8k1H8ZJRHklzs2T1WcS3FvqMwJQLfig7rmZmbvI4x/GSIREYjMB/YEJcCSoAcnmCVM4mfvIrz+MK6+QSDz1/EQ4UWitqMEatHJPZO5COBk81Wce5o7reJ2RcZCBeEg/JaIJ64Q7LstYmxrtO6Be2L1AAQ+1ugOvc68hOsoIq13d+HJ9gLmPePiH2V1Yl1+TZajscWX6AFsb1PgNePFGhgSteLjvk9/rr+C3Ad9aKScCdEGKwkHUCQ9Fuatjh+RDsQvcexcu4BF3TfxQahd3/6H4hdTeCxfih7j7U7sO0XK+qQ/yCbUcJzwPuElwAKTDL34m3kyfVE6rT8UvkC+rpbYzKGq/C3Bxyp8GwWeQgPVealauVq5u5uLvD7zxxkCmf2r3+SSDT8jcR0j6PloP+ga+UJevK2Z166FcL/BOwSkQfb2s/OzHMeUHpDv24y/GP/4Yugz5ROkiG34So33hxyAlLnwMxxPKskH1eCjPOW1QlJN8WyahH8dIt/IDtSgoYIqi1Pb5LuWpAirJpKjE00/iI9HYBx/EKoGxPgRGfhyY6kOVueB7kmcRuo1+8t9VXqbPAvPTZ4GhP1QZW3v2k1/zJ/lr1Gc5Z9RpgC4ADfRVFULqTfV2bjrtRB9+eI4y+YcfMrw/+T3/MPALhzVvMvAPM+akn+3I2vjC7q7W18w0nhxQZ6PYkt+oJZ5TIXBvjgeefj5I5QXC4jwmQt7CwvGFfYOBUmXLJ6f1C/gHddXY22oEo2C0Ox1ORxDYr0byS/5QNBKNBD3A1kDrEeWhpbG+uvr6ur7YUnJW6dq1fk04Gg2vWb+LXAl8eSHO7aqX+mKP4U0ynN/w6/Vrw5FD8Y8vxCisl/Uyfwhh+STBGZUEawhhULAi8AUFFkD4It8OfP1x/FAkvHb9rzcAFBmBQsFS/WcppEPkygx0YJezGcwYXUkNFrHaEQAlJwycTAkMIKiwFZFw8u1TIc299KkUj6tD7MHQeSkRFKwX+jMFRkn1kpWfhj23a0rKKR+9qg/xN4G0cEAt2qH4GiAqFCVQbwSqzQojhD7oEsfeFl02ctRcYyZHbbJyQjnBiS6XyBWVWUg0P1952VKm+MgPSbHyodJJadDKnaTUCQVOKEvl8W/pH+SP6iy6Up3OQIvw0hKgzo2+IKIWtAb5V1N9oivB6S1+C6dPuJTvjyJDjspxl0jOkjeKipRGpUt0yeQvxKp8oNiZXE6XbYOyNQzV4nFU0ROXmFOw0iWLiKZWpqz2L57yYQh4Qw916EcpD4gZJhBtCNrdJNBFwkG7mdQ0E/5VrEW+elxVpPrkuv5l/XVy797P7u2dRn5G7MpflFCA1pADaqijoED5saXszvr+urr++r69vb17KT0MB6vOk0VPBrgK28tghye0QKqPwmOwDROAUTB9DKRK8z9D/X1BZ4e2qdTpotZQJOqLAJO6iMFNoPOJnnDQYzUQq2Q9VWIhf8i38RyZabHJf38uSTYA+5wZLeMeKi43PKM35ev1H283VBQrrbLM/c8tqcPkqRWKOr588jzAeYByZ9CaKToNT+R2y6SnyArlysVmcqvJrucquMN3G8ssyjQo7kuWMuPX9UK+3ohijI6zx/grdaKuStejW4FSys0FA1EzBzXWTCRHEKrJ4Jc80NUEj98ZiDpEu1GwesKhZgI15SIeK9RfKOoIRKIeNxHUW2GUDkUCDhHGaj+5jnxsbJvfWFaqb1sIw3vTwjZ9aVnj/DZyoaFU+WJpQ0EB5yh4q66GRKcpJyqaI80VyolpUVKztN/OfdPev8rlTD3jdFmKXYnrnrgu4SrmtzX0S0LTnPr6OU2C1H/E19zsM+Xl/dlmyg+tFJUfyhXNFfAvk05xZSjfZKuvqamfZXU6rSbBrLy7/LrrlpNSs6CNGyr94clpJ8YaIAm4RDKKdocTCe8iATclHBgoNCVxvIT4pxbZ+5ciYaSJshJpmhYdh77yAEUwjTzjKhV5xlvPQJs/pCvTNermo7xlLY7V3g1DeNATcFQR2ixGLyALuOKHt0aygn1gBE4PQtt0EYcTeF47QNJCLUQfDIyVBpoj1XcJTjP3hNkp3FUd+XxhUcuKquoVG/CjpaiQO5PacVNJzYwaqduc55fyzN2LtAMJzpbcRLYpT4MKt6xqS3t36L3CoqLC/wx3t2/pI7UeTy2+ifJLvvqXrv4ZNY21dovFXtuofdfM6Hf/graDRuMM4Oyp6LN+Kj1bJ5LTnBIuir19EtSrlKcvirDKO88A7xyD/g4ygMDA7iFRB2heVo8Vxj9rWuhEgj5gGCZpgHn4QoMh9V1y05inWXle2clXlwXKQPocQCHD305bfxl+8CG4oDz7+7pS5d+JnHqW/A2ee4PeVQ3iW70LPjSZm+BvAentQPkDQwLiIWoIQBWKoFDxMHhGnfqQrFyr7CTnU2/a3W47f7voGkuQm8i1ZafjQ6fjZJAsUx5GiDID5RIDyrNk4djTp2NwWZeWGw+CvsXkXRVABAgqyZ3QNUzQeJGgDRoyKnrDPg+0DBaEVPK3K8NKoUscVYZHR/lfpArJPn4bE78AiZurHCNn54uu1ElZHoV/5SlG33P6rSD3rIw+myrHM5UMPdPqs/nQxLyb/LywshA+GDyZr1aGeWLqUb6lPNPD3UAcgqD8p2BO3U7F+gHz9NTbXPWHqb/9boHyHhEXqm2rwXNOBg3qEtT1cYD4NuUnyvd7yGfI/kmgdCkfkuIFyrfIHEYPyh2t/nS2sNpIWVVIfEHRK0IbnkK+yK691MnRUXJUGeb+PJ+eztTcOTkh5/BmuU6CtgFJlsOPHirLDEgD40nGn/z9ofayNC9ynzNUuZRPGEXfy/Al5ynL4sOysublnt8yyq6enCexxWoAC7+XaaLQUbLYktakZFM5szVENTVr6mWNNRWL8tIsrNNZ1Yw991mpHhdq1bhTuUWt2AVjf2EsqsnMY7Q/1EzZH2xYw96wNxwMB/XBdK9gPVHrFfMTCRn+wWqpnqxbpK7Hq4ksmEhv3afRmwM5Q7UGGqhmnDT7DhX8/VOTnXqOoUBxeFF/L3/k0+gGNRoUaVbn3bKyV9nF+VMnGXC7e+wLZB+5duNQbGgoTv9jZBuVCVtT35ShVbKI78Ob1Puy4V9SHeRg0RZchjp4ug7sbqwD1vIPZaNylxXNiWXBNg0TqAjrQuXbZM781Gdy0KFy6hz0421g6VkAp3K0INIdIQqdzEPEoCAFQUIJHj2R0xJj7G2QGicSyWSC3J5aF+Dz+G3J1PW0WxxOgj5dSM4m4W9UpjRrMEpQL7N5MiBAwxS9zqhN8gjn+Gq1eM4vQ8FnAlhuplTlBBZINsgyq8dHgZdOgnzw6eagBBIkLJLaWNBfo6BxSTa76BTMRMQREWwgYrRRs8hF3JxoF6QIqmhQ/VIkqB50kZf578S2hmYohZTfgmvbSx77b31s5rzIugg5by5KfcSNbly2uLm1fW2wbp4Zzkq18/qXgKq7eFZ82tX8ibFYfKtI+bBn7wq7tT38mPK+0TivTLyqB27mOLOZLGltXrxso9W+Ym/Pkv55tVJ0bcQ8rw4U5mnxWr8ul7Yq3bQpaCMBJ6WCRHg4Ik7gI+MUBHB/DrYhvsqV/V9bEu/fYm+c1rm79aOp0FUxIw/VkQ01nuvn53urP0LEmE17DGyGZvhRAxUrOLtAHWR4UEszB0W02xlq/I4VC+dd49ogrtjdTVGhEDMo0gphmHF31FRfv8A7YyBA0chYpRQ/WvUUJ1WGM3xqdL04vma17aTYOEEdz2YIUIiw2bHaOOQAbrfWtJPhBw2UZgT4gP9Z2+0b7SuundW7lz+UadPJUAbbrG91KeOByLqd6yILOqs7NoSgyEvsg04qC8lkfXA4CZKNK5+6D5Kzk/TBHAhCUAQpa8spnRzFcg9PLPaEWiTlh2f0FSDPO1HnZuaOmOPdCOZ4PrK8K1bVrMQ7wDDiztBaaWqct+CZBfMam+T26ZvkP8mbprdjRZ7AGm1ZsmlJi9zU1QTal43Vv/LXAbwZnxogbym+vfgAPrmX2DKtoPy1dUlLy5JWYlP+WtXUpI39QdClLdSmyRn3Aw7UywLAR4hXJ9GMOGYOdxKvyDDX7GE21qROuhpc8E9H9iy7mN+maa3wmbqQxGP2wWyYJDOTR0fpT+AFgeo926Cd0M/g1FWABPBSDSWQrV1FggbgCgmUR9SlDcAbklcM+uBbH9T0IIC6DBlE1jzXyaSMrZpRJamWnOqjp9E3AQeynETxir7nSfDQ2XKVMFBdGQbIPwK8USE7mK2MJZnPWgaeUQplmQ9l1LFRDSyFCVCZzqz1A4Sq81lhXAAOAaAR7AcwcngMMFjrt8pjb8uqDnIAO0IX93hg7GOuHAu0A5syhuU6FDDOoHydTtMpM+WPK90Jr3Elf4cW+j5WX6ZMnlfLY3y0Ffg/Tv0CGVci82CC6eWkFqcEprI/BHYYcj/IQ2QuND+ZEUrVy2DA4WRdIewDfmPcBrynJ+igezPtqescbovOjMUXbFs/eI9fkvz3DK7/GT0EBm9aWOpdH2Ic1bCgGvuKMpzRSsnjaYcfLc9bvbxedGQVQQ+3zYfeUl9bW0+5uLyU9pmqc+P11jv0hP+Brhr6z2ysR2CHmhYwPWk3p0I309VBAhgy/sdM/URzFOsdlnzBODJishv0Mak+jWS9pLyU7son0n1aE6ORdR8rTxaY+UOHDAaTUSCrpy9Zvn4Xek/Reblr/fIlTWnfZcbFGlm3a104DB8RynMJoOWbMNa6dbW6Bm0cycgtNnRYiFOIOtHZHxQFfwsRYdQIc7tzq5Q20ewHdpTdfnvZjgeKR/tWbZI3rerjXsi5gx6culPcfn9///3bRa4lMWNa/rFj+dNmJCg+D/Lv86d1Jl0R2FYiSmqDYJPg38fjLAi8cSzgdg+Rktd73nuv53VSskHmBsCu4XYojmeV85/7HCl81sH1olcX36OjjFef1O/kH9F16/pR6zQTCzFaiJmrIg44chP4roKxs5tE4KiLwHc36eJaiB+Omgl8t5BmDu6U+KiTOAlXVBNvL64XzIs99YUFFQZDRUFhvWexWagvbo/XrLRYVn7K9QvxI6Qirhzn77/MB8dfV6bH7yMVMeW41sc1Om/QHfzfUSp04b1w1sEewYLgyMjKwzvhyM8ewGLgCIqKRHknkYj0v66hU3k1JSuam1eU1OTVOxoXF5sNlRZLpcFcvLjRUX+Ra1UjZEtceefI/7pm118yyNxryh8Bg5jyzn2abhMEmcvD2CbqXKj9hz0E3iDHg2GPNpIQGEmQu88xrYa+nyYbQN1n4wWo/8MJ7gzPycoIjhfooHeJaAxQrzo/Dk4aCr7T46Ynq/TUmzgDxQonTaxc/GflnlXHwJf1C0C/xDLTY5ItaPXim4z7TsjQBWUwXfALBzv4IvfgPKJygjucuh7sxzf558fmwaj8tDq+blXxzZSNup765qF6cK4Sp3MP0hH8DJ2mO4GfozK+yB5lGIvmbx87AMN3EkzzPu7MKHb6nPGOwcgpnZZINmR9QllYDpan+SaCadp1GqX4PgUDeTXQOMwIpBgAYTrdpz2XTHJnklSDHP8cyqfjIIefBDlchn5mVcmokXwGNqqEIqDy+AzExp0RXThYKAklkSca9C7uETYtzp+E1uzNt+j/8Acjjgb8d0G9GRv77nfVeQGt/MlLn6TgyQpU9XU27qNe5EELDbkXdKBcHa2DhGk70hk53osMDoLbI3oxgEJOZvS0JHcYOfLj2IXT8aFzCb46gZzIHwOlKEdVU7qgZe+OXzgdGyJ/TCQCgcA4XCRdEHBBMDVGUVVsABN/I55DXKiihv0uKHoMzihOpVMHA3mL4cMUt6QMnAqdJCEDnomxt4lf8y3APx8ahxXO7XVxZwCbQOKBrBvH4Vala7x4PRGoHNun15LSNRq4SBUVKsO0JxxFbVem/SwbB69aR5+Ch0d9k0/HJ3VSBikE/0rXp6El0z8NNXUObgP0lWI6zgdQV+JtDmq7il4rVfH1wH/8s88ajCaDMPZVmZ+ZquP+/XP8IWBUg/JT5aegMPGj/PMAYVTrR0/rQ/yX4MiCto0HdSwnjF20TGDy7algZZ2Fry4mlY5Uicz9LXWOu89eyZtTsywNVUm1r7AyCtn4KVqBaQIRv0Q4S12lzL3vqCTF/BEzX2kfiyWrGiw6dW6d0QJyZhwpd/LfzaUiF33V7mHtVAqtVAu8EtBFdV06nWGi9mxHz4MRVDOvm7M5nJGox2sUujhfMBI1c4agXzJGQZlu5rjdE7Rkevjv8/N/kr/wprUFq1cXkMaf5M+bd9PCsQ9/kj9//k0LiedHcPqVefSOJeOfZIfXHT+16LObSfS548efO3Xcsfmz36Sfi+D3Q/SSOnb8s/4K/n7Q42ww6km6Vpy3sXlAtXQiQRLOy0RxIrCegASSkDCwFoAy0DajniBe8dPbIlF85hApEfy+Wde8MKO9sLB9xgvXzPL5Be4XyvsTzypf+R9jdVUkUlVt1L7Jnpv2XLPFenDDppHhTRsOWrdcs+emiWeu3Lxx5cqNm/9F/b5SlXUJ/YOgH5tVO5Day4LBh8Y79gswP31WtMnwpQ/mCcpCZaGQJ+sXwJi0gWyAcfYoMD+8+UWp6rxC/gc/4AvzuLdlObX0S1/iTrG+wGfBYf6JXCjYYXHSKwdAqoQVPb5gHJiYGUvL/SLw1dO6duAmtFUo90hQ92h5dWLv6CDYINSfFaTzlmCPNBJ2NYvtRAEkgQ9kp35rlXtnb/W0eY79bBr1/sLhlQPJgZXDhfezEwl4ZzGMnEhdn/h+rHvmSssmISSVN1cm4YbNjza3tDQ/uhkOk5XN5XB2dOv6NYf9dXX+w2vWbx1FZ2dSm9PWaPjf4H/ZeF8uyml+uRnslxpdi65PNw/Ho6AmbV3Eq0lTVPbSTneSbfIaMrZjxgiLis6oFEZBS2WwTOVsAvSWE9QtdSZjECrHc0xFejC6N7aSXyhTqTxKnQ2pPnWOQulSn4OP5ERL8z++vie26laNPxldUervyoyxaXs3iEhrw60nTMbZkJQkn0oIHUjI7Q1OJzUaY7O6QzjwopY3EX/lBBJwWh1TQt2zYtTudDobCB2B5VTJRNRv+A2g/qw6Jjyl387/E+gq6CdFNAQ0YkCIIucAbk4zGERoBqEtYwDuauaoiQNWj0Crn9o1EcpHgpF7It5b6nSW9pb0rhsYXHcnPY631tRsuvWW1hL4bo2TB3N/xyc+wW2L9a4bHFwL5/DnnesGB9ZBKbfcugkesLbdcmtr/E+5P2MTH8D+YUiPHTi6h0HOdtLR1EXUAb6RiNqkoTc91CPbAQeCThxUpxbhfhz78Sy/Q3QlsIUSLlEpzByDQQ3yJkk9ROQ8es9OJjg/lUHHoPnYzTLerN4AzZwqobfQeJwAGiykKaHqRtsAZ55KVR/GhIoeH3aNrGkg1E4IiByeoucBRMkN5LxSyA0AA2cUNlDVAggtddL1NbALRhlshg05jyoHYJ9A5ZXF5m3lQzqrzg0wTURUpYOdDjdeqYM4nHAEPCw4ud1KITnPRlEuuvXK/dfK8g0bB6cvWjIof/ihnRwlR0eZ18hu397Tq5f13lk+330vvaTGeSKcknFQkOMaSU7Jvn0LFq2Uc4oT5+xyVam8+zX9NfyXQRcpxphJM5F4nz8SBaNcKCI2/XblA6No+qPSbiN2/jt2+72ph0n5MX7fWMzO2chPnxfsAukSbIf+ZbfymipLv6a/Gsozw2jsD9FyaKEmco+NlmBUPjTa854D2TLMzRRK6OOg59iJjTyADktVxi2BsaoEpEEQ5IHOB9RBZyfQ20EYY28xEHbKpP22kazfGGUF6Pv0hpkmg4E3KvMKKwuVefR4JoB5QD3dqrRq58rJ87nnyPOFlWbl5yRAAudrjXaTgVf+JghEMMChvvYj8lv15J+JUz3FfU/5Gz1U/pM46EUiCDtf+Na3NPmGNFkoTbrx6E9C4QSK0tRkoZ0mJZfCSakhv5uAct4klPFPTkKGOvZ8HXjun0AOdOuW6UA4EPTgpKUA9dyg01UCvSKKqgVKAh4DZNC7I8CBxDcT5tSBO7xWAsOqAShHH5ATTVmgXjBEI/Q6N+Qb9L+2EjvaAs7j+aR0urNibqXyictiKbG7xAtnaqoWzq+4y1NQOlog6H9jqrIcqFviNouFphXkQqG7UPkvS35F0YHmtZVn53ndpaknlhJSm6cvuMtcz3+mlJTeDh24S3TV9toeAlns5J2vOPqrzA1OcgMMW0vcFZZS9wO1mxsSgqOARIry9f4Cu8tin1GuvEh+nWd6zpwv6H3mKkn5L7KhWLkh/kqXubrwCxaOtvUr+oX8QZA7jToMVk3XUJp66GE+6v2CFnY4DQ6U/5RoGxv2nFqlWYiDjhvIFVrFRaL8BS8Vgq/ZOqsOlEdsFqvBTsxlHWWvFab6l5RAVyIl0wq8xYLjroplsVdEV8kK79rV1Xf5CyurxWbbb2ymImhjS96BlvU1lgpzZTV3zm3HsZ7UlttNvrwiu6W4xfxcMSm+PU/ZHLe0WF4xm+xdlT2lX3AbyPNw72eryudVlVR6H2jYHZiRpy+8vaCxhOw2GnmfuRSKnBcT1XiErfxDIIFbqVe0WVNEIlFJC0YKAPkhKa1hGe1UkAWoYuWbTFXh4549d6ET/q49npX2/qXoN1/abyd7J7cmxg5MdA5zvuhs6n+fHQ3VSMz37lk4uTWzbaILOmduolTXRn3aGcsp26JyTkpwFOdCpwDXN5G0lZ49/LHJqRudQEYoOjvtJxoEe7GFauY6Hxo57BVEp0UXKrVUl0JLyIj6ipdNL7pB4XUGbWgY4VSDZDWge+n5EltLa1/HvBm9jQG7y9NIGqrdYltD34x5HX2tLT6mrlYEA7Lc1fHU0NBTHd3KG8nkD3neVGgVy6tqG2DMbDGFY2ETaRFdDbVV5aK10GQETVcZgY9R7ktFJYG5qZvnBkqKyCIrrgDh0jQ4cfwmaWytOVT4stG26s2AVu+hdXv3rjvUq2I69lIaO86N4GeHfOWpP5X7QrM1rE5kEHlfx+xLEHgP8mGoSRuNr4ug1hNFl8G4OToS8tcYcWYpmg6wAyuBZ9EC0NgwIvuikiAJzlPo/0O9+F2qVJRCdzvK5jWzYukStd1lMb88vNUfL+0h1ydjX1kTe/RGboDqNxj/jFqSiA+5xMzkk/L1itKYv7HRHyutmJWMPT4Y+zLqbSoNGK/tAz6dDmNyrufKOzn2JI16jRHEDgbIHKTqEMU8df0ErJX30zjP6eZ+nPQ+GlvzFT6kYYyuP2VkItY3ajhXkNpk7Zdjg48zX8WEuqc8/A/WPjp58XX51f8rUP0vq+rJBvSWq3Hoxgn1H6Y+istuAZ9KwGU0AVkv42zwpdf/QoY29rvJeH/2P1z7BDlfcAIHSdF/oAP8ZM2a2OBgjH5eXlNcpT0Gn1l9IU9tC7Rh7MYaPwYjkPFNMmVfyLh0o+QthjozkdVmeXOq9vgoQ0aMy2OYE2du+0zeMRoyZMTGtQ1aNnU4/uDMAz+OCPQZOTFqIZsYAYWlJ9RMaFMEMpgrXXTaY3RUubtmRt+MGvpxsHVJC9nQsoSutjuTjSwa+cka9baaGa+3LGmFe3U5Mgfxq6XxVeO5Box3ATELNWc8E2nM5mfzBzdAmgKTI8VzGV7AWaFkNkJHVISyx+lWnQ4sGvQljPd1gtqJ8QS5k+iiHYxzcqdyoaNjwiB980bPgJyrGLRYq8UOYtp184Rx/XFrS+4MtjzguV+nxfcw3KbGbCoMpgCm6iZnwPa9F1qgHEZ+QfLkmryCR8K5Co+T+8v+fcq3Mnau8u0wmTf2NpkX23nqlMvOfRdDYLGGyVaMM9nKcD4DON9L7c4JJUvjS8RygGHUctxEi90+B/jhmgcfSBfKIWwVmhq8pEaWGTDmCThGHd+DJCh6aQRMfV1vbBk5Sn0yqT76xd+OAUvDLHAJpwKUEVnm2pfFetWQhtRJ+pVkwWVro8oI3nhUzvgxNZzK6CzqpBj51OmdyTDgBtAxOhlImQExpOuuiPpgy6mHQMiuPh+2C5IpqaSSdb/TqjJl5JLQNhuo7xUR33mKfzhdsTI00BbyuKzC0mfBslKaxkEidJKKvbOB9NEScoomZ2WtWMpbh/XH+O/pCml0rwNdihztwzarERd8CFYP6L4eFEZRjyOiJxmptrYsUJaaPsCtNxhSu0XX77h/gw7+ebgBFF32mXqT/NRgUHbEuOOlwTK3feyKU8Q9Hm5VLlynGlmO5EUxrtxNsoHWYzx5qv53NJy8d28uPNmgzBBdSKyLlJWxcMG03cJkRs8/IDVs41aWXZYUuT57udnliBQynL0CLddGqbsIFfy4pWhTYXsgK/BuCrzI+UnWpWV4vmZSfp9QW+N5PpFdI5NxfX1/fX0u3RpM1wS+H09sNu9nETiuB2hkIRyNHx+Dce4rQFXFZJLQi25OqxfO8JvvvVcZ06YqcVjDuEHZtZyKRnoq9bbo4pfJqTe5AbuL1plWdhnWmWFC4ZoATwPh3siBoYy1Ei7VR7h1qZMM2rocYDI5o/Tt5TdrICnMU5RXynQBtBPIOE43pJnHmeHzaA7/C2IQsMkxbLcdvDrNS8yQBga/P5vrO5LKSI5x25HFWXKat6uzGD4xKpMNahtoOFddFGOv1RP2TonYMZk0JafEYVQ5IWfzsQASCCOIo1ZJVGM9rM4cFuPeSCSUE2AKyMi8+9P8xXl2KyPDw6BndSHburM5TDeOb8UJfBsGQGGnNYtfcbUq2ZDI5dR/VmFMiKOg8aU+/2RTvV4PrtvFNbYeeBNL/yRuCYx1xjEVhtbZsUkcEThRzw0kssyfrHmDUl0zcBVacTiuTgQfBbRsngmS1FFF0CfIq+EtBydB6vOA638RPleIdk6Pn0iPkuTxCVLq80CA8qtcAbrk/ulx7r7USXJWM4PSa5gegnG6SeUvFp4m0hlA0GJDUnpyCs2EkF+KMl8VeUseWDFcNGw0FG7BhaBKV5c6FcX96wqfJPlWNJXCH3+sZdojm0/ni8aGz+P84LdXL0rPPo29FY0e+uyhaLR3weInFi/QxiWGT5jONKGfKb28hQbne8JBGkaNrlafOmkGWHMCXeyDfrZcPPmrioZXqN3R6WzogkYGPLYUGoxj/0aVl3mfWZHPLVyYHF1RXcPfm4U6N3PzI9Na0pNri1Z/G2c3P99gFPMPUn2o78a5jptqRhIr9w1Jm5RHcolhsVMYT6ZnUZi+IJGIwRMmkQDUsV0gHgIWI7HFyesxpZmvHjvAPWpuMN9nsaR+xC1QPo7DH3k9rjR/bQQumO8zN1hSP+Y2wll1TS2WbcQ5DZz3CRMnH2UlWwj5Dw7nzj8YOTLEShyKyyPwk1QMsYKGNNkSojHsGB1upGEDETD7IhhU4HOqXjPBG41or6BRINeWFM7dsm7JosY5N3qkf73nNnIyUB7tWLxyUzIg8057TVv3mu2f+/Lr8+eTrpaGcGHh9OiSuTd5VlbffKMUWNg3pzlQWDZqO7z86J6j227smXNuvjY/fYrG05fRdSFph11QA41YRfTB17/8ue1ruttq7E5eDiQ3rlo0M1o+PyBJjfyxOT03boNClx+2jZYVzggsnrs4EJA6Z1M639M38OuhRXBFN6bnQW+PVldg7BJvmGwl34grK8jWeHzwiKXegvU0GI8r4ZFl5Km4spx8BBfuM5uH4NoRdkHtP6xsHPt1JKtQEhWcUC73m0xpyvF4/A1l/wj3UqYgsiU+8oZyYCQzPj2k84O9i7PewOG0P+K8txO9leFs0QG9wYYz9zYUKryXR4/hVJEuXFHIWGsvtPGhWmuFvr9PqkuLhjqpr19fYa2VS0pmd84+C++Sksn9tuSD5+12I28rfH6+aFU+nL54+bpM/od1yxdPJ8VWURnmjBXEpFyoMHLy5A5dXTatqLcFLxKjE5WofQSswJaEkGCY3gknpvIvP9gE9CjfA0Kbwj2z7pvVo4wkQ4C2vdYYmiIe53tPWUXR+lSjs7TUSTbPfx5qymi3P0/b91/08/iD0LpOzJGDQ2HuqmNsZH6OrJRxZ2TQ5lnA1vSYEo7zS2TQT/5DTt3GtBa7uymmhOLaOMjKpXFbJmhiMkmpyj0j5PrxhSqHR8h1k5SJdfqv+gegTCeMQrMwwxEwC9YhfdHlBFi7IBgj2ryLgOFC1O6TItGslwFuiEoCXyME++N3XWHjOcEmNq5eu2le59WLi23+h//H4jd/wcwVvuQsc0TDX/jqtg3rBnvmSNWFeXreUN43e806UmgwzNi/+hGOF9psNt/WufmueaEZwRpRDK2bGb/37ZcKOSjBb76wYf2ynu5+B05aR4KNTRWtkm1Lf195xfV6w4xHVu+ndcXoqqFrwC8Ze+75y8DymcvC5xTY0Q+BnuQBeYKJewRJ8GX6Psp2nOT0s1QY/O6hR04PnX5kiJhA9JpPWyxH9lssygFLg1mxWizkDjg5pt4CssdyGkX2AfhQ4DbyAUhrcrvFovYZBreAzvarkE1EILZLgL5FWX2EnAx/Kg6KlTx5nzLAvTE1Lno6b7GUv4X66HzUP4fhVTTGQAuUCEVsLCQC1PdgmJ4KGqLQt81cMxcZ5c6kSlRzAfn7JtIkugLJAPpwZW7+wECp1dra09NqtfIViQRG3dAVPxhu4xKpEgbn5LsHB0vpTXBrek4I8bKwqFrbZWCUvDRsDl0aKpRPrtP38j+C0d+LsgN6IRVsVMYBz/Io0lggohpDw+2+0IdxKXetHRxcexce9V0gXavd8PeN6/fsuf4beLSaj3zcm76B3tpL7lDOrqJ3VLlcVfTeVdq4ynAowSxK4+GRIGanGl8+dwfmmJtQHE/Lup3/JdRtBa5y8WVF/2DaMJImMNJNJKCwBVOJ0cwR/FdWXzs8vOdrVVUVlcteifG/jaUCXaK9tPS2wVWrB/u+tQQOZ1+4Ln6GdPXUeDjzssqKqqon9w4PX7v6ldhYTYz7177B1asGbysttYtdW5bA4ayPr4u/qJztXr74G+m6Zrg5abY8XO+aRq+bUCwEUk9hH8sg81sVops7TAEdy0D+o1r8EtXOeFF/A9gtxbpO3ULdetSV3aAkY3XSgauLkHHDMxO7dhyWAywCM4gBm2EUV36c7sYlW27OzMFvB0qyZg4ZI+qGgS2yLmLpvtrfstBZEVlHVhWmo7IK6/2xOoksjfctXhrzu1z+2NLFffGlRKqL+ZX/KiPllStawhtCJLJ+qMW7p8TorNgwtD5CQi1eyb+Lr4Ny62uF7pAxXNe8c11E+WN9Y2aVY2N9vqMOCz4CEOrFqiqxHso9ggDqHMquGYc6/PVQ7sYQqbD/qXFDXTOUu3FofYXdENT6XlI/TPteNXqiSUTNX4P+KmcX4SnNDmcbEI1imyCv0NnkZoKU86tE6p3o2NbddNfGauKpHT4Q7ZhF+vbe0dGs3N10x6Iy06xoxx17+8isjmauujXMXBbdV/cLPQsVZ/8X48GIvqrm2juun11TTl7oXiTM2D9UVTP7+juurSnP8hUVUl8hCx2kyQHAMMQMVw7M8+MVeQFjJjAdwHllGKdgEomvydQBn0iVjHLvyzgJgpkAdLr8dJnZazAyKy4xXwaLmffim1e/yfjfT5KjNCLrJF0+mYA/fhl+JvA3txOjw+TUSb46kepL8NXUCUtdsewMq/v9+i/xLwMOzOealmomkj0gSE4Tx/9gkImzWSCsFBsXhoFgALRR+ICBYOi0cpxsIZtXZokz/p7UKzgGrDabyZNwAHc9oxzH+3TjYbsuBpt4Ph0298NPh0ztbqY/YpzOHN1S3Zq0d4Qt3W7ECS87JrTJWTxpo8Gu6B0bp0o7nH6ezZTZjR7twKcdaKqm39fds2CLt7WhrSZL92xsWxHY0rqsNQKK8FuoEbe1Ll+5teyJqqamrqYm8hj7/kTHvvlj3pr9i5evWTCry+dv81a1Vte0ZQdzvBlYEWhd2gYWVnMrVa2vXLM6Mt3URK7Ap7X/BPtSZZNWF01gNXddWk3wgQib2fRoB5J2cHFq96tknWPfZy+JKqVwUuQNNAfMMP8A9Bk3jNg+mhdA8rM8WwTEogHjgVAX6ySAfNQQ5CXBWUF8vGBEqeEmRtJmziu2kdds/jxSlme1KW12v2BIiq6v2qx5RLrmGnn58pXnyZ6PfmvzFxdLfksxt6MWbjkjFNtSc9WDAs4lFvXl+W2biFV6tZaMpZ5IcGv+nkfv9/u1OR2GK+Y0rNDV6nRonHRjPBMIElsWxsDvEadWm7/uBTw2frRedJFxSCr/kVd8ks2Tzq0A2O8pS10iaSVHclDjXrD7j7rq3e565jf9Eeg3d4Kc6dH14doKXDPbAo2Nml8VjarDqFtJW1NIw25pMFZEXYjo1JYi0gBeXMHDF3qM9rvrmh9y5TnmfbG5esdse8O911xjKC0w6E8LBZ8UFnOE22/kWjlzodGg5Jv+kF9q5ImH5L1oIia94d18b3wkxlmqm784z5Hneqi57m7oRLvvbbDP/vq7hXkGXv9iHvFw9kKj/g+mfKXQzhPSyhn3G4UCg/GTAuG0qTRfz12jH4q/oeapZDQ24SjiEy6XGvPlYv63y0aSzaXdoa5t92etB1MtOJopKUqXbYWpyBFp6BG3IRNV64qTo6m+tfGRkfhaGMWSuJ6fa1evsdBglPsiu+PWPuq2r2f1c05/CGAX02yNNLVKFgznOFTIBsywokEYzUKAyxsdldVyA9mAKX0f6Wv4tXS9JdIXYQqUgNGP0A5gi0dCElBo4UDXchIcw0HLCrdc4asvruCcsdS7gb0NtQ7rsKOryUESj8YGBodiQ8rZmHLBUl/JFej5eVZHbcPeQOrdGOesKK73XdEy7GjqcpQMxB4pGYrtUH4QU/7HXOm36NUx5j/1jbwMtU17Hom4OYpNMzceF0HFpanlirkOK+ceSv2eHjFMHnwkNjAwFB9Snhm64Ohu4G0GfrnVMfeKltTvhzg3PVLRiD9iRYxHhj52NLY7DOk2v5LO8vhprmXWvs2kkYTRCSkaJkmxwP+etSDmasBkDSyYQq1sGgxO3lPbuJ7OAPUFxjGB1uY3A+zsNp8aLv8utvlkEGmbTwYH8xt/8mWA8VWdkUpinLVuS8fCG2hQCJ9eg0F1GhoOH8bg9w6Cce/RrLcn6817yLov7Fg9dM02eZQuZUviF9p0uMiVLWlr0v5v/ZfGbwW+tYP7L7ieTMANmOcBja0R6vBOqrke6HStKcv/7hqHNdQSW57ns0WdnlxU7YLkuwi+3BsMIHfNYOrfVUzJUW7L2NvjseVeg2vK3aeUXTu+qOE57YU84ckfTURWtVMS+h66Nr+MZhnE2nQYvTxdb+OXMPUhDH4e/saE3UXc4t+Iyw5DGVHOFBUQO+kH26yJ5v/Q4lQ2mZ3GL6ux11hueTrXB5bbSKzpgrEGYOD3GTyCiJMgwahXDOrNuWDeF0F1KyJW0q/84nekn6LPn6bGrpa+xSXeYC4VPisP+3GlcCKRm8eiFK3uqVfcTZbFYco40YlhqVO47+SJ8a/jYk8MLNp2YhTuVMCngKTT1j88yBu1HMwSTUaPmaX1DyrHY6RCeSeWeozmEyBbYuRx5XicVNBEBco7cVCtt8TVMnr4CMsrzsrAmU5uvvJIHEuIk824SoOMKI/E6NOpHnW955f579A+WgQk2gResJECeJaP2rhf3fLeLT9cys16564HlD/VHbqLrFROrCIb9/Ge1M+V75Hr7MSm3LhYuYfVzZP8Y/wjNOs4K4V7+EtHvvTaPK6U3KmsDpInj3N/Tv23FivAv0ptHBvNe0itmnGDDGrJqC3j4hKccaXTsKjckFlMw+FDNJNMJgkjLmth4WVaHOw2uua7gsXhEZGu+QqPnxem6+/J2SQIEWU4E4Xz35w/dT1bnsUdtrsxfNDuziqXrjv0iU5MljihTKQI+jwYVGqkG1sS8zRf/X9kXJScUyh3mC2OZ/M7D9K18RiBorNhvWilejD5OeJ6QE0EUxrQL/j7czwHleMP0LL6AmmZcE4fAtkuUa8tcCU6/nG8Rc9VOvsLnentwDg9eIGyE/VLXpExcQd6FQSqIYFyRP7q3drVVOCz7thnqyi31dUdP3rPrzo69ZzL9jt7JWfqMOUVn9lYZ7k9HHzxppvvLtu0uq9e4ufe2EAc5E9dW71dxXlwD1dp/53Nxek7O351z9HjdXW28grbvh1WX0FB3+pNZXfffNOLwfDtlrqNxQ7ScONcXqI8xeiox5qeDPMqwlDXSES9TR+ssHnExx44+pvObg5QPJ1vJrxlml4v7Gz75t6FhuK8jdsrTUU/PQ3IcN2dvzn6wGOix1ZRZKrcvjGv2LBw7zfbdgp6/TQLT8zq/OFCOl/OxuisBdqdJLvdBZxtxh+oqvHP06VQyFCMqTAAELMebcAFV03cTpWZxYAWfjCaTPWhb0DGRUgqXHKpfQT3ArgeQajBfWTvJfQR5nMN8beATtao66VrU+xONUErvDqJunzAoH6L2VeB2pzcWem1Bup1lMkY/qlJZTchthLRH7rv+H0hv1jSvWb9a+vXdHNn1IOsS2Nvd87ctv389m0zO9MH5Oxiei3rNnpIHi8qsdvKXa5ym72kaJfkcDod0ij72pV9iZzvDAfcVVXuQLhTKUwfk+fo5fLMnewwkzcC68dJ143qiJihspNkcooZstKLZd0SJuPWWdJL+uBE6sYOTEbxvpzfeMC1JzJUZA6/O9nJTmLDr33ab3pA7WMtJ4nmWdJhPIZvXMYxHs9p3iQbdybVpyX5TufogpMn0aVEfkWaApkrLqVeGUnK5LwWU8fgmbS12jYmzjDKJ50FJYrrCeF9DgsACefib2fA0HWFycEwagO6UiETpximcJ4qQKyfBNV4jYbxdhOG2uAwHQ7ZEILqwMAky0Al90vSrPnny8rYqB2QUzz1kWAEHK6fZB2HfJ5jGkRZar0sc2fKyqgqwZMjoOfq0zgYwHqjMSOki4t6yqBevZT/+fEdl1bq4IObCpSvcGfGCrs6N1/x1azJAq4DCPx1waYHB5Ue5VG++rorNnd2caU53bhP1uJF2Lw96g5WdTU8Xcvso+ELBN2RYj0ueKZrS3kBVytjA3EDSRBImLlGGcHAZn7bKKaLGR07AB+jCXJUq19WPnojbWqWZzozI3p8qoKrD8IzQMfbtJjbcSEzf/v/hTISoL/CB5RTmC7HokaLTrAIfJhXVaQZVkVUrA3Uk0ozrEHbRdVv7bcvy+uJ3/yMREIOUE0auGPsAK7ClzHnBn7B+E6/ydlEgrlEkX2+FqDe0EQgiU3KcnTI7EsZVn/KGMFDnaPaGgtcP5rrm01n35nsfRA03gDixVLxJOAYODqUzic04a3pvrgOl8b5EmfapchEDErWKMtillk6hQE1GJFElrUvnpaJ+2qZtrh9y4z2LIWzfQZZLPNdy6avyIoo2yUPrJi+rH/HroM58V67dihfR6WR8dmT+j7Q70w6u65ZN5+OFjAmW4gUiYaloIgprTAFgA3NR286RaGRnaUZL9VkmHb6TCfLTUdTXaIMdQItYvpSNMLvb20pXD1gTMp8f3fBovZuPsA8C0v76zsiBXOa2vi+PX37rwLR6BY2uXma7LJ9R9Ocjvhc5YN4dS3nF1a7+PJyclPgqp+sFdseeWFu4q2rfrDU3B07uZY8Bg/XYWhiXWLFFzsL+5uv6/kKnEp2dWzbvi9xaH9F+a7drsTGpYtbWn2eeEt5+ZNzGrZGhlfOswSC7RZ50Vw1XzH/A2gnM/Q8zOGDmzoIEgkT3O/GRKxRPipx7/5aeUd+M048yu/ib8qoih+BP/I4nCaL8Hwr8cTfJIuUd5S3lHfuI74j92m5ur9K+wvmWw0Al0EtVUMN4proakzWrw4rgmr7pH/TUdcJx0LHDffdT2bef98N3dsP3aa8e9uh7RtXXjn0x6ErV3bNXT14dnD13I2h7tn3zu4OddVtGtpUt7F+qH4Dd3xTMBwOblq0EhMrrLy23+f3+/oXtVfDX/t1jY7SUkfjomqvt/paj+c6zY/5bcD1c8AlVbo6XQT6MgCXIjiPrKWAjUq0ndVPInkZ6rxGAU15y+0O12/YUK9s56+NKanmtvCmuq7W62d9ZudA19Ite1bN644tGuY+t6dgD1JwxYXjKmX3zupZuX2J57rrPHzX2L0x0Pa81YukZv4z7vjC2b699TMXTa8fVu7Z4/f3L1xM7lZpK1hZrsWwB3nc68pOPbCUfa2qv9vLeDTrJw0fOxVZF0kOb7viWEOjjOPyvhe+euJvfXGZaZNfw6S6/saGY1dsG97HhvJ4399OfPUFppNmwbTQ/H4627jixVzoIkXpFIOR6Jjx6l33PMSAJ2jfRWT4bQzEQ/fc9eqMjiQDTrt3Ei5nx2fX6+bqFkCHTuvR6VwcLIvHBHM6OkGHkXC2Q52Iw3hDD7l54bVVniwh46m6dmHT2sj0tByaHlk7rVeqS0871km90xraaIaLtoZdCWXE2njnslXrsqXPulXL7mxcE1q74S1NSr21YW1osK6vP5OIor+vbk3FYIitYAgNVlQrIxqtKD850JxjwI02jy2d13Ec+k7+kiuC2w142qI9dE6xJ9prtdFdL2zWZyehvndJcyuKpO9hqt3W5iX/VxkhVTW778QJxjt313zWXOdk+U2cdWbl2OTE35V5nh3k5iSapusArXShbpVu40VX06b9IhlfiRO9nainYssaNDPCox1E1e9AVDtzGS6V5SbRwhkfL0bvaCVGPaC9kfqAfd9tcde7XPVPq+bJFCt0J3G/fNXIWUTTO8XoSq2sYiYM+3/OQqcylmpmTVZ+rVI1x9FsugPHVDUERi6tIlY/fidbnRfye7SDqLpgLxTVzkxVHWRBnmj6dSUiWfy4kfOrxP+YfW+0IO3uoxcnXvl/Amc8VonVV/yOSXwqh1Yznbe5Ok0r0xVCQGsRame2HPUXBZnHegrMTb+mWpINo9wZbidNMqjm4x3FxGoZnxvGTNLRzEYXxeVorlHxFDYo8/hjcaM4v5ApjDuDeT0z/a8AtLxampdGpOtmQMPjMWKaOk21GXI0oolXJDaaMj9BE4OMsnlyZQTT+nMXHuGP0XT6ibF56OAexTWQstueelMZcRHL8Zz1JwUAUcqF6Uxr/bjUjxo4uNjP4yBCWAU7mk7TT84zipRpVnJ+VAPM0vBYlWmYmJHVQGvqidHRTMw26v+Z2Xp1p6esYHRctKFmpKJZqUiWxRRP9SW0jFT4XpKdrpjm1OYOy+l8xLmwJkDCGGuD+s6Bkro/AyMHAve+5lhW58GDKj9p9mGObWhDX72HqNtcsAxbmmXI+ZOjmHgv9WYiTRC3kzl66QYJJ0YztGTqzaruqFE9HhY2GFgZBprKWSUpDYy1FLCKBotr13ZDYCt35dHRNGGqXGBrH3DOB705DTg7bPDUsLQbQTVgw24mksgybQtWikK64dDQeDWFS3XUJZ11/WuhIyZTJ9GtoxI8OroENEtmzqVO0jkyln4nwVenSjBtaIb+DD5qhMfFsMm0LNiyk6CR6kujMAUGaPakKyRjO6M9hlZr1n4m6fxEYc2l5UMfv4fcACCpMzbBXFhuewBMhBHokEoh91pCc0ElspxeGFpSmN5zMg2z6iIQO8hU0EanhKTB4NMy0abyL64/HDeh5aRpi0UPzRZ+AzmfSBvfYgKsQUyWSpom5JVEpwetPS4LhlPN3TgOQhR3eu0H2jMlU3OUDyWTOYUm02NWKIcXaG7KifkgRRVzW9ZcE8sPNQkNanZHDCnkj+XSkqTEYF46ZpqSJlmTZRpd6gqYyaizgXgNq2+8Po7SURXyhon0pq6neWJBVCQ1unNlp3cK6ZklcVD6jJegaO3jBAe+wXSfRIaeoVNnnF++RJlNs1ypfQ69U7nSdLMGbxwsvjqZVKcWcRWoFpvO5FwZ9vGoNcQ2yFJrtJkYwlTZCLJMNij4vFZJOAWdWHXqrm9d0gLS43OY+PxUUnR567jd8qlTG7nHqBBAuC1LKjAMBt10qb9bMb2XLI+D7c7IlwwCkgbbClarnlBQGuC4CvHUqSUtS1qzgMkMFE23e1S1AQ8CnFegLjXenci6dAKGTvayZHvpHI3jeDe9FvlM6qTWpnSLgLT7S1bnQdFnksxaj6zhwPr9FBhocnQiVJV9zk8ApqVv5LL4pnQSjmHJ0CVhHKsAJaNQh7lbQrHMsZl5XNbvLNSTMM4ba6Btk7u9Q9+pUzlbOcSxLG0eibU55nBDD5KHZQwIejR+yzCAet5TI/lolFoQRvNUHzNNaPqC65lxxR0WXWNv48mB1MlIM/e+NnvLh6gVhD/xtgH4gKdK4E5yvmI/aqlcFj7ei2MjfCoOgYvCTSK8jC5YDqM8xhWjkzJTmc6szidZWQYfr5UGP1hxl206X0OamhZVVi5qogaMGBjFBWmY6sYuq0kaa6ura1l7QOPCFRzm8KsvC34R40MYOVmUIIVZTzRuDLCNIL36oDIMPQ6DwFMXGHjcfEOW7dz7rMelWx1uS5XImt8C82hbaY+bEC8U9Bhwtatk03yqoAdzd5JvaOwHFO5Vvg8MuFaOUw2X57TEENpIB6P2CbaNlTanyOC5JoNmy6jb3vFwXKyUXAjArWz7K3XPHG3PsUyuF1QznagGoK4u2XBXWulmXLUJfbSLlMrkcQyVWC6Pnf44fnoIw+jV1sD06xswz/bfT1+AK7ocGKUoBcEWZKV60gkz2YpEnkLhjy/tp0UrRxAeZ6C7eG2icMg9deROKJxBU/cAUz5QIbF1dHugnmjUrFOrHqdHjXKR0AzgzcQLn57HRLdbJHtkcsDuukI5Iit/ns8vu1ZfUVKbOjifu82ttgUKJ7ZjSsAq0nR/dG6UwXFMgKJByC597JTMz8CSs8oEQXcUS8zMGW+l8whONvPskYITWvkcZZj7cpuX5yizZDeuOnfL+GUSbhnPIbmsoY4nfweZsTDta9fZaGZMGCvUb5YYB2em5PQRv1AG9YLlvqa6RW4ZTFeDZzFVhKi+NeWePInJ30dplHRilGbHx2TwIflgIgkv8hYoLVRvyC2zhGGGmWOJ+m2IsrxJNAX+UW0AU4aT2ejNP6Wc0F1aeRYyWXnJccXR9d3oHxrV96TLK6NjcQujWnv5tNQ2HHCJM9DFaSllgqjl4DJ57plsc1R5keYCizaXk4rmShJZFybqdiWReYlR3EsAMEGdLkBFMv2QMylsufehowOxhK55aOAP4w5HJkIdLoSmdcVsl24uQuP+shaTdMFJeq0Zr/Fm5R2zq8FMKlx2e/vChS7lHZrO9dZWUh5X3smsYOklFa233rrJ42lV3nEtXNhut7tIBXeF8idLvdsCT7NT8DS7CeNq3unF5bl3YhF98LTHg8XC0wwQqaDyluWrxbngIO7VHVUz0tKFpGoWWguXvUYEt/WiKWxtTiLxp+Ja+lnMPJtJUjuS/SOeuckbVx6JfxTX0s1q6WpZTtqR7B/xzE3kX/ApTQ4R6H9ME4p6w8FoUKBv0Uvf3ih9hz3BqJccF3/xm/KtFUl4P/vdrGNS81Pxp6QnCaY0GNPaF5M/7+mj/IDuSrrSly43IVnrejGqRDSqKX0FlqpXzUasJvrFtStudTEhXXJHNyrpJtoz6LChaX6j2nnOMrs71p4v+YpMnfN6Y73t7vJqkGiCiZit7foZJYKhdjW3ps5bbrNV2p08Z8yr4ESjWF5QV2vKb6ovr6h22fMFjisq48uMxOQdJGslb7m9xGUr4TneUGybYZherC8IcLvmbbzqWluRTSrZd7W8eEGjs9BiKy4pqwrP+nLBw11ltspV3GBVZYHJ7qwr8zasFuIVjoaSfEddyZwqm8FoLrCbSxy9S0xLawWhcrV6a4nL6vS29xwverjTnOfLzelj1TLojNdYgx4a94G6KroeHk5khCZoYH3UqhkIJBLccS2ehA6tI9QsoVprTp6eQm1HjywoKGwwhy9m6OGf18oPcO+Pve3idiUyAcT8siSAT70pyzm4W3Ln9bMmuTEcBtOkA+anMnqvi7+STXSi4ZS77xeddT1Prafc/EImVXKnS/d5NMcBocnPVZX63bFSzc+U5PK0UFS2QQLO+7Iy/0l/E/+ULh8wx7gag01bT2LieeDhLg6XUPm5XvJBXAmZ1eWMHyj7yUlyR1i5YDOb/cGQHz5DQf6puGJVwmwho5lsUfYrA+QOUKwu2LRb4FMbXzW4zhyoPjeAbAaQjlyQ3GB2GbmQarORyGqLKiqbojh+azaJKtjTNcfymUfpRAg0PAwEkWiY7jKGr4Os+mhOsBpWqfR49vT+/ul8NX6OvT2qpb3jPMRGo5z+SjOIKX+l9W2jPxZW7vrMrsoHHmBf1ETjs/Ckvq5Pw9Kn2mlTYUVmMkwuhkcZs9tYu4eg/nFdfZW2O3C6E2Avs2Zv/nWKPFHkLiJPpJVK3OO8Qh3fuMOkPC9P+ZMaM3tX6uvcyj8rt2dGP7W9Gbzy8dDUpPKM6FxA5OxUUMCayhSvxueG+G+C3PDR8T29w/kUni5qdEe1HeBFcgOdxhrvMqJmt7rrObdcZuvhZE24oCuO2sjU/NYSFunTuJTTFUPT2VrGCZh0UBxxt0JMfhj2aQe2Gpz6p5hJ3O6+XKR695Iu2VVXyYMsw6+E1FvPkyZ/j8SfnoAahqYXBkRXmc0YYF/kLNy5S8aHqD6YpLGb6Gmu1dVpuLKwBBSwZkwN4Jd4GthNM5SAqomB6NoOAXwOrlT3T7b7OZctNdPm4vztSTQUyBOpVR7uKkVhgSaJ8GCUJ0eDq0P8ITrNEJCVdnt5uZ38RA4w86GLhZvQvWTPwo0zA/iMOreQi3PoUzBGQ4xuvAjvS8L2tnTal9FPRTT1JsWRO5yNI/Lig/ob+NPAi37UjaK4CJIGednYHI9dUPG0ZXcxT/aPV2Vode5qOfV57mk4OKivsKZmQJNmdYfOzPF/M3vjJGDtEo1GpdAKMv+FTAfJ7ioT8SOe6Di8whrGU+JHgty3y8YjByhPjh90nQxiIkV2rHQK9NRYD9xX3KZGRel8aqwynZvGOQhQr0hWDFAn8ajJ7rjHRlMnR7c8Oq2Fr26Z9qjSk55iH3talvl3ZfkbV8rylbirhozSUh5YOczNzewqsZTt6MFn4aBGNk+CweQwU7GLAILCUVf8uf6H/D6coURb0Imb8GhZ220gEoq4ZKFD+L6BGFNJwZ6X+qmRGL4vOPibCvKV0TyrkHooT+CuEqx5xJhfQGWrVl7p5CU6cafqqYr13Uv+jfzbvZOXLr+kcER5SdM/zuqP8HeD5MCdQ3QVIA2EAg6zpGCulCguFhPSPRDXkOVszJ7s4X7Rkzx37r1fvF5YbxUMr//CWl9QwC/jKm1jI7ZKbhlfbreRt7K4Zm7qN5z3TtKh/JiI9xKfVSg0CMpb9xbkWS0lqX5bWZmNe9Hu4TilMJuDuDSemNlUZ7sYftkjz1cuGa9/v2Rk+Ky4+3y0/XEWxOqsIFEQBsBGQgE5iGoa2hFjpTJf/fV33pkGX6dIv/LiKejQx5SfkdCNpEH5VU4Mf35OSVlF4MO458pIInVSl71HLNq/ZuoB9LNnMUlDAee1BW04Lx5kbeSVxCBO6NPUc7RY9NkfW79+6AtyggzK6p64sqzG78MNMRn3/SNHPwHGVvaQ+zDB11E6YCZlV4MLPQ9aXKa2V2054NA8iYZsDVobiSABTr4ga5lGONeJAyfcla00k6/Ie4bmz9/+GZncM58pQqfk+fkWS/44FfqvGCn7858rj29hutCJZMBit2Tt7VFKo8mil7umhofRT7SGnZ7wZYSCHCFncT740hfZQOUlyNnEaFr/13B20Zx+U2GMG9lJvBPE1ZTIJXHP0dHkFKhwh+VR5cRoIg33pP4A/yjNUz+IawOpecoin7SU8Lh8jRjpIdushtmwYLBK0SpC10A3quKAzjuAOMVplg5VODRSrYL/vd8aDK3esHP72sD8r68cXHT17B6TKdT7mim1fqortxEbtjtL3FsTkA8qf839TUxrfrhsRSBKSGh1Y5XFMq1n51X7D+6RrvkLKZnqylvAJJRhAgE5c5jdBhXAMxhnlN5BnQVT80E1jJNuxJG9QiMStXnVTYejuALt0mqE+HtXrNrAGrHU0XTXQRritnz+3Ci3faorSvDTqoQvn+lhEVrbFs2b00XclFerq2ek9uZcUH6vXXh28grhc/pR3+X2Ipvmikc/eRCThjnRF3MZXeoRFiVzK9vQ8NbEZfUt+AvI7Ek5O864FEe3qXsXYsuy8WtO0+BFuloogxziOgWC5Gwak0BW/t1M3WJc+OXWLi6fFZzRy6jOXRfgb2ho6NKrkbuLPTGUU3+VF6u/i6E0MjIylUxKwrWJ8mjOPyCPnIbJ+e4fET9EHseB/4i4+dE4VhwnZxb943JGmpzSf0Ss/GUcoZcvRF4ZT+Y4+TH/H5EfbhLA5sWt9iQgsYtDX6vgrzFeBtsXXriQ17/Wu7J6VeuMLV1CMCh0bZnRuqp6pXdt/2VIlLNy4wz3jBopvHa6PH1tWKqBX7lyJXKxfgGKMm7rgjOwmNrezeH29JIRlNWppctPp8Q778JUHck/EctGOTtOqAgsw3q6M1MUrHyaWwjq1IzLnHGhs9U4fgaL+23/vkCqL7Cv39re115ROHvZ7MKbt3Nntqf2Zy/jsVt62x5+uK3X4qqpudXf1uYvW5D6hCMLyKvZ4QW58/82Gr1Is0DVGDEVlObpLCMafDdhq/C6iD44+9QV1vZYu/WKU7PTyZIBdvzk+sJZy2YVrj/J/XK+XOL2et0l8vz7qZfs96kvUo/JtpmLiv0tLf7iRTo1F5eWW6z+0rKLGYJ82Gu7tBxjZPjguYPnLjHT2JvKi+dIf27OsxK09SZmHDOgZ9w2ed4xMgwgJ08+9uY5BoKnBvgxPgQSPJAVJewi6ZzIyANqfLiNrYJ0qNIG2QVXd9XQ6Q92GnstTRYLL243C9Nn0fj337x/3gI9O777xusW9HV2L1m5/sahLfv0C6678e71K5d0d/bRk9/JHPKhUsfyyPTOZOf0yHJHaZ1/dt/i19lx6qS3pr3CG3e5rSXuijUtNR01XnK+xOp2xWP0ZNahuj4c6aygHiQxl7zsDaSmjJPWPziBkLcpfak3s+h8O3NIHpez0N7Fjik95F/p177MGXao6gAhGsdr0aJ4qPcSE+wFBdA8DON+kycTaowuLu9iRzyndCWoJTE6msgcZvezAuqHzyor51gtk5zXQhfUQpRh9UC18V6GOj2kc1MrM4h576kyiyNOWlqAjMZsbkEaeMJr252rqw+CYWAVH3R0NEOj6Kjjhci6SMUf1PgC+Q8V8JOGovwTurpZKB+a3BURaUdbLXFJ7bwM74pm/lBk3c5mOT3rgfnYMEgFUSZnlS7ufdxJFe72TTcSeDgiCRXUAaXPoaNFN/PTqYBK4i+fgumynLw8xAv56smRzuiKTp1H10R3SqP58zDFLy7Jp7mSRC+gTLcWt2LD+nAMFanawFyoTi/L3mAUMAt7UIQBl9sNFn+pY+MRZeTbFrbJDlmJ7u7UyXopNn+3u5qcPzS8oz9WtBVdXS8ProrepozIsSuHyJ66/vqq6eI6edU3LeoeO8kksAtpCqxfvmT6TY13LFuxlpzvbN921UF0nrU2L5VJ08H14chEevr+F/RQHcnpsTovnxx57dLF03coI/tim+XLpkfy9e4gTfuWTGvR5gSC/GmdQGd7qNeVeZ4E5iCbGJGL8YC5uxqEcX/zrH0MsiYGAtwZpTDrEvdC1kYOfdnb7rAA5Oyrusz8CcMP509UrDwTtqlnWNsmYMY2LBpOpMP8cLIivRdCLlbZ+FAclPO5CKEseQza/ys6l65Dt0a3TfcZxAnanK2hhGEGDmgUeIhNpod9F79Kkz0IdMdcuvuyn66qxG0R8SbiyaxTl2gxKPSxP3vwBhT3nTiKkSeBaXiBWPPM6QPOP/Gc8qLoMudZicDDKfVA2clXp3XFgOiSfJ8dwMA60TXwWZ8ElbbX7nZDQxoEUmwuc7exZlV/BS5yTSYusc1dZi4mgoGDggnc6VJ/Bu1uxbdr/dpwJBJeu/51tz2wdd3gYakek6W57A3S4cF1WwN2F1Hl3mP6rbTOZ+gGdNd/Wo0T1MRYvdLFqkbBgxtasw6YW9/Gmtz6FsYX7CbZBU9Sy8oI0w5ZreFyBqw1ZLTx9fyziQ9ftGqVFwG6a7KKge6WW7OunIqFenPlFEqyYLCx9Q2oz73Q33tpxiAtYyBWi2aOUlUqiMIKw+1YKgmcn8KM3BIzBtT8iXAHv2z+zbX+SPPK2WuDy0tLlwfXzl7ZHPHX3jx/Vk+koSHSs7svvKd9ZvOStrpl1fF49bK61iUtM9v3hPvE8nJ+76Le2Mprd6xdMbvb22Y2t3m7Z69Yu+PalbHeRaSqvKGhvHrso8aGtZvkne3rAkTCAqTQ2vad8qa1DY1FFoua71aj6dIo+jSMLwErVT59Q38z/yXqRce8w7gnHN3HVLKRKG6DraY+ycQh+VswqRp6BP6ZfzD+4ivKQMBbG9z5LNl4m+Kudjj4iumi3RNaFltcI1bOvUKWenvLqnf3HGhrT8xdwH9xbHv8zCvk5Iyj/ye6S4krj95G/uDbsIEEps+fm2hfGlsiXbFlbqXDO3Oms2h3nr8p5LGLrM01PMtysDQw9CZFiX+aYZL67qTQtzCQXG8ajMpbN0M7+OnusJO1RAsJO9XGCLDGcOYyVTdxRjHySaK539ktGv/xO3LabXV4Y9+qpvWdBVktNyuLx4p2XZlo+eNT8LG//QbKbaLKiePbN+ibHVuzicgkEMQmrqYtLKeZLRAgT40ukr8xupDIGynXFaVZMof/mqfiP0pVGKgSvBdlRUbSey2JK5/6I3z8suAiTKkivXD0G/Ki0afagjnMmYlvxpwxu+gOKdQjowWAOWkSxUjUw5wwYZqsh3kOMW18dlrjtONmSi8BGrqa48dIZyJOn4hNj/YsjixvNOiLxfq2+cGG8nBpZbHy8hfPnCHwyMJk8jFHk/TTslxX3+aVy5ULk3sVlHfDW5u6gtHINHeZkc8rqPA8N8fTV11bF6v3VnhLRMGQbyzJC7ZXRWsW63nj+promgVFnb1zcj0rTQ3fmcLZWd453W02l9orbGJlsV2Xvc6GBztnmi6i62Z5WKxZaWRt6qLrqFNgOXY0ZYnmx7ZNyC6La8K4M+lVx/0d8bn/NDfeMTc2p6WsnClO5WUtc2I/E9WtFNXvPcoJcnajttB4I9kEt9Mb50IJizS9fBEtSjmTvR5VtZ8f5DktLpJkdpaVvFpsfwfmWaXR7tTPL+BkV5hF3BNP2ENsLL4/GUiwoP9EgGxIHybVi4Akrp7icM863IcOQwNIE8bly9pGtDLdx45uapde46OtlY6AdX/l5a6TJjSsEQZpm5POyTXSBNM4mUqdD24YfpEutmwBqJT8dAtqKPAynHHKecnkcZny3G1/37fDWlpqnVlnMrmrTceKCck3VVhMeadvsVcKJuUwXtx+Z0OeyeUxlZSYPJexfjr1cr/ZZPWYg8VE+kVpTWnM7LGazCSvoqrcKT6W57EoPy+XrHDhz3MtcMVSXW0xqePQjfow/6ouqjuow0RvfqMQseBUO6ZQ9bLdIKg07SJUmQmwLFzqPiuaD9ov4T1GrQ9rx/RVI2lWWFYsKAyrEdYuabcKvGgKdn+0i4s6BCPfb613c8Ymaaa/wOycJjYuLK0iJNRS6xStxZa8Olf1/KpKn8liMZltotdenJ8fKK8kJF5e0VYfa7TYvA43If6KplKLsajM4y6prKj2ljrNIUt5R2VxZWmR6KjxVLptVcEqL2mu3R+r8NhqywpLSkvyy5rKGmxVjc1NxhLrzLUNBquF20hMBYS3FhXxRpOVtNRHly16si9Y5iB6gbcK8FfMC3piE0Ou6jxT68ye+deuz9/GF1d25xVXSZGu+e31LqtBdM9oa3J4rHZi1Dv1gmAozNcbCRFLvM6muRuv2nz1ku75wBMGcwFvNOhNJcaCAZ9Yqp/W1hhrIc1t09j89xv6Iv4a6I3bdAd09+m+pDuN+TiCqlymS9xp20k0vRt6rqA5o/+ftjcBjKu67ofnvmXe7PubRdLMaGY0mzTaZrVka7OlGVu7d9nyhjPebZAwYAK2IcQ0wSxxQiqgLCEmBJP0A5wF0gSS1ElaFbJAEBQobXFS2oYSSIJbqOJ5/d/lvZk32myRfLZme9s999ztnHPP+Z1mZabYOl6Ebk+w1ZCzLmkUfAdurZbS1gJpoozUUkEbb5eaEFnmibsvSqCFLyCYA5wyKPeSIFcT/2BpNwPO+ncbjPGGlQPByvq6ZoMGaBk21BRprKbMIZ/OtiRooyhAUzYvF1KyZrWWAfvq+kMejU6jV6poxlbd3dzu5R1uT1040+axmu3WCouD09c7G9SMwWP1OyydwUiwFqpxaksyYrcoGb21sdpu0XDC76NmA0v5eEe0xsoweiPvFN7ha3i+pha9vRyucmo1LM1wGoO52Wkz6ilWZegEGpOaVUEi7ZYKE8dWR2ubG+hKm87m76o2Q1IZyupW1XldOiUNwIG2XMCu0Zt4e1Wlrzph1nGwNWEzq/QAMEqt0ekOdy4PRFSs1mULhLy1sD52nmJirnoAzPpKs7uhImQxOq1H2YC7wZ40mjU1zQ6Xs9JgtnsSbQm3G755/k1lt9ZUu4xWk0NvZk16J2+p9bRinWcK6pnXQHk2DdfvYYRaA9e9OMr0UZyiS1FZS9H8mI4DHzLwmJG5x4esPFAxZkkeDJIFwyf/AW4+/dBp5Gs/uhdKSo3DTYXryOfeUaMnSvUUrnPX0WE3R52En7GCmGIZPCrCIuw6fdrgjhpHG1c3CmPkRnAK/hg1Rt3Cu5EqThjz1NLhKhU45Y1NeGwkshnF6UjfFPK5H2Weq4Wz1zDCkQ8gRxglATkURb9wAIlUYTjhE78YNHnF0wAHiYlyh3XeLEjeK4wd+9yPRGqjn/+HPRvWNsdtfxuq3gDMeLvYBEyt3UuEozuqDnWBvsyGTbs2DvX/Ye5loeqxjhSoXLNl+7rV4xWqTGbj5r2dbS3dHakkVYWT8y6votx+H9jz2JKe1Q1NNYGLP7pkLqR7FTa47l0l5b+asbSF54XDQLJliktwmUAGqathabqAyiredYM/0GD3FqcBpORi0Gxx8FLjc2y0zgOYkQN6n8c0cLdvGV/lU6o0BqPNptHSjHXZYHfO6mhSUoDlLK6tG5d01S7ldAYjHEBKduv+7iUp3m80MRSdnL3YzZMnSlgGqjJxUPXjWzdxWgoOS5XGqtGpdJxKQ9MdfqWSYliV1WLmjTxnqG3w0DRDRRtcNovaYDDZOAnr4Q+QtxvE+BqC+0Q7rLQv4wvSASvwAdpHB7kEeOv9jb+7D/zLiOAD//q7J38nPAi2gOwThWufBBe6bqF+IFxxD3hIaLo3D993UlThBeFlUP/ImEKO8aJTVEJ9J6VYrhiAsznOXYczL0Hh2gFEIVuUjqVvYQOw4ogJIpPDRmfRUXQbXJSxhR/N46id5uvVjIKOBGwVK7fpNeyB48JKg7E5Yh7pdJhTXStWBoSHGzM3XVObsNsGr8r4Gq65i9ZrT9zXlXE6wIcqvStwamfUlbhh+eBXWwf1bt/afp9D/dt52v5v2q5s5B3LIpUOg84MxqyOXM4TSFutMadLmAKszt3b73OHPyP0NTUeaQCV9pBBmevq+OtYU35bcldtNBRdW39slYrRabZsD74273AQdWk3/VeQk19QnEYol2IOAwxLieovLjx+0oXTqTRmTSNoaib9HRkFAVk54f+SpILHBQZ5LMa9OEpLp7R4wivxwEFIzCgyRlLhJFi3RDxNo1gYBwJAUIbCzQ2ACrr5J3QGv15fuaZeZaZNq4LNtXoToJ0VlnSAob2U0aQzBz5XEVVTBl6jAUsqKaqqoqomuVmp1pmszsqupZ0xtVZr1Bo4zfLWaF+A90eaoFSjUj8Qtkec1epqGmiNy+o6fF4QDwZCVU5fTGfnWI5W29RGpcpgdvLBfmV1tIqiae2gjqaoQzaPUbt1RaUOztLAogx6DRY4cADDaiobGtNff8RgUkLlyMX6XCzQ6AvqqnBlq81BK306k86qMVC0zd4Al02nOxBp2jOytK7Hp7dpVGats5Lj9E530//3rd1DV3XUm1XAZmn3e9Jmp92oV0OxiWaVGotGa1RrzeA3cNA7TYySpVRKipX2CJ/EtvMmxSo4yxPAR3k2Dshac9FBGmuoCNmedoMEF6DnndwfQUZtGZLewzvzeZbR2oLujCvs8vstWvqYKx+fu3M7sDldDrC3fkwHovm1jRV2W9BmZCjldkZjrfCtzQtj8/ddtF4fhQz4uQJpWDimFHBWBFql5GgWTudB+NWIxWcrZ6WBlQX/fjh93a1K3kKdBKPOVicY3Uq5tbft5zxc35uPvQem2oR/pgZfB8NawGhYre7ik6+bTK9Th41qzYm/1+uF30+BJYUPwY+Fbc9I+9L0tzG2pRrtl6lBQA0SIEyH7xTeBpXozXxn4YUc+HfhbXSA+lnh+RyxW3ybCdF3I50hiMaJowFZYsSBFsIjhMxYsFVCRbsBbIG0JPNzZKDYeQ41ihLl50hlkghVlsiKODUn1Ama8VD0Y0FSiS8kW7QeEkaGrd/oSrxdC9bbHA4KmJ1am8UQslbZeThweIPKHKVUh1uWJS1+lYOFAlx9avnJrlR9tFrJ2tU+S6qt5bAGGHmacfCVDRVApzbRLr6/oamxQcOyRk0kZXW0f6bdbktFNEaW1dQ3NNUP8E7KpFKqXPVVNidD2Q09e/RVlQzF2xkuFDZzaqvFR9EVJqWWqaqs6hs6uWVl/zo7B+DMZ/CbTH6DjoVCIb+uP7f15FBfVXXwszRvtAUY1hJ2PegKqAwRL61yVuwYysY1bn1Nva5Gr7RYlPoabaxG79bEs0M7Kpwq2hsxcBbe/qArbGEZv81op+Msbp9fM1F6F8q0Bnx2jK7MlSd0Sciw+WSmGnjKR90Ivk5nO1t6BzZtGO6/IdjUFLyhf3jDyGDvslWxlqXLS8aEDat6NmuFZ8Arbs/ux5emKt3VnrFVO6Z2rBrzVHs9S1bVOZxFg0Uk/Nn14hr7JSZDfxWvrg6cyQVh5JFoQZQvgnjPckFgRkkxM8CROa/X0dUWrVapu/iWJaLh3OCbbwG3sBGE3hwa+qxAvbWMflQpNGkiFh360Fq0Bvoh3l34zvlHweOFb4HQEPwHIueXFWVHlBdPh1GfNyg+Q+waZAsIGauJ6kLUmKCIlWYP+kkcJH6TuiB+S8QlHQl32xCGRiZvcQecc2iHnYezDpx3aNgGUBqDzUDDWsKGgE1Bw6YgG3lSena8a/RZ9AZuCyaC8E/43pbldekab6POAOUaQFEGXaO3Jh3t2i4e1xpnHN9Z46nN7u6P0OgwHenfna1zh87NdZBqFcstbmvhN30FKjg4djmFyYnLX6I42UEpzjAp+lFjpLuZXtRo3xBAWTUhjnsSMIp+i+sxQhWFp7B7mEOJcuskO1AqMdivjfA65EoFDxXNaedlHjw56tnCY+FlllMtrFqtNFhNvCHYZvmUyeLxeUNOl8rJmDVqndZftTIUZl2Mk09ZmtYbrUlvMLTB4fM1VleXu2djACFh6SPZd3ijRk3DhU1v9tyfHQo4Kyuqmqvco0a1Q6P36XfXBmzWLXqTvWLwHzp8NdEaG6jxNfjgH5FnIGO+QVcpTFCHy6G8eYFi0krsMxeUPFTQDrA4fsVxTJXOhItRtiKjmGY+ubyjfsjvcVpWDnYsWdoghEzmdYmtV3c2hG2+TG7j1cd3a3Q67a7jV2/MZXy2cEPn1VsT68y1Hv9QfcfyJF/RsHRJx+BKy9SKocx9yxNB+8bhtb9/yOM73XFN1N+2F3jzNx7Vm836ozfmhfN72/zRazpO+z+VWH5fZmjF0O/XDm+0F9fzSjj+Vio+jbI3yRZztxgwLJoymm1yqxJJioerJnIj5ZAdsIpCF6yxxDBimipGGadKOJduIJPg7PRfwBZKtnylJVnpDJjVRpahKVbrMeitfDBs08DOyyaibSmPJ9UWTbCw52ps4SBvNZh0FhVL0QxcIQJ6q9FldlQ39S9b1t9U7TBD3Vxv10ScGhZO+RUaS1U42jf86nBfNFxl0VQAwLEaZ0QDTm6uWr1iVbShIbpqxeqqzfWeeNhrNQEQ5flwtMGnM3JqJaOG0hkU09CbmlGqOaPO1xAN8y4TD4DJ6g3HvcLnHXoNx9C0Ukkj64XeEY6pa0w2p3fZBl/zSs3hLduSmUxy25bDmlWN/g3LvE6bqUYdk+SrnzF5+kbFCsVP0B5pCslXIbyvwpHdOq4k69odvLgBgPRoMe7bITMFpjMNIBjHnTAkSWREbIbLPS/2TTJuSSi4ATiaiTztAaXdDyXKUhUqfvcXhXGsshYF8xSRzCEdRT0WH6IraMrudHVEV9dX8AxdwTC822QwuYxmvSoSdrvsfq2zqt7j0PrtLk8oQqm0JqPHqWc9DprW6QoFjdFq1nCswxz0NaQ6rxuusdpZpcpoUrNqncOodZoqAK8xazQqg7sm0arW6tRGfyelZBiLxgQa68wWvZ0J2EOjNbyfs+st5pqYyaQyMjRHtdcYNVqtenWb1w40Ssas5hne6DbpteD/oGoZa6putjsdscqG6voNEY9KlV7ms7sqLUadETAqVqd1qUxarZlzaXWwpVm91mD2RW2GtgzkU9ClVNObmlobAjV+K9/rjzQsybXTNMdQlEmnt5m1Kqhaq528xR7z1GqAAc5sas6koSuMZgrQQM3RGg6KPRqTSe1kTZyG5lSwz9EmfRWtMXGojnrK2F3TQNn0WjWrpJRqi13DK5miTSIN5UiPohNJ6cAsFyvEoDb7UmBGmwZtgEt4KAcP28tcXGfFdFSiH0aATNb+ENXlqd46PICwigeGvwu/NKzeHI83DjZ8a71m6eiSvu7BrqtOXLV8+VXL9fpYXyzWN9JXdz6YrKlJBul7hR8oG+sHh743NFjfiL5s+64fOBtWN8Xzma3tmtXa+qTwxeVjXV1jnx7rGo71buqNxXrrXXjdI+OiwOyhexQBxRpx54OzoV6JxFAphZhd2mNE/Y8l3roJdBAn8xTVwwaAEw6Lc1IyQ7o7nQgvj1AW3Zp7P2evrT2wUcvCFh3uXXJkZFNj3GxzB4V/BcvHlsc3+00eqycE28uVbR/fddNQftsjvnTL1hQXr2711YG2m27x2/U89VaoKzykswCt7cgNoyMrMhyce5hWRutcvmL/VZ8zOtwW+x1dV3WGAoDhHD2VQf+3T94wlHWZ1OpMgNHbQ2y1J9m1fs+NX/hiCs6AlKRb/5q5m84r3IoRbGtKYqhv0Q8JzQ6IEQ5sIIKDGk68kD9oiOJtFWyCJpMAcfYm/t5oSHtR6jsluRj1CTbtSJNlm+TbsZF1jLK0HepWr2nv6lvds2IwqbJXUBVtXpvDWRUPhz0eR5Vrh1Zv5oEKaHW6YDid3LzlQH7juiu1605GotVujY1SAjPsrgO8w+p0Lj+yCWTrItpqNtjanLwh2dwKP9osFhACVNuhfmPr9qoqX/WVnavaVY6WapOWpemtHMMwxhY4h7tMm8zVen3t7syWoYH6hkj4tnVM77K2XGyNX8NX5fQ2KNk36GiarhswKo111craZGwIJQgf2gQ/KCzrPM9cQR9TqPCe/3rUp2bu8SE1BrNS9DIlPBYTWEtclfkllOu0mPsceL4yGEyHQiBRGQqlg0FhaY0nG6jweg9u3bRv36atr8GPYEDjcTPVBjNfAeBUYFQrG5yucPC2TVue37LptmAYf90VClYFveCfg/Ah0p9wE1z34DzXELv37D318N89mxI7arXeNXX3qCnKy4/zUaOGS3d2ZUeGB4744L8jA8NPoq9+llFaxT71X8y99FaFVzGsOIDsNSLx4uRNNhvIMoNWHqIGNkjIIfhnEm9WGIAkiifiReEbLj8ErATt+wf8ygYgW4EYbSR0+8jWTxydau9aN5i7t2NFpKa/pc3jMy/11/yLgVEZVFy9LxDRqDi3zQi1OyXHO6ojm6Kd3TvXrN853N+zJN1eHzYZwAgbiPJKZXpLmo8EVHbe48VBt6C+fWnrqKtyoDu3aeUD/T1rWSZU02JXq2vru5y19fXGGltAp2Y5zsRQgDHrAxanF2o9QGdaGm37ZDyzrdLNW/zVg+HKOh3LbbbxmhqbqwKWonZEAgyHY3rDeG4ifQlHsKmltofsi5PuEwwVR6jYe2Q9K5W83L5EvyrY4TpgU28Dah170GBQq8BDmdXrrzhY7ERA1rsKay+nR1Gjwn9QtPl5iuXUTJ+KfrojEJR1JEOxh430Fr53Wb2KLtqIeEWT4kYoM8tt4WQh8iIe4OlodlVDYWs8QdQ5AvNDskSSP/igRHPaEfdKTmBkTw1+BpQBmdghCkPgRM3W18vs1Wm++nPdvsCsveLum1pWQhFCqYVrIathVRYo4DG0zWupqdOzDKPiQoDTscwnGCWglYxBrVRrrXbGpHIfXKe2sMurzVUUXNCVqu18usxI/vrWmus/91HLTd2zbFcBH3U/FD2ZREJnVGtsDKviWJ/HXG1RQhWNa+QAFaM4BqjVDoPKwLGsUgMntapeFSwtF/Q3BikVq6YZMoafZzrp43BtrEU2hiAXJk4rogkOB+jgZAAO5H2LA8vYDM6jTvvMAS4coD637kB1X1Uwlq33OZsrK5m/n4wlhpIH6ndqDb86duwasG3J+sngbeDUxLF431+kz+za7A9Ec7XV7taO5b35ye1NGzp/am+szU/mL8QQXhY1UuiWcG+h/rSbTinCcGxsIXb1EEmqQPazbZLqbq8ubnHCjoKTbnBFJZ+0LdHkYRMX90Ex9BMRV4GZpX9LGzTO/n3Ca/v6nRqo4LMqFcuRYyAiO7bZoKQBxSg16mRN6vF1vcNbcztDNUk1lAGRekxOhHbmtg6LZwqTIEY9pDVJjzRpnUsGvzO4xDn7UPOSwy2NybZELhJMa4ykHK0mHYzkEm1J6bhWKgieEVxg25PiXHyCWUG/jONCmhQKFki7uSLkFQbKx0zAXEGCTxmKAjUunJsZmJGbFTBSCja/EbTPDNbIzYwZ+QjcPgNrRaIRZapWzyQxKI96p58Uzs2iSDhQIuBHwrlZJJyYib1S4kmUxKqVc4CfxSWAPczpvbNqPps7wgWEgAQ0s2p952zWgPY8xn0r8QDj9wGErpqyzuIE9UgexLrnYAAFpoXTeXRiVhn42X/HDNG34Nw9aC0JG6kwF86EO6iwwwjgMkF9FZzJ1kwFclMfZT+cyp2dqtn/mztBT9U79KeEkVzN1Nnc1IfZj6ZyAXjinSrhe3f+RvRtk56rKHtohhksf1oOvF7+lKxopyN1tkPps1GxBEcBzGgLMSsKiwLN/Err7HaRsio75J2WvqrTzjsIINxfOB28vTOyovuh7hXCtd/+tuuK6654YI5WO0f2r/mSnQ6YV2we2bj5VtSEt27eOLJ5RWcI/jv57W8nOjqE2+dozTHiVpWPdhODW3e0bAzaFREUFTtPHenZlbucOr06V10uWQkhOQf5ull038s00E9AqlcpNiDdAFEnhnQ6PKW80gGfv+hShLYurRkC0eoFmTAR1FB1UWWRsQGuImUeJMBaH/vS7t1fitVrr1DSzDHWpqbpq4y8IPDGq1Q2FUUdY2jlFdreKA8LpzwZPtqcsZhYtdc73tc37vWqWZMlA3pKUwA4fuzqKx+rq3vsyquPtS0dVZpV/6ZWsoAeMxjGOI5i/k1lVo4uFd6P8A4HH9mcsDS5EokdIxtui0Zv2zCyI5FwNVkSF2ZidNzL1GNepNCOSOqyeJEpm7pAwCTV1LQLqoI3wppS9Bip6RiqKbiRpZXgm6WavLuy79j4lY/FYo9dOX6sb+UmpUX1M6iaw1nZaBznOJr6mcqifLccj4bF+Cq9UHasg7R2wJb7hEJhLe5VSjY2bFQT9VooSBLvIGyJy2AzD7LM4ZBBtC+TlhbK4saCvSwEDbLDA55vaFu2e++Ne7f1ZILegLNCrVKqowackaklvWZ51B+udKrVNJtnAK031hosKerLLKU06v0GU8N9XT2rbsuk/P6drc0pnLfJaFn1lXB0+5qhxkZ136+pjdv23rhv17K2ejdLq9XOyrA/unxNuuUGeKzdEIVSkrrCGfAGM36Twa83KinWV/iW2VBr1NOAiQJ/KnPbqp6u+CqLsalxaPX2VHPrzrXqRvh1RyRy5NfSXt0PmVX0UYVGkVC0KXrJSEXcgEwRnSOIwxMSCMkOc3HI4k19EUUSXQs5hnbuMx7aAW8AJk5VU+e0+l00EvXYEEup1E0BT82SrGNg3frTHe01Wg8D69Xk9wQ711iuHr/mr72e9RU1ZrPBV0GDQvvaao8rcv3dD/SNHRqnvq9WBSo5QLv8BmGtWr2ms8YTaFKrKNatrWnv+PKGtQPO7JKgx9+E2B1SV3m8X792/IPaGiPkfIXPmlk3fuiq3gfuvj7q9FQTrEn6GYwF6MJ4PMVkh3XAHLCaRWyTAIiBbSXgoel8fpq4dtK7i6BFwhQCFcewoZd8Lj/3c1GiauI7WvZc6tlJ2fp9D5T/noWrWRj5rFrNGTZjxnA5vJkNsmSHieXCM+ZTFrvaGyi743wBxD7s0lgZSjgtTAk/Qd9QvH6rDf47PNTfP3QYfRP+cGe4snJgz56Bysow9VThpoMT+6lPVTEqNcsWlkxMfAZ/w4H+LcWb8O033xXCd8F7Q/I97i9jLBmyAswkOINFDysXJiCGSnrvcpeDP1ZO5QMmp6vzw7NnzxKQ0x0+H3isa/OGkdQsolasW7uu4yPQDi/F18Gr5XmZDyhOEOTP4ryQLvkDidvsRVeIZg9FYmrT0mRedP8MNxfnDdGGLAnUkurZTFxx53UQX51ye/Ae+/AqGip7lu06CrCAUqp4e72jUqPUKrU6zmzxGODhWrvD67ky12WgoPakNansfnOVmoE6jFLPsRTL0KxPYzarbKBKx7M0gOIwLMAx9xY/9TeZ7KohvMXvcVWZTbV5vVHrY00qrUrN0ZwWLhtmlZJTm3mzpkpZ6Ux2dGZX96680huz0hqb2gyFbZpRuvS8k3eZVBa1iqXpkNrIUgxQMpxGBYnmtTajrqBY2LdF8nHuwBFM87p1NTWjOQcfN4pAEZDh2O4KW4SC7YCCvP3YUQj2q2YxCIc0oOQvJ+2VwDHRbC/Cvc6fD6lBq9RUOurq1EqaYhjtdgtHK5VbujSAMngsZk6n/fn6wb4WI2wayAyW11UBm8ps1vhYmoHNwenhqgsYdZXZb1eZtJyKoYwrh+bzei68ZVZqIeNNGpXRVOnS5Wst1urKYF91SFmlgY2g5pQqM/ipz7dUU23T8rB0lYaDqjNDsUZ1iKZZldqiMrlgc+hdSgY2PmVW2zQU3xRQiHlTd8G5iGSoiOFV3MdjTyI49qxEYHFYzeIRK8ZvDvvm9tJ383HefVQX91BLPHHdUfwzjmFRf0MbDhQm1d5YrD0GVW3ymY0TF3zgq/L5qoR/FV3yT02DbdOFN9AV0l8JV3aXiP0bwdr3ApQCH+2zSlKwT/pSpPK4NuGl4t6E9jj+WXDRlrHCz5UigT1lBJ4DQ+6aGrdwVmgXf8dmkEdyqPdj30QFYPmg2cGHuVTGzKaCZsQfnnoWuflPnD8/gUC24D1UWyF/XLiwti8e71sLdMfzBWBCSSlE3DyCsYXyBwVlSOjiFjFt9pnVtK9MDn6ymDGBjyMUWgQeJtxH3V04UxKbPHIsBbi8XCh0gwtCDl56Hzg1UxckNHBQ76rBMRwI61MNZFRgzE85CSg7BHgJQcaqpXTeBBACxzOIz0ew6vAig/A/VLgU94oAQmXCGlMc/zzUgdI47g7Zs4DogS3lZ7apcRrRgN8xX956a3GjBdJIv3sOwdDesSIYLkUQ/AR0PZ3ZsGn35s3zAP+UKAOBc5DwO5YMrR4tuUAtF16DT1jT2DSPeybOnyA+o3xu4xUNiqXz1Qx87BoJYx+3IoOXUwPSP4/DOYNRqBRajFWI/EOtjgQNB124zEqS/C449cd/B9sev+Wd9wQ/uPKZJzF4Ffb9BfeBTMFCnRQm3wM/ELrA2pfFE/BNIfVBVA7COLXCyYq2qilfGdYmXf0eHFcFCxyQZ2RP9oBvgxb46FDhDeqk/KElXAySqVcBgmkpBskfDspzQ+Fe7jBzCKmaPgBYFY8colRK4Y/yqOdJlG5ohGp6WklDUbvwFY2RffqX0kk3L5y6Ayy7A1SgWG0FsQ0Uy79E2fOXOW9pEs8kvxJYP+uM8YrAClkH2cKTPI4S8Sfl8wICBd56gaMZmr7AmVhap1LSydJIRQDd1LNfP82aOJo+zdIcVLuyKp2EzU7K9s0umXibmlEf7iA+p2WlgmOsUqWj4VMv0LBorqzIFYxOJXxXyXI0e5qGKyErrgeytsT40AD568/LVRYBVMSlDUyp9izHO+gWSMBc3D6JGk44oWRf5xiGZl7H/KCempykk27+l3M2A8po8QJzErPnJMtwLAvsKh24o+YOIu8WaW6+JL0kOAHyi0L8aqRC89EJDJyW4gxK5nXYaIBlXmfnp+/3GiUjvMNqWZo6SdNKA0ufZGRrK4fRNpE1hsMAy+GgzzEL8LhsDIblujzF5H9AV/8gLxRQPu4SrPvkdN/x3t7jE+itD0c/7EBvNEVgDPJ5eQcvXCdeCd/y4pXwrYidvgvjuRIq56JuLoipTJlp5Z9mUlfUs4pJWFenxTwP6S307nLyussuxF9keSEkW8PnmRP0Mwq9ogqOwyTCUGGLFIYzgEM5lcIE7wpt/jmgwoE92dkwZHqAC2dIzdg0Dl+xIa2NfvfijxAR7kNZ+l+yFz8Yoh47VLOxEXLWW7XS2zjclK4Hn8//IP+GMVdPKlj4D4sVnqaurYh7CPFXZi/6s7SucOZQlRc2RePGmlx9GjaI9/o8eCZvzNbDqiYpeMZquTZeIcldUl2CJKf5jJpIoe0Y56pUJSAzoxSrA1ew8moUNgQJv1v2RnOVK4KQ7S4ndfvzFD5otTwkVkXYGGoxyitBfS26t4W0WzDndMH7gisqhbuet1jxQepBVJVHjS0hsd8gvOmbFUsUyzCeDfGhTmBAbxy9SUKD5PlyzdLxNuKnQfQ1PoHS7qXEYBApnBPBuZQWTPEI+sCRkPQEuDBBV+JVFmVbIufANnlqXBGIHZ/EjxZ00xjbBxRpRwj4i6cY1/T8ZRFK4M9uv2wS0T24fxyH/eN5rEFEFe1oFxJ1C7FDO0T32wDRzSDv0ig5MRtOZxLKRowXgferEeofqRw9+D5qYOBccbi7xj+QHdjY33uFbpd2SXr9yJ786CPNWY5iV4Y1u3RTA0ykJ9o0YOrzId/Nm99DPUr4j6Huwys0g9XIVWHPyPr0Eu0LL2iAj8s2v7uyY9XViUGzBQHgZup6WxBMyeQy3D+kOmDc+SCcegMpoqonEG9hRcJK4sQDYOVoTH0YlEgeHs2Tsnbprujt3wip9tcg4Pb/RCSNEmqFVYTMes0LL5DarLstHKke1EAqhoALV/oaTCJ4RiINr6sTzBb6rMKEJXEpmk2KZSPmViwtOiTtGOPNiz6twuadlrE167+/fs2YZaf9zt3739u/+06MMi9MEZwWEIOfhetto3dH6+qid4/arn4mmUoln5HwZEjZPjzfSnHQUqhz+PLImdPLd27KBuA1whTBkQGxKHbOvQxSMa0FppLuh7Mvwb1D6HuOcECaq4JpTCqkKBMmLhMZEXiAOvm1b33raz9HWx38OaBW8TqjlXsnV1ObqFvZUu1zV1F33z55e5igvLyupIzqi/+uNbDfW1m1pim1uXJlbUfnqu62Vsl3CtFgRcgawcsoGzw7f7FvXrpEqd5PivUOLlRv4ODwXhSCjwT/jer8sx+hCMMfARUs3GDjwM/P5s6ezeK/3NyVBl8+m33qKXQJfJdseKR8K84Kd6lyIwsUOavCM0pjcFn3iHWthauRAmTM4UCKTrB2jGzUADhWxDoK2sRtXDQNInZz6AuHc4Qgsw/4xNe+9q04ZDxnNep4lfAhagimMd48kutFvas3N9Icn/Z6UisjDQ2RlSmPl1LdLvhvnxSmXkexyhVqI6V8nYDYTH7y0P6BXMfG0edHN3bkBvYf+mS2o612ZeXG/EbYWG0dxXa6B/OpBucT+Bg0H1sMuW9+HDIxnSehHP99uN67kVU2WIbeQCC5eATpgP3b6CJ0lFUG0gC23bBv97K2i0fblu3ed8Oxaax/PQS2bF8DhTkozq3ZDn7cDk/dKHSCH96IL+3zt/r9rT7cn0j5OBflvOVR43MUQX9/nqeSvnMjnON/hnOlYORynBuyA8AnYzkGtoAvU3TLDouAK3YeiEXS3y2EoSxtq38SCy5VNsr89TwSU77cs6ppvA0viYUPCCG1RquyEpzdufHJ3EV/jvp1skUYuyr/3JpsdzgaXunzIxinQ4U3sM5KeC7R5kT5osspo8ElaFlW+MLCBID11JUzCpXbWOsRTsdiUYlnapGLwIaIlOuXi4ApXjFL8aRk9ahdCJd1lgI6H8FfL1dF58NffWy2VsqU8fRjYD3TCXPACl+L4GUUJzpZBAtDJM3RTDs7zlM+P/fMCfx/PsIu5uelgTpJCgSxGX2uefFo/WbfYjiDSl0cYxSKsv60IP41nJLm5QaILcgMhULKEb2Lvg/Oc17s59GF9laDGKTXx/swTm8gBfDvBB/Av30p64zzrGTaBrO/DBoHdwwaQUGg8ZeXQIF8voQ/BPqlmee3iaAFXeRT+A35vD62ZEksj9/Atrm/54mLh3C6/FPWx6R6LrqGi67GZZBb9JdL0Ekx5l1hleWSLCamxK8kTgMJL1dhTNEB+iaMrRxSxOG82afYiDwJiCIQIGaGhDVVNIkkHDjbvXjCUfT1h4qElCEA+ZZbi2YUN0ISkiLxUhm+GJ8XAAdadrZMte5sgR/jnmRb0uNJesBUy87D+BDwogPwKHiwBR1ohWdaPeKx/Cv4GLwyL91J3wQPvYKPCd8bly6cJAXILvSOUeP4AHqE8D3p9vFJseDWsTGp5CLuKuFRBdmJnsEbOT/KeEDL6i2va6mKlKFYs/uLFZLVo/BBkXpKX6S58IFEaandwfvYH70CZ+ZFgIjJkG/Wl2lxP+gX5FPYTz7B+/LdH3EPSHwupcLxlaEZsZW+eX8AqywlzZdL34XPyI6r5sqyVO7fgm2/1LP0bqleQKoFPesLNU4q4i37oHeTqhQs5BMckXbfyLNfgc+eq270vD+o8VIdKuf8Su8u1QIlxy7uUGyb6Wd0K/PX9I9wzkRFkLWCYCVggRU4wplGYIQKBjUufGlI+EfwhccfB18Q/nFI+NJU4zf/sHv3H77Z2Pd34E5gaQJXCZ9vEt4TDoMlR95/1P3P/+x+9H3RX096tuzJM5838yG4n3+a+QL9E9jHM4pujN+XQW7oiTgOs7MZAd6dhCpwI4rFbEOrCArGSyccPOeAKlomkYLiZiDMzW9PBS982lBr+PR3ePctRuMtbv475T/jR48+Jf0dLRks0zL+Jue8sfgz/5TsEYKuZMbMz+S/VNfk5dcTLKIqYFvJRnApogtvlEJ3Z8gUi5e4ECg9WBSyWRd4xFhjE7YaaxYhXNwqbLXVGMEjtpoZMsZCUpdI27x5NoR3xWca5xM3fiNSavvTZVOc5WVxsunS/Pxi4VxMOokyNS5aLg3z8ydWuHcBuRQLwpNS/tTzUBYg+2aueaKxwxkHcMyIoxbGpnJ3gsrcHAHRhTemcneByqxCykNOns/PfjrK6hbm5E8Gh8HOnPD2nTOeW7gO7MwKb9+VU8ykeWb+W4lmKMvMjPw+g8IG5grgJvlpqbLnznqqlfel5E/8OrgwM91tXpbnVnqOdx76cMIkktpkFmfzk5P5yTkJRScm8+W0zpWrV0rqAx9fzl3ygFmEo8PlehHCmkK+dKWt+RLCNJBvy8u3661hLsw5zs+RWuTUPBpn7uId2V+Cr8weQdQV84A+3Z67eHv25RlzCZS/2Pn8BtSo/847k4AjwnO/zN5xcb6xclh47uXs7RdnjM2PpcPxi9Hh7kSddVG5WxSL0OEAP3/iN+FhcGHemQN2cXkZNQtncSt2wnlnKdIf5y9O7Jgl3mthmcj6KRs/8+K5zdkOVAd+6PRltwR4lRBZeOOyW2NGX2lZ9IqTcXCS6Xgx2a/uzN0p/S2i6/yj7LYZfWjB9oVDnXPAoQWpnJfIS1NELS0vfgbvWhfLu7IN78Uwr7Q/c/m8myjhp5TxLbgQ38r8BuYjsCTUzpdxLSbbeif+NRXUS2gHXg0caig6ceCn2cJ7wrkslOp/miv8FnRkRV3tL+F1SoVGYUJokfhi2IxGCn40Uzuy4ExWsAjncmc/zH30cg7enwN9WfBYTrDAJwQ+yn00lYNfsqRM+inq18iGAMp67Ie5D6U/8F+yH+I9v6ApfA8UYVASUBTbBEclzjILJZNXpS+xvEx2c+GcLDGcGbvoYFMH5H4jUYCOwmcih5cg2XQ5gpxZsKuDmy9cx7s9PFS5t/HuicIbyJkRikLfO5vbP5WjHiJZ5eElk8QDBrsxnaZC04U38mez+1+Z0TcRPZHLooYGaFVciBIXlKOm9i9AQ6EbXvHKfonnvwCvIkrQJI42H8CrWPAgAfy/oA5iu44CiBYdgiKNXtTBvCQ7/AOUHVAeVp2YSxW2AQirAYfNP+BCXngRdgPYEerz1IeFl6hG4cUcOCOM5KQ1Zsb9pMfB9hTvB01ZYUQYyYKmfH0efAY05YQRcCYnvEg1KsScsvfA+yugTrVUlDFKo0QcJywaPWw7lQw1Ug0UHC1GCo8YL/DRCS4MF5a+2mhWf9X6kcmR9Vfps9HaSOS2tYJu7W2RCO1s3Z5paY4oNes+NfGpdRplpLkls71VBaa+g8IJ8sCwoXdl7IqHEUrEw1fEVvZ+bVVusxJwm3Or7mDa89fu8roae4/09BzpbXR5d12bb2cA2DY9PfnnoB0tWRnHx6I9D4n/OKTHJienp8X5KYFz0iDcORTB6OMD5pn+aikHl0IdK0+NFM7kJR875AYEYtPTwhgwTNPV02i7UnIjAhcwV4trxz2wDCWKLsV9MJyhE0WQolLWv0ARJMJeihwCPchbeHo6/pn0ip6+kotmX8+K9Geye/Z/Uu6W8cn9e2DXh0ULuiZXZXFOrnQ1bU2lZTNlOiWjK4qjXmfhogVm4aIhPwdOaYWs8KUcVMeMgrPzEPg28nKeHi4rfets6kAMpbUi/DrOJOnnFWbkGWkNsmTrmGOD2K0A6go2u4MNIqeD4KvgfnC/2Z7rEH4s/LgjZx9srIVTO1vbKJymrxodZarMgr7/RO3LL9ee6AcfmKvWC6nESNUTT1SNJMALg9jeI5U1R0kznz7nI6U5sERz9FJU0zJJbYEaxHGmr8uoh/AVksPr0ryTa0EzSwY3iJnA5ipQeBATM6uuKGfIzEIyelCqLOdAugY1XlaUGdwvnJYqelNWOAcVZ/r52aUy2kF5Rb+dQ1feVd5HHHNRgJJ0OMDMUqkbProzNwXa5yxK+MNHd6GTM9vTg2ycc3BSLrJwPjylzeLoX5f8kL8Pfsi177x6Z/vc7D1Qck2eXjKaSo2KvlQSn2sV8Uv1qrKYdDjTwi+OBXpXiTRBIJRxl9PVrp5J6JIyH32EZRhW1OG5tCy1miQUOOAMS8t9QOCKTR+YFr0q89Mo6IN3x5Er6NsjuRHpT3gBxKgX80gQQFJAHuekmi6cATHZReABuOrTMloCONOkWLR7BkmAJPzF8jqWG46Qsou0UEtnEYCLnSiRIYzJLqH6kdBRzgsvHiHz8AKIG6lz8wAZT7DMN6vewpi0i4oyHivkWOBSmeGFWwCIe8v0/NwX2vFm8uQ8fD9HSEBmOsm+8wXsi+skMSKl5TMM4KqCYFFpK4IxLAnF4E7qZbyO1uvtnPDfKhXQcvbwb35DfUY4LVOAJMuMTgNO6T16cEqjywunoQz4rPCbGXoSJaPDOzcVQKaizUkAGF64bOHW8kKVCikPHIkjiEINDfmfz/JFlod0sMj3HrYPyuUbhC9pj9AN6AfzJW/3fNGpuHAdtoKhFgGn8vk41nGotZD2M7hlRmCryQJEBR24MIkMrvDqOAlBjYv9RKIVjVKSz2RBSrkiZVbR3RW95qGSuD5P5BG4Qyw/L3lxiSR4XV5MjS3Lp4f42EgsGnK0wpnZ9LBKU5zykJMm7ROJ5UFPiaaZ8QrCmEPcEXHkJ8ApkZNy8uRk5wXdKwZp+8MwDi6ItIv+kITeOuwPuSAfkbNwccWwg0u1t3A6L1EJzAs3ttA3Pl6kEFwra25xLkTybQ3UzGLlI0JOIwHCFdNIcWLnBEeIuiWmI8Rgt7vWr41tqr5+ZffhFSg4pH1yklLBCUlMoAPpwri46eTG+vb+FYe7cYTbhMwOJ9FyeZSgLncJKiYWJgD1MMkH/y76Gew3W6/owijaRTRgKPKKzutcmX8vpMgRFp3xkY+yCPkWFoV0JYgTF2z6nq5V/cMnrhu/32Ha0PUA9ghjEz0mx02j2/Zet2dXpqttT1vg3dNquOY6wcO5uA2f6Vg6tGMfvstReJfj4DWZqN2+rPVnN43cv+xB7Nf+x4Yj3fmHYw2tuwPwdFfm3dN2J3zIvpUrN6DD5qEQuvw42A7PGqS4yLvg/GeBM1EcZ1zCpCJlolqsatqKzcJFmzDOgDx/FMc4ofD+8euEj6RvJ/ZuG73JgSrxovRlL6Sgbc8N6K2tJFrQuxF9N/2sdZn0efGthtjDeUS89HlMvA2+5WUBWnSxLkgGgxKFFdFeLa8NKye0rArrEJVAVUY5pSyZs7pl6B9fkZMHP28sGbDysr1FYk/6HPUK9uYNZ0JoEYNMLPdxdiAQKPTmD4N3d4Q3rTqYPVC/TL/Tenzrjjd2bD1u3alfVn8ge3DVpvCOSMO2hmsq7q5uO5g7mP5U1rL38cbm5sbH91qyn0rDQ23Vd1fcrVKVYsU+R72IoqmgbFsqXARwKi+askVKRdfvP3YzsNx8bH99WclAd7frbp9YtKo/Wlsb7VeJBfvgKZU0f0jjxo/mOCsaJ2HZwAHFkSINFCCNDi4sws9xf8RD4quyQUJ1rfL6YRsYe6OwMfqEd6WBMPi3NDxgsVIv4wHwaHFACMt6jZGeqN+7qqMPtiM1QXr+3r+1WuBPmtB6hjlEP6yw4TVY9BYtbdHg6WXOgCAWco3KYBdS5EB6Yd/upe0Yk6MI8v196QvF3QVVlYfR2Qtl1198q+w6/IW5EyorlIwu5zxUgXkIoPzzlfYmerSszhUk6i3okFpHerQERKLk0pk509JlkEWCvufV3KtLs72DN0hF4/IqXF9srKgoq9j2bGd7k9CNbBI/gfc0uirKWTbYm7U3tXdmy1lXUdEI6vMz6O34mPTKtOfF0v0G1mIXS7ioXStkbYkxKhagXq5oz0uk0EGePB89wCQq3fJyPQuXiwT6+corPA5OLVCWZFvup+9TNCvaFX2KETTTGYreWnG7AwEaS5MswgzkYFdGiYRKzlrJckAf+Q9r2cJy7pdV/bVEWKntr/qlUnJYwT+UxZPwoBhsRNyfuub0HXr8arcfX+t3X40DwIo/4k7pFAone1LmVhSTuRudKXOgInFWSfpmtKdZD8o4EJzBARZygC3nAPX6/ymcnQGS2SnQ6QQKRgxdRL/+T8EwoHgeHn7gDmcl/lLpvMNikY6iHzUW6RS81SJhpOzCMhSa4XgJMEpKW5CQ5zggAhULwiCQ8pkDVIeU7YOk6tilz/YcGLuJWPFQimuqQxjLgVNvQwWDnthVyu6B8oIc27u7tY2Y+nAy7QfwpVD/LaOpbhE0hX3mS1IEBOFsDgw/Ck5dkqA3hadyYOhRYUyKuTzHXE3/BV4LGsncyM4YLngOnte7xZwIQlUVjTQxuEAcMeTLHCvD5yem84Wfnc2dpTXwDV2197+lAfbfe+F9+cZGePnqYXT58OrvI9AmqL6DbRueyp798KncWVEHkuiuwLnq56aaTkH6UmABAlfmpwuZBYgB5xAaHhgulY3m5q8y99CPKKqJRxCU0AnYJ43TpYlSejydwbmwPACFw1tTKI8agTmmlRykivoAdMJhqforpct48WkklT+hs8NLWYtqNBzUChuphruEH1Yn7Kp6ilP5/st6cz5PNcM79tkswmcNZiLFazXgFhXL1tuG64SfC6Ng076aVu9ZtYkxCd+oCOJGRv3uW8y99F8q1Di6PWEWo42CIn3GOSpwbAIZMODJTqWVq7MY2dYStYVf8W5KVzhDKOiCl1DKakOt/ddy4qgVvMirRyGvTpd4RSItMyL2CNn78iuRToEAoDOQVzSP6EHANF6UwArSC94XfiiVTvdKvBLeF3kFHi/88i7QWc4r4CDkgOsROUjv0WqE4yKvQBw8KjxW5BUYrAiCUyKvvgnp/SLhFYDtRGhkRfo65qgAswszS/iV8EOJWSVyKQ/vBsuoEUJCF7ykjFmEusJzvOTb3gbnB7NomcLacsYsW7jMCbhsJcozwyLLCOzcaBRa0dTLI4Ww5EcTv3h0ghop6svTkDPP5PbnCi74tpcI+DYQK+1GIEUQxEpaMzUyoYGXBuBLeLsbi/pR0Y5GaJWsOXNQak0gglKYUDmd5dShVK2rZ9E2B1Eo0yuiieKKJBX3FAF9k4JTaNDOMGcGKbyxSL0yiUDECiPACf9vQsaWU+BcPi9sAV8ha5d0n0KNboG3UnoMOzY1CTbhK9uJg5cSz931OA8b8uVNKDoVAyIWgZTr0FqW+BBBEyI4aTjk7WU/WNKRyNAD8h/UuAgbKQYU/J1GY7nFEuG16L1wsxZ/2vAx6ouaCPzU8uhdUziIf2ls+Bh9r5sn5lfeXbCUvoMLloimT6utwe/CEfmvz1m02j5NpAa/g13yX7J1q5LgRaAtL7T1zkuw0SgonIjnNk4StxJwJU2kimtbOkWN79q0IfNpEMuX9uKwVwQo4CbGZyG3S2fpZFPDatjsx6QtOeJ5IYzhD3ROmCqdK/pQ3AdbKCHSyfnM3EJUZnzmTBmN29evWXIdiF2Vze+5ZjaN+KwwJTtLJ+uiq9ANG5vjs2lE5+DlxXO4z/0K+97hWNvyjUO8wqYSM1QeZOehn8w1dXTlytfSfPlCu2XtaupXueaKqnJpvnzFCwQUIu4Sak8os1lnO+IF+BmaFxZFeORvgSSUY5fwhym1C/jKLP+UcjeYQ7IeIcVNA/qswqGIIaumQzadBOTRlHPLJzKRuTS/lAyFILamh8xpPV+RvqwpecrsK002pbkPnCu7HH8pQ61Afe4eTLMWedzKKZ6TyhJhwthscmQ0zFWyQsIeS2C7vQOjebQjPwK8FJUlbEWYNUDKAoTy4iDI2xnGKzHiCUr6ldSzRElA0QSVeerZwuuN0ab+odFNA31N0frA/mOHHisBkDSJkQ+U7B78DOwscsjmXlUXq41kPfamJUtfKkGR5EsxH8U6INyUOenP+EhzZ+TNOovSM1R7U+/AU/1978jhUcrJivcgFn67DBJFtKH3w3Yz49kc2f94cSzCvkbGXfiS/UyuYVMnm5K45+A+fiiRWLC7gZ1YYwUVe824p+GWjy/Y24Sponot4lYi+tVQ+q1Fq55vIaodZYQKunlJfEMkSzg2H0WTEhXlNPgvSQOL/EYXKhtMCWMLlTxd8pE+wWTpH+Nyay5ZLnKIDGeobUJ7JjW69WBFRXF8P4ICi6Ph7uyLZ3MfQf0pLVxzcOsoKjuMT8quEr6KL5H6Dimf9J2Wj9l3CFmnSr0GEpdIzCZuTWZLKrXlEO41I4TQ+n0W3GvmozYvXn9oS0pYLhE+s89nPibduBkX09epLahdF9HRT+OGRvTexnTRP/gTx6jcu3CiOYGjyfM4qjtBfpTxj0AYHUIsB3+5P7sf/eXgH4jsM+PWOAR5no6XtdAj4pbeIbGhhGfQLeK94jjpuuyxypYRLOjmJRXo5fQtMHC+ia8gf2T8nGLa6e9gesKXnjvCuKfCieO+BYj5aDQ7NZUd/SaoltEBT69Ap1eQ6yZHc1NTuVFx75/QQNp22cds2xJpi2rYm4vE4l7Zs2Y+isum3yL1ZB0+DmWoFxROuIJ1KQYVo/CgaLeRgQvZcPoP2u6lUPi8KO4VV2Wct7Qo1tjswfk3lxRXPhVPyASpRPypK8f/N7upqr29avuqps7lK/u6u450rN2wHcqB7TWhopxRC3bPGeNmdt25a8+1cs+0a/fsutM1DrxLeGVHh9Le0VxV5fFYlwchzR3xIx0yzMOjd8wT8ib6A+2mn4d8Qe2qYLnw3FwBosA7xzJP/Wp8fHZ1C/+zZGj106uHlrQPrH5i9cBvSxtT5vHxOSsDAusampsb1rV6q6u9j8h2qKT9/ZuKsma3Yt2fIm+yuFr4HisCHoPKRqqdQog1+cVLomAqe8DtyTc3DXP925Yf7qntCadjH0c8/RvvVdlVw5v7VtVQn/OeXJ/7ZL9yl7K5ry6xzl6SgY6Lsmst8pa/pPyKK+rAFSW7Dh6Kx+ZdvHy9jqZGYWz2Ega8/UeDIeVEwP+VjkAgvmRLcsXhbtMlxN0x686e3Oodm9Y/vaR/aOO+zdrcnmXdh1fIfHiQj3+bIqsYWjxihIjGJAKDZGYh8y4m2iYvS4caF4OdxVjhRURSkFBOgvR0Zi4cX6nOCMV3ociGYlo80coengXoO3/0jmwzV6rJkwvWBJzrLm0TR/ML0Y0w/RouEVcUvHxaf4l21i6PxlP5/EQ5ZeV9CPFzxceJyUr9Kf1mVFaBxXeXWH56BrP/DOMiTFYfOJMR7yD6TxoXc3SmRddzQt69QOxPGRfBhFi7BKldZhHjYq4hvnCnm5YN5/8sI7vUTk1Q7skphlFWNlBcGsNz7OUiDEA0y8ox3OH1BgrBuGeCcZSbG4MvhUkizGTaJ32R6qTdVG562bFeZ7JXtX46K6sy+HHOqteHkklrFeUS3kvvCDR2THQ0BnZ8UqzyMVHzv1eMM0puMpe3e53V6DAEgjI+FL6UtSaTIb3eWjXkDtSF61wu+Daz7zKyvbG4Yilcj2UcCTVSGKXeAzLKciB7q19pBA4oTHmxm84sKAqp8imlQZnLKZ10pSnK94xu+5ms4yZGA6rGjr4VLQZY0bfFinaUV/TIfruZy2Y592CV0Qhy4Yi8gteF/eo6l42do1rYPrSL/k/61wov8ioLlnb2ZHlPipp5olwM6hj9Yl1dIr5+4083ro8n6uq+ODo9nZ+ejpdQYT/S7Rtes3U3Oo2u2711zfA+3R4co1hCg5XomIS6303YQ1oBMnijM8VJWXTl5kZ7eZDZ786ifc6zwUiRElxUxzXfLNFB7T+bF8bePtt0TUeRGHxppPBQGSF0GSYFMkZaWdoaZK10MANbks7AvzBXvjinqPGXwd63tcKXhC9p3wZ7X/7LwpdV//sR9+XC/2Kxk0g89I+EF/YLrwm3HT8OjoDI/hNv9L0k/O/ICOBe6vsWsQRlRtPp0UwZLkalnAJrgBScwUsn2rKeUfJVsKgDmzJ0HgGCttIzixT+B5YQH0lq4OlUGO1FQFn4HigL24r+rmgPDKHBdsG+cEmpkuyu8gGkwaKXGeo6yAEGzs8pH3xR4wsi8DLIYVQ4mT2Qo1K5/dns/lzhhdyBLP3ziYtvTVy/IBwv9R66hv5s8Z5h+BT4bX8WfBG7oapldSNoA8RvsgkhXcxZM/pjVObTi6wBveYSZMts39UzM5ZkZu++U2tbPL5k8/qRXcMrsylVtvvK8U/v2rr5ZCjS2XbgIH1vKrtyeNfI+uakz9Nyy8EDbZ2R0MnNW3d9evzK7qzkx4nyTPrRugRKJfGzU3IsRcTILinlQoLHKT025a9c3tE8a91l45VVwhSe0sd3bE0kktjgr9vRspR6CO8XVFXG2VnLWnPHcuH7eOpe2rJDh/cPkonE1h0l2yKyaaM9yNWwPRPIeohzGZK8qXKdVcoKwidSwZlw/JyY16WEvdtG4HUpXSKfYB22sMFNV/uL7eevpt2GsM2hnBTytQ5HcVVxOGo5Pmxyw3E1CV9uU5j//PR0XTRYZ/TQkR3JkkaU3BFmPMa6YPRz8fh0sqMrW1Ixsl0dSTUfddaGjpHp4Fio1hnlSTv9gUnTgwSlRw2I+QW9PDjleAOFqm23kow/HipNNYPP5nJHczfm9uf2H/Iaa2pJWpym2isPm9w2W+vAQCt+Bz8Bt8ELszfCHrn/yqarr6xt8vt33PypptqgUXjUPTDYwvMtgwPwXYrBZO6hXiRrBShlxJIlRfaRpYJHGGbyWfpLunUdnatKjFjV2bFOBz7CA2hMpltenT1c7Ssy3Fd9OAtXi8nJCdmmxp8F8wT56i9CVnwJBXAsBvUEXIBUE7mB9FW0Yz6gWIt66yV6aoBPzEocMW9PBQk6FbBSuufn760/n7x0dwWfOHb+2PnPX6LLgthldVlAo/3ponzxDeZ+egKuZEEJYwihCxUdxjGuEDrK+mCfNvvMmTD1/i3GqHHKaHyOOMo/Z4Q/osZbQFD4xtG7ngEXnrmLZm8xGNDB54Q0dhh//jl0i8FwS/7oXU8L7eDc03eJ/rbF8hcsfb4y5y9IzI2wC/s1I0mBF9N9wXWExF4GRfdZJUeGSRtgdsXqevtHjuWBcnNu1brC3/b3LN/paPEH2ASeC6mHjo3099bFpsG2OIqXnfR6DvU0L+8ZwPPrhJQLApWJohNTkhSaRhO0rHypPOx8jwIuYF8LBpBb71IcsAB6NvSt+oS+vnXZ8vMiRXlMAH3iWNueNvQqdCOIZviid4dDn1lb73JJpJ0ixAhT8CoXfJ2PQyUCvWTx0zdD+lplPMFGU8nKRlBPM2nWT7o0SsuE2YSw5uHSgvPvMYk1/bef+PqzurzZTEalpzPpSTQvFc7iDtiQXbElflX3ysCX7/nXZR10PNnYHvPQN+X/85F7B/u61+xef8VXyejWqCiGZtfhDptc2b40uaEz13fFiZtvfZalaDVHi34WiOaojOJ2Cg0/ku9rLuJF+razob72Kp1GY7y/b4CeSatET/+1uzMum1mv3vKpW89ZZtIm+m+QfXdWoYWSpx3KLGjHiseBzGZfKpECVpRCIGB1cAkaTbIokQOUyYEV+ZCcgCNOmHrz4LKfLjv4Zrz96NRknj6RnwSGSQI9MAnOFd6YmKBCpx4A51AoGLw+L+HL4XJpWK4B29rNbIBOZBKOBHAEmAQOmScPFv7QfpTejeATJ9DDwMQDYq7qK+j7cJwC2mly2A0U7IPhDI+dFhpB0BrG0xvsoNj5sgOEUSLqDJSoUSfFeZah3ktf7HeChtWNe6an99jMlSbjQOEPFQcTmrrq++5rGm50JA5SG6OO5MFK4V141FK5zDiwccC5eiv4zq3Rrasbjz355DGNaVnFrX8nvNix2WzzxvKNw9sjm9vB087opg7hxU+1b7JojKbKE/ETtQ2Y7meZDfQdkNdhbN2HKwaUqcOIcJx3qJGSCIe08tyclFOQcor+fb+zYQ2mm2NVShoMCImKDUlaq2YJ5cmNVBekfEOF8F8bk7RSZVbS/bf0I9L/GpHeBHY9+eQnAMOY1cytvxRejG9ScmoDAGACNA1vi26Kg3MO+A5rAM/QLM0xt/bdGm0AZJ+a/kUJKwrMEVeFQvLpB3FsHAk5CqGIsnx+FgITMkKJcXfiM52zn1hCH5Q9EgUaIn+gmcBLElgoiV36B+yLhXG/rGE1AmXgzKJm1wisvGhtT7GArQfnJ6kRlEBEm83v+c89+aw2v2Rg6KmhgSXClHAl+AL4Anz/ybVgm3Ba2AiuWip8Q7+xOR5v3qgHtt91BILBQMfvngTb3nnnHdE36B9g/1SiyHA1QhZjS4VR4yhAEvLjojO7Z/8f9u/JCmP0vSgmEdQInwePnz+/NZVOp7ae/00R++qvIG+CiqXYJiLOXwYKripwZbYnfHGU+QCuKFAaEdNkWA2UG+BwtnCq6EdA8ziIk3gR4tONINROwPfgSP8nvPqGEnqjiY956TXeGG8y6hMhvB5P1vaEhbFwD3Kqxi5nE/k6rzNsUJkqL75VaVIZwk5vXZ7kk1xtsfSsr6trbbsFZSG7pa21rm59j8WCHy/8km3ujfX3x3qbWYp4bwun47/y1rkbnHW9Q/v2DfXWORvcdd5fxaU8QPfQe6AMOoC9JJF4lSZRUz5csbgDo2SFyJJDlCYSNSKmEmnGwX9FLpF8fGgPguaEqVVd7et0Gi1cTsAp+KbV6Na1d/1ap/e3+KGAmIcfel1di5LWGpQakoVMozRoaWVLHb3b57s6B+BNfX3o9tzVPp/wMAXvOB+Pn4cftKqn3mbTu2qckUbia9YYcda49DZbfY9K8WfAd85g1fH/Twy96Ty4sFgMPRTcuQC28wIYeigWGZzCkMYzedP3cXiTQT0B9hU4b5CUIBRJf7MYYy1mmJtH3bgyqtypiq+shXNrdjEsfLq6j3fH2mP+CmukM9g43LR0ywx+phfmZxtoB6RLoyAtPFxRgic4gBPzczmThSXVroyrdiqjlYh8ONsuwPc15i1LYcWCnRFrhR8S6+b7JJ13khmAMgpHEPzgDAp88MX6OLPDlzGzKPYnDezCO8J1wjvADnYIz7/5Jki/WfhbZManbyqeOAns+TfJyX35ku2NPFtbejKOKJc9kQanyp8ibCz5uxAeGnBeP/iEYsQP2k5Wl9sxQLqcsRLD0+Ao1Ryx2wleVWc7eKbwC9nPwpvZOVgGVfW3Cr9ItHd24y5jtxd2UM2yn9Tf9cxuFPhVjidHMKwVwWK+V0y1UaRajCNNZ+gLabeHdM9Na4a7cmW/9nYNr9lEuoDHnc6V/ZL246V+1qjoUnSjWXQO30biBwqUslzTUDbGBthEygFSgeLePFYKg3yCljYHZvk9SmChMnZEXovHJ18T/if9e9lB4efuIdGsPNshkuwvbJM1ROK19LH8UC/QpH8vO7rKDayiWZkp8tWiqIWzRnoWbzmQ4MMz+RvmEbRBwBFIWcnOQNw+g+VgSXpCOF926LXJePybbhcpubwRhMm0CnjLDr02lD92zA26SG2lPkBsrSzsBYogRh42y/CCMd5wOWjwcxhouHBkLuzg40w//TyW4TFOGhxL8C/ImtmgGSwQmQv+SQgKQfh+GzgCjgi3zY36+7zw28Ibwm8hWaEvvS4Mvv46+IawfW5PB0pGi0WiA8xdqAyiV1aCsFHukFCODRa6LGwwFH2+EDLYNBVaEJmMCpG1+RXm0/QRKL0RSy6six0ND1QcQaOww+lKst5SD4B/1mgtWsPFlbxbCb9HLDphPa0TboijBYTedPHvzREt57FB2aHFotVwF6eoRwof5MG5aVxHqSwe4cXOLgkvqgiYdo5iNs75/MJ+uJZuQym/CD4d/RCdVKgVFdgvUEwKXgdwCBqU1smyyHlAkPdJ8PCPn8dR2P7z4AIUb2AP6YEfPneiDQryVnIKvIojrYUgPENXw7fYsNezt5PkDBFx1Q7AcrUoB0kqYcXCGZ2ActfYF/bfC07BN1seCdyFM6LN5I9QBxiQcOywqgk/6QP5vKCD9XkfbLv4BF5W1ginRZ3fK8U3sAGQAAHal/HRoPEgOJoHRw9eLxyMgO7TGfrpi70glgcT0rpBsNbQfUj39HH4Xi2FI1mtwrPDB9HVsYPX33CD8B0Mv7ZpknoPpQYFceHnUC4U91jh22lYP/QcPO5KTwqmIP0ppTj2yneO1gvP5g+CzjzoPHjHDTfQTD7fQMaSbNBhQLCLb4FtqEBHpTBWWSl6W5X5FZViPBzY0lTMppUwy/zUzWhPHjxORmtpXwMVAJfWdiKEg3NCu9yF5uITecn2ivIaWLFHnJ3HqSVTaOqEuoMPNmjQh9cLtDogTzVk7HHQh80P3n7j9Vcf+QGoVhZ+RJ8QrhHe1+mq7/jClbs2H/hu1/YM6Aw37hpvGV9+ZaNPmc9P6Ay1S7fe0nwweZ23sYrH4++PsNwBMZ+CkWRUMMteGBYP+VYXPwfyhevyOCKuiAcyxzPQixY/8TMm0c2TxW9lj1EV6y89wyoi5BSxAKX/AFKVQeNU/KQ6ENosRtkRP4UxbBMhZhA4aJN5DMeSx3E1yB6NP7BNpsC00H2yMl3IJhNIheGISMjKbCQwVU9MQGIn0MCQXlfnHt2Ue5j6j4mJPNQpt+GUE9/PfmVT9stYJoB1ytBduPdbFHbkfQICHJ/Bq30gIysgmGyn0NxgRFhAqQxe8o1wcliWXBXvmGyfwllxxZfwQFVza3OVvXvd5FHO4rIA0Et32QYNX+3rO48JeMPdXAXcze6aqqG+JXepnVazzijaoAqQx30Y+9BeRB+CxXPFhODSF84sfZMybIDHqZOF656cKwfBKXQGveh43lXXEYt11Amn6zrq4B8QzpAD4JVPTO8S+3kjNQ0lSZRFubgHHSbZ2+HK2UARddPOLnSSfititYWDn90cG4BCpVFti1fU99Y1rm4M9wrBeU9RP6hrSq3cMDx4HOrXmVg61KRRUWzTQD08W125wDlFcX/kIJ5nURwj6iPi3Mniid1I4ZgzpPPi1oOU/hOS+YXTebolsSEeUj3698Lp3/OJXJwC+cQGOon6DJp8hNN09WR8Y7wzrnkuPwh4V3Uw0eDn4BFZuUvh6ojwWHiOuPghaxsCtRAVL+yHGpQRxWw/3jYQ35CoH0xB5aSpuiaRqOGtXXe/XnhDpIq6On/KtKsTkhbO1lo9kcTKpGbw8fyknCwp98btuN52NEKC0oIBy2LNxHkA1tvBJajj6LF4UJ/r68sLv5123XmnjTwIPXQSQ2WtAGcf/KBUry7YE3E8coBLO8RwbWUI16ydktJMWstr9pqzooJsp3fvt+xQp/xkf8IRNWxeUjgjVe+T+RMcQB7RKbCmo6o6CioaMg2VNks9aJ+zjldDWvRirgwu7qFIwpNMWdni4oIpY+puycBnY6/eyu8V3MXGrmqowEVVNlCfPC/5ZTeAnrJSCx9UomsIUcV2HsB8tszkcsDMpTLUs0X2nsrnj8kZCyv9TuVelDJNZmumcW2CIsoGHMNhpGlgrAMzfsd6B08HpB9Qdigb7RPxiTgUrCbyeSReocCL4khPwp/wXLzwxjFXHP4Jv4274pNxcA4n3SnHQU4WvWlmbzzPifNhJUCji7AffAlhaYruMrN0pItH50J1n8Q7eHJalbAnIloRiihUUxZFMjWOnrcIYG4C5nru8ikup/Xj8ZWAzy6Gr5jMRTP2z0Ir7JyLgxBHLbAoUs+hXiO3FSBavQtRmghzCX5+c9CC3BJ0mDOXXRYamwvAky9UW6Gd1Oyyy0Jb+vMnGrh3odGFq7WosjhHav7kH7sXrJYI1sspSjnFq+B8XQtlqzi27xE1tUOuvwYT5jBnhv0eASryaIuYz5CZD+uUCNoP7YPxbvMzImJw4W5czjSIFc5YDdNmAn6HhEiPmwfX240P/1pCOsuDxieeEF6ahDLtfv0bRnsvgvK7kBflS0KjSuahpChSA+YgFYHPcaISiuD7wD9hQqiRMvKE32NyULCyWLowNZMuRIOIQSjixTyKMSN0ChPUtN1I++UTJJwfIVTA5c0HuWEVgS5hrwOxyfgfvxWfJHojmv5hJ6BPC1PXYx3xwvWFLyIJmFpReA6tQ9SKSVEXkJfjxOtYIKXGu9ZQzoVl+BCgAnwx98Qh3VAWjzP9UAnCCipa3jTw2UhyJ+UgQRs+Xhyj34HPPgUldbjQsUXETJCOO6CsnEH+MWi7ESp1lN3BAIKVOUExxpCRYiaEsTN2ozHW2sqr1Xxra8xotPN4f+sceEWvF+qEqTPwcJ3JhM6bTHXwQjyHSWXakFwws1QaG4Bgke0U2jpsBx5Kyc0qOo/qCWKXKH8MvAvMwvuCLT+bkOL+1G56j4KH9Sc4a6jfOKzyTbyMtRRcoAUkGx9s5F8xlRbqWUslkwcE+Ro8N/geNv68N7jaffTeo+6v09V0h9luNwvtSlY4jSnbxirBrcJp0ft5m9C+Yu3aFcjYIflGEFpQ1jKOxrlw0eYPpCJMQ7nNKkUABKw+YBXLRls7IA+pCUnFUwfp3bNKPWe2C+1SuQoxv+x99A+hzjKEpDMDCCHgAvRKd4B2gF52BGKAXrATGADyACq53sAZRx7ejrEDigbYNP2BnrFaGb2pNRjScJymJrTUpGOtVlZnWhqqQUdCwdbCa5OTWHFft2n9XXlZ+OHRvsPDOxJL/19jxxbbRhH0+vxInPjss+988St+nX1p6iSN7fj8SPNS48R5NG3SkrSorySkSChNEFRFTWlaoFKLVFQENVC1gOgHIKiQisQPEaDSD3/0A1XtR6mEVF4CIfWLL0NO7OydnTQpVRTv7eYeuzNzc7szu7MzJPLLHo+pqsrkiWQYRsfa9VamXfTB8z6xnbHq7ayOYTI/Tjdg1X90z4XurV0LK/sov4iFU1vzTx16gezwexTn3o3hbIxJ3OPwy2rVCfoNIZpIbFmL12yRIdsnN4TfVwzzGITUHZuqTbKui/pV00piMEKA1xADOhPOAWgl5jws4pJ45RFYgancgPNV/hPUP6If8oyyTKl4f1LXLknGad+poactHD1NB/2bPPGgX2hoTKTfXhyAcyShD4id5dP5vlR8czic9lbX2Dn/aFcgEzTTxlyz2ElbbcF0kKxYUosWkxxGx0wWyLNCUJ9/cTieDoVt7MDJQfQpnC+hC+TyPLpvsiwrNtJOZ6xpW2bXa8N1kp3VGtqQHyqLZqOCHhc8FD5UbDbexeNGDZbeiX9g6DqJJ6GAPqh+ZuRfPblCvrhICMvshQK6UCjABAf5kKIlDEVJdXcv36G0y9twN7s0XQTPxDB0RckgoizxqzHr36O+xPyWBGsqhcMqPEc4DFKF55Jh0HMNDh45YhLEYJACbdTvT2YuKzDgcmstZyzUaGvRDUvUgm4MyFPy4hGsc2zxhrNWzFmsTuEszGuEs+AMY82GvbiWN2uqi7RglmsZBv3dIyfR529V1rnK8HdvEH4wySNWeUmJdxiMCLxBNpPH4gHHhlDBpBY8m20MIwqjXj1GSe7AKMkdtdqagpGrRZd0G0LqlN9aa98UabDbTB5DBTuzQBera6oV3O7q5qgTxE8WmTcxGKvBXxFIVLCTkwfHLg6+GpVHQQkPSgadOcWxgQQEtEgEWG5+MF/IZAr5oeVc2MMF0QF0IMh58pPTkdt953XioQOUSxrKX8xCxIvsxfzQHDwMD54MT06J8ofooDg1mcdP3s69QfltXjKXDHCdJDNnK1ApH6SRl0JxAG0NGKnuvROjN/vuIASwrGlT6rYxwZt9d+HGVTJlTjOOZQlBTEqKthoC1lOEOC5gMCr9gGJECVMiuH3wOmEIrV/v5VjFVVfFiS2NdP3yg5ao42qxOIyZAC0tXUKS1VPX5mqMD7Zu4qw6/eax5EiXlJp42Pvc3OI6wXV5bzLgrqmiDM76pqQU74g+8++4dWivFNxnoHQjQcmXiVfZDCa9kbOF3KFNuQbBv63x8EymfZ3wO/4qa/VwdjdbR9P1qa3l+dWzuqt4HIC1YZ7I1j7MyC1IonjIOpEdwmli8UMvQtaJqNM9Cws9PSdO/FMqnTmD02fz2fa5ufastnZs7MqVsbHL1Hcn4HpPj/wbueFMST6dnZ/P4vQ+3IBTWeZY3XalZb2ao7UtyqeU6kraW2ubCiiwYIGi0gIZ46g/qG80QQ1GVu9QbEZE4lSSvFMHvFHLyhKzHSKYk3eclGit4tKUmNvCTiPSyb7cPcDafZ7h7uMmX13Cm65L1fthQ8i50ZSN6baZpXAsZdl+pHPw5EBToxjgDx5F0PfPxPsX0CtTh3YODnSOHh7v7QjFuLbe/pGZid2tceql3OKOgef9fS3Im9mfyC8Opp8VQ17XjLqe8jr1J8YhUvYCB6MugQkjQUYyDDIRPyTV1leF1V+fqkt7E3U+0/HcTrc3KMwKfENjPOMEeI/GAaqR/t42Lhbq6B2f2ZnbuWN83+SsrqquPt0fJ4Dh9mEvxHndMPU1fj+iZosmrenRDGp2afZpMHQgpVZiEeDerRx3gY+QcYTXO8jgIdojqulXuFzAHUkiAi6ww45kAnclrMPOGppRIlmPxHJBKhe0nXySR8d4t5uXz+EiPuDihNnp5pEPjg9tMUGICfItJUfbHX5/k88nUzaXS3A6/3KFXPh3DcpCOaOumc336Ga3vN3dTN9Tyug6Ls9WWWj5uqvF/LGRtqBhfAaJJhb8VplMbD3L1ssGsxS3u6SE7XsT3RhlcZJ/4Wg22ojTyLrCozQMYG0SPAL0arbjPufgE2jYSs6GmTAiBMIDir1MK7FckMoFpK7jx0R1Z1ysQuHHUy+Genk3rBbL9xV6nLYBjVyXFZJ9q2SozybEBSH+k5KhtELY/6Xd+BKcPXsPXb8nd3KENCwt/1Am0951BTRgApKy7Uom767FZHXitKKTKHONdtAqw1jFFtdG5QHbBmNbiBMh4hOWQRQLQlVP3Q+zB8Wcdim2yv/7RAH03kJlbuZnXYLYLDpJ5OdVikYkpK/U/qBsmwi+7kitj5osllYq3RDcdgls9WHG7DFwl0hVxcKjgJNtAcXiRuBGldpXwb38iVrtGmPLj5Rq/wP55JMYeJxjYGRgYADi8psfLeP5bb4ycLNsAIowPIm5moug/6eynGR+AuRyMDCBRAFwYA0BeJxjYGRgYP7z34eBgeURAxCwnGRgZEABTL0AbAAEjwB4nO3DQQ0AAAgAoXvYP6RJTGAD2KiaVVXV/wHf4knnAAAAAAAAGgA0AEwAZAB4AIwAoAC0AMIA0ADeAOwBBgEgAToBVAFqAYABlAGoAcwB8AIEAhgCPgJkAoICoALAAtYC9gMMA0IDeAOuA+QEEAQyBGAEhgTIBQAFNAVcBdwGLgagBvoHQAd4B7AH6AgYCEgIigjICQIJRAmECcwJ/gooCpYK4gsqC44LwAvqDEYMlAzYDRINQg1qDeYOTA6UDsAPNA/8EDAQWhCIELoQ2BD0ERARQBFmEawR+hI8EooStBLWEvATEBN4E9wUEBQ8FJ4U9BVgFb4WLhaIFsQW+BccF0QXZhfQGDIYxhlKGbgaCBpqGqgbChtmG8ocJhyQHPQdRB2MHdoeBh40HlYeoB7SHwgfNB9wH6YgCiBMIIYguCDmISAheiGwIeIiCiJKIqoi8iNYI4YjqCPuJBwkSiRwJOYlOiVmJZAl/CZEJoAmxicSJ1gnmifAKA4oPijQKSApSimOKcwqBiqMKuorQCuCK/QsRiyELLYs/i1ALX4tsC4KLmIuji7OLxgvRC9mL4Ivpi+8L+4wGjBIMGww0DESMU4xgDIQMnoysjLiMyQzYjOSM7Y0GDRMNJY1IDVONaQ2AjY8NnY27DdaN+w4YjiIOKw45jkkOVo5ijnAOfg6QDqAOro67DseO0Y7ijvCO/48NDxyPKY86D0aPUY9bD20Pew+LD5ePpY+xD72Pyo/Xj+GP64/zj/wQBpAQkBqQLhBFkFuQZ5CQEJ0Qp5C0EL6QzZDZEO4Q/ZELkReRKRE+EVSRaRF9EZERoZGtEbcRxBHZEeqR9BH6kguSHZI0EkMSZJKGkqASshLIEtUS8ZMOkysTQBNRk2GTdJOAk52TspO+k8gT4RP3lBGUK5Q/lFGUgBSqFMSU05TolPWVFJUnFU+VaJV8FaSV2pYeljuWWxaGlpMWvRb5FxSXJJcrl1+XcxeDF7SX1xfzGCUYbZiIGKiY0hjzGRuZPZlrmX8ZpJm5GccZ2ZnlGfAZ+BoVGiwaTZpjGooaqRq0Gr8a1ZrmmxibRZtbG26beBuIm5ibtBvMG9kb45vzm/+cDxwdHDOcRpxbnHCcihyinLoczhzmnPodCZ0fHS+dPh1OHVudcx2IHZgdox22ncUd3h3vngWeE54oHjUeUh5lHmuekB6kHq8evx7Kntqe5h7tHwqfHh80n0MfWJ9mn3KffR+IH5EfnZ+on74fzB/gn+0f+6ARoCkgOSBQIF+gZKBuIHSgeqCMoJygoCClIK0gtSDMoOQg8KEDoRahJCEtIT4hSqFbIWchd6GNIZ6hrqG9Ic0h3iHsogIiFaIrokAiUaJhIn4il6KporkiyCLdovCi/CMSIyojOSNGI2cjeiOMo58jtiPFo9uj6yQBJBCkJiQ3pD6kRCRjpHikjSSdpLCkxyTVJO2k/iUWJSalNaVFpVylcqWLpZ2lriXGJekl/iYepjWmVCZrJn4mmKa3Js2m8CcLJxwnLSc9p0qnZid9J4qnoae/p9Cn4af3KBcoJygyqEEoVShrqHwoiyiTKKoowqjNKNeo5yjwqRApK6lBKU8paymAKYupk6mqqbgp1anrKfSqBioQKh8qLKo4qkeqTapTqlqqY6p0KoAqjyqXqqAqrqq6qsyq3Sr0qwOrE6seqzArQKtJq1orb6uFK5qrsCu9q8sr2KvmK/qsDCwZLCSsMyxErFYsZCyCrJ2swazQrOitBC0XLSMtQ61TLV8td62HrbAt1y3jre4t+q4FHicY2BkYGDqZTjGwMMAAkxAzAWEDAz/wXwGACvLAngAeJxtkb1u2zAUhY8cJ2lioIMLBEiniw5ZCssdggxZCnTL6iE7LVOOAIo0SCqIHqvv0Gfo2KlDn6BzDynWKJBKEPWdc/9ICcASP1Bhui74TFyRLwrPcM6siU/oXheekz8UPsUCHwuf0b8rfAmPz4UXeIev7FDN05wlvhWuyN8Lz/AWvwqf0P9deI5l9abwKa6q94XP6H8qfImf1ZfCC9zMbja6714eGmd9go6w0fvBKH/UR3jUPnTOym19908yQVK9dEGUBB3FteIO2q6CG3yjxeohemVWIY5GSxhD1D1f/daZINqorfMqajNK41Ub9U5a52WnQ7e3HCjK7qietWFPH2p5ivFwv163zrLIuLpxPTbQ6NHhBQ9o4GD5Rf86XXFSzh4DDBSjr+OvnUc6HoE6KcEtav6z/3eeHDnOF+rAVfEJjEe+Hdq8HqgtVvQd9+NZoelbrgPzPGtMjkaMJJ07jFmnOZPqsWW1yTN0PlPSqTZmPdJvsm6zs6Nuc4aQdT7VPs/0ZZ8256TYc+4w7TNFa/pP7BLp3GPNu81nnCalzDqfuv8DluGfuHicdVoFeBy3Es6M0sZsB5q0SZnpCk7KzMzM3bvdu9t6b3Ve8MUpM/dx+5iZmZmZmZmZ+T1pRlppbdff5++b/19pVjAk7S3DZfw3tmzJP3wYEAQsh61ga1gBQzAMIzAKYzAOEzAJU7ASVsFqWAPbwFpYB9vCdrAeNsD2sAPsCDvBzrAL7Aq7we6wB+wJe8HesA/sC/vB/tCAA+BAOAgOhmnYCJvgEDgUDoPD4Qg4Eo6Co+EYOBaOg+PhBDgRToKT4RQ4FU6D0+EMOBPOgrPhHDgXzoPz4QK4EC6Ci+ESuBQug8vhCrgSroKr4Rq4Fq6D6yGAJrQghAja0IEuxHADzEACPUhBQh9mIYMcCihhDgawGeZhC9wIN8HNcAvcCrfB7XAH3Al3wd1wD9wL98H98AA8CA/Bw/AIPAGeCE+CJ8NT4KnwNHgUHoOnwzPgmfAseDY8B54Lz4PnwwvghfAieDG8BF4KL4OXwyvglfAqeDW8Bl4Lr4PXwxvgjfAmeDO8Bd4Kb4O3wzvgnfAueDe8B94L74P3wwfgg/Ah+DB8BD4KH4OPwyfgk/Ap+DR8Bj4Ln4PPwxfgi/Al+DJ8Bb4KX4Ovwzfgm/At+DZ8B74L34Pvww/gh/Aj+DH8BH4KP4Ofwy/gl/Ar+DX8Bn4Lv4Pfwx/gj/An+DP8Bf4Kf4O/wz/gn/Av+Df8B/4L/8NlCIgocDluhVvjChzCYRzBURzDcZzASZzClbgKV+Ma3AbX4jrcFrfD9bgBt8cdcEfcCXfGXXBX3A13xz1wT9wL98Z9cF/cD/fHBh6AB+JBeDBO40bchIfgoXgYHo5H4JF4FB6Nx+CxeBwejyfgiXgSnoyn4Kl4Gp6OZ+CZeBaejefguXgeno8X4IV4EV6Ml+CleBlejlfglXgVXo3X4LV4HV6PATaxhSFG2MYOdjHGG3AGE+xhihL7OIsZ5lhgiXM4wM04j1vwRrwJb8Zb8Fa8DW/HO/BOvAvvxnvwXrwP78cH8EF8CB/GR/AJ+ER8Ej4Zn4JPxafho/gYPh2fgc/EZ+Gz8Tn4XHwePh9fgC/EF+GL8SX4UnwZvhxfga/EV+Gr8TX4Wnwdvh7fgG/EN+Gb8S34Vnwbvh3fge/Ed+G78T34Xnwfvh8/gB/ED+GH8SP4UfwYfhw/gZ/ET+Gn8TP4Wfwcfh6/gF/EL+GX8Sv4Vfwafh2/gd/Eb+G38Tv4Xfwefh9/gD/EH+GP8Sf4U/wZ/hx/gb/EX+Gv8Tf4W/wd/h7/gH/EP+Gf8S/4V/wb/h3/gf/Ef+G/8T/4X/yfWCZAoBBiudhKbC1WiCExLEbEqBgT42JCTIopsVKsEqvFGrGNWCvWiW3FdmK92CC2FzuIHcVOYmexi9hV7CZ2F3uIPcVeYm+xj9hX7Cf2Fw1xgDhQHCQOFtNio9gkDhGHisPE4eIIcaQ4ShwtjhHHiuPE8eIEcaI4SZwsThGnitPE6eIMcaY4S5wtzhHnivPE+eICcaG4SFwsLhGXisvE5eIKcaW4SlwtrhHXiuvE9SIQTdESoYhEW3REV8TiBjEjEtETqZCiL2ZFJnJRiFLMiYHYLObFFnGjuEncLG4Rt4rbxO3iDnGnuEvcLe4R94r7xP3iAfGgeEg8LB5ZNhVkmRw0srjTLRpJnEaTTIRykPo4idr8fJxx2fefKpQTXuWrY2qlp7DGkMp8kZp2nCQL1GiqrsZjjBrNjOUzcb8aGgE3sQnC1bwYVtOqumo9fleNva4OUldvsKWnfBtvaG4EruEgDiOi1nizqsj1LZmlUUYT0RpCWTYTfrTBPWK93rO13ks9ep2/lobXw14dbe4HaVgb90JOt1truAWTWYLWrc3MO7LRltkgyEJ/mkWZpY1m0JrxB0ak33hVpaJqOtyVvciT9JtGSdpErJXJLEjOe7Ga5zTbW42hDW6WcRLGace08DGbVtqKo7RodIIiMjbrM2xshczsKyqgn0z1gjhplGkWBTyjSSJa3chMZ4JwHqWhB2U/ShdCsjbXeJFymounXONxwkHIuh3y2iYyj/yBESZTjtOm3NwIslY3nuMmCygakepQhg3ZbvN4HdRPRxh6IlkAqylTX/ciksYYFEXQ6vb0YnNscJjWvZ/JdmyMuwI0LquG98SD+umKgPWNBGRpNL5eFAYJa2WRm66ei7K4HUehssCwEy3JGUvlN+SFtdQFFDlQM8jU/gSZMp5Mlv2IV2TK0dOLCZqPI2g+DtI+N6Wc6QUZv9chGmwrSJTBUHtrdB5X7b/jorlqvSuOhzXaTgLrJ2uKLA7STpmop0QvSZJ3ml4kdxLZVItL2oxsPDiVZWY9mGSKIa1SuVNPhbk8yubiFo91MUuLW402V1MNSxsLF9O04erZTG4tJ06LKKsDapRF/WSebYVFzgnaA/tJkBrX8TD1cjYw4vZ+Ku8GM1GjqyIlv7ZGsDPJ/ryXpRxk5486QV+tTWRCQwVpTP0gzxtzQRKbOONhCmOEVSCh0EZhrMa4NiqYx5kxzDpDzqH0tWx4rgBtobLHorGRt9DIjp/2+Gk7nzwPlPtstPOxsPZ0uv7UhFXS44XVGkFzIaIW+msMrZnHsLk7THMN41xZWl4HTlc31qF+fgmGtM+pJC4bxJN2D7u3z0lrvj5m0+lHwYwxKBJpBaMwrlbTyLResyptJY0qcTionw7lMVdCJNCu6ABhyiMrUyghnToUUyipEA2jmZV5lwfHIi0Mi9N1QJvSD5QrNVyvGqGbD4eZ5DGwxMEsUc5vM4pDvKsykeSa1l3rDOlsWZ2qlCyaUtsnj2eEX++JnERUfCgKm0QMME/SwvpbBThbBJ24xZpY5OovLWIVUVszgzi3aaFGUd9CyoTNyIg2kXr9Jup9JsJMhdBqsTzIwTPo9czsrczeFmctY9tW5hWSprwcV4vWi1MbkFtllsusJnO8UwZSuNAz3pK9fml3YKgX8EqMKUGnHrPAVfMRF6VGw6gK4qNFoOpP4xthoFCQW1/1MfXTcd7Oysg0sq7e3TCrCgYPsxvoqB+ktjSz0IJqIcZUQq3ARN4tC1cJT7VVgIwyygsm+yZlpLauYKseHqhigBeGJGu6Q5mJFiSQG3b6htECBbIwyLtsoxwGawRnTxfCrKz5NbkyrJn5RiqVtdoSbxFJxmNKpNyM3kH3tIg2+08J0vhc4412MRzh+utU5fUnaMw67vN0jFlbyNtaqq2cN9vKMjmeMrfYWm4FaDxkYDpeVaWTR5BxFzKUvC8kuVn4vXyCRkJqTPIyMtddWnb1uINkbm2ZhMoU7fL7mMKVwa7yqjM8Nmaqd9QItgAm2AJY5lVK4k7aaEW6XBmhLSG1k3Ea6goujFoqHeaRxXFqMDXVpDLsuFAL7Krq6eW6LFrRVUZYBJ3hfCYqVA2bdkYHQWKd1cqmLk1nXEHgQZqb8hnl7UqTtR6f4OJAVcEyNSGHZdLrGpJeB2ld867s93XZ0jQN6gz7h2P0NIx/LCApbFdky9bXCygaaaHCbdfYqpFpjnP6PiAOetKeynyCJq0JlZQGNgzVCJqtI2i2DlLUmLPJey62SXqzKhZSc/RwiOZdoVAmug6neS8kqbZWI1QO10rVv0sUi1kuuNR6aLuVsbFSn6A9qV6hu9Ke1Biq0Fl3VGbSf+USNHmXrjn7qny2ScLDNKZBQDk/CWx54RMm0ZnhDlfjVBW5dMW5NF443InN7Q9LtMrTmxpddRDhkO0Qnapq9sY3Dws50tuUA06uLJHfdiNtVOwRFbA1ZhLPmLhnAc2Vm/XLxBQINYLsU0WDfjBvQmaqioPY3qEkcVMl04Y7gU8E/X6DryloHRQ0WzHSDOKwNJVXrDqqf1u5Z/biZVyfGKpzxIhLt+NKbDbtbdO4OkhmlInIBNtBK6Lw6e38eFsdLCjP07DbSVnYsmK0ExfdsmlkKTumy5SR1XHLZJw4VYesThb0WGWczsV5bGLKcC8qApJWzM7y8zwN+lVRPlrEM4UpWcaKQexeP4iqRuNGNlXkIIqbnGEmzQO77uMDhXK9uNRwSzfu8lqOzcuyKJv25Bb0G8pOqqNNBcmPLCxis9x1hgtTVUD3jWlXoNa7zG2BXGPIUjJZ+ZSViacTrOGNbMrgbMbudgXIQzKpjlv6BTT7CpGfafs0hwUWKZa1TEQigdq5c/RI3As6NZGmxKJnNXWGAmiiD9GtoG9W2EEaJp+8jEk4RK9nRO9kkdw2sSbNEqeqQBXWgfEGlvncxrIt+3xMY1OeGnrndgdpcXvq8GC7VoDPGApM+yLnDpmUvcirTn2C8w8TvdJ4Xo3gdMOEOf55kNZbuawqY1tBYZ2ozlDqqDF2+ItZLgK0p3rbVyPafO+gjLO2wzWGtKhw1a9p8QmaVTRbqlC3xdi9B2lHVXnDvjis/DP3JH5qYyFLfEJ2d7pWprYq2vArWOITkjo0Kq/I7fnFw6aEy5omHluZZhWnCvXcUtcIsl0q6arzeIX0sw0V0sWcOcoV9uvA0s+4cFT1qVVZASoeql7eSi8idcvt6mq95ks/oVXSr3ocTLvOt5GPy5CtZEEYy0ZTJQprnTWG3MWrt1n0voGMuCvPIVu3r61m2CuTIrbJcAmatiQvm0UWtMxNAtkZ72zZT6S5kBrX/lih1RVySXilae2l5UR2VKC2O7NKQZU2altRp+yBuBtHSViTTZVMsqok7bVVjam1cStWY9j1mKkSSI2gPmGkDgRRo1kltTpDm+0xCzHN1mJ9Xzq9FEW1ur4WaehbyYG034jqFLkbUcZ1jUwDJ7lME1sB1ghyjWg+cgd4DSqBY4wSnAF5sNaZrSTS9/9mFA7Rsy1S9hp6I8kDCdlsbkG9HVeu3cBWbCyaHdSi7zQ1hnoGqubvmVqPRNKu6qte02YBh2h3GLlPvx6mfWA1gyBLbWWwgKI3tPlabtoWewaZPQrsqXYykdL/Putj0mPacp09lUUqvHrNhytDHHY2GrTUcTJ1V5k1gpRS2+rjWIVo+oRUBCvNNQ3rVWcnOVhM0JC9HrQahMvUa7KAcmpov8LFhO60zg5bl3DeJi/F01bTdyXeahZpu6KepJTSVSmPa9UFFB1qLJXqFJQsyVEUslyZOn2LSJqOJXN7T+8TNN6BOlWwjQ1ZYZLyqncv72EqIvPS9NCCyd/SlziaagNplgmfIUZm1BGTDXFoxt45KdeytxprXHN3ohwr1F7E5lKgAsa9ozCpDL1CXDNGQduTdIv1+mudyhlqd7OoJTtpXOX8x3lEEUUR89VFmAU0z1Cam1qWaK/UISgsuXZomaJ8IccVjGwHpoLREltIlik1NYeuUzTP2TLKq4E7RA6d99URzFyhGZl8qZ/JrjpIFpH9MuUw1Rx+yWND7yKSoi/ZQTdI2jammiKrjnTT7Ren7mai76ZMDIyywhd1l+VNmYRbx4UqGlsrdJGur73aUn8lCJTpzY+QTJ8bhknMVXE5XKpiJ+P3F5k6rRfqmFx2uiN8N6d/ETHKIoWrMXdL15j2wcYJAiqBRdrzpxmWqSEmTQEzW6rjdN7IhMok6n+j+t+k/g9R/4eq/4PHfC1rqt+Y1OKG9xMQ/w7G+/XJYpp+2eHXIQtV6wVcSjXd+ixW7dG+atrkluz1SuUD5nTvIBtZqyulKbeMTEZGv+vgO5GFmHyHf14wXQfkYnSCD/iWowJkEPrL7Gic9in/qoJnzL/VG/Pv/MwtjlFvgX8tw3WTPjwn7rcmNYI8U9+HsGeSxJ5uvxCyRNvSVlobXZnFW5Ql0o8VHocmDyN6LtL36FXbRaRuuWzZ/wFvvfvjAA==) format("woff")}.ri-arrow-right-line:before{content:"\ea6c"}.ri-arrow-down-line:before{content:"\ea4c"}.ri-arrow-left-line:before{content:"\ea60"}.ri-arrow-up-line:before{content:"\ea76"}.ri-arrow-up-s-line:before{content:"\ea78"}.ri-arrow-right-s-line:before{content:"\ea6e"}.ri-arrow-down-s-line:before{content:"\ea4e"}.ri-arrow-left-s-line:before{content:"\ea64"}.ri-arrow-up-s-fill:before{content:"\ea77"}.ri-arrow-right-s-fill:before{content:"\ea6d"}.ri-arrow-down-s-fill:before{content:"\ea4d"}.ri-arrow-left-s-fill:before{content:"\ea63"}.ri-skip-up-line:before{content:"\f367"}.ri-skip-right-line:before{content:"\f365"}.ri-skip-down-line:before{content:"\f361"}.ri-skip-left-line:before{content:"\f363"}.ri-skip-up-fill:before{content:"\f366"}.ri-skip-right-fill:before{content:"\f364"}.ri-skip-down-fill:before{content:"\f360"}.ri-skip-left-fill:before{content:"\f362"}.ri-arrow-up-down-line:before{content:"\ea74"}.ri-arrow-left-right-line:before{content:"\ea62"}.ri-arrow-up-wide-line:before{content:"\f498"}.ri-arrow-down-wide-line:before{content:"\f492"}.ri-corner-up-left-double-line:before{content:"\f313"}.ri-corner-up-right-double-line:before{content:"\f317"}.ri-arrow-left-double-line:before{content:"\f2e3"}.ri-arrow-right-double-fill:before{content:"\f2e4"}.ri-expand-up-down-line:before{content:"\f327"}.ri-expand-up-down-fill:before{content:"\f326"}.ri-expand-left-right-line:before{content:"\f323"}.ri-expand-left-right-fill:before{content:"\f322"}.ri-arrow-go-forward-line:before{content:"\ea5a"}.ri-arrow-turn-back-line:before{content:"\f2e7"}.ri-arrow-turn-forward-line:before{content:"\f2e9"}.ri-arrow-go-back-line:before{content:"\ea58"}.ri-home-line:before{content:"\ee2b"}.ri-home-fill:before{content:"\ee26"}.ri-home-4-line:before{content:"\ee1d"}.ri-home-4-fill:before{content:"\ee1c"}.ri-home-smile-2-line:before{content:"\ee2d"}.ri-home-smile-2-fill:before{content:"\ee2c"}.ri-building-2-line:before{content:"\eb09"}.ri-building-2-fill:before{content:"\eb08"}.ri-ancient-gate-line:before{content:"\ea32"}.ri-ancient-gate-fill:before{content:"\ea31"}.ri-store-2-line:before{content:"\f1a5"}.ri-store-2-fill:before{content:"\f1a4"}.ri-mail-unread-line:before{content:"\ef02"}.ri-mail-check-line:before{content:"\eeee"}.ri-mail-send-line:before{content:"\eefc"}.ri-mail-open-line:before{content:"\eefa"}.ri-mail-open-fill:before{content:"\eef9"}.ri-mail-send-fill:before{content:"\eefb"}.ri-mail-unread-fill:before{content:"\ef01"}.ri-mail-check-fill:before{content:"\eeed"}.ri-mail-add-line:before{content:"\eeec"}.ri-mail-add-fill:before{content:"\eeeb"}.ri-mail-close-line:before{content:"\eef0"}.ri-mail-close-fill:before{content:"\eeef"}.ri-inbox-archive-line:before{content:"\ee4d"}.ri-inbox-archive-fill:before{content:"\ee4c"}.ri-cloud-off-line:before{content:"\eb9f"}.ri-cloud-off-fill:before{content:"\eb9e"}.ri-cloud-fill:before{content:"\eb9c"}.ri-cloud-line:before{content:"\eb9d"}.ri-inbox-unarchive-line:before{content:"\ee51"}.ri-inbox-unarchive-fill:before{content:"\ee50"}.ri-attachment-line:before{content:"\ea86"}.ri-attachment-fill:before{content:"\ea85"}.ri-profile-line:before{content:"\f02d"}.ri-profile-fill:before{content:"\f02c"}.ri-archive-2-line:before{content:"\f3a7"}.ri-archive-2-fill:before{content:"\f3a6"}.ri-at-line:before{content:"\ea83"}.ri-award-fill:before{content:"\ea89"}.ri-medal-fill:before{content:"\ef27"}.ri-medal-2-fill:before{content:"\ef25"}.ri-verified-badge-fill:before{content:"\f3e8"}.ri-verified-badge-line:before{content:"\f3e9"}.ri-archive-stack-line:before{content:"\f428"}.ri-archive-stack-fill:before{content:"\f427"}.ri-bar-chart-grouped-line:before{content:"\ea9b"}.ri-bar-chart-grouped-fill:before{content:"\ea9a"}.ri-bar-chart-2-line:before{content:"\ea96"}.ri-bar-chart-2-fill:before{content:"\ea95"}.ri-bar-chart-line:before{content:"\ea9e"}.ri-bar-chart-fill:before{content:"\ea99"}.ri-bookmark-line:before{content:"\eae5"}.ri-bookmark-fill:before{content:"\eae4"}.ri-calendar-check-line:before{content:"\eb23"}.ri-calendar-close-line:before{content:"\f38e"}.ri-calendar-event-line:before{content:"\eb25"}.ri-calendar-2-line:before{content:"\eb21"}.ri-flag-2-line:before{content:"\ed39"}.ri-triangular-flag-line:before{content:"\f54a"}.ri-triangular-flag-fill:before{content:"\f549"}.ri-flag-2-fill:before{content:"\ed38"}.ri-global-line:before{content:"\edcf"}.ri-global-fill:before{content:"\edce"}.ri-honour-line:before{content:"\ee35"}.ri-honour-fill:before{content:"\ee34"}.ri-customer-service-line:before{content:"\ec0e"}.ri-customer-service-fill:before{content:"\ec0d"}.ri-calendar-schedule-line:before{content:"\f3f3"}.ri-calendar-schedule-fill:before{content:"\f3f2"}.ri-links-line:before{content:"\eeb8"}.ri-printer-line:before{content:"\f029"}.ri-printer-fill:before{content:"\f028"}.ri-reply-line:before{content:"\f07a"}.ri-reply-fill:before{content:"\f079"}.ri-send-plane-line:before{content:"\f0da"}.ri-send-plane-fill:before{content:"\f0d9"}.ri-stack-line:before{content:"\f181"}.ri-stack-fill:before{content:"\f180"}.ri-shake-hands-line:before{content:"\f3ab"}.ri-shake-hands-fill:before{content:"\f3aa"}.ri-copyright-line:before{content:"\ebe2"}.ri-copyright-fill:before{content:"\ebe1"}.ri-megaphone-line:before{content:"\f385"}.ri-megaphone-fill:before{content:"\f384"}.ri-pass-valid-line:before{content:"\f38b"}.ri-pass-valid-fill:before{content:"\f38a"}.ri-pass-pending-line:before{content:"\f389"}.ri-pass-pending-fill:before{content:"\f388"}.ri-pass-expired-line:before{content:"\f387"}.ri-pass-expired-fill:before{content:"\f386"}.ri-id-card-line:before{content:"\f4e9"}.ri-id-card-fill:before{content:"\f4e8"}.ri-chat-3-line:before{content:"\eb51"}.ri-chat-3-fill:before{content:"\eb50"}.ri-chat-2-line:before{content:"\eb4f"}.ri-chat-2-fill:before{content:"\eb4e"}.ri-message-3-line:before{content:"\ef46"}.ri-message-3-fill:before{content:"\ef45"}.ri-message-2-line:before{content:"\ef44"}.ri-message-2-fill:before{content:"\ef43"}.ri-chat-unread-line:before{content:"\f52a"}.ri-chat-unread-fill:before{content:"\f529"}.ri-chat-smile-2-line:before{content:"\eb6f"}.ri-chat-smile-2-fill:before{content:"\eb6e"}.ri-chat-smile-line:before{content:"\eb73"}.ri-chat-smile-fill:before{content:"\eb72"}.ri-discuss-fill:before{content:"\ec39"}.ri-discuss-line:before{content:"\ec3a"}.ri-chat-history-line:before{content:"\eb61"}.ri-chat-history-fill:before{content:"\eb60"}.ri-video-chat-line:before{content:"\f27e"}.ri-video-chat-fill:before{content:"\f27d"}.ri-chat-voice-fill:before{content:"\eb76"}.ri-chat-voice-line:before{content:"\eb77"}.ri-speak-fill:before{content:"\f36e"}.ri-speak-line:before{content:"\f36f"}.ri-edit-2-line:before{content:"\ec80"}.ri-edit-2-fill:before{content:"\ec7f"}.ri-quill-pen-line:before{content:"\f04a"}.ri-quill-pen-fill:before{content:"\f049"}.ri-sip-line:before{content:"\f13e"}.ri-sip-fill:before{content:"\f13d"}.ri-markup-line:before{content:"\ef20"}.ri-markup-fill:before{content:"\ef1f"}.ri-edit-box-line:before{content:"\ec82"}.ri-edit-box-fill:before{content:"\ec81"}.ri-brush-line:before{content:"\eb01"}.ri-brush-fill:before{content:"\eb00"}.ri-brush-2-fill:before{content:"\eafa"}.ri-brush-2-line:before{content:"\eafb"}.ri-paint-brush-line:before{content:"\efc1"}.ri-paint-brush-fill:before{content:"\efc0"}.ri-drop-line:before{content:"\ec6a"}.ri-drop-fill:before{content:"\ec69"}.ri-blur-off-line:before{content:"\eace"}.ri-blur-off-fill:before{content:"\eacd"}.ri-color-filter-line:before{content:"\f42f"}.ri-color-filter-fill:before{content:"\f42e"}.ri-crop-line:before{content:"\ec02"}.ri-artboard-2-line:before{content:"\ea7a"}.ri-paint-line:before{content:"\efc3"}.ri-paint-fill:before{content:"\efc2"}.ri-palette-line:before{content:"\efc5"}.ri-palette-fill:before{content:"\efc4"}.ri-pantone-line:before{content:"\efc7"}.ri-pantone-fill:before{content:"\efc6"}.ri-magic-line:before{content:"\eeea"}.ri-magic-fill:before{content:"\eee9"}.ri-anticlockwise-line:before{content:"\ea3c"}.ri-anticlockwise-fill:before{content:"\ea3b"}.ri-tools-line:before{content:"\f21b"}.ri-tools-fill:before{content:"\f21a"}.ri-clockwise-line:before{content:"\eb95"}.ri-clockwise-fill:before{content:"\eb94"}.ri-drag-drop-line:before{content:"\ec5e"}.ri-drag-drop-fill:before{content:"\ec5d"}.ri-hammer-fill:before{content:"\edee"}.ri-hammer-line:before{content:"\edef"}.ri-circle-line:before{content:"\f3c2"}.ri-circle-fill:before{content:"\f3c1"}.ri-code-line:before{content:"\eba9"}.ri-code-fill:before{content:"\eba8"}.ri-terminal-line:before{content:"\f1f8"}.ri-terminal-fill:before{content:"\f1f7"}.ri-cursor-line:before{content:"\ec0a"}.ri-cursor-fill:before{content:"\ec09"}.ri-smartphone-line:before{content:"\f15a"}.ri-computer-line:before{content:"\ebca"}.ri-mac-line:before{content:"\eee6"}.ri-macbook-line:before{content:"\eee8"}.ri-phone-line:before{content:"\efec"}.ri-phone-fill:before{content:"\efe9"}.ri-device-line:before{content:"\ec2e"}.ri-tablet-line:before{content:"\f1e0"}.ri-database-2-line:before{content:"\ec16"}.ri-database-2-fill:before{content:"\ec15"}.ri-server-line:before{content:"\f0e0"}.ri-server-fill:before{content:"\f0df"}.ri-hard-drive-fill:before{content:"\edfa"}.ri-hard-drive-line:before{content:"\edfb"}.ri-qr-scan-2-line:before{content:"\f03f"}.ri-qr-scan-line:before{content:"\f041"}.ri-qr-code-line:before{content:"\f03d"}.ri-barcode-line:before{content:"\eaa2"}.ri-shut-down-line:before{content:"\f126"}.ri-fingerprint-line:before{content:"\ed31"}.ri-bluetooth-line:before{content:"\eacc"}.ri-wifi-line:before{content:"\f2c0"}.ri-wifi-off-line:before{content:"\f2c2"}.ri-rss-line:before{content:"\f09f"}.ri-rss-fill:before{content:"\f09e"}.ri-gps-line:before{content:"\eddb"}.ri-gps-fill:before{content:"\edda"}.ri-dashboard-3-line:before{content:"\ec12"}.ri-dashboard-3-fill:before{content:"\ec11"}.ri-file-2-line:before{content:"\ecc3"}.ri-file-2-fill:before{content:"\ecc2"}.ri-sticky-note-add-line:before{content:"\f466"}.ri-sticky-note-add-fill:before{content:"\f465"}.ri-file-list-line:before{content:"\ecf1"}.ri-file-list-fill:before{content:"\ecf0"}.ri-file-text-line:before{content:"\ed0f"}.ri-file-text-fill:before{content:"\ed0e"}.ri-file-list-3-line:before{content:"\ecef"}.ri-file-list-3-fill:before{content:"\ecee"}.ri-file-copy-line:before{content:"\ecd5"}.ri-file-copy-fill:before{content:"\ecd4"}.ri-clipboard-line:before{content:"\eb91"}.ri-clipboard-fill:before{content:"\eb90"}.ri-survey-line:before{content:"\f1c7"}.ri-survey-fill:before{content:"\f1c6"}.ri-article-line:before{content:"\ea7e"}.ri-article-fill:before{content:"\ea7d"}.ri-book-marked-line:before{content:"\ead9"}.ri-book-marked-fill:before{content:"\ead8"}.ri-todo-line:before{content:"\f217"}.ri-todo-fill:before{content:"\f216"}.ri-file-marked-line:before{content:"\ecf5"}.ri-file-marked-fill:before{content:"\ecf4"}.ri-book-3-line:before{content:"\ead5"}.ri-book-3-fill:before{content:"\ead4"}.ri-book-open-line:before{content:"\eadb"}.ri-book-open-fill:before{content:"\eada"}.ri-folder-add-line:before{content:"\ed5a"}.ri-folder-add-fill:before{content:"\ed59"}.ri-folder-check-line:before{content:"\f43e"}.ri-folder-check-fill:before{content:"\f43d"}.ri-folder-open-line:before{content:"\ed70"}.ri-folder-open-fill:before{content:"\ed6f"}.ri-folder-line:before{content:"\ed6a"}.ri-folder-fill:before{content:"\ed61"}.ri-align-center:before{content:"\ea25"}.ri-list-check:before{content:"\eeba"}.ri-indent-decrease:before{content:"\ee54"}.ri-indent-increase:before{content:"\ee55"}.ri-list-indefinite:before{content:"\f399"}.ri-attachment-2:before{content:"\ea84"}.ri-link:before{content:"\eeb2"}.ri-hashtag:before{content:"\edfc"}.ri-sketching:before{content:"\f35f"}.ri-wallet-line:before{content:"\f2ae"}.ri-wallet-fill:before{content:"\f2ad"}.ri-bank-card-line:before{content:"\ea92"}.ri-bank-card-fill:before{content:"\ea91"}.ri-price-tag-3-line:before{content:"\f023"}.ri-price-tag-3-fill:before{content:"\f022"}.ri-coupon-line:before{content:"\ebee"}.ri-coupon-fill:before{content:"\ebed"}.ri-price-tag-line:before{content:"\f025"}.ri-price-tag-fill:before{content:"\f024"}.ri-shopping-bag-line:before{content:"\f118"}.ri-shopping-bag-fill:before{content:"\f117"}.ri-shopping-basket-line:before{content:"\f11c"}.ri-shopping-basket-fill:before{content:"\f11b"}.ri-shopping-cart-line:before{content:"\f120"}.ri-shopping-cart-fill:before{content:"\f11f"}.ri-trophy-line:before{content:"\f22f"}.ri-trophy-fill:before{content:"\f22e"}.ri-vip-diamond-fill:before{content:"\f28f"}.ri-vip-diamond-line:before{content:"\f290"}.ri-vip-crown-2-line:before{content:"\f28c"}.ri-vip-crown-2-fill:before{content:"\f28b"}.ri-vip-crown-line:before{content:"\f28e"}.ri-vip-crown-fill:before{content:"\f28d"}.ri-vip-line:before{content:"\f292"}.ri-vip-fill:before{content:"\f291"}.ri-exchange-line:before{content:"\ecad"}.ri-exchange-fill:before{content:"\ecaa"}.ri-exchange-dollar-line:before{content:"\eca9"}.ri-exchange-dollar-fill:before{content:"\eca8"}.ri-money-cny-circle-line:before{content:"\ef61"}.ri-money-cny-circle-fill:before{content:"\ef60"}.ri-copper-coin-line:before{content:"\ebdc"}.ri-copper-coin-fill:before{content:"\ebdb"}.ri-exchange-cny-line:before{content:"\eca7"}.ri-exchange-cny-fill:before{content:"\eca6"}.ri-money-euro-circle-line:before{content:"\ef69"}.ri-money-euro-circle-fill:before{content:"\ef68"}.ri-red-packet-line:before{content:"\f060"}.ri-red-packet-fill:before{content:"\f05f"}.ri-water-flash-line:before{content:"\f2b0"}.ri-water-flash-fill:before{content:"\f2af"}.ri-coin-line:before{content:"\ebb2"}.ri-coin-fill:before{content:"\ebb1"}.ri-stock-line:before{content:"\f19d"}.ri-stock-fill:before{content:"\f19c"}.ri-gift-line:before{content:"\edbb"}.ri-gift-fill:before{content:"\edba"}.ri-24-hours-line:before{content:"\ea02"}.ri-24-hours-fill:before{content:"\ea01"}.ri-shopping-bag-4-line:before{content:"\f511"}.ri-shopping-bag-4-fill:before{content:"\f510"}.ri-bowl-line:before{content:"\f42a"}.ri-bowl-fill:before{content:"\f429"}.ri-heart-3-line:before{content:"\ee0b"}.ri-heart-3-fill:before{content:"\ee0a"}.ri-dislike-line:before{content:"\ec3c"}.ri-dislike-fill:before{content:"\ec3b"}.ri-heart-pulse-line:before{content:"\ee11"}.ri-heart-pulse-fill:before{content:"\ee10"}.ri-alipay-line:before{content:"\ea2c"}.ri-android-line:before{content:"\ea36"}.ri-alibaba-cloud-line:before{content:"\f4b8"}.ri-app-store-line:before{content:"\ea3e"}.ri-apple-line:before{content:"\ea40"}.ri-baidu-line:before{content:"\ea8c"}.ri-bilibili-line:before{content:"\eac0"}.ri-chrome-line:before{content:"\eb8d"}.ri-dingding-line:before{content:"\ec32"}.ri-drive-line:before{content:"\ec66"}.ri-dribbble-line:before{content:"\ec64"}.ri-evernote-line:before{content:"\eca3"}.ri-facebook-circle-line:before{content:"\ecbb"}.ri-firebase-line:before{content:"\f4d4"}.ri-flutter-line:before{content:"\ed48"}.ri-github-line:before{content:"\edcb"}.ri-google-line:before{content:"\edd5"}.ri-google-play-line:before{content:"\edd7"}.ri-instagram-line:before{content:"\ee66"}.ri-invision-line:before{content:"\ee6a"}.ri-meta-line:before{content:"\f343"}.ri-qq-line:before{content:"\f03b"}.ri-snapchat-line:before{content:"\f15c"}.ri-tiktok-line:before{content:"\f373"}.ri-twitter-line:before{content:"\f23b"}.ri-wechat-line:before{content:"\f2b6"}.ri-wechat-2-line:before{content:"\f2b4"}.ri-weibo-line:before{content:"\f2ba"}.ri-wechat-pay-line:before{content:"\f2b8"}.ri-whatsapp-line:before{content:"\f2bc"}.ri-zhihu-line:before{content:"\f2d9"}.ri-youtube-line:before{content:"\f2d5"}.ri-map-pin-2-line:before{content:"\ef0a"}.ri-map-pin-2-fill:before{content:"\ef09"}.ri-map-pin-time-line:before{content:"\ef18"}.ri-map-pin-time-fill:before{content:"\ef17"}.ri-pushpin-line:before{content:"\f039"}.ri-pushpin-fill:before{content:"\f038"}.ri-map-pin-user-line:before{content:"\ef1a"}.ri-map-pin-user-fill:before{content:"\ef19"}.ri-rocket-line:before{content:"\f096"}.ri-rocket-fill:before{content:"\f095"}.ri-planet-line:before{content:"\f39f"}.ri-planet-fill:before{content:"\f39e"}.ri-parking-line:before{content:"\efd0"}.ri-parking-fill:before{content:"\efcf"}.ri-road-map-line:before{content:"\f08e"}.ri-road-map-fill:before{content:"\f08d"}.ri-earth-line:before{content:"\ec7a"}.ri-earth-fill:before{content:"\ec79"}.ri-car-line:before{content:"\eb39"}.ri-car-fill:before{content:"\eb38"}.ri-plane-line:before{content:"\f005"}.ri-image-line:before{content:"\ee4b"}.ri-image-fill:before{content:"\ee4a"}.ri-image-circle-line:before{content:"\f413"}.ri-image-circle-fill:before{content:"\f412"}.ri-landscape-line:before{content:"\ee7d"}.ri-landscape-fill:before{content:"\ee7c"}.ri-video-on-line:before{content:"\f51e"}.ri-video-on-fill:before{content:"\f51d"}.ri-video-line:before{content:"\f282"}.ri-video-fill:before{content:"\f281"}.ri-live-line:before{content:"\eec0"}.ri-live-fill:before{content:"\eebf"}.ri-camera-line:before{content:"\eb31"}.ri-camera-fill:before{content:"\eb2e"}.ri-camera-off-line:before{content:"\eb33"}.ri-camera-off-fill:before{content:"\eb32"}.ri-headphone-line:before{content:"\ee05"}.ri-headphone-fill:before{content:"\ee04"}.ri-mic-off-line:before{content:"\ef52"}.ri-mic-off-fill:before{content:"\ef51"}.ri-mic-2-fill:before{content:"\ef4d"}.ri-mic-2-line:before{content:"\ef4e"}.ri-volume-down-line:before{content:"\f29c"}.ri-volume-down-fill:before{content:"\f29b"}.ri-volume-mute-line:before{content:"\f29e"}.ri-volume-mute-fill:before{content:"\f29d"}.ri-volume-up-line:before{content:"\f2a2"}.ri-volume-up-fill:before{content:"\f2a1"}.ri-notification-line:before{content:"\ef9a"}.ri-notification-fill:before{content:"\ef99"}.ri-notification-off-line:before{content:"\ef9c"}.ri-notification-off-fill:before{content:"\ef9b"}.ri-play-circle-line:before{content:"\f009"}.ri-play-circle-fill:before{content:"\f008"}.ri-pause-circle-line:before{content:"\efd6"}.ri-pause-circle-fill:before{content:"\efd5"}.ri-stop-circle-line:before{content:"\f19f"}.ri-stop-circle-fill:before{content:"\f19e"}.ri-equalizer-line:before{content:"\ec9d"}.ri-equalizer-fill:before{content:"\ec9c"}.ri-menu-line:before{content:"\ef3e"}.ri-menu-fill:before{content:"\ef3b"}.ri-apps-line:before{content:"\ea44"}.ri-apps-fill:before{content:"\ea43"}.ri-more-line:before{content:"\ef79"}.ri-more-fill:before{content:"\ef78"}.ri-more-2-line:before{content:"\ef77"}.ri-more-2-fill:before{content:"\ef76"}.ri-star-line:before{content:"\f18b"}.ri-star-fill:before{content:"\f186"}.ri-settings-2-line:before{content:"\f0e4"}.ri-settings-2-fill:before{content:"\f0e3"}.ri-forbid-line:before{content:"\ed95"}.ri-forbid-fill:before{content:"\ed94"}.ri-information-line:before{content:"\ee59"}.ri-information-fill:before{content:"\ee58"}.ri-checkbox-blank-circle-line:before{content:"\eb7d"}.ri-checkbox-blank-circle-fill:before{content:"\eb7c"}.ri-checkbox-line:before{content:"\eb85"}.ri-checkbox-fill:before{content:"\eb82"}.ri-checkbox-indeterminate-line:before{content:"\eb84"}.ri-checkbox-indeterminate-fill:before{content:"\eb83"}.ri-add-box-line:before{content:"\ea0f"}.ri-add-box-fill:before{content:"\ea0e"}.ri-checkbox-circle-line:before{content:"\eb81"}.ri-checkbox-circle-fill:before{content:"\eb80"}.ri-indeterminate-circle-line:before{content:"\ee57"}.ri-indeterminate-circle-fill:before{content:"\ee56"}.ri-add-circle-fill:before{content:"\ea10"}.ri-add-circle-line:before{content:"\ea11"}.ri-close-circle-line:before{content:"\eb97"}.ri-close-circle-fill:before{content:"\eb96"}.ri-radio-button-line:before{content:"\f050"}.ri-radio-button-fill:before{content:"\f04f"}.ri-check-line:before{content:"\eb7b"}.ri-check-double-line:before{content:"\eb79"}.ri-close-line:before{content:"\eb99"}.ri-add-line:before{content:"\ea13"}.ri-checkbox-multiple-line:before{content:"\eb89"}.ri-checkbox-multiple-fill:before{content:"\eb88"}.ri-subtract-line:before{content:"\f1af"}.ri-equal-line:before{content:"\f31f"}.ri-upload-line:before{content:"\f250"}.ri-download-line:before{content:"\ec5a"}.ri-download-cloud-line:before{content:"\ec58"}.ri-upload-cloud-line:before{content:"\f24e"}.ri-login-box-line:before{content:"\eed4"}.ri-logout-circle-line:before{content:"\eedc"}.ri-logout-circle-r-line:before{content:"\eede"}.ri-shield-line:before{content:"\f108"}.ri-shield-fill:before{content:"\f103"}.ri-shield-cross-line:before{content:"\f102"}.ri-shield-cross-fill:before{content:"\f101"}.ri-shield-check-line:before{content:"\f100"}.ri-shield-check-fill:before{content:"\f0ff"}.ri-shield-user-fill:before{content:"\f10b"}.ri-shield-user-line:before{content:"\f10c"}.ri-delete-bin-2-line:before{content:"\ec1e"}.ri-delete-bin-2-fill:before{content:"\ec1d"}.ri-delete-bin-fill:before{content:"\ec29"}.ri-delete-bin-line:before{content:"\ec2a"}.ri-delete-back-2-line:before{content:"\ec1a"}.ri-delete-back-2-fill:before{content:"\ec19"}.ri-lock-password-line:before{content:"\eed0"}.ri-lock-password-fill:before{content:"\eecf"}.ri-lock-2-line:before{content:"\eecc"}.ri-lock-2-fill:before{content:"\eecb"}.ri-lock-unlock-line:before{content:"\eed2"}.ri-lock-unlock-fill:before{content:"\eed1"}.ri-eye-off-line:before{content:"\ecb7"}.ri-eye-line:before{content:"\ecb5"}.ri-eye-fill:before{content:"\ecb4"}.ri-eye-close-line:before{content:"\ecb3"}.ri-eye-close-fill:before{content:"\ecb2"}.ri-eye-off-fill:before{content:"\ecb6"}.ri-search-2-line:before{content:"\f0cd"}.ri-search-2-fill:before{content:"\f0cc"}.ri-zoom-out-line:before{content:"\f2dd"}.ri-zoom-in-line:before{content:"\f2db"}.ri-zoom-in-fill:before{content:"\f2da"}.ri-zoom-out-fill:before{content:"\f2dc"}.ri-share-line:before{content:"\f0fe"}.ri-share-fill:before{content:"\f0f7"}.ri-share-circle-line:before{content:"\f0f6"}.ri-share-circle-fill:before{content:"\f0f5"}.ri-alarm-line:before{content:"\ea1b"}.ri-alarm-fill:before{content:"\ea1a"}.ri-thumb-up-line:before{content:"\f207"}.ri-thumb-up-fill:before{content:"\f206"}.ri-thumb-down-line:before{content:"\f205"}.ri-thumb-down-fill:before{content:"\f204"}.ri-alarm-warning-line:before{content:"\ea1d"}.ri-alarm-warning-fill:before{content:"\ea1c"}.ri-filter-2-line:before{content:"\ed23"}.ri-filter-2-fill:before{content:"\ed22"}.ri-loader-line:before{content:"\eeca"}.ri-loader-fill:before{content:"\eec9"}.ri-loop-right-line:before{content:"\f33f"}.ri-loop-right-fill:before{content:"\f33e"}.ri-loader-4-line:before{content:"\eec6"}.ri-loader-4-fill:before{content:"\eec5"}.ri-reset-right-line:before{content:"\f544"}.ri-user-line:before{content:"\f264"}.ri-user-fill:before{content:"\f25f"}.ri-account-box-line:before{content:"\ea07"}.ri-account-box-fill:before{content:"\ea06"}.ri-user-add-line:before{content:"\f25e"}.ri-user-add-fill:before{content:"\f25d"}.ri-user-minus-fill:before{content:"\f54b"}.ri-user-follow-fill:before{content:"\f260"}.ri-user-follow-line:before{content:"\f261"}.ri-user-minus-line:before{content:"\f54c"}.ri-user-unfollow-line:before{content:"\f278"}.ri-user-unfollow-fill:before{content:"\f277"}.ri-user-shared-fill:before{content:"\f271"}.ri-user-shared-line:before{content:"\f272"}.ri-account-pin-circle-line:before{content:"\ea0d"}.ri-account-pin-circle-fill:before{content:"\ea0c"}.ri-group-line:before{content:"\ede3"}.ri-group-fill:before{content:"\ede2"}.ri-emotion-happy-line:before{content:"\ec8d"}.ri-emotion-happy-fill:before{content:"\ec8c"}.ri-emotion-normal-fill:before{content:"\ec91"}.ri-emotion-normal-line:before{content:"\ec92"}.ri-emotion-unhappy-line:before{content:"\ec96"}.ri-emotion-unhappy-fill:before{content:"\ec95"}.ri-emotion-sad-line:before{content:"\ec94"}.ri-emotion-sad-fill:before{content:"\ec93"}.ri-women-line:before{content:"\f2ce"}.ri-men-line:before{content:"\ef2e"}.ri-star-smile-line:before{content:"\f18f"}.ri-star-smile-fill:before{content:"\f18e"}.ri-sun-line:before{content:"\f1bf"}.ri-sun-fill:before{content:"\f1bc"}.ri-moon-fill:before{content:"\ef72"}.ri-moon-line:before{content:"\ef75"}.ri-lightbulb-line:before{content:"\eea9"}.ri-key-2-line:before{content:"\ee6f"}.ri-key-line:before{content:"\ee71"}.ri-outlet-line:before{content:"\efbc"}.ri-lightbulb-flash-line:before{content:"\eea8"}.ri-t-shirt-line:before{content:"\f1d9"}.ri-t-shirt-fill:before{content:"\f1d8"}.ri-seedling-fill:before{content:"\f0d4"}.ri-seedling-line:before{content:"\f0d5"}.ri-leaf-line:before{content:"\eea3"}.ri-leaf-fill:before{content:"\eea2"}.ri-character-recognition-line:before{content:"\eb47"}.ri-character-recognition-fill:before{content:"\eb46"}.ri-recycle-line:before{content:"\f05e"}.ri-recycle-fill:before{content:"\f05d"}.ri-door-line:before{content:"\ec46"}.ri-door-fill:before{content:"\ec45"}.ri-graduation-cap-line:before{content:"\f333"}.ri-graduation-cap-fill:before{content:"\f332"}.ri-sofa-line:before{content:"\f41e"}.ri-sofa-fill:before{content:"\f41d"}.ri-error-warning-line:before{content:"\eca1"}.ri-error-warning-fill:before{content:"\eca0"}.ri-question-line:before{content:"\f045"}.ri-question-fill:before{content:"\f044"}.ri-spam-3-line:before{content:"\f16b"}.ri-spam-3-fill:before{content:"\f16a"}.ri-prohibited-line:before{content:"\f3a1"}.ri-prohibited-fill:before{content:"\f3a0"}.ri-information-off-line:before{content:"\f4eb"}.ri-information-off-fill:before{content:"\f4ea"}.ri-star-half-line:before{content:"\f188"}.ri-star-half-fill:before{content:"\f187"}.ri-settings-line:before{content:"\f0ee"}.ri-settings-fill:before{content:"\f0ed"}.ri-checkbox-multiple-blank-line:before{content:"\eb87"}.ri-alert-line:before{content:"\ea21"}.ri-alert-fill:before{content:"\ea20"}.ri-bold:before{content:"\ead1"}.ri-italic:before{content:"\ee6b"}.ri-heading:before{content:"\ee03"}.ri-font-family:before{content:"\f390"}.ri-font-color:before{content:"\ed8b"}.ri-font-size:before{content:"\ed8d"}.ri-underline:before{content:"\f244"}.ri-strikethrough:before{content:"\f1ab"}.ri-align-left:before{content:"\ea27"}.ri-align-right:before{content:"\ea28"}.ri-list-check-2:before{content:"\eeb9"}.ri-list-check-3:before{content:"\f398"}.ri-list-ordered-2:before{content:"\f39a"}.ri-list-unordered:before{content:"\eebe"}.ri-double-quotes-r:before{content:"\ec52"}.ri-h-2:before{content:"\ede7"}.ri-h-3:before{content:"\ede8"}.ri-h-4:before{content:"\ede9"}.ri-h-5:before{content:"\edea"}.ri-h-6:before{content:"\edeb"}.ri-h-1:before{content:"\ede6"}.ri-list-ordered:before{content:"\eebb"}.ri-arrow-up-circle-line:before{content:"\ea72"}.ri-arrow-right-circle-line:before{content:"\ea68"}.ri-arrow-down-circle-line:before{content:"\ea4a"}.ri-arrow-left-circle-line:before{content:"\ea5c"}.ri-arrow-up-circle-fill:before{content:"\ea71"}.ri-arrow-right-circle-fill:before{content:"\ea67"}.ri-arrow-down-circle-fill:before{content:"\ea49"}.ri-arrow-left-circle-fill:before{content:"\ea5b"}.ri-community-line:before{content:"\ebba"}.ri-community-fill:before{content:"\ebb9"}.ri-school-line:before{content:"\f35a"}.ri-school-fill:before{content:"\f359"}.ri-home-heart-fill:before{content:"\ee29"}.ri-home-heart-line:before{content:"\ee2a"}.ri-inbox-2-line:before{content:"\f3a9"}.ri-inbox-2-fill:before{content:"\f3a8"}.ri-chat-ai-line:before{content:"\f56a"}.ri-chat-ai-fill:before{content:"\f569"}.ri-hand:before{content:"\f445"}.ri-input-field:before{content:"\f47a"}.ri-diamond-line:before{content:"\f5e4"}.ri-diamond-fill:before{content:"\f5e3"}.ri-heart-2-line:before{content:"\ee09"}.ri-heart-2-fill:before{content:"\ee08"}.ri-alipay-fill:before{content:"\ea2b"}.ri-sparkling-2-line:before{content:"\f36b"}.ri-sparkling-2-fill:before{content:"\f36a"}.ri-fire-line:before{content:"\ed33"}.ri-fire-fill:before{content:"\ed32"}.ri-dice-fill:before{content:"\f400"}.ri-dice-line:before{content:"\f401"}.ri-flip-horizontal-2-line:before{content:"\f4d6"}.ri-flip-horizontal-2-fill:before{content:"\f4d5"}.ri-flip-vertical-2-line:before{content:"\f4da"}.ri-flip-vertical-2-fill:before{content:"\f4d9"} \ No newline at end of file diff --git a/uni_modules/tmx-ui/scss/uvue.css b/uni_modules/tmx-ui/scss/uvue.css new file mode 100644 index 0000000..f02473e --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvue.css @@ -0,0 +1,7985 @@ +@charset "UTF-8"; +.overflow { + overflow: hidden; } + +.show { + visibility: visible; } + +.hidden { + visibility: hidden; } + +.none { + display: none; } + +.relative { + position: relative; } + +.absolute { + position: absolute; } + +.fixed { + position: fixed; } + +.fulled { + width: 100%; } + +.fulled-height { + flex: 1; } + +.zIndex-0 { + z-index: 0; } + +.zIndex-n0 { + z-index: 0; } + +.zIndex-1 { + z-index: 1; } + +.zIndex-n1 { + z-index: 4; } + +.zIndex-2 { + z-index: 2; } + +.zIndex-n2 { + z-index: 8; } + +.zIndex-3 { + z-index: 3; } + +.zIndex-n3 { + z-index: 12; } + +.zIndex-4 { + z-index: 4; } + +.zIndex-n4 { + z-index: 16; } + +.zIndex-5 { + z-index: 5; } + +.zIndex-n5 { + z-index: 20; } + +.zIndex-6 { + z-index: 6; } + +.zIndex-n6 { + z-index: 24; } + +.zIndex-7 { + z-index: 7; } + +.zIndex-n7 { + z-index: 28; } + +.zIndex-8 { + z-index: 8; } + +.zIndex-n8 { + z-index: 32; } + +.zIndex-9 { + z-index: 9; } + +.zIndex-n9 { + z-index: 36; } + +.zIndex-10 { + z-index: 10; } + +.zIndex-n10 { + z-index: 40; } + +.zIndex-11 { + z-index: 11; } + +.zIndex-n11 { + z-index: 44; } + +.zIndex-12 { + z-index: 12; } + +.zIndex-n12 { + z-index: 48; } + +.zIndex-13 { + z-index: 13; } + +.zIndex-n13 { + z-index: 52; } + +.zIndex-14 { + z-index: 14; } + +.zIndex-n14 { + z-index: 56; } + +.zIndex-15 { + z-index: 15; } + +.zIndex-n15 { + z-index: 60; } + +.zIndex-16 { + z-index: 16; } + +.zIndex-n16 { + z-index: 64; } + +.zIndex-17 { + z-index: 17; } + +.zIndex-n17 { + z-index: 68; } + +.zIndex-18 { + z-index: 18; } + +.zIndex-n18 { + z-index: 72; } + +.zIndex-19 { + z-index: 19; } + +.zIndex-n19 { + z-index: 76; } + +.zIndex-20 { + z-index: 20; } + +.zIndex-n20 { + z-index: 80; } + +.zIndex-21 { + z-index: 21; } + +.zIndex-n21 { + z-index: 84; } + +.zIndex-22 { + z-index: 22; } + +.zIndex-n22 { + z-index: 88; } + +.zIndex-23 { + z-index: 23; } + +.zIndex-n23 { + z-index: 92; } + +.zIndex-24 { + z-index: 24; } + +.zIndex-n24 { + z-index: 96; } + +.zIndex-25 { + z-index: 25; } + +.zIndex-n25 { + z-index: 100; } + +.zIndex-26 { + z-index: 26; } + +.zIndex-n26 { + z-index: 104; } + +.text-overflow { + text-overflow: ellipsis; } + +.text-overflow-1 { + text-overflow: ellipsis; + lines: 1; } + +.text-overflow-2 { + text-overflow: ellipsis; + lines: 2; } + +.text-overflow-3 { + text-overflow: ellipsis; + lines: 3; } + +.text-overflow-4 { + text-overflow: ellipsis; + lines: 4; } + +.text-size-xxs { + font-size: 20rpx; } + +.text-size-xs { + font-size: 22rpx; } + +.text-size-s { + font-size: 24rpx; } + +.text-size-m { + font-size: 28rpx; } + +.text-size-n { + font-size: 30rpx; } + +.text-size-g { + font-size: 34rpx; } + +.text-size-lg { + font-size: 36rpx; } + +.text-size-xl { + font-size: 40rpx; } + +.text-weight-s { + font-weight: 400; } + +.text-weight-n { + font-weight: 400; } + +.text-weight-b { + font-weight: 700; } + +.text-align-left { + text-align: left; } + +.text-align-right { + text-align: right; } + +.text-align-center { + text-align: center; } + +.round-tl-0 { + border-top-left-radius: 0rpx; } + +.round-tl-1 { + border-top-left-radius: 2rpx; } + +.round-tl-2 { + border-top-left-radius: 4rpx; } + +.round-tl-3 { + border-top-left-radius: 6rpx; } + +.round-tl-4 { + border-top-left-radius: 8rpx; } + +.round-tl-5 { + border-top-left-radius: 10rpx; } + +.round-tl-6 { + border-top-left-radius: 12rpx; } + +.round-tl-7 { + border-top-left-radius: 14rpx; } + +.round-tl-8 { + border-top-left-radius: 16rpx; } + +.round-tl-9 { + border-top-left-radius: 18rpx; } + +.round-tl-10 { + border-top-left-radius: 20rpx; } + +.round-tl-11 { + border-top-left-radius: 22rpx; } + +.round-tl-12 { + border-top-left-radius: 24rpx; } + +.round-tl-13 { + border-top-left-radius: 26rpx; } + +.round-tl-14 { + border-top-left-radius: 28rpx; } + +.round-tl-15 { + border-top-left-radius: 30rpx; } + +.round-tl-16 { + border-top-left-radius: 32rpx; } + +.round-tl-17 { + border-top-left-radius: 34rpx; } + +.round-tl-18 { + border-top-left-radius: 36rpx; } + +.round-tl-19 { + border-top-left-radius: 38rpx; } + +.round-tl-20 { + border-top-left-radius: 40rpx; } + +.round-tl-21 { + border-top-left-radius: 42rpx; } + +.round-tl-22 { + border-top-left-radius: 44rpx; } + +.round-tl-23 { + border-top-left-radius: 46rpx; } + +.round-tl-24 { + border-top-left-radius: 48rpx; } + +.round-tl-25 { + border-top-left-radius: 50rpx; } + +.round-tr-0 { + border-top-right-radius: 0rpx; } + +.round-tr-1 { + border-top-right-radius: 2rpx; } + +.round-tr-2 { + border-top-right-radius: 4rpx; } + +.round-tr-3 { + border-top-right-radius: 6rpx; } + +.round-tr-4 { + border-top-right-radius: 8rpx; } + +.round-tr-5 { + border-top-right-radius: 10rpx; } + +.round-tr-6 { + border-top-right-radius: 12rpx; } + +.round-tr-7 { + border-top-right-radius: 14rpx; } + +.round-tr-8 { + border-top-right-radius: 16rpx; } + +.round-tr-9 { + border-top-right-radius: 18rpx; } + +.round-tr-10 { + border-top-right-radius: 20rpx; } + +.round-tr-11 { + border-top-right-radius: 22rpx; } + +.round-tr-12 { + border-top-right-radius: 24rpx; } + +.round-tr-13 { + border-top-right-radius: 26rpx; } + +.round-tr-14 { + border-top-right-radius: 28rpx; } + +.round-tr-15 { + border-top-right-radius: 30rpx; } + +.round-tr-16 { + border-top-right-radius: 32rpx; } + +.round-tr-17 { + border-top-right-radius: 34rpx; } + +.round-tr-18 { + border-top-right-radius: 36rpx; } + +.round-tr-19 { + border-top-right-radius: 38rpx; } + +.round-tr-20 { + border-top-right-radius: 40rpx; } + +.round-tr-21 { + border-top-right-radius: 42rpx; } + +.round-tr-22 { + border-top-right-radius: 44rpx; } + +.round-tr-23 { + border-top-right-radius: 46rpx; } + +.round-tr-24 { + border-top-right-radius: 48rpx; } + +.round-tr-25 { + border-top-right-radius: 50rpx; } + +.round-bl-0 { + border-bottom-left-radius: 0rpx; } + +.round-bl-1 { + border-bottom-left-radius: 2rpx; } + +.round-bl-2 { + border-bottom-left-radius: 4rpx; } + +.round-bl-3 { + border-bottom-left-radius: 6rpx; } + +.round-bl-4 { + border-bottom-left-radius: 8rpx; } + +.round-bl-5 { + border-bottom-left-radius: 10rpx; } + +.round-bl-6 { + border-bottom-left-radius: 12rpx; } + +.round-bl-7 { + border-bottom-left-radius: 14rpx; } + +.round-bl-8 { + border-bottom-left-radius: 16rpx; } + +.round-bl-9 { + border-bottom-left-radius: 18rpx; } + +.round-bl-10 { + border-bottom-left-radius: 20rpx; } + +.round-bl-11 { + border-bottom-left-radius: 22rpx; } + +.round-bl-12 { + border-bottom-left-radius: 24rpx; } + +.round-bl-13 { + border-bottom-left-radius: 26rpx; } + +.round-bl-14 { + border-bottom-left-radius: 28rpx; } + +.round-bl-15 { + border-bottom-left-radius: 30rpx; } + +.round-bl-16 { + border-bottom-left-radius: 32rpx; } + +.round-bl-17 { + border-bottom-left-radius: 34rpx; } + +.round-bl-18 { + border-bottom-left-radius: 36rpx; } + +.round-bl-19 { + border-bottom-left-radius: 38rpx; } + +.round-bl-20 { + border-bottom-left-radius: 40rpx; } + +.round-bl-21 { + border-bottom-left-radius: 42rpx; } + +.round-bl-22 { + border-bottom-left-radius: 44rpx; } + +.round-bl-23 { + border-bottom-left-radius: 46rpx; } + +.round-bl-24 { + border-bottom-left-radius: 48rpx; } + +.round-bl-25 { + border-bottom-left-radius: 50rpx; } + +.round-br-0 { + border-bottom-right-radius: 0rpx; } + +.round-br-1 { + border-bottom-right-radius: 2rpx; } + +.round-br-2 { + border-bottom-right-radius: 4rpx; } + +.round-br-3 { + border-bottom-right-radius: 6rpx; } + +.round-br-4 { + border-bottom-right-radius: 8rpx; } + +.round-br-5 { + border-bottom-right-radius: 10rpx; } + +.round-br-6 { + border-bottom-right-radius: 12rpx; } + +.round-br-7 { + border-bottom-right-radius: 14rpx; } + +.round-br-8 { + border-bottom-right-radius: 16rpx; } + +.round-br-9 { + border-bottom-right-radius: 18rpx; } + +.round-br-10 { + border-bottom-right-radius: 20rpx; } + +.round-br-11 { + border-bottom-right-radius: 22rpx; } + +.round-br-12 { + border-bottom-right-radius: 24rpx; } + +.round-br-13 { + border-bottom-right-radius: 26rpx; } + +.round-br-14 { + border-bottom-right-radius: 28rpx; } + +.round-br-15 { + border-bottom-right-radius: 30rpx; } + +.round-br-16 { + border-bottom-right-radius: 32rpx; } + +.round-br-17 { + border-bottom-right-radius: 34rpx; } + +.round-br-18 { + border-bottom-right-radius: 36rpx; } + +.round-br-19 { + border-bottom-right-radius: 38rpx; } + +.round-br-20 { + border-bottom-right-radius: 40rpx; } + +.round-br-21 { + border-bottom-right-radius: 42rpx; } + +.round-br-22 { + border-bottom-right-radius: 44rpx; } + +.round-br-23 { + border-bottom-right-radius: 46rpx; } + +.round-br-24 { + border-bottom-right-radius: 48rpx; } + +.round-br-25 { + border-bottom-right-radius: 50rpx; } + +.round-a-0 { + border-radius: 0rpx; } + +.round-a-1 { + border-radius: 2rpx; } + +.round-a-2 { + border-radius: 4rpx; } + +.round-a-3 { + border-radius: 6rpx; } + +.round-a-4 { + border-radius: 8rpx; } + +.round-a-5 { + border-radius: 10rpx; } + +.round-a-6 { + border-radius: 12rpx; } + +.round-a-7 { + border-radius: 14rpx; } + +.round-a-8 { + border-radius: 16rpx; } + +.round-a-9 { + border-radius: 18rpx; } + +.round-a-10 { + border-radius: 20rpx; } + +.round-a-11 { + border-radius: 22rpx; } + +.round-a-12 { + border-radius: 24rpx; } + +.round-a-13 { + border-radius: 26rpx; } + +.round-a-14 { + border-radius: 28rpx; } + +.round-a-15 { + border-radius: 30rpx; } + +.round-a-16 { + border-radius: 32rpx; } + +.round-a-17 { + border-radius: 34rpx; } + +.round-a-18 { + border-radius: 36rpx; } + +.round-a-19 { + border-radius: 38rpx; } + +.round-a-20 { + border-radius: 40rpx; } + +.round-a-21 { + border-radius: 42rpx; } + +.round-a-22 { + border-radius: 44rpx; } + +.round-a-23 { + border-radius: 46rpx; } + +.round-a-24 { + border-radius: 48rpx; } + +.round-a-25 { + border-radius: 50rpx; } + +.round-t-0 { + border-top-left-radius: 0rpx; + border-top-right-radius: 0rpx; } + +.round-t-1 { + border-top-left-radius: 2rpx; + border-top-right-radius: 2rpx; } + +.round-t-2 { + border-top-left-radius: 4rpx; + border-top-right-radius: 4rpx; } + +.round-t-3 { + border-top-left-radius: 6rpx; + border-top-right-radius: 6rpx; } + +.round-t-4 { + border-top-left-radius: 8rpx; + border-top-right-radius: 8rpx; } + +.round-t-5 { + border-top-left-radius: 10rpx; + border-top-right-radius: 10rpx; } + +.round-t-6 { + border-top-left-radius: 12rpx; + border-top-right-radius: 12rpx; } + +.round-t-7 { + border-top-left-radius: 14rpx; + border-top-right-radius: 14rpx; } + +.round-t-8 { + border-top-left-radius: 16rpx; + border-top-right-radius: 16rpx; } + +.round-t-9 { + border-top-left-radius: 18rpx; + border-top-right-radius: 18rpx; } + +.round-t-10 { + border-top-left-radius: 20rpx; + border-top-right-radius: 20rpx; } + +.round-t-11 { + border-top-left-radius: 22rpx; + border-top-right-radius: 22rpx; } + +.round-t-12 { + border-top-left-radius: 24rpx; + border-top-right-radius: 24rpx; } + +.round-t-13 { + border-top-left-radius: 26rpx; + border-top-right-radius: 26rpx; } + +.round-t-14 { + border-top-left-radius: 28rpx; + border-top-right-radius: 28rpx; } + +.round-t-15 { + border-top-left-radius: 30rpx; + border-top-right-radius: 30rpx; } + +.round-t-16 { + border-top-left-radius: 32rpx; + border-top-right-radius: 32rpx; } + +.round-t-17 { + border-top-left-radius: 34rpx; + border-top-right-radius: 34rpx; } + +.round-t-18 { + border-top-left-radius: 36rpx; + border-top-right-radius: 36rpx; } + +.round-t-19 { + border-top-left-radius: 38rpx; + border-top-right-radius: 38rpx; } + +.round-t-20 { + border-top-left-radius: 40rpx; + border-top-right-radius: 40rpx; } + +.round-t-21 { + border-top-left-radius: 42rpx; + border-top-right-radius: 42rpx; } + +.round-t-22 { + border-top-left-radius: 44rpx; + border-top-right-radius: 44rpx; } + +.round-t-23 { + border-top-left-radius: 46rpx; + border-top-right-radius: 46rpx; } + +.round-t-24 { + border-top-left-radius: 48rpx; + border-top-right-radius: 48rpx; } + +.round-t-25 { + border-top-left-radius: 50rpx; + border-top-right-radius: 50rpx; } + +.round-b-0 { + border-bottom-left-radius: 0rpx; + border-bottom-right-radius: 0rpx; } + +.round-b-1 { + border-bottom-left-radius: 2rpx; + border-bottom-right-radius: 2rpx; } + +.round-b-2 { + border-bottom-left-radius: 4rpx; + border-bottom-right-radius: 4rpx; } + +.round-b-3 { + border-bottom-left-radius: 6rpx; + border-bottom-right-radius: 6rpx; } + +.round-b-4 { + border-bottom-left-radius: 8rpx; + border-bottom-right-radius: 8rpx; } + +.round-b-5 { + border-bottom-left-radius: 10rpx; + border-bottom-right-radius: 10rpx; } + +.round-b-6 { + border-bottom-left-radius: 12rpx; + border-bottom-right-radius: 12rpx; } + +.round-b-7 { + border-bottom-left-radius: 14rpx; + border-bottom-right-radius: 14rpx; } + +.round-b-8 { + border-bottom-left-radius: 16rpx; + border-bottom-right-radius: 16rpx; } + +.round-b-9 { + border-bottom-left-radius: 18rpx; + border-bottom-right-radius: 18rpx; } + +.round-b-10 { + border-bottom-left-radius: 20rpx; + border-bottom-right-radius: 20rpx; } + +.round-b-11 { + border-bottom-left-radius: 22rpx; + border-bottom-right-radius: 22rpx; } + +.round-b-12 { + border-bottom-left-radius: 24rpx; + border-bottom-right-radius: 24rpx; } + +.round-b-13 { + border-bottom-left-radius: 26rpx; + border-bottom-right-radius: 26rpx; } + +.round-b-14 { + border-bottom-left-radius: 28rpx; + border-bottom-right-radius: 28rpx; } + +.round-b-15 { + border-bottom-left-radius: 30rpx; + border-bottom-right-radius: 30rpx; } + +.round-b-16 { + border-bottom-left-radius: 32rpx; + border-bottom-right-radius: 32rpx; } + +.round-b-17 { + border-bottom-left-radius: 34rpx; + border-bottom-right-radius: 34rpx; } + +.round-b-18 { + border-bottom-left-radius: 36rpx; + border-bottom-right-radius: 36rpx; } + +.round-b-19 { + border-bottom-left-radius: 38rpx; + border-bottom-right-radius: 38rpx; } + +.round-b-20 { + border-bottom-left-radius: 40rpx; + border-bottom-right-radius: 40rpx; } + +.round-b-21 { + border-bottom-left-radius: 42rpx; + border-bottom-right-radius: 42rpx; } + +.round-b-22 { + border-bottom-left-radius: 44rpx; + border-bottom-right-radius: 44rpx; } + +.round-b-23 { + border-bottom-left-radius: 46rpx; + border-bottom-right-radius: 46rpx; } + +.round-b-24 { + border-bottom-left-radius: 48rpx; + border-bottom-right-radius: 48rpx; } + +.round-b-25 { + border-bottom-left-radius: 50rpx; + border-bottom-right-radius: 50rpx; } + +.round-l-0 { + border-top-left-radius: 0rpx; + border-bottom-left-radius: 0rpx; } + +.round-l-1 { + border-top-left-radius: 2rpx; + border-bottom-left-radius: 2rpx; } + +.round-l-2 { + border-top-left-radius: 4rpx; + border-bottom-left-radius: 4rpx; } + +.round-l-3 { + border-top-left-radius: 6rpx; + border-bottom-left-radius: 6rpx; } + +.round-l-4 { + border-top-left-radius: 8rpx; + border-bottom-left-radius: 8rpx; } + +.round-l-5 { + border-top-left-radius: 10rpx; + border-bottom-left-radius: 10rpx; } + +.round-l-6 { + border-top-left-radius: 12rpx; + border-bottom-left-radius: 12rpx; } + +.round-l-7 { + border-top-left-radius: 14rpx; + border-bottom-left-radius: 14rpx; } + +.round-l-8 { + border-top-left-radius: 16rpx; + border-bottom-left-radius: 16rpx; } + +.round-l-9 { + border-top-left-radius: 18rpx; + border-bottom-left-radius: 18rpx; } + +.round-l-10 { + border-top-left-radius: 20rpx; + border-bottom-left-radius: 20rpx; } + +.round-l-11 { + border-top-left-radius: 22rpx; + border-bottom-left-radius: 22rpx; } + +.round-l-12 { + border-top-left-radius: 24rpx; + border-bottom-left-radius: 24rpx; } + +.round-l-13 { + border-top-left-radius: 26rpx; + border-bottom-left-radius: 26rpx; } + +.round-l-14 { + border-top-left-radius: 28rpx; + border-bottom-left-radius: 28rpx; } + +.round-l-15 { + border-top-left-radius: 30rpx; + border-bottom-left-radius: 30rpx; } + +.round-l-16 { + border-top-left-radius: 32rpx; + border-bottom-left-radius: 32rpx; } + +.round-l-17 { + border-top-left-radius: 34rpx; + border-bottom-left-radius: 34rpx; } + +.round-l-18 { + border-top-left-radius: 36rpx; + border-bottom-left-radius: 36rpx; } + +.round-l-19 { + border-top-left-radius: 38rpx; + border-bottom-left-radius: 38rpx; } + +.round-l-20 { + border-top-left-radius: 40rpx; + border-bottom-left-radius: 40rpx; } + +.round-l-21 { + border-top-left-radius: 42rpx; + border-bottom-left-radius: 42rpx; } + +.round-l-22 { + border-top-left-radius: 44rpx; + border-bottom-left-radius: 44rpx; } + +.round-l-23 { + border-top-left-radius: 46rpx; + border-bottom-left-radius: 46rpx; } + +.round-l-24 { + border-top-left-radius: 48rpx; + border-bottom-left-radius: 48rpx; } + +.round-l-25 { + border-top-left-radius: 50rpx; + border-bottom-left-radius: 50rpx; } + +.round-r-0 { + border-top-right-radius: 0rpx; + border-bottom-right-radius: 0rpx; } + +.round-r-1 { + border-top-right-radius: 2rpx; + border-bottom-right-radius: 2rpx; } + +.round-r-2 { + border-top-right-radius: 4rpx; + border-bottom-right-radius: 4rpx; } + +.round-r-3 { + border-top-right-radius: 6rpx; + border-bottom-right-radius: 6rpx; } + +.round-r-4 { + border-top-right-radius: 8rpx; + border-bottom-right-radius: 8rpx; } + +.round-r-5 { + border-top-right-radius: 10rpx; + border-bottom-right-radius: 10rpx; } + +.round-r-6 { + border-top-right-radius: 12rpx; + border-bottom-right-radius: 12rpx; } + +.round-r-7 { + border-top-right-radius: 14rpx; + border-bottom-right-radius: 14rpx; } + +.round-r-8 { + border-top-right-radius: 16rpx; + border-bottom-right-radius: 16rpx; } + +.round-r-9 { + border-top-right-radius: 18rpx; + border-bottom-right-radius: 18rpx; } + +.round-r-10 { + border-top-right-radius: 20rpx; + border-bottom-right-radius: 20rpx; } + +.round-r-11 { + border-top-right-radius: 22rpx; + border-bottom-right-radius: 22rpx; } + +.round-r-12 { + border-top-right-radius: 24rpx; + border-bottom-right-radius: 24rpx; } + +.round-r-13 { + border-top-right-radius: 26rpx; + border-bottom-right-radius: 26rpx; } + +.round-r-14 { + border-top-right-radius: 28rpx; + border-bottom-right-radius: 28rpx; } + +.round-r-15 { + border-top-right-radius: 30rpx; + border-bottom-right-radius: 30rpx; } + +.round-r-16 { + border-top-right-radius: 32rpx; + border-bottom-right-radius: 32rpx; } + +.round-r-17 { + border-top-right-radius: 34rpx; + border-bottom-right-radius: 34rpx; } + +.round-r-18 { + border-top-right-radius: 36rpx; + border-bottom-right-radius: 36rpx; } + +.round-r-19 { + border-top-right-radius: 38rpx; + border-bottom-right-radius: 38rpx; } + +.round-r-20 { + border-top-right-radius: 40rpx; + border-bottom-right-radius: 40rpx; } + +.round-r-21 { + border-top-right-radius: 42rpx; + border-bottom-right-radius: 42rpx; } + +.round-r-22 { + border-top-right-radius: 44rpx; + border-bottom-right-radius: 44rpx; } + +.round-r-23 { + border-top-right-radius: 46rpx; + border-bottom-right-radius: 46rpx; } + +.round-r-24 { + border-top-right-radius: 48rpx; + border-bottom-right-radius: 48rpx; } + +.round-r-25 { + border-top-right-radius: 50rpx; + border-bottom-right-radius: 50rpx; } + +.round-0 { + border-radius: 0rpx; } + +.round-1 { + border-radius: 2rpx; } + +.round-2 { + border-radius: 4rpx; } + +.round-3 { + border-radius: 6rpx; } + +.round-4 { + border-radius: 8rpx; } + +.round-5 { + border-radius: 10rpx; } + +.round-6 { + border-radius: 12rpx; } + +.round-7 { + border-radius: 14rpx; } + +.round-8 { + border-radius: 16rpx; } + +.round-9 { + border-radius: 18rpx; } + +.round-10 { + border-radius: 20rpx; } + +.round-11 { + border-radius: 22rpx; } + +.round-12 { + border-radius: 24rpx; } + +.round-13 { + border-radius: 26rpx; } + +.round-14 { + border-radius: 28rpx; } + +.round-15 { + border-radius: 30rpx; } + +.round-16 { + border-radius: 32rpx; } + +.round-17 { + border-radius: 34rpx; } + +.round-18 { + border-radius: 36rpx; } + +.round-19 { + border-radius: 38rpx; } + +.round-20 { + border-radius: 40rpx; } + +.round-21 { + border-radius: 42rpx; } + +.round-22 { + border-radius: 44rpx; } + +.round-23 { + border-radius: 46rpx; } + +.round-24 { + border-radius: 48rpx; } + +.round-25 { + border-radius: 50rpx; } + +.round-26 { + border-radius: 52rpx; } + +/** 0-20表示的是1.0~3.0之间的行高 */ +.line-0 { + line-height: 1; } + +.line-1 { + line-height: 1.1; } + +.line-2 { + line-height: 1.2; } + +.line-3 { + line-height: 1.3; } + +.line-4 { + line-height: 1.4; } + +.line-5 { + line-height: 1.5; } + +.line-6 { + line-height: 1.6; } + +.line-7 { + line-height: 1.7; } + +.line-8 { + line-height: 1.8; } + +.line-9 { + line-height: 1.9; } + +.line-10 { + line-height: 2; } + +.line-11 { + line-height: 2.1; } + +.line-12 { + line-height: 2.2; } + +.line-13 { + line-height: 2.3; } + +.line-14 { + line-height: 2.4; } + +.line-15 { + line-height: 2.5; } + +.line-16 { + line-height: 2.6; } + +.line-17 { + line-height: 2.7; } + +.line-18 { + line-height: 2.8; } + +.line-19 { + line-height: 2.9; } + +.line-20 { + line-height: 3; } + +.line-21 { + line-height: 3.1; } + +.opacity-0 { + opacity: 0; } + +.opacity-1 { + opacity: 0.1; } + +.opacity-2 { + opacity: 0.2; } + +.opacity-3 { + opacity: 0.3; } + +.opacity-4 { + opacity: 0.4; } + +.opacity-5 { + opacity: 0.5; } + +.opacity-6 { + opacity: 0.6; } + +.opacity-7 { + opacity: 0.7; } + +.opacity-8 { + opacity: 0.8; } + +.opacity-9 { + opacity: 0.9; } + +.opacity-10 { + opacity: 1; } + +.border-0 { + border: 0rpx solid #f5f5f5; } + +.border { + border: 2rpx solid #f5f5f5; } + +.border-1 { + border: 2rpx solid #f5f5f5; } + +.border-1-bk { + border: 2rpx solid #f5f5f5; } + +.border-2 { + border: 4rpx solid #f5f5f5; } + +.border-2-bk { + border: 4rpx solid #f5f5f5; } + +.border-3 { + border: 6rpx solid #f5f5f5; } + +.border-3-bk { + border: 6rpx solid #f5f5f5; } + +.border-4 { + border: 8rpx solid #f5f5f5; } + +.border-4-bk { + border: 8rpx solid #f5f5f5; } + +.border-5 { + border: 10rpx solid #f5f5f5; } + +.border-5-bk { + border: 10rpx solid #f5f5f5; } + +.border-l-1 { + border-left: 2rpx solid whitesmoke; } + +.border-l-2 { + border-left: 4rpx solid whitesmoke; } + +.border-l-3 { + border-left: 6rpx solid whitesmoke; } + +.border-l-4 { + border-left: 8rpx solid whitesmoke; } + +.border-l-5 { + border-left: 10rpx solid whitesmoke; } + +.border-r-1 { + border-right: 2rpx solid whitesmoke; } + +.border-r-2 { + border-right: 4rpx solid whitesmoke; } + +.border-r-3 { + border-right: 6rpx solid whitesmoke; } + +.border-r-4 { + border-right: 8rpx solid whitesmoke; } + +.border-r-5 { + border-right: 10rpx solid whitesmoke; } + +.border-t-1 { + border-top: 2rpx solid whitesmoke; } + +.border-t-2 { + border-top: 4rpx solid whitesmoke; } + +.border-t-3 { + border-top: 6rpx solid whitesmoke; } + +.border-t-4 { + border-top: 8rpx solid whitesmoke; } + +.border-t-5 { + border-top: 10rpx solid whitesmoke; } + +.border-b-1 { + border-bottom: 2rpx solid whitesmoke; } + +.border-b-2 { + border-bottom: 4rpx solid whitesmoke; } + +.border-b-3 { + border-bottom: 6rpx solid whitesmoke; } + +.border-b-4 { + border-bottom: 8rpx solid whitesmoke; } + +.border-b-5 { + border-bottom: 10rpx solid whitesmoke; } + +.border-a-1 { + border: 2rpx solid whitesmoke; } + +.border-a-2 { + border: 4rpx solid whitesmoke; } + +.border-a-3 { + border: 6rpx solid whitesmoke; } + +.border-a-4 { + border: 8rpx solid whitesmoke; } + +.border-a-5 { + border: 10rpx solid whitesmoke; } + +.pa-0 { + padding: 0rpx; } + +.pa-1 { + padding: 1rpx; } + +.pa-2 { + padding: 2rpx; } + +.pa-3 { + padding: 3rpx; } + +.pa-4 { + padding: 4rpx; } + +.pa-5 { + padding: 5rpx; } + +.pa-6 { + padding: 6rpx; } + +.pa-7 { + padding: 7rpx; } + +.pa-8 { + padding: 8rpx; } + +.pa-9 { + padding: 9rpx; } + +.pa-10 { + padding: 10rpx; } + +.pa-11 { + padding: 11rpx; } + +.pa-12 { + padding: 12rpx; } + +.pa-13 { + padding: 13rpx; } + +.pa-14 { + padding: 14rpx; } + +.pa-15 { + padding: 15rpx; } + +.pa-16 { + padding: 16rpx; } + +.pa-17 { + padding: 17rpx; } + +.pa-18 { + padding: 18rpx; } + +.pa-19 { + padding: 19rpx; } + +.pa-20 { + padding: 20rpx; } + +.pa-21 { + padding: 21rpx; } + +.pa-22 { + padding: 22rpx; } + +.pa-23 { + padding: 23rpx; } + +.pa-24 { + padding: 24rpx; } + +.pa-25 { + padding: 25rpx; } + +.pa-26 { + padding: 26rpx; } + +.pa-27 { + padding: 27rpx; } + +.pa-28 { + padding: 28rpx; } + +.pa-29 { + padding: 29rpx; } + +.pa-30 { + padding: 30rpx; } + +.pa-31 { + padding: 31rpx; } + +.pa-32 { + padding: 32rpx; } + +.pa-33 { + padding: 33rpx; } + +.pa-34 { + padding: 34rpx; } + +.pa-35 { + padding: 35rpx; } + +.pa-36 { + padding: 36rpx; } + +.pa-37 { + padding: 37rpx; } + +.pa-38 { + padding: 38rpx; } + +.pa-39 { + padding: 39rpx; } + +.pa-40 { + padding: 40rpx; } + +.pa-41 { + padding: 41rpx; } + +.pa-42 { + padding: 42rpx; } + +.pa-43 { + padding: 43rpx; } + +.pa-44 { + padding: 44rpx; } + +.pa-45 { + padding: 45rpx; } + +.pa-46 { + padding: 46rpx; } + +.pa-47 { + padding: 47rpx; } + +.pa-48 { + padding: 48rpx; } + +.pa-49 { + padding: 49rpx; } + +.pa-50 { + padding: 50rpx; } + +.pa-n1 { + padding: 4rpx; } + +.pa-n2 { + padding: 8rpx; } + +.pa-n3 { + padding: 12rpx; } + +.pa-n4 { + padding: 16rpx; } + +.pa-n5 { + padding: 20rpx; } + +.pa-n6 { + padding: 24rpx; } + +.pa-n7 { + padding: 28rpx; } + +.pa-n8 { + padding: 32rpx; } + +.pa-n9 { + padding: 36rpx; } + +.pa-n10 { + padding: 40rpx; } + +.pa-n11 { + padding: 44rpx; } + +.pa-n12 { + padding: 48rpx; } + +.pa-n13 { + padding: 52rpx; } + +.pa-n14 { + padding: 56rpx; } + +.pa-n15 { + padding: 60rpx; } + +.pa-n16 { + padding: 64rpx; } + +.pa-n17 { + padding: 68rpx; } + +.pa-n18 { + padding: 72rpx; } + +.pa-n19 { + padding: 76rpx; } + +.pa-n20 { + padding: 80rpx; } + +.pa-n21 { + padding: 84rpx; } + +.pa-n22 { + padding: 88rpx; } + +.pa-n23 { + padding: 92rpx; } + +.pa-n24 { + padding: 96rpx; } + +.pa-n25 { + padding: 100rpx; } + +.pt-0 { + padding-top: 0rpx; } + +.pt-1 { + padding-top: 1rpx; } + +.pt-2 { + padding-top: 2rpx; } + +.pt-3 { + padding-top: 3rpx; } + +.pt-4 { + padding-top: 4rpx; } + +.pt-5 { + padding-top: 5rpx; } + +.pt-6 { + padding-top: 6rpx; } + +.pt-7 { + padding-top: 7rpx; } + +.pt-8 { + padding-top: 8rpx; } + +.pt-9 { + padding-top: 9rpx; } + +.pt-10 { + padding-top: 10rpx; } + +.pt-11 { + padding-top: 11rpx; } + +.pt-12 { + padding-top: 12rpx; } + +.pt-13 { + padding-top: 13rpx; } + +.pt-14 { + padding-top: 14rpx; } + +.pt-15 { + padding-top: 15rpx; } + +.pt-16 { + padding-top: 16rpx; } + +.pt-17 { + padding-top: 17rpx; } + +.pt-18 { + padding-top: 18rpx; } + +.pt-19 { + padding-top: 19rpx; } + +.pt-20 { + padding-top: 20rpx; } + +.pt-21 { + padding-top: 21rpx; } + +.pt-22 { + padding-top: 22rpx; } + +.pt-23 { + padding-top: 23rpx; } + +.pt-24 { + padding-top: 24rpx; } + +.pt-25 { + padding-top: 25rpx; } + +.pt-26 { + padding-top: 26rpx; } + +.pt-27 { + padding-top: 27rpx; } + +.pt-28 { + padding-top: 28rpx; } + +.pt-29 { + padding-top: 29rpx; } + +.pt-30 { + padding-top: 30rpx; } + +.pt-31 { + padding-top: 31rpx; } + +.pt-32 { + padding-top: 32rpx; } + +.pt-33 { + padding-top: 33rpx; } + +.pt-34 { + padding-top: 34rpx; } + +.pt-35 { + padding-top: 35rpx; } + +.pt-36 { + padding-top: 36rpx; } + +.pt-37 { + padding-top: 37rpx; } + +.pt-38 { + padding-top: 38rpx; } + +.pt-39 { + padding-top: 39rpx; } + +.pt-40 { + padding-top: 40rpx; } + +.pt-41 { + padding-top: 41rpx; } + +.pt-42 { + padding-top: 42rpx; } + +.pt-43 { + padding-top: 43rpx; } + +.pt-44 { + padding-top: 44rpx; } + +.pt-45 { + padding-top: 45rpx; } + +.pt-46 { + padding-top: 46rpx; } + +.pt-47 { + padding-top: 47rpx; } + +.pt-48 { + padding-top: 48rpx; } + +.pt-49 { + padding-top: 49rpx; } + +.pt-50 { + padding-top: 50rpx; } + +.pt-n1 { + padding-top: 4rpx; } + +.pt-n2 { + padding-top: 8rpx; } + +.pt-n3 { + padding-top: 12rpx; } + +.pt-n4 { + padding-top: 16rpx; } + +.pt-n5 { + padding-top: 20rpx; } + +.pt-n6 { + padding-top: 24rpx; } + +.pt-n7 { + padding-top: 28rpx; } + +.pt-n8 { + padding-top: 32rpx; } + +.pt-n9 { + padding-top: 36rpx; } + +.pt-n10 { + padding-top: 40rpx; } + +.pt-n11 { + padding-top: 44rpx; } + +.pt-n12 { + padding-top: 48rpx; } + +.pt-n13 { + padding-top: 52rpx; } + +.pt-n14 { + padding-top: 56rpx; } + +.pt-n15 { + padding-top: 60rpx; } + +.pt-n16 { + padding-top: 64rpx; } + +.pt-n17 { + padding-top: 68rpx; } + +.pt-n18 { + padding-top: 72rpx; } + +.pt-n19 { + padding-top: 76rpx; } + +.pt-n20 { + padding-top: 80rpx; } + +.pt-n21 { + padding-top: 84rpx; } + +.pt-n22 { + padding-top: 88rpx; } + +.pt-n23 { + padding-top: 92rpx; } + +.pt-n24 { + padding-top: 96rpx; } + +.pt-n25 { + padding-top: 100rpx; } + +.pr-0 { + padding-right: 0rpx; } + +.pr-1 { + padding-right: 1rpx; } + +.pr-2 { + padding-right: 2rpx; } + +.pr-3 { + padding-right: 3rpx; } + +.pr-4 { + padding-right: 4rpx; } + +.pr-5 { + padding-right: 5rpx; } + +.pr-6 { + padding-right: 6rpx; } + +.pr-7 { + padding-right: 7rpx; } + +.pr-8 { + padding-right: 8rpx; } + +.pr-9 { + padding-right: 9rpx; } + +.pr-10 { + padding-right: 10rpx; } + +.pr-11 { + padding-right: 11rpx; } + +.pr-12 { + padding-right: 12rpx; } + +.pr-13 { + padding-right: 13rpx; } + +.pr-14 { + padding-right: 14rpx; } + +.pr-15 { + padding-right: 15rpx; } + +.pr-16 { + padding-right: 16rpx; } + +.pr-17 { + padding-right: 17rpx; } + +.pr-18 { + padding-right: 18rpx; } + +.pr-19 { + padding-right: 19rpx; } + +.pr-20 { + padding-right: 20rpx; } + +.pr-21 { + padding-right: 21rpx; } + +.pr-22 { + padding-right: 22rpx; } + +.pr-23 { + padding-right: 23rpx; } + +.pr-24 { + padding-right: 24rpx; } + +.pr-25 { + padding-right: 25rpx; } + +.pr-26 { + padding-right: 26rpx; } + +.pr-27 { + padding-right: 27rpx; } + +.pr-28 { + padding-right: 28rpx; } + +.pr-29 { + padding-right: 29rpx; } + +.pr-30 { + padding-right: 30rpx; } + +.pr-31 { + padding-right: 31rpx; } + +.pr-32 { + padding-right: 32rpx; } + +.pr-33 { + padding-right: 33rpx; } + +.pr-34 { + padding-right: 34rpx; } + +.pr-35 { + padding-right: 35rpx; } + +.pr-36 { + padding-right: 36rpx; } + +.pr-37 { + padding-right: 37rpx; } + +.pr-38 { + padding-right: 38rpx; } + +.pr-39 { + padding-right: 39rpx; } + +.pr-40 { + padding-right: 40rpx; } + +.pr-41 { + padding-right: 41rpx; } + +.pr-42 { + padding-right: 42rpx; } + +.pr-43 { + padding-right: 43rpx; } + +.pr-44 { + padding-right: 44rpx; } + +.pr-45 { + padding-right: 45rpx; } + +.pr-46 { + padding-right: 46rpx; } + +.pr-47 { + padding-right: 47rpx; } + +.pr-48 { + padding-right: 48rpx; } + +.pr-49 { + padding-right: 49rpx; } + +.pr-50 { + padding-right: 50rpx; } + +.pr-n1 { + padding-right: 4rpx; } + +.pr-n2 { + padding-right: 8rpx; } + +.pr-n3 { + padding-right: 12rpx; } + +.pr-n4 { + padding-right: 16rpx; } + +.pr-n5 { + padding-right: 20rpx; } + +.pr-n6 { + padding-right: 24rpx; } + +.pr-n7 { + padding-right: 28rpx; } + +.pr-n8 { + padding-right: 32rpx; } + +.pr-n9 { + padding-right: 36rpx; } + +.pr-n10 { + padding-right: 40rpx; } + +.pr-n11 { + padding-right: 44rpx; } + +.pr-n12 { + padding-right: 48rpx; } + +.pr-n13 { + padding-right: 52rpx; } + +.pr-n14 { + padding-right: 56rpx; } + +.pr-n15 { + padding-right: 60rpx; } + +.pr-n16 { + padding-right: 64rpx; } + +.pr-n17 { + padding-right: 68rpx; } + +.pr-n18 { + padding-right: 72rpx; } + +.pr-n19 { + padding-right: 76rpx; } + +.pr-n20 { + padding-right: 80rpx; } + +.pr-n21 { + padding-right: 84rpx; } + +.pr-n22 { + padding-right: 88rpx; } + +.pr-n23 { + padding-right: 92rpx; } + +.pr-n24 { + padding-right: 96rpx; } + +.pr-n25 { + padding-right: 100rpx; } + +.pb-0 { + padding-bottom: 0rpx; } + +.pb-1 { + padding-bottom: 1rpx; } + +.pb-2 { + padding-bottom: 2rpx; } + +.pb-3 { + padding-bottom: 3rpx; } + +.pb-4 { + padding-bottom: 4rpx; } + +.pb-5 { + padding-bottom: 5rpx; } + +.pb-6 { + padding-bottom: 6rpx; } + +.pb-7 { + padding-bottom: 7rpx; } + +.pb-8 { + padding-bottom: 8rpx; } + +.pb-9 { + padding-bottom: 9rpx; } + +.pb-10 { + padding-bottom: 10rpx; } + +.pb-11 { + padding-bottom: 11rpx; } + +.pb-12 { + padding-bottom: 12rpx; } + +.pb-13 { + padding-bottom: 13rpx; } + +.pb-14 { + padding-bottom: 14rpx; } + +.pb-15 { + padding-bottom: 15rpx; } + +.pb-16 { + padding-bottom: 16rpx; } + +.pb-17 { + padding-bottom: 17rpx; } + +.pb-18 { + padding-bottom: 18rpx; } + +.pb-19 { + padding-bottom: 19rpx; } + +.pb-20 { + padding-bottom: 20rpx; } + +.pb-21 { + padding-bottom: 21rpx; } + +.pb-22 { + padding-bottom: 22rpx; } + +.pb-23 { + padding-bottom: 23rpx; } + +.pb-24 { + padding-bottom: 24rpx; } + +.pb-25 { + padding-bottom: 25rpx; } + +.pb-26 { + padding-bottom: 26rpx; } + +.pb-27 { + padding-bottom: 27rpx; } + +.pb-28 { + padding-bottom: 28rpx; } + +.pb-29 { + padding-bottom: 29rpx; } + +.pb-30 { + padding-bottom: 30rpx; } + +.pb-31 { + padding-bottom: 31rpx; } + +.pb-32 { + padding-bottom: 32rpx; } + +.pb-33 { + padding-bottom: 33rpx; } + +.pb-34 { + padding-bottom: 34rpx; } + +.pb-35 { + padding-bottom: 35rpx; } + +.pb-36 { + padding-bottom: 36rpx; } + +.pb-37 { + padding-bottom: 37rpx; } + +.pb-38 { + padding-bottom: 38rpx; } + +.pb-39 { + padding-bottom: 39rpx; } + +.pb-40 { + padding-bottom: 40rpx; } + +.pb-41 { + padding-bottom: 41rpx; } + +.pb-42 { + padding-bottom: 42rpx; } + +.pb-43 { + padding-bottom: 43rpx; } + +.pb-44 { + padding-bottom: 44rpx; } + +.pb-45 { + padding-bottom: 45rpx; } + +.pb-46 { + padding-bottom: 46rpx; } + +.pb-47 { + padding-bottom: 47rpx; } + +.pb-48 { + padding-bottom: 48rpx; } + +.pb-49 { + padding-bottom: 49rpx; } + +.pb-50 { + padding-bottom: 50rpx; } + +.pb-n1 { + padding-bottom: 4rpx; } + +.pb-n2 { + padding-bottom: 8rpx; } + +.pb-n3 { + padding-bottom: 12rpx; } + +.pb-n4 { + padding-bottom: 16rpx; } + +.pb-n5 { + padding-bottom: 20rpx; } + +.pb-n6 { + padding-bottom: 24rpx; } + +.pb-n7 { + padding-bottom: 28rpx; } + +.pb-n8 { + padding-bottom: 32rpx; } + +.pb-n9 { + padding-bottom: 36rpx; } + +.pb-n10 { + padding-bottom: 40rpx; } + +.pb-n11 { + padding-bottom: 44rpx; } + +.pb-n12 { + padding-bottom: 48rpx; } + +.pb-n13 { + padding-bottom: 52rpx; } + +.pb-n14 { + padding-bottom: 56rpx; } + +.pb-n15 { + padding-bottom: 60rpx; } + +.pb-n16 { + padding-bottom: 64rpx; } + +.pb-n17 { + padding-bottom: 68rpx; } + +.pb-n18 { + padding-bottom: 72rpx; } + +.pb-n19 { + padding-bottom: 76rpx; } + +.pb-n20 { + padding-bottom: 80rpx; } + +.pb-n21 { + padding-bottom: 84rpx; } + +.pb-n22 { + padding-bottom: 88rpx; } + +.pb-n23 { + padding-bottom: 92rpx; } + +.pb-n24 { + padding-bottom: 96rpx; } + +.pb-n25 { + padding-bottom: 100rpx; } + +.pl-0 { + padding-left: 0rpx; } + +.pl-1 { + padding-left: 1rpx; } + +.pl-2 { + padding-left: 2rpx; } + +.pl-3 { + padding-left: 3rpx; } + +.pl-4 { + padding-left: 4rpx; } + +.pl-5 { + padding-left: 5rpx; } + +.pl-6 { + padding-left: 6rpx; } + +.pl-7 { + padding-left: 7rpx; } + +.pl-8 { + padding-left: 8rpx; } + +.pl-9 { + padding-left: 9rpx; } + +.pl-10 { + padding-left: 10rpx; } + +.pl-11 { + padding-left: 11rpx; } + +.pl-12 { + padding-left: 12rpx; } + +.pl-13 { + padding-left: 13rpx; } + +.pl-14 { + padding-left: 14rpx; } + +.pl-15 { + padding-left: 15rpx; } + +.pl-16 { + padding-left: 16rpx; } + +.pl-17 { + padding-left: 17rpx; } + +.pl-18 { + padding-left: 18rpx; } + +.pl-19 { + padding-left: 19rpx; } + +.pl-20 { + padding-left: 20rpx; } + +.pl-21 { + padding-left: 21rpx; } + +.pl-22 { + padding-left: 22rpx; } + +.pl-23 { + padding-left: 23rpx; } + +.pl-24 { + padding-left: 24rpx; } + +.pl-25 { + padding-left: 25rpx; } + +.pl-26 { + padding-left: 26rpx; } + +.pl-27 { + padding-left: 27rpx; } + +.pl-28 { + padding-left: 28rpx; } + +.pl-29 { + padding-left: 29rpx; } + +.pl-30 { + padding-left: 30rpx; } + +.pl-31 { + padding-left: 31rpx; } + +.pl-32 { + padding-left: 32rpx; } + +.pl-33 { + padding-left: 33rpx; } + +.pl-34 { + padding-left: 34rpx; } + +.pl-35 { + padding-left: 35rpx; } + +.pl-36 { + padding-left: 36rpx; } + +.pl-37 { + padding-left: 37rpx; } + +.pl-38 { + padding-left: 38rpx; } + +.pl-39 { + padding-left: 39rpx; } + +.pl-40 { + padding-left: 40rpx; } + +.pl-41 { + padding-left: 41rpx; } + +.pl-42 { + padding-left: 42rpx; } + +.pl-43 { + padding-left: 43rpx; } + +.pl-44 { + padding-left: 44rpx; } + +.pl-45 { + padding-left: 45rpx; } + +.pl-46 { + padding-left: 46rpx; } + +.pl-47 { + padding-left: 47rpx; } + +.pl-48 { + padding-left: 48rpx; } + +.pl-49 { + padding-left: 49rpx; } + +.pl-50 { + padding-left: 50rpx; } + +.pl-n1 { + padding-left: 4rpx; } + +.pl-n2 { + padding-left: 8rpx; } + +.pl-n3 { + padding-left: 12rpx; } + +.pl-n4 { + padding-left: 16rpx; } + +.pl-n5 { + padding-left: 20rpx; } + +.pl-n6 { + padding-left: 24rpx; } + +.pl-n7 { + padding-left: 28rpx; } + +.pl-n8 { + padding-left: 32rpx; } + +.pl-n9 { + padding-left: 36rpx; } + +.pl-n10 { + padding-left: 40rpx; } + +.pl-n11 { + padding-left: 44rpx; } + +.pl-n12 { + padding-left: 48rpx; } + +.pl-n13 { + padding-left: 52rpx; } + +.pl-n14 { + padding-left: 56rpx; } + +.pl-n15 { + padding-left: 60rpx; } + +.pl-n16 { + padding-left: 64rpx; } + +.pl-n17 { + padding-left: 68rpx; } + +.pl-n18 { + padding-left: 72rpx; } + +.pl-n19 { + padding-left: 76rpx; } + +.pl-n20 { + padding-left: 80rpx; } + +.pl-n21 { + padding-left: 84rpx; } + +.pl-n22 { + padding-left: 88rpx; } + +.pl-n23 { + padding-left: 92rpx; } + +.pl-n24 { + padding-left: 96rpx; } + +.pl-n25 { + padding-left: 100rpx; } + +.px-0 { + padding-left: 0rpx; + padding-right: 0rpx; } + +.px-1 { + padding-left: 1rpx; + padding-right: 1rpx; } + +.px-2 { + padding-left: 2rpx; + padding-right: 2rpx; } + +.px-3 { + padding-left: 3rpx; + padding-right: 3rpx; } + +.px-4 { + padding-left: 4rpx; + padding-right: 4rpx; } + +.px-5 { + padding-left: 5rpx; + padding-right: 5rpx; } + +.px-6 { + padding-left: 6rpx; + padding-right: 6rpx; } + +.px-7 { + padding-left: 7rpx; + padding-right: 7rpx; } + +.px-8 { + padding-left: 8rpx; + padding-right: 8rpx; } + +.px-9 { + padding-left: 9rpx; + padding-right: 9rpx; } + +.px-10 { + padding-left: 10rpx; + padding-right: 10rpx; } + +.px-11 { + padding-left: 11rpx; + padding-right: 11rpx; } + +.px-12 { + padding-left: 12rpx; + padding-right: 12rpx; } + +.px-13 { + padding-left: 13rpx; + padding-right: 13rpx; } + +.px-14 { + padding-left: 14rpx; + padding-right: 14rpx; } + +.px-15 { + padding-left: 15rpx; + padding-right: 15rpx; } + +.px-16 { + padding-left: 16rpx; + padding-right: 16rpx; } + +.px-17 { + padding-left: 17rpx; + padding-right: 17rpx; } + +.px-18 { + padding-left: 18rpx; + padding-right: 18rpx; } + +.px-19 { + padding-left: 19rpx; + padding-right: 19rpx; } + +.px-20 { + padding-left: 20rpx; + padding-right: 20rpx; } + +.px-21 { + padding-left: 21rpx; + padding-right: 21rpx; } + +.px-22 { + padding-left: 22rpx; + padding-right: 22rpx; } + +.px-23 { + padding-left: 23rpx; + padding-right: 23rpx; } + +.px-24 { + padding-left: 24rpx; + padding-right: 24rpx; } + +.px-25 { + padding-left: 25rpx; + padding-right: 25rpx; } + +.px-26 { + padding-left: 26rpx; + padding-right: 26rpx; } + +.px-27 { + padding-left: 27rpx; + padding-right: 27rpx; } + +.px-28 { + padding-left: 28rpx; + padding-right: 28rpx; } + +.px-29 { + padding-left: 29rpx; + padding-right: 29rpx; } + +.px-30 { + padding-left: 30rpx; + padding-right: 30rpx; } + +.px-31 { + padding-left: 31rpx; + padding-right: 31rpx; } + +.px-32 { + padding-left: 32rpx; + padding-right: 32rpx; } + +.px-33 { + padding-left: 33rpx; + padding-right: 33rpx; } + +.px-34 { + padding-left: 34rpx; + padding-right: 34rpx; } + +.px-35 { + padding-left: 35rpx; + padding-right: 35rpx; } + +.px-36 { + padding-left: 36rpx; + padding-right: 36rpx; } + +.px-37 { + padding-left: 37rpx; + padding-right: 37rpx; } + +.px-38 { + padding-left: 38rpx; + padding-right: 38rpx; } + +.px-39 { + padding-left: 39rpx; + padding-right: 39rpx; } + +.px-40 { + padding-left: 40rpx; + padding-right: 40rpx; } + +.px-41 { + padding-left: 41rpx; + padding-right: 41rpx; } + +.px-42 { + padding-left: 42rpx; + padding-right: 42rpx; } + +.px-43 { + padding-left: 43rpx; + padding-right: 43rpx; } + +.px-44 { + padding-left: 44rpx; + padding-right: 44rpx; } + +.px-45 { + padding-left: 45rpx; + padding-right: 45rpx; } + +.px-46 { + padding-left: 46rpx; + padding-right: 46rpx; } + +.px-47 { + padding-left: 47rpx; + padding-right: 47rpx; } + +.px-48 { + padding-left: 48rpx; + padding-right: 48rpx; } + +.px-49 { + padding-left: 49rpx; + padding-right: 49rpx; } + +.px-50 { + padding-left: 50rpx; + padding-right: 50rpx; } + +.px-n1 { + padding-left: 4rpx; + padding-right: 4rpx; } + +.px-n2 { + padding-left: 8rpx; + padding-right: 8rpx; } + +.px-n3 { + padding-left: 12rpx; + padding-right: 12rpx; } + +.px-n4 { + padding-left: 16rpx; + padding-right: 16rpx; } + +.px-n5 { + padding-left: 20rpx; + padding-right: 20rpx; } + +.px-n6 { + padding-left: 24rpx; + padding-right: 24rpx; } + +.px-n7 { + padding-left: 28rpx; + padding-right: 28rpx; } + +.px-n8 { + padding-left: 32rpx; + padding-right: 32rpx; } + +.px-n9 { + padding-left: 36rpx; + padding-right: 36rpx; } + +.px-n10 { + padding-left: 40rpx; + padding-right: 40rpx; } + +.px-n11 { + padding-left: 44rpx; + padding-right: 44rpx; } + +.px-n12 { + padding-left: 48rpx; + padding-right: 48rpx; } + +.px-n13 { + padding-left: 52rpx; + padding-right: 52rpx; } + +.px-n14 { + padding-left: 56rpx; + padding-right: 56rpx; } + +.px-n15 { + padding-left: 60rpx; + padding-right: 60rpx; } + +.px-n16 { + padding-left: 64rpx; + padding-right: 64rpx; } + +.px-n17 { + padding-left: 68rpx; + padding-right: 68rpx; } + +.px-n18 { + padding-left: 72rpx; + padding-right: 72rpx; } + +.px-n19 { + padding-left: 76rpx; + padding-right: 76rpx; } + +.px-n20 { + padding-left: 80rpx; + padding-right: 80rpx; } + +.px-n21 { + padding-left: 84rpx; + padding-right: 84rpx; } + +.px-n22 { + padding-left: 88rpx; + padding-right: 88rpx; } + +.px-n23 { + padding-left: 92rpx; + padding-right: 92rpx; } + +.px-n24 { + padding-left: 96rpx; + padding-right: 96rpx; } + +.px-n25 { + padding-left: 100rpx; + padding-right: 100rpx; } + +.py-0 { + padding-top: 0rpx; + padding-bottom: 0rpx; } + +.py-1 { + padding-top: 1rpx; + padding-bottom: 1rpx; } + +.py-2 { + padding-top: 2rpx; + padding-bottom: 2rpx; } + +.py-3 { + padding-top: 3rpx; + padding-bottom: 3rpx; } + +.py-4 { + padding-top: 4rpx; + padding-bottom: 4rpx; } + +.py-5 { + padding-top: 5rpx; + padding-bottom: 5rpx; } + +.py-6 { + padding-top: 6rpx; + padding-bottom: 6rpx; } + +.py-7 { + padding-top: 7rpx; + padding-bottom: 7rpx; } + +.py-8 { + padding-top: 8rpx; + padding-bottom: 8rpx; } + +.py-9 { + padding-top: 9rpx; + padding-bottom: 9rpx; } + +.py-10 { + padding-top: 10rpx; + padding-bottom: 10rpx; } + +.py-11 { + padding-top: 11rpx; + padding-bottom: 11rpx; } + +.py-12 { + padding-top: 12rpx; + padding-bottom: 12rpx; } + +.py-13 { + padding-top: 13rpx; + padding-bottom: 13rpx; } + +.py-14 { + padding-top: 14rpx; + padding-bottom: 14rpx; } + +.py-15 { + padding-top: 15rpx; + padding-bottom: 15rpx; } + +.py-16 { + padding-top: 16rpx; + padding-bottom: 16rpx; } + +.py-17 { + padding-top: 17rpx; + padding-bottom: 17rpx; } + +.py-18 { + padding-top: 18rpx; + padding-bottom: 18rpx; } + +.py-19 { + padding-top: 19rpx; + padding-bottom: 19rpx; } + +.py-20 { + padding-top: 20rpx; + padding-bottom: 20rpx; } + +.py-21 { + padding-top: 21rpx; + padding-bottom: 21rpx; } + +.py-22 { + padding-top: 22rpx; + padding-bottom: 22rpx; } + +.py-23 { + padding-top: 23rpx; + padding-bottom: 23rpx; } + +.py-24 { + padding-top: 24rpx; + padding-bottom: 24rpx; } + +.py-25 { + padding-top: 25rpx; + padding-bottom: 25rpx; } + +.py-26 { + padding-top: 26rpx; + padding-bottom: 26rpx; } + +.py-27 { + padding-top: 27rpx; + padding-bottom: 27rpx; } + +.py-28 { + padding-top: 28rpx; + padding-bottom: 28rpx; } + +.py-29 { + padding-top: 29rpx; + padding-bottom: 29rpx; } + +.py-30 { + padding-top: 30rpx; + padding-bottom: 30rpx; } + +.py-31 { + padding-top: 31rpx; + padding-bottom: 31rpx; } + +.py-32 { + padding-top: 32rpx; + padding-bottom: 32rpx; } + +.py-33 { + padding-top: 33rpx; + padding-bottom: 33rpx; } + +.py-34 { + padding-top: 34rpx; + padding-bottom: 34rpx; } + +.py-35 { + padding-top: 35rpx; + padding-bottom: 35rpx; } + +.py-36 { + padding-top: 36rpx; + padding-bottom: 36rpx; } + +.py-37 { + padding-top: 37rpx; + padding-bottom: 37rpx; } + +.py-38 { + padding-top: 38rpx; + padding-bottom: 38rpx; } + +.py-39 { + padding-top: 39rpx; + padding-bottom: 39rpx; } + +.py-40 { + padding-top: 40rpx; + padding-bottom: 40rpx; } + +.py-41 { + padding-top: 41rpx; + padding-bottom: 41rpx; } + +.py-42 { + padding-top: 42rpx; + padding-bottom: 42rpx; } + +.py-43 { + padding-top: 43rpx; + padding-bottom: 43rpx; } + +.py-44 { + padding-top: 44rpx; + padding-bottom: 44rpx; } + +.py-45 { + padding-top: 45rpx; + padding-bottom: 45rpx; } + +.py-46 { + padding-top: 46rpx; + padding-bottom: 46rpx; } + +.py-47 { + padding-top: 47rpx; + padding-bottom: 47rpx; } + +.py-48 { + padding-top: 48rpx; + padding-bottom: 48rpx; } + +.py-49 { + padding-top: 49rpx; + padding-bottom: 49rpx; } + +.py-50 { + padding-top: 50rpx; + padding-bottom: 50rpx; } + +.py-n1 { + padding-top: 4rpx; + padding-bottom: 4rpx; } + +.py-n2 { + padding-top: 8rpx; + padding-bottom: 8rpx; } + +.py-n3 { + padding-top: 12rpx; + padding-bottom: 12rpx; } + +.py-n4 { + padding-top: 16rpx; + padding-bottom: 16rpx; } + +.py-n5 { + padding-top: 20rpx; + padding-bottom: 20rpx; } + +.py-n6 { + padding-top: 24rpx; + padding-bottom: 24rpx; } + +.py-n7 { + padding-top: 28rpx; + padding-bottom: 28rpx; } + +.py-n8 { + padding-top: 32rpx; + padding-bottom: 32rpx; } + +.py-n9 { + padding-top: 36rpx; + padding-bottom: 36rpx; } + +.py-n10 { + padding-top: 40rpx; + padding-bottom: 40rpx; } + +.py-n11 { + padding-top: 44rpx; + padding-bottom: 44rpx; } + +.py-n12 { + padding-top: 48rpx; + padding-bottom: 48rpx; } + +.py-n13 { + padding-top: 52rpx; + padding-bottom: 52rpx; } + +.py-n14 { + padding-top: 56rpx; + padding-bottom: 56rpx; } + +.py-n15 { + padding-top: 60rpx; + padding-bottom: 60rpx; } + +.py-n16 { + padding-top: 64rpx; + padding-bottom: 64rpx; } + +.py-n17 { + padding-top: 68rpx; + padding-bottom: 68rpx; } + +.py-n18 { + padding-top: 72rpx; + padding-bottom: 72rpx; } + +.py-n19 { + padding-top: 76rpx; + padding-bottom: 76rpx; } + +.py-n20 { + padding-top: 80rpx; + padding-bottom: 80rpx; } + +.py-n21 { + padding-top: 84rpx; + padding-bottom: 84rpx; } + +.py-n22 { + padding-top: 88rpx; + padding-bottom: 88rpx; } + +.py-n23 { + padding-top: 92rpx; + padding-bottom: 92rpx; } + +.py-n24 { + padding-top: 96rpx; + padding-bottom: 96rpx; } + +.py-n25 { + padding-top: 100rpx; + padding-bottom: 100rpx; } + +.ma-0 { + margin: 0rpx; } + +.ma-1 { + margin: 1rpx; } + +.ma-2 { + margin: 2rpx; } + +.ma-3 { + margin: 3rpx; } + +.ma-4 { + margin: 4rpx; } + +.ma-5 { + margin: 5rpx; } + +.ma-6 { + margin: 6rpx; } + +.ma-7 { + margin: 7rpx; } + +.ma-8 { + margin: 8rpx; } + +.ma-9 { + margin: 9rpx; } + +.ma-10 { + margin: 10rpx; } + +.ma-11 { + margin: 11rpx; } + +.ma-12 { + margin: 12rpx; } + +.ma-13 { + margin: 13rpx; } + +.ma-14 { + margin: 14rpx; } + +.ma-15 { + margin: 15rpx; } + +.ma-16 { + margin: 16rpx; } + +.ma-17 { + margin: 17rpx; } + +.ma-18 { + margin: 18rpx; } + +.ma-19 { + margin: 19rpx; } + +.ma-20 { + margin: 20rpx; } + +.ma-21 { + margin: 21rpx; } + +.ma-22 { + margin: 22rpx; } + +.ma-23 { + margin: 23rpx; } + +.ma-24 { + margin: 24rpx; } + +.ma-25 { + margin: 25rpx; } + +.ma-26 { + margin: 26rpx; } + +.ma-27 { + margin: 27rpx; } + +.ma-28 { + margin: 28rpx; } + +.ma-29 { + margin: 29rpx; } + +.ma-30 { + margin: 30rpx; } + +.ma-31 { + margin: 31rpx; } + +.ma-32 { + margin: 32rpx; } + +.ma-33 { + margin: 33rpx; } + +.ma-34 { + margin: 34rpx; } + +.ma-35 { + margin: 35rpx; } + +.ma-36 { + margin: 36rpx; } + +.ma-37 { + margin: 37rpx; } + +.ma-38 { + margin: 38rpx; } + +.ma-39 { + margin: 39rpx; } + +.ma-40 { + margin: 40rpx; } + +.ma-41 { + margin: 41rpx; } + +.ma-42 { + margin: 42rpx; } + +.ma-43 { + margin: 43rpx; } + +.ma-44 { + margin: 44rpx; } + +.ma-45 { + margin: 45rpx; } + +.ma-46 { + margin: 46rpx; } + +.ma-47 { + margin: 47rpx; } + +.ma-48 { + margin: 48rpx; } + +.ma-49 { + margin: 49rpx; } + +.ma-50 { + margin: 50rpx; } + +.ma-n1 { + margin: 4rpx; } + +.ma-n2 { + margin: 8rpx; } + +.ma-n3 { + margin: 12rpx; } + +.ma-n4 { + margin: 16rpx; } + +.ma-n5 { + margin: 20rpx; } + +.ma-n6 { + margin: 24rpx; } + +.ma-n7 { + margin: 28rpx; } + +.ma-n8 { + margin: 32rpx; } + +.ma-n9 { + margin: 36rpx; } + +.ma-n10 { + margin: 40rpx; } + +.ma-n11 { + margin: 44rpx; } + +.ma-n12 { + margin: 48rpx; } + +.ma-n13 { + margin: 52rpx; } + +.ma-n14 { + margin: 56rpx; } + +.ma-n15 { + margin: 60rpx; } + +.ma-n16 { + margin: 64rpx; } + +.ma-n17 { + margin: 68rpx; } + +.ma-n18 { + margin: 72rpx; } + +.ma-n19 { + margin: 76rpx; } + +.ma-n20 { + margin: 80rpx; } + +.ma-n21 { + margin: 84rpx; } + +.ma-n22 { + margin: 88rpx; } + +.ma-n23 { + margin: 92rpx; } + +.ma-n24 { + margin: 96rpx; } + +.ma-n25 { + margin: 100rpx; } + +.mt-0 { + margin-top: 0rpx; } + +.mt--0 { + margin-top: -0rpx; } + +.mt-1 { + margin-top: 1rpx; } + +.mt--1 { + margin-top: -1rpx; } + +.mt-2 { + margin-top: 2rpx; } + +.mt--2 { + margin-top: -2rpx; } + +.mt-3 { + margin-top: 3rpx; } + +.mt--3 { + margin-top: -3rpx; } + +.mt-4 { + margin-top: 4rpx; } + +.mt--4 { + margin-top: -4rpx; } + +.mt-5 { + margin-top: 5rpx; } + +.mt--5 { + margin-top: -5rpx; } + +.mt-6 { + margin-top: 6rpx; } + +.mt--6 { + margin-top: -6rpx; } + +.mt-7 { + margin-top: 7rpx; } + +.mt--7 { + margin-top: -7rpx; } + +.mt-8 { + margin-top: 8rpx; } + +.mt--8 { + margin-top: -8rpx; } + +.mt-9 { + margin-top: 9rpx; } + +.mt--9 { + margin-top: -9rpx; } + +.mt-10 { + margin-top: 10rpx; } + +.mt--10 { + margin-top: -10rpx; } + +.mt-11 { + margin-top: 11rpx; } + +.mt--11 { + margin-top: -11rpx; } + +.mt-12 { + margin-top: 12rpx; } + +.mt--12 { + margin-top: -12rpx; } + +.mt-13 { + margin-top: 13rpx; } + +.mt--13 { + margin-top: -13rpx; } + +.mt-14 { + margin-top: 14rpx; } + +.mt--14 { + margin-top: -14rpx; } + +.mt-15 { + margin-top: 15rpx; } + +.mt--15 { + margin-top: -15rpx; } + +.mt-16 { + margin-top: 16rpx; } + +.mt--16 { + margin-top: -16rpx; } + +.mt-17 { + margin-top: 17rpx; } + +.mt--17 { + margin-top: -17rpx; } + +.mt-18 { + margin-top: 18rpx; } + +.mt--18 { + margin-top: -18rpx; } + +.mt-19 { + margin-top: 19rpx; } + +.mt--19 { + margin-top: -19rpx; } + +.mt-20 { + margin-top: 20rpx; } + +.mt--20 { + margin-top: -20rpx; } + +.mt-21 { + margin-top: 21rpx; } + +.mt--21 { + margin-top: -21rpx; } + +.mt-22 { + margin-top: 22rpx; } + +.mt--22 { + margin-top: -22rpx; } + +.mt-23 { + margin-top: 23rpx; } + +.mt--23 { + margin-top: -23rpx; } + +.mt-24 { + margin-top: 24rpx; } + +.mt--24 { + margin-top: -24rpx; } + +.mt-25 { + margin-top: 25rpx; } + +.mt--25 { + margin-top: -25rpx; } + +.mt-26 { + margin-top: 26rpx; } + +.mt--26 { + margin-top: -26rpx; } + +.mt-27 { + margin-top: 27rpx; } + +.mt--27 { + margin-top: -27rpx; } + +.mt-28 { + margin-top: 28rpx; } + +.mt--28 { + margin-top: -28rpx; } + +.mt-29 { + margin-top: 29rpx; } + +.mt--29 { + margin-top: -29rpx; } + +.mt-30 { + margin-top: 30rpx; } + +.mt--30 { + margin-top: -30rpx; } + +.mt-31 { + margin-top: 31rpx; } + +.mt--31 { + margin-top: -31rpx; } + +.mt-32 { + margin-top: 32rpx; } + +.mt--32 { + margin-top: -32rpx; } + +.mt-33 { + margin-top: 33rpx; } + +.mt--33 { + margin-top: -33rpx; } + +.mt-34 { + margin-top: 34rpx; } + +.mt--34 { + margin-top: -34rpx; } + +.mt-35 { + margin-top: 35rpx; } + +.mt--35 { + margin-top: -35rpx; } + +.mt-36 { + margin-top: 36rpx; } + +.mt--36 { + margin-top: -36rpx; } + +.mt-37 { + margin-top: 37rpx; } + +.mt--37 { + margin-top: -37rpx; } + +.mt-38 { + margin-top: 38rpx; } + +.mt--38 { + margin-top: -38rpx; } + +.mt-39 { + margin-top: 39rpx; } + +.mt--39 { + margin-top: -39rpx; } + +.mt-40 { + margin-top: 40rpx; } + +.mt--40 { + margin-top: -40rpx; } + +.mt-41 { + margin-top: 41rpx; } + +.mt--41 { + margin-top: -41rpx; } + +.mt-42 { + margin-top: 42rpx; } + +.mt--42 { + margin-top: -42rpx; } + +.mt-43 { + margin-top: 43rpx; } + +.mt--43 { + margin-top: -43rpx; } + +.mt-44 { + margin-top: 44rpx; } + +.mt--44 { + margin-top: -44rpx; } + +.mt-45 { + margin-top: 45rpx; } + +.mt--45 { + margin-top: -45rpx; } + +.mt-46 { + margin-top: 46rpx; } + +.mt--46 { + margin-top: -46rpx; } + +.mt-47 { + margin-top: 47rpx; } + +.mt--47 { + margin-top: -47rpx; } + +.mt-48 { + margin-top: 48rpx; } + +.mt--48 { + margin-top: -48rpx; } + +.mt-49 { + margin-top: 49rpx; } + +.mt--49 { + margin-top: -49rpx; } + +.mt-50 { + margin-top: 50rpx; } + +.mt--50 { + margin-top: -50rpx; } + +.mt-n1 { + margin-top: 4rpx; } + +.mt--n1 { + margin-top: -4rpx; } + +.mt-n2 { + margin-top: 8rpx; } + +.mt--n2 { + margin-top: -8rpx; } + +.mt-n3 { + margin-top: 12rpx; } + +.mt--n3 { + margin-top: -12rpx; } + +.mt-n4 { + margin-top: 16rpx; } + +.mt--n4 { + margin-top: -16rpx; } + +.mt-n5 { + margin-top: 20rpx; } + +.mt--n5 { + margin-top: -20rpx; } + +.mt-n6 { + margin-top: 24rpx; } + +.mt--n6 { + margin-top: -24rpx; } + +.mt-n7 { + margin-top: 28rpx; } + +.mt--n7 { + margin-top: -28rpx; } + +.mt-n8 { + margin-top: 32rpx; } + +.mt--n8 { + margin-top: -32rpx; } + +.mt-n9 { + margin-top: 36rpx; } + +.mt--n9 { + margin-top: -36rpx; } + +.mt-n10 { + margin-top: 40rpx; } + +.mt--n10 { + margin-top: -40rpx; } + +.mt-n11 { + margin-top: 44rpx; } + +.mt--n11 { + margin-top: -44rpx; } + +.mt-n12 { + margin-top: 48rpx; } + +.mt--n12 { + margin-top: -48rpx; } + +.mt-n13 { + margin-top: 52rpx; } + +.mt--n13 { + margin-top: -52rpx; } + +.mt-n14 { + margin-top: 56rpx; } + +.mt--n14 { + margin-top: -56rpx; } + +.mt-n15 { + margin-top: 60rpx; } + +.mt--n15 { + margin-top: -60rpx; } + +.mt-n16 { + margin-top: 64rpx; } + +.mt--n16 { + margin-top: -64rpx; } + +.mt-n17 { + margin-top: 68rpx; } + +.mt--n17 { + margin-top: -68rpx; } + +.mt-n18 { + margin-top: 72rpx; } + +.mt--n18 { + margin-top: -72rpx; } + +.mt-n19 { + margin-top: 76rpx; } + +.mt--n19 { + margin-top: -76rpx; } + +.mt-n20 { + margin-top: 80rpx; } + +.mt--n20 { + margin-top: -80rpx; } + +.mt-n21 { + margin-top: 84rpx; } + +.mt--n21 { + margin-top: -84rpx; } + +.mt-n22 { + margin-top: 88rpx; } + +.mt--n22 { + margin-top: -88rpx; } + +.mt-n23 { + margin-top: 92rpx; } + +.mt--n23 { + margin-top: -92rpx; } + +.mt-n24 { + margin-top: 96rpx; } + +.mt--n24 { + margin-top: -96rpx; } + +.mt-n25 { + margin-top: 100rpx; } + +.mt--n25 { + margin-top: -100rpx; } + +.mr-0 { + margin-right: 0rpx; } + +.mr--0 { + margin-right: -0rpx; } + +.mr-1 { + margin-right: 1rpx; } + +.mr--1 { + margin-right: -1rpx; } + +.mr-2 { + margin-right: 2rpx; } + +.mr--2 { + margin-right: -2rpx; } + +.mr-3 { + margin-right: 3rpx; } + +.mr--3 { + margin-right: -3rpx; } + +.mr-4 { + margin-right: 4rpx; } + +.mr--4 { + margin-right: -4rpx; } + +.mr-5 { + margin-right: 5rpx; } + +.mr--5 { + margin-right: -5rpx; } + +.mr-6 { + margin-right: 6rpx; } + +.mr--6 { + margin-right: -6rpx; } + +.mr-7 { + margin-right: 7rpx; } + +.mr--7 { + margin-right: -7rpx; } + +.mr-8 { + margin-right: 8rpx; } + +.mr--8 { + margin-right: -8rpx; } + +.mr-9 { + margin-right: 9rpx; } + +.mr--9 { + margin-right: -9rpx; } + +.mr-10 { + margin-right: 10rpx; } + +.mr--10 { + margin-right: -10rpx; } + +.mr-11 { + margin-right: 11rpx; } + +.mr--11 { + margin-right: -11rpx; } + +.mr-12 { + margin-right: 12rpx; } + +.mr--12 { + margin-right: -12rpx; } + +.mr-13 { + margin-right: 13rpx; } + +.mr--13 { + margin-right: -13rpx; } + +.mr-14 { + margin-right: 14rpx; } + +.mr--14 { + margin-right: -14rpx; } + +.mr-15 { + margin-right: 15rpx; } + +.mr--15 { + margin-right: -15rpx; } + +.mr-16 { + margin-right: 16rpx; } + +.mr--16 { + margin-right: -16rpx; } + +.mr-17 { + margin-right: 17rpx; } + +.mr--17 { + margin-right: -17rpx; } + +.mr-18 { + margin-right: 18rpx; } + +.mr--18 { + margin-right: -18rpx; } + +.mr-19 { + margin-right: 19rpx; } + +.mr--19 { + margin-right: -19rpx; } + +.mr-20 { + margin-right: 20rpx; } + +.mr--20 { + margin-right: -20rpx; } + +.mr-21 { + margin-right: 21rpx; } + +.mr--21 { + margin-right: -21rpx; } + +.mr-22 { + margin-right: 22rpx; } + +.mr--22 { + margin-right: -22rpx; } + +.mr-23 { + margin-right: 23rpx; } + +.mr--23 { + margin-right: -23rpx; } + +.mr-24 { + margin-right: 24rpx; } + +.mr--24 { + margin-right: -24rpx; } + +.mr-25 { + margin-right: 25rpx; } + +.mr--25 { + margin-right: -25rpx; } + +.mr-26 { + margin-right: 26rpx; } + +.mr--26 { + margin-right: -26rpx; } + +.mr-27 { + margin-right: 27rpx; } + +.mr--27 { + margin-right: -27rpx; } + +.mr-28 { + margin-right: 28rpx; } + +.mr--28 { + margin-right: -28rpx; } + +.mr-29 { + margin-right: 29rpx; } + +.mr--29 { + margin-right: -29rpx; } + +.mr-30 { + margin-right: 30rpx; } + +.mr--30 { + margin-right: -30rpx; } + +.mr-31 { + margin-right: 31rpx; } + +.mr--31 { + margin-right: -31rpx; } + +.mr-32 { + margin-right: 32rpx; } + +.mr--32 { + margin-right: -32rpx; } + +.mr-33 { + margin-right: 33rpx; } + +.mr--33 { + margin-right: -33rpx; } + +.mr-34 { + margin-right: 34rpx; } + +.mr--34 { + margin-right: -34rpx; } + +.mr-35 { + margin-right: 35rpx; } + +.mr--35 { + margin-right: -35rpx; } + +.mr-36 { + margin-right: 36rpx; } + +.mr--36 { + margin-right: -36rpx; } + +.mr-37 { + margin-right: 37rpx; } + +.mr--37 { + margin-right: -37rpx; } + +.mr-38 { + margin-right: 38rpx; } + +.mr--38 { + margin-right: -38rpx; } + +.mr-39 { + margin-right: 39rpx; } + +.mr--39 { + margin-right: -39rpx; } + +.mr-40 { + margin-right: 40rpx; } + +.mr--40 { + margin-right: -40rpx; } + +.mr-41 { + margin-right: 41rpx; } + +.mr--41 { + margin-right: -41rpx; } + +.mr-42 { + margin-right: 42rpx; } + +.mr--42 { + margin-right: -42rpx; } + +.mr-43 { + margin-right: 43rpx; } + +.mr--43 { + margin-right: -43rpx; } + +.mr-44 { + margin-right: 44rpx; } + +.mr--44 { + margin-right: -44rpx; } + +.mr-45 { + margin-right: 45rpx; } + +.mr--45 { + margin-right: -45rpx; } + +.mr-46 { + margin-right: 46rpx; } + +.mr--46 { + margin-right: -46rpx; } + +.mr-47 { + margin-right: 47rpx; } + +.mr--47 { + margin-right: -47rpx; } + +.mr-48 { + margin-right: 48rpx; } + +.mr--48 { + margin-right: -48rpx; } + +.mr-49 { + margin-right: 49rpx; } + +.mr--49 { + margin-right: -49rpx; } + +.mr-50 { + margin-right: 50rpx; } + +.mr--50 { + margin-right: -50rpx; } + +.mr-n1 { + margin-right: 4rpx; } + +.mr--n1 { + margin-right: -4rpx; } + +.mr-n2 { + margin-right: 8rpx; } + +.mr--n2 { + margin-right: -8rpx; } + +.mr-n3 { + margin-right: 12rpx; } + +.mr--n3 { + margin-right: -12rpx; } + +.mr-n4 { + margin-right: 16rpx; } + +.mr--n4 { + margin-right: -16rpx; } + +.mr-n5 { + margin-right: 20rpx; } + +.mr--n5 { + margin-right: -20rpx; } + +.mr-n6 { + margin-right: 24rpx; } + +.mr--n6 { + margin-right: -24rpx; } + +.mr-n7 { + margin-right: 28rpx; } + +.mr--n7 { + margin-right: -28rpx; } + +.mr-n8 { + margin-right: 32rpx; } + +.mr--n8 { + margin-right: -32rpx; } + +.mr-n9 { + margin-right: 36rpx; } + +.mr--n9 { + margin-right: -36rpx; } + +.mr-n10 { + margin-right: 40rpx; } + +.mr--n10 { + margin-right: -40rpx; } + +.mr-n11 { + margin-right: 44rpx; } + +.mr--n11 { + margin-right: -44rpx; } + +.mr-n12 { + margin-right: 48rpx; } + +.mr--n12 { + margin-right: -48rpx; } + +.mr-n13 { + margin-right: 52rpx; } + +.mr--n13 { + margin-right: -52rpx; } + +.mr-n14 { + margin-right: 56rpx; } + +.mr--n14 { + margin-right: -56rpx; } + +.mr-n15 { + margin-right: 60rpx; } + +.mr--n15 { + margin-right: -60rpx; } + +.mr-n16 { + margin-right: 64rpx; } + +.mr--n16 { + margin-right: -64rpx; } + +.mr-n17 { + margin-right: 68rpx; } + +.mr--n17 { + margin-right: -68rpx; } + +.mr-n18 { + margin-right: 72rpx; } + +.mr--n18 { + margin-right: -72rpx; } + +.mr-n19 { + margin-right: 76rpx; } + +.mr--n19 { + margin-right: -76rpx; } + +.mr-n20 { + margin-right: 80rpx; } + +.mr--n20 { + margin-right: -80rpx; } + +.mr-n21 { + margin-right: 84rpx; } + +.mr--n21 { + margin-right: -84rpx; } + +.mr-n22 { + margin-right: 88rpx; } + +.mr--n22 { + margin-right: -88rpx; } + +.mr-n23 { + margin-right: 92rpx; } + +.mr--n23 { + margin-right: -92rpx; } + +.mr-n24 { + margin-right: 96rpx; } + +.mr--n24 { + margin-right: -96rpx; } + +.mr-n25 { + margin-right: 100rpx; } + +.mr--n25 { + margin-right: -100rpx; } + +.mb-0 { + margin-bottom: 0rpx; } + +.mb--0 { + margin-bottom: -0rpx; } + +.mb-1 { + margin-bottom: 1rpx; } + +.mb--1 { + margin-bottom: -1rpx; } + +.mb-2 { + margin-bottom: 2rpx; } + +.mb--2 { + margin-bottom: -2rpx; } + +.mb-3 { + margin-bottom: 3rpx; } + +.mb--3 { + margin-bottom: -3rpx; } + +.mb-4 { + margin-bottom: 4rpx; } + +.mb--4 { + margin-bottom: -4rpx; } + +.mb-5 { + margin-bottom: 5rpx; } + +.mb--5 { + margin-bottom: -5rpx; } + +.mb-6 { + margin-bottom: 6rpx; } + +.mb--6 { + margin-bottom: -6rpx; } + +.mb-7 { + margin-bottom: 7rpx; } + +.mb--7 { + margin-bottom: -7rpx; } + +.mb-8 { + margin-bottom: 8rpx; } + +.mb--8 { + margin-bottom: -8rpx; } + +.mb-9 { + margin-bottom: 9rpx; } + +.mb--9 { + margin-bottom: -9rpx; } + +.mb-10 { + margin-bottom: 10rpx; } + +.mb--10 { + margin-bottom: -10rpx; } + +.mb-11 { + margin-bottom: 11rpx; } + +.mb--11 { + margin-bottom: -11rpx; } + +.mb-12 { + margin-bottom: 12rpx; } + +.mb--12 { + margin-bottom: -12rpx; } + +.mb-13 { + margin-bottom: 13rpx; } + +.mb--13 { + margin-bottom: -13rpx; } + +.mb-14 { + margin-bottom: 14rpx; } + +.mb--14 { + margin-bottom: -14rpx; } + +.mb-15 { + margin-bottom: 15rpx; } + +.mb--15 { + margin-bottom: -15rpx; } + +.mb-16 { + margin-bottom: 16rpx; } + +.mb--16 { + margin-bottom: -16rpx; } + +.mb-17 { + margin-bottom: 17rpx; } + +.mb--17 { + margin-bottom: -17rpx; } + +.mb-18 { + margin-bottom: 18rpx; } + +.mb--18 { + margin-bottom: -18rpx; } + +.mb-19 { + margin-bottom: 19rpx; } + +.mb--19 { + margin-bottom: -19rpx; } + +.mb-20 { + margin-bottom: 20rpx; } + +.mb--20 { + margin-bottom: -20rpx; } + +.mb-21 { + margin-bottom: 21rpx; } + +.mb--21 { + margin-bottom: -21rpx; } + +.mb-22 { + margin-bottom: 22rpx; } + +.mb--22 { + margin-bottom: -22rpx; } + +.mb-23 { + margin-bottom: 23rpx; } + +.mb--23 { + margin-bottom: -23rpx; } + +.mb-24 { + margin-bottom: 24rpx; } + +.mb--24 { + margin-bottom: -24rpx; } + +.mb-25 { + margin-bottom: 25rpx; } + +.mb--25 { + margin-bottom: -25rpx; } + +.mb-26 { + margin-bottom: 26rpx; } + +.mb--26 { + margin-bottom: -26rpx; } + +.mb-27 { + margin-bottom: 27rpx; } + +.mb--27 { + margin-bottom: -27rpx; } + +.mb-28 { + margin-bottom: 28rpx; } + +.mb--28 { + margin-bottom: -28rpx; } + +.mb-29 { + margin-bottom: 29rpx; } + +.mb--29 { + margin-bottom: -29rpx; } + +.mb-30 { + margin-bottom: 30rpx; } + +.mb--30 { + margin-bottom: -30rpx; } + +.mb-31 { + margin-bottom: 31rpx; } + +.mb--31 { + margin-bottom: -31rpx; } + +.mb-32 { + margin-bottom: 32rpx; } + +.mb--32 { + margin-bottom: -32rpx; } + +.mb-33 { + margin-bottom: 33rpx; } + +.mb--33 { + margin-bottom: -33rpx; } + +.mb-34 { + margin-bottom: 34rpx; } + +.mb--34 { + margin-bottom: -34rpx; } + +.mb-35 { + margin-bottom: 35rpx; } + +.mb--35 { + margin-bottom: -35rpx; } + +.mb-36 { + margin-bottom: 36rpx; } + +.mb--36 { + margin-bottom: -36rpx; } + +.mb-37 { + margin-bottom: 37rpx; } + +.mb--37 { + margin-bottom: -37rpx; } + +.mb-38 { + margin-bottom: 38rpx; } + +.mb--38 { + margin-bottom: -38rpx; } + +.mb-39 { + margin-bottom: 39rpx; } + +.mb--39 { + margin-bottom: -39rpx; } + +.mb-40 { + margin-bottom: 40rpx; } + +.mb--40 { + margin-bottom: -40rpx; } + +.mb-41 { + margin-bottom: 41rpx; } + +.mb--41 { + margin-bottom: -41rpx; } + +.mb-42 { + margin-bottom: 42rpx; } + +.mb--42 { + margin-bottom: -42rpx; } + +.mb-43 { + margin-bottom: 43rpx; } + +.mb--43 { + margin-bottom: -43rpx; } + +.mb-44 { + margin-bottom: 44rpx; } + +.mb--44 { + margin-bottom: -44rpx; } + +.mb-45 { + margin-bottom: 45rpx; } + +.mb--45 { + margin-bottom: -45rpx; } + +.mb-46 { + margin-bottom: 46rpx; } + +.mb--46 { + margin-bottom: -46rpx; } + +.mb-47 { + margin-bottom: 47rpx; } + +.mb--47 { + margin-bottom: -47rpx; } + +.mb-48 { + margin-bottom: 48rpx; } + +.mb--48 { + margin-bottom: -48rpx; } + +.mb-49 { + margin-bottom: 49rpx; } + +.mb--49 { + margin-bottom: -49rpx; } + +.mb-50 { + margin-bottom: 50rpx; } + +.mb--50 { + margin-bottom: -50rpx; } + +.mb-n1 { + margin-bottom: 4rpx; } + +.mb--n1 { + margin-bottom: -4rpx; } + +.mb-n2 { + margin-bottom: 8rpx; } + +.mb--n2 { + margin-bottom: -8rpx; } + +.mb-n3 { + margin-bottom: 12rpx; } + +.mb--n3 { + margin-bottom: -12rpx; } + +.mb-n4 { + margin-bottom: 16rpx; } + +.mb--n4 { + margin-bottom: -16rpx; } + +.mb-n5 { + margin-bottom: 20rpx; } + +.mb--n5 { + margin-bottom: -20rpx; } + +.mb-n6 { + margin-bottom: 24rpx; } + +.mb--n6 { + margin-bottom: -24rpx; } + +.mb-n7 { + margin-bottom: 28rpx; } + +.mb--n7 { + margin-bottom: -28rpx; } + +.mb-n8 { + margin-bottom: 32rpx; } + +.mb--n8 { + margin-bottom: -32rpx; } + +.mb-n9 { + margin-bottom: 36rpx; } + +.mb--n9 { + margin-bottom: -36rpx; } + +.mb-n10 { + margin-bottom: 40rpx; } + +.mb--n10 { + margin-bottom: -40rpx; } + +.mb-n11 { + margin-bottom: 44rpx; } + +.mb--n11 { + margin-bottom: -44rpx; } + +.mb-n12 { + margin-bottom: 48rpx; } + +.mb--n12 { + margin-bottom: -48rpx; } + +.mb-n13 { + margin-bottom: 52rpx; } + +.mb--n13 { + margin-bottom: -52rpx; } + +.mb-n14 { + margin-bottom: 56rpx; } + +.mb--n14 { + margin-bottom: -56rpx; } + +.mb-n15 { + margin-bottom: 60rpx; } + +.mb--n15 { + margin-bottom: -60rpx; } + +.mb-n16 { + margin-bottom: 64rpx; } + +.mb--n16 { + margin-bottom: -64rpx; } + +.mb-n17 { + margin-bottom: 68rpx; } + +.mb--n17 { + margin-bottom: -68rpx; } + +.mb-n18 { + margin-bottom: 72rpx; } + +.mb--n18 { + margin-bottom: -72rpx; } + +.mb-n19 { + margin-bottom: 76rpx; } + +.mb--n19 { + margin-bottom: -76rpx; } + +.mb-n20 { + margin-bottom: 80rpx; } + +.mb--n20 { + margin-bottom: -80rpx; } + +.mb-n21 { + margin-bottom: 84rpx; } + +.mb--n21 { + margin-bottom: -84rpx; } + +.mb-n22 { + margin-bottom: 88rpx; } + +.mb--n22 { + margin-bottom: -88rpx; } + +.mb-n23 { + margin-bottom: 92rpx; } + +.mb--n23 { + margin-bottom: -92rpx; } + +.mb-n24 { + margin-bottom: 96rpx; } + +.mb--n24 { + margin-bottom: -96rpx; } + +.mb-n25 { + margin-bottom: 100rpx; } + +.mb--n25 { + margin-bottom: -100rpx; } + +.ml-0 { + margin-left: 0rpx; } + +.ml--0 { + margin-left: -0rpx; } + +.ml-1 { + margin-left: 1rpx; } + +.ml--1 { + margin-left: -1rpx; } + +.ml-2 { + margin-left: 2rpx; } + +.ml--2 { + margin-left: -2rpx; } + +.ml-3 { + margin-left: 3rpx; } + +.ml--3 { + margin-left: -3rpx; } + +.ml-4 { + margin-left: 4rpx; } + +.ml--4 { + margin-left: -4rpx; } + +.ml-5 { + margin-left: 5rpx; } + +.ml--5 { + margin-left: -5rpx; } + +.ml-6 { + margin-left: 6rpx; } + +.ml--6 { + margin-left: -6rpx; } + +.ml-7 { + margin-left: 7rpx; } + +.ml--7 { + margin-left: -7rpx; } + +.ml-8 { + margin-left: 8rpx; } + +.ml--8 { + margin-left: -8rpx; } + +.ml-9 { + margin-left: 9rpx; } + +.ml--9 { + margin-left: -9rpx; } + +.ml-10 { + margin-left: 10rpx; } + +.ml--10 { + margin-left: -10rpx; } + +.ml-11 { + margin-left: 11rpx; } + +.ml--11 { + margin-left: -11rpx; } + +.ml-12 { + margin-left: 12rpx; } + +.ml--12 { + margin-left: -12rpx; } + +.ml-13 { + margin-left: 13rpx; } + +.ml--13 { + margin-left: -13rpx; } + +.ml-14 { + margin-left: 14rpx; } + +.ml--14 { + margin-left: -14rpx; } + +.ml-15 { + margin-left: 15rpx; } + +.ml--15 { + margin-left: -15rpx; } + +.ml-16 { + margin-left: 16rpx; } + +.ml--16 { + margin-left: -16rpx; } + +.ml-17 { + margin-left: 17rpx; } + +.ml--17 { + margin-left: -17rpx; } + +.ml-18 { + margin-left: 18rpx; } + +.ml--18 { + margin-left: -18rpx; } + +.ml-19 { + margin-left: 19rpx; } + +.ml--19 { + margin-left: -19rpx; } + +.ml-20 { + margin-left: 20rpx; } + +.ml--20 { + margin-left: -20rpx; } + +.ml-21 { + margin-left: 21rpx; } + +.ml--21 { + margin-left: -21rpx; } + +.ml-22 { + margin-left: 22rpx; } + +.ml--22 { + margin-left: -22rpx; } + +.ml-23 { + margin-left: 23rpx; } + +.ml--23 { + margin-left: -23rpx; } + +.ml-24 { + margin-left: 24rpx; } + +.ml--24 { + margin-left: -24rpx; } + +.ml-25 { + margin-left: 25rpx; } + +.ml--25 { + margin-left: -25rpx; } + +.ml-26 { + margin-left: 26rpx; } + +.ml--26 { + margin-left: -26rpx; } + +.ml-27 { + margin-left: 27rpx; } + +.ml--27 { + margin-left: -27rpx; } + +.ml-28 { + margin-left: 28rpx; } + +.ml--28 { + margin-left: -28rpx; } + +.ml-29 { + margin-left: 29rpx; } + +.ml--29 { + margin-left: -29rpx; } + +.ml-30 { + margin-left: 30rpx; } + +.ml--30 { + margin-left: -30rpx; } + +.ml-31 { + margin-left: 31rpx; } + +.ml--31 { + margin-left: -31rpx; } + +.ml-32 { + margin-left: 32rpx; } + +.ml--32 { + margin-left: -32rpx; } + +.ml-33 { + margin-left: 33rpx; } + +.ml--33 { + margin-left: -33rpx; } + +.ml-34 { + margin-left: 34rpx; } + +.ml--34 { + margin-left: -34rpx; } + +.ml-35 { + margin-left: 35rpx; } + +.ml--35 { + margin-left: -35rpx; } + +.ml-36 { + margin-left: 36rpx; } + +.ml--36 { + margin-left: -36rpx; } + +.ml-37 { + margin-left: 37rpx; } + +.ml--37 { + margin-left: -37rpx; } + +.ml-38 { + margin-left: 38rpx; } + +.ml--38 { + margin-left: -38rpx; } + +.ml-39 { + margin-left: 39rpx; } + +.ml--39 { + margin-left: -39rpx; } + +.ml-40 { + margin-left: 40rpx; } + +.ml--40 { + margin-left: -40rpx; } + +.ml-41 { + margin-left: 41rpx; } + +.ml--41 { + margin-left: -41rpx; } + +.ml-42 { + margin-left: 42rpx; } + +.ml--42 { + margin-left: -42rpx; } + +.ml-43 { + margin-left: 43rpx; } + +.ml--43 { + margin-left: -43rpx; } + +.ml-44 { + margin-left: 44rpx; } + +.ml--44 { + margin-left: -44rpx; } + +.ml-45 { + margin-left: 45rpx; } + +.ml--45 { + margin-left: -45rpx; } + +.ml-46 { + margin-left: 46rpx; } + +.ml--46 { + margin-left: -46rpx; } + +.ml-47 { + margin-left: 47rpx; } + +.ml--47 { + margin-left: -47rpx; } + +.ml-48 { + margin-left: 48rpx; } + +.ml--48 { + margin-left: -48rpx; } + +.ml-49 { + margin-left: 49rpx; } + +.ml--49 { + margin-left: -49rpx; } + +.ml-50 { + margin-left: 50rpx; } + +.ml--50 { + margin-left: -50rpx; } + +.ml-n1 { + margin-left: 4rpx; } + +.ml--n1 { + margin-left: -4rpx; } + +.ml-n2 { + margin-left: 8rpx; } + +.ml--n2 { + margin-left: -8rpx; } + +.ml-n3 { + margin-left: 12rpx; } + +.ml--n3 { + margin-left: -12rpx; } + +.ml-n4 { + margin-left: 16rpx; } + +.ml--n4 { + margin-left: -16rpx; } + +.ml-n5 { + margin-left: 20rpx; } + +.ml--n5 { + margin-left: -20rpx; } + +.ml-n6 { + margin-left: 24rpx; } + +.ml--n6 { + margin-left: -24rpx; } + +.ml-n7 { + margin-left: 28rpx; } + +.ml--n7 { + margin-left: -28rpx; } + +.ml-n8 { + margin-left: 32rpx; } + +.ml--n8 { + margin-left: -32rpx; } + +.ml-n9 { + margin-left: 36rpx; } + +.ml--n9 { + margin-left: -36rpx; } + +.ml-n10 { + margin-left: 40rpx; } + +.ml--n10 { + margin-left: -40rpx; } + +.ml-n11 { + margin-left: 44rpx; } + +.ml--n11 { + margin-left: -44rpx; } + +.ml-n12 { + margin-left: 48rpx; } + +.ml--n12 { + margin-left: -48rpx; } + +.ml-n13 { + margin-left: 52rpx; } + +.ml--n13 { + margin-left: -52rpx; } + +.ml-n14 { + margin-left: 56rpx; } + +.ml--n14 { + margin-left: -56rpx; } + +.ml-n15 { + margin-left: 60rpx; } + +.ml--n15 { + margin-left: -60rpx; } + +.ml-n16 { + margin-left: 64rpx; } + +.ml--n16 { + margin-left: -64rpx; } + +.ml-n17 { + margin-left: 68rpx; } + +.ml--n17 { + margin-left: -68rpx; } + +.ml-n18 { + margin-left: 72rpx; } + +.ml--n18 { + margin-left: -72rpx; } + +.ml-n19 { + margin-left: 76rpx; } + +.ml--n19 { + margin-left: -76rpx; } + +.ml-n20 { + margin-left: 80rpx; } + +.ml--n20 { + margin-left: -80rpx; } + +.ml-n21 { + margin-left: 84rpx; } + +.ml--n21 { + margin-left: -84rpx; } + +.ml-n22 { + margin-left: 88rpx; } + +.ml--n22 { + margin-left: -88rpx; } + +.ml-n23 { + margin-left: 92rpx; } + +.ml--n23 { + margin-left: -92rpx; } + +.ml-n24 { + margin-left: 96rpx; } + +.ml--n24 { + margin-left: -96rpx; } + +.ml-n25 { + margin-left: 100rpx; } + +.ml--n25 { + margin-left: -100rpx; } + +.mx-0 { + margin-left: 0rpx; + margin-right: 0rpx; } + +.mx-1 { + margin-left: 1rpx; + margin-right: 1rpx; } + +.mx-2 { + margin-left: 2rpx; + margin-right: 2rpx; } + +.mx-3 { + margin-left: 3rpx; + margin-right: 3rpx; } + +.mx-4 { + margin-left: 4rpx; + margin-right: 4rpx; } + +.mx-5 { + margin-left: 5rpx; + margin-right: 5rpx; } + +.mx-6 { + margin-left: 6rpx; + margin-right: 6rpx; } + +.mx-7 { + margin-left: 7rpx; + margin-right: 7rpx; } + +.mx-8 { + margin-left: 8rpx; + margin-right: 8rpx; } + +.mx-9 { + margin-left: 9rpx; + margin-right: 9rpx; } + +.mx-10 { + margin-left: 10rpx; + margin-right: 10rpx; } + +.mx-11 { + margin-left: 11rpx; + margin-right: 11rpx; } + +.mx-12 { + margin-left: 12rpx; + margin-right: 12rpx; } + +.mx-13 { + margin-left: 13rpx; + margin-right: 13rpx; } + +.mx-14 { + margin-left: 14rpx; + margin-right: 14rpx; } + +.mx-15 { + margin-left: 15rpx; + margin-right: 15rpx; } + +.mx-16 { + margin-left: 16rpx; + margin-right: 16rpx; } + +.mx-17 { + margin-left: 17rpx; + margin-right: 17rpx; } + +.mx-18 { + margin-left: 18rpx; + margin-right: 18rpx; } + +.mx-19 { + margin-left: 19rpx; + margin-right: 19rpx; } + +.mx-20 { + margin-left: 20rpx; + margin-right: 20rpx; } + +.mx-21 { + margin-left: 21rpx; + margin-right: 21rpx; } + +.mx-22 { + margin-left: 22rpx; + margin-right: 22rpx; } + +.mx-23 { + margin-left: 23rpx; + margin-right: 23rpx; } + +.mx-24 { + margin-left: 24rpx; + margin-right: 24rpx; } + +.mx-25 { + margin-left: 25rpx; + margin-right: 25rpx; } + +.mx-26 { + margin-left: 26rpx; + margin-right: 26rpx; } + +.mx-27 { + margin-left: 27rpx; + margin-right: 27rpx; } + +.mx-28 { + margin-left: 28rpx; + margin-right: 28rpx; } + +.mx-29 { + margin-left: 29rpx; + margin-right: 29rpx; } + +.mx-30 { + margin-left: 30rpx; + margin-right: 30rpx; } + +.mx-31 { + margin-left: 31rpx; + margin-right: 31rpx; } + +.mx-32 { + margin-left: 32rpx; + margin-right: 32rpx; } + +.mx-33 { + margin-left: 33rpx; + margin-right: 33rpx; } + +.mx-34 { + margin-left: 34rpx; + margin-right: 34rpx; } + +.mx-35 { + margin-left: 35rpx; + margin-right: 35rpx; } + +.mx-36 { + margin-left: 36rpx; + margin-right: 36rpx; } + +.mx-37 { + margin-left: 37rpx; + margin-right: 37rpx; } + +.mx-38 { + margin-left: 38rpx; + margin-right: 38rpx; } + +.mx-39 { + margin-left: 39rpx; + margin-right: 39rpx; } + +.mx-40 { + margin-left: 40rpx; + margin-right: 40rpx; } + +.mx-41 { + margin-left: 41rpx; + margin-right: 41rpx; } + +.mx-42 { + margin-left: 42rpx; + margin-right: 42rpx; } + +.mx-43 { + margin-left: 43rpx; + margin-right: 43rpx; } + +.mx-44 { + margin-left: 44rpx; + margin-right: 44rpx; } + +.mx-45 { + margin-left: 45rpx; + margin-right: 45rpx; } + +.mx-46 { + margin-left: 46rpx; + margin-right: 46rpx; } + +.mx-47 { + margin-left: 47rpx; + margin-right: 47rpx; } + +.mx-48 { + margin-left: 48rpx; + margin-right: 48rpx; } + +.mx-49 { + margin-left: 49rpx; + margin-right: 49rpx; } + +.mx-50 { + margin-left: 50rpx; + margin-right: 50rpx; } + +.mx-n1 { + margin-left: 4rpx; + margin-right: 4rpx; } + +.mx-n2 { + margin-left: 8rpx; + margin-right: 8rpx; } + +.mx-n3 { + margin-left: 12rpx; + margin-right: 12rpx; } + +.mx-n4 { + margin-left: 16rpx; + margin-right: 16rpx; } + +.mx-n5 { + margin-left: 20rpx; + margin-right: 20rpx; } + +.mx-n6 { + margin-left: 24rpx; + margin-right: 24rpx; } + +.mx-n7 { + margin-left: 28rpx; + margin-right: 28rpx; } + +.mx-n8 { + margin-left: 32rpx; + margin-right: 32rpx; } + +.mx-n9 { + margin-left: 36rpx; + margin-right: 36rpx; } + +.mx-n10 { + margin-left: 40rpx; + margin-right: 40rpx; } + +.mx-n11 { + margin-left: 44rpx; + margin-right: 44rpx; } + +.mx-n12 { + margin-left: 48rpx; + margin-right: 48rpx; } + +.mx-n13 { + margin-left: 52rpx; + margin-right: 52rpx; } + +.mx-n14 { + margin-left: 56rpx; + margin-right: 56rpx; } + +.mx-n15 { + margin-left: 60rpx; + margin-right: 60rpx; } + +.mx-n16 { + margin-left: 64rpx; + margin-right: 64rpx; } + +.mx-n17 { + margin-left: 68rpx; + margin-right: 68rpx; } + +.mx-n18 { + margin-left: 72rpx; + margin-right: 72rpx; } + +.mx-n19 { + margin-left: 76rpx; + margin-right: 76rpx; } + +.mx-n20 { + margin-left: 80rpx; + margin-right: 80rpx; } + +.mx-n21 { + margin-left: 84rpx; + margin-right: 84rpx; } + +.mx-n22 { + margin-left: 88rpx; + margin-right: 88rpx; } + +.mx-n23 { + margin-left: 92rpx; + margin-right: 92rpx; } + +.mx-n24 { + margin-left: 96rpx; + margin-right: 96rpx; } + +.mx-n25 { + margin-left: 100rpx; + margin-right: 100rpx; } + +.my-0 { + margin-top: 0rpx; + margin-bottom: 0rpx; } + +.my-1 { + margin-top: 1rpx; + margin-bottom: 1rpx; } + +.my-2 { + margin-top: 2rpx; + margin-bottom: 2rpx; } + +.my-3 { + margin-top: 3rpx; + margin-bottom: 3rpx; } + +.my-4 { + margin-top: 4rpx; + margin-bottom: 4rpx; } + +.my-5 { + margin-top: 5rpx; + margin-bottom: 5rpx; } + +.my-6 { + margin-top: 6rpx; + margin-bottom: 6rpx; } + +.my-7 { + margin-top: 7rpx; + margin-bottom: 7rpx; } + +.my-8 { + margin-top: 8rpx; + margin-bottom: 8rpx; } + +.my-9 { + margin-top: 9rpx; + margin-bottom: 9rpx; } + +.my-10 { + margin-top: 10rpx; + margin-bottom: 10rpx; } + +.my-11 { + margin-top: 11rpx; + margin-bottom: 11rpx; } + +.my-12 { + margin-top: 12rpx; + margin-bottom: 12rpx; } + +.my-13 { + margin-top: 13rpx; + margin-bottom: 13rpx; } + +.my-14 { + margin-top: 14rpx; + margin-bottom: 14rpx; } + +.my-15 { + margin-top: 15rpx; + margin-bottom: 15rpx; } + +.my-16 { + margin-top: 16rpx; + margin-bottom: 16rpx; } + +.my-17 { + margin-top: 17rpx; + margin-bottom: 17rpx; } + +.my-18 { + margin-top: 18rpx; + margin-bottom: 18rpx; } + +.my-19 { + margin-top: 19rpx; + margin-bottom: 19rpx; } + +.my-20 { + margin-top: 20rpx; + margin-bottom: 20rpx; } + +.my-21 { + margin-top: 21rpx; + margin-bottom: 21rpx; } + +.my-22 { + margin-top: 22rpx; + margin-bottom: 22rpx; } + +.my-23 { + margin-top: 23rpx; + margin-bottom: 23rpx; } + +.my-24 { + margin-top: 24rpx; + margin-bottom: 24rpx; } + +.my-25 { + margin-top: 25rpx; + margin-bottom: 25rpx; } + +.my-26 { + margin-top: 26rpx; + margin-bottom: 26rpx; } + +.my-27 { + margin-top: 27rpx; + margin-bottom: 27rpx; } + +.my-28 { + margin-top: 28rpx; + margin-bottom: 28rpx; } + +.my-29 { + margin-top: 29rpx; + margin-bottom: 29rpx; } + +.my-30 { + margin-top: 30rpx; + margin-bottom: 30rpx; } + +.my-31 { + margin-top: 31rpx; + margin-bottom: 31rpx; } + +.my-32 { + margin-top: 32rpx; + margin-bottom: 32rpx; } + +.my-33 { + margin-top: 33rpx; + margin-bottom: 33rpx; } + +.my-34 { + margin-top: 34rpx; + margin-bottom: 34rpx; } + +.my-35 { + margin-top: 35rpx; + margin-bottom: 35rpx; } + +.my-36 { + margin-top: 36rpx; + margin-bottom: 36rpx; } + +.my-37 { + margin-top: 37rpx; + margin-bottom: 37rpx; } + +.my-38 { + margin-top: 38rpx; + margin-bottom: 38rpx; } + +.my-39 { + margin-top: 39rpx; + margin-bottom: 39rpx; } + +.my-40 { + margin-top: 40rpx; + margin-bottom: 40rpx; } + +.my-41 { + margin-top: 41rpx; + margin-bottom: 41rpx; } + +.my-42 { + margin-top: 42rpx; + margin-bottom: 42rpx; } + +.my-43 { + margin-top: 43rpx; + margin-bottom: 43rpx; } + +.my-44 { + margin-top: 44rpx; + margin-bottom: 44rpx; } + +.my-45 { + margin-top: 45rpx; + margin-bottom: 45rpx; } + +.my-46 { + margin-top: 46rpx; + margin-bottom: 46rpx; } + +.my-47 { + margin-top: 47rpx; + margin-bottom: 47rpx; } + +.my-48 { + margin-top: 48rpx; + margin-bottom: 48rpx; } + +.my-49 { + margin-top: 49rpx; + margin-bottom: 49rpx; } + +.my-50 { + margin-top: 50rpx; + margin-bottom: 50rpx; } + +.my-n1 { + margin-top: 4rpx; + margin-bottom: 4rpx; } + +.my-n2 { + margin-top: 8rpx; + margin-bottom: 8rpx; } + +.my-n3 { + margin-top: 12rpx; + margin-bottom: 12rpx; } + +.my-n4 { + margin-top: 16rpx; + margin-bottom: 16rpx; } + +.my-n5 { + margin-top: 20rpx; + margin-bottom: 20rpx; } + +.my-n6 { + margin-top: 24rpx; + margin-bottom: 24rpx; } + +.my-n7 { + margin-top: 28rpx; + margin-bottom: 28rpx; } + +.my-n8 { + margin-top: 32rpx; + margin-bottom: 32rpx; } + +.my-n9 { + margin-top: 36rpx; + margin-bottom: 36rpx; } + +.my-n10 { + margin-top: 40rpx; + margin-bottom: 40rpx; } + +.my-n11 { + margin-top: 44rpx; + margin-bottom: 44rpx; } + +.my-n12 { + margin-top: 48rpx; + margin-bottom: 48rpx; } + +.my-n13 { + margin-top: 52rpx; + margin-bottom: 52rpx; } + +.my-n14 { + margin-top: 56rpx; + margin-bottom: 56rpx; } + +.my-n15 { + margin-top: 60rpx; + margin-bottom: 60rpx; } + +.my-n16 { + margin-top: 64rpx; + margin-bottom: 64rpx; } + +.my-n17 { + margin-top: 68rpx; + margin-bottom: 68rpx; } + +.my-n18 { + margin-top: 72rpx; + margin-bottom: 72rpx; } + +.my-n19 { + margin-top: 76rpx; + margin-bottom: 76rpx; } + +.my-n20 { + margin-top: 80rpx; + margin-bottom: 80rpx; } + +.my-n21 { + margin-top: 84rpx; + margin-bottom: 84rpx; } + +.my-n22 { + margin-top: 88rpx; + margin-bottom: 88rpx; } + +.my-n23 { + margin-top: 92rpx; + margin-bottom: 92rpx; } + +.my-n24 { + margin-top: 96rpx; + margin-bottom: 96rpx; } + +.my-n25 { + margin-top: 100rpx; + margin-bottom: 100rpx; } + +.t-0 { + top: 0rpx; } + +.t--0 { + top: -0rpx; } + +.t-1 { + top: 1rpx; } + +.t--1 { + top: -1rpx; } + +.t-2 { + top: 2rpx; } + +.t--2 { + top: -2rpx; } + +.t-3 { + top: 3rpx; } + +.t--3 { + top: -3rpx; } + +.t-4 { + top: 4rpx; } + +.t--4 { + top: -4rpx; } + +.t-5 { + top: 5rpx; } + +.t--5 { + top: -5rpx; } + +.t-6 { + top: 6rpx; } + +.t--6 { + top: -6rpx; } + +.t-7 { + top: 7rpx; } + +.t--7 { + top: -7rpx; } + +.t-8 { + top: 8rpx; } + +.t--8 { + top: -8rpx; } + +.t-9 { + top: 9rpx; } + +.t--9 { + top: -9rpx; } + +.t-10 { + top: 10rpx; } + +.t--10 { + top: -10rpx; } + +.t-11 { + top: 11rpx; } + +.t--11 { + top: -11rpx; } + +.t-12 { + top: 12rpx; } + +.t--12 { + top: -12rpx; } + +.t-13 { + top: 13rpx; } + +.t--13 { + top: -13rpx; } + +.t-14 { + top: 14rpx; } + +.t--14 { + top: -14rpx; } + +.t-15 { + top: 15rpx; } + +.t--15 { + top: -15rpx; } + +.t-16 { + top: 16rpx; } + +.t--16 { + top: -16rpx; } + +.t-17 { + top: 17rpx; } + +.t--17 { + top: -17rpx; } + +.t-18 { + top: 18rpx; } + +.t--18 { + top: -18rpx; } + +.t-19 { + top: 19rpx; } + +.t--19 { + top: -19rpx; } + +.t-20 { + top: 20rpx; } + +.t--20 { + top: -20rpx; } + +.t-21 { + top: 21rpx; } + +.t--21 { + top: -21rpx; } + +.t-22 { + top: 22rpx; } + +.t--22 { + top: -22rpx; } + +.t-23 { + top: 23rpx; } + +.t--23 { + top: -23rpx; } + +.t-24 { + top: 24rpx; } + +.t--24 { + top: -24rpx; } + +.t-25 { + top: 25rpx; } + +.t--25 { + top: -25rpx; } + +.t-26 { + top: 26rpx; } + +.t--26 { + top: -26rpx; } + +.t-27 { + top: 27rpx; } + +.t--27 { + top: -27rpx; } + +.t-28 { + top: 28rpx; } + +.t--28 { + top: -28rpx; } + +.t-29 { + top: 29rpx; } + +.t--29 { + top: -29rpx; } + +.t-30 { + top: 30rpx; } + +.t--30 { + top: -30rpx; } + +.t-31 { + top: 31rpx; } + +.t--31 { + top: -31rpx; } + +.t-32 { + top: 32rpx; } + +.t--32 { + top: -32rpx; } + +.t-33 { + top: 33rpx; } + +.t--33 { + top: -33rpx; } + +.t-34 { + top: 34rpx; } + +.t--34 { + top: -34rpx; } + +.t-35 { + top: 35rpx; } + +.t--35 { + top: -35rpx; } + +.t-36 { + top: 36rpx; } + +.t--36 { + top: -36rpx; } + +.t-37 { + top: 37rpx; } + +.t--37 { + top: -37rpx; } + +.t-38 { + top: 38rpx; } + +.t--38 { + top: -38rpx; } + +.t-39 { + top: 39rpx; } + +.t--39 { + top: -39rpx; } + +.t-40 { + top: 40rpx; } + +.t--40 { + top: -40rpx; } + +.t-41 { + top: 41rpx; } + +.t--41 { + top: -41rpx; } + +.t-42 { + top: 42rpx; } + +.t--42 { + top: -42rpx; } + +.t-43 { + top: 43rpx; } + +.t--43 { + top: -43rpx; } + +.t-44 { + top: 44rpx; } + +.t--44 { + top: -44rpx; } + +.t-45 { + top: 45rpx; } + +.t--45 { + top: -45rpx; } + +.t-46 { + top: 46rpx; } + +.t--46 { + top: -46rpx; } + +.t-47 { + top: 47rpx; } + +.t--47 { + top: -47rpx; } + +.t-48 { + top: 48rpx; } + +.t--48 { + top: -48rpx; } + +.t-49 { + top: 49rpx; } + +.t--49 { + top: -49rpx; } + +.t-50 { + top: 50rpx; } + +.t--50 { + top: -50rpx; } + +.t-n1 { + top: 4rpx; } + +.t--n1 { + top: -4rpx; } + +.t-n2 { + top: 8rpx; } + +.t--n2 { + top: -8rpx; } + +.t-n3 { + top: 12rpx; } + +.t--n3 { + top: -12rpx; } + +.t-n4 { + top: 16rpx; } + +.t--n4 { + top: -16rpx; } + +.t-n5 { + top: 20rpx; } + +.t--n5 { + top: -20rpx; } + +.t-n6 { + top: 24rpx; } + +.t--n6 { + top: -24rpx; } + +.t-n7 { + top: 28rpx; } + +.t--n7 { + top: -28rpx; } + +.t-n8 { + top: 32rpx; } + +.t--n8 { + top: -32rpx; } + +.t-n9 { + top: 36rpx; } + +.t--n9 { + top: -36rpx; } + +.t-n10 { + top: 40rpx; } + +.t--n10 { + top: -40rpx; } + +.t-n11 { + top: 44rpx; } + +.t--n11 { + top: -44rpx; } + +.t-n12 { + top: 48rpx; } + +.t--n12 { + top: -48rpx; } + +.t-n13 { + top: 52rpx; } + +.t--n13 { + top: -52rpx; } + +.t-n14 { + top: 56rpx; } + +.t--n14 { + top: -56rpx; } + +.t-n15 { + top: 60rpx; } + +.t--n15 { + top: -60rpx; } + +.t-n16 { + top: 64rpx; } + +.t--n16 { + top: -64rpx; } + +.t-n17 { + top: 68rpx; } + +.t--n17 { + top: -68rpx; } + +.t-n18 { + top: 72rpx; } + +.t--n18 { + top: -72rpx; } + +.t-n19 { + top: 76rpx; } + +.t--n19 { + top: -76rpx; } + +.t-n20 { + top: 80rpx; } + +.t--n20 { + top: -80rpx; } + +.t-n21 { + top: 84rpx; } + +.t--n21 { + top: -84rpx; } + +.t-n22 { + top: 88rpx; } + +.t--n22 { + top: -88rpx; } + +.t-n23 { + top: 92rpx; } + +.t--n23 { + top: -92rpx; } + +.t-n24 { + top: 96rpx; } + +.t--n24 { + top: -96rpx; } + +.t-n25 { + top: 100rpx; } + +.t--n25 { + top: -100rpx; } + +.r-0 { + right: 0rpx; } + +.r--0 { + right: -0rpx; } + +.r-1 { + right: 1rpx; } + +.r--1 { + right: -1rpx; } + +.r-2 { + right: 2rpx; } + +.r--2 { + right: -2rpx; } + +.r-3 { + right: 3rpx; } + +.r--3 { + right: -3rpx; } + +.r-4 { + right: 4rpx; } + +.r--4 { + right: -4rpx; } + +.r-5 { + right: 5rpx; } + +.r--5 { + right: -5rpx; } + +.r-6 { + right: 6rpx; } + +.r--6 { + right: -6rpx; } + +.r-7 { + right: 7rpx; } + +.r--7 { + right: -7rpx; } + +.r-8 { + right: 8rpx; } + +.r--8 { + right: -8rpx; } + +.r-9 { + right: 9rpx; } + +.r--9 { + right: -9rpx; } + +.r-10 { + right: 10rpx; } + +.r--10 { + right: -10rpx; } + +.r-11 { + right: 11rpx; } + +.r--11 { + right: -11rpx; } + +.r-12 { + right: 12rpx; } + +.r--12 { + right: -12rpx; } + +.r-13 { + right: 13rpx; } + +.r--13 { + right: -13rpx; } + +.r-14 { + right: 14rpx; } + +.r--14 { + right: -14rpx; } + +.r-15 { + right: 15rpx; } + +.r--15 { + right: -15rpx; } + +.r-16 { + right: 16rpx; } + +.r--16 { + right: -16rpx; } + +.r-17 { + right: 17rpx; } + +.r--17 { + right: -17rpx; } + +.r-18 { + right: 18rpx; } + +.r--18 { + right: -18rpx; } + +.r-19 { + right: 19rpx; } + +.r--19 { + right: -19rpx; } + +.r-20 { + right: 20rpx; } + +.r--20 { + right: -20rpx; } + +.r-21 { + right: 21rpx; } + +.r--21 { + right: -21rpx; } + +.r-22 { + right: 22rpx; } + +.r--22 { + right: -22rpx; } + +.r-23 { + right: 23rpx; } + +.r--23 { + right: -23rpx; } + +.r-24 { + right: 24rpx; } + +.r--24 { + right: -24rpx; } + +.r-25 { + right: 25rpx; } + +.r--25 { + right: -25rpx; } + +.r-26 { + right: 26rpx; } + +.r--26 { + right: -26rpx; } + +.r-27 { + right: 27rpx; } + +.r--27 { + right: -27rpx; } + +.r-28 { + right: 28rpx; } + +.r--28 { + right: -28rpx; } + +.r-29 { + right: 29rpx; } + +.r--29 { + right: -29rpx; } + +.r-30 { + right: 30rpx; } + +.r--30 { + right: -30rpx; } + +.r-31 { + right: 31rpx; } + +.r--31 { + right: -31rpx; } + +.r-32 { + right: 32rpx; } + +.r--32 { + right: -32rpx; } + +.r-33 { + right: 33rpx; } + +.r--33 { + right: -33rpx; } + +.r-34 { + right: 34rpx; } + +.r--34 { + right: -34rpx; } + +.r-35 { + right: 35rpx; } + +.r--35 { + right: -35rpx; } + +.r-36 { + right: 36rpx; } + +.r--36 { + right: -36rpx; } + +.r-37 { + right: 37rpx; } + +.r--37 { + right: -37rpx; } + +.r-38 { + right: 38rpx; } + +.r--38 { + right: -38rpx; } + +.r-39 { + right: 39rpx; } + +.r--39 { + right: -39rpx; } + +.r-40 { + right: 40rpx; } + +.r--40 { + right: -40rpx; } + +.r-41 { + right: 41rpx; } + +.r--41 { + right: -41rpx; } + +.r-42 { + right: 42rpx; } + +.r--42 { + right: -42rpx; } + +.r-43 { + right: 43rpx; } + +.r--43 { + right: -43rpx; } + +.r-44 { + right: 44rpx; } + +.r--44 { + right: -44rpx; } + +.r-45 { + right: 45rpx; } + +.r--45 { + right: -45rpx; } + +.r-46 { + right: 46rpx; } + +.r--46 { + right: -46rpx; } + +.r-47 { + right: 47rpx; } + +.r--47 { + right: -47rpx; } + +.r-48 { + right: 48rpx; } + +.r--48 { + right: -48rpx; } + +.r-49 { + right: 49rpx; } + +.r--49 { + right: -49rpx; } + +.r-50 { + right: 50rpx; } + +.r--50 { + right: -50rpx; } + +.r-n1 { + right: 4rpx; } + +.r--n1 { + right: -4rpx; } + +.r-n2 { + right: 8rpx; } + +.r--n2 { + right: -8rpx; } + +.r-n3 { + right: 12rpx; } + +.r--n3 { + right: -12rpx; } + +.r-n4 { + right: 16rpx; } + +.r--n4 { + right: -16rpx; } + +.r-n5 { + right: 20rpx; } + +.r--n5 { + right: -20rpx; } + +.r-n6 { + right: 24rpx; } + +.r--n6 { + right: -24rpx; } + +.r-n7 { + right: 28rpx; } + +.r--n7 { + right: -28rpx; } + +.r-n8 { + right: 32rpx; } + +.r--n8 { + right: -32rpx; } + +.r-n9 { + right: 36rpx; } + +.r--n9 { + right: -36rpx; } + +.r-n10 { + right: 40rpx; } + +.r--n10 { + right: -40rpx; } + +.r-n11 { + right: 44rpx; } + +.r--n11 { + right: -44rpx; } + +.r-n12 { + right: 48rpx; } + +.r--n12 { + right: -48rpx; } + +.r-n13 { + right: 52rpx; } + +.r--n13 { + right: -52rpx; } + +.r-n14 { + right: 56rpx; } + +.r--n14 { + right: -56rpx; } + +.r-n15 { + right: 60rpx; } + +.r--n15 { + right: -60rpx; } + +.r-n16 { + right: 64rpx; } + +.r--n16 { + right: -64rpx; } + +.r-n17 { + right: 68rpx; } + +.r--n17 { + right: -68rpx; } + +.r-n18 { + right: 72rpx; } + +.r--n18 { + right: -72rpx; } + +.r-n19 { + right: 76rpx; } + +.r--n19 { + right: -76rpx; } + +.r-n20 { + right: 80rpx; } + +.r--n20 { + right: -80rpx; } + +.r-n21 { + right: 84rpx; } + +.r--n21 { + right: -84rpx; } + +.r-n22 { + right: 88rpx; } + +.r--n22 { + right: -88rpx; } + +.r-n23 { + right: 92rpx; } + +.r--n23 { + right: -92rpx; } + +.r-n24 { + right: 96rpx; } + +.r--n24 { + right: -96rpx; } + +.r-n25 { + right: 100rpx; } + +.r--n25 { + right: -100rpx; } + +.b-0 { + bottom: 0rpx; } + +.b--0 { + bottom: -0rpx; } + +.b-1 { + bottom: 1rpx; } + +.b--1 { + bottom: -1rpx; } + +.b-2 { + bottom: 2rpx; } + +.b--2 { + bottom: -2rpx; } + +.b-3 { + bottom: 3rpx; } + +.b--3 { + bottom: -3rpx; } + +.b-4 { + bottom: 4rpx; } + +.b--4 { + bottom: -4rpx; } + +.b-5 { + bottom: 5rpx; } + +.b--5 { + bottom: -5rpx; } + +.b-6 { + bottom: 6rpx; } + +.b--6 { + bottom: -6rpx; } + +.b-7 { + bottom: 7rpx; } + +.b--7 { + bottom: -7rpx; } + +.b-8 { + bottom: 8rpx; } + +.b--8 { + bottom: -8rpx; } + +.b-9 { + bottom: 9rpx; } + +.b--9 { + bottom: -9rpx; } + +.b-10 { + bottom: 10rpx; } + +.b--10 { + bottom: -10rpx; } + +.b-11 { + bottom: 11rpx; } + +.b--11 { + bottom: -11rpx; } + +.b-12 { + bottom: 12rpx; } + +.b--12 { + bottom: -12rpx; } + +.b-13 { + bottom: 13rpx; } + +.b--13 { + bottom: -13rpx; } + +.b-14 { + bottom: 14rpx; } + +.b--14 { + bottom: -14rpx; } + +.b-15 { + bottom: 15rpx; } + +.b--15 { + bottom: -15rpx; } + +.b-16 { + bottom: 16rpx; } + +.b--16 { + bottom: -16rpx; } + +.b-17 { + bottom: 17rpx; } + +.b--17 { + bottom: -17rpx; } + +.b-18 { + bottom: 18rpx; } + +.b--18 { + bottom: -18rpx; } + +.b-19 { + bottom: 19rpx; } + +.b--19 { + bottom: -19rpx; } + +.b-20 { + bottom: 20rpx; } + +.b--20 { + bottom: -20rpx; } + +.b-21 { + bottom: 21rpx; } + +.b--21 { + bottom: -21rpx; } + +.b-22 { + bottom: 22rpx; } + +.b--22 { + bottom: -22rpx; } + +.b-23 { + bottom: 23rpx; } + +.b--23 { + bottom: -23rpx; } + +.b-24 { + bottom: 24rpx; } + +.b--24 { + bottom: -24rpx; } + +.b-25 { + bottom: 25rpx; } + +.b--25 { + bottom: -25rpx; } + +.b-26 { + bottom: 26rpx; } + +.b--26 { + bottom: -26rpx; } + +.b-27 { + bottom: 27rpx; } + +.b--27 { + bottom: -27rpx; } + +.b-28 { + bottom: 28rpx; } + +.b--28 { + bottom: -28rpx; } + +.b-29 { + bottom: 29rpx; } + +.b--29 { + bottom: -29rpx; } + +.b-30 { + bottom: 30rpx; } + +.b--30 { + bottom: -30rpx; } + +.b-31 { + bottom: 31rpx; } + +.b--31 { + bottom: -31rpx; } + +.b-32 { + bottom: 32rpx; } + +.b--32 { + bottom: -32rpx; } + +.b-33 { + bottom: 33rpx; } + +.b--33 { + bottom: -33rpx; } + +.b-34 { + bottom: 34rpx; } + +.b--34 { + bottom: -34rpx; } + +.b-35 { + bottom: 35rpx; } + +.b--35 { + bottom: -35rpx; } + +.b-36 { + bottom: 36rpx; } + +.b--36 { + bottom: -36rpx; } + +.b-37 { + bottom: 37rpx; } + +.b--37 { + bottom: -37rpx; } + +.b-38 { + bottom: 38rpx; } + +.b--38 { + bottom: -38rpx; } + +.b-39 { + bottom: 39rpx; } + +.b--39 { + bottom: -39rpx; } + +.b-40 { + bottom: 40rpx; } + +.b--40 { + bottom: -40rpx; } + +.b-41 { + bottom: 41rpx; } + +.b--41 { + bottom: -41rpx; } + +.b-42 { + bottom: 42rpx; } + +.b--42 { + bottom: -42rpx; } + +.b-43 { + bottom: 43rpx; } + +.b--43 { + bottom: -43rpx; } + +.b-44 { + bottom: 44rpx; } + +.b--44 { + bottom: -44rpx; } + +.b-45 { + bottom: 45rpx; } + +.b--45 { + bottom: -45rpx; } + +.b-46 { + bottom: 46rpx; } + +.b--46 { + bottom: -46rpx; } + +.b-47 { + bottom: 47rpx; } + +.b--47 { + bottom: -47rpx; } + +.b-48 { + bottom: 48rpx; } + +.b--48 { + bottom: -48rpx; } + +.b-49 { + bottom: 49rpx; } + +.b--49 { + bottom: -49rpx; } + +.b-50 { + bottom: 50rpx; } + +.b--50 { + bottom: -50rpx; } + +.b-n1 { + bottom: 4rpx; } + +.b--n1 { + bottom: -4rpx; } + +.b-n2 { + bottom: 8rpx; } + +.b--n2 { + bottom: -8rpx; } + +.b-n3 { + bottom: 12rpx; } + +.b--n3 { + bottom: -12rpx; } + +.b-n4 { + bottom: 16rpx; } + +.b--n4 { + bottom: -16rpx; } + +.b-n5 { + bottom: 20rpx; } + +.b--n5 { + bottom: -20rpx; } + +.b-n6 { + bottom: 24rpx; } + +.b--n6 { + bottom: -24rpx; } + +.b-n7 { + bottom: 28rpx; } + +.b--n7 { + bottom: -28rpx; } + +.b-n8 { + bottom: 32rpx; } + +.b--n8 { + bottom: -32rpx; } + +.b-n9 { + bottom: 36rpx; } + +.b--n9 { + bottom: -36rpx; } + +.b-n10 { + bottom: 40rpx; } + +.b--n10 { + bottom: -40rpx; } + +.b-n11 { + bottom: 44rpx; } + +.b--n11 { + bottom: -44rpx; } + +.b-n12 { + bottom: 48rpx; } + +.b--n12 { + bottom: -48rpx; } + +.b-n13 { + bottom: 52rpx; } + +.b--n13 { + bottom: -52rpx; } + +.b-n14 { + bottom: 56rpx; } + +.b--n14 { + bottom: -56rpx; } + +.b-n15 { + bottom: 60rpx; } + +.b--n15 { + bottom: -60rpx; } + +.b-n16 { + bottom: 64rpx; } + +.b--n16 { + bottom: -64rpx; } + +.b-n17 { + bottom: 68rpx; } + +.b--n17 { + bottom: -68rpx; } + +.b-n18 { + bottom: 72rpx; } + +.b--n18 { + bottom: -72rpx; } + +.b-n19 { + bottom: 76rpx; } + +.b--n19 { + bottom: -76rpx; } + +.b-n20 { + bottom: 80rpx; } + +.b--n20 { + bottom: -80rpx; } + +.b-n21 { + bottom: 84rpx; } + +.b--n21 { + bottom: -84rpx; } + +.b-n22 { + bottom: 88rpx; } + +.b--n22 { + bottom: -88rpx; } + +.b-n23 { + bottom: 92rpx; } + +.b--n23 { + bottom: -92rpx; } + +.b-n24 { + bottom: 96rpx; } + +.b--n24 { + bottom: -96rpx; } + +.b-n25 { + bottom: 100rpx; } + +.b--n25 { + bottom: -100rpx; } + +.l-0 { + left: 0rpx; } + +.l--0 { + left: -0rpx; } + +.l-1 { + left: 1rpx; } + +.l--1 { + left: -1rpx; } + +.l-2 { + left: 2rpx; } + +.l--2 { + left: -2rpx; } + +.l-3 { + left: 3rpx; } + +.l--3 { + left: -3rpx; } + +.l-4 { + left: 4rpx; } + +.l--4 { + left: -4rpx; } + +.l-5 { + left: 5rpx; } + +.l--5 { + left: -5rpx; } + +.l-6 { + left: 6rpx; } + +.l--6 { + left: -6rpx; } + +.l-7 { + left: 7rpx; } + +.l--7 { + left: -7rpx; } + +.l-8 { + left: 8rpx; } + +.l--8 { + left: -8rpx; } + +.l-9 { + left: 9rpx; } + +.l--9 { + left: -9rpx; } + +.l-10 { + left: 10rpx; } + +.l--10 { + left: -10rpx; } + +.l-11 { + left: 11rpx; } + +.l--11 { + left: -11rpx; } + +.l-12 { + left: 12rpx; } + +.l--12 { + left: -12rpx; } + +.l-13 { + left: 13rpx; } + +.l--13 { + left: -13rpx; } + +.l-14 { + left: 14rpx; } + +.l--14 { + left: -14rpx; } + +.l-15 { + left: 15rpx; } + +.l--15 { + left: -15rpx; } + +.l-16 { + left: 16rpx; } + +.l--16 { + left: -16rpx; } + +.l-17 { + left: 17rpx; } + +.l--17 { + left: -17rpx; } + +.l-18 { + left: 18rpx; } + +.l--18 { + left: -18rpx; } + +.l-19 { + left: 19rpx; } + +.l--19 { + left: -19rpx; } + +.l-20 { + left: 20rpx; } + +.l--20 { + left: -20rpx; } + +.l-21 { + left: 21rpx; } + +.l--21 { + left: -21rpx; } + +.l-22 { + left: 22rpx; } + +.l--22 { + left: -22rpx; } + +.l-23 { + left: 23rpx; } + +.l--23 { + left: -23rpx; } + +.l-24 { + left: 24rpx; } + +.l--24 { + left: -24rpx; } + +.l-25 { + left: 25rpx; } + +.l--25 { + left: -25rpx; } + +.l-26 { + left: 26rpx; } + +.l--26 { + left: -26rpx; } + +.l-27 { + left: 27rpx; } + +.l--27 { + left: -27rpx; } + +.l-28 { + left: 28rpx; } + +.l--28 { + left: -28rpx; } + +.l-29 { + left: 29rpx; } + +.l--29 { + left: -29rpx; } + +.l-30 { + left: 30rpx; } + +.l--30 { + left: -30rpx; } + +.l-31 { + left: 31rpx; } + +.l--31 { + left: -31rpx; } + +.l-32 { + left: 32rpx; } + +.l--32 { + left: -32rpx; } + +.l-33 { + left: 33rpx; } + +.l--33 { + left: -33rpx; } + +.l-34 { + left: 34rpx; } + +.l--34 { + left: -34rpx; } + +.l-35 { + left: 35rpx; } + +.l--35 { + left: -35rpx; } + +.l-36 { + left: 36rpx; } + +.l--36 { + left: -36rpx; } + +.l-37 { + left: 37rpx; } + +.l--37 { + left: -37rpx; } + +.l-38 { + left: 38rpx; } + +.l--38 { + left: -38rpx; } + +.l-39 { + left: 39rpx; } + +.l--39 { + left: -39rpx; } + +.l-40 { + left: 40rpx; } + +.l--40 { + left: -40rpx; } + +.l-41 { + left: 41rpx; } + +.l--41 { + left: -41rpx; } + +.l-42 { + left: 42rpx; } + +.l--42 { + left: -42rpx; } + +.l-43 { + left: 43rpx; } + +.l--43 { + left: -43rpx; } + +.l-44 { + left: 44rpx; } + +.l--44 { + left: -44rpx; } + +.l-45 { + left: 45rpx; } + +.l--45 { + left: -45rpx; } + +.l-46 { + left: 46rpx; } + +.l--46 { + left: -46rpx; } + +.l-47 { + left: 47rpx; } + +.l--47 { + left: -47rpx; } + +.l-48 { + left: 48rpx; } + +.l--48 { + left: -48rpx; } + +.l-49 { + left: 49rpx; } + +.l--49 { + left: -49rpx; } + +.l-50 { + left: 50rpx; } + +.l--50 { + left: -50rpx; } + +.l-n1 { + left: 4rpx; } + +.l--n1 { + left: -4rpx; } + +.l-n2 { + left: 8rpx; } + +.l--n2 { + left: -8rpx; } + +.l-n3 { + left: 12rpx; } + +.l--n3 { + left: -12rpx; } + +.l-n4 { + left: 16rpx; } + +.l--n4 { + left: -16rpx; } + +.l-n5 { + left: 20rpx; } + +.l--n5 { + left: -20rpx; } + +.l-n6 { + left: 24rpx; } + +.l--n6 { + left: -24rpx; } + +.l-n7 { + left: 28rpx; } + +.l--n7 { + left: -28rpx; } + +.l-n8 { + left: 32rpx; } + +.l--n8 { + left: -32rpx; } + +.l-n9 { + left: 36rpx; } + +.l--n9 { + left: -36rpx; } + +.l-n10 { + left: 40rpx; } + +.l--n10 { + left: -40rpx; } + +.l-n11 { + left: 44rpx; } + +.l--n11 { + left: -44rpx; } + +.l-n12 { + left: 48rpx; } + +.l--n12 { + left: -48rpx; } + +.l-n13 { + left: 52rpx; } + +.l--n13 { + left: -52rpx; } + +.l-n14 { + left: 56rpx; } + +.l--n14 { + left: -56rpx; } + +.l-n15 { + left: 60rpx; } + +.l--n15 { + left: -60rpx; } + +.l-n16 { + left: 64rpx; } + +.l--n16 { + left: -64rpx; } + +.l-n17 { + left: 68rpx; } + +.l--n17 { + left: -68rpx; } + +.l-n18 { + left: 72rpx; } + +.l--n18 { + left: -72rpx; } + +.l-n19 { + left: 76rpx; } + +.l--n19 { + left: -76rpx; } + +.l-n20 { + left: 80rpx; } + +.l--n20 { + left: -80rpx; } + +.l-n21 { + left: 84rpx; } + +.l--n21 { + left: -84rpx; } + +.l-n22 { + left: 88rpx; } + +.l--n22 { + left: -88rpx; } + +.l-n23 { + left: 92rpx; } + +.l--n23 { + left: -92rpx; } + +.l-n24 { + left: 96rpx; } + +.l--n24 { + left: -96rpx; } + +.l-n25 { + left: 100rpx; } + +.l--n25 { + left: -100rpx; } + +.flex { + display: flex; } + +.flex-col { + flex-direction: column; } + +.flex-wrap { + flex-flow: row wrap; } + +.flex-shrink { + flex-shrink: 0; } + +.flex-row { + flex-direction: row; } + +.flex-reverse { + flex-direction: row-reverse; } + +.flex-row-top-start { + justify-content: flex-start; + align-items: flex-start; + display: flex; } + +.flex-row-top-center { + justify-content: center; + align-items: flex-start; + display: flex; } + +.flex-row-top-end { + justify-content: flex-end; + align-items: flex-start; + display: flex; } + +.flex-row-center-start { + justify-content: flex-start; + align-items: center; + display: flex; } + +.flex-row-center-center { + justify-content: center; + align-items: center; + display: flex; } + +.flex-row-center-end { + justify-content: flex-end; + align-items: center; + display: flex; } + +.flex-row-bottom-start { + justify-content: flex-start; + align-items: flex-end; + display: flex; } + +.flex-row-bottom-center { + justify-content: center; + align-items: flex-end; + display: flex; } + +.flex-row-bottom-end { + justify-content: flex-end; + align-items: flex-end; + display: flex; } + +.flex-row-center-between { + justify-content: space-between; + align-items: center; + display: flex; } + +.flex-col-top-start { + justify-content: flex-start; + align-items: flex-start; + display: flex; } + +.flex-col-top-center { + justify-content: flex-start; + align-items: center; + display: flex; } + +.flex-col-top-end { + justify-content: flex-start; + align-items: flex-end; + display: flex; } + +.flex-col-center-start { + justify-content: center; + align-items: flex-start; + display: flex; } + +.flex-col-center-center { + justify-content: center; + align-items: center; + display: flex; } + +.flex-col-center-end { + justify-content: center; + align-items: flex-end; + display: flex; } + +.flex-col-bottom-start { + justify-content: flex-end; + align-items: flex-start; + display: flex; } + +.flex-col-bottom-center { + justify-content: flex-end; + align-items: center; + display: flex; } + +.flex-col-bottom-end { + justify-content: flex-end; + align-items: flex-end; + display: flex; } + +.flex-start { + justify-content: flex-start; + align-items: center; + display: flex; } + +.flex-end { + justify-content: flex-end; + align-items: center; + display: flex; } + +.flex-center { + justify-content: center; + align-items: center; + display: flex; } + +.flex-between { + justify-content: space-between; } + +.flex-col-full { + flex-direction: column; + align-items: stretch; } + +.flex-around { + justify-content: space-around; } + +.flex-0 { + flex: 0; } + +.flex-1 { + flex: 1; } + +.flex-2 { + flex: 2; } + +.flex-3 { + flex: 3; } + +.flex-4 { + flex: 4; } + +.flex-5 { + flex: 5; } + +.flex-6 { + flex: 6; } + +.flex-7 { + flex: 7; } + +.flex-8 { + flex: 8; } + +.flex-9 { + flex: 9; } + +.flex-10 { + flex: 10; } + +.flex-11 { + flex: 11; } + +.flex-12 { + flex: 12; } + +.text-red { + color: #f44336; } + +.red { + background-color: #f44336; } + +.text-pink { + color: #e91e63; } + +.pink { + background-color: #e91e63; } + +.text-purple { + color: #9c27b0; } + +.purple { + background-color: #9c27b0; } + +.text-deep-purple { + color: #673ab7; } + +.deep-purple { + background-color: #673ab7; } + +.text-indigo { + color: #3f51b5; } + +.indigo { + background-color: #3f51b5; } + +.text-blue { + color: #2196f3; } + +.blue { + background-color: #2196f3; } + +.text-light-blue { + color: #03a9f4; } + +.light-blue { + background-color: #03a9f4; } + +.text-cyan { + color: #00bcd4; } + +.cyan { + background-color: #00bcd4; } + +.text-teal { + color: #009688; } + +.teal { + background-color: #009688; } + +.text-green { + color: #4caf50; } + +.green { + background-color: #4caf50; } + +.text-light-green { + color: #8bc34a; } + +.light-green { + background-color: #8bc34a; } + +.text-lime { + color: #cddc39; } + +.lime { + background-color: #cddc39; } + +.text-yellow { + color: #ffeb3b; } + +.yellow { + background-color: #ffeb3b; } + +.text-amber { + color: #ffc107; } + +.amber { + background-color: #ffc107; } + +.text-orange { + color: #ff9800; } + +.orange { + background-color: #ff9800; } + +.text-deep-orange { + color: #ff5722; } + +.deep-orange { + background-color: #ff5722; } + +.text-brown { + color: #795548; } + +.brown { + background-color: #795548; } + +.text-blue-grey { + color: #607d8b; } + +.blue-grey { + background-color: #607d8b; } + +.text-primary { + color: #0088ff; } + +.primary { + background-color: #0088ff; } + +.text-success { + color: #34c759; } + +.success { + background-color: #34c759; } + +.text-danger { + color: #ff8d28; } + +.danger { + background-color: #ff8d28; } + +.text-warn { + color: #F3BF12; } + +.warn { + background-color: #F3BF12; } + +.text-error { + color: #ff383c; } + +.error { + background-color: #ff383c; } + +.text-info { + color: #f2f2f7; } + +.info { + background-color: #f2f2f7; } + +.text-grey { + color: #9e9e9e; } + +.grey { + background-color: #9e9e9e; } + +.text-black { + color: #000000; } + +.black { + background-color: #000000; } + +.text-white { + color: #ffffff; } + +.white { + background-color: #ffffff; } + +.text-lighten-5 { + color: #fafafa; } + +.lighten-5 { + background-color: #fafafa; } + +.text-lighten-4 { + color: #f5f5f5; } + +.lighten-4 { + background-color: #f5f5f5; } + +.text-lighten-3 { + color: #eeeeee; } + +.lighten-3 { + background-color: #eeeeee; } + +.text-lighten-2 { + color: #e0e0e0; } + +.lighten-2 { + background-color: #e0e0e0; } + +.text-lighten-1 { + color: #bdbdbd; } + +.lighten-1 { + background-color: #bdbdbd; } + +.text-darken-1 { + color: #757575; } + +.darken-1 { + background-color: #757575; } + +.text-darken-2 { + color: #616161; } + +.darken-2 { + background-color: #616161; } + +.text-darken-3 { + color: #424242; } + +.darken-3 { + background-color: #424242; } + +.text-darken-4 { + color: #212121; } + +.darken-4 { + background-color: #212121; } + +.text-darken-5 { + color: #131313; } + +.darken-5 { + background-color: #131313; } + +.text-darken-6 { + color: #0a0a0a; } + +.darken-6 { + background-color: #0a0a0a; } diff --git a/uni_modules/tmx-ui/scss/uvue.css.map b/uni_modules/tmx-ui/scss/uvue.css.map new file mode 100644 index 0000000..dcefac4 --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvue.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["uvue.css","uvue.scss"],"names":[],"mappings":"AAAA,gBAAgB;ACChB;EACC,gBAAA;ADCD;;ACCA;EACC,mBAAA;ADED;;ACAA;EACC,kBAAA;ADGD;;ACDA;EACC,aAAA;ADID;;ACOC;EACC,kBAVW;ADMb;;ACGC;EACC,kBAVW;ADUb;;ACDC;EACC,eAVW;ADcb;;ACDA;EACC,WAAA;ADID;;ACFA;EACC,OAAA;ADKD;;ACEC;EACC,UAAA;ADCF;;ACCC;EACC,UAAA;ADEF;;ACNC;EACC,UAAA;ADSF;;ACPC;EACC,UAAA;ADUF;;ACdC;EACC,UAAA;ADiBF;;ACfC;EACC,UAAA;ADkBF;;ACtBC;EACC,UAAA;ADyBF;;ACvBC;EACC,WAAA;AD0BF;;AC9BC;EACC,UAAA;ADiCF;;AC/BC;EACC,WAAA;ADkCF;;ACtCC;EACC,UAAA;ADyCF;;ACvCC;EACC,WAAA;AD0CF;;AC9CC;EACC,UAAA;ADiDF;;AC/CC;EACC,WAAA;ADkDF;;ACtDC;EACC,UAAA;ADyDF;;ACvDC;EACC,WAAA;AD0DF;;AC9DC;EACC,UAAA;ADiEF;;AC/DC;EACC,WAAA;ADkEF;;ACtEC;EACC,UAAA;ADyEF;;ACvEC;EACC,WAAA;AD0EF;;AC9EC;EACC,WAAA;ADiFF;;AC/EC;EACC,WAAA;ADkFF;;ACtFC;EACC,WAAA;ADyFF;;ACvFC;EACC,WAAA;AD0FF;;AC9FC;EACC,WAAA;ADiGF;;AC/FC;EACC,WAAA;ADkGF;;ACtGC;EACC,WAAA;ADyGF;;ACvGC;EACC,WAAA;AD0GF;;AC9GC;EACC,WAAA;ADiHF;;AC/GC;EACC,WAAA;ADkHF;;ACtHC;EACC,WAAA;ADyHF;;ACvHC;EACC,WAAA;AD0HF;;AC9HC;EACC,WAAA;ADiIF;;AC/HC;EACC,WAAA;ADkIF;;ACtIC;EACC,WAAA;ADyIF;;ACvIC;EACC,WAAA;AD0IF;;AC9IC;EACC,WAAA;ADiJF;;AC/IC;EACC,WAAA;ADkJF;;ACtJC;EACC,WAAA;ADyJF;;ACvJC;EACC,WAAA;AD0JF;;AC9JC;EACC,WAAA;ADiKF;;AC/JC;EACC,WAAA;ADkKF;;ACtKC;EACC,WAAA;ADyKF;;ACvKC;EACC,WAAA;AD0KF;;AC9KC;EACC,WAAA;ADiLF;;AC/KC;EACC,WAAA;ADkLF;;ACtLC;EACC,WAAA;ADyLF;;ACvLC;EACC,WAAA;AD0LF;;AC9LC;EACC,WAAA;ADiMF;;AC/LC;EACC,WAAA;ADkMF;;ACtMC;EACC,WAAA;ADyMF;;ACvMC;EACC,YAAA;AD0MF;;AC9MC;EACC,WAAA;ADiNF;;AC/MC;EACC,YAAA;ADkNF;;AC9MA;EACC,uBAAA;ADiND;;AC7MC;EACC,uBAAA;EACA,QAHW;ADmNb;;AClNC;EACC,uBAAA;EACA,QAHW;ADwNb;;ACvNC;EACC,uBAAA;EACA,QAHW;AD6Nb;;AC5NC;EACC,uBAAA;EACA,QAHW;ADkOb;;ACxNC;EACC,gBAFkB;AD6NpB;;AC5NC;EACC,gBAFkB;ADiOpB;;AChOC;EACC,gBAFkB;ADqOpB;;ACpOC;EACC,gBAFkB;ADyOpB;;ACxOC;EACC,gBAFkB;AD6OpB;;AC5OC;EACC,gBAFkB;ADiPpB;;AChPC;EACC,gBAFkB;ADqPpB;;ACpPC;EACC,gBAFkB;ADyPpB;;ACjPC;EACC,gBAFkB;ADsPpB;;ACrPC;EACC,gBAFkB;AD0PpB;;ACzPC;EACC,gBAFkB;AD8PpB;;ACtPC;EACC,gBAFkB;AD2PpB;;AC1PC;EACC,iBAFkB;AD+PpB;;AC9PC;EACC,kBAFkB;ADmQpB;;ACxPE;EAEE,4BAAA;AD0PJ;;AC5PE;EAEE,4BAAA;AD8PJ;;AChQE;EAEE,4BAAA;ADkQJ;;ACpQE;EAEE,4BAAA;ADsQJ;;ACxQE;EAEE,4BAAA;AD0QJ;;AC5QE;EAEE,6BAAA;AD8QJ;;AChRE;EAEE,6BAAA;ADkRJ;;ACpRE;EAEE,6BAAA;ADsRJ;;ACxRE;EAEE,6BAAA;AD0RJ;;AC5RE;EAEE,6BAAA;AD8RJ;;AChSE;EAEE,6BAAA;ADkSJ;;ACpSE;EAEE,6BAAA;ADsSJ;;ACxSE;EAEE,6BAAA;AD0SJ;;AC5SE;EAEE,6BAAA;AD8SJ;;AChTE;EAEE,6BAAA;ADkTJ;;ACpTE;EAEE,6BAAA;ADsTJ;;ACxTE;EAEE,6BAAA;AD0TJ;;AC5TE;EAEE,6BAAA;AD8TJ;;AChUE;EAEE,6BAAA;ADkUJ;;ACpUE;EAEE,6BAAA;ADsUJ;;ACxUE;EAEE,6BAAA;AD0UJ;;AC5UE;EAEE,6BAAA;AD8UJ;;AChVE;EAEE,6BAAA;ADkVJ;;ACpVE;EAEE,6BAAA;ADsVJ;;ACxVE;EAEE,6BAAA;AD0VJ;;AC5VE;EAEE,6BAAA;AD8VJ;;AChWE;EAME,6BAAA;AD8VJ;;ACpWE;EAME,6BAAA;ADkWJ;;ACxWE;EAME,6BAAA;ADsWJ;;AC5WE;EAME,6BAAA;AD0WJ;;AChXE;EAME,6BAAA;AD8WJ;;ACpXE;EAME,8BAAA;ADkXJ;;ACxXE;EAME,8BAAA;ADsXJ;;AC5XE;EAME,8BAAA;AD0XJ;;AChYE;EAME,8BAAA;AD8XJ;;ACpYE;EAME,8BAAA;ADkYJ;;ACxYE;EAME,8BAAA;ADsYJ;;AC5YE;EAME,8BAAA;AD0YJ;;AChZE;EAME,8BAAA;AD8YJ;;ACpZE;EAME,8BAAA;ADkZJ;;ACxZE;EAME,8BAAA;ADsZJ;;AC5ZE;EAME,8BAAA;AD0ZJ;;AChaE;EAME,8BAAA;AD8ZJ;;ACpaE;EAME,8BAAA;ADkaJ;;ACxaE;EAME,8BAAA;ADsaJ;;AC5aE;EAME,8BAAA;AD0aJ;;AChbE;EAME,8BAAA;AD8aJ;;ACpbE;EAME,8BAAA;ADkbJ;;ACxbE;EAME,8BAAA;ADsbJ;;AC5bE;EAME,8BAAA;AD0bJ;;AChcE;EAME,8BAAA;AD8bJ;;ACpcE;EAME,8BAAA;ADkcJ;;ACxcE;EAUE,+BAAA;ADkcJ;;AC5cE;EAUE,+BAAA;ADscJ;;AChdE;EAUE,+BAAA;AD0cJ;;ACpdE;EAUE,+BAAA;AD8cJ;;ACxdE;EAUE,+BAAA;ADkdJ;;AC5dE;EAUE,gCAAA;ADsdJ;;ACheE;EAUE,gCAAA;AD0dJ;;ACpeE;EAUE,gCAAA;AD8dJ;;ACxeE;EAUE,gCAAA;ADkeJ;;AC5eE;EAUE,gCAAA;ADseJ;;AChfE;EAUE,gCAAA;AD0eJ;;ACpfE;EAUE,gCAAA;AD8eJ;;ACxfE;EAUE,gCAAA;ADkfJ;;AC5fE;EAUE,gCAAA;ADsfJ;;AChgBE;EAUE,gCAAA;AD0fJ;;ACpgBE;EAUE,gCAAA;AD8fJ;;ACxgBE;EAUE,gCAAA;ADkgBJ;;AC5gBE;EAUE,gCAAA;ADsgBJ;;AChhBE;EAUE,gCAAA;AD0gBJ;;ACphBE;EAUE,gCAAA;AD8gBJ;;ACxhBE;EAUE,gCAAA;ADkhBJ;;AC5hBE;EAUE,gCAAA;ADshBJ;;AChiBE;EAUE,gCAAA;AD0hBJ;;ACpiBE;EAUE,gCAAA;AD8hBJ;;ACxiBE;EAUE,gCAAA;ADkiBJ;;AC5iBE;EAUE,gCAAA;ADsiBJ;;AChjBE;EAcE,gCAAA;ADsiBJ;;ACpjBE;EAcE,gCAAA;AD0iBJ;;ACxjBE;EAcE,gCAAA;AD8iBJ;;AC5jBE;EAcE,gCAAA;ADkjBJ;;AChkBE;EAcE,gCAAA;ADsjBJ;;ACpkBE;EAcE,iCAAA;AD0jBJ;;ACxkBE;EAcE,iCAAA;AD8jBJ;;AC5kBE;EAcE,iCAAA;ADkkBJ;;AChlBE;EAcE,iCAAA;ADskBJ;;ACplBE;EAcE,iCAAA;AD0kBJ;;ACxlBE;EAcE,iCAAA;AD8kBJ;;AC5lBE;EAcE,iCAAA;ADklBJ;;AChmBE;EAcE,iCAAA;ADslBJ;;ACpmBE;EAcE,iCAAA;AD0lBJ;;ACxmBE;EAcE,iCAAA;AD8lBJ;;AC5mBE;EAcE,iCAAA;ADkmBJ;;AChnBE;EAcE,iCAAA;ADsmBJ;;ACpnBE;EAcE,iCAAA;AD0mBJ;;ACxnBE;EAcE,iCAAA;AD8mBJ;;AC5nBE;EAcE,iCAAA;ADknBJ;;AChoBE;EAcE,iCAAA;ADsnBJ;;ACpoBE;EAcE,iCAAA;AD0nBJ;;ACxoBE;EAcE,iCAAA;AD8nBJ;;AC5oBE;EAcE,iCAAA;ADkoBJ;;AChpBE;EAcE,iCAAA;ADsoBJ;;ACppBE;EAcE,iCAAA;AD0oBJ;;ACxpBE;EAsCE,mBAAA;ADsnBJ;;AC5pBE;EAsCE,mBAAA;AD0nBJ;;AChqBE;EAsCE,mBAAA;AD8nBJ;;ACpqBE;EAsCE,mBAAA;ADkoBJ;;ACxqBE;EAsCE,mBAAA;ADsoBJ;;AC5qBE;EAsCE,oBAAA;AD0oBJ;;AChrBE;EAsCE,oBAAA;AD8oBJ;;ACprBE;EAsCE,oBAAA;ADkpBJ;;ACxrBE;EAsCE,oBAAA;ADspBJ;;AC5rBE;EAsCE,oBAAA;AD0pBJ;;AChsBE;EAsCE,oBAAA;AD8pBJ;;ACpsBE;EAsCE,oBAAA;ADkqBJ;;ACxsBE;EAsCE,oBAAA;ADsqBJ;;AC5sBE;EAsCE,oBAAA;AD0qBJ;;AChtBE;EAsCE,oBAAA;AD8qBJ;;ACptBE;EAsCE,oBAAA;ADkrBJ;;ACxtBE;EAsCE,oBAAA;ADsrBJ;;AC5tBE;EAsCE,oBAAA;AD0rBJ;;AChuBE;EAsCE,oBAAA;AD8rBJ;;ACpuBE;EAsCE,oBAAA;ADksBJ;;ACxuBE;EAsCE,oBAAA;ADssBJ;;AC5uBE;EAsCE,oBAAA;AD0sBJ;;AChvBE;EAsCE,oBAAA;AD8sBJ;;ACpvBE;EAsCE,oBAAA;ADktBJ;;ACxvBE;EAsCE,oBAAA;ADstBJ;;AC5vBE;EAsCE,oBAAA;AD0tBJ;;AChwBE;EAkBE,4BAAA;EACA,6BAAA;ADkvBJ;;ACrwBE;EAkBE,4BAAA;EACA,6BAAA;ADuvBJ;;AC1wBE;EAkBE,4BAAA;EACA,6BAAA;AD4vBJ;;AC/wBE;EAkBE,4BAAA;EACA,6BAAA;ADiwBJ;;ACpxBE;EAkBE,4BAAA;EACA,6BAAA;ADswBJ;;ACzxBE;EAkBE,6BAAA;EACA,8BAAA;AD2wBJ;;AC9xBE;EAkBE,6BAAA;EACA,8BAAA;ADgxBJ;;ACnyBE;EAkBE,6BAAA;EACA,8BAAA;ADqxBJ;;ACxyBE;EAkBE,6BAAA;EACA,8BAAA;AD0xBJ;;AC7yBE;EAkBE,6BAAA;EACA,8BAAA;AD+xBJ;;AClzBE;EAkBE,6BAAA;EACA,8BAAA;ADoyBJ;;ACvzBE;EAkBE,6BAAA;EACA,8BAAA;ADyyBJ;;AC5zBE;EAkBE,6BAAA;EACA,8BAAA;AD8yBJ;;ACj0BE;EAkBE,6BAAA;EACA,8BAAA;ADmzBJ;;ACt0BE;EAkBE,6BAAA;EACA,8BAAA;ADwzBJ;;AC30BE;EAkBE,6BAAA;EACA,8BAAA;AD6zBJ;;ACh1BE;EAkBE,6BAAA;EACA,8BAAA;ADk0BJ;;ACr1BE;EAkBE,6BAAA;EACA,8BAAA;ADu0BJ;;AC11BE;EAkBE,6BAAA;EACA,8BAAA;AD40BJ;;AC/1BE;EAkBE,6BAAA;EACA,8BAAA;ADi1BJ;;ACp2BE;EAkBE,6BAAA;EACA,8BAAA;ADs1BJ;;ACz2BE;EAkBE,6BAAA;EACA,8BAAA;AD21BJ;;AC92BE;EAkBE,6BAAA;EACA,8BAAA;ADg2BJ;;ACn3BE;EAkBE,6BAAA;EACA,8BAAA;ADq2BJ;;ACx3BE;EAkBE,6BAAA;EACA,8BAAA;AD02BJ;;AC73BE;EAkBE,6BAAA;EACA,8BAAA;AD+2BJ;;ACl4BE;EAuBE,+BAAA;EACA,gCAAA;AD+2BJ;;ACv4BE;EAuBE,+BAAA;EACA,gCAAA;ADo3BJ;;AC54BE;EAuBE,+BAAA;EACA,gCAAA;ADy3BJ;;ACj5BE;EAuBE,+BAAA;EACA,gCAAA;AD83BJ;;ACt5BE;EAuBE,+BAAA;EACA,gCAAA;ADm4BJ;;AC35BE;EAuBE,gCAAA;EACA,iCAAA;ADw4BJ;;ACh6BE;EAuBE,gCAAA;EACA,iCAAA;AD64BJ;;ACr6BE;EAuBE,gCAAA;EACA,iCAAA;ADk5BJ;;AC16BE;EAuBE,gCAAA;EACA,iCAAA;ADu5BJ;;AC/6BE;EAuBE,gCAAA;EACA,iCAAA;AD45BJ;;ACp7BE;EAuBE,gCAAA;EACA,iCAAA;ADi6BJ;;ACz7BE;EAuBE,gCAAA;EACA,iCAAA;ADs6BJ;;AC97BE;EAuBE,gCAAA;EACA,iCAAA;AD26BJ;;ACn8BE;EAuBE,gCAAA;EACA,iCAAA;ADg7BJ;;ACx8BE;EAuBE,gCAAA;EACA,iCAAA;ADq7BJ;;AC78BE;EAuBE,gCAAA;EACA,iCAAA;AD07BJ;;ACl9BE;EAuBE,gCAAA;EACA,iCAAA;AD+7BJ;;ACv9BE;EAuBE,gCAAA;EACA,iCAAA;ADo8BJ;;AC59BE;EAuBE,gCAAA;EACA,iCAAA;ADy8BJ;;ACj+BE;EAuBE,gCAAA;EACA,iCAAA;AD88BJ;;ACt+BE;EAuBE,gCAAA;EACA,iCAAA;ADm9BJ;;AC3+BE;EAuBE,gCAAA;EACA,iCAAA;ADw9BJ;;ACh/BE;EAuBE,gCAAA;EACA,iCAAA;AD69BJ;;ACr/BE;EAuBE,gCAAA;EACA,iCAAA;ADk+BJ;;AC1/BE;EAuBE,gCAAA;EACA,iCAAA;ADu+BJ;;AC//BE;EAuBE,gCAAA;EACA,iCAAA;AD4+BJ;;ACpgCE;EA4BE,4BAAA;EACA,+BAAA;AD4+BJ;;ACzgCE;EA4BE,4BAAA;EACA,+BAAA;ADi/BJ;;AC9gCE;EA4BE,4BAAA;EACA,+BAAA;ADs/BJ;;ACnhCE;EA4BE,4BAAA;EACA,+BAAA;AD2/BJ;;ACxhCE;EA4BE,4BAAA;EACA,+BAAA;ADggCJ;;AC7hCE;EA4BE,6BAAA;EACA,gCAAA;ADqgCJ;;ACliCE;EA4BE,6BAAA;EACA,gCAAA;AD0gCJ;;ACviCE;EA4BE,6BAAA;EACA,gCAAA;AD+gCJ;;AC5iCE;EA4BE,6BAAA;EACA,gCAAA;ADohCJ;;ACjjCE;EA4BE,6BAAA;EACA,gCAAA;ADyhCJ;;ACtjCE;EA4BE,6BAAA;EACA,gCAAA;AD8hCJ;;AC3jCE;EA4BE,6BAAA;EACA,gCAAA;ADmiCJ;;AChkCE;EA4BE,6BAAA;EACA,gCAAA;ADwiCJ;;ACrkCE;EA4BE,6BAAA;EACA,gCAAA;AD6iCJ;;AC1kCE;EA4BE,6BAAA;EACA,gCAAA;ADkjCJ;;AC/kCE;EA4BE,6BAAA;EACA,gCAAA;ADujCJ;;ACplCE;EA4BE,6BAAA;EACA,gCAAA;AD4jCJ;;ACzlCE;EA4BE,6BAAA;EACA,gCAAA;ADikCJ;;AC9lCE;EA4BE,6BAAA;EACA,gCAAA;ADskCJ;;ACnmCE;EA4BE,6BAAA;EACA,gCAAA;AD2kCJ;;ACxmCE;EA4BE,6BAAA;EACA,gCAAA;ADglCJ;;AC7mCE;EA4BE,6BAAA;EACA,gCAAA;ADqlCJ;;AClnCE;EA4BE,6BAAA;EACA,gCAAA;AD0lCJ;;ACvnCE;EA4BE,6BAAA;EACA,gCAAA;AD+lCJ;;AC5nCE;EA4BE,6BAAA;EACA,gCAAA;ADomCJ;;ACjoCE;EA4BE,6BAAA;EACA,gCAAA;ADymCJ;;ACtoCE;EAiCE,6BAAA;EACA,gCAAA;ADymCJ;;AC3oCE;EAiCE,6BAAA;EACA,gCAAA;AD8mCJ;;AChpCE;EAiCE,6BAAA;EACA,gCAAA;ADmnCJ;;ACrpCE;EAiCE,6BAAA;EACA,gCAAA;ADwnCJ;;AC1pCE;EAiCE,6BAAA;EACA,gCAAA;AD6nCJ;;AC/pCE;EAiCE,8BAAA;EACA,iCAAA;ADkoCJ;;ACpqCE;EAiCE,8BAAA;EACA,iCAAA;ADuoCJ;;ACzqCE;EAiCE,8BAAA;EACA,iCAAA;AD4oCJ;;AC9qCE;EAiCE,8BAAA;EACA,iCAAA;ADipCJ;;ACnrCE;EAiCE,8BAAA;EACA,iCAAA;ADspCJ;;ACxrCE;EAiCE,8BAAA;EACA,iCAAA;AD2pCJ;;AC7rCE;EAiCE,8BAAA;EACA,iCAAA;ADgqCJ;;AClsCE;EAiCE,8BAAA;EACA,iCAAA;ADqqCJ;;ACvsCE;EAiCE,8BAAA;EACA,iCAAA;AD0qCJ;;AC5sCE;EAiCE,8BAAA;EACA,iCAAA;AD+qCJ;;ACjtCE;EAiCE,8BAAA;EACA,iCAAA;ADorCJ;;ACttCE;EAiCE,8BAAA;EACA,iCAAA;ADyrCJ;;AC3tCE;EAiCE,8BAAA;EACA,iCAAA;AD8rCJ;;AChuCE;EAiCE,8BAAA;EACA,iCAAA;ADmsCJ;;ACruCE;EAiCE,8BAAA;EACA,iCAAA;ADwsCJ;;AC1uCE;EAiCE,8BAAA;EACA,iCAAA;AD6sCJ;;AC/uCE;EAiCE,8BAAA;EACA,iCAAA;ADktCJ;;ACpvCE;EAiCE,8BAAA;EACA,iCAAA;ADutCJ;;ACzvCE;EAiCE,8BAAA;EACA,iCAAA;AD4tCJ;;AC9vCE;EAiCE,8BAAA;EACA,iCAAA;ADiuCJ;;ACnwCE;EAiCE,8BAAA;EACA,iCAAA;ADsuCJ;;AC1tCC;EACC,mBAAA;AD6tCF;;AC9tCC;EACC,mBAAA;ADiuCF;;ACluCC;EACC,mBAAA;ADquCF;;ACtuCC;EACC,mBAAA;ADyuCF;;AC1uCC;EACC,mBAAA;AD6uCF;;AC9uCC;EACC,oBAAA;ADivCF;;AClvCC;EACC,oBAAA;ADqvCF;;ACtvCC;EACC,oBAAA;ADyvCF;;AC1vCC;EACC,oBAAA;AD6vCF;;AC9vCC;EACC,oBAAA;ADiwCF;;AClwCC;EACC,oBAAA;ADqwCF;;ACtwCC;EACC,oBAAA;ADywCF;;AC1wCC;EACC,oBAAA;AD6wCF;;AC9wCC;EACC,oBAAA;ADixCF;;AClxCC;EACC,oBAAA;ADqxCF;;ACtxCC;EACC,oBAAA;ADyxCF;;AC1xCC;EACC,oBAAA;AD6xCF;;AC9xCC;EACC,oBAAA;ADiyCF;;AClyCC;EACC,oBAAA;ADqyCF;;ACtyCC;EACC,oBAAA;ADyyCF;;AC1yCC;EACC,oBAAA;AD6yCF;;AC9yCC;EACC,oBAAA;ADizCF;;AClzCC;EACC,oBAAA;ADqzCF;;ACtzCC;EACC,oBAAA;ADyzCF;;AC1zCC;EACC,oBAAA;AD6zCF;;AC9zCC;EACC,oBAAA;ADi0CF;;ACl0CC;EACC,oBAAA;ADq0CF;;ACh0CA,0BAAA;AAEC;EACC,cAAA;ADk0CF;;ACn0CC;EACC,gBAAA;ADs0CF;;ACv0CC;EACC,gBAAA;AD00CF;;AC30CC;EACC,gBAAA;AD80CF;;AC/0CC;EACC,gBAAA;ADk1CF;;ACn1CC;EACC,gBAAA;ADs1CF;;ACv1CC;EACC,gBAAA;AD01CF;;AC31CC;EACC,gBAAA;AD81CF;;AC/1CC;EACC,gBAAA;ADk2CF;;ACn2CC;EACC,gBAAA;ADs2CF;;ACv2CC;EACC,cAAA;AD02CF;;AC32CC;EACC,gBAAA;AD82CF;;AC/2CC;EACC,gBAAA;ADk3CF;;ACn3CC;EACC,gBAAA;ADs3CF;;ACv3CC;EACC,gBAAA;AD03CF;;AC33CC;EACC,gBAAA;AD83CF;;AC/3CC;EACC,gBAAA;ADk4CF;;ACn4CC;EACC,gBAAA;ADs4CF;;ACv4CC;EACC,gBAAA;AD04CF;;AC34CC;EACC,gBAAA;AD84CF;;AC/4CC;EACC,cAAA;ADk5CF;;ACn5CC;EACC,gBAAA;ADs5CF;;AC94CC;EAME,UAAA;AD44CH;;ACl5CC;EAEE,YAAA;ADo5CH;;ACt5CC;EAEE,YAAA;ADw5CH;;AC15CC;EAEE,YAAA;AD45CH;;AC95CC;EAEE,YAAA;ADg6CH;;ACl6CC;EAEE,YAAA;ADo6CH;;ACt6CC;EAEE,YAAA;ADw6CH;;AC16CC;EAEE,YAAA;AD46CH;;AC96CC;EAEE,YAAA;ADg7CH;;ACl7CC;EAEE,YAAA;ADo7CH;;ACt7CC;EAUE,UAAA;ADg7CH;;ACx6CE;EACC,0BAAA;AD26CH;;ACx6CE;EACC,0BAAA;AD26CH;;ACr6CE;EACC,0BAAA;ADw6CH;;ACr6CE;EACC,0BAAA;ADw6CH;;AC76CE;EACC,0BAAA;ADg7CH;;AC76CE;EACC,0BAAA;ADg7CH;;ACr7CE;EACC,0BAAA;ADw7CH;;ACr7CE;EACC,0BAAA;ADw7CH;;AC77CE;EACC,0BAAA;ADg8CH;;AC77CE;EACC,0BAAA;ADg8CH;;ACr8CE;EACC,2BAAA;ADw8CH;;ACr8CE;EACC,2BAAA;ADw8CH;;ACh8CE;EAME,kCAAA;AD87CJ;;ACp8CE;EAME,kCAAA;ADk8CJ;;ACx8CE;EAME,kCAAA;ADs8CJ;;AC58CE;EAME,kCAAA;AD08CJ;;ACh9CE;EAME,mCAAA;AD88CJ;;ACp9CE;EAME,mCAAA;ADk9CJ;;ACx9CE;EAME,mCAAA;ADs9CJ;;AC59CE;EAME,mCAAA;AD09CJ;;ACh+CE;EAME,mCAAA;AD89CJ;;ACp+CE;EAME,oCAAA;ADk+CJ;;ACx+CE;EAME,iCAAA;ADs+CJ;;AC5+CE;EAME,iCAAA;AD0+CJ;;ACh/CE;EAME,iCAAA;AD8+CJ;;ACp/CE;EAME,iCAAA;ADk/CJ;;ACx/CE;EAME,kCAAA;ADs/CJ;;AC5/CE;EAME,oCAAA;AD0/CJ;;AChgDE;EAME,oCAAA;AD8/CJ;;ACpgDE;EAME,oCAAA;ADkgDJ;;ACxgDE;EAME,oCAAA;ADsgDJ;;AC5gDE;EAME,qCAAA;AD0gDJ;;AChhDE;EAEE,6BAAA;ADkhDJ;;ACphDE;EAEE,6BAAA;ADshDJ;;ACxhDE;EAEE,6BAAA;AD0hDJ;;AC5hDE;EAEE,6BAAA;AD8hDJ;;AChiDE;EAEE,8BAAA;ADkiDJ;;ACnhDG;EACC,aAAA;ADshDJ;;ACvhDG;EACC,aAAA;AD0hDJ;;AC3hDG;EACC,aAAA;AD8hDJ;;AC/hDG;EACC,aAAA;ADkiDJ;;ACniDG;EACC,aAAA;ADsiDJ;;ACviDG;EACC,aAAA;AD0iDJ;;AC3iDG;EACC,aAAA;AD8iDJ;;AC/iDG;EACC,aAAA;ADkjDJ;;ACnjDG;EACC,aAAA;ADsjDJ;;ACvjDG;EACC,aAAA;AD0jDJ;;AC3jDG;EACC,cAAA;AD8jDJ;;AC/jDG;EACC,cAAA;ADkkDJ;;ACnkDG;EACC,cAAA;ADskDJ;;ACvkDG;EACC,cAAA;AD0kDJ;;AC3kDG;EACC,cAAA;AD8kDJ;;AC/kDG;EACC,cAAA;ADklDJ;;ACnlDG;EACC,cAAA;ADslDJ;;ACvlDG;EACC,cAAA;AD0lDJ;;AC3lDG;EACC,cAAA;AD8lDJ;;AC/lDG;EACC,cAAA;ADkmDJ;;ACnmDG;EACC,cAAA;ADsmDJ;;ACvmDG;EACC,cAAA;AD0mDJ;;AC3mDG;EACC,cAAA;AD8mDJ;;AC/mDG;EACC,cAAA;ADknDJ;;ACnnDG;EACC,cAAA;ADsnDJ;;ACvnDG;EACC,cAAA;AD0nDJ;;AC3nDG;EACC,cAAA;AD8nDJ;;AC/nDG;EACC,cAAA;ADkoDJ;;ACnoDG;EACC,cAAA;ADsoDJ;;ACvoDG;EACC,cAAA;AD0oDJ;;AC3oDG;EACC,cAAA;AD8oDJ;;AC/oDG;EACC,cAAA;ADkpDJ;;ACnpDG;EACC,cAAA;ADspDJ;;ACvpDG;EACC,cAAA;AD0pDJ;;AC3pDG;EACC,cAAA;AD8pDJ;;AC/pDG;EACC,cAAA;ADkqDJ;;ACnqDG;EACC,cAAA;ADsqDJ;;ACvqDG;EACC,cAAA;AD0qDJ;;AC3qDG;EACC,cAAA;AD8qDJ;;AC/qDG;EACC,cAAA;ADkrDJ;;ACnrDG;EACC,cAAA;ADsrDJ;;ACvrDG;EACC,cAAA;AD0rDJ;;AC3rDG;EACC,cAAA;AD8rDJ;;AC/rDG;EACC,cAAA;ADksDJ;;ACnsDG;EACC,cAAA;ADssDJ;;ACvsDG;EACC,cAAA;AD0sDJ;;AC3sDG;EACC,cAAA;AD8sDJ;;AC/sDG;EACC,cAAA;ADktDJ;;ACntDG;EACC,cAAA;ADstDJ;;ACvtDG;EACC,cAAA;AD0tDJ;;AC3tDG;EACC,cAAA;AD8tDJ;;ACzsDG;EACC,aAAA;AD4sDJ;;AC7sDG;EACC,aAAA;ADgtDJ;;ACjtDG;EACC,cAAA;ADotDJ;;ACrtDG;EACC,cAAA;ADwtDJ;;ACztDG;EACC,cAAA;AD4tDJ;;AC7tDG;EACC,cAAA;ADguDJ;;ACjuDG;EACC,cAAA;ADouDJ;;ACruDG;EACC,cAAA;ADwuDJ;;ACzuDG;EACC,cAAA;AD4uDJ;;AC7uDG;EACC,cAAA;ADgvDJ;;ACjvDG;EACC,cAAA;ADovDJ;;ACrvDG;EACC,cAAA;ADwvDJ;;ACzvDG;EACC,cAAA;AD4vDJ;;AC7vDG;EACC,cAAA;ADgwDJ;;ACjwDG;EACC,cAAA;ADowDJ;;ACrwDG;EACC,cAAA;ADwwDJ;;ACzwDG;EACC,cAAA;AD4wDJ;;AC7wDG;EACC,cAAA;ADgxDJ;;ACjxDG;EACC,cAAA;ADoxDJ;;ACrxDG;EACC,cAAA;ADwxDJ;;ACzxDG;EACC,cAAA;AD4xDJ;;AC7xDG;EACC,cAAA;ADgyDJ;;ACjyDG;EACC,cAAA;ADoyDJ;;ACryDG;EACC,cAAA;ADwyDJ;;ACzyDG;EACC,eAAA;AD4yDJ;;ACn0DG;EACC,iBAAA;ADs0DJ;;ACv0DG;EACC,iBAAA;AD00DJ;;AC30DG;EACC,iBAAA;AD80DJ;;AC/0DG;EACC,iBAAA;ADk1DJ;;ACn1DG;EACC,iBAAA;ADs1DJ;;ACv1DG;EACC,iBAAA;AD01DJ;;AC31DG;EACC,iBAAA;AD81DJ;;AC/1DG;EACC,iBAAA;ADk2DJ;;ACn2DG;EACC,iBAAA;ADs2DJ;;ACv2DG;EACC,iBAAA;AD02DJ;;AC32DG;EACC,kBAAA;AD82DJ;;AC/2DG;EACC,kBAAA;ADk3DJ;;ACn3DG;EACC,kBAAA;ADs3DJ;;ACv3DG;EACC,kBAAA;AD03DJ;;AC33DG;EACC,kBAAA;AD83DJ;;AC/3DG;EACC,kBAAA;ADk4DJ;;ACn4DG;EACC,kBAAA;ADs4DJ;;ACv4DG;EACC,kBAAA;AD04DJ;;AC34DG;EACC,kBAAA;AD84DJ;;AC/4DG;EACC,kBAAA;ADk5DJ;;ACn5DG;EACC,kBAAA;ADs5DJ;;ACv5DG;EACC,kBAAA;AD05DJ;;AC35DG;EACC,kBAAA;AD85DJ;;AC/5DG;EACC,kBAAA;ADk6DJ;;ACn6DG;EACC,kBAAA;ADs6DJ;;ACv6DG;EACC,kBAAA;AD06DJ;;AC36DG;EACC,kBAAA;AD86DJ;;AC/6DG;EACC,kBAAA;ADk7DJ;;ACn7DG;EACC,kBAAA;ADs7DJ;;ACv7DG;EACC,kBAAA;AD07DJ;;AC37DG;EACC,kBAAA;AD87DJ;;AC/7DG;EACC,kBAAA;ADk8DJ;;ACn8DG;EACC,kBAAA;ADs8DJ;;ACv8DG;EACC,kBAAA;AD08DJ;;AC38DG;EACC,kBAAA;AD88DJ;;AC/8DG;EACC,kBAAA;ADk9DJ;;ACn9DG;EACC,kBAAA;ADs9DJ;;ACv9DG;EACC,kBAAA;AD09DJ;;AC39DG;EACC,kBAAA;AD89DJ;;AC/9DG;EACC,kBAAA;ADk+DJ;;ACn+DG;EACC,kBAAA;ADs+DJ;;ACv+DG;EACC,kBAAA;AD0+DJ;;AC3+DG;EACC,kBAAA;AD8+DJ;;AC/+DG;EACC,kBAAA;ADk/DJ;;ACn/DG;EACC,kBAAA;ADs/DJ;;ACv/DG;EACC,kBAAA;AD0/DJ;;AC3/DG;EACC,kBAAA;AD8/DJ;;AC//DG;EACC,kBAAA;ADkgEJ;;ACngEG;EACC,kBAAA;ADsgEJ;;ACvgEG;EACC,kBAAA;AD0gEJ;;AC3gEG;EACC,kBAAA;AD8gEJ;;ACz/DG;EACC,iBAAA;AD4/DJ;;AC7/DG;EACC,iBAAA;ADggEJ;;ACjgEG;EACC,kBAAA;ADogEJ;;ACrgEG;EACC,kBAAA;ADwgEJ;;ACzgEG;EACC,kBAAA;AD4gEJ;;AC7gEG;EACC,kBAAA;ADghEJ;;ACjhEG;EACC,kBAAA;ADohEJ;;ACrhEG;EACC,kBAAA;ADwhEJ;;ACzhEG;EACC,kBAAA;AD4hEJ;;AC7hEG;EACC,kBAAA;ADgiEJ;;ACjiEG;EACC,kBAAA;ADoiEJ;;ACriEG;EACC,kBAAA;ADwiEJ;;ACziEG;EACC,kBAAA;AD4iEJ;;AC7iEG;EACC,kBAAA;ADgjEJ;;ACjjEG;EACC,kBAAA;ADojEJ;;ACrjEG;EACC,kBAAA;ADwjEJ;;ACzjEG;EACC,kBAAA;AD4jEJ;;AC7jEG;EACC,kBAAA;ADgkEJ;;ACjkEG;EACC,kBAAA;ADokEJ;;ACrkEG;EACC,kBAAA;ADwkEJ;;ACzkEG;EACC,kBAAA;AD4kEJ;;AC7kEG;EACC,kBAAA;ADglEJ;;ACjlEG;EACC,kBAAA;ADolEJ;;ACrlEG;EACC,kBAAA;ADwlEJ;;ACzlEG;EACC,mBAAA;AD4lEJ;;ACnnEG;EACC,mBAAA;ADsnEJ;;ACvnEG;EACC,mBAAA;AD0nEJ;;AC3nEG;EACC,mBAAA;AD8nEJ;;AC/nEG;EACC,mBAAA;ADkoEJ;;ACnoEG;EACC,mBAAA;ADsoEJ;;ACvoEG;EACC,mBAAA;AD0oEJ;;AC3oEG;EACC,mBAAA;AD8oEJ;;AC/oEG;EACC,mBAAA;ADkpEJ;;ACnpEG;EACC,mBAAA;ADspEJ;;ACvpEG;EACC,mBAAA;AD0pEJ;;AC3pEG;EACC,oBAAA;AD8pEJ;;AC/pEG;EACC,oBAAA;ADkqEJ;;ACnqEG;EACC,oBAAA;ADsqEJ;;ACvqEG;EACC,oBAAA;AD0qEJ;;AC3qEG;EACC,oBAAA;AD8qEJ;;AC/qEG;EACC,oBAAA;ADkrEJ;;ACnrEG;EACC,oBAAA;ADsrEJ;;ACvrEG;EACC,oBAAA;AD0rEJ;;AC3rEG;EACC,oBAAA;AD8rEJ;;AC/rEG;EACC,oBAAA;ADksEJ;;ACnsEG;EACC,oBAAA;ADssEJ;;ACvsEG;EACC,oBAAA;AD0sEJ;;AC3sEG;EACC,oBAAA;AD8sEJ;;AC/sEG;EACC,oBAAA;ADktEJ;;ACntEG;EACC,oBAAA;ADstEJ;;ACvtEG;EACC,oBAAA;AD0tEJ;;AC3tEG;EACC,oBAAA;AD8tEJ;;AC/tEG;EACC,oBAAA;ADkuEJ;;ACnuEG;EACC,oBAAA;ADsuEJ;;ACvuEG;EACC,oBAAA;AD0uEJ;;AC3uEG;EACC,oBAAA;AD8uEJ;;AC/uEG;EACC,oBAAA;ADkvEJ;;ACnvEG;EACC,oBAAA;ADsvEJ;;ACvvEG;EACC,oBAAA;AD0vEJ;;AC3vEG;EACC,oBAAA;AD8vEJ;;AC/vEG;EACC,oBAAA;ADkwEJ;;ACnwEG;EACC,oBAAA;ADswEJ;;ACvwEG;EACC,oBAAA;AD0wEJ;;AC3wEG;EACC,oBAAA;AD8wEJ;;AC/wEG;EACC,oBAAA;ADkxEJ;;ACnxEG;EACC,oBAAA;ADsxEJ;;ACvxEG;EACC,oBAAA;AD0xEJ;;AC3xEG;EACC,oBAAA;AD8xEJ;;AC/xEG;EACC,oBAAA;ADkyEJ;;ACnyEG;EACC,oBAAA;ADsyEJ;;ACvyEG;EACC,oBAAA;AD0yEJ;;AC3yEG;EACC,oBAAA;AD8yEJ;;AC/yEG;EACC,oBAAA;ADkzEJ;;ACnzEG;EACC,oBAAA;ADszEJ;;ACvzEG;EACC,oBAAA;AD0zEJ;;AC3zEG;EACC,oBAAA;AD8zEJ;;ACzyEG;EACC,mBAAA;AD4yEJ;;AC7yEG;EACC,mBAAA;ADgzEJ;;ACjzEG;EACC,oBAAA;ADozEJ;;ACrzEG;EACC,oBAAA;ADwzEJ;;ACzzEG;EACC,oBAAA;AD4zEJ;;AC7zEG;EACC,oBAAA;ADg0EJ;;ACj0EG;EACC,oBAAA;ADo0EJ;;ACr0EG;EACC,oBAAA;ADw0EJ;;ACz0EG;EACC,oBAAA;AD40EJ;;AC70EG;EACC,oBAAA;ADg1EJ;;ACj1EG;EACC,oBAAA;ADo1EJ;;ACr1EG;EACC,oBAAA;ADw1EJ;;ACz1EG;EACC,oBAAA;AD41EJ;;AC71EG;EACC,oBAAA;ADg2EJ;;ACj2EG;EACC,oBAAA;ADo2EJ;;ACr2EG;EACC,oBAAA;ADw2EJ;;ACz2EG;EACC,oBAAA;AD42EJ;;AC72EG;EACC,oBAAA;ADg3EJ;;ACj3EG;EACC,oBAAA;ADo3EJ;;ACr3EG;EACC,oBAAA;ADw3EJ;;ACz3EG;EACC,oBAAA;AD43EJ;;AC73EG;EACC,oBAAA;ADg4EJ;;ACj4EG;EACC,oBAAA;ADo4EJ;;ACr4EG;EACC,oBAAA;ADw4EJ;;ACz4EG;EACC,qBAAA;AD44EJ;;ACn6EG;EACC,oBAAA;ADs6EJ;;ACv6EG;EACC,oBAAA;AD06EJ;;AC36EG;EACC,oBAAA;AD86EJ;;AC/6EG;EACC,oBAAA;ADk7EJ;;ACn7EG;EACC,oBAAA;ADs7EJ;;ACv7EG;EACC,oBAAA;AD07EJ;;AC37EG;EACC,oBAAA;AD87EJ;;AC/7EG;EACC,oBAAA;ADk8EJ;;ACn8EG;EACC,oBAAA;ADs8EJ;;ACv8EG;EACC,oBAAA;AD08EJ;;AC38EG;EACC,qBAAA;AD88EJ;;AC/8EG;EACC,qBAAA;ADk9EJ;;ACn9EG;EACC,qBAAA;ADs9EJ;;ACv9EG;EACC,qBAAA;AD09EJ;;AC39EG;EACC,qBAAA;AD89EJ;;AC/9EG;EACC,qBAAA;ADk+EJ;;ACn+EG;EACC,qBAAA;ADs+EJ;;ACv+EG;EACC,qBAAA;AD0+EJ;;AC3+EG;EACC,qBAAA;AD8+EJ;;AC/+EG;EACC,qBAAA;ADk/EJ;;ACn/EG;EACC,qBAAA;ADs/EJ;;ACv/EG;EACC,qBAAA;AD0/EJ;;AC3/EG;EACC,qBAAA;AD8/EJ;;AC//EG;EACC,qBAAA;ADkgFJ;;ACngFG;EACC,qBAAA;ADsgFJ;;ACvgFG;EACC,qBAAA;AD0gFJ;;AC3gFG;EACC,qBAAA;AD8gFJ;;AC/gFG;EACC,qBAAA;ADkhFJ;;ACnhFG;EACC,qBAAA;ADshFJ;;ACvhFG;EACC,qBAAA;AD0hFJ;;AC3hFG;EACC,qBAAA;AD8hFJ;;AC/hFG;EACC,qBAAA;ADkiFJ;;ACniFG;EACC,qBAAA;ADsiFJ;;ACviFG;EACC,qBAAA;AD0iFJ;;AC3iFG;EACC,qBAAA;AD8iFJ;;AC/iFG;EACC,qBAAA;ADkjFJ;;ACnjFG;EACC,qBAAA;ADsjFJ;;ACvjFG;EACC,qBAAA;AD0jFJ;;AC3jFG;EACC,qBAAA;AD8jFJ;;AC/jFG;EACC,qBAAA;ADkkFJ;;ACnkFG;EACC,qBAAA;ADskFJ;;ACvkFG;EACC,qBAAA;AD0kFJ;;AC3kFG;EACC,qBAAA;AD8kFJ;;AC/kFG;EACC,qBAAA;ADklFJ;;ACnlFG;EACC,qBAAA;ADslFJ;;ACvlFG;EACC,qBAAA;AD0lFJ;;AC3lFG;EACC,qBAAA;AD8lFJ;;AC/lFG;EACC,qBAAA;ADkmFJ;;ACnmFG;EACC,qBAAA;ADsmFJ;;ACvmFG;EACC,qBAAA;AD0mFJ;;AC3mFG;EACC,qBAAA;AD8mFJ;;ACzlFG;EACC,oBAAA;AD4lFJ;;AC7lFG;EACC,oBAAA;ADgmFJ;;ACjmFG;EACC,qBAAA;ADomFJ;;ACrmFG;EACC,qBAAA;ADwmFJ;;ACzmFG;EACC,qBAAA;AD4mFJ;;AC7mFG;EACC,qBAAA;ADgnFJ;;ACjnFG;EACC,qBAAA;ADonFJ;;ACrnFG;EACC,qBAAA;ADwnFJ;;ACznFG;EACC,qBAAA;AD4nFJ;;AC7nFG;EACC,qBAAA;ADgoFJ;;ACjoFG;EACC,qBAAA;ADooFJ;;ACroFG;EACC,qBAAA;ADwoFJ;;ACzoFG;EACC,qBAAA;AD4oFJ;;AC7oFG;EACC,qBAAA;ADgpFJ;;ACjpFG;EACC,qBAAA;ADopFJ;;ACrpFG;EACC,qBAAA;ADwpFJ;;ACzpFG;EACC,qBAAA;AD4pFJ;;AC7pFG;EACC,qBAAA;ADgqFJ;;ACjqFG;EACC,qBAAA;ADoqFJ;;ACrqFG;EACC,qBAAA;ADwqFJ;;ACzqFG;EACC,qBAAA;AD4qFJ;;AC7qFG;EACC,qBAAA;ADgrFJ;;ACjrFG;EACC,qBAAA;ADorFJ;;ACrrFG;EACC,qBAAA;ADwrFJ;;ACzrFG;EACC,sBAAA;AD4rFJ;;ACntFG;EACC,kBAAA;ADstFJ;;ACvtFG;EACC,kBAAA;AD0tFJ;;AC3tFG;EACC,kBAAA;AD8tFJ;;AC/tFG;EACC,kBAAA;ADkuFJ;;ACnuFG;EACC,kBAAA;ADsuFJ;;ACvuFG;EACC,kBAAA;AD0uFJ;;AC3uFG;EACC,kBAAA;AD8uFJ;;AC/uFG;EACC,kBAAA;ADkvFJ;;ACnvFG;EACC,kBAAA;ADsvFJ;;ACvvFG;EACC,kBAAA;AD0vFJ;;AC3vFG;EACC,mBAAA;AD8vFJ;;AC/vFG;EACC,mBAAA;ADkwFJ;;ACnwFG;EACC,mBAAA;ADswFJ;;ACvwFG;EACC,mBAAA;AD0wFJ;;AC3wFG;EACC,mBAAA;AD8wFJ;;AC/wFG;EACC,mBAAA;ADkxFJ;;ACnxFG;EACC,mBAAA;ADsxFJ;;ACvxFG;EACC,mBAAA;AD0xFJ;;AC3xFG;EACC,mBAAA;AD8xFJ;;AC/xFG;EACC,mBAAA;ADkyFJ;;ACnyFG;EACC,mBAAA;ADsyFJ;;ACvyFG;EACC,mBAAA;AD0yFJ;;AC3yFG;EACC,mBAAA;AD8yFJ;;AC/yFG;EACC,mBAAA;ADkzFJ;;ACnzFG;EACC,mBAAA;ADszFJ;;ACvzFG;EACC,mBAAA;AD0zFJ;;AC3zFG;EACC,mBAAA;AD8zFJ;;AC/zFG;EACC,mBAAA;ADk0FJ;;ACn0FG;EACC,mBAAA;ADs0FJ;;ACv0FG;EACC,mBAAA;AD00FJ;;AC30FG;EACC,mBAAA;AD80FJ;;AC/0FG;EACC,mBAAA;ADk1FJ;;ACn1FG;EACC,mBAAA;ADs1FJ;;ACv1FG;EACC,mBAAA;AD01FJ;;AC31FG;EACC,mBAAA;AD81FJ;;AC/1FG;EACC,mBAAA;ADk2FJ;;ACn2FG;EACC,mBAAA;ADs2FJ;;ACv2FG;EACC,mBAAA;AD02FJ;;AC32FG;EACC,mBAAA;AD82FJ;;AC/2FG;EACC,mBAAA;ADk3FJ;;ACn3FG;EACC,mBAAA;ADs3FJ;;ACv3FG;EACC,mBAAA;AD03FJ;;AC33FG;EACC,mBAAA;AD83FJ;;AC/3FG;EACC,mBAAA;ADk4FJ;;ACn4FG;EACC,mBAAA;ADs4FJ;;ACv4FG;EACC,mBAAA;AD04FJ;;AC34FG;EACC,mBAAA;AD84FJ;;AC/4FG;EACC,mBAAA;ADk5FJ;;ACn5FG;EACC,mBAAA;ADs5FJ;;ACv5FG;EACC,mBAAA;AD05FJ;;AC35FG;EACC,mBAAA;AD85FJ;;ACz4FG;EACC,kBAAA;AD44FJ;;AC74FG;EACC,kBAAA;ADg5FJ;;ACj5FG;EACC,mBAAA;ADo5FJ;;ACr5FG;EACC,mBAAA;ADw5FJ;;ACz5FG;EACC,mBAAA;AD45FJ;;AC75FG;EACC,mBAAA;ADg6FJ;;ACj6FG;EACC,mBAAA;ADo6FJ;;ACr6FG;EACC,mBAAA;ADw6FJ;;ACz6FG;EACC,mBAAA;AD46FJ;;AC76FG;EACC,mBAAA;ADg7FJ;;ACj7FG;EACC,mBAAA;ADo7FJ;;ACr7FG;EACC,mBAAA;ADw7FJ;;ACz7FG;EACC,mBAAA;AD47FJ;;AC77FG;EACC,mBAAA;ADg8FJ;;ACj8FG;EACC,mBAAA;ADo8FJ;;ACr8FG;EACC,mBAAA;ADw8FJ;;ACz8FG;EACC,mBAAA;AD48FJ;;AC78FG;EACC,mBAAA;ADg9FJ;;ACj9FG;EACC,mBAAA;ADo9FJ;;ACr9FG;EACC,mBAAA;ADw9FJ;;ACz9FG;EACC,mBAAA;AD49FJ;;AC79FG;EACC,mBAAA;ADg+FJ;;ACj+FG;EACC,mBAAA;ADo+FJ;;ACr+FG;EACC,mBAAA;ADw+FJ;;ACz+FG;EACC,oBAAA;AD4+FJ;;AC7/FG;EACC,kBAAA;EACA,mBAAA;ADggGJ;;AClgGG;EACC,kBAAA;EACA,mBAAA;ADqgGJ;;ACvgGG;EACC,kBAAA;EACA,mBAAA;AD0gGJ;;AC5gGG;EACC,kBAAA;EACA,mBAAA;AD+gGJ;;ACjhGG;EACC,kBAAA;EACA,mBAAA;ADohGJ;;ACthGG;EACC,kBAAA;EACA,mBAAA;ADyhGJ;;AC3hGG;EACC,kBAAA;EACA,mBAAA;AD8hGJ;;AChiGG;EACC,kBAAA;EACA,mBAAA;ADmiGJ;;ACriGG;EACC,kBAAA;EACA,mBAAA;ADwiGJ;;AC1iGG;EACC,kBAAA;EACA,mBAAA;AD6iGJ;;AC/iGG;EACC,mBAAA;EACA,oBAAA;ADkjGJ;;ACpjGG;EACC,mBAAA;EACA,oBAAA;ADujGJ;;ACzjGG;EACC,mBAAA;EACA,oBAAA;AD4jGJ;;AC9jGG;EACC,mBAAA;EACA,oBAAA;ADikGJ;;ACnkGG;EACC,mBAAA;EACA,oBAAA;ADskGJ;;ACxkGG;EACC,mBAAA;EACA,oBAAA;AD2kGJ;;AC7kGG;EACC,mBAAA;EACA,oBAAA;ADglGJ;;ACllGG;EACC,mBAAA;EACA,oBAAA;ADqlGJ;;ACvlGG;EACC,mBAAA;EACA,oBAAA;AD0lGJ;;AC5lGG;EACC,mBAAA;EACA,oBAAA;AD+lGJ;;ACjmGG;EACC,mBAAA;EACA,oBAAA;ADomGJ;;ACtmGG;EACC,mBAAA;EACA,oBAAA;ADymGJ;;AC3mGG;EACC,mBAAA;EACA,oBAAA;AD8mGJ;;AChnGG;EACC,mBAAA;EACA,oBAAA;ADmnGJ;;ACrnGG;EACC,mBAAA;EACA,oBAAA;ADwnGJ;;AC1nGG;EACC,mBAAA;EACA,oBAAA;AD6nGJ;;AC/nGG;EACC,mBAAA;EACA,oBAAA;ADkoGJ;;ACpoGG;EACC,mBAAA;EACA,oBAAA;ADuoGJ;;ACzoGG;EACC,mBAAA;EACA,oBAAA;AD4oGJ;;AC9oGG;EACC,mBAAA;EACA,oBAAA;ADipGJ;;ACnpGG;EACC,mBAAA;EACA,oBAAA;ADspGJ;;ACxpGG;EACC,mBAAA;EACA,oBAAA;AD2pGJ;;AC7pGG;EACC,mBAAA;EACA,oBAAA;ADgqGJ;;AClqGG;EACC,mBAAA;EACA,oBAAA;ADqqGJ;;ACvqGG;EACC,mBAAA;EACA,oBAAA;AD0qGJ;;AC5qGG;EACC,mBAAA;EACA,oBAAA;AD+qGJ;;ACjrGG;EACC,mBAAA;EACA,oBAAA;ADorGJ;;ACtrGG;EACC,mBAAA;EACA,oBAAA;ADyrGJ;;AC3rGG;EACC,mBAAA;EACA,oBAAA;AD8rGJ;;AChsGG;EACC,mBAAA;EACA,oBAAA;ADmsGJ;;ACrsGG;EACC,mBAAA;EACA,oBAAA;ADwsGJ;;AC1sGG;EACC,mBAAA;EACA,oBAAA;AD6sGJ;;AC/sGG;EACC,mBAAA;EACA,oBAAA;ADktGJ;;ACptGG;EACC,mBAAA;EACA,oBAAA;ADutGJ;;ACztGG;EACC,mBAAA;EACA,oBAAA;AD4tGJ;;AC9tGG;EACC,mBAAA;EACA,oBAAA;ADiuGJ;;ACnuGG;EACC,mBAAA;EACA,oBAAA;ADsuGJ;;ACxuGG;EACC,mBAAA;EACA,oBAAA;AD2uGJ;;AC7uGG;EACC,mBAAA;EACA,oBAAA;ADgvGJ;;AClvGG;EACC,mBAAA;EACA,oBAAA;ADqvGJ;;ACvvGG;EACC,mBAAA;EACA,oBAAA;AD0vGJ;;ACtuGG;EACC,kBAAA;EACA,mBAAA;ADyuGJ;;AC3uGG;EACC,kBAAA;EACA,mBAAA;AD8uGJ;;AChvGG;EACC,mBAAA;EACA,oBAAA;ADmvGJ;;ACrvGG;EACC,mBAAA;EACA,oBAAA;ADwvGJ;;AC1vGG;EACC,mBAAA;EACA,oBAAA;AD6vGJ;;AC/vGG;EACC,mBAAA;EACA,oBAAA;ADkwGJ;;ACpwGG;EACC,mBAAA;EACA,oBAAA;ADuwGJ;;ACzwGG;EACC,mBAAA;EACA,oBAAA;AD4wGJ;;AC9wGG;EACC,mBAAA;EACA,oBAAA;ADixGJ;;ACnxGG;EACC,mBAAA;EACA,oBAAA;ADsxGJ;;ACxxGG;EACC,mBAAA;EACA,oBAAA;AD2xGJ;;AC7xGG;EACC,mBAAA;EACA,oBAAA;ADgyGJ;;AClyGG;EACC,mBAAA;EACA,oBAAA;ADqyGJ;;ACvyGG;EACC,mBAAA;EACA,oBAAA;AD0yGJ;;AC5yGG;EACC,mBAAA;EACA,oBAAA;AD+yGJ;;ACjzGG;EACC,mBAAA;EACA,oBAAA;ADozGJ;;ACtzGG;EACC,mBAAA;EACA,oBAAA;ADyzGJ;;AC3zGG;EACC,mBAAA;EACA,oBAAA;AD8zGJ;;ACh0GG;EACC,mBAAA;EACA,oBAAA;ADm0GJ;;ACr0GG;EACC,mBAAA;EACA,oBAAA;ADw0GJ;;AC10GG;EACC,mBAAA;EACA,oBAAA;AD60GJ;;AC/0GG;EACC,mBAAA;EACA,oBAAA;ADk1GJ;;ACp1GG;EACC,mBAAA;EACA,oBAAA;ADu1GJ;;ACz1GG;EACC,mBAAA;EACA,oBAAA;AD41GJ;;AC91GG;EACC,oBAAA;EACA,qBAAA;ADi2GJ;;ACl3GG;EACC,iBAAA;EACA,oBAAA;ADq3GJ;;ACv3GG;EACC,iBAAA;EACA,oBAAA;AD03GJ;;AC53GG;EACC,iBAAA;EACA,oBAAA;AD+3GJ;;ACj4GG;EACC,iBAAA;EACA,oBAAA;ADo4GJ;;ACt4GG;EACC,iBAAA;EACA,oBAAA;ADy4GJ;;AC34GG;EACC,iBAAA;EACA,oBAAA;AD84GJ;;ACh5GG;EACC,iBAAA;EACA,oBAAA;ADm5GJ;;ACr5GG;EACC,iBAAA;EACA,oBAAA;ADw5GJ;;AC15GG;EACC,iBAAA;EACA,oBAAA;AD65GJ;;AC/5GG;EACC,iBAAA;EACA,oBAAA;ADk6GJ;;ACp6GG;EACC,kBAAA;EACA,qBAAA;ADu6GJ;;ACz6GG;EACC,kBAAA;EACA,qBAAA;AD46GJ;;AC96GG;EACC,kBAAA;EACA,qBAAA;ADi7GJ;;ACn7GG;EACC,kBAAA;EACA,qBAAA;ADs7GJ;;ACx7GG;EACC,kBAAA;EACA,qBAAA;AD27GJ;;AC77GG;EACC,kBAAA;EACA,qBAAA;ADg8GJ;;ACl8GG;EACC,kBAAA;EACA,qBAAA;ADq8GJ;;ACv8GG;EACC,kBAAA;EACA,qBAAA;AD08GJ;;AC58GG;EACC,kBAAA;EACA,qBAAA;AD+8GJ;;ACj9GG;EACC,kBAAA;EACA,qBAAA;ADo9GJ;;ACt9GG;EACC,kBAAA;EACA,qBAAA;ADy9GJ;;AC39GG;EACC,kBAAA;EACA,qBAAA;AD89GJ;;ACh+GG;EACC,kBAAA;EACA,qBAAA;ADm+GJ;;ACr+GG;EACC,kBAAA;EACA,qBAAA;ADw+GJ;;AC1+GG;EACC,kBAAA;EACA,qBAAA;AD6+GJ;;AC/+GG;EACC,kBAAA;EACA,qBAAA;ADk/GJ;;ACp/GG;EACC,kBAAA;EACA,qBAAA;ADu/GJ;;ACz/GG;EACC,kBAAA;EACA,qBAAA;AD4/GJ;;AC9/GG;EACC,kBAAA;EACA,qBAAA;ADigHJ;;ACngHG;EACC,kBAAA;EACA,qBAAA;ADsgHJ;;ACxgHG;EACC,kBAAA;EACA,qBAAA;AD2gHJ;;AC7gHG;EACC,kBAAA;EACA,qBAAA;ADghHJ;;AClhHG;EACC,kBAAA;EACA,qBAAA;ADqhHJ;;ACvhHG;EACC,kBAAA;EACA,qBAAA;AD0hHJ;;AC5hHG;EACC,kBAAA;EACA,qBAAA;AD+hHJ;;ACjiHG;EACC,kBAAA;EACA,qBAAA;ADoiHJ;;ACtiHG;EACC,kBAAA;EACA,qBAAA;ADyiHJ;;AC3iHG;EACC,kBAAA;EACA,qBAAA;AD8iHJ;;AChjHG;EACC,kBAAA;EACA,qBAAA;ADmjHJ;;ACrjHG;EACC,kBAAA;EACA,qBAAA;ADwjHJ;;AC1jHG;EACC,kBAAA;EACA,qBAAA;AD6jHJ;;AC/jHG;EACC,kBAAA;EACA,qBAAA;ADkkHJ;;ACpkHG;EACC,kBAAA;EACA,qBAAA;ADukHJ;;ACzkHG;EACC,kBAAA;EACA,qBAAA;AD4kHJ;;AC9kHG;EACC,kBAAA;EACA,qBAAA;ADilHJ;;ACnlHG;EACC,kBAAA;EACA,qBAAA;ADslHJ;;ACxlHG;EACC,kBAAA;EACA,qBAAA;AD2lHJ;;AC7lHG;EACC,kBAAA;EACA,qBAAA;ADgmHJ;;AClmHG;EACC,kBAAA;EACA,qBAAA;ADqmHJ;;ACvmHG;EACC,kBAAA;EACA,qBAAA;AD0mHJ;;AC5mHG;EACC,kBAAA;EACA,qBAAA;AD+mHJ;;AC3lHG;EACC,iBAAA;EACA,oBAAA;AD8lHJ;;AChmHG;EACC,iBAAA;EACA,oBAAA;ADmmHJ;;ACrmHG;EACC,kBAAA;EACA,qBAAA;ADwmHJ;;AC1mHG;EACC,kBAAA;EACA,qBAAA;AD6mHJ;;AC/mHG;EACC,kBAAA;EACA,qBAAA;ADknHJ;;ACpnHG;EACC,kBAAA;EACA,qBAAA;ADunHJ;;ACznHG;EACC,kBAAA;EACA,qBAAA;AD4nHJ;;AC9nHG;EACC,kBAAA;EACA,qBAAA;ADioHJ;;ACnoHG;EACC,kBAAA;EACA,qBAAA;ADsoHJ;;ACxoHG;EACC,kBAAA;EACA,qBAAA;AD2oHJ;;AC7oHG;EACC,kBAAA;EACA,qBAAA;ADgpHJ;;AClpHG;EACC,kBAAA;EACA,qBAAA;ADqpHJ;;ACvpHG;EACC,kBAAA;EACA,qBAAA;AD0pHJ;;AC5pHG;EACC,kBAAA;EACA,qBAAA;AD+pHJ;;ACjqHG;EACC,kBAAA;EACA,qBAAA;ADoqHJ;;ACtqHG;EACC,kBAAA;EACA,qBAAA;ADyqHJ;;AC3qHG;EACC,kBAAA;EACA,qBAAA;AD8qHJ;;AChrHG;EACC,kBAAA;EACA,qBAAA;ADmrHJ;;ACrrHG;EACC,kBAAA;EACA,qBAAA;ADwrHJ;;AC1rHG;EACC,kBAAA;EACA,qBAAA;AD6rHJ;;AC/rHG;EACC,kBAAA;EACA,qBAAA;ADksHJ;;ACpsHG;EACC,kBAAA;EACA,qBAAA;ADusHJ;;ACzsHG;EACC,kBAAA;EACA,qBAAA;AD4sHJ;;AC9sHG;EACC,kBAAA;EACA,qBAAA;ADitHJ;;ACntHG;EACC,mBAAA;EACA,sBAAA;ADstHJ;;AC5sHG;EACC,YAAA;AD+sHJ;;AChtHG;EACC,YAAA;ADmtHJ;;ACptHG;EACC,YAAA;ADutHJ;;ACxtHG;EACC,YAAA;AD2tHJ;;AC5tHG;EACC,YAAA;AD+tHJ;;AChuHG;EACC,YAAA;ADmuHJ;;ACpuHG;EACC,YAAA;ADuuHJ;;ACxuHG;EACC,YAAA;AD2uHJ;;AC5uHG;EACC,YAAA;AD+uHJ;;AChvHG;EACC,YAAA;ADmvHJ;;ACpvHG;EACC,aAAA;ADuvHJ;;ACxvHG;EACC,aAAA;AD2vHJ;;AC5vHG;EACC,aAAA;AD+vHJ;;AChwHG;EACC,aAAA;ADmwHJ;;ACpwHG;EACC,aAAA;ADuwHJ;;ACxwHG;EACC,aAAA;AD2wHJ;;AC5wHG;EACC,aAAA;AD+wHJ;;AChxHG;EACC,aAAA;ADmxHJ;;ACpxHG;EACC,aAAA;ADuxHJ;;ACxxHG;EACC,aAAA;AD2xHJ;;AC5xHG;EACC,aAAA;AD+xHJ;;AChyHG;EACC,aAAA;ADmyHJ;;ACpyHG;EACC,aAAA;ADuyHJ;;ACxyHG;EACC,aAAA;AD2yHJ;;AC5yHG;EACC,aAAA;AD+yHJ;;AChzHG;EACC,aAAA;ADmzHJ;;ACpzHG;EACC,aAAA;ADuzHJ;;ACxzHG;EACC,aAAA;AD2zHJ;;AC5zHG;EACC,aAAA;AD+zHJ;;ACh0HG;EACC,aAAA;ADm0HJ;;ACp0HG;EACC,aAAA;ADu0HJ;;ACx0HG;EACC,aAAA;AD20HJ;;AC50HG;EACC,aAAA;AD+0HJ;;ACh1HG;EACC,aAAA;ADm1HJ;;ACp1HG;EACC,aAAA;ADu1HJ;;ACx1HG;EACC,aAAA;AD21HJ;;AC51HG;EACC,aAAA;AD+1HJ;;ACh2HG;EACC,aAAA;ADm2HJ;;ACp2HG;EACC,aAAA;ADu2HJ;;ACx2HG;EACC,aAAA;AD22HJ;;AC52HG;EACC,aAAA;AD+2HJ;;ACh3HG;EACC,aAAA;ADm3HJ;;ACp3HG;EACC,aAAA;ADu3HJ;;ACx3HG;EACC,aAAA;AD23HJ;;AC53HG;EACC,aAAA;AD+3HJ;;ACh4HG;EACC,aAAA;ADm4HJ;;ACp4HG;EACC,aAAA;ADu4HJ;;ACx4HG;EACC,aAAA;AD24HJ;;AC54HG;EACC,aAAA;AD+4HJ;;ACh5HG;EACC,aAAA;ADm5HJ;;ACp5HG;EACC,aAAA;ADu5HJ;;AC73HG;EACC,YAAA;ADg4HJ;;ACj4HG;EACC,YAAA;ADo4HJ;;ACr4HG;EACC,aAAA;ADw4HJ;;ACz4HG;EACC,aAAA;AD44HJ;;AC74HG;EACC,aAAA;ADg5HJ;;ACj5HG;EACC,aAAA;ADo5HJ;;ACr5HG;EACC,aAAA;ADw5HJ;;ACz5HG;EACC,aAAA;AD45HJ;;AC75HG;EACC,aAAA;ADg6HJ;;ACj6HG;EACC,aAAA;ADo6HJ;;ACr6HG;EACC,aAAA;ADw6HJ;;ACz6HG;EACC,aAAA;AD46HJ;;AC76HG;EACC,aAAA;ADg7HJ;;ACj7HG;EACC,aAAA;ADo7HJ;;ACr7HG;EACC,aAAA;ADw7HJ;;ACz7HG;EACC,aAAA;AD47HJ;;AC77HG;EACC,aAAA;ADg8HJ;;ACj8HG;EACC,aAAA;ADo8HJ;;ACr8HG;EACC,aAAA;ADw8HJ;;ACz8HG;EACC,aAAA;AD48HJ;;AC78HG;EACC,aAAA;ADg9HJ;;ACj9HG;EACC,aAAA;ADo9HJ;;ACr9HG;EACC,aAAA;ADw9HJ;;ACz9HG;EACC,aAAA;AD49HJ;;AC79HG;EACC,cAAA;ADg+HJ;;AC5/HG;EACC,gBAAA;AD+/HJ;;AC3/HI;EACC,iBAAA;AD8/HL;;ACpgIG;EACC,gBAAA;ADugIJ;;ACngII;EACC,iBAAA;ADsgIL;;AC5gIG;EACC,gBAAA;AD+gIJ;;AC3gII;EACC,iBAAA;AD8gIL;;ACphIG;EACC,gBAAA;ADuhIJ;;ACnhII;EACC,iBAAA;ADshIL;;AC5hIG;EACC,gBAAA;AD+hIJ;;AC3hII;EACC,iBAAA;AD8hIL;;ACpiIG;EACC,gBAAA;ADuiIJ;;ACniII;EACC,iBAAA;ADsiIL;;AC5iIG;EACC,gBAAA;AD+iIJ;;AC3iII;EACC,iBAAA;AD8iIL;;ACpjIG;EACC,gBAAA;ADujIJ;;ACnjII;EACC,iBAAA;ADsjIL;;AC5jIG;EACC,gBAAA;AD+jIJ;;AC3jII;EACC,iBAAA;AD8jIL;;ACpkIG;EACC,gBAAA;ADukIJ;;ACnkII;EACC,iBAAA;ADskIL;;AC5kIG;EACC,iBAAA;AD+kIJ;;AC3kII;EACC,kBAAA;AD8kIL;;ACplIG;EACC,iBAAA;ADulIJ;;ACnlII;EACC,kBAAA;ADslIL;;AC5lIG;EACC,iBAAA;AD+lIJ;;AC3lII;EACC,kBAAA;AD8lIL;;ACpmIG;EACC,iBAAA;ADumIJ;;ACnmII;EACC,kBAAA;ADsmIL;;AC5mIG;EACC,iBAAA;AD+mIJ;;AC3mII;EACC,kBAAA;AD8mIL;;ACpnIG;EACC,iBAAA;ADunIJ;;ACnnII;EACC,kBAAA;ADsnIL;;AC5nIG;EACC,iBAAA;AD+nIJ;;AC3nII;EACC,kBAAA;AD8nIL;;ACpoIG;EACC,iBAAA;ADuoIJ;;ACnoII;EACC,kBAAA;ADsoIL;;AC5oIG;EACC,iBAAA;AD+oIJ;;AC3oII;EACC,kBAAA;AD8oIL;;ACppIG;EACC,iBAAA;ADupIJ;;ACnpII;EACC,kBAAA;ADspIL;;AC5pIG;EACC,iBAAA;AD+pIJ;;AC3pII;EACC,kBAAA;AD8pIL;;ACpqIG;EACC,iBAAA;ADuqIJ;;ACnqII;EACC,kBAAA;ADsqIL;;AC5qIG;EACC,iBAAA;AD+qIJ;;AC3qII;EACC,kBAAA;AD8qIL;;ACprIG;EACC,iBAAA;ADurIJ;;ACnrII;EACC,kBAAA;ADsrIL;;AC5rIG;EACC,iBAAA;AD+rIJ;;AC3rII;EACC,kBAAA;AD8rIL;;ACpsIG;EACC,iBAAA;ADusIJ;;ACnsII;EACC,kBAAA;ADssIL;;AC5sIG;EACC,iBAAA;AD+sIJ;;AC3sII;EACC,kBAAA;AD8sIL;;ACptIG;EACC,iBAAA;ADutIJ;;ACntII;EACC,kBAAA;ADstIL;;AC5tIG;EACC,iBAAA;AD+tIJ;;AC3tII;EACC,kBAAA;AD8tIL;;ACpuIG;EACC,iBAAA;ADuuIJ;;ACnuII;EACC,kBAAA;ADsuIL;;AC5uIG;EACC,iBAAA;AD+uIJ;;AC3uII;EACC,kBAAA;AD8uIL;;ACpvIG;EACC,iBAAA;ADuvIJ;;ACnvII;EACC,kBAAA;ADsvIL;;AC5vIG;EACC,iBAAA;AD+vIJ;;AC3vII;EACC,kBAAA;AD8vIL;;ACpwIG;EACC,iBAAA;ADuwIJ;;ACnwII;EACC,kBAAA;ADswIL;;AC5wIG;EACC,iBAAA;AD+wIJ;;AC3wII;EACC,kBAAA;AD8wIL;;ACpxIG;EACC,iBAAA;ADuxIJ;;ACnxII;EACC,kBAAA;ADsxIL;;AC5xIG;EACC,iBAAA;AD+xIJ;;AC3xII;EACC,kBAAA;AD8xIL;;ACpyIG;EACC,iBAAA;ADuyIJ;;ACnyII;EACC,kBAAA;ADsyIL;;AC5yIG;EACC,iBAAA;AD+yIJ;;AC3yII;EACC,kBAAA;AD8yIL;;ACpzIG;EACC,iBAAA;ADuzIJ;;ACnzII;EACC,kBAAA;ADszIL;;AC5zIG;EACC,iBAAA;AD+zIJ;;AC3zII;EACC,kBAAA;AD8zIL;;ACp0IG;EACC,iBAAA;ADu0IJ;;ACn0II;EACC,kBAAA;ADs0IL;;AC50IG;EACC,iBAAA;AD+0IJ;;AC30II;EACC,kBAAA;AD80IL;;ACp1IG;EACC,iBAAA;ADu1IJ;;ACn1II;EACC,kBAAA;ADs1IL;;AC51IG;EACC,iBAAA;AD+1IJ;;AC31II;EACC,kBAAA;AD81IL;;ACp2IG;EACC,iBAAA;ADu2IJ;;ACn2II;EACC,kBAAA;ADs2IL;;AC52IG;EACC,iBAAA;AD+2IJ;;AC32II;EACC,kBAAA;AD82IL;;ACp3IG;EACC,iBAAA;ADu3IJ;;ACn3II;EACC,kBAAA;ADs3IL;;AC53IG;EACC,iBAAA;AD+3IJ;;AC33II;EACC,kBAAA;AD83IL;;ACp4IG;EACC,iBAAA;ADu4IJ;;ACn4II;EACC,kBAAA;ADs4IL;;AC54IG;EACC,iBAAA;AD+4IJ;;AC34II;EACC,kBAAA;AD84IL;;ACz3IG;EACC,gBAAA;AD43IJ;;ACx3II;EACC,iBAAA;AD23IL;;ACj4IG;EACC,gBAAA;ADo4IJ;;ACh4II;EACC,iBAAA;ADm4IL;;ACz4IG;EACC,iBAAA;AD44IJ;;ACx4II;EACC,kBAAA;AD24IL;;ACj5IG;EACC,iBAAA;ADo5IJ;;ACh5II;EACC,kBAAA;ADm5IL;;ACz5IG;EACC,iBAAA;AD45IJ;;ACx5II;EACC,kBAAA;AD25IL;;ACj6IG;EACC,iBAAA;ADo6IJ;;ACh6II;EACC,kBAAA;ADm6IL;;ACz6IG;EACC,iBAAA;AD46IJ;;ACx6II;EACC,kBAAA;AD26IL;;ACj7IG;EACC,iBAAA;ADo7IJ;;ACh7II;EACC,kBAAA;ADm7IL;;ACz7IG;EACC,iBAAA;AD47IJ;;ACx7II;EACC,kBAAA;AD27IL;;ACj8IG;EACC,iBAAA;ADo8IJ;;ACh8II;EACC,kBAAA;ADm8IL;;ACz8IG;EACC,iBAAA;AD48IJ;;ACx8II;EACC,kBAAA;AD28IL;;ACj9IG;EACC,iBAAA;ADo9IJ;;ACh9II;EACC,kBAAA;ADm9IL;;ACz9IG;EACC,iBAAA;AD49IJ;;ACx9II;EACC,kBAAA;AD29IL;;ACj+IG;EACC,iBAAA;ADo+IJ;;ACh+II;EACC,kBAAA;ADm+IL;;ACz+IG;EACC,iBAAA;AD4+IJ;;ACx+II;EACC,kBAAA;AD2+IL;;ACj/IG;EACC,iBAAA;ADo/IJ;;ACh/II;EACC,kBAAA;ADm/IL;;ACz/IG;EACC,iBAAA;AD4/IJ;;ACx/II;EACC,kBAAA;AD2/IL;;ACjgJG;EACC,iBAAA;ADogJJ;;AChgJI;EACC,kBAAA;ADmgJL;;ACzgJG;EACC,iBAAA;AD4gJJ;;ACxgJI;EACC,kBAAA;AD2gJL;;ACjhJG;EACC,iBAAA;ADohJJ;;AChhJI;EACC,kBAAA;ADmhJL;;ACzhJG;EACC,iBAAA;AD4hJJ;;ACxhJI;EACC,kBAAA;AD2hJL;;ACjiJG;EACC,iBAAA;ADoiJJ;;AChiJI;EACC,kBAAA;ADmiJL;;ACziJG;EACC,iBAAA;AD4iJJ;;ACxiJI;EACC,kBAAA;AD2iJL;;ACjjJG;EACC,iBAAA;ADojJJ;;AChjJI;EACC,kBAAA;ADmjJL;;ACzjJG;EACC,kBAAA;AD4jJJ;;ACxjJI;EACC,mBAAA;AD2jJL;;AC5lJG;EACC,kBAAA;AD+lJJ;;AC3lJI;EACC,mBAAA;AD8lJL;;ACpmJG;EACC,kBAAA;ADumJJ;;ACnmJI;EACC,mBAAA;ADsmJL;;AC5mJG;EACC,kBAAA;AD+mJJ;;AC3mJI;EACC,mBAAA;AD8mJL;;ACpnJG;EACC,kBAAA;ADunJJ;;ACnnJI;EACC,mBAAA;ADsnJL;;AC5nJG;EACC,kBAAA;AD+nJJ;;AC3nJI;EACC,mBAAA;AD8nJL;;ACpoJG;EACC,kBAAA;ADuoJJ;;ACnoJI;EACC,mBAAA;ADsoJL;;AC5oJG;EACC,kBAAA;AD+oJJ;;AC3oJI;EACC,mBAAA;AD8oJL;;ACppJG;EACC,kBAAA;ADupJJ;;ACnpJI;EACC,mBAAA;ADspJL;;AC5pJG;EACC,kBAAA;AD+pJJ;;AC3pJI;EACC,mBAAA;AD8pJL;;ACpqJG;EACC,kBAAA;ADuqJJ;;ACnqJI;EACC,mBAAA;ADsqJL;;AC5qJG;EACC,mBAAA;AD+qJJ;;AC3qJI;EACC,oBAAA;AD8qJL;;ACprJG;EACC,mBAAA;ADurJJ;;ACnrJI;EACC,oBAAA;ADsrJL;;AC5rJG;EACC,mBAAA;AD+rJJ;;AC3rJI;EACC,oBAAA;AD8rJL;;ACpsJG;EACC,mBAAA;ADusJJ;;ACnsJI;EACC,oBAAA;ADssJL;;AC5sJG;EACC,mBAAA;AD+sJJ;;AC3sJI;EACC,oBAAA;AD8sJL;;ACptJG;EACC,mBAAA;ADutJJ;;ACntJI;EACC,oBAAA;ADstJL;;AC5tJG;EACC,mBAAA;AD+tJJ;;AC3tJI;EACC,oBAAA;AD8tJL;;ACpuJG;EACC,mBAAA;ADuuJJ;;ACnuJI;EACC,oBAAA;ADsuJL;;AC5uJG;EACC,mBAAA;AD+uJJ;;AC3uJI;EACC,oBAAA;AD8uJL;;ACpvJG;EACC,mBAAA;ADuvJJ;;ACnvJI;EACC,oBAAA;ADsvJL;;AC5vJG;EACC,mBAAA;AD+vJJ;;AC3vJI;EACC,oBAAA;AD8vJL;;ACpwJG;EACC,mBAAA;ADuwJJ;;ACnwJI;EACC,oBAAA;ADswJL;;AC5wJG;EACC,mBAAA;AD+wJJ;;AC3wJI;EACC,oBAAA;AD8wJL;;ACpxJG;EACC,mBAAA;ADuxJJ;;ACnxJI;EACC,oBAAA;ADsxJL;;AC5xJG;EACC,mBAAA;AD+xJJ;;AC3xJI;EACC,oBAAA;AD8xJL;;ACpyJG;EACC,mBAAA;ADuyJJ;;ACnyJI;EACC,oBAAA;ADsyJL;;AC5yJG;EACC,mBAAA;AD+yJJ;;AC3yJI;EACC,oBAAA;AD8yJL;;ACpzJG;EACC,mBAAA;ADuzJJ;;ACnzJI;EACC,oBAAA;ADszJL;;AC5zJG;EACC,mBAAA;AD+zJJ;;AC3zJI;EACC,oBAAA;AD8zJL;;ACp0JG;EACC,mBAAA;ADu0JJ;;ACn0JI;EACC,oBAAA;ADs0JL;;AC50JG;EACC,mBAAA;AD+0JJ;;AC30JI;EACC,oBAAA;AD80JL;;ACp1JG;EACC,mBAAA;ADu1JJ;;ACn1JI;EACC,oBAAA;ADs1JL;;AC51JG;EACC,mBAAA;AD+1JJ;;AC31JI;EACC,oBAAA;AD81JL;;ACp2JG;EACC,mBAAA;ADu2JJ;;ACn2JI;EACC,oBAAA;ADs2JL;;AC52JG;EACC,mBAAA;AD+2JJ;;AC32JI;EACC,oBAAA;AD82JL;;ACp3JG;EACC,mBAAA;ADu3JJ;;ACn3JI;EACC,oBAAA;ADs3JL;;AC53JG;EACC,mBAAA;AD+3JJ;;AC33JI;EACC,oBAAA;AD83JL;;ACp4JG;EACC,mBAAA;ADu4JJ;;ACn4JI;EACC,oBAAA;ADs4JL;;AC54JG;EACC,mBAAA;AD+4JJ;;AC34JI;EACC,oBAAA;AD84JL;;ACp5JG;EACC,mBAAA;ADu5JJ;;ACn5JI;EACC,oBAAA;ADs5JL;;AC55JG;EACC,mBAAA;AD+5JJ;;AC35JI;EACC,oBAAA;AD85JL;;ACp6JG;EACC,mBAAA;ADu6JJ;;ACn6JI;EACC,oBAAA;ADs6JL;;AC56JG;EACC,mBAAA;AD+6JJ;;AC36JI;EACC,oBAAA;AD86JL;;ACp7JG;EACC,mBAAA;ADu7JJ;;ACn7JI;EACC,oBAAA;ADs7JL;;AC57JG;EACC,mBAAA;AD+7JJ;;AC37JI;EACC,oBAAA;AD87JL;;ACp8JG;EACC,mBAAA;ADu8JJ;;ACn8JI;EACC,oBAAA;ADs8JL;;AC58JG;EACC,mBAAA;AD+8JJ;;AC38JI;EACC,oBAAA;AD88JL;;ACp9JG;EACC,mBAAA;ADu9JJ;;ACn9JI;EACC,oBAAA;ADs9JL;;AC59JG;EACC,mBAAA;AD+9JJ;;AC39JI;EACC,oBAAA;AD89JL;;ACp+JG;EACC,mBAAA;ADu+JJ;;ACn+JI;EACC,oBAAA;ADs+JL;;AC5+JG;EACC,mBAAA;AD++JJ;;AC3+JI;EACC,oBAAA;AD8+JL;;ACz9JG;EACC,kBAAA;AD49JJ;;ACx9JI;EACC,mBAAA;AD29JL;;ACj+JG;EACC,kBAAA;ADo+JJ;;ACh+JI;EACC,mBAAA;ADm+JL;;ACz+JG;EACC,mBAAA;AD4+JJ;;ACx+JI;EACC,oBAAA;AD2+JL;;ACj/JG;EACC,mBAAA;ADo/JJ;;ACh/JI;EACC,oBAAA;ADm/JL;;ACz/JG;EACC,mBAAA;AD4/JJ;;ACx/JI;EACC,oBAAA;AD2/JL;;ACjgKG;EACC,mBAAA;ADogKJ;;AChgKI;EACC,oBAAA;ADmgKL;;ACzgKG;EACC,mBAAA;AD4gKJ;;ACxgKI;EACC,oBAAA;AD2gKL;;ACjhKG;EACC,mBAAA;ADohKJ;;AChhKI;EACC,oBAAA;ADmhKL;;ACzhKG;EACC,mBAAA;AD4hKJ;;ACxhKI;EACC,oBAAA;AD2hKL;;ACjiKG;EACC,mBAAA;ADoiKJ;;AChiKI;EACC,oBAAA;ADmiKL;;ACziKG;EACC,mBAAA;AD4iKJ;;ACxiKI;EACC,oBAAA;AD2iKL;;ACjjKG;EACC,mBAAA;ADojKJ;;AChjKI;EACC,oBAAA;ADmjKL;;ACzjKG;EACC,mBAAA;AD4jKJ;;ACxjKI;EACC,oBAAA;AD2jKL;;ACjkKG;EACC,mBAAA;ADokKJ;;AChkKI;EACC,oBAAA;ADmkKL;;ACzkKG;EACC,mBAAA;AD4kKJ;;ACxkKI;EACC,oBAAA;AD2kKL;;ACjlKG;EACC,mBAAA;ADolKJ;;AChlKI;EACC,oBAAA;ADmlKL;;ACzlKG;EACC,mBAAA;AD4lKJ;;ACxlKI;EACC,oBAAA;AD2lKL;;ACjmKG;EACC,mBAAA;ADomKJ;;AChmKI;EACC,oBAAA;ADmmKL;;ACzmKG;EACC,mBAAA;AD4mKJ;;ACxmKI;EACC,oBAAA;AD2mKL;;ACjnKG;EACC,mBAAA;ADonKJ;;AChnKI;EACC,oBAAA;ADmnKL;;ACznKG;EACC,mBAAA;AD4nKJ;;ACxnKI;EACC,oBAAA;AD2nKL;;ACjoKG;EACC,mBAAA;ADooKJ;;AChoKI;EACC,oBAAA;ADmoKL;;ACzoKG;EACC,mBAAA;AD4oKJ;;ACxoKI;EACC,oBAAA;AD2oKL;;ACjpKG;EACC,mBAAA;ADopKJ;;AChpKI;EACC,oBAAA;ADmpKL;;ACzpKG;EACC,oBAAA;AD4pKJ;;ACxpKI;EACC,qBAAA;AD2pKL;;AC5rKG;EACC,mBAAA;AD+rKJ;;AC3rKI;EACC,oBAAA;AD8rKL;;ACpsKG;EACC,mBAAA;ADusKJ;;ACnsKI;EACC,oBAAA;ADssKL;;AC5sKG;EACC,mBAAA;AD+sKJ;;AC3sKI;EACC,oBAAA;AD8sKL;;ACptKG;EACC,mBAAA;ADutKJ;;ACntKI;EACC,oBAAA;ADstKL;;AC5tKG;EACC,mBAAA;AD+tKJ;;AC3tKI;EACC,oBAAA;AD8tKL;;ACpuKG;EACC,mBAAA;ADuuKJ;;ACnuKI;EACC,oBAAA;ADsuKL;;AC5uKG;EACC,mBAAA;AD+uKJ;;AC3uKI;EACC,oBAAA;AD8uKL;;ACpvKG;EACC,mBAAA;ADuvKJ;;ACnvKI;EACC,oBAAA;ADsvKL;;AC5vKG;EACC,mBAAA;AD+vKJ;;AC3vKI;EACC,oBAAA;AD8vKL;;ACpwKG;EACC,mBAAA;ADuwKJ;;ACnwKI;EACC,oBAAA;ADswKL;;AC5wKG;EACC,oBAAA;AD+wKJ;;AC3wKI;EACC,qBAAA;AD8wKL;;ACpxKG;EACC,oBAAA;ADuxKJ;;ACnxKI;EACC,qBAAA;ADsxKL;;AC5xKG;EACC,oBAAA;AD+xKJ;;AC3xKI;EACC,qBAAA;AD8xKL;;ACpyKG;EACC,oBAAA;ADuyKJ;;ACnyKI;EACC,qBAAA;ADsyKL;;AC5yKG;EACC,oBAAA;AD+yKJ;;AC3yKI;EACC,qBAAA;AD8yKL;;ACpzKG;EACC,oBAAA;ADuzKJ;;ACnzKI;EACC,qBAAA;ADszKL;;AC5zKG;EACC,oBAAA;AD+zKJ;;AC3zKI;EACC,qBAAA;AD8zKL;;ACp0KG;EACC,oBAAA;ADu0KJ;;ACn0KI;EACC,qBAAA;ADs0KL;;AC50KG;EACC,oBAAA;AD+0KJ;;AC30KI;EACC,qBAAA;AD80KL;;ACp1KG;EACC,oBAAA;ADu1KJ;;ACn1KI;EACC,qBAAA;ADs1KL;;AC51KG;EACC,oBAAA;AD+1KJ;;AC31KI;EACC,qBAAA;AD81KL;;ACp2KG;EACC,oBAAA;ADu2KJ;;ACn2KI;EACC,qBAAA;ADs2KL;;AC52KG;EACC,oBAAA;AD+2KJ;;AC32KI;EACC,qBAAA;AD82KL;;ACp3KG;EACC,oBAAA;ADu3KJ;;ACn3KI;EACC,qBAAA;ADs3KL;;AC53KG;EACC,oBAAA;AD+3KJ;;AC33KI;EACC,qBAAA;AD83KL;;ACp4KG;EACC,oBAAA;ADu4KJ;;ACn4KI;EACC,qBAAA;ADs4KL;;AC54KG;EACC,oBAAA;AD+4KJ;;AC34KI;EACC,qBAAA;AD84KL;;ACp5KG;EACC,oBAAA;ADu5KJ;;ACn5KI;EACC,qBAAA;ADs5KL;;AC55KG;EACC,oBAAA;AD+5KJ;;AC35KI;EACC,qBAAA;AD85KL;;ACp6KG;EACC,oBAAA;ADu6KJ;;ACn6KI;EACC,qBAAA;ADs6KL;;AC56KG;EACC,oBAAA;AD+6KJ;;AC36KI;EACC,qBAAA;AD86KL;;ACp7KG;EACC,oBAAA;ADu7KJ;;ACn7KI;EACC,qBAAA;ADs7KL;;AC57KG;EACC,oBAAA;AD+7KJ;;AC37KI;EACC,qBAAA;AD87KL;;ACp8KG;EACC,oBAAA;ADu8KJ;;ACn8KI;EACC,qBAAA;ADs8KL;;AC58KG;EACC,oBAAA;AD+8KJ;;AC38KI;EACC,qBAAA;AD88KL;;ACp9KG;EACC,oBAAA;ADu9KJ;;ACn9KI;EACC,qBAAA;ADs9KL;;AC59KG;EACC,oBAAA;AD+9KJ;;AC39KI;EACC,qBAAA;AD89KL;;ACp+KG;EACC,oBAAA;ADu+KJ;;ACn+KI;EACC,qBAAA;ADs+KL;;AC5+KG;EACC,oBAAA;AD++KJ;;AC3+KI;EACC,qBAAA;AD8+KL;;ACp/KG;EACC,oBAAA;ADu/KJ;;ACn/KI;EACC,qBAAA;ADs/KL;;AC5/KG;EACC,oBAAA;AD+/KJ;;AC3/KI;EACC,qBAAA;AD8/KL;;ACpgLG;EACC,oBAAA;ADugLJ;;ACngLI;EACC,qBAAA;ADsgLL;;AC5gLG;EACC,oBAAA;AD+gLJ;;AC3gLI;EACC,qBAAA;AD8gLL;;ACphLG;EACC,oBAAA;ADuhLJ;;ACnhLI;EACC,qBAAA;ADshLL;;AC5hLG;EACC,oBAAA;AD+hLJ;;AC3hLI;EACC,qBAAA;AD8hLL;;ACpiLG;EACC,oBAAA;ADuiLJ;;ACniLI;EACC,qBAAA;ADsiLL;;AC5iLG;EACC,oBAAA;AD+iLJ;;AC3iLI;EACC,qBAAA;AD8iLL;;ACpjLG;EACC,oBAAA;ADujLJ;;ACnjLI;EACC,qBAAA;ADsjLL;;AC5jLG;EACC,oBAAA;AD+jLJ;;AC3jLI;EACC,qBAAA;AD8jLL;;ACpkLG;EACC,oBAAA;ADukLJ;;ACnkLI;EACC,qBAAA;ADskLL;;AC5kLG;EACC,oBAAA;AD+kLJ;;AC3kLI;EACC,qBAAA;AD8kLL;;ACzjLG;EACC,mBAAA;AD4jLJ;;ACxjLI;EACC,oBAAA;AD2jLL;;ACjkLG;EACC,mBAAA;ADokLJ;;AChkLI;EACC,oBAAA;ADmkLL;;ACzkLG;EACC,oBAAA;AD4kLJ;;ACxkLI;EACC,qBAAA;AD2kLL;;ACjlLG;EACC,oBAAA;ADolLJ;;AChlLI;EACC,qBAAA;ADmlLL;;ACzlLG;EACC,oBAAA;AD4lLJ;;ACxlLI;EACC,qBAAA;AD2lLL;;ACjmLG;EACC,oBAAA;ADomLJ;;AChmLI;EACC,qBAAA;ADmmLL;;ACzmLG;EACC,oBAAA;AD4mLJ;;ACxmLI;EACC,qBAAA;AD2mLL;;ACjnLG;EACC,oBAAA;ADonLJ;;AChnLI;EACC,qBAAA;ADmnLL;;ACznLG;EACC,oBAAA;AD4nLJ;;ACxnLI;EACC,qBAAA;AD2nLL;;ACjoLG;EACC,oBAAA;ADooLJ;;AChoLI;EACC,qBAAA;ADmoLL;;ACzoLG;EACC,oBAAA;AD4oLJ;;ACxoLI;EACC,qBAAA;AD2oLL;;ACjpLG;EACC,oBAAA;ADopLJ;;AChpLI;EACC,qBAAA;ADmpLL;;ACzpLG;EACC,oBAAA;AD4pLJ;;ACxpLI;EACC,qBAAA;AD2pLL;;ACjqLG;EACC,oBAAA;ADoqLJ;;AChqLI;EACC,qBAAA;ADmqLL;;ACzqLG;EACC,oBAAA;AD4qLJ;;ACxqLI;EACC,qBAAA;AD2qLL;;ACjrLG;EACC,oBAAA;ADorLJ;;AChrLI;EACC,qBAAA;ADmrLL;;ACzrLG;EACC,oBAAA;AD4rLJ;;ACxrLI;EACC,qBAAA;AD2rLL;;ACjsLG;EACC,oBAAA;ADosLJ;;AChsLI;EACC,qBAAA;ADmsLL;;ACzsLG;EACC,oBAAA;AD4sLJ;;ACxsLI;EACC,qBAAA;AD2sLL;;ACjtLG;EACC,oBAAA;ADotLJ;;AChtLI;EACC,qBAAA;ADmtLL;;ACztLG;EACC,oBAAA;AD4tLJ;;ACxtLI;EACC,qBAAA;AD2tLL;;ACjuLG;EACC,oBAAA;ADouLJ;;AChuLI;EACC,qBAAA;ADmuLL;;ACzuLG;EACC,oBAAA;AD4uLJ;;ACxuLI;EACC,qBAAA;AD2uLL;;ACjvLG;EACC,oBAAA;ADovLJ;;AChvLI;EACC,qBAAA;ADmvLL;;ACzvLG;EACC,qBAAA;AD4vLJ;;ACxvLI;EACC,sBAAA;AD2vLL;;AC5xLG;EACC,iBAAA;AD+xLJ;;AC3xLI;EACC,kBAAA;AD8xLL;;ACpyLG;EACC,iBAAA;ADuyLJ;;ACnyLI;EACC,kBAAA;ADsyLL;;AC5yLG;EACC,iBAAA;AD+yLJ;;AC3yLI;EACC,kBAAA;AD8yLL;;ACpzLG;EACC,iBAAA;ADuzLJ;;ACnzLI;EACC,kBAAA;ADszLL;;AC5zLG;EACC,iBAAA;AD+zLJ;;AC3zLI;EACC,kBAAA;AD8zLL;;ACp0LG;EACC,iBAAA;ADu0LJ;;ACn0LI;EACC,kBAAA;ADs0LL;;AC50LG;EACC,iBAAA;AD+0LJ;;AC30LI;EACC,kBAAA;AD80LL;;ACp1LG;EACC,iBAAA;ADu1LJ;;ACn1LI;EACC,kBAAA;ADs1LL;;AC51LG;EACC,iBAAA;AD+1LJ;;AC31LI;EACC,kBAAA;AD81LL;;ACp2LG;EACC,iBAAA;ADu2LJ;;ACn2LI;EACC,kBAAA;ADs2LL;;AC52LG;EACC,kBAAA;AD+2LJ;;AC32LI;EACC,mBAAA;AD82LL;;ACp3LG;EACC,kBAAA;ADu3LJ;;ACn3LI;EACC,mBAAA;ADs3LL;;AC53LG;EACC,kBAAA;AD+3LJ;;AC33LI;EACC,mBAAA;AD83LL;;ACp4LG;EACC,kBAAA;ADu4LJ;;ACn4LI;EACC,mBAAA;ADs4LL;;AC54LG;EACC,kBAAA;AD+4LJ;;AC34LI;EACC,mBAAA;AD84LL;;ACp5LG;EACC,kBAAA;ADu5LJ;;ACn5LI;EACC,mBAAA;ADs5LL;;AC55LG;EACC,kBAAA;AD+5LJ;;AC35LI;EACC,mBAAA;AD85LL;;ACp6LG;EACC,kBAAA;ADu6LJ;;ACn6LI;EACC,mBAAA;ADs6LL;;AC56LG;EACC,kBAAA;AD+6LJ;;AC36LI;EACC,mBAAA;AD86LL;;ACp7LG;EACC,kBAAA;ADu7LJ;;ACn7LI;EACC,mBAAA;ADs7LL;;AC57LG;EACC,kBAAA;AD+7LJ;;AC37LI;EACC,mBAAA;AD87LL;;ACp8LG;EACC,kBAAA;ADu8LJ;;ACn8LI;EACC,mBAAA;ADs8LL;;AC58LG;EACC,kBAAA;AD+8LJ;;AC38LI;EACC,mBAAA;AD88LL;;ACp9LG;EACC,kBAAA;ADu9LJ;;ACn9LI;EACC,mBAAA;ADs9LL;;AC59LG;EACC,kBAAA;AD+9LJ;;AC39LI;EACC,mBAAA;AD89LL;;ACp+LG;EACC,kBAAA;ADu+LJ;;ACn+LI;EACC,mBAAA;ADs+LL;;AC5+LG;EACC,kBAAA;AD++LJ;;AC3+LI;EACC,mBAAA;AD8+LL;;ACp/LG;EACC,kBAAA;ADu/LJ;;ACn/LI;EACC,mBAAA;ADs/LL;;AC5/LG;EACC,kBAAA;AD+/LJ;;AC3/LI;EACC,mBAAA;AD8/LL;;ACpgMG;EACC,kBAAA;ADugMJ;;ACngMI;EACC,mBAAA;ADsgML;;AC5gMG;EACC,kBAAA;AD+gMJ;;AC3gMI;EACC,mBAAA;AD8gML;;ACphMG;EACC,kBAAA;ADuhMJ;;ACnhMI;EACC,mBAAA;ADshML;;AC5hMG;EACC,kBAAA;AD+hMJ;;AC3hMI;EACC,mBAAA;AD8hML;;ACpiMG;EACC,kBAAA;ADuiMJ;;ACniMI;EACC,mBAAA;ADsiML;;AC5iMG;EACC,kBAAA;AD+iMJ;;AC3iMI;EACC,mBAAA;AD8iML;;ACpjMG;EACC,kBAAA;ADujMJ;;ACnjMI;EACC,mBAAA;ADsjML;;AC5jMG;EACC,kBAAA;AD+jMJ;;AC3jMI;EACC,mBAAA;AD8jML;;ACpkMG;EACC,kBAAA;ADukMJ;;ACnkMI;EACC,mBAAA;ADskML;;AC5kMG;EACC,kBAAA;AD+kMJ;;AC3kMI;EACC,mBAAA;AD8kML;;ACplMG;EACC,kBAAA;ADulMJ;;ACnlMI;EACC,mBAAA;ADslML;;AC5lMG;EACC,kBAAA;AD+lMJ;;AC3lMI;EACC,mBAAA;AD8lML;;ACpmMG;EACC,kBAAA;ADumMJ;;ACnmMI;EACC,mBAAA;ADsmML;;AC5mMG;EACC,kBAAA;AD+mMJ;;AC3mMI;EACC,mBAAA;AD8mML;;ACpnMG;EACC,kBAAA;ADunMJ;;ACnnMI;EACC,mBAAA;ADsnML;;AC5nMG;EACC,kBAAA;AD+nMJ;;AC3nMI;EACC,mBAAA;AD8nML;;ACpoMG;EACC,kBAAA;ADuoMJ;;ACnoMI;EACC,mBAAA;ADsoML;;AC5oMG;EACC,kBAAA;AD+oMJ;;AC3oMI;EACC,mBAAA;AD8oML;;ACppMG;EACC,kBAAA;ADupMJ;;ACnpMI;EACC,mBAAA;ADspML;;AC5pMG;EACC,kBAAA;AD+pMJ;;AC3pMI;EACC,mBAAA;AD8pML;;ACpqMG;EACC,kBAAA;ADuqMJ;;ACnqMI;EACC,mBAAA;ADsqML;;AC5qMG;EACC,kBAAA;AD+qMJ;;AC3qMI;EACC,mBAAA;AD8qML;;ACzpMG;EACC,iBAAA;AD4pMJ;;ACxpMI;EACC,kBAAA;AD2pML;;ACjqMG;EACC,iBAAA;ADoqMJ;;AChqMI;EACC,kBAAA;ADmqML;;ACzqMG;EACC,kBAAA;AD4qMJ;;ACxqMI;EACC,mBAAA;AD2qML;;ACjrMG;EACC,kBAAA;ADorMJ;;AChrMI;EACC,mBAAA;ADmrML;;ACzrMG;EACC,kBAAA;AD4rMJ;;ACxrMI;EACC,mBAAA;AD2rML;;ACjsMG;EACC,kBAAA;ADosMJ;;AChsMI;EACC,mBAAA;ADmsML;;ACzsMG;EACC,kBAAA;AD4sMJ;;ACxsMI;EACC,mBAAA;AD2sML;;ACjtMG;EACC,kBAAA;ADotMJ;;AChtMI;EACC,mBAAA;ADmtML;;ACztMG;EACC,kBAAA;AD4tMJ;;ACxtMI;EACC,mBAAA;AD2tML;;ACjuMG;EACC,kBAAA;ADouMJ;;AChuMI;EACC,mBAAA;ADmuML;;ACzuMG;EACC,kBAAA;AD4uMJ;;ACxuMI;EACC,mBAAA;AD2uML;;ACjvMG;EACC,kBAAA;ADovMJ;;AChvMI;EACC,mBAAA;ADmvML;;ACzvMG;EACC,kBAAA;AD4vMJ;;ACxvMI;EACC,mBAAA;AD2vML;;ACjwMG;EACC,kBAAA;ADowMJ;;AChwMI;EACC,mBAAA;ADmwML;;ACzwMG;EACC,kBAAA;AD4wMJ;;ACxwMI;EACC,mBAAA;AD2wML;;ACjxMG;EACC,kBAAA;ADoxMJ;;AChxMI;EACC,mBAAA;ADmxML;;ACzxMG;EACC,kBAAA;AD4xMJ;;ACxxMI;EACC,mBAAA;AD2xML;;ACjyMG;EACC,kBAAA;ADoyMJ;;AChyMI;EACC,mBAAA;ADmyML;;ACzyMG;EACC,kBAAA;AD4yMJ;;ACxyMI;EACC,mBAAA;AD2yML;;ACjzMG;EACC,kBAAA;ADozMJ;;AChzMI;EACC,mBAAA;ADmzML;;ACzzMG;EACC,kBAAA;AD4zMJ;;ACxzMI;EACC,mBAAA;AD2zML;;ACj0MG;EACC,kBAAA;ADo0MJ;;ACh0MI;EACC,mBAAA;ADm0ML;;ACz0MG;EACC,kBAAA;AD40MJ;;ACx0MI;EACC,mBAAA;AD20ML;;ACj1MG;EACC,kBAAA;ADo1MJ;;ACh1MI;EACC,mBAAA;ADm1ML;;ACz1MG;EACC,mBAAA;AD41MJ;;ACx1MI;EACC,oBAAA;AD21ML;;ACj3MG;EACC,iBAAA;EACA,kBAAA;ADo3MJ;;ACt3MG;EACC,iBAAA;EACA,kBAAA;ADy3MJ;;AC33MG;EACC,iBAAA;EACA,kBAAA;AD83MJ;;ACh4MG;EACC,iBAAA;EACA,kBAAA;ADm4MJ;;ACr4MG;EACC,iBAAA;EACA,kBAAA;ADw4MJ;;AC14MG;EACC,iBAAA;EACA,kBAAA;AD64MJ;;AC/4MG;EACC,iBAAA;EACA,kBAAA;ADk5MJ;;ACp5MG;EACC,iBAAA;EACA,kBAAA;ADu5MJ;;ACz5MG;EACC,iBAAA;EACA,kBAAA;AD45MJ;;AC95MG;EACC,iBAAA;EACA,kBAAA;ADi6MJ;;ACn6MG;EACC,kBAAA;EACA,mBAAA;ADs6MJ;;ACx6MG;EACC,kBAAA;EACA,mBAAA;AD26MJ;;AC76MG;EACC,kBAAA;EACA,mBAAA;ADg7MJ;;ACl7MG;EACC,kBAAA;EACA,mBAAA;ADq7MJ;;ACv7MG;EACC,kBAAA;EACA,mBAAA;AD07MJ;;AC57MG;EACC,kBAAA;EACA,mBAAA;AD+7MJ;;ACj8MG;EACC,kBAAA;EACA,mBAAA;ADo8MJ;;ACt8MG;EACC,kBAAA;EACA,mBAAA;ADy8MJ;;AC38MG;EACC,kBAAA;EACA,mBAAA;AD88MJ;;ACh9MG;EACC,kBAAA;EACA,mBAAA;ADm9MJ;;ACr9MG;EACC,kBAAA;EACA,mBAAA;ADw9MJ;;AC19MG;EACC,kBAAA;EACA,mBAAA;AD69MJ;;AC/9MG;EACC,kBAAA;EACA,mBAAA;ADk+MJ;;ACp+MG;EACC,kBAAA;EACA,mBAAA;ADu+MJ;;ACz+MG;EACC,kBAAA;EACA,mBAAA;AD4+MJ;;AC9+MG;EACC,kBAAA;EACA,mBAAA;ADi/MJ;;ACn/MG;EACC,kBAAA;EACA,mBAAA;ADs/MJ;;ACx/MG;EACC,kBAAA;EACA,mBAAA;AD2/MJ;;AC7/MG;EACC,kBAAA;EACA,mBAAA;ADggNJ;;AClgNG;EACC,kBAAA;EACA,mBAAA;ADqgNJ;;ACvgNG;EACC,kBAAA;EACA,mBAAA;AD0gNJ;;AC5gNG;EACC,kBAAA;EACA,mBAAA;AD+gNJ;;ACjhNG;EACC,kBAAA;EACA,mBAAA;ADohNJ;;ACthNG;EACC,kBAAA;EACA,mBAAA;ADyhNJ;;AC3hNG;EACC,kBAAA;EACA,mBAAA;AD8hNJ;;AChiNG;EACC,kBAAA;EACA,mBAAA;ADmiNJ;;ACriNG;EACC,kBAAA;EACA,mBAAA;ADwiNJ;;AC1iNG;EACC,kBAAA;EACA,mBAAA;AD6iNJ;;AC/iNG;EACC,kBAAA;EACA,mBAAA;ADkjNJ;;ACpjNG;EACC,kBAAA;EACA,mBAAA;ADujNJ;;ACzjNG;EACC,kBAAA;EACA,mBAAA;AD4jNJ;;AC9jNG;EACC,kBAAA;EACA,mBAAA;ADikNJ;;ACnkNG;EACC,kBAAA;EACA,mBAAA;ADskNJ;;ACxkNG;EACC,kBAAA;EACA,mBAAA;AD2kNJ;;AC7kNG;EACC,kBAAA;EACA,mBAAA;ADglNJ;;ACllNG;EACC,kBAAA;EACA,mBAAA;ADqlNJ;;ACvlNG;EACC,kBAAA;EACA,mBAAA;AD0lNJ;;AC5lNG;EACC,kBAAA;EACA,mBAAA;AD+lNJ;;ACjmNG;EACC,kBAAA;EACA,mBAAA;ADomNJ;;ACtmNG;EACC,kBAAA;EACA,mBAAA;ADymNJ;;AC3mNG;EACC,kBAAA;EACA,mBAAA;AD8mNJ;;ACplNG;EACC,iBAAA;EACA,kBAAA;ADulNJ;;ACzlNG;EACC,iBAAA;EACA,kBAAA;AD4lNJ;;AC9lNG;EACC,kBAAA;EACA,mBAAA;ADimNJ;;ACnmNG;EACC,kBAAA;EACA,mBAAA;ADsmNJ;;ACxmNG;EACC,kBAAA;EACA,mBAAA;AD2mNJ;;AC7mNG;EACC,kBAAA;EACA,mBAAA;ADgnNJ;;AClnNG;EACC,kBAAA;EACA,mBAAA;ADqnNJ;;ACvnNG;EACC,kBAAA;EACA,mBAAA;AD0nNJ;;AC5nNG;EACC,kBAAA;EACA,mBAAA;AD+nNJ;;ACjoNG;EACC,kBAAA;EACA,mBAAA;ADooNJ;;ACtoNG;EACC,kBAAA;EACA,mBAAA;ADyoNJ;;AC3oNG;EACC,kBAAA;EACA,mBAAA;AD8oNJ;;AChpNG;EACC,kBAAA;EACA,mBAAA;ADmpNJ;;ACrpNG;EACC,kBAAA;EACA,mBAAA;ADwpNJ;;AC1pNG;EACC,kBAAA;EACA,mBAAA;AD6pNJ;;AC/pNG;EACC,kBAAA;EACA,mBAAA;ADkqNJ;;ACpqNG;EACC,kBAAA;EACA,mBAAA;ADuqNJ;;ACzqNG;EACC,kBAAA;EACA,mBAAA;AD4qNJ;;AC9qNG;EACC,kBAAA;EACA,mBAAA;ADirNJ;;ACnrNG;EACC,kBAAA;EACA,mBAAA;ADsrNJ;;ACxrNG;EACC,kBAAA;EACA,mBAAA;AD2rNJ;;AC7rNG;EACC,kBAAA;EACA,mBAAA;ADgsNJ;;AClsNG;EACC,kBAAA;EACA,mBAAA;ADqsNJ;;ACvsNG;EACC,kBAAA;EACA,mBAAA;AD0sNJ;;AC5sNG;EACC,mBAAA;EACA,oBAAA;AD+sNJ;;ACtuNG;EACC,gBAAA;EACA,mBAAA;ADyuNJ;;AC3uNG;EACC,gBAAA;EACA,mBAAA;AD8uNJ;;AChvNG;EACC,gBAAA;EACA,mBAAA;ADmvNJ;;ACrvNG;EACC,gBAAA;EACA,mBAAA;ADwvNJ;;AC1vNG;EACC,gBAAA;EACA,mBAAA;AD6vNJ;;AC/vNG;EACC,gBAAA;EACA,mBAAA;ADkwNJ;;ACpwNG;EACC,gBAAA;EACA,mBAAA;ADuwNJ;;ACzwNG;EACC,gBAAA;EACA,mBAAA;AD4wNJ;;AC9wNG;EACC,gBAAA;EACA,mBAAA;ADixNJ;;ACnxNG;EACC,gBAAA;EACA,mBAAA;ADsxNJ;;ACxxNG;EACC,iBAAA;EACA,oBAAA;AD2xNJ;;AC7xNG;EACC,iBAAA;EACA,oBAAA;ADgyNJ;;AClyNG;EACC,iBAAA;EACA,oBAAA;ADqyNJ;;ACvyNG;EACC,iBAAA;EACA,oBAAA;AD0yNJ;;AC5yNG;EACC,iBAAA;EACA,oBAAA;AD+yNJ;;ACjzNG;EACC,iBAAA;EACA,oBAAA;ADozNJ;;ACtzNG;EACC,iBAAA;EACA,oBAAA;ADyzNJ;;AC3zNG;EACC,iBAAA;EACA,oBAAA;AD8zNJ;;ACh0NG;EACC,iBAAA;EACA,oBAAA;ADm0NJ;;ACr0NG;EACC,iBAAA;EACA,oBAAA;ADw0NJ;;AC10NG;EACC,iBAAA;EACA,oBAAA;AD60NJ;;AC/0NG;EACC,iBAAA;EACA,oBAAA;ADk1NJ;;ACp1NG;EACC,iBAAA;EACA,oBAAA;ADu1NJ;;ACz1NG;EACC,iBAAA;EACA,oBAAA;AD41NJ;;AC91NG;EACC,iBAAA;EACA,oBAAA;ADi2NJ;;ACn2NG;EACC,iBAAA;EACA,oBAAA;ADs2NJ;;ACx2NG;EACC,iBAAA;EACA,oBAAA;AD22NJ;;AC72NG;EACC,iBAAA;EACA,oBAAA;ADg3NJ;;ACl3NG;EACC,iBAAA;EACA,oBAAA;ADq3NJ;;ACv3NG;EACC,iBAAA;EACA,oBAAA;AD03NJ;;AC53NG;EACC,iBAAA;EACA,oBAAA;AD+3NJ;;ACj4NG;EACC,iBAAA;EACA,oBAAA;ADo4NJ;;ACt4NG;EACC,iBAAA;EACA,oBAAA;ADy4NJ;;AC34NG;EACC,iBAAA;EACA,oBAAA;AD84NJ;;ACh5NG;EACC,iBAAA;EACA,oBAAA;ADm5NJ;;ACr5NG;EACC,iBAAA;EACA,oBAAA;ADw5NJ;;AC15NG;EACC,iBAAA;EACA,oBAAA;AD65NJ;;AC/5NG;EACC,iBAAA;EACA,oBAAA;ADk6NJ;;ACp6NG;EACC,iBAAA;EACA,oBAAA;ADu6NJ;;ACz6NG;EACC,iBAAA;EACA,oBAAA;AD46NJ;;AC96NG;EACC,iBAAA;EACA,oBAAA;ADi7NJ;;ACn7NG;EACC,iBAAA;EACA,oBAAA;ADs7NJ;;ACx7NG;EACC,iBAAA;EACA,oBAAA;AD27NJ;;AC77NG;EACC,iBAAA;EACA,oBAAA;ADg8NJ;;ACl8NG;EACC,iBAAA;EACA,oBAAA;ADq8NJ;;ACv8NG;EACC,iBAAA;EACA,oBAAA;AD08NJ;;AC58NG;EACC,iBAAA;EACA,oBAAA;AD+8NJ;;ACj9NG;EACC,iBAAA;EACA,oBAAA;ADo9NJ;;ACt9NG;EACC,iBAAA;EACA,oBAAA;ADy9NJ;;AC39NG;EACC,iBAAA;EACA,oBAAA;AD89NJ;;ACh+NG;EACC,iBAAA;EACA,oBAAA;ADm+NJ;;ACz8NG;EACC,gBAAA;EACA,mBAAA;AD48NJ;;AC98NG;EACC,gBAAA;EACA,mBAAA;ADi9NJ;;ACn9NG;EACC,iBAAA;EACA,oBAAA;ADs9NJ;;ACx9NG;EACC,iBAAA;EACA,oBAAA;AD29NJ;;AC79NG;EACC,iBAAA;EACA,oBAAA;ADg+NJ;;ACl+NG;EACC,iBAAA;EACA,oBAAA;ADq+NJ;;ACv+NG;EACC,iBAAA;EACA,oBAAA;AD0+NJ;;AC5+NG;EACC,iBAAA;EACA,oBAAA;AD++NJ;;ACj/NG;EACC,iBAAA;EACA,oBAAA;ADo/NJ;;ACt/NG;EACC,iBAAA;EACA,oBAAA;ADy/NJ;;AC3/NG;EACC,iBAAA;EACA,oBAAA;AD8/NJ;;AChgOG;EACC,iBAAA;EACA,oBAAA;ADmgOJ;;ACrgOG;EACC,iBAAA;EACA,oBAAA;ADwgOJ;;AC1gOG;EACC,iBAAA;EACA,oBAAA;AD6gOJ;;AC/gOG;EACC,iBAAA;EACA,oBAAA;ADkhOJ;;ACphOG;EACC,iBAAA;EACA,oBAAA;ADuhOJ;;ACzhOG;EACC,iBAAA;EACA,oBAAA;AD4hOJ;;AC9hOG;EACC,iBAAA;EACA,oBAAA;ADiiOJ;;ACniOG;EACC,iBAAA;EACA,oBAAA;ADsiOJ;;ACxiOG;EACC,iBAAA;EACA,oBAAA;AD2iOJ;;AC7iOG;EACC,iBAAA;EACA,oBAAA;ADgjOJ;;ACljOG;EACC,iBAAA;EACA,oBAAA;ADqjOJ;;ACvjOG;EACC,iBAAA;EACA,oBAAA;AD0jOJ;;AC5jOG;EACC,iBAAA;EACA,oBAAA;AD+jOJ;;ACjkOG;EACC,kBAAA;EACA,qBAAA;ADokOJ;;AC3jOE;EACC,SAAA;AD8jOH;;AC3jOE;EACC,UAAA;AD8jOH;;ACnkOE;EACC,SAAA;ADskOH;;ACnkOE;EACC,UAAA;ADskOH;;AC3kOE;EACC,SAAA;AD8kOH;;AC3kOE;EACC,UAAA;AD8kOH;;ACnlOE;EACC,SAAA;ADslOH;;ACnlOE;EACC,UAAA;ADslOH;;AC3lOE;EACC,SAAA;AD8lOH;;AC3lOE;EACC,UAAA;AD8lOH;;ACnmOE;EACC,SAAA;ADsmOH;;ACnmOE;EACC,UAAA;ADsmOH;;AC3mOE;EACC,SAAA;AD8mOH;;AC3mOE;EACC,UAAA;AD8mOH;;ACnnOE;EACC,SAAA;ADsnOH;;ACnnOE;EACC,UAAA;ADsnOH;;AC3nOE;EACC,SAAA;AD8nOH;;AC3nOE;EACC,UAAA;AD8nOH;;ACnoOE;EACC,SAAA;ADsoOH;;ACnoOE;EACC,UAAA;ADsoOH;;AC3oOE;EACC,UAAA;AD8oOH;;AC3oOE;EACC,WAAA;AD8oOH;;ACnpOE;EACC,UAAA;ADspOH;;ACnpOE;EACC,WAAA;ADspOH;;AC3pOE;EACC,UAAA;AD8pOH;;AC3pOE;EACC,WAAA;AD8pOH;;ACnqOE;EACC,UAAA;ADsqOH;;ACnqOE;EACC,WAAA;ADsqOH;;AC3qOE;EACC,UAAA;AD8qOH;;AC3qOE;EACC,WAAA;AD8qOH;;ACnrOE;EACC,UAAA;ADsrOH;;ACnrOE;EACC,WAAA;ADsrOH;;AC3rOE;EACC,UAAA;AD8rOH;;AC3rOE;EACC,WAAA;AD8rOH;;ACnsOE;EACC,UAAA;ADssOH;;ACnsOE;EACC,WAAA;ADssOH;;AC3sOE;EACC,UAAA;AD8sOH;;AC3sOE;EACC,WAAA;AD8sOH;;ACntOE;EACC,UAAA;ADstOH;;ACntOE;EACC,WAAA;ADstOH;;AC3tOE;EACC,UAAA;AD8tOH;;AC3tOE;EACC,WAAA;AD8tOH;;ACnuOE;EACC,UAAA;ADsuOH;;ACnuOE;EACC,WAAA;ADsuOH;;AC3uOE;EACC,UAAA;AD8uOH;;AC3uOE;EACC,WAAA;AD8uOH;;ACnvOE;EACC,UAAA;ADsvOH;;ACnvOE;EACC,WAAA;ADsvOH;;AC3vOE;EACC,UAAA;AD8vOH;;AC3vOE;EACC,WAAA;AD8vOH;;ACnwOE;EACC,UAAA;ADswOH;;ACnwOE;EACC,WAAA;ADswOH;;AC3wOE;EACC,UAAA;AD8wOH;;AC3wOE;EACC,WAAA;AD8wOH;;ACnxOE;EACC,UAAA;ADsxOH;;ACnxOE;EACC,WAAA;ADsxOH;;AC3xOE;EACC,UAAA;AD8xOH;;AC3xOE;EACC,WAAA;AD8xOH;;ACnyOE;EACC,UAAA;ADsyOH;;ACnyOE;EACC,WAAA;ADsyOH;;AC3yOE;EACC,UAAA;AD8yOH;;AC3yOE;EACC,WAAA;AD8yOH;;ACnzOE;EACC,UAAA;ADszOH;;ACnzOE;EACC,WAAA;ADszOH;;AC3zOE;EACC,UAAA;AD8zOH;;AC3zOE;EACC,WAAA;AD8zOH;;ACn0OE;EACC,UAAA;ADs0OH;;ACn0OE;EACC,WAAA;ADs0OH;;AC30OE;EACC,UAAA;AD80OH;;AC30OE;EACC,WAAA;AD80OH;;ACn1OE;EACC,UAAA;ADs1OH;;ACn1OE;EACC,WAAA;ADs1OH;;AC31OE;EACC,UAAA;AD81OH;;AC31OE;EACC,WAAA;AD81OH;;ACn2OE;EACC,UAAA;ADs2OH;;ACn2OE;EACC,WAAA;ADs2OH;;AC32OE;EACC,UAAA;AD82OH;;AC32OE;EACC,WAAA;AD82OH;;ACn3OE;EACC,UAAA;ADs3OH;;ACn3OE;EACC,WAAA;ADs3OH;;AC33OE;EACC,UAAA;AD83OH;;AC33OE;EACC,WAAA;AD83OH;;ACn4OE;EACC,UAAA;ADs4OH;;ACn4OE;EACC,WAAA;ADs4OH;;AC34OE;EACC,UAAA;AD84OH;;AC34OE;EACC,WAAA;AD84OH;;ACn5OE;EACC,UAAA;ADs5OH;;ACn5OE;EACC,WAAA;ADs5OH;;AC35OE;EACC,UAAA;AD85OH;;AC35OE;EACC,WAAA;AD85OH;;ACn6OE;EACC,UAAA;ADs6OH;;ACn6OE;EACC,WAAA;ADs6OH;;AC36OE;EACC,UAAA;AD86OH;;AC36OE;EACC,WAAA;AD86OH;;ACn7OE;EACC,UAAA;ADs7OH;;ACn7OE;EACC,WAAA;ADs7OH;;AC37OE;EACC,UAAA;AD87OH;;AC37OE;EACC,WAAA;AD87OH;;ACn8OE;EACC,UAAA;ADs8OH;;ACn8OE;EACC,WAAA;ADs8OH;;AC38OE;EACC,UAAA;AD88OH;;AC38OE;EACC,WAAA;AD88OH;;ACz8OE;EACC,SAAA;AD48OH;;ACz8OE;EACC,UAAA;AD48OH;;ACj9OE;EACC,SAAA;ADo9OH;;ACj9OE;EACC,UAAA;ADo9OH;;ACz9OE;EACC,UAAA;AD49OH;;ACz9OE;EACC,WAAA;AD49OH;;ACj+OE;EACC,UAAA;ADo+OH;;ACj+OE;EACC,WAAA;ADo+OH;;ACz+OE;EACC,UAAA;AD4+OH;;ACz+OE;EACC,WAAA;AD4+OH;;ACj/OE;EACC,UAAA;ADo/OH;;ACj/OE;EACC,WAAA;ADo/OH;;ACz/OE;EACC,UAAA;AD4/OH;;ACz/OE;EACC,WAAA;AD4/OH;;ACjgPE;EACC,UAAA;ADogPH;;ACjgPE;EACC,WAAA;ADogPH;;ACzgPE;EACC,UAAA;AD4gPH;;ACzgPE;EACC,WAAA;AD4gPH;;ACjhPE;EACC,UAAA;ADohPH;;ACjhPE;EACC,WAAA;ADohPH;;ACzhPE;EACC,UAAA;AD4hPH;;ACzhPE;EACC,WAAA;AD4hPH;;ACjiPE;EACC,UAAA;ADoiPH;;ACjiPE;EACC,WAAA;ADoiPH;;ACziPE;EACC,UAAA;AD4iPH;;ACziPE;EACC,WAAA;AD4iPH;;ACjjPE;EACC,UAAA;ADojPH;;ACjjPE;EACC,WAAA;ADojPH;;ACzjPE;EACC,UAAA;AD4jPH;;ACzjPE;EACC,WAAA;AD4jPH;;ACjkPE;EACC,UAAA;ADokPH;;ACjkPE;EACC,WAAA;ADokPH;;ACzkPE;EACC,UAAA;AD4kPH;;ACzkPE;EACC,WAAA;AD4kPH;;ACjlPE;EACC,UAAA;ADolPH;;ACjlPE;EACC,WAAA;ADolPH;;ACzlPE;EACC,UAAA;AD4lPH;;ACzlPE;EACC,WAAA;AD4lPH;;ACjmPE;EACC,UAAA;ADomPH;;ACjmPE;EACC,WAAA;ADomPH;;ACzmPE;EACC,UAAA;AD4mPH;;ACzmPE;EACC,WAAA;AD4mPH;;ACjnPE;EACC,UAAA;ADonPH;;ACjnPE;EACC,WAAA;ADonPH;;ACznPE;EACC,UAAA;AD4nPH;;ACznPE;EACC,WAAA;AD4nPH;;ACjoPE;EACC,UAAA;ADooPH;;ACjoPE;EACC,WAAA;ADooPH;;ACzoPE;EACC,WAAA;AD4oPH;;ACzoPE;EACC,YAAA;AD4oPH;;AC3pPE;EACC,WAAA;AD8pPH;;AC3pPE;EACC,YAAA;AD8pPH;;ACnqPE;EACC,WAAA;ADsqPH;;ACnqPE;EACC,YAAA;ADsqPH;;AC3qPE;EACC,WAAA;AD8qPH;;AC3qPE;EACC,YAAA;AD8qPH;;ACnrPE;EACC,WAAA;ADsrPH;;ACnrPE;EACC,YAAA;ADsrPH;;AC3rPE;EACC,WAAA;AD8rPH;;AC3rPE;EACC,YAAA;AD8rPH;;ACnsPE;EACC,WAAA;ADssPH;;ACnsPE;EACC,YAAA;ADssPH;;AC3sPE;EACC,WAAA;AD8sPH;;AC3sPE;EACC,YAAA;AD8sPH;;ACntPE;EACC,WAAA;ADstPH;;ACntPE;EACC,YAAA;ADstPH;;AC3tPE;EACC,WAAA;AD8tPH;;AC3tPE;EACC,YAAA;AD8tPH;;ACnuPE;EACC,WAAA;ADsuPH;;ACnuPE;EACC,YAAA;ADsuPH;;AC3uPE;EACC,YAAA;AD8uPH;;AC3uPE;EACC,aAAA;AD8uPH;;ACnvPE;EACC,YAAA;ADsvPH;;ACnvPE;EACC,aAAA;ADsvPH;;AC3vPE;EACC,YAAA;AD8vPH;;AC3vPE;EACC,aAAA;AD8vPH;;ACnwPE;EACC,YAAA;ADswPH;;ACnwPE;EACC,aAAA;ADswPH;;AC3wPE;EACC,YAAA;AD8wPH;;AC3wPE;EACC,aAAA;AD8wPH;;ACnxPE;EACC,YAAA;ADsxPH;;ACnxPE;EACC,aAAA;ADsxPH;;AC3xPE;EACC,YAAA;AD8xPH;;AC3xPE;EACC,aAAA;AD8xPH;;ACnyPE;EACC,YAAA;ADsyPH;;ACnyPE;EACC,aAAA;ADsyPH;;AC3yPE;EACC,YAAA;AD8yPH;;AC3yPE;EACC,aAAA;AD8yPH;;ACnzPE;EACC,YAAA;ADszPH;;ACnzPE;EACC,aAAA;ADszPH;;AC3zPE;EACC,YAAA;AD8zPH;;AC3zPE;EACC,aAAA;AD8zPH;;ACn0PE;EACC,YAAA;ADs0PH;;ACn0PE;EACC,aAAA;ADs0PH;;AC30PE;EACC,YAAA;AD80PH;;AC30PE;EACC,aAAA;AD80PH;;ACn1PE;EACC,YAAA;ADs1PH;;ACn1PE;EACC,aAAA;ADs1PH;;AC31PE;EACC,YAAA;AD81PH;;AC31PE;EACC,aAAA;AD81PH;;ACn2PE;EACC,YAAA;ADs2PH;;ACn2PE;EACC,aAAA;ADs2PH;;AC32PE;EACC,YAAA;AD82PH;;AC32PE;EACC,aAAA;AD82PH;;ACn3PE;EACC,YAAA;ADs3PH;;ACn3PE;EACC,aAAA;ADs3PH;;AC33PE;EACC,YAAA;AD83PH;;AC33PE;EACC,aAAA;AD83PH;;ACn4PE;EACC,YAAA;ADs4PH;;ACn4PE;EACC,aAAA;ADs4PH;;AC34PE;EACC,YAAA;AD84PH;;AC34PE;EACC,aAAA;AD84PH;;ACn5PE;EACC,YAAA;ADs5PH;;ACn5PE;EACC,aAAA;ADs5PH;;AC35PE;EACC,YAAA;AD85PH;;AC35PE;EACC,aAAA;AD85PH;;ACn6PE;EACC,YAAA;ADs6PH;;ACn6PE;EACC,aAAA;ADs6PH;;AC36PE;EACC,YAAA;AD86PH;;AC36PE;EACC,aAAA;AD86PH;;ACn7PE;EACC,YAAA;ADs7PH;;ACn7PE;EACC,aAAA;ADs7PH;;AC37PE;EACC,YAAA;AD87PH;;AC37PE;EACC,aAAA;AD87PH;;ACn8PE;EACC,YAAA;ADs8PH;;ACn8PE;EACC,aAAA;ADs8PH;;AC38PE;EACC,YAAA;AD88PH;;AC38PE;EACC,aAAA;AD88PH;;ACn9PE;EACC,YAAA;ADs9PH;;ACn9PE;EACC,aAAA;ADs9PH;;AC39PE;EACC,YAAA;AD89PH;;AC39PE;EACC,aAAA;AD89PH;;ACn+PE;EACC,YAAA;ADs+PH;;ACn+PE;EACC,aAAA;ADs+PH;;AC3+PE;EACC,YAAA;AD8+PH;;AC3+PE;EACC,aAAA;AD8+PH;;ACn/PE;EACC,YAAA;ADs/PH;;ACn/PE;EACC,aAAA;ADs/PH;;AC3/PE;EACC,YAAA;AD8/PH;;AC3/PE;EACC,aAAA;AD8/PH;;ACngQE;EACC,YAAA;ADsgQH;;ACngQE;EACC,aAAA;ADsgQH;;AC3gQE;EACC,YAAA;AD8gQH;;AC3gQE;EACC,aAAA;AD8gQH;;ACnhQE;EACC,YAAA;ADshQH;;ACnhQE;EACC,aAAA;ADshQH;;AC3hQE;EACC,YAAA;AD8hQH;;AC3hQE;EACC,aAAA;AD8hQH;;ACniQE;EACC,YAAA;ADsiQH;;ACniQE;EACC,aAAA;ADsiQH;;AC3iQE;EACC,YAAA;AD8iQH;;AC3iQE;EACC,aAAA;AD8iQH;;ACziQE;EACC,WAAA;AD4iQH;;ACziQE;EACC,YAAA;AD4iQH;;ACjjQE;EACC,WAAA;ADojQH;;ACjjQE;EACC,YAAA;ADojQH;;ACzjQE;EACC,YAAA;AD4jQH;;ACzjQE;EACC,aAAA;AD4jQH;;ACjkQE;EACC,YAAA;ADokQH;;ACjkQE;EACC,aAAA;ADokQH;;ACzkQE;EACC,YAAA;AD4kQH;;ACzkQE;EACC,aAAA;AD4kQH;;ACjlQE;EACC,YAAA;ADolQH;;ACjlQE;EACC,aAAA;ADolQH;;ACzlQE;EACC,YAAA;AD4lQH;;ACzlQE;EACC,aAAA;AD4lQH;;ACjmQE;EACC,YAAA;ADomQH;;ACjmQE;EACC,aAAA;ADomQH;;ACzmQE;EACC,YAAA;AD4mQH;;ACzmQE;EACC,aAAA;AD4mQH;;ACjnQE;EACC,YAAA;ADonQH;;ACjnQE;EACC,aAAA;ADonQH;;ACznQE;EACC,YAAA;AD4nQH;;ACznQE;EACC,aAAA;AD4nQH;;ACjoQE;EACC,YAAA;ADooQH;;ACjoQE;EACC,aAAA;ADooQH;;ACzoQE;EACC,YAAA;AD4oQH;;ACzoQE;EACC,aAAA;AD4oQH;;ACjpQE;EACC,YAAA;ADopQH;;ACjpQE;EACC,aAAA;ADopQH;;ACzpQE;EACC,YAAA;AD4pQH;;ACzpQE;EACC,aAAA;AD4pQH;;ACjqQE;EACC,YAAA;ADoqQH;;ACjqQE;EACC,aAAA;ADoqQH;;ACzqQE;EACC,YAAA;AD4qQH;;ACzqQE;EACC,aAAA;AD4qQH;;ACjrQE;EACC,YAAA;ADorQH;;ACjrQE;EACC,aAAA;ADorQH;;ACzrQE;EACC,YAAA;AD4rQH;;ACzrQE;EACC,aAAA;AD4rQH;;ACjsQE;EACC,YAAA;ADosQH;;ACjsQE;EACC,aAAA;ADosQH;;ACzsQE;EACC,YAAA;AD4sQH;;ACzsQE;EACC,aAAA;AD4sQH;;ACjtQE;EACC,YAAA;ADotQH;;ACjtQE;EACC,aAAA;ADotQH;;ACztQE;EACC,YAAA;AD4tQH;;ACztQE;EACC,aAAA;AD4tQH;;ACjuQE;EACC,YAAA;ADouQH;;ACjuQE;EACC,aAAA;ADouQH;;ACzuQE;EACC,aAAA;AD4uQH;;ACzuQE;EACC,cAAA;AD4uQH;;AC3vQE;EACC,YAAA;AD8vQH;;AC3vQE;EACC,aAAA;AD8vQH;;ACnwQE;EACC,YAAA;ADswQH;;ACnwQE;EACC,aAAA;ADswQH;;AC3wQE;EACC,YAAA;AD8wQH;;AC3wQE;EACC,aAAA;AD8wQH;;ACnxQE;EACC,YAAA;ADsxQH;;ACnxQE;EACC,aAAA;ADsxQH;;AC3xQE;EACC,YAAA;AD8xQH;;AC3xQE;EACC,aAAA;AD8xQH;;ACnyQE;EACC,YAAA;ADsyQH;;ACnyQE;EACC,aAAA;ADsyQH;;AC3yQE;EACC,YAAA;AD8yQH;;AC3yQE;EACC,aAAA;AD8yQH;;ACnzQE;EACC,YAAA;ADszQH;;ACnzQE;EACC,aAAA;ADszQH;;AC3zQE;EACC,YAAA;AD8zQH;;AC3zQE;EACC,aAAA;AD8zQH;;ACn0QE;EACC,YAAA;ADs0QH;;ACn0QE;EACC,aAAA;ADs0QH;;AC30QE;EACC,aAAA;AD80QH;;AC30QE;EACC,cAAA;AD80QH;;ACn1QE;EACC,aAAA;ADs1QH;;ACn1QE;EACC,cAAA;ADs1QH;;AC31QE;EACC,aAAA;AD81QH;;AC31QE;EACC,cAAA;AD81QH;;ACn2QE;EACC,aAAA;ADs2QH;;ACn2QE;EACC,cAAA;ADs2QH;;AC32QE;EACC,aAAA;AD82QH;;AC32QE;EACC,cAAA;AD82QH;;ACn3QE;EACC,aAAA;ADs3QH;;ACn3QE;EACC,cAAA;ADs3QH;;AC33QE;EACC,aAAA;AD83QH;;AC33QE;EACC,cAAA;AD83QH;;ACn4QE;EACC,aAAA;ADs4QH;;ACn4QE;EACC,cAAA;ADs4QH;;AC34QE;EACC,aAAA;AD84QH;;AC34QE;EACC,cAAA;AD84QH;;ACn5QE;EACC,aAAA;ADs5QH;;ACn5QE;EACC,cAAA;ADs5QH;;AC35QE;EACC,aAAA;AD85QH;;AC35QE;EACC,cAAA;AD85QH;;ACn6QE;EACC,aAAA;ADs6QH;;ACn6QE;EACC,cAAA;ADs6QH;;AC36QE;EACC,aAAA;AD86QH;;AC36QE;EACC,cAAA;AD86QH;;ACn7QE;EACC,aAAA;ADs7QH;;ACn7QE;EACC,cAAA;ADs7QH;;AC37QE;EACC,aAAA;AD87QH;;AC37QE;EACC,cAAA;AD87QH;;ACn8QE;EACC,aAAA;ADs8QH;;ACn8QE;EACC,cAAA;ADs8QH;;AC38QE;EACC,aAAA;AD88QH;;AC38QE;EACC,cAAA;AD88QH;;ACn9QE;EACC,aAAA;ADs9QH;;ACn9QE;EACC,cAAA;ADs9QH;;AC39QE;EACC,aAAA;AD89QH;;AC39QE;EACC,cAAA;AD89QH;;ACn+QE;EACC,aAAA;ADs+QH;;ACn+QE;EACC,cAAA;ADs+QH;;AC3+QE;EACC,aAAA;AD8+QH;;AC3+QE;EACC,cAAA;AD8+QH;;ACn/QE;EACC,aAAA;ADs/QH;;ACn/QE;EACC,cAAA;ADs/QH;;AC3/QE;EACC,aAAA;AD8/QH;;AC3/QE;EACC,cAAA;AD8/QH;;ACngRE;EACC,aAAA;ADsgRH;;ACngRE;EACC,cAAA;ADsgRH;;AC3gRE;EACC,aAAA;AD8gRH;;AC3gRE;EACC,cAAA;AD8gRH;;ACnhRE;EACC,aAAA;ADshRH;;ACnhRE;EACC,cAAA;ADshRH;;AC3hRE;EACC,aAAA;AD8hRH;;AC3hRE;EACC,cAAA;AD8hRH;;ACniRE;EACC,aAAA;ADsiRH;;ACniRE;EACC,cAAA;ADsiRH;;AC3iRE;EACC,aAAA;AD8iRH;;AC3iRE;EACC,cAAA;AD8iRH;;ACnjRE;EACC,aAAA;ADsjRH;;ACnjRE;EACC,cAAA;ADsjRH;;AC3jRE;EACC,aAAA;AD8jRH;;AC3jRE;EACC,cAAA;AD8jRH;;ACnkRE;EACC,aAAA;ADskRH;;ACnkRE;EACC,cAAA;ADskRH;;AC3kRE;EACC,aAAA;AD8kRH;;AC3kRE;EACC,cAAA;AD8kRH;;ACnlRE;EACC,aAAA;ADslRH;;ACnlRE;EACC,cAAA;ADslRH;;AC3lRE;EACC,aAAA;AD8lRH;;AC3lRE;EACC,cAAA;AD8lRH;;ACnmRE;EACC,aAAA;ADsmRH;;ACnmRE;EACC,cAAA;ADsmRH;;AC3mRE;EACC,aAAA;AD8mRH;;AC3mRE;EACC,cAAA;AD8mRH;;ACnnRE;EACC,aAAA;ADsnRH;;ACnnRE;EACC,cAAA;ADsnRH;;AC3nRE;EACC,aAAA;AD8nRH;;AC3nRE;EACC,cAAA;AD8nRH;;ACnoRE;EACC,aAAA;ADsoRH;;ACnoRE;EACC,cAAA;ADsoRH;;AC3oRE;EACC,aAAA;AD8oRH;;AC3oRE;EACC,cAAA;AD8oRH;;ACzoRE;EACC,YAAA;AD4oRH;;ACzoRE;EACC,aAAA;AD4oRH;;ACjpRE;EACC,YAAA;ADopRH;;ACjpRE;EACC,aAAA;ADopRH;;ACzpRE;EACC,aAAA;AD4pRH;;ACzpRE;EACC,cAAA;AD4pRH;;ACjqRE;EACC,aAAA;ADoqRH;;ACjqRE;EACC,cAAA;ADoqRH;;ACzqRE;EACC,aAAA;AD4qRH;;ACzqRE;EACC,cAAA;AD4qRH;;ACjrRE;EACC,aAAA;ADorRH;;ACjrRE;EACC,cAAA;ADorRH;;ACzrRE;EACC,aAAA;AD4rRH;;ACzrRE;EACC,cAAA;AD4rRH;;ACjsRE;EACC,aAAA;ADosRH;;ACjsRE;EACC,cAAA;ADosRH;;ACzsRE;EACC,aAAA;AD4sRH;;ACzsRE;EACC,cAAA;AD4sRH;;ACjtRE;EACC,aAAA;ADotRH;;ACjtRE;EACC,cAAA;ADotRH;;ACztRE;EACC,aAAA;AD4tRH;;ACztRE;EACC,cAAA;AD4tRH;;ACjuRE;EACC,aAAA;ADouRH;;ACjuRE;EACC,cAAA;ADouRH;;ACzuRE;EACC,aAAA;AD4uRH;;ACzuRE;EACC,cAAA;AD4uRH;;ACjvRE;EACC,aAAA;ADovRH;;ACjvRE;EACC,cAAA;ADovRH;;ACzvRE;EACC,aAAA;AD4vRH;;ACzvRE;EACC,cAAA;AD4vRH;;ACjwRE;EACC,aAAA;ADowRH;;ACjwRE;EACC,cAAA;ADowRH;;ACzwRE;EACC,aAAA;AD4wRH;;ACzwRE;EACC,cAAA;AD4wRH;;ACjxRE;EACC,aAAA;ADoxRH;;ACjxRE;EACC,cAAA;ADoxRH;;ACzxRE;EACC,aAAA;AD4xRH;;ACzxRE;EACC,cAAA;AD4xRH;;ACjyRE;EACC,aAAA;ADoyRH;;ACjyRE;EACC,cAAA;ADoyRH;;ACzyRE;EACC,aAAA;AD4yRH;;ACzyRE;EACC,cAAA;AD4yRH;;ACjzRE;EACC,aAAA;ADozRH;;ACjzRE;EACC,cAAA;ADozRH;;ACzzRE;EACC,aAAA;AD4zRH;;ACzzRE;EACC,cAAA;AD4zRH;;ACj0RE;EACC,aAAA;ADo0RH;;ACj0RE;EACC,cAAA;ADo0RH;;ACz0RE;EACC,cAAA;AD40RH;;ACz0RE;EACC,eAAA;AD40RH;;AC31RE;EACC,UAAA;AD81RH;;AC31RE;EACC,WAAA;AD81RH;;ACn2RE;EACC,UAAA;ADs2RH;;ACn2RE;EACC,WAAA;ADs2RH;;AC32RE;EACC,UAAA;AD82RH;;AC32RE;EACC,WAAA;AD82RH;;ACn3RE;EACC,UAAA;ADs3RH;;ACn3RE;EACC,WAAA;ADs3RH;;AC33RE;EACC,UAAA;AD83RH;;AC33RE;EACC,WAAA;AD83RH;;ACn4RE;EACC,UAAA;ADs4RH;;ACn4RE;EACC,WAAA;ADs4RH;;AC34RE;EACC,UAAA;AD84RH;;AC34RE;EACC,WAAA;AD84RH;;ACn5RE;EACC,UAAA;ADs5RH;;ACn5RE;EACC,WAAA;ADs5RH;;AC35RE;EACC,UAAA;AD85RH;;AC35RE;EACC,WAAA;AD85RH;;ACn6RE;EACC,UAAA;ADs6RH;;ACn6RE;EACC,WAAA;ADs6RH;;AC36RE;EACC,WAAA;AD86RH;;AC36RE;EACC,YAAA;AD86RH;;ACn7RE;EACC,WAAA;ADs7RH;;ACn7RE;EACC,YAAA;ADs7RH;;AC37RE;EACC,WAAA;AD87RH;;AC37RE;EACC,YAAA;AD87RH;;ACn8RE;EACC,WAAA;ADs8RH;;ACn8RE;EACC,YAAA;ADs8RH;;AC38RE;EACC,WAAA;AD88RH;;AC38RE;EACC,YAAA;AD88RH;;ACn9RE;EACC,WAAA;ADs9RH;;ACn9RE;EACC,YAAA;ADs9RH;;AC39RE;EACC,WAAA;AD89RH;;AC39RE;EACC,YAAA;AD89RH;;ACn+RE;EACC,WAAA;ADs+RH;;ACn+RE;EACC,YAAA;ADs+RH;;AC3+RE;EACC,WAAA;AD8+RH;;AC3+RE;EACC,YAAA;AD8+RH;;ACn/RE;EACC,WAAA;ADs/RH;;ACn/RE;EACC,YAAA;ADs/RH;;AC3/RE;EACC,WAAA;AD8/RH;;AC3/RE;EACC,YAAA;AD8/RH;;ACngSE;EACC,WAAA;ADsgSH;;ACngSE;EACC,YAAA;ADsgSH;;AC3gSE;EACC,WAAA;AD8gSH;;AC3gSE;EACC,YAAA;AD8gSH;;ACnhSE;EACC,WAAA;ADshSH;;ACnhSE;EACC,YAAA;ADshSH;;AC3hSE;EACC,WAAA;AD8hSH;;AC3hSE;EACC,YAAA;AD8hSH;;ACniSE;EACC,WAAA;ADsiSH;;ACniSE;EACC,YAAA;ADsiSH;;AC3iSE;EACC,WAAA;AD8iSH;;AC3iSE;EACC,YAAA;AD8iSH;;ACnjSE;EACC,WAAA;ADsjSH;;ACnjSE;EACC,YAAA;ADsjSH;;AC3jSE;EACC,WAAA;AD8jSH;;AC3jSE;EACC,YAAA;AD8jSH;;ACnkSE;EACC,WAAA;ADskSH;;ACnkSE;EACC,YAAA;ADskSH;;AC3kSE;EACC,WAAA;AD8kSH;;AC3kSE;EACC,YAAA;AD8kSH;;ACnlSE;EACC,WAAA;ADslSH;;ACnlSE;EACC,YAAA;ADslSH;;AC3lSE;EACC,WAAA;AD8lSH;;AC3lSE;EACC,YAAA;AD8lSH;;ACnmSE;EACC,WAAA;ADsmSH;;ACnmSE;EACC,YAAA;ADsmSH;;AC3mSE;EACC,WAAA;AD8mSH;;AC3mSE;EACC,YAAA;AD8mSH;;ACnnSE;EACC,WAAA;ADsnSH;;ACnnSE;EACC,YAAA;ADsnSH;;AC3nSE;EACC,WAAA;AD8nSH;;AC3nSE;EACC,YAAA;AD8nSH;;ACnoSE;EACC,WAAA;ADsoSH;;ACnoSE;EACC,YAAA;ADsoSH;;AC3oSE;EACC,WAAA;AD8oSH;;AC3oSE;EACC,YAAA;AD8oSH;;ACnpSE;EACC,WAAA;ADspSH;;ACnpSE;EACC,YAAA;ADspSH;;AC3pSE;EACC,WAAA;AD8pSH;;AC3pSE;EACC,YAAA;AD8pSH;;ACnqSE;EACC,WAAA;ADsqSH;;ACnqSE;EACC,YAAA;ADsqSH;;AC3qSE;EACC,WAAA;AD8qSH;;AC3qSE;EACC,YAAA;AD8qSH;;ACnrSE;EACC,WAAA;ADsrSH;;ACnrSE;EACC,YAAA;ADsrSH;;AC3rSE;EACC,WAAA;AD8rSH;;AC3rSE;EACC,YAAA;AD8rSH;;ACnsSE;EACC,WAAA;ADssSH;;ACnsSE;EACC,YAAA;ADssSH;;AC3sSE;EACC,WAAA;AD8sSH;;AC3sSE;EACC,YAAA;AD8sSH;;ACntSE;EACC,WAAA;ADstSH;;ACntSE;EACC,YAAA;ADstSH;;AC3tSE;EACC,WAAA;AD8tSH;;AC3tSE;EACC,YAAA;AD8tSH;;ACnuSE;EACC,WAAA;ADsuSH;;ACnuSE;EACC,YAAA;ADsuSH;;AC3uSE;EACC,WAAA;AD8uSH;;AC3uSE;EACC,YAAA;AD8uSH;;ACzuSE;EACC,UAAA;AD4uSH;;ACzuSE;EACC,WAAA;AD4uSH;;ACjvSE;EACC,UAAA;ADovSH;;ACjvSE;EACC,WAAA;ADovSH;;ACzvSE;EACC,WAAA;AD4vSH;;ACzvSE;EACC,YAAA;AD4vSH;;ACjwSE;EACC,WAAA;ADowSH;;ACjwSE;EACC,YAAA;ADowSH;;ACzwSE;EACC,WAAA;AD4wSH;;ACzwSE;EACC,YAAA;AD4wSH;;ACjxSE;EACC,WAAA;ADoxSH;;ACjxSE;EACC,YAAA;ADoxSH;;ACzxSE;EACC,WAAA;AD4xSH;;ACzxSE;EACC,YAAA;AD4xSH;;ACjySE;EACC,WAAA;ADoySH;;ACjySE;EACC,YAAA;ADoySH;;ACzySE;EACC,WAAA;AD4ySH;;ACzySE;EACC,YAAA;AD4ySH;;ACjzSE;EACC,WAAA;ADozSH;;ACjzSE;EACC,YAAA;ADozSH;;ACzzSE;EACC,WAAA;AD4zSH;;ACzzSE;EACC,YAAA;AD4zSH;;ACj0SE;EACC,WAAA;ADo0SH;;ACj0SE;EACC,YAAA;ADo0SH;;ACz0SE;EACC,WAAA;AD40SH;;ACz0SE;EACC,YAAA;AD40SH;;ACj1SE;EACC,WAAA;ADo1SH;;ACj1SE;EACC,YAAA;ADo1SH;;ACz1SE;EACC,WAAA;AD41SH;;ACz1SE;EACC,YAAA;AD41SH;;ACj2SE;EACC,WAAA;ADo2SH;;ACj2SE;EACC,YAAA;ADo2SH;;ACz2SE;EACC,WAAA;AD42SH;;ACz2SE;EACC,YAAA;AD42SH;;ACj3SE;EACC,WAAA;ADo3SH;;ACj3SE;EACC,YAAA;ADo3SH;;ACz3SE;EACC,WAAA;AD43SH;;ACz3SE;EACC,YAAA;AD43SH;;ACj4SE;EACC,WAAA;ADo4SH;;ACj4SE;EACC,YAAA;ADo4SH;;ACz4SE;EACC,WAAA;AD44SH;;ACz4SE;EACC,YAAA;AD44SH;;ACj5SE;EACC,WAAA;ADo5SH;;ACj5SE;EACC,YAAA;ADo5SH;;ACz5SE;EACC,WAAA;AD45SH;;ACz5SE;EACC,YAAA;AD45SH;;ACj6SE;EACC,WAAA;ADo6SH;;ACj6SE;EACC,YAAA;ADo6SH;;ACz6SE;EACC,YAAA;AD46SH;;ACz6SE;EACC,aAAA;AD46SH;;ACh6SA;EACC,aAAA;ADm6SD;;ACh6SA;EACC,sBAAA;ADm6SD;;ACh6SA;EACC,mBAAA;ADm6SD;;ACh6SA;EACC,cAAA;ADm6SD;;ACh6SA;EACC,mBAAA;ADm6SD;;ACh6SA;EACC,2BAAA;ADm6SD;;AC/5SA;EA9BC,2BA+BqB;EA9BrB,uBA8BiC;EA7BjC,aAAA;ADi8SD;;ACh6SA;EAnCC,uBAoCqB;EAnCrB,uBAmC6B;EAlC7B,aAAA;ADu8SD;;ACj6SA;EAxCC,yBAyCqB;EAxCrB,uBAwC+B;EAvC/B,aAAA;AD68SD;;ACl6SA;EA7CC,2BA8CqB;EA7CrB,mBA6CiC;EA5CjC,aAAA;ADm9SD;;ACn6SA;EAlDC,uBAmDqB;EAlDrB,mBAkD6B;EAjD7B,aAAA;ADy9SD;;ACp6SA;EAvDC,yBAwDqB;EAvDrB,mBAuD+B;EAtD/B,aAAA;AD+9SD;;ACr6SA;EA5DC,2BA6DqB;EA5DrB,qBA4DiC;EA3DjC,aAAA;ADq+SD;;ACt6SA;EAjEC,uBAkEqB;EAjErB,qBAiE6B;EAhE7B,aAAA;AD2+SD;;ACv6SA;EAtEC,yBAuEqB;EAtErB,qBAsE+B;EArE/B,aAAA;ADi/SD;;ACx6SA;EA3EC,8BA4EqB;EA3ErB,mBA2EoC;EA1EpC,aAAA;ADu/SD;;ACx6SA;EAjFC,2BAkFqB;EAjFrB,uBAiFiC;EAhFjC,aAAA;AD6/SD;;ACz6SA;EAtFC,2BAuFqB;EAtFrB,mBAsFiC;EArFjC,aAAA;ADmgTD;;AC16SA;EA3FC,2BA4FqB;EA3FrB,qBA2FiC;EA1FjC,aAAA;ADygTD;;AC36SA;EAhGC,uBAiGqB;EAhGrB,uBAgG6B;EA/F7B,aAAA;AD+gTD;;AC56SA;EArGC,uBAsGqB;EArGrB,mBAqG6B;EApG7B,aAAA;ADqhTD;;AC76SA;EA1GC,uBA2GqB;EA1GrB,qBA0G6B;EAzG7B,aAAA;AD2hTD;;AC96SA;EA/GC,yBAgHqB;EA/GrB,uBA+G+B;EA9G/B,aAAA;ADiiTD;;AC/6SA;EApHC,yBAqHqB;EApHrB,mBAoH+B;EAnH/B,aAAA;ADuiTD;;ACh7SA;EAzHC,yBA0HqB;EAzHrB,qBAyH+B;EAxH/B,aAAA;AD6iTD;;AC/6SA;EAhIC,2BAiIqB;EAhIrB,mBAgIiC;EA/HjC,aAAA;ADmjTD;;ACh7SA;EArIC,yBAsIqB;EArIrB,mBAqI+B;EApI/B,aAAA;ADyjTD;;ACj7SA;EA1IC,uBA2IqB;EA1IrB,mBA0I6B;EAzI7B,aAAA;AD+jTD;;ACl7SA;EACC,8BAAA;ADq7SD;;ACj7SA;EACC,sBAAA;EACA,oBAAA;ADo7SD;;ACh7SA;EACC,6BAAA;ADm7SD;;AC/6SC;EACC,OAFW;ADo7Sb;;ACn7SC;EACC,OAFW;ADw7Sb;;ACv7SC;EACC,OAFW;AD47Sb;;AC37SC;EACC,OAFW;ADg8Sb;;AC/7SC;EACC,OAFW;ADo8Sb;;ACn8SC;EACC,OAFW;ADw8Sb;;ACv8SC;EACC,OAFW;AD48Sb;;AC38SC;EACC,OAFW;ADg9Sb;;AC/8SC;EACC,OAFW;ADo9Sb;;ACn9SC;EACC,OAFW;ADw9Sb;;ACv9SC;EACC,QAFW;AD49Sb;;AC39SC;EACC,QAFW;ADg+Sb;;AC/9SC;EACC,QAFW;ADo+Sb;;ACt7SC;EACC,cAxBO;ADi9ST;;ACt7SC;EACC,yBA5BO;ADq9ST;;AC97SC;EACC,cAxBO;ADy9ST;;AC97SC;EACC,yBA5BO;AD69ST;;ACt8SC;EACC,cAxBO;ADi+ST;;ACt8SC;EACC,yBA5BO;ADq+ST;;AC98SC;EACC,cAxBO;ADy+ST;;AC98SC;EACC,yBA5BO;AD6+ST;;ACt9SC;EACC,cAxBO;ADi/ST;;ACt9SC;EACC,yBA5BO;ADq/ST;;AC99SC;EACC,cAxBO;ADy/ST;;AC99SC;EACC,yBA5BO;AD6/ST;;ACt+SC;EACC,cAxBO;ADigTT;;ACt+SC;EACC,yBA5BO;ADqgTT;;AC9+SC;EACC,cAxBO;ADygTT;;AC9+SC;EACC,yBA5BO;AD6gTT;;ACt/SC;EACC,cAxBO;ADihTT;;ACt/SC;EACC,yBA5BO;ADqhTT;;AC9/SC;EACC,cAxBO;ADyhTT;;AC9/SC;EACC,yBA5BO;AD6hTT;;ACtgTC;EACC,cAxBO;ADiiTT;;ACtgTC;EACC,yBA5BO;ADqiTT;;AC9gTC;EACC,cAxBO;ADyiTT;;AC9gTC;EACC,yBA5BO;AD6iTT;;ACthTC;EACC,cAxBO;ADijTT;;ACthTC;EACC,yBA5BO;ADqjTT;;AC9hTC;EACC,cAxBO;ADyjTT;;AC9hTC;EACC,yBA5BO;AD6jTT;;ACtiTC;EACC,cAxBO;ADikTT;;ACtiTC;EACC,yBA5BO;ADqkTT;;AC9iTC;EACC,cAxBO;ADykTT;;AC9iTC;EACC,yBA5BO;AD6kTT;;ACtjTC;EACC,cAxBO;ADilTT;;ACtjTC;EACC,yBA5BO;ADqlTT;;AC9jTC;EACC,cAxBO;ADylTT;;AC9jTC;EACC,yBA5BO;AD6lTT;;AC5jTC;EACC,cAlDc;ADinThB;;AC5jTC;EACC,yBAtDc;ADqnThB;;ACpkTC;EACC,cAlDc;ADynThB;;ACpkTC;EACC,yBAtDc;AD6nThB;;AC5kTC;EACC,cAlDc;ADioThB;;AC5kTC;EACC,yBAtDc;ADqoThB;;ACplTC;EACC,cAlDc;ADyoThB;;ACplTC;EACC,yBAtDc;AD6oThB;;AC5lTC;EACC,cAlDc;ADipThB;;AC5lTC;EACC,yBAtDc;ADqpThB;;ACpmTC;EACC,cAlDc;ADypThB;;ACpmTC;EACC,yBAtDc;AD6pThB;;AC5mTC;EACC,cAlDc;ADiqThB;;AC5mTC;EACC,yBAtDc;ADqqThB;;ACpnTC;EACC,cAlDc;ADyqThB;;ACpnTC;EACC,yBAtDc;AD6qThB;;AC5nTC;EACC,cAlDc;ADirThB;;AC5nTC;EACC,yBAtDc;ADqrThB;;ACpoTC;EACC,cAlDc;ADyrThB;;ACpoTC;EACC,yBAtDc;AD6rThB;;AC5oTC;EACC,cAlDc;ADisThB;;AC5oTC;EACC,yBAtDc;ADqsThB;;ACppTC;EACC,cAlDc;ADysThB;;ACppTC;EACC,yBAtDc;AD6sThB;;AC5pTC;EACC,cAlDc;ADitThB;;AC5pTC;EACC,yBAtDc;ADqtThB;;ACpqTC;EACC,cAlDc;ADytThB;;ACpqTC;EACC,yBAtDc;AD6tThB","file":"uvue.css"} \ No newline at end of file diff --git a/uni_modules/tmx-ui/scss/uvue.min.css b/uni_modules/tmx-ui/scss/uvue.min.css new file mode 100644 index 0000000..2541483 --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvue.min.css @@ -0,0 +1 @@ +@charset "UTF-8";.overflow{overflow:hidden}.show{visibility:visible}.hidden{visibility:hidden}.none{display:none}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.fulled{width:100%}.fulled-height{flex:1}.zIndex-0{z-index:0}.zIndex-n0{z-index:0}.zIndex-1{z-index:1}.zIndex-n1{z-index:4}.zIndex-2{z-index:2}.zIndex-n2{z-index:8}.zIndex-3{z-index:3}.zIndex-n3{z-index:12}.zIndex-4{z-index:4}.zIndex-n4{z-index:16}.zIndex-5{z-index:5}.zIndex-n5{z-index:20}.zIndex-6{z-index:6}.zIndex-n6{z-index:24}.zIndex-7{z-index:7}.zIndex-n7{z-index:28}.zIndex-8{z-index:8}.zIndex-n8{z-index:32}.zIndex-9{z-index:9}.zIndex-n9{z-index:36}.zIndex-10{z-index:10}.zIndex-n10{z-index:40}.zIndex-11{z-index:11}.zIndex-n11{z-index:44}.zIndex-12{z-index:12}.zIndex-n12{z-index:48}.zIndex-13{z-index:13}.zIndex-n13{z-index:52}.zIndex-14{z-index:14}.zIndex-n14{z-index:56}.zIndex-15{z-index:15}.zIndex-n15{z-index:60}.zIndex-16{z-index:16}.zIndex-n16{z-index:64}.zIndex-17{z-index:17}.zIndex-n17{z-index:68}.zIndex-18{z-index:18}.zIndex-n18{z-index:72}.zIndex-19{z-index:19}.zIndex-n19{z-index:76}.zIndex-20{z-index:20}.zIndex-n20{z-index:80}.zIndex-21{z-index:21}.zIndex-n21{z-index:84}.zIndex-22{z-index:22}.zIndex-n22{z-index:88}.zIndex-23{z-index:23}.zIndex-n23{z-index:92}.zIndex-24{z-index:24}.zIndex-n24{z-index:96}.zIndex-25{z-index:25}.zIndex-n25{z-index:100}.zIndex-26{z-index:26}.zIndex-n26{z-index:104}.text-overflow{text-overflow:ellipsis}.text-overflow-1{text-overflow:ellipsis;lines:1}.text-overflow-2{text-overflow:ellipsis;lines:2}.text-overflow-3{text-overflow:ellipsis;lines:3}.text-overflow-4{text-overflow:ellipsis;lines:4}.text-size-xxs{font-size:20rpx}.text-size-xs{font-size:22rpx}.text-size-s{font-size:24rpx}.text-size-m{font-size:28rpx}.text-size-n{font-size:30rpx}.text-size-g{font-size:34rpx}.text-size-lg{font-size:36rpx}.text-size-xl{font-size:40rpx}.text-weight-s{font-weight:400}.text-weight-n{font-weight:400}.text-weight-b{font-weight:700}.text-align-left{text-align:left}.text-align-right{text-align:right}.text-align-center{text-align:center}.round-tl-0{border-top-left-radius:0rpx}.round-tl-1{border-top-left-radius:2rpx}.round-tl-2{border-top-left-radius:4rpx}.round-tl-3{border-top-left-radius:6rpx}.round-tl-4{border-top-left-radius:8rpx}.round-tl-5{border-top-left-radius:10rpx}.round-tl-6{border-top-left-radius:12rpx}.round-tl-7{border-top-left-radius:14rpx}.round-tl-8{border-top-left-radius:16rpx}.round-tl-9{border-top-left-radius:18rpx}.round-tl-10{border-top-left-radius:20rpx}.round-tl-11{border-top-left-radius:22rpx}.round-tl-12{border-top-left-radius:24rpx}.round-tl-13{border-top-left-radius:26rpx}.round-tl-14{border-top-left-radius:28rpx}.round-tl-15{border-top-left-radius:30rpx}.round-tl-16{border-top-left-radius:32rpx}.round-tl-17{border-top-left-radius:34rpx}.round-tl-18{border-top-left-radius:36rpx}.round-tl-19{border-top-left-radius:38rpx}.round-tl-20{border-top-left-radius:40rpx}.round-tl-21{border-top-left-radius:42rpx}.round-tl-22{border-top-left-radius:44rpx}.round-tl-23{border-top-left-radius:46rpx}.round-tl-24{border-top-left-radius:48rpx}.round-tl-25{border-top-left-radius:50rpx}.round-tr-0{border-top-right-radius:0rpx}.round-tr-1{border-top-right-radius:2rpx}.round-tr-2{border-top-right-radius:4rpx}.round-tr-3{border-top-right-radius:6rpx}.round-tr-4{border-top-right-radius:8rpx}.round-tr-5{border-top-right-radius:10rpx}.round-tr-6{border-top-right-radius:12rpx}.round-tr-7{border-top-right-radius:14rpx}.round-tr-8{border-top-right-radius:16rpx}.round-tr-9{border-top-right-radius:18rpx}.round-tr-10{border-top-right-radius:20rpx}.round-tr-11{border-top-right-radius:22rpx}.round-tr-12{border-top-right-radius:24rpx}.round-tr-13{border-top-right-radius:26rpx}.round-tr-14{border-top-right-radius:28rpx}.round-tr-15{border-top-right-radius:30rpx}.round-tr-16{border-top-right-radius:32rpx}.round-tr-17{border-top-right-radius:34rpx}.round-tr-18{border-top-right-radius:36rpx}.round-tr-19{border-top-right-radius:38rpx}.round-tr-20{border-top-right-radius:40rpx}.round-tr-21{border-top-right-radius:42rpx}.round-tr-22{border-top-right-radius:44rpx}.round-tr-23{border-top-right-radius:46rpx}.round-tr-24{border-top-right-radius:48rpx}.round-tr-25{border-top-right-radius:50rpx}.round-bl-0{border-bottom-left-radius:0rpx}.round-bl-1{border-bottom-left-radius:2rpx}.round-bl-2{border-bottom-left-radius:4rpx}.round-bl-3{border-bottom-left-radius:6rpx}.round-bl-4{border-bottom-left-radius:8rpx}.round-bl-5{border-bottom-left-radius:10rpx}.round-bl-6{border-bottom-left-radius:12rpx}.round-bl-7{border-bottom-left-radius:14rpx}.round-bl-8{border-bottom-left-radius:16rpx}.round-bl-9{border-bottom-left-radius:18rpx}.round-bl-10{border-bottom-left-radius:20rpx}.round-bl-11{border-bottom-left-radius:22rpx}.round-bl-12{border-bottom-left-radius:24rpx}.round-bl-13{border-bottom-left-radius:26rpx}.round-bl-14{border-bottom-left-radius:28rpx}.round-bl-15{border-bottom-left-radius:30rpx}.round-bl-16{border-bottom-left-radius:32rpx}.round-bl-17{border-bottom-left-radius:34rpx}.round-bl-18{border-bottom-left-radius:36rpx}.round-bl-19{border-bottom-left-radius:38rpx}.round-bl-20{border-bottom-left-radius:40rpx}.round-bl-21{border-bottom-left-radius:42rpx}.round-bl-22{border-bottom-left-radius:44rpx}.round-bl-23{border-bottom-left-radius:46rpx}.round-bl-24{border-bottom-left-radius:48rpx}.round-bl-25{border-bottom-left-radius:50rpx}.round-br-0{border-bottom-right-radius:0rpx}.round-br-1{border-bottom-right-radius:2rpx}.round-br-2{border-bottom-right-radius:4rpx}.round-br-3{border-bottom-right-radius:6rpx}.round-br-4{border-bottom-right-radius:8rpx}.round-br-5{border-bottom-right-radius:10rpx}.round-br-6{border-bottom-right-radius:12rpx}.round-br-7{border-bottom-right-radius:14rpx}.round-br-8{border-bottom-right-radius:16rpx}.round-br-9{border-bottom-right-radius:18rpx}.round-br-10{border-bottom-right-radius:20rpx}.round-br-11{border-bottom-right-radius:22rpx}.round-br-12{border-bottom-right-radius:24rpx}.round-br-13{border-bottom-right-radius:26rpx}.round-br-14{border-bottom-right-radius:28rpx}.round-br-15{border-bottom-right-radius:30rpx}.round-br-16{border-bottom-right-radius:32rpx}.round-br-17{border-bottom-right-radius:34rpx}.round-br-18{border-bottom-right-radius:36rpx}.round-br-19{border-bottom-right-radius:38rpx}.round-br-20{border-bottom-right-radius:40rpx}.round-br-21{border-bottom-right-radius:42rpx}.round-br-22{border-bottom-right-radius:44rpx}.round-br-23{border-bottom-right-radius:46rpx}.round-br-24{border-bottom-right-radius:48rpx}.round-br-25{border-bottom-right-radius:50rpx}.round-a-0{border-radius:0rpx}.round-a-1{border-radius:2rpx}.round-a-2{border-radius:4rpx}.round-a-3{border-radius:6rpx}.round-a-4{border-radius:8rpx}.round-a-5{border-radius:10rpx}.round-a-6{border-radius:12rpx}.round-a-7{border-radius:14rpx}.round-a-8{border-radius:16rpx}.round-a-9{border-radius:18rpx}.round-a-10{border-radius:20rpx}.round-a-11{border-radius:22rpx}.round-a-12{border-radius:24rpx}.round-a-13{border-radius:26rpx}.round-a-14{border-radius:28rpx}.round-a-15{border-radius:30rpx}.round-a-16{border-radius:32rpx}.round-a-17{border-radius:34rpx}.round-a-18{border-radius:36rpx}.round-a-19{border-radius:38rpx}.round-a-20{border-radius:40rpx}.round-a-21{border-radius:42rpx}.round-a-22{border-radius:44rpx}.round-a-23{border-radius:46rpx}.round-a-24{border-radius:48rpx}.round-a-25{border-radius:50rpx}.round-t-0{border-top-left-radius:0rpx;border-top-right-radius:0rpx}.round-t-1{border-top-left-radius:2rpx;border-top-right-radius:2rpx}.round-t-2{border-top-left-radius:4rpx;border-top-right-radius:4rpx}.round-t-3{border-top-left-radius:6rpx;border-top-right-radius:6rpx}.round-t-4{border-top-left-radius:8rpx;border-top-right-radius:8rpx}.round-t-5{border-top-left-radius:10rpx;border-top-right-radius:10rpx}.round-t-6{border-top-left-radius:12rpx;border-top-right-radius:12rpx}.round-t-7{border-top-left-radius:14rpx;border-top-right-radius:14rpx}.round-t-8{border-top-left-radius:16rpx;border-top-right-radius:16rpx}.round-t-9{border-top-left-radius:18rpx;border-top-right-radius:18rpx}.round-t-10{border-top-left-radius:20rpx;border-top-right-radius:20rpx}.round-t-11{border-top-left-radius:22rpx;border-top-right-radius:22rpx}.round-t-12{border-top-left-radius:24rpx;border-top-right-radius:24rpx}.round-t-13{border-top-left-radius:26rpx;border-top-right-radius:26rpx}.round-t-14{border-top-left-radius:28rpx;border-top-right-radius:28rpx}.round-t-15{border-top-left-radius:30rpx;border-top-right-radius:30rpx}.round-t-16{border-top-left-radius:32rpx;border-top-right-radius:32rpx}.round-t-17{border-top-left-radius:34rpx;border-top-right-radius:34rpx}.round-t-18{border-top-left-radius:36rpx;border-top-right-radius:36rpx}.round-t-19{border-top-left-radius:38rpx;border-top-right-radius:38rpx}.round-t-20{border-top-left-radius:40rpx;border-top-right-radius:40rpx}.round-t-21{border-top-left-radius:42rpx;border-top-right-radius:42rpx}.round-t-22{border-top-left-radius:44rpx;border-top-right-radius:44rpx}.round-t-23{border-top-left-radius:46rpx;border-top-right-radius:46rpx}.round-t-24{border-top-left-radius:48rpx;border-top-right-radius:48rpx}.round-t-25{border-top-left-radius:50rpx;border-top-right-radius:50rpx}.round-b-0{border-bottom-left-radius:0rpx;border-bottom-right-radius:0rpx}.round-b-1{border-bottom-left-radius:2rpx;border-bottom-right-radius:2rpx}.round-b-2{border-bottom-left-radius:4rpx;border-bottom-right-radius:4rpx}.round-b-3{border-bottom-left-radius:6rpx;border-bottom-right-radius:6rpx}.round-b-4{border-bottom-left-radius:8rpx;border-bottom-right-radius:8rpx}.round-b-5{border-bottom-left-radius:10rpx;border-bottom-right-radius:10rpx}.round-b-6{border-bottom-left-radius:12rpx;border-bottom-right-radius:12rpx}.round-b-7{border-bottom-left-radius:14rpx;border-bottom-right-radius:14rpx}.round-b-8{border-bottom-left-radius:16rpx;border-bottom-right-radius:16rpx}.round-b-9{border-bottom-left-radius:18rpx;border-bottom-right-radius:18rpx}.round-b-10{border-bottom-left-radius:20rpx;border-bottom-right-radius:20rpx}.round-b-11{border-bottom-left-radius:22rpx;border-bottom-right-radius:22rpx}.round-b-12{border-bottom-left-radius:24rpx;border-bottom-right-radius:24rpx}.round-b-13{border-bottom-left-radius:26rpx;border-bottom-right-radius:26rpx}.round-b-14{border-bottom-left-radius:28rpx;border-bottom-right-radius:28rpx}.round-b-15{border-bottom-left-radius:30rpx;border-bottom-right-radius:30rpx}.round-b-16{border-bottom-left-radius:32rpx;border-bottom-right-radius:32rpx}.round-b-17{border-bottom-left-radius:34rpx;border-bottom-right-radius:34rpx}.round-b-18{border-bottom-left-radius:36rpx;border-bottom-right-radius:36rpx}.round-b-19{border-bottom-left-radius:38rpx;border-bottom-right-radius:38rpx}.round-b-20{border-bottom-left-radius:40rpx;border-bottom-right-radius:40rpx}.round-b-21{border-bottom-left-radius:42rpx;border-bottom-right-radius:42rpx}.round-b-22{border-bottom-left-radius:44rpx;border-bottom-right-radius:44rpx}.round-b-23{border-bottom-left-radius:46rpx;border-bottom-right-radius:46rpx}.round-b-24{border-bottom-left-radius:48rpx;border-bottom-right-radius:48rpx}.round-b-25{border-bottom-left-radius:50rpx;border-bottom-right-radius:50rpx}.round-l-0{border-top-left-radius:0rpx;border-bottom-left-radius:0rpx}.round-l-1{border-top-left-radius:2rpx;border-bottom-left-radius:2rpx}.round-l-2{border-top-left-radius:4rpx;border-bottom-left-radius:4rpx}.round-l-3{border-top-left-radius:6rpx;border-bottom-left-radius:6rpx}.round-l-4{border-top-left-radius:8rpx;border-bottom-left-radius:8rpx}.round-l-5{border-top-left-radius:10rpx;border-bottom-left-radius:10rpx}.round-l-6{border-top-left-radius:12rpx;border-bottom-left-radius:12rpx}.round-l-7{border-top-left-radius:14rpx;border-bottom-left-radius:14rpx}.round-l-8{border-top-left-radius:16rpx;border-bottom-left-radius:16rpx}.round-l-9{border-top-left-radius:18rpx;border-bottom-left-radius:18rpx}.round-l-10{border-top-left-radius:20rpx;border-bottom-left-radius:20rpx}.round-l-11{border-top-left-radius:22rpx;border-bottom-left-radius:22rpx}.round-l-12{border-top-left-radius:24rpx;border-bottom-left-radius:24rpx}.round-l-13{border-top-left-radius:26rpx;border-bottom-left-radius:26rpx}.round-l-14{border-top-left-radius:28rpx;border-bottom-left-radius:28rpx}.round-l-15{border-top-left-radius:30rpx;border-bottom-left-radius:30rpx}.round-l-16{border-top-left-radius:32rpx;border-bottom-left-radius:32rpx}.round-l-17{border-top-left-radius:34rpx;border-bottom-left-radius:34rpx}.round-l-18{border-top-left-radius:36rpx;border-bottom-left-radius:36rpx}.round-l-19{border-top-left-radius:38rpx;border-bottom-left-radius:38rpx}.round-l-20{border-top-left-radius:40rpx;border-bottom-left-radius:40rpx}.round-l-21{border-top-left-radius:42rpx;border-bottom-left-radius:42rpx}.round-l-22{border-top-left-radius:44rpx;border-bottom-left-radius:44rpx}.round-l-23{border-top-left-radius:46rpx;border-bottom-left-radius:46rpx}.round-l-24{border-top-left-radius:48rpx;border-bottom-left-radius:48rpx}.round-l-25{border-top-left-radius:50rpx;border-bottom-left-radius:50rpx}.round-r-0{border-top-right-radius:0rpx;border-bottom-right-radius:0rpx}.round-r-1{border-top-right-radius:2rpx;border-bottom-right-radius:2rpx}.round-r-2{border-top-right-radius:4rpx;border-bottom-right-radius:4rpx}.round-r-3{border-top-right-radius:6rpx;border-bottom-right-radius:6rpx}.round-r-4{border-top-right-radius:8rpx;border-bottom-right-radius:8rpx}.round-r-5{border-top-right-radius:10rpx;border-bottom-right-radius:10rpx}.round-r-6{border-top-right-radius:12rpx;border-bottom-right-radius:12rpx}.round-r-7{border-top-right-radius:14rpx;border-bottom-right-radius:14rpx}.round-r-8{border-top-right-radius:16rpx;border-bottom-right-radius:16rpx}.round-r-9{border-top-right-radius:18rpx;border-bottom-right-radius:18rpx}.round-r-10{border-top-right-radius:20rpx;border-bottom-right-radius:20rpx}.round-r-11{border-top-right-radius:22rpx;border-bottom-right-radius:22rpx}.round-r-12{border-top-right-radius:24rpx;border-bottom-right-radius:24rpx}.round-r-13{border-top-right-radius:26rpx;border-bottom-right-radius:26rpx}.round-r-14{border-top-right-radius:28rpx;border-bottom-right-radius:28rpx}.round-r-15{border-top-right-radius:30rpx;border-bottom-right-radius:30rpx}.round-r-16{border-top-right-radius:32rpx;border-bottom-right-radius:32rpx}.round-r-17{border-top-right-radius:34rpx;border-bottom-right-radius:34rpx}.round-r-18{border-top-right-radius:36rpx;border-bottom-right-radius:36rpx}.round-r-19{border-top-right-radius:38rpx;border-bottom-right-radius:38rpx}.round-r-20{border-top-right-radius:40rpx;border-bottom-right-radius:40rpx}.round-r-21{border-top-right-radius:42rpx;border-bottom-right-radius:42rpx}.round-r-22{border-top-right-radius:44rpx;border-bottom-right-radius:44rpx}.round-r-23{border-top-right-radius:46rpx;border-bottom-right-radius:46rpx}.round-r-24{border-top-right-radius:48rpx;border-bottom-right-radius:48rpx}.round-r-25{border-top-right-radius:50rpx;border-bottom-right-radius:50rpx}.round-0{border-radius:0rpx}.round-1{border-radius:2rpx}.round-2{border-radius:4rpx}.round-3{border-radius:6rpx}.round-4{border-radius:8rpx}.round-5{border-radius:10rpx}.round-6{border-radius:12rpx}.round-7{border-radius:14rpx}.round-8{border-radius:16rpx}.round-9{border-radius:18rpx}.round-10{border-radius:20rpx}.round-11{border-radius:22rpx}.round-12{border-radius:24rpx}.round-13{border-radius:26rpx}.round-14{border-radius:28rpx}.round-15{border-radius:30rpx}.round-16{border-radius:32rpx}.round-17{border-radius:34rpx}.round-18{border-radius:36rpx}.round-19{border-radius:38rpx}.round-20{border-radius:40rpx}.round-21{border-radius:42rpx}.round-22{border-radius:44rpx}.round-23{border-radius:46rpx}.round-24{border-radius:48rpx}.round-25{border-radius:50rpx}.round-26{border-radius:52rpx}.line-0{line-height:1}.line-1{line-height:1.1}.line-2{line-height:1.2}.line-3{line-height:1.3}.line-4{line-height:1.4}.line-5{line-height:1.5}.line-6{line-height:1.6}.line-7{line-height:1.7}.line-8{line-height:1.8}.line-9{line-height:1.9}.line-10{line-height:2}.line-11{line-height:2.1}.line-12{line-height:2.2}.line-13{line-height:2.3}.line-14{line-height:2.4}.line-15{line-height:2.5}.line-16{line-height:2.6}.line-17{line-height:2.7}.line-18{line-height:2.8}.line-19{line-height:2.9}.line-20{line-height:3}.line-21{line-height:3.1}.opacity-0{opacity:0}.opacity-1{opacity:.1}.opacity-2{opacity:.2}.opacity-3{opacity:.3}.opacity-4{opacity:.4}.opacity-5{opacity:.5}.opacity-6{opacity:.6}.opacity-7{opacity:.7}.opacity-8{opacity:.8}.opacity-9{opacity:.9}.opacity-10{opacity:1}.border-0{border:0rpx solid #f5f5f5}.border{border:2rpx solid #f5f5f5}.border-1{border:2rpx solid #f5f5f5}.border-1-bk{border:2rpx solid #f5f5f5}.border-2{border:4rpx solid #f5f5f5}.border-2-bk{border:4rpx solid #f5f5f5}.border-3{border:6rpx solid #f5f5f5}.border-3-bk{border:6rpx solid #f5f5f5}.border-4{border:8rpx solid #f5f5f5}.border-4-bk{border:8rpx solid #f5f5f5}.border-5{border:10rpx solid #f5f5f5}.border-5-bk{border:10rpx solid #f5f5f5}.border-l-1{border-left:2rpx solid #f5f5f5}.border-l-2{border-left:4rpx solid #f5f5f5}.border-l-3{border-left:6rpx solid #f5f5f5}.border-l-4{border-left:8rpx solid #f5f5f5}.border-l-5{border-left:10rpx solid #f5f5f5}.border-r-1{border-right:2rpx solid #f5f5f5}.border-r-2{border-right:4rpx solid #f5f5f5}.border-r-3{border-right:6rpx solid #f5f5f5}.border-r-4{border-right:8rpx solid #f5f5f5}.border-r-5{border-right:10rpx solid #f5f5f5}.border-t-1{border-top:2rpx solid #f5f5f5}.border-t-2{border-top:4rpx solid #f5f5f5}.border-t-3{border-top:6rpx solid #f5f5f5}.border-t-4{border-top:8rpx solid #f5f5f5}.border-t-5{border-top:10rpx solid #f5f5f5}.border-b-1{border-bottom:2rpx solid #f5f5f5}.border-b-2{border-bottom:4rpx solid #f5f5f5}.border-b-3{border-bottom:6rpx solid #f5f5f5}.border-b-4{border-bottom:8rpx solid #f5f5f5}.border-b-5{border-bottom:10rpx solid #f5f5f5}.border-a-1{border:2rpx solid #f5f5f5}.border-a-2{border:4rpx solid #f5f5f5}.border-a-3{border:6rpx solid #f5f5f5}.border-a-4{border:8rpx solid #f5f5f5}.border-a-5{border:10rpx solid #f5f5f5}.pa-0{padding:0rpx}.pa-1{padding:1rpx}.pa-2{padding:2rpx}.pa-3{padding:3rpx}.pa-4{padding:4rpx}.pa-5{padding:5rpx}.pa-6{padding:6rpx}.pa-7{padding:7rpx}.pa-8{padding:8rpx}.pa-9{padding:9rpx}.pa-10{padding:10rpx}.pa-11{padding:11rpx}.pa-12{padding:12rpx}.pa-13{padding:13rpx}.pa-14{padding:14rpx}.pa-15{padding:15rpx}.pa-16{padding:16rpx}.pa-17{padding:17rpx}.pa-18{padding:18rpx}.pa-19{padding:19rpx}.pa-20{padding:20rpx}.pa-21{padding:21rpx}.pa-22{padding:22rpx}.pa-23{padding:23rpx}.pa-24{padding:24rpx}.pa-25{padding:25rpx}.pa-26{padding:26rpx}.pa-27{padding:27rpx}.pa-28{padding:28rpx}.pa-29{padding:29rpx}.pa-30{padding:30rpx}.pa-31{padding:31rpx}.pa-32{padding:32rpx}.pa-33{padding:33rpx}.pa-34{padding:34rpx}.pa-35{padding:35rpx}.pa-36{padding:36rpx}.pa-37{padding:37rpx}.pa-38{padding:38rpx}.pa-39{padding:39rpx}.pa-40{padding:40rpx}.pa-41{padding:41rpx}.pa-42{padding:42rpx}.pa-43{padding:43rpx}.pa-44{padding:44rpx}.pa-45{padding:45rpx}.pa-46{padding:46rpx}.pa-47{padding:47rpx}.pa-48{padding:48rpx}.pa-49{padding:49rpx}.pa-50{padding:50rpx}.pa-n1{padding:4rpx}.pa-n2{padding:8rpx}.pa-n3{padding:12rpx}.pa-n4{padding:16rpx}.pa-n5{padding:20rpx}.pa-n6{padding:24rpx}.pa-n7{padding:28rpx}.pa-n8{padding:32rpx}.pa-n9{padding:36rpx}.pa-n10{padding:40rpx}.pa-n11{padding:44rpx}.pa-n12{padding:48rpx}.pa-n13{padding:52rpx}.pa-n14{padding:56rpx}.pa-n15{padding:60rpx}.pa-n16{padding:64rpx}.pa-n17{padding:68rpx}.pa-n18{padding:72rpx}.pa-n19{padding:76rpx}.pa-n20{padding:80rpx}.pa-n21{padding:84rpx}.pa-n22{padding:88rpx}.pa-n23{padding:92rpx}.pa-n24{padding:96rpx}.pa-n25{padding:100rpx}.pt-0{padding-top:0rpx}.pt-1{padding-top:1rpx}.pt-2{padding-top:2rpx}.pt-3{padding-top:3rpx}.pt-4{padding-top:4rpx}.pt-5{padding-top:5rpx}.pt-6{padding-top:6rpx}.pt-7{padding-top:7rpx}.pt-8{padding-top:8rpx}.pt-9{padding-top:9rpx}.pt-10{padding-top:10rpx}.pt-11{padding-top:11rpx}.pt-12{padding-top:12rpx}.pt-13{padding-top:13rpx}.pt-14{padding-top:14rpx}.pt-15{padding-top:15rpx}.pt-16{padding-top:16rpx}.pt-17{padding-top:17rpx}.pt-18{padding-top:18rpx}.pt-19{padding-top:19rpx}.pt-20{padding-top:20rpx}.pt-21{padding-top:21rpx}.pt-22{padding-top:22rpx}.pt-23{padding-top:23rpx}.pt-24{padding-top:24rpx}.pt-25{padding-top:25rpx}.pt-26{padding-top:26rpx}.pt-27{padding-top:27rpx}.pt-28{padding-top:28rpx}.pt-29{padding-top:29rpx}.pt-30{padding-top:30rpx}.pt-31{padding-top:31rpx}.pt-32{padding-top:32rpx}.pt-33{padding-top:33rpx}.pt-34{padding-top:34rpx}.pt-35{padding-top:35rpx}.pt-36{padding-top:36rpx}.pt-37{padding-top:37rpx}.pt-38{padding-top:38rpx}.pt-39{padding-top:39rpx}.pt-40{padding-top:40rpx}.pt-41{padding-top:41rpx}.pt-42{padding-top:42rpx}.pt-43{padding-top:43rpx}.pt-44{padding-top:44rpx}.pt-45{padding-top:45rpx}.pt-46{padding-top:46rpx}.pt-47{padding-top:47rpx}.pt-48{padding-top:48rpx}.pt-49{padding-top:49rpx}.pt-50{padding-top:50rpx}.pt-n1{padding-top:4rpx}.pt-n2{padding-top:8rpx}.pt-n3{padding-top:12rpx}.pt-n4{padding-top:16rpx}.pt-n5{padding-top:20rpx}.pt-n6{padding-top:24rpx}.pt-n7{padding-top:28rpx}.pt-n8{padding-top:32rpx}.pt-n9{padding-top:36rpx}.pt-n10{padding-top:40rpx}.pt-n11{padding-top:44rpx}.pt-n12{padding-top:48rpx}.pt-n13{padding-top:52rpx}.pt-n14{padding-top:56rpx}.pt-n15{padding-top:60rpx}.pt-n16{padding-top:64rpx}.pt-n17{padding-top:68rpx}.pt-n18{padding-top:72rpx}.pt-n19{padding-top:76rpx}.pt-n20{padding-top:80rpx}.pt-n21{padding-top:84rpx}.pt-n22{padding-top:88rpx}.pt-n23{padding-top:92rpx}.pt-n24{padding-top:96rpx}.pt-n25{padding-top:100rpx}.pr-0{padding-right:0rpx}.pr-1{padding-right:1rpx}.pr-2{padding-right:2rpx}.pr-3{padding-right:3rpx}.pr-4{padding-right:4rpx}.pr-5{padding-right:5rpx}.pr-6{padding-right:6rpx}.pr-7{padding-right:7rpx}.pr-8{padding-right:8rpx}.pr-9{padding-right:9rpx}.pr-10{padding-right:10rpx}.pr-11{padding-right:11rpx}.pr-12{padding-right:12rpx}.pr-13{padding-right:13rpx}.pr-14{padding-right:14rpx}.pr-15{padding-right:15rpx}.pr-16{padding-right:16rpx}.pr-17{padding-right:17rpx}.pr-18{padding-right:18rpx}.pr-19{padding-right:19rpx}.pr-20{padding-right:20rpx}.pr-21{padding-right:21rpx}.pr-22{padding-right:22rpx}.pr-23{padding-right:23rpx}.pr-24{padding-right:24rpx}.pr-25{padding-right:25rpx}.pr-26{padding-right:26rpx}.pr-27{padding-right:27rpx}.pr-28{padding-right:28rpx}.pr-29{padding-right:29rpx}.pr-30{padding-right:30rpx}.pr-31{padding-right:31rpx}.pr-32{padding-right:32rpx}.pr-33{padding-right:33rpx}.pr-34{padding-right:34rpx}.pr-35{padding-right:35rpx}.pr-36{padding-right:36rpx}.pr-37{padding-right:37rpx}.pr-38{padding-right:38rpx}.pr-39{padding-right:39rpx}.pr-40{padding-right:40rpx}.pr-41{padding-right:41rpx}.pr-42{padding-right:42rpx}.pr-43{padding-right:43rpx}.pr-44{padding-right:44rpx}.pr-45{padding-right:45rpx}.pr-46{padding-right:46rpx}.pr-47{padding-right:47rpx}.pr-48{padding-right:48rpx}.pr-49{padding-right:49rpx}.pr-50{padding-right:50rpx}.pr-n1{padding-right:4rpx}.pr-n2{padding-right:8rpx}.pr-n3{padding-right:12rpx}.pr-n4{padding-right:16rpx}.pr-n5{padding-right:20rpx}.pr-n6{padding-right:24rpx}.pr-n7{padding-right:28rpx}.pr-n8{padding-right:32rpx}.pr-n9{padding-right:36rpx}.pr-n10{padding-right:40rpx}.pr-n11{padding-right:44rpx}.pr-n12{padding-right:48rpx}.pr-n13{padding-right:52rpx}.pr-n14{padding-right:56rpx}.pr-n15{padding-right:60rpx}.pr-n16{padding-right:64rpx}.pr-n17{padding-right:68rpx}.pr-n18{padding-right:72rpx}.pr-n19{padding-right:76rpx}.pr-n20{padding-right:80rpx}.pr-n21{padding-right:84rpx}.pr-n22{padding-right:88rpx}.pr-n23{padding-right:92rpx}.pr-n24{padding-right:96rpx}.pr-n25{padding-right:100rpx}.pb-0{padding-bottom:0rpx}.pb-1{padding-bottom:1rpx}.pb-2{padding-bottom:2rpx}.pb-3{padding-bottom:3rpx}.pb-4{padding-bottom:4rpx}.pb-5{padding-bottom:5rpx}.pb-6{padding-bottom:6rpx}.pb-7{padding-bottom:7rpx}.pb-8{padding-bottom:8rpx}.pb-9{padding-bottom:9rpx}.pb-10{padding-bottom:10rpx}.pb-11{padding-bottom:11rpx}.pb-12{padding-bottom:12rpx}.pb-13{padding-bottom:13rpx}.pb-14{padding-bottom:14rpx}.pb-15{padding-bottom:15rpx}.pb-16{padding-bottom:16rpx}.pb-17{padding-bottom:17rpx}.pb-18{padding-bottom:18rpx}.pb-19{padding-bottom:19rpx}.pb-20{padding-bottom:20rpx}.pb-21{padding-bottom:21rpx}.pb-22{padding-bottom:22rpx}.pb-23{padding-bottom:23rpx}.pb-24{padding-bottom:24rpx}.pb-25{padding-bottom:25rpx}.pb-26{padding-bottom:26rpx}.pb-27{padding-bottom:27rpx}.pb-28{padding-bottom:28rpx}.pb-29{padding-bottom:29rpx}.pb-30{padding-bottom:30rpx}.pb-31{padding-bottom:31rpx}.pb-32{padding-bottom:32rpx}.pb-33{padding-bottom:33rpx}.pb-34{padding-bottom:34rpx}.pb-35{padding-bottom:35rpx}.pb-36{padding-bottom:36rpx}.pb-37{padding-bottom:37rpx}.pb-38{padding-bottom:38rpx}.pb-39{padding-bottom:39rpx}.pb-40{padding-bottom:40rpx}.pb-41{padding-bottom:41rpx}.pb-42{padding-bottom:42rpx}.pb-43{padding-bottom:43rpx}.pb-44{padding-bottom:44rpx}.pb-45{padding-bottom:45rpx}.pb-46{padding-bottom:46rpx}.pb-47{padding-bottom:47rpx}.pb-48{padding-bottom:48rpx}.pb-49{padding-bottom:49rpx}.pb-50{padding-bottom:50rpx}.pb-n1{padding-bottom:4rpx}.pb-n2{padding-bottom:8rpx}.pb-n3{padding-bottom:12rpx}.pb-n4{padding-bottom:16rpx}.pb-n5{padding-bottom:20rpx}.pb-n6{padding-bottom:24rpx}.pb-n7{padding-bottom:28rpx}.pb-n8{padding-bottom:32rpx}.pb-n9{padding-bottom:36rpx}.pb-n10{padding-bottom:40rpx}.pb-n11{padding-bottom:44rpx}.pb-n12{padding-bottom:48rpx}.pb-n13{padding-bottom:52rpx}.pb-n14{padding-bottom:56rpx}.pb-n15{padding-bottom:60rpx}.pb-n16{padding-bottom:64rpx}.pb-n17{padding-bottom:68rpx}.pb-n18{padding-bottom:72rpx}.pb-n19{padding-bottom:76rpx}.pb-n20{padding-bottom:80rpx}.pb-n21{padding-bottom:84rpx}.pb-n22{padding-bottom:88rpx}.pb-n23{padding-bottom:92rpx}.pb-n24{padding-bottom:96rpx}.pb-n25{padding-bottom:100rpx}.pl-0{padding-left:0rpx}.pl-1{padding-left:1rpx}.pl-2{padding-left:2rpx}.pl-3{padding-left:3rpx}.pl-4{padding-left:4rpx}.pl-5{padding-left:5rpx}.pl-6{padding-left:6rpx}.pl-7{padding-left:7rpx}.pl-8{padding-left:8rpx}.pl-9{padding-left:9rpx}.pl-10{padding-left:10rpx}.pl-11{padding-left:11rpx}.pl-12{padding-left:12rpx}.pl-13{padding-left:13rpx}.pl-14{padding-left:14rpx}.pl-15{padding-left:15rpx}.pl-16{padding-left:16rpx}.pl-17{padding-left:17rpx}.pl-18{padding-left:18rpx}.pl-19{padding-left:19rpx}.pl-20{padding-left:20rpx}.pl-21{padding-left:21rpx}.pl-22{padding-left:22rpx}.pl-23{padding-left:23rpx}.pl-24{padding-left:24rpx}.pl-25{padding-left:25rpx}.pl-26{padding-left:26rpx}.pl-27{padding-left:27rpx}.pl-28{padding-left:28rpx}.pl-29{padding-left:29rpx}.pl-30{padding-left:30rpx}.pl-31{padding-left:31rpx}.pl-32{padding-left:32rpx}.pl-33{padding-left:33rpx}.pl-34{padding-left:34rpx}.pl-35{padding-left:35rpx}.pl-36{padding-left:36rpx}.pl-37{padding-left:37rpx}.pl-38{padding-left:38rpx}.pl-39{padding-left:39rpx}.pl-40{padding-left:40rpx}.pl-41{padding-left:41rpx}.pl-42{padding-left:42rpx}.pl-43{padding-left:43rpx}.pl-44{padding-left:44rpx}.pl-45{padding-left:45rpx}.pl-46{padding-left:46rpx}.pl-47{padding-left:47rpx}.pl-48{padding-left:48rpx}.pl-49{padding-left:49rpx}.pl-50{padding-left:50rpx}.pl-n1{padding-left:4rpx}.pl-n2{padding-left:8rpx}.pl-n3{padding-left:12rpx}.pl-n4{padding-left:16rpx}.pl-n5{padding-left:20rpx}.pl-n6{padding-left:24rpx}.pl-n7{padding-left:28rpx}.pl-n8{padding-left:32rpx}.pl-n9{padding-left:36rpx}.pl-n10{padding-left:40rpx}.pl-n11{padding-left:44rpx}.pl-n12{padding-left:48rpx}.pl-n13{padding-left:52rpx}.pl-n14{padding-left:56rpx}.pl-n15{padding-left:60rpx}.pl-n16{padding-left:64rpx}.pl-n17{padding-left:68rpx}.pl-n18{padding-left:72rpx}.pl-n19{padding-left:76rpx}.pl-n20{padding-left:80rpx}.pl-n21{padding-left:84rpx}.pl-n22{padding-left:88rpx}.pl-n23{padding-left:92rpx}.pl-n24{padding-left:96rpx}.pl-n25{padding-left:100rpx}.px-0{padding-left:0rpx;padding-right:0rpx}.px-1{padding-left:1rpx;padding-right:1rpx}.px-2{padding-left:2rpx;padding-right:2rpx}.px-3{padding-left:3rpx;padding-right:3rpx}.px-4{padding-left:4rpx;padding-right:4rpx}.px-5{padding-left:5rpx;padding-right:5rpx}.px-6{padding-left:6rpx;padding-right:6rpx}.px-7{padding-left:7rpx;padding-right:7rpx}.px-8{padding-left:8rpx;padding-right:8rpx}.px-9{padding-left:9rpx;padding-right:9rpx}.px-10{padding-left:10rpx;padding-right:10rpx}.px-11{padding-left:11rpx;padding-right:11rpx}.px-12{padding-left:12rpx;padding-right:12rpx}.px-13{padding-left:13rpx;padding-right:13rpx}.px-14{padding-left:14rpx;padding-right:14rpx}.px-15{padding-left:15rpx;padding-right:15rpx}.px-16{padding-left:16rpx;padding-right:16rpx}.px-17{padding-left:17rpx;padding-right:17rpx}.px-18{padding-left:18rpx;padding-right:18rpx}.px-19{padding-left:19rpx;padding-right:19rpx}.px-20{padding-left:20rpx;padding-right:20rpx}.px-21{padding-left:21rpx;padding-right:21rpx}.px-22{padding-left:22rpx;padding-right:22rpx}.px-23{padding-left:23rpx;padding-right:23rpx}.px-24{padding-left:24rpx;padding-right:24rpx}.px-25{padding-left:25rpx;padding-right:25rpx}.px-26{padding-left:26rpx;padding-right:26rpx}.px-27{padding-left:27rpx;padding-right:27rpx}.px-28{padding-left:28rpx;padding-right:28rpx}.px-29{padding-left:29rpx;padding-right:29rpx}.px-30{padding-left:30rpx;padding-right:30rpx}.px-31{padding-left:31rpx;padding-right:31rpx}.px-32{padding-left:32rpx;padding-right:32rpx}.px-33{padding-left:33rpx;padding-right:33rpx}.px-34{padding-left:34rpx;padding-right:34rpx}.px-35{padding-left:35rpx;padding-right:35rpx}.px-36{padding-left:36rpx;padding-right:36rpx}.px-37{padding-left:37rpx;padding-right:37rpx}.px-38{padding-left:38rpx;padding-right:38rpx}.px-39{padding-left:39rpx;padding-right:39rpx}.px-40{padding-left:40rpx;padding-right:40rpx}.px-41{padding-left:41rpx;padding-right:41rpx}.px-42{padding-left:42rpx;padding-right:42rpx}.px-43{padding-left:43rpx;padding-right:43rpx}.px-44{padding-left:44rpx;padding-right:44rpx}.px-45{padding-left:45rpx;padding-right:45rpx}.px-46{padding-left:46rpx;padding-right:46rpx}.px-47{padding-left:47rpx;padding-right:47rpx}.px-48{padding-left:48rpx;padding-right:48rpx}.px-49{padding-left:49rpx;padding-right:49rpx}.px-50{padding-left:50rpx;padding-right:50rpx}.px-n1{padding-left:4rpx;padding-right:4rpx}.px-n2{padding-left:8rpx;padding-right:8rpx}.px-n3{padding-left:12rpx;padding-right:12rpx}.px-n4{padding-left:16rpx;padding-right:16rpx}.px-n5{padding-left:20rpx;padding-right:20rpx}.px-n6{padding-left:24rpx;padding-right:24rpx}.px-n7{padding-left:28rpx;padding-right:28rpx}.px-n8{padding-left:32rpx;padding-right:32rpx}.px-n9{padding-left:36rpx;padding-right:36rpx}.px-n10{padding-left:40rpx;padding-right:40rpx}.px-n11{padding-left:44rpx;padding-right:44rpx}.px-n12{padding-left:48rpx;padding-right:48rpx}.px-n13{padding-left:52rpx;padding-right:52rpx}.px-n14{padding-left:56rpx;padding-right:56rpx}.px-n15{padding-left:60rpx;padding-right:60rpx}.px-n16{padding-left:64rpx;padding-right:64rpx}.px-n17{padding-left:68rpx;padding-right:68rpx}.px-n18{padding-left:72rpx;padding-right:72rpx}.px-n19{padding-left:76rpx;padding-right:76rpx}.px-n20{padding-left:80rpx;padding-right:80rpx}.px-n21{padding-left:84rpx;padding-right:84rpx}.px-n22{padding-left:88rpx;padding-right:88rpx}.px-n23{padding-left:92rpx;padding-right:92rpx}.px-n24{padding-left:96rpx;padding-right:96rpx}.px-n25{padding-left:100rpx;padding-right:100rpx}.py-0{padding-top:0rpx;padding-bottom:0rpx}.py-1{padding-top:1rpx;padding-bottom:1rpx}.py-2{padding-top:2rpx;padding-bottom:2rpx}.py-3{padding-top:3rpx;padding-bottom:3rpx}.py-4{padding-top:4rpx;padding-bottom:4rpx}.py-5{padding-top:5rpx;padding-bottom:5rpx}.py-6{padding-top:6rpx;padding-bottom:6rpx}.py-7{padding-top:7rpx;padding-bottom:7rpx}.py-8{padding-top:8rpx;padding-bottom:8rpx}.py-9{padding-top:9rpx;padding-bottom:9rpx}.py-10{padding-top:10rpx;padding-bottom:10rpx}.py-11{padding-top:11rpx;padding-bottom:11rpx}.py-12{padding-top:12rpx;padding-bottom:12rpx}.py-13{padding-top:13rpx;padding-bottom:13rpx}.py-14{padding-top:14rpx;padding-bottom:14rpx}.py-15{padding-top:15rpx;padding-bottom:15rpx}.py-16{padding-top:16rpx;padding-bottom:16rpx}.py-17{padding-top:17rpx;padding-bottom:17rpx}.py-18{padding-top:18rpx;padding-bottom:18rpx}.py-19{padding-top:19rpx;padding-bottom:19rpx}.py-20{padding-top:20rpx;padding-bottom:20rpx}.py-21{padding-top:21rpx;padding-bottom:21rpx}.py-22{padding-top:22rpx;padding-bottom:22rpx}.py-23{padding-top:23rpx;padding-bottom:23rpx}.py-24{padding-top:24rpx;padding-bottom:24rpx}.py-25{padding-top:25rpx;padding-bottom:25rpx}.py-26{padding-top:26rpx;padding-bottom:26rpx}.py-27{padding-top:27rpx;padding-bottom:27rpx}.py-28{padding-top:28rpx;padding-bottom:28rpx}.py-29{padding-top:29rpx;padding-bottom:29rpx}.py-30{padding-top:30rpx;padding-bottom:30rpx}.py-31{padding-top:31rpx;padding-bottom:31rpx}.py-32{padding-top:32rpx;padding-bottom:32rpx}.py-33{padding-top:33rpx;padding-bottom:33rpx}.py-34{padding-top:34rpx;padding-bottom:34rpx}.py-35{padding-top:35rpx;padding-bottom:35rpx}.py-36{padding-top:36rpx;padding-bottom:36rpx}.py-37{padding-top:37rpx;padding-bottom:37rpx}.py-38{padding-top:38rpx;padding-bottom:38rpx}.py-39{padding-top:39rpx;padding-bottom:39rpx}.py-40{padding-top:40rpx;padding-bottom:40rpx}.py-41{padding-top:41rpx;padding-bottom:41rpx}.py-42{padding-top:42rpx;padding-bottom:42rpx}.py-43{padding-top:43rpx;padding-bottom:43rpx}.py-44{padding-top:44rpx;padding-bottom:44rpx}.py-45{padding-top:45rpx;padding-bottom:45rpx}.py-46{padding-top:46rpx;padding-bottom:46rpx}.py-47{padding-top:47rpx;padding-bottom:47rpx}.py-48{padding-top:48rpx;padding-bottom:48rpx}.py-49{padding-top:49rpx;padding-bottom:49rpx}.py-50{padding-top:50rpx;padding-bottom:50rpx}.py-n1{padding-top:4rpx;padding-bottom:4rpx}.py-n2{padding-top:8rpx;padding-bottom:8rpx}.py-n3{padding-top:12rpx;padding-bottom:12rpx}.py-n4{padding-top:16rpx;padding-bottom:16rpx}.py-n5{padding-top:20rpx;padding-bottom:20rpx}.py-n6{padding-top:24rpx;padding-bottom:24rpx}.py-n7{padding-top:28rpx;padding-bottom:28rpx}.py-n8{padding-top:32rpx;padding-bottom:32rpx}.py-n9{padding-top:36rpx;padding-bottom:36rpx}.py-n10{padding-top:40rpx;padding-bottom:40rpx}.py-n11{padding-top:44rpx;padding-bottom:44rpx}.py-n12{padding-top:48rpx;padding-bottom:48rpx}.py-n13{padding-top:52rpx;padding-bottom:52rpx}.py-n14{padding-top:56rpx;padding-bottom:56rpx}.py-n15{padding-top:60rpx;padding-bottom:60rpx}.py-n16{padding-top:64rpx;padding-bottom:64rpx}.py-n17{padding-top:68rpx;padding-bottom:68rpx}.py-n18{padding-top:72rpx;padding-bottom:72rpx}.py-n19{padding-top:76rpx;padding-bottom:76rpx}.py-n20{padding-top:80rpx;padding-bottom:80rpx}.py-n21{padding-top:84rpx;padding-bottom:84rpx}.py-n22{padding-top:88rpx;padding-bottom:88rpx}.py-n23{padding-top:92rpx;padding-bottom:92rpx}.py-n24{padding-top:96rpx;padding-bottom:96rpx}.py-n25{padding-top:100rpx;padding-bottom:100rpx}.ma-0{margin:0rpx}.ma-1{margin:1rpx}.ma-2{margin:2rpx}.ma-3{margin:3rpx}.ma-4{margin:4rpx}.ma-5{margin:5rpx}.ma-6{margin:6rpx}.ma-7{margin:7rpx}.ma-8{margin:8rpx}.ma-9{margin:9rpx}.ma-10{margin:10rpx}.ma-11{margin:11rpx}.ma-12{margin:12rpx}.ma-13{margin:13rpx}.ma-14{margin:14rpx}.ma-15{margin:15rpx}.ma-16{margin:16rpx}.ma-17{margin:17rpx}.ma-18{margin:18rpx}.ma-19{margin:19rpx}.ma-20{margin:20rpx}.ma-21{margin:21rpx}.ma-22{margin:22rpx}.ma-23{margin:23rpx}.ma-24{margin:24rpx}.ma-25{margin:25rpx}.ma-26{margin:26rpx}.ma-27{margin:27rpx}.ma-28{margin:28rpx}.ma-29{margin:29rpx}.ma-30{margin:30rpx}.ma-31{margin:31rpx}.ma-32{margin:32rpx}.ma-33{margin:33rpx}.ma-34{margin:34rpx}.ma-35{margin:35rpx}.ma-36{margin:36rpx}.ma-37{margin:37rpx}.ma-38{margin:38rpx}.ma-39{margin:39rpx}.ma-40{margin:40rpx}.ma-41{margin:41rpx}.ma-42{margin:42rpx}.ma-43{margin:43rpx}.ma-44{margin:44rpx}.ma-45{margin:45rpx}.ma-46{margin:46rpx}.ma-47{margin:47rpx}.ma-48{margin:48rpx}.ma-49{margin:49rpx}.ma-50{margin:50rpx}.ma-n1{margin:4rpx}.ma-n2{margin:8rpx}.ma-n3{margin:12rpx}.ma-n4{margin:16rpx}.ma-n5{margin:20rpx}.ma-n6{margin:24rpx}.ma-n7{margin:28rpx}.ma-n8{margin:32rpx}.ma-n9{margin:36rpx}.ma-n10{margin:40rpx}.ma-n11{margin:44rpx}.ma-n12{margin:48rpx}.ma-n13{margin:52rpx}.ma-n14{margin:56rpx}.ma-n15{margin:60rpx}.ma-n16{margin:64rpx}.ma-n17{margin:68rpx}.ma-n18{margin:72rpx}.ma-n19{margin:76rpx}.ma-n20{margin:80rpx}.ma-n21{margin:84rpx}.ma-n22{margin:88rpx}.ma-n23{margin:92rpx}.ma-n24{margin:96rpx}.ma-n25{margin:100rpx}.mt-0{margin-top:0rpx}.mt--0{margin-top:0rpx}.mt-1{margin-top:1rpx}.mt--1{margin-top:-1rpx}.mt-2{margin-top:2rpx}.mt--2{margin-top:-2rpx}.mt-3{margin-top:3rpx}.mt--3{margin-top:-3rpx}.mt-4{margin-top:4rpx}.mt--4{margin-top:-4rpx}.mt-5{margin-top:5rpx}.mt--5{margin-top:-5rpx}.mt-6{margin-top:6rpx}.mt--6{margin-top:-6rpx}.mt-7{margin-top:7rpx}.mt--7{margin-top:-7rpx}.mt-8{margin-top:8rpx}.mt--8{margin-top:-8rpx}.mt-9{margin-top:9rpx}.mt--9{margin-top:-9rpx}.mt-10{margin-top:10rpx}.mt--10{margin-top:-10rpx}.mt-11{margin-top:11rpx}.mt--11{margin-top:-11rpx}.mt-12{margin-top:12rpx}.mt--12{margin-top:-12rpx}.mt-13{margin-top:13rpx}.mt--13{margin-top:-13rpx}.mt-14{margin-top:14rpx}.mt--14{margin-top:-14rpx}.mt-15{margin-top:15rpx}.mt--15{margin-top:-15rpx}.mt-16{margin-top:16rpx}.mt--16{margin-top:-16rpx}.mt-17{margin-top:17rpx}.mt--17{margin-top:-17rpx}.mt-18{margin-top:18rpx}.mt--18{margin-top:-18rpx}.mt-19{margin-top:19rpx}.mt--19{margin-top:-19rpx}.mt-20{margin-top:20rpx}.mt--20{margin-top:-20rpx}.mt-21{margin-top:21rpx}.mt--21{margin-top:-21rpx}.mt-22{margin-top:22rpx}.mt--22{margin-top:-22rpx}.mt-23{margin-top:23rpx}.mt--23{margin-top:-23rpx}.mt-24{margin-top:24rpx}.mt--24{margin-top:-24rpx}.mt-25{margin-top:25rpx}.mt--25{margin-top:-25rpx}.mt-26{margin-top:26rpx}.mt--26{margin-top:-26rpx}.mt-27{margin-top:27rpx}.mt--27{margin-top:-27rpx}.mt-28{margin-top:28rpx}.mt--28{margin-top:-28rpx}.mt-29{margin-top:29rpx}.mt--29{margin-top:-29rpx}.mt-30{margin-top:30rpx}.mt--30{margin-top:-30rpx}.mt-31{margin-top:31rpx}.mt--31{margin-top:-31rpx}.mt-32{margin-top:32rpx}.mt--32{margin-top:-32rpx}.mt-33{margin-top:33rpx}.mt--33{margin-top:-33rpx}.mt-34{margin-top:34rpx}.mt--34{margin-top:-34rpx}.mt-35{margin-top:35rpx}.mt--35{margin-top:-35rpx}.mt-36{margin-top:36rpx}.mt--36{margin-top:-36rpx}.mt-37{margin-top:37rpx}.mt--37{margin-top:-37rpx}.mt-38{margin-top:38rpx}.mt--38{margin-top:-38rpx}.mt-39{margin-top:39rpx}.mt--39{margin-top:-39rpx}.mt-40{margin-top:40rpx}.mt--40{margin-top:-40rpx}.mt-41{margin-top:41rpx}.mt--41{margin-top:-41rpx}.mt-42{margin-top:42rpx}.mt--42{margin-top:-42rpx}.mt-43{margin-top:43rpx}.mt--43{margin-top:-43rpx}.mt-44{margin-top:44rpx}.mt--44{margin-top:-44rpx}.mt-45{margin-top:45rpx}.mt--45{margin-top:-45rpx}.mt-46{margin-top:46rpx}.mt--46{margin-top:-46rpx}.mt-47{margin-top:47rpx}.mt--47{margin-top:-47rpx}.mt-48{margin-top:48rpx}.mt--48{margin-top:-48rpx}.mt-49{margin-top:49rpx}.mt--49{margin-top:-49rpx}.mt-50{margin-top:50rpx}.mt--50{margin-top:-50rpx}.mt-n1{margin-top:4rpx}.mt--n1{margin-top:-4rpx}.mt-n2{margin-top:8rpx}.mt--n2{margin-top:-8rpx}.mt-n3{margin-top:12rpx}.mt--n3{margin-top:-12rpx}.mt-n4{margin-top:16rpx}.mt--n4{margin-top:-16rpx}.mt-n5{margin-top:20rpx}.mt--n5{margin-top:-20rpx}.mt-n6{margin-top:24rpx}.mt--n6{margin-top:-24rpx}.mt-n7{margin-top:28rpx}.mt--n7{margin-top:-28rpx}.mt-n8{margin-top:32rpx}.mt--n8{margin-top:-32rpx}.mt-n9{margin-top:36rpx}.mt--n9{margin-top:-36rpx}.mt-n10{margin-top:40rpx}.mt--n10{margin-top:-40rpx}.mt-n11{margin-top:44rpx}.mt--n11{margin-top:-44rpx}.mt-n12{margin-top:48rpx}.mt--n12{margin-top:-48rpx}.mt-n13{margin-top:52rpx}.mt--n13{margin-top:-52rpx}.mt-n14{margin-top:56rpx}.mt--n14{margin-top:-56rpx}.mt-n15{margin-top:60rpx}.mt--n15{margin-top:-60rpx}.mt-n16{margin-top:64rpx}.mt--n16{margin-top:-64rpx}.mt-n17{margin-top:68rpx}.mt--n17{margin-top:-68rpx}.mt-n18{margin-top:72rpx}.mt--n18{margin-top:-72rpx}.mt-n19{margin-top:76rpx}.mt--n19{margin-top:-76rpx}.mt-n20{margin-top:80rpx}.mt--n20{margin-top:-80rpx}.mt-n21{margin-top:84rpx}.mt--n21{margin-top:-84rpx}.mt-n22{margin-top:88rpx}.mt--n22{margin-top:-88rpx}.mt-n23{margin-top:92rpx}.mt--n23{margin-top:-92rpx}.mt-n24{margin-top:96rpx}.mt--n24{margin-top:-96rpx}.mt-n25{margin-top:100rpx}.mt--n25{margin-top:-100rpx}.mr-0{margin-right:0rpx}.mr--0{margin-right:0rpx}.mr-1{margin-right:1rpx}.mr--1{margin-right:-1rpx}.mr-2{margin-right:2rpx}.mr--2{margin-right:-2rpx}.mr-3{margin-right:3rpx}.mr--3{margin-right:-3rpx}.mr-4{margin-right:4rpx}.mr--4{margin-right:-4rpx}.mr-5{margin-right:5rpx}.mr--5{margin-right:-5rpx}.mr-6{margin-right:6rpx}.mr--6{margin-right:-6rpx}.mr-7{margin-right:7rpx}.mr--7{margin-right:-7rpx}.mr-8{margin-right:8rpx}.mr--8{margin-right:-8rpx}.mr-9{margin-right:9rpx}.mr--9{margin-right:-9rpx}.mr-10{margin-right:10rpx}.mr--10{margin-right:-10rpx}.mr-11{margin-right:11rpx}.mr--11{margin-right:-11rpx}.mr-12{margin-right:12rpx}.mr--12{margin-right:-12rpx}.mr-13{margin-right:13rpx}.mr--13{margin-right:-13rpx}.mr-14{margin-right:14rpx}.mr--14{margin-right:-14rpx}.mr-15{margin-right:15rpx}.mr--15{margin-right:-15rpx}.mr-16{margin-right:16rpx}.mr--16{margin-right:-16rpx}.mr-17{margin-right:17rpx}.mr--17{margin-right:-17rpx}.mr-18{margin-right:18rpx}.mr--18{margin-right:-18rpx}.mr-19{margin-right:19rpx}.mr--19{margin-right:-19rpx}.mr-20{margin-right:20rpx}.mr--20{margin-right:-20rpx}.mr-21{margin-right:21rpx}.mr--21{margin-right:-21rpx}.mr-22{margin-right:22rpx}.mr--22{margin-right:-22rpx}.mr-23{margin-right:23rpx}.mr--23{margin-right:-23rpx}.mr-24{margin-right:24rpx}.mr--24{margin-right:-24rpx}.mr-25{margin-right:25rpx}.mr--25{margin-right:-25rpx}.mr-26{margin-right:26rpx}.mr--26{margin-right:-26rpx}.mr-27{margin-right:27rpx}.mr--27{margin-right:-27rpx}.mr-28{margin-right:28rpx}.mr--28{margin-right:-28rpx}.mr-29{margin-right:29rpx}.mr--29{margin-right:-29rpx}.mr-30{margin-right:30rpx}.mr--30{margin-right:-30rpx}.mr-31{margin-right:31rpx}.mr--31{margin-right:-31rpx}.mr-32{margin-right:32rpx}.mr--32{margin-right:-32rpx}.mr-33{margin-right:33rpx}.mr--33{margin-right:-33rpx}.mr-34{margin-right:34rpx}.mr--34{margin-right:-34rpx}.mr-35{margin-right:35rpx}.mr--35{margin-right:-35rpx}.mr-36{margin-right:36rpx}.mr--36{margin-right:-36rpx}.mr-37{margin-right:37rpx}.mr--37{margin-right:-37rpx}.mr-38{margin-right:38rpx}.mr--38{margin-right:-38rpx}.mr-39{margin-right:39rpx}.mr--39{margin-right:-39rpx}.mr-40{margin-right:40rpx}.mr--40{margin-right:-40rpx}.mr-41{margin-right:41rpx}.mr--41{margin-right:-41rpx}.mr-42{margin-right:42rpx}.mr--42{margin-right:-42rpx}.mr-43{margin-right:43rpx}.mr--43{margin-right:-43rpx}.mr-44{margin-right:44rpx}.mr--44{margin-right:-44rpx}.mr-45{margin-right:45rpx}.mr--45{margin-right:-45rpx}.mr-46{margin-right:46rpx}.mr--46{margin-right:-46rpx}.mr-47{margin-right:47rpx}.mr--47{margin-right:-47rpx}.mr-48{margin-right:48rpx}.mr--48{margin-right:-48rpx}.mr-49{margin-right:49rpx}.mr--49{margin-right:-49rpx}.mr-50{margin-right:50rpx}.mr--50{margin-right:-50rpx}.mr-n1{margin-right:4rpx}.mr--n1{margin-right:-4rpx}.mr-n2{margin-right:8rpx}.mr--n2{margin-right:-8rpx}.mr-n3{margin-right:12rpx}.mr--n3{margin-right:-12rpx}.mr-n4{margin-right:16rpx}.mr--n4{margin-right:-16rpx}.mr-n5{margin-right:20rpx}.mr--n5{margin-right:-20rpx}.mr-n6{margin-right:24rpx}.mr--n6{margin-right:-24rpx}.mr-n7{margin-right:28rpx}.mr--n7{margin-right:-28rpx}.mr-n8{margin-right:32rpx}.mr--n8{margin-right:-32rpx}.mr-n9{margin-right:36rpx}.mr--n9{margin-right:-36rpx}.mr-n10{margin-right:40rpx}.mr--n10{margin-right:-40rpx}.mr-n11{margin-right:44rpx}.mr--n11{margin-right:-44rpx}.mr-n12{margin-right:48rpx}.mr--n12{margin-right:-48rpx}.mr-n13{margin-right:52rpx}.mr--n13{margin-right:-52rpx}.mr-n14{margin-right:56rpx}.mr--n14{margin-right:-56rpx}.mr-n15{margin-right:60rpx}.mr--n15{margin-right:-60rpx}.mr-n16{margin-right:64rpx}.mr--n16{margin-right:-64rpx}.mr-n17{margin-right:68rpx}.mr--n17{margin-right:-68rpx}.mr-n18{margin-right:72rpx}.mr--n18{margin-right:-72rpx}.mr-n19{margin-right:76rpx}.mr--n19{margin-right:-76rpx}.mr-n20{margin-right:80rpx}.mr--n20{margin-right:-80rpx}.mr-n21{margin-right:84rpx}.mr--n21{margin-right:-84rpx}.mr-n22{margin-right:88rpx}.mr--n22{margin-right:-88rpx}.mr-n23{margin-right:92rpx}.mr--n23{margin-right:-92rpx}.mr-n24{margin-right:96rpx}.mr--n24{margin-right:-96rpx}.mr-n25{margin-right:100rpx}.mr--n25{margin-right:-100rpx}.mb-0{margin-bottom:0rpx}.mb--0{margin-bottom:0rpx}.mb-1{margin-bottom:1rpx}.mb--1{margin-bottom:-1rpx}.mb-2{margin-bottom:2rpx}.mb--2{margin-bottom:-2rpx}.mb-3{margin-bottom:3rpx}.mb--3{margin-bottom:-3rpx}.mb-4{margin-bottom:4rpx}.mb--4{margin-bottom:-4rpx}.mb-5{margin-bottom:5rpx}.mb--5{margin-bottom:-5rpx}.mb-6{margin-bottom:6rpx}.mb--6{margin-bottom:-6rpx}.mb-7{margin-bottom:7rpx}.mb--7{margin-bottom:-7rpx}.mb-8{margin-bottom:8rpx}.mb--8{margin-bottom:-8rpx}.mb-9{margin-bottom:9rpx}.mb--9{margin-bottom:-9rpx}.mb-10{margin-bottom:10rpx}.mb--10{margin-bottom:-10rpx}.mb-11{margin-bottom:11rpx}.mb--11{margin-bottom:-11rpx}.mb-12{margin-bottom:12rpx}.mb--12{margin-bottom:-12rpx}.mb-13{margin-bottom:13rpx}.mb--13{margin-bottom:-13rpx}.mb-14{margin-bottom:14rpx}.mb--14{margin-bottom:-14rpx}.mb-15{margin-bottom:15rpx}.mb--15{margin-bottom:-15rpx}.mb-16{margin-bottom:16rpx}.mb--16{margin-bottom:-16rpx}.mb-17{margin-bottom:17rpx}.mb--17{margin-bottom:-17rpx}.mb-18{margin-bottom:18rpx}.mb--18{margin-bottom:-18rpx}.mb-19{margin-bottom:19rpx}.mb--19{margin-bottom:-19rpx}.mb-20{margin-bottom:20rpx}.mb--20{margin-bottom:-20rpx}.mb-21{margin-bottom:21rpx}.mb--21{margin-bottom:-21rpx}.mb-22{margin-bottom:22rpx}.mb--22{margin-bottom:-22rpx}.mb-23{margin-bottom:23rpx}.mb--23{margin-bottom:-23rpx}.mb-24{margin-bottom:24rpx}.mb--24{margin-bottom:-24rpx}.mb-25{margin-bottom:25rpx}.mb--25{margin-bottom:-25rpx}.mb-26{margin-bottom:26rpx}.mb--26{margin-bottom:-26rpx}.mb-27{margin-bottom:27rpx}.mb--27{margin-bottom:-27rpx}.mb-28{margin-bottom:28rpx}.mb--28{margin-bottom:-28rpx}.mb-29{margin-bottom:29rpx}.mb--29{margin-bottom:-29rpx}.mb-30{margin-bottom:30rpx}.mb--30{margin-bottom:-30rpx}.mb-31{margin-bottom:31rpx}.mb--31{margin-bottom:-31rpx}.mb-32{margin-bottom:32rpx}.mb--32{margin-bottom:-32rpx}.mb-33{margin-bottom:33rpx}.mb--33{margin-bottom:-33rpx}.mb-34{margin-bottom:34rpx}.mb--34{margin-bottom:-34rpx}.mb-35{margin-bottom:35rpx}.mb--35{margin-bottom:-35rpx}.mb-36{margin-bottom:36rpx}.mb--36{margin-bottom:-36rpx}.mb-37{margin-bottom:37rpx}.mb--37{margin-bottom:-37rpx}.mb-38{margin-bottom:38rpx}.mb--38{margin-bottom:-38rpx}.mb-39{margin-bottom:39rpx}.mb--39{margin-bottom:-39rpx}.mb-40{margin-bottom:40rpx}.mb--40{margin-bottom:-40rpx}.mb-41{margin-bottom:41rpx}.mb--41{margin-bottom:-41rpx}.mb-42{margin-bottom:42rpx}.mb--42{margin-bottom:-42rpx}.mb-43{margin-bottom:43rpx}.mb--43{margin-bottom:-43rpx}.mb-44{margin-bottom:44rpx}.mb--44{margin-bottom:-44rpx}.mb-45{margin-bottom:45rpx}.mb--45{margin-bottom:-45rpx}.mb-46{margin-bottom:46rpx}.mb--46{margin-bottom:-46rpx}.mb-47{margin-bottom:47rpx}.mb--47{margin-bottom:-47rpx}.mb-48{margin-bottom:48rpx}.mb--48{margin-bottom:-48rpx}.mb-49{margin-bottom:49rpx}.mb--49{margin-bottom:-49rpx}.mb-50{margin-bottom:50rpx}.mb--50{margin-bottom:-50rpx}.mb-n1{margin-bottom:4rpx}.mb--n1{margin-bottom:-4rpx}.mb-n2{margin-bottom:8rpx}.mb--n2{margin-bottom:-8rpx}.mb-n3{margin-bottom:12rpx}.mb--n3{margin-bottom:-12rpx}.mb-n4{margin-bottom:16rpx}.mb--n4{margin-bottom:-16rpx}.mb-n5{margin-bottom:20rpx}.mb--n5{margin-bottom:-20rpx}.mb-n6{margin-bottom:24rpx}.mb--n6{margin-bottom:-24rpx}.mb-n7{margin-bottom:28rpx}.mb--n7{margin-bottom:-28rpx}.mb-n8{margin-bottom:32rpx}.mb--n8{margin-bottom:-32rpx}.mb-n9{margin-bottom:36rpx}.mb--n9{margin-bottom:-36rpx}.mb-n10{margin-bottom:40rpx}.mb--n10{margin-bottom:-40rpx}.mb-n11{margin-bottom:44rpx}.mb--n11{margin-bottom:-44rpx}.mb-n12{margin-bottom:48rpx}.mb--n12{margin-bottom:-48rpx}.mb-n13{margin-bottom:52rpx}.mb--n13{margin-bottom:-52rpx}.mb-n14{margin-bottom:56rpx}.mb--n14{margin-bottom:-56rpx}.mb-n15{margin-bottom:60rpx}.mb--n15{margin-bottom:-60rpx}.mb-n16{margin-bottom:64rpx}.mb--n16{margin-bottom:-64rpx}.mb-n17{margin-bottom:68rpx}.mb--n17{margin-bottom:-68rpx}.mb-n18{margin-bottom:72rpx}.mb--n18{margin-bottom:-72rpx}.mb-n19{margin-bottom:76rpx}.mb--n19{margin-bottom:-76rpx}.mb-n20{margin-bottom:80rpx}.mb--n20{margin-bottom:-80rpx}.mb-n21{margin-bottom:84rpx}.mb--n21{margin-bottom:-84rpx}.mb-n22{margin-bottom:88rpx}.mb--n22{margin-bottom:-88rpx}.mb-n23{margin-bottom:92rpx}.mb--n23{margin-bottom:-92rpx}.mb-n24{margin-bottom:96rpx}.mb--n24{margin-bottom:-96rpx}.mb-n25{margin-bottom:100rpx}.mb--n25{margin-bottom:-100rpx}.ml-0{margin-left:0rpx}.ml--0{margin-left:0rpx}.ml-1{margin-left:1rpx}.ml--1{margin-left:-1rpx}.ml-2{margin-left:2rpx}.ml--2{margin-left:-2rpx}.ml-3{margin-left:3rpx}.ml--3{margin-left:-3rpx}.ml-4{margin-left:4rpx}.ml--4{margin-left:-4rpx}.ml-5{margin-left:5rpx}.ml--5{margin-left:-5rpx}.ml-6{margin-left:6rpx}.ml--6{margin-left:-6rpx}.ml-7{margin-left:7rpx}.ml--7{margin-left:-7rpx}.ml-8{margin-left:8rpx}.ml--8{margin-left:-8rpx}.ml-9{margin-left:9rpx}.ml--9{margin-left:-9rpx}.ml-10{margin-left:10rpx}.ml--10{margin-left:-10rpx}.ml-11{margin-left:11rpx}.ml--11{margin-left:-11rpx}.ml-12{margin-left:12rpx}.ml--12{margin-left:-12rpx}.ml-13{margin-left:13rpx}.ml--13{margin-left:-13rpx}.ml-14{margin-left:14rpx}.ml--14{margin-left:-14rpx}.ml-15{margin-left:15rpx}.ml--15{margin-left:-15rpx}.ml-16{margin-left:16rpx}.ml--16{margin-left:-16rpx}.ml-17{margin-left:17rpx}.ml--17{margin-left:-17rpx}.ml-18{margin-left:18rpx}.ml--18{margin-left:-18rpx}.ml-19{margin-left:19rpx}.ml--19{margin-left:-19rpx}.ml-20{margin-left:20rpx}.ml--20{margin-left:-20rpx}.ml-21{margin-left:21rpx}.ml--21{margin-left:-21rpx}.ml-22{margin-left:22rpx}.ml--22{margin-left:-22rpx}.ml-23{margin-left:23rpx}.ml--23{margin-left:-23rpx}.ml-24{margin-left:24rpx}.ml--24{margin-left:-24rpx}.ml-25{margin-left:25rpx}.ml--25{margin-left:-25rpx}.ml-26{margin-left:26rpx}.ml--26{margin-left:-26rpx}.ml-27{margin-left:27rpx}.ml--27{margin-left:-27rpx}.ml-28{margin-left:28rpx}.ml--28{margin-left:-28rpx}.ml-29{margin-left:29rpx}.ml--29{margin-left:-29rpx}.ml-30{margin-left:30rpx}.ml--30{margin-left:-30rpx}.ml-31{margin-left:31rpx}.ml--31{margin-left:-31rpx}.ml-32{margin-left:32rpx}.ml--32{margin-left:-32rpx}.ml-33{margin-left:33rpx}.ml--33{margin-left:-33rpx}.ml-34{margin-left:34rpx}.ml--34{margin-left:-34rpx}.ml-35{margin-left:35rpx}.ml--35{margin-left:-35rpx}.ml-36{margin-left:36rpx}.ml--36{margin-left:-36rpx}.ml-37{margin-left:37rpx}.ml--37{margin-left:-37rpx}.ml-38{margin-left:38rpx}.ml--38{margin-left:-38rpx}.ml-39{margin-left:39rpx}.ml--39{margin-left:-39rpx}.ml-40{margin-left:40rpx}.ml--40{margin-left:-40rpx}.ml-41{margin-left:41rpx}.ml--41{margin-left:-41rpx}.ml-42{margin-left:42rpx}.ml--42{margin-left:-42rpx}.ml-43{margin-left:43rpx}.ml--43{margin-left:-43rpx}.ml-44{margin-left:44rpx}.ml--44{margin-left:-44rpx}.ml-45{margin-left:45rpx}.ml--45{margin-left:-45rpx}.ml-46{margin-left:46rpx}.ml--46{margin-left:-46rpx}.ml-47{margin-left:47rpx}.ml--47{margin-left:-47rpx}.ml-48{margin-left:48rpx}.ml--48{margin-left:-48rpx}.ml-49{margin-left:49rpx}.ml--49{margin-left:-49rpx}.ml-50{margin-left:50rpx}.ml--50{margin-left:-50rpx}.ml-n1{margin-left:4rpx}.ml--n1{margin-left:-4rpx}.ml-n2{margin-left:8rpx}.ml--n2{margin-left:-8rpx}.ml-n3{margin-left:12rpx}.ml--n3{margin-left:-12rpx}.ml-n4{margin-left:16rpx}.ml--n4{margin-left:-16rpx}.ml-n5{margin-left:20rpx}.ml--n5{margin-left:-20rpx}.ml-n6{margin-left:24rpx}.ml--n6{margin-left:-24rpx}.ml-n7{margin-left:28rpx}.ml--n7{margin-left:-28rpx}.ml-n8{margin-left:32rpx}.ml--n8{margin-left:-32rpx}.ml-n9{margin-left:36rpx}.ml--n9{margin-left:-36rpx}.ml-n10{margin-left:40rpx}.ml--n10{margin-left:-40rpx}.ml-n11{margin-left:44rpx}.ml--n11{margin-left:-44rpx}.ml-n12{margin-left:48rpx}.ml--n12{margin-left:-48rpx}.ml-n13{margin-left:52rpx}.ml--n13{margin-left:-52rpx}.ml-n14{margin-left:56rpx}.ml--n14{margin-left:-56rpx}.ml-n15{margin-left:60rpx}.ml--n15{margin-left:-60rpx}.ml-n16{margin-left:64rpx}.ml--n16{margin-left:-64rpx}.ml-n17{margin-left:68rpx}.ml--n17{margin-left:-68rpx}.ml-n18{margin-left:72rpx}.ml--n18{margin-left:-72rpx}.ml-n19{margin-left:76rpx}.ml--n19{margin-left:-76rpx}.ml-n20{margin-left:80rpx}.ml--n20{margin-left:-80rpx}.ml-n21{margin-left:84rpx}.ml--n21{margin-left:-84rpx}.ml-n22{margin-left:88rpx}.ml--n22{margin-left:-88rpx}.ml-n23{margin-left:92rpx}.ml--n23{margin-left:-92rpx}.ml-n24{margin-left:96rpx}.ml--n24{margin-left:-96rpx}.ml-n25{margin-left:100rpx}.ml--n25{margin-left:-100rpx}.mx-0{margin-left:0rpx;margin-right:0rpx}.mx-1{margin-left:1rpx;margin-right:1rpx}.mx-2{margin-left:2rpx;margin-right:2rpx}.mx-3{margin-left:3rpx;margin-right:3rpx}.mx-4{margin-left:4rpx;margin-right:4rpx}.mx-5{margin-left:5rpx;margin-right:5rpx}.mx-6{margin-left:6rpx;margin-right:6rpx}.mx-7{margin-left:7rpx;margin-right:7rpx}.mx-8{margin-left:8rpx;margin-right:8rpx}.mx-9{margin-left:9rpx;margin-right:9rpx}.mx-10{margin-left:10rpx;margin-right:10rpx}.mx-11{margin-left:11rpx;margin-right:11rpx}.mx-12{margin-left:12rpx;margin-right:12rpx}.mx-13{margin-left:13rpx;margin-right:13rpx}.mx-14{margin-left:14rpx;margin-right:14rpx}.mx-15{margin-left:15rpx;margin-right:15rpx}.mx-16{margin-left:16rpx;margin-right:16rpx}.mx-17{margin-left:17rpx;margin-right:17rpx}.mx-18{margin-left:18rpx;margin-right:18rpx}.mx-19{margin-left:19rpx;margin-right:19rpx}.mx-20{margin-left:20rpx;margin-right:20rpx}.mx-21{margin-left:21rpx;margin-right:21rpx}.mx-22{margin-left:22rpx;margin-right:22rpx}.mx-23{margin-left:23rpx;margin-right:23rpx}.mx-24{margin-left:24rpx;margin-right:24rpx}.mx-25{margin-left:25rpx;margin-right:25rpx}.mx-26{margin-left:26rpx;margin-right:26rpx}.mx-27{margin-left:27rpx;margin-right:27rpx}.mx-28{margin-left:28rpx;margin-right:28rpx}.mx-29{margin-left:29rpx;margin-right:29rpx}.mx-30{margin-left:30rpx;margin-right:30rpx}.mx-31{margin-left:31rpx;margin-right:31rpx}.mx-32{margin-left:32rpx;margin-right:32rpx}.mx-33{margin-left:33rpx;margin-right:33rpx}.mx-34{margin-left:34rpx;margin-right:34rpx}.mx-35{margin-left:35rpx;margin-right:35rpx}.mx-36{margin-left:36rpx;margin-right:36rpx}.mx-37{margin-left:37rpx;margin-right:37rpx}.mx-38{margin-left:38rpx;margin-right:38rpx}.mx-39{margin-left:39rpx;margin-right:39rpx}.mx-40{margin-left:40rpx;margin-right:40rpx}.mx-41{margin-left:41rpx;margin-right:41rpx}.mx-42{margin-left:42rpx;margin-right:42rpx}.mx-43{margin-left:43rpx;margin-right:43rpx}.mx-44{margin-left:44rpx;margin-right:44rpx}.mx-45{margin-left:45rpx;margin-right:45rpx}.mx-46{margin-left:46rpx;margin-right:46rpx}.mx-47{margin-left:47rpx;margin-right:47rpx}.mx-48{margin-left:48rpx;margin-right:48rpx}.mx-49{margin-left:49rpx;margin-right:49rpx}.mx-50{margin-left:50rpx;margin-right:50rpx}.mx-n1{margin-left:4rpx;margin-right:4rpx}.mx-n2{margin-left:8rpx;margin-right:8rpx}.mx-n3{margin-left:12rpx;margin-right:12rpx}.mx-n4{margin-left:16rpx;margin-right:16rpx}.mx-n5{margin-left:20rpx;margin-right:20rpx}.mx-n6{margin-left:24rpx;margin-right:24rpx}.mx-n7{margin-left:28rpx;margin-right:28rpx}.mx-n8{margin-left:32rpx;margin-right:32rpx}.mx-n9{margin-left:36rpx;margin-right:36rpx}.mx-n10{margin-left:40rpx;margin-right:40rpx}.mx-n11{margin-left:44rpx;margin-right:44rpx}.mx-n12{margin-left:48rpx;margin-right:48rpx}.mx-n13{margin-left:52rpx;margin-right:52rpx}.mx-n14{margin-left:56rpx;margin-right:56rpx}.mx-n15{margin-left:60rpx;margin-right:60rpx}.mx-n16{margin-left:64rpx;margin-right:64rpx}.mx-n17{margin-left:68rpx;margin-right:68rpx}.mx-n18{margin-left:72rpx;margin-right:72rpx}.mx-n19{margin-left:76rpx;margin-right:76rpx}.mx-n20{margin-left:80rpx;margin-right:80rpx}.mx-n21{margin-left:84rpx;margin-right:84rpx}.mx-n22{margin-left:88rpx;margin-right:88rpx}.mx-n23{margin-left:92rpx;margin-right:92rpx}.mx-n24{margin-left:96rpx;margin-right:96rpx}.mx-n25{margin-left:100rpx;margin-right:100rpx}.my-0{margin-top:0rpx;margin-bottom:0rpx}.my-1{margin-top:1rpx;margin-bottom:1rpx}.my-2{margin-top:2rpx;margin-bottom:2rpx}.my-3{margin-top:3rpx;margin-bottom:3rpx}.my-4{margin-top:4rpx;margin-bottom:4rpx}.my-5{margin-top:5rpx;margin-bottom:5rpx}.my-6{margin-top:6rpx;margin-bottom:6rpx}.my-7{margin-top:7rpx;margin-bottom:7rpx}.my-8{margin-top:8rpx;margin-bottom:8rpx}.my-9{margin-top:9rpx;margin-bottom:9rpx}.my-10{margin-top:10rpx;margin-bottom:10rpx}.my-11{margin-top:11rpx;margin-bottom:11rpx}.my-12{margin-top:12rpx;margin-bottom:12rpx}.my-13{margin-top:13rpx;margin-bottom:13rpx}.my-14{margin-top:14rpx;margin-bottom:14rpx}.my-15{margin-top:15rpx;margin-bottom:15rpx}.my-16{margin-top:16rpx;margin-bottom:16rpx}.my-17{margin-top:17rpx;margin-bottom:17rpx}.my-18{margin-top:18rpx;margin-bottom:18rpx}.my-19{margin-top:19rpx;margin-bottom:19rpx}.my-20{margin-top:20rpx;margin-bottom:20rpx}.my-21{margin-top:21rpx;margin-bottom:21rpx}.my-22{margin-top:22rpx;margin-bottom:22rpx}.my-23{margin-top:23rpx;margin-bottom:23rpx}.my-24{margin-top:24rpx;margin-bottom:24rpx}.my-25{margin-top:25rpx;margin-bottom:25rpx}.my-26{margin-top:26rpx;margin-bottom:26rpx}.my-27{margin-top:27rpx;margin-bottom:27rpx}.my-28{margin-top:28rpx;margin-bottom:28rpx}.my-29{margin-top:29rpx;margin-bottom:29rpx}.my-30{margin-top:30rpx;margin-bottom:30rpx}.my-31{margin-top:31rpx;margin-bottom:31rpx}.my-32{margin-top:32rpx;margin-bottom:32rpx}.my-33{margin-top:33rpx;margin-bottom:33rpx}.my-34{margin-top:34rpx;margin-bottom:34rpx}.my-35{margin-top:35rpx;margin-bottom:35rpx}.my-36{margin-top:36rpx;margin-bottom:36rpx}.my-37{margin-top:37rpx;margin-bottom:37rpx}.my-38{margin-top:38rpx;margin-bottom:38rpx}.my-39{margin-top:39rpx;margin-bottom:39rpx}.my-40{margin-top:40rpx;margin-bottom:40rpx}.my-41{margin-top:41rpx;margin-bottom:41rpx}.my-42{margin-top:42rpx;margin-bottom:42rpx}.my-43{margin-top:43rpx;margin-bottom:43rpx}.my-44{margin-top:44rpx;margin-bottom:44rpx}.my-45{margin-top:45rpx;margin-bottom:45rpx}.my-46{margin-top:46rpx;margin-bottom:46rpx}.my-47{margin-top:47rpx;margin-bottom:47rpx}.my-48{margin-top:48rpx;margin-bottom:48rpx}.my-49{margin-top:49rpx;margin-bottom:49rpx}.my-50{margin-top:50rpx;margin-bottom:50rpx}.my-n1{margin-top:4rpx;margin-bottom:4rpx}.my-n2{margin-top:8rpx;margin-bottom:8rpx}.my-n3{margin-top:12rpx;margin-bottom:12rpx}.my-n4{margin-top:16rpx;margin-bottom:16rpx}.my-n5{margin-top:20rpx;margin-bottom:20rpx}.my-n6{margin-top:24rpx;margin-bottom:24rpx}.my-n7{margin-top:28rpx;margin-bottom:28rpx}.my-n8{margin-top:32rpx;margin-bottom:32rpx}.my-n9{margin-top:36rpx;margin-bottom:36rpx}.my-n10{margin-top:40rpx;margin-bottom:40rpx}.my-n11{margin-top:44rpx;margin-bottom:44rpx}.my-n12{margin-top:48rpx;margin-bottom:48rpx}.my-n13{margin-top:52rpx;margin-bottom:52rpx}.my-n14{margin-top:56rpx;margin-bottom:56rpx}.my-n15{margin-top:60rpx;margin-bottom:60rpx}.my-n16{margin-top:64rpx;margin-bottom:64rpx}.my-n17{margin-top:68rpx;margin-bottom:68rpx}.my-n18{margin-top:72rpx;margin-bottom:72rpx}.my-n19{margin-top:76rpx;margin-bottom:76rpx}.my-n20{margin-top:80rpx;margin-bottom:80rpx}.my-n21{margin-top:84rpx;margin-bottom:84rpx}.my-n22{margin-top:88rpx;margin-bottom:88rpx}.my-n23{margin-top:92rpx;margin-bottom:92rpx}.my-n24{margin-top:96rpx;margin-bottom:96rpx}.my-n25{margin-top:100rpx;margin-bottom:100rpx}.t-0{top:0rpx}.t--0{top:0rpx}.t-1{top:1rpx}.t--1{top:-1rpx}.t-2{top:2rpx}.t--2{top:-2rpx}.t-3{top:3rpx}.t--3{top:-3rpx}.t-4{top:4rpx}.t--4{top:-4rpx}.t-5{top:5rpx}.t--5{top:-5rpx}.t-6{top:6rpx}.t--6{top:-6rpx}.t-7{top:7rpx}.t--7{top:-7rpx}.t-8{top:8rpx}.t--8{top:-8rpx}.t-9{top:9rpx}.t--9{top:-9rpx}.t-10{top:10rpx}.t--10{top:-10rpx}.t-11{top:11rpx}.t--11{top:-11rpx}.t-12{top:12rpx}.t--12{top:-12rpx}.t-13{top:13rpx}.t--13{top:-13rpx}.t-14{top:14rpx}.t--14{top:-14rpx}.t-15{top:15rpx}.t--15{top:-15rpx}.t-16{top:16rpx}.t--16{top:-16rpx}.t-17{top:17rpx}.t--17{top:-17rpx}.t-18{top:18rpx}.t--18{top:-18rpx}.t-19{top:19rpx}.t--19{top:-19rpx}.t-20{top:20rpx}.t--20{top:-20rpx}.t-21{top:21rpx}.t--21{top:-21rpx}.t-22{top:22rpx}.t--22{top:-22rpx}.t-23{top:23rpx}.t--23{top:-23rpx}.t-24{top:24rpx}.t--24{top:-24rpx}.t-25{top:25rpx}.t--25{top:-25rpx}.t-26{top:26rpx}.t--26{top:-26rpx}.t-27{top:27rpx}.t--27{top:-27rpx}.t-28{top:28rpx}.t--28{top:-28rpx}.t-29{top:29rpx}.t--29{top:-29rpx}.t-30{top:30rpx}.t--30{top:-30rpx}.t-31{top:31rpx}.t--31{top:-31rpx}.t-32{top:32rpx}.t--32{top:-32rpx}.t-33{top:33rpx}.t--33{top:-33rpx}.t-34{top:34rpx}.t--34{top:-34rpx}.t-35{top:35rpx}.t--35{top:-35rpx}.t-36{top:36rpx}.t--36{top:-36rpx}.t-37{top:37rpx}.t--37{top:-37rpx}.t-38{top:38rpx}.t--38{top:-38rpx}.t-39{top:39rpx}.t--39{top:-39rpx}.t-40{top:40rpx}.t--40{top:-40rpx}.t-41{top:41rpx}.t--41{top:-41rpx}.t-42{top:42rpx}.t--42{top:-42rpx}.t-43{top:43rpx}.t--43{top:-43rpx}.t-44{top:44rpx}.t--44{top:-44rpx}.t-45{top:45rpx}.t--45{top:-45rpx}.t-46{top:46rpx}.t--46{top:-46rpx}.t-47{top:47rpx}.t--47{top:-47rpx}.t-48{top:48rpx}.t--48{top:-48rpx}.t-49{top:49rpx}.t--49{top:-49rpx}.t-50{top:50rpx}.t--50{top:-50rpx}.t-n1{top:4rpx}.t--n1{top:-4rpx}.t-n2{top:8rpx}.t--n2{top:-8rpx}.t-n3{top:12rpx}.t--n3{top:-12rpx}.t-n4{top:16rpx}.t--n4{top:-16rpx}.t-n5{top:20rpx}.t--n5{top:-20rpx}.t-n6{top:24rpx}.t--n6{top:-24rpx}.t-n7{top:28rpx}.t--n7{top:-28rpx}.t-n8{top:32rpx}.t--n8{top:-32rpx}.t-n9{top:36rpx}.t--n9{top:-36rpx}.t-n10{top:40rpx}.t--n10{top:-40rpx}.t-n11{top:44rpx}.t--n11{top:-44rpx}.t-n12{top:48rpx}.t--n12{top:-48rpx}.t-n13{top:52rpx}.t--n13{top:-52rpx}.t-n14{top:56rpx}.t--n14{top:-56rpx}.t-n15{top:60rpx}.t--n15{top:-60rpx}.t-n16{top:64rpx}.t--n16{top:-64rpx}.t-n17{top:68rpx}.t--n17{top:-68rpx}.t-n18{top:72rpx}.t--n18{top:-72rpx}.t-n19{top:76rpx}.t--n19{top:-76rpx}.t-n20{top:80rpx}.t--n20{top:-80rpx}.t-n21{top:84rpx}.t--n21{top:-84rpx}.t-n22{top:88rpx}.t--n22{top:-88rpx}.t-n23{top:92rpx}.t--n23{top:-92rpx}.t-n24{top:96rpx}.t--n24{top:-96rpx}.t-n25{top:100rpx}.t--n25{top:-100rpx}.r-0{right:0rpx}.r--0{right:0rpx}.r-1{right:1rpx}.r--1{right:-1rpx}.r-2{right:2rpx}.r--2{right:-2rpx}.r-3{right:3rpx}.r--3{right:-3rpx}.r-4{right:4rpx}.r--4{right:-4rpx}.r-5{right:5rpx}.r--5{right:-5rpx}.r-6{right:6rpx}.r--6{right:-6rpx}.r-7{right:7rpx}.r--7{right:-7rpx}.r-8{right:8rpx}.r--8{right:-8rpx}.r-9{right:9rpx}.r--9{right:-9rpx}.r-10{right:10rpx}.r--10{right:-10rpx}.r-11{right:11rpx}.r--11{right:-11rpx}.r-12{right:12rpx}.r--12{right:-12rpx}.r-13{right:13rpx}.r--13{right:-13rpx}.r-14{right:14rpx}.r--14{right:-14rpx}.r-15{right:15rpx}.r--15{right:-15rpx}.r-16{right:16rpx}.r--16{right:-16rpx}.r-17{right:17rpx}.r--17{right:-17rpx}.r-18{right:18rpx}.r--18{right:-18rpx}.r-19{right:19rpx}.r--19{right:-19rpx}.r-20{right:20rpx}.r--20{right:-20rpx}.r-21{right:21rpx}.r--21{right:-21rpx}.r-22{right:22rpx}.r--22{right:-22rpx}.r-23{right:23rpx}.r--23{right:-23rpx}.r-24{right:24rpx}.r--24{right:-24rpx}.r-25{right:25rpx}.r--25{right:-25rpx}.r-26{right:26rpx}.r--26{right:-26rpx}.r-27{right:27rpx}.r--27{right:-27rpx}.r-28{right:28rpx}.r--28{right:-28rpx}.r-29{right:29rpx}.r--29{right:-29rpx}.r-30{right:30rpx}.r--30{right:-30rpx}.r-31{right:31rpx}.r--31{right:-31rpx}.r-32{right:32rpx}.r--32{right:-32rpx}.r-33{right:33rpx}.r--33{right:-33rpx}.r-34{right:34rpx}.r--34{right:-34rpx}.r-35{right:35rpx}.r--35{right:-35rpx}.r-36{right:36rpx}.r--36{right:-36rpx}.r-37{right:37rpx}.r--37{right:-37rpx}.r-38{right:38rpx}.r--38{right:-38rpx}.r-39{right:39rpx}.r--39{right:-39rpx}.r-40{right:40rpx}.r--40{right:-40rpx}.r-41{right:41rpx}.r--41{right:-41rpx}.r-42{right:42rpx}.r--42{right:-42rpx}.r-43{right:43rpx}.r--43{right:-43rpx}.r-44{right:44rpx}.r--44{right:-44rpx}.r-45{right:45rpx}.r--45{right:-45rpx}.r-46{right:46rpx}.r--46{right:-46rpx}.r-47{right:47rpx}.r--47{right:-47rpx}.r-48{right:48rpx}.r--48{right:-48rpx}.r-49{right:49rpx}.r--49{right:-49rpx}.r-50{right:50rpx}.r--50{right:-50rpx}.r-n1{right:4rpx}.r--n1{right:-4rpx}.r-n2{right:8rpx}.r--n2{right:-8rpx}.r-n3{right:12rpx}.r--n3{right:-12rpx}.r-n4{right:16rpx}.r--n4{right:-16rpx}.r-n5{right:20rpx}.r--n5{right:-20rpx}.r-n6{right:24rpx}.r--n6{right:-24rpx}.r-n7{right:28rpx}.r--n7{right:-28rpx}.r-n8{right:32rpx}.r--n8{right:-32rpx}.r-n9{right:36rpx}.r--n9{right:-36rpx}.r-n10{right:40rpx}.r--n10{right:-40rpx}.r-n11{right:44rpx}.r--n11{right:-44rpx}.r-n12{right:48rpx}.r--n12{right:-48rpx}.r-n13{right:52rpx}.r--n13{right:-52rpx}.r-n14{right:56rpx}.r--n14{right:-56rpx}.r-n15{right:60rpx}.r--n15{right:-60rpx}.r-n16{right:64rpx}.r--n16{right:-64rpx}.r-n17{right:68rpx}.r--n17{right:-68rpx}.r-n18{right:72rpx}.r--n18{right:-72rpx}.r-n19{right:76rpx}.r--n19{right:-76rpx}.r-n20{right:80rpx}.r--n20{right:-80rpx}.r-n21{right:84rpx}.r--n21{right:-84rpx}.r-n22{right:88rpx}.r--n22{right:-88rpx}.r-n23{right:92rpx}.r--n23{right:-92rpx}.r-n24{right:96rpx}.r--n24{right:-96rpx}.r-n25{right:100rpx}.r--n25{right:-100rpx}.b-0{bottom:0rpx}.b--0{bottom:0rpx}.b-1{bottom:1rpx}.b--1{bottom:-1rpx}.b-2{bottom:2rpx}.b--2{bottom:-2rpx}.b-3{bottom:3rpx}.b--3{bottom:-3rpx}.b-4{bottom:4rpx}.b--4{bottom:-4rpx}.b-5{bottom:5rpx}.b--5{bottom:-5rpx}.b-6{bottom:6rpx}.b--6{bottom:-6rpx}.b-7{bottom:7rpx}.b--7{bottom:-7rpx}.b-8{bottom:8rpx}.b--8{bottom:-8rpx}.b-9{bottom:9rpx}.b--9{bottom:-9rpx}.b-10{bottom:10rpx}.b--10{bottom:-10rpx}.b-11{bottom:11rpx}.b--11{bottom:-11rpx}.b-12{bottom:12rpx}.b--12{bottom:-12rpx}.b-13{bottom:13rpx}.b--13{bottom:-13rpx}.b-14{bottom:14rpx}.b--14{bottom:-14rpx}.b-15{bottom:15rpx}.b--15{bottom:-15rpx}.b-16{bottom:16rpx}.b--16{bottom:-16rpx}.b-17{bottom:17rpx}.b--17{bottom:-17rpx}.b-18{bottom:18rpx}.b--18{bottom:-18rpx}.b-19{bottom:19rpx}.b--19{bottom:-19rpx}.b-20{bottom:20rpx}.b--20{bottom:-20rpx}.b-21{bottom:21rpx}.b--21{bottom:-21rpx}.b-22{bottom:22rpx}.b--22{bottom:-22rpx}.b-23{bottom:23rpx}.b--23{bottom:-23rpx}.b-24{bottom:24rpx}.b--24{bottom:-24rpx}.b-25{bottom:25rpx}.b--25{bottom:-25rpx}.b-26{bottom:26rpx}.b--26{bottom:-26rpx}.b-27{bottom:27rpx}.b--27{bottom:-27rpx}.b-28{bottom:28rpx}.b--28{bottom:-28rpx}.b-29{bottom:29rpx}.b--29{bottom:-29rpx}.b-30{bottom:30rpx}.b--30{bottom:-30rpx}.b-31{bottom:31rpx}.b--31{bottom:-31rpx}.b-32{bottom:32rpx}.b--32{bottom:-32rpx}.b-33{bottom:33rpx}.b--33{bottom:-33rpx}.b-34{bottom:34rpx}.b--34{bottom:-34rpx}.b-35{bottom:35rpx}.b--35{bottom:-35rpx}.b-36{bottom:36rpx}.b--36{bottom:-36rpx}.b-37{bottom:37rpx}.b--37{bottom:-37rpx}.b-38{bottom:38rpx}.b--38{bottom:-38rpx}.b-39{bottom:39rpx}.b--39{bottom:-39rpx}.b-40{bottom:40rpx}.b--40{bottom:-40rpx}.b-41{bottom:41rpx}.b--41{bottom:-41rpx}.b-42{bottom:42rpx}.b--42{bottom:-42rpx}.b-43{bottom:43rpx}.b--43{bottom:-43rpx}.b-44{bottom:44rpx}.b--44{bottom:-44rpx}.b-45{bottom:45rpx}.b--45{bottom:-45rpx}.b-46{bottom:46rpx}.b--46{bottom:-46rpx}.b-47{bottom:47rpx}.b--47{bottom:-47rpx}.b-48{bottom:48rpx}.b--48{bottom:-48rpx}.b-49{bottom:49rpx}.b--49{bottom:-49rpx}.b-50{bottom:50rpx}.b--50{bottom:-50rpx}.b-n1{bottom:4rpx}.b--n1{bottom:-4rpx}.b-n2{bottom:8rpx}.b--n2{bottom:-8rpx}.b-n3{bottom:12rpx}.b--n3{bottom:-12rpx}.b-n4{bottom:16rpx}.b--n4{bottom:-16rpx}.b-n5{bottom:20rpx}.b--n5{bottom:-20rpx}.b-n6{bottom:24rpx}.b--n6{bottom:-24rpx}.b-n7{bottom:28rpx}.b--n7{bottom:-28rpx}.b-n8{bottom:32rpx}.b--n8{bottom:-32rpx}.b-n9{bottom:36rpx}.b--n9{bottom:-36rpx}.b-n10{bottom:40rpx}.b--n10{bottom:-40rpx}.b-n11{bottom:44rpx}.b--n11{bottom:-44rpx}.b-n12{bottom:48rpx}.b--n12{bottom:-48rpx}.b-n13{bottom:52rpx}.b--n13{bottom:-52rpx}.b-n14{bottom:56rpx}.b--n14{bottom:-56rpx}.b-n15{bottom:60rpx}.b--n15{bottom:-60rpx}.b-n16{bottom:64rpx}.b--n16{bottom:-64rpx}.b-n17{bottom:68rpx}.b--n17{bottom:-68rpx}.b-n18{bottom:72rpx}.b--n18{bottom:-72rpx}.b-n19{bottom:76rpx}.b--n19{bottom:-76rpx}.b-n20{bottom:80rpx}.b--n20{bottom:-80rpx}.b-n21{bottom:84rpx}.b--n21{bottom:-84rpx}.b-n22{bottom:88rpx}.b--n22{bottom:-88rpx}.b-n23{bottom:92rpx}.b--n23{bottom:-92rpx}.b-n24{bottom:96rpx}.b--n24{bottom:-96rpx}.b-n25{bottom:100rpx}.b--n25{bottom:-100rpx}.l-0{left:0rpx}.l--0{left:0rpx}.l-1{left:1rpx}.l--1{left:-1rpx}.l-2{left:2rpx}.l--2{left:-2rpx}.l-3{left:3rpx}.l--3{left:-3rpx}.l-4{left:4rpx}.l--4{left:-4rpx}.l-5{left:5rpx}.l--5{left:-5rpx}.l-6{left:6rpx}.l--6{left:-6rpx}.l-7{left:7rpx}.l--7{left:-7rpx}.l-8{left:8rpx}.l--8{left:-8rpx}.l-9{left:9rpx}.l--9{left:-9rpx}.l-10{left:10rpx}.l--10{left:-10rpx}.l-11{left:11rpx}.l--11{left:-11rpx}.l-12{left:12rpx}.l--12{left:-12rpx}.l-13{left:13rpx}.l--13{left:-13rpx}.l-14{left:14rpx}.l--14{left:-14rpx}.l-15{left:15rpx}.l--15{left:-15rpx}.l-16{left:16rpx}.l--16{left:-16rpx}.l-17{left:17rpx}.l--17{left:-17rpx}.l-18{left:18rpx}.l--18{left:-18rpx}.l-19{left:19rpx}.l--19{left:-19rpx}.l-20{left:20rpx}.l--20{left:-20rpx}.l-21{left:21rpx}.l--21{left:-21rpx}.l-22{left:22rpx}.l--22{left:-22rpx}.l-23{left:23rpx}.l--23{left:-23rpx}.l-24{left:24rpx}.l--24{left:-24rpx}.l-25{left:25rpx}.l--25{left:-25rpx}.l-26{left:26rpx}.l--26{left:-26rpx}.l-27{left:27rpx}.l--27{left:-27rpx}.l-28{left:28rpx}.l--28{left:-28rpx}.l-29{left:29rpx}.l--29{left:-29rpx}.l-30{left:30rpx}.l--30{left:-30rpx}.l-31{left:31rpx}.l--31{left:-31rpx}.l-32{left:32rpx}.l--32{left:-32rpx}.l-33{left:33rpx}.l--33{left:-33rpx}.l-34{left:34rpx}.l--34{left:-34rpx}.l-35{left:35rpx}.l--35{left:-35rpx}.l-36{left:36rpx}.l--36{left:-36rpx}.l-37{left:37rpx}.l--37{left:-37rpx}.l-38{left:38rpx}.l--38{left:-38rpx}.l-39{left:39rpx}.l--39{left:-39rpx}.l-40{left:40rpx}.l--40{left:-40rpx}.l-41{left:41rpx}.l--41{left:-41rpx}.l-42{left:42rpx}.l--42{left:-42rpx}.l-43{left:43rpx}.l--43{left:-43rpx}.l-44{left:44rpx}.l--44{left:-44rpx}.l-45{left:45rpx}.l--45{left:-45rpx}.l-46{left:46rpx}.l--46{left:-46rpx}.l-47{left:47rpx}.l--47{left:-47rpx}.l-48{left:48rpx}.l--48{left:-48rpx}.l-49{left:49rpx}.l--49{left:-49rpx}.l-50{left:50rpx}.l--50{left:-50rpx}.l-n1{left:4rpx}.l--n1{left:-4rpx}.l-n2{left:8rpx}.l--n2{left:-8rpx}.l-n3{left:12rpx}.l--n3{left:-12rpx}.l-n4{left:16rpx}.l--n4{left:-16rpx}.l-n5{left:20rpx}.l--n5{left:-20rpx}.l-n6{left:24rpx}.l--n6{left:-24rpx}.l-n7{left:28rpx}.l--n7{left:-28rpx}.l-n8{left:32rpx}.l--n8{left:-32rpx}.l-n9{left:36rpx}.l--n9{left:-36rpx}.l-n10{left:40rpx}.l--n10{left:-40rpx}.l-n11{left:44rpx}.l--n11{left:-44rpx}.l-n12{left:48rpx}.l--n12{left:-48rpx}.l-n13{left:52rpx}.l--n13{left:-52rpx}.l-n14{left:56rpx}.l--n14{left:-56rpx}.l-n15{left:60rpx}.l--n15{left:-60rpx}.l-n16{left:64rpx}.l--n16{left:-64rpx}.l-n17{left:68rpx}.l--n17{left:-68rpx}.l-n18{left:72rpx}.l--n18{left:-72rpx}.l-n19{left:76rpx}.l--n19{left:-76rpx}.l-n20{left:80rpx}.l--n20{left:-80rpx}.l-n21{left:84rpx}.l--n21{left:-84rpx}.l-n22{left:88rpx}.l--n22{left:-88rpx}.l-n23{left:92rpx}.l--n23{left:-92rpx}.l-n24{left:96rpx}.l--n24{left:-96rpx}.l-n25{left:100rpx}.l--n25{left:-100rpx}.flex{display:flex}.flex-col{flex-direction:column}.flex-wrap{flex-flow:row wrap}.flex-shrink{flex-shrink:0}.flex-row{flex-direction:row}.flex-reverse{flex-direction:row-reverse}.flex-row-top-start{justify-content:flex-start;align-items:flex-start;display:flex}.flex-row-top-center{justify-content:center;align-items:flex-start;display:flex}.flex-row-top-end{justify-content:flex-end;align-items:flex-start;display:flex}.flex-row-center-start{justify-content:flex-start;align-items:center;display:flex}.flex-row-center-center{justify-content:center;align-items:center;display:flex}.flex-row-center-end{justify-content:flex-end;align-items:center;display:flex}.flex-row-bottom-start{justify-content:flex-start;align-items:flex-end;display:flex}.flex-row-bottom-center{justify-content:center;align-items:flex-end;display:flex}.flex-row-bottom-end{justify-content:flex-end;align-items:flex-end;display:flex}.flex-row-center-between{justify-content:space-between;align-items:center;display:flex}.flex-col-top-start{justify-content:flex-start;align-items:flex-start;display:flex}.flex-col-top-center{justify-content:flex-start;align-items:center;display:flex}.flex-col-top-end{justify-content:flex-start;align-items:flex-end;display:flex}.flex-col-center-start{justify-content:center;align-items:flex-start;display:flex}.flex-col-center-center{justify-content:center;align-items:center;display:flex}.flex-col-center-end{justify-content:center;align-items:flex-end;display:flex}.flex-col-bottom-start{justify-content:flex-end;align-items:flex-start;display:flex}.flex-col-bottom-center{justify-content:flex-end;align-items:center;display:flex}.flex-col-bottom-end{justify-content:flex-end;align-items:flex-end;display:flex}.flex-start{justify-content:flex-start;align-items:center;display:flex}.flex-end{justify-content:flex-end;align-items:center;display:flex}.flex-center{justify-content:center;align-items:center;display:flex}.flex-between{justify-content:space-between}.flex-col-full{flex-direction:column;align-items:stretch}.flex-around{justify-content:space-around}.flex-0{flex:0}.flex-1{flex:1}.flex-2{flex:2}.flex-3{flex:3}.flex-4{flex:4}.flex-5{flex:5}.flex-6{flex:6}.flex-7{flex:7}.flex-8{flex:8}.flex-9{flex:9}.flex-10{flex:10}.flex-11{flex:11}.flex-12{flex:12}.text-red{color:#f44336}.red{background-color:#f44336}.text-pink{color:#e91e63}.pink{background-color:#e91e63}.text-purple{color:#9c27b0}.purple{background-color:#9c27b0}.text-deep-purple{color:#673ab7}.deep-purple{background-color:#673ab7}.text-indigo{color:#3f51b5}.indigo{background-color:#3f51b5}.text-blue{color:#2196f3}.blue{background-color:#2196f3}.text-light-blue{color:#03a9f4}.light-blue{background-color:#03a9f4}.text-cyan{color:#00bcd4}.cyan{background-color:#00bcd4}.text-teal{color:#009688}.teal{background-color:#009688}.text-green{color:#4caf50}.green{background-color:#4caf50}.text-light-green{color:#8bc34a}.light-green{background-color:#8bc34a}.text-lime{color:#cddc39}.lime{background-color:#cddc39}.text-yellow{color:#ffeb3b}.yellow{background-color:#ffeb3b}.text-amber{color:#ffc107}.amber{background-color:#ffc107}.text-orange{color:#ff9800}.orange{background-color:#ff9800}.text-deep-orange{color:#ff5722}.deep-orange{background-color:#ff5722}.text-brown{color:#795548}.brown{background-color:#795548}.text-blue-grey{color:#607d8b}.blue-grey{background-color:#607d8b}.text-primary{color:#08f}.primary{background-color:#08f}.text-success{color:#34c759}.success{background-color:#34c759}.text-danger{color:#ff8d28}.danger{background-color:#ff8d28}.text-warn{color:#f3bf12}.warn{background-color:#f3bf12}.text-error{color:#ff383c}.error{background-color:#ff383c}.text-info{color:#f2f2f7}.info{background-color:#f2f2f7}.text-grey{color:#9e9e9e}.grey{background-color:#9e9e9e}.text-black{color:#000}.black{background-color:#000}.text-white{color:#fff}.white{background-color:#fff}.text-lighten-5{color:#fafafa}.lighten-5{background-color:#fafafa}.text-lighten-4{color:#f5f5f5}.lighten-4{background-color:#f5f5f5}.text-lighten-3{color:#eee}.lighten-3{background-color:#eee}.text-lighten-2{color:#e0e0e0}.lighten-2{background-color:#e0e0e0}.text-lighten-1{color:#bdbdbd}.lighten-1{background-color:#bdbdbd}.text-darken-1{color:#757575}.darken-1{background-color:#757575}.text-darken-2{color:#616161}.darken-2{background-color:#616161}.text-darken-3{color:#424242}.darken-3{background-color:#424242}.text-darken-4{color:#212121}.darken-4{background-color:#212121}.text-darken-5{color:#131313}.darken-5{background-color:#131313}.text-darken-6{color:#0a0a0a}.darken-6{background-color:#0a0a0a} \ No newline at end of file diff --git a/uni_modules/tmx-ui/scss/uvue.scss b/uni_modules/tmx-ui/scss/uvue.scss new file mode 100644 index 0000000..a3c7d5d --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvue.scss @@ -0,0 +1,561 @@ +// 溢出隐藏。 +.overflow { + overflow: hidden; +} +.show{ + visibility:visible; +} +.hidden{ + visibility:hidden; +} +.none{ + display:none; +} +$v_position: ( + relative: relative, + absolute: absolute, + fixed: fixed, + // sticky: sticky, + // static : static , +); + +@each $name,$key in $v_position { + .#{$name} { + position: $key ; + } +} +.fulled{ + width:100%; +} +.fulled-height { + flex: 1; +} + + + + +@for $i from 0 through 26 { + .zIndex-#{$i} { + z-index: #{$i * 1}; + } + .zIndex-n#{$i} { + z-index: #{$i * 4}; + } +} + +.text-overflow { + text-overflow: ellipsis; +} + +@for $i from 1 to 5 { + .text-overflow-#{$i} { + text-overflow: ellipsis; + lines: $i; + } +} + + +// 文本大小 。text-size-xs大小名称,xxs,xs,s,n,g,lg,xl +@each $name,$key in (xxs: 20rpx, xs: 22rpx, s: 24rpx, m: 28rpx, n: 30rpx, g: 34rpx, lg: 36rpx, xl: 40rpx) { + .text-size-#{$name} { + font-size: $key; + } +} + +// 文本加粗text-weight-s,n,b +@each $name,$key in (s: 400, n: 400, b: 700) { + .text-weight-#{$name} { + font-weight: $key; + } +} + +// 文本对齐 。text-align-left,right,center +@each $name,$key in (left: left, right: right, center: center) { + .text-align-#{$name} { + text-align: $key; + } +} + +// 圆角半径 +// 圆角说明 round-方向-大小。 +// tl,顶左,tr顶右。bt底左,br底右。a全部。t:顶左和顶右,b:底左和底右,l:顶左和底左,r:顶右,底右。 +@each $name,$key in (tl: 'tl', tr: 'tr', bl: 'bl', br: 'br', a: 'a', t: 't', b: 'b', l: 'l', r: 'r') { + @for $i from 0 to 26 { + .round-#{$name}-#{$i} { + @if $key=='tl' { + border-top-left-radius: #{$i * 2}rpx; + } + + @if $key=='tr' { + border-top-right-radius: #{$i * 2}rpx; + } + + @if $key=='bl' { + border-bottom-left-radius: #{$i * 2}rpx; + } + + @if $key=='br' { + border-bottom-right-radius: #{$i * 2}rpx; + } + + @if $key=='t' { + border-top-left-radius: #{$i * 2}rpx; + border-top-right-radius: #{$i * 2}rpx; + } + + @if $key=='b' { + border-bottom-left-radius: #{$i * 2}rpx; + border-bottom-right-radius: #{$i * 2}rpx; + } + + @if $key=='l' { + border-top-left-radius: #{$i * 2}rpx; + border-bottom-left-radius: #{$i * 2}rpx; + } + + @if $key=='r' { + border-top-right-radius: #{$i * 2}rpx; + border-bottom-right-radius: #{$i * 2}rpx; + } + + @if $key=='a' { + border-radius: #{$i * 2}rpx; + } + } + } +} + +// 从0-100的圆角round-数字 +@for $i from 0 through 26 { + .round-#{$i} { + border-radius: #{$i * 2}rpx; + } + +} + +/** 0-20表示的是1.0~3.0之间的行高 */ +@for $i from 0 through 21 { + .line-#{$i}{ + line-height: #{$i / 10 + 1}; + } +} + + + +// 透明度opacity-[1-10] +@for $i from 0 to 11 { + .opacity-#{$i} { + @if $i>0 and $i<10 { + opacity: $i / 10; + } + + @if $i==0 { + opacity: 0; + } + + @if $i==10 { + opacity: 1; + } + } +} + +// 添加边线 最大5 +@for $i from 0 to 6 { + @if $i==0 { + .border-0 { + border:0rpx solid #f5f5f5; + } + + .border { + border:2rpx solid #f5f5f5; + } + + } + + @if $i>0 { + .border-#{$i} { + border:#{$i * 2}rpx solid #f5f5f5; + } + + .border-#{$i}-bk { + border:#{$i * 2}rpx solid #f5f5f5; + } + } +} + +// 边线格式1:border-方向t,r,l,b-宽度 +@each $name,$key in (l: 'left', r: 'right', t: 'top', b: 'bottom', a: 'a') { + @for $i from 1 to 6 { + .border-#{$name}-#{$i} { + @if $key=='a' { + border:#{$i * 2}rpx solid opacify($color: #f5f5f5, $amount: 1); + } + + @if $key !='a' { + border-#{$key}:#{$i * 2}rpx solid opacify($color: #f5f5f5, $amount: 1); + } + } + + } +} + +// 内间距。p[a,t,r,b,l,x,y]如:pa表示所有边距,px:左右,py:上下,pr:右边距 +@each $name,$key in (a: 'padding', t: 'padding-top', r: 'padding-right', b: 'padding-bottom', l: 'padding-left', x: 'x', y: 'y') { + @for $i from 0 to 51 { + @if $key !='x' and $key !='y' { + .p#{$name}-#{$i} { + #{$key}: #{$i}rpx; + } + } + + @if $key=='x' { + .px-#{$i} { + padding-left: #{$i}rpx; + padding-right: #{$i}rpx; + } + } + + @if $key=='y' { + .py-#{$i} { + padding-top: #{$i}rpx; + padding-bottom: #{$i}rpx; + } + } + } + + @for $i from 1 to 26 { + @if $key !='x' and $key !='y' { + .p#{$name}-n#{$i} { + #{$key}: #{$i * 4}rpx; + } + } + + @if $key=='x' { + .px-n#{$i} { + padding-left: #{$i * 4}rpx; + padding-right: #{$i * 4}rpx; + } + } + + @if $key=='y' { + .py-n#{$i} { + padding-top: #{$i * 4}rpx; + padding-bottom: #{$i * 4}rpx; + } + } + } +} + +// 外间距。m[a,t,r,b,l,x,y]如:ma表示所有外边距,mx:左右,my:上下,mr:右边距 +@each $name,$key in (a: 'margin', t: 'margin-top', r: 'margin-right', b: 'margin-bottom', l: 'margin-left', x: 'x', y: 'y') { + @for $i from 0 to 51 { + @if $key !='x' and $key !='y' { + .m#{$name}-#{$i} { + #{$key}: #{$i}rpx; + } + + @if $key !='margin' { + .m#{$name}--#{$i} { + #{$key}: -#{$i}rpx; + } + } + } + @if $key=='x' { + .mx-#{$i} { + margin-left: #{$i}rpx; + margin-right: #{$i}rpx; + } + } + + @if $key=='y' { + .my-#{$i} { + margin-top: #{$i}rpx; + margin-bottom: #{$i}rpx; + } + } + } + + @for $i from 1 to 26 { + @if $key !='x' and $key !='y' { + .m#{$name}-n#{$i} { + #{$key}: #{$i * 4}rpx; + } + + @if $key !='margin' { + .m#{$name}--n#{$i} { + #{$key}: -#{$i * 4}rpx; + } + } + } + + @if $key=='x' { + .mx-n#{$i} { + margin-left: #{$i * 4}rpx; + margin-right: #{$i * 4}rpx; + } + } + + @if $key=='y' { + .my-n#{$i} { + margin-top: #{$i * 4}rpx; + margin-bottom: #{$i * 4}rpx; + } + } + } +} + +// 位置。 +@each $name,$key in (t: 'top', r: 'right', b: 'bottom', l: 'left') { + @for $i from 0 to 51 { + .#{$name}-#{$i} { + #{$key}: #{$i}rpx; + } + + .#{$name}--#{$i} { + #{$key}: -#{$i}rpx; + } + } + + @for $i from 1 to 26 { + .#{$name}-n#{$i} { + #{$key}: #{$i * 4}rpx; + } + + .#{$name}--n#{$i} { + #{$key}: -#{$i * 4}rpx; + } + } +} + +// Flex辅助。 +@mixin dsplay-flex($justify, $items, $content) { + justify-content: $justify; + align-items: $items ; + display: flex; +} + +.flex { + display: flex; +} + +.flex-col { + flex-direction: column; +} + +.flex-wrap { + flex-flow: row wrap; +} + +.flex-shrink { + flex-shrink: 0; +} + +.flex-row { + flex-direction: row; +} + +.flex-reverse { + flex-direction: row-reverse; +} + +//row模式下,上左对齐 +.flex-row-top-start { + @include dsplay-flex(flex-start, flex-start, center); +} + +//row模式下,上中对齐 +.flex-row-top-center { + @include dsplay-flex(center, flex-start, center); +} + +//row模式下,上右对齐 +.flex-row-top-end { + @include dsplay-flex(flex-end, flex-start, center); +} + +//row模式下,中左对齐 +.flex-row-center-start { + @include dsplay-flex(flex-start, center, center); +} + +//row模式下,中中对齐 +.flex-row-center-center { + @include dsplay-flex(center, center, center); +} + +//row模式下,上右对齐 +.flex-row-center-end { + @include dsplay-flex(flex-end, center, center); +} + +//row模式下,下左对齐 +.flex-row-bottom-start { + @include dsplay-flex(flex-start, flex-end, center); +} + +//row模式下,下中对齐 +.flex-row-bottom-center { + @include dsplay-flex(center, flex-end, center); +} + +//row模式下,下右对齐 +.flex-row-bottom-end { + @include dsplay-flex(flex-end, flex-end, center); +} + +//上下居中,两边对齐。 +.flex-row-center-between { + @include dsplay-flex(space-between, center, center); +} + +//-------- +//col模式下,上左对齐 +.flex-col-top-start { + @include dsplay-flex(flex-start, flex-start, center); +} + +//col模式下,上中对齐 +.flex-col-top-center { + @include dsplay-flex(flex-start, center, center); +} + +//col模式下,上右对齐 +.flex-col-top-end { + @include dsplay-flex(flex-start, flex-end, center); +} + +//col模式下,中左对齐 +.flex-col-center-start { + @include dsplay-flex(center, flex-start, center); +} + +//col模式下,中中对齐 +.flex-col-center-center { + @include dsplay-flex(center, center, center); +} + +//col模式下,上右对齐 +.flex-col-center-end { + @include dsplay-flex(center, flex-end, center); +} + +//col模式下,下左对齐 +.flex-col-bottom-start { + @include dsplay-flex(flex-end, flex-start, center); +} + +//col模式下,下中对齐 +.flex-col-bottom-center { + @include dsplay-flex(flex-end, center, center); +} + +//col模式下,下右对齐 +.flex-col-bottom-end { + @include dsplay-flex(flex-end, flex-end, center); +} + +//----------- + +// row居中左对齐 +.flex-start { + @include dsplay-flex(flex-start, center, center); +} + +// row居中右对齐 +.flex-end { + @include dsplay-flex(flex-end, center, center); +} + +// col,row上下左右居中对齐 +.flex-center { + @include dsplay-flex(center, center, center); +} + +// col,row两端对齐 +.flex-between { + justify-content: space-between; +} + +//横向的内容在col模式一睥100%宽,与flex-1中的flex-row是功能一样。 +.flex-col-full { + flex-direction: column; + align-items: stretch; +} + +// col,row居中等分对齐 +.flex-around { + justify-content: space-around; +} + +@for $i from 0 through 12 { + .flex-#{$i} { + flex: $i ; + } +} + + +$colorsDefault: ( + 'grey': #9e9e9e, + 'black': #000000, + 'white': #ffffff, + 'lighten-5': #fafafa, + 'lighten-4': #f5f5f5, + 'lighten-3': #eeeeee, + 'lighten-2': #e0e0e0, + 'lighten-1': #bdbdbd, + 'darken-1': #757575, + 'darken-2': #616161, + 'darken-3': #424242, + 'darken-4': #212121, + 'darken-5': #131313, + 'darken-6': #0a0a0a +); +$colors: ( + 'red': #f44336, + 'pink': #e91e63, + 'purple': #9c27b0, + 'deep-purple': #673ab7, + 'indigo': #3f51b5, + 'blue': #2196f3, + 'light-blue': #03a9f4, + 'cyan': #00bcd4, + 'teal': #009688, + 'green': #4caf50, + 'light-green': #8bc34a, + 'lime': #cddc39, + 'yellow': #ffeb3b, + 'amber': #ffc107, + 'orange': #ff9800, + 'deep-orange': #ff5722, + 'brown': #795548, + 'blue-grey': #607d8b, + 'primary':#0088ff, + 'success': #34c759, + 'danger': #ff8d28, + 'warn': #F3BF12, + 'error': #ff383c, + 'info': #f2f2f7 +); + +// 文本颜色。text-颜色名 +@each $name,$color in $colors { + .text-#{$name} { + color: $color ; + } + + .#{$name} { + background-color: $color; + } +} + +@each $name,$color in $colorsDefault { + .text-#{$name} { + color: $color ; + } + + .#{$name} { + background-color: $color; + } +} + + diff --git a/uni_modules/tmx-ui/scss/uvuePx.css b/uni_modules/tmx-ui/scss/uvuePx.css new file mode 100644 index 0000000..c3580ba --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvuePx.css @@ -0,0 +1,8769 @@ +@charset "UTF-8"; +/* #ifdef WEB */ +.uni-picker-view-mask { + background-image: none !important; } + +/* #endif */ +.overflow { + overflow: hidden; } + +.show { + visibility: visible; } + +.hidden { + visibility: hidden; } + +.none { + display: none; } + +.relative { + position: relative; } + +.absolute { + position: absolute; } + +.fixed { + position: fixed; } + +.fulled { + width: 100%; } + +.fulled-height { + flex: 1; } + +.zIndex-0 { + z-index: 0; } + +.zIndex-n0 { + z-index: 0; } + +.zIndex-1 { + z-index: 1; } + +.zIndex-n1 { + z-index: 2; } + +.zIndex-2 { + z-index: 2; } + +.zIndex-n2 { + z-index: 4; } + +.zIndex-3 { + z-index: 3; } + +.zIndex-n3 { + z-index: 6; } + +.zIndex-4 { + z-index: 4; } + +.zIndex-n4 { + z-index: 8; } + +.zIndex-5 { + z-index: 5; } + +.zIndex-n5 { + z-index: 10; } + +.zIndex-6 { + z-index: 6; } + +.zIndex-n6 { + z-index: 12; } + +.zIndex-7 { + z-index: 7; } + +.zIndex-n7 { + z-index: 14; } + +.zIndex-8 { + z-index: 8; } + +.zIndex-n8 { + z-index: 16; } + +.zIndex-9 { + z-index: 9; } + +.zIndex-n9 { + z-index: 18; } + +.zIndex-10 { + z-index: 10; } + +.zIndex-n10 { + z-index: 20; } + +.zIndex-11 { + z-index: 11; } + +.zIndex-n11 { + z-index: 22; } + +.zIndex-12 { + z-index: 12; } + +.zIndex-n12 { + z-index: 24; } + +.zIndex-13 { + z-index: 13; } + +.zIndex-n13 { + z-index: 26; } + +.zIndex-14 { + z-index: 14; } + +.zIndex-n14 { + z-index: 28; } + +.zIndex-15 { + z-index: 15; } + +.zIndex-n15 { + z-index: 30; } + +.zIndex-16 { + z-index: 16; } + +.zIndex-n16 { + z-index: 32; } + +.zIndex-17 { + z-index: 17; } + +.zIndex-n17 { + z-index: 34; } + +.zIndex-18 { + z-index: 18; } + +.zIndex-n18 { + z-index: 36; } + +.zIndex-19 { + z-index: 19; } + +.zIndex-n19 { + z-index: 38; } + +.zIndex-20 { + z-index: 20; } + +.zIndex-n20 { + z-index: 40; } + +.zIndex-21 { + z-index: 21; } + +.zIndex-n21 { + z-index: 42; } + +.zIndex-22 { + z-index: 22; } + +.zIndex-n22 { + z-index: 44; } + +.zIndex-23 { + z-index: 23; } + +.zIndex-n23 { + z-index: 46; } + +.zIndex-24 { + z-index: 24; } + +.zIndex-n24 { + z-index: 48; } + +.zIndex-25 { + z-index: 25; } + +.zIndex-n25 { + z-index: 50; } + +.zIndex-26 { + z-index: 26; } + +.zIndex-n26 { + z-index: 52; } + +.text-overflow { + text-overflow: ellipsis; } + +.text-overflow-1 { + text-overflow: ellipsis; + lines: 1; } + +.text-overflow-2 { + text-overflow: ellipsis; + lines: 2; } + +.text-overflow-3 { + text-overflow: ellipsis; + lines: 3; } + +.text-overflow-4 { + text-overflow: ellipsis; + lines: 4; } + +.text-overflow-5 { + text-overflow: ellipsis; + lines: 5; } + +.text-size-xxs { + font-size: 10px; } + +.text-size-xs { + font-size: 11px; } + +.text-size-s { + font-size: 12px; } + +.text-size-m { + font-size: 14px; } + +.text-size-n { + font-size: 15px; } + +.text-size-g { + font-size: 17px; } + +.text-size-lg { + font-size: 18px; } + +.text-size-xl { + font-size: 20px; } + +.text-weight-s { + font-weight: 400; } + +.text-weight-n { + font-weight: 400; } + +.text-weight-b { + font-weight: 700; } + +.text-align-left { + text-align: left; } + +.text-align-right { + text-align: right; } + +.text-align-center { + text-align: center; } + +.round-tl-0 { + border-top-left-radius: 0px; } + +.round-tl-1 { + border-top-left-radius: 1px; } + +.round-tl-2 { + border-top-left-radius: 2px; } + +.round-tl-3 { + border-top-left-radius: 3px; } + +.round-tl-4 { + border-top-left-radius: 4px; } + +.round-tl-5 { + border-top-left-radius: 5px; } + +.round-tl-6 { + border-top-left-radius: 6px; } + +.round-tl-7 { + border-top-left-radius: 7px; } + +.round-tl-8 { + border-top-left-radius: 8px; } + +.round-tl-9 { + border-top-left-radius: 9px; } + +.round-tl-10 { + border-top-left-radius: 10px; } + +.round-tl-11 { + border-top-left-radius: 11px; } + +.round-tl-12 { + border-top-left-radius: 12px; } + +.round-tl-13 { + border-top-left-radius: 13px; } + +.round-tl-14 { + border-top-left-radius: 14px; } + +.round-tl-15 { + border-top-left-radius: 15px; } + +.round-tl-16 { + border-top-left-radius: 16px; } + +.round-tl-17 { + border-top-left-radius: 17px; } + +.round-tl-18 { + border-top-left-radius: 18px; } + +.round-tl-19 { + border-top-left-radius: 19px; } + +.round-tl-20 { + border-top-left-radius: 20px; } + +.round-tl-21 { + border-top-left-radius: 21px; } + +.round-tl-22 { + border-top-left-radius: 22px; } + +.round-tl-23 { + border-top-left-radius: 23px; } + +.round-tl-24 { + border-top-left-radius: 24px; } + +.round-tl-25 { + border-top-left-radius: 25px; } + +.round-tl-26 { + border-top-left-radius: 26px; } + +.round-tl-27 { + border-top-left-radius: 27px; } + +.round-tl-28 { + border-top-left-radius: 28px; } + +.round-tl-29 { + border-top-left-radius: 29px; } + +.round-tl-30 { + border-top-left-radius: 30px; } + +.round-tl-31 { + border-top-left-radius: 31px; } + +.round-tl-32 { + border-top-left-radius: 32px; } + +.round-tl-33 { + border-top-left-radius: 33px; } + +.round-tl-34 { + border-top-left-radius: 34px; } + +.round-tl-35 { + border-top-left-radius: 35px; } + +.round-tl-36 { + border-top-left-radius: 36px; } + +.round-tl-37 { + border-top-left-radius: 37px; } + +.round-tl-38 { + border-top-left-radius: 38px; } + +.round-tl-39 { + border-top-left-radius: 39px; } + +.round-tl-40 { + border-top-left-radius: 40px; } + +.round-tl-41 { + border-top-left-radius: 41px; } + +.round-tl-42 { + border-top-left-radius: 42px; } + +.round-tl-43 { + border-top-left-radius: 43px; } + +.round-tl-44 { + border-top-left-radius: 44px; } + +.round-tl-45 { + border-top-left-radius: 45px; } + +.round-tl-46 { + border-top-left-radius: 46px; } + +.round-tl-47 { + border-top-left-radius: 47px; } + +.round-tl-48 { + border-top-left-radius: 48px; } + +.round-tl-49 { + border-top-left-radius: 49px; } + +.round-tl-50 { + border-top-left-radius: 50px; } + +.round-tr-0 { + border-top-right-radius: 0px; } + +.round-tr-1 { + border-top-right-radius: 1px; } + +.round-tr-2 { + border-top-right-radius: 2px; } + +.round-tr-3 { + border-top-right-radius: 3px; } + +.round-tr-4 { + border-top-right-radius: 4px; } + +.round-tr-5 { + border-top-right-radius: 5px; } + +.round-tr-6 { + border-top-right-radius: 6px; } + +.round-tr-7 { + border-top-right-radius: 7px; } + +.round-tr-8 { + border-top-right-radius: 8px; } + +.round-tr-9 { + border-top-right-radius: 9px; } + +.round-tr-10 { + border-top-right-radius: 10px; } + +.round-tr-11 { + border-top-right-radius: 11px; } + +.round-tr-12 { + border-top-right-radius: 12px; } + +.round-tr-13 { + border-top-right-radius: 13px; } + +.round-tr-14 { + border-top-right-radius: 14px; } + +.round-tr-15 { + border-top-right-radius: 15px; } + +.round-tr-16 { + border-top-right-radius: 16px; } + +.round-tr-17 { + border-top-right-radius: 17px; } + +.round-tr-18 { + border-top-right-radius: 18px; } + +.round-tr-19 { + border-top-right-radius: 19px; } + +.round-tr-20 { + border-top-right-radius: 20px; } + +.round-tr-21 { + border-top-right-radius: 21px; } + +.round-tr-22 { + border-top-right-radius: 22px; } + +.round-tr-23 { + border-top-right-radius: 23px; } + +.round-tr-24 { + border-top-right-radius: 24px; } + +.round-tr-25 { + border-top-right-radius: 25px; } + +.round-tr-26 { + border-top-right-radius: 26px; } + +.round-tr-27 { + border-top-right-radius: 27px; } + +.round-tr-28 { + border-top-right-radius: 28px; } + +.round-tr-29 { + border-top-right-radius: 29px; } + +.round-tr-30 { + border-top-right-radius: 30px; } + +.round-tr-31 { + border-top-right-radius: 31px; } + +.round-tr-32 { + border-top-right-radius: 32px; } + +.round-tr-33 { + border-top-right-radius: 33px; } + +.round-tr-34 { + border-top-right-radius: 34px; } + +.round-tr-35 { + border-top-right-radius: 35px; } + +.round-tr-36 { + border-top-right-radius: 36px; } + +.round-tr-37 { + border-top-right-radius: 37px; } + +.round-tr-38 { + border-top-right-radius: 38px; } + +.round-tr-39 { + border-top-right-radius: 39px; } + +.round-tr-40 { + border-top-right-radius: 40px; } + +.round-tr-41 { + border-top-right-radius: 41px; } + +.round-tr-42 { + border-top-right-radius: 42px; } + +.round-tr-43 { + border-top-right-radius: 43px; } + +.round-tr-44 { + border-top-right-radius: 44px; } + +.round-tr-45 { + border-top-right-radius: 45px; } + +.round-tr-46 { + border-top-right-radius: 46px; } + +.round-tr-47 { + border-top-right-radius: 47px; } + +.round-tr-48 { + border-top-right-radius: 48px; } + +.round-tr-49 { + border-top-right-radius: 49px; } + +.round-tr-50 { + border-top-right-radius: 50px; } + +.round-bl-0 { + border-bottom-left-radius: 0px; } + +.round-bl-1 { + border-bottom-left-radius: 1px; } + +.round-bl-2 { + border-bottom-left-radius: 2px; } + +.round-bl-3 { + border-bottom-left-radius: 3px; } + +.round-bl-4 { + border-bottom-left-radius: 4px; } + +.round-bl-5 { + border-bottom-left-radius: 5px; } + +.round-bl-6 { + border-bottom-left-radius: 6px; } + +.round-bl-7 { + border-bottom-left-radius: 7px; } + +.round-bl-8 { + border-bottom-left-radius: 8px; } + +.round-bl-9 { + border-bottom-left-radius: 9px; } + +.round-bl-10 { + border-bottom-left-radius: 10px; } + +.round-bl-11 { + border-bottom-left-radius: 11px; } + +.round-bl-12 { + border-bottom-left-radius: 12px; } + +.round-bl-13 { + border-bottom-left-radius: 13px; } + +.round-bl-14 { + border-bottom-left-radius: 14px; } + +.round-bl-15 { + border-bottom-left-radius: 15px; } + +.round-bl-16 { + border-bottom-left-radius: 16px; } + +.round-bl-17 { + border-bottom-left-radius: 17px; } + +.round-bl-18 { + border-bottom-left-radius: 18px; } + +.round-bl-19 { + border-bottom-left-radius: 19px; } + +.round-bl-20 { + border-bottom-left-radius: 20px; } + +.round-bl-21 { + border-bottom-left-radius: 21px; } + +.round-bl-22 { + border-bottom-left-radius: 22px; } + +.round-bl-23 { + border-bottom-left-radius: 23px; } + +.round-bl-24 { + border-bottom-left-radius: 24px; } + +.round-bl-25 { + border-bottom-left-radius: 25px; } + +.round-bl-26 { + border-bottom-left-radius: 26px; } + +.round-bl-27 { + border-bottom-left-radius: 27px; } + +.round-bl-28 { + border-bottom-left-radius: 28px; } + +.round-bl-29 { + border-bottom-left-radius: 29px; } + +.round-bl-30 { + border-bottom-left-radius: 30px; } + +.round-bl-31 { + border-bottom-left-radius: 31px; } + +.round-bl-32 { + border-bottom-left-radius: 32px; } + +.round-bl-33 { + border-bottom-left-radius: 33px; } + +.round-bl-34 { + border-bottom-left-radius: 34px; } + +.round-bl-35 { + border-bottom-left-radius: 35px; } + +.round-bl-36 { + border-bottom-left-radius: 36px; } + +.round-bl-37 { + border-bottom-left-radius: 37px; } + +.round-bl-38 { + border-bottom-left-radius: 38px; } + +.round-bl-39 { + border-bottom-left-radius: 39px; } + +.round-bl-40 { + border-bottom-left-radius: 40px; } + +.round-bl-41 { + border-bottom-left-radius: 41px; } + +.round-bl-42 { + border-bottom-left-radius: 42px; } + +.round-bl-43 { + border-bottom-left-radius: 43px; } + +.round-bl-44 { + border-bottom-left-radius: 44px; } + +.round-bl-45 { + border-bottom-left-radius: 45px; } + +.round-bl-46 { + border-bottom-left-radius: 46px; } + +.round-bl-47 { + border-bottom-left-radius: 47px; } + +.round-bl-48 { + border-bottom-left-radius: 48px; } + +.round-bl-49 { + border-bottom-left-radius: 49px; } + +.round-bl-50 { + border-bottom-left-radius: 50px; } + +.round-br-0 { + border-bottom-right-radius: 0px; } + +.round-br-1 { + border-bottom-right-radius: 1px; } + +.round-br-2 { + border-bottom-right-radius: 2px; } + +.round-br-3 { + border-bottom-right-radius: 3px; } + +.round-br-4 { + border-bottom-right-radius: 4px; } + +.round-br-5 { + border-bottom-right-radius: 5px; } + +.round-br-6 { + border-bottom-right-radius: 6px; } + +.round-br-7 { + border-bottom-right-radius: 7px; } + +.round-br-8 { + border-bottom-right-radius: 8px; } + +.round-br-9 { + border-bottom-right-radius: 9px; } + +.round-br-10 { + border-bottom-right-radius: 10px; } + +.round-br-11 { + border-bottom-right-radius: 11px; } + +.round-br-12 { + border-bottom-right-radius: 12px; } + +.round-br-13 { + border-bottom-right-radius: 13px; } + +.round-br-14 { + border-bottom-right-radius: 14px; } + +.round-br-15 { + border-bottom-right-radius: 15px; } + +.round-br-16 { + border-bottom-right-radius: 16px; } + +.round-br-17 { + border-bottom-right-radius: 17px; } + +.round-br-18 { + border-bottom-right-radius: 18px; } + +.round-br-19 { + border-bottom-right-radius: 19px; } + +.round-br-20 { + border-bottom-right-radius: 20px; } + +.round-br-21 { + border-bottom-right-radius: 21px; } + +.round-br-22 { + border-bottom-right-radius: 22px; } + +.round-br-23 { + border-bottom-right-radius: 23px; } + +.round-br-24 { + border-bottom-right-radius: 24px; } + +.round-br-25 { + border-bottom-right-radius: 25px; } + +.round-br-26 { + border-bottom-right-radius: 26px; } + +.round-br-27 { + border-bottom-right-radius: 27px; } + +.round-br-28 { + border-bottom-right-radius: 28px; } + +.round-br-29 { + border-bottom-right-radius: 29px; } + +.round-br-30 { + border-bottom-right-radius: 30px; } + +.round-br-31 { + border-bottom-right-radius: 31px; } + +.round-br-32 { + border-bottom-right-radius: 32px; } + +.round-br-33 { + border-bottom-right-radius: 33px; } + +.round-br-34 { + border-bottom-right-radius: 34px; } + +.round-br-35 { + border-bottom-right-radius: 35px; } + +.round-br-36 { + border-bottom-right-radius: 36px; } + +.round-br-37 { + border-bottom-right-radius: 37px; } + +.round-br-38 { + border-bottom-right-radius: 38px; } + +.round-br-39 { + border-bottom-right-radius: 39px; } + +.round-br-40 { + border-bottom-right-radius: 40px; } + +.round-br-41 { + border-bottom-right-radius: 41px; } + +.round-br-42 { + border-bottom-right-radius: 42px; } + +.round-br-43 { + border-bottom-right-radius: 43px; } + +.round-br-44 { + border-bottom-right-radius: 44px; } + +.round-br-45 { + border-bottom-right-radius: 45px; } + +.round-br-46 { + border-bottom-right-radius: 46px; } + +.round-br-47 { + border-bottom-right-radius: 47px; } + +.round-br-48 { + border-bottom-right-radius: 48px; } + +.round-br-49 { + border-bottom-right-radius: 49px; } + +.round-br-50 { + border-bottom-right-radius: 50px; } + +.round-a-0 { + border-radius: 0px; } + +.round-a-1 { + border-radius: 1px; } + +.round-a-2 { + border-radius: 2px; } + +.round-a-3 { + border-radius: 3px; } + +.round-a-4 { + border-radius: 4px; } + +.round-a-5 { + border-radius: 5px; } + +.round-a-6 { + border-radius: 6px; } + +.round-a-7 { + border-radius: 7px; } + +.round-a-8 { + border-radius: 8px; } + +.round-a-9 { + border-radius: 9px; } + +.round-a-10 { + border-radius: 10px; } + +.round-a-11 { + border-radius: 11px; } + +.round-a-12 { + border-radius: 12px; } + +.round-a-13 { + border-radius: 13px; } + +.round-a-14 { + border-radius: 14px; } + +.round-a-15 { + border-radius: 15px; } + +.round-a-16 { + border-radius: 16px; } + +.round-a-17 { + border-radius: 17px; } + +.round-a-18 { + border-radius: 18px; } + +.round-a-19 { + border-radius: 19px; } + +.round-a-20 { + border-radius: 20px; } + +.round-a-21 { + border-radius: 21px; } + +.round-a-22 { + border-radius: 22px; } + +.round-a-23 { + border-radius: 23px; } + +.round-a-24 { + border-radius: 24px; } + +.round-a-25 { + border-radius: 25px; } + +.round-a-26 { + border-radius: 26px; } + +.round-a-27 { + border-radius: 27px; } + +.round-a-28 { + border-radius: 28px; } + +.round-a-29 { + border-radius: 29px; } + +.round-a-30 { + border-radius: 30px; } + +.round-a-31 { + border-radius: 31px; } + +.round-a-32 { + border-radius: 32px; } + +.round-a-33 { + border-radius: 33px; } + +.round-a-34 { + border-radius: 34px; } + +.round-a-35 { + border-radius: 35px; } + +.round-a-36 { + border-radius: 36px; } + +.round-a-37 { + border-radius: 37px; } + +.round-a-38 { + border-radius: 38px; } + +.round-a-39 { + border-radius: 39px; } + +.round-a-40 { + border-radius: 40px; } + +.round-a-41 { + border-radius: 41px; } + +.round-a-42 { + border-radius: 42px; } + +.round-a-43 { + border-radius: 43px; } + +.round-a-44 { + border-radius: 44px; } + +.round-a-45 { + border-radius: 45px; } + +.round-a-46 { + border-radius: 46px; } + +.round-a-47 { + border-radius: 47px; } + +.round-a-48 { + border-radius: 48px; } + +.round-a-49 { + border-radius: 49px; } + +.round-a-50 { + border-radius: 50px; } + +.round-t-0 { + border-top-left-radius: 0px; + border-top-right-radius: 0px; } + +.round-t-1 { + border-top-left-radius: 1px; + border-top-right-radius: 1px; } + +.round-t-2 { + border-top-left-radius: 2px; + border-top-right-radius: 2px; } + +.round-t-3 { + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + +.round-t-4 { + border-top-left-radius: 4px; + border-top-right-radius: 4px; } + +.round-t-5 { + border-top-left-radius: 5px; + border-top-right-radius: 5px; } + +.round-t-6 { + border-top-left-radius: 6px; + border-top-right-radius: 6px; } + +.round-t-7 { + border-top-left-radius: 7px; + border-top-right-radius: 7px; } + +.round-t-8 { + border-top-left-radius: 8px; + border-top-right-radius: 8px; } + +.round-t-9 { + border-top-left-radius: 9px; + border-top-right-radius: 9px; } + +.round-t-10 { + border-top-left-radius: 10px; + border-top-right-radius: 10px; } + +.round-t-11 { + border-top-left-radius: 11px; + border-top-right-radius: 11px; } + +.round-t-12 { + border-top-left-radius: 12px; + border-top-right-radius: 12px; } + +.round-t-13 { + border-top-left-radius: 13px; + border-top-right-radius: 13px; } + +.round-t-14 { + border-top-left-radius: 14px; + border-top-right-radius: 14px; } + +.round-t-15 { + border-top-left-radius: 15px; + border-top-right-radius: 15px; } + +.round-t-16 { + border-top-left-radius: 16px; + border-top-right-radius: 16px; } + +.round-t-17 { + border-top-left-radius: 17px; + border-top-right-radius: 17px; } + +.round-t-18 { + border-top-left-radius: 18px; + border-top-right-radius: 18px; } + +.round-t-19 { + border-top-left-radius: 19px; + border-top-right-radius: 19px; } + +.round-t-20 { + border-top-left-radius: 20px; + border-top-right-radius: 20px; } + +.round-t-21 { + border-top-left-radius: 21px; + border-top-right-radius: 21px; } + +.round-t-22 { + border-top-left-radius: 22px; + border-top-right-radius: 22px; } + +.round-t-23 { + border-top-left-radius: 23px; + border-top-right-radius: 23px; } + +.round-t-24 { + border-top-left-radius: 24px; + border-top-right-radius: 24px; } + +.round-t-25 { + border-top-left-radius: 25px; + border-top-right-radius: 25px; } + +.round-t-26 { + border-top-left-radius: 26px; + border-top-right-radius: 26px; } + +.round-t-27 { + border-top-left-radius: 27px; + border-top-right-radius: 27px; } + +.round-t-28 { + border-top-left-radius: 28px; + border-top-right-radius: 28px; } + +.round-t-29 { + border-top-left-radius: 29px; + border-top-right-radius: 29px; } + +.round-t-30 { + border-top-left-radius: 30px; + border-top-right-radius: 30px; } + +.round-t-31 { + border-top-left-radius: 31px; + border-top-right-radius: 31px; } + +.round-t-32 { + border-top-left-radius: 32px; + border-top-right-radius: 32px; } + +.round-t-33 { + border-top-left-radius: 33px; + border-top-right-radius: 33px; } + +.round-t-34 { + border-top-left-radius: 34px; + border-top-right-radius: 34px; } + +.round-t-35 { + border-top-left-radius: 35px; + border-top-right-radius: 35px; } + +.round-t-36 { + border-top-left-radius: 36px; + border-top-right-radius: 36px; } + +.round-t-37 { + border-top-left-radius: 37px; + border-top-right-radius: 37px; } + +.round-t-38 { + border-top-left-radius: 38px; + border-top-right-radius: 38px; } + +.round-t-39 { + border-top-left-radius: 39px; + border-top-right-radius: 39px; } + +.round-t-40 { + border-top-left-radius: 40px; + border-top-right-radius: 40px; } + +.round-t-41 { + border-top-left-radius: 41px; + border-top-right-radius: 41px; } + +.round-t-42 { + border-top-left-radius: 42px; + border-top-right-radius: 42px; } + +.round-t-43 { + border-top-left-radius: 43px; + border-top-right-radius: 43px; } + +.round-t-44 { + border-top-left-radius: 44px; + border-top-right-radius: 44px; } + +.round-t-45 { + border-top-left-radius: 45px; + border-top-right-radius: 45px; } + +.round-t-46 { + border-top-left-radius: 46px; + border-top-right-radius: 46px; } + +.round-t-47 { + border-top-left-radius: 47px; + border-top-right-radius: 47px; } + +.round-t-48 { + border-top-left-radius: 48px; + border-top-right-radius: 48px; } + +.round-t-49 { + border-top-left-radius: 49px; + border-top-right-radius: 49px; } + +.round-t-50 { + border-top-left-radius: 50px; + border-top-right-radius: 50px; } + +.round-b-0 { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; } + +.round-b-1 { + border-bottom-left-radius: 1px; + border-bottom-right-radius: 1px; } + +.round-b-2 { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; } + +.round-b-3 { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; } + +.round-b-4 { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; } + +.round-b-5 { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; } + +.round-b-6 { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; } + +.round-b-7 { + border-bottom-left-radius: 7px; + border-bottom-right-radius: 7px; } + +.round-b-8 { + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; } + +.round-b-9 { + border-bottom-left-radius: 9px; + border-bottom-right-radius: 9px; } + +.round-b-10 { + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; } + +.round-b-11 { + border-bottom-left-radius: 11px; + border-bottom-right-radius: 11px; } + +.round-b-12 { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; } + +.round-b-13 { + border-bottom-left-radius: 13px; + border-bottom-right-radius: 13px; } + +.round-b-14 { + border-bottom-left-radius: 14px; + border-bottom-right-radius: 14px; } + +.round-b-15 { + border-bottom-left-radius: 15px; + border-bottom-right-radius: 15px; } + +.round-b-16 { + border-bottom-left-radius: 16px; + border-bottom-right-radius: 16px; } + +.round-b-17 { + border-bottom-left-radius: 17px; + border-bottom-right-radius: 17px; } + +.round-b-18 { + border-bottom-left-radius: 18px; + border-bottom-right-radius: 18px; } + +.round-b-19 { + border-bottom-left-radius: 19px; + border-bottom-right-radius: 19px; } + +.round-b-20 { + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; } + +.round-b-21 { + border-bottom-left-radius: 21px; + border-bottom-right-radius: 21px; } + +.round-b-22 { + border-bottom-left-radius: 22px; + border-bottom-right-radius: 22px; } + +.round-b-23 { + border-bottom-left-radius: 23px; + border-bottom-right-radius: 23px; } + +.round-b-24 { + border-bottom-left-radius: 24px; + border-bottom-right-radius: 24px; } + +.round-b-25 { + border-bottom-left-radius: 25px; + border-bottom-right-radius: 25px; } + +.round-b-26 { + border-bottom-left-radius: 26px; + border-bottom-right-radius: 26px; } + +.round-b-27 { + border-bottom-left-radius: 27px; + border-bottom-right-radius: 27px; } + +.round-b-28 { + border-bottom-left-radius: 28px; + border-bottom-right-radius: 28px; } + +.round-b-29 { + border-bottom-left-radius: 29px; + border-bottom-right-radius: 29px; } + +.round-b-30 { + border-bottom-left-radius: 30px; + border-bottom-right-radius: 30px; } + +.round-b-31 { + border-bottom-left-radius: 31px; + border-bottom-right-radius: 31px; } + +.round-b-32 { + border-bottom-left-radius: 32px; + border-bottom-right-radius: 32px; } + +.round-b-33 { + border-bottom-left-radius: 33px; + border-bottom-right-radius: 33px; } + +.round-b-34 { + border-bottom-left-radius: 34px; + border-bottom-right-radius: 34px; } + +.round-b-35 { + border-bottom-left-radius: 35px; + border-bottom-right-radius: 35px; } + +.round-b-36 { + border-bottom-left-radius: 36px; + border-bottom-right-radius: 36px; } + +.round-b-37 { + border-bottom-left-radius: 37px; + border-bottom-right-radius: 37px; } + +.round-b-38 { + border-bottom-left-radius: 38px; + border-bottom-right-radius: 38px; } + +.round-b-39 { + border-bottom-left-radius: 39px; + border-bottom-right-radius: 39px; } + +.round-b-40 { + border-bottom-left-radius: 40px; + border-bottom-right-radius: 40px; } + +.round-b-41 { + border-bottom-left-radius: 41px; + border-bottom-right-radius: 41px; } + +.round-b-42 { + border-bottom-left-radius: 42px; + border-bottom-right-radius: 42px; } + +.round-b-43 { + border-bottom-left-radius: 43px; + border-bottom-right-radius: 43px; } + +.round-b-44 { + border-bottom-left-radius: 44px; + border-bottom-right-radius: 44px; } + +.round-b-45 { + border-bottom-left-radius: 45px; + border-bottom-right-radius: 45px; } + +.round-b-46 { + border-bottom-left-radius: 46px; + border-bottom-right-radius: 46px; } + +.round-b-47 { + border-bottom-left-radius: 47px; + border-bottom-right-radius: 47px; } + +.round-b-48 { + border-bottom-left-radius: 48px; + border-bottom-right-radius: 48px; } + +.round-b-49 { + border-bottom-left-radius: 49px; + border-bottom-right-radius: 49px; } + +.round-b-50 { + border-bottom-left-radius: 50px; + border-bottom-right-radius: 50px; } + +.round-l-0 { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; } + +.round-l-1 { + border-top-left-radius: 1px; + border-bottom-left-radius: 1px; } + +.round-l-2 { + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; } + +.round-l-3 { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } + +.round-l-4 { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; } + +.round-l-5 { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; } + +.round-l-6 { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; } + +.round-l-7 { + border-top-left-radius: 7px; + border-bottom-left-radius: 7px; } + +.round-l-8 { + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; } + +.round-l-9 { + border-top-left-radius: 9px; + border-bottom-left-radius: 9px; } + +.round-l-10 { + border-top-left-radius: 10px; + border-bottom-left-radius: 10px; } + +.round-l-11 { + border-top-left-radius: 11px; + border-bottom-left-radius: 11px; } + +.round-l-12 { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; } + +.round-l-13 { + border-top-left-radius: 13px; + border-bottom-left-radius: 13px; } + +.round-l-14 { + border-top-left-radius: 14px; + border-bottom-left-radius: 14px; } + +.round-l-15 { + border-top-left-radius: 15px; + border-bottom-left-radius: 15px; } + +.round-l-16 { + border-top-left-radius: 16px; + border-bottom-left-radius: 16px; } + +.round-l-17 { + border-top-left-radius: 17px; + border-bottom-left-radius: 17px; } + +.round-l-18 { + border-top-left-radius: 18px; + border-bottom-left-radius: 18px; } + +.round-l-19 { + border-top-left-radius: 19px; + border-bottom-left-radius: 19px; } + +.round-l-20 { + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; } + +.round-l-21 { + border-top-left-radius: 21px; + border-bottom-left-radius: 21px; } + +.round-l-22 { + border-top-left-radius: 22px; + border-bottom-left-radius: 22px; } + +.round-l-23 { + border-top-left-radius: 23px; + border-bottom-left-radius: 23px; } + +.round-l-24 { + border-top-left-radius: 24px; + border-bottom-left-radius: 24px; } + +.round-l-25 { + border-top-left-radius: 25px; + border-bottom-left-radius: 25px; } + +.round-l-26 { + border-top-left-radius: 26px; + border-bottom-left-radius: 26px; } + +.round-l-27 { + border-top-left-radius: 27px; + border-bottom-left-radius: 27px; } + +.round-l-28 { + border-top-left-radius: 28px; + border-bottom-left-radius: 28px; } + +.round-l-29 { + border-top-left-radius: 29px; + border-bottom-left-radius: 29px; } + +.round-l-30 { + border-top-left-radius: 30px; + border-bottom-left-radius: 30px; } + +.round-l-31 { + border-top-left-radius: 31px; + border-bottom-left-radius: 31px; } + +.round-l-32 { + border-top-left-radius: 32px; + border-bottom-left-radius: 32px; } + +.round-l-33 { + border-top-left-radius: 33px; + border-bottom-left-radius: 33px; } + +.round-l-34 { + border-top-left-radius: 34px; + border-bottom-left-radius: 34px; } + +.round-l-35 { + border-top-left-radius: 35px; + border-bottom-left-radius: 35px; } + +.round-l-36 { + border-top-left-radius: 36px; + border-bottom-left-radius: 36px; } + +.round-l-37 { + border-top-left-radius: 37px; + border-bottom-left-radius: 37px; } + +.round-l-38 { + border-top-left-radius: 38px; + border-bottom-left-radius: 38px; } + +.round-l-39 { + border-top-left-radius: 39px; + border-bottom-left-radius: 39px; } + +.round-l-40 { + border-top-left-radius: 40px; + border-bottom-left-radius: 40px; } + +.round-l-41 { + border-top-left-radius: 41px; + border-bottom-left-radius: 41px; } + +.round-l-42 { + border-top-left-radius: 42px; + border-bottom-left-radius: 42px; } + +.round-l-43 { + border-top-left-radius: 43px; + border-bottom-left-radius: 43px; } + +.round-l-44 { + border-top-left-radius: 44px; + border-bottom-left-radius: 44px; } + +.round-l-45 { + border-top-left-radius: 45px; + border-bottom-left-radius: 45px; } + +.round-l-46 { + border-top-left-radius: 46px; + border-bottom-left-radius: 46px; } + +.round-l-47 { + border-top-left-radius: 47px; + border-bottom-left-radius: 47px; } + +.round-l-48 { + border-top-left-radius: 48px; + border-bottom-left-radius: 48px; } + +.round-l-49 { + border-top-left-radius: 49px; + border-bottom-left-radius: 49px; } + +.round-l-50 { + border-top-left-radius: 50px; + border-bottom-left-radius: 50px; } + +.round-r-0 { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; } + +.round-r-1 { + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; } + +.round-r-2 { + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; } + +.round-r-3 { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } + +.round-r-4 { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; } + +.round-r-5 { + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; } + +.round-r-6 { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; } + +.round-r-7 { + border-top-right-radius: 7px; + border-bottom-right-radius: 7px; } + +.round-r-8 { + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; } + +.round-r-9 { + border-top-right-radius: 9px; + border-bottom-right-radius: 9px; } + +.round-r-10 { + border-top-right-radius: 10px; + border-bottom-right-radius: 10px; } + +.round-r-11 { + border-top-right-radius: 11px; + border-bottom-right-radius: 11px; } + +.round-r-12 { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; } + +.round-r-13 { + border-top-right-radius: 13px; + border-bottom-right-radius: 13px; } + +.round-r-14 { + border-top-right-radius: 14px; + border-bottom-right-radius: 14px; } + +.round-r-15 { + border-top-right-radius: 15px; + border-bottom-right-radius: 15px; } + +.round-r-16 { + border-top-right-radius: 16px; + border-bottom-right-radius: 16px; } + +.round-r-17 { + border-top-right-radius: 17px; + border-bottom-right-radius: 17px; } + +.round-r-18 { + border-top-right-radius: 18px; + border-bottom-right-radius: 18px; } + +.round-r-19 { + border-top-right-radius: 19px; + border-bottom-right-radius: 19px; } + +.round-r-20 { + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; } + +.round-r-21 { + border-top-right-radius: 21px; + border-bottom-right-radius: 21px; } + +.round-r-22 { + border-top-right-radius: 22px; + border-bottom-right-radius: 22px; } + +.round-r-23 { + border-top-right-radius: 23px; + border-bottom-right-radius: 23px; } + +.round-r-24 { + border-top-right-radius: 24px; + border-bottom-right-radius: 24px; } + +.round-r-25 { + border-top-right-radius: 25px; + border-bottom-right-radius: 25px; } + +.round-r-26 { + border-top-right-radius: 26px; + border-bottom-right-radius: 26px; } + +.round-r-27 { + border-top-right-radius: 27px; + border-bottom-right-radius: 27px; } + +.round-r-28 { + border-top-right-radius: 28px; + border-bottom-right-radius: 28px; } + +.round-r-29 { + border-top-right-radius: 29px; + border-bottom-right-radius: 29px; } + +.round-r-30 { + border-top-right-radius: 30px; + border-bottom-right-radius: 30px; } + +.round-r-31 { + border-top-right-radius: 31px; + border-bottom-right-radius: 31px; } + +.round-r-32 { + border-top-right-radius: 32px; + border-bottom-right-radius: 32px; } + +.round-r-33 { + border-top-right-radius: 33px; + border-bottom-right-radius: 33px; } + +.round-r-34 { + border-top-right-radius: 34px; + border-bottom-right-radius: 34px; } + +.round-r-35 { + border-top-right-radius: 35px; + border-bottom-right-radius: 35px; } + +.round-r-36 { + border-top-right-radius: 36px; + border-bottom-right-radius: 36px; } + +.round-r-37 { + border-top-right-radius: 37px; + border-bottom-right-radius: 37px; } + +.round-r-38 { + border-top-right-radius: 38px; + border-bottom-right-radius: 38px; } + +.round-r-39 { + border-top-right-radius: 39px; + border-bottom-right-radius: 39px; } + +.round-r-40 { + border-top-right-radius: 40px; + border-bottom-right-radius: 40px; } + +.round-r-41 { + border-top-right-radius: 41px; + border-bottom-right-radius: 41px; } + +.round-r-42 { + border-top-right-radius: 42px; + border-bottom-right-radius: 42px; } + +.round-r-43 { + border-top-right-radius: 43px; + border-bottom-right-radius: 43px; } + +.round-r-44 { + border-top-right-radius: 44px; + border-bottom-right-radius: 44px; } + +.round-r-45 { + border-top-right-radius: 45px; + border-bottom-right-radius: 45px; } + +.round-r-46 { + border-top-right-radius: 46px; + border-bottom-right-radius: 46px; } + +.round-r-47 { + border-top-right-radius: 47px; + border-bottom-right-radius: 47px; } + +.round-r-48 { + border-top-right-radius: 48px; + border-bottom-right-radius: 48px; } + +.round-r-49 { + border-top-right-radius: 49px; + border-bottom-right-radius: 49px; } + +.round-r-50 { + border-top-right-radius: 50px; + border-bottom-right-radius: 50px; } + +.round-0 { + border-radius: 0px; } + +.round-1 { + border-radius: 1px; } + +.round-2 { + border-radius: 2px; } + +.round-3 { + border-radius: 3px; } + +.round-4 { + border-radius: 4px; } + +.round-5 { + border-radius: 5px; } + +.round-6 { + border-radius: 6px; } + +.round-7 { + border-radius: 7px; } + +.round-8 { + border-radius: 8px; } + +.round-9 { + border-radius: 9px; } + +.round-10 { + border-radius: 10px; } + +.round-11 { + border-radius: 11px; } + +.round-12 { + border-radius: 12px; } + +.round-13 { + border-radius: 13px; } + +.round-14 { + border-radius: 14px; } + +.round-15 { + border-radius: 15px; } + +.round-16 { + border-radius: 16px; } + +.round-17 { + border-radius: 17px; } + +.round-18 { + border-radius: 18px; } + +.round-19 { + border-radius: 19px; } + +.round-20 { + border-radius: 20px; } + +.round-21 { + border-radius: 21px; } + +.round-22 { + border-radius: 22px; } + +.round-23 { + border-radius: 23px; } + +.round-24 { + border-radius: 24px; } + +.round-25 { + border-radius: 25px; } + +.round-26 { + border-radius: 26px; } + +/** 0-20表示的是1.0~3.0之间的行高 */ +.line-0 { + line-height: 1; } + +.line-1 { + line-height: 1.1; } + +.line-2 { + line-height: 1.2; } + +.line-3 { + line-height: 1.3; } + +.line-4 { + line-height: 1.4; } + +.line-5 { + line-height: 1.5; } + +.line-6 { + line-height: 1.6; } + +.line-7 { + line-height: 1.7; } + +.line-8 { + line-height: 1.8; } + +.line-9 { + line-height: 1.9; } + +.line-10 { + line-height: 2; } + +.line-11 { + line-height: 2.1; } + +.line-12 { + line-height: 2.2; } + +.line-13 { + line-height: 2.3; } + +.line-14 { + line-height: 2.4; } + +.line-15 { + line-height: 2.5; } + +.line-16 { + line-height: 2.6; } + +.line-17 { + line-height: 2.7; } + +.line-18 { + line-height: 2.8; } + +.line-19 { + line-height: 2.9; } + +.line-20 { + line-height: 3; } + +.line-21 { + line-height: 3.1; } + +.opacity-0 { + opacity: 0; } + +.opacity-1 { + opacity: 0.1; } + +.opacity-2 { + opacity: 0.2; } + +.opacity-3 { + opacity: 0.3; } + +.opacity-4 { + opacity: 0.4; } + +.opacity-5 { + opacity: 0.5; } + +.opacity-6 { + opacity: 0.6; } + +.opacity-7 { + opacity: 0.7; } + +.opacity-8 { + opacity: 0.8; } + +.opacity-9 { + opacity: 0.9; } + +.opacity-10 { + opacity: 1; } + +.border-0 { + border: 0px solid #f5f5f5; } + +.border { + border: 1px solid #f5f5f5; } + +.border-1 { + border: 1px solid #f5f5f5; } + +.border-1-bk { + border: 1px solid #f5f5f5; } + +.border-2 { + border: 2px solid #f5f5f5; } + +.border-2-bk { + border: 2px solid #f5f5f5; } + +.border-3 { + border: 3px solid #f5f5f5; } + +.border-3-bk { + border: 3px solid #f5f5f5; } + +.border-4 { + border: 4px solid #f5f5f5; } + +.border-4-bk { + border: 4px solid #f5f5f5; } + +.border-5 { + border: 5px solid #f5f5f5; } + +.border-5-bk { + border: 5px solid #f5f5f5; } + +.border-l-1 { + border-left: 1px solid whitesmoke; } + +.border-l-2 { + border-left: 2px solid whitesmoke; } + +.border-l-3 { + border-left: 3px solid whitesmoke; } + +.border-l-4 { + border-left: 4px solid whitesmoke; } + +.border-l-5 { + border-left: 5px solid whitesmoke; } + +.border-r-1 { + border-right: 1px solid whitesmoke; } + +.border-r-2 { + border-right: 2px solid whitesmoke; } + +.border-r-3 { + border-right: 3px solid whitesmoke; } + +.border-r-4 { + border-right: 4px solid whitesmoke; } + +.border-r-5 { + border-right: 5px solid whitesmoke; } + +.border-t-1 { + border-top: 1px solid whitesmoke; } + +.border-t-2 { + border-top: 2px solid whitesmoke; } + +.border-t-3 { + border-top: 3px solid whitesmoke; } + +.border-t-4 { + border-top: 4px solid whitesmoke; } + +.border-t-5 { + border-top: 5px solid whitesmoke; } + +.border-b-1 { + border-bottom: 1px solid whitesmoke; } + +.border-b-2 { + border-bottom: 2px solid whitesmoke; } + +.border-b-3 { + border-bottom: 3px solid whitesmoke; } + +.border-b-4 { + border-bottom: 4px solid whitesmoke; } + +.border-b-5 { + border-bottom: 5px solid whitesmoke; } + +.border-a-1 { + border: 1px solid whitesmoke; } + +.border-a-2 { + border: 2px solid whitesmoke; } + +.border-a-3 { + border: 3px solid whitesmoke; } + +.border-a-4 { + border: 4px solid whitesmoke; } + +.border-a-5 { + border: 5px solid whitesmoke; } + +.pa-0 { + padding: 0px; } + +.pa-1 { + padding: 1px; } + +.pa-2 { + padding: 2px; } + +.pa-3 { + padding: 3px; } + +.pa-4 { + padding: 4px; } + +.pa-5 { + padding: 5px; } + +.pa-6 { + padding: 6px; } + +.pa-7 { + padding: 7px; } + +.pa-8 { + padding: 8px; } + +.pa-9 { + padding: 9px; } + +.pa-10 { + padding: 10px; } + +.pa-11 { + padding: 11px; } + +.pa-12 { + padding: 12px; } + +.pa-13 { + padding: 13px; } + +.pa-14 { + padding: 14px; } + +.pa-15 { + padding: 15px; } + +.pa-16 { + padding: 16px; } + +.pa-17 { + padding: 17px; } + +.pa-18 { + padding: 18px; } + +.pa-19 { + padding: 19px; } + +.pa-20 { + padding: 20px; } + +.pa-21 { + padding: 21px; } + +.pa-22 { + padding: 22px; } + +.pa-23 { + padding: 23px; } + +.pa-24 { + padding: 24px; } + +.pa-25 { + padding: 25px; } + +.pa-26 { + padding: 26px; } + +.pa-27 { + padding: 27px; } + +.pa-28 { + padding: 28px; } + +.pa-29 { + padding: 29px; } + +.pa-30 { + padding: 30px; } + +.pa-31 { + padding: 31px; } + +.pa-32 { + padding: 32px; } + +.pa-33 { + padding: 33px; } + +.pa-34 { + padding: 34px; } + +.pa-35 { + padding: 35px; } + +.pa-36 { + padding: 36px; } + +.pa-37 { + padding: 37px; } + +.pa-38 { + padding: 38px; } + +.pa-39 { + padding: 39px; } + +.pa-40 { + padding: 40px; } + +.pa-41 { + padding: 41px; } + +.pa-42 { + padding: 42px; } + +.pa-43 { + padding: 43px; } + +.pa-44 { + padding: 44px; } + +.pa-45 { + padding: 45px; } + +.pa-46 { + padding: 46px; } + +.pa-47 { + padding: 47px; } + +.pa-48 { + padding: 48px; } + +.pa-49 { + padding: 49px; } + +.pa-50 { + padding: 50px; } + +.pa-n1 { + padding: 2px; } + +.pa-n2 { + padding: 4px; } + +.pa-n3 { + padding: 6px; } + +.pa-n4 { + padding: 8px; } + +.pa-n5 { + padding: 10px; } + +.pa-n6 { + padding: 12px; } + +.pa-n7 { + padding: 14px; } + +.pa-n8 { + padding: 16px; } + +.pa-n9 { + padding: 18px; } + +.pa-n10 { + padding: 20px; } + +.pa-n11 { + padding: 22px; } + +.pa-n12 { + padding: 24px; } + +.pa-n13 { + padding: 26px; } + +.pa-n14 { + padding: 28px; } + +.pa-n15 { + padding: 30px; } + +.pa-n16 { + padding: 32px; } + +.pa-n17 { + padding: 34px; } + +.pa-n18 { + padding: 36px; } + +.pa-n19 { + padding: 38px; } + +.pa-n20 { + padding: 40px; } + +.pa-n21 { + padding: 42px; } + +.pa-n22 { + padding: 44px; } + +.pa-n23 { + padding: 46px; } + +.pa-n24 { + padding: 48px; } + +.pa-n25 { + padding: 50px; } + +.pt-0 { + padding-top: 0px; } + +.pt-1 { + padding-top: 1px; } + +.pt-2 { + padding-top: 2px; } + +.pt-3 { + padding-top: 3px; } + +.pt-4 { + padding-top: 4px; } + +.pt-5 { + padding-top: 5px; } + +.pt-6 { + padding-top: 6px; } + +.pt-7 { + padding-top: 7px; } + +.pt-8 { + padding-top: 8px; } + +.pt-9 { + padding-top: 9px; } + +.pt-10 { + padding-top: 10px; } + +.pt-11 { + padding-top: 11px; } + +.pt-12 { + padding-top: 12px; } + +.pt-13 { + padding-top: 13px; } + +.pt-14 { + padding-top: 14px; } + +.pt-15 { + padding-top: 15px; } + +.pt-16 { + padding-top: 16px; } + +.pt-17 { + padding-top: 17px; } + +.pt-18 { + padding-top: 18px; } + +.pt-19 { + padding-top: 19px; } + +.pt-20 { + padding-top: 20px; } + +.pt-21 { + padding-top: 21px; } + +.pt-22 { + padding-top: 22px; } + +.pt-23 { + padding-top: 23px; } + +.pt-24 { + padding-top: 24px; } + +.pt-25 { + padding-top: 25px; } + +.pt-26 { + padding-top: 26px; } + +.pt-27 { + padding-top: 27px; } + +.pt-28 { + padding-top: 28px; } + +.pt-29 { + padding-top: 29px; } + +.pt-30 { + padding-top: 30px; } + +.pt-31 { + padding-top: 31px; } + +.pt-32 { + padding-top: 32px; } + +.pt-33 { + padding-top: 33px; } + +.pt-34 { + padding-top: 34px; } + +.pt-35 { + padding-top: 35px; } + +.pt-36 { + padding-top: 36px; } + +.pt-37 { + padding-top: 37px; } + +.pt-38 { + padding-top: 38px; } + +.pt-39 { + padding-top: 39px; } + +.pt-40 { + padding-top: 40px; } + +.pt-41 { + padding-top: 41px; } + +.pt-42 { + padding-top: 42px; } + +.pt-43 { + padding-top: 43px; } + +.pt-44 { + padding-top: 44px; } + +.pt-45 { + padding-top: 45px; } + +.pt-46 { + padding-top: 46px; } + +.pt-47 { + padding-top: 47px; } + +.pt-48 { + padding-top: 48px; } + +.pt-49 { + padding-top: 49px; } + +.pt-50 { + padding-top: 50px; } + +.pt-n1 { + padding-top: 2px; } + +.pt-n2 { + padding-top: 4px; } + +.pt-n3 { + padding-top: 6px; } + +.pt-n4 { + padding-top: 8px; } + +.pt-n5 { + padding-top: 10px; } + +.pt-n6 { + padding-top: 12px; } + +.pt-n7 { + padding-top: 14px; } + +.pt-n8 { + padding-top: 16px; } + +.pt-n9 { + padding-top: 18px; } + +.pt-n10 { + padding-top: 20px; } + +.pt-n11 { + padding-top: 22px; } + +.pt-n12 { + padding-top: 24px; } + +.pt-n13 { + padding-top: 26px; } + +.pt-n14 { + padding-top: 28px; } + +.pt-n15 { + padding-top: 30px; } + +.pt-n16 { + padding-top: 32px; } + +.pt-n17 { + padding-top: 34px; } + +.pt-n18 { + padding-top: 36px; } + +.pt-n19 { + padding-top: 38px; } + +.pt-n20 { + padding-top: 40px; } + +.pt-n21 { + padding-top: 42px; } + +.pt-n22 { + padding-top: 44px; } + +.pt-n23 { + padding-top: 46px; } + +.pt-n24 { + padding-top: 48px; } + +.pt-n25 { + padding-top: 50px; } + +.pr-0 { + padding-right: 0px; } + +.pr-1 { + padding-right: 1px; } + +.pr-2 { + padding-right: 2px; } + +.pr-3 { + padding-right: 3px; } + +.pr-4 { + padding-right: 4px; } + +.pr-5 { + padding-right: 5px; } + +.pr-6 { + padding-right: 6px; } + +.pr-7 { + padding-right: 7px; } + +.pr-8 { + padding-right: 8px; } + +.pr-9 { + padding-right: 9px; } + +.pr-10 { + padding-right: 10px; } + +.pr-11 { + padding-right: 11px; } + +.pr-12 { + padding-right: 12px; } + +.pr-13 { + padding-right: 13px; } + +.pr-14 { + padding-right: 14px; } + +.pr-15 { + padding-right: 15px; } + +.pr-16 { + padding-right: 16px; } + +.pr-17 { + padding-right: 17px; } + +.pr-18 { + padding-right: 18px; } + +.pr-19 { + padding-right: 19px; } + +.pr-20 { + padding-right: 20px; } + +.pr-21 { + padding-right: 21px; } + +.pr-22 { + padding-right: 22px; } + +.pr-23 { + padding-right: 23px; } + +.pr-24 { + padding-right: 24px; } + +.pr-25 { + padding-right: 25px; } + +.pr-26 { + padding-right: 26px; } + +.pr-27 { + padding-right: 27px; } + +.pr-28 { + padding-right: 28px; } + +.pr-29 { + padding-right: 29px; } + +.pr-30 { + padding-right: 30px; } + +.pr-31 { + padding-right: 31px; } + +.pr-32 { + padding-right: 32px; } + +.pr-33 { + padding-right: 33px; } + +.pr-34 { + padding-right: 34px; } + +.pr-35 { + padding-right: 35px; } + +.pr-36 { + padding-right: 36px; } + +.pr-37 { + padding-right: 37px; } + +.pr-38 { + padding-right: 38px; } + +.pr-39 { + padding-right: 39px; } + +.pr-40 { + padding-right: 40px; } + +.pr-41 { + padding-right: 41px; } + +.pr-42 { + padding-right: 42px; } + +.pr-43 { + padding-right: 43px; } + +.pr-44 { + padding-right: 44px; } + +.pr-45 { + padding-right: 45px; } + +.pr-46 { + padding-right: 46px; } + +.pr-47 { + padding-right: 47px; } + +.pr-48 { + padding-right: 48px; } + +.pr-49 { + padding-right: 49px; } + +.pr-50 { + padding-right: 50px; } + +.pr-n1 { + padding-right: 2px; } + +.pr-n2 { + padding-right: 4px; } + +.pr-n3 { + padding-right: 6px; } + +.pr-n4 { + padding-right: 8px; } + +.pr-n5 { + padding-right: 10px; } + +.pr-n6 { + padding-right: 12px; } + +.pr-n7 { + padding-right: 14px; } + +.pr-n8 { + padding-right: 16px; } + +.pr-n9 { + padding-right: 18px; } + +.pr-n10 { + padding-right: 20px; } + +.pr-n11 { + padding-right: 22px; } + +.pr-n12 { + padding-right: 24px; } + +.pr-n13 { + padding-right: 26px; } + +.pr-n14 { + padding-right: 28px; } + +.pr-n15 { + padding-right: 30px; } + +.pr-n16 { + padding-right: 32px; } + +.pr-n17 { + padding-right: 34px; } + +.pr-n18 { + padding-right: 36px; } + +.pr-n19 { + padding-right: 38px; } + +.pr-n20 { + padding-right: 40px; } + +.pr-n21 { + padding-right: 42px; } + +.pr-n22 { + padding-right: 44px; } + +.pr-n23 { + padding-right: 46px; } + +.pr-n24 { + padding-right: 48px; } + +.pr-n25 { + padding-right: 50px; } + +.pb-0 { + padding-bottom: 0px; } + +.pb-1 { + padding-bottom: 1px; } + +.pb-2 { + padding-bottom: 2px; } + +.pb-3 { + padding-bottom: 3px; } + +.pb-4 { + padding-bottom: 4px; } + +.pb-5 { + padding-bottom: 5px; } + +.pb-6 { + padding-bottom: 6px; } + +.pb-7 { + padding-bottom: 7px; } + +.pb-8 { + padding-bottom: 8px; } + +.pb-9 { + padding-bottom: 9px; } + +.pb-10 { + padding-bottom: 10px; } + +.pb-11 { + padding-bottom: 11px; } + +.pb-12 { + padding-bottom: 12px; } + +.pb-13 { + padding-bottom: 13px; } + +.pb-14 { + padding-bottom: 14px; } + +.pb-15 { + padding-bottom: 15px; } + +.pb-16 { + padding-bottom: 16px; } + +.pb-17 { + padding-bottom: 17px; } + +.pb-18 { + padding-bottom: 18px; } + +.pb-19 { + padding-bottom: 19px; } + +.pb-20 { + padding-bottom: 20px; } + +.pb-21 { + padding-bottom: 21px; } + +.pb-22 { + padding-bottom: 22px; } + +.pb-23 { + padding-bottom: 23px; } + +.pb-24 { + padding-bottom: 24px; } + +.pb-25 { + padding-bottom: 25px; } + +.pb-26 { + padding-bottom: 26px; } + +.pb-27 { + padding-bottom: 27px; } + +.pb-28 { + padding-bottom: 28px; } + +.pb-29 { + padding-bottom: 29px; } + +.pb-30 { + padding-bottom: 30px; } + +.pb-31 { + padding-bottom: 31px; } + +.pb-32 { + padding-bottom: 32px; } + +.pb-33 { + padding-bottom: 33px; } + +.pb-34 { + padding-bottom: 34px; } + +.pb-35 { + padding-bottom: 35px; } + +.pb-36 { + padding-bottom: 36px; } + +.pb-37 { + padding-bottom: 37px; } + +.pb-38 { + padding-bottom: 38px; } + +.pb-39 { + padding-bottom: 39px; } + +.pb-40 { + padding-bottom: 40px; } + +.pb-41 { + padding-bottom: 41px; } + +.pb-42 { + padding-bottom: 42px; } + +.pb-43 { + padding-bottom: 43px; } + +.pb-44 { + padding-bottom: 44px; } + +.pb-45 { + padding-bottom: 45px; } + +.pb-46 { + padding-bottom: 46px; } + +.pb-47 { + padding-bottom: 47px; } + +.pb-48 { + padding-bottom: 48px; } + +.pb-49 { + padding-bottom: 49px; } + +.pb-50 { + padding-bottom: 50px; } + +.pb-n1 { + padding-bottom: 2px; } + +.pb-n2 { + padding-bottom: 4px; } + +.pb-n3 { + padding-bottom: 6px; } + +.pb-n4 { + padding-bottom: 8px; } + +.pb-n5 { + padding-bottom: 10px; } + +.pb-n6 { + padding-bottom: 12px; } + +.pb-n7 { + padding-bottom: 14px; } + +.pb-n8 { + padding-bottom: 16px; } + +.pb-n9 { + padding-bottom: 18px; } + +.pb-n10 { + padding-bottom: 20px; } + +.pb-n11 { + padding-bottom: 22px; } + +.pb-n12 { + padding-bottom: 24px; } + +.pb-n13 { + padding-bottom: 26px; } + +.pb-n14 { + padding-bottom: 28px; } + +.pb-n15 { + padding-bottom: 30px; } + +.pb-n16 { + padding-bottom: 32px; } + +.pb-n17 { + padding-bottom: 34px; } + +.pb-n18 { + padding-bottom: 36px; } + +.pb-n19 { + padding-bottom: 38px; } + +.pb-n20 { + padding-bottom: 40px; } + +.pb-n21 { + padding-bottom: 42px; } + +.pb-n22 { + padding-bottom: 44px; } + +.pb-n23 { + padding-bottom: 46px; } + +.pb-n24 { + padding-bottom: 48px; } + +.pb-n25 { + padding-bottom: 50px; } + +.pl-0 { + padding-left: 0px; } + +.pl-1 { + padding-left: 1px; } + +.pl-2 { + padding-left: 2px; } + +.pl-3 { + padding-left: 3px; } + +.pl-4 { + padding-left: 4px; } + +.pl-5 { + padding-left: 5px; } + +.pl-6 { + padding-left: 6px; } + +.pl-7 { + padding-left: 7px; } + +.pl-8 { + padding-left: 8px; } + +.pl-9 { + padding-left: 9px; } + +.pl-10 { + padding-left: 10px; } + +.pl-11 { + padding-left: 11px; } + +.pl-12 { + padding-left: 12px; } + +.pl-13 { + padding-left: 13px; } + +.pl-14 { + padding-left: 14px; } + +.pl-15 { + padding-left: 15px; } + +.pl-16 { + padding-left: 16px; } + +.pl-17 { + padding-left: 17px; } + +.pl-18 { + padding-left: 18px; } + +.pl-19 { + padding-left: 19px; } + +.pl-20 { + padding-left: 20px; } + +.pl-21 { + padding-left: 21px; } + +.pl-22 { + padding-left: 22px; } + +.pl-23 { + padding-left: 23px; } + +.pl-24 { + padding-left: 24px; } + +.pl-25 { + padding-left: 25px; } + +.pl-26 { + padding-left: 26px; } + +.pl-27 { + padding-left: 27px; } + +.pl-28 { + padding-left: 28px; } + +.pl-29 { + padding-left: 29px; } + +.pl-30 { + padding-left: 30px; } + +.pl-31 { + padding-left: 31px; } + +.pl-32 { + padding-left: 32px; } + +.pl-33 { + padding-left: 33px; } + +.pl-34 { + padding-left: 34px; } + +.pl-35 { + padding-left: 35px; } + +.pl-36 { + padding-left: 36px; } + +.pl-37 { + padding-left: 37px; } + +.pl-38 { + padding-left: 38px; } + +.pl-39 { + padding-left: 39px; } + +.pl-40 { + padding-left: 40px; } + +.pl-41 { + padding-left: 41px; } + +.pl-42 { + padding-left: 42px; } + +.pl-43 { + padding-left: 43px; } + +.pl-44 { + padding-left: 44px; } + +.pl-45 { + padding-left: 45px; } + +.pl-46 { + padding-left: 46px; } + +.pl-47 { + padding-left: 47px; } + +.pl-48 { + padding-left: 48px; } + +.pl-49 { + padding-left: 49px; } + +.pl-50 { + padding-left: 50px; } + +.pl-n1 { + padding-left: 2px; } + +.pl-n2 { + padding-left: 4px; } + +.pl-n3 { + padding-left: 6px; } + +.pl-n4 { + padding-left: 8px; } + +.pl-n5 { + padding-left: 10px; } + +.pl-n6 { + padding-left: 12px; } + +.pl-n7 { + padding-left: 14px; } + +.pl-n8 { + padding-left: 16px; } + +.pl-n9 { + padding-left: 18px; } + +.pl-n10 { + padding-left: 20px; } + +.pl-n11 { + padding-left: 22px; } + +.pl-n12 { + padding-left: 24px; } + +.pl-n13 { + padding-left: 26px; } + +.pl-n14 { + padding-left: 28px; } + +.pl-n15 { + padding-left: 30px; } + +.pl-n16 { + padding-left: 32px; } + +.pl-n17 { + padding-left: 34px; } + +.pl-n18 { + padding-left: 36px; } + +.pl-n19 { + padding-left: 38px; } + +.pl-n20 { + padding-left: 40px; } + +.pl-n21 { + padding-left: 42px; } + +.pl-n22 { + padding-left: 44px; } + +.pl-n23 { + padding-left: 46px; } + +.pl-n24 { + padding-left: 48px; } + +.pl-n25 { + padding-left: 50px; } + +.px-0 { + padding-left: 0px; + padding-right: 0px; } + +.px-1 { + padding-left: 1px; + padding-right: 1px; } + +.px-2 { + padding-left: 2px; + padding-right: 2px; } + +.px-3 { + padding-left: 3px; + padding-right: 3px; } + +.px-4 { + padding-left: 4px; + padding-right: 4px; } + +.px-5 { + padding-left: 5px; + padding-right: 5px; } + +.px-6 { + padding-left: 6px; + padding-right: 6px; } + +.px-7 { + padding-left: 7px; + padding-right: 7px; } + +.px-8 { + padding-left: 8px; + padding-right: 8px; } + +.px-9 { + padding-left: 9px; + padding-right: 9px; } + +.px-10 { + padding-left: 10px; + padding-right: 10px; } + +.px-11 { + padding-left: 11px; + padding-right: 11px; } + +.px-12 { + padding-left: 12px; + padding-right: 12px; } + +.px-13 { + padding-left: 13px; + padding-right: 13px; } + +.px-14 { + padding-left: 14px; + padding-right: 14px; } + +.px-15 { + padding-left: 15px; + padding-right: 15px; } + +.px-16 { + padding-left: 16px; + padding-right: 16px; } + +.px-17 { + padding-left: 17px; + padding-right: 17px; } + +.px-18 { + padding-left: 18px; + padding-right: 18px; } + +.px-19 { + padding-left: 19px; + padding-right: 19px; } + +.px-20 { + padding-left: 20px; + padding-right: 20px; } + +.px-21 { + padding-left: 21px; + padding-right: 21px; } + +.px-22 { + padding-left: 22px; + padding-right: 22px; } + +.px-23 { + padding-left: 23px; + padding-right: 23px; } + +.px-24 { + padding-left: 24px; + padding-right: 24px; } + +.px-25 { + padding-left: 25px; + padding-right: 25px; } + +.px-26 { + padding-left: 26px; + padding-right: 26px; } + +.px-27 { + padding-left: 27px; + padding-right: 27px; } + +.px-28 { + padding-left: 28px; + padding-right: 28px; } + +.px-29 { + padding-left: 29px; + padding-right: 29px; } + +.px-30 { + padding-left: 30px; + padding-right: 30px; } + +.px-31 { + padding-left: 31px; + padding-right: 31px; } + +.px-32 { + padding-left: 32px; + padding-right: 32px; } + +.px-33 { + padding-left: 33px; + padding-right: 33px; } + +.px-34 { + padding-left: 34px; + padding-right: 34px; } + +.px-35 { + padding-left: 35px; + padding-right: 35px; } + +.px-36 { + padding-left: 36px; + padding-right: 36px; } + +.px-37 { + padding-left: 37px; + padding-right: 37px; } + +.px-38 { + padding-left: 38px; + padding-right: 38px; } + +.px-39 { + padding-left: 39px; + padding-right: 39px; } + +.px-40 { + padding-left: 40px; + padding-right: 40px; } + +.px-41 { + padding-left: 41px; + padding-right: 41px; } + +.px-42 { + padding-left: 42px; + padding-right: 42px; } + +.px-43 { + padding-left: 43px; + padding-right: 43px; } + +.px-44 { + padding-left: 44px; + padding-right: 44px; } + +.px-45 { + padding-left: 45px; + padding-right: 45px; } + +.px-46 { + padding-left: 46px; + padding-right: 46px; } + +.px-47 { + padding-left: 47px; + padding-right: 47px; } + +.px-48 { + padding-left: 48px; + padding-right: 48px; } + +.px-49 { + padding-left: 49px; + padding-right: 49px; } + +.px-50 { + padding-left: 50px; + padding-right: 50px; } + +.px-n1 { + padding-left: 2px; + padding-right: 2px; } + +.px-n2 { + padding-left: 4px; + padding-right: 4px; } + +.px-n3 { + padding-left: 6px; + padding-right: 6px; } + +.px-n4 { + padding-left: 8px; + padding-right: 8px; } + +.px-n5 { + padding-left: 10px; + padding-right: 10px; } + +.px-n6 { + padding-left: 12px; + padding-right: 12px; } + +.px-n7 { + padding-left: 14px; + padding-right: 14px; } + +.px-n8 { + padding-left: 16px; + padding-right: 16px; } + +.px-n9 { + padding-left: 18px; + padding-right: 18px; } + +.px-n10 { + padding-left: 20px; + padding-right: 20px; } + +.px-n11 { + padding-left: 22px; + padding-right: 22px; } + +.px-n12 { + padding-left: 24px; + padding-right: 24px; } + +.px-n13 { + padding-left: 26px; + padding-right: 26px; } + +.px-n14 { + padding-left: 28px; + padding-right: 28px; } + +.px-n15 { + padding-left: 30px; + padding-right: 30px; } + +.px-n16 { + padding-left: 32px; + padding-right: 32px; } + +.px-n17 { + padding-left: 34px; + padding-right: 34px; } + +.px-n18 { + padding-left: 36px; + padding-right: 36px; } + +.px-n19 { + padding-left: 38px; + padding-right: 38px; } + +.px-n20 { + padding-left: 40px; + padding-right: 40px; } + +.px-n21 { + padding-left: 42px; + padding-right: 42px; } + +.px-n22 { + padding-left: 44px; + padding-right: 44px; } + +.px-n23 { + padding-left: 46px; + padding-right: 46px; } + +.px-n24 { + padding-left: 48px; + padding-right: 48px; } + +.px-n25 { + padding-left: 50px; + padding-right: 50px; } + +.py-0 { + padding-top: 0px; + padding-bottom: 0px; } + +.py-1 { + padding-top: 1px; + padding-bottom: 1px; } + +.py-2 { + padding-top: 2px; + padding-bottom: 2px; } + +.py-3 { + padding-top: 3px; + padding-bottom: 3px; } + +.py-4 { + padding-top: 4px; + padding-bottom: 4px; } + +.py-5 { + padding-top: 5px; + padding-bottom: 5px; } + +.py-6 { + padding-top: 6px; + padding-bottom: 6px; } + +.py-7 { + padding-top: 7px; + padding-bottom: 7px; } + +.py-8 { + padding-top: 8px; + padding-bottom: 8px; } + +.py-9 { + padding-top: 9px; + padding-bottom: 9px; } + +.py-10 { + padding-top: 10px; + padding-bottom: 10px; } + +.py-11 { + padding-top: 11px; + padding-bottom: 11px; } + +.py-12 { + padding-top: 12px; + padding-bottom: 12px; } + +.py-13 { + padding-top: 13px; + padding-bottom: 13px; } + +.py-14 { + padding-top: 14px; + padding-bottom: 14px; } + +.py-15 { + padding-top: 15px; + padding-bottom: 15px; } + +.py-16 { + padding-top: 16px; + padding-bottom: 16px; } + +.py-17 { + padding-top: 17px; + padding-bottom: 17px; } + +.py-18 { + padding-top: 18px; + padding-bottom: 18px; } + +.py-19 { + padding-top: 19px; + padding-bottom: 19px; } + +.py-20 { + padding-top: 20px; + padding-bottom: 20px; } + +.py-21 { + padding-top: 21px; + padding-bottom: 21px; } + +.py-22 { + padding-top: 22px; + padding-bottom: 22px; } + +.py-23 { + padding-top: 23px; + padding-bottom: 23px; } + +.py-24 { + padding-top: 24px; + padding-bottom: 24px; } + +.py-25 { + padding-top: 25px; + padding-bottom: 25px; } + +.py-26 { + padding-top: 26px; + padding-bottom: 26px; } + +.py-27 { + padding-top: 27px; + padding-bottom: 27px; } + +.py-28 { + padding-top: 28px; + padding-bottom: 28px; } + +.py-29 { + padding-top: 29px; + padding-bottom: 29px; } + +.py-30 { + padding-top: 30px; + padding-bottom: 30px; } + +.py-31 { + padding-top: 31px; + padding-bottom: 31px; } + +.py-32 { + padding-top: 32px; + padding-bottom: 32px; } + +.py-33 { + padding-top: 33px; + padding-bottom: 33px; } + +.py-34 { + padding-top: 34px; + padding-bottom: 34px; } + +.py-35 { + padding-top: 35px; + padding-bottom: 35px; } + +.py-36 { + padding-top: 36px; + padding-bottom: 36px; } + +.py-37 { + padding-top: 37px; + padding-bottom: 37px; } + +.py-38 { + padding-top: 38px; + padding-bottom: 38px; } + +.py-39 { + padding-top: 39px; + padding-bottom: 39px; } + +.py-40 { + padding-top: 40px; + padding-bottom: 40px; } + +.py-41 { + padding-top: 41px; + padding-bottom: 41px; } + +.py-42 { + padding-top: 42px; + padding-bottom: 42px; } + +.py-43 { + padding-top: 43px; + padding-bottom: 43px; } + +.py-44 { + padding-top: 44px; + padding-bottom: 44px; } + +.py-45 { + padding-top: 45px; + padding-bottom: 45px; } + +.py-46 { + padding-top: 46px; + padding-bottom: 46px; } + +.py-47 { + padding-top: 47px; + padding-bottom: 47px; } + +.py-48 { + padding-top: 48px; + padding-bottom: 48px; } + +.py-49 { + padding-top: 49px; + padding-bottom: 49px; } + +.py-50 { + padding-top: 50px; + padding-bottom: 50px; } + +.py-n1 { + padding-top: 2px; + padding-bottom: 2px; } + +.py-n2 { + padding-top: 4px; + padding-bottom: 4px; } + +.py-n3 { + padding-top: 6px; + padding-bottom: 6px; } + +.py-n4 { + padding-top: 8px; + padding-bottom: 8px; } + +.py-n5 { + padding-top: 10px; + padding-bottom: 10px; } + +.py-n6 { + padding-top: 12px; + padding-bottom: 12px; } + +.py-n7 { + padding-top: 14px; + padding-bottom: 14px; } + +.py-n8 { + padding-top: 16px; + padding-bottom: 16px; } + +.py-n9 { + padding-top: 18px; + padding-bottom: 18px; } + +.py-n10 { + padding-top: 20px; + padding-bottom: 20px; } + +.py-n11 { + padding-top: 22px; + padding-bottom: 22px; } + +.py-n12 { + padding-top: 24px; + padding-bottom: 24px; } + +.py-n13 { + padding-top: 26px; + padding-bottom: 26px; } + +.py-n14 { + padding-top: 28px; + padding-bottom: 28px; } + +.py-n15 { + padding-top: 30px; + padding-bottom: 30px; } + +.py-n16 { + padding-top: 32px; + padding-bottom: 32px; } + +.py-n17 { + padding-top: 34px; + padding-bottom: 34px; } + +.py-n18 { + padding-top: 36px; + padding-bottom: 36px; } + +.py-n19 { + padding-top: 38px; + padding-bottom: 38px; } + +.py-n20 { + padding-top: 40px; + padding-bottom: 40px; } + +.py-n21 { + padding-top: 42px; + padding-bottom: 42px; } + +.py-n22 { + padding-top: 44px; + padding-bottom: 44px; } + +.py-n23 { + padding-top: 46px; + padding-bottom: 46px; } + +.py-n24 { + padding-top: 48px; + padding-bottom: 48px; } + +.py-n25 { + padding-top: 50px; + padding-bottom: 50px; } + +.ma-0 { + margin: 0px; } + +.ma-1 { + margin: 1px; } + +.ma-2 { + margin: 2px; } + +.ma-3 { + margin: 3px; } + +.ma-4 { + margin: 4px; } + +.ma-5 { + margin: 5px; } + +.ma-6 { + margin: 6px; } + +.ma-7 { + margin: 7px; } + +.ma-8 { + margin: 8px; } + +.ma-9 { + margin: 9px; } + +.ma-10 { + margin: 10px; } + +.ma-11 { + margin: 11px; } + +.ma-12 { + margin: 12px; } + +.ma-13 { + margin: 13px; } + +.ma-14 { + margin: 14px; } + +.ma-15 { + margin: 15px; } + +.ma-16 { + margin: 16px; } + +.ma-17 { + margin: 17px; } + +.ma-18 { + margin: 18px; } + +.ma-19 { + margin: 19px; } + +.ma-20 { + margin: 20px; } + +.ma-21 { + margin: 21px; } + +.ma-22 { + margin: 22px; } + +.ma-23 { + margin: 23px; } + +.ma-24 { + margin: 24px; } + +.ma-25 { + margin: 25px; } + +.ma-26 { + margin: 26px; } + +.ma-27 { + margin: 27px; } + +.ma-28 { + margin: 28px; } + +.ma-29 { + margin: 29px; } + +.ma-30 { + margin: 30px; } + +.ma-31 { + margin: 31px; } + +.ma-32 { + margin: 32px; } + +.ma-33 { + margin: 33px; } + +.ma-34 { + margin: 34px; } + +.ma-35 { + margin: 35px; } + +.ma-36 { + margin: 36px; } + +.ma-37 { + margin: 37px; } + +.ma-38 { + margin: 38px; } + +.ma-39 { + margin: 39px; } + +.ma-40 { + margin: 40px; } + +.ma-41 { + margin: 41px; } + +.ma-42 { + margin: 42px; } + +.ma-43 { + margin: 43px; } + +.ma-44 { + margin: 44px; } + +.ma-45 { + margin: 45px; } + +.ma-46 { + margin: 46px; } + +.ma-47 { + margin: 47px; } + +.ma-48 { + margin: 48px; } + +.ma-49 { + margin: 49px; } + +.ma-50 { + margin: 50px; } + +.ma-n1 { + margin: 2px; } + +.ma-n2 { + margin: 4px; } + +.ma-n3 { + margin: 6px; } + +.ma-n4 { + margin: 8px; } + +.ma-n5 { + margin: 10px; } + +.ma-n6 { + margin: 12px; } + +.ma-n7 { + margin: 14px; } + +.ma-n8 { + margin: 16px; } + +.ma-n9 { + margin: 18px; } + +.ma-n10 { + margin: 20px; } + +.ma-n11 { + margin: 22px; } + +.ma-n12 { + margin: 24px; } + +.ma-n13 { + margin: 26px; } + +.ma-n14 { + margin: 28px; } + +.ma-n15 { + margin: 30px; } + +.ma-n16 { + margin: 32px; } + +.ma-n17 { + margin: 34px; } + +.ma-n18 { + margin: 36px; } + +.ma-n19 { + margin: 38px; } + +.ma-n20 { + margin: 40px; } + +.ma-n21 { + margin: 42px; } + +.ma-n22 { + margin: 44px; } + +.ma-n23 { + margin: 46px; } + +.ma-n24 { + margin: 48px; } + +.ma-n25 { + margin: 50px; } + +.mt-0 { + margin-top: 0px; } + +.mt--0 { + margin-top: -0px; } + +.mt-1 { + margin-top: 1px; } + +.mt--1 { + margin-top: -1px; } + +.mt-2 { + margin-top: 2px; } + +.mt--2 { + margin-top: -2px; } + +.mt-3 { + margin-top: 3px; } + +.mt--3 { + margin-top: -3px; } + +.mt-4 { + margin-top: 4px; } + +.mt--4 { + margin-top: -4px; } + +.mt-5 { + margin-top: 5px; } + +.mt--5 { + margin-top: -5px; } + +.mt-6 { + margin-top: 6px; } + +.mt--6 { + margin-top: -6px; } + +.mt-7 { + margin-top: 7px; } + +.mt--7 { + margin-top: -7px; } + +.mt-8 { + margin-top: 8px; } + +.mt--8 { + margin-top: -8px; } + +.mt-9 { + margin-top: 9px; } + +.mt--9 { + margin-top: -9px; } + +.mt-10 { + margin-top: 10px; } + +.mt--10 { + margin-top: -10px; } + +.mt-11 { + margin-top: 11px; } + +.mt--11 { + margin-top: -11px; } + +.mt-12 { + margin-top: 12px; } + +.mt--12 { + margin-top: -12px; } + +.mt-13 { + margin-top: 13px; } + +.mt--13 { + margin-top: -13px; } + +.mt-14 { + margin-top: 14px; } + +.mt--14 { + margin-top: -14px; } + +.mt-15 { + margin-top: 15px; } + +.mt--15 { + margin-top: -15px; } + +.mt-16 { + margin-top: 16px; } + +.mt--16 { + margin-top: -16px; } + +.mt-17 { + margin-top: 17px; } + +.mt--17 { + margin-top: -17px; } + +.mt-18 { + margin-top: 18px; } + +.mt--18 { + margin-top: -18px; } + +.mt-19 { + margin-top: 19px; } + +.mt--19 { + margin-top: -19px; } + +.mt-20 { + margin-top: 20px; } + +.mt--20 { + margin-top: -20px; } + +.mt-21 { + margin-top: 21px; } + +.mt--21 { + margin-top: -21px; } + +.mt-22 { + margin-top: 22px; } + +.mt--22 { + margin-top: -22px; } + +.mt-23 { + margin-top: 23px; } + +.mt--23 { + margin-top: -23px; } + +.mt-24 { + margin-top: 24px; } + +.mt--24 { + margin-top: -24px; } + +.mt-25 { + margin-top: 25px; } + +.mt--25 { + margin-top: -25px; } + +.mt-26 { + margin-top: 26px; } + +.mt--26 { + margin-top: -26px; } + +.mt-27 { + margin-top: 27px; } + +.mt--27 { + margin-top: -27px; } + +.mt-28 { + margin-top: 28px; } + +.mt--28 { + margin-top: -28px; } + +.mt-29 { + margin-top: 29px; } + +.mt--29 { + margin-top: -29px; } + +.mt-30 { + margin-top: 30px; } + +.mt--30 { + margin-top: -30px; } + +.mt-31 { + margin-top: 31px; } + +.mt--31 { + margin-top: -31px; } + +.mt-32 { + margin-top: 32px; } + +.mt--32 { + margin-top: -32px; } + +.mt-33 { + margin-top: 33px; } + +.mt--33 { + margin-top: -33px; } + +.mt-34 { + margin-top: 34px; } + +.mt--34 { + margin-top: -34px; } + +.mt-35 { + margin-top: 35px; } + +.mt--35 { + margin-top: -35px; } + +.mt-36 { + margin-top: 36px; } + +.mt--36 { + margin-top: -36px; } + +.mt-37 { + margin-top: 37px; } + +.mt--37 { + margin-top: -37px; } + +.mt-38 { + margin-top: 38px; } + +.mt--38 { + margin-top: -38px; } + +.mt-39 { + margin-top: 39px; } + +.mt--39 { + margin-top: -39px; } + +.mt-40 { + margin-top: 40px; } + +.mt--40 { + margin-top: -40px; } + +.mt-41 { + margin-top: 41px; } + +.mt--41 { + margin-top: -41px; } + +.mt-42 { + margin-top: 42px; } + +.mt--42 { + margin-top: -42px; } + +.mt-43 { + margin-top: 43px; } + +.mt--43 { + margin-top: -43px; } + +.mt-44 { + margin-top: 44px; } + +.mt--44 { + margin-top: -44px; } + +.mt-45 { + margin-top: 45px; } + +.mt--45 { + margin-top: -45px; } + +.mt-46 { + margin-top: 46px; } + +.mt--46 { + margin-top: -46px; } + +.mt-47 { + margin-top: 47px; } + +.mt--47 { + margin-top: -47px; } + +.mt-48 { + margin-top: 48px; } + +.mt--48 { + margin-top: -48px; } + +.mt-49 { + margin-top: 49px; } + +.mt--49 { + margin-top: -49px; } + +.mt-50 { + margin-top: 50px; } + +.mt--50 { + margin-top: -50px; } + +.mt-n1 { + margin-top: 2px; } + +.mt--n1 { + margin-top: -2px; } + +.mt-n2 { + margin-top: 4px; } + +.mt--n2 { + margin-top: -4px; } + +.mt-n3 { + margin-top: 6px; } + +.mt--n3 { + margin-top: -6px; } + +.mt-n4 { + margin-top: 8px; } + +.mt--n4 { + margin-top: -8px; } + +.mt-n5 { + margin-top: 10px; } + +.mt--n5 { + margin-top: -10px; } + +.mt-n6 { + margin-top: 12px; } + +.mt--n6 { + margin-top: -12px; } + +.mt-n7 { + margin-top: 14px; } + +.mt--n7 { + margin-top: -14px; } + +.mt-n8 { + margin-top: 16px; } + +.mt--n8 { + margin-top: -16px; } + +.mt-n9 { + margin-top: 18px; } + +.mt--n9 { + margin-top: -18px; } + +.mt-n10 { + margin-top: 20px; } + +.mt--n10 { + margin-top: -20px; } + +.mt-n11 { + margin-top: 22px; } + +.mt--n11 { + margin-top: -22px; } + +.mt-n12 { + margin-top: 24px; } + +.mt--n12 { + margin-top: -24px; } + +.mt-n13 { + margin-top: 26px; } + +.mt--n13 { + margin-top: -26px; } + +.mt-n14 { + margin-top: 28px; } + +.mt--n14 { + margin-top: -28px; } + +.mt-n15 { + margin-top: 30px; } + +.mt--n15 { + margin-top: -30px; } + +.mt-n16 { + margin-top: 32px; } + +.mt--n16 { + margin-top: -32px; } + +.mt-n17 { + margin-top: 34px; } + +.mt--n17 { + margin-top: -34px; } + +.mt-n18 { + margin-top: 36px; } + +.mt--n18 { + margin-top: -36px; } + +.mt-n19 { + margin-top: 38px; } + +.mt--n19 { + margin-top: -38px; } + +.mt-n20 { + margin-top: 40px; } + +.mt--n20 { + margin-top: -40px; } + +.mt-n21 { + margin-top: 42px; } + +.mt--n21 { + margin-top: -42px; } + +.mt-n22 { + margin-top: 44px; } + +.mt--n22 { + margin-top: -44px; } + +.mt-n23 { + margin-top: 46px; } + +.mt--n23 { + margin-top: -46px; } + +.mt-n24 { + margin-top: 48px; } + +.mt--n24 { + margin-top: -48px; } + +.mt-n25 { + margin-top: 50px; } + +.mt--n25 { + margin-top: -50px; } + +.mr-0 { + margin-right: 0px; } + +.mr--0 { + margin-right: -0px; } + +.mr-1 { + margin-right: 1px; } + +.mr--1 { + margin-right: -1px; } + +.mr-2 { + margin-right: 2px; } + +.mr--2 { + margin-right: -2px; } + +.mr-3 { + margin-right: 3px; } + +.mr--3 { + margin-right: -3px; } + +.mr-4 { + margin-right: 4px; } + +.mr--4 { + margin-right: -4px; } + +.mr-5 { + margin-right: 5px; } + +.mr--5 { + margin-right: -5px; } + +.mr-6 { + margin-right: 6px; } + +.mr--6 { + margin-right: -6px; } + +.mr-7 { + margin-right: 7px; } + +.mr--7 { + margin-right: -7px; } + +.mr-8 { + margin-right: 8px; } + +.mr--8 { + margin-right: -8px; } + +.mr-9 { + margin-right: 9px; } + +.mr--9 { + margin-right: -9px; } + +.mr-10 { + margin-right: 10px; } + +.mr--10 { + margin-right: -10px; } + +.mr-11 { + margin-right: 11px; } + +.mr--11 { + margin-right: -11px; } + +.mr-12 { + margin-right: 12px; } + +.mr--12 { + margin-right: -12px; } + +.mr-13 { + margin-right: 13px; } + +.mr--13 { + margin-right: -13px; } + +.mr-14 { + margin-right: 14px; } + +.mr--14 { + margin-right: -14px; } + +.mr-15 { + margin-right: 15px; } + +.mr--15 { + margin-right: -15px; } + +.mr-16 { + margin-right: 16px; } + +.mr--16 { + margin-right: -16px; } + +.mr-17 { + margin-right: 17px; } + +.mr--17 { + margin-right: -17px; } + +.mr-18 { + margin-right: 18px; } + +.mr--18 { + margin-right: -18px; } + +.mr-19 { + margin-right: 19px; } + +.mr--19 { + margin-right: -19px; } + +.mr-20 { + margin-right: 20px; } + +.mr--20 { + margin-right: -20px; } + +.mr-21 { + margin-right: 21px; } + +.mr--21 { + margin-right: -21px; } + +.mr-22 { + margin-right: 22px; } + +.mr--22 { + margin-right: -22px; } + +.mr-23 { + margin-right: 23px; } + +.mr--23 { + margin-right: -23px; } + +.mr-24 { + margin-right: 24px; } + +.mr--24 { + margin-right: -24px; } + +.mr-25 { + margin-right: 25px; } + +.mr--25 { + margin-right: -25px; } + +.mr-26 { + margin-right: 26px; } + +.mr--26 { + margin-right: -26px; } + +.mr-27 { + margin-right: 27px; } + +.mr--27 { + margin-right: -27px; } + +.mr-28 { + margin-right: 28px; } + +.mr--28 { + margin-right: -28px; } + +.mr-29 { + margin-right: 29px; } + +.mr--29 { + margin-right: -29px; } + +.mr-30 { + margin-right: 30px; } + +.mr--30 { + margin-right: -30px; } + +.mr-31 { + margin-right: 31px; } + +.mr--31 { + margin-right: -31px; } + +.mr-32 { + margin-right: 32px; } + +.mr--32 { + margin-right: -32px; } + +.mr-33 { + margin-right: 33px; } + +.mr--33 { + margin-right: -33px; } + +.mr-34 { + margin-right: 34px; } + +.mr--34 { + margin-right: -34px; } + +.mr-35 { + margin-right: 35px; } + +.mr--35 { + margin-right: -35px; } + +.mr-36 { + margin-right: 36px; } + +.mr--36 { + margin-right: -36px; } + +.mr-37 { + margin-right: 37px; } + +.mr--37 { + margin-right: -37px; } + +.mr-38 { + margin-right: 38px; } + +.mr--38 { + margin-right: -38px; } + +.mr-39 { + margin-right: 39px; } + +.mr--39 { + margin-right: -39px; } + +.mr-40 { + margin-right: 40px; } + +.mr--40 { + margin-right: -40px; } + +.mr-41 { + margin-right: 41px; } + +.mr--41 { + margin-right: -41px; } + +.mr-42 { + margin-right: 42px; } + +.mr--42 { + margin-right: -42px; } + +.mr-43 { + margin-right: 43px; } + +.mr--43 { + margin-right: -43px; } + +.mr-44 { + margin-right: 44px; } + +.mr--44 { + margin-right: -44px; } + +.mr-45 { + margin-right: 45px; } + +.mr--45 { + margin-right: -45px; } + +.mr-46 { + margin-right: 46px; } + +.mr--46 { + margin-right: -46px; } + +.mr-47 { + margin-right: 47px; } + +.mr--47 { + margin-right: -47px; } + +.mr-48 { + margin-right: 48px; } + +.mr--48 { + margin-right: -48px; } + +.mr-49 { + margin-right: 49px; } + +.mr--49 { + margin-right: -49px; } + +.mr-50 { + margin-right: 50px; } + +.mr--50 { + margin-right: -50px; } + +.mr-n1 { + margin-right: 2px; } + +.mr--n1 { + margin-right: -2px; } + +.mr-n2 { + margin-right: 4px; } + +.mr--n2 { + margin-right: -4px; } + +.mr-n3 { + margin-right: 6px; } + +.mr--n3 { + margin-right: -6px; } + +.mr-n4 { + margin-right: 8px; } + +.mr--n4 { + margin-right: -8px; } + +.mr-n5 { + margin-right: 10px; } + +.mr--n5 { + margin-right: -10px; } + +.mr-n6 { + margin-right: 12px; } + +.mr--n6 { + margin-right: -12px; } + +.mr-n7 { + margin-right: 14px; } + +.mr--n7 { + margin-right: -14px; } + +.mr-n8 { + margin-right: 16px; } + +.mr--n8 { + margin-right: -16px; } + +.mr-n9 { + margin-right: 18px; } + +.mr--n9 { + margin-right: -18px; } + +.mr-n10 { + margin-right: 20px; } + +.mr--n10 { + margin-right: -20px; } + +.mr-n11 { + margin-right: 22px; } + +.mr--n11 { + margin-right: -22px; } + +.mr-n12 { + margin-right: 24px; } + +.mr--n12 { + margin-right: -24px; } + +.mr-n13 { + margin-right: 26px; } + +.mr--n13 { + margin-right: -26px; } + +.mr-n14 { + margin-right: 28px; } + +.mr--n14 { + margin-right: -28px; } + +.mr-n15 { + margin-right: 30px; } + +.mr--n15 { + margin-right: -30px; } + +.mr-n16 { + margin-right: 32px; } + +.mr--n16 { + margin-right: -32px; } + +.mr-n17 { + margin-right: 34px; } + +.mr--n17 { + margin-right: -34px; } + +.mr-n18 { + margin-right: 36px; } + +.mr--n18 { + margin-right: -36px; } + +.mr-n19 { + margin-right: 38px; } + +.mr--n19 { + margin-right: -38px; } + +.mr-n20 { + margin-right: 40px; } + +.mr--n20 { + margin-right: -40px; } + +.mr-n21 { + margin-right: 42px; } + +.mr--n21 { + margin-right: -42px; } + +.mr-n22 { + margin-right: 44px; } + +.mr--n22 { + margin-right: -44px; } + +.mr-n23 { + margin-right: 46px; } + +.mr--n23 { + margin-right: -46px; } + +.mr-n24 { + margin-right: 48px; } + +.mr--n24 { + margin-right: -48px; } + +.mr-n25 { + margin-right: 50px; } + +.mr--n25 { + margin-right: -50px; } + +.mb-0 { + margin-bottom: 0px; } + +.mb--0 { + margin-bottom: -0px; } + +.mb-1 { + margin-bottom: 1px; } + +.mb--1 { + margin-bottom: -1px; } + +.mb-2 { + margin-bottom: 2px; } + +.mb--2 { + margin-bottom: -2px; } + +.mb-3 { + margin-bottom: 3px; } + +.mb--3 { + margin-bottom: -3px; } + +.mb-4 { + margin-bottom: 4px; } + +.mb--4 { + margin-bottom: -4px; } + +.mb-5 { + margin-bottom: 5px; } + +.mb--5 { + margin-bottom: -5px; } + +.mb-6 { + margin-bottom: 6px; } + +.mb--6 { + margin-bottom: -6px; } + +.mb-7 { + margin-bottom: 7px; } + +.mb--7 { + margin-bottom: -7px; } + +.mb-8 { + margin-bottom: 8px; } + +.mb--8 { + margin-bottom: -8px; } + +.mb-9 { + margin-bottom: 9px; } + +.mb--9 { + margin-bottom: -9px; } + +.mb-10 { + margin-bottom: 10px; } + +.mb--10 { + margin-bottom: -10px; } + +.mb-11 { + margin-bottom: 11px; } + +.mb--11 { + margin-bottom: -11px; } + +.mb-12 { + margin-bottom: 12px; } + +.mb--12 { + margin-bottom: -12px; } + +.mb-13 { + margin-bottom: 13px; } + +.mb--13 { + margin-bottom: -13px; } + +.mb-14 { + margin-bottom: 14px; } + +.mb--14 { + margin-bottom: -14px; } + +.mb-15 { + margin-bottom: 15px; } + +.mb--15 { + margin-bottom: -15px; } + +.mb-16 { + margin-bottom: 16px; } + +.mb--16 { + margin-bottom: -16px; } + +.mb-17 { + margin-bottom: 17px; } + +.mb--17 { + margin-bottom: -17px; } + +.mb-18 { + margin-bottom: 18px; } + +.mb--18 { + margin-bottom: -18px; } + +.mb-19 { + margin-bottom: 19px; } + +.mb--19 { + margin-bottom: -19px; } + +.mb-20 { + margin-bottom: 20px; } + +.mb--20 { + margin-bottom: -20px; } + +.mb-21 { + margin-bottom: 21px; } + +.mb--21 { + margin-bottom: -21px; } + +.mb-22 { + margin-bottom: 22px; } + +.mb--22 { + margin-bottom: -22px; } + +.mb-23 { + margin-bottom: 23px; } + +.mb--23 { + margin-bottom: -23px; } + +.mb-24 { + margin-bottom: 24px; } + +.mb--24 { + margin-bottom: -24px; } + +.mb-25 { + margin-bottom: 25px; } + +.mb--25 { + margin-bottom: -25px; } + +.mb-26 { + margin-bottom: 26px; } + +.mb--26 { + margin-bottom: -26px; } + +.mb-27 { + margin-bottom: 27px; } + +.mb--27 { + margin-bottom: -27px; } + +.mb-28 { + margin-bottom: 28px; } + +.mb--28 { + margin-bottom: -28px; } + +.mb-29 { + margin-bottom: 29px; } + +.mb--29 { + margin-bottom: -29px; } + +.mb-30 { + margin-bottom: 30px; } + +.mb--30 { + margin-bottom: -30px; } + +.mb-31 { + margin-bottom: 31px; } + +.mb--31 { + margin-bottom: -31px; } + +.mb-32 { + margin-bottom: 32px; } + +.mb--32 { + margin-bottom: -32px; } + +.mb-33 { + margin-bottom: 33px; } + +.mb--33 { + margin-bottom: -33px; } + +.mb-34 { + margin-bottom: 34px; } + +.mb--34 { + margin-bottom: -34px; } + +.mb-35 { + margin-bottom: 35px; } + +.mb--35 { + margin-bottom: -35px; } + +.mb-36 { + margin-bottom: 36px; } + +.mb--36 { + margin-bottom: -36px; } + +.mb-37 { + margin-bottom: 37px; } + +.mb--37 { + margin-bottom: -37px; } + +.mb-38 { + margin-bottom: 38px; } + +.mb--38 { + margin-bottom: -38px; } + +.mb-39 { + margin-bottom: 39px; } + +.mb--39 { + margin-bottom: -39px; } + +.mb-40 { + margin-bottom: 40px; } + +.mb--40 { + margin-bottom: -40px; } + +.mb-41 { + margin-bottom: 41px; } + +.mb--41 { + margin-bottom: -41px; } + +.mb-42 { + margin-bottom: 42px; } + +.mb--42 { + margin-bottom: -42px; } + +.mb-43 { + margin-bottom: 43px; } + +.mb--43 { + margin-bottom: -43px; } + +.mb-44 { + margin-bottom: 44px; } + +.mb--44 { + margin-bottom: -44px; } + +.mb-45 { + margin-bottom: 45px; } + +.mb--45 { + margin-bottom: -45px; } + +.mb-46 { + margin-bottom: 46px; } + +.mb--46 { + margin-bottom: -46px; } + +.mb-47 { + margin-bottom: 47px; } + +.mb--47 { + margin-bottom: -47px; } + +.mb-48 { + margin-bottom: 48px; } + +.mb--48 { + margin-bottom: -48px; } + +.mb-49 { + margin-bottom: 49px; } + +.mb--49 { + margin-bottom: -49px; } + +.mb-50 { + margin-bottom: 50px; } + +.mb--50 { + margin-bottom: -50px; } + +.mb-n1 { + margin-bottom: 2px; } + +.mb--n1 { + margin-bottom: -2px; } + +.mb-n2 { + margin-bottom: 4px; } + +.mb--n2 { + margin-bottom: -4px; } + +.mb-n3 { + margin-bottom: 6px; } + +.mb--n3 { + margin-bottom: -6px; } + +.mb-n4 { + margin-bottom: 8px; } + +.mb--n4 { + margin-bottom: -8px; } + +.mb-n5 { + margin-bottom: 10px; } + +.mb--n5 { + margin-bottom: -10px; } + +.mb-n6 { + margin-bottom: 12px; } + +.mb--n6 { + margin-bottom: -12px; } + +.mb-n7 { + margin-bottom: 14px; } + +.mb--n7 { + margin-bottom: -14px; } + +.mb-n8 { + margin-bottom: 16px; } + +.mb--n8 { + margin-bottom: -16px; } + +.mb-n9 { + margin-bottom: 18px; } + +.mb--n9 { + margin-bottom: -18px; } + +.mb-n10 { + margin-bottom: 20px; } + +.mb--n10 { + margin-bottom: -20px; } + +.mb-n11 { + margin-bottom: 22px; } + +.mb--n11 { + margin-bottom: -22px; } + +.mb-n12 { + margin-bottom: 24px; } + +.mb--n12 { + margin-bottom: -24px; } + +.mb-n13 { + margin-bottom: 26px; } + +.mb--n13 { + margin-bottom: -26px; } + +.mb-n14 { + margin-bottom: 28px; } + +.mb--n14 { + margin-bottom: -28px; } + +.mb-n15 { + margin-bottom: 30px; } + +.mb--n15 { + margin-bottom: -30px; } + +.mb-n16 { + margin-bottom: 32px; } + +.mb--n16 { + margin-bottom: -32px; } + +.mb-n17 { + margin-bottom: 34px; } + +.mb--n17 { + margin-bottom: -34px; } + +.mb-n18 { + margin-bottom: 36px; } + +.mb--n18 { + margin-bottom: -36px; } + +.mb-n19 { + margin-bottom: 38px; } + +.mb--n19 { + margin-bottom: -38px; } + +.mb-n20 { + margin-bottom: 40px; } + +.mb--n20 { + margin-bottom: -40px; } + +.mb-n21 { + margin-bottom: 42px; } + +.mb--n21 { + margin-bottom: -42px; } + +.mb-n22 { + margin-bottom: 44px; } + +.mb--n22 { + margin-bottom: -44px; } + +.mb-n23 { + margin-bottom: 46px; } + +.mb--n23 { + margin-bottom: -46px; } + +.mb-n24 { + margin-bottom: 48px; } + +.mb--n24 { + margin-bottom: -48px; } + +.mb-n25 { + margin-bottom: 50px; } + +.mb--n25 { + margin-bottom: -50px; } + +.ml-0 { + margin-left: 0px; } + +.ml--0 { + margin-left: -0px; } + +.ml-1 { + margin-left: 1px; } + +.ml--1 { + margin-left: -1px; } + +.ml-2 { + margin-left: 2px; } + +.ml--2 { + margin-left: -2px; } + +.ml-3 { + margin-left: 3px; } + +.ml--3 { + margin-left: -3px; } + +.ml-4 { + margin-left: 4px; } + +.ml--4 { + margin-left: -4px; } + +.ml-5 { + margin-left: 5px; } + +.ml--5 { + margin-left: -5px; } + +.ml-6 { + margin-left: 6px; } + +.ml--6 { + margin-left: -6px; } + +.ml-7 { + margin-left: 7px; } + +.ml--7 { + margin-left: -7px; } + +.ml-8 { + margin-left: 8px; } + +.ml--8 { + margin-left: -8px; } + +.ml-9 { + margin-left: 9px; } + +.ml--9 { + margin-left: -9px; } + +.ml-10 { + margin-left: 10px; } + +.ml--10 { + margin-left: -10px; } + +.ml-11 { + margin-left: 11px; } + +.ml--11 { + margin-left: -11px; } + +.ml-12 { + margin-left: 12px; } + +.ml--12 { + margin-left: -12px; } + +.ml-13 { + margin-left: 13px; } + +.ml--13 { + margin-left: -13px; } + +.ml-14 { + margin-left: 14px; } + +.ml--14 { + margin-left: -14px; } + +.ml-15 { + margin-left: 15px; } + +.ml--15 { + margin-left: -15px; } + +.ml-16 { + margin-left: 16px; } + +.ml--16 { + margin-left: -16px; } + +.ml-17 { + margin-left: 17px; } + +.ml--17 { + margin-left: -17px; } + +.ml-18 { + margin-left: 18px; } + +.ml--18 { + margin-left: -18px; } + +.ml-19 { + margin-left: 19px; } + +.ml--19 { + margin-left: -19px; } + +.ml-20 { + margin-left: 20px; } + +.ml--20 { + margin-left: -20px; } + +.ml-21 { + margin-left: 21px; } + +.ml--21 { + margin-left: -21px; } + +.ml-22 { + margin-left: 22px; } + +.ml--22 { + margin-left: -22px; } + +.ml-23 { + margin-left: 23px; } + +.ml--23 { + margin-left: -23px; } + +.ml-24 { + margin-left: 24px; } + +.ml--24 { + margin-left: -24px; } + +.ml-25 { + margin-left: 25px; } + +.ml--25 { + margin-left: -25px; } + +.ml-26 { + margin-left: 26px; } + +.ml--26 { + margin-left: -26px; } + +.ml-27 { + margin-left: 27px; } + +.ml--27 { + margin-left: -27px; } + +.ml-28 { + margin-left: 28px; } + +.ml--28 { + margin-left: -28px; } + +.ml-29 { + margin-left: 29px; } + +.ml--29 { + margin-left: -29px; } + +.ml-30 { + margin-left: 30px; } + +.ml--30 { + margin-left: -30px; } + +.ml-31 { + margin-left: 31px; } + +.ml--31 { + margin-left: -31px; } + +.ml-32 { + margin-left: 32px; } + +.ml--32 { + margin-left: -32px; } + +.ml-33 { + margin-left: 33px; } + +.ml--33 { + margin-left: -33px; } + +.ml-34 { + margin-left: 34px; } + +.ml--34 { + margin-left: -34px; } + +.ml-35 { + margin-left: 35px; } + +.ml--35 { + margin-left: -35px; } + +.ml-36 { + margin-left: 36px; } + +.ml--36 { + margin-left: -36px; } + +.ml-37 { + margin-left: 37px; } + +.ml--37 { + margin-left: -37px; } + +.ml-38 { + margin-left: 38px; } + +.ml--38 { + margin-left: -38px; } + +.ml-39 { + margin-left: 39px; } + +.ml--39 { + margin-left: -39px; } + +.ml-40 { + margin-left: 40px; } + +.ml--40 { + margin-left: -40px; } + +.ml-41 { + margin-left: 41px; } + +.ml--41 { + margin-left: -41px; } + +.ml-42 { + margin-left: 42px; } + +.ml--42 { + margin-left: -42px; } + +.ml-43 { + margin-left: 43px; } + +.ml--43 { + margin-left: -43px; } + +.ml-44 { + margin-left: 44px; } + +.ml--44 { + margin-left: -44px; } + +.ml-45 { + margin-left: 45px; } + +.ml--45 { + margin-left: -45px; } + +.ml-46 { + margin-left: 46px; } + +.ml--46 { + margin-left: -46px; } + +.ml-47 { + margin-left: 47px; } + +.ml--47 { + margin-left: -47px; } + +.ml-48 { + margin-left: 48px; } + +.ml--48 { + margin-left: -48px; } + +.ml-49 { + margin-left: 49px; } + +.ml--49 { + margin-left: -49px; } + +.ml-50 { + margin-left: 50px; } + +.ml--50 { + margin-left: -50px; } + +.ml-n1 { + margin-left: 2px; } + +.ml--n1 { + margin-left: -2px; } + +.ml-n2 { + margin-left: 4px; } + +.ml--n2 { + margin-left: -4px; } + +.ml-n3 { + margin-left: 6px; } + +.ml--n3 { + margin-left: -6px; } + +.ml-n4 { + margin-left: 8px; } + +.ml--n4 { + margin-left: -8px; } + +.ml-n5 { + margin-left: 10px; } + +.ml--n5 { + margin-left: -10px; } + +.ml-n6 { + margin-left: 12px; } + +.ml--n6 { + margin-left: -12px; } + +.ml-n7 { + margin-left: 14px; } + +.ml--n7 { + margin-left: -14px; } + +.ml-n8 { + margin-left: 16px; } + +.ml--n8 { + margin-left: -16px; } + +.ml-n9 { + margin-left: 18px; } + +.ml--n9 { + margin-left: -18px; } + +.ml-n10 { + margin-left: 20px; } + +.ml--n10 { + margin-left: -20px; } + +.ml-n11 { + margin-left: 22px; } + +.ml--n11 { + margin-left: -22px; } + +.ml-n12 { + margin-left: 24px; } + +.ml--n12 { + margin-left: -24px; } + +.ml-n13 { + margin-left: 26px; } + +.ml--n13 { + margin-left: -26px; } + +.ml-n14 { + margin-left: 28px; } + +.ml--n14 { + margin-left: -28px; } + +.ml-n15 { + margin-left: 30px; } + +.ml--n15 { + margin-left: -30px; } + +.ml-n16 { + margin-left: 32px; } + +.ml--n16 { + margin-left: -32px; } + +.ml-n17 { + margin-left: 34px; } + +.ml--n17 { + margin-left: -34px; } + +.ml-n18 { + margin-left: 36px; } + +.ml--n18 { + margin-left: -36px; } + +.ml-n19 { + margin-left: 38px; } + +.ml--n19 { + margin-left: -38px; } + +.ml-n20 { + margin-left: 40px; } + +.ml--n20 { + margin-left: -40px; } + +.ml-n21 { + margin-left: 42px; } + +.ml--n21 { + margin-left: -42px; } + +.ml-n22 { + margin-left: 44px; } + +.ml--n22 { + margin-left: -44px; } + +.ml-n23 { + margin-left: 46px; } + +.ml--n23 { + margin-left: -46px; } + +.ml-n24 { + margin-left: 48px; } + +.ml--n24 { + margin-left: -48px; } + +.ml-n25 { + margin-left: 50px; } + +.ml--n25 { + margin-left: -50px; } + +.mx-0 { + margin-left: 0px; + margin-right: 0px; } + +.mx-1 { + margin-left: 1px; + margin-right: 1px; } + +.mx-2 { + margin-left: 2px; + margin-right: 2px; } + +.mx-3 { + margin-left: 3px; + margin-right: 3px; } + +.mx-4 { + margin-left: 4px; + margin-right: 4px; } + +.mx-5 { + margin-left: 5px; + margin-right: 5px; } + +.mx-6 { + margin-left: 6px; + margin-right: 6px; } + +.mx-7 { + margin-left: 7px; + margin-right: 7px; } + +.mx-8 { + margin-left: 8px; + margin-right: 8px; } + +.mx-9 { + margin-left: 9px; + margin-right: 9px; } + +.mx-10 { + margin-left: 10px; + margin-right: 10px; } + +.mx-11 { + margin-left: 11px; + margin-right: 11px; } + +.mx-12 { + margin-left: 12px; + margin-right: 12px; } + +.mx-13 { + margin-left: 13px; + margin-right: 13px; } + +.mx-14 { + margin-left: 14px; + margin-right: 14px; } + +.mx-15 { + margin-left: 15px; + margin-right: 15px; } + +.mx-16 { + margin-left: 16px; + margin-right: 16px; } + +.mx-17 { + margin-left: 17px; + margin-right: 17px; } + +.mx-18 { + margin-left: 18px; + margin-right: 18px; } + +.mx-19 { + margin-left: 19px; + margin-right: 19px; } + +.mx-20 { + margin-left: 20px; + margin-right: 20px; } + +.mx-21 { + margin-left: 21px; + margin-right: 21px; } + +.mx-22 { + margin-left: 22px; + margin-right: 22px; } + +.mx-23 { + margin-left: 23px; + margin-right: 23px; } + +.mx-24 { + margin-left: 24px; + margin-right: 24px; } + +.mx-25 { + margin-left: 25px; + margin-right: 25px; } + +.mx-26 { + margin-left: 26px; + margin-right: 26px; } + +.mx-27 { + margin-left: 27px; + margin-right: 27px; } + +.mx-28 { + margin-left: 28px; + margin-right: 28px; } + +.mx-29 { + margin-left: 29px; + margin-right: 29px; } + +.mx-30 { + margin-left: 30px; + margin-right: 30px; } + +.mx-31 { + margin-left: 31px; + margin-right: 31px; } + +.mx-32 { + margin-left: 32px; + margin-right: 32px; } + +.mx-33 { + margin-left: 33px; + margin-right: 33px; } + +.mx-34 { + margin-left: 34px; + margin-right: 34px; } + +.mx-35 { + margin-left: 35px; + margin-right: 35px; } + +.mx-36 { + margin-left: 36px; + margin-right: 36px; } + +.mx-37 { + margin-left: 37px; + margin-right: 37px; } + +.mx-38 { + margin-left: 38px; + margin-right: 38px; } + +.mx-39 { + margin-left: 39px; + margin-right: 39px; } + +.mx-40 { + margin-left: 40px; + margin-right: 40px; } + +.mx-41 { + margin-left: 41px; + margin-right: 41px; } + +.mx-42 { + margin-left: 42px; + margin-right: 42px; } + +.mx-43 { + margin-left: 43px; + margin-right: 43px; } + +.mx-44 { + margin-left: 44px; + margin-right: 44px; } + +.mx-45 { + margin-left: 45px; + margin-right: 45px; } + +.mx-46 { + margin-left: 46px; + margin-right: 46px; } + +.mx-47 { + margin-left: 47px; + margin-right: 47px; } + +.mx-48 { + margin-left: 48px; + margin-right: 48px; } + +.mx-49 { + margin-left: 49px; + margin-right: 49px; } + +.mx-50 { + margin-left: 50px; + margin-right: 50px; } + +.mx-n1 { + margin-left: 2px; + margin-right: 2px; } + +.mx-n2 { + margin-left: 4px; + margin-right: 4px; } + +.mx-n3 { + margin-left: 6px; + margin-right: 6px; } + +.mx-n4 { + margin-left: 8px; + margin-right: 8px; } + +.mx-n5 { + margin-left: 10px; + margin-right: 10px; } + +.mx-n6 { + margin-left: 12px; + margin-right: 12px; } + +.mx-n7 { + margin-left: 14px; + margin-right: 14px; } + +.mx-n8 { + margin-left: 16px; + margin-right: 16px; } + +.mx-n9 { + margin-left: 18px; + margin-right: 18px; } + +.mx-n10 { + margin-left: 20px; + margin-right: 20px; } + +.mx-n11 { + margin-left: 22px; + margin-right: 22px; } + +.mx-n12 { + margin-left: 24px; + margin-right: 24px; } + +.mx-n13 { + margin-left: 26px; + margin-right: 26px; } + +.mx-n14 { + margin-left: 28px; + margin-right: 28px; } + +.mx-n15 { + margin-left: 30px; + margin-right: 30px; } + +.mx-n16 { + margin-left: 32px; + margin-right: 32px; } + +.mx-n17 { + margin-left: 34px; + margin-right: 34px; } + +.mx-n18 { + margin-left: 36px; + margin-right: 36px; } + +.mx-n19 { + margin-left: 38px; + margin-right: 38px; } + +.mx-n20 { + margin-left: 40px; + margin-right: 40px; } + +.mx-n21 { + margin-left: 42px; + margin-right: 42px; } + +.mx-n22 { + margin-left: 44px; + margin-right: 44px; } + +.mx-n23 { + margin-left: 46px; + margin-right: 46px; } + +.mx-n24 { + margin-left: 48px; + margin-right: 48px; } + +.mx-n25 { + margin-left: 50px; + margin-right: 50px; } + +.my-0 { + margin-top: 0px; + margin-bottom: 0px; } + +.my-1 { + margin-top: 1px; + margin-bottom: 1px; } + +.my-2 { + margin-top: 2px; + margin-bottom: 2px; } + +.my-3 { + margin-top: 3px; + margin-bottom: 3px; } + +.my-4 { + margin-top: 4px; + margin-bottom: 4px; } + +.my-5 { + margin-top: 5px; + margin-bottom: 5px; } + +.my-6 { + margin-top: 6px; + margin-bottom: 6px; } + +.my-7 { + margin-top: 7px; + margin-bottom: 7px; } + +.my-8 { + margin-top: 8px; + margin-bottom: 8px; } + +.my-9 { + margin-top: 9px; + margin-bottom: 9px; } + +.my-10 { + margin-top: 10px; + margin-bottom: 10px; } + +.my-11 { + margin-top: 11px; + margin-bottom: 11px; } + +.my-12 { + margin-top: 12px; + margin-bottom: 12px; } + +.my-13 { + margin-top: 13px; + margin-bottom: 13px; } + +.my-14 { + margin-top: 14px; + margin-bottom: 14px; } + +.my-15 { + margin-top: 15px; + margin-bottom: 15px; } + +.my-16 { + margin-top: 16px; + margin-bottom: 16px; } + +.my-17 { + margin-top: 17px; + margin-bottom: 17px; } + +.my-18 { + margin-top: 18px; + margin-bottom: 18px; } + +.my-19 { + margin-top: 19px; + margin-bottom: 19px; } + +.my-20 { + margin-top: 20px; + margin-bottom: 20px; } + +.my-21 { + margin-top: 21px; + margin-bottom: 21px; } + +.my-22 { + margin-top: 22px; + margin-bottom: 22px; } + +.my-23 { + margin-top: 23px; + margin-bottom: 23px; } + +.my-24 { + margin-top: 24px; + margin-bottom: 24px; } + +.my-25 { + margin-top: 25px; + margin-bottom: 25px; } + +.my-26 { + margin-top: 26px; + margin-bottom: 26px; } + +.my-27 { + margin-top: 27px; + margin-bottom: 27px; } + +.my-28 { + margin-top: 28px; + margin-bottom: 28px; } + +.my-29 { + margin-top: 29px; + margin-bottom: 29px; } + +.my-30 { + margin-top: 30px; + margin-bottom: 30px; } + +.my-31 { + margin-top: 31px; + margin-bottom: 31px; } + +.my-32 { + margin-top: 32px; + margin-bottom: 32px; } + +.my-33 { + margin-top: 33px; + margin-bottom: 33px; } + +.my-34 { + margin-top: 34px; + margin-bottom: 34px; } + +.my-35 { + margin-top: 35px; + margin-bottom: 35px; } + +.my-36 { + margin-top: 36px; + margin-bottom: 36px; } + +.my-37 { + margin-top: 37px; + margin-bottom: 37px; } + +.my-38 { + margin-top: 38px; + margin-bottom: 38px; } + +.my-39 { + margin-top: 39px; + margin-bottom: 39px; } + +.my-40 { + margin-top: 40px; + margin-bottom: 40px; } + +.my-41 { + margin-top: 41px; + margin-bottom: 41px; } + +.my-42 { + margin-top: 42px; + margin-bottom: 42px; } + +.my-43 { + margin-top: 43px; + margin-bottom: 43px; } + +.my-44 { + margin-top: 44px; + margin-bottom: 44px; } + +.my-45 { + margin-top: 45px; + margin-bottom: 45px; } + +.my-46 { + margin-top: 46px; + margin-bottom: 46px; } + +.my-47 { + margin-top: 47px; + margin-bottom: 47px; } + +.my-48 { + margin-top: 48px; + margin-bottom: 48px; } + +.my-49 { + margin-top: 49px; + margin-bottom: 49px; } + +.my-50 { + margin-top: 50px; + margin-bottom: 50px; } + +.my-n1 { + margin-top: 2px; + margin-bottom: 2px; } + +.my-n2 { + margin-top: 4px; + margin-bottom: 4px; } + +.my-n3 { + margin-top: 6px; + margin-bottom: 6px; } + +.my-n4 { + margin-top: 8px; + margin-bottom: 8px; } + +.my-n5 { + margin-top: 10px; + margin-bottom: 10px; } + +.my-n6 { + margin-top: 12px; + margin-bottom: 12px; } + +.my-n7 { + margin-top: 14px; + margin-bottom: 14px; } + +.my-n8 { + margin-top: 16px; + margin-bottom: 16px; } + +.my-n9 { + margin-top: 18px; + margin-bottom: 18px; } + +.my-n10 { + margin-top: 20px; + margin-bottom: 20px; } + +.my-n11 { + margin-top: 22px; + margin-bottom: 22px; } + +.my-n12 { + margin-top: 24px; + margin-bottom: 24px; } + +.my-n13 { + margin-top: 26px; + margin-bottom: 26px; } + +.my-n14 { + margin-top: 28px; + margin-bottom: 28px; } + +.my-n15 { + margin-top: 30px; + margin-bottom: 30px; } + +.my-n16 { + margin-top: 32px; + margin-bottom: 32px; } + +.my-n17 { + margin-top: 34px; + margin-bottom: 34px; } + +.my-n18 { + margin-top: 36px; + margin-bottom: 36px; } + +.my-n19 { + margin-top: 38px; + margin-bottom: 38px; } + +.my-n20 { + margin-top: 40px; + margin-bottom: 40px; } + +.my-n21 { + margin-top: 42px; + margin-bottom: 42px; } + +.my-n22 { + margin-top: 44px; + margin-bottom: 44px; } + +.my-n23 { + margin-top: 46px; + margin-bottom: 46px; } + +.my-n24 { + margin-top: 48px; + margin-bottom: 48px; } + +.my-n25 { + margin-top: 50px; + margin-bottom: 50px; } + +.t-0 { + top: 0px; } + +.t--0 { + top: -0px; } + +.t-1 { + top: 1px; } + +.t--1 { + top: -1px; } + +.t-2 { + top: 2px; } + +.t--2 { + top: -2px; } + +.t-3 { + top: 3px; } + +.t--3 { + top: -3px; } + +.t-4 { + top: 4px; } + +.t--4 { + top: -4px; } + +.t-5 { + top: 5px; } + +.t--5 { + top: -5px; } + +.t-6 { + top: 6px; } + +.t--6 { + top: -6px; } + +.t-7 { + top: 7px; } + +.t--7 { + top: -7px; } + +.t-8 { + top: 8px; } + +.t--8 { + top: -8px; } + +.t-9 { + top: 9px; } + +.t--9 { + top: -9px; } + +.t-10 { + top: 10px; } + +.t--10 { + top: -10px; } + +.t-11 { + top: 11px; } + +.t--11 { + top: -11px; } + +.t-12 { + top: 12px; } + +.t--12 { + top: -12px; } + +.t-13 { + top: 13px; } + +.t--13 { + top: -13px; } + +.t-14 { + top: 14px; } + +.t--14 { + top: -14px; } + +.t-15 { + top: 15px; } + +.t--15 { + top: -15px; } + +.t-16 { + top: 16px; } + +.t--16 { + top: -16px; } + +.t-17 { + top: 17px; } + +.t--17 { + top: -17px; } + +.t-18 { + top: 18px; } + +.t--18 { + top: -18px; } + +.t-19 { + top: 19px; } + +.t--19 { + top: -19px; } + +.t-20 { + top: 20px; } + +.t--20 { + top: -20px; } + +.t-21 { + top: 21px; } + +.t--21 { + top: -21px; } + +.t-22 { + top: 22px; } + +.t--22 { + top: -22px; } + +.t-23 { + top: 23px; } + +.t--23 { + top: -23px; } + +.t-24 { + top: 24px; } + +.t--24 { + top: -24px; } + +.t-25 { + top: 25px; } + +.t--25 { + top: -25px; } + +.t-26 { + top: 26px; } + +.t--26 { + top: -26px; } + +.t-27 { + top: 27px; } + +.t--27 { + top: -27px; } + +.t-28 { + top: 28px; } + +.t--28 { + top: -28px; } + +.t-29 { + top: 29px; } + +.t--29 { + top: -29px; } + +.t-30 { + top: 30px; } + +.t--30 { + top: -30px; } + +.t-31 { + top: 31px; } + +.t--31 { + top: -31px; } + +.t-32 { + top: 32px; } + +.t--32 { + top: -32px; } + +.t-33 { + top: 33px; } + +.t--33 { + top: -33px; } + +.t-34 { + top: 34px; } + +.t--34 { + top: -34px; } + +.t-35 { + top: 35px; } + +.t--35 { + top: -35px; } + +.t-36 { + top: 36px; } + +.t--36 { + top: -36px; } + +.t-37 { + top: 37px; } + +.t--37 { + top: -37px; } + +.t-38 { + top: 38px; } + +.t--38 { + top: -38px; } + +.t-39 { + top: 39px; } + +.t--39 { + top: -39px; } + +.t-40 { + top: 40px; } + +.t--40 { + top: -40px; } + +.t-41 { + top: 41px; } + +.t--41 { + top: -41px; } + +.t-42 { + top: 42px; } + +.t--42 { + top: -42px; } + +.t-43 { + top: 43px; } + +.t--43 { + top: -43px; } + +.t-44 { + top: 44px; } + +.t--44 { + top: -44px; } + +.t-45 { + top: 45px; } + +.t--45 { + top: -45px; } + +.t-46 { + top: 46px; } + +.t--46 { + top: -46px; } + +.t-47 { + top: 47px; } + +.t--47 { + top: -47px; } + +.t-48 { + top: 48px; } + +.t--48 { + top: -48px; } + +.t-49 { + top: 49px; } + +.t--49 { + top: -49px; } + +.t-50 { + top: 50px; } + +.t--50 { + top: -50px; } + +.t-n1 { + top: 2px; } + +.t--n1 { + top: -2px; } + +.t-n2 { + top: 4px; } + +.t--n2 { + top: -4px; } + +.t-n3 { + top: 6px; } + +.t--n3 { + top: -6px; } + +.t-n4 { + top: 8px; } + +.t--n4 { + top: -8px; } + +.t-n5 { + top: 10px; } + +.t--n5 { + top: -10px; } + +.t-n6 { + top: 12px; } + +.t--n6 { + top: -12px; } + +.t-n7 { + top: 14px; } + +.t--n7 { + top: -14px; } + +.t-n8 { + top: 16px; } + +.t--n8 { + top: -16px; } + +.t-n9 { + top: 18px; } + +.t--n9 { + top: -18px; } + +.t-n10 { + top: 20px; } + +.t--n10 { + top: -20px; } + +.t-n11 { + top: 22px; } + +.t--n11 { + top: -22px; } + +.t-n12 { + top: 24px; } + +.t--n12 { + top: -24px; } + +.t-n13 { + top: 26px; } + +.t--n13 { + top: -26px; } + +.t-n14 { + top: 28px; } + +.t--n14 { + top: -28px; } + +.t-n15 { + top: 30px; } + +.t--n15 { + top: -30px; } + +.t-n16 { + top: 32px; } + +.t--n16 { + top: -32px; } + +.t-n17 { + top: 34px; } + +.t--n17 { + top: -34px; } + +.t-n18 { + top: 36px; } + +.t--n18 { + top: -36px; } + +.t-n19 { + top: 38px; } + +.t--n19 { + top: -38px; } + +.t-n20 { + top: 40px; } + +.t--n20 { + top: -40px; } + +.t-n21 { + top: 42px; } + +.t--n21 { + top: -42px; } + +.t-n22 { + top: 44px; } + +.t--n22 { + top: -44px; } + +.t-n23 { + top: 46px; } + +.t--n23 { + top: -46px; } + +.t-n24 { + top: 48px; } + +.t--n24 { + top: -48px; } + +.t-n25 { + top: 50px; } + +.t--n25 { + top: -50px; } + +.r-0 { + right: 0px; } + +.r--0 { + right: -0px; } + +.r-1 { + right: 1px; } + +.r--1 { + right: -1px; } + +.r-2 { + right: 2px; } + +.r--2 { + right: -2px; } + +.r-3 { + right: 3px; } + +.r--3 { + right: -3px; } + +.r-4 { + right: 4px; } + +.r--4 { + right: -4px; } + +.r-5 { + right: 5px; } + +.r--5 { + right: -5px; } + +.r-6 { + right: 6px; } + +.r--6 { + right: -6px; } + +.r-7 { + right: 7px; } + +.r--7 { + right: -7px; } + +.r-8 { + right: 8px; } + +.r--8 { + right: -8px; } + +.r-9 { + right: 9px; } + +.r--9 { + right: -9px; } + +.r-10 { + right: 10px; } + +.r--10 { + right: -10px; } + +.r-11 { + right: 11px; } + +.r--11 { + right: -11px; } + +.r-12 { + right: 12px; } + +.r--12 { + right: -12px; } + +.r-13 { + right: 13px; } + +.r--13 { + right: -13px; } + +.r-14 { + right: 14px; } + +.r--14 { + right: -14px; } + +.r-15 { + right: 15px; } + +.r--15 { + right: -15px; } + +.r-16 { + right: 16px; } + +.r--16 { + right: -16px; } + +.r-17 { + right: 17px; } + +.r--17 { + right: -17px; } + +.r-18 { + right: 18px; } + +.r--18 { + right: -18px; } + +.r-19 { + right: 19px; } + +.r--19 { + right: -19px; } + +.r-20 { + right: 20px; } + +.r--20 { + right: -20px; } + +.r-21 { + right: 21px; } + +.r--21 { + right: -21px; } + +.r-22 { + right: 22px; } + +.r--22 { + right: -22px; } + +.r-23 { + right: 23px; } + +.r--23 { + right: -23px; } + +.r-24 { + right: 24px; } + +.r--24 { + right: -24px; } + +.r-25 { + right: 25px; } + +.r--25 { + right: -25px; } + +.r-26 { + right: 26px; } + +.r--26 { + right: -26px; } + +.r-27 { + right: 27px; } + +.r--27 { + right: -27px; } + +.r-28 { + right: 28px; } + +.r--28 { + right: -28px; } + +.r-29 { + right: 29px; } + +.r--29 { + right: -29px; } + +.r-30 { + right: 30px; } + +.r--30 { + right: -30px; } + +.r-31 { + right: 31px; } + +.r--31 { + right: -31px; } + +.r-32 { + right: 32px; } + +.r--32 { + right: -32px; } + +.r-33 { + right: 33px; } + +.r--33 { + right: -33px; } + +.r-34 { + right: 34px; } + +.r--34 { + right: -34px; } + +.r-35 { + right: 35px; } + +.r--35 { + right: -35px; } + +.r-36 { + right: 36px; } + +.r--36 { + right: -36px; } + +.r-37 { + right: 37px; } + +.r--37 { + right: -37px; } + +.r-38 { + right: 38px; } + +.r--38 { + right: -38px; } + +.r-39 { + right: 39px; } + +.r--39 { + right: -39px; } + +.r-40 { + right: 40px; } + +.r--40 { + right: -40px; } + +.r-41 { + right: 41px; } + +.r--41 { + right: -41px; } + +.r-42 { + right: 42px; } + +.r--42 { + right: -42px; } + +.r-43 { + right: 43px; } + +.r--43 { + right: -43px; } + +.r-44 { + right: 44px; } + +.r--44 { + right: -44px; } + +.r-45 { + right: 45px; } + +.r--45 { + right: -45px; } + +.r-46 { + right: 46px; } + +.r--46 { + right: -46px; } + +.r-47 { + right: 47px; } + +.r--47 { + right: -47px; } + +.r-48 { + right: 48px; } + +.r--48 { + right: -48px; } + +.r-49 { + right: 49px; } + +.r--49 { + right: -49px; } + +.r-50 { + right: 50px; } + +.r--50 { + right: -50px; } + +.r-n1 { + right: 2px; } + +.r--n1 { + right: -2px; } + +.r-n2 { + right: 4px; } + +.r--n2 { + right: -4px; } + +.r-n3 { + right: 6px; } + +.r--n3 { + right: -6px; } + +.r-n4 { + right: 8px; } + +.r--n4 { + right: -8px; } + +.r-n5 { + right: 10px; } + +.r--n5 { + right: -10px; } + +.r-n6 { + right: 12px; } + +.r--n6 { + right: -12px; } + +.r-n7 { + right: 14px; } + +.r--n7 { + right: -14px; } + +.r-n8 { + right: 16px; } + +.r--n8 { + right: -16px; } + +.r-n9 { + right: 18px; } + +.r--n9 { + right: -18px; } + +.r-n10 { + right: 20px; } + +.r--n10 { + right: -20px; } + +.r-n11 { + right: 22px; } + +.r--n11 { + right: -22px; } + +.r-n12 { + right: 24px; } + +.r--n12 { + right: -24px; } + +.r-n13 { + right: 26px; } + +.r--n13 { + right: -26px; } + +.r-n14 { + right: 28px; } + +.r--n14 { + right: -28px; } + +.r-n15 { + right: 30px; } + +.r--n15 { + right: -30px; } + +.r-n16 { + right: 32px; } + +.r--n16 { + right: -32px; } + +.r-n17 { + right: 34px; } + +.r--n17 { + right: -34px; } + +.r-n18 { + right: 36px; } + +.r--n18 { + right: -36px; } + +.r-n19 { + right: 38px; } + +.r--n19 { + right: -38px; } + +.r-n20 { + right: 40px; } + +.r--n20 { + right: -40px; } + +.r-n21 { + right: 42px; } + +.r--n21 { + right: -42px; } + +.r-n22 { + right: 44px; } + +.r--n22 { + right: -44px; } + +.r-n23 { + right: 46px; } + +.r--n23 { + right: -46px; } + +.r-n24 { + right: 48px; } + +.r--n24 { + right: -48px; } + +.r-n25 { + right: 50px; } + +.r--n25 { + right: -50px; } + +.b-0 { + bottom: 0px; } + +.b--0 { + bottom: -0px; } + +.b-1 { + bottom: 1px; } + +.b--1 { + bottom: -1px; } + +.b-2 { + bottom: 2px; } + +.b--2 { + bottom: -2px; } + +.b-3 { + bottom: 3px; } + +.b--3 { + bottom: -3px; } + +.b-4 { + bottom: 4px; } + +.b--4 { + bottom: -4px; } + +.b-5 { + bottom: 5px; } + +.b--5 { + bottom: -5px; } + +.b-6 { + bottom: 6px; } + +.b--6 { + bottom: -6px; } + +.b-7 { + bottom: 7px; } + +.b--7 { + bottom: -7px; } + +.b-8 { + bottom: 8px; } + +.b--8 { + bottom: -8px; } + +.b-9 { + bottom: 9px; } + +.b--9 { + bottom: -9px; } + +.b-10 { + bottom: 10px; } + +.b--10 { + bottom: -10px; } + +.b-11 { + bottom: 11px; } + +.b--11 { + bottom: -11px; } + +.b-12 { + bottom: 12px; } + +.b--12 { + bottom: -12px; } + +.b-13 { + bottom: 13px; } + +.b--13 { + bottom: -13px; } + +.b-14 { + bottom: 14px; } + +.b--14 { + bottom: -14px; } + +.b-15 { + bottom: 15px; } + +.b--15 { + bottom: -15px; } + +.b-16 { + bottom: 16px; } + +.b--16 { + bottom: -16px; } + +.b-17 { + bottom: 17px; } + +.b--17 { + bottom: -17px; } + +.b-18 { + bottom: 18px; } + +.b--18 { + bottom: -18px; } + +.b-19 { + bottom: 19px; } + +.b--19 { + bottom: -19px; } + +.b-20 { + bottom: 20px; } + +.b--20 { + bottom: -20px; } + +.b-21 { + bottom: 21px; } + +.b--21 { + bottom: -21px; } + +.b-22 { + bottom: 22px; } + +.b--22 { + bottom: -22px; } + +.b-23 { + bottom: 23px; } + +.b--23 { + bottom: -23px; } + +.b-24 { + bottom: 24px; } + +.b--24 { + bottom: -24px; } + +.b-25 { + bottom: 25px; } + +.b--25 { + bottom: -25px; } + +.b-26 { + bottom: 26px; } + +.b--26 { + bottom: -26px; } + +.b-27 { + bottom: 27px; } + +.b--27 { + bottom: -27px; } + +.b-28 { + bottom: 28px; } + +.b--28 { + bottom: -28px; } + +.b-29 { + bottom: 29px; } + +.b--29 { + bottom: -29px; } + +.b-30 { + bottom: 30px; } + +.b--30 { + bottom: -30px; } + +.b-31 { + bottom: 31px; } + +.b--31 { + bottom: -31px; } + +.b-32 { + bottom: 32px; } + +.b--32 { + bottom: -32px; } + +.b-33 { + bottom: 33px; } + +.b--33 { + bottom: -33px; } + +.b-34 { + bottom: 34px; } + +.b--34 { + bottom: -34px; } + +.b-35 { + bottom: 35px; } + +.b--35 { + bottom: -35px; } + +.b-36 { + bottom: 36px; } + +.b--36 { + bottom: -36px; } + +.b-37 { + bottom: 37px; } + +.b--37 { + bottom: -37px; } + +.b-38 { + bottom: 38px; } + +.b--38 { + bottom: -38px; } + +.b-39 { + bottom: 39px; } + +.b--39 { + bottom: -39px; } + +.b-40 { + bottom: 40px; } + +.b--40 { + bottom: -40px; } + +.b-41 { + bottom: 41px; } + +.b--41 { + bottom: -41px; } + +.b-42 { + bottom: 42px; } + +.b--42 { + bottom: -42px; } + +.b-43 { + bottom: 43px; } + +.b--43 { + bottom: -43px; } + +.b-44 { + bottom: 44px; } + +.b--44 { + bottom: -44px; } + +.b-45 { + bottom: 45px; } + +.b--45 { + bottom: -45px; } + +.b-46 { + bottom: 46px; } + +.b--46 { + bottom: -46px; } + +.b-47 { + bottom: 47px; } + +.b--47 { + bottom: -47px; } + +.b-48 { + bottom: 48px; } + +.b--48 { + bottom: -48px; } + +.b-49 { + bottom: 49px; } + +.b--49 { + bottom: -49px; } + +.b-50 { + bottom: 50px; } + +.b--50 { + bottom: -50px; } + +.b-n1 { + bottom: 2px; } + +.b--n1 { + bottom: -2px; } + +.b-n2 { + bottom: 4px; } + +.b--n2 { + bottom: -4px; } + +.b-n3 { + bottom: 6px; } + +.b--n3 { + bottom: -6px; } + +.b-n4 { + bottom: 8px; } + +.b--n4 { + bottom: -8px; } + +.b-n5 { + bottom: 10px; } + +.b--n5 { + bottom: -10px; } + +.b-n6 { + bottom: 12px; } + +.b--n6 { + bottom: -12px; } + +.b-n7 { + bottom: 14px; } + +.b--n7 { + bottom: -14px; } + +.b-n8 { + bottom: 16px; } + +.b--n8 { + bottom: -16px; } + +.b-n9 { + bottom: 18px; } + +.b--n9 { + bottom: -18px; } + +.b-n10 { + bottom: 20px; } + +.b--n10 { + bottom: -20px; } + +.b-n11 { + bottom: 22px; } + +.b--n11 { + bottom: -22px; } + +.b-n12 { + bottom: 24px; } + +.b--n12 { + bottom: -24px; } + +.b-n13 { + bottom: 26px; } + +.b--n13 { + bottom: -26px; } + +.b-n14 { + bottom: 28px; } + +.b--n14 { + bottom: -28px; } + +.b-n15 { + bottom: 30px; } + +.b--n15 { + bottom: -30px; } + +.b-n16 { + bottom: 32px; } + +.b--n16 { + bottom: -32px; } + +.b-n17 { + bottom: 34px; } + +.b--n17 { + bottom: -34px; } + +.b-n18 { + bottom: 36px; } + +.b--n18 { + bottom: -36px; } + +.b-n19 { + bottom: 38px; } + +.b--n19 { + bottom: -38px; } + +.b-n20 { + bottom: 40px; } + +.b--n20 { + bottom: -40px; } + +.b-n21 { + bottom: 42px; } + +.b--n21 { + bottom: -42px; } + +.b-n22 { + bottom: 44px; } + +.b--n22 { + bottom: -44px; } + +.b-n23 { + bottom: 46px; } + +.b--n23 { + bottom: -46px; } + +.b-n24 { + bottom: 48px; } + +.b--n24 { + bottom: -48px; } + +.b-n25 { + bottom: 50px; } + +.b--n25 { + bottom: -50px; } + +.l-0 { + left: 0px; } + +.l--0 { + left: -0px; } + +.l-1 { + left: 1px; } + +.l--1 { + left: -1px; } + +.l-2 { + left: 2px; } + +.l--2 { + left: -2px; } + +.l-3 { + left: 3px; } + +.l--3 { + left: -3px; } + +.l-4 { + left: 4px; } + +.l--4 { + left: -4px; } + +.l-5 { + left: 5px; } + +.l--5 { + left: -5px; } + +.l-6 { + left: 6px; } + +.l--6 { + left: -6px; } + +.l-7 { + left: 7px; } + +.l--7 { + left: -7px; } + +.l-8 { + left: 8px; } + +.l--8 { + left: -8px; } + +.l-9 { + left: 9px; } + +.l--9 { + left: -9px; } + +.l-10 { + left: 10px; } + +.l--10 { + left: -10px; } + +.l-11 { + left: 11px; } + +.l--11 { + left: -11px; } + +.l-12 { + left: 12px; } + +.l--12 { + left: -12px; } + +.l-13 { + left: 13px; } + +.l--13 { + left: -13px; } + +.l-14 { + left: 14px; } + +.l--14 { + left: -14px; } + +.l-15 { + left: 15px; } + +.l--15 { + left: -15px; } + +.l-16 { + left: 16px; } + +.l--16 { + left: -16px; } + +.l-17 { + left: 17px; } + +.l--17 { + left: -17px; } + +.l-18 { + left: 18px; } + +.l--18 { + left: -18px; } + +.l-19 { + left: 19px; } + +.l--19 { + left: -19px; } + +.l-20 { + left: 20px; } + +.l--20 { + left: -20px; } + +.l-21 { + left: 21px; } + +.l--21 { + left: -21px; } + +.l-22 { + left: 22px; } + +.l--22 { + left: -22px; } + +.l-23 { + left: 23px; } + +.l--23 { + left: -23px; } + +.l-24 { + left: 24px; } + +.l--24 { + left: -24px; } + +.l-25 { + left: 25px; } + +.l--25 { + left: -25px; } + +.l-26 { + left: 26px; } + +.l--26 { + left: -26px; } + +.l-27 { + left: 27px; } + +.l--27 { + left: -27px; } + +.l-28 { + left: 28px; } + +.l--28 { + left: -28px; } + +.l-29 { + left: 29px; } + +.l--29 { + left: -29px; } + +.l-30 { + left: 30px; } + +.l--30 { + left: -30px; } + +.l-31 { + left: 31px; } + +.l--31 { + left: -31px; } + +.l-32 { + left: 32px; } + +.l--32 { + left: -32px; } + +.l-33 { + left: 33px; } + +.l--33 { + left: -33px; } + +.l-34 { + left: 34px; } + +.l--34 { + left: -34px; } + +.l-35 { + left: 35px; } + +.l--35 { + left: -35px; } + +.l-36 { + left: 36px; } + +.l--36 { + left: -36px; } + +.l-37 { + left: 37px; } + +.l--37 { + left: -37px; } + +.l-38 { + left: 38px; } + +.l--38 { + left: -38px; } + +.l-39 { + left: 39px; } + +.l--39 { + left: -39px; } + +.l-40 { + left: 40px; } + +.l--40 { + left: -40px; } + +.l-41 { + left: 41px; } + +.l--41 { + left: -41px; } + +.l-42 { + left: 42px; } + +.l--42 { + left: -42px; } + +.l-43 { + left: 43px; } + +.l--43 { + left: -43px; } + +.l-44 { + left: 44px; } + +.l--44 { + left: -44px; } + +.l-45 { + left: 45px; } + +.l--45 { + left: -45px; } + +.l-46 { + left: 46px; } + +.l--46 { + left: -46px; } + +.l-47 { + left: 47px; } + +.l--47 { + left: -47px; } + +.l-48 { + left: 48px; } + +.l--48 { + left: -48px; } + +.l-49 { + left: 49px; } + +.l--49 { + left: -49px; } + +.l-50 { + left: 50px; } + +.l--50 { + left: -50px; } + +.l-n1 { + left: 2px; } + +.l--n1 { + left: -2px; } + +.l-n2 { + left: 4px; } + +.l--n2 { + left: -4px; } + +.l-n3 { + left: 6px; } + +.l--n3 { + left: -6px; } + +.l-n4 { + left: 8px; } + +.l--n4 { + left: -8px; } + +.l-n5 { + left: 10px; } + +.l--n5 { + left: -10px; } + +.l-n6 { + left: 12px; } + +.l--n6 { + left: -12px; } + +.l-n7 { + left: 14px; } + +.l--n7 { + left: -14px; } + +.l-n8 { + left: 16px; } + +.l--n8 { + left: -16px; } + +.l-n9 { + left: 18px; } + +.l--n9 { + left: -18px; } + +.l-n10 { + left: 20px; } + +.l--n10 { + left: -20px; } + +.l-n11 { + left: 22px; } + +.l--n11 { + left: -22px; } + +.l-n12 { + left: 24px; } + +.l--n12 { + left: -24px; } + +.l-n13 { + left: 26px; } + +.l--n13 { + left: -26px; } + +.l-n14 { + left: 28px; } + +.l--n14 { + left: -28px; } + +.l-n15 { + left: 30px; } + +.l--n15 { + left: -30px; } + +.l-n16 { + left: 32px; } + +.l--n16 { + left: -32px; } + +.l-n17 { + left: 34px; } + +.l--n17 { + left: -34px; } + +.l-n18 { + left: 36px; } + +.l--n18 { + left: -36px; } + +.l-n19 { + left: 38px; } + +.l--n19 { + left: -38px; } + +.l-n20 { + left: 40px; } + +.l--n20 { + left: -40px; } + +.l-n21 { + left: 42px; } + +.l--n21 { + left: -42px; } + +.l-n22 { + left: 44px; } + +.l--n22 { + left: -44px; } + +.l-n23 { + left: 46px; } + +.l--n23 { + left: -46px; } + +.l-n24 { + left: 48px; } + +.l--n24 { + left: -48px; } + +.l-n25 { + left: 50px; } + +.l--n25 { + left: -50px; } + +.flex { + display: flex; } + +.flex-col { + flex-direction: column; } + +.flex-wrap { + flex-flow: row wrap; } + +.flex-shrink { + flex-shrink: 0; } + +.flex-row { + flex-direction: row; } + +.flex-reverse { + flex-direction: row-reverse; } + +.flex-row-top-start { + justify-content: flex-start; + align-items: flex-start; + display: flex; } + +.flex-row-top-center { + justify-content: center; + align-items: flex-start; + display: flex; } + +.flex-row-top-end { + justify-content: flex-end; + align-items: flex-start; + display: flex; } + +.flex-row-center-start { + justify-content: flex-start; + align-items: center; + display: flex; } + +.flex-row-center-center { + justify-content: center; + align-items: center; + display: flex; } + +.flex-row-center-end { + justify-content: flex-end; + align-items: center; + display: flex; } + +.flex-row-bottom-start { + justify-content: flex-start; + align-items: flex-end; + display: flex; } + +.flex-row-bottom-center { + justify-content: center; + align-items: flex-end; + display: flex; } + +.flex-row-bottom-end { + justify-content: flex-end; + align-items: flex-end; + display: flex; } + +.flex-row-center-between { + justify-content: space-between; + align-items: center; + display: flex; } + +.flex-col-top-start { + justify-content: flex-start; + align-items: flex-start; + display: flex; } + +.flex-col-top-center { + justify-content: flex-start; + align-items: center; + display: flex; } + +.flex-col-top-end { + justify-content: flex-start; + align-items: flex-end; + display: flex; } + +.flex-col-center-start { + justify-content: center; + align-items: flex-start; + display: flex; } + +.flex-col-center-center { + justify-content: center; + align-items: center; + display: flex; } + +.flex-col-center-end { + justify-content: center; + align-items: flex-end; + display: flex; } + +.flex-col-bottom-start { + justify-content: flex-end; + align-items: flex-start; + display: flex; } + +.flex-col-bottom-center { + justify-content: flex-end; + align-items: center; + display: flex; } + +.flex-col-bottom-end { + justify-content: flex-end; + align-items: flex-end; + display: flex; } + +.flex-start { + justify-content: flex-start; + align-items: center; + display: flex; } + +.flex-end { + justify-content: flex-end; + align-items: center; + display: flex; } + +.flex-center { + justify-content: center; + align-items: center; + display: flex; } + +.flex-between { + justify-content: space-between; } + +.flex-col-full { + flex-direction: column; + align-items: stretch; } + +.flex-around { + justify-content: space-around; } + +.flex-0 { + flex: 0; } + +.flex-1 { + flex: 1; } + +.flex-2 { + flex: 2; } + +.flex-3 { + flex: 3; } + +.flex-4 { + flex: 4; } + +.flex-5 { + flex: 5; } + +.flex-6 { + flex: 6; } + +.flex-7 { + flex: 7; } + +.flex-8 { + flex: 8; } + +.flex-9 { + flex: 9; } + +.flex-10 { + flex: 10; } + +.flex-11 { + flex: 11; } + +.flex-12 { + flex: 12; } + +.text-red { + color: #f44336; } + +.red { + background-color: #f44336; } + +.text-pink { + color: #e91e63; } + +.pink { + background-color: #e91e63; } + +.text-purple { + color: #9c27b0; } + +.purple { + background-color: #9c27b0; } + +.text-deep-purple { + color: #673ab7; } + +.deep-purple { + background-color: #673ab7; } + +.text-indigo { + color: #3f51b5; } + +.indigo { + background-color: #3f51b5; } + +.text-blue { + color: #2196f3; } + +.blue { + background-color: #2196f3; } + +.text-light-blue { + color: #03a9f4; } + +.light-blue { + background-color: #03a9f4; } + +.text-cyan { + color: #00bcd4; } + +.cyan { + background-color: #00bcd4; } + +.text-teal { + color: #009688; } + +.teal { + background-color: #009688; } + +.text-green { + color: #4caf50; } + +.green { + background-color: #4caf50; } + +.text-light-green { + color: #8bc34a; } + +.light-green { + background-color: #8bc34a; } + +.text-lime { + color: #cddc39; } + +.lime { + background-color: #cddc39; } + +.text-yellow { + color: #ffeb3b; } + +.yellow { + background-color: #ffeb3b; } + +.text-amber { + color: #ffc107; } + +.amber { + background-color: #ffc107; } + +.text-orange { + color: #ff9800; } + +.orange { + background-color: #ff9800; } + +.text-deep-orange { + color: #ff5722; } + +.deep-orange { + background-color: #ff5722; } + +.text-brown { + color: #795548; } + +.brown { + background-color: #795548; } + +.text-blue-grey { + color: #607d8b; } + +.blue-grey { + background-color: #607d8b; } + +.text-primary { + color: #0088ff; } + +.primary { + background-color: #0088ff; } + +.text-success { + color: #34c759; } + +.success { + background-color: #34c759; } + +.text-danger { + color: #ff8d28; } + +.danger { + background-color: #ff8d28; } + +.text-warn { + color: #F3BF12; } + +.warn { + background-color: #F3BF12; } + +.text-error { + color: #ff383c; } + +.error { + background-color: #ff383c; } + +.text-info { + color: #f2f2f7; } + +.info { + background-color: #f2f2f7; } + +.text-grey { + color: #9e9e9e; } + +.grey { + background-color: #9e9e9e; } + +.text-black { + color: #000000; } + +.black { + background-color: #000000; } + +.text-white { + color: #ffffff; } + +.white { + background-color: #ffffff; } + +.text-lighten-5 { + color: #fafafa; } + +.lighten-5 { + background-color: #fafafa; } + +.text-lighten-4 { + color: #f5f5f5; } + +.lighten-4 { + background-color: #f5f5f5; } + +.text-lighten-3 { + color: #eeeeee; } + +.lighten-3 { + background-color: #eeeeee; } + +.text-lighten-2 { + color: #e0e0e0; } + +.lighten-2 { + background-color: #e0e0e0; } + +.text-lighten-1 { + color: #bdbdbd; } + +.lighten-1 { + background-color: #bdbdbd; } + +.text-darken-1 { + color: #757575; } + +.darken-1 { + background-color: #757575; } + +.text-darken-2 { + color: #616161; } + +.darken-2 { + background-color: #616161; } + +.text-darken-3 { + color: #424242; } + +.darken-3 { + background-color: #424242; } + +.text-darken-4 { + color: #212121; } + +.darken-4 { + background-color: #212121; } + +.text-darken-5 { + color: #131313; } + +.darken-5 { + background-color: #131313; } + +.text-darken-6 { + color: #0a0a0a; } + +.darken-6 { + background-color: #0a0a0a; } diff --git a/uni_modules/tmx-ui/scss/uvuePx.css.map b/uni_modules/tmx-ui/scss/uvuePx.css.map new file mode 100644 index 0000000..14b4226 --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvuePx.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["uvuePx.css","uvuePx.scss"],"names":[],"mappings":"AAAA,gBAAgB;ACAhB,eAAA;AACA;EACC,iCAAA;ADED;;ACAA,WAAA;AAEA;EACC,gBAAA;ADED;;ACAA;EACC,mBAAA;ADGD;;ACDA;EACC,kBAAA;ADID;;ACFA;EACC,aAAA;ADKD;;ACMC;EACC,kBAVW;ADOb;;ACEC;EACC,kBAVW;ADWb;;ACFC;EACC,eAVW;ADeb;;ACFA;EACC,WAAA;ADKD;;ACHA;EACC,OAAA;ADMD;;ACCC;EACC,UAAA;ADEF;;ACAC;EACC,UAAA;ADGF;;ACPC;EACC,UAAA;ADUF;;ACRC;EACC,UAAA;ADWF;;ACfC;EACC,UAAA;ADkBF;;AChBC;EACC,UAAA;ADmBF;;ACvBC;EACC,UAAA;AD0BF;;ACxBC;EACC,UAAA;AD2BF;;AC/BC;EACC,UAAA;ADkCF;;AChCC;EACC,UAAA;ADmCF;;ACvCC;EACC,UAAA;AD0CF;;ACxCC;EACC,WAAA;AD2CF;;AC/CC;EACC,UAAA;ADkDF;;AChDC;EACC,WAAA;ADmDF;;ACvDC;EACC,UAAA;AD0DF;;ACxDC;EACC,WAAA;AD2DF;;AC/DC;EACC,UAAA;ADkEF;;AChEC;EACC,WAAA;ADmEF;;ACvEC;EACC,UAAA;AD0EF;;ACxEC;EACC,WAAA;AD2EF;;AC/EC;EACC,WAAA;ADkFF;;AChFC;EACC,WAAA;ADmFF;;ACvFC;EACC,WAAA;AD0FF;;ACxFC;EACC,WAAA;AD2FF;;AC/FC;EACC,WAAA;ADkGF;;AChGC;EACC,WAAA;ADmGF;;ACvGC;EACC,WAAA;AD0GF;;ACxGC;EACC,WAAA;AD2GF;;AC/GC;EACC,WAAA;ADkHF;;AChHC;EACC,WAAA;ADmHF;;ACvHC;EACC,WAAA;AD0HF;;ACxHC;EACC,WAAA;AD2HF;;AC/HC;EACC,WAAA;ADkIF;;AChIC;EACC,WAAA;ADmIF;;ACvIC;EACC,WAAA;AD0IF;;ACxIC;EACC,WAAA;AD2IF;;AC/IC;EACC,WAAA;ADkJF;;AChJC;EACC,WAAA;ADmJF;;ACvJC;EACC,WAAA;AD0JF;;ACxJC;EACC,WAAA;AD2JF;;AC/JC;EACC,WAAA;ADkKF;;AChKC;EACC,WAAA;ADmKF;;ACvKC;EACC,WAAA;AD0KF;;ACxKC;EACC,WAAA;AD2KF;;AC/KC;EACC,WAAA;ADkLF;;AChLC;EACC,WAAA;ADmLF;;ACvLC;EACC,WAAA;AD0LF;;ACxLC;EACC,WAAA;AD2LF;;AC/LC;EACC,WAAA;ADkMF;;AChMC;EACC,WAAA;ADmMF;;ACvMC;EACC,WAAA;AD0MF;;ACxMC;EACC,WAAA;AD2MF;;AC/MC;EACC,WAAA;ADkNF;;AChNC;EACC,WAAA;ADmNF;;AC/MA;EACC,uBAAA;ADkND;;AC9MC;EACC,uBAAA;EACA,QAHW;ADoNb;;ACnNC;EACC,uBAAA;EACA,QAHW;ADyNb;;ACxNC;EACC,uBAAA;EACA,QAHW;AD8Nb;;AC7NC;EACC,uBAAA;EACA,QAHW;ADmOb;;AClOC;EACC,uBAAA;EACA,QAHW;ADwOb;;AC9NC;EACC,eAFkB;ADmOpB;;AClOC;EACC,eAFkB;ADuOpB;;ACtOC;EACC,eAFkB;AD2OpB;;AC1OC;EACC,eAFkB;AD+OpB;;AC9OC;EACC,eAFkB;ADmPpB;;AClPC;EACC,eAFkB;ADuPpB;;ACtPC;EACC,eAFkB;AD2PpB;;AC1PC;EACC,eAFkB;AD+PpB;;ACvPC;EACC,gBAFkB;AD4PpB;;AC3PC;EACC,gBAFkB;ADgQpB;;AC/PC;EACC,gBAFkB;ADoQpB;;AC5PC;EACC,gBAFkB;ADiQpB;;AChQC;EACC,iBAFkB;ADqQpB;;ACpQC;EACC,kBAFkB;ADyQpB;;AC9PE;EAEE,2BAAA;ADgQJ;;AClQE;EAEE,2BAAA;ADoQJ;;ACtQE;EAEE,2BAAA;ADwQJ;;AC1QE;EAEE,2BAAA;AD4QJ;;AC9QE;EAEE,2BAAA;ADgRJ;;AClRE;EAEE,2BAAA;ADoRJ;;ACtRE;EAEE,2BAAA;ADwRJ;;AC1RE;EAEE,2BAAA;AD4RJ;;AC9RE;EAEE,2BAAA;ADgSJ;;AClSE;EAEE,2BAAA;ADoSJ;;ACtSE;EAEE,4BAAA;ADwSJ;;AC1SE;EAEE,4BAAA;AD4SJ;;AC9SE;EAEE,4BAAA;ADgTJ;;AClTE;EAEE,4BAAA;ADoTJ;;ACtTE;EAEE,4BAAA;ADwTJ;;AC1TE;EAEE,4BAAA;AD4TJ;;AC9TE;EAEE,4BAAA;ADgUJ;;AClUE;EAEE,4BAAA;ADoUJ;;ACtUE;EAEE,4BAAA;ADwUJ;;AC1UE;EAEE,4BAAA;AD4UJ;;AC9UE;EAEE,4BAAA;ADgVJ;;AClVE;EAEE,4BAAA;ADoVJ;;ACtVE;EAEE,4BAAA;ADwVJ;;AC1VE;EAEE,4BAAA;AD4VJ;;AC9VE;EAEE,4BAAA;ADgWJ;;AClWE;EAEE,4BAAA;ADoWJ;;ACtWE;EAEE,4BAAA;ADwWJ;;AC1WE;EAEE,4BAAA;AD4WJ;;AC9WE;EAEE,4BAAA;ADgXJ;;AClXE;EAEE,4BAAA;ADoXJ;;ACtXE;EAEE,4BAAA;ADwXJ;;AC1XE;EAEE,4BAAA;AD4XJ;;AC9XE;EAEE,4BAAA;ADgYJ;;AClYE;EAEE,4BAAA;ADoYJ;;ACtYE;EAEE,4BAAA;ADwYJ;;AC1YE;EAEE,4BAAA;AD4YJ;;AC9YE;EAEE,4BAAA;ADgZJ;;AClZE;EAEE,4BAAA;ADoZJ;;ACtZE;EAEE,4BAAA;ADwZJ;;AC1ZE;EAEE,4BAAA;AD4ZJ;;AC9ZE;EAEE,4BAAA;ADgaJ;;AClaE;EAEE,4BAAA;ADoaJ;;ACtaE;EAEE,4BAAA;ADwaJ;;AC1aE;EAEE,4BAAA;AD4aJ;;AC9aE;EAEE,4BAAA;ADgbJ;;AClbE;EAEE,4BAAA;ADobJ;;ACtbE;EAEE,4BAAA;ADwbJ;;AC1bE;EAEE,4BAAA;AD4bJ;;AC9bE;EAEE,4BAAA;ADgcJ;;AClcE;EAEE,4BAAA;ADocJ;;ACtcE;EAEE,4BAAA;ADwcJ;;AC1cE;EAME,4BAAA;ADwcJ;;AC9cE;EAME,4BAAA;AD4cJ;;ACldE;EAME,4BAAA;ADgdJ;;ACtdE;EAME,4BAAA;ADodJ;;AC1dE;EAME,4BAAA;ADwdJ;;AC9dE;EAME,4BAAA;AD4dJ;;ACleE;EAME,4BAAA;ADgeJ;;ACteE;EAME,4BAAA;ADoeJ;;AC1eE;EAME,4BAAA;ADweJ;;AC9eE;EAME,4BAAA;AD4eJ;;AClfE;EAME,6BAAA;ADgfJ;;ACtfE;EAME,6BAAA;ADofJ;;AC1fE;EAME,6BAAA;ADwfJ;;AC9fE;EAME,6BAAA;AD4fJ;;AClgBE;EAME,6BAAA;ADggBJ;;ACtgBE;EAME,6BAAA;ADogBJ;;AC1gBE;EAME,6BAAA;ADwgBJ;;AC9gBE;EAME,6BAAA;AD4gBJ;;AClhBE;EAME,6BAAA;ADghBJ;;ACthBE;EAME,6BAAA;ADohBJ;;AC1hBE;EAME,6BAAA;ADwhBJ;;AC9hBE;EAME,6BAAA;AD4hBJ;;ACliBE;EAME,6BAAA;ADgiBJ;;ACtiBE;EAME,6BAAA;ADoiBJ;;AC1iBE;EAME,6BAAA;ADwiBJ;;AC9iBE;EAME,6BAAA;AD4iBJ;;ACljBE;EAME,6BAAA;ADgjBJ;;ACtjBE;EAME,6BAAA;ADojBJ;;AC1jBE;EAME,6BAAA;ADwjBJ;;AC9jBE;EAME,6BAAA;AD4jBJ;;AClkBE;EAME,6BAAA;ADgkBJ;;ACtkBE;EAME,6BAAA;ADokBJ;;AC1kBE;EAME,6BAAA;ADwkBJ;;AC9kBE;EAME,6BAAA;AD4kBJ;;ACllBE;EAME,6BAAA;ADglBJ;;ACtlBE;EAME,6BAAA;ADolBJ;;AC1lBE;EAME,6BAAA;ADwlBJ;;AC9lBE;EAME,6BAAA;AD4lBJ;;AClmBE;EAME,6BAAA;ADgmBJ;;ACtmBE;EAME,6BAAA;ADomBJ;;AC1mBE;EAME,6BAAA;ADwmBJ;;AC9mBE;EAME,6BAAA;AD4mBJ;;AClnBE;EAME,6BAAA;ADgnBJ;;ACtnBE;EAME,6BAAA;ADonBJ;;AC1nBE;EAME,6BAAA;ADwnBJ;;AC9nBE;EAME,6BAAA;AD4nBJ;;ACloBE;EAME,6BAAA;ADgoBJ;;ACtoBE;EAME,6BAAA;ADooBJ;;AC1oBE;EAME,6BAAA;ADwoBJ;;AC9oBE;EAME,6BAAA;AD4oBJ;;AClpBE;EAME,6BAAA;ADgpBJ;;ACtpBE;EAUE,8BAAA;ADgpBJ;;AC1pBE;EAUE,8BAAA;ADopBJ;;AC9pBE;EAUE,8BAAA;ADwpBJ;;AClqBE;EAUE,8BAAA;AD4pBJ;;ACtqBE;EAUE,8BAAA;ADgqBJ;;AC1qBE;EAUE,8BAAA;ADoqBJ;;AC9qBE;EAUE,8BAAA;ADwqBJ;;AClrBE;EAUE,8BAAA;AD4qBJ;;ACtrBE;EAUE,8BAAA;ADgrBJ;;AC1rBE;EAUE,8BAAA;ADorBJ;;AC9rBE;EAUE,+BAAA;ADwrBJ;;AClsBE;EAUE,+BAAA;AD4rBJ;;ACtsBE;EAUE,+BAAA;ADgsBJ;;AC1sBE;EAUE,+BAAA;ADosBJ;;AC9sBE;EAUE,+BAAA;ADwsBJ;;ACltBE;EAUE,+BAAA;AD4sBJ;;ACttBE;EAUE,+BAAA;ADgtBJ;;AC1tBE;EAUE,+BAAA;ADotBJ;;AC9tBE;EAUE,+BAAA;ADwtBJ;;ACluBE;EAUE,+BAAA;AD4tBJ;;ACtuBE;EAUE,+BAAA;ADguBJ;;AC1uBE;EAUE,+BAAA;ADouBJ;;AC9uBE;EAUE,+BAAA;ADwuBJ;;AClvBE;EAUE,+BAAA;AD4uBJ;;ACtvBE;EAUE,+BAAA;ADgvBJ;;AC1vBE;EAUE,+BAAA;ADovBJ;;AC9vBE;EAUE,+BAAA;ADwvBJ;;AClwBE;EAUE,+BAAA;AD4vBJ;;ACtwBE;EAUE,+BAAA;ADgwBJ;;AC1wBE;EAUE,+BAAA;ADowBJ;;AC9wBE;EAUE,+BAAA;ADwwBJ;;AClxBE;EAUE,+BAAA;AD4wBJ;;ACtxBE;EAUE,+BAAA;ADgxBJ;;AC1xBE;EAUE,+BAAA;ADoxBJ;;AC9xBE;EAUE,+BAAA;ADwxBJ;;AClyBE;EAUE,+BAAA;AD4xBJ;;ACtyBE;EAUE,+BAAA;ADgyBJ;;AC1yBE;EAUE,+BAAA;ADoyBJ;;AC9yBE;EAUE,+BAAA;ADwyBJ;;AClzBE;EAUE,+BAAA;AD4yBJ;;ACtzBE;EAUE,+BAAA;ADgzBJ;;AC1zBE;EAUE,+BAAA;ADozBJ;;AC9zBE;EAUE,+BAAA;ADwzBJ;;ACl0BE;EAUE,+BAAA;AD4zBJ;;ACt0BE;EAUE,+BAAA;ADg0BJ;;AC10BE;EAUE,+BAAA;ADo0BJ;;AC90BE;EAUE,+BAAA;ADw0BJ;;ACl1BE;EAUE,+BAAA;AD40BJ;;ACt1BE;EAUE,+BAAA;ADg1BJ;;AC11BE;EAUE,+BAAA;ADo1BJ;;AC91BE;EAUE,+BAAA;ADw1BJ;;ACl2BE;EAcE,+BAAA;ADw1BJ;;ACt2BE;EAcE,+BAAA;AD41BJ;;AC12BE;EAcE,+BAAA;ADg2BJ;;AC92BE;EAcE,+BAAA;ADo2BJ;;ACl3BE;EAcE,+BAAA;ADw2BJ;;ACt3BE;EAcE,+BAAA;AD42BJ;;AC13BE;EAcE,+BAAA;ADg3BJ;;AC93BE;EAcE,+BAAA;ADo3BJ;;ACl4BE;EAcE,+BAAA;ADw3BJ;;ACt4BE;EAcE,+BAAA;AD43BJ;;AC14BE;EAcE,gCAAA;ADg4BJ;;AC94BE;EAcE,gCAAA;ADo4BJ;;ACl5BE;EAcE,gCAAA;ADw4BJ;;ACt5BE;EAcE,gCAAA;AD44BJ;;AC15BE;EAcE,gCAAA;ADg5BJ;;AC95BE;EAcE,gCAAA;ADo5BJ;;ACl6BE;EAcE,gCAAA;ADw5BJ;;ACt6BE;EAcE,gCAAA;AD45BJ;;AC16BE;EAcE,gCAAA;ADg6BJ;;AC96BE;EAcE,gCAAA;ADo6BJ;;ACl7BE;EAcE,gCAAA;ADw6BJ;;ACt7BE;EAcE,gCAAA;AD46BJ;;AC17BE;EAcE,gCAAA;ADg7BJ;;AC97BE;EAcE,gCAAA;ADo7BJ;;ACl8BE;EAcE,gCAAA;ADw7BJ;;ACt8BE;EAcE,gCAAA;AD47BJ;;AC18BE;EAcE,gCAAA;ADg8BJ;;AC98BE;EAcE,gCAAA;ADo8BJ;;ACl9BE;EAcE,gCAAA;ADw8BJ;;ACt9BE;EAcE,gCAAA;AD48BJ;;AC19BE;EAcE,gCAAA;ADg9BJ;;AC99BE;EAcE,gCAAA;ADo9BJ;;ACl+BE;EAcE,gCAAA;ADw9BJ;;ACt+BE;EAcE,gCAAA;AD49BJ;;AC1+BE;EAcE,gCAAA;ADg+BJ;;AC9+BE;EAcE,gCAAA;ADo+BJ;;ACl/BE;EAcE,gCAAA;ADw+BJ;;ACt/BE;EAcE,gCAAA;AD4+BJ;;AC1/BE;EAcE,gCAAA;ADg/BJ;;AC9/BE;EAcE,gCAAA;ADo/BJ;;AClgCE;EAcE,gCAAA;ADw/BJ;;ACtgCE;EAcE,gCAAA;AD4/BJ;;AC1gCE;EAcE,gCAAA;ADggCJ;;AC9gCE;EAcE,gCAAA;ADogCJ;;AClhCE;EAcE,gCAAA;ADwgCJ;;ACthCE;EAcE,gCAAA;AD4gCJ;;AC1hCE;EAcE,gCAAA;ADghCJ;;AC9hCE;EAcE,gCAAA;ADohCJ;;ACliCE;EAcE,gCAAA;ADwhCJ;;ACtiCE;EAcE,gCAAA;AD4hCJ;;AC1iCE;EAcE,gCAAA;ADgiCJ;;AC9iCE;EAsCE,kBAAA;AD4gCJ;;ACljCE;EAsCE,kBAAA;ADghCJ;;ACtjCE;EAsCE,kBAAA;ADohCJ;;AC1jCE;EAsCE,kBAAA;ADwhCJ;;AC9jCE;EAsCE,kBAAA;AD4hCJ;;AClkCE;EAsCE,kBAAA;ADgiCJ;;ACtkCE;EAsCE,kBAAA;ADoiCJ;;AC1kCE;EAsCE,kBAAA;ADwiCJ;;AC9kCE;EAsCE,kBAAA;AD4iCJ;;ACllCE;EAsCE,kBAAA;ADgjCJ;;ACtlCE;EAsCE,mBAAA;ADojCJ;;AC1lCE;EAsCE,mBAAA;ADwjCJ;;AC9lCE;EAsCE,mBAAA;AD4jCJ;;AClmCE;EAsCE,mBAAA;ADgkCJ;;ACtmCE;EAsCE,mBAAA;ADokCJ;;AC1mCE;EAsCE,mBAAA;ADwkCJ;;AC9mCE;EAsCE,mBAAA;AD4kCJ;;AClnCE;EAsCE,mBAAA;ADglCJ;;ACtnCE;EAsCE,mBAAA;ADolCJ;;AC1nCE;EAsCE,mBAAA;ADwlCJ;;AC9nCE;EAsCE,mBAAA;AD4lCJ;;ACloCE;EAsCE,mBAAA;ADgmCJ;;ACtoCE;EAsCE,mBAAA;ADomCJ;;AC1oCE;EAsCE,mBAAA;ADwmCJ;;AC9oCE;EAsCE,mBAAA;AD4mCJ;;AClpCE;EAsCE,mBAAA;ADgnCJ;;ACtpCE;EAsCE,mBAAA;ADonCJ;;AC1pCE;EAsCE,mBAAA;ADwnCJ;;AC9pCE;EAsCE,mBAAA;AD4nCJ;;AClqCE;EAsCE,mBAAA;ADgoCJ;;ACtqCE;EAsCE,mBAAA;ADooCJ;;AC1qCE;EAsCE,mBAAA;ADwoCJ;;AC9qCE;EAsCE,mBAAA;AD4oCJ;;AClrCE;EAsCE,mBAAA;ADgpCJ;;ACtrCE;EAsCE,mBAAA;ADopCJ;;AC1rCE;EAsCE,mBAAA;ADwpCJ;;AC9rCE;EAsCE,mBAAA;AD4pCJ;;AClsCE;EAsCE,mBAAA;ADgqCJ;;ACtsCE;EAsCE,mBAAA;ADoqCJ;;AC1sCE;EAsCE,mBAAA;ADwqCJ;;AC9sCE;EAsCE,mBAAA;AD4qCJ;;ACltCE;EAsCE,mBAAA;ADgrCJ;;ACttCE;EAsCE,mBAAA;ADorCJ;;AC1tCE;EAsCE,mBAAA;ADwrCJ;;AC9tCE;EAsCE,mBAAA;AD4rCJ;;ACluCE;EAsCE,mBAAA;ADgsCJ;;ACtuCE;EAsCE,mBAAA;ADosCJ;;AC1uCE;EAsCE,mBAAA;ADwsCJ;;AC9uCE;EAsCE,mBAAA;AD4sCJ;;AClvCE;EAsCE,mBAAA;ADgtCJ;;ACtvCE;EAsCE,mBAAA;ADotCJ;;AC1vCE;EAkBE,2BAAA;EACA,4BAAA;AD4uCJ;;AC/vCE;EAkBE,2BAAA;EACA,4BAAA;ADivCJ;;ACpwCE;EAkBE,2BAAA;EACA,4BAAA;ADsvCJ;;ACzwCE;EAkBE,2BAAA;EACA,4BAAA;AD2vCJ;;AC9wCE;EAkBE,2BAAA;EACA,4BAAA;ADgwCJ;;ACnxCE;EAkBE,2BAAA;EACA,4BAAA;ADqwCJ;;ACxxCE;EAkBE,2BAAA;EACA,4BAAA;AD0wCJ;;AC7xCE;EAkBE,2BAAA;EACA,4BAAA;AD+wCJ;;AClyCE;EAkBE,2BAAA;EACA,4BAAA;ADoxCJ;;ACvyCE;EAkBE,2BAAA;EACA,4BAAA;ADyxCJ;;AC5yCE;EAkBE,4BAAA;EACA,6BAAA;AD8xCJ;;ACjzCE;EAkBE,4BAAA;EACA,6BAAA;ADmyCJ;;ACtzCE;EAkBE,4BAAA;EACA,6BAAA;ADwyCJ;;AC3zCE;EAkBE,4BAAA;EACA,6BAAA;AD6yCJ;;ACh0CE;EAkBE,4BAAA;EACA,6BAAA;ADkzCJ;;ACr0CE;EAkBE,4BAAA;EACA,6BAAA;ADuzCJ;;AC10CE;EAkBE,4BAAA;EACA,6BAAA;AD4zCJ;;AC/0CE;EAkBE,4BAAA;EACA,6BAAA;ADi0CJ;;ACp1CE;EAkBE,4BAAA;EACA,6BAAA;ADs0CJ;;ACz1CE;EAkBE,4BAAA;EACA,6BAAA;AD20CJ;;AC91CE;EAkBE,4BAAA;EACA,6BAAA;ADg1CJ;;ACn2CE;EAkBE,4BAAA;EACA,6BAAA;ADq1CJ;;ACx2CE;EAkBE,4BAAA;EACA,6BAAA;AD01CJ;;AC72CE;EAkBE,4BAAA;EACA,6BAAA;AD+1CJ;;ACl3CE;EAkBE,4BAAA;EACA,6BAAA;ADo2CJ;;ACv3CE;EAkBE,4BAAA;EACA,6BAAA;ADy2CJ;;AC53CE;EAkBE,4BAAA;EACA,6BAAA;AD82CJ;;ACj4CE;EAkBE,4BAAA;EACA,6BAAA;ADm3CJ;;ACt4CE;EAkBE,4BAAA;EACA,6BAAA;ADw3CJ;;AC34CE;EAkBE,4BAAA;EACA,6BAAA;AD63CJ;;ACh5CE;EAkBE,4BAAA;EACA,6BAAA;ADk4CJ;;ACr5CE;EAkBE,4BAAA;EACA,6BAAA;ADu4CJ;;AC15CE;EAkBE,4BAAA;EACA,6BAAA;AD44CJ;;AC/5CE;EAkBE,4BAAA;EACA,6BAAA;ADi5CJ;;ACp6CE;EAkBE,4BAAA;EACA,6BAAA;ADs5CJ;;ACz6CE;EAkBE,4BAAA;EACA,6BAAA;AD25CJ;;AC96CE;EAkBE,4BAAA;EACA,6BAAA;ADg6CJ;;ACn7CE;EAkBE,4BAAA;EACA,6BAAA;ADq6CJ;;ACx7CE;EAkBE,4BAAA;EACA,6BAAA;AD06CJ;;AC77CE;EAkBE,4BAAA;EACA,6BAAA;AD+6CJ;;ACl8CE;EAkBE,4BAAA;EACA,6BAAA;ADo7CJ;;ACv8CE;EAkBE,4BAAA;EACA,6BAAA;ADy7CJ;;AC58CE;EAkBE,4BAAA;EACA,6BAAA;AD87CJ;;ACj9CE;EAkBE,4BAAA;EACA,6BAAA;ADm8CJ;;ACt9CE;EAkBE,4BAAA;EACA,6BAAA;ADw8CJ;;AC39CE;EAkBE,4BAAA;EACA,6BAAA;AD68CJ;;ACh+CE;EAkBE,4BAAA;EACA,6BAAA;ADk9CJ;;ACr+CE;EAkBE,4BAAA;EACA,6BAAA;ADu9CJ;;AC1+CE;EAkBE,4BAAA;EACA,6BAAA;AD49CJ;;AC/+CE;EAkBE,4BAAA;EACA,6BAAA;ADi+CJ;;ACp/CE;EAkBE,4BAAA;EACA,6BAAA;ADs+CJ;;ACz/CE;EAuBE,8BAAA;EACA,+BAAA;ADs+CJ;;AC9/CE;EAuBE,8BAAA;EACA,+BAAA;AD2+CJ;;ACngDE;EAuBE,8BAAA;EACA,+BAAA;ADg/CJ;;ACxgDE;EAuBE,8BAAA;EACA,+BAAA;ADq/CJ;;AC7gDE;EAuBE,8BAAA;EACA,+BAAA;AD0/CJ;;AClhDE;EAuBE,8BAAA;EACA,+BAAA;AD+/CJ;;ACvhDE;EAuBE,8BAAA;EACA,+BAAA;ADogDJ;;AC5hDE;EAuBE,8BAAA;EACA,+BAAA;ADygDJ;;ACjiDE;EAuBE,8BAAA;EACA,+BAAA;AD8gDJ;;ACtiDE;EAuBE,8BAAA;EACA,+BAAA;ADmhDJ;;AC3iDE;EAuBE,+BAAA;EACA,gCAAA;ADwhDJ;;AChjDE;EAuBE,+BAAA;EACA,gCAAA;AD6hDJ;;ACrjDE;EAuBE,+BAAA;EACA,gCAAA;ADkiDJ;;AC1jDE;EAuBE,+BAAA;EACA,gCAAA;ADuiDJ;;AC/jDE;EAuBE,+BAAA;EACA,gCAAA;AD4iDJ;;ACpkDE;EAuBE,+BAAA;EACA,gCAAA;ADijDJ;;ACzkDE;EAuBE,+BAAA;EACA,gCAAA;ADsjDJ;;AC9kDE;EAuBE,+BAAA;EACA,gCAAA;AD2jDJ;;ACnlDE;EAuBE,+BAAA;EACA,gCAAA;ADgkDJ;;ACxlDE;EAuBE,+BAAA;EACA,gCAAA;ADqkDJ;;AC7lDE;EAuBE,+BAAA;EACA,gCAAA;AD0kDJ;;AClmDE;EAuBE,+BAAA;EACA,gCAAA;AD+kDJ;;ACvmDE;EAuBE,+BAAA;EACA,gCAAA;ADolDJ;;AC5mDE;EAuBE,+BAAA;EACA,gCAAA;ADylDJ;;ACjnDE;EAuBE,+BAAA;EACA,gCAAA;AD8lDJ;;ACtnDE;EAuBE,+BAAA;EACA,gCAAA;ADmmDJ;;AC3nDE;EAuBE,+BAAA;EACA,gCAAA;ADwmDJ;;AChoDE;EAuBE,+BAAA;EACA,gCAAA;AD6mDJ;;ACroDE;EAuBE,+BAAA;EACA,gCAAA;ADknDJ;;AC1oDE;EAuBE,+BAAA;EACA,gCAAA;ADunDJ;;AC/oDE;EAuBE,+BAAA;EACA,gCAAA;AD4nDJ;;ACppDE;EAuBE,+BAAA;EACA,gCAAA;ADioDJ;;ACzpDE;EAuBE,+BAAA;EACA,gCAAA;ADsoDJ;;AC9pDE;EAuBE,+BAAA;EACA,gCAAA;AD2oDJ;;ACnqDE;EAuBE,+BAAA;EACA,gCAAA;ADgpDJ;;ACxqDE;EAuBE,+BAAA;EACA,gCAAA;ADqpDJ;;AC7qDE;EAuBE,+BAAA;EACA,gCAAA;AD0pDJ;;AClrDE;EAuBE,+BAAA;EACA,gCAAA;AD+pDJ;;ACvrDE;EAuBE,+BAAA;EACA,gCAAA;ADoqDJ;;AC5rDE;EAuBE,+BAAA;EACA,gCAAA;ADyqDJ;;ACjsDE;EAuBE,+BAAA;EACA,gCAAA;AD8qDJ;;ACtsDE;EAuBE,+BAAA;EACA,gCAAA;ADmrDJ;;AC3sDE;EAuBE,+BAAA;EACA,gCAAA;ADwrDJ;;AChtDE;EAuBE,+BAAA;EACA,gCAAA;AD6rDJ;;ACrtDE;EAuBE,+BAAA;EACA,gCAAA;ADksDJ;;AC1tDE;EAuBE,+BAAA;EACA,gCAAA;ADusDJ;;AC/tDE;EAuBE,+BAAA;EACA,gCAAA;AD4sDJ;;ACpuDE;EAuBE,+BAAA;EACA,gCAAA;ADitDJ;;ACzuDE;EAuBE,+BAAA;EACA,gCAAA;ADstDJ;;AC9uDE;EAuBE,+BAAA;EACA,gCAAA;AD2tDJ;;ACnvDE;EAuBE,+BAAA;EACA,gCAAA;ADguDJ;;ACxvDE;EA4BE,2BAAA;EACA,8BAAA;ADguDJ;;AC7vDE;EA4BE,2BAAA;EACA,8BAAA;ADquDJ;;AClwDE;EA4BE,2BAAA;EACA,8BAAA;AD0uDJ;;ACvwDE;EA4BE,2BAAA;EACA,8BAAA;AD+uDJ;;AC5wDE;EA4BE,2BAAA;EACA,8BAAA;ADovDJ;;ACjxDE;EA4BE,2BAAA;EACA,8BAAA;ADyvDJ;;ACtxDE;EA4BE,2BAAA;EACA,8BAAA;AD8vDJ;;AC3xDE;EA4BE,2BAAA;EACA,8BAAA;ADmwDJ;;AChyDE;EA4BE,2BAAA;EACA,8BAAA;ADwwDJ;;ACryDE;EA4BE,2BAAA;EACA,8BAAA;AD6wDJ;;AC1yDE;EA4BE,4BAAA;EACA,+BAAA;ADkxDJ;;AC/yDE;EA4BE,4BAAA;EACA,+BAAA;ADuxDJ;;ACpzDE;EA4BE,4BAAA;EACA,+BAAA;AD4xDJ;;ACzzDE;EA4BE,4BAAA;EACA,+BAAA;ADiyDJ;;AC9zDE;EA4BE,4BAAA;EACA,+BAAA;ADsyDJ;;ACn0DE;EA4BE,4BAAA;EACA,+BAAA;AD2yDJ;;ACx0DE;EA4BE,4BAAA;EACA,+BAAA;ADgzDJ;;AC70DE;EA4BE,4BAAA;EACA,+BAAA;ADqzDJ;;ACl1DE;EA4BE,4BAAA;EACA,+BAAA;AD0zDJ;;ACv1DE;EA4BE,4BAAA;EACA,+BAAA;AD+zDJ;;AC51DE;EA4BE,4BAAA;EACA,+BAAA;ADo0DJ;;ACj2DE;EA4BE,4BAAA;EACA,+BAAA;ADy0DJ;;ACt2DE;EA4BE,4BAAA;EACA,+BAAA;AD80DJ;;AC32DE;EA4BE,4BAAA;EACA,+BAAA;ADm1DJ;;ACh3DE;EA4BE,4BAAA;EACA,+BAAA;ADw1DJ;;ACr3DE;EA4BE,4BAAA;EACA,+BAAA;AD61DJ;;AC13DE;EA4BE,4BAAA;EACA,+BAAA;ADk2DJ;;AC/3DE;EA4BE,4BAAA;EACA,+BAAA;ADu2DJ;;ACp4DE;EA4BE,4BAAA;EACA,+BAAA;AD42DJ;;ACz4DE;EA4BE,4BAAA;EACA,+BAAA;ADi3DJ;;AC94DE;EA4BE,4BAAA;EACA,+BAAA;ADs3DJ;;ACn5DE;EA4BE,4BAAA;EACA,+BAAA;AD23DJ;;ACx5DE;EA4BE,4BAAA;EACA,+BAAA;ADg4DJ;;AC75DE;EA4BE,4BAAA;EACA,+BAAA;ADq4DJ;;ACl6DE;EA4BE,4BAAA;EACA,+BAAA;AD04DJ;;ACv6DE;EA4BE,4BAAA;EACA,+BAAA;AD+4DJ;;AC56DE;EA4BE,4BAAA;EACA,+BAAA;ADo5DJ;;ACj7DE;EA4BE,4BAAA;EACA,+BAAA;ADy5DJ;;ACt7DE;EA4BE,4BAAA;EACA,+BAAA;AD85DJ;;AC37DE;EA4BE,4BAAA;EACA,+BAAA;ADm6DJ;;ACh8DE;EA4BE,4BAAA;EACA,+BAAA;ADw6DJ;;ACr8DE;EA4BE,4BAAA;EACA,+BAAA;AD66DJ;;AC18DE;EA4BE,4BAAA;EACA,+BAAA;ADk7DJ;;AC/8DE;EA4BE,4BAAA;EACA,+BAAA;ADu7DJ;;ACp9DE;EA4BE,4BAAA;EACA,+BAAA;AD47DJ;;ACz9DE;EA4BE,4BAAA;EACA,+BAAA;ADi8DJ;;AC99DE;EA4BE,4BAAA;EACA,+BAAA;ADs8DJ;;ACn+DE;EA4BE,4BAAA;EACA,+BAAA;AD28DJ;;ACx+DE;EA4BE,4BAAA;EACA,+BAAA;ADg9DJ;;AC7+DE;EA4BE,4BAAA;EACA,+BAAA;ADq9DJ;;ACl/DE;EA4BE,4BAAA;EACA,+BAAA;AD09DJ;;ACv/DE;EAiCE,4BAAA;EACA,+BAAA;AD09DJ;;AC5/DE;EAiCE,4BAAA;EACA,+BAAA;AD+9DJ;;ACjgEE;EAiCE,4BAAA;EACA,+BAAA;ADo+DJ;;ACtgEE;EAiCE,4BAAA;EACA,+BAAA;ADy+DJ;;AC3gEE;EAiCE,4BAAA;EACA,+BAAA;AD8+DJ;;AChhEE;EAiCE,4BAAA;EACA,+BAAA;ADm/DJ;;ACrhEE;EAiCE,4BAAA;EACA,+BAAA;ADw/DJ;;AC1hEE;EAiCE,4BAAA;EACA,+BAAA;AD6/DJ;;AC/hEE;EAiCE,4BAAA;EACA,+BAAA;ADkgEJ;;ACpiEE;EAiCE,4BAAA;EACA,+BAAA;ADugEJ;;ACziEE;EAiCE,6BAAA;EACA,gCAAA;AD4gEJ;;AC9iEE;EAiCE,6BAAA;EACA,gCAAA;ADihEJ;;ACnjEE;EAiCE,6BAAA;EACA,gCAAA;ADshEJ;;ACxjEE;EAiCE,6BAAA;EACA,gCAAA;AD2hEJ;;AC7jEE;EAiCE,6BAAA;EACA,gCAAA;ADgiEJ;;AClkEE;EAiCE,6BAAA;EACA,gCAAA;ADqiEJ;;ACvkEE;EAiCE,6BAAA;EACA,gCAAA;AD0iEJ;;AC5kEE;EAiCE,6BAAA;EACA,gCAAA;AD+iEJ;;ACjlEE;EAiCE,6BAAA;EACA,gCAAA;ADojEJ;;ACtlEE;EAiCE,6BAAA;EACA,gCAAA;ADyjEJ;;AC3lEE;EAiCE,6BAAA;EACA,gCAAA;AD8jEJ;;AChmEE;EAiCE,6BAAA;EACA,gCAAA;ADmkEJ;;ACrmEE;EAiCE,6BAAA;EACA,gCAAA;ADwkEJ;;AC1mEE;EAiCE,6BAAA;EACA,gCAAA;AD6kEJ;;AC/mEE;EAiCE,6BAAA;EACA,gCAAA;ADklEJ;;ACpnEE;EAiCE,6BAAA;EACA,gCAAA;ADulEJ;;ACznEE;EAiCE,6BAAA;EACA,gCAAA;AD4lEJ;;AC9nEE;EAiCE,6BAAA;EACA,gCAAA;ADimEJ;;ACnoEE;EAiCE,6BAAA;EACA,gCAAA;ADsmEJ;;ACxoEE;EAiCE,6BAAA;EACA,gCAAA;AD2mEJ;;AC7oEE;EAiCE,6BAAA;EACA,gCAAA;ADgnEJ;;AClpEE;EAiCE,6BAAA;EACA,gCAAA;ADqnEJ;;ACvpEE;EAiCE,6BAAA;EACA,gCAAA;AD0nEJ;;AC5pEE;EAiCE,6BAAA;EACA,gCAAA;AD+nEJ;;ACjqEE;EAiCE,6BAAA;EACA,gCAAA;ADooEJ;;ACtqEE;EAiCE,6BAAA;EACA,gCAAA;ADyoEJ;;AC3qEE;EAiCE,6BAAA;EACA,gCAAA;AD8oEJ;;AChrEE;EAiCE,6BAAA;EACA,gCAAA;ADmpEJ;;ACrrEE;EAiCE,6BAAA;EACA,gCAAA;ADwpEJ;;AC1rEE;EAiCE,6BAAA;EACA,gCAAA;AD6pEJ;;AC/rEE;EAiCE,6BAAA;EACA,gCAAA;ADkqEJ;;ACpsEE;EAiCE,6BAAA;EACA,gCAAA;ADuqEJ;;ACzsEE;EAiCE,6BAAA;EACA,gCAAA;AD4qEJ;;AC9sEE;EAiCE,6BAAA;EACA,gCAAA;ADirEJ;;ACntEE;EAiCE,6BAAA;EACA,gCAAA;ADsrEJ;;ACxtEE;EAiCE,6BAAA;EACA,gCAAA;AD2rEJ;;AC7tEE;EAiCE,6BAAA;EACA,gCAAA;ADgsEJ;;ACluEE;EAiCE,6BAAA;EACA,gCAAA;ADqsEJ;;ACvuEE;EAiCE,6BAAA;EACA,gCAAA;AD0sEJ;;AC5uEE;EAiCE,6BAAA;EACA,gCAAA;AD+sEJ;;ACjvEE;EAiCE,6BAAA;EACA,gCAAA;ADotEJ;;ACxsEC;EACC,kBAAA;AD2sEF;;AC5sEC;EACC,kBAAA;AD+sEF;;AChtEC;EACC,kBAAA;ADmtEF;;ACptEC;EACC,kBAAA;ADutEF;;ACxtEC;EACC,kBAAA;AD2tEF;;AC5tEC;EACC,kBAAA;AD+tEF;;AChuEC;EACC,kBAAA;ADmuEF;;ACpuEC;EACC,kBAAA;ADuuEF;;ACxuEC;EACC,kBAAA;AD2uEF;;AC5uEC;EACC,kBAAA;AD+uEF;;AChvEC;EACC,mBAAA;ADmvEF;;ACpvEC;EACC,mBAAA;ADuvEF;;ACxvEC;EACC,mBAAA;AD2vEF;;AC5vEC;EACC,mBAAA;AD+vEF;;AChwEC;EACC,mBAAA;ADmwEF;;ACpwEC;EACC,mBAAA;ADuwEF;;ACxwEC;EACC,mBAAA;AD2wEF;;AC5wEC;EACC,mBAAA;AD+wEF;;AChxEC;EACC,mBAAA;ADmxEF;;ACpxEC;EACC,mBAAA;ADuxEF;;ACxxEC;EACC,mBAAA;AD2xEF;;AC5xEC;EACC,mBAAA;AD+xEF;;AChyEC;EACC,mBAAA;ADmyEF;;ACpyEC;EACC,mBAAA;ADuyEF;;ACxyEC;EACC,mBAAA;AD2yEF;;AC5yEC;EACC,mBAAA;AD+yEF;;AChzEC;EACC,mBAAA;ADmzEF;;AC9yEA,0BAAA;AAEC;EACC,cAAA;ADgzEF;;ACjzEC;EACC,gBAAA;ADozEF;;ACrzEC;EACC,gBAAA;ADwzEF;;ACzzEC;EACC,gBAAA;AD4zEF;;AC7zEC;EACC,gBAAA;ADg0EF;;ACj0EC;EACC,gBAAA;ADo0EF;;ACr0EC;EACC,gBAAA;ADw0EF;;ACz0EC;EACC,gBAAA;AD40EF;;AC70EC;EACC,gBAAA;ADg1EF;;ACj1EC;EACC,gBAAA;ADo1EF;;ACr1EC;EACC,cAAA;ADw1EF;;ACz1EC;EACC,gBAAA;AD41EF;;AC71EC;EACC,gBAAA;ADg2EF;;ACj2EC;EACC,gBAAA;ADo2EF;;ACr2EC;EACC,gBAAA;ADw2EF;;ACz2EC;EACC,gBAAA;AD42EF;;AC72EC;EACC,gBAAA;ADg3EF;;ACj3EC;EACC,gBAAA;ADo3EF;;ACr3EC;EACC,gBAAA;ADw3EF;;ACz3EC;EACC,gBAAA;AD43EF;;AC73EC;EACC,cAAA;ADg4EF;;ACj4EC;EACC,gBAAA;ADo4EF;;AC53EC;EAME,UAAA;AD03EH;;ACh4EC;EAEE,YAAA;ADk4EH;;ACp4EC;EAEE,YAAA;ADs4EH;;ACx4EC;EAEE,YAAA;AD04EH;;AC54EC;EAEE,YAAA;AD84EH;;ACh5EC;EAEE,YAAA;ADk5EH;;ACp5EC;EAEE,YAAA;ADs5EH;;ACx5EC;EAEE,YAAA;AD05EH;;AC55EC;EAEE,YAAA;AD85EH;;ACh6EC;EAEE,YAAA;ADk6EH;;ACp6EC;EAUE,UAAA;AD85EH;;ACt5EE;EACC,yBAAA;ADy5EH;;ACt5EE;EACC,yBAAA;ADy5EH;;ACn5EE;EACC,yBAAA;ADs5EH;;ACn5EE;EACC,yBAAA;ADs5EH;;AC35EE;EACC,yBAAA;AD85EH;;AC35EE;EACC,yBAAA;AD85EH;;ACn6EE;EACC,yBAAA;ADs6EH;;ACn6EE;EACC,yBAAA;ADs6EH;;AC36EE;EACC,yBAAA;AD86EH;;AC36EE;EACC,yBAAA;AD86EH;;ACn7EE;EACC,yBAAA;ADs7EH;;ACn7EE;EACC,yBAAA;ADs7EH;;AC96EE;EAME,iCAAA;AD46EJ;;ACl7EE;EAME,iCAAA;ADg7EJ;;ACt7EE;EAME,iCAAA;ADo7EJ;;AC17EE;EAME,iCAAA;ADw7EJ;;AC97EE;EAME,iCAAA;AD47EJ;;ACl8EE;EAME,kCAAA;ADg8EJ;;ACt8EE;EAME,kCAAA;ADo8EJ;;AC18EE;EAME,kCAAA;ADw8EJ;;AC98EE;EAME,kCAAA;AD48EJ;;ACl9EE;EAME,kCAAA;ADg9EJ;;ACt9EE;EAME,gCAAA;ADo9EJ;;AC19EE;EAME,gCAAA;ADw9EJ;;AC99EE;EAME,gCAAA;AD49EJ;;ACl+EE;EAME,gCAAA;ADg+EJ;;ACt+EE;EAME,gCAAA;ADo+EJ;;AC1+EE;EAME,mCAAA;ADw+EJ;;AC9+EE;EAME,mCAAA;AD4+EJ;;ACl/EE;EAME,mCAAA;ADg/EJ;;ACt/EE;EAME,mCAAA;ADo/EJ;;AC1/EE;EAME,mCAAA;ADw/EJ;;AC9/EE;EAEE,4BAAA;ADggFJ;;AClgFE;EAEE,4BAAA;ADogFJ;;ACtgFE;EAEE,4BAAA;ADwgFJ;;AC1gFE;EAEE,4BAAA;AD4gFJ;;AC9gFE;EAEE,4BAAA;ADghFJ;;ACjgFG;EACC,YAAA;ADogFJ;;ACrgFG;EACC,YAAA;ADwgFJ;;ACzgFG;EACC,YAAA;AD4gFJ;;AC7gFG;EACC,YAAA;ADghFJ;;ACjhFG;EACC,YAAA;ADohFJ;;ACrhFG;EACC,YAAA;ADwhFJ;;ACzhFG;EACC,YAAA;AD4hFJ;;AC7hFG;EACC,YAAA;ADgiFJ;;ACjiFG;EACC,YAAA;ADoiFJ;;ACriFG;EACC,YAAA;ADwiFJ;;ACziFG;EACC,aAAA;AD4iFJ;;AC7iFG;EACC,aAAA;ADgjFJ;;ACjjFG;EACC,aAAA;ADojFJ;;ACrjFG;EACC,aAAA;ADwjFJ;;ACzjFG;EACC,aAAA;AD4jFJ;;AC7jFG;EACC,aAAA;ADgkFJ;;ACjkFG;EACC,aAAA;ADokFJ;;ACrkFG;EACC,aAAA;ADwkFJ;;ACzkFG;EACC,aAAA;AD4kFJ;;AC7kFG;EACC,aAAA;ADglFJ;;ACjlFG;EACC,aAAA;ADolFJ;;ACrlFG;EACC,aAAA;ADwlFJ;;ACzlFG;EACC,aAAA;AD4lFJ;;AC7lFG;EACC,aAAA;ADgmFJ;;ACjmFG;EACC,aAAA;ADomFJ;;ACrmFG;EACC,aAAA;ADwmFJ;;ACzmFG;EACC,aAAA;AD4mFJ;;AC7mFG;EACC,aAAA;ADgnFJ;;ACjnFG;EACC,aAAA;ADonFJ;;ACrnFG;EACC,aAAA;ADwnFJ;;ACznFG;EACC,aAAA;AD4nFJ;;AC7nFG;EACC,aAAA;ADgoFJ;;ACjoFG;EACC,aAAA;ADooFJ;;ACroFG;EACC,aAAA;ADwoFJ;;ACzoFG;EACC,aAAA;AD4oFJ;;AC7oFG;EACC,aAAA;ADgpFJ;;ACjpFG;EACC,aAAA;ADopFJ;;ACrpFG;EACC,aAAA;ADwpFJ;;ACzpFG;EACC,aAAA;AD4pFJ;;AC7pFG;EACC,aAAA;ADgqFJ;;ACjqFG;EACC,aAAA;ADoqFJ;;ACrqFG;EACC,aAAA;ADwqFJ;;ACzqFG;EACC,aAAA;AD4qFJ;;AC7qFG;EACC,aAAA;ADgrFJ;;ACjrFG;EACC,aAAA;ADorFJ;;ACrrFG;EACC,aAAA;ADwrFJ;;ACzrFG;EACC,aAAA;AD4rFJ;;AC7rFG;EACC,aAAA;ADgsFJ;;ACjsFG;EACC,aAAA;ADosFJ;;ACrsFG;EACC,aAAA;ADwsFJ;;ACzsFG;EACC,aAAA;AD4sFJ;;ACvrFG;EACC,YAAA;AD0rFJ;;AC3rFG;EACC,YAAA;AD8rFJ;;AC/rFG;EACC,YAAA;ADksFJ;;ACnsFG;EACC,YAAA;ADssFJ;;ACvsFG;EACC,aAAA;AD0sFJ;;AC3sFG;EACC,aAAA;AD8sFJ;;AC/sFG;EACC,aAAA;ADktFJ;;ACntFG;EACC,aAAA;ADstFJ;;ACvtFG;EACC,aAAA;AD0tFJ;;AC3tFG;EACC,aAAA;AD8tFJ;;AC/tFG;EACC,aAAA;ADkuFJ;;ACnuFG;EACC,aAAA;ADsuFJ;;ACvuFG;EACC,aAAA;AD0uFJ;;AC3uFG;EACC,aAAA;AD8uFJ;;AC/uFG;EACC,aAAA;ADkvFJ;;ACnvFG;EACC,aAAA;ADsvFJ;;ACvvFG;EACC,aAAA;AD0vFJ;;AC3vFG;EACC,aAAA;AD8vFJ;;AC/vFG;EACC,aAAA;ADkwFJ;;ACnwFG;EACC,aAAA;ADswFJ;;ACvwFG;EACC,aAAA;AD0wFJ;;AC3wFG;EACC,aAAA;AD8wFJ;;AC/wFG;EACC,aAAA;ADkxFJ;;ACnxFG;EACC,aAAA;ADsxFJ;;ACvxFG;EACC,aAAA;AD0xFJ;;ACjzFG;EACC,gBAAA;ADozFJ;;ACrzFG;EACC,gBAAA;ADwzFJ;;ACzzFG;EACC,gBAAA;AD4zFJ;;AC7zFG;EACC,gBAAA;ADg0FJ;;ACj0FG;EACC,gBAAA;ADo0FJ;;ACr0FG;EACC,gBAAA;ADw0FJ;;ACz0FG;EACC,gBAAA;AD40FJ;;AC70FG;EACC,gBAAA;ADg1FJ;;ACj1FG;EACC,gBAAA;ADo1FJ;;ACr1FG;EACC,gBAAA;ADw1FJ;;ACz1FG;EACC,iBAAA;AD41FJ;;AC71FG;EACC,iBAAA;ADg2FJ;;ACj2FG;EACC,iBAAA;ADo2FJ;;ACr2FG;EACC,iBAAA;ADw2FJ;;ACz2FG;EACC,iBAAA;AD42FJ;;AC72FG;EACC,iBAAA;ADg3FJ;;ACj3FG;EACC,iBAAA;ADo3FJ;;ACr3FG;EACC,iBAAA;ADw3FJ;;ACz3FG;EACC,iBAAA;AD43FJ;;AC73FG;EACC,iBAAA;ADg4FJ;;ACj4FG;EACC,iBAAA;ADo4FJ;;ACr4FG;EACC,iBAAA;ADw4FJ;;ACz4FG;EACC,iBAAA;AD44FJ;;AC74FG;EACC,iBAAA;ADg5FJ;;ACj5FG;EACC,iBAAA;ADo5FJ;;ACr5FG;EACC,iBAAA;ADw5FJ;;ACz5FG;EACC,iBAAA;AD45FJ;;AC75FG;EACC,iBAAA;ADg6FJ;;ACj6FG;EACC,iBAAA;ADo6FJ;;ACr6FG;EACC,iBAAA;ADw6FJ;;ACz6FG;EACC,iBAAA;AD46FJ;;AC76FG;EACC,iBAAA;ADg7FJ;;ACj7FG;EACC,iBAAA;ADo7FJ;;ACr7FG;EACC,iBAAA;ADw7FJ;;ACz7FG;EACC,iBAAA;AD47FJ;;AC77FG;EACC,iBAAA;ADg8FJ;;ACj8FG;EACC,iBAAA;ADo8FJ;;ACr8FG;EACC,iBAAA;ADw8FJ;;ACz8FG;EACC,iBAAA;AD48FJ;;AC78FG;EACC,iBAAA;ADg9FJ;;ACj9FG;EACC,iBAAA;ADo9FJ;;ACr9FG;EACC,iBAAA;ADw9FJ;;ACz9FG;EACC,iBAAA;AD49FJ;;AC79FG;EACC,iBAAA;ADg+FJ;;ACj+FG;EACC,iBAAA;ADo+FJ;;ACr+FG;EACC,iBAAA;ADw+FJ;;ACz+FG;EACC,iBAAA;AD4+FJ;;AC7+FG;EACC,iBAAA;ADg/FJ;;ACj/FG;EACC,iBAAA;ADo/FJ;;ACr/FG;EACC,iBAAA;ADw/FJ;;ACz/FG;EACC,iBAAA;AD4/FJ;;ACv+FG;EACC,gBAAA;AD0+FJ;;AC3+FG;EACC,gBAAA;AD8+FJ;;AC/+FG;EACC,gBAAA;ADk/FJ;;ACn/FG;EACC,gBAAA;ADs/FJ;;ACv/FG;EACC,iBAAA;AD0/FJ;;AC3/FG;EACC,iBAAA;AD8/FJ;;AC//FG;EACC,iBAAA;ADkgGJ;;ACngGG;EACC,iBAAA;ADsgGJ;;ACvgGG;EACC,iBAAA;AD0gGJ;;AC3gGG;EACC,iBAAA;AD8gGJ;;AC/gGG;EACC,iBAAA;ADkhGJ;;ACnhGG;EACC,iBAAA;ADshGJ;;ACvhGG;EACC,iBAAA;AD0hGJ;;AC3hGG;EACC,iBAAA;AD8hGJ;;AC/hGG;EACC,iBAAA;ADkiGJ;;ACniGG;EACC,iBAAA;ADsiGJ;;ACviGG;EACC,iBAAA;AD0iGJ;;AC3iGG;EACC,iBAAA;AD8iGJ;;AC/iGG;EACC,iBAAA;ADkjGJ;;ACnjGG;EACC,iBAAA;ADsjGJ;;ACvjGG;EACC,iBAAA;AD0jGJ;;AC3jGG;EACC,iBAAA;AD8jGJ;;AC/jGG;EACC,iBAAA;ADkkGJ;;ACnkGG;EACC,iBAAA;ADskGJ;;ACvkGG;EACC,iBAAA;AD0kGJ;;ACjmGG;EACC,kBAAA;ADomGJ;;ACrmGG;EACC,kBAAA;ADwmGJ;;ACzmGG;EACC,kBAAA;AD4mGJ;;AC7mGG;EACC,kBAAA;ADgnGJ;;ACjnGG;EACC,kBAAA;ADonGJ;;ACrnGG;EACC,kBAAA;ADwnGJ;;ACznGG;EACC,kBAAA;AD4nGJ;;AC7nGG;EACC,kBAAA;ADgoGJ;;ACjoGG;EACC,kBAAA;ADooGJ;;ACroGG;EACC,kBAAA;ADwoGJ;;ACzoGG;EACC,mBAAA;AD4oGJ;;AC7oGG;EACC,mBAAA;ADgpGJ;;ACjpGG;EACC,mBAAA;ADopGJ;;ACrpGG;EACC,mBAAA;ADwpGJ;;ACzpGG;EACC,mBAAA;AD4pGJ;;AC7pGG;EACC,mBAAA;ADgqGJ;;ACjqGG;EACC,mBAAA;ADoqGJ;;ACrqGG;EACC,mBAAA;ADwqGJ;;ACzqGG;EACC,mBAAA;AD4qGJ;;AC7qGG;EACC,mBAAA;ADgrGJ;;ACjrGG;EACC,mBAAA;ADorGJ;;ACrrGG;EACC,mBAAA;ADwrGJ;;ACzrGG;EACC,mBAAA;AD4rGJ;;AC7rGG;EACC,mBAAA;ADgsGJ;;ACjsGG;EACC,mBAAA;ADosGJ;;ACrsGG;EACC,mBAAA;ADwsGJ;;ACzsGG;EACC,mBAAA;AD4sGJ;;AC7sGG;EACC,mBAAA;ADgtGJ;;ACjtGG;EACC,mBAAA;ADotGJ;;ACrtGG;EACC,mBAAA;ADwtGJ;;ACztGG;EACC,mBAAA;AD4tGJ;;AC7tGG;EACC,mBAAA;ADguGJ;;ACjuGG;EACC,mBAAA;ADouGJ;;ACruGG;EACC,mBAAA;ADwuGJ;;ACzuGG;EACC,mBAAA;AD4uGJ;;AC7uGG;EACC,mBAAA;ADgvGJ;;ACjvGG;EACC,mBAAA;ADovGJ;;ACrvGG;EACC,mBAAA;ADwvGJ;;ACzvGG;EACC,mBAAA;AD4vGJ;;AC7vGG;EACC,mBAAA;ADgwGJ;;ACjwGG;EACC,mBAAA;ADowGJ;;ACrwGG;EACC,mBAAA;ADwwGJ;;ACzwGG;EACC,mBAAA;AD4wGJ;;AC7wGG;EACC,mBAAA;ADgxGJ;;ACjxGG;EACC,mBAAA;ADoxGJ;;ACrxGG;EACC,mBAAA;ADwxGJ;;ACzxGG;EACC,mBAAA;AD4xGJ;;AC7xGG;EACC,mBAAA;ADgyGJ;;ACjyGG;EACC,mBAAA;ADoyGJ;;ACryGG;EACC,mBAAA;ADwyGJ;;ACzyGG;EACC,mBAAA;AD4yGJ;;ACvxGG;EACC,kBAAA;AD0xGJ;;AC3xGG;EACC,kBAAA;AD8xGJ;;AC/xGG;EACC,kBAAA;ADkyGJ;;ACnyGG;EACC,kBAAA;ADsyGJ;;ACvyGG;EACC,mBAAA;AD0yGJ;;AC3yGG;EACC,mBAAA;AD8yGJ;;AC/yGG;EACC,mBAAA;ADkzGJ;;ACnzGG;EACC,mBAAA;ADszGJ;;ACvzGG;EACC,mBAAA;AD0zGJ;;AC3zGG;EACC,mBAAA;AD8zGJ;;AC/zGG;EACC,mBAAA;ADk0GJ;;ACn0GG;EACC,mBAAA;ADs0GJ;;ACv0GG;EACC,mBAAA;AD00GJ;;AC30GG;EACC,mBAAA;AD80GJ;;AC/0GG;EACC,mBAAA;ADk1GJ;;ACn1GG;EACC,mBAAA;ADs1GJ;;ACv1GG;EACC,mBAAA;AD01GJ;;AC31GG;EACC,mBAAA;AD81GJ;;AC/1GG;EACC,mBAAA;ADk2GJ;;ACn2GG;EACC,mBAAA;ADs2GJ;;ACv2GG;EACC,mBAAA;AD02GJ;;AC32GG;EACC,mBAAA;AD82GJ;;AC/2GG;EACC,mBAAA;ADk3GJ;;ACn3GG;EACC,mBAAA;ADs3GJ;;ACv3GG;EACC,mBAAA;AD03GJ;;ACj5GG;EACC,mBAAA;ADo5GJ;;ACr5GG;EACC,mBAAA;ADw5GJ;;ACz5GG;EACC,mBAAA;AD45GJ;;AC75GG;EACC,mBAAA;ADg6GJ;;ACj6GG;EACC,mBAAA;ADo6GJ;;ACr6GG;EACC,mBAAA;ADw6GJ;;ACz6GG;EACC,mBAAA;AD46GJ;;AC76GG;EACC,mBAAA;ADg7GJ;;ACj7GG;EACC,mBAAA;ADo7GJ;;ACr7GG;EACC,mBAAA;ADw7GJ;;ACz7GG;EACC,oBAAA;AD47GJ;;AC77GG;EACC,oBAAA;ADg8GJ;;ACj8GG;EACC,oBAAA;ADo8GJ;;ACr8GG;EACC,oBAAA;ADw8GJ;;ACz8GG;EACC,oBAAA;AD48GJ;;AC78GG;EACC,oBAAA;ADg9GJ;;ACj9GG;EACC,oBAAA;ADo9GJ;;ACr9GG;EACC,oBAAA;ADw9GJ;;ACz9GG;EACC,oBAAA;AD49GJ;;AC79GG;EACC,oBAAA;ADg+GJ;;ACj+GG;EACC,oBAAA;ADo+GJ;;ACr+GG;EACC,oBAAA;ADw+GJ;;ACz+GG;EACC,oBAAA;AD4+GJ;;AC7+GG;EACC,oBAAA;ADg/GJ;;ACj/GG;EACC,oBAAA;ADo/GJ;;ACr/GG;EACC,oBAAA;ADw/GJ;;ACz/GG;EACC,oBAAA;AD4/GJ;;AC7/GG;EACC,oBAAA;ADggHJ;;ACjgHG;EACC,oBAAA;ADogHJ;;ACrgHG;EACC,oBAAA;ADwgHJ;;ACzgHG;EACC,oBAAA;AD4gHJ;;AC7gHG;EACC,oBAAA;ADghHJ;;ACjhHG;EACC,oBAAA;ADohHJ;;ACrhHG;EACC,oBAAA;ADwhHJ;;ACzhHG;EACC,oBAAA;AD4hHJ;;AC7hHG;EACC,oBAAA;ADgiHJ;;ACjiHG;EACC,oBAAA;ADoiHJ;;ACriHG;EACC,oBAAA;ADwiHJ;;ACziHG;EACC,oBAAA;AD4iHJ;;AC7iHG;EACC,oBAAA;ADgjHJ;;ACjjHG;EACC,oBAAA;ADojHJ;;ACrjHG;EACC,oBAAA;ADwjHJ;;ACzjHG;EACC,oBAAA;AD4jHJ;;AC7jHG;EACC,oBAAA;ADgkHJ;;ACjkHG;EACC,oBAAA;ADokHJ;;ACrkHG;EACC,oBAAA;ADwkHJ;;ACzkHG;EACC,oBAAA;AD4kHJ;;AC7kHG;EACC,oBAAA;ADglHJ;;ACjlHG;EACC,oBAAA;ADolHJ;;ACrlHG;EACC,oBAAA;ADwlHJ;;ACzlHG;EACC,oBAAA;AD4lHJ;;ACvkHG;EACC,mBAAA;AD0kHJ;;AC3kHG;EACC,mBAAA;AD8kHJ;;AC/kHG;EACC,mBAAA;ADklHJ;;ACnlHG;EACC,mBAAA;ADslHJ;;ACvlHG;EACC,oBAAA;AD0lHJ;;AC3lHG;EACC,oBAAA;AD8lHJ;;AC/lHG;EACC,oBAAA;ADkmHJ;;ACnmHG;EACC,oBAAA;ADsmHJ;;ACvmHG;EACC,oBAAA;AD0mHJ;;AC3mHG;EACC,oBAAA;AD8mHJ;;AC/mHG;EACC,oBAAA;ADknHJ;;ACnnHG;EACC,oBAAA;ADsnHJ;;ACvnHG;EACC,oBAAA;AD0nHJ;;AC3nHG;EACC,oBAAA;AD8nHJ;;AC/nHG;EACC,oBAAA;ADkoHJ;;ACnoHG;EACC,oBAAA;ADsoHJ;;ACvoHG;EACC,oBAAA;AD0oHJ;;AC3oHG;EACC,oBAAA;AD8oHJ;;AC/oHG;EACC,oBAAA;ADkpHJ;;ACnpHG;EACC,oBAAA;ADspHJ;;ACvpHG;EACC,oBAAA;AD0pHJ;;AC3pHG;EACC,oBAAA;AD8pHJ;;AC/pHG;EACC,oBAAA;ADkqHJ;;ACnqHG;EACC,oBAAA;ADsqHJ;;ACvqHG;EACC,oBAAA;AD0qHJ;;ACjsHG;EACC,iBAAA;ADosHJ;;ACrsHG;EACC,iBAAA;ADwsHJ;;ACzsHG;EACC,iBAAA;AD4sHJ;;AC7sHG;EACC,iBAAA;ADgtHJ;;ACjtHG;EACC,iBAAA;ADotHJ;;ACrtHG;EACC,iBAAA;ADwtHJ;;ACztHG;EACC,iBAAA;AD4tHJ;;AC7tHG;EACC,iBAAA;ADguHJ;;ACjuHG;EACC,iBAAA;ADouHJ;;ACruHG;EACC,iBAAA;ADwuHJ;;ACzuHG;EACC,kBAAA;AD4uHJ;;AC7uHG;EACC,kBAAA;ADgvHJ;;ACjvHG;EACC,kBAAA;ADovHJ;;ACrvHG;EACC,kBAAA;ADwvHJ;;ACzvHG;EACC,kBAAA;AD4vHJ;;AC7vHG;EACC,kBAAA;ADgwHJ;;ACjwHG;EACC,kBAAA;ADowHJ;;ACrwHG;EACC,kBAAA;ADwwHJ;;ACzwHG;EACC,kBAAA;AD4wHJ;;AC7wHG;EACC,kBAAA;ADgxHJ;;ACjxHG;EACC,kBAAA;ADoxHJ;;ACrxHG;EACC,kBAAA;ADwxHJ;;ACzxHG;EACC,kBAAA;AD4xHJ;;AC7xHG;EACC,kBAAA;ADgyHJ;;ACjyHG;EACC,kBAAA;ADoyHJ;;ACryHG;EACC,kBAAA;ADwyHJ;;ACzyHG;EACC,kBAAA;AD4yHJ;;AC7yHG;EACC,kBAAA;ADgzHJ;;ACjzHG;EACC,kBAAA;ADozHJ;;ACrzHG;EACC,kBAAA;ADwzHJ;;ACzzHG;EACC,kBAAA;AD4zHJ;;AC7zHG;EACC,kBAAA;ADg0HJ;;ACj0HG;EACC,kBAAA;ADo0HJ;;ACr0HG;EACC,kBAAA;ADw0HJ;;ACz0HG;EACC,kBAAA;AD40HJ;;AC70HG;EACC,kBAAA;ADg1HJ;;ACj1HG;EACC,kBAAA;ADo1HJ;;ACr1HG;EACC,kBAAA;ADw1HJ;;ACz1HG;EACC,kBAAA;AD41HJ;;AC71HG;EACC,kBAAA;ADg2HJ;;ACj2HG;EACC,kBAAA;ADo2HJ;;ACr2HG;EACC,kBAAA;ADw2HJ;;ACz2HG;EACC,kBAAA;AD42HJ;;AC72HG;EACC,kBAAA;ADg3HJ;;ACj3HG;EACC,kBAAA;ADo3HJ;;ACr3HG;EACC,kBAAA;ADw3HJ;;ACz3HG;EACC,kBAAA;AD43HJ;;AC73HG;EACC,kBAAA;ADg4HJ;;ACj4HG;EACC,kBAAA;ADo4HJ;;ACr4HG;EACC,kBAAA;ADw4HJ;;ACz4HG;EACC,kBAAA;AD44HJ;;ACv3HG;EACC,iBAAA;AD03HJ;;AC33HG;EACC,iBAAA;AD83HJ;;AC/3HG;EACC,iBAAA;ADk4HJ;;ACn4HG;EACC,iBAAA;ADs4HJ;;ACv4HG;EACC,kBAAA;AD04HJ;;AC34HG;EACC,kBAAA;AD84HJ;;AC/4HG;EACC,kBAAA;ADk5HJ;;ACn5HG;EACC,kBAAA;ADs5HJ;;ACv5HG;EACC,kBAAA;AD05HJ;;AC35HG;EACC,kBAAA;AD85HJ;;AC/5HG;EACC,kBAAA;ADk6HJ;;ACn6HG;EACC,kBAAA;ADs6HJ;;ACv6HG;EACC,kBAAA;AD06HJ;;AC36HG;EACC,kBAAA;AD86HJ;;AC/6HG;EACC,kBAAA;ADk7HJ;;ACn7HG;EACC,kBAAA;ADs7HJ;;ACv7HG;EACC,kBAAA;AD07HJ;;AC37HG;EACC,kBAAA;AD87HJ;;AC/7HG;EACC,kBAAA;ADk8HJ;;ACn8HG;EACC,kBAAA;ADs8HJ;;ACv8HG;EACC,kBAAA;AD08HJ;;AC38HG;EACC,kBAAA;AD88HJ;;AC/8HG;EACC,kBAAA;ADk9HJ;;ACn9HG;EACC,kBAAA;ADs9HJ;;ACv9HG;EACC,kBAAA;AD09HJ;;AC3+HG;EACC,iBAAA;EACA,kBAAA;AD8+HJ;;ACh/HG;EACC,iBAAA;EACA,kBAAA;ADm/HJ;;ACr/HG;EACC,iBAAA;EACA,kBAAA;ADw/HJ;;AC1/HG;EACC,iBAAA;EACA,kBAAA;AD6/HJ;;AC//HG;EACC,iBAAA;EACA,kBAAA;ADkgIJ;;ACpgIG;EACC,iBAAA;EACA,kBAAA;ADugIJ;;ACzgIG;EACC,iBAAA;EACA,kBAAA;AD4gIJ;;AC9gIG;EACC,iBAAA;EACA,kBAAA;ADihIJ;;ACnhIG;EACC,iBAAA;EACA,kBAAA;ADshIJ;;ACxhIG;EACC,iBAAA;EACA,kBAAA;AD2hIJ;;AC7hIG;EACC,kBAAA;EACA,mBAAA;ADgiIJ;;ACliIG;EACC,kBAAA;EACA,mBAAA;ADqiIJ;;ACviIG;EACC,kBAAA;EACA,mBAAA;AD0iIJ;;AC5iIG;EACC,kBAAA;EACA,mBAAA;AD+iIJ;;ACjjIG;EACC,kBAAA;EACA,mBAAA;ADojIJ;;ACtjIG;EACC,kBAAA;EACA,mBAAA;ADyjIJ;;AC3jIG;EACC,kBAAA;EACA,mBAAA;AD8jIJ;;AChkIG;EACC,kBAAA;EACA,mBAAA;ADmkIJ;;ACrkIG;EACC,kBAAA;EACA,mBAAA;ADwkIJ;;AC1kIG;EACC,kBAAA;EACA,mBAAA;AD6kIJ;;AC/kIG;EACC,kBAAA;EACA,mBAAA;ADklIJ;;ACplIG;EACC,kBAAA;EACA,mBAAA;ADulIJ;;ACzlIG;EACC,kBAAA;EACA,mBAAA;AD4lIJ;;AC9lIG;EACC,kBAAA;EACA,mBAAA;ADimIJ;;ACnmIG;EACC,kBAAA;EACA,mBAAA;ADsmIJ;;ACxmIG;EACC,kBAAA;EACA,mBAAA;AD2mIJ;;AC7mIG;EACC,kBAAA;EACA,mBAAA;ADgnIJ;;AClnIG;EACC,kBAAA;EACA,mBAAA;ADqnIJ;;ACvnIG;EACC,kBAAA;EACA,mBAAA;AD0nIJ;;AC5nIG;EACC,kBAAA;EACA,mBAAA;AD+nIJ;;ACjoIG;EACC,kBAAA;EACA,mBAAA;ADooIJ;;ACtoIG;EACC,kBAAA;EACA,mBAAA;ADyoIJ;;AC3oIG;EACC,kBAAA;EACA,mBAAA;AD8oIJ;;AChpIG;EACC,kBAAA;EACA,mBAAA;ADmpIJ;;ACrpIG;EACC,kBAAA;EACA,mBAAA;ADwpIJ;;AC1pIG;EACC,kBAAA;EACA,mBAAA;AD6pIJ;;AC/pIG;EACC,kBAAA;EACA,mBAAA;ADkqIJ;;ACpqIG;EACC,kBAAA;EACA,mBAAA;ADuqIJ;;ACzqIG;EACC,kBAAA;EACA,mBAAA;AD4qIJ;;AC9qIG;EACC,kBAAA;EACA,mBAAA;ADirIJ;;ACnrIG;EACC,kBAAA;EACA,mBAAA;ADsrIJ;;ACxrIG;EACC,kBAAA;EACA,mBAAA;AD2rIJ;;AC7rIG;EACC,kBAAA;EACA,mBAAA;ADgsIJ;;AClsIG;EACC,kBAAA;EACA,mBAAA;ADqsIJ;;ACvsIG;EACC,kBAAA;EACA,mBAAA;AD0sIJ;;AC5sIG;EACC,kBAAA;EACA,mBAAA;AD+sIJ;;ACjtIG;EACC,kBAAA;EACA,mBAAA;ADotIJ;;ACttIG;EACC,kBAAA;EACA,mBAAA;ADytIJ;;AC3tIG;EACC,kBAAA;EACA,mBAAA;AD8tIJ;;AChuIG;EACC,kBAAA;EACA,mBAAA;ADmuIJ;;ACruIG;EACC,kBAAA;EACA,mBAAA;ADwuIJ;;ACptIG;EACC,iBAAA;EACA,kBAAA;ADutIJ;;ACztIG;EACC,iBAAA;EACA,kBAAA;AD4tIJ;;AC9tIG;EACC,iBAAA;EACA,kBAAA;ADiuIJ;;ACnuIG;EACC,iBAAA;EACA,kBAAA;ADsuIJ;;ACxuIG;EACC,kBAAA;EACA,mBAAA;AD2uIJ;;AC7uIG;EACC,kBAAA;EACA,mBAAA;ADgvIJ;;AClvIG;EACC,kBAAA;EACA,mBAAA;ADqvIJ;;ACvvIG;EACC,kBAAA;EACA,mBAAA;AD0vIJ;;AC5vIG;EACC,kBAAA;EACA,mBAAA;AD+vIJ;;ACjwIG;EACC,kBAAA;EACA,mBAAA;ADowIJ;;ACtwIG;EACC,kBAAA;EACA,mBAAA;ADywIJ;;AC3wIG;EACC,kBAAA;EACA,mBAAA;AD8wIJ;;AChxIG;EACC,kBAAA;EACA,mBAAA;ADmxIJ;;ACrxIG;EACC,kBAAA;EACA,mBAAA;ADwxIJ;;AC1xIG;EACC,kBAAA;EACA,mBAAA;AD6xIJ;;AC/xIG;EACC,kBAAA;EACA,mBAAA;ADkyIJ;;ACpyIG;EACC,kBAAA;EACA,mBAAA;ADuyIJ;;ACzyIG;EACC,kBAAA;EACA,mBAAA;AD4yIJ;;AC9yIG;EACC,kBAAA;EACA,mBAAA;ADizIJ;;ACnzIG;EACC,kBAAA;EACA,mBAAA;ADszIJ;;ACxzIG;EACC,kBAAA;EACA,mBAAA;AD2zIJ;;AC7zIG;EACC,kBAAA;EACA,mBAAA;ADg0IJ;;ACl0IG;EACC,kBAAA;EACA,mBAAA;ADq0IJ;;ACv0IG;EACC,kBAAA;EACA,mBAAA;AD00IJ;;AC50IG;EACC,kBAAA;EACA,mBAAA;AD+0IJ;;ACh2IG;EACC,gBAAA;EACA,mBAAA;ADm2IJ;;ACr2IG;EACC,gBAAA;EACA,mBAAA;ADw2IJ;;AC12IG;EACC,gBAAA;EACA,mBAAA;AD62IJ;;AC/2IG;EACC,gBAAA;EACA,mBAAA;ADk3IJ;;ACp3IG;EACC,gBAAA;EACA,mBAAA;ADu3IJ;;ACz3IG;EACC,gBAAA;EACA,mBAAA;AD43IJ;;AC93IG;EACC,gBAAA;EACA,mBAAA;ADi4IJ;;ACn4IG;EACC,gBAAA;EACA,mBAAA;ADs4IJ;;ACx4IG;EACC,gBAAA;EACA,mBAAA;AD24IJ;;AC74IG;EACC,gBAAA;EACA,mBAAA;ADg5IJ;;ACl5IG;EACC,iBAAA;EACA,oBAAA;ADq5IJ;;ACv5IG;EACC,iBAAA;EACA,oBAAA;AD05IJ;;AC55IG;EACC,iBAAA;EACA,oBAAA;AD+5IJ;;ACj6IG;EACC,iBAAA;EACA,oBAAA;ADo6IJ;;ACt6IG;EACC,iBAAA;EACA,oBAAA;ADy6IJ;;AC36IG;EACC,iBAAA;EACA,oBAAA;AD86IJ;;ACh7IG;EACC,iBAAA;EACA,oBAAA;ADm7IJ;;ACr7IG;EACC,iBAAA;EACA,oBAAA;ADw7IJ;;AC17IG;EACC,iBAAA;EACA,oBAAA;AD67IJ;;AC/7IG;EACC,iBAAA;EACA,oBAAA;ADk8IJ;;ACp8IG;EACC,iBAAA;EACA,oBAAA;ADu8IJ;;ACz8IG;EACC,iBAAA;EACA,oBAAA;AD48IJ;;AC98IG;EACC,iBAAA;EACA,oBAAA;ADi9IJ;;ACn9IG;EACC,iBAAA;EACA,oBAAA;ADs9IJ;;ACx9IG;EACC,iBAAA;EACA,oBAAA;AD29IJ;;AC79IG;EACC,iBAAA;EACA,oBAAA;ADg+IJ;;ACl+IG;EACC,iBAAA;EACA,oBAAA;ADq+IJ;;ACv+IG;EACC,iBAAA;EACA,oBAAA;AD0+IJ;;AC5+IG;EACC,iBAAA;EACA,oBAAA;AD++IJ;;ACj/IG;EACC,iBAAA;EACA,oBAAA;ADo/IJ;;ACt/IG;EACC,iBAAA;EACA,oBAAA;ADy/IJ;;AC3/IG;EACC,iBAAA;EACA,oBAAA;AD8/IJ;;AChgJG;EACC,iBAAA;EACA,oBAAA;ADmgJJ;;ACrgJG;EACC,iBAAA;EACA,oBAAA;ADwgJJ;;AC1gJG;EACC,iBAAA;EACA,oBAAA;AD6gJJ;;AC/gJG;EACC,iBAAA;EACA,oBAAA;ADkhJJ;;ACphJG;EACC,iBAAA;EACA,oBAAA;ADuhJJ;;ACzhJG;EACC,iBAAA;EACA,oBAAA;AD4hJJ;;AC9hJG;EACC,iBAAA;EACA,oBAAA;ADiiJJ;;ACniJG;EACC,iBAAA;EACA,oBAAA;ADsiJJ;;ACxiJG;EACC,iBAAA;EACA,oBAAA;AD2iJJ;;AC7iJG;EACC,iBAAA;EACA,oBAAA;ADgjJJ;;ACljJG;EACC,iBAAA;EACA,oBAAA;ADqjJJ;;ACvjJG;EACC,iBAAA;EACA,oBAAA;AD0jJJ;;AC5jJG;EACC,iBAAA;EACA,oBAAA;AD+jJJ;;ACjkJG;EACC,iBAAA;EACA,oBAAA;ADokJJ;;ACtkJG;EACC,iBAAA;EACA,oBAAA;ADykJJ;;AC3kJG;EACC,iBAAA;EACA,oBAAA;AD8kJJ;;AChlJG;EACC,iBAAA;EACA,oBAAA;ADmlJJ;;ACrlJG;EACC,iBAAA;EACA,oBAAA;ADwlJJ;;AC1lJG;EACC,iBAAA;EACA,oBAAA;AD6lJJ;;ACzkJG;EACC,gBAAA;EACA,mBAAA;AD4kJJ;;AC9kJG;EACC,gBAAA;EACA,mBAAA;ADilJJ;;ACnlJG;EACC,gBAAA;EACA,mBAAA;ADslJJ;;ACxlJG;EACC,gBAAA;EACA,mBAAA;AD2lJJ;;AC7lJG;EACC,iBAAA;EACA,oBAAA;ADgmJJ;;AClmJG;EACC,iBAAA;EACA,oBAAA;ADqmJJ;;ACvmJG;EACC,iBAAA;EACA,oBAAA;AD0mJJ;;AC5mJG;EACC,iBAAA;EACA,oBAAA;AD+mJJ;;ACjnJG;EACC,iBAAA;EACA,oBAAA;ADonJJ;;ACtnJG;EACC,iBAAA;EACA,oBAAA;ADynJJ;;AC3nJG;EACC,iBAAA;EACA,oBAAA;AD8nJJ;;AChoJG;EACC,iBAAA;EACA,oBAAA;ADmoJJ;;ACroJG;EACC,iBAAA;EACA,oBAAA;ADwoJJ;;AC1oJG;EACC,iBAAA;EACA,oBAAA;AD6oJJ;;AC/oJG;EACC,iBAAA;EACA,oBAAA;ADkpJJ;;ACppJG;EACC,iBAAA;EACA,oBAAA;ADupJJ;;ACzpJG;EACC,iBAAA;EACA,oBAAA;AD4pJJ;;AC9pJG;EACC,iBAAA;EACA,oBAAA;ADiqJJ;;ACnqJG;EACC,iBAAA;EACA,oBAAA;ADsqJJ;;ACxqJG;EACC,iBAAA;EACA,oBAAA;AD2qJJ;;AC7qJG;EACC,iBAAA;EACA,oBAAA;ADgrJJ;;AClrJG;EACC,iBAAA;EACA,oBAAA;ADqrJJ;;ACvrJG;EACC,iBAAA;EACA,oBAAA;AD0rJJ;;AC5rJG;EACC,iBAAA;EACA,oBAAA;AD+rJJ;;ACjsJG;EACC,iBAAA;EACA,oBAAA;ADosJJ;;AC1rJG;EACC,WAAA;AD6rJJ;;AC9rJG;EACC,WAAA;ADisJJ;;AClsJG;EACC,WAAA;ADqsJJ;;ACtsJG;EACC,WAAA;ADysJJ;;AC1sJG;EACC,WAAA;AD6sJJ;;AC9sJG;EACC,WAAA;ADitJJ;;ACltJG;EACC,WAAA;ADqtJJ;;ACttJG;EACC,WAAA;ADytJJ;;AC1tJG;EACC,WAAA;AD6tJJ;;AC9tJG;EACC,WAAA;ADiuJJ;;ACluJG;EACC,YAAA;ADquJJ;;ACtuJG;EACC,YAAA;ADyuJJ;;AC1uJG;EACC,YAAA;AD6uJJ;;AC9uJG;EACC,YAAA;ADivJJ;;AClvJG;EACC,YAAA;ADqvJJ;;ACtvJG;EACC,YAAA;ADyvJJ;;AC1vJG;EACC,YAAA;AD6vJJ;;AC9vJG;EACC,YAAA;ADiwJJ;;AClwJG;EACC,YAAA;ADqwJJ;;ACtwJG;EACC,YAAA;ADywJJ;;AC1wJG;EACC,YAAA;AD6wJJ;;AC9wJG;EACC,YAAA;ADixJJ;;AClxJG;EACC,YAAA;ADqxJJ;;ACtxJG;EACC,YAAA;ADyxJJ;;AC1xJG;EACC,YAAA;AD6xJJ;;AC9xJG;EACC,YAAA;ADiyJJ;;AClyJG;EACC,YAAA;ADqyJJ;;ACtyJG;EACC,YAAA;ADyyJJ;;AC1yJG;EACC,YAAA;AD6yJJ;;AC9yJG;EACC,YAAA;ADizJJ;;AClzJG;EACC,YAAA;ADqzJJ;;ACtzJG;EACC,YAAA;ADyzJJ;;AC1zJG;EACC,YAAA;AD6zJJ;;AC9zJG;EACC,YAAA;ADi0JJ;;ACl0JG;EACC,YAAA;ADq0JJ;;ACt0JG;EACC,YAAA;ADy0JJ;;AC10JG;EACC,YAAA;AD60JJ;;AC90JG;EACC,YAAA;ADi1JJ;;ACl1JG;EACC,YAAA;ADq1JJ;;ACt1JG;EACC,YAAA;ADy1JJ;;AC11JG;EACC,YAAA;AD61JJ;;AC91JG;EACC,YAAA;ADi2JJ;;ACl2JG;EACC,YAAA;ADq2JJ;;ACt2JG;EACC,YAAA;ADy2JJ;;AC12JG;EACC,YAAA;AD62JJ;;AC92JG;EACC,YAAA;ADi3JJ;;ACl3JG;EACC,YAAA;ADq3JJ;;ACt3JG;EACC,YAAA;ADy3JJ;;AC13JG;EACC,YAAA;AD63JJ;;AC93JG;EACC,YAAA;ADi4JJ;;ACl4JG;EACC,YAAA;ADq4JJ;;AC32JG;EACC,WAAA;AD82JJ;;AC/2JG;EACC,WAAA;ADk3JJ;;ACn3JG;EACC,WAAA;ADs3JJ;;ACv3JG;EACC,WAAA;AD03JJ;;AC33JG;EACC,YAAA;AD83JJ;;AC/3JG;EACC,YAAA;ADk4JJ;;ACn4JG;EACC,YAAA;ADs4JJ;;ACv4JG;EACC,YAAA;AD04JJ;;AC34JG;EACC,YAAA;AD84JJ;;AC/4JG;EACC,YAAA;ADk5JJ;;ACn5JG;EACC,YAAA;ADs5JJ;;ACv5JG;EACC,YAAA;AD05JJ;;AC35JG;EACC,YAAA;AD85JJ;;AC/5JG;EACC,YAAA;ADk6JJ;;ACn6JG;EACC,YAAA;ADs6JJ;;ACv6JG;EACC,YAAA;AD06JJ;;AC36JG;EACC,YAAA;AD86JJ;;AC/6JG;EACC,YAAA;ADk7JJ;;ACn7JG;EACC,YAAA;ADs7JJ;;ACv7JG;EACC,YAAA;AD07JJ;;AC37JG;EACC,YAAA;AD87JJ;;AC/7JG;EACC,YAAA;ADk8JJ;;ACn8JG;EACC,YAAA;ADs8JJ;;ACv8JG;EACC,YAAA;AD08JJ;;AC38JG;EACC,YAAA;AD88JJ;;AC1+JG;EACC,eAAA;AD6+JJ;;ACz+JI;EACC,gBAAA;AD4+JL;;ACl/JG;EACC,eAAA;ADq/JJ;;ACj/JI;EACC,gBAAA;ADo/JL;;AC1/JG;EACC,eAAA;AD6/JJ;;ACz/JI;EACC,gBAAA;AD4/JL;;AClgKG;EACC,eAAA;ADqgKJ;;ACjgKI;EACC,gBAAA;ADogKL;;AC1gKG;EACC,eAAA;AD6gKJ;;ACzgKI;EACC,gBAAA;AD4gKL;;AClhKG;EACC,eAAA;ADqhKJ;;ACjhKI;EACC,gBAAA;ADohKL;;AC1hKG;EACC,eAAA;AD6hKJ;;ACzhKI;EACC,gBAAA;AD4hKL;;ACliKG;EACC,eAAA;ADqiKJ;;ACjiKI;EACC,gBAAA;ADoiKL;;AC1iKG;EACC,eAAA;AD6iKJ;;ACziKI;EACC,gBAAA;AD4iKL;;ACljKG;EACC,eAAA;ADqjKJ;;ACjjKI;EACC,gBAAA;ADojKL;;AC1jKG;EACC,gBAAA;AD6jKJ;;ACzjKI;EACC,iBAAA;AD4jKL;;AClkKG;EACC,gBAAA;ADqkKJ;;ACjkKI;EACC,iBAAA;ADokKL;;AC1kKG;EACC,gBAAA;AD6kKJ;;ACzkKI;EACC,iBAAA;AD4kKL;;ACllKG;EACC,gBAAA;ADqlKJ;;ACjlKI;EACC,iBAAA;ADolKL;;AC1lKG;EACC,gBAAA;AD6lKJ;;ACzlKI;EACC,iBAAA;AD4lKL;;AClmKG;EACC,gBAAA;ADqmKJ;;ACjmKI;EACC,iBAAA;ADomKL;;AC1mKG;EACC,gBAAA;AD6mKJ;;ACzmKI;EACC,iBAAA;AD4mKL;;AClnKG;EACC,gBAAA;ADqnKJ;;ACjnKI;EACC,iBAAA;ADonKL;;AC1nKG;EACC,gBAAA;AD6nKJ;;ACznKI;EACC,iBAAA;AD4nKL;;ACloKG;EACC,gBAAA;ADqoKJ;;ACjoKI;EACC,iBAAA;ADooKL;;AC1oKG;EACC,gBAAA;AD6oKJ;;ACzoKI;EACC,iBAAA;AD4oKL;;AClpKG;EACC,gBAAA;ADqpKJ;;ACjpKI;EACC,iBAAA;ADopKL;;AC1pKG;EACC,gBAAA;AD6pKJ;;ACzpKI;EACC,iBAAA;AD4pKL;;AClqKG;EACC,gBAAA;ADqqKJ;;ACjqKI;EACC,iBAAA;ADoqKL;;AC1qKG;EACC,gBAAA;AD6qKJ;;ACzqKI;EACC,iBAAA;AD4qKL;;AClrKG;EACC,gBAAA;ADqrKJ;;ACjrKI;EACC,iBAAA;ADorKL;;AC1rKG;EACC,gBAAA;AD6rKJ;;ACzrKI;EACC,iBAAA;AD4rKL;;AClsKG;EACC,gBAAA;ADqsKJ;;ACjsKI;EACC,iBAAA;ADosKL;;AC1sKG;EACC,gBAAA;AD6sKJ;;ACzsKI;EACC,iBAAA;AD4sKL;;ACltKG;EACC,gBAAA;ADqtKJ;;ACjtKI;EACC,iBAAA;ADotKL;;AC1tKG;EACC,gBAAA;AD6tKJ;;ACztKI;EACC,iBAAA;AD4tKL;;ACluKG;EACC,gBAAA;ADquKJ;;ACjuKI;EACC,iBAAA;ADouKL;;AC1uKG;EACC,gBAAA;AD6uKJ;;ACzuKI;EACC,iBAAA;AD4uKL;;AClvKG;EACC,gBAAA;ADqvKJ;;ACjvKI;EACC,iBAAA;ADovKL;;AC1vKG;EACC,gBAAA;AD6vKJ;;ACzvKI;EACC,iBAAA;AD4vKL;;AClwKG;EACC,gBAAA;ADqwKJ;;ACjwKI;EACC,iBAAA;ADowKL;;AC1wKG;EACC,gBAAA;AD6wKJ;;ACzwKI;EACC,iBAAA;AD4wKL;;AClxKG;EACC,gBAAA;ADqxKJ;;ACjxKI;EACC,iBAAA;ADoxKL;;AC1xKG;EACC,gBAAA;AD6xKJ;;ACzxKI;EACC,iBAAA;AD4xKL;;AClyKG;EACC,gBAAA;ADqyKJ;;ACjyKI;EACC,iBAAA;ADoyKL;;AC1yKG;EACC,gBAAA;AD6yKJ;;ACzyKI;EACC,iBAAA;AD4yKL;;AClzKG;EACC,gBAAA;ADqzKJ;;ACjzKI;EACC,iBAAA;ADozKL;;AC1zKG;EACC,gBAAA;AD6zKJ;;ACzzKI;EACC,iBAAA;AD4zKL;;ACl0KG;EACC,gBAAA;ADq0KJ;;ACj0KI;EACC,iBAAA;ADo0KL;;AC10KG;EACC,gBAAA;AD60KJ;;ACz0KI;EACC,iBAAA;AD40KL;;ACl1KG;EACC,gBAAA;ADq1KJ;;ACj1KI;EACC,iBAAA;ADo1KL;;AC11KG;EACC,gBAAA;AD61KJ;;ACz1KI;EACC,iBAAA;AD41KL;;ACl2KG;EACC,gBAAA;ADq2KJ;;ACj2KI;EACC,iBAAA;ADo2KL;;AC12KG;EACC,gBAAA;AD62KJ;;ACz2KI;EACC,iBAAA;AD42KL;;ACl3KG;EACC,gBAAA;ADq3KJ;;ACj3KI;EACC,iBAAA;ADo3KL;;AC13KG;EACC,gBAAA;AD63KJ;;ACz3KI;EACC,iBAAA;AD43KL;;ACv2KG;EACC,eAAA;AD02KJ;;ACt2KI;EACC,gBAAA;ADy2KL;;AC/2KG;EACC,eAAA;ADk3KJ;;AC92KI;EACC,gBAAA;ADi3KL;;ACv3KG;EACC,eAAA;AD03KJ;;ACt3KI;EACC,gBAAA;ADy3KL;;AC/3KG;EACC,eAAA;ADk4KJ;;AC93KI;EACC,gBAAA;ADi4KL;;ACv4KG;EACC,gBAAA;AD04KJ;;ACt4KI;EACC,iBAAA;ADy4KL;;AC/4KG;EACC,gBAAA;ADk5KJ;;AC94KI;EACC,iBAAA;ADi5KL;;ACv5KG;EACC,gBAAA;AD05KJ;;ACt5KI;EACC,iBAAA;ADy5KL;;AC/5KG;EACC,gBAAA;ADk6KJ;;AC95KI;EACC,iBAAA;ADi6KL;;ACv6KG;EACC,gBAAA;AD06KJ;;ACt6KI;EACC,iBAAA;ADy6KL;;AC/6KG;EACC,gBAAA;ADk7KJ;;AC96KI;EACC,iBAAA;ADi7KL;;ACv7KG;EACC,gBAAA;AD07KJ;;ACt7KI;EACC,iBAAA;ADy7KL;;AC/7KG;EACC,gBAAA;ADk8KJ;;AC97KI;EACC,iBAAA;ADi8KL;;ACv8KG;EACC,gBAAA;AD08KJ;;ACt8KI;EACC,iBAAA;ADy8KL;;AC/8KG;EACC,gBAAA;ADk9KJ;;AC98KI;EACC,iBAAA;ADi9KL;;ACv9KG;EACC,gBAAA;AD09KJ;;ACt9KI;EACC,iBAAA;ADy9KL;;AC/9KG;EACC,gBAAA;ADk+KJ;;AC99KI;EACC,iBAAA;ADi+KL;;ACv+KG;EACC,gBAAA;AD0+KJ;;ACt+KI;EACC,iBAAA;ADy+KL;;AC/+KG;EACC,gBAAA;ADk/KJ;;AC9+KI;EACC,iBAAA;ADi/KL;;ACv/KG;EACC,gBAAA;AD0/KJ;;ACt/KI;EACC,iBAAA;ADy/KL;;AC//KG;EACC,gBAAA;ADkgLJ;;AC9/KI;EACC,iBAAA;ADigLL;;ACvgLG;EACC,gBAAA;AD0gLJ;;ACtgLI;EACC,iBAAA;ADygLL;;AC/gLG;EACC,gBAAA;ADkhLJ;;AC9gLI;EACC,iBAAA;ADihLL;;ACvhLG;EACC,gBAAA;AD0hLJ;;ACthLI;EACC,iBAAA;ADyhLL;;AC/hLG;EACC,gBAAA;ADkiLJ;;AC9hLI;EACC,iBAAA;ADiiLL;;ACviLG;EACC,gBAAA;AD0iLJ;;ACtiLI;EACC,iBAAA;ADyiLL;;AC1kLG;EACC,iBAAA;AD6kLJ;;ACzkLI;EACC,kBAAA;AD4kLL;;ACllLG;EACC,iBAAA;ADqlLJ;;ACjlLI;EACC,kBAAA;ADolLL;;AC1lLG;EACC,iBAAA;AD6lLJ;;ACzlLI;EACC,kBAAA;AD4lLL;;AClmLG;EACC,iBAAA;ADqmLJ;;ACjmLI;EACC,kBAAA;ADomLL;;AC1mLG;EACC,iBAAA;AD6mLJ;;ACzmLI;EACC,kBAAA;AD4mLL;;AClnLG;EACC,iBAAA;ADqnLJ;;ACjnLI;EACC,kBAAA;ADonLL;;AC1nLG;EACC,iBAAA;AD6nLJ;;ACznLI;EACC,kBAAA;AD4nLL;;ACloLG;EACC,iBAAA;ADqoLJ;;ACjoLI;EACC,kBAAA;ADooLL;;AC1oLG;EACC,iBAAA;AD6oLJ;;ACzoLI;EACC,kBAAA;AD4oLL;;AClpLG;EACC,iBAAA;ADqpLJ;;ACjpLI;EACC,kBAAA;ADopLL;;AC1pLG;EACC,kBAAA;AD6pLJ;;ACzpLI;EACC,mBAAA;AD4pLL;;AClqLG;EACC,kBAAA;ADqqLJ;;ACjqLI;EACC,mBAAA;ADoqLL;;AC1qLG;EACC,kBAAA;AD6qLJ;;ACzqLI;EACC,mBAAA;AD4qLL;;AClrLG;EACC,kBAAA;ADqrLJ;;ACjrLI;EACC,mBAAA;ADorLL;;AC1rLG;EACC,kBAAA;AD6rLJ;;ACzrLI;EACC,mBAAA;AD4rLL;;AClsLG;EACC,kBAAA;ADqsLJ;;ACjsLI;EACC,mBAAA;ADosLL;;AC1sLG;EACC,kBAAA;AD6sLJ;;ACzsLI;EACC,mBAAA;AD4sLL;;ACltLG;EACC,kBAAA;ADqtLJ;;ACjtLI;EACC,mBAAA;ADotLL;;AC1tLG;EACC,kBAAA;AD6tLJ;;ACztLI;EACC,mBAAA;AD4tLL;;ACluLG;EACC,kBAAA;ADquLJ;;ACjuLI;EACC,mBAAA;ADouLL;;AC1uLG;EACC,kBAAA;AD6uLJ;;ACzuLI;EACC,mBAAA;AD4uLL;;AClvLG;EACC,kBAAA;ADqvLJ;;ACjvLI;EACC,mBAAA;ADovLL;;AC1vLG;EACC,kBAAA;AD6vLJ;;ACzvLI;EACC,mBAAA;AD4vLL;;AClwLG;EACC,kBAAA;ADqwLJ;;ACjwLI;EACC,mBAAA;ADowLL;;AC1wLG;EACC,kBAAA;AD6wLJ;;ACzwLI;EACC,mBAAA;AD4wLL;;AClxLG;EACC,kBAAA;ADqxLJ;;ACjxLI;EACC,mBAAA;ADoxLL;;AC1xLG;EACC,kBAAA;AD6xLJ;;ACzxLI;EACC,mBAAA;AD4xLL;;AClyLG;EACC,kBAAA;ADqyLJ;;ACjyLI;EACC,mBAAA;ADoyLL;;AC1yLG;EACC,kBAAA;AD6yLJ;;ACzyLI;EACC,mBAAA;AD4yLL;;AClzLG;EACC,kBAAA;ADqzLJ;;ACjzLI;EACC,mBAAA;ADozLL;;AC1zLG;EACC,kBAAA;AD6zLJ;;ACzzLI;EACC,mBAAA;AD4zLL;;ACl0LG;EACC,kBAAA;ADq0LJ;;ACj0LI;EACC,mBAAA;ADo0LL;;AC10LG;EACC,kBAAA;AD60LJ;;ACz0LI;EACC,mBAAA;AD40LL;;ACl1LG;EACC,kBAAA;ADq1LJ;;ACj1LI;EACC,mBAAA;ADo1LL;;AC11LG;EACC,kBAAA;AD61LJ;;ACz1LI;EACC,mBAAA;AD41LL;;ACl2LG;EACC,kBAAA;ADq2LJ;;ACj2LI;EACC,mBAAA;ADo2LL;;AC12LG;EACC,kBAAA;AD62LJ;;ACz2LI;EACC,mBAAA;AD42LL;;ACl3LG;EACC,kBAAA;ADq3LJ;;ACj3LI;EACC,mBAAA;ADo3LL;;AC13LG;EACC,kBAAA;AD63LJ;;ACz3LI;EACC,mBAAA;AD43LL;;ACl4LG;EACC,kBAAA;ADq4LJ;;ACj4LI;EACC,mBAAA;ADo4LL;;AC14LG;EACC,kBAAA;AD64LJ;;ACz4LI;EACC,mBAAA;AD44LL;;ACl5LG;EACC,kBAAA;ADq5LJ;;ACj5LI;EACC,mBAAA;ADo5LL;;AC15LG;EACC,kBAAA;AD65LJ;;ACz5LI;EACC,mBAAA;AD45LL;;ACl6LG;EACC,kBAAA;ADq6LJ;;ACj6LI;EACC,mBAAA;ADo6LL;;AC16LG;EACC,kBAAA;AD66LJ;;ACz6LI;EACC,mBAAA;AD46LL;;ACl7LG;EACC,kBAAA;ADq7LJ;;ACj7LI;EACC,mBAAA;ADo7LL;;AC17LG;EACC,kBAAA;AD67LJ;;ACz7LI;EACC,mBAAA;AD47LL;;ACl8LG;EACC,kBAAA;ADq8LJ;;ACj8LI;EACC,mBAAA;ADo8LL;;AC18LG;EACC,kBAAA;AD68LJ;;ACz8LI;EACC,mBAAA;AD48LL;;ACl9LG;EACC,kBAAA;ADq9LJ;;ACj9LI;EACC,mBAAA;ADo9LL;;AC19LG;EACC,kBAAA;AD69LJ;;ACz9LI;EACC,mBAAA;AD49LL;;ACv8LG;EACC,iBAAA;AD08LJ;;ACt8LI;EACC,kBAAA;ADy8LL;;AC/8LG;EACC,iBAAA;ADk9LJ;;AC98LI;EACC,kBAAA;ADi9LL;;ACv9LG;EACC,iBAAA;AD09LJ;;ACt9LI;EACC,kBAAA;ADy9LL;;AC/9LG;EACC,iBAAA;ADk+LJ;;AC99LI;EACC,kBAAA;ADi+LL;;ACv+LG;EACC,kBAAA;AD0+LJ;;ACt+LI;EACC,mBAAA;ADy+LL;;AC/+LG;EACC,kBAAA;ADk/LJ;;AC9+LI;EACC,mBAAA;ADi/LL;;ACv/LG;EACC,kBAAA;AD0/LJ;;ACt/LI;EACC,mBAAA;ADy/LL;;AC//LG;EACC,kBAAA;ADkgMJ;;AC9/LI;EACC,mBAAA;ADigML;;ACvgMG;EACC,kBAAA;AD0gMJ;;ACtgMI;EACC,mBAAA;ADygML;;AC/gMG;EACC,kBAAA;ADkhMJ;;AC9gMI;EACC,mBAAA;ADihML;;ACvhMG;EACC,kBAAA;AD0hMJ;;ACthMI;EACC,mBAAA;ADyhML;;AC/hMG;EACC,kBAAA;ADkiMJ;;AC9hMI;EACC,mBAAA;ADiiML;;ACviMG;EACC,kBAAA;AD0iMJ;;ACtiMI;EACC,mBAAA;ADyiML;;AC/iMG;EACC,kBAAA;ADkjMJ;;AC9iMI;EACC,mBAAA;ADijML;;ACvjMG;EACC,kBAAA;AD0jMJ;;ACtjMI;EACC,mBAAA;ADyjML;;AC/jMG;EACC,kBAAA;ADkkMJ;;AC9jMI;EACC,mBAAA;ADikML;;ACvkMG;EACC,kBAAA;AD0kMJ;;ACtkMI;EACC,mBAAA;ADykML;;AC/kMG;EACC,kBAAA;ADklMJ;;AC9kMI;EACC,mBAAA;ADilML;;ACvlMG;EACC,kBAAA;AD0lMJ;;ACtlMI;EACC,mBAAA;ADylML;;AC/lMG;EACC,kBAAA;ADkmMJ;;AC9lMI;EACC,mBAAA;ADimML;;ACvmMG;EACC,kBAAA;AD0mMJ;;ACtmMI;EACC,mBAAA;ADymML;;AC/mMG;EACC,kBAAA;ADknMJ;;AC9mMI;EACC,mBAAA;ADinML;;ACvnMG;EACC,kBAAA;AD0nMJ;;ACtnMI;EACC,mBAAA;ADynML;;AC/nMG;EACC,kBAAA;ADkoMJ;;AC9nMI;EACC,mBAAA;ADioML;;ACvoMG;EACC,kBAAA;AD0oMJ;;ACtoMI;EACC,mBAAA;ADyoML;;AC1qMG;EACC,kBAAA;AD6qMJ;;ACzqMI;EACC,mBAAA;AD4qML;;AClrMG;EACC,kBAAA;ADqrMJ;;ACjrMI;EACC,mBAAA;ADorML;;AC1rMG;EACC,kBAAA;AD6rMJ;;ACzrMI;EACC,mBAAA;AD4rML;;AClsMG;EACC,kBAAA;ADqsMJ;;ACjsMI;EACC,mBAAA;ADosML;;AC1sMG;EACC,kBAAA;AD6sMJ;;ACzsMI;EACC,mBAAA;AD4sML;;ACltMG;EACC,kBAAA;ADqtMJ;;ACjtMI;EACC,mBAAA;ADotML;;AC1tMG;EACC,kBAAA;AD6tMJ;;ACztMI;EACC,mBAAA;AD4tML;;ACluMG;EACC,kBAAA;ADquMJ;;ACjuMI;EACC,mBAAA;ADouML;;AC1uMG;EACC,kBAAA;AD6uMJ;;ACzuMI;EACC,mBAAA;AD4uML;;AClvMG;EACC,kBAAA;ADqvMJ;;ACjvMI;EACC,mBAAA;ADovML;;AC1vMG;EACC,mBAAA;AD6vMJ;;ACzvMI;EACC,oBAAA;AD4vML;;AClwMG;EACC,mBAAA;ADqwMJ;;ACjwMI;EACC,oBAAA;ADowML;;AC1wMG;EACC,mBAAA;AD6wMJ;;ACzwMI;EACC,oBAAA;AD4wML;;AClxMG;EACC,mBAAA;ADqxMJ;;ACjxMI;EACC,oBAAA;ADoxML;;AC1xMG;EACC,mBAAA;AD6xMJ;;ACzxMI;EACC,oBAAA;AD4xML;;AClyMG;EACC,mBAAA;ADqyMJ;;ACjyMI;EACC,oBAAA;ADoyML;;AC1yMG;EACC,mBAAA;AD6yMJ;;ACzyMI;EACC,oBAAA;AD4yML;;AClzMG;EACC,mBAAA;ADqzMJ;;ACjzMI;EACC,oBAAA;ADozML;;AC1zMG;EACC,mBAAA;AD6zMJ;;ACzzMI;EACC,oBAAA;AD4zML;;ACl0MG;EACC,mBAAA;ADq0MJ;;ACj0MI;EACC,oBAAA;ADo0ML;;AC10MG;EACC,mBAAA;AD60MJ;;ACz0MI;EACC,oBAAA;AD40ML;;ACl1MG;EACC,mBAAA;ADq1MJ;;ACj1MI;EACC,oBAAA;ADo1ML;;AC11MG;EACC,mBAAA;AD61MJ;;ACz1MI;EACC,oBAAA;AD41ML;;ACl2MG;EACC,mBAAA;ADq2MJ;;ACj2MI;EACC,oBAAA;ADo2ML;;AC12MG;EACC,mBAAA;AD62MJ;;ACz2MI;EACC,oBAAA;AD42ML;;ACl3MG;EACC,mBAAA;ADq3MJ;;ACj3MI;EACC,oBAAA;ADo3ML;;AC13MG;EACC,mBAAA;AD63MJ;;ACz3MI;EACC,oBAAA;AD43ML;;ACl4MG;EACC,mBAAA;ADq4MJ;;ACj4MI;EACC,oBAAA;ADo4ML;;AC14MG;EACC,mBAAA;AD64MJ;;ACz4MI;EACC,oBAAA;AD44ML;;ACl5MG;EACC,mBAAA;ADq5MJ;;ACj5MI;EACC,oBAAA;ADo5ML;;AC15MG;EACC,mBAAA;AD65MJ;;ACz5MI;EACC,oBAAA;AD45ML;;ACl6MG;EACC,mBAAA;ADq6MJ;;ACj6MI;EACC,oBAAA;ADo6ML;;AC16MG;EACC,mBAAA;AD66MJ;;ACz6MI;EACC,oBAAA;AD46ML;;ACl7MG;EACC,mBAAA;ADq7MJ;;ACj7MI;EACC,oBAAA;ADo7ML;;AC17MG;EACC,mBAAA;AD67MJ;;ACz7MI;EACC,oBAAA;AD47ML;;ACl8MG;EACC,mBAAA;ADq8MJ;;ACj8MI;EACC,oBAAA;ADo8ML;;AC18MG;EACC,mBAAA;AD68MJ;;ACz8MI;EACC,oBAAA;AD48ML;;ACl9MG;EACC,mBAAA;ADq9MJ;;ACj9MI;EACC,oBAAA;ADo9ML;;AC19MG;EACC,mBAAA;AD69MJ;;ACz9MI;EACC,oBAAA;AD49ML;;ACl+MG;EACC,mBAAA;ADq+MJ;;ACj+MI;EACC,oBAAA;ADo+ML;;AC1+MG;EACC,mBAAA;AD6+MJ;;ACz+MI;EACC,oBAAA;AD4+ML;;ACl/MG;EACC,mBAAA;ADq/MJ;;ACj/MI;EACC,oBAAA;ADo/ML;;AC1/MG;EACC,mBAAA;AD6/MJ;;ACz/MI;EACC,oBAAA;AD4/ML;;AClgNG;EACC,mBAAA;ADqgNJ;;ACjgNI;EACC,oBAAA;ADogNL;;AC1gNG;EACC,mBAAA;AD6gNJ;;ACzgNI;EACC,oBAAA;AD4gNL;;AClhNG;EACC,mBAAA;ADqhNJ;;ACjhNI;EACC,oBAAA;ADohNL;;AC1hNG;EACC,mBAAA;AD6hNJ;;ACzhNI;EACC,oBAAA;AD4hNL;;ACliNG;EACC,mBAAA;ADqiNJ;;ACjiNI;EACC,oBAAA;ADoiNL;;AC1iNG;EACC,mBAAA;AD6iNJ;;ACziNI;EACC,oBAAA;AD4iNL;;ACljNG;EACC,mBAAA;ADqjNJ;;ACjjNI;EACC,oBAAA;ADojNL;;AC1jNG;EACC,mBAAA;AD6jNJ;;ACzjNI;EACC,oBAAA;AD4jNL;;ACviNG;EACC,kBAAA;AD0iNJ;;ACtiNI;EACC,mBAAA;ADyiNL;;AC/iNG;EACC,kBAAA;ADkjNJ;;AC9iNI;EACC,mBAAA;ADijNL;;ACvjNG;EACC,kBAAA;AD0jNJ;;ACtjNI;EACC,mBAAA;ADyjNL;;AC/jNG;EACC,kBAAA;ADkkNJ;;AC9jNI;EACC,mBAAA;ADikNL;;ACvkNG;EACC,mBAAA;AD0kNJ;;ACtkNI;EACC,oBAAA;ADykNL;;AC/kNG;EACC,mBAAA;ADklNJ;;AC9kNI;EACC,oBAAA;ADilNL;;ACvlNG;EACC,mBAAA;AD0lNJ;;ACtlNI;EACC,oBAAA;ADylNL;;AC/lNG;EACC,mBAAA;ADkmNJ;;AC9lNI;EACC,oBAAA;ADimNL;;ACvmNG;EACC,mBAAA;AD0mNJ;;ACtmNI;EACC,oBAAA;ADymNL;;AC/mNG;EACC,mBAAA;ADknNJ;;AC9mNI;EACC,oBAAA;ADinNL;;ACvnNG;EACC,mBAAA;AD0nNJ;;ACtnNI;EACC,oBAAA;ADynNL;;AC/nNG;EACC,mBAAA;ADkoNJ;;AC9nNI;EACC,oBAAA;ADioNL;;ACvoNG;EACC,mBAAA;AD0oNJ;;ACtoNI;EACC,oBAAA;ADyoNL;;AC/oNG;EACC,mBAAA;ADkpNJ;;AC9oNI;EACC,oBAAA;ADipNL;;ACvpNG;EACC,mBAAA;AD0pNJ;;ACtpNI;EACC,oBAAA;ADypNL;;AC/pNG;EACC,mBAAA;ADkqNJ;;AC9pNI;EACC,oBAAA;ADiqNL;;ACvqNG;EACC,mBAAA;AD0qNJ;;ACtqNI;EACC,oBAAA;ADyqNL;;AC/qNG;EACC,mBAAA;ADkrNJ;;AC9qNI;EACC,oBAAA;ADirNL;;ACvrNG;EACC,mBAAA;AD0rNJ;;ACtrNI;EACC,oBAAA;ADyrNL;;AC/rNG;EACC,mBAAA;ADksNJ;;AC9rNI;EACC,oBAAA;ADisNL;;ACvsNG;EACC,mBAAA;AD0sNJ;;ACtsNI;EACC,oBAAA;ADysNL;;AC/sNG;EACC,mBAAA;ADktNJ;;AC9sNI;EACC,oBAAA;ADitNL;;ACvtNG;EACC,mBAAA;AD0tNJ;;ACttNI;EACC,oBAAA;ADytNL;;AC/tNG;EACC,mBAAA;ADkuNJ;;AC9tNI;EACC,oBAAA;ADiuNL;;ACvuNG;EACC,mBAAA;AD0uNJ;;ACtuNI;EACC,oBAAA;ADyuNL;;AC1wNG;EACC,gBAAA;AD6wNJ;;ACzwNI;EACC,iBAAA;AD4wNL;;AClxNG;EACC,gBAAA;ADqxNJ;;ACjxNI;EACC,iBAAA;ADoxNL;;AC1xNG;EACC,gBAAA;AD6xNJ;;ACzxNI;EACC,iBAAA;AD4xNL;;AClyNG;EACC,gBAAA;ADqyNJ;;ACjyNI;EACC,iBAAA;ADoyNL;;AC1yNG;EACC,gBAAA;AD6yNJ;;ACzyNI;EACC,iBAAA;AD4yNL;;AClzNG;EACC,gBAAA;ADqzNJ;;ACjzNI;EACC,iBAAA;ADozNL;;AC1zNG;EACC,gBAAA;AD6zNJ;;ACzzNI;EACC,iBAAA;AD4zNL;;ACl0NG;EACC,gBAAA;ADq0NJ;;ACj0NI;EACC,iBAAA;ADo0NL;;AC10NG;EACC,gBAAA;AD60NJ;;ACz0NI;EACC,iBAAA;AD40NL;;ACl1NG;EACC,gBAAA;ADq1NJ;;ACj1NI;EACC,iBAAA;ADo1NL;;AC11NG;EACC,iBAAA;AD61NJ;;ACz1NI;EACC,kBAAA;AD41NL;;ACl2NG;EACC,iBAAA;ADq2NJ;;ACj2NI;EACC,kBAAA;ADo2NL;;AC12NG;EACC,iBAAA;AD62NJ;;ACz2NI;EACC,kBAAA;AD42NL;;ACl3NG;EACC,iBAAA;ADq3NJ;;ACj3NI;EACC,kBAAA;ADo3NL;;AC13NG;EACC,iBAAA;AD63NJ;;ACz3NI;EACC,kBAAA;AD43NL;;ACl4NG;EACC,iBAAA;ADq4NJ;;ACj4NI;EACC,kBAAA;ADo4NL;;AC14NG;EACC,iBAAA;AD64NJ;;ACz4NI;EACC,kBAAA;AD44NL;;ACl5NG;EACC,iBAAA;ADq5NJ;;ACj5NI;EACC,kBAAA;ADo5NL;;AC15NG;EACC,iBAAA;AD65NJ;;ACz5NI;EACC,kBAAA;AD45NL;;ACl6NG;EACC,iBAAA;ADq6NJ;;ACj6NI;EACC,kBAAA;ADo6NL;;AC16NG;EACC,iBAAA;AD66NJ;;ACz6NI;EACC,kBAAA;AD46NL;;ACl7NG;EACC,iBAAA;ADq7NJ;;ACj7NI;EACC,kBAAA;ADo7NL;;AC17NG;EACC,iBAAA;AD67NJ;;ACz7NI;EACC,kBAAA;AD47NL;;ACl8NG;EACC,iBAAA;ADq8NJ;;ACj8NI;EACC,kBAAA;ADo8NL;;AC18NG;EACC,iBAAA;AD68NJ;;ACz8NI;EACC,kBAAA;AD48NL;;ACl9NG;EACC,iBAAA;ADq9NJ;;ACj9NI;EACC,kBAAA;ADo9NL;;AC19NG;EACC,iBAAA;AD69NJ;;ACz9NI;EACC,kBAAA;AD49NL;;ACl+NG;EACC,iBAAA;ADq+NJ;;ACj+NI;EACC,kBAAA;ADo+NL;;AC1+NG;EACC,iBAAA;AD6+NJ;;ACz+NI;EACC,kBAAA;AD4+NL;;ACl/NG;EACC,iBAAA;ADq/NJ;;ACj/NI;EACC,kBAAA;ADo/NL;;AC1/NG;EACC,iBAAA;AD6/NJ;;ACz/NI;EACC,kBAAA;AD4/NL;;AClgOG;EACC,iBAAA;ADqgOJ;;ACjgOI;EACC,kBAAA;ADogOL;;AC1gOG;EACC,iBAAA;AD6gOJ;;ACzgOI;EACC,kBAAA;AD4gOL;;AClhOG;EACC,iBAAA;ADqhOJ;;ACjhOI;EACC,kBAAA;ADohOL;;AC1hOG;EACC,iBAAA;AD6hOJ;;ACzhOI;EACC,kBAAA;AD4hOL;;ACliOG;EACC,iBAAA;ADqiOJ;;ACjiOI;EACC,kBAAA;ADoiOL;;AC1iOG;EACC,iBAAA;AD6iOJ;;ACziOI;EACC,kBAAA;AD4iOL;;ACljOG;EACC,iBAAA;ADqjOJ;;ACjjOI;EACC,kBAAA;ADojOL;;AC1jOG;EACC,iBAAA;AD6jOJ;;ACzjOI;EACC,kBAAA;AD4jOL;;AClkOG;EACC,iBAAA;ADqkOJ;;ACjkOI;EACC,kBAAA;ADokOL;;AC1kOG;EACC,iBAAA;AD6kOJ;;ACzkOI;EACC,kBAAA;AD4kOL;;ACllOG;EACC,iBAAA;ADqlOJ;;ACjlOI;EACC,kBAAA;ADolOL;;AC1lOG;EACC,iBAAA;AD6lOJ;;ACzlOI;EACC,kBAAA;AD4lOL;;AClmOG;EACC,iBAAA;ADqmOJ;;ACjmOI;EACC,kBAAA;ADomOL;;AC1mOG;EACC,iBAAA;AD6mOJ;;ACzmOI;EACC,kBAAA;AD4mOL;;AClnOG;EACC,iBAAA;ADqnOJ;;ACjnOI;EACC,kBAAA;ADonOL;;AC1nOG;EACC,iBAAA;AD6nOJ;;ACznOI;EACC,kBAAA;AD4nOL;;ACloOG;EACC,iBAAA;ADqoOJ;;ACjoOI;EACC,kBAAA;ADooOL;;AC1oOG;EACC,iBAAA;AD6oOJ;;ACzoOI;EACC,kBAAA;AD4oOL;;AClpOG;EACC,iBAAA;ADqpOJ;;ACjpOI;EACC,kBAAA;ADopOL;;AC1pOG;EACC,iBAAA;AD6pOJ;;ACzpOI;EACC,kBAAA;AD4pOL;;ACvoOG;EACC,gBAAA;AD0oOJ;;ACtoOI;EACC,iBAAA;ADyoOL;;AC/oOG;EACC,gBAAA;ADkpOJ;;AC9oOI;EACC,iBAAA;ADipOL;;ACvpOG;EACC,gBAAA;AD0pOJ;;ACtpOI;EACC,iBAAA;ADypOL;;AC/pOG;EACC,gBAAA;ADkqOJ;;AC9pOI;EACC,iBAAA;ADiqOL;;ACvqOG;EACC,iBAAA;AD0qOJ;;ACtqOI;EACC,kBAAA;ADyqOL;;AC/qOG;EACC,iBAAA;ADkrOJ;;AC9qOI;EACC,kBAAA;ADirOL;;ACvrOG;EACC,iBAAA;AD0rOJ;;ACtrOI;EACC,kBAAA;ADyrOL;;AC/rOG;EACC,iBAAA;ADksOJ;;AC9rOI;EACC,kBAAA;ADisOL;;ACvsOG;EACC,iBAAA;AD0sOJ;;ACtsOI;EACC,kBAAA;ADysOL;;AC/sOG;EACC,iBAAA;ADktOJ;;AC9sOI;EACC,kBAAA;ADitOL;;ACvtOG;EACC,iBAAA;AD0tOJ;;ACttOI;EACC,kBAAA;ADytOL;;AC/tOG;EACC,iBAAA;ADkuOJ;;AC9tOI;EACC,kBAAA;ADiuOL;;ACvuOG;EACC,iBAAA;AD0uOJ;;ACtuOI;EACC,kBAAA;ADyuOL;;AC/uOG;EACC,iBAAA;ADkvOJ;;AC9uOI;EACC,kBAAA;ADivOL;;ACvvOG;EACC,iBAAA;AD0vOJ;;ACtvOI;EACC,kBAAA;ADyvOL;;AC/vOG;EACC,iBAAA;ADkwOJ;;AC9vOI;EACC,kBAAA;ADiwOL;;ACvwOG;EACC,iBAAA;AD0wOJ;;ACtwOI;EACC,kBAAA;ADywOL;;AC/wOG;EACC,iBAAA;ADkxOJ;;AC9wOI;EACC,kBAAA;ADixOL;;ACvxOG;EACC,iBAAA;AD0xOJ;;ACtxOI;EACC,kBAAA;ADyxOL;;AC/xOG;EACC,iBAAA;ADkyOJ;;AC9xOI;EACC,kBAAA;ADiyOL;;ACvyOG;EACC,iBAAA;AD0yOJ;;ACtyOI;EACC,kBAAA;ADyyOL;;AC/yOG;EACC,iBAAA;ADkzOJ;;AC9yOI;EACC,kBAAA;ADizOL;;ACvzOG;EACC,iBAAA;AD0zOJ;;ACtzOI;EACC,kBAAA;ADyzOL;;AC/zOG;EACC,iBAAA;ADk0OJ;;AC9zOI;EACC,kBAAA;ADi0OL;;ACv0OG;EACC,iBAAA;AD00OJ;;ACt0OI;EACC,kBAAA;ADy0OL;;AC/1OG;EACC,gBAAA;EACA,iBAAA;ADk2OJ;;ACp2OG;EACC,gBAAA;EACA,iBAAA;ADu2OJ;;ACz2OG;EACC,gBAAA;EACA,iBAAA;AD42OJ;;AC92OG;EACC,gBAAA;EACA,iBAAA;ADi3OJ;;ACn3OG;EACC,gBAAA;EACA,iBAAA;ADs3OJ;;ACx3OG;EACC,gBAAA;EACA,iBAAA;AD23OJ;;AC73OG;EACC,gBAAA;EACA,iBAAA;ADg4OJ;;ACl4OG;EACC,gBAAA;EACA,iBAAA;ADq4OJ;;ACv4OG;EACC,gBAAA;EACA,iBAAA;AD04OJ;;AC54OG;EACC,gBAAA;EACA,iBAAA;AD+4OJ;;ACj5OG;EACC,iBAAA;EACA,kBAAA;ADo5OJ;;ACt5OG;EACC,iBAAA;EACA,kBAAA;ADy5OJ;;AC35OG;EACC,iBAAA;EACA,kBAAA;AD85OJ;;ACh6OG;EACC,iBAAA;EACA,kBAAA;ADm6OJ;;ACr6OG;EACC,iBAAA;EACA,kBAAA;ADw6OJ;;AC16OG;EACC,iBAAA;EACA,kBAAA;AD66OJ;;AC/6OG;EACC,iBAAA;EACA,kBAAA;ADk7OJ;;ACp7OG;EACC,iBAAA;EACA,kBAAA;ADu7OJ;;ACz7OG;EACC,iBAAA;EACA,kBAAA;AD47OJ;;AC97OG;EACC,iBAAA;EACA,kBAAA;ADi8OJ;;ACn8OG;EACC,iBAAA;EACA,kBAAA;ADs8OJ;;ACx8OG;EACC,iBAAA;EACA,kBAAA;AD28OJ;;AC78OG;EACC,iBAAA;EACA,kBAAA;ADg9OJ;;ACl9OG;EACC,iBAAA;EACA,kBAAA;ADq9OJ;;ACv9OG;EACC,iBAAA;EACA,kBAAA;AD09OJ;;AC59OG;EACC,iBAAA;EACA,kBAAA;AD+9OJ;;ACj+OG;EACC,iBAAA;EACA,kBAAA;ADo+OJ;;ACt+OG;EACC,iBAAA;EACA,kBAAA;ADy+OJ;;AC3+OG;EACC,iBAAA;EACA,kBAAA;AD8+OJ;;ACh/OG;EACC,iBAAA;EACA,kBAAA;ADm/OJ;;ACr/OG;EACC,iBAAA;EACA,kBAAA;ADw/OJ;;AC1/OG;EACC,iBAAA;EACA,kBAAA;AD6/OJ;;AC//OG;EACC,iBAAA;EACA,kBAAA;ADkgPJ;;ACpgPG;EACC,iBAAA;EACA,kBAAA;ADugPJ;;ACzgPG;EACC,iBAAA;EACA,kBAAA;AD4gPJ;;AC9gPG;EACC,iBAAA;EACA,kBAAA;ADihPJ;;ACnhPG;EACC,iBAAA;EACA,kBAAA;ADshPJ;;ACxhPG;EACC,iBAAA;EACA,kBAAA;AD2hPJ;;AC7hPG;EACC,iBAAA;EACA,kBAAA;ADgiPJ;;ACliPG;EACC,iBAAA;EACA,kBAAA;ADqiPJ;;ACviPG;EACC,iBAAA;EACA,kBAAA;AD0iPJ;;AC5iPG;EACC,iBAAA;EACA,kBAAA;AD+iPJ;;ACjjPG;EACC,iBAAA;EACA,kBAAA;ADojPJ;;ACtjPG;EACC,iBAAA;EACA,kBAAA;ADyjPJ;;AC3jPG;EACC,iBAAA;EACA,kBAAA;AD8jPJ;;AChkPG;EACC,iBAAA;EACA,kBAAA;ADmkPJ;;ACrkPG;EACC,iBAAA;EACA,kBAAA;ADwkPJ;;AC1kPG;EACC,iBAAA;EACA,kBAAA;AD6kPJ;;AC/kPG;EACC,iBAAA;EACA,kBAAA;ADklPJ;;ACplPG;EACC,iBAAA;EACA,kBAAA;ADulPJ;;ACzlPG;EACC,iBAAA;EACA,kBAAA;AD4lPJ;;AClkPG;EACC,gBAAA;EACA,iBAAA;ADqkPJ;;ACvkPG;EACC,gBAAA;EACA,iBAAA;AD0kPJ;;AC5kPG;EACC,gBAAA;EACA,iBAAA;AD+kPJ;;ACjlPG;EACC,gBAAA;EACA,iBAAA;ADolPJ;;ACtlPG;EACC,iBAAA;EACA,kBAAA;ADylPJ;;AC3lPG;EACC,iBAAA;EACA,kBAAA;AD8lPJ;;AChmPG;EACC,iBAAA;EACA,kBAAA;ADmmPJ;;ACrmPG;EACC,iBAAA;EACA,kBAAA;ADwmPJ;;AC1mPG;EACC,iBAAA;EACA,kBAAA;AD6mPJ;;AC/mPG;EACC,iBAAA;EACA,kBAAA;ADknPJ;;ACpnPG;EACC,iBAAA;EACA,kBAAA;ADunPJ;;ACznPG;EACC,iBAAA;EACA,kBAAA;AD4nPJ;;AC9nPG;EACC,iBAAA;EACA,kBAAA;ADioPJ;;ACnoPG;EACC,iBAAA;EACA,kBAAA;ADsoPJ;;ACxoPG;EACC,iBAAA;EACA,kBAAA;AD2oPJ;;AC7oPG;EACC,iBAAA;EACA,kBAAA;ADgpPJ;;AClpPG;EACC,iBAAA;EACA,kBAAA;ADqpPJ;;ACvpPG;EACC,iBAAA;EACA,kBAAA;AD0pPJ;;AC5pPG;EACC,iBAAA;EACA,kBAAA;AD+pPJ;;ACjqPG;EACC,iBAAA;EACA,kBAAA;ADoqPJ;;ACtqPG;EACC,iBAAA;EACA,kBAAA;ADyqPJ;;AC3qPG;EACC,iBAAA;EACA,kBAAA;AD8qPJ;;AChrPG;EACC,iBAAA;EACA,kBAAA;ADmrPJ;;ACrrPG;EACC,iBAAA;EACA,kBAAA;ADwrPJ;;AC1rPG;EACC,iBAAA;EACA,kBAAA;AD6rPJ;;ACptPG;EACC,eAAA;EACA,kBAAA;ADutPJ;;ACztPG;EACC,eAAA;EACA,kBAAA;AD4tPJ;;AC9tPG;EACC,eAAA;EACA,kBAAA;ADiuPJ;;ACnuPG;EACC,eAAA;EACA,kBAAA;ADsuPJ;;ACxuPG;EACC,eAAA;EACA,kBAAA;AD2uPJ;;AC7uPG;EACC,eAAA;EACA,kBAAA;ADgvPJ;;AClvPG;EACC,eAAA;EACA,kBAAA;ADqvPJ;;ACvvPG;EACC,eAAA;EACA,kBAAA;AD0vPJ;;AC5vPG;EACC,eAAA;EACA,kBAAA;AD+vPJ;;ACjwPG;EACC,eAAA;EACA,kBAAA;ADowPJ;;ACtwPG;EACC,gBAAA;EACA,mBAAA;ADywPJ;;AC3wPG;EACC,gBAAA;EACA,mBAAA;AD8wPJ;;AChxPG;EACC,gBAAA;EACA,mBAAA;ADmxPJ;;ACrxPG;EACC,gBAAA;EACA,mBAAA;ADwxPJ;;AC1xPG;EACC,gBAAA;EACA,mBAAA;AD6xPJ;;AC/xPG;EACC,gBAAA;EACA,mBAAA;ADkyPJ;;ACpyPG;EACC,gBAAA;EACA,mBAAA;ADuyPJ;;ACzyPG;EACC,gBAAA;EACA,mBAAA;AD4yPJ;;AC9yPG;EACC,gBAAA;EACA,mBAAA;ADizPJ;;ACnzPG;EACC,gBAAA;EACA,mBAAA;ADszPJ;;ACxzPG;EACC,gBAAA;EACA,mBAAA;AD2zPJ;;AC7zPG;EACC,gBAAA;EACA,mBAAA;ADg0PJ;;ACl0PG;EACC,gBAAA;EACA,mBAAA;ADq0PJ;;ACv0PG;EACC,gBAAA;EACA,mBAAA;AD00PJ;;AC50PG;EACC,gBAAA;EACA,mBAAA;AD+0PJ;;ACj1PG;EACC,gBAAA;EACA,mBAAA;ADo1PJ;;ACt1PG;EACC,gBAAA;EACA,mBAAA;ADy1PJ;;AC31PG;EACC,gBAAA;EACA,mBAAA;AD81PJ;;ACh2PG;EACC,gBAAA;EACA,mBAAA;ADm2PJ;;ACr2PG;EACC,gBAAA;EACA,mBAAA;ADw2PJ;;AC12PG;EACC,gBAAA;EACA,mBAAA;AD62PJ;;AC/2PG;EACC,gBAAA;EACA,mBAAA;ADk3PJ;;ACp3PG;EACC,gBAAA;EACA,mBAAA;ADu3PJ;;ACz3PG;EACC,gBAAA;EACA,mBAAA;AD43PJ;;AC93PG;EACC,gBAAA;EACA,mBAAA;ADi4PJ;;ACn4PG;EACC,gBAAA;EACA,mBAAA;ADs4PJ;;ACx4PG;EACC,gBAAA;EACA,mBAAA;AD24PJ;;AC74PG;EACC,gBAAA;EACA,mBAAA;ADg5PJ;;ACl5PG;EACC,gBAAA;EACA,mBAAA;ADq5PJ;;ACv5PG;EACC,gBAAA;EACA,mBAAA;AD05PJ;;AC55PG;EACC,gBAAA;EACA,mBAAA;AD+5PJ;;ACj6PG;EACC,gBAAA;EACA,mBAAA;ADo6PJ;;ACt6PG;EACC,gBAAA;EACA,mBAAA;ADy6PJ;;AC36PG;EACC,gBAAA;EACA,mBAAA;AD86PJ;;ACh7PG;EACC,gBAAA;EACA,mBAAA;ADm7PJ;;ACr7PG;EACC,gBAAA;EACA,mBAAA;ADw7PJ;;AC17PG;EACC,gBAAA;EACA,mBAAA;AD67PJ;;AC/7PG;EACC,gBAAA;EACA,mBAAA;ADk8PJ;;ACp8PG;EACC,gBAAA;EACA,mBAAA;ADu8PJ;;ACz8PG;EACC,gBAAA;EACA,mBAAA;AD48PJ;;AC98PG;EACC,gBAAA;EACA,mBAAA;ADi9PJ;;ACv7PG;EACC,eAAA;EACA,kBAAA;AD07PJ;;AC57PG;EACC,eAAA;EACA,kBAAA;AD+7PJ;;ACj8PG;EACC,eAAA;EACA,kBAAA;ADo8PJ;;ACt8PG;EACC,eAAA;EACA,kBAAA;ADy8PJ;;AC38PG;EACC,gBAAA;EACA,mBAAA;AD88PJ;;ACh9PG;EACC,gBAAA;EACA,mBAAA;ADm9PJ;;ACr9PG;EACC,gBAAA;EACA,mBAAA;ADw9PJ;;AC19PG;EACC,gBAAA;EACA,mBAAA;AD69PJ;;AC/9PG;EACC,gBAAA;EACA,mBAAA;ADk+PJ;;ACp+PG;EACC,gBAAA;EACA,mBAAA;ADu+PJ;;ACz+PG;EACC,gBAAA;EACA,mBAAA;AD4+PJ;;AC9+PG;EACC,gBAAA;EACA,mBAAA;ADi/PJ;;ACn/PG;EACC,gBAAA;EACA,mBAAA;ADs/PJ;;ACx/PG;EACC,gBAAA;EACA,mBAAA;AD2/PJ;;AC7/PG;EACC,gBAAA;EACA,mBAAA;ADggQJ;;AClgQG;EACC,gBAAA;EACA,mBAAA;ADqgQJ;;ACvgQG;EACC,gBAAA;EACA,mBAAA;AD0gQJ;;AC5gQG;EACC,gBAAA;EACA,mBAAA;AD+gQJ;;ACjhQG;EACC,gBAAA;EACA,mBAAA;ADohQJ;;ACthQG;EACC,gBAAA;EACA,mBAAA;ADyhQJ;;AC3hQG;EACC,gBAAA;EACA,mBAAA;AD8hQJ;;AChiQG;EACC,gBAAA;EACA,mBAAA;ADmiQJ;;ACriQG;EACC,gBAAA;EACA,mBAAA;ADwiQJ;;AC1iQG;EACC,gBAAA;EACA,mBAAA;AD6iQJ;;AC/iQG;EACC,gBAAA;EACA,mBAAA;ADkjQJ;;ACziQE;EACC,QAAA;AD4iQH;;ACziQE;EACC,SAAA;AD4iQH;;ACjjQE;EACC,QAAA;ADojQH;;ACjjQE;EACC,SAAA;ADojQH;;ACzjQE;EACC,QAAA;AD4jQH;;ACzjQE;EACC,SAAA;AD4jQH;;ACjkQE;EACC,QAAA;ADokQH;;ACjkQE;EACC,SAAA;ADokQH;;ACzkQE;EACC,QAAA;AD4kQH;;ACzkQE;EACC,SAAA;AD4kQH;;ACjlQE;EACC,QAAA;ADolQH;;ACjlQE;EACC,SAAA;ADolQH;;ACzlQE;EACC,QAAA;AD4lQH;;ACzlQE;EACC,SAAA;AD4lQH;;ACjmQE;EACC,QAAA;ADomQH;;ACjmQE;EACC,SAAA;ADomQH;;ACzmQE;EACC,QAAA;AD4mQH;;ACzmQE;EACC,SAAA;AD4mQH;;ACjnQE;EACC,QAAA;ADonQH;;ACjnQE;EACC,SAAA;ADonQH;;ACznQE;EACC,SAAA;AD4nQH;;ACznQE;EACC,UAAA;AD4nQH;;ACjoQE;EACC,SAAA;ADooQH;;ACjoQE;EACC,UAAA;ADooQH;;ACzoQE;EACC,SAAA;AD4oQH;;ACzoQE;EACC,UAAA;AD4oQH;;ACjpQE;EACC,SAAA;ADopQH;;ACjpQE;EACC,UAAA;ADopQH;;ACzpQE;EACC,SAAA;AD4pQH;;ACzpQE;EACC,UAAA;AD4pQH;;ACjqQE;EACC,SAAA;ADoqQH;;ACjqQE;EACC,UAAA;ADoqQH;;ACzqQE;EACC,SAAA;AD4qQH;;ACzqQE;EACC,UAAA;AD4qQH;;ACjrQE;EACC,SAAA;ADorQH;;ACjrQE;EACC,UAAA;ADorQH;;ACzrQE;EACC,SAAA;AD4rQH;;ACzrQE;EACC,UAAA;AD4rQH;;ACjsQE;EACC,SAAA;ADosQH;;ACjsQE;EACC,UAAA;ADosQH;;ACzsQE;EACC,SAAA;AD4sQH;;ACzsQE;EACC,UAAA;AD4sQH;;ACjtQE;EACC,SAAA;ADotQH;;ACjtQE;EACC,UAAA;ADotQH;;ACztQE;EACC,SAAA;AD4tQH;;ACztQE;EACC,UAAA;AD4tQH;;ACjuQE;EACC,SAAA;ADouQH;;ACjuQE;EACC,UAAA;ADouQH;;ACzuQE;EACC,SAAA;AD4uQH;;ACzuQE;EACC,UAAA;AD4uQH;;ACjvQE;EACC,SAAA;ADovQH;;ACjvQE;EACC,UAAA;ADovQH;;ACzvQE;EACC,SAAA;AD4vQH;;ACzvQE;EACC,UAAA;AD4vQH;;ACjwQE;EACC,SAAA;ADowQH;;ACjwQE;EACC,UAAA;ADowQH;;ACzwQE;EACC,SAAA;AD4wQH;;ACzwQE;EACC,UAAA;AD4wQH;;ACjxQE;EACC,SAAA;ADoxQH;;ACjxQE;EACC,UAAA;ADoxQH;;ACzxQE;EACC,SAAA;AD4xQH;;ACzxQE;EACC,UAAA;AD4xQH;;ACjyQE;EACC,SAAA;ADoyQH;;ACjyQE;EACC,UAAA;ADoyQH;;ACzyQE;EACC,SAAA;AD4yQH;;ACzyQE;EACC,UAAA;AD4yQH;;ACjzQE;EACC,SAAA;ADozQH;;ACjzQE;EACC,UAAA;ADozQH;;ACzzQE;EACC,SAAA;AD4zQH;;ACzzQE;EACC,UAAA;AD4zQH;;ACj0QE;EACC,SAAA;ADo0QH;;ACj0QE;EACC,UAAA;ADo0QH;;ACz0QE;EACC,SAAA;AD40QH;;ACz0QE;EACC,UAAA;AD40QH;;ACj1QE;EACC,SAAA;ADo1QH;;ACj1QE;EACC,UAAA;ADo1QH;;ACz1QE;EACC,SAAA;AD41QH;;ACz1QE;EACC,UAAA;AD41QH;;ACj2QE;EACC,SAAA;ADo2QH;;ACj2QE;EACC,UAAA;ADo2QH;;ACz2QE;EACC,SAAA;AD42QH;;ACz2QE;EACC,UAAA;AD42QH;;ACj3QE;EACC,SAAA;ADo3QH;;ACj3QE;EACC,UAAA;ADo3QH;;ACz3QE;EACC,SAAA;AD43QH;;ACz3QE;EACC,UAAA;AD43QH;;ACj4QE;EACC,SAAA;ADo4QH;;ACj4QE;EACC,UAAA;ADo4QH;;ACz4QE;EACC,SAAA;AD44QH;;ACz4QE;EACC,UAAA;AD44QH;;ACj5QE;EACC,SAAA;ADo5QH;;ACj5QE;EACC,UAAA;ADo5QH;;ACz5QE;EACC,SAAA;AD45QH;;ACz5QE;EACC,UAAA;AD45QH;;ACj6QE;EACC,SAAA;ADo6QH;;ACj6QE;EACC,UAAA;ADo6QH;;ACz6QE;EACC,SAAA;AD46QH;;ACz6QE;EACC,UAAA;AD46QH;;ACj7QE;EACC,SAAA;ADo7QH;;ACj7QE;EACC,UAAA;ADo7QH;;ACz7QE;EACC,SAAA;AD47QH;;ACz7QE;EACC,UAAA;AD47QH;;ACv7QE;EACC,QAAA;AD07QH;;ACv7QE;EACC,SAAA;AD07QH;;AC/7QE;EACC,QAAA;ADk8QH;;AC/7QE;EACC,SAAA;ADk8QH;;ACv8QE;EACC,QAAA;AD08QH;;ACv8QE;EACC,SAAA;AD08QH;;AC/8QE;EACC,QAAA;ADk9QH;;AC/8QE;EACC,SAAA;ADk9QH;;ACv9QE;EACC,SAAA;AD09QH;;ACv9QE;EACC,UAAA;AD09QH;;AC/9QE;EACC,SAAA;ADk+QH;;AC/9QE;EACC,UAAA;ADk+QH;;ACv+QE;EACC,SAAA;AD0+QH;;ACv+QE;EACC,UAAA;AD0+QH;;AC/+QE;EACC,SAAA;ADk/QH;;AC/+QE;EACC,UAAA;ADk/QH;;ACv/QE;EACC,SAAA;AD0/QH;;ACv/QE;EACC,UAAA;AD0/QH;;AC//QE;EACC,SAAA;ADkgRH;;AC//QE;EACC,UAAA;ADkgRH;;ACvgRE;EACC,SAAA;AD0gRH;;ACvgRE;EACC,UAAA;AD0gRH;;AC/gRE;EACC,SAAA;ADkhRH;;AC/gRE;EACC,UAAA;ADkhRH;;ACvhRE;EACC,SAAA;AD0hRH;;ACvhRE;EACC,UAAA;AD0hRH;;AC/hRE;EACC,SAAA;ADkiRH;;AC/hRE;EACC,UAAA;ADkiRH;;ACviRE;EACC,SAAA;AD0iRH;;ACviRE;EACC,UAAA;AD0iRH;;AC/iRE;EACC,SAAA;ADkjRH;;AC/iRE;EACC,UAAA;ADkjRH;;ACvjRE;EACC,SAAA;AD0jRH;;ACvjRE;EACC,UAAA;AD0jRH;;AC/jRE;EACC,SAAA;ADkkRH;;AC/jRE;EACC,UAAA;ADkkRH;;ACvkRE;EACC,SAAA;AD0kRH;;ACvkRE;EACC,UAAA;AD0kRH;;AC/kRE;EACC,SAAA;ADklRH;;AC/kRE;EACC,UAAA;ADklRH;;ACvlRE;EACC,SAAA;AD0lRH;;ACvlRE;EACC,UAAA;AD0lRH;;AC/lRE;EACC,SAAA;ADkmRH;;AC/lRE;EACC,UAAA;ADkmRH;;ACvmRE;EACC,SAAA;AD0mRH;;ACvmRE;EACC,UAAA;AD0mRH;;AC/mRE;EACC,SAAA;ADknRH;;AC/mRE;EACC,UAAA;ADknRH;;ACvnRE;EACC,SAAA;AD0nRH;;ACvnRE;EACC,UAAA;AD0nRH;;ACzoRE;EACC,UAAA;AD4oRH;;ACzoRE;EACC,WAAA;AD4oRH;;ACjpRE;EACC,UAAA;ADopRH;;ACjpRE;EACC,WAAA;ADopRH;;ACzpRE;EACC,UAAA;AD4pRH;;ACzpRE;EACC,WAAA;AD4pRH;;ACjqRE;EACC,UAAA;ADoqRH;;ACjqRE;EACC,WAAA;ADoqRH;;ACzqRE;EACC,UAAA;AD4qRH;;ACzqRE;EACC,WAAA;AD4qRH;;ACjrRE;EACC,UAAA;ADorRH;;ACjrRE;EACC,WAAA;ADorRH;;ACzrRE;EACC,UAAA;AD4rRH;;ACzrRE;EACC,WAAA;AD4rRH;;ACjsRE;EACC,UAAA;ADosRH;;ACjsRE;EACC,WAAA;ADosRH;;ACzsRE;EACC,UAAA;AD4sRH;;ACzsRE;EACC,WAAA;AD4sRH;;ACjtRE;EACC,UAAA;ADotRH;;ACjtRE;EACC,WAAA;ADotRH;;ACztRE;EACC,WAAA;AD4tRH;;ACztRE;EACC,YAAA;AD4tRH;;ACjuRE;EACC,WAAA;ADouRH;;ACjuRE;EACC,YAAA;ADouRH;;ACzuRE;EACC,WAAA;AD4uRH;;ACzuRE;EACC,YAAA;AD4uRH;;ACjvRE;EACC,WAAA;ADovRH;;ACjvRE;EACC,YAAA;ADovRH;;ACzvRE;EACC,WAAA;AD4vRH;;ACzvRE;EACC,YAAA;AD4vRH;;ACjwRE;EACC,WAAA;ADowRH;;ACjwRE;EACC,YAAA;ADowRH;;ACzwRE;EACC,WAAA;AD4wRH;;ACzwRE;EACC,YAAA;AD4wRH;;ACjxRE;EACC,WAAA;ADoxRH;;ACjxRE;EACC,YAAA;ADoxRH;;ACzxRE;EACC,WAAA;AD4xRH;;ACzxRE;EACC,YAAA;AD4xRH;;ACjyRE;EACC,WAAA;ADoyRH;;ACjyRE;EACC,YAAA;ADoyRH;;ACzyRE;EACC,WAAA;AD4yRH;;ACzyRE;EACC,YAAA;AD4yRH;;ACjzRE;EACC,WAAA;ADozRH;;ACjzRE;EACC,YAAA;ADozRH;;ACzzRE;EACC,WAAA;AD4zRH;;ACzzRE;EACC,YAAA;AD4zRH;;ACj0RE;EACC,WAAA;ADo0RH;;ACj0RE;EACC,YAAA;ADo0RH;;ACz0RE;EACC,WAAA;AD40RH;;ACz0RE;EACC,YAAA;AD40RH;;ACj1RE;EACC,WAAA;ADo1RH;;ACj1RE;EACC,YAAA;ADo1RH;;ACz1RE;EACC,WAAA;AD41RH;;ACz1RE;EACC,YAAA;AD41RH;;ACj2RE;EACC,WAAA;ADo2RH;;ACj2RE;EACC,YAAA;ADo2RH;;ACz2RE;EACC,WAAA;AD42RH;;ACz2RE;EACC,YAAA;AD42RH;;ACj3RE;EACC,WAAA;ADo3RH;;ACj3RE;EACC,YAAA;ADo3RH;;ACz3RE;EACC,WAAA;AD43RH;;ACz3RE;EACC,YAAA;AD43RH;;ACj4RE;EACC,WAAA;ADo4RH;;ACj4RE;EACC,YAAA;ADo4RH;;ACz4RE;EACC,WAAA;AD44RH;;ACz4RE;EACC,YAAA;AD44RH;;ACj5RE;EACC,WAAA;ADo5RH;;ACj5RE;EACC,YAAA;ADo5RH;;ACz5RE;EACC,WAAA;AD45RH;;ACz5RE;EACC,YAAA;AD45RH;;ACj6RE;EACC,WAAA;ADo6RH;;ACj6RE;EACC,YAAA;ADo6RH;;ACz6RE;EACC,WAAA;AD46RH;;ACz6RE;EACC,YAAA;AD46RH;;ACj7RE;EACC,WAAA;ADo7RH;;ACj7RE;EACC,YAAA;ADo7RH;;ACz7RE;EACC,WAAA;AD47RH;;ACz7RE;EACC,YAAA;AD47RH;;ACj8RE;EACC,WAAA;ADo8RH;;ACj8RE;EACC,YAAA;ADo8RH;;ACz8RE;EACC,WAAA;AD48RH;;ACz8RE;EACC,YAAA;AD48RH;;ACj9RE;EACC,WAAA;ADo9RH;;ACj9RE;EACC,YAAA;ADo9RH;;ACz9RE;EACC,WAAA;AD49RH;;ACz9RE;EACC,YAAA;AD49RH;;ACj+RE;EACC,WAAA;ADo+RH;;ACj+RE;EACC,YAAA;ADo+RH;;ACz+RE;EACC,WAAA;AD4+RH;;ACz+RE;EACC,YAAA;AD4+RH;;ACj/RE;EACC,WAAA;ADo/RH;;ACj/RE;EACC,YAAA;ADo/RH;;ACz/RE;EACC,WAAA;AD4/RH;;ACz/RE;EACC,YAAA;AD4/RH;;ACjgSE;EACC,WAAA;ADogSH;;ACjgSE;EACC,YAAA;ADogSH;;ACzgSE;EACC,WAAA;AD4gSH;;ACzgSE;EACC,YAAA;AD4gSH;;ACjhSE;EACC,WAAA;ADohSH;;ACjhSE;EACC,YAAA;ADohSH;;ACzhSE;EACC,WAAA;AD4hSH;;ACzhSE;EACC,YAAA;AD4hSH;;ACvhSE;EACC,UAAA;AD0hSH;;ACvhSE;EACC,WAAA;AD0hSH;;AC/hSE;EACC,UAAA;ADkiSH;;AC/hSE;EACC,WAAA;ADkiSH;;ACviSE;EACC,UAAA;AD0iSH;;ACviSE;EACC,WAAA;AD0iSH;;AC/iSE;EACC,UAAA;ADkjSH;;AC/iSE;EACC,WAAA;ADkjSH;;ACvjSE;EACC,WAAA;AD0jSH;;ACvjSE;EACC,YAAA;AD0jSH;;AC/jSE;EACC,WAAA;ADkkSH;;AC/jSE;EACC,YAAA;ADkkSH;;ACvkSE;EACC,WAAA;AD0kSH;;ACvkSE;EACC,YAAA;AD0kSH;;AC/kSE;EACC,WAAA;ADklSH;;AC/kSE;EACC,YAAA;ADklSH;;ACvlSE;EACC,WAAA;AD0lSH;;ACvlSE;EACC,YAAA;AD0lSH;;AC/lSE;EACC,WAAA;ADkmSH;;AC/lSE;EACC,YAAA;ADkmSH;;ACvmSE;EACC,WAAA;AD0mSH;;ACvmSE;EACC,YAAA;AD0mSH;;AC/mSE;EACC,WAAA;ADknSH;;AC/mSE;EACC,YAAA;ADknSH;;ACvnSE;EACC,WAAA;AD0nSH;;ACvnSE;EACC,YAAA;AD0nSH;;AC/nSE;EACC,WAAA;ADkoSH;;AC/nSE;EACC,YAAA;ADkoSH;;ACvoSE;EACC,WAAA;AD0oSH;;ACvoSE;EACC,YAAA;AD0oSH;;AC/oSE;EACC,WAAA;ADkpSH;;AC/oSE;EACC,YAAA;ADkpSH;;ACvpSE;EACC,WAAA;AD0pSH;;ACvpSE;EACC,YAAA;AD0pSH;;AC/pSE;EACC,WAAA;ADkqSH;;AC/pSE;EACC,YAAA;ADkqSH;;ACvqSE;EACC,WAAA;AD0qSH;;ACvqSE;EACC,YAAA;AD0qSH;;AC/qSE;EACC,WAAA;ADkrSH;;AC/qSE;EACC,YAAA;ADkrSH;;ACvrSE;EACC,WAAA;AD0rSH;;ACvrSE;EACC,YAAA;AD0rSH;;AC/rSE;EACC,WAAA;ADksSH;;AC/rSE;EACC,YAAA;ADksSH;;ACvsSE;EACC,WAAA;AD0sSH;;ACvsSE;EACC,YAAA;AD0sSH;;AC/sSE;EACC,WAAA;ADktSH;;AC/sSE;EACC,YAAA;ADktSH;;ACvtSE;EACC,WAAA;AD0tSH;;ACvtSE;EACC,YAAA;AD0tSH;;ACzuSE;EACC,WAAA;AD4uSH;;ACzuSE;EACC,YAAA;AD4uSH;;ACjvSE;EACC,WAAA;ADovSH;;ACjvSE;EACC,YAAA;ADovSH;;ACzvSE;EACC,WAAA;AD4vSH;;ACzvSE;EACC,YAAA;AD4vSH;;ACjwSE;EACC,WAAA;ADowSH;;ACjwSE;EACC,YAAA;ADowSH;;ACzwSE;EACC,WAAA;AD4wSH;;ACzwSE;EACC,YAAA;AD4wSH;;ACjxSE;EACC,WAAA;ADoxSH;;ACjxSE;EACC,YAAA;ADoxSH;;ACzxSE;EACC,WAAA;AD4xSH;;ACzxSE;EACC,YAAA;AD4xSH;;ACjySE;EACC,WAAA;ADoySH;;ACjySE;EACC,YAAA;ADoySH;;ACzySE;EACC,WAAA;AD4ySH;;ACzySE;EACC,YAAA;AD4ySH;;ACjzSE;EACC,WAAA;ADozSH;;ACjzSE;EACC,YAAA;ADozSH;;ACzzSE;EACC,YAAA;AD4zSH;;ACzzSE;EACC,aAAA;AD4zSH;;ACj0SE;EACC,YAAA;ADo0SH;;ACj0SE;EACC,aAAA;ADo0SH;;ACz0SE;EACC,YAAA;AD40SH;;ACz0SE;EACC,aAAA;AD40SH;;ACj1SE;EACC,YAAA;ADo1SH;;ACj1SE;EACC,aAAA;ADo1SH;;ACz1SE;EACC,YAAA;AD41SH;;ACz1SE;EACC,aAAA;AD41SH;;ACj2SE;EACC,YAAA;ADo2SH;;ACj2SE;EACC,aAAA;ADo2SH;;ACz2SE;EACC,YAAA;AD42SH;;ACz2SE;EACC,aAAA;AD42SH;;ACj3SE;EACC,YAAA;ADo3SH;;ACj3SE;EACC,aAAA;ADo3SH;;ACz3SE;EACC,YAAA;AD43SH;;ACz3SE;EACC,aAAA;AD43SH;;ACj4SE;EACC,YAAA;ADo4SH;;ACj4SE;EACC,aAAA;ADo4SH;;ACz4SE;EACC,YAAA;AD44SH;;ACz4SE;EACC,aAAA;AD44SH;;ACj5SE;EACC,YAAA;ADo5SH;;ACj5SE;EACC,aAAA;ADo5SH;;ACz5SE;EACC,YAAA;AD45SH;;ACz5SE;EACC,aAAA;AD45SH;;ACj6SE;EACC,YAAA;ADo6SH;;ACj6SE;EACC,aAAA;ADo6SH;;ACz6SE;EACC,YAAA;AD46SH;;ACz6SE;EACC,aAAA;AD46SH;;ACj7SE;EACC,YAAA;ADo7SH;;ACj7SE;EACC,aAAA;ADo7SH;;ACz7SE;EACC,YAAA;AD47SH;;ACz7SE;EACC,aAAA;AD47SH;;ACj8SE;EACC,YAAA;ADo8SH;;ACj8SE;EACC,aAAA;ADo8SH;;ACz8SE;EACC,YAAA;AD48SH;;ACz8SE;EACC,aAAA;AD48SH;;ACj9SE;EACC,YAAA;ADo9SH;;ACj9SE;EACC,aAAA;ADo9SH;;ACz9SE;EACC,YAAA;AD49SH;;ACz9SE;EACC,aAAA;AD49SH;;ACj+SE;EACC,YAAA;ADo+SH;;ACj+SE;EACC,aAAA;ADo+SH;;ACz+SE;EACC,YAAA;AD4+SH;;ACz+SE;EACC,aAAA;AD4+SH;;ACj/SE;EACC,YAAA;ADo/SH;;ACj/SE;EACC,aAAA;ADo/SH;;ACz/SE;EACC,YAAA;AD4/SH;;ACz/SE;EACC,aAAA;AD4/SH;;ACjgTE;EACC,YAAA;ADogTH;;ACjgTE;EACC,aAAA;ADogTH;;ACzgTE;EACC,YAAA;AD4gTH;;ACzgTE;EACC,aAAA;AD4gTH;;ACjhTE;EACC,YAAA;ADohTH;;ACjhTE;EACC,aAAA;ADohTH;;ACzhTE;EACC,YAAA;AD4hTH;;ACzhTE;EACC,aAAA;AD4hTH;;ACjiTE;EACC,YAAA;ADoiTH;;ACjiTE;EACC,aAAA;ADoiTH;;ACziTE;EACC,YAAA;AD4iTH;;ACziTE;EACC,aAAA;AD4iTH;;ACjjTE;EACC,YAAA;ADojTH;;ACjjTE;EACC,aAAA;ADojTH;;ACzjTE;EACC,YAAA;AD4jTH;;ACzjTE;EACC,aAAA;AD4jTH;;ACjkTE;EACC,YAAA;ADokTH;;ACjkTE;EACC,aAAA;ADokTH;;ACzkTE;EACC,YAAA;AD4kTH;;ACzkTE;EACC,aAAA;AD4kTH;;ACjlTE;EACC,YAAA;ADolTH;;ACjlTE;EACC,aAAA;ADolTH;;ACzlTE;EACC,YAAA;AD4lTH;;ACzlTE;EACC,aAAA;AD4lTH;;ACjmTE;EACC,YAAA;ADomTH;;ACjmTE;EACC,aAAA;ADomTH;;ACzmTE;EACC,YAAA;AD4mTH;;ACzmTE;EACC,aAAA;AD4mTH;;ACjnTE;EACC,YAAA;ADonTH;;ACjnTE;EACC,aAAA;ADonTH;;ACznTE;EACC,YAAA;AD4nTH;;ACznTE;EACC,aAAA;AD4nTH;;ACvnTE;EACC,WAAA;AD0nTH;;ACvnTE;EACC,YAAA;AD0nTH;;AC/nTE;EACC,WAAA;ADkoTH;;AC/nTE;EACC,YAAA;ADkoTH;;ACvoTE;EACC,WAAA;AD0oTH;;ACvoTE;EACC,YAAA;AD0oTH;;AC/oTE;EACC,WAAA;ADkpTH;;AC/oTE;EACC,YAAA;ADkpTH;;ACvpTE;EACC,YAAA;AD0pTH;;ACvpTE;EACC,aAAA;AD0pTH;;AC/pTE;EACC,YAAA;ADkqTH;;AC/pTE;EACC,aAAA;ADkqTH;;ACvqTE;EACC,YAAA;AD0qTH;;ACvqTE;EACC,aAAA;AD0qTH;;AC/qTE;EACC,YAAA;ADkrTH;;AC/qTE;EACC,aAAA;ADkrTH;;ACvrTE;EACC,YAAA;AD0rTH;;ACvrTE;EACC,aAAA;AD0rTH;;AC/rTE;EACC,YAAA;ADksTH;;AC/rTE;EACC,aAAA;ADksTH;;ACvsTE;EACC,YAAA;AD0sTH;;ACvsTE;EACC,aAAA;AD0sTH;;AC/sTE;EACC,YAAA;ADktTH;;AC/sTE;EACC,aAAA;ADktTH;;ACvtTE;EACC,YAAA;AD0tTH;;ACvtTE;EACC,aAAA;AD0tTH;;AC/tTE;EACC,YAAA;ADkuTH;;AC/tTE;EACC,aAAA;ADkuTH;;ACvuTE;EACC,YAAA;AD0uTH;;ACvuTE;EACC,aAAA;AD0uTH;;AC/uTE;EACC,YAAA;ADkvTH;;AC/uTE;EACC,aAAA;ADkvTH;;ACvvTE;EACC,YAAA;AD0vTH;;ACvvTE;EACC,aAAA;AD0vTH;;AC/vTE;EACC,YAAA;ADkwTH;;AC/vTE;EACC,aAAA;ADkwTH;;ACvwTE;EACC,YAAA;AD0wTH;;ACvwTE;EACC,aAAA;AD0wTH;;AC/wTE;EACC,YAAA;ADkxTH;;AC/wTE;EACC,aAAA;ADkxTH;;ACvxTE;EACC,YAAA;AD0xTH;;ACvxTE;EACC,aAAA;AD0xTH;;AC/xTE;EACC,YAAA;ADkyTH;;AC/xTE;EACC,aAAA;ADkyTH;;ACvyTE;EACC,YAAA;AD0yTH;;ACvyTE;EACC,aAAA;AD0yTH;;AC/yTE;EACC,YAAA;ADkzTH;;AC/yTE;EACC,aAAA;ADkzTH;;ACvzTE;EACC,YAAA;AD0zTH;;ACvzTE;EACC,aAAA;AD0zTH;;ACz0TE;EACC,SAAA;AD40TH;;ACz0TE;EACC,UAAA;AD40TH;;ACj1TE;EACC,SAAA;ADo1TH;;ACj1TE;EACC,UAAA;ADo1TH;;ACz1TE;EACC,SAAA;AD41TH;;ACz1TE;EACC,UAAA;AD41TH;;ACj2TE;EACC,SAAA;ADo2TH;;ACj2TE;EACC,UAAA;ADo2TH;;ACz2TE;EACC,SAAA;AD42TH;;ACz2TE;EACC,UAAA;AD42TH;;ACj3TE;EACC,SAAA;ADo3TH;;ACj3TE;EACC,UAAA;ADo3TH;;ACz3TE;EACC,SAAA;AD43TH;;ACz3TE;EACC,UAAA;AD43TH;;ACj4TE;EACC,SAAA;ADo4TH;;ACj4TE;EACC,UAAA;ADo4TH;;ACz4TE;EACC,SAAA;AD44TH;;ACz4TE;EACC,UAAA;AD44TH;;ACj5TE;EACC,SAAA;ADo5TH;;ACj5TE;EACC,UAAA;ADo5TH;;ACz5TE;EACC,UAAA;AD45TH;;ACz5TE;EACC,WAAA;AD45TH;;ACj6TE;EACC,UAAA;ADo6TH;;ACj6TE;EACC,WAAA;ADo6TH;;ACz6TE;EACC,UAAA;AD46TH;;ACz6TE;EACC,WAAA;AD46TH;;ACj7TE;EACC,UAAA;ADo7TH;;ACj7TE;EACC,WAAA;ADo7TH;;ACz7TE;EACC,UAAA;AD47TH;;ACz7TE;EACC,WAAA;AD47TH;;ACj8TE;EACC,UAAA;ADo8TH;;ACj8TE;EACC,WAAA;ADo8TH;;ACz8TE;EACC,UAAA;AD48TH;;ACz8TE;EACC,WAAA;AD48TH;;ACj9TE;EACC,UAAA;ADo9TH;;ACj9TE;EACC,WAAA;ADo9TH;;ACz9TE;EACC,UAAA;AD49TH;;ACz9TE;EACC,WAAA;AD49TH;;ACj+TE;EACC,UAAA;ADo+TH;;ACj+TE;EACC,WAAA;ADo+TH;;ACz+TE;EACC,UAAA;AD4+TH;;ACz+TE;EACC,WAAA;AD4+TH;;ACj/TE;EACC,UAAA;ADo/TH;;ACj/TE;EACC,WAAA;ADo/TH;;ACz/TE;EACC,UAAA;AD4/TH;;ACz/TE;EACC,WAAA;AD4/TH;;ACjgUE;EACC,UAAA;ADogUH;;ACjgUE;EACC,WAAA;ADogUH;;ACzgUE;EACC,UAAA;AD4gUH;;ACzgUE;EACC,WAAA;AD4gUH;;ACjhUE;EACC,UAAA;ADohUH;;ACjhUE;EACC,WAAA;ADohUH;;ACzhUE;EACC,UAAA;AD4hUH;;ACzhUE;EACC,WAAA;AD4hUH;;ACjiUE;EACC,UAAA;ADoiUH;;ACjiUE;EACC,WAAA;ADoiUH;;ACziUE;EACC,UAAA;AD4iUH;;ACziUE;EACC,WAAA;AD4iUH;;ACjjUE;EACC,UAAA;ADojUH;;ACjjUE;EACC,WAAA;ADojUH;;ACzjUE;EACC,UAAA;AD4jUH;;ACzjUE;EACC,WAAA;AD4jUH;;ACjkUE;EACC,UAAA;ADokUH;;ACjkUE;EACC,WAAA;ADokUH;;ACzkUE;EACC,UAAA;AD4kUH;;ACzkUE;EACC,WAAA;AD4kUH;;ACjlUE;EACC,UAAA;ADolUH;;ACjlUE;EACC,WAAA;ADolUH;;ACzlUE;EACC,UAAA;AD4lUH;;ACzlUE;EACC,WAAA;AD4lUH;;ACjmUE;EACC,UAAA;ADomUH;;ACjmUE;EACC,WAAA;ADomUH;;ACzmUE;EACC,UAAA;AD4mUH;;ACzmUE;EACC,WAAA;AD4mUH;;ACjnUE;EACC,UAAA;ADonUH;;ACjnUE;EACC,WAAA;ADonUH;;ACznUE;EACC,UAAA;AD4nUH;;ACznUE;EACC,WAAA;AD4nUH;;ACjoUE;EACC,UAAA;ADooUH;;ACjoUE;EACC,WAAA;ADooUH;;ACzoUE;EACC,UAAA;AD4oUH;;ACzoUE;EACC,WAAA;AD4oUH;;ACjpUE;EACC,UAAA;ADopUH;;ACjpUE;EACC,WAAA;ADopUH;;ACzpUE;EACC,UAAA;AD4pUH;;ACzpUE;EACC,WAAA;AD4pUH;;ACjqUE;EACC,UAAA;ADoqUH;;ACjqUE;EACC,WAAA;ADoqUH;;ACzqUE;EACC,UAAA;AD4qUH;;ACzqUE;EACC,WAAA;AD4qUH;;ACjrUE;EACC,UAAA;ADorUH;;ACjrUE;EACC,WAAA;ADorUH;;ACzrUE;EACC,UAAA;AD4rUH;;ACzrUE;EACC,WAAA;AD4rUH;;ACjsUE;EACC,UAAA;ADosUH;;ACjsUE;EACC,WAAA;ADosUH;;ACzsUE;EACC,UAAA;AD4sUH;;ACzsUE;EACC,WAAA;AD4sUH;;ACjtUE;EACC,UAAA;ADotUH;;ACjtUE;EACC,WAAA;ADotUH;;ACztUE;EACC,UAAA;AD4tUH;;ACztUE;EACC,WAAA;AD4tUH;;ACvtUE;EACC,SAAA;AD0tUH;;ACvtUE;EACC,UAAA;AD0tUH;;AC/tUE;EACC,SAAA;ADkuUH;;AC/tUE;EACC,UAAA;ADkuUH;;ACvuUE;EACC,SAAA;AD0uUH;;ACvuUE;EACC,UAAA;AD0uUH;;AC/uUE;EACC,SAAA;ADkvUH;;AC/uUE;EACC,UAAA;ADkvUH;;ACvvUE;EACC,UAAA;AD0vUH;;ACvvUE;EACC,WAAA;AD0vUH;;AC/vUE;EACC,UAAA;ADkwUH;;AC/vUE;EACC,WAAA;ADkwUH;;ACvwUE;EACC,UAAA;AD0wUH;;ACvwUE;EACC,WAAA;AD0wUH;;AC/wUE;EACC,UAAA;ADkxUH;;AC/wUE;EACC,WAAA;ADkxUH;;ACvxUE;EACC,UAAA;AD0xUH;;ACvxUE;EACC,WAAA;AD0xUH;;AC/xUE;EACC,UAAA;ADkyUH;;AC/xUE;EACC,WAAA;ADkyUH;;ACvyUE;EACC,UAAA;AD0yUH;;ACvyUE;EACC,WAAA;AD0yUH;;AC/yUE;EACC,UAAA;ADkzUH;;AC/yUE;EACC,WAAA;ADkzUH;;ACvzUE;EACC,UAAA;AD0zUH;;ACvzUE;EACC,WAAA;AD0zUH;;AC/zUE;EACC,UAAA;ADk0UH;;AC/zUE;EACC,WAAA;ADk0UH;;ACv0UE;EACC,UAAA;AD00UH;;ACv0UE;EACC,WAAA;AD00UH;;AC/0UE;EACC,UAAA;ADk1UH;;AC/0UE;EACC,WAAA;ADk1UH;;ACv1UE;EACC,UAAA;AD01UH;;ACv1UE;EACC,WAAA;AD01UH;;AC/1UE;EACC,UAAA;ADk2UH;;AC/1UE;EACC,WAAA;ADk2UH;;ACv2UE;EACC,UAAA;AD02UH;;ACv2UE;EACC,WAAA;AD02UH;;AC/2UE;EACC,UAAA;ADk3UH;;AC/2UE;EACC,WAAA;ADk3UH;;ACv3UE;EACC,UAAA;AD03UH;;ACv3UE;EACC,WAAA;AD03UH;;AC/3UE;EACC,UAAA;ADk4UH;;AC/3UE;EACC,WAAA;ADk4UH;;ACv4UE;EACC,UAAA;AD04UH;;ACv4UE;EACC,WAAA;AD04UH;;AC/4UE;EACC,UAAA;ADk5UH;;AC/4UE;EACC,WAAA;ADk5UH;;ACv5UE;EACC,UAAA;AD05UH;;ACv5UE;EACC,WAAA;AD05UH;;AC94UA;EACC,aAAA;ADi5UD;;AC94UA;EACC,sBAAA;ADi5UD;;AC94UA;EACC,mBAAA;ADi5UD;;AC94UA;EACC,cAAA;ADi5UD;;AC94UA;EACC,mBAAA;ADi5UD;;AC94UA;EACC,2BAAA;ADi5UD;;AC74UA;EA9BC,2BA+BqB;EA9BrB,uBA8BiC;EA7BjC,aAAA;AD+6UD;;AC94UA;EAnCC,uBAoCqB;EAnCrB,uBAmC6B;EAlC7B,aAAA;ADq7UD;;AC/4UA;EAxCC,yBAyCqB;EAxCrB,uBAwC+B;EAvC/B,aAAA;AD27UD;;ACh5UA;EA7CC,2BA8CqB;EA7CrB,mBA6CiC;EA5CjC,aAAA;ADi8UD;;ACj5UA;EAlDC,uBAmDqB;EAlDrB,mBAkD6B;EAjD7B,aAAA;ADu8UD;;ACl5UA;EAvDC,yBAwDqB;EAvDrB,mBAuD+B;EAtD/B,aAAA;AD68UD;;ACn5UA;EA5DC,2BA6DqB;EA5DrB,qBA4DiC;EA3DjC,aAAA;ADm9UD;;ACp5UA;EAjEC,uBAkEqB;EAjErB,qBAiE6B;EAhE7B,aAAA;ADy9UD;;ACr5UA;EAtEC,yBAuEqB;EAtErB,qBAsE+B;EArE/B,aAAA;AD+9UD;;ACt5UA;EA3EC,8BA4EqB;EA3ErB,mBA2EoC;EA1EpC,aAAA;ADq+UD;;ACt5UA;EAjFC,2BAkFqB;EAjFrB,uBAiFiC;EAhFjC,aAAA;AD2+UD;;ACv5UA;EAtFC,2BAuFqB;EAtFrB,mBAsFiC;EArFjC,aAAA;ADi/UD;;ACx5UA;EA3FC,2BA4FqB;EA3FrB,qBA2FiC;EA1FjC,aAAA;ADu/UD;;ACz5UA;EAhGC,uBAiGqB;EAhGrB,uBAgG6B;EA/F7B,aAAA;AD6/UD;;AC15UA;EArGC,uBAsGqB;EArGrB,mBAqG6B;EApG7B,aAAA;ADmgVD;;AC35UA;EA1GC,uBA2GqB;EA1GrB,qBA0G6B;EAzG7B,aAAA;ADygVD;;AC55UA;EA/GC,yBAgHqB;EA/GrB,uBA+G+B;EA9G/B,aAAA;AD+gVD;;AC75UA;EApHC,yBAqHqB;EApHrB,mBAoH+B;EAnH/B,aAAA;ADqhVD;;AC95UA;EAzHC,yBA0HqB;EAzHrB,qBAyH+B;EAxH/B,aAAA;AD2hVD;;AC75UA;EAhIC,2BAiIqB;EAhIrB,mBAgIiC;EA/HjC,aAAA;ADiiVD;;AC95UA;EArIC,yBAsIqB;EArIrB,mBAqI+B;EApI/B,aAAA;ADuiVD;;AC/5UA;EA1IC,uBA2IqB;EA1IrB,mBA0I6B;EAzI7B,aAAA;AD6iVD;;ACh6UA;EACC,8BAAA;ADm6UD;;AC/5UA;EACC,sBAAA;EACA,oBAAA;ADk6UD;;AC95UA;EACC,6BAAA;ADi6UD;;AC75UC;EACC,OAFW;ADk6Ub;;ACj6UC;EACC,OAFW;ADs6Ub;;ACr6UC;EACC,OAFW;AD06Ub;;ACz6UC;EACC,OAFW;AD86Ub;;AC76UC;EACC,OAFW;ADk7Ub;;ACj7UC;EACC,OAFW;ADs7Ub;;ACr7UC;EACC,OAFW;AD07Ub;;ACz7UC;EACC,OAFW;AD87Ub;;AC77UC;EACC,OAFW;ADk8Ub;;ACj8UC;EACC,OAFW;ADs8Ub;;ACr8UC;EACC,QAFW;AD08Ub;;ACz8UC;EACC,QAFW;AD88Ub;;AC78UC;EACC,QAFW;ADk9Ub;;ACp6UC;EACC,cAxBO;AD+7UT;;ACp6UC;EACC,yBA5BO;ADm8UT;;AC56UC;EACC,cAxBO;ADu8UT;;AC56UC;EACC,yBA5BO;AD28UT;;ACp7UC;EACC,cAxBO;AD+8UT;;ACp7UC;EACC,yBA5BO;ADm9UT;;AC57UC;EACC,cAxBO;ADu9UT;;AC57UC;EACC,yBA5BO;AD29UT;;ACp8UC;EACC,cAxBO;AD+9UT;;ACp8UC;EACC,yBA5BO;ADm+UT;;AC58UC;EACC,cAxBO;ADu+UT;;AC58UC;EACC,yBA5BO;AD2+UT;;ACp9UC;EACC,cAxBO;AD++UT;;ACp9UC;EACC,yBA5BO;ADm/UT;;AC59UC;EACC,cAxBO;ADu/UT;;AC59UC;EACC,yBA5BO;AD2/UT;;ACp+UC;EACC,cAxBO;AD+/UT;;ACp+UC;EACC,yBA5BO;ADmgVT;;AC5+UC;EACC,cAxBO;ADugVT;;AC5+UC;EACC,yBA5BO;AD2gVT;;ACp/UC;EACC,cAxBO;AD+gVT;;ACp/UC;EACC,yBA5BO;ADmhVT;;AC5/UC;EACC,cAxBO;ADuhVT;;AC5/UC;EACC,yBA5BO;AD2hVT;;ACpgVC;EACC,cAxBO;AD+hVT;;ACpgVC;EACC,yBA5BO;ADmiVT;;AC5gVC;EACC,cAxBO;ADuiVT;;AC5gVC;EACC,yBA5BO;AD2iVT;;ACphVC;EACC,cAxBO;AD+iVT;;ACphVC;EACC,yBA5BO;ADmjVT;;AC5hVC;EACC,cAxBO;ADujVT;;AC5hVC;EACC,yBA5BO;AD2jVT;;ACpiVC;EACC,cAxBO;AD+jVT;;ACpiVC;EACC,yBA5BO;ADmkVT;;AC5iVC;EACC,cAxBO;ADukVT;;AC5iVC;EACC,yBA5BO;AD2kVT;;AC1iVC;EACC,cAlDc;AD+lVhB;;AC1iVC;EACC,yBAtDc;ADmmVhB;;ACljVC;EACC,cAlDc;ADumVhB;;ACljVC;EACC,yBAtDc;AD2mVhB;;AC1jVC;EACC,cAlDc;AD+mVhB;;AC1jVC;EACC,yBAtDc;ADmnVhB;;AClkVC;EACC,cAlDc;ADunVhB;;AClkVC;EACC,yBAtDc;AD2nVhB;;AC1kVC;EACC,cAlDc;AD+nVhB;;AC1kVC;EACC,yBAtDc;ADmoVhB;;ACllVC;EACC,cAlDc;ADuoVhB;;ACllVC;EACC,yBAtDc;AD2oVhB;;AC1lVC;EACC,cAlDc;AD+oVhB;;AC1lVC;EACC,yBAtDc;ADmpVhB;;AClmVC;EACC,cAlDc;ADupVhB;;AClmVC;EACC,yBAtDc;AD2pVhB;;AC1mVC;EACC,cAlDc;AD+pVhB;;AC1mVC;EACC,yBAtDc;ADmqVhB;;AClnVC;EACC,cAlDc;ADuqVhB;;AClnVC;EACC,yBAtDc;AD2qVhB;;AC1nVC;EACC,cAlDc;AD+qVhB;;AC1nVC;EACC,yBAtDc;ADmrVhB;;ACloVC;EACC,cAlDc;ADurVhB;;ACloVC;EACC,yBAtDc;AD2rVhB;;AC1oVC;EACC,cAlDc;AD+rVhB;;AC1oVC;EACC,yBAtDc;ADmsVhB;;AClpVC;EACC,cAlDc;ADusVhB;;AClpVC;EACC,yBAtDc;AD2sVhB","file":"uvuePx.css"} \ No newline at end of file diff --git a/uni_modules/tmx-ui/scss/uvuePx.min.css b/uni_modules/tmx-ui/scss/uvuePx.min.css new file mode 100644 index 0000000..8ba4b58 --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvuePx.min.css @@ -0,0 +1 @@ +@charset "UTF-8";.uni-picker-view-mask{background-image:none!important}.overflow{overflow:hidden}.show{visibility:visible}.hidden{visibility:hidden}.none{display:none}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.fulled{width:100%}.fulled-height{flex:1}.zIndex-0{z-index:0}.zIndex-n0{z-index:0}.zIndex-1{z-index:1}.zIndex-n1{z-index:2}.zIndex-2{z-index:2}.zIndex-n2{z-index:4}.zIndex-3{z-index:3}.zIndex-n3{z-index:6}.zIndex-4{z-index:4}.zIndex-n4{z-index:8}.zIndex-5{z-index:5}.zIndex-n5{z-index:10}.zIndex-6{z-index:6}.zIndex-n6{z-index:12}.zIndex-7{z-index:7}.zIndex-n7{z-index:14}.zIndex-8{z-index:8}.zIndex-n8{z-index:16}.zIndex-9{z-index:9}.zIndex-n9{z-index:18}.zIndex-10{z-index:10}.zIndex-n10{z-index:20}.zIndex-11{z-index:11}.zIndex-n11{z-index:22}.zIndex-12{z-index:12}.zIndex-n12{z-index:24}.zIndex-13{z-index:13}.zIndex-n13{z-index:26}.zIndex-14{z-index:14}.zIndex-n14{z-index:28}.zIndex-15{z-index:15}.zIndex-n15{z-index:30}.zIndex-16{z-index:16}.zIndex-n16{z-index:32}.zIndex-17{z-index:17}.zIndex-n17{z-index:34}.zIndex-18{z-index:18}.zIndex-n18{z-index:36}.zIndex-19{z-index:19}.zIndex-n19{z-index:38}.zIndex-20{z-index:20}.zIndex-n20{z-index:40}.zIndex-21{z-index:21}.zIndex-n21{z-index:42}.zIndex-22{z-index:22}.zIndex-n22{z-index:44}.zIndex-23{z-index:23}.zIndex-n23{z-index:46}.zIndex-24{z-index:24}.zIndex-n24{z-index:48}.zIndex-25{z-index:25}.zIndex-n25{z-index:50}.zIndex-26{z-index:26}.zIndex-n26{z-index:52}.text-overflow{text-overflow:ellipsis}.text-overflow-1{text-overflow:ellipsis;lines:1}.text-overflow-2{text-overflow:ellipsis;lines:2}.text-overflow-3{text-overflow:ellipsis;lines:3}.text-overflow-4{text-overflow:ellipsis;lines:4}.text-overflow-5{text-overflow:ellipsis;lines:5}.text-size-xxs{font-size:10px}.text-size-xs{font-size:11px}.text-size-s{font-size:12px}.text-size-m{font-size:14px}.text-size-n{font-size:15px}.text-size-g{font-size:17px}.text-size-lg{font-size:18px}.text-size-xl{font-size:20px}.text-weight-s{font-weight:400}.text-weight-n{font-weight:400}.text-weight-b{font-weight:700}.text-align-left{text-align:left}.text-align-right{text-align:right}.text-align-center{text-align:center}.round-tl-0{border-top-left-radius:0}.round-tl-1{border-top-left-radius:1px}.round-tl-2{border-top-left-radius:2px}.round-tl-3{border-top-left-radius:3px}.round-tl-4{border-top-left-radius:4px}.round-tl-5{border-top-left-radius:5px}.round-tl-6{border-top-left-radius:6px}.round-tl-7{border-top-left-radius:7px}.round-tl-8{border-top-left-radius:8px}.round-tl-9{border-top-left-radius:9px}.round-tl-10{border-top-left-radius:10px}.round-tl-11{border-top-left-radius:11px}.round-tl-12{border-top-left-radius:12px}.round-tl-13{border-top-left-radius:13px}.round-tl-14{border-top-left-radius:14px}.round-tl-15{border-top-left-radius:15px}.round-tl-16{border-top-left-radius:16px}.round-tl-17{border-top-left-radius:17px}.round-tl-18{border-top-left-radius:18px}.round-tl-19{border-top-left-radius:19px}.round-tl-20{border-top-left-radius:20px}.round-tl-21{border-top-left-radius:21px}.round-tl-22{border-top-left-radius:22px}.round-tl-23{border-top-left-radius:23px}.round-tl-24{border-top-left-radius:24px}.round-tl-25{border-top-left-radius:25px}.round-tl-26{border-top-left-radius:26px}.round-tl-27{border-top-left-radius:27px}.round-tl-28{border-top-left-radius:28px}.round-tl-29{border-top-left-radius:29px}.round-tl-30{border-top-left-radius:30px}.round-tl-31{border-top-left-radius:31px}.round-tl-32{border-top-left-radius:32px}.round-tl-33{border-top-left-radius:33px}.round-tl-34{border-top-left-radius:34px}.round-tl-35{border-top-left-radius:35px}.round-tl-36{border-top-left-radius:36px}.round-tl-37{border-top-left-radius:37px}.round-tl-38{border-top-left-radius:38px}.round-tl-39{border-top-left-radius:39px}.round-tl-40{border-top-left-radius:40px}.round-tl-41{border-top-left-radius:41px}.round-tl-42{border-top-left-radius:42px}.round-tl-43{border-top-left-radius:43px}.round-tl-44{border-top-left-radius:44px}.round-tl-45{border-top-left-radius:45px}.round-tl-46{border-top-left-radius:46px}.round-tl-47{border-top-left-radius:47px}.round-tl-48{border-top-left-radius:48px}.round-tl-49{border-top-left-radius:49px}.round-tl-50{border-top-left-radius:50px}.round-tr-0{border-top-right-radius:0}.round-tr-1{border-top-right-radius:1px}.round-tr-2{border-top-right-radius:2px}.round-tr-3{border-top-right-radius:3px}.round-tr-4{border-top-right-radius:4px}.round-tr-5{border-top-right-radius:5px}.round-tr-6{border-top-right-radius:6px}.round-tr-7{border-top-right-radius:7px}.round-tr-8{border-top-right-radius:8px}.round-tr-9{border-top-right-radius:9px}.round-tr-10{border-top-right-radius:10px}.round-tr-11{border-top-right-radius:11px}.round-tr-12{border-top-right-radius:12px}.round-tr-13{border-top-right-radius:13px}.round-tr-14{border-top-right-radius:14px}.round-tr-15{border-top-right-radius:15px}.round-tr-16{border-top-right-radius:16px}.round-tr-17{border-top-right-radius:17px}.round-tr-18{border-top-right-radius:18px}.round-tr-19{border-top-right-radius:19px}.round-tr-20{border-top-right-radius:20px}.round-tr-21{border-top-right-radius:21px}.round-tr-22{border-top-right-radius:22px}.round-tr-23{border-top-right-radius:23px}.round-tr-24{border-top-right-radius:24px}.round-tr-25{border-top-right-radius:25px}.round-tr-26{border-top-right-radius:26px}.round-tr-27{border-top-right-radius:27px}.round-tr-28{border-top-right-radius:28px}.round-tr-29{border-top-right-radius:29px}.round-tr-30{border-top-right-radius:30px}.round-tr-31{border-top-right-radius:31px}.round-tr-32{border-top-right-radius:32px}.round-tr-33{border-top-right-radius:33px}.round-tr-34{border-top-right-radius:34px}.round-tr-35{border-top-right-radius:35px}.round-tr-36{border-top-right-radius:36px}.round-tr-37{border-top-right-radius:37px}.round-tr-38{border-top-right-radius:38px}.round-tr-39{border-top-right-radius:39px}.round-tr-40{border-top-right-radius:40px}.round-tr-41{border-top-right-radius:41px}.round-tr-42{border-top-right-radius:42px}.round-tr-43{border-top-right-radius:43px}.round-tr-44{border-top-right-radius:44px}.round-tr-45{border-top-right-radius:45px}.round-tr-46{border-top-right-radius:46px}.round-tr-47{border-top-right-radius:47px}.round-tr-48{border-top-right-radius:48px}.round-tr-49{border-top-right-radius:49px}.round-tr-50{border-top-right-radius:50px}.round-bl-0{border-bottom-left-radius:0}.round-bl-1{border-bottom-left-radius:1px}.round-bl-2{border-bottom-left-radius:2px}.round-bl-3{border-bottom-left-radius:3px}.round-bl-4{border-bottom-left-radius:4px}.round-bl-5{border-bottom-left-radius:5px}.round-bl-6{border-bottom-left-radius:6px}.round-bl-7{border-bottom-left-radius:7px}.round-bl-8{border-bottom-left-radius:8px}.round-bl-9{border-bottom-left-radius:9px}.round-bl-10{border-bottom-left-radius:10px}.round-bl-11{border-bottom-left-radius:11px}.round-bl-12{border-bottom-left-radius:12px}.round-bl-13{border-bottom-left-radius:13px}.round-bl-14{border-bottom-left-radius:14px}.round-bl-15{border-bottom-left-radius:15px}.round-bl-16{border-bottom-left-radius:16px}.round-bl-17{border-bottom-left-radius:17px}.round-bl-18{border-bottom-left-radius:18px}.round-bl-19{border-bottom-left-radius:19px}.round-bl-20{border-bottom-left-radius:20px}.round-bl-21{border-bottom-left-radius:21px}.round-bl-22{border-bottom-left-radius:22px}.round-bl-23{border-bottom-left-radius:23px}.round-bl-24{border-bottom-left-radius:24px}.round-bl-25{border-bottom-left-radius:25px}.round-bl-26{border-bottom-left-radius:26px}.round-bl-27{border-bottom-left-radius:27px}.round-bl-28{border-bottom-left-radius:28px}.round-bl-29{border-bottom-left-radius:29px}.round-bl-30{border-bottom-left-radius:30px}.round-bl-31{border-bottom-left-radius:31px}.round-bl-32{border-bottom-left-radius:32px}.round-bl-33{border-bottom-left-radius:33px}.round-bl-34{border-bottom-left-radius:34px}.round-bl-35{border-bottom-left-radius:35px}.round-bl-36{border-bottom-left-radius:36px}.round-bl-37{border-bottom-left-radius:37px}.round-bl-38{border-bottom-left-radius:38px}.round-bl-39{border-bottom-left-radius:39px}.round-bl-40{border-bottom-left-radius:40px}.round-bl-41{border-bottom-left-radius:41px}.round-bl-42{border-bottom-left-radius:42px}.round-bl-43{border-bottom-left-radius:43px}.round-bl-44{border-bottom-left-radius:44px}.round-bl-45{border-bottom-left-radius:45px}.round-bl-46{border-bottom-left-radius:46px}.round-bl-47{border-bottom-left-radius:47px}.round-bl-48{border-bottom-left-radius:48px}.round-bl-49{border-bottom-left-radius:49px}.round-bl-50{border-bottom-left-radius:50px}.round-br-0{border-bottom-right-radius:0}.round-br-1{border-bottom-right-radius:1px}.round-br-2{border-bottom-right-radius:2px}.round-br-3{border-bottom-right-radius:3px}.round-br-4{border-bottom-right-radius:4px}.round-br-5{border-bottom-right-radius:5px}.round-br-6{border-bottom-right-radius:6px}.round-br-7{border-bottom-right-radius:7px}.round-br-8{border-bottom-right-radius:8px}.round-br-9{border-bottom-right-radius:9px}.round-br-10{border-bottom-right-radius:10px}.round-br-11{border-bottom-right-radius:11px}.round-br-12{border-bottom-right-radius:12px}.round-br-13{border-bottom-right-radius:13px}.round-br-14{border-bottom-right-radius:14px}.round-br-15{border-bottom-right-radius:15px}.round-br-16{border-bottom-right-radius:16px}.round-br-17{border-bottom-right-radius:17px}.round-br-18{border-bottom-right-radius:18px}.round-br-19{border-bottom-right-radius:19px}.round-br-20{border-bottom-right-radius:20px}.round-br-21{border-bottom-right-radius:21px}.round-br-22{border-bottom-right-radius:22px}.round-br-23{border-bottom-right-radius:23px}.round-br-24{border-bottom-right-radius:24px}.round-br-25{border-bottom-right-radius:25px}.round-br-26{border-bottom-right-radius:26px}.round-br-27{border-bottom-right-radius:27px}.round-br-28{border-bottom-right-radius:28px}.round-br-29{border-bottom-right-radius:29px}.round-br-30{border-bottom-right-radius:30px}.round-br-31{border-bottom-right-radius:31px}.round-br-32{border-bottom-right-radius:32px}.round-br-33{border-bottom-right-radius:33px}.round-br-34{border-bottom-right-radius:34px}.round-br-35{border-bottom-right-radius:35px}.round-br-36{border-bottom-right-radius:36px}.round-br-37{border-bottom-right-radius:37px}.round-br-38{border-bottom-right-radius:38px}.round-br-39{border-bottom-right-radius:39px}.round-br-40{border-bottom-right-radius:40px}.round-br-41{border-bottom-right-radius:41px}.round-br-42{border-bottom-right-radius:42px}.round-br-43{border-bottom-right-radius:43px}.round-br-44{border-bottom-right-radius:44px}.round-br-45{border-bottom-right-radius:45px}.round-br-46{border-bottom-right-radius:46px}.round-br-47{border-bottom-right-radius:47px}.round-br-48{border-bottom-right-radius:48px}.round-br-49{border-bottom-right-radius:49px}.round-br-50{border-bottom-right-radius:50px}.round-a-0{border-radius:0}.round-a-1{border-radius:1px}.round-a-2{border-radius:2px}.round-a-3{border-radius:3px}.round-a-4{border-radius:4px}.round-a-5{border-radius:5px}.round-a-6{border-radius:6px}.round-a-7{border-radius:7px}.round-a-8{border-radius:8px}.round-a-9{border-radius:9px}.round-a-10{border-radius:10px}.round-a-11{border-radius:11px}.round-a-12{border-radius:12px}.round-a-13{border-radius:13px}.round-a-14{border-radius:14px}.round-a-15{border-radius:15px}.round-a-16{border-radius:16px}.round-a-17{border-radius:17px}.round-a-18{border-radius:18px}.round-a-19{border-radius:19px}.round-a-20{border-radius:20px}.round-a-21{border-radius:21px}.round-a-22{border-radius:22px}.round-a-23{border-radius:23px}.round-a-24{border-radius:24px}.round-a-25{border-radius:25px}.round-a-26{border-radius:26px}.round-a-27{border-radius:27px}.round-a-28{border-radius:28px}.round-a-29{border-radius:29px}.round-a-30{border-radius:30px}.round-a-31{border-radius:31px}.round-a-32{border-radius:32px}.round-a-33{border-radius:33px}.round-a-34{border-radius:34px}.round-a-35{border-radius:35px}.round-a-36{border-radius:36px}.round-a-37{border-radius:37px}.round-a-38{border-radius:38px}.round-a-39{border-radius:39px}.round-a-40{border-radius:40px}.round-a-41{border-radius:41px}.round-a-42{border-radius:42px}.round-a-43{border-radius:43px}.round-a-44{border-radius:44px}.round-a-45{border-radius:45px}.round-a-46{border-radius:46px}.round-a-47{border-radius:47px}.round-a-48{border-radius:48px}.round-a-49{border-radius:49px}.round-a-50{border-radius:50px}.round-t-0{border-top-left-radius:0;border-top-right-radius:0}.round-t-1{border-top-left-radius:1px;border-top-right-radius:1px}.round-t-2{border-top-left-radius:2px;border-top-right-radius:2px}.round-t-3{border-top-left-radius:3px;border-top-right-radius:3px}.round-t-4{border-top-left-radius:4px;border-top-right-radius:4px}.round-t-5{border-top-left-radius:5px;border-top-right-radius:5px}.round-t-6{border-top-left-radius:6px;border-top-right-radius:6px}.round-t-7{border-top-left-radius:7px;border-top-right-radius:7px}.round-t-8{border-top-left-radius:8px;border-top-right-radius:8px}.round-t-9{border-top-left-radius:9px;border-top-right-radius:9px}.round-t-10{border-top-left-radius:10px;border-top-right-radius:10px}.round-t-11{border-top-left-radius:11px;border-top-right-radius:11px}.round-t-12{border-top-left-radius:12px;border-top-right-radius:12px}.round-t-13{border-top-left-radius:13px;border-top-right-radius:13px}.round-t-14{border-top-left-radius:14px;border-top-right-radius:14px}.round-t-15{border-top-left-radius:15px;border-top-right-radius:15px}.round-t-16{border-top-left-radius:16px;border-top-right-radius:16px}.round-t-17{border-top-left-radius:17px;border-top-right-radius:17px}.round-t-18{border-top-left-radius:18px;border-top-right-radius:18px}.round-t-19{border-top-left-radius:19px;border-top-right-radius:19px}.round-t-20{border-top-left-radius:20px;border-top-right-radius:20px}.round-t-21{border-top-left-radius:21px;border-top-right-radius:21px}.round-t-22{border-top-left-radius:22px;border-top-right-radius:22px}.round-t-23{border-top-left-radius:23px;border-top-right-radius:23px}.round-t-24{border-top-left-radius:24px;border-top-right-radius:24px}.round-t-25{border-top-left-radius:25px;border-top-right-radius:25px}.round-t-26{border-top-left-radius:26px;border-top-right-radius:26px}.round-t-27{border-top-left-radius:27px;border-top-right-radius:27px}.round-t-28{border-top-left-radius:28px;border-top-right-radius:28px}.round-t-29{border-top-left-radius:29px;border-top-right-radius:29px}.round-t-30{border-top-left-radius:30px;border-top-right-radius:30px}.round-t-31{border-top-left-radius:31px;border-top-right-radius:31px}.round-t-32{border-top-left-radius:32px;border-top-right-radius:32px}.round-t-33{border-top-left-radius:33px;border-top-right-radius:33px}.round-t-34{border-top-left-radius:34px;border-top-right-radius:34px}.round-t-35{border-top-left-radius:35px;border-top-right-radius:35px}.round-t-36{border-top-left-radius:36px;border-top-right-radius:36px}.round-t-37{border-top-left-radius:37px;border-top-right-radius:37px}.round-t-38{border-top-left-radius:38px;border-top-right-radius:38px}.round-t-39{border-top-left-radius:39px;border-top-right-radius:39px}.round-t-40{border-top-left-radius:40px;border-top-right-radius:40px}.round-t-41{border-top-left-radius:41px;border-top-right-radius:41px}.round-t-42{border-top-left-radius:42px;border-top-right-radius:42px}.round-t-43{border-top-left-radius:43px;border-top-right-radius:43px}.round-t-44{border-top-left-radius:44px;border-top-right-radius:44px}.round-t-45{border-top-left-radius:45px;border-top-right-radius:45px}.round-t-46{border-top-left-radius:46px;border-top-right-radius:46px}.round-t-47{border-top-left-radius:47px;border-top-right-radius:47px}.round-t-48{border-top-left-radius:48px;border-top-right-radius:48px}.round-t-49{border-top-left-radius:49px;border-top-right-radius:49px}.round-t-50{border-top-left-radius:50px;border-top-right-radius:50px}.round-b-0{border-bottom-left-radius:0;border-bottom-right-radius:0}.round-b-1{border-bottom-left-radius:1px;border-bottom-right-radius:1px}.round-b-2{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.round-b-3{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.round-b-4{border-bottom-left-radius:4px;border-bottom-right-radius:4px}.round-b-5{border-bottom-left-radius:5px;border-bottom-right-radius:5px}.round-b-6{border-bottom-left-radius:6px;border-bottom-right-radius:6px}.round-b-7{border-bottom-left-radius:7px;border-bottom-right-radius:7px}.round-b-8{border-bottom-left-radius:8px;border-bottom-right-radius:8px}.round-b-9{border-bottom-left-radius:9px;border-bottom-right-radius:9px}.round-b-10{border-bottom-left-radius:10px;border-bottom-right-radius:10px}.round-b-11{border-bottom-left-radius:11px;border-bottom-right-radius:11px}.round-b-12{border-bottom-left-radius:12px;border-bottom-right-radius:12px}.round-b-13{border-bottom-left-radius:13px;border-bottom-right-radius:13px}.round-b-14{border-bottom-left-radius:14px;border-bottom-right-radius:14px}.round-b-15{border-bottom-left-radius:15px;border-bottom-right-radius:15px}.round-b-16{border-bottom-left-radius:16px;border-bottom-right-radius:16px}.round-b-17{border-bottom-left-radius:17px;border-bottom-right-radius:17px}.round-b-18{border-bottom-left-radius:18px;border-bottom-right-radius:18px}.round-b-19{border-bottom-left-radius:19px;border-bottom-right-radius:19px}.round-b-20{border-bottom-left-radius:20px;border-bottom-right-radius:20px}.round-b-21{border-bottom-left-radius:21px;border-bottom-right-radius:21px}.round-b-22{border-bottom-left-radius:22px;border-bottom-right-radius:22px}.round-b-23{border-bottom-left-radius:23px;border-bottom-right-radius:23px}.round-b-24{border-bottom-left-radius:24px;border-bottom-right-radius:24px}.round-b-25{border-bottom-left-radius:25px;border-bottom-right-radius:25px}.round-b-26{border-bottom-left-radius:26px;border-bottom-right-radius:26px}.round-b-27{border-bottom-left-radius:27px;border-bottom-right-radius:27px}.round-b-28{border-bottom-left-radius:28px;border-bottom-right-radius:28px}.round-b-29{border-bottom-left-radius:29px;border-bottom-right-radius:29px}.round-b-30{border-bottom-left-radius:30px;border-bottom-right-radius:30px}.round-b-31{border-bottom-left-radius:31px;border-bottom-right-radius:31px}.round-b-32{border-bottom-left-radius:32px;border-bottom-right-radius:32px}.round-b-33{border-bottom-left-radius:33px;border-bottom-right-radius:33px}.round-b-34{border-bottom-left-radius:34px;border-bottom-right-radius:34px}.round-b-35{border-bottom-left-radius:35px;border-bottom-right-radius:35px}.round-b-36{border-bottom-left-radius:36px;border-bottom-right-radius:36px}.round-b-37{border-bottom-left-radius:37px;border-bottom-right-radius:37px}.round-b-38{border-bottom-left-radius:38px;border-bottom-right-radius:38px}.round-b-39{border-bottom-left-radius:39px;border-bottom-right-radius:39px}.round-b-40{border-bottom-left-radius:40px;border-bottom-right-radius:40px}.round-b-41{border-bottom-left-radius:41px;border-bottom-right-radius:41px}.round-b-42{border-bottom-left-radius:42px;border-bottom-right-radius:42px}.round-b-43{border-bottom-left-radius:43px;border-bottom-right-radius:43px}.round-b-44{border-bottom-left-radius:44px;border-bottom-right-radius:44px}.round-b-45{border-bottom-left-radius:45px;border-bottom-right-radius:45px}.round-b-46{border-bottom-left-radius:46px;border-bottom-right-radius:46px}.round-b-47{border-bottom-left-radius:47px;border-bottom-right-radius:47px}.round-b-48{border-bottom-left-radius:48px;border-bottom-right-radius:48px}.round-b-49{border-bottom-left-radius:49px;border-bottom-right-radius:49px}.round-b-50{border-bottom-left-radius:50px;border-bottom-right-radius:50px}.round-l-0{border-top-left-radius:0;border-bottom-left-radius:0}.round-l-1{border-top-left-radius:1px;border-bottom-left-radius:1px}.round-l-2{border-top-left-radius:2px;border-bottom-left-radius:2px}.round-l-3{border-top-left-radius:3px;border-bottom-left-radius:3px}.round-l-4{border-top-left-radius:4px;border-bottom-left-radius:4px}.round-l-5{border-top-left-radius:5px;border-bottom-left-radius:5px}.round-l-6{border-top-left-radius:6px;border-bottom-left-radius:6px}.round-l-7{border-top-left-radius:7px;border-bottom-left-radius:7px}.round-l-8{border-top-left-radius:8px;border-bottom-left-radius:8px}.round-l-9{border-top-left-radius:9px;border-bottom-left-radius:9px}.round-l-10{border-top-left-radius:10px;border-bottom-left-radius:10px}.round-l-11{border-top-left-radius:11px;border-bottom-left-radius:11px}.round-l-12{border-top-left-radius:12px;border-bottom-left-radius:12px}.round-l-13{border-top-left-radius:13px;border-bottom-left-radius:13px}.round-l-14{border-top-left-radius:14px;border-bottom-left-radius:14px}.round-l-15{border-top-left-radius:15px;border-bottom-left-radius:15px}.round-l-16{border-top-left-radius:16px;border-bottom-left-radius:16px}.round-l-17{border-top-left-radius:17px;border-bottom-left-radius:17px}.round-l-18{border-top-left-radius:18px;border-bottom-left-radius:18px}.round-l-19{border-top-left-radius:19px;border-bottom-left-radius:19px}.round-l-20{border-top-left-radius:20px;border-bottom-left-radius:20px}.round-l-21{border-top-left-radius:21px;border-bottom-left-radius:21px}.round-l-22{border-top-left-radius:22px;border-bottom-left-radius:22px}.round-l-23{border-top-left-radius:23px;border-bottom-left-radius:23px}.round-l-24{border-top-left-radius:24px;border-bottom-left-radius:24px}.round-l-25{border-top-left-radius:25px;border-bottom-left-radius:25px}.round-l-26{border-top-left-radius:26px;border-bottom-left-radius:26px}.round-l-27{border-top-left-radius:27px;border-bottom-left-radius:27px}.round-l-28{border-top-left-radius:28px;border-bottom-left-radius:28px}.round-l-29{border-top-left-radius:29px;border-bottom-left-radius:29px}.round-l-30{border-top-left-radius:30px;border-bottom-left-radius:30px}.round-l-31{border-top-left-radius:31px;border-bottom-left-radius:31px}.round-l-32{border-top-left-radius:32px;border-bottom-left-radius:32px}.round-l-33{border-top-left-radius:33px;border-bottom-left-radius:33px}.round-l-34{border-top-left-radius:34px;border-bottom-left-radius:34px}.round-l-35{border-top-left-radius:35px;border-bottom-left-radius:35px}.round-l-36{border-top-left-radius:36px;border-bottom-left-radius:36px}.round-l-37{border-top-left-radius:37px;border-bottom-left-radius:37px}.round-l-38{border-top-left-radius:38px;border-bottom-left-radius:38px}.round-l-39{border-top-left-radius:39px;border-bottom-left-radius:39px}.round-l-40{border-top-left-radius:40px;border-bottom-left-radius:40px}.round-l-41{border-top-left-radius:41px;border-bottom-left-radius:41px}.round-l-42{border-top-left-radius:42px;border-bottom-left-radius:42px}.round-l-43{border-top-left-radius:43px;border-bottom-left-radius:43px}.round-l-44{border-top-left-radius:44px;border-bottom-left-radius:44px}.round-l-45{border-top-left-radius:45px;border-bottom-left-radius:45px}.round-l-46{border-top-left-radius:46px;border-bottom-left-radius:46px}.round-l-47{border-top-left-radius:47px;border-bottom-left-radius:47px}.round-l-48{border-top-left-radius:48px;border-bottom-left-radius:48px}.round-l-49{border-top-left-radius:49px;border-bottom-left-radius:49px}.round-l-50{border-top-left-radius:50px;border-bottom-left-radius:50px}.round-r-0{border-top-right-radius:0;border-bottom-right-radius:0}.round-r-1{border-top-right-radius:1px;border-bottom-right-radius:1px}.round-r-2{border-top-right-radius:2px;border-bottom-right-radius:2px}.round-r-3{border-top-right-radius:3px;border-bottom-right-radius:3px}.round-r-4{border-top-right-radius:4px;border-bottom-right-radius:4px}.round-r-5{border-top-right-radius:5px;border-bottom-right-radius:5px}.round-r-6{border-top-right-radius:6px;border-bottom-right-radius:6px}.round-r-7{border-top-right-radius:7px;border-bottom-right-radius:7px}.round-r-8{border-top-right-radius:8px;border-bottom-right-radius:8px}.round-r-9{border-top-right-radius:9px;border-bottom-right-radius:9px}.round-r-10{border-top-right-radius:10px;border-bottom-right-radius:10px}.round-r-11{border-top-right-radius:11px;border-bottom-right-radius:11px}.round-r-12{border-top-right-radius:12px;border-bottom-right-radius:12px}.round-r-13{border-top-right-radius:13px;border-bottom-right-radius:13px}.round-r-14{border-top-right-radius:14px;border-bottom-right-radius:14px}.round-r-15{border-top-right-radius:15px;border-bottom-right-radius:15px}.round-r-16{border-top-right-radius:16px;border-bottom-right-radius:16px}.round-r-17{border-top-right-radius:17px;border-bottom-right-radius:17px}.round-r-18{border-top-right-radius:18px;border-bottom-right-radius:18px}.round-r-19{border-top-right-radius:19px;border-bottom-right-radius:19px}.round-r-20{border-top-right-radius:20px;border-bottom-right-radius:20px}.round-r-21{border-top-right-radius:21px;border-bottom-right-radius:21px}.round-r-22{border-top-right-radius:22px;border-bottom-right-radius:22px}.round-r-23{border-top-right-radius:23px;border-bottom-right-radius:23px}.round-r-24{border-top-right-radius:24px;border-bottom-right-radius:24px}.round-r-25{border-top-right-radius:25px;border-bottom-right-radius:25px}.round-r-26{border-top-right-radius:26px;border-bottom-right-radius:26px}.round-r-27{border-top-right-radius:27px;border-bottom-right-radius:27px}.round-r-28{border-top-right-radius:28px;border-bottom-right-radius:28px}.round-r-29{border-top-right-radius:29px;border-bottom-right-radius:29px}.round-r-30{border-top-right-radius:30px;border-bottom-right-radius:30px}.round-r-31{border-top-right-radius:31px;border-bottom-right-radius:31px}.round-r-32{border-top-right-radius:32px;border-bottom-right-radius:32px}.round-r-33{border-top-right-radius:33px;border-bottom-right-radius:33px}.round-r-34{border-top-right-radius:34px;border-bottom-right-radius:34px}.round-r-35{border-top-right-radius:35px;border-bottom-right-radius:35px}.round-r-36{border-top-right-radius:36px;border-bottom-right-radius:36px}.round-r-37{border-top-right-radius:37px;border-bottom-right-radius:37px}.round-r-38{border-top-right-radius:38px;border-bottom-right-radius:38px}.round-r-39{border-top-right-radius:39px;border-bottom-right-radius:39px}.round-r-40{border-top-right-radius:40px;border-bottom-right-radius:40px}.round-r-41{border-top-right-radius:41px;border-bottom-right-radius:41px}.round-r-42{border-top-right-radius:42px;border-bottom-right-radius:42px}.round-r-43{border-top-right-radius:43px;border-bottom-right-radius:43px}.round-r-44{border-top-right-radius:44px;border-bottom-right-radius:44px}.round-r-45{border-top-right-radius:45px;border-bottom-right-radius:45px}.round-r-46{border-top-right-radius:46px;border-bottom-right-radius:46px}.round-r-47{border-top-right-radius:47px;border-bottom-right-radius:47px}.round-r-48{border-top-right-radius:48px;border-bottom-right-radius:48px}.round-r-49{border-top-right-radius:49px;border-bottom-right-radius:49px}.round-r-50{border-top-right-radius:50px;border-bottom-right-radius:50px}.round-0{border-radius:0}.round-1{border-radius:1px}.round-2{border-radius:2px}.round-3{border-radius:3px}.round-4{border-radius:4px}.round-5{border-radius:5px}.round-6{border-radius:6px}.round-7{border-radius:7px}.round-8{border-radius:8px}.round-9{border-radius:9px}.round-10{border-radius:10px}.round-11{border-radius:11px}.round-12{border-radius:12px}.round-13{border-radius:13px}.round-14{border-radius:14px}.round-15{border-radius:15px}.round-16{border-radius:16px}.round-17{border-radius:17px}.round-18{border-radius:18px}.round-19{border-radius:19px}.round-20{border-radius:20px}.round-21{border-radius:21px}.round-22{border-radius:22px}.round-23{border-radius:23px}.round-24{border-radius:24px}.round-25{border-radius:25px}.round-26{border-radius:26px}.line-0{line-height:1}.line-1{line-height:1.1}.line-2{line-height:1.2}.line-3{line-height:1.3}.line-4{line-height:1.4}.line-5{line-height:1.5}.line-6{line-height:1.6}.line-7{line-height:1.7}.line-8{line-height:1.8}.line-9{line-height:1.9}.line-10{line-height:2}.line-11{line-height:2.1}.line-12{line-height:2.2}.line-13{line-height:2.3}.line-14{line-height:2.4}.line-15{line-height:2.5}.line-16{line-height:2.6}.line-17{line-height:2.7}.line-18{line-height:2.8}.line-19{line-height:2.9}.line-20{line-height:3}.line-21{line-height:3.1}.opacity-0{opacity:0}.opacity-1{opacity:.1}.opacity-2{opacity:.2}.opacity-3{opacity:.3}.opacity-4{opacity:.4}.opacity-5{opacity:.5}.opacity-6{opacity:.6}.opacity-7{opacity:.7}.opacity-8{opacity:.8}.opacity-9{opacity:.9}.opacity-10{opacity:1}.border-0{border:0 solid #f5f5f5}.border{border:1px solid #f5f5f5}.border-1{border:1px solid #f5f5f5}.border-1-bk{border:1px solid #f5f5f5}.border-2{border:2px solid #f5f5f5}.border-2-bk{border:2px solid #f5f5f5}.border-3{border:3px solid #f5f5f5}.border-3-bk{border:3px solid #f5f5f5}.border-4{border:4px solid #f5f5f5}.border-4-bk{border:4px solid #f5f5f5}.border-5{border:5px solid #f5f5f5}.border-5-bk{border:5px solid #f5f5f5}.border-l-1{border-left:1px solid #f5f5f5}.border-l-2{border-left:2px solid #f5f5f5}.border-l-3{border-left:3px solid #f5f5f5}.border-l-4{border-left:4px solid #f5f5f5}.border-l-5{border-left:5px solid #f5f5f5}.border-r-1{border-right:1px solid #f5f5f5}.border-r-2{border-right:2px solid #f5f5f5}.border-r-3{border-right:3px solid #f5f5f5}.border-r-4{border-right:4px solid #f5f5f5}.border-r-5{border-right:5px solid #f5f5f5}.border-t-1{border-top:1px solid #f5f5f5}.border-t-2{border-top:2px solid #f5f5f5}.border-t-3{border-top:3px solid #f5f5f5}.border-t-4{border-top:4px solid #f5f5f5}.border-t-5{border-top:5px solid #f5f5f5}.border-b-1{border-bottom:1px solid #f5f5f5}.border-b-2{border-bottom:2px solid #f5f5f5}.border-b-3{border-bottom:3px solid #f5f5f5}.border-b-4{border-bottom:4px solid #f5f5f5}.border-b-5{border-bottom:5px solid #f5f5f5}.border-a-1{border:1px solid #f5f5f5}.border-a-2{border:2px solid #f5f5f5}.border-a-3{border:3px solid #f5f5f5}.border-a-4{border:4px solid #f5f5f5}.border-a-5{border:5px solid #f5f5f5}.pa-0{padding:0}.pa-1{padding:1px}.pa-2{padding:2px}.pa-3{padding:3px}.pa-4{padding:4px}.pa-5{padding:5px}.pa-6{padding:6px}.pa-7{padding:7px}.pa-8{padding:8px}.pa-9{padding:9px}.pa-10{padding:10px}.pa-11{padding:11px}.pa-12{padding:12px}.pa-13{padding:13px}.pa-14{padding:14px}.pa-15{padding:15px}.pa-16{padding:16px}.pa-17{padding:17px}.pa-18{padding:18px}.pa-19{padding:19px}.pa-20{padding:20px}.pa-21{padding:21px}.pa-22{padding:22px}.pa-23{padding:23px}.pa-24{padding:24px}.pa-25{padding:25px}.pa-26{padding:26px}.pa-27{padding:27px}.pa-28{padding:28px}.pa-29{padding:29px}.pa-30{padding:30px}.pa-31{padding:31px}.pa-32{padding:32px}.pa-33{padding:33px}.pa-34{padding:34px}.pa-35{padding:35px}.pa-36{padding:36px}.pa-37{padding:37px}.pa-38{padding:38px}.pa-39{padding:39px}.pa-40{padding:40px}.pa-41{padding:41px}.pa-42{padding:42px}.pa-43{padding:43px}.pa-44{padding:44px}.pa-45{padding:45px}.pa-46{padding:46px}.pa-47{padding:47px}.pa-48{padding:48px}.pa-49{padding:49px}.pa-50{padding:50px}.pa-n1{padding:2px}.pa-n2{padding:4px}.pa-n3{padding:6px}.pa-n4{padding:8px}.pa-n5{padding:10px}.pa-n6{padding:12px}.pa-n7{padding:14px}.pa-n8{padding:16px}.pa-n9{padding:18px}.pa-n10{padding:20px}.pa-n11{padding:22px}.pa-n12{padding:24px}.pa-n13{padding:26px}.pa-n14{padding:28px}.pa-n15{padding:30px}.pa-n16{padding:32px}.pa-n17{padding:34px}.pa-n18{padding:36px}.pa-n19{padding:38px}.pa-n20{padding:40px}.pa-n21{padding:42px}.pa-n22{padding:44px}.pa-n23{padding:46px}.pa-n24{padding:48px}.pa-n25{padding:50px}.pt-0{padding-top:0}.pt-1{padding-top:1px}.pt-2{padding-top:2px}.pt-3{padding-top:3px}.pt-4{padding-top:4px}.pt-5{padding-top:5px}.pt-6{padding-top:6px}.pt-7{padding-top:7px}.pt-8{padding-top:8px}.pt-9{padding-top:9px}.pt-10{padding-top:10px}.pt-11{padding-top:11px}.pt-12{padding-top:12px}.pt-13{padding-top:13px}.pt-14{padding-top:14px}.pt-15{padding-top:15px}.pt-16{padding-top:16px}.pt-17{padding-top:17px}.pt-18{padding-top:18px}.pt-19{padding-top:19px}.pt-20{padding-top:20px}.pt-21{padding-top:21px}.pt-22{padding-top:22px}.pt-23{padding-top:23px}.pt-24{padding-top:24px}.pt-25{padding-top:25px}.pt-26{padding-top:26px}.pt-27{padding-top:27px}.pt-28{padding-top:28px}.pt-29{padding-top:29px}.pt-30{padding-top:30px}.pt-31{padding-top:31px}.pt-32{padding-top:32px}.pt-33{padding-top:33px}.pt-34{padding-top:34px}.pt-35{padding-top:35px}.pt-36{padding-top:36px}.pt-37{padding-top:37px}.pt-38{padding-top:38px}.pt-39{padding-top:39px}.pt-40{padding-top:40px}.pt-41{padding-top:41px}.pt-42{padding-top:42px}.pt-43{padding-top:43px}.pt-44{padding-top:44px}.pt-45{padding-top:45px}.pt-46{padding-top:46px}.pt-47{padding-top:47px}.pt-48{padding-top:48px}.pt-49{padding-top:49px}.pt-50{padding-top:50px}.pt-n1{padding-top:2px}.pt-n2{padding-top:4px}.pt-n3{padding-top:6px}.pt-n4{padding-top:8px}.pt-n5{padding-top:10px}.pt-n6{padding-top:12px}.pt-n7{padding-top:14px}.pt-n8{padding-top:16px}.pt-n9{padding-top:18px}.pt-n10{padding-top:20px}.pt-n11{padding-top:22px}.pt-n12{padding-top:24px}.pt-n13{padding-top:26px}.pt-n14{padding-top:28px}.pt-n15{padding-top:30px}.pt-n16{padding-top:32px}.pt-n17{padding-top:34px}.pt-n18{padding-top:36px}.pt-n19{padding-top:38px}.pt-n20{padding-top:40px}.pt-n21{padding-top:42px}.pt-n22{padding-top:44px}.pt-n23{padding-top:46px}.pt-n24{padding-top:48px}.pt-n25{padding-top:50px}.pr-0{padding-right:0}.pr-1{padding-right:1px}.pr-2{padding-right:2px}.pr-3{padding-right:3px}.pr-4{padding-right:4px}.pr-5{padding-right:5px}.pr-6{padding-right:6px}.pr-7{padding-right:7px}.pr-8{padding-right:8px}.pr-9{padding-right:9px}.pr-10{padding-right:10px}.pr-11{padding-right:11px}.pr-12{padding-right:12px}.pr-13{padding-right:13px}.pr-14{padding-right:14px}.pr-15{padding-right:15px}.pr-16{padding-right:16px}.pr-17{padding-right:17px}.pr-18{padding-right:18px}.pr-19{padding-right:19px}.pr-20{padding-right:20px}.pr-21{padding-right:21px}.pr-22{padding-right:22px}.pr-23{padding-right:23px}.pr-24{padding-right:24px}.pr-25{padding-right:25px}.pr-26{padding-right:26px}.pr-27{padding-right:27px}.pr-28{padding-right:28px}.pr-29{padding-right:29px}.pr-30{padding-right:30px}.pr-31{padding-right:31px}.pr-32{padding-right:32px}.pr-33{padding-right:33px}.pr-34{padding-right:34px}.pr-35{padding-right:35px}.pr-36{padding-right:36px}.pr-37{padding-right:37px}.pr-38{padding-right:38px}.pr-39{padding-right:39px}.pr-40{padding-right:40px}.pr-41{padding-right:41px}.pr-42{padding-right:42px}.pr-43{padding-right:43px}.pr-44{padding-right:44px}.pr-45{padding-right:45px}.pr-46{padding-right:46px}.pr-47{padding-right:47px}.pr-48{padding-right:48px}.pr-49{padding-right:49px}.pr-50{padding-right:50px}.pr-n1{padding-right:2px}.pr-n2{padding-right:4px}.pr-n3{padding-right:6px}.pr-n4{padding-right:8px}.pr-n5{padding-right:10px}.pr-n6{padding-right:12px}.pr-n7{padding-right:14px}.pr-n8{padding-right:16px}.pr-n9{padding-right:18px}.pr-n10{padding-right:20px}.pr-n11{padding-right:22px}.pr-n12{padding-right:24px}.pr-n13{padding-right:26px}.pr-n14{padding-right:28px}.pr-n15{padding-right:30px}.pr-n16{padding-right:32px}.pr-n17{padding-right:34px}.pr-n18{padding-right:36px}.pr-n19{padding-right:38px}.pr-n20{padding-right:40px}.pr-n21{padding-right:42px}.pr-n22{padding-right:44px}.pr-n23{padding-right:46px}.pr-n24{padding-right:48px}.pr-n25{padding-right:50px}.pb-0{padding-bottom:0}.pb-1{padding-bottom:1px}.pb-2{padding-bottom:2px}.pb-3{padding-bottom:3px}.pb-4{padding-bottom:4px}.pb-5{padding-bottom:5px}.pb-6{padding-bottom:6px}.pb-7{padding-bottom:7px}.pb-8{padding-bottom:8px}.pb-9{padding-bottom:9px}.pb-10{padding-bottom:10px}.pb-11{padding-bottom:11px}.pb-12{padding-bottom:12px}.pb-13{padding-bottom:13px}.pb-14{padding-bottom:14px}.pb-15{padding-bottom:15px}.pb-16{padding-bottom:16px}.pb-17{padding-bottom:17px}.pb-18{padding-bottom:18px}.pb-19{padding-bottom:19px}.pb-20{padding-bottom:20px}.pb-21{padding-bottom:21px}.pb-22{padding-bottom:22px}.pb-23{padding-bottom:23px}.pb-24{padding-bottom:24px}.pb-25{padding-bottom:25px}.pb-26{padding-bottom:26px}.pb-27{padding-bottom:27px}.pb-28{padding-bottom:28px}.pb-29{padding-bottom:29px}.pb-30{padding-bottom:30px}.pb-31{padding-bottom:31px}.pb-32{padding-bottom:32px}.pb-33{padding-bottom:33px}.pb-34{padding-bottom:34px}.pb-35{padding-bottom:35px}.pb-36{padding-bottom:36px}.pb-37{padding-bottom:37px}.pb-38{padding-bottom:38px}.pb-39{padding-bottom:39px}.pb-40{padding-bottom:40px}.pb-41{padding-bottom:41px}.pb-42{padding-bottom:42px}.pb-43{padding-bottom:43px}.pb-44{padding-bottom:44px}.pb-45{padding-bottom:45px}.pb-46{padding-bottom:46px}.pb-47{padding-bottom:47px}.pb-48{padding-bottom:48px}.pb-49{padding-bottom:49px}.pb-50{padding-bottom:50px}.pb-n1{padding-bottom:2px}.pb-n2{padding-bottom:4px}.pb-n3{padding-bottom:6px}.pb-n4{padding-bottom:8px}.pb-n5{padding-bottom:10px}.pb-n6{padding-bottom:12px}.pb-n7{padding-bottom:14px}.pb-n8{padding-bottom:16px}.pb-n9{padding-bottom:18px}.pb-n10{padding-bottom:20px}.pb-n11{padding-bottom:22px}.pb-n12{padding-bottom:24px}.pb-n13{padding-bottom:26px}.pb-n14{padding-bottom:28px}.pb-n15{padding-bottom:30px}.pb-n16{padding-bottom:32px}.pb-n17{padding-bottom:34px}.pb-n18{padding-bottom:36px}.pb-n19{padding-bottom:38px}.pb-n20{padding-bottom:40px}.pb-n21{padding-bottom:42px}.pb-n22{padding-bottom:44px}.pb-n23{padding-bottom:46px}.pb-n24{padding-bottom:48px}.pb-n25{padding-bottom:50px}.pl-0{padding-left:0}.pl-1{padding-left:1px}.pl-2{padding-left:2px}.pl-3{padding-left:3px}.pl-4{padding-left:4px}.pl-5{padding-left:5px}.pl-6{padding-left:6px}.pl-7{padding-left:7px}.pl-8{padding-left:8px}.pl-9{padding-left:9px}.pl-10{padding-left:10px}.pl-11{padding-left:11px}.pl-12{padding-left:12px}.pl-13{padding-left:13px}.pl-14{padding-left:14px}.pl-15{padding-left:15px}.pl-16{padding-left:16px}.pl-17{padding-left:17px}.pl-18{padding-left:18px}.pl-19{padding-left:19px}.pl-20{padding-left:20px}.pl-21{padding-left:21px}.pl-22{padding-left:22px}.pl-23{padding-left:23px}.pl-24{padding-left:24px}.pl-25{padding-left:25px}.pl-26{padding-left:26px}.pl-27{padding-left:27px}.pl-28{padding-left:28px}.pl-29{padding-left:29px}.pl-30{padding-left:30px}.pl-31{padding-left:31px}.pl-32{padding-left:32px}.pl-33{padding-left:33px}.pl-34{padding-left:34px}.pl-35{padding-left:35px}.pl-36{padding-left:36px}.pl-37{padding-left:37px}.pl-38{padding-left:38px}.pl-39{padding-left:39px}.pl-40{padding-left:40px}.pl-41{padding-left:41px}.pl-42{padding-left:42px}.pl-43{padding-left:43px}.pl-44{padding-left:44px}.pl-45{padding-left:45px}.pl-46{padding-left:46px}.pl-47{padding-left:47px}.pl-48{padding-left:48px}.pl-49{padding-left:49px}.pl-50{padding-left:50px}.pl-n1{padding-left:2px}.pl-n2{padding-left:4px}.pl-n3{padding-left:6px}.pl-n4{padding-left:8px}.pl-n5{padding-left:10px}.pl-n6{padding-left:12px}.pl-n7{padding-left:14px}.pl-n8{padding-left:16px}.pl-n9{padding-left:18px}.pl-n10{padding-left:20px}.pl-n11{padding-left:22px}.pl-n12{padding-left:24px}.pl-n13{padding-left:26px}.pl-n14{padding-left:28px}.pl-n15{padding-left:30px}.pl-n16{padding-left:32px}.pl-n17{padding-left:34px}.pl-n18{padding-left:36px}.pl-n19{padding-left:38px}.pl-n20{padding-left:40px}.pl-n21{padding-left:42px}.pl-n22{padding-left:44px}.pl-n23{padding-left:46px}.pl-n24{padding-left:48px}.pl-n25{padding-left:50px}.px-0{padding-left:0;padding-right:0}.px-1{padding-left:1px;padding-right:1px}.px-2{padding-left:2px;padding-right:2px}.px-3{padding-left:3px;padding-right:3px}.px-4{padding-left:4px;padding-right:4px}.px-5{padding-left:5px;padding-right:5px}.px-6{padding-left:6px;padding-right:6px}.px-7{padding-left:7px;padding-right:7px}.px-8{padding-left:8px;padding-right:8px}.px-9{padding-left:9px;padding-right:9px}.px-10{padding-left:10px;padding-right:10px}.px-11{padding-left:11px;padding-right:11px}.px-12{padding-left:12px;padding-right:12px}.px-13{padding-left:13px;padding-right:13px}.px-14{padding-left:14px;padding-right:14px}.px-15{padding-left:15px;padding-right:15px}.px-16{padding-left:16px;padding-right:16px}.px-17{padding-left:17px;padding-right:17px}.px-18{padding-left:18px;padding-right:18px}.px-19{padding-left:19px;padding-right:19px}.px-20{padding-left:20px;padding-right:20px}.px-21{padding-left:21px;padding-right:21px}.px-22{padding-left:22px;padding-right:22px}.px-23{padding-left:23px;padding-right:23px}.px-24{padding-left:24px;padding-right:24px}.px-25{padding-left:25px;padding-right:25px}.px-26{padding-left:26px;padding-right:26px}.px-27{padding-left:27px;padding-right:27px}.px-28{padding-left:28px;padding-right:28px}.px-29{padding-left:29px;padding-right:29px}.px-30{padding-left:30px;padding-right:30px}.px-31{padding-left:31px;padding-right:31px}.px-32{padding-left:32px;padding-right:32px}.px-33{padding-left:33px;padding-right:33px}.px-34{padding-left:34px;padding-right:34px}.px-35{padding-left:35px;padding-right:35px}.px-36{padding-left:36px;padding-right:36px}.px-37{padding-left:37px;padding-right:37px}.px-38{padding-left:38px;padding-right:38px}.px-39{padding-left:39px;padding-right:39px}.px-40{padding-left:40px;padding-right:40px}.px-41{padding-left:41px;padding-right:41px}.px-42{padding-left:42px;padding-right:42px}.px-43{padding-left:43px;padding-right:43px}.px-44{padding-left:44px;padding-right:44px}.px-45{padding-left:45px;padding-right:45px}.px-46{padding-left:46px;padding-right:46px}.px-47{padding-left:47px;padding-right:47px}.px-48{padding-left:48px;padding-right:48px}.px-49{padding-left:49px;padding-right:49px}.px-50{padding-left:50px;padding-right:50px}.px-n1{padding-left:2px;padding-right:2px}.px-n2{padding-left:4px;padding-right:4px}.px-n3{padding-left:6px;padding-right:6px}.px-n4{padding-left:8px;padding-right:8px}.px-n5{padding-left:10px;padding-right:10px}.px-n6{padding-left:12px;padding-right:12px}.px-n7{padding-left:14px;padding-right:14px}.px-n8{padding-left:16px;padding-right:16px}.px-n9{padding-left:18px;padding-right:18px}.px-n10{padding-left:20px;padding-right:20px}.px-n11{padding-left:22px;padding-right:22px}.px-n12{padding-left:24px;padding-right:24px}.px-n13{padding-left:26px;padding-right:26px}.px-n14{padding-left:28px;padding-right:28px}.px-n15{padding-left:30px;padding-right:30px}.px-n16{padding-left:32px;padding-right:32px}.px-n17{padding-left:34px;padding-right:34px}.px-n18{padding-left:36px;padding-right:36px}.px-n19{padding-left:38px;padding-right:38px}.px-n20{padding-left:40px;padding-right:40px}.px-n21{padding-left:42px;padding-right:42px}.px-n22{padding-left:44px;padding-right:44px}.px-n23{padding-left:46px;padding-right:46px}.px-n24{padding-left:48px;padding-right:48px}.px-n25{padding-left:50px;padding-right:50px}.py-0{padding-top:0;padding-bottom:0}.py-1{padding-top:1px;padding-bottom:1px}.py-2{padding-top:2px;padding-bottom:2px}.py-3{padding-top:3px;padding-bottom:3px}.py-4{padding-top:4px;padding-bottom:4px}.py-5{padding-top:5px;padding-bottom:5px}.py-6{padding-top:6px;padding-bottom:6px}.py-7{padding-top:7px;padding-bottom:7px}.py-8{padding-top:8px;padding-bottom:8px}.py-9{padding-top:9px;padding-bottom:9px}.py-10{padding-top:10px;padding-bottom:10px}.py-11{padding-top:11px;padding-bottom:11px}.py-12{padding-top:12px;padding-bottom:12px}.py-13{padding-top:13px;padding-bottom:13px}.py-14{padding-top:14px;padding-bottom:14px}.py-15{padding-top:15px;padding-bottom:15px}.py-16{padding-top:16px;padding-bottom:16px}.py-17{padding-top:17px;padding-bottom:17px}.py-18{padding-top:18px;padding-bottom:18px}.py-19{padding-top:19px;padding-bottom:19px}.py-20{padding-top:20px;padding-bottom:20px}.py-21{padding-top:21px;padding-bottom:21px}.py-22{padding-top:22px;padding-bottom:22px}.py-23{padding-top:23px;padding-bottom:23px}.py-24{padding-top:24px;padding-bottom:24px}.py-25{padding-top:25px;padding-bottom:25px}.py-26{padding-top:26px;padding-bottom:26px}.py-27{padding-top:27px;padding-bottom:27px}.py-28{padding-top:28px;padding-bottom:28px}.py-29{padding-top:29px;padding-bottom:29px}.py-30{padding-top:30px;padding-bottom:30px}.py-31{padding-top:31px;padding-bottom:31px}.py-32{padding-top:32px;padding-bottom:32px}.py-33{padding-top:33px;padding-bottom:33px}.py-34{padding-top:34px;padding-bottom:34px}.py-35{padding-top:35px;padding-bottom:35px}.py-36{padding-top:36px;padding-bottom:36px}.py-37{padding-top:37px;padding-bottom:37px}.py-38{padding-top:38px;padding-bottom:38px}.py-39{padding-top:39px;padding-bottom:39px}.py-40{padding-top:40px;padding-bottom:40px}.py-41{padding-top:41px;padding-bottom:41px}.py-42{padding-top:42px;padding-bottom:42px}.py-43{padding-top:43px;padding-bottom:43px}.py-44{padding-top:44px;padding-bottom:44px}.py-45{padding-top:45px;padding-bottom:45px}.py-46{padding-top:46px;padding-bottom:46px}.py-47{padding-top:47px;padding-bottom:47px}.py-48{padding-top:48px;padding-bottom:48px}.py-49{padding-top:49px;padding-bottom:49px}.py-50{padding-top:50px;padding-bottom:50px}.py-n1{padding-top:2px;padding-bottom:2px}.py-n2{padding-top:4px;padding-bottom:4px}.py-n3{padding-top:6px;padding-bottom:6px}.py-n4{padding-top:8px;padding-bottom:8px}.py-n5{padding-top:10px;padding-bottom:10px}.py-n6{padding-top:12px;padding-bottom:12px}.py-n7{padding-top:14px;padding-bottom:14px}.py-n8{padding-top:16px;padding-bottom:16px}.py-n9{padding-top:18px;padding-bottom:18px}.py-n10{padding-top:20px;padding-bottom:20px}.py-n11{padding-top:22px;padding-bottom:22px}.py-n12{padding-top:24px;padding-bottom:24px}.py-n13{padding-top:26px;padding-bottom:26px}.py-n14{padding-top:28px;padding-bottom:28px}.py-n15{padding-top:30px;padding-bottom:30px}.py-n16{padding-top:32px;padding-bottom:32px}.py-n17{padding-top:34px;padding-bottom:34px}.py-n18{padding-top:36px;padding-bottom:36px}.py-n19{padding-top:38px;padding-bottom:38px}.py-n20{padding-top:40px;padding-bottom:40px}.py-n21{padding-top:42px;padding-bottom:42px}.py-n22{padding-top:44px;padding-bottom:44px}.py-n23{padding-top:46px;padding-bottom:46px}.py-n24{padding-top:48px;padding-bottom:48px}.py-n25{padding-top:50px;padding-bottom:50px}.ma-0{margin:0}.ma-1{margin:1px}.ma-2{margin:2px}.ma-3{margin:3px}.ma-4{margin:4px}.ma-5{margin:5px}.ma-6{margin:6px}.ma-7{margin:7px}.ma-8{margin:8px}.ma-9{margin:9px}.ma-10{margin:10px}.ma-11{margin:11px}.ma-12{margin:12px}.ma-13{margin:13px}.ma-14{margin:14px}.ma-15{margin:15px}.ma-16{margin:16px}.ma-17{margin:17px}.ma-18{margin:18px}.ma-19{margin:19px}.ma-20{margin:20px}.ma-21{margin:21px}.ma-22{margin:22px}.ma-23{margin:23px}.ma-24{margin:24px}.ma-25{margin:25px}.ma-26{margin:26px}.ma-27{margin:27px}.ma-28{margin:28px}.ma-29{margin:29px}.ma-30{margin:30px}.ma-31{margin:31px}.ma-32{margin:32px}.ma-33{margin:33px}.ma-34{margin:34px}.ma-35{margin:35px}.ma-36{margin:36px}.ma-37{margin:37px}.ma-38{margin:38px}.ma-39{margin:39px}.ma-40{margin:40px}.ma-41{margin:41px}.ma-42{margin:42px}.ma-43{margin:43px}.ma-44{margin:44px}.ma-45{margin:45px}.ma-46{margin:46px}.ma-47{margin:47px}.ma-48{margin:48px}.ma-49{margin:49px}.ma-50{margin:50px}.ma-n1{margin:2px}.ma-n2{margin:4px}.ma-n3{margin:6px}.ma-n4{margin:8px}.ma-n5{margin:10px}.ma-n6{margin:12px}.ma-n7{margin:14px}.ma-n8{margin:16px}.ma-n9{margin:18px}.ma-n10{margin:20px}.ma-n11{margin:22px}.ma-n12{margin:24px}.ma-n13{margin:26px}.ma-n14{margin:28px}.ma-n15{margin:30px}.ma-n16{margin:32px}.ma-n17{margin:34px}.ma-n18{margin:36px}.ma-n19{margin:38px}.ma-n20{margin:40px}.ma-n21{margin:42px}.ma-n22{margin:44px}.ma-n23{margin:46px}.ma-n24{margin:48px}.ma-n25{margin:50px}.mt-0{margin-top:0}.mt--0{margin-top:0}.mt-1{margin-top:1px}.mt--1{margin-top:-1px}.mt-2{margin-top:2px}.mt--2{margin-top:-2px}.mt-3{margin-top:3px}.mt--3{margin-top:-3px}.mt-4{margin-top:4px}.mt--4{margin-top:-4px}.mt-5{margin-top:5px}.mt--5{margin-top:-5px}.mt-6{margin-top:6px}.mt--6{margin-top:-6px}.mt-7{margin-top:7px}.mt--7{margin-top:-7px}.mt-8{margin-top:8px}.mt--8{margin-top:-8px}.mt-9{margin-top:9px}.mt--9{margin-top:-9px}.mt-10{margin-top:10px}.mt--10{margin-top:-10px}.mt-11{margin-top:11px}.mt--11{margin-top:-11px}.mt-12{margin-top:12px}.mt--12{margin-top:-12px}.mt-13{margin-top:13px}.mt--13{margin-top:-13px}.mt-14{margin-top:14px}.mt--14{margin-top:-14px}.mt-15{margin-top:15px}.mt--15{margin-top:-15px}.mt-16{margin-top:16px}.mt--16{margin-top:-16px}.mt-17{margin-top:17px}.mt--17{margin-top:-17px}.mt-18{margin-top:18px}.mt--18{margin-top:-18px}.mt-19{margin-top:19px}.mt--19{margin-top:-19px}.mt-20{margin-top:20px}.mt--20{margin-top:-20px}.mt-21{margin-top:21px}.mt--21{margin-top:-21px}.mt-22{margin-top:22px}.mt--22{margin-top:-22px}.mt-23{margin-top:23px}.mt--23{margin-top:-23px}.mt-24{margin-top:24px}.mt--24{margin-top:-24px}.mt-25{margin-top:25px}.mt--25{margin-top:-25px}.mt-26{margin-top:26px}.mt--26{margin-top:-26px}.mt-27{margin-top:27px}.mt--27{margin-top:-27px}.mt-28{margin-top:28px}.mt--28{margin-top:-28px}.mt-29{margin-top:29px}.mt--29{margin-top:-29px}.mt-30{margin-top:30px}.mt--30{margin-top:-30px}.mt-31{margin-top:31px}.mt--31{margin-top:-31px}.mt-32{margin-top:32px}.mt--32{margin-top:-32px}.mt-33{margin-top:33px}.mt--33{margin-top:-33px}.mt-34{margin-top:34px}.mt--34{margin-top:-34px}.mt-35{margin-top:35px}.mt--35{margin-top:-35px}.mt-36{margin-top:36px}.mt--36{margin-top:-36px}.mt-37{margin-top:37px}.mt--37{margin-top:-37px}.mt-38{margin-top:38px}.mt--38{margin-top:-38px}.mt-39{margin-top:39px}.mt--39{margin-top:-39px}.mt-40{margin-top:40px}.mt--40{margin-top:-40px}.mt-41{margin-top:41px}.mt--41{margin-top:-41px}.mt-42{margin-top:42px}.mt--42{margin-top:-42px}.mt-43{margin-top:43px}.mt--43{margin-top:-43px}.mt-44{margin-top:44px}.mt--44{margin-top:-44px}.mt-45{margin-top:45px}.mt--45{margin-top:-45px}.mt-46{margin-top:46px}.mt--46{margin-top:-46px}.mt-47{margin-top:47px}.mt--47{margin-top:-47px}.mt-48{margin-top:48px}.mt--48{margin-top:-48px}.mt-49{margin-top:49px}.mt--49{margin-top:-49px}.mt-50{margin-top:50px}.mt--50{margin-top:-50px}.mt-n1{margin-top:2px}.mt--n1{margin-top:-2px}.mt-n2{margin-top:4px}.mt--n2{margin-top:-4px}.mt-n3{margin-top:6px}.mt--n3{margin-top:-6px}.mt-n4{margin-top:8px}.mt--n4{margin-top:-8px}.mt-n5{margin-top:10px}.mt--n5{margin-top:-10px}.mt-n6{margin-top:12px}.mt--n6{margin-top:-12px}.mt-n7{margin-top:14px}.mt--n7{margin-top:-14px}.mt-n8{margin-top:16px}.mt--n8{margin-top:-16px}.mt-n9{margin-top:18px}.mt--n9{margin-top:-18px}.mt-n10{margin-top:20px}.mt--n10{margin-top:-20px}.mt-n11{margin-top:22px}.mt--n11{margin-top:-22px}.mt-n12{margin-top:24px}.mt--n12{margin-top:-24px}.mt-n13{margin-top:26px}.mt--n13{margin-top:-26px}.mt-n14{margin-top:28px}.mt--n14{margin-top:-28px}.mt-n15{margin-top:30px}.mt--n15{margin-top:-30px}.mt-n16{margin-top:32px}.mt--n16{margin-top:-32px}.mt-n17{margin-top:34px}.mt--n17{margin-top:-34px}.mt-n18{margin-top:36px}.mt--n18{margin-top:-36px}.mt-n19{margin-top:38px}.mt--n19{margin-top:-38px}.mt-n20{margin-top:40px}.mt--n20{margin-top:-40px}.mt-n21{margin-top:42px}.mt--n21{margin-top:-42px}.mt-n22{margin-top:44px}.mt--n22{margin-top:-44px}.mt-n23{margin-top:46px}.mt--n23{margin-top:-46px}.mt-n24{margin-top:48px}.mt--n24{margin-top:-48px}.mt-n25{margin-top:50px}.mt--n25{margin-top:-50px}.mr-0{margin-right:0}.mr--0{margin-right:0}.mr-1{margin-right:1px}.mr--1{margin-right:-1px}.mr-2{margin-right:2px}.mr--2{margin-right:-2px}.mr-3{margin-right:3px}.mr--3{margin-right:-3px}.mr-4{margin-right:4px}.mr--4{margin-right:-4px}.mr-5{margin-right:5px}.mr--5{margin-right:-5px}.mr-6{margin-right:6px}.mr--6{margin-right:-6px}.mr-7{margin-right:7px}.mr--7{margin-right:-7px}.mr-8{margin-right:8px}.mr--8{margin-right:-8px}.mr-9{margin-right:9px}.mr--9{margin-right:-9px}.mr-10{margin-right:10px}.mr--10{margin-right:-10px}.mr-11{margin-right:11px}.mr--11{margin-right:-11px}.mr-12{margin-right:12px}.mr--12{margin-right:-12px}.mr-13{margin-right:13px}.mr--13{margin-right:-13px}.mr-14{margin-right:14px}.mr--14{margin-right:-14px}.mr-15{margin-right:15px}.mr--15{margin-right:-15px}.mr-16{margin-right:16px}.mr--16{margin-right:-16px}.mr-17{margin-right:17px}.mr--17{margin-right:-17px}.mr-18{margin-right:18px}.mr--18{margin-right:-18px}.mr-19{margin-right:19px}.mr--19{margin-right:-19px}.mr-20{margin-right:20px}.mr--20{margin-right:-20px}.mr-21{margin-right:21px}.mr--21{margin-right:-21px}.mr-22{margin-right:22px}.mr--22{margin-right:-22px}.mr-23{margin-right:23px}.mr--23{margin-right:-23px}.mr-24{margin-right:24px}.mr--24{margin-right:-24px}.mr-25{margin-right:25px}.mr--25{margin-right:-25px}.mr-26{margin-right:26px}.mr--26{margin-right:-26px}.mr-27{margin-right:27px}.mr--27{margin-right:-27px}.mr-28{margin-right:28px}.mr--28{margin-right:-28px}.mr-29{margin-right:29px}.mr--29{margin-right:-29px}.mr-30{margin-right:30px}.mr--30{margin-right:-30px}.mr-31{margin-right:31px}.mr--31{margin-right:-31px}.mr-32{margin-right:32px}.mr--32{margin-right:-32px}.mr-33{margin-right:33px}.mr--33{margin-right:-33px}.mr-34{margin-right:34px}.mr--34{margin-right:-34px}.mr-35{margin-right:35px}.mr--35{margin-right:-35px}.mr-36{margin-right:36px}.mr--36{margin-right:-36px}.mr-37{margin-right:37px}.mr--37{margin-right:-37px}.mr-38{margin-right:38px}.mr--38{margin-right:-38px}.mr-39{margin-right:39px}.mr--39{margin-right:-39px}.mr-40{margin-right:40px}.mr--40{margin-right:-40px}.mr-41{margin-right:41px}.mr--41{margin-right:-41px}.mr-42{margin-right:42px}.mr--42{margin-right:-42px}.mr-43{margin-right:43px}.mr--43{margin-right:-43px}.mr-44{margin-right:44px}.mr--44{margin-right:-44px}.mr-45{margin-right:45px}.mr--45{margin-right:-45px}.mr-46{margin-right:46px}.mr--46{margin-right:-46px}.mr-47{margin-right:47px}.mr--47{margin-right:-47px}.mr-48{margin-right:48px}.mr--48{margin-right:-48px}.mr-49{margin-right:49px}.mr--49{margin-right:-49px}.mr-50{margin-right:50px}.mr--50{margin-right:-50px}.mr-n1{margin-right:2px}.mr--n1{margin-right:-2px}.mr-n2{margin-right:4px}.mr--n2{margin-right:-4px}.mr-n3{margin-right:6px}.mr--n3{margin-right:-6px}.mr-n4{margin-right:8px}.mr--n4{margin-right:-8px}.mr-n5{margin-right:10px}.mr--n5{margin-right:-10px}.mr-n6{margin-right:12px}.mr--n6{margin-right:-12px}.mr-n7{margin-right:14px}.mr--n7{margin-right:-14px}.mr-n8{margin-right:16px}.mr--n8{margin-right:-16px}.mr-n9{margin-right:18px}.mr--n9{margin-right:-18px}.mr-n10{margin-right:20px}.mr--n10{margin-right:-20px}.mr-n11{margin-right:22px}.mr--n11{margin-right:-22px}.mr-n12{margin-right:24px}.mr--n12{margin-right:-24px}.mr-n13{margin-right:26px}.mr--n13{margin-right:-26px}.mr-n14{margin-right:28px}.mr--n14{margin-right:-28px}.mr-n15{margin-right:30px}.mr--n15{margin-right:-30px}.mr-n16{margin-right:32px}.mr--n16{margin-right:-32px}.mr-n17{margin-right:34px}.mr--n17{margin-right:-34px}.mr-n18{margin-right:36px}.mr--n18{margin-right:-36px}.mr-n19{margin-right:38px}.mr--n19{margin-right:-38px}.mr-n20{margin-right:40px}.mr--n20{margin-right:-40px}.mr-n21{margin-right:42px}.mr--n21{margin-right:-42px}.mr-n22{margin-right:44px}.mr--n22{margin-right:-44px}.mr-n23{margin-right:46px}.mr--n23{margin-right:-46px}.mr-n24{margin-right:48px}.mr--n24{margin-right:-48px}.mr-n25{margin-right:50px}.mr--n25{margin-right:-50px}.mb-0{margin-bottom:0}.mb--0{margin-bottom:0}.mb-1{margin-bottom:1px}.mb--1{margin-bottom:-1px}.mb-2{margin-bottom:2px}.mb--2{margin-bottom:-2px}.mb-3{margin-bottom:3px}.mb--3{margin-bottom:-3px}.mb-4{margin-bottom:4px}.mb--4{margin-bottom:-4px}.mb-5{margin-bottom:5px}.mb--5{margin-bottom:-5px}.mb-6{margin-bottom:6px}.mb--6{margin-bottom:-6px}.mb-7{margin-bottom:7px}.mb--7{margin-bottom:-7px}.mb-8{margin-bottom:8px}.mb--8{margin-bottom:-8px}.mb-9{margin-bottom:9px}.mb--9{margin-bottom:-9px}.mb-10{margin-bottom:10px}.mb--10{margin-bottom:-10px}.mb-11{margin-bottom:11px}.mb--11{margin-bottom:-11px}.mb-12{margin-bottom:12px}.mb--12{margin-bottom:-12px}.mb-13{margin-bottom:13px}.mb--13{margin-bottom:-13px}.mb-14{margin-bottom:14px}.mb--14{margin-bottom:-14px}.mb-15{margin-bottom:15px}.mb--15{margin-bottom:-15px}.mb-16{margin-bottom:16px}.mb--16{margin-bottom:-16px}.mb-17{margin-bottom:17px}.mb--17{margin-bottom:-17px}.mb-18{margin-bottom:18px}.mb--18{margin-bottom:-18px}.mb-19{margin-bottom:19px}.mb--19{margin-bottom:-19px}.mb-20{margin-bottom:20px}.mb--20{margin-bottom:-20px}.mb-21{margin-bottom:21px}.mb--21{margin-bottom:-21px}.mb-22{margin-bottom:22px}.mb--22{margin-bottom:-22px}.mb-23{margin-bottom:23px}.mb--23{margin-bottom:-23px}.mb-24{margin-bottom:24px}.mb--24{margin-bottom:-24px}.mb-25{margin-bottom:25px}.mb--25{margin-bottom:-25px}.mb-26{margin-bottom:26px}.mb--26{margin-bottom:-26px}.mb-27{margin-bottom:27px}.mb--27{margin-bottom:-27px}.mb-28{margin-bottom:28px}.mb--28{margin-bottom:-28px}.mb-29{margin-bottom:29px}.mb--29{margin-bottom:-29px}.mb-30{margin-bottom:30px}.mb--30{margin-bottom:-30px}.mb-31{margin-bottom:31px}.mb--31{margin-bottom:-31px}.mb-32{margin-bottom:32px}.mb--32{margin-bottom:-32px}.mb-33{margin-bottom:33px}.mb--33{margin-bottom:-33px}.mb-34{margin-bottom:34px}.mb--34{margin-bottom:-34px}.mb-35{margin-bottom:35px}.mb--35{margin-bottom:-35px}.mb-36{margin-bottom:36px}.mb--36{margin-bottom:-36px}.mb-37{margin-bottom:37px}.mb--37{margin-bottom:-37px}.mb-38{margin-bottom:38px}.mb--38{margin-bottom:-38px}.mb-39{margin-bottom:39px}.mb--39{margin-bottom:-39px}.mb-40{margin-bottom:40px}.mb--40{margin-bottom:-40px}.mb-41{margin-bottom:41px}.mb--41{margin-bottom:-41px}.mb-42{margin-bottom:42px}.mb--42{margin-bottom:-42px}.mb-43{margin-bottom:43px}.mb--43{margin-bottom:-43px}.mb-44{margin-bottom:44px}.mb--44{margin-bottom:-44px}.mb-45{margin-bottom:45px}.mb--45{margin-bottom:-45px}.mb-46{margin-bottom:46px}.mb--46{margin-bottom:-46px}.mb-47{margin-bottom:47px}.mb--47{margin-bottom:-47px}.mb-48{margin-bottom:48px}.mb--48{margin-bottom:-48px}.mb-49{margin-bottom:49px}.mb--49{margin-bottom:-49px}.mb-50{margin-bottom:50px}.mb--50{margin-bottom:-50px}.mb-n1{margin-bottom:2px}.mb--n1{margin-bottom:-2px}.mb-n2{margin-bottom:4px}.mb--n2{margin-bottom:-4px}.mb-n3{margin-bottom:6px}.mb--n3{margin-bottom:-6px}.mb-n4{margin-bottom:8px}.mb--n4{margin-bottom:-8px}.mb-n5{margin-bottom:10px}.mb--n5{margin-bottom:-10px}.mb-n6{margin-bottom:12px}.mb--n6{margin-bottom:-12px}.mb-n7{margin-bottom:14px}.mb--n7{margin-bottom:-14px}.mb-n8{margin-bottom:16px}.mb--n8{margin-bottom:-16px}.mb-n9{margin-bottom:18px}.mb--n9{margin-bottom:-18px}.mb-n10{margin-bottom:20px}.mb--n10{margin-bottom:-20px}.mb-n11{margin-bottom:22px}.mb--n11{margin-bottom:-22px}.mb-n12{margin-bottom:24px}.mb--n12{margin-bottom:-24px}.mb-n13{margin-bottom:26px}.mb--n13{margin-bottom:-26px}.mb-n14{margin-bottom:28px}.mb--n14{margin-bottom:-28px}.mb-n15{margin-bottom:30px}.mb--n15{margin-bottom:-30px}.mb-n16{margin-bottom:32px}.mb--n16{margin-bottom:-32px}.mb-n17{margin-bottom:34px}.mb--n17{margin-bottom:-34px}.mb-n18{margin-bottom:36px}.mb--n18{margin-bottom:-36px}.mb-n19{margin-bottom:38px}.mb--n19{margin-bottom:-38px}.mb-n20{margin-bottom:40px}.mb--n20{margin-bottom:-40px}.mb-n21{margin-bottom:42px}.mb--n21{margin-bottom:-42px}.mb-n22{margin-bottom:44px}.mb--n22{margin-bottom:-44px}.mb-n23{margin-bottom:46px}.mb--n23{margin-bottom:-46px}.mb-n24{margin-bottom:48px}.mb--n24{margin-bottom:-48px}.mb-n25{margin-bottom:50px}.mb--n25{margin-bottom:-50px}.ml-0{margin-left:0}.ml--0{margin-left:0}.ml-1{margin-left:1px}.ml--1{margin-left:-1px}.ml-2{margin-left:2px}.ml--2{margin-left:-2px}.ml-3{margin-left:3px}.ml--3{margin-left:-3px}.ml-4{margin-left:4px}.ml--4{margin-left:-4px}.ml-5{margin-left:5px}.ml--5{margin-left:-5px}.ml-6{margin-left:6px}.ml--6{margin-left:-6px}.ml-7{margin-left:7px}.ml--7{margin-left:-7px}.ml-8{margin-left:8px}.ml--8{margin-left:-8px}.ml-9{margin-left:9px}.ml--9{margin-left:-9px}.ml-10{margin-left:10px}.ml--10{margin-left:-10px}.ml-11{margin-left:11px}.ml--11{margin-left:-11px}.ml-12{margin-left:12px}.ml--12{margin-left:-12px}.ml-13{margin-left:13px}.ml--13{margin-left:-13px}.ml-14{margin-left:14px}.ml--14{margin-left:-14px}.ml-15{margin-left:15px}.ml--15{margin-left:-15px}.ml-16{margin-left:16px}.ml--16{margin-left:-16px}.ml-17{margin-left:17px}.ml--17{margin-left:-17px}.ml-18{margin-left:18px}.ml--18{margin-left:-18px}.ml-19{margin-left:19px}.ml--19{margin-left:-19px}.ml-20{margin-left:20px}.ml--20{margin-left:-20px}.ml-21{margin-left:21px}.ml--21{margin-left:-21px}.ml-22{margin-left:22px}.ml--22{margin-left:-22px}.ml-23{margin-left:23px}.ml--23{margin-left:-23px}.ml-24{margin-left:24px}.ml--24{margin-left:-24px}.ml-25{margin-left:25px}.ml--25{margin-left:-25px}.ml-26{margin-left:26px}.ml--26{margin-left:-26px}.ml-27{margin-left:27px}.ml--27{margin-left:-27px}.ml-28{margin-left:28px}.ml--28{margin-left:-28px}.ml-29{margin-left:29px}.ml--29{margin-left:-29px}.ml-30{margin-left:30px}.ml--30{margin-left:-30px}.ml-31{margin-left:31px}.ml--31{margin-left:-31px}.ml-32{margin-left:32px}.ml--32{margin-left:-32px}.ml-33{margin-left:33px}.ml--33{margin-left:-33px}.ml-34{margin-left:34px}.ml--34{margin-left:-34px}.ml-35{margin-left:35px}.ml--35{margin-left:-35px}.ml-36{margin-left:36px}.ml--36{margin-left:-36px}.ml-37{margin-left:37px}.ml--37{margin-left:-37px}.ml-38{margin-left:38px}.ml--38{margin-left:-38px}.ml-39{margin-left:39px}.ml--39{margin-left:-39px}.ml-40{margin-left:40px}.ml--40{margin-left:-40px}.ml-41{margin-left:41px}.ml--41{margin-left:-41px}.ml-42{margin-left:42px}.ml--42{margin-left:-42px}.ml-43{margin-left:43px}.ml--43{margin-left:-43px}.ml-44{margin-left:44px}.ml--44{margin-left:-44px}.ml-45{margin-left:45px}.ml--45{margin-left:-45px}.ml-46{margin-left:46px}.ml--46{margin-left:-46px}.ml-47{margin-left:47px}.ml--47{margin-left:-47px}.ml-48{margin-left:48px}.ml--48{margin-left:-48px}.ml-49{margin-left:49px}.ml--49{margin-left:-49px}.ml-50{margin-left:50px}.ml--50{margin-left:-50px}.ml-n1{margin-left:2px}.ml--n1{margin-left:-2px}.ml-n2{margin-left:4px}.ml--n2{margin-left:-4px}.ml-n3{margin-left:6px}.ml--n3{margin-left:-6px}.ml-n4{margin-left:8px}.ml--n4{margin-left:-8px}.ml-n5{margin-left:10px}.ml--n5{margin-left:-10px}.ml-n6{margin-left:12px}.ml--n6{margin-left:-12px}.ml-n7{margin-left:14px}.ml--n7{margin-left:-14px}.ml-n8{margin-left:16px}.ml--n8{margin-left:-16px}.ml-n9{margin-left:18px}.ml--n9{margin-left:-18px}.ml-n10{margin-left:20px}.ml--n10{margin-left:-20px}.ml-n11{margin-left:22px}.ml--n11{margin-left:-22px}.ml-n12{margin-left:24px}.ml--n12{margin-left:-24px}.ml-n13{margin-left:26px}.ml--n13{margin-left:-26px}.ml-n14{margin-left:28px}.ml--n14{margin-left:-28px}.ml-n15{margin-left:30px}.ml--n15{margin-left:-30px}.ml-n16{margin-left:32px}.ml--n16{margin-left:-32px}.ml-n17{margin-left:34px}.ml--n17{margin-left:-34px}.ml-n18{margin-left:36px}.ml--n18{margin-left:-36px}.ml-n19{margin-left:38px}.ml--n19{margin-left:-38px}.ml-n20{margin-left:40px}.ml--n20{margin-left:-40px}.ml-n21{margin-left:42px}.ml--n21{margin-left:-42px}.ml-n22{margin-left:44px}.ml--n22{margin-left:-44px}.ml-n23{margin-left:46px}.ml--n23{margin-left:-46px}.ml-n24{margin-left:48px}.ml--n24{margin-left:-48px}.ml-n25{margin-left:50px}.ml--n25{margin-left:-50px}.mx-0{margin-left:0;margin-right:0}.mx-1{margin-left:1px;margin-right:1px}.mx-2{margin-left:2px;margin-right:2px}.mx-3{margin-left:3px;margin-right:3px}.mx-4{margin-left:4px;margin-right:4px}.mx-5{margin-left:5px;margin-right:5px}.mx-6{margin-left:6px;margin-right:6px}.mx-7{margin-left:7px;margin-right:7px}.mx-8{margin-left:8px;margin-right:8px}.mx-9{margin-left:9px;margin-right:9px}.mx-10{margin-left:10px;margin-right:10px}.mx-11{margin-left:11px;margin-right:11px}.mx-12{margin-left:12px;margin-right:12px}.mx-13{margin-left:13px;margin-right:13px}.mx-14{margin-left:14px;margin-right:14px}.mx-15{margin-left:15px;margin-right:15px}.mx-16{margin-left:16px;margin-right:16px}.mx-17{margin-left:17px;margin-right:17px}.mx-18{margin-left:18px;margin-right:18px}.mx-19{margin-left:19px;margin-right:19px}.mx-20{margin-left:20px;margin-right:20px}.mx-21{margin-left:21px;margin-right:21px}.mx-22{margin-left:22px;margin-right:22px}.mx-23{margin-left:23px;margin-right:23px}.mx-24{margin-left:24px;margin-right:24px}.mx-25{margin-left:25px;margin-right:25px}.mx-26{margin-left:26px;margin-right:26px}.mx-27{margin-left:27px;margin-right:27px}.mx-28{margin-left:28px;margin-right:28px}.mx-29{margin-left:29px;margin-right:29px}.mx-30{margin-left:30px;margin-right:30px}.mx-31{margin-left:31px;margin-right:31px}.mx-32{margin-left:32px;margin-right:32px}.mx-33{margin-left:33px;margin-right:33px}.mx-34{margin-left:34px;margin-right:34px}.mx-35{margin-left:35px;margin-right:35px}.mx-36{margin-left:36px;margin-right:36px}.mx-37{margin-left:37px;margin-right:37px}.mx-38{margin-left:38px;margin-right:38px}.mx-39{margin-left:39px;margin-right:39px}.mx-40{margin-left:40px;margin-right:40px}.mx-41{margin-left:41px;margin-right:41px}.mx-42{margin-left:42px;margin-right:42px}.mx-43{margin-left:43px;margin-right:43px}.mx-44{margin-left:44px;margin-right:44px}.mx-45{margin-left:45px;margin-right:45px}.mx-46{margin-left:46px;margin-right:46px}.mx-47{margin-left:47px;margin-right:47px}.mx-48{margin-left:48px;margin-right:48px}.mx-49{margin-left:49px;margin-right:49px}.mx-50{margin-left:50px;margin-right:50px}.mx-n1{margin-left:2px;margin-right:2px}.mx-n2{margin-left:4px;margin-right:4px}.mx-n3{margin-left:6px;margin-right:6px}.mx-n4{margin-left:8px;margin-right:8px}.mx-n5{margin-left:10px;margin-right:10px}.mx-n6{margin-left:12px;margin-right:12px}.mx-n7{margin-left:14px;margin-right:14px}.mx-n8{margin-left:16px;margin-right:16px}.mx-n9{margin-left:18px;margin-right:18px}.mx-n10{margin-left:20px;margin-right:20px}.mx-n11{margin-left:22px;margin-right:22px}.mx-n12{margin-left:24px;margin-right:24px}.mx-n13{margin-left:26px;margin-right:26px}.mx-n14{margin-left:28px;margin-right:28px}.mx-n15{margin-left:30px;margin-right:30px}.mx-n16{margin-left:32px;margin-right:32px}.mx-n17{margin-left:34px;margin-right:34px}.mx-n18{margin-left:36px;margin-right:36px}.mx-n19{margin-left:38px;margin-right:38px}.mx-n20{margin-left:40px;margin-right:40px}.mx-n21{margin-left:42px;margin-right:42px}.mx-n22{margin-left:44px;margin-right:44px}.mx-n23{margin-left:46px;margin-right:46px}.mx-n24{margin-left:48px;margin-right:48px}.mx-n25{margin-left:50px;margin-right:50px}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:1px;margin-bottom:1px}.my-2{margin-top:2px;margin-bottom:2px}.my-3{margin-top:3px;margin-bottom:3px}.my-4{margin-top:4px;margin-bottom:4px}.my-5{margin-top:5px;margin-bottom:5px}.my-6{margin-top:6px;margin-bottom:6px}.my-7{margin-top:7px;margin-bottom:7px}.my-8{margin-top:8px;margin-bottom:8px}.my-9{margin-top:9px;margin-bottom:9px}.my-10{margin-top:10px;margin-bottom:10px}.my-11{margin-top:11px;margin-bottom:11px}.my-12{margin-top:12px;margin-bottom:12px}.my-13{margin-top:13px;margin-bottom:13px}.my-14{margin-top:14px;margin-bottom:14px}.my-15{margin-top:15px;margin-bottom:15px}.my-16{margin-top:16px;margin-bottom:16px}.my-17{margin-top:17px;margin-bottom:17px}.my-18{margin-top:18px;margin-bottom:18px}.my-19{margin-top:19px;margin-bottom:19px}.my-20{margin-top:20px;margin-bottom:20px}.my-21{margin-top:21px;margin-bottom:21px}.my-22{margin-top:22px;margin-bottom:22px}.my-23{margin-top:23px;margin-bottom:23px}.my-24{margin-top:24px;margin-bottom:24px}.my-25{margin-top:25px;margin-bottom:25px}.my-26{margin-top:26px;margin-bottom:26px}.my-27{margin-top:27px;margin-bottom:27px}.my-28{margin-top:28px;margin-bottom:28px}.my-29{margin-top:29px;margin-bottom:29px}.my-30{margin-top:30px;margin-bottom:30px}.my-31{margin-top:31px;margin-bottom:31px}.my-32{margin-top:32px;margin-bottom:32px}.my-33{margin-top:33px;margin-bottom:33px}.my-34{margin-top:34px;margin-bottom:34px}.my-35{margin-top:35px;margin-bottom:35px}.my-36{margin-top:36px;margin-bottom:36px}.my-37{margin-top:37px;margin-bottom:37px}.my-38{margin-top:38px;margin-bottom:38px}.my-39{margin-top:39px;margin-bottom:39px}.my-40{margin-top:40px;margin-bottom:40px}.my-41{margin-top:41px;margin-bottom:41px}.my-42{margin-top:42px;margin-bottom:42px}.my-43{margin-top:43px;margin-bottom:43px}.my-44{margin-top:44px;margin-bottom:44px}.my-45{margin-top:45px;margin-bottom:45px}.my-46{margin-top:46px;margin-bottom:46px}.my-47{margin-top:47px;margin-bottom:47px}.my-48{margin-top:48px;margin-bottom:48px}.my-49{margin-top:49px;margin-bottom:49px}.my-50{margin-top:50px;margin-bottom:50px}.my-n1{margin-top:2px;margin-bottom:2px}.my-n2{margin-top:4px;margin-bottom:4px}.my-n3{margin-top:6px;margin-bottom:6px}.my-n4{margin-top:8px;margin-bottom:8px}.my-n5{margin-top:10px;margin-bottom:10px}.my-n6{margin-top:12px;margin-bottom:12px}.my-n7{margin-top:14px;margin-bottom:14px}.my-n8{margin-top:16px;margin-bottom:16px}.my-n9{margin-top:18px;margin-bottom:18px}.my-n10{margin-top:20px;margin-bottom:20px}.my-n11{margin-top:22px;margin-bottom:22px}.my-n12{margin-top:24px;margin-bottom:24px}.my-n13{margin-top:26px;margin-bottom:26px}.my-n14{margin-top:28px;margin-bottom:28px}.my-n15{margin-top:30px;margin-bottom:30px}.my-n16{margin-top:32px;margin-bottom:32px}.my-n17{margin-top:34px;margin-bottom:34px}.my-n18{margin-top:36px;margin-bottom:36px}.my-n19{margin-top:38px;margin-bottom:38px}.my-n20{margin-top:40px;margin-bottom:40px}.my-n21{margin-top:42px;margin-bottom:42px}.my-n22{margin-top:44px;margin-bottom:44px}.my-n23{margin-top:46px;margin-bottom:46px}.my-n24{margin-top:48px;margin-bottom:48px}.my-n25{margin-top:50px;margin-bottom:50px}.t-0{top:0}.t--0{top:0}.t-1{top:1px}.t--1{top:-1px}.t-2{top:2px}.t--2{top:-2px}.t-3{top:3px}.t--3{top:-3px}.t-4{top:4px}.t--4{top:-4px}.t-5{top:5px}.t--5{top:-5px}.t-6{top:6px}.t--6{top:-6px}.t-7{top:7px}.t--7{top:-7px}.t-8{top:8px}.t--8{top:-8px}.t-9{top:9px}.t--9{top:-9px}.t-10{top:10px}.t--10{top:-10px}.t-11{top:11px}.t--11{top:-11px}.t-12{top:12px}.t--12{top:-12px}.t-13{top:13px}.t--13{top:-13px}.t-14{top:14px}.t--14{top:-14px}.t-15{top:15px}.t--15{top:-15px}.t-16{top:16px}.t--16{top:-16px}.t-17{top:17px}.t--17{top:-17px}.t-18{top:18px}.t--18{top:-18px}.t-19{top:19px}.t--19{top:-19px}.t-20{top:20px}.t--20{top:-20px}.t-21{top:21px}.t--21{top:-21px}.t-22{top:22px}.t--22{top:-22px}.t-23{top:23px}.t--23{top:-23px}.t-24{top:24px}.t--24{top:-24px}.t-25{top:25px}.t--25{top:-25px}.t-26{top:26px}.t--26{top:-26px}.t-27{top:27px}.t--27{top:-27px}.t-28{top:28px}.t--28{top:-28px}.t-29{top:29px}.t--29{top:-29px}.t-30{top:30px}.t--30{top:-30px}.t-31{top:31px}.t--31{top:-31px}.t-32{top:32px}.t--32{top:-32px}.t-33{top:33px}.t--33{top:-33px}.t-34{top:34px}.t--34{top:-34px}.t-35{top:35px}.t--35{top:-35px}.t-36{top:36px}.t--36{top:-36px}.t-37{top:37px}.t--37{top:-37px}.t-38{top:38px}.t--38{top:-38px}.t-39{top:39px}.t--39{top:-39px}.t-40{top:40px}.t--40{top:-40px}.t-41{top:41px}.t--41{top:-41px}.t-42{top:42px}.t--42{top:-42px}.t-43{top:43px}.t--43{top:-43px}.t-44{top:44px}.t--44{top:-44px}.t-45{top:45px}.t--45{top:-45px}.t-46{top:46px}.t--46{top:-46px}.t-47{top:47px}.t--47{top:-47px}.t-48{top:48px}.t--48{top:-48px}.t-49{top:49px}.t--49{top:-49px}.t-50{top:50px}.t--50{top:-50px}.t-n1{top:2px}.t--n1{top:-2px}.t-n2{top:4px}.t--n2{top:-4px}.t-n3{top:6px}.t--n3{top:-6px}.t-n4{top:8px}.t--n4{top:-8px}.t-n5{top:10px}.t--n5{top:-10px}.t-n6{top:12px}.t--n6{top:-12px}.t-n7{top:14px}.t--n7{top:-14px}.t-n8{top:16px}.t--n8{top:-16px}.t-n9{top:18px}.t--n9{top:-18px}.t-n10{top:20px}.t--n10{top:-20px}.t-n11{top:22px}.t--n11{top:-22px}.t-n12{top:24px}.t--n12{top:-24px}.t-n13{top:26px}.t--n13{top:-26px}.t-n14{top:28px}.t--n14{top:-28px}.t-n15{top:30px}.t--n15{top:-30px}.t-n16{top:32px}.t--n16{top:-32px}.t-n17{top:34px}.t--n17{top:-34px}.t-n18{top:36px}.t--n18{top:-36px}.t-n19{top:38px}.t--n19{top:-38px}.t-n20{top:40px}.t--n20{top:-40px}.t-n21{top:42px}.t--n21{top:-42px}.t-n22{top:44px}.t--n22{top:-44px}.t-n23{top:46px}.t--n23{top:-46px}.t-n24{top:48px}.t--n24{top:-48px}.t-n25{top:50px}.t--n25{top:-50px}.r-0{right:0}.r--0{right:0}.r-1{right:1px}.r--1{right:-1px}.r-2{right:2px}.r--2{right:-2px}.r-3{right:3px}.r--3{right:-3px}.r-4{right:4px}.r--4{right:-4px}.r-5{right:5px}.r--5{right:-5px}.r-6{right:6px}.r--6{right:-6px}.r-7{right:7px}.r--7{right:-7px}.r-8{right:8px}.r--8{right:-8px}.r-9{right:9px}.r--9{right:-9px}.r-10{right:10px}.r--10{right:-10px}.r-11{right:11px}.r--11{right:-11px}.r-12{right:12px}.r--12{right:-12px}.r-13{right:13px}.r--13{right:-13px}.r-14{right:14px}.r--14{right:-14px}.r-15{right:15px}.r--15{right:-15px}.r-16{right:16px}.r--16{right:-16px}.r-17{right:17px}.r--17{right:-17px}.r-18{right:18px}.r--18{right:-18px}.r-19{right:19px}.r--19{right:-19px}.r-20{right:20px}.r--20{right:-20px}.r-21{right:21px}.r--21{right:-21px}.r-22{right:22px}.r--22{right:-22px}.r-23{right:23px}.r--23{right:-23px}.r-24{right:24px}.r--24{right:-24px}.r-25{right:25px}.r--25{right:-25px}.r-26{right:26px}.r--26{right:-26px}.r-27{right:27px}.r--27{right:-27px}.r-28{right:28px}.r--28{right:-28px}.r-29{right:29px}.r--29{right:-29px}.r-30{right:30px}.r--30{right:-30px}.r-31{right:31px}.r--31{right:-31px}.r-32{right:32px}.r--32{right:-32px}.r-33{right:33px}.r--33{right:-33px}.r-34{right:34px}.r--34{right:-34px}.r-35{right:35px}.r--35{right:-35px}.r-36{right:36px}.r--36{right:-36px}.r-37{right:37px}.r--37{right:-37px}.r-38{right:38px}.r--38{right:-38px}.r-39{right:39px}.r--39{right:-39px}.r-40{right:40px}.r--40{right:-40px}.r-41{right:41px}.r--41{right:-41px}.r-42{right:42px}.r--42{right:-42px}.r-43{right:43px}.r--43{right:-43px}.r-44{right:44px}.r--44{right:-44px}.r-45{right:45px}.r--45{right:-45px}.r-46{right:46px}.r--46{right:-46px}.r-47{right:47px}.r--47{right:-47px}.r-48{right:48px}.r--48{right:-48px}.r-49{right:49px}.r--49{right:-49px}.r-50{right:50px}.r--50{right:-50px}.r-n1{right:2px}.r--n1{right:-2px}.r-n2{right:4px}.r--n2{right:-4px}.r-n3{right:6px}.r--n3{right:-6px}.r-n4{right:8px}.r--n4{right:-8px}.r-n5{right:10px}.r--n5{right:-10px}.r-n6{right:12px}.r--n6{right:-12px}.r-n7{right:14px}.r--n7{right:-14px}.r-n8{right:16px}.r--n8{right:-16px}.r-n9{right:18px}.r--n9{right:-18px}.r-n10{right:20px}.r--n10{right:-20px}.r-n11{right:22px}.r--n11{right:-22px}.r-n12{right:24px}.r--n12{right:-24px}.r-n13{right:26px}.r--n13{right:-26px}.r-n14{right:28px}.r--n14{right:-28px}.r-n15{right:30px}.r--n15{right:-30px}.r-n16{right:32px}.r--n16{right:-32px}.r-n17{right:34px}.r--n17{right:-34px}.r-n18{right:36px}.r--n18{right:-36px}.r-n19{right:38px}.r--n19{right:-38px}.r-n20{right:40px}.r--n20{right:-40px}.r-n21{right:42px}.r--n21{right:-42px}.r-n22{right:44px}.r--n22{right:-44px}.r-n23{right:46px}.r--n23{right:-46px}.r-n24{right:48px}.r--n24{right:-48px}.r-n25{right:50px}.r--n25{right:-50px}.b-0{bottom:0}.b--0{bottom:0}.b-1{bottom:1px}.b--1{bottom:-1px}.b-2{bottom:2px}.b--2{bottom:-2px}.b-3{bottom:3px}.b--3{bottom:-3px}.b-4{bottom:4px}.b--4{bottom:-4px}.b-5{bottom:5px}.b--5{bottom:-5px}.b-6{bottom:6px}.b--6{bottom:-6px}.b-7{bottom:7px}.b--7{bottom:-7px}.b-8{bottom:8px}.b--8{bottom:-8px}.b-9{bottom:9px}.b--9{bottom:-9px}.b-10{bottom:10px}.b--10{bottom:-10px}.b-11{bottom:11px}.b--11{bottom:-11px}.b-12{bottom:12px}.b--12{bottom:-12px}.b-13{bottom:13px}.b--13{bottom:-13px}.b-14{bottom:14px}.b--14{bottom:-14px}.b-15{bottom:15px}.b--15{bottom:-15px}.b-16{bottom:16px}.b--16{bottom:-16px}.b-17{bottom:17px}.b--17{bottom:-17px}.b-18{bottom:18px}.b--18{bottom:-18px}.b-19{bottom:19px}.b--19{bottom:-19px}.b-20{bottom:20px}.b--20{bottom:-20px}.b-21{bottom:21px}.b--21{bottom:-21px}.b-22{bottom:22px}.b--22{bottom:-22px}.b-23{bottom:23px}.b--23{bottom:-23px}.b-24{bottom:24px}.b--24{bottom:-24px}.b-25{bottom:25px}.b--25{bottom:-25px}.b-26{bottom:26px}.b--26{bottom:-26px}.b-27{bottom:27px}.b--27{bottom:-27px}.b-28{bottom:28px}.b--28{bottom:-28px}.b-29{bottom:29px}.b--29{bottom:-29px}.b-30{bottom:30px}.b--30{bottom:-30px}.b-31{bottom:31px}.b--31{bottom:-31px}.b-32{bottom:32px}.b--32{bottom:-32px}.b-33{bottom:33px}.b--33{bottom:-33px}.b-34{bottom:34px}.b--34{bottom:-34px}.b-35{bottom:35px}.b--35{bottom:-35px}.b-36{bottom:36px}.b--36{bottom:-36px}.b-37{bottom:37px}.b--37{bottom:-37px}.b-38{bottom:38px}.b--38{bottom:-38px}.b-39{bottom:39px}.b--39{bottom:-39px}.b-40{bottom:40px}.b--40{bottom:-40px}.b-41{bottom:41px}.b--41{bottom:-41px}.b-42{bottom:42px}.b--42{bottom:-42px}.b-43{bottom:43px}.b--43{bottom:-43px}.b-44{bottom:44px}.b--44{bottom:-44px}.b-45{bottom:45px}.b--45{bottom:-45px}.b-46{bottom:46px}.b--46{bottom:-46px}.b-47{bottom:47px}.b--47{bottom:-47px}.b-48{bottom:48px}.b--48{bottom:-48px}.b-49{bottom:49px}.b--49{bottom:-49px}.b-50{bottom:50px}.b--50{bottom:-50px}.b-n1{bottom:2px}.b--n1{bottom:-2px}.b-n2{bottom:4px}.b--n2{bottom:-4px}.b-n3{bottom:6px}.b--n3{bottom:-6px}.b-n4{bottom:8px}.b--n4{bottom:-8px}.b-n5{bottom:10px}.b--n5{bottom:-10px}.b-n6{bottom:12px}.b--n6{bottom:-12px}.b-n7{bottom:14px}.b--n7{bottom:-14px}.b-n8{bottom:16px}.b--n8{bottom:-16px}.b-n9{bottom:18px}.b--n9{bottom:-18px}.b-n10{bottom:20px}.b--n10{bottom:-20px}.b-n11{bottom:22px}.b--n11{bottom:-22px}.b-n12{bottom:24px}.b--n12{bottom:-24px}.b-n13{bottom:26px}.b--n13{bottom:-26px}.b-n14{bottom:28px}.b--n14{bottom:-28px}.b-n15{bottom:30px}.b--n15{bottom:-30px}.b-n16{bottom:32px}.b--n16{bottom:-32px}.b-n17{bottom:34px}.b--n17{bottom:-34px}.b-n18{bottom:36px}.b--n18{bottom:-36px}.b-n19{bottom:38px}.b--n19{bottom:-38px}.b-n20{bottom:40px}.b--n20{bottom:-40px}.b-n21{bottom:42px}.b--n21{bottom:-42px}.b-n22{bottom:44px}.b--n22{bottom:-44px}.b-n23{bottom:46px}.b--n23{bottom:-46px}.b-n24{bottom:48px}.b--n24{bottom:-48px}.b-n25{bottom:50px}.b--n25{bottom:-50px}.l-0{left:0}.l--0{left:0}.l-1{left:1px}.l--1{left:-1px}.l-2{left:2px}.l--2{left:-2px}.l-3{left:3px}.l--3{left:-3px}.l-4{left:4px}.l--4{left:-4px}.l-5{left:5px}.l--5{left:-5px}.l-6{left:6px}.l--6{left:-6px}.l-7{left:7px}.l--7{left:-7px}.l-8{left:8px}.l--8{left:-8px}.l-9{left:9px}.l--9{left:-9px}.l-10{left:10px}.l--10{left:-10px}.l-11{left:11px}.l--11{left:-11px}.l-12{left:12px}.l--12{left:-12px}.l-13{left:13px}.l--13{left:-13px}.l-14{left:14px}.l--14{left:-14px}.l-15{left:15px}.l--15{left:-15px}.l-16{left:16px}.l--16{left:-16px}.l-17{left:17px}.l--17{left:-17px}.l-18{left:18px}.l--18{left:-18px}.l-19{left:19px}.l--19{left:-19px}.l-20{left:20px}.l--20{left:-20px}.l-21{left:21px}.l--21{left:-21px}.l-22{left:22px}.l--22{left:-22px}.l-23{left:23px}.l--23{left:-23px}.l-24{left:24px}.l--24{left:-24px}.l-25{left:25px}.l--25{left:-25px}.l-26{left:26px}.l--26{left:-26px}.l-27{left:27px}.l--27{left:-27px}.l-28{left:28px}.l--28{left:-28px}.l-29{left:29px}.l--29{left:-29px}.l-30{left:30px}.l--30{left:-30px}.l-31{left:31px}.l--31{left:-31px}.l-32{left:32px}.l--32{left:-32px}.l-33{left:33px}.l--33{left:-33px}.l-34{left:34px}.l--34{left:-34px}.l-35{left:35px}.l--35{left:-35px}.l-36{left:36px}.l--36{left:-36px}.l-37{left:37px}.l--37{left:-37px}.l-38{left:38px}.l--38{left:-38px}.l-39{left:39px}.l--39{left:-39px}.l-40{left:40px}.l--40{left:-40px}.l-41{left:41px}.l--41{left:-41px}.l-42{left:42px}.l--42{left:-42px}.l-43{left:43px}.l--43{left:-43px}.l-44{left:44px}.l--44{left:-44px}.l-45{left:45px}.l--45{left:-45px}.l-46{left:46px}.l--46{left:-46px}.l-47{left:47px}.l--47{left:-47px}.l-48{left:48px}.l--48{left:-48px}.l-49{left:49px}.l--49{left:-49px}.l-50{left:50px}.l--50{left:-50px}.l-n1{left:2px}.l--n1{left:-2px}.l-n2{left:4px}.l--n2{left:-4px}.l-n3{left:6px}.l--n3{left:-6px}.l-n4{left:8px}.l--n4{left:-8px}.l-n5{left:10px}.l--n5{left:-10px}.l-n6{left:12px}.l--n6{left:-12px}.l-n7{left:14px}.l--n7{left:-14px}.l-n8{left:16px}.l--n8{left:-16px}.l-n9{left:18px}.l--n9{left:-18px}.l-n10{left:20px}.l--n10{left:-20px}.l-n11{left:22px}.l--n11{left:-22px}.l-n12{left:24px}.l--n12{left:-24px}.l-n13{left:26px}.l--n13{left:-26px}.l-n14{left:28px}.l--n14{left:-28px}.l-n15{left:30px}.l--n15{left:-30px}.l-n16{left:32px}.l--n16{left:-32px}.l-n17{left:34px}.l--n17{left:-34px}.l-n18{left:36px}.l--n18{left:-36px}.l-n19{left:38px}.l--n19{left:-38px}.l-n20{left:40px}.l--n20{left:-40px}.l-n21{left:42px}.l--n21{left:-42px}.l-n22{left:44px}.l--n22{left:-44px}.l-n23{left:46px}.l--n23{left:-46px}.l-n24{left:48px}.l--n24{left:-48px}.l-n25{left:50px}.l--n25{left:-50px}.flex{display:flex}.flex-col{flex-direction:column}.flex-wrap{flex-flow:row wrap}.flex-shrink{flex-shrink:0}.flex-row{flex-direction:row}.flex-reverse{flex-direction:row-reverse}.flex-row-top-start{justify-content:flex-start;align-items:flex-start;display:flex}.flex-row-top-center{justify-content:center;align-items:flex-start;display:flex}.flex-row-top-end{justify-content:flex-end;align-items:flex-start;display:flex}.flex-row-center-start{justify-content:flex-start;align-items:center;display:flex}.flex-row-center-center{justify-content:center;align-items:center;display:flex}.flex-row-center-end{justify-content:flex-end;align-items:center;display:flex}.flex-row-bottom-start{justify-content:flex-start;align-items:flex-end;display:flex}.flex-row-bottom-center{justify-content:center;align-items:flex-end;display:flex}.flex-row-bottom-end{justify-content:flex-end;align-items:flex-end;display:flex}.flex-row-center-between{justify-content:space-between;align-items:center;display:flex}.flex-col-top-start{justify-content:flex-start;align-items:flex-start;display:flex}.flex-col-top-center{justify-content:flex-start;align-items:center;display:flex}.flex-col-top-end{justify-content:flex-start;align-items:flex-end;display:flex}.flex-col-center-start{justify-content:center;align-items:flex-start;display:flex}.flex-col-center-center{justify-content:center;align-items:center;display:flex}.flex-col-center-end{justify-content:center;align-items:flex-end;display:flex}.flex-col-bottom-start{justify-content:flex-end;align-items:flex-start;display:flex}.flex-col-bottom-center{justify-content:flex-end;align-items:center;display:flex}.flex-col-bottom-end{justify-content:flex-end;align-items:flex-end;display:flex}.flex-start{justify-content:flex-start;align-items:center;display:flex}.flex-end{justify-content:flex-end;align-items:center;display:flex}.flex-center{justify-content:center;align-items:center;display:flex}.flex-between{justify-content:space-between}.flex-col-full{flex-direction:column;align-items:stretch}.flex-around{justify-content:space-around}.flex-0{flex:0}.flex-1{flex:1}.flex-2{flex:2}.flex-3{flex:3}.flex-4{flex:4}.flex-5{flex:5}.flex-6{flex:6}.flex-7{flex:7}.flex-8{flex:8}.flex-9{flex:9}.flex-10{flex:10}.flex-11{flex:11}.flex-12{flex:12}.text-red{color:#f44336}.red{background-color:#f44336}.text-pink{color:#e91e63}.pink{background-color:#e91e63}.text-purple{color:#9c27b0}.purple{background-color:#9c27b0}.text-deep-purple{color:#673ab7}.deep-purple{background-color:#673ab7}.text-indigo{color:#3f51b5}.indigo{background-color:#3f51b5}.text-blue{color:#2196f3}.blue{background-color:#2196f3}.text-light-blue{color:#03a9f4}.light-blue{background-color:#03a9f4}.text-cyan{color:#00bcd4}.cyan{background-color:#00bcd4}.text-teal{color:#009688}.teal{background-color:#009688}.text-green{color:#4caf50}.green{background-color:#4caf50}.text-light-green{color:#8bc34a}.light-green{background-color:#8bc34a}.text-lime{color:#cddc39}.lime{background-color:#cddc39}.text-yellow{color:#ffeb3b}.yellow{background-color:#ffeb3b}.text-amber{color:#ffc107}.amber{background-color:#ffc107}.text-orange{color:#ff9800}.orange{background-color:#ff9800}.text-deep-orange{color:#ff5722}.deep-orange{background-color:#ff5722}.text-brown{color:#795548}.brown{background-color:#795548}.text-blue-grey{color:#607d8b}.blue-grey{background-color:#607d8b}.text-primary{color:#08f}.primary{background-color:#08f}.text-success{color:#34c759}.success{background-color:#34c759}.text-danger{color:#ff8d28}.danger{background-color:#ff8d28}.text-warn{color:#f3bf12}.warn{background-color:#f3bf12}.text-error{color:#ff383c}.error{background-color:#ff383c}.text-info{color:#f2f2f7}.info{background-color:#f2f2f7}.text-grey{color:#9e9e9e}.grey{background-color:#9e9e9e}.text-black{color:#000}.black{background-color:#000}.text-white{color:#fff}.white{background-color:#fff}.text-lighten-5{color:#fafafa}.lighten-5{background-color:#fafafa}.text-lighten-4{color:#f5f5f5}.lighten-4{background-color:#f5f5f5}.text-lighten-3{color:#eee}.lighten-3{background-color:#eee}.text-lighten-2{color:#e0e0e0}.lighten-2{background-color:#e0e0e0}.text-lighten-1{color:#bdbdbd}.lighten-1{background-color:#bdbdbd}.text-darken-1{color:#757575}.darken-1{background-color:#757575}.text-darken-2{color:#616161}.darken-2{background-color:#616161}.text-darken-3{color:#424242}.darken-3{background-color:#424242}.text-darken-4{color:#212121}.darken-4{background-color:#212121}.text-darken-5{color:#131313}.darken-5{background-color:#131313}.text-darken-6{color:#0a0a0a}.darken-6{background-color:#0a0a0a} \ No newline at end of file diff --git a/uni_modules/tmx-ui/scss/uvuePx.scss b/uni_modules/tmx-ui/scss/uvuePx.scss new file mode 100644 index 0000000..5917461 --- /dev/null +++ b/uni_modules/tmx-ui/scss/uvuePx.scss @@ -0,0 +1,566 @@ +/* #ifdef WEB */ +.uni-picker-view-mask{ + background-image:none !important; +} +/* #endif */ +// 溢出隐藏。 +.overflow { + overflow: hidden; +} +.show{ + visibility:visible; +} +.hidden{ + visibility:hidden; +} +.none{ + display:none; +} +$v_position: ( + relative: relative, + absolute: absolute, + fixed: fixed, + // sticky: sticky, + // static : static , +); + +@each $name,$key in $v_position { + .#{$name} { + position: $key ; + } +} +.fulled{ + width:100%; +} +.fulled-height { + flex: 1; +} + + + + +@for $i from 0 through 26 { + .zIndex-#{$i} { + z-index: #{$i * 1}; + } + .zIndex-n#{$i} { + z-index: #{$i * 2}; + } +} + +.text-overflow { + text-overflow: ellipsis; +} + +@for $i from 1 to 6 { + .text-overflow-#{$i} { + text-overflow: ellipsis; + lines: $i; + } +} + + +// 文本大小 。text-size-xs大小名称,xxs,xs,s,n,g,lg,xl +@each $name,$key in (xxs: 10px, xs: 11px, s: 12px, m: 14px, n: 15px, g: 17px, lg: 18px, xl: 20px) { + .text-size-#{$name} { + font-size: $key; + } +} + +// 文本加粗text-weight-s,n,b +@each $name,$key in (s: 400, n: 400, b: 700) { + .text-weight-#{$name} { + font-weight: $key; + } +} + +// 文本对齐 。text-align-left,right,center +@each $name,$key in (left: left, right: right, center: center) { + .text-align-#{$name} { + text-align: $key; + } +} + +// 圆角半径 +// 圆角说明 round-方向-大小。 +// tl,顶左,tr顶右。bt底左,br底右。a全部。t:顶左和顶右,b:底左和底右,l:顶左和底左,r:顶右,底右。 +@each $name,$key in (tl: 'tl', tr: 'tr', bl: 'bl', br: 'br', a: 'a', t: 't', b: 'b', l: 'l', r: 'r') { + @for $i from 0 to 51 { + .round-#{$name}-#{$i} { + @if $key=='tl' { + border-top-left-radius: #{$i}px; + } + + @if $key=='tr' { + border-top-right-radius: #{$i}px; + } + + @if $key=='bl' { + border-bottom-left-radius: #{$i}px; + } + + @if $key=='br' { + border-bottom-right-radius: #{$i}px; + } + + @if $key=='t' { + border-top-left-radius: #{$i}px; + border-top-right-radius: #{$i}px; + } + + @if $key=='b' { + border-bottom-left-radius: #{$i}px; + border-bottom-right-radius: #{$i}px; + } + + @if $key=='l' { + border-top-left-radius: #{$i}px; + border-bottom-left-radius: #{$i}px; + } + + @if $key=='r' { + border-top-right-radius: #{$i}px; + border-bottom-right-radius: #{$i}px; + } + + @if $key=='a' { + border-radius: #{$i}px; + } + } + } +} + +// 从0-100的圆角round-数字 +@for $i from 0 through 26 { + .round-#{$i} { + border-radius: #{$i}px; + } + +} + +/** 0-20表示的是1.0~3.0之间的行高 */ +@for $i from 0 through 21 { + .line-#{$i}{ + line-height: #{$i / 10 + 1}; + } +} + + + +// 透明度opacity-[1-10] +@for $i from 0 to 11 { + .opacity-#{$i} { + @if $i>0 and $i<10 { + opacity: $i / 10; + } + + @if $i==0 { + opacity: 0; + } + + @if $i==10 { + opacity: 1; + } + } +} + +// 添加边线 最大5 +@for $i from 0 to 6 { + @if $i==0 { + .border-0 { + border:0px solid #f5f5f5; + } + + .border { + border:1px solid #f5f5f5; + } + + } + + @if $i>0 { + .border-#{$i} { + border:#{$i}px solid #f5f5f5; + } + + .border-#{$i}-bk { + border:#{$i}px solid #f5f5f5; + } + } +} + +// 边线格式1:border-方向t,r,l,b-宽度 +@each $name,$key in (l: 'left', r: 'right', t: 'top', b: 'bottom', a: 'a') { + @for $i from 1 to 6 { + .border-#{$name}-#{$i} { + @if $key=='a' { + border:#{$i}px solid opacify($color: #f5f5f5, $amount: 1); + } + + @if $key !='a' { + border-#{$key}:#{$i}px solid opacify($color: #f5f5f5, $amount: 1); + } + } + + } +} + +// 内间距。p[a,t,r,b,l,x,y]如:pa表示所有边距,px:左右,py:上下,pr:右边距 +@each $name,$key in (a: 'padding', t: 'padding-top', r: 'padding-right', b: 'padding-bottom', l: 'padding-left', x: 'x', y: 'y') { + @for $i from 0 to 51 { + @if $key !='x' and $key !='y' { + .p#{$name}-#{$i} { + #{$key}: #{$i}px; + } + } + + @if $key=='x' { + .px-#{$i} { + padding-left: #{$i}px; + padding-right: #{$i}px; + } + } + + @if $key=='y' { + .py-#{$i} { + padding-top: #{$i}px; + padding-bottom: #{$i}px; + } + } + } + + @for $i from 1 to 26 { + @if $key !='x' and $key !='y' { + .p#{$name}-n#{$i} { + #{$key}: #{$i * 2}px; + } + } + + @if $key=='x' { + .px-n#{$i} { + padding-left: #{$i * 2}px; + padding-right: #{$i * 2}px; + } + } + + @if $key=='y' { + .py-n#{$i} { + padding-top: #{$i * 2}px; + padding-bottom: #{$i * 2}px; + } + } + } +} + +// 外间距。m[a,t,r,b,l,x,y]如:ma表示所有外边距,mx:左右,my:上下,mr:右边距 +@each $name,$key in (a: 'margin', t: 'margin-top', r: 'margin-right', b: 'margin-bottom', l: 'margin-left', x: 'x', y: 'y') { + @for $i from 0 to 51 { + @if $key !='x' and $key !='y' { + .m#{$name}-#{$i} { + #{$key}: #{$i}px; + } + + @if $key !='margin' { + .m#{$name}--#{$i} { + #{$key}: -#{$i}px; + } + } + } + @if $key=='x' { + .mx-#{$i} { + margin-left: #{$i}px; + margin-right: #{$i}px; + } + } + + @if $key=='y' { + .my-#{$i} { + margin-top: #{$i}px; + margin-bottom: #{$i}px; + } + } + } + + @for $i from 1 to 26 { + @if $key !='x' and $key !='y' { + .m#{$name}-n#{$i} { + #{$key}: #{$i * 2}px; + } + + @if $key !='margin' { + .m#{$name}--n#{$i} { + #{$key}: -#{$i * 2}px; + } + } + } + + @if $key=='x' { + .mx-n#{$i} { + margin-left: #{$i * 2}px; + margin-right: #{$i * 2}px; + } + } + + @if $key=='y' { + .my-n#{$i} { + margin-top: #{$i * 2}px; + margin-bottom: #{$i * 2}px; + } + } + } +} + +// 位置。 +@each $name,$key in (t: 'top', r: 'right', b: 'bottom', l: 'left') { + @for $i from 0 to 51 { + .#{$name}-#{$i} { + #{$key}: #{$i}px; + } + + .#{$name}--#{$i} { + #{$key}: -#{$i}px; + } + } + + @for $i from 1 to 26 { + .#{$name}-n#{$i} { + #{$key}: #{$i * 2}px; + } + + .#{$name}--n#{$i} { + #{$key}: -#{$i * 2}px; + } + } +} + +// Flex辅助。 +@mixin dsplay-flex($justify, $items, $content) { + justify-content: $justify; + align-items: $items ; + display: flex; +} + +.flex { + display: flex; +} + +.flex-col { + flex-direction: column; +} + +.flex-wrap { + flex-flow: row wrap; +} + +.flex-shrink { + flex-shrink: 0; +} + +.flex-row { + flex-direction: row; +} + +.flex-reverse { + flex-direction: row-reverse; +} + +//row模式下,上左对齐 +.flex-row-top-start { + @include dsplay-flex(flex-start, flex-start, center); +} + +//row模式下,上中对齐 +.flex-row-top-center { + @include dsplay-flex(center, flex-start, center); +} + +//row模式下,上右对齐 +.flex-row-top-end { + @include dsplay-flex(flex-end, flex-start, center); +} + +//row模式下,中左对齐 +.flex-row-center-start { + @include dsplay-flex(flex-start, center, center); +} + +//row模式下,中中对齐 +.flex-row-center-center { + @include dsplay-flex(center, center, center); +} + +//row模式下,上右对齐 +.flex-row-center-end { + @include dsplay-flex(flex-end, center, center); +} + +//row模式下,下左对齐 +.flex-row-bottom-start { + @include dsplay-flex(flex-start, flex-end, center); +} + +//row模式下,下中对齐 +.flex-row-bottom-center { + @include dsplay-flex(center, flex-end, center); +} + +//row模式下,下右对齐 +.flex-row-bottom-end { + @include dsplay-flex(flex-end, flex-end, center); +} + +//上下居中,两边对齐。 +.flex-row-center-between { + @include dsplay-flex(space-between, center, center); +} + +//-------- +//col模式下,上左对齐 +.flex-col-top-start { + @include dsplay-flex(flex-start, flex-start, center); +} + +//col模式下,上中对齐 +.flex-col-top-center { + @include dsplay-flex(flex-start, center, center); +} + +//col模式下,上右对齐 +.flex-col-top-end { + @include dsplay-flex(flex-start, flex-end, center); +} + +//col模式下,中左对齐 +.flex-col-center-start { + @include dsplay-flex(center, flex-start, center); +} + +//col模式下,中中对齐 +.flex-col-center-center { + @include dsplay-flex(center, center, center); +} + +//col模式下,上右对齐 +.flex-col-center-end { + @include dsplay-flex(center, flex-end, center); +} + +//col模式下,下左对齐 +.flex-col-bottom-start { + @include dsplay-flex(flex-end, flex-start, center); +} + +//col模式下,下中对齐 +.flex-col-bottom-center { + @include dsplay-flex(flex-end, center, center); +} + +//col模式下,下右对齐 +.flex-col-bottom-end { + @include dsplay-flex(flex-end, flex-end, center); +} + +//----------- + +// row居中左对齐 +.flex-start { + @include dsplay-flex(flex-start, center, center); +} + +// row居中右对齐 +.flex-end { + @include dsplay-flex(flex-end, center, center); +} + +// col,row上下左右居中对齐 +.flex-center { + @include dsplay-flex(center, center, center); +} + +// col,row两端对齐 +.flex-between { + justify-content: space-between; +} + +//横向的内容在col模式一睥100%宽,与flex-1中的flex-row是功能一样。 +.flex-col-full { + flex-direction: column; + align-items: stretch; +} + +// col,row居中等分对齐 +.flex-around { + justify-content: space-around; +} + +@for $i from 0 through 12 { + .flex-#{$i} { + flex: $i ; + } +} + + +$colorsDefault: ( + 'grey': #9e9e9e, + 'black': #000000, + 'white': #ffffff, + 'lighten-5': #fafafa, + 'lighten-4': #f5f5f5, + 'lighten-3': #eeeeee, + 'lighten-2': #e0e0e0, + 'lighten-1': #bdbdbd, + 'darken-1': #757575, + 'darken-2': #616161, + 'darken-3': #424242, + 'darken-4': #212121, + 'darken-5': #131313, + 'darken-6': #0a0a0a +); +$colors: ( + 'red': #f44336, + 'pink': #e91e63, + 'purple': #9c27b0, + 'deep-purple': #673ab7, + 'indigo': #3f51b5, + 'blue': #2196f3, + 'light-blue': #03a9f4, + 'cyan': #00bcd4, + 'teal': #009688, + 'green': #4caf50, + 'light-green': #8bc34a, + 'lime': #cddc39, + 'yellow': #ffeb3b, + 'amber': #ffc107, + 'orange': #ff9800, + 'deep-orange': #ff5722, + 'brown': #795548, + 'blue-grey': #607d8b, + 'primary':#0088ff, + 'success': #34c759, + 'danger': #ff8d28, + 'warn': #F3BF12, + 'error': #ff383c, + 'info': #f2f2f7 +); + +// 文本颜色。text-颜色名 +@each $name,$color in $colors { + .text-#{$name} { + color: $color ; + } + + .#{$name} { + background-color: $color; + } +} + +@each $name,$color in $colorsDefault { + .text-#{$name} { + color: $color ; + } + + .#{$name} { + background-color: $color; + } +} + + diff --git a/uni_modules/tmx-ui/utssdk/app-android/config.json b/uni_modules/tmx-ui/utssdk/app-android/config.json new file mode 100644 index 0000000..beefb01 --- /dev/null +++ b/uni_modules/tmx-ui/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "20" +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/utssdk/app-android/index.vue b/uni_modules/tmx-ui/utssdk/app-android/index.vue new file mode 100644 index 0000000..a178b62 --- /dev/null +++ b/uni_modules/tmx-ui/utssdk/app-android/index.vue @@ -0,0 +1,195 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/tmx-ui/utssdk/app-ios/config.json b/uni_modules/tmx-ui/utssdk/app-ios/config.json new file mode 100644 index 0000000..721b81e --- /dev/null +++ b/uni_modules/tmx-ui/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "9" +} \ No newline at end of file diff --git a/uni_modules/tmx-ui/utssdk/app-ios/index.vue b/uni_modules/tmx-ui/utssdk/app-ios/index.vue new file mode 100644 index 0000000..e0915ee --- /dev/null +++ b/uni_modules/tmx-ui/utssdk/app-ios/index.vue @@ -0,0 +1,212 @@ + + + + \ No newline at end of file diff --git a/uni_modules/x-animation-s/changelog.md b/uni_modules/x-animation-s/changelog.md new file mode 100644 index 0000000..358a3e3 --- /dev/null +++ b/uni_modules/x-animation-s/changelog.md @@ -0,0 +1,2 @@ +## 1.0.0(2025-02-13) +* 全端兼容 \ No newline at end of file diff --git a/uni_modules/x-animation-s/package.json b/uni_modules/x-animation-s/package.json new file mode 100644 index 0000000..1392da7 --- /dev/null +++ b/uni_modules/x-animation-s/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-animation-s", + "displayName": "x-animation-s", + "version": "1.0.0", + "description": "x-animation-s", + "keywords": [ + "x-animation-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/readme.md b/uni_modules/x-animation-s/readme.md new file mode 100644 index 0000000..f86e6ae --- /dev/null +++ b/uni_modules/x-animation-s/readme.md @@ -0,0 +1,206 @@ +# x-animation-s +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +### 功能特色 + +这是原生动画,性能好,有3d旋转效果,给你的应用增彩。基于原生实现,非CSS样式动画,具有高性能和流畅的动画效果。 + +### 兼容性 + +| IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件。种子用户可免于购买。 + +### 使用前提 + +需要自定义基座运行,且安卓5.0+(含5.0)以上支持。 + +### API接口说明 + +#### 1. translate - 位移动画 + +```ts + +interface XDANIMATION_TRANSLATE_OPTIONS { + ele: UniElement|null; // 目标元素 + duration?: number; // 动画持续时间,默认1000ms + delay?: number; // 延迟执行时间,默认0ms + translation?: number; // 位移方向,默认0 + from?: number; // 起始位置,默认360 + len?: number; // 位移距离,默认360 + loop?: number; // 循环次数,默认0 + start?: Function; // 动画开始回调 + end?: Function; // 动画结束回调 +} +``` + +#### 2. rotate - 旋转动画 +```ts + +interface XDANIMATION_ROTATE_OPTIONS { + ele: UniElement|null; // 目标元素 + duration?: number; // 动画持续时间,默认1000ms + delay?: number; // 延迟执行时间,默认0ms + from?: number; // 起始角度,默认0 + deg?: number; // 旋转角度,默认360 + loop?: number; // 循环次数,默认0 + start?: Function; // 动画开始回调 + end?: Function; // 动画结束回调 +} +``` + +#### 3. scale - 缩放动画 +```ts + +interface XDANIMATION_SCALE_OPTIONS { + ele: UniElement|null; // 目标元素 + duration?: number; // 动画持续时间,默认1000ms + delay?: number; // 延迟执行时间,默认0ms + direction?: number; // 缩放方向,默认2 + scale?: number; // 目标缩放比例,默认1 + from?: number; // 起始缩放比例,默认0 + loop?: number; // 循环次数,默认0 + start?: Function; // 动画开始回调 + end?: Function; // 动画结束回调 +} +``` + +#### 4. flip3D - 3D翻转动画 +```ts + +interface XDANIMATION_FLIP3D_OPTIONS { + ele: UniElement|null; // 目标元素 + duration?: number; // 动画持续时间,默认1000ms + delay?: number; // 延迟执行时间,默认0ms + axis?: number; // 翻转轴,默认1 + from?: number; // 起始角度,默认0 + deg?: number; // 翻转角度,默认360 + loop?: number; // 循环次数,默认0 + cameraDistance?: number; // 摄像机距离,默认12 + scaleZ?: number; // Z轴缩放,默认0.5 + start?: Function; // 动画开始回调 + end?: Function; // 动画结束回调 +} +``` + +### 特别注意事项 + +1. **iOS平台3D翻转限制**: + - iOS平台下,3D翻转角度只能在0-180度之间 + - 如需实现360度翻转,需要分段执行: + 1. 先执行0-180度翻转 + 2. 在回调中执行180-0度翻转 + +2. **生命周期回调**: + - start:动画开始时触发 + - end:动画结束时触发 + - 可以在回调中执行连续动画或其他操作 + +### 使用示例 + +```vue + + + + +``` + +### 动画组合示例 + +```ts + +// 连续动画示例:缩放-旋转-位移 +const complexAnimation = () => { + xAnimationS.scale({ + ele: uni.getElementById("xta"), + duration: 500, + from: 1, + scale: 1.2, + end: () => { + xAnimationS.rotate({ + ele: uni.getElementById("xta"), + duration: 500, + deg: 180, + end: () => { + xAnimationS.translate({ + ele: uni.getElementById("xta"), + duration: 500, + len: 100 + }) + } + }) + } + }) +} +``` \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/app-android/config.json b/uni_modules/x-animation-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/app-android/index.uts b/uni_modules/x-animation-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..df27d9e --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-android/index.uts @@ -0,0 +1,63 @@ +// import UniversalBlurHelper from 'uts.sdk.modules.utsXdBlur.UniversalBlurHelper'; +import Color from 'android.graphics.Color'; +import { hexToRgb } from '../libs/color.uts' +import View from 'android.view.View'; + +import xdAnimation from 'uts.sdk.modules.utsXdxdAnimation.xdAnimation'; +import {XDANIMATION_FLIP3D_OPTIONS,XDANIMATION_TRANSLATE_OPTIONS,XDANIMATION_ROTATE_OPTIONS,XDANIMATION_SCALE_OPTIONS} from "../interface.uts" + + +export class xAnimationS { + public static translate(opts:XDANIMATION_TRANSLATE_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration??1000).toLong() + let delay_s = (opts?.delay??0).toLong() + let translation_s = (opts?.translation??0).toInt() + let fromlen_s = (opts?.from??360).toFloat() + let len_s = (opts?.len??360).toFloat() + let loop_s = (opts?.loop??0).toInt() + xdAnimation.translate(view,duration_s,delay_s,translation_s,fromlen_s,len_s,loop_s,opts?.start,opts?.end) + } + public static rotate(opts:XDANIMATION_ROTATE_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration??1000).toLong() + let delay_s = (opts?.delay??0).toLong() + let from_s = (opts?.from??0).toFloat() + let deg_s = (opts?.deg??360).toFloat() + let loop_s = (opts?.loop??0).toInt() + xdAnimation.rotate(view,duration_s,delay_s,from_s,deg_s,loop_s,opts?.start,opts?.end) + } + public static scale(opts:XDANIMATION_SCALE_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration??1000).toLong() + let delay_s = (opts?.delay??0).toLong() + let direction_s = (opts?.direction??2).toInt() + let scale_s = (opts?.scale??1).toFloat() + let from_s = (opts?.from??0).toFloat() + + let loop_s = (opts?.loop??0).toInt() + xdAnimation.scale(view,duration_s,delay_s,direction_s,from_s,scale_s,loop_s,opts?.start,opts?.end) + } + public static flip3D(opts:XDANIMATION_FLIP3D_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration??1000).toLong() + let delay_s = (opts?.delay??0).toLong() + let axis_s = (opts?.axis??1).toInt() + let from_s = (opts?.from??0).toFloat() + let deg_s = (opts?.deg??360).toFloat() + let loop_s = (opts?.loop??0).toInt() + let cameraDistance_s = (opts?.cameraDistance??12).toFloat() + let scaleZ_s = (opts?.scaleZ??0.5).toFloat() + xdAnimation.flip3D(view,duration_s,delay_s,axis_s,from_s,deg_s,loop_s,cameraDistance_s,scaleZ_s,opts?.start,opts?.end) + } + public static clearAnimations(ele:UniElement|null,reset:boolean = true){ + if(ele == null) return + let view = (ele as UniElement).getAndroidView()! as View + xdAnimation.clearAnimations(view,reset) + } + +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/app-android/xdAnimation.kt b/uni_modules/x-animation-s/utssdk/app-android/xdAnimation.kt new file mode 100644 index 0000000..f8682d1 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-android/xdAnimation.kt @@ -0,0 +1,264 @@ +package uts.sdk.modules.utsXdxdAnimation + + +import android.view.View +import android.animation.ObjectAnimator +import android.animation.Animator +import android.animation.AnimatorInflater +import android.graphics.Path +import android.animation.AnimatorSet +import android.animation.AnimatorListenerAdapter +import android.animation.TimeInterpolator +import android.view.animation.LinearInterpolator +import android.animation.ValueAnimator + +class xdAnimation private constructor() { + val runningAnimators = mutableListOf() + companion object { + + // 平移动画 + fun translate( + view: View, + duration: Long = 1000, + delay: Long = 0, + translation : Int = 0, //0平行移x,1平移y,2平移x,y + fromLen:Float = 0f, + len:Float = 0f, + loop: Int = 0, + start: (() -> Unit)? = null, + end: (() -> Unit)? = null + ) { + + val animator = when (translation) { + 1 -> { // Y轴平移 + ObjectAnimator.ofFloat(view, "translationY", fromLen, len) + } + 2 -> { // XY轴同时平移 + val path = Path().apply { + moveTo(fromLen, fromLen) + lineTo(len, len) + } + ObjectAnimator.ofFloat(view, View.X, View.Y, path) + } + else -> { // X轴平移 + ObjectAnimator.ofFloat(view, "translationX", fromLen, len) + } + } + // animator.repeatMode = ObjectAnimator.RESTART + if (loop == -1) { + animator.repeatCount = ObjectAnimator.INFINITE + } else { + animator.repeatCount = loop + } + + animator.duration = duration + animator.startDelay = delay + animator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + start?.invoke() + } + + override fun onAnimationEnd(animation: Animator) { + end?.invoke() + } + }) + animator.start() + } + + // 旋转动画 + fun rotate( + view: View, + duration: Long = 1000, + delay: Long = 0, + fromDeg: Float = 0f, + deg: Float = 360f, + loop: Int = 0, + start: (() -> Unit)? = null, + end: (() -> Unit)? = null + ) { + val animator = ObjectAnimator.ofFloat(view, "rotation", fromDeg, deg) + animator.repeatMode = ObjectAnimator.RESTART + if (loop == -1) { + animator.repeatCount = ObjectAnimator.INFINITE + } else { + animator.repeatCount = loop + } + + animator.interpolator = LinearInterpolator() + animator.duration = duration + animator.startDelay = delay + animator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + start?.invoke() + } + override fun onAnimationEnd(animation: Animator) { + end?.invoke() + } + }) + animator.start() + // runningAnimators.add(animator) + } + + // 3D翻转动画 + fun flip3D( + view: View, + duration: Long = 1000, + delay: Long = 0, + axis: Int = 1, // 0: X轴, 1: Y轴 + fromDeg: Float = 0f, // 旋转角度 + deg: Float = 180f, // 旋转角度 + loop: Int = 0, + cameraDistance: Float = 8f, // 控制视角距离,默认值更合理 + scaleZ: Float = 0.8f, // 控制Z轴缩放,默认值更自然 + start: (() -> Unit)? = null, + end: (() -> Unit)? = null + ) { + view.pivotX = if (axis == 0) view.width / 2f else view.pivotX + view.pivotY = if (axis == 1) view.height / 2f else view.pivotY + + val rotateProperty = if (axis == 0) "rotationX" else "rotationY" + val rotateFrom = fromDeg + val rotateTo = deg + + val rotateAnimator = ObjectAnimator.ofFloat(view, rotateProperty, rotateFrom, rotateTo) + val scaleZAnimator = ObjectAnimator.ofFloat(view, "scale", scaleZ, scaleZ) + + rotateAnimator.repeatMode = ObjectAnimator.RESTART + if (loop == -1) { + rotateAnimator.repeatCount = ObjectAnimator.INFINITE + } else { + rotateAnimator.repeatCount = loop + } + + val animatorSet = AnimatorSet() + animatorSet.playTogether(rotateAnimator, scaleZAnimator) + animatorSet.duration = duration + animatorSet.startDelay = delay + + animatorSet.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + start?.invoke() + // 使用传入的参数控制摄像机距离 + view.cameraDistance = view.width * cameraDistance + } + + override fun onAnimationEnd(animation: Animator) { + end?.invoke() + } + }) + + animatorSet.start() + } + + /** + * 清除视图上的所有动画 + * @param view 需要清除动画的视图 + * @param reset 是否重置视图属性到初始状态 + */ + fun clearAnimations( + view: View, + reset: Boolean = true + ) { + view.animate().cancel() + view.clearAnimation() + + // 如果需要重置视图属性 + if (reset) { + // 重置所有变换 + view.translationX = 0f + view.translationY = 0f + view.scaleX = 1f + view.scaleY = 1f + view.rotation = 0f + view.rotationX = 0f + view.rotationY = 0f + view.alpha = 1f + // 重置视角距离 + view.cameraDistance = 0f + } + } + + fun scale( + view: View, + duration: Long = 1000, + delay: Long = 0, + direction: Int = 0, // 0: 水平缩放, 1: 竖直翻转,2:x,y缩放, + fromScale: Float = 0f, + scale: Float = 1f, + loop: Int = 0, + start: (() -> Unit)? = null, + end: (() -> Unit)? = null + ) { + when (direction) { + 1 -> { // Y轴缩放 + val scaleY = ObjectAnimator.ofFloat(view, "scaleY", fromScale, scale) + scaleY.duration = duration + scaleY.startDelay = delay + // scaleY.interpolator = LinearInterpolator() + if (loop == -1) { + scaleY.repeatCount = ObjectAnimator.INFINITE + } else { + scaleY.repeatCount = loop + } + scaleY.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + start?.invoke() + } + override fun onAnimationEnd(animation: Animator) { + end?.invoke() + } + }) + scaleY.start() + } + 2 -> { // XY轴同时缩放 + val scaleX = ObjectAnimator.ofFloat(view, "scaleX", fromScale, scale) + val scaleY = ObjectAnimator.ofFloat(view, "scaleY", fromScale, scale) + + // 为每个动画单独设置循环 + if (loop == -1) { + scaleX.repeatCount = ObjectAnimator.INFINITE + scaleY.repeatCount = ObjectAnimator.INFINITE + } else { + scaleX.repeatCount = loop + scaleY.repeatCount = loop + } + + val animatorSet = AnimatorSet() + animatorSet.playTogether(scaleX, scaleY) + animatorSet.duration = duration + animatorSet.startDelay = delay + // animatorSet.interpolator = LinearInterpolator() + animatorSet.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + start?.invoke() + } + override fun onAnimationEnd(animation: Animator) { + end?.invoke() + } + }) + animatorSet.start() + } + else -> { // X轴缩放 + val scaleX = ObjectAnimator.ofFloat(view, "scaleX", fromScale, scale) + // scaleX.interpolator = LinearInterpolator() + scaleX.duration = duration + scaleX.startDelay = delay + if (loop == -1) { + scaleX.repeatCount = ObjectAnimator.INFINITE + } else { + scaleX.repeatCount = loop + } + scaleX.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + start?.invoke() + } + override fun onAnimationEnd(animation: Animator) { + end?.invoke() + } + }) + scaleX.start() + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/app-harmony/index.uts b/uni_modules/x-animation-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..9058671 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-harmony/index.uts @@ -0,0 +1,55 @@ +import { XDANIMATION_FLIP3D_OPTIONS, XDANIMATION_TRANSLATE_OPTIONS, XDANIMATION_ROTATE_OPTIONS, XDANIMATION_SCALE_OPTIONS } from "../interface.uts" + +/** + * 截止 4.76 官方未提供鸿蒙下实现节点获取的方法,因此暂无法兼容鸿蒙。 + */ + +export class xAnimationS { + public static translate(opts : XDANIMATION_TRANSLATE_OPTIONS) { + if (opts.ele == null) return + // let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration ?? 1000).toLong() + let delay_s = (opts?.delay ?? 0).toLong() + let translation_s = (opts?.translation ?? 0).toInt() + let fromlen_s = (opts?.from ?? 360).toFloat() + let len_s = (opts?.len ?? 360).toFloat() + let loop_s = (opts?.loop ?? 0).toInt() + } + public static rotate(opts : XDANIMATION_ROTATE_OPTIONS) { + if (opts.ele == null) return + // let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration ?? 1000).toLong() + let delay_s = (opts?.delay ?? 0).toLong() + let from_s = (opts?.from ?? 0).toFloat() + let deg_s = (opts?.deg ?? 360).toFloat() + let loop_s = (opts?.loop ?? 0).toInt() + } + public static scale(opts : XDANIMATION_SCALE_OPTIONS) { + if (opts.ele == null) return + // let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration ?? 1000).toLong() + let delay_s = (opts?.delay ?? 0).toLong() + let direction_s = (opts?.direction ?? 2).toInt() + let scale_s = (opts?.scale ?? 1).toFloat() + let from_s = (opts?.from ?? 0).toFloat() + + let loop_s = (opts?.loop ?? 0).toInt() + } + public static flip3D(opts : XDANIMATION_FLIP3D_OPTIONS) { + if (opts.ele == null) return + // let view = (opts.ele as UniElement).getAndroidView()! as View + let duration_s = (opts?.duration ?? 1000).toLong() + let delay_s = (opts?.delay ?? 0).toLong() + let axis_s = (opts?.axis ?? 1).toInt() + let from_s = (opts?.from ?? 0).toFloat() + let deg_s = (opts?.deg ?? 360).toFloat() + let loop_s = (opts?.loop ?? 0).toInt() + let cameraDistance_s = (opts?.cameraDistance ?? 12).toFloat() + let scaleZ_s = (opts?.scaleZ ?? 0.5).toFloat() + } + public static clearAnimations(ele : UniElement | null, reset : boolean = true) { + if (ele == null) return + // let view = (ele as UniElement).getAndroidView()! as View + } + +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-animation-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-animation-s/utssdk/app-ios/config.json b/uni_modules/x-animation-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-animation-s/utssdk/app-ios/index.uts b/uni_modules/x-animation-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..625811a --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-ios/index.uts @@ -0,0 +1,110 @@ +// import UniversalBlurHelper from 'uts.sdk.modules.utsXdBlur.UniversalBlurHelper'; + +import { hexToRgb } from '../libs/color.uts' +import {XDANIMATION_FLIP3D_OPTIONS,XDANIMATION_TRANSLATE_OPTIONS,XDANIMATION_ROTATE_OPTIONS,XDANIMATION_SCALE_OPTIONS} from "../interface.uts" +import { UIView } from 'UIKit'; +import { CGFloat } from 'CoreFoundation'; +import { CABasicAnimation } from "QuartzCore"; + +export class xAnimationS { + public static translate(opts:XDANIMATION_TRANSLATE_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getIOSView()! as UIView + let duration_s = ((opts.duration==null?1000:(opts.duration!))/1000).toDouble() + let delay_s = ((opts.delay==null?0:(opts.delay!))/1000).toDouble() + let translation_s = (opts.translation==null?0:(opts.translation!)).toInt() + let from_s = new CGFloat((opts.from==null?0:(opts.from!))) + let len_s = new CGFloat(opts.len==null?0:(opts.len!)) + let loop_s = (opts.loop==null?0:(opts.loop!)).toInt() + + + xdAnimation.translate( + view=view, + duration=duration_s, + delay=delay_s, + translation=translation_s, + fromLen=from_s, + len=len_s, + loop=loop_s, + start=opts.start, + end=opts.end + ) + } + public static rotate(opts:XDANIMATION_ROTATE_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getIOSView()! as UIView + let duration_s = ((opts.duration==null?1000:(opts.duration!))/1000).toDouble() + let delay_s = ((opts.delay==null?0:(opts.delay!))/1000).toDouble() + let from_s = new CGFloat((opts.from==null?0:(opts.from!))) + let deg_s = new CGFloat(opts.deg==null?360:(opts.deg!)) + let loop_s = (opts.loop==null?0:(opts.loop!)).toInt() + + xdAnimation.rotate( + view=view, + duration=duration_s, + delay=delay_s, + fromDeg=from_s, + deg=deg_s, + loop=loop_s, + start=opts.start, + end=opts.end + ) + } + public static scale(opts:XDANIMATION_SCALE_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getIOSView()! as UIView + let duration_s = ((opts.duration==null?1000:(opts.duration!))/1000).toDouble() + let delay_s = ((opts.delay==null?0:(opts.delay!))/1000).toDouble() + let direction_s = (opts.direction==null?2:(opts.direction!)).toInt() + let from_s = new CGFloat((opts.from==null?0:(opts.from!))) + let scale_s = new CGFloat(opts.scale==null?1:(opts.scale!)) + let loop_s = (opts.loop==null?0:(opts.loop!)).toInt() + + xdAnimation.scale( + view=view, + duration=duration_s, + delay=delay_s, + direction = direction_s, + fromScale=from_s, + scale=scale_s, + loop=loop_s, + start=opts.start, + end=opts.end + ) + + } + public static flip3D(opts:XDANIMATION_FLIP3D_OPTIONS){ + if(opts.ele == null) return + let view = (opts.ele as UniElement).getIOSView()! as UIView + let duration_s = ((opts.duration==null?1000:(opts.duration!))/1000).toDouble() + let delay_s = ((opts.delay==null?0:(opts.delay!))/1000).toDouble() + let axis_s = (opts.axis==null?1:(opts.axis!)).toInt() + let from_s = new CGFloat((opts.from==null?0:(opts.from!))) + let deg_s = new CGFloat(opts.deg==null?360:(opts.deg!)) + let cameraDistance_s = new CGFloat((opts.cameraDistance==null?12:(opts.cameraDistance!))) + let scaleZ_s = new CGFloat(opts.scaleZ==null?0.5:(opts.scaleZ!)) + let loop_s = (opts.loop==null?0:(opts.loop!)).toInt() + + + xdAnimation.flip3D( + view=view, + duration=duration_s, + delay=delay_s, + axis = axis_s, + fromDeg=from_s, + deg=deg_s, + loop=loop_s, + cameraDistance=cameraDistance_s, + scaleZ=scaleZ_s, + start=opts.start, + end=opts.end + ) + + } + public static clearAnimations(ele:UniElement|null,reset:boolean = true){ + if(ele == null) return + let view = (ele as UniElement).getIOSView()! as UIView + // xdAnimation.clearAnimations(view,reset) + } + +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/app-ios/xdAnimation.swift b/uni_modules/x-animation-s/utssdk/app-ios/xdAnimation.swift new file mode 100644 index 0000000..9486050 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/app-ios/xdAnimation.swift @@ -0,0 +1,307 @@ +import UIKit +import QuartzCore + +// 动画代理类,用于回调 +class AnimationDelegate: NSObject, CAAnimationDelegate { + var start: (() -> Void)? + var end: (() -> Void)? + + init(start: (() -> Void)?, end: (() -> Void)?) { + self.start = start + self.end = end + } + + func animationDidStart(_ anim: CAAnimation) { + start?() + } + + func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { + end?() + } +} + +// 扩展CGFloat以支持角度到弧度的转换 +extension CGFloat { + func toRadians() -> CGFloat { + return self * .pi / 180.0 + } +} + +class xdAnimation { + // 平移动画 + static func translate( + view: UIView, + duration: TimeInterval = 1.0, + delay: TimeInterval = 0, + translation: Int = 0, // 0平行移x,1平移y,2平移x,y + fromLen: CGFloat = 0, + len: CGFloat = 0, + loop: Int = 0, + start: (() -> Void)? = nil, + end: (() -> Void)? = nil + ) { + let timingFunction: CAMediaTimingFunction = CAMediaTimingFunction(name: .easeInEaseOut) + // 创建动画 + let animation: CAPropertyAnimation + + switch translation { + case 1: // Y轴平移 + let basicAnimation = CABasicAnimation(keyPath: "transform.translation.y") + basicAnimation.fromValue = fromLen + basicAnimation.toValue = len + animation = basicAnimation + + case 2: // XY轴同时平移 + let keyframeAnimation = CAKeyframeAnimation(keyPath: "position") + let path = CGMutablePath() + let startPoint = CGPoint(x: view.frame.origin.x + fromLen, y: view.frame.origin.y + fromLen) + let endPoint = CGPoint(x: view.frame.origin.x + len, y: view.frame.origin.y + len) + path.move(to: startPoint) + path.addLine(to: endPoint) + keyframeAnimation.path = path + animation = keyframeAnimation + + default: // X轴平移 + let basicAnimation = CABasicAnimation(keyPath: "transform.translation.x") + basicAnimation.fromValue = fromLen + basicAnimation.toValue = len + animation = basicAnimation + } + + // 设置基本属性 + animation.duration = duration + animation.beginTime = CACurrentMediaTime() + delay + animation.timingFunction = timingFunction // 设置时间曲线 + animation.isRemovedOnCompletion = false // 动画结束后不要移除 + animation.fillMode = .forwards // 保持动画最后一帧 + + // 设置循环 + if loop == -1 { + animation.repeatCount = .infinity + } else { + animation.repeatCount = Float(loop) + } + + // 添加动画 + CATransaction.begin() + CATransaction.setCompletionBlock { + end?() + } + start?() + view.layer.add(animation, forKey: "translation") + CATransaction.commit() + } + + static func rotate(view: UIView, + duration: TimeInterval = 1.0, + delay: TimeInterval = 0.0, + fromDeg: CGFloat = 0.0, + deg: CGFloat = 360.0, + loop: Int = 0, + start: (() -> Void)? = nil, + end: (() -> Void)? = nil) { + + // 创建旋转动画 + let timingFunction: CAMediaTimingFunction = CAMediaTimingFunction(name: .linear) + let rotation = CABasicAnimation(keyPath: "transform.rotation") + rotation.fromValue = fromDeg * .pi / 180.0 // 将度数转为弧度 + rotation.toValue = deg * .pi / 180.0 // 将度数转为弧度 + rotation.duration = duration + rotation.beginTime = CACurrentMediaTime() + delay + rotation.isCumulative = true + rotation.timingFunction = timingFunction // 设置时间曲线 + rotation.isRemovedOnCompletion = false // 动画结束后不要移除 + rotation.fillMode = .forwards // 保持动画最后一帧 + + // 设置循环次数 + if loop == -1 { + rotation.repeatCount = .infinity + } else { + rotation.repeatCount = Float(loop) + } + + // 开始时的回调 + if let startAction = start { + DispatchQueue.main.asyncAfter(deadline: .now() + delay) { + startAction() + } + } + + // 使用 CATransaction 来处理动画完成后的回调 + CATransaction.begin() + + // 设置动画完成时的回调 + CATransaction.setCompletionBlock { + end?() + } + + // 添加动画到视图的层上 + view.layer.add(rotation, forKey: "rotationAnimation") + + // 提交事务 + CATransaction.commit() + } + + // 缩放动画 + static func scale(view: UIView, + duration: TimeInterval = 1.0, + delay: TimeInterval = 0.0, + direction: Int = 0, + fromScale: CGFloat = 0.0, + scale: CGFloat = 1.0, + loop: Int = 0, + start: (() -> Void)? = nil, + end: (() -> Void)? = nil) { + + // 创建动画集合 + var scaleAnimations = [CABasicAnimation]() + + switch direction { + case 1: // 竖直缩放 (Y轴) + let scaleY = CABasicAnimation(keyPath: "transform.scale.y") + scaleY.fromValue = fromScale + scaleY.toValue = scale + scaleAnimations = [scaleY] + + case 2: // XY轴同时缩放 + let scaleX = CABasicAnimation(keyPath: "transform.scale.x") + scaleX.fromValue = fromScale + scaleX.toValue = scale + + let scaleY = CABasicAnimation(keyPath: "transform.scale.y") + scaleY.fromValue = fromScale + scaleY.toValue = scale + + scaleAnimations = [scaleX, scaleY] + + default: // 水平缩放 (X轴) + let scaleX = CABasicAnimation(keyPath: "transform.scale.x") + scaleX.fromValue = fromScale + scaleX.toValue = scale + scaleAnimations = [scaleX] + } + + // 设置动画属性 + for animation in scaleAnimations { + animation.duration = duration + animation.beginTime = CACurrentMediaTime() + delay + animation.isCumulative = true + animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) // 设置时间曲线 + animation.isRemovedOnCompletion = false // 动画结束后不要移除 + animation.fillMode = .forwards // 保持动画最后一帧 + + if loop == -1 { + animation.repeatCount = .infinity + } else { + animation.repeatCount = Float(loop) + } + + } + + // 使用 CATransaction 来管理动画的开始和结束 + CATransaction.begin() + + // 动画开始时的回调 + if let startAction = start { + DispatchQueue.main.asyncAfter(deadline: .now() + delay) { + startAction() + } + } + + // 设置动画完成时的回调 + CATransaction.setCompletionBlock { + end?() + } + + // 添加动画到视图的层上 + var i=0 + for animation in scaleAnimations { + view.layer.add(animation, forKey: "scaleAnimation"+i.toString()) + i+=1; + } + + // 提交事务 + CATransaction.commit() + } + private func deg2rad(_ degree: CGFloat) -> CGFloat { + return degree * .pi / 180 + } + + // 3D翻转动画 + static func flip3D( + view: UIView, + duration: TimeInterval = 1.0, + delay: TimeInterval = 0.0, + axis: Int = 1, + fromDeg: CGFloat = 0.0, // 旋转角度 + deg: CGFloat = 180.0, // 旋转角度 + loop: Int = 0, + cameraDistance: CGFloat = 8.0, + scaleZ: CGFloat = 0.8, + start: (() -> Void)? = nil, + end: (() -> Void)? = nil) { + + let adjustedDeg: CGFloat = deg + // 设置3D透视效果 + var transform = CATransform3DIdentity + transform.m34 = -1.0 / cameraDistance + view.layer.transform = transform + + // 根据旋转轴选择旋转方式 + var rotationTransform: CATransform3D + if axis == 1 { // 绕Y轴旋转 + rotationTransform = CATransform3DMakeRotation(fromDeg.toRadians(), 0, 1, 0) + } else { // 绕X轴旋转 + rotationTransform = CATransform3DMakeRotation(fromDeg.toRadians(), 1, 0, 0) + } + + // 设置初始角度 + view.layer.transform = rotationTransform + + // 执行动画 + UIView.animate( + withDuration: duration, + delay: delay, + options: [.curveLinear], + animations: { + start?() // 执行开始时的回调 + // 计算目标角度 + let finalTransform: CATransform3D + if axis == 1 { // 绕Y轴旋转 + finalTransform = CATransform3DMakeRotation(adjustedDeg.toRadians(), 0, 1, 0) + } else { // 绕X轴旋转 + finalTransform = CATransform3DMakeRotation(adjustedDeg.toRadians(), 1, 0, 0) + } + + // 添加Z轴缩放效果 + let scaleTransform = CATransform3DScale(finalTransform, 1, 1, scaleZ) + view.layer.transform = scaleTransform + }, + completion: { finished in + if loop > 1 { + // 如果需要循环,递归调用 + flip3D( + view: view, + duration: duration, + delay: delay, + axis: axis, + fromDeg: adjustedDeg, + deg: fromDeg, + loop: loop - 1, + cameraDistance: cameraDistance, + scaleZ: scaleZ, + start: start, + end: end + ) + } else { + end?() // 执行结束时的回调 + } + } + ) + } + + + + + +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/interface.uts b/uni_modules/x-animation-s/utssdk/interface.uts new file mode 100644 index 0000000..f689971 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/interface.uts @@ -0,0 +1,83 @@ +export type XDANIMATION_TRANSLATE_OPTIONS = { + /** 播放元素 */ + ele : UniElement|null, + /** 播放时间 */ + duration?: number, + /** 延迟 */ + delay?: number, + /** 0平行移x,1平移y,2平移x,y */ + translation?: number, + /** 起始位置 */ + from?: number, + /** 移动的距离 */ + len?: number, + /** 播放次数,-1循环永久播放,0表示1次,依次类推 */ + loop?: number, + /** 开始回调 */ + start?: (() => void)|null, + /** 结束回调 */ + end?: (() => void) +} + +export type XDANIMATION_ROTATE_OPTIONS = { + /** 播放元素 */ + ele : UniElement|null, + /** 播放时间 */ + duration?: number, + /** 延迟 */ + delay?: number, + /** 起始角度,默认是0 */ + from?: number, + /** 旋转的角度 */ + deg?: number, + /** 播放次数,-1循环永久播放,0表示1次,依次类推 */ + loop?: number, + /** 开始回调 */ + start?: (() => void)|null, + /** 结束回调 */ + end?: (() => void) +} +export type XDANIMATION_SCALE_OPTIONS = { + /** 播放元素 */ + ele : UniElement|null, + /** 播放时间 */ + duration?: number, + /** 延迟 */ + delay?: number, + /** 0缩放x,1缩放y,2缩放x,y */ + direction?: number, + /** 缩放起始值,默认是0 */ + from?:number, + /** 缩放的值 */ + scale?: number, + /** 播放次数,-1循环永久播放,0表示1次,依次类推 */ + loop?: number, + /** 开始回调 */ + start?: (() => void)|null, + /** 结束回调 */ + end?: (() => void) +} +export type XDANIMATION_FLIP3D_OPTIONS = { + /** 播放元素 */ + ele : UniElement|null, + /** 播放时间 */ + duration?: number, + /** 延迟 */ + delay?: number, + /** 0: X轴, 1: Y轴 */ + axis?: number, + /** 起始角度,默认是0 */ + from?: number, + /** 旋转角度 */ + deg?: number, + /** 播放次数,-1循环永久播放,0表示1次,依次类推 */ + loop?: number, + /** 视角距离 */ + cameraDistance?: number, + /** Z轴缩放 */ + scaleZ?: number, + /** 开始回调 */ + start?: (() => void)|null, + /** 结束回调 */ + end?: (() => void) +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/libs/color.uts b/uni_modules/x-animation-s/utssdk/libs/color.uts new file mode 100644 index 0000000..e4e51a9 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/libs/color.uts @@ -0,0 +1,65 @@ +type RGBA = { r : number, g : number, b : number, a : number } +export function hexToRgb(sColors : string) : RGBA | null { + if (sColors == "") { + return { r: 0, g: 0, b: 0, a: 0 } as RGBA + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + + let p : number[] = arr.map((val : string) : number => parseInt(val)); + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + arr.push('1') + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: parseFloat(arr[3]) + } as RGBA + } else { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + + return null; +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/mp-weixin/index.uts b/uni_modules/x-animation-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..77105c6 --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,60 @@ +import { hexToRgb } from '../libs/color.uts' +import { xdAnimation } from './xdAnimation.uts'; +export { XDANIMATION_FLIP3D_OPTIONS, XDANIMATION_TRANSLATE_OPTIONS, XDANIMATION_ROTATE_OPTIONS, XDANIMATION_SCALE_OPTIONS } from "../interface.uts" + + +export class xAnimationS { + public static translate(opts : XDANIMATION_TRANSLATE_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let translation_s = (opts?.translation ?? 0) + let fromlen_s = (opts?.from ?? 360) + let len_s = (opts?.len ?? 360) + let loop_s = (opts?.loop ?? 0) + console.log(view) + xdAnimation.translate(view, duration_s, delay_s, translation_s, fromlen_s, len_s, loop_s, opts?.start, opts?.end) + } + public static rotate(opts : XDANIMATION_ROTATE_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let from_s = (opts?.from ?? 0) + let deg_s = (opts?.deg ?? 360) + let loop_s = (opts?.loop ?? 0) + xdAnimation.rotate(view, duration_s, delay_s, from_s, deg_s, loop_s, opts?.start, opts?.end) + } + public static scale(opts : XDANIMATION_SCALE_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let direction_s = (opts?.direction ?? 2) + let scale_s = (opts?.scale ?? 1) + let from_s = (opts?.from ?? 0) + + let loop_s = (opts?.loop ?? 0) + xdAnimation.scale(view, duration_s, delay_s, direction_s, from_s, scale_s, loop_s, opts?.start, opts?.end) + } + public static flip3D(opts : XDANIMATION_FLIP3D_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let axis_s = (opts?.axis ?? 1) + let from_s = (opts?.from ?? 0) + let deg_s = (opts?.deg ?? 360) + let loop_s = (opts?.loop ?? 0) + let cameraDistance_s = (opts?.cameraDistance ?? 12) + let scaleZ_s = (opts?.scaleZ ?? 0.5) + xdAnimation.flip3D(view, duration_s, delay_s, axis_s, from_s, deg_s, loop_s, cameraDistance_s, scaleZ_s, opts?.start, opts?.end) + } + public static clearAnimations(ele : UniElement | null, reset : boolean = true) { + if (ele == null) return + let view = ele as HTMLElement + xdAnimation.clearAnimations(view,reset) + } + +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/mp-weixin/xdAnimation.uts b/uni_modules/x-animation-s/utssdk/mp-weixin/xdAnimation.uts new file mode 100644 index 0000000..ec74b5a --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/mp-weixin/xdAnimation.uts @@ -0,0 +1,256 @@ +let tid = 25 +export class xdAnimation { + + public static translate( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + translation : number = 0, //0平行移x,1平移y,2平移x,y + fromLen : number = 0, // 起始位置 + len : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + // 设置初始位置 + if (translation === 0) { + view.style.transform = `translateX(${fromLen}px)`; + + } else if (translation === 1) { + view.style.transform = `translateY(${fromLen}px)`; + } else if (translation === 2) { + view.style.transform = `translate(${fromLen}px, ${fromLen}px)`; + } + + function starttras() { + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + if (translation === 0) { + console.log(fromLen, len) + view.style.transform = `translateX(${len}px)`; + } else if (translation === 1) { + view.style.transform = `translateY(${len}px)`; + } else if (translation === 2) { + view.style.transform = `translate(${len}px, ${len}px)`; + } + + // 动画开始回调 + if (start) start(); + } + // 设置动画结束后的位置 + if (delay == 0) { + setTimeout(() => { + starttras() + }, 50); + } else { + setTimeout(() => { + starttras() + }, duration); + } + let _this = this; + // 动画结束后的处理 + clearTimeout(tid) + tid = setTimeout(function() { + if (loop === -1) { + // 永久循环 + _this.translate(view, duration, delay, translation, fromLen, len, loop, start, end); + } else if (loop > 0) { + // 有限循环 + _this.translate(view, duration, delay, translation, fromLen, len, loop - 1, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, duration); + + } + + public static scale( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + direction : number = 0, // 0: 水平缩放, 1: 竖直翻转,2:x,y缩放, + fromScale : number = 0, // 起始位置 + scale : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + // 设置初始位置 + function setValue(value : number) { + if (direction === 0) { + view.style.transform = `scaleX(${value})`; + + } else if (direction === 1) { + view.style.transform = `scaleY(${value})`; + } else if (direction === 2) { + view.style.transform = `scale(${value}, ${value})`; + } + } + setValue(fromScale) + function starttras() { + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + setValue(scale) + // 动画开始回调 + if (start) start(); + } + // 设置动画结束后的位置 + if (delay == 0) { + setTimeout(() => { + starttras() + }, 50); + } else { + setTimeout(() => { + starttras() + }, delay); + } + let _this = this; + // 动画结束后的处理 + + clearTimeout(tid) + tid = setTimeout(function() { + if (loop === -1) { + // 永久循环 + _this.scale(view, duration, delay, direction, fromScale, scale, loop, start, end); + } else if (loop > 0) { + // 有限循环 + _this.scale(view, duration, delay, direction, fromScale, scale, loop - 1, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, duration); + + } + + public static rotate( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + fromDeg : number = 0, // 起始位置 + deg : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + // 设置初始位置 + function setValue(value : number) { + view.style.transform = `rotate(${value}deg)`; + } + setValue(fromDeg) + function starttras() { + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + setValue(deg) + // 动画开始回调 + if (start) start(); + } + // 设置动画结束后的位置 + if (delay == 0) { + setTimeout(() => { + starttras() + }, 50); + } else { + setTimeout(() => { + starttras() + }, delay); + } + let _this = this; + + clearTimeout(tid) + tid = setTimeout(function() { + if (loop === -1) { + // 永久循环 + _this.rotate(view, duration, delay, fromDeg, deg, loop, start, end); + } else if (loop > 0) { + // 有限循环 + _this.rotate(view, duration, delay, fromDeg, deg, loop - 1, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, duration); + } + + + public static flip3D( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + axis : number = 1, // 0: X轴, 1: Y轴 + fromDeg : number = 0, // 起始位置 + deg : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + cameraDistance : number = 8, // 控制视角距离,默认值更合理 + scaleZ : number = 0.8, // 控制Z轴缩放,默认值更自然 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + // 设置透视视角 + view.style.perspective = `${cameraDistance}px`; + view.style.transformStyle = "preserve-3d"; + // 设置动画延迟 + view.style.transitionDelay = `${0}ms`; + + // 设置动画持续时间 + view.style.transitionDuration = `${0}ms`; + // 设置初始角度 + function setValue(value : number) { + if (axis === 0) { + view.style.transform = `rotateX(${value}deg) scaleZ(${scaleZ})`; + } else if (axis === 1) { + view.style.transform = `rotateY(${value}deg) scaleZ(${scaleZ})`; + } + } + + setValue(fromDeg) + + // 设置动画结束后的角度 + setTimeout(() => { + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + setValue(deg) + // 动画开始回调 + if (start) start(); + }, delay || 50); + + let _this = this; + + clearTimeout(tid) + tid = setTimeout(function() { + if (loop === -1) { + // 永久循环 + _this.flip3D(view, duration, delay, axis, fromDeg, deg, loop, cameraDistance, scaleZ, start, end); + } else if (loop > 0) { + // 有限循环 + _this.flip3D(view, duration, delay, axis, fromDeg, deg, loop - 1, cameraDistance, scaleZ, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, duration); + + } + public static clearAnimations(view : HTMLElement, _ : boolean = true) { + view.style.removeProperty('transform') + view.style.removeProperty('transition-delay') + view.style.removeProperty('transition-duration') + } +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/unierror.uts b/uni_modules/x-animation-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-animation-s/utssdk/web/index.uts b/uni_modules/x-animation-s/utssdk/web/index.uts new file mode 100644 index 0000000..d9c818e --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/web/index.uts @@ -0,0 +1,59 @@ +import { hexToRgb } from '../libs/color.uts' +import { xdAnimation } from './xdAnimation.uts'; +export { XDANIMATION_FLIP3D_OPTIONS, XDANIMATION_TRANSLATE_OPTIONS, XDANIMATION_ROTATE_OPTIONS, XDANIMATION_SCALE_OPTIONS } from "../interface.uts" + + +export class xAnimationS { + public static translate(opts : XDANIMATION_TRANSLATE_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let translation_s = (opts?.translation ?? 0) + let fromlen_s = (opts?.from ?? 360) + let len_s = (opts?.len ?? 360) + let loop_s = (opts?.loop ?? 0) + xdAnimation.translate(view, duration_s, delay_s, translation_s, fromlen_s, len_s, loop_s, opts?.start, opts?.end) + } + public static rotate(opts : XDANIMATION_ROTATE_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let from_s = (opts?.from ?? 0) + let deg_s = (opts?.deg ?? 360) + let loop_s = (opts?.loop ?? 0) + xdAnimation.rotate(view, duration_s, delay_s, from_s, deg_s, loop_s, opts?.start, opts?.end) + } + public static scale(opts : XDANIMATION_SCALE_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let direction_s = (opts?.direction ?? 2) + let scale_s = (opts?.scale ?? 1) + let from_s = (opts?.from ?? 0) + + let loop_s = (opts?.loop ?? 0) + xdAnimation.scale(view, duration_s, delay_s, direction_s, from_s, scale_s, loop_s, opts?.start, opts?.end) + } + public static flip3D(opts : XDANIMATION_FLIP3D_OPTIONS) { + if (opts.ele == null) return + let view = opts.ele as HTMLElement + let duration_s = (opts?.duration ?? 1000) + let delay_s = (opts?.delay ?? 0) + let axis_s = (opts?.axis ?? 1) + let from_s = (opts?.from ?? 0) + let deg_s = (opts?.deg ?? 360) + let loop_s = (opts?.loop ?? 0) + let cameraDistance_s = (opts?.cameraDistance ?? 12) + let scaleZ_s = (opts?.scaleZ ?? 0.5) + xdAnimation.flip3D(view, duration_s, delay_s, axis_s, from_s, deg_s, loop_s, cameraDistance_s, scaleZ_s, opts?.start, opts?.end) + } + public static clearAnimations(ele : UniElement | null, reset : boolean = true) { + if (ele == null) return + let view = ele as HTMLElement + xdAnimation.clearAnimations(view,reset) + } + +} \ No newline at end of file diff --git a/uni_modules/x-animation-s/utssdk/web/xdAnimation.uts b/uni_modules/x-animation-s/utssdk/web/xdAnimation.uts new file mode 100644 index 0000000..c138b2b --- /dev/null +++ b/uni_modules/x-animation-s/utssdk/web/xdAnimation.uts @@ -0,0 +1,251 @@ +export class xdAnimation { + public static translate( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + translation : number = 0, //0平行移x,1平移y,2平移x,y + fromLen : number = 0, // 起始位置 + len : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + view.style.transitionTimingFunction = 'linear' + // 设置初始位置 + if (translation === 0) { + view.style.transform = `translateX(${fromLen}px)`; + + } else if (translation === 1) { + view.style.transform = `translateY(${fromLen}px)`; + } else if (translation === 2) { + view.style.transform = `translate(${fromLen}px, ${fromLen}px)`; + } + + function starttras() { + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + if (translation === 0) { + console.log(fromLen, len) + view.style.transform = `translateX(${len}px)`; + } else if (translation === 1) { + view.style.transform = `translateY(${len}px)`; + } else if (translation === 2) { + view.style.transform = `translate(${len}px, ${len}px)`; + } + + // 动画开始回调 + if (start) start(); + } + // 设置动画结束后的位置 + if (delay == 0) { + setTimeout(() => { + starttras() + }, 50); + } else { + setTimeout(() => { + starttras() + }, delay); + } + let _this = this; + // 动画结束后的处理 + view.addEventListener('transitionend', () => { + if (loop === -1) { + // 永久循环 + _this.translate(view, duration, delay, translation, fromLen, len, loop, start, end); + } else if (loop > 0) { + // 有限循环 + _this.translate(view, duration, delay, translation, fromLen, len, loop - 1, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, { once: true }); + } + + public static scale( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + direction : number = 0, // 0: 水平缩放, 1: 竖直翻转,2:x,y缩放, + fromScale : number = 0, // 起始位置 + scale : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + view.style.transitionTimingFunction = 'linear' + // 设置初始位置 + function setValue(value : number) { + if (direction === 0) { + view.style.transform = `scaleX(${value})`; + + } else if (direction === 1) { + view.style.transform = `scaleY(${value})`; + } else if (direction === 2) { + view.style.transform = `scale(${value}, ${value})`; + } + } + setValue(fromScale) + function starttras() { + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + setValue(scale) + // 动画开始回调 + if (start) start(); + } + // 设置动画结束后的位置 + if (delay == 0) { + setTimeout(() => { + starttras() + }, 50); + } else { + setTimeout(() => { + starttras() + }, delay); + } + let _this = this; + // 动画结束后的处理 + view.addEventListener('transitionend', () => { + if (loop === -1) { + // 永久循环 + _this.scale(view, duration, delay, direction, fromScale, scale, loop, start, end); + } else if (loop > 0) { + // 有限循环 + _this.scale(view, duration, delay, direction, fromScale, scale, loop - 1, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, { once: true }); + } + + public static rotate( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + fromDeg : number = 0, // 起始位置 + deg : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + view.style.transitionTimingFunction = 'linear' + // 设置初始位置 + function setValue(value : number) { + view.style.transform = `rotate(${value}deg)`; + } + setValue(fromDeg) + function starttras() { + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + view.style.transitionTimingFunction = 'linear' + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + setValue(deg) + // 动画开始回调 + if (start) start(); + } + // 设置动画结束后的位置 + if (delay == 0) { + setTimeout(() => { + starttras() + }, 50); + } else { + setTimeout(() => { + starttras() + }, delay); + } + let _this = this; + // 动画结束后的处理 + view.addEventListener('transitionend', () => { + if (loop === -1) { + // 永久循环 + _this.rotate(view, duration, delay, fromDeg, deg, loop, start, end); + } else if (loop > 0) { + // 有限循环 + _this.rotate(view, duration, delay, fromDeg, deg, loop - 1, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, { once: true }); + } + + + public static flip3D( + view : HTMLElement, + duration : number = 1000, + delay : number = 0, + axis : number = 1, // 0: X轴, 1: Y轴 + fromDeg : number = 0, // 起始位置 + deg : number = 0, // 移动的距离 + loop : number = 0,//-1永久播放动画,0循环1次,依次类推 + cameraDistance : number = 8, // 控制视角距离,默认值更合理 + scaleZ : number = 0.8, // 控制Z轴缩放,默认值更自然 + start : (() => void) | null = null, + end : (() => void) | null = null + ) { + view.style.transitionDuration = `${0}ms`; + view.style.transitionDelay = `${0}ms`; + view.style.transitionTimingFunction = 'linear' + // 设置透视视角 + view.style.perspective = `${cameraDistance}px`; + view.style.transformStyle = "preserve-3d"; + // 设置动画延迟 + view.style.transitionDelay = `${0}ms`; + + // 设置动画持续时间 + view.style.transitionDuration = `${0}ms`; + // 设置初始角度 + function setValue(value : number) { + if (axis === 0) { + view.style.transform = `rotateX(${value}deg) scaleZ(${scaleZ})`; + } else if (axis === 1) { + view.style.transform = `rotateY(${value}deg) scaleZ(${scaleZ})`; + } + } + + setValue(fromDeg) + + // 设置动画结束后的角度 + setTimeout(() => { + // 设置动画延迟 + view.style.transitionDelay = `${delay}ms`; + // 设置动画持续时间 + view.style.transitionDuration = `${duration}ms`; + setValue(deg) + // 动画开始回调 + if (start) start(); + }, delay || 50); + + let _this = this; + // 动画结束后的处理 + view.addEventListener('transitionend', () => { + if (loop === -1) { + // 永久循环 + _this.flip3D(view, duration, delay, axis, fromDeg, deg, loop, cameraDistance, scaleZ, start, end); + } else if (loop > 0) { + // 有限循环 + _this.flip3D(view, duration, delay, axis, fromDeg, deg, loop - 1, cameraDistance, scaleZ, start, end); + } else { + // 动画结束回调 + if (end) end(); + } + }, { once: true }); + } + public static clearAnimations(view : HTMLElement, _ : boolean = true) { + view.style.removeProperty('transform') + view.style.removeProperty('transition-delay') + view.style.removeProperty('transition-duration') + } +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/changelog.md b/uni_modules/x-base642file-s/changelog.md new file mode 100644 index 0000000..5084f59 --- /dev/null +++ b/uni_modules/x-base642file-s/changelog.md @@ -0,0 +1,6 @@ +## 1.0.2(2025-07-25) +* 兼容原生鸿蒙 +## 1.0.1(2025-02-10) +* 兼容所有平台 +## 1.0.0(2024-11-21) +* 将base64对象转换为图片文件PNG格式 \ No newline at end of file diff --git a/uni_modules/x-base642file-s/package.json b/uni_modules/x-base642file-s/package.json new file mode 100644 index 0000000..02a9ffb --- /dev/null +++ b/uni_modules/x-base642file-s/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-base642file-s", + "displayName": "x-base642file-s", + "version": "1.0.0", + "description": "x-base642file-s", + "keywords": [ + "x-base642file-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/readme.md b/uni_modules/x-base642file-s/readme.md new file mode 100644 index 0000000..b00aa2d --- /dev/null +++ b/uni_modules/x-base642file-s/readme.md @@ -0,0 +1,57 @@ +# x-base642file-s + +### 功能介绍 + +将Base64格式的图片数据转换为本地PNG文件,支持跨平台使用。 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### API文档 + +#### toPngFile + +`toPngFile(data: string): Promise` +将Base64格式的图片数据转换为本地PNG文件。 + +**参数说明:** +- data: Base64格式的图片数据字符串,支持带前缀(如:data:image/png;base64,)或纯Base64字符串 + +**返回值:** +- `Promise`: 返回生成的PNG文件路径 + - 成功:resolve(文件路径) + - 失败:reject(空字符串) + +### 平台差异说明 + +- Android:文件保存在应用的外部缓存目录 +- iOS:文件保存在应用的缓存目录 +- Web:返回Blob URL +- 小程序:文件保存在小程序用户目录 + +### 使用示例 + +```ts + +import { toPngFile } from "@/uni_modules/x-base642file-s" + +// 示例:将Base64图片转换为本地文件 +const convertToFile = async (base64Data: string) => { + try { + const filePath = await toPngFile(base64Data) + console.log('文件保存成功:', filePath) + } catch (error) { + console.error('转换失败') + } +} +``` + +### 注意事项 + +1. 使用前,Windows用户需要先在页面引用,打基座,再编译使用 +2. Mac用户可直接引用使用 +3. 建议在处理大量数据时进行适当的性能优化 +4. 生成的文件会保存在各平台对应的缓存目录中,请注意及时清理不需要的文件 \ No newline at end of file diff --git a/uni_modules/x-base642file-s/utssdk/app-android/config.json b/uni_modules/x-base642file-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/utssdk/app-android/index.uts b/uni_modules/x-base642file-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..98826db --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/app-android/index.uts @@ -0,0 +1,33 @@ +import Context from "android.content.Context" +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Base64 from "android.util.Base64" +import File from "java.io.File" +import FileOutputStream from "java.io.FileOutputStream" + +export function toPngFile(data : string) : Promise { + let fileName = Math.random().toString(16).substring(2, 16) + let baesestrAr = data.split(',') as string[] + let base64Data = baesestrAr[1] + let fileUrl = '' + + try { + let context = UTSAndroid.getAppContext()! + let filepath = context.getExternalCacheDir()?.getPath() ?? "" + // 解码Base64字符串 + let decodedBytes = Base64.decode(base64Data, Base64.DEFAULT) + let bitmap = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.size) + let file = new File(filepath, fileName + '.png'); + + let fos = new FileOutputStream(file) + bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); + fileUrl = file.getPath(); + + } catch (error) { + console.error('处理图片错误:', error) + //TODO handle the exception + return Promise.reject(fileUrl) as Promise + } + + return Promise.resolve(fileUrl) +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/utssdk/app-harmony/config.json b/uni_modules/x-base642file-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..6df5a0e --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_library_s": "./lib/x_library_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/utssdk/app-harmony/index.uts b/uni_modules/x-base642file-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..b654f5d --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/app-harmony/index.uts @@ -0,0 +1,14 @@ +import { x_toPngFile } from "x_library_s"; +import { BusinessError } from "@kit.BasicServicesKit"; + +export function toPngFile(data : string) : Promise { + try { + const file = x_toPngFile(UTSHarmony.getCurrentWindow()!.getUIContext(),data) + return Promise.resolve(file); + } catch (error) { + const e = error as BusinessError; + console.error("TMUI",e.message) + return Promise.reject(e.message); + } + +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/utssdk/app-harmony/lib/x_library_s.har b/uni_modules/x-base642file-s/utssdk/app-harmony/lib/x_library_s.har new file mode 100644 index 0000000..192275e Binary files /dev/null and b/uni_modules/x-base642file-s/utssdk/app-harmony/lib/x_library_s.har differ diff --git a/uni_modules/x-base642file-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-base642file-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-base642file-s/utssdk/app-ios/config.json b/uni_modules/x-base642file-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-base642file-s/utssdk/app-ios/index.uts b/uni_modules/x-base642file-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..c82dc52 --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/app-ios/index.uts @@ -0,0 +1,19 @@ +import { Data } from 'Foundation'; +import { UIImage } from 'UIKit'; +export function toPngFile(data : string):Promise { + let fileName = Math.random().toString(16).substring(2,16) + let baesestrAr = data.split(',') as string[] + let base64Data = baesestrAr[1] + let imageData = new Data(base64Encoded = base64Data) + if(imageData==null) return Promise.reject('') as Promise + let image = new UIImage(data = imageData!) + if(image==null) return Promise.reject('') as Promise + let userDir = FileManager.default.urls(for = FileManager.SearchPathDirectory.cachesDirectory, in = FileManager.SearchPathDomainMask.userDomainMask).first! + let destinationFileName = fileName + ".png" + let fileURL = userDir.appendingPathComponent(destinationFileName) + + let isSuccess = UTSiOS.try(imageData!.write(to =fileURL),"?") + if(isSuccess==null) return Promise.reject('') as Promise + + return Promise.resolve(fileURL.path) +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/utssdk/interface.uts b/uni_modules/x-base642file-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-base642file-s/utssdk/mp-weixin/index.uts b/uni_modules/x-base642file-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..12ee73d --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,18 @@ +export function toPngFile(data : string) : Promise { + let bdataBase64 = data.split(',')[1] + let fileMg = wx.getFileSystemManager(); + let filepath = `${wx.env.USER_DATA_PATH}/${Math.random().toString(16).substring(4, 20)}.png` + return new Promise((res, rej) => { + fileMg.writeFile({ + filePath: filepath, + data: bdataBase64, + encoding: "base64", + success() { + res(filepath) + }, + faile() { + rej("") + } + }) + }) +} \ No newline at end of file diff --git a/uni_modules/x-base642file-s/utssdk/unierror.uts b/uni_modules/x-base642file-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-base642file-s/utssdk/web/index.uts b/uni_modules/x-base642file-s/utssdk/web/index.uts new file mode 100644 index 0000000..5941ec0 --- /dev/null +++ b/uni_modules/x-base642file-s/utssdk/web/index.uts @@ -0,0 +1,20 @@ +// function compressImage(quality:number) : string { +// let base64data = canvas.toDataURL('image/jpeg', attrs.compress / 100); +// return base64data; +// } +function base64ToBlob(data : string) : Blob { + let bytes = window.atob(data.split(',')[1]) + let ab = new ArrayBuffer(bytes.length) + let ia = new Uint8Array(ab) + for (let i = 0; i < bytes.length; i++) { + ia[i] = bytes.charCodeAt(i) + } + // @ts-ignore + return new Blob([ab], { type: 'image/jpeg' }) +} + +// ,quality:number +export function toPngFile(data : string) : Promise { + let bloblfaile = URL.createObjectURL(base64ToBlob(data)); + return Promise.resolve(bloblfaile); +} \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/changelog.md b/uni_modules/x-base64toarraybuff-s/changelog.md new file mode 100644 index 0000000..3e8db58 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/changelog.md @@ -0,0 +1,4 @@ +## 1.0.2(2025-07-25) +* 兼容原生鸿蒙 +## 1.0.1(2025-02-10) +* 兼容所有平台 \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/package.json b/uni_modules/x-base64toarraybuff-s/package.json new file mode 100644 index 0000000..6b83851 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-base64toarraybuff-s", + "displayName": "x-base64toarraybuff-s", + "version": "1.0.0", + "description": "x-base64toarraybuff-s", + "keywords": [ + "x-base64toarraybuff-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/readme.md b/uni_modules/x-base64toarraybuff-s/readme.md new file mode 100644 index 0000000..6b2ccb2 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/readme.md @@ -0,0 +1,61 @@ +# x-base64toarraybuff-s + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 开发文档 + +这是一个跨平台的base64和ArrayBuffer转换工具,提供了两个主要API: + +#### base64ToArrayBuffer + +将Base64字符串转换为ArrayBuffer。 + +**参数:** +- data: string - 需要转换的Base64字符串 + +**返回值:** +- ArrayBuffer - 转换后的二进制数据 + +**示例:** +```ts + +import { base64ToArrayBuffer } from "@/uni_modules/x-base64toarraybuff-s" + +const base64Str = "SGVsbG8gV29ybGQ=" +const buffer = base64ToArrayBuffer(base64Str) +``` + +#### arrayBufferToBase64 + +将ArrayBuffer转换为Base64字符串。 + +**参数:** +- data: ArrayBuffer - 需要转换的二进制数据 + +**返回值:** +- string - 转换后的Base64字符串 + +**示例:** +```ts + +import { arrayBufferToBase64 } from "@/uni_modules/x-base64toarraybuff-s" + +const buffer = new ArrayBuffer(8) +const base64Str = arrayBufferToBase64(buffer) +``` + +### 使用说明 + +1. 使用前,如果是win请先在页面引用,打基座,再编译使用 +2. 如果你是Mac用户不需要打基座,直接引用使用 +3. 如果你是加密插件用户,不管是win,mac都要打基座。 + +### 注意事项 + +1. 该插件在所有平台(iOS、Android、Web、小程序)上均可用 +2. 转换过程中会自动处理不同平台的实现差异,开发者无需关心具体实现 +3. 建议在处理大量数据时进行适当的性能优化 \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/app-android/index.uts b/uni_modules/x-base64toarraybuff-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..3b3af53 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/app-android/index.uts @@ -0,0 +1,10 @@ +import Base64 from "android.util.Base64" +import ByteBuffer from 'java.nio.ByteBuffer'; + +export const base64ToArrayBuffer = (data : string) :ArrayBuffer => { + return ArrayBuffer.fromByteBuffer(ByteBuffer.wrap(Base64.decode(data, Base64.DEFAULT))) +} + +export const arrayBufferToBase64 = (data : ArrayBuffer) : string => { + return Base64.encodeToString(data.toByteBuffer().array(),Base64.DEFAULT) +} \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/config.json b/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..6df5a0e --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_library_s": "./lib/x_library_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/index.uts b/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..92a1e85 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/index.uts @@ -0,0 +1,42 @@ +import { util } from "@kit.ArkTS"; +import { BusinessError } from "@kit.BasicServicesKit"; + +/** + * 将base64数据转换为arraybuffer + * @param data base64数据 + * @returns Promise + */ +function btoa_x(data: string): ArrayBuffer { + const base64 = new util.Base64Helper(); + const dataSplit = data.split(","); + const uint8Array = base64.decodeSync(dataSplit.length > 1 ? data.split(",")[1] : data); + const buffer: ArrayBuffer = uint8Array.buffer.slice(0, uint8Array.byteLength); + + return buffer +} + +function atob_x(data:ArrayBuffer){ + const base64 = new util.Base64Helper(); + const unit8data = new Uint8Array(data) + return base64.encodeToStringSync(unit8data) +} + +export const base64ToArrayBuffer = (data : string) :ArrayBuffer => { + try { + return btoa_x(data) + } catch (error) { + const e = error as BusinessError; + console.error("TMUI",e.message) + return new ArrayBuffer(0) + } +} + +export const arrayBufferToBase64 = (data : ArrayBuffer) : string => { + try { + return atob_x(data) + } catch (error) { + const e = error as BusinessError; + console.error("TMUI",e.message) + return '' + } +} \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/lib/x_library_s.har b/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/lib/x_library_s.har new file mode 100644 index 0000000..2afe522 Binary files /dev/null and b/uni_modules/x-base64toarraybuff-s/utssdk/app-harmony/lib/x_library_s.har differ diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/config.json b/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/index.uts b/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..2b69ed2 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/app-ios/index.uts @@ -0,0 +1,12 @@ +import { Data } from 'Foundation'; +export const base64ToArrayBuffer = (data : string) : ArrayBuffer => { + let dadx = new Data(base64Encoded = data) + if(dadx == null) return new ArrayBuffer(0) + return ArrayBuffer.fromData(dadx!) + +} + +export const arrayBufferToBase64 = (data : ArrayBuffer) : string => { + let dadx = data.toData() + return dadx.base64EncodedString() +} \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/interface.uts b/uni_modules/x-base64toarraybuff-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/mp-weixin/base64ToArraybuffer.uts b/uni_modules/x-base64toarraybuff-s/utssdk/mp-weixin/base64ToArraybuffer.uts new file mode 100644 index 0000000..2b8df45 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/mp-weixin/base64ToArraybuffer.uts @@ -0,0 +1,43 @@ + +const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +let lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256); +for (let i = 0; i < chars.length; i++) { + lookup[chars.charCodeAt(i)] = i; +} +export const encode = function (arraybuffer) { + let bytes = new Uint8Array(arraybuffer), i, len = bytes.length, base64 = ''; + for (i = 0; i < len; i += 3) { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } + if (len % 3 === 2) { + base64 = base64.substring(0, base64.length - 1) + '='; + } + else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + '=='; + } + return base64; +}; + +export const decode = function (base64) { + let bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4; + if (base64[base64.length - 1] === '=') { + bufferLength--; + if (base64[base64.length - 2] === '=') { + bufferLength--; + } + } + let arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer); + for (i = 0; i < len; i += 4) { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i + 1)]; + encoded3 = lookup[base64.charCodeAt(i + 2)]; + encoded4 = lookup[base64.charCodeAt(i + 3)]; + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); + } + return arraybuffer; +}; \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/mp-weixin/index.uts b/uni_modules/x-base64toarraybuff-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..04a73bb --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,9 @@ +import {decode,encode} from "./base64ToArraybuffer.uts" + +export const base64ToArrayBuffer = (data : string) :ArrayBuffer => { + return decode(data) +} + +export const arrayBufferToBase64 = (data : ArrayBuffer) : string => { + return encode(data) +} \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/unierror.uts b/uni_modules/x-base64toarraybuff-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/web/base64ToArraybuffer.uts b/uni_modules/x-base64toarraybuff-s/utssdk/web/base64ToArraybuffer.uts new file mode 100644 index 0000000..2b8df45 --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/web/base64ToArraybuffer.uts @@ -0,0 +1,43 @@ + +const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +let lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256); +for (let i = 0; i < chars.length; i++) { + lookup[chars.charCodeAt(i)] = i; +} +export const encode = function (arraybuffer) { + let bytes = new Uint8Array(arraybuffer), i, len = bytes.length, base64 = ''; + for (i = 0; i < len; i += 3) { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } + if (len % 3 === 2) { + base64 = base64.substring(0, base64.length - 1) + '='; + } + else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + '=='; + } + return base64; +}; + +export const decode = function (base64) { + let bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4; + if (base64[base64.length - 1] === '=') { + bufferLength--; + if (base64[base64.length - 2] === '=') { + bufferLength--; + } + } + let arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer); + for (i = 0; i < len; i += 4) { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i + 1)]; + encoded3 = lookup[base64.charCodeAt(i + 2)]; + encoded4 = lookup[base64.charCodeAt(i + 3)]; + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); + } + return arraybuffer; +}; \ No newline at end of file diff --git a/uni_modules/x-base64toarraybuff-s/utssdk/web/index.uts b/uni_modules/x-base64toarraybuff-s/utssdk/web/index.uts new file mode 100644 index 0000000..04a73bb --- /dev/null +++ b/uni_modules/x-base64toarraybuff-s/utssdk/web/index.uts @@ -0,0 +1,9 @@ +import {decode,encode} from "./base64ToArraybuffer.uts" + +export const base64ToArrayBuffer = (data : string) :ArrayBuffer => { + return decode(data) +} + +export const arrayBufferToBase64 = (data : ArrayBuffer) : string => { + return encode(data) +} \ No newline at end of file diff --git a/uni_modules/x-call-phone/changelog.md b/uni_modules/x-call-phone/changelog.md new file mode 100644 index 0000000..53c0050 --- /dev/null +++ b/uni_modules/x-call-phone/changelog.md @@ -0,0 +1,4 @@ +## 1.0.3(2025-07-25) +* 兼容原生鸿蒙 +## 1.0.2(2024-08-11) +* 拨号,三端可用. \ No newline at end of file diff --git a/uni_modules/x-call-phone/package.json b/uni_modules/x-call-phone/package.json new file mode 100644 index 0000000..3a9985d --- /dev/null +++ b/uni_modules/x-call-phone/package.json @@ -0,0 +1,82 @@ +{ + "id": "x-call-phone", + "displayName": "x-call-phone", + "version": "1.0.0", + "description": "x-call-phone", + "keywords": [ + "x-call-phone" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-call-phone/readme.md b/uni_modules/x-call-phone/readme.md new file mode 100644 index 0000000..42073c0 --- /dev/null +++ b/uni_modules/x-call-phone/readme.md @@ -0,0 +1,55 @@ +# x-call-phone +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +拨打号码插件,支持跨平台调用系统拨号功能。 + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件,提供了统一的API接口来实现拨打电话功能。 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 使用前准备 + +#### Android平台 +需要在应用中申请电话权限(CALL_PHONE)。插件会自动处理权限申请流程,如果用户拒绝授权,将无法使用拨号功能。 + +#### iOS平台 +无需特殊权限设置。 + +### 开发环境配置 +- 如果是uniapp应用需要自定基座 +- uniappx不需要定义基座,但win开发ios时需要 +- 如果是mac开发uniappx不需要基座 + +### API接口 + +#### makePhone(tel: string) +拨打电话号码 + +**参数说明:** +- tel: string 类型,要拨打的电话号码 + +**平台差异说明:** +- Android 10及以上版本:使用ACTION_DIAL实现,直接跳转到拨号界面 +- Android 10以下版本:使用ACTION_CALL实现,直接拨打电话 +- iOS:统一使用系统拨号功能 + +**示例代码:** +```ts + +import {makePhone} from "@/uni_modules/x-call-phone" + +// 拨打电话 +makePhone('10086') +``` + +### 注意事项 +1. Android平台需要在应用启动时确保已获取CALL_PHONE权限 +2. 不同Android版本的实现方式有所不同,以确保符合系统安全策略 +3. 建议在调用接口前先进行平台判断,确保更好的兼容性 \ No newline at end of file diff --git a/uni_modules/x-call-phone/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-call-phone/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..afc7ba4 --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/uni_modules/x-call-phone/utssdk/app-android/config.json b/uni_modules/x-call-phone/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-call-phone/utssdk/app-android/index.uts b/uni_modules/x-call-phone/utssdk/app-android/index.uts new file mode 100644 index 0000000..2b99e6a --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-android/index.uts @@ -0,0 +1,30 @@ +import Intent from 'android.content.Intent'; +import Uri from 'android.net.Uri'; +import Build from 'android.os.Build'; +import Activity from 'android.app.Activity'; +export function makePhone(tel : string) { + let phone = "tel:" + tel; + let ac = UTSAndroid.getUniActivity() as Activity + let permissionCheck = ["android.permission.CALL_PHONE"] + let _this = this; + function callphone() { + //10以上 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + let intent = new Intent(Intent.ACTION_DIAL, Uri.parse(phone)) + ac.startActivity(intent) + // 10以下. + } else { + let intent = new Intent(Intent.ACTION_CALL, Uri.parse(phone)) + ac.startActivity(intent) + } + } + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + callphone() + } else { + console.log("当前不具备指定权限") + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (_ : boolean, _ : string[]) { + callphone() + }, function (_ : boolean, _ : string[]) { + }) + } +} \ No newline at end of file diff --git a/uni_modules/x-call-phone/utssdk/app-harmony/index.uts b/uni_modules/x-call-phone/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..31aa59d --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-harmony/index.uts @@ -0,0 +1,7 @@ +import { call } from '@kit.TelephonyKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +export function makePhone(tel : string) { + call.makeCall(tel, (err : BusinessError) => { + console.error(err.message) + }) +} diff --git a/uni_modules/x-call-phone/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-call-phone/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-call-phone/utssdk/app-ios/config.json b/uni_modules/x-call-phone/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-call-phone/utssdk/app-ios/index.uts b/uni_modules/x-call-phone/utssdk/app-ios/index.uts new file mode 100644 index 0000000..1365312 --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-ios/index.uts @@ -0,0 +1,12 @@ +import { URL } from 'Foundation'; +import { UIApplication } from 'UIKit'; + +export function makePhone(tel : string) { + let phone = new URL(string = `tel://\(${tel})`); + + if (UIApplication.shared.canOpenURL(phone!)) { + + UIApplication.shared.open(phone!, options= new Map(), completionHandler= nil) + + } +} \ No newline at end of file diff --git a/uni_modules/x-call-phone/utssdk/app-ios/info.plist b/uni_modules/x-call-phone/utssdk/app-ios/info.plist new file mode 100644 index 0000000..accc2cf --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/app-ios/info.plist @@ -0,0 +1,10 @@ + + + + + LSApplicationQueriesSchemes + + tel + + + \ No newline at end of file diff --git a/uni_modules/x-call-phone/utssdk/interface.uts b/uni_modules/x-call-phone/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-call-phone/utssdk/mp-weixin/index.uts b/uni_modules/x-call-phone/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..72d8f0d --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/mp-weixin/index.uts @@ -0,0 +1,8 @@ +export function makePhone(tel : string) { + wx.makePhoneCall({ + phoneNumber:tel, + fail(er) { + console.error(er) + } + }) +} \ No newline at end of file diff --git a/uni_modules/x-call-phone/utssdk/unierror.uts b/uni_modules/x-call-phone/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-call-phone/utssdk/web/index.uts b/uni_modules/x-call-phone/utssdk/web/index.uts new file mode 100644 index 0000000..6df7df0 --- /dev/null +++ b/uni_modules/x-call-phone/utssdk/web/index.uts @@ -0,0 +1,12 @@ +export function makePhone(tel : string) { + let isCanalinks = document.body.querySelector("#xPhoneAlinks") + if (!isCanalinks) { + let a = document.createElement("a") + a.href = `tel:${tel}` + a.id = "xPhoneAlinks" + document.body.append(a) + isCanalinks = a; + } + isCanalinks.click(); + +} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/changelog.md b/uni_modules/x-camrea-u/changelog.md new file mode 100644 index 0000000..9527061 --- /dev/null +++ b/uni_modules/x-camrea-u/changelog.md @@ -0,0 +1,13 @@ +## 1.0.7(2025-08-17) +* 针对微信的浏览器内核设定相关属性,以防止全屏脱离文档。 +## 1.0.6(2025-08-4) +* 安卓,ios 现在支持屏幕旋转横向拍摄 +* 图片拍摄后会自动旋转为正向角度。 +## 1.0.5(2025-02-11) +* 兼容微信,同时电脑(带摄像头的电脑),h5手机端返回的类型已经和app,微信一致返回Blob临时文件地址,而不是对象了.注意兼容. +## 1.0.4 (2024-12-19) +* 相机增强了start,stop,pause视频录制功能,增加事件recoder,具体见demo,可以在录制视频的同时进行抓拍相片. +## 1.0.3(2024-10-27) +增加属性orientation,flash以控制前置,后置摄像头,闪光灯是否开启,web不支持这些属性 +## 1.0.2(2024-08-11) +* 相机预览拍照,先期保证三端可用,后期再完善具体细节. \ No newline at end of file diff --git a/uni_modules/x-camrea-u/components/x-camrea-u/x-camrea-u.uvue b/uni_modules/x-camrea-u/components/x-camrea-u/x-camrea-u.uvue new file mode 100644 index 0000000..9d0fabc --- /dev/null +++ b/uni_modules/x-camrea-u/components/x-camrea-u/x-camrea-u.uvue @@ -0,0 +1,177 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/x-camrea-u/package.json b/uni_modules/x-camrea-u/package.json new file mode 100644 index 0000000..3268a3f --- /dev/null +++ b/uni_modules/x-camrea-u/package.json @@ -0,0 +1,97 @@ +{ + "id": "x-camrea-u", + "displayName": "x-camrea-u", + "version": "1.0.0", + "description": "x-camrea-u", + "keywords": [ + "x-camrea-u" + ], + "repository": "", + "engines": { + "HBuilderX": "^4.31", + "uni-app": "^3.1.0", + "uni-app-x": "^3.1.0" + }, + "dcloudext": { + "type": "uts-vue-component", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "", + "darkmode": "-", + "i18n": "-", + "widescreen": "-" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "-", + "aliyun": "-", + "alipay": "-" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/readme.md b/uni_modules/x-camrea-u/readme.md new file mode 100644 index 0000000..5604875 --- /dev/null +++ b/uni_modules/x-camrea-u/readme.md @@ -0,0 +1,117 @@ +# x-camrea-u + +### 特性说明 + +可以预览拍照,并嵌入到你的页面中直接使用.使用ref函数控制相机. + +### 兼容性 + +| IOS | Andriod | WEB | 小程序 | +| --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | + +### 开发文档 +**使用注意** +打开,关闭,录制中等相关相机状态,请自行通过事件管理. +录制视频或者拍照时,如果出现错误,接受到的数据为空字符串来判断是否有误.(web正确为blob视频文件或者base64图片数据) + +图片格式:jpg,png +视频格式:mp4,webm + +**ref方法** +| 方法 | 参数 | 说明 | +| --- | --- | --- | +| open | - | 打开相机,微信是自动打开为了兼容可以执行,但无效果 | +| close | - | 关闭相机,微信是关闭页面自动关闭相机,其它平台一定要执行 | +| take | - | 抓拍 | +| start | - | 打开相机开始录制视频 | +| pause | - | 暂停录制视频(ios,web,h5不支持,执行后无效果) | +| stop | - | 停止录制视频(不是关闭相机) | + +**事件** +| 事件名称 | 参数 | 说明 | +| --- | --- | --- | +| @take | `Map` | get('path')为图片路径,web为base64数据 | +| @recoder | `Map` | get('path')为视频路径,web为Blob文件对象 | + + +页面放置组件: +```vue +/** + * 标签上有两个属性: + * orientation:front,back(默认),选择前置还是后置摄像头,web不支持 + * flash:true,false,拍摄时,是否打开闪光灯,web不支持.注意使用闪光灯时,请不要使用前置摄像头. + */ + +// 前置摄像头 + +// 打开闪光灯 + + +``` +选项式调用: +```ts +export default { + data() { + return { + urlSrc: '' + } + }, + methods: { + open() { + let el = (this.$refs['camrea'] as XCamreaUElement) + el.open() + }, + close() { + let el = (this.$refs['camrea'] as XCamreaUElement) + el.close() + }, + take() { + let el = (this.$refs['camrea'] as XCamreaUElement) + el.take() + }, + recoder(result:Map) { + let src = result['path'] as string; + if (src != '') { + this.videoUrlSrc = src! as string; + } + }, + getPhoto(result:Map) { + let src = src = result['path'] as string; + if (src != '') { + this.urlSrc = src! as string; + } + } + } +} + +``` + +组合式调用: + +```ts +const camrea = ref(null) +const open = ()=>{ + el.value?.open?.() +} +const close = ()=>{ + el.value?.open?.() +} +const take = ()=>{ + el.value?.open?.() +} + +// 拍照的事件内获取图片路径. +const getPhoto = (result:Map)=>{ + let src = src = result['path'] as string; + if (src != '') { + this.urlSrc = src! as string; + } +} + +``` + +参数配置: + +ios组件上有属性 +savePhoto:boolean 是否保存到相册(仅ios支持) diff --git a/uni_modules/x-camrea-u/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-camrea-u/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..c5d0aa5 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/uni_modules/x-camrea-u/utssdk/app-android/config.json b/uni_modules/x-camrea-u/utssdk/app-android/config.json new file mode 100644 index 0000000..51e8ee8 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-android/config.json @@ -0,0 +1,11 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "androidx.camera:camera-core:1.3.4", + "androidx.camera:camera-camera2:1.3.4", + "androidx.camera:camera-lifecycle:1.3.4", + "androidx.camera:camera-video:1.3.4", + "androidx.camera:camera-view:1.3.4", + "androidx.camera:camera-extensions:1.3.4" + ] +} diff --git a/uni_modules/x-camrea-u/utssdk/app-android/index.uts b/uni_modules/x-camrea-u/utssdk/app-android/index.uts new file mode 100644 index 0000000..d2a3688 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-android/index.uts @@ -0,0 +1,82 @@ +import FrameLayout from "android.widget.FrameLayout"; +import { xCamreaUOpts } from '../../utssdk/interface'; +import { xCamrea } from "./libs/camrea.uts" +import LinearLayout from 'android.widget.LinearLayout'; +import Color from 'android.graphics.Color'; +import View from "android.view.View"; +import ViewGroup from 'android.view.ViewGroup'; +import TextView from 'android.widget.TextView' + +/** + * 检查相机权限 + */ +export function checkPermissions() : Promise { + let permissionCheck = ["android.permission.CAMERA"] + return new Promise((res, rej) => { + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + res(true) + } else { + console.log("当前不具备指定权限") + // 请求拍照权限 + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (a : boolean, _ : string[]) { + res(true) + }, function (a : boolean, _ : string[]) { + //用户拒绝了部分权限 + rej(false) + }) + } + }) +} + + +export class xCamreaU { + viewBox_width = 0; + viewBox_height = 0; + $element : UniNativeViewElement; + targetView : FrameLayout | null = null; + config : xCamreaUOpts; + camera : xCamrea | null = null; + constructor(element : UniNativeViewElement, opts : xCamreaUOpts) { + this.config = opts; + this.$element = element; + this.bindView(); + this.camera = new xCamrea(this.targetView!) + } + bindView() { + let layview = new FrameLayout(this.$element.getAndroidActivity()!); + this.targetView = layview + this.$element.bindAndroidView(this.targetView!); + } + getIsOpeningCameraing() : boolean { + return this.camera!.getIsOpeningCameraing() + } + setCameraDir(dir : string) { + this.camera!.setCameraDir(dir) + } + setFlash(flash : boolean) { + this.camera!.setFlash(flash) + } + openCamrea() { + this.camera!.openCamrea() + } + + takePhoto(call : (path : string) => void) { + this.camera!.takePhoto(call) + } + start(call : (path : string) => void) { + this.camera!.startRecoderVideo(call) + } + pause() { + this.camera!.pauseRecoderVideo() + } + + stop() { + this.camera!.stopRecoderVideo() + } + + /** 关闭相机 */ + close() { + this.camera!.closeCamrea() + } + +} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/utssdk/app-android/libs/camrea.uts b/uni_modules/x-camrea-u/utssdk/app-android/libs/camrea.uts new file mode 100644 index 0000000..11de574 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-android/libs/camrea.uts @@ -0,0 +1,509 @@ +import ListView from 'android.widget.ListView'; +import FrameLayout from 'android.widget.FrameLayout'; +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' +import Range from 'android.util.Range'; + +import Executor from 'java.util.concurrent.Executor' +import Looper from 'android.os.Looper' +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; +import Matrix from 'android.graphics.Matrix'; + + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import IntentFilter from 'android.content.IntentFilter'; + +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import OnImageAvailableListener from 'android.media.ImageReader.OnImageAvailableListener' + + +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import ViewGroup from 'android.view.ViewGroup'; + +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' + +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" + + +// x +import ProcessCameraProvider from "androidx.camera.lifecycle.ProcessCameraProvider" +import PreviewView from "androidx.camera.view.PreviewView" +import CameraController from "androidx.camera.view.CameraController" +import CameraSelector from "androidx.camera.core.CameraSelector" +import Preview from 'androidx.camera.core.Preview' +import Camera from 'androidx.camera.core.Camera' +import LifecycleObserver from "androidx.lifecycle.LifecycleObserver" +import LifecycleOwner from "androidx.lifecycle.LifecycleOwner" +import OnLifecycleEvent from "androidx.lifecycle.OnLifecycleEvent" +import ImageAnalysis from 'androidx.camera.core.ImageAnalysis' +import ImageProxy from 'androidx.camera.core.ImageProxy' +import ImageCapture from 'androidx.camera.core.ImageCapture'; +import AspectRatio from 'androidx.camera.core.AspectRatio'; +import CameraInfo from 'androidx.camera.core.CameraInfo'; + + +import NonNull from 'androidx.annotation.NonNull' +import ExecutorService from 'java.util.concurrent.ExecutorService' +import Executors from 'java.util.concurrent.Executors' + +import ContextCompat from 'androidx.core.content.ContextCompat'; +import FileOutputStream from 'java.io.FileOutputStream'; +import PreviewConfig from 'androidx.camera.core.impl.PreviewConfig'; +import VideoSource from 'android.media.MediaRecorder.VideoSource'; +import VideoCapture from 'androidx.camera.video.VideoCapture'; +import OutputFileOptions from 'androidx.camera.core.ImageCapture.OutputFileOptions'; +import Recorder from 'androidx.camera.video.Recorder'; +import Quality from 'androidx.camera.video.Quality'; +import QualitySelector from 'androidx.camera.video.QualitySelector'; +import OutputFileResults from 'androidx.camera.core.ImageCapture.OutputFileResults'; +import FileDescriptor from 'java.io.FileDescriptor'; +import FileOutputOptions from 'androidx.camera.video.FileOutputOptions'; + +import VideoRecordEvent from 'androidx.camera.video.VideoRecordEvent'; +import Consumer from 'androidx.core.util.Consumer'; +import Recording from 'androidx.camera.video.Recording'; +import ResolutionCorrector from 'androidx.camera.camera2.internal.compat.workaround.ResolutionCorrector'; +import AspectRatioStrategy from 'androidx.camera.core.resolutionselector.AspectRatioStrategy'; +import ResolutionSelector from 'androidx.camera.core.resolutionselector.ResolutionSelector'; +import Display from 'android.view.Display'; + +import { CAMERA_PHOTO_SIZE,xCamreaUOpts } from '../../../utssdk/interface'; + +type buffoptsPlanesType = { + data : ByteBuffer, + getRowStride : number, + getPixelStride : number, +} +type buffoptsType = { + width : number, + height : number, + format : number, + rect : Rect, + planes : buffoptsPlanesType[], +} + +type cameraListNameType = { id : string, device : CameraCharacteristics } +type TAKE_CALL_BACK = (path : string) => void; + +let callFuntake = (path : string) => { } +let callVideoFun = (path : string) => { } + +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} + + + + +export class xCamrea { + parentView : FrameLayout; + + viewBox_width = 0 + viewBox_height = 0 + + imgPointsBycanmarea = [] as RelativeLayout[] + + + /** 手动震动服务 */ + vibrator = null as null | Vibrator + context : Context; + // 相机旋转的角度。 + cameraRate = new Map([ + [Surface.ROTATION_0, 0], + [Surface.ROTATION_90, 0], + [Surface.ROTATION_180, 0], + [Surface.ROTATION_270, 0] + ]) + // 相机服务 + cameraService : CameraManager + // 相机列表,name,id + cameraListName = new Map(); + // + cameraPreviewSize = { width: 800, height: 800 } as CAMERA_PHOTO_SIZE + // 当前预览的什么是设备 + cameraDevice : CameraDevice | null = null + cameraDeviceCaptureSession : CameraCaptureSession | null = null + sufaceHolderView : Surface | null = null + + // 相机区域视图 + cameraView : PreviewView | null = null; + cameraProvider : ProcessCameraProvider | null = null + camera : Camera | null = null; + cameraPreview : Preview | null = null; + videoCapture : VideoCapture | null = null; + // Recording + recoderVideoObj : Recording | null = null; + + // 是否拍照中 + isDecoderQring = false + // 当前相机是否正在预览中。 + isOpeningCameraing = false; + + callFunEvent : TAKE_CALL_BACK = (str : string) => { } + //摄像头朝向,默认是向后置摄像头. + CamerDeviceDir = CameraSelector.LENS_FACING_FRONT + //摄像头的是否开 + flashMode = false + // 拍照模式,还是录像模式. + takeModelType = 'photo'; //photo,video + + private PHOTO_TYPE = "image/jpeg" + private RATIO_4_3_VALUE = 4.0 / 3.0 + private RATIO_16_9_VALUE = 16.0 / 9.0 + + constructor(GroupView : FrameLayout) { + this.context = UTSAndroid.getAppContext()! as Context; + this.parentView = GroupView; + + + this.cameraService = this.context.getSystemService(Context.CAMERA_SERVICE) as CameraManager + this.vibrator = this.context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + this._createCameraView() + } + + /** 创建相机预览区域 */ + private _createCameraView() { + + let sv = new PreviewView(UTSAndroid.getAppContext()!) + sv.scaleType = PreviewView.ScaleType.FILL_CENTER + + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + + this.parentView.addView(this.cameraView!) + } + + openCamrea() { + let _this = this; + if (this.isOpeningCameraing) { + this.closeCamrea() + } + _this._openCamera(); + } + startRecoderVideo(call : (path : string) => void) { + callVideoFun = call; + let _this = this; + + if (_this.recoderVideoObj?.isClosed() == false) { + _this.recoderVideoObj?.resume() + } else { + if (this.isOpeningCameraing || this.recoderVideoObj != null) { + this.stopRecoderVideo() + this.closeCamrea() + } + _this.takeModelType = 'video' + _this._openCamera(); + } + } + pauseRecoderVideo() { + let _this = this; + _this.recoderVideoObj?.pause() + } + stopRecoderVideo() { + let _this = this; + _this.takeModelType = 'photo' + _this.recoderVideoObj?.stop() + _this.recoderVideoObj?.close() + _this.recoderVideoObj = null; + _this.videoCapture = null; + // closeCamrea(); + } + + // 设置识别成功的回调函数 + setCallEvent(call : TAKE_CALL_BACK) { + this.callFunEvent = call; + } + getCamraRotation() : Number { + return 0 + } + getIsOpeningCameraing():boolean{ + return this.isOpeningCameraing; + } + getDevRation(){ + const display:Display = UTSAndroid.getUniActivity()!.getDisplay()! + let rotations = display.getRotation() + let rotation = 90 + if(rotations==0){ + rotation =90 + }else if(rotations==1){ + rotation = 0 + }else if(rotations==2){ + rotation = 270 + }else if(rotations==3){ + rotation = 180 + } + console.log(rotations) + return rotation + } + closeCamrea() { + let t = this; + class IntentRunable2 extends Runnable { + override run() { + t.cameraProvider?.unbindAll() + t.cameraPreview?.setSurfaceProvider(null) + t.isOpeningCameraing = false; + } + } + // 确保在主线程中关闭相机 + new Handler(Looper.getMainLooper()).post(new IntentRunable2()); + } + + private aspectRatio(width : Int, height : Int) : Int { + let previewRatio = Math.max(width, height).toDouble() / Math.min(width, height) + if (Math.abs(previewRatio - this.RATIO_4_3_VALUE) <= Math.abs(previewRatio - this.RATIO_16_9_VALUE)) { + return AspectRatio.RATIO_4_3 + } + return AspectRatio.RATIO_16_9 + } + private _openCamera() { + let _this = this; + let cameraProviderFuture = ProcessCameraProvider.getInstance(this.context) + + class IntentRunable extends Runnable { + override run() { + let cameraProvider : ProcessCameraProvider = cameraProviderFuture.get() + let previewView = _this.cameraView! as PreviewView + + const display:Display = UTSAndroid.getUniActivity()!.getDisplay()! + let rotations = display.getRotation() + + let cameraSelector : CameraSelector = new CameraSelector.Builder() + .requireLensFacing(_this.CamerDeviceDir) + .build(); + + // 预览比例 + let screenAspectRatio = _this.aspectRatio((1280).toInt(), (720).toInt()) + let preview : Preview = new Preview.Builder() + .setTargetAspectRatio(screenAspectRatio) + .build(); + preview.setSurfaceProvider(previewView.getSurfaceProvider()) + // 创建ImageCapture用例,并设置闪光灯模式 + + let imageCapture : ImageCapture = new ImageCapture.Builder() + .setTargetAspectRatio(screenAspectRatio) + .build(); + + imageCapture.targetRotation = rotations + + let imageAnalysis = new ImageAnalysis.Builder() + .setTargetResolution(new Size(1280, 720)) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + class MyImageAnalyzer implements ImageAnalysis.Analyzer { + constructor() { + super() + } + override analyze(image : ImageProxy) { + + // image + if (_this.isDecoderQring) { + + // _this.closeCamrea() + _this.savePhotoTocache(image) + + } else { + image.close() + } + + } + override getDefaultTargetResolution() : Size { + return new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt()); + } + + } + let cameraExecutor = Executors.newSingleThreadExecutor(); + imageAnalysis.setAnalyzer(cameraExecutor, new MyImageAnalyzer()); + + + let recorder = Recorder.Builder() + .setQualitySelector(QualitySelector.from(Quality.HIGHEST)) // 选择录制质量,HD、FHD等 + .build() + + let tempCapture = VideoCapture.withOutput(recorder); + tempCapture.targetRotation = rotations + // tempCapture.setTargetRotation(1) + _this.videoCapture = tempCapture + + + + let camera : Camera = cameraProvider.bindToLifecycle(UTSAndroid.getUniActivity()! as LifecycleOwner, + cameraSelector, + imageCapture, + imageAnalysis, + preview, + videoCapture! + ); + + + if (_this.takeModelType == 'video') { + // 录制视频 + let filepath = _this.context.getExternalCacheDir()?.getPath() ?? "" + let videoFile = new File(filepath, 'tmui4xCamreaVideo' + getUid(1, 12) + '.mp4') + let outputOptions = FileOutputOptions.Builder(videoFile).build() + class DirectExecutor implements Executor { + override execute(r : Runnable) { + r.run(); + console.error('录制错误') + callVideoFun('') + } + } + // Consumer + class reocdereventClass implements Consumer { + override accept(event : VideoRecordEvent) { + if (event instanceof VideoRecordEvent.Start) { + console.log("开始录制") + } else if (event instanceof VideoRecordEvent.Finalize) { + console.log("结束录制", videoFile.absolutePath) + callVideoFun(videoFile.absolutePath) + } + } + } + // ContextCompat.getMainExecutor(_this.context) + _this.recoderVideoObj = _this.videoCapture!.getOutput() + .prepareRecording(_this.context, outputOptions) + .start(ContextCompat.getMainExecutor(_this.context), new reocdereventClass() as Consumer) + + + } + + + let cameraControl = camera.cameraControl + let cameraInfo : CameraInfo = camera.cameraInfo + + // 闪光灯. + cameraControl.enableTorch(_this.flashMode) + _this.camera = camera + _this.cameraPreview = preview + + _this.cameraProvider = cameraProvider + _this.isDecoderQring = false + _this.isOpeningCameraing = true + + } + } + + try { + cameraProviderFuture.addListener(new IntentRunable(), ContextCompat.getMainExecutor(this.context)) + } catch (e) { + console.error('开启错误.') + } + } + + takePhoto(call : (path : string) => void) { + callFuntake = call; + this.isDecoderQring = true; + } + //front,前置,back后置 + setCameraDir(type : string) { + this.CamerDeviceDir = type == 'back' ? CameraSelector.LENS_FACING_BACK : CameraSelector.LENS_FACING_FRONT + } + setFlash(type : boolean) { + this.flashMode = type; + } + + /** + * 将Bitmap图片根据指定角度旋转为正确方向 + * @param bitmap 需要旋转的Bitmap + * @param rotationDegrees 需要旋转的角度(如90, 180, 270等) + * @return 正确方向的Bitmap + */ + rotateBitmap( bitmap:Bitmap, rotationDegrees:Number):Bitmap { + if (rotationDegrees == 0) return bitmap; + const matrix:Matrix = new Matrix(); + matrix.postRotate(rotationDegrees.toFloat()); + const rotatedBitmap:Bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + return rotatedBitmap; + } + + savePhotoTocache(image : ImageProxy) { + let context = UTSAndroid.getAppContext()! + let filepath = context.getExternalCacheDir()?.getPath() ?? "" + let img : Bitmap | null = image.toBitmap() + img = this.rotateBitmap(img!,this.getDevRation()) + let file = new File(filepath, 'tmui4xCamrea' + getUid(1, 12) + '.jpg'); + let fos = new FileOutputStream(file) + let conunt = (img?.getByteCount() ?? 0) / 1024 / 1024 + + let saved = img!.compress(Bitmap.CompressFormat.JPEG, conunt > 1 ? 64 : 100, fos); + let t = this; + class IntentRunable2 extends Runnable { + override run() { + if (saved) { + callFuntake(file.getPath()) + t.isDecoderQring = false + } + // ,拍照暂不关闭相机让用户手动关闭. + // t.closeCamrea() + } + } + image.close() + new Handler(Looper.getMainLooper()).post(new IntentRunable2()); + } + + + +} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/utssdk/app-harmony/index.uts b/uni_modules/x-camrea-u/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..5181089 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-harmony/index.uts @@ -0,0 +1,2 @@ +export function checkPermissions() : Promise {} +export class xCamreaU {} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-camrea-u/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-camrea-u/utssdk/app-ios/config.json b/uni_modules/x-camrea-u/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-camrea-u/utssdk/app-ios/index.uts b/uni_modules/x-camrea-u/utssdk/app-ios/index.uts new file mode 100644 index 0000000..aba8dab --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-ios/index.uts @@ -0,0 +1,90 @@ +import { AVCaptureSession, AVAssetExportPresetHighestQuality, AVCaptureDevice, AVMediaType, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureDeviceInput, AVCaptureInput, AVCaptureVideoDataOutput, AVCaptureConnection, AVCaptureVideoPreviewLayer, AVLayerVideoGravity, AVCaptureVideoOrientation, AVCaptureMovieFileOutput, AVCaptureFileOutputRecordingDelegate, AVCaptureOutput, AVCaptureFileOutput, AVAsset, AVAssetExportSession, AVFileType } from 'AVFoundation'; +import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos'; +import { CMSampleBuffer, CMSampleBufferGetFormatDescription, CMFormatDescription, CMVideoFormatDescriptionGetDimensions, CMSampleBufferGetImageBuffer } from 'CoreMedia'; +import { DispatchQueue } from "Dispatch" +import { UIView, UIImage, UISaveVideoAtPathToSavedPhotosAlbum, UIImageWriteToSavedPhotosAlbum, UIApplication, UIImageView, UILabel, UIViewController, UIFontDescriptor, UIFont, NSTextAlignment, UITapGestureRecognizer, UIAlertController, UIGraphicsImageRenderer, UIGraphicsRendererContext, UIBezierPath, CameraDevice, UIImagePickerController } from 'UIKit'; +import { CGRect, CGFloat, CGPoint, CGAffineTransform, CGSize } from 'CoreFoundation'; + +import { NotificationCenter, NSNotification, Notification, FileManager, Data, URL, NSError } from 'Foundation'; +import { Selector } from 'ObjectiveC'; +import { Alignment } from 'ARKit'; +import { CIImage, CIContext } from 'CoreImage'; +import { CGPath } from 'CoreGraphics'; + +import { xCamreaUOpts } from '../interface.uts'; +import { xCamrea } from './libs/camrea.uts'; + +const camera = new xCamrea(); +export class xCamreaU { + $element : UniNativeViewElement; + targetView : UIView = new UIView(); + config : xCamreaUOpts; + + constructor(element : UniNativeViewElement, opts : xCamreaUOpts) { + this.config = opts; + this.$element = element; + this.$element.bindIOSView(this.targetView); + camera.setView(this.targetView) + } + getIsOpeningCameraing():boolean{ + return camera.getIsOpeningCameraing() + } + setCameraDir(dir:string){ + camera.setCameraDir(dir) + } + setFlash(flash:boolean){ + camera.setFlash(flash) + } + openCamrea(){ + camera.openCamrea() + } + + takePhoto(call:(path:string)=>void){ + camera.takePhoto((path:string)=>{ + call(path) + },false) + } + start(call:(path:string)=>void) { + camera.startRecoderVideo(call) + } + pause(){ + camera.pauseRecoderVideo() + } + + stop(){ + camera.stopRecoderVideo() + } + + /** 关闭相机 */ + close() { + camera.closeCamrea() + } + +} + +// 检查权限 +export function checkPermissions():Promise { + return new Promise((res, rej) => { + PHPhotoLibrary.requestAuthorization((isok : PHAuthorizationStatus) => { + // 拒绝了相册选取权限。 + if (isok != PHAuthorizationStatus.authorized) { + rej(false) + return; + } + AVCaptureDevice.requestAccess(for = AVMediaType.video, completionHandler = (isok2 : boolean) => { + if (!isok2) { + rej(false) + return; + } + + AVCaptureDevice.requestAccess(for = AVMediaType.audio, completionHandler = (isok3 : boolean) => { + if (!isok3) { + rej(false) + return; + } + res(true) + }) + }) + }) + } +} diff --git a/uni_modules/x-camrea-u/utssdk/app-ios/info.plist b/uni_modules/x-camrea-u/utssdk/app-ios/info.plist new file mode 100644 index 0000000..22ba602 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-ios/info.plist @@ -0,0 +1,14 @@ + + + + + NSCameraUsageDescription + 我们需要您的相机权限来拍照或录像。 + NSPhotoLibraryUsageDescription + 需要使用你的相册进行选择视频及图片 + NSPhotoLibraryAddUsageDescription + 需要保存图片和视频至你的相册中 + PHPhotoLibraryPreventAutomaticLimitedAccessAlert + 需要保存图片和视频至你的相册中 + + \ No newline at end of file diff --git a/uni_modules/x-camrea-u/utssdk/app-ios/libs/camrea.uts b/uni_modules/x-camrea-u/utssdk/app-ios/libs/camrea.uts new file mode 100644 index 0000000..4d203c2 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/app-ios/libs/camrea.uts @@ -0,0 +1,519 @@ +import { AVCaptureSession, AVAssetExportPresetHighestQuality, AVCaptureDevice, AVMediaType, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureDeviceInput, AVCaptureInput, AVCaptureVideoDataOutput, AVCaptureConnection, AVCaptureVideoPreviewLayer, AVLayerVideoGravity, AVCaptureVideoOrientation, AVCaptureMovieFileOutput, AVCaptureFileOutputRecordingDelegate, AVCaptureOutput, AVCaptureFileOutput, AVAsset, AVAssetExportSession, AVFileType } from 'AVFoundation'; +import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos'; +import { CMSampleBuffer, CMSampleBufferGetFormatDescription, CMFormatDescription, CMVideoFormatDescriptionGetDimensions, CMSampleBufferGetImageBuffer } from 'CoreMedia'; +import { DispatchQueue } from "Dispatch" +import { UIView, UIImage, UISaveVideoAtPathToSavedPhotosAlbum, UIImageWriteToSavedPhotosAlbum, UIApplication, UIImageView, UILabel, UIViewController, UIFontDescriptor, UIFont, NSTextAlignment, UITapGestureRecognizer, UIAlertController, UIGraphicsImageRenderer, UIGraphicsRendererContext, UIBezierPath, CameraDevice, UIGraphicsGetCurrentContext, UIGraphicsBeginImageContextWithOptions, UIGraphicsGetImageFromCurrentImageContext, UIGraphicsEndImageContext, UIDevice, UIDeviceOrientation } from 'UIKit'; +import { CGRect, CGFloat, CGPoint, CGAffineTransform, CGSize } from 'CoreFoundation'; + +import { NotificationCenter, NSNotification, Notification, FileManager, Data, URL, NSError } from 'Foundation'; +import { Selector } from 'ObjectiveC'; +import { Alignment } from 'ARKit'; +import { CIImage, CIContext } from 'CoreImage'; +import { CGPath } from 'CoreGraphics'; + +type TAKE_CALL_BACK = (path : CMSampleBuffer) => void; + + +let captureSession : null | AVCaptureSession = null; +// 图像捕捉事件代理。 +let captureOutDelegate : CaptureOutSessionBuffer | null = null; +let recorderingDelegate : recorderingDelegateObj | null = null; +let isOpeing : boolean = false; +let taking : boolean = false; +let takingTaron = false +let takePhotoCall = (path : string) => { } +let takvideoRecoderCall = (path : string) => { } +class CaptureOutSessionBuffer implements AVCaptureVideoDataOutputSampleBufferDelegate { + callback : TAKE_CALL_BACK = (imgBuffer : CMSampleBuffer) => { } + camrea : xCamrea; + camreaDevsBuilder : AVCaptureDevice + constructor(dv : TAKE_CALL_BACK, ca : xCamrea, cdv : AVCaptureDevice) { + this.callback = dv; + this.camrea = ca; + this.camreaDevsBuilder = cdv; + super() + } + captureOutput(output : AVCaptureOutput, @argumentLabel("didOutput") sampleBuffer : CMSampleBuffer, @argumentLabel("from") connection : AVCaptureConnection) { + + if (taking) { + + taking = false + // this.camrea.pasue() + + takingTaron = false; + let islock = UTSiOS.try(this.camreaDevsBuilder.lockForConfiguration(), "?") + if (islock != null) { + if (this.camreaDevsBuilder.isTorchActive) { + this.camreaDevsBuilder.torchMode = AVCaptureDevice.TorchMode.off + } + this.camreaDevsBuilder.unlockForConfiguration() + } + + + this.callback(sampleBuffer) + } + } +} + +class recorderingDelegateObj implements AVCaptureFileOutputRecordingDelegate { + callback : TAKE_CALL_BACK = (imgBuffer : CMSampleBuffer) => { } + // 保存到相册的回调方法 + @objc video(videoPath : String, + @argumentLabel("didFinishSavingWithError") error ?: NSError, + contextInfo ?: UnsafeMutableRawPointer) { + if (error != null) { + console.error("tmui4x:Error recording movie: ", error) + return + } + console.log("Video saved successfully") + } + + fileOutput( + output : AVCaptureFileOutput, + @argumentLabel("didStartRecordingTo") fileURL : URL, + @argumentLabel("from") connections : AVCaptureConnection[]) { + // console.log("开始录制") + } + fileOutput( + output : AVCaptureFileOutput, + @argumentLabel("didFinishRecordingTo") outputFileURL : URL, + @argumentLabel("from") connections : AVCaptureConnection[], + @argumentLabel("error") error ?: NSError) { + if (error != null) { + console.error("tmui4x:Error recording movie: ", error) + return + } + // UISaveVideoAtPathToSavedPhotosAlbum( + // outputFileURL.path, + // nil, + // #selector(this.video), + // nil + // ) + // recorderingDelegate = null; + let mp4FileURL = outputFileURL.deletingPathExtension().appendingPathExtension("mp4") // 转换后的文件路径 + let _this = this; + convertMovToMp4(outputFileURL, mp4FileURL, (okmp4str : string) => { + // console.log('end...recodervideo', okmp4str) + takvideoRecoderCall(okmp4str) + // 保存到相册 + // UISaveVideoAtPathToSavedPhotosAlbum( + // mp4FileURL.path, + // nil, + // #selector(_this.video), + // nil + // ) + recorderingDelegate = null; + }) + + } +} + +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} +function getDevRation():AVCaptureVideoOrientation{ + // let ration = 0 + let deviceOrientation = UIDevice.current.orientation + switch (deviceOrientation) { + case UIDeviceOrientation.portrait: + console.log("竖屏正向") + // ration = 90 + return AVCaptureVideoOrientation.portrait + + case UIDeviceOrientation.portraitUpsideDown: + console.log("竖屏倒向") + return AVCaptureVideoOrientation.portraitUpsideDown + case UIDeviceOrientation.landscapeLeft: + console.log("横屏左") + return AVCaptureVideoOrientation.landscapeRight + case UIDeviceOrientation.landscapeRight: + console.log("横屏右") + return AVCaptureVideoOrientation.landscapeLeft + case UIDeviceOrientation.faceDown: + console.log("屏幕朝下") + break; + case UIDeviceOrientation.unknown: + console.log("未知方向") + break; + default: + console.log("其他方向") + } + + return AVCaptureVideoOrientation.portrait +} +function fixImageOrientation(image : UIImage) : UIImage { + let cgImage = image.cgImage! + const width = cgImage.width + const height = cgImage.width + + // let ration = 0 + // 计算绘制尺寸 + let drawRect = CGRect.zero + let imageSize = image.size + // 获取设备物理方向 + let deviceOrientation = UIDevice.current.orientation + if (deviceOrientation == UIDeviceOrientation.portrait) { + drawRect.size = new CGSize(width = imageSize.height, height = imageSize.width) + }else{ + drawRect.size = image.size + } + // 竖屏正向 + if (deviceOrientation == UIDeviceOrientation.portrait) { + // ration = 90 + UIGraphicsBeginImageContextWithOptions(drawRect.size, false, image.scale) + // 获取当前上下文 + let context = UIGraphicsGetCurrentContext()! + // 逆时针旋转90度 + context.translateBy(x = drawRect.size.width, y = 0) + context.rotate(by = new CGFloat(Math.PI / 2)) + } else if (deviceOrientation == UIDeviceOrientation.landscapeRight) { + // ration = 180 + UIGraphicsBeginImageContextWithOptions(drawRect.size, false, image.scale) + let context = UIGraphicsGetCurrentContext()! + context.translateBy(x = drawRect.size.width, y = drawRect.size.height) + context.rotate(by = new CGFloat(Math.PI)) + + } else if (deviceOrientation == UIDeviceOrientation.landscapeLeft) { + + } + + image.draw(in = new CGRect(origin = CGPoint.zero, size = imageSize)) + let normalizedImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return normalizedImage == null ? image : normalizedImage! +} + + +function convertMovToMp4(movFileURL : URL, mp4FileURL : URL, ok : (str : string) => void) { + // 加载 AVAsset + let asset = new AVAsset(url = movFileURL) + let exportSession = new AVAssetExportSession(asset = asset, presetName = AVAssetExportPresetHighestQuality) + // 创建 AVAssetExportSession + if (exportSession == null) { + ok('') + return; + } + + // 配置导出设置 + exportSession!.outputURL = mp4FileURL + exportSession!.outputFileType = AVFileType.mp4 + exportSession!.shouldOptimizeForNetworkUse = true + exportSession!.exportAsynchronously(completionHandler = () => { + switch (exportSession!.status) { + case AVAssetExportSession.Status.completed: + // console.log("导出成功", mp4FileURL.path) + ok(mp4FileURL.path) + break + case AVAssetExportSession.Status.failed: + if (exportSession!.error != null) { + // console.error("导出失败", mp4FileURL.path) + ok('') + } + break + case AVAssetExportSession.Status.cancelled: + // console.error("导出被取消") + ok('') + break + default: + ok('') + break + } + }) + +} + +export class xCamrea { + parentView : UIView | null = null; + camreaViewLayer : UIView | null = null; + imageUiView : UIImageView | null = null; + isSaveToPhoto : boolean = false; + //摄像头朝向,默认是向后置摄像头. + CamerDeviceDir = AVCaptureDevice.Position.back + //摄像头的是否开 + flashMode = false + // 是否拍照 中 + isTakePhoto = false + // AVCaptureMovieFileOutput + movieFileOutput : AVCaptureMovieFileOutput | null = null; + takeModelType = 'photo'; //photo,video + isPaused = false + constructor() { + super(); + } + setView(view : UIView) { + this.parentView = view; + } + getIsOpeningCameraing() : boolean { + return captureSession != null + } + openCamrea() { + this.closeCamrea(); + if (captureSession == null) { + this._openCamrea() + } + } + + startRecoderVideo(call : (path : string) => void) { + takvideoRecoderCall = call; + let _this = this; + if (_this.movieFileOutput?.isRecording == true && _this.isPaused) { + // if (UTSiOS.available("iOS 18.0, *")) { + // _this.movieFileOutput?.resumeRecording() + // _this.isPaused = false; + // } + } else { + if (isOpeing || _this.movieFileOutput != null) { + this.stopRecoderVideo() + this.closeCamrea() + } + _this.takeModelType = 'video' + _this._openCamrea(); + } + } + pauseRecoderVideo() { + let _this = this; + // if (UTSiOS.available("iOS 18.0, *")) { + // _this.movieFileOutput?.pauseRecording() + // _this.isPaused = true; + // } + + } + stopRecoderVideo() { + let _this = this; + _this.takeModelType = 'photo' + _this.movieFileOutput?.stopRecording() + _this.isPaused = false; + _this.movieFileOutput = null; + + } + + recoderVideoCan() { + if (this.movieFileOutput == null || isOpeing == false) { + // console.error('no recoder video by tmui4x,') + return; + } + let userDir = FileManager.default.urls(for = FileManager.SearchPathDirectory.cachesDirectory, in = FileManager.SearchPathDomainMask.userDomainMask).first! + let filename = 'tmui4xCamreaVido' + getUid(1, 12) + '.mov'; + let outputURL = userDir.appendingPathComponent(filename) as URL + // AVCaptureFileOutputRecordingDelegate + recorderingDelegate = new recorderingDelegateObj() + // 开始录制 + this.movieFileOutput!.startRecording(to = outputURL, recordingDelegate = recorderingDelegate!) + + this.isPaused = false + } + takePhoto(call : (path : string) => void, savetophoto : boolean) { + + this.isSaveToPhoto = savetophoto + // isOpeing = false; + taking = true; + takePhotoCall = call; + + } + savePhoto(imageData : UIImage) { + DispatchQueue.main.asyncAfter(deadline = (DispatchTime.now() + 1) as DispatchTime, execute = () => { + new UIImageWriteToSavedPhotosAlbum(imageData, nil, nil, nil) + let alertController = new UIAlertController(title = "提醒", message = "保存成功", preferredStyle = UIAlertController.Style.alert); + UTSiOS.getCurrentViewController().present(alertController, animated = true, completion = () => { + alertController.dismiss(animated = true, completion = nil) + }) + + }) + + + } + setCameraDir(type : string) { + this.CamerDeviceDir = type == 'back' ? AVCaptureDevice.Position.back : AVCaptureDevice.Position.front + } + setFlash(type : boolean) { + this.flashMode = type; + } + saveCacheDir(imgs : UIImage) { + let img = fixImageOrientation(imgs) + if (this.isSaveToPhoto) { + this.savePhoto(img) + } + // 获得当前用户的缓存目录路径主目录。 + let userDir = FileManager.default.urls(for = FileManager.SearchPathDirectory.cachesDirectory, in = FileManager.SearchPathDomainMask.userDomainMask).first! + let filename = 'tmui4xCamrea' + getUid(1, 12) + '.jpg'; + let destinationURL = userDir.appendingPathComponent(filename) + let imageData = img.jpegData(compressionQuality = 1); + if (imageData == null) { + return; + } + + let real = UTSiOS.try(imageData!.write(to = destinationURL), "?"); + + if (real != null) { + takePhotoCall(destinationURL.path) + } + + } + closeCamrea() { + this.pasue() + if (this.camreaViewLayer != null) { + this.camreaViewLayer!.removeFromSuperview() + } + if (this.imageUiView != null) { + this.imageUiView!.removeFromSuperview() + } + this.camreaViewLayer = null + this.imageUiView = null + // this.movieFileOutput?.stopRecording() + this.movieFileOutput = null; + recorderingDelegate = null; + } + pasue() { + if (captureSession != null) { + if (captureSession!.isRunning) { + captureSession!.stopRunning() + } + for (input in captureSession!.inputs) { + captureSession!.removeInput(input) + } + for (output in captureSession!.outputs) { + captureSession!.removeOutput(output) + } + } + captureSession = null; + captureOutDelegate = null; + isOpeing = false; + taking = false + + } + private _openCamrea() { + let t = this; + isOpeing = true; + captureSession = new AVCaptureSession(); + if (this.flashMode) { + takingTaron = true; + } else { + takingTaron = false + } + let captureDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for = AVMediaType.video, position = this.CamerDeviceDir) + + let captureOut = new AVCaptureVideoDataOutput(); + captureSession!.sessionPreset = AVCaptureSession.Preset.photo + captureOutDelegate = new CaptureOutSessionBuffer((result : CMSampleBuffer) => { + + let pixelBuffer = CMSampleBufferGetImageBuffer(result) + if (pixelBuffer == null) return; + let ciImage = new CIImage(cvPixelBuffer = pixelBuffer!) + let context = new CIContext(options = nil) + if (context != null) { + let cgImage = context.createCGImage(ciImage, from = ciImage.extent) + let image = new UIImage(cgImage = cgImage!) + // t.rotateImage(image, Math.PI/2) + t.saveCacheDir(image) + } + + }, this, captureDevice!) + + // 新建设备的输入设备 + let inputDevice = UTSiOS.try(new AVCaptureDeviceInput(device = captureDevice!), "?") + if (inputDevice != null) { + // 添加输入到会话中。 + captureSession!.addInput(inputDevice!) + } + + captureOut.alwaysDiscardsLateVideoFrames = true; + // 设置输出会话 + captureOut.setSampleBufferDelegate(captureOutDelegate!, queue = DispatchQueue.global()) + if (captureSession!.canAddOutput(captureOut)) { + captureSession!.addOutput(captureOut) + console.log("绑定输出层正确!") + } + + this.xCamreaInit(captureDevice!); + } + + xCamreaInit(cdv : AVCaptureDevice) { + let camreaDevsBuilder : AVCaptureDevice = cdv + + + let t = this; + + let parentView = this.parentView! + + + // 绘制界面 + // 创建一张图片预览层。 + + // imageUiView!.frame = this.parentView!.frame + // imageUiView!.alpha = new CGFloat(0) + + // parentView!.addSubview(imageUiView!); + + // 创建视频预览层。 + let camelayer = new UIView() + let parentCGrect = parentView.layer.bounds + let width = Int(parentCGrect.width) + let height = Int(parentCGrect.height) + camelayer.frame = new CGRect(x = 0, y = 0, width = width, height = height) + this.camreaViewLayer = camelayer; + + let isopenRecoderVideo = true; + + if (this.takeModelType == 'video') { + console.log('开始录制视频') + this.movieFileOutput = new AVCaptureMovieFileOutput(); + let audioDevice = AVCaptureDevice.default(for = AVMediaType.audio) + let audioInput = UTSiOS.try(new AVCaptureDeviceInput(device = audioDevice!), '?') + console.log('配置声音', audioInput) + if (audioInput != null && captureSession!.canAddInput(audioInput!)) { + captureSession!.addInput(audioInput!) + } + console.log('配置输出视频文件', this.movieFileOutput) + if (captureSession!.canAddOutput(this.movieFileOutput!)) { + captureSession!.addOutput(this.movieFileOutput!) + } else { + isopenRecoderVideo = false + } + + + + } + + let cameraView = new AVCaptureVideoPreviewLayer(session = captureSession!) + + cameraView.videoGravity = AVLayerVideoGravity.resizeAspectFill + // AVCaptureVideoOrientation.portrait + cameraView.connection!.videoOrientation = getDevRation() + cameraView.frame = new CGRect(x = 0, y = 0, width = width, height = height) + + + + DispatchQueue.main.async(execute = () : void => { + parentView.addSubview(camelayer); + // 绑定渲染层。 + camelayer.layer.addSublayer(cameraView) + captureSession!.startRunning() + + t.isPaused = false + + if (t.takeModelType == 'video') { + if (isopenRecoderVideo) { + setTimeout(function () { + t.recoderVideoCan() + }, 500); + } else { + takvideoRecoderCall('') + } + } + + if (takingTaron && !camreaDevsBuilder.isTorchActive) { + let islock = UTSiOS.try(camreaDevsBuilder.lockForConfiguration(), "?") + if (islock != null) { + camreaDevsBuilder.torchMode = AVCaptureDevice.TorchMode.on + camreaDevsBuilder.unlockForConfiguration() + } + + } + }) + + } +} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/utssdk/interface.uts b/uni_modules/x-camrea-u/utssdk/interface.uts new file mode 100644 index 0000000..6b51d19 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/interface.uts @@ -0,0 +1,35 @@ + +export type AUTH_CALL_BACK_TYPE = (auth : boolean) => void; + +export type CAMERA_PHOTO_SIZE = { + width : number, + height : number +} +export type xCamreaUOpts = { + autoOpenCamera : boolean, + /** + * 是否打开闪光灯,对于orientation为back有效. + */ + flash : boolean, + /** + * 摄像头朝向,默认是后置 + * back,front + */ + orientation : string, + /** + * 相机的像素宽 + */ + cameraWidth : number, + /** + * 相机的像素高 + */ + cameraHeight : number, + /** + * 容器的宽和高 + */ + width : number, + /** + * 容器的宽和高 + */ + height : number +} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/utssdk/mp-weixin/index.uts b/uni_modules/x-camrea-u/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..b00ddad --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/mp-weixin/index.uts @@ -0,0 +1,119 @@ +export type xCamreaUOpts = { + autoOpenCamera : boolean, + /** + * 是否打开闪光灯,对于orientation为back有效. + */ + flash : boolean, + /** + * 摄像头朝向,默认是后置 + * back,front + */ + orientation : string, + /** + * 相机的像素宽 + */ + cameraWidth : number, + /** + * 相机的像素高 + */ + cameraHeight : number, + /** + * 容器的宽和高 + */ + width : number, + /** + * 容器的宽和高 + */ + height : number +} + +export class xCamreaU { + $element : any; + targetView : WechatMiniprogram.CameraContext = wx.createCameraContext(); + config : xCamreaUOpts; + opening = false; + timeId = 232 + private startRecoderVideoFunc = (path : string) => { } + constructor(element : any, opts : xCamreaUOpts) { + this.config = opts; + this.$element = element; + } + + getIsOpeningCameraing() : boolean { + return this.opening + } + setCameraDir(dir : string) { + } + setFlash(flash : boolean) { + } + start(call : (path : string) => void) { + let t = this; + this.takeModelType = 'video' + this.opening = true; + this.startRecoderVideoFunc = call; + clearTimeout(this.timeId) + this.targetView.startRecord({ + quality: 'high', + timeout: 5 * 60, + timeoutCallback(ok) { + call(ok.tempVideoPath || "") + }, + success: (res) => { + t.timeId = setTimeout(function () { + t.stop() + }, (4 * 60 + 57) * 1000); + }, + fail(er) { + console.error(er) + } + }) + + } + /** 关闭相机 */ + close() { + this.stop() + } + openCamrea() { + this.opening = true; + } + takePhoto(call : (path : string) => void) { + this.targetView.takePhoto({ + quality: 'high', + success: (res) => { + call(res.tempImagePath) + }, + fail(er) { + console.error(er) + } + }) + } + + pause() { + this.stop() + } + + stop() { + let t = this; + this.opening = false; + clearTimeout(this.timeId) + this.targetView.stopRecord({ + compressed: true, + timeout: 5 * 60, + success(ok) { + t.startRecoderVideoFunc(ok.tempVideoPath || "") + }, + fail(er) { + console.error(er) + } + }) + + } + +} + +// 检查权限 +export function checkPermissions() : Promise { + return new Promise(async (res, rej) => { + res(true) + }) +} \ No newline at end of file diff --git a/uni_modules/x-camrea-u/utssdk/web/index.uts b/uni_modules/x-camrea-u/utssdk/web/index.uts new file mode 100644 index 0000000..9fbd5d7 --- /dev/null +++ b/uni_modules/x-camrea-u/utssdk/web/index.uts @@ -0,0 +1,200 @@ +export type xCamreaUOpts = { + autoOpenCamera : boolean, + /** + * 是否打开闪光灯,对于orientation为back有效. + */ + flash : boolean, + /** + * 摄像头朝向,默认是后置 + * back,front + */ + orientation : string, + /** + * 相机的像素宽 + */ + cameraWidth : number, + /** + * 相机的像素高 + */ + cameraHeight : number, + /** + * 容器的宽和高 + */ + width : number, + /** + * 容器的宽和高 + */ + height : number +} + +export class xCamreaU { + $element : HTMLDivElement; + targetView : HTMLVideoElement = document.createElement("video"); + config : xCamreaUOpts; + opening = false; + private stream:any = null; + private takeModelType = 'photo' + private mediaRecorder: null | MediaRecorder = null + private startRecoderVideoFunc = (path:string)=>{} + + constructor(element : HTMLDivElement, opts : xCamreaUOpts) { + this.config = opts; + this.$element = element; + this.createVideo(); + } + private createVideo(){ + this.targetView.style.width = "100%" + this.targetView.style.height = "100%" + this.targetView.style.objectFit = "cover" + this.targetView.playsInline = true; + this.targetView.muted = true; + this.targetView.autoplay = true; + this.targetView.controls = false; + // 针对微信的x5内核 + this.targetView.setAttribute('playsinline',true) + this.targetView.setAttribute('webkit-playsinline',true) + this.targetView.setAttribute('x5-playsinline',true) + this.targetView.setAttribute('x5-video-player-type','h5') + this.targetView.setAttribute('x5-video-player-fullscreen','false') + + this.$element.appendChild(this.targetView) + } + getIsOpeningCameraing():boolean{ + return this.opening + } + setCameraDir(dir:string){ + } + setFlash(flash:boolean){ + } + start(call:(path:string)=>void) { + this.takeModelType = 'video' + this.startRecoderVideoFunc = call; + if(!this.opening){ + this.openCamrea(); + } + + } + /** 关闭相机 */ + close() { + let t = this; + this.targetView.pause() + if (t.stream) { + t.stream.getTracks().forEach(function (track) { + track.stop(); + }); + t.stream = null; + } + this.mediaRecorder = null; + this.opening = false; + } + createMediaRecorder() { + let t = this; + if (!MediaRecorder.isTypeSupported('video/mp4')) { + console.error("设备不支持录制 mp4 格式") + this.startRecoderVideoFunc('') + return; + } + const options = { mimeType: 'video/mp4' }; // 默认格式为 WebM + this.mediaRecorder = new MediaRecorder(t.stream, options); + let chunks = []; + + this.mediaRecorder!.ondataavailable = (event) => { + if (event.data.size > 0) { + chunks.push(event.data); + } + }; + + this.mediaRecorder!.onstop = () => { + // 将录制的片段合并为 Blob 对象 + const blob = new Blob(chunks, { type: 'video/mp4' }); + chunks = []; + const dataURL = URL.createObjectURL(blob) + this.startRecoderVideoFunc(dataURL) + }; + this.mediaRecorder!.onerror = () => { + console.error("录制出错,请重试。") + this.startRecoderVideoFunc('') + } + this.mediaRecorder!.start() + } + openCamrea(){ + + if(this.opening) return; + this.opening = true; + var constraints = { + audio: true, + video: { + width: 1920, + height: 1080, + facingMode:this.config.orientation=='front'?{ exact: 'user' }:{ exact: 'environment' } + } + }; + let t = this; + + window.navigator.mediaDevices + .getUserMedia(constraints) + .then(function (mediaStream) { + t.stream = mediaStream + t.targetView.srcObject = t.stream; + t.targetView.onloadedmetadata = function (e) { + t.targetView.play(); + + if (t.takeModelType == 'video') { + t.createMediaRecorder() + } + }; + + }) + .catch(function (err) { + console.log(err.name + ": " + err.message); + t.close() + }); + + } + takePhoto(call:(path:string)=>void){ + let t = this; + if (!t.targetView || !t.stream || !t.opening) return call(''); + var canvas = document.createElement('canvas'); + canvas.width = t.targetView.videoWidth; // 设置canvas的宽度为视频的宽度 + canvas.height = t.targetView.videoHeight; // 设置canvas的高度为视频的高度 + var ctx = canvas.getContext('2d'); + ctx!.drawImage(t.targetView, 0, 0, canvas.width, canvas.height); + canvas.toBlob((data) => { + const dataURL = data ? URL.createObjectURL(data) : "" + call(dataURL) + }, 'image/png', 1) + } + + pause(){ + // this.mediaRecorder?.pause() + this.close(); + } + + stop(){ + this.mediaRecorder?.stop() + } + +} + +// 检查权限 +export function checkPermissions():Promise { + return new Promise(async (res, rej) => { + + let devices = await navigator.mediaDevices.enumerateDevices() + let videoDevices = devices.filter( + (device) => device.kind === 'videoinput' + ); + + if (videoDevices.length == 0) { + rej(false) + console.error('没有找到可用的摄像设备') + return; + } + if(!(window.navigator?.mediaDevices??undefined)){ + rej(false) + console.error('设备不支持') + return; + } + res(true) + }) +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/changelog.md b/uni_modules/x-chinesetopinyin-s/changelog.md new file mode 100644 index 0000000..5ed9baf --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/changelog.md @@ -0,0 +1,4 @@ +## 1.0.1(2025-09-24) +支持Android,iOS,Harmony,web/h5,小程序 +## 1.0.0(2024-06-1) +安卓,ios支持。 \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/package.json b/uni_modules/x-chinesetopinyin-s/package.json new file mode 100644 index 0000000..a020b3a --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/package.json @@ -0,0 +1,115 @@ +{ + "id": "x-chinesetopinyin-s", + "displayName": "中文转拼音 全平台支持", + "version": "1.0.1", + "description": "支持多达5个端已经在安卓,ios,鸿蒙,web/h5,微信小程序上测试通过", + "keywords": [ + "中文转拼音" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "^4.76", + "uni-app-x": "^4.76" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "99.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "369986563" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "音频播放权限" + }, + "npmurl": "", + "darkmode": "√", + "i18n": "√", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": { + "extVersion": "1.0.0", + "minVersion": "100" + }, + "chrome": { + "extVersion": "1.0.0", + "minVersion": "100" + } + }, + "app": { + "android": { + "extVersion": "1.0.0", + "minVersion": "21" + }, + "ios": { + "extVersion": "1.0.0", + "minVersion": "12" + }, + "harmony": { + "extVersion": "1.0.0", + "minVersion": "5.1" + } + }, + "mp": { + "weixin": { + "extVersion": "1.0.0", + "minVersion": "3.0.2" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/readme.md b/uni_modules/x-chinesetopinyin-s/readme.md new file mode 100644 index 0000000..da1b2c3 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/readme.md @@ -0,0 +1,51 @@ +# x-chinesetopinyin-s + +### 开发文档 + +将中文转为拼音,带注音和不注音 + +### 兼容性 + +| iOS | Harmony | 小程序 | Andriod | WEB | +| --- | --- | --- | --- | --- | +| 9+ | 12+ | 全部 | 5.0+ | 全部 | + +### 方法说明 + +使用 +```ts + +import { toPinYin } from '@/uni_modules/x-chinesetopinyin-s'; +toPinYin({ + char: "你好", + success(res) { + // 输出:{detail: "ni hao", zhuyin: "nĭ hăo"} + console.log(res) + } +}) + +``` + +### toPinYin(opts:XuiChineseToPinYinOpts) + +```ts + +export type XuiChineseToPinYinResult = { + detail : string, + zhuyin : string +} + +export interface XuiChineseToPinYinFail extends IUniError { + errCode : number +}; + +export type XuiChineseToPinYinOpts = { + /** 待转换的字符串 */ + char : string + success ?: (res : XuiChineseToPinYinResult) => void + fail ?: (res : XuiChineseToPinYinFail) => void + complete ?: (res : XuiChineseToPinYinResult|null) => void +} + + +``` \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/app-android/config.json b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/config.json new file mode 100644 index 0000000..0f96bed --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/config.json @@ -0,0 +1,4 @@ +{ + "minSdkVersion": "19", + "dependencies":[] +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/app-android/index.uts b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..f0e8728 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/index.uts @@ -0,0 +1,39 @@ +// https://github.com/promeG/TinyPinyin +import Pinyin from "com.github.promeg.pinyinhelper.Pinyin"; +import PinyinHelper from "net.sourceforge.pinyin4j.PinyinHelper"; +import HanyuPinyinOutputFormat from 'net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat'; +import HanyuPinyinToneType from 'net.sourceforge.pinyin4j.format.HanyuPinyinToneType'; +import HanyuPinyinVCharType from 'net.sourceforge.pinyin4j.format.HanyuPinyinVCharType'; +import { XuiChineseToPinYinOpts, XuiChineseToPinYinResult } from "../interface.uts" +import { XuiChineseToPinYinFailImpl } from "../unierror.uts" + +/** 中文转拼音 */ +export function toPinYin(opts : XuiChineseToPinYinOpts){ + try { + let c = opts.char; + if (c == '') { + let errorIml = new XuiChineseToPinYinFailImpl(1002) + opts.fail?.(errorIml) + opts.complete?.(null) + console.error('TMUI Error:','参数不能为空') + return; + } + let result = Pinyin.toPinyin(c," ",null) as string; + const fmt = new HanyuPinyinOutputFormat() + fmt.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE); + fmt.setToneType(HanyuPinyinToneType.WITH_TONE_MARK) + const ok : XuiChineseToPinYinResult = { + detail: result.toLowerCase(), + zhuyin: PinyinHelper.toHanyuPinyinString(c,fmt,' ') + } + opts.success?.(ok) + opts.complete?.(ok) + + } catch (error:Error) { + opts.fail?.(new XuiChineseToPinYinFailImpl(1001)) + opts.complete?.(null) + console.error('TMUI Error:',error.message) + } + + +} diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/app-android/libs/pinyin4j-2.5.0.jar b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/libs/pinyin4j-2.5.0.jar new file mode 100644 index 0000000..e8ede13 Binary files /dev/null and b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/libs/pinyin4j-2.5.0.jar differ diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/app-android/libs/tinypinyin-3.0.0.jar b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/libs/tinypinyin-3.0.0.jar new file mode 100644 index 0000000..e3c740f Binary files /dev/null and b/uni_modules/x-chinesetopinyin-s/utssdk/app-android/libs/tinypinyin-3.0.0.jar differ diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/app-harmony/index.uts b/uni_modules/x-chinesetopinyin-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..37dfaa9 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/app-harmony/index.uts @@ -0,0 +1,32 @@ +import { i18n } from '@kit.LocalizationKit'; +import { XuiChineseToPinYinOpts, XuiChineseToPinYinResult } from "../interface.uts" +import { XuiChineseToPinYinFailImpl } from "../unierror.uts" + +/** 中文转拼音 */ +export function toPinYin(opts : XuiChineseToPinYinOpts) { + try { + let c = opts.char; + if (c == '') { + let errorIml = new XuiChineseToPinYinFailImpl(1002) + opts?.fail?.(errorIml) + opts?.complete?.(null) + return; + } + let transliterator = i18n.Transliterator.getInstance('Any-Latn'); + let result = transliterator.transform(opts.char); + + let voiceRemovedTransliterator = i18n.Transliterator.getInstance('Latin-ASCII'); + let resultZhuying = voiceRemovedTransliterator.transform(opts.char); + const ok : XuiChineseToPinYinResult = { + detail: result, + zhuyin: resultZhuying + } + opts?.success?.(ok) + opts?.complete?.(ok) + } catch (error) { + console.error(error) + opts?.fail?.(new XuiChineseToPinYinFailImpl(1001)) + opts?.complete?.(null) + } + +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/app-ios/config.json b/uni_modules/x-chinesetopinyin-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..721b81e --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "9" +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/app-ios/index.uts b/uni_modules/x-chinesetopinyin-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..96041d9 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/app-ios/index.uts @@ -0,0 +1,35 @@ +import {NSMutableString,CFStringTransform,kCFStringTransformToLatin,kCFStringTransformStripDiacritics, StringTransform} from "Foundation" +import { XuiChineseToPinYinOpts, XuiChineseToPinYinResult } from "../interface.uts" +import { XuiChineseToPinYinFailImpl } from "../unierror.uts" + +/** 中文转拼音 */ +export function toPinYin(opts : XuiChineseToPinYinOpts){ + try { + let c = opts.char; + if (c == '') { + let errorIml = new XuiChineseToPinYinFailImpl(1002) + opts.fail?.(errorIml) + opts.complete?.(null) + return; + } + + let tostrings = new NSMutableString(string = opts.char) + let tostrings2 = new NSMutableString(string = opts.char) + CFStringTransform(tostrings,null,kCFStringTransformToLatin,false) + + CFStringTransform(tostrings2,null,kCFStringTransformToLatin,false) + CFStringTransform(tostrings2,null,kCFStringTransformStripDiacritics,false) + const ok : XuiChineseToPinYinResult = { + detail: tostrings2 as string, + zhuyin: tostrings as string + } + opts.success?.(ok) + opts.complete?.(ok) + } catch (error) { + console.error(error) + opts.fail?.(new XuiChineseToPinYinFailImpl(1001)) + opts.complete?.(null) + } + + +} diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/interface.uts b/uni_modules/x-chinesetopinyin-s/utssdk/interface.uts new file mode 100644 index 0000000..d27ef87 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/interface.uts @@ -0,0 +1,20 @@ + +export type XuiChineseToPinYinResult = { + detail : string, + zhuyin : string +} + +export interface XuiChineseToPinYinFail extends IUniError { + errCode : number +}; + +export type XuiChineseToPinYinOpts = { + /** 待转换的字符串 */ + char : string + success ?: (res : XuiChineseToPinYinResult) => void + fail ?: (res : XuiChineseToPinYinFail) => void + complete ?: (res : XuiChineseToPinYinResult|null) => void +} + + + diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/mp-weixin/index.uts b/uni_modules/x-chinesetopinyin-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..ace3c65 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,28 @@ +import { pinyin } from "./pinyintojs.js" +import { XuiChineseToPinYinOpts, XuiChineseToPinYinResult } from "../interface.uts" +import { XuiChineseToPinYinFailImpl } from "../unierror.uts" + +/** 中文转拼音 */ +export function toPinYin(opts : XuiChineseToPinYinOpts){ + try { + let c = opts.char; + if (c == '') { + let errorIml = new XuiChineseToPinYinFailImpl(1002) + opts?.fail?.(errorIml) + opts?.complete?.(null) + return; + } + const result = pinyin(c, { toneType: 'none', style: pinyin.STYLE_NORMAL }) + const resultZhuying = pinyin(c, { toneType: 'symbol', style: pinyin.STYLE_NORMAL }) + const ok : XuiChineseToPinYinResult = { + detail: result, + zhuyin: resultZhuying + } + opts?.success?.(ok) + opts?.complete?.(ok) + } catch (error) { + console.error(error) + opts?.fail?.(new XuiChineseToPinYinFailImpl(1001)) + opts?.complete?.(null) + } +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/mp-weixin/pinyintojs.js b/uni_modules/x-chinesetopinyin-s/utssdk/mp-weixin/pinyintojs.js new file mode 100644 index 0000000..dbcc7a1 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/mp-weixin/pinyintojs.js @@ -0,0 +1 @@ +const DoubleUnicodePrefixReg=/^[\uD800-\uDBFF]$/;const DoubleUnicodeSuffixReg=/^[\uDC00-\uDFFF]$/;const DoubleUnicodeReg=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;var Probability;(function(Probability){Probability[Probability["Unknown"]=1e-13]="Unknown";Probability[Probability["Rule"]=1e-12]="Rule";Probability[Probability["DICT"]=2e-8]="DICT";Probability[Probability["Surname"]=1]="Surname";Probability[Probability["Custom"]=1]="Custom"})(Probability||(Probability={}));const Priority={Normal:1,Surname:10,Custom:100,};function stringLength(text){var _a;return text.length-(((_a=text.match(DoubleUnicodeReg))===null||_a===void 0?void 0:_a.length)||0)}function splitString(text){const result=[];let i=0;while(i1){return this.StringDICT.get(word)}else{const code=word.charCodeAt(0);return this.NumberDICT[code]}}set(word,pinyin){if(word.length>1){this.StringDICT.set(word,pinyin)}else{const code=word.charCodeAt(0);this.NumberDICT[code]=pinyin}}clear(){this.NumberDICT=[];this.StringDICT.clear()}}const map={'bǎng páng pāng':['膀'],líng:['〇','伶','凌','刢','囹','坽','夌','姈','婈','孁','岺','彾','掕','昤','朎','柃','棂','櫺','欞','泠','淩','澪','灵','燯','爧','狑','玲','琌','瓴','皊','砱','祾','秢','竛','笭','紷','綾','绫','羐','羚','翎','聆','舲','苓','菱','蓤','蔆','蕶','蛉','衑','裬','詅','跉','軨','輘','酃','醽','鈴','錂','铃','閝','陵','零','霊','霗','霛','霝','靈','駖','魿','鯪','鲮','鴒','鸰','鹷','麢','齡','齢','龄','龗','㥄',],yī:['一','乊','伊','依','医','吚','咿','噫','壱','壹','夁','嫛','嬄','弌','揖','撎','檹','毉','洢','渏','漪','瑿','畩','祎','禕','稦','繄','蛜','衤','譩','辷','郼','醫','銥','铱','鷖','鹥','黟','黳',],'dīng zhēng':['丁'],'kǎo qiǎo yú':['丂'],qī:['七','倛','僛','凄','嘁','墄','娸','悽','慼','慽','戚','捿','柒','桤','桼','棲','榿','欺','沏','淒','漆','紪','緀','萋','褄','諆','迉','郪','鏚','霋','魌','鶈',],shàng:['丄','尙','尚','恦','緔','绱'],xià:['丅','下','乤','圷','夏','夓','懗','梺','疜','睱','罅','鎼','鏬',],hǎn:['丆','喊','浫','罕','豃','㘎'],'wàn mò':['万'],zhàng:['丈','仗','墇','嶂','帐','帳','幛','扙','杖','涱','痮','瘬','瘴','瞕','粀','胀','脹','賬','账','障',],sān:['三','厁','叁','弎','毵','毶','毿','犙','鬖'],'shàng shǎng shang':['上'],'qí jī':['丌','其','奇'],'bù fǒu':['不'],'yǔ yù yú':['与'],miǎn:['丏','偭','免','冕','勉','勔','喕','娩','愐','汅','沔','湎','睌','緬','缅','腼','葂','靦','鮸','𩾃',],gài:['丐','乢','匃','匄','戤','概','槩','槪','溉','漑','瓂','葢','鈣','钙','𬮿',],chǒu:['丑','丒','侴','吜','杽','瞅','矁','醜','魗'],zhuān:['专','叀','嫥','専','專','瑼','甎','砖','磗','磚','蟤','諯','鄟','顓','颛','鱄','䏝',],'qiě jū':['且'],pī:['丕','伓','伾','噼','坯','岯','憵','批','披','炋','狉','狓','砒','磇','礔','礕','秛','秠','耚','豾','邳','鈚','鉟','銔','錃','錍','霹','駓','髬','魾','𬳵',],shì:['世','丗','亊','事','仕','侍','冟','势','勢','卋','呩','嗜','噬','士','奭','嬕','室','市','式','弑','弒','恀','恃','戺','拭','揓','是','昰','枾','柿','栻','澨','烒','煶','眂','眎','眡','睗','示','礻','筮','簭','舐','舓','襫','視','视','觢','試','誓','諡','謚','试','谥','貰','贳','軾','轼','逝','遾','釈','释','釋','鈰','鉃','鉽','铈','飾','餙','餝','饰','鰘','䏡','𬤊',],qiū:['丘','丠','坵','媝','恘','恷','楸','秋','秌','穐','篍','緧','萩','蘒','蚯','蝵','蟗','蠤','趥','邱','鞦','鞧','鰌','鰍','鳅','鶖','鹙','龝',],bǐng:['丙','屛','怲','抦','昞','昺','柄','棅','炳','禀','秉','稟','苪','蛃','邴','鈵','陃','鞆','餅','餠','饼',],yè:['业','亱','僷','墷','夜','嶪','嶫','抴','捙','擛','擪','擫','晔','曄','曅','曗','曳','曵','枼','枽','業','洂','液','澲','烨','燁','爗','璍','皣','瞱','瞸','礏','腋','葉','謁','谒','邺','鄴','鍱','鐷','靥','靨','頁','页','餣','饁','馌','驜','鵺','鸈',],cóng:['丛','从','叢','婃','孮','従','徔','徖','悰','樷','欉','淙','灇','爜','琮','藂','誴','賨','賩','錝',],dōng:['东','倲','冬','咚','埬','岽','崬','徚','昸','東','氡','氭','涷','笗','苳','菄','蝀','鮗','鯟','鶇','鶫','鸫','鼕','𬟽',],sī:['丝','俬','凘','厮','司','咝','嘶','噝','媤','廝','恖','撕','斯','楒','泀','澌','燍','禗','禠','私','糹','絲','緦','纟','缌','罳','蕬','虒','蛳','蜤','螄','蟖','蟴','鉰','銯','鍶','鐁','锶','颸','飔','騦','鷥','鸶','鼶','㟃',],chéng:['丞','呈','城','埕','堘','塍','塖','宬','峸','惩','懲','成','承','挰','掁','揨','枨','棖','橙','檙','洆','溗','澂','珵','珹','畻','程','窚','筬','絾','脭','荿','誠','诚','郕','酲','鋮','铖','騬','鯎',],diū:['丟','丢','銩','铥'],liǎng:['両','两','兩','唡','啢','掚','緉','脼','蜽','裲','魉','魎','𬜯',],yǒu:['丣','卣','友','梄','湵','牖','禉','羑','聈','苃','莠','蜏','酉','銪','铕','黝',],yán:['严','厳','啱','喦','嚴','塩','壛','壧','妍','姸','娫','娮','岩','嵒','嵓','巌','巖','巗','延','揅','昖','楌','檐','櫩','欕','沿','炎','炏','狿','琂','盐','碞','筵','簷','莚','蔅','虤','蜒','言','訁','訮','詽','讠','郔','閆','閻','闫','阎','顏','顔','颜','鹽','麣','𫄧',],bìng:['並','併','倂','傡','垪','摒','栤','病','窉','竝','誁','靐','鮩',],'sàng sāng':['丧'],gǔn:['丨','惃','滚','滾','磙','緄','绲','蓘','蔉','衮','袞','輥','辊','鮌','鯀','鲧',],jiū:['丩','勼','啾','揪','揫','朻','究','糾','纠','萛','赳','阄','鬏','鬮','鳩','鸠',],'gè gě':['个','個','各'],yā:['丫','圧','孲','庘','押','枒','桠','椏','錏','鐚','鴉','鴨','鵶','鸦','鸭',],pán:['丬','媻','幋','槃','洀','瀊','爿','盘','盤','磐','縏','蒰','蟠','蹒','蹣','鎜','鞶',],'zhōng zhòng':['中'],jǐ:['丮','妀','己','戟','挤','掎','撠','擠','橶','泲','犱','脊','虮','蟣','魢','鱾','麂',],jiè:['丯','介','借','唶','堺','屆','届','岕','庎','徣','戒','楐','犗','玠','琾','界','畍','疥','砎','蚧','蛶','衸','褯','誡','诫','鎅','骱','魪',],fēng:['丰','仹','偑','僼','凨','凬','凮','妦','寷','封','峯','峰','崶','枫','楓','檒','沣','沨','渢','灃','烽','犎','猦','琒','疯','瘋','盽','砜','碸','篈','蘴','蜂','蠭','豐','鄷','酆','鋒','鎽','鏠','锋','霻','靊','飌','麷',],'guàn kuàng':['丱'],chuàn:['串','汌','玔','賗','釧','钏'],chǎn:['丳','产','冁','剷','囅','嵼','旵','浐','滻','灛','產','産','簅','蒇','蕆','諂','譂','讇','谄','鏟','铲','閳','闡','阐','骣','𬊤',],lín:['临','冧','壣','崊','嶙','斴','晽','暽','林','潾','瀶','燐','琳','璘','瞵','碄','磷','粦','粼','繗','翷','臨','轔','辚','遴','邻','鄰','鏻','阾','隣','霖','驎','鱗','鳞','麐','麟','𬴊','𬭸',],zhuó:['丵','劅','卓','啄','圴','妰','娺','撯','擆','擢','斫','斮','斱','斲','斵','晫','椓','浊','浞','濁','灼','烵','琸','硺','禚','窡','籗','籱','罬','茁','蠗','蠿','諁','諑','謶','诼','酌','鐲','镯','鵫','鷟','䓬','𬸦',],zhǔ:['丶','主','劯','嘱','囑','宔','帾','拄','渚','濐','煑','煮','燝','瞩','矚','罜','詝','陼','鸀','麈','𬣞',],bā:['丷','仈','八','叭','哵','夿','岜','巴','捌','朳','玐','疤','笆','粑','羓','芭','蚆','豝','釟',],wán:['丸','刓','完','岏','抏','捖','汍','烷','玩','琓','笂','紈','纨','翫','芄','貦','頑','顽',],dān:['丹','勯','匰','単','妉','媅','殚','殫','甔','眈','砃','箪','簞','耼','耽','聃','聸','褝','襌','躭','郸','鄲','酖','頕',],'wèi wéi':['为'],'jǐng dǎn':['丼'],'lì lí':['丽'],jǔ:['举','弆','挙','擧','椇','榉','榘','櫸','欅','矩','筥','聥','舉','莒','蒟','襷','踽','齟','龃',],piě:['丿','苤','鐅','𬭯'],fú:['乀','伏','俘','凫','刜','匐','咈','哹','垘','孚','岪','巿','帗','幅','幞','弗','彿','怫','扶','柫','栿','桴','氟','泭','浮','涪','澓','炥','玸','甶','畉','癁','祓','福','稪','符','箙','紱','紼','絥','綍','绂','绋','罘','罦','翇','艀','芙','芣','苻','茀','茯','菔','葍','虙','蚨','蜉','蝠','袚','袱','襆','襥','諨','豧','踾','輻','辐','郛','鉘','鉜','韍','韨','颫','髴','鮄','鮲','鳧','鳬','鴔','鵩','黻',],'yí jí':['乁'],yì:['乂','义','亄','亦','亿','伇','伿','佾','俋','億','兿','刈','劓','劮','勚','勩','匇','呓','呭','呹','唈','囈','圛','坄','垼','埸','奕','嫕','嬑','寱','屹','峄','嶧','帟','帠','幆','廙','异','弈','弋','役','忆','怈','怿','悒','意','憶','懌','懿','抑','挹','敡','易','晹','曀','曎','杙','枍','棭','榏','槸','檍','歝','殔','殪','殹','毅','浂','浥','浳','湙','溢','潩','澺','瀷','炈','焲','熠','熤','熼','燚','燡','燱','獈','玴','異','疫','痬','瘗','瘞','瘱','癔','益','瞖','穓','竩','篒','縊','繶','繹','绎','缢','義','羿','翊','翌','翳','翼','耴','肄','肊','膉','臆','艗','艺','芅','苅','萟','蓺','薏','藙','藝','蘙','虉','蜴','螠','衪','袣','裔','裛','褹','襼','訲','訳','詍','詣','誼','譯','議','讛','议','译','诣','谊','豙','豛','豷','貖','贀','跇','轶','逸','邑','鄓','醷','釴','鈠','鎰','鐿','镒','镱','阣','隿','霬','饐','駅','驛','驿','骮','鮨','鶂','鶃','鶍','鷁','鷊','鷧','鷾','鸃','鹝','鹢','黓','齸','𬬩','㑊','𫄷','𬟁',],nǎi:['乃','倷','奶','嬭','廼','氖','疓','艿','迺','釢'],wǔ:['乄','五','仵','伍','侮','倵','儛','午','啎','妩','娬','嫵','庑','廡','忤','怃','憮','摀','武','潕','熓','牾','玝','珷','瑦','甒','碔','舞','躌','迕','逜','陚','鵡','鹉','𣲘',],jiǔ:['久','乆','九','乣','奺','杦','汣','灸','玖','紤','舏','酒','镹','韭','韮',],'tuō zhé':['乇','杔','馲'],'me mó ma yāo':['么'],zhī:['之','倁','卮','巵','搘','支','栀','梔','椥','榰','汁','泜','疷','祗','祬','秓','稙','綕','肢','胑','胝','脂','芝','蘵','蜘','衼','隻','鳷','鴲','鼅','𦭜',],'wū wù':['乌'],zhà:['乍','咤','宱','搾','榨','溠','痄','蚱','詐','诈','醡','霅','䃎',],hū:['乎','乯','匢','匫','呼','唿','嘑','垀','寣','幠','忽','惚','昒','歑','泘','淴','滹','烀','苸','虍','虖','謼','軤','轷','雐',],fá:['乏','伐','傠','坺','垡','墢','姂','栰','浌','瞂','笩','筏','罚','罰','罸','藅','閥','阀',],'lè yuè yào lào':['乐','樂'],yín:['乑','吟','噖','嚚','圁','垠','夤','婬','寅','峾','崟','崯','檭','殥','泿','淫','滛','烎','犾','狺','璌','硍','碒','荶','蔩','訔','訚','訡','誾','鄞','鈝','銀','银','霪','鷣','齦',],pīng:['乒','俜','娉','涄','甹','砯','聠','艵','頩'],pāng:['乓','滂','胮','膖','雱','霶'],qiáo:['乔','侨','僑','嫶','憔','桥','槗','樵','橋','櫵','犞','瞧','硚','礄','荍','荞','蕎','藮','譙','趫','鐈','鞒','鞽','顦',],hǔ:['乕','琥','萀','虎','虝','錿','鯱'],guāi:['乖'],'chéng shèng':['乗','乘','娍'],yǐ:['乙','乛','以','倚','偯','嬟','崺','已','庡','扆','攺','敼','旑','旖','檥','矣','礒','笖','舣','艤','苡','苢','蚁','螘','蟻','裿','踦','輢','轙','逘','酏','釔','鈘','鉯','钇','顗','鳦','齮','𫖮','𬺈',],'háo yǐ':['乚'],'niè miē':['乜'],qǐ:['乞','企','启','唘','啓','啔','啟','婍','屺','杞','棨','玘','盀','綺','绮','芑','諬','起','邔','闙',],yě:['也','冶','嘢','埜','壄','漜','野'],xí:['习','喺','媳','嶍','席','椺','檄','漝','習','蓆','袭','襲','覡','觋','謵','趘','郋','鎴','隰','霫','飁','騱','騽','驨','鰼','鳛','𠅤','𫘬',],xiāng:['乡','厢','廂','忀','楿','欀','湘','瓖','稥','箱','緗','缃','膷','芗','萫','葙','薌','襄','郷','鄉','鄊','鄕','鑲','镶','香','驤','骧','鱜','麘','𬙋',],shū:['书','倏','倐','儵','叔','姝','尗','抒','掓','摅','攄','書','枢','梳','樞','殊','殳','毹','毺','淑','瀭','焂','疎','疏','紓','綀','纾','舒','菽','蔬','踈','軗','輸','输','鄃','陎','鮛','鵨',],dǒu:['乧','抖','枓','蚪','鈄','阧','陡'],shǐ:['乨','使','兘','史','始','宩','屎','榁','矢','笶','豕','鉂','駛','驶',],jī:['乩','僟','击','刉','刏','剞','叽','唧','喞','嗘','嘰','圾','基','墼','姬','屐','嵆','嵇','撃','擊','朞','机','枅','樭','機','毄','激','犄','玑','璣','畸','畿','癪','矶','磯','积','積','笄','筓','箕','簊','緁','羁','羇','羈','耭','肌','芨','虀','覉','覊','譏','譤','讥','賫','賷','赍','跻','踑','躋','躸','銈','錤','鐖','鑇','鑙','隮','雞','鞿','韲','飢','饑','饥','魕','鳮','鶏','鶺','鷄','鸄','鸡','齎','齏','齑','𬯀','𫓯','𫓹','𫌀',],náng:['乪','嚢','欜','蠰','饢'],jiā:['乫','佳','傢','加','嘉','抸','枷','梜','毠','泇','浃','浹','犌','猳','珈','痂','笳','糘','耞','腵','葭','袈','豭','貑','跏','迦','鉫','鎵','镓','鴐','麚','𬂩',],jù:['乬','倨','倶','具','剧','劇','勮','埧','埾','壉','姖','屦','屨','岠','巨','巪','怇','惧','愳','懅','懼','拒','拠','昛','歫','洰','澽','炬','烥','犋','秬','窭','窶','簴','粔','耟','聚','虡','蚷','詎','讵','豦','距','踞','躆','遽','邭','醵','鉅','鐻','钜','颶','飓','駏','鮔',],shí:['乭','十','埘','塒','姼','实','実','寔','實','峕','嵵','时','旹','時','榯','湜','溡','炻','祏','竍','蚀','蝕','辻','遈','鉐','飠','饣','鮖','鰣','鲥','鼫','鼭',],mǎo:['乮','冇','卯','峁','戼','昴','泖','笷','蓩','鉚','铆'],mǎi:['买','嘪','荬','蕒','買','鷶'],luàn:['乱','亂','釠'],rǔ:['乳','擩','汝','肗','辱','鄏'],xué:['乴','学','學','峃','嶨','斈','泶','澩','燢','穴','茓','袕','踅','鷽','鸴',],yǎn:['䶮','乵','俨','偃','儼','兖','兗','厣','厴','噞','孍','嵃','巘','巚','弇','愝','戭','扊','抁','掩','揜','曮','椼','檿','沇','渷','演','琰','甗','眼','罨','萒','蝘','衍','褗','躽','遃','郾','隒','顩','魇','魘','鰋','鶠','黡','黤','黬','黭','黶','鼴','鼹','齴','龑','𬸘','𬙂','𪩘',],fǔ:['乶','俌','俛','俯','府','弣','抚','拊','撫','斧','椨','滏','焤','甫','盙','簠','腐','腑','蜅','輔','辅','郙','釜','釡','阝','頫','鬴','黼','㕮','𫖯',],shā:['乷','唦','杀','桬','殺','毮','猀','痧','砂','硰','紗','繺','纱','蔱','裟','鎩','铩','閷','髿','魦','鯊','鯋','鲨',],nǎ:['乸','雫'],qián:['乹','亁','仱','偂','前','墘','媊','岒','拑','掮','榩','橬','歬','潛','潜','濳','灊','箝','葥','虔','軡','鈐','鉗','銭','錢','鎆','钤','钱','钳','靬','騚','騝','鰬','黔','黚',],suǒ:['乺','唢','嗩','所','暛','溑','溹','琐','琑','瑣','索','褨','鎖','鎻','鏁','锁',],yú:['乻','于','亐','伃','余','堣','堬','妤','娛','娯','娱','嬩','崳','嵎','嵛','愚','扵','揄','旟','楡','楰','榆','欤','歈','歟','歶','渔','渝','湡','漁','澞','牏','狳','玗','玙','瑜','璵','盂','睮','窬','竽','籅','羭','腴','臾','舁','舆','艅','茰','萮','萸','蕍','蘛','虞','虶','蝓','螸','衧','褕','覦','觎','諛','謣','谀','踰','輿','轝','逾','邘','酑','鍝','隅','雓','雩','餘','馀','騟','骬','髃','魚','魣','鮽','鯲','鰅','鱼','鷠','鸆','齵',],zhù:['乼','伫','佇','住','坾','墸','壴','嵀','拀','杼','柱','樦','殶','注','炷','疰','眝','祝','祩','竚','筯','箸','篫','簗','紵','紸','纻','羜','翥','苎','莇','蛀','註','貯','贮','跓','軴','鉒','鋳','鑄','铸','馵','駐','驻',],zhě:['乽','者','褶','襵','赭','踷','鍺','锗'],'qián gān':['乾'],'zhì luàn':['乿'],guī:['亀','圭','妫','媯','嫢','嬀','帰','归','摫','椝','槻','槼','櫷','歸','珪','瑰','璝','瓌','皈','瞡','硅','茥','蘬','規','规','邽','郌','閨','闺','騩','鬶','鬹',],'lǐn lìn':['亃'],jué:['亅','决','刔','劂','匷','厥','噊','孒','孓','崛','崫','嶥','彏','憠','憰','戄','抉','挗','掘','攫','桷','橛','橜','欮','氒','決','灍','焳','熦','爑','爴','爵','獗','玃','玦','玨','珏','瑴','瘚','矍','矡','砄','絕','絶','绝','臄','芵','蕝','蕨','虳','蟨','蟩','觖','觮','觼','訣','譎','诀','谲','貜','赽','趉','蹷','躩','鈌','鐍','鐝','钁','镢','鴂','鴃','鷢','𫘝','㵐','𫔎',],'le liǎo':['了'],'gè mā':['亇'],'yǔ yú':['予','懙'],zhēng:['争','佂','凧','姃','媜','峥','崝','崢','征','徰','炡','烝','爭','狰','猙','癥','眐','睁','睜','筝','箏','篜','聇','脀','蒸','踭','鉦','錚','鏳','鬇',],èr:['二','刵','咡','弍','弐','樲','誀','貮','貳','贰','髶'],chù:['亍','傗','儊','怵','憷','搐','斶','歜','珿','琡','矗','竌','絀','绌','臅','触','觸','豖','鄐','閦','黜',],kuī:['亏','刲','岿','巋','盔','窥','窺','聧','虧','闚','顝'],yún:['云','伝','勻','匀','囩','妘','愪','抣','昀','橒','沄','涢','溳','澐','熉','畇','秐','筼','篔','紜','縜','纭','耘','芸','蒷','蕓','郧','鄖','鋆','雲',],hù:['互','冱','嗀','嚛','婟','嫭','嫮','岵','帍','弖','怙','戶','户','戸','戽','扈','护','昈','槴','沍','沪','滬','熩','瓠','祜','笏','簄','粐','綔','蔰','護','豰','鄠','鍙','頀','鱯','鳠','鳸','鸌','鹱',],qí:['亓','剘','埼','岐','岓','崎','嵜','愭','掑','斉','斊','旂','旗','棊','棋','檱','櫀','歧','淇','濝','猉','玂','琦','琪','璂','畦','疧','碁','碕','祁','祈','祺','禥','竒','簯','簱','籏','粸','綥','綦','肵','脐','臍','艩','芪','萁','萕','蕲','藄','蘄','蚑','蚚','蛴','蜝','蜞','螧','蠐','褀','軝','鄿','釮','錡','锜','陭','頎','颀','騎','騏','騹','骐','骑','鬐','鬿','鯕','鰭','鲯','鳍','鵸','鶀','麒','麡','𨙸','𬨂','䓫',],jǐng:['井','儆','刭','剄','坓','宑','幜','憬','暻','殌','汫','汬','澋','璄','璟','璥','穽','肼','蟼','警','阱','頚','頸',],sì:['亖','佀','価','儩','兕','嗣','四','姒','娰','孠','寺','巳','柶','榹','汜','泗','泤','洍','洠','涘','瀃','牭','祀','禩','竢','笥','耜','肂','肆','蕼','覗','貄','釲','鈶','鈻','飤','飼','饲','駟','騃','驷',],suì:['亗','嬘','岁','嵗','旞','檖','歲','歳','澻','煫','燧','璲','砕','碎','祟','禭','穂','穗','穟','繀','繐','繸','襚','誶','譢','谇','賥','邃','鐆','鐩','隧','韢','𫟦','𬭼',],gèn:['亘','亙','揯','搄','茛'],yà:['亚','亜','俹','冴','劜','圔','圠','埡','娅','婭','揠','氩','氬','犽','砑','稏','聐','襾','覀','訝','讶','迓','齾',],'xiē suò':['些'],'qí zhāi':['亝','齊'],'yā yà':['亞','压','垭','壓','铔'],'jí qì':['亟','焏'],tóu:['亠','投','頭','骰'],'wáng wú':['亡'],'kàng háng gāng':['亢'],dà:['亣','眔'],jiāo:['交','僬','娇','嬌','峧','嶕','嶣','憍','椒','浇','澆','焦','礁','穚','簥','胶','膠','膲','茭','茮','蕉','虠','蛟','蟭','跤','轇','郊','鐎','驕','骄','鮫','鲛','鵁','鷦','鷮','鹪','䴔',],hài:['亥','嗐','害','氦','餀','饚','駭','駴','骇'],'hēng pēng':['亨'],mǔ:['亩','姆','峔','拇','母','牡','牳','畂','畆','畒','畝','畞','畮','砪','胟','踇','鉧','𬭁','𧿹',],ye:['亪'],xiǎng:['享','亯','响','想','晑','蚃','蠁','響','飨','餉','饗','饷','鮝','鯗','鱶','鲞',],jīng:['京','亰','兢','坕','坙','婛','惊','旌','旍','晶','橸','泾','涇','猄','睛','秔','稉','粳','精','経','經','綡','聙','腈','茎','荆','荊','菁','葏','驚','鯨','鲸','鶁','鶄','麖','麠','鼱','䴖',],tíng:['亭','停','婷','嵉','庭','廷','楟','榳','筳','聤','莛','葶','蜓','蝏','諪','邒','霆','鼮','䗴',],liàng:['亮','喨','悢','晾','湸','諒','谅','輌','輛','辆','鍄'],'qīn qìng':['亲','親'],bó:['亳','仢','侼','僰','博','帛','愽','懪','挬','搏','欂','浡','淿','渤','煿','牔','狛','瓝','礴','秡','箔','簙','糪','胉','脖','膊','舶','艊','萡','葧','袯','襏','襮','謈','踣','郣','鈸','鉑','鋍','鎛','鑮','钹','铂','镈','餺','馎','馛','馞','駁','駮','驳','髆','鵓','鹁',],yòu:['亴','佑','佦','侑','又','右','哊','唀','囿','姷','宥','峟','幼','狖','祐','蚴','誘','诱','貁','迶','酭','釉','鼬',],xiè:['亵','伳','偞','偰','僁','卨','卸','噧','塮','夑','媟','屑','屧','廨','徢','懈','暬','械','榍','榭','泻','洩','渫','澥','瀉','瀣','灺','炧','炨','燮','爕','獬','祄','禼','糏','紲','絏','絬','繲','纈','绁','缷','薢','薤','蟹','蠏','褉','褻','謝','谢','躞','邂','靾','韰','齂','齘','齛','齥','𬹼','𤫉',],'dǎn dàn':['亶','馾'],lián:['亷','劆','匲','匳','嗹','噒','奁','奩','嫾','帘','廉','怜','憐','涟','漣','濂','濓','瀮','熑','燫','簾','籢','籨','縺','翴','联','聨','聫','聮','聯','臁','莲','蓮','薕','螊','蠊','裢','褳','覝','謰','蹥','连','連','鎌','鐮','镰','鬑','鰱','鲢',],duǒ:['亸','哚','嚲','埵','崜','朵','朶','綞','缍','趓','躱','躲','軃',],'wěi mén':['亹','斖'],rén:['人','亻','仁','壬','忈','忎','朲','秂','芢','魜','鵀'],jí:['亼','亽','伋','佶','偮','卙','即','卽','及','叝','吉','堲','塉','姞','嫉','岌','嵴','嶯','彶','忣','急','愱','戢','揤','极','棘','楫','極','槉','檝','殛','汲','湒','潗','疾','瘠','皍','笈','箿','籍','級','级','膌','艥','蒺','蕀','蕺','蝍','螏','襋','觙','谻','踖','蹐','躤','輯','轚','辑','郆','銡','鍓','鏶','集','雧','霵','鹡','㴔',],wáng:['亾','仼','兦','莣','蚟'],'shén shí':['什'],lè:['仂','叻','忇','氻','泐','玏','砳','簕','艻','阞','韷','餎','鰳','鱳','鳓',],dīng:['仃','叮','帄','玎','疔','盯','耵','虰','靪'],zè:['仄','崱','庂','捑','昃','昗','汄'],'jǐn jìn':['仅','僅','嫤'],'pú pū':['仆'],'chóu qiú':['仇'],zhǎng:['仉','幥','掌','礃'],jīn:['今','堻','巾','惍','斤','津','珒','琻','璡','砛','筋','荕','衿','襟','觔','金','釒','釿','钅','鹶','黅','𬬱',],bīng:['仌','仒','兵','冫','冰','掤','氷','鋲'],réng:['仍','礽','芿','辸','陾'],fó:['仏','坲','梻'],'jīn sǎn':['仐'],lún:['仑','伦','侖','倫','囵','圇','婨','崘','崙','棆','沦','淪','磮','腀','菕','蜦','踚','輪','轮','錀','陯','鯩','𬬭',],cāng:['仓','仺','倉','凔','嵢','沧','滄','濸','獊','舱','艙','苍','蒼','螥','鸧',],'zǎi zǐ zī':['仔'],tā:['他','塌','它','榙','溻','牠','祂','褟','趿','遢','闧'],fù:['付','偩','傅','冨','副','咐','坿','复','妇','婦','媍','嬔','富','復','椱','祔','禣','竎','緮','縛','缚','腹','萯','蕧','蚹','蛗','蝜','蝮','袝','複','覄','覆','訃','詂','讣','負','賦','賻','负','赋','赙','赴','輹','鍑','鍢','阜','附','馥','駙','驸','鮒','鰒','鲋','鳆','㳇',],xiān:['仙','仚','佡','僊','僲','先','嘕','奾','屳','廯','忺','憸','掀','暹','杴','氙','珗','祆','秈','籼','繊','纎','纖','苮','褼','襳','跹','蹮','躚','酰','鍁','锨','韯','韱','馦','鱻','鶱','𬸣',],'tuō chà duó':['仛'],hóng:['仜','吰','垬','妅','娂','宏','宖','弘','彋','汯','泓','洪','浤','渱','潂','玒','玜','竑','竤','篊','粠','紘','紭','綋','纮','翃','翝','耾','苰','荭','葒','葓','谹','谼','鈜','鉷','鋐','閎','闳','霐','霟','鞃','魟','鴻','鸿','黉','黌','𫟹','𬭎',],tóng:['仝','佟','哃','峂','峝','庝','彤','晍','曈','桐','氃','浵','潼','犝','獞','眮','瞳','砼','秱','童','粡','膧','茼','蚒','詷','赨','酮','鉖','鉵','銅','铜','餇','鮦','鲖','𫍣','𦒍',],rèn:['仞','仭','刃','刄','妊','姙','屻','岃','扨','牣','祍','紉','紝','絍','纫','纴','肕','腍','衽','袵','訒','認','认','讱','軔','轫','鈓','靭','靱','韌','韧','飪','餁','饪',],qiān:['仟','佥','僉','千','圲','奷','孯','岍','悭','愆','慳','扦','拪','搴','撁','攐','攑','攓','杄','櫏','汘','汧','牵','牽','竏','签','簽','籖','籤','粁','芊','茾','蚈','褰','諐','謙','谦','谸','迁','遷','釺','鈆','鉛','鏲','钎','阡','韆','顅','騫','骞','鬜','鬝','鵮','鹐',],'gǎn hàn':['仠'],'yì gē':['仡'],dài:['代','侢','叇','垈','埭','岱','帒','带','帯','帶','廗','怠','戴','曃','柋','殆','瀻','玳','瑇','甙','簤','紿','緿','绐','艜','蝳','袋','襶','貣','贷','蹛','軑','軚','軩','轪','迨','霴','靆','鴏','黛','黱',],'lìng líng lǐng':['令'],chào:['仦','耖','觘'],'cháng zhǎng':['仧','兏','長','长'],sā:['仨'],cháng:['仩','偿','償','嘗','嚐','嫦','尝','常','徜','瑺','瓺','甞','肠','腸','膓','苌','萇','镸','鱨','鲿',],yí:['仪','侇','儀','冝','匜','咦','圯','夷','姨','宐','宜','宧','寲','峓','嶬','嶷','巸','彛','彜','彝','彞','怡','恞','扅','暆','栘','椬','椸','沂','洟','熪','瓵','痍','移','簃','籎','羠','胰','萓','蛦','螔','觺','謻','貽','贻','跠','迻','遺','鏔','頉','頤','頥','顊','颐','饴','鮧','鴺',],mù:['仫','凩','募','墓','幕','幙','慔','慕','暮','暯','木','楘','毣','沐','炑','牧','狇','目','睦','穆','艒','苜','莯','蚞','鉬','钼','雮','霂',],'men mén':['们'],fǎn:['仮','反','橎','返'],'chào miǎo':['仯'],'yǎng áng':['仰'],zhòng:['仲','众','堹','妕','媑','狆','眾','祌','筗','茽','蚛','衆','衶','諥',],'pǐ pí':['仳'],wò:['仴','偓','卧','媉','幄','握','楃','沃','渥','濣','瓁','瞃','硪','肟','腛','臥','齷','龌',],jiàn:['件','俴','健','僭','剑','剣','剱','劍','劎','劒','劔','墹','寋','建','徤','擶','旔','楗','毽','洊','涧','澗','牮','珔','瞷','磵','礀','箭','糋','繝','腱','臶','舰','艦','荐','薦','覸','諓','諫','譛','谏','賎','賤','贱','趝','践','踐','踺','轞','鉴','鍳','鍵','鐱','鑑','鑒','鑬','鑳','键','間','餞','饯','𬣡',],'jià jiè jie':['价'],'yǎo fó':['仸'],'rèn rén':['任'],'fèn bīn':['份'],dī:['仾','低','啲','埞','堤','岻','彽','樀','滴','磾','秪','羝','袛','趆','隄','鞮','䃅',],fǎng:['仿','倣','旊','昉','昘','瓬','眆','紡','纺','舫','訪','访','髣','鶭',],zhōng:['伀','刣','妐','幒','彸','忠','柊','汷','泈','炂','盅','籦','終','终','舯','蔠','蜙','螤','螽','衳','衷','蹱','鈡','鍾','鐘','钟','锺','鴤','鼨',],pèi:['伂','佩','姵','帔','斾','旆','沛','浿','珮','蓜','轡','辔','配','霈','馷',],diào:['伄','吊','弔','掉','瘹','盄','窎','窵','竨','訋','釣','鈟','銱','鋽','鑃','钓','铞','雿','魡',],dùn:['伅','潡','炖','燉','盾','砘','碷','踲','逇','遁','遯','鈍','钝',],wěn:['伆','刎','吻','呅','抆','桽','稳','穏','穩','紊','肳','脗'],xǐn:['伈'],kàng:['伉','匟','囥','抗','炕','鈧','钪'],ài:['伌','僾','塧','壒','嫒','嬡','愛','懓','暧','曖','爱','瑷','璦','皧','瞹','砹','硋','碍','礙','薆','譺','賹','鑀','隘','靉','餲','馤','鱫','鴱',],'jì qí':['伎','薺'],'xiū xǔ':['休'],'jìn yín':['伒'],dǎn:['伔','刐','撢','玬','瓭','紞','胆','膽','衴','賧','赕','黕','𬘘',],fū:['伕','呋','娐','孵','尃','怤','懯','敷','旉','玞','砆','稃','筟','糐','綒','肤','膚','荂','荴','衭','趺','跗','邞','鄜','酜','鈇','麩','麬','麱','麸','𫓧',],tǎng:['伖','傥','儻','埫','戃','曭','爣','矘','躺','鎲','钂','镋',],yōu:['优','優','呦','嚘','峳','幽','忧','悠','憂','攸','櫌','滺','瀀','纋','羪','耰','逌','鄾','麀',],huǒ:['伙','夥','火','煷','邩','鈥','钬'],'huì kuài':['会','會','浍','璯'],yǔ:['伛','俁','俣','偊','傴','匬','噳','圄','圉','宇','寙','屿','嶼','庾','挧','敔','斞','楀','瑀','瘐','祤','禹','穥','窳','羽','與','萭','貐','鄅','頨','麌','齬','龉','㺄',],cuì:['伜','啛','忰','悴','毳','淬','焠','疩','瘁','竁','粋','粹','紣','綷','翆','翠','脃','脆','脺','膬','膵','臎','萃','襊','顇',],sǎn:['伞','傘','糤','繖','饊','馓'],wěi:['伟','伪','偉','偽','僞','儰','娓','寪','屗','崣','嶉','徫','愇','捤','暐','梶','洧','浘','渨','炜','煒','猥','玮','瑋','痿','緯','纬','腲','艉','芛','苇','荱','萎','葦','蒍','蔿','蜼','諉','诿','踓','鍡','韑','韙','韡','韪','頠','颹','骩','骪','骫','鮪','鲔','𫇭','𬀩','𬱟',],'chuán zhuàn':['传','傳'],'chē jū':['伡','俥','车'],'jū chē':['車'],yá:['伢','厑','厓','堐','岈','崕','崖','涯','漄','牙','玡','琊','睚','笌','芽','蚜','衙','齖',],qiàn:['伣','俔','倩','儙','刋','壍','嬱','悓','棈','椠','槧','欠','歉','皘','篏','篟','縴','芡','蒨','蔳','輤','𬘬',],shāng:['伤','傷','商','墒','慯','殇','殤','滳','漡','熵','蔏','螪','觞','觴','謪','鬺',],chāng:['伥','倀','娼','昌','椙','淐','猖','琩','菖','裮','錩','锠','閶','阊','鯧','鲳','鼚',],'chen cāng':['伧'],xùn:['伨','侚','卂','噀','巺','巽','徇','愻','殉','殾','汛','潠','狥','蕈','訊','訓','訙','训','讯','迅','迿','逊','遜','鑂','顨','馴','驯',],xìn:['伩','囟','孞','脪','舋','衅','訫','釁','阠','顖'],chǐ:['伬','侈','卶','叺','呎','垑','恥','歯','耻','肔','胣','蚇','裭','褫','豉','鉹','齒','齿',],'xián xuán':['伭'],'nú nǔ':['伮'],'bó bǎi':['伯'],'gū gù':['估'],nǐ:['伱','你','儞','孴','拟','擬','旎','晲','狔','苨','薿','隬'],'nì ní':['伲'],bàn:['伴','办','半','姅','怑','扮','瓣','秚','絆','绊','辦','鉡','靽',],xù:['伵','侐','勖','勗','卹','叙','垿','壻','婿','序','恤','敍','敘','旭','昫','朂','槒','欰','殈','汿','沀','洫','溆','漵','潊','烅','烼','煦','獝','珬','盢','瞁','稸','絮','続','緒','緖','續','绪','续','聓','聟','蓄','藚','訹','賉','酗','頊','鱮','㳚',],zhòu:['伷','僽','冑','呪','咒','咮','宙','昼','晝','甃','皱','皺','籀','籒','籕','粙','紂','縐','纣','绉','胄','荮','葤','詋','酎','駎','驟','骤','㤘','㑇',],shēn:['伸','侁','兟','呻','堔','妽','娠','屾','峷','扟','敒','曑','柛','氠','深','燊','珅','甡','甧','申','眒','砷','穼','籶','籸','糂','紳','绅','罙','罧','葠','蓡','蔘','薓','裑','訷','詵','诜','身','駪','鯓','鯵','鰺','鲹','鵢','𬳽',],qū:['伹','佉','匤','呿','坥','屈','岖','岴','嶇','憈','抾','敺','浀','煀','祛','筁','粬','胠','蛆','蛐','袪','覻','詘','诎','趍','躯','軀','阹','駆','駈','驅','驱','髷','魼','鰸','鱋','鶌','麯','麴','麹','黢','㭕','𪨰','䓛',],'sì cì':['伺'],bēng:['伻','嘣','奟','崩','嵭','閍'],'sì shì':['似'],'jiā qié gā':['伽'],'yǐ chì':['佁'],'diàn tián':['佃','钿'],'hān gàn':['佄'],mài:['佅','劢','勱','卖','唛','売','脈','衇','賣','迈','邁','霡','霢','麥','麦','鿏',],dàn:['但','僤','啖','啗','啿','噉','嚪','帎','憺','旦','柦','氮','沊','泹','淡','狚','疍','癚','禫','窞','腅','萏','蓞','蛋','蜑','觛','訑','誕','诞','贉','霮','餤','饏','駳','髧','鴠','𫢸',],bù:['佈','勏','吥','咘','埗','埠','布','廍','怖','悑','步','歨','歩','瓿','篰','荹','蔀','踄','部','郶','鈈','钚','餢',],bǐ:['佊','俾','匕','夶','妣','彼','朼','柀','比','毞','沘','疕','秕','笔','筆','粃','聛','舭','貏','鄙',],'zhāo shào':['佋'],cǐ:['佌','此','泚','皉','𫚖'],wèi:['位','卫','味','喂','墛','媦','慰','懀','未','渭','煟','熭','犚','猬','畏','緭','罻','胃','苿','菋','藯','蘶','蝟','螱','衛','衞','褽','謂','讆','讏','谓','躗','躛','軎','轊','鏏','霨','餧','餵','饖','魏','鮇','鳚',],zuǒ:['佐','左','繓'],yǎng:['佒','傟','养','坱','岟','慃','懩','攁','氧','氱','炴','痒','癢','礢','紻','蝆','軮','養','駚',],'tǐ tī':['体','體'],zhàn:['佔','偡','嶘','战','戦','戰','栈','桟','棧','湛','站','綻','绽','菚','蘸','虥','虦','譧','轏','驏',],'hé hē hè':['何'],bì:['佖','咇','哔','嗶','坒','堛','壁','奰','妼','婢','嬖','币','幣','幤','庇','庳','廦','弊','弻','弼','彃','必','怭','愊','愎','敝','斃','梐','毕','毖','毙','湢','滗','滭','潷','煏','熚','狴','獘','獙','珌','璧','畀','畢','疪','痹','痺','皕','睤','碧','筚','箅','箆','篦','篳','粊','綼','縪','繴','罼','腷','苾','荜','萆','萞','蓖','蓽','蔽','薜','蜌','袐','襅','襞','襣','觱','詖','诐','貱','贔','赑','跸','蹕','躃','躄','避','邲','鄨','鄪','鉍','鏎','鐴','铋','閇','閉','閟','闭','陛','韠','飶','饆','馝','駜','驆','髀','魓','鮅','鷝','鷩','鼊',],tuó:['佗','坨','堶','岮','槖','橐','沱','砣','砤','碢','紽','詑','跎','酡','阤','陀','陁','駝','駞','騨','驒','驝','驼','鮀','鴕','鸵','鼉','鼍','鼧','𬶍',],shé:['佘','舌','虵','蛥'],'yì dié':['佚','昳','泆','軼'],'fó fú bì bó':['佛'],'zuò zuō':['作'],gōu:['佝','沟','溝','痀','篝','簼','緱','缑','袧','褠','鈎','鉤','钩','鞲','韝',],nìng:['佞','侫','倿','寕','泞','澝','濘'],qú:['佢','劬','戵','斪','欋','欔','氍','淭','灈','爠','璖','璩','癯','磲','籧','絇','胊','臞','菃','葋','蕖','蘧','蟝','蠷','蠼','衐','衢','躣','軥','鑺','鴝','鸜','鸲','鼩',],'yōng yòng':['佣'],wǎ:['佤','咓','砙','邷'],kǎ:['佧','垰','胩','裃','鉲'],bāo:['佨','勹','包','孢','煲','笣','胞','苞','蕔','裦','褒','襃','闁','齙','龅',],'huái huí':['佪'],'gé hè':['佫'],lǎo:['佬','咾','恅','栳','狫','珯','硓','老','耂','荖','蛯','轑','銠','铑','鮱',],xiáng:['佭','庠','栙','祥','絴','翔','詳','跭'],gé:['佮','匌','呄','嗝','塥','愅','挌','搿','槅','櫊','滆','膈','臵','茖','觡','諽','輵','轕','閣','阁','隔','鞷','韐','韚','騔','骼','鮯',],yáng:['佯','劷','垟','崸','徉','扬','揚','敭','旸','昜','暘','杨','楊','洋','炀','珜','疡','瘍','眻','蛘','諹','輰','鍚','钖','阦','阳','陽','霷','颺','飏','鰑','鴹','鸉',],bǎi:['佰','捭','摆','擺','栢','百','竡','粨','襬'],fǎ:['佱','峜','法','灋','砝','鍅'],mǐng:['佲','凕','姳','慏','酩'],'èr nài':['佴'],hěn:['佷','很','狠','詪','𬣳'],huó:['佸','活'],guǐ:['佹','匦','匭','厬','垝','姽','宄','庋','庪','恑','晷','湀','癸','祪','簋','蛫','蟡','觤','詭','诡','軌','轨','陒','鬼',],quán:['佺','全','啳','埢','姾','峑','巏','拳','搼','权','楾','権','權','泉','洤','湶','牷','犈','瑔','痊','硂','筌','縓','荃','葲','蜷','蠸','觠','詮','诠','跧','踡','輇','辁','醛','銓','铨','闎','顴','颧','駩','騡','鬈','鰁','鳈','齤',],tiāo:['佻','庣','旫','祧','聎'],jiǎo:['佼','儌','孂','挢','搅','撟','撹','攪','敫','敽','敿','晈','暞','曒','灚','燞','狡','璬','皎','皦','絞','纐','绞','腳','臫','蟜','譑','賋','踋','鉸','铰','餃','饺','鱎','龣',],cì:['佽','刾','庛','朿','栨','次','絘','茦','莿','蛓','螆','賜','赐',],xíng:['侀','刑','哘','型','娙','形','洐','硎','蛵','邢','郉','鈃','鉶','銒','钘','铏','陉','陘','餳','𫰛',],tuō:['侂','咃','咜','圫','托','拕','拖','汑','脫','脱','莌','袥','託','讬','飥','饦','魠','鮵',],kǎn:['侃','偘','冚','坎','惂','砍','莰','輡','轗','顑'],zhí:['侄','値','值','埴','執','姪','嬂','戠','执','摭','植','樴','淔','漐','直','禃','絷','縶','聀','职','職','膱','蟙','跖','踯','蹠','躑','軄','釞','馽',],gāi:['侅','垓','姟','峐','晐','畡','祴','荄','該','该','豥','賅','賌','赅','陔',],lái:['來','俫','倈','崃','崍','庲','来','梾','棶','涞','淶','猍','琜','筙','箂','莱','萊','逨','郲','錸','铼','騋','鯠','鶆','麳',],kuǎ:['侉','咵','垮','銙'],gōng:['侊','公','功','匑','匔','塨','宫','宮','工','幊','弓','恭','攻','杛','碽','糼','糿','肱','觥','觵','躬','躳','髸','龔','龚','䢼',],lì:['例','俐','俪','傈','儮','儷','凓','利','力','励','勵','历','厉','厤','厯','厲','叓','吏','呖','唎','唳','嚦','囇','坜','塛','壢','娳','婯','屴','岦','悧','悷','慄','戾','搮','暦','曆','曞','朸','枥','栃','栗','栛','檪','櫔','櫪','欐','歴','歷','沥','沴','涖','溧','濿','瀝','爏','犡','猁','珕','瑮','瓅','瓑','瓥','疬','痢','癧','盭','睙','砅','砺','砾','磿','礪','礫','礰','禲','秝','立','笠','篥','粒','粝','糲','脷','苈','茘','荔','莅','莉','蒚','蒞','藶','蚸','蛎','蛠','蜧','蝷','蠇','蠣','詈','讈','赲','轢','轣','轹','酈','鉝','隶','隷','雳','靂','靋','鬁','鳨','鴗','鷅','麜','𫵷','𬍛',],yīn:['侌','凐','喑','噾','囙','因','垔','堙','姻','婣','愔','慇','栶','氤','洇','溵','濦','瘖','禋','秵','筃','絪','緸','茵','蒑','蔭','裀','諲','銦','铟','闉','阥','阴','陰','陻','隂','霒','霠','鞇','音','韾','駰','骃','齗','𬘡','𬤇','𬮱',],mǐ:['侎','孊','弭','敉','洣','渳','灖','米','粎','羋','脒','芈','葞','蔝','銤',],zhū:['侏','株','槠','橥','櫧','櫫','洙','潴','瀦','猪','珠','硃','秼','絑','茱','蕏','蛛','蝫','蠩','袾','誅','諸','诛','诸','豬','跦','邾','銖','铢','駯','鮢','鯺','鴸','鼄',],ān:['侒','偣','媕','安','峖','庵','桉','氨','盦','盫','腤','菴','萻','葊','蓭','誝','諳','谙','鞌','鞍','韽','馣','鮟','鵪','鶕','鹌','𩽾',],lù:['侓','僇','勎','勠','圥','坴','塶','娽','峍','廘','彔','录','戮','摝','椂','樚','淕','淥','渌','漉','潞','琭','璐','甪','盝','睩','硉','祿','禄','稑','穋','箓','簏','簬','簵','簶','籙','粶','蔍','蕗','虂','螰','賂','赂','趢','路','踛','蹗','輅','轆','辂','辘','逯','醁','錄','録','錴','鏴','陸','騄','騼','鯥','鴼','鵦','鵱','鷺','鹭','鹿','麓','𫘧',],móu:['侔','劺','恈','眸','蛑','謀','谋','踎','鍪','鴾','麰'],ér:['侕','儿','児','兒','峏','栭','洏','粫','而','胹','荋','袻','輀','轜','陑','隭','髵','鮞','鲕','鴯','鸸',],'dòng tǒng tóng':['侗'],chà:['侘','奼','姹','岔','汊','詫','诧'],chì:['侙','傺','勅','勑','叱','啻','彳','恜','慗','憏','懘','抶','敕','斥','杘','湁','灻','炽','烾','熾','痓','痸','瘛','翄','翅','翤','翨','腟','赤','趩','遫','鉓','雴','飭','饬','鶒','鷘',],'gòng gōng':['供','共'],zhōu:['侜','周','喌','州','徟','洲','淍','炿','烐','珘','矪','舟','謅','譸','诌','賙','赒','輈','輖','辀','週','郮','銂','霌','駲','騆','鵃','鸼',],rú:['侞','儒','嚅','如','嬬','孺','帤','曘','桇','渪','濡','筎','茹','蕠','薷','蝡','蠕','袽','襦','邚','醹','銣','铷','顬','颥','鱬','鴑','鴽',],'jiàn cún':['侟'],xiá:['侠','俠','匣','峡','峽','敮','暇','柙','炠','烚','狎','狭','狹','珨','瑕','硖','硤','碬','祫','筪','縖','翈','舝','舺','蕸','赮','轄','辖','遐','鍜','鎋','陜','陿','霞','騢','魻','鶷','黠',],lǚ:['侣','侶','儢','吕','呂','屡','屢','履','挔','捛','旅','梠','焒','祣','稆','穭','絽','縷','缕','膂','膐','褛','褸','郘','鋁','铝',],ta:['侤'],'jiǎo yáo':['侥','僥','徺'],zhēn:['侦','偵','寊','帧','帪','幀','搸','斟','桢','楨','榛','樼','殝','浈','湞','潧','澵','獉','珍','珎','瑧','甄','眞','真','砧','碪','祯','禎','禛','箴','胗','臻','葴','蒖','蓁','薽','貞','贞','轃','遉','酙','針','鉁','錱','鍼','针','鱵',],'cè zè zhāi':['侧','側'],kuài:['侩','儈','凷','哙','噲','圦','块','塊','巜','廥','快','旝','欳','狯','獪','筷','糩','脍','膾','郐','鄶','鱠','鲙',],chái:['侪','儕','喍','柴','犲','祡','豺'],nóng:['侬','儂','农','哝','噥','檂','欁','浓','濃','燶','禯','秾','穠','脓','膿','蕽','襛','譨','農','辳','醲','鬞','𬪩',],jǐn:['侭','儘','卺','厪','巹','槿','漌','瑾','紧','緊','菫','蓳','謹','谨','錦','锦','饉','馑',],'hóu hòu':['侯','矦'],jiǒng:['侰','僒','冏','囧','泂','澃','炯','烱','煚','煛','熲','燛','窘','綗','褧','迥','逈','顈','颎','䌹',],'chěng tǐng':['侱'],'zhèn zhēn':['侲','揕'],zuò:['侳','做','唑','坐','岝','岞','座','祚','糳','胙','葃','葄','蓙','袏','阼',],qīn:['侵','兓','媇','嵚','嶔','欽','衾','誛','钦','顉','駸','骎','鮼',],jú:['侷','啹','婅','局','巈','椈','橘','泦','淗','湨','焗','犑','狊','粷','菊','蘜','趜','跼','蹫','輂','郹','閰','駶','驧','鵙','鵴','鶪','鼰','鼳','䴗',],'shù dōu':['侸'],tǐng:['侹','圢','娗','挺','涏','烶','珽','脡','艇','誔','頲','颋',],shèn:['侺','愼','慎','昚','涁','渗','滲','瘆','瘮','眘','祳','肾','胂','脤','腎','蜃','蜄','鋠',],'tuì tuó':['侻'],nán:['侽','喃','娚','抩','暔','枏','柟','楠','男','畘','莮','萳','遖',],xiāo:['侾','哓','嘵','嚻','囂','婋','宯','宵','庨','彇','揱','枭','枵','梟','櫹','歊','毊','消','潇','瀟','灱','灲','烋','焇','猇','獢','痚','痟','硝','硣','窙','箫','簘','簫','綃','绡','翛','膮','萧','蕭','虈','虓','蟂','蟏','蟰','蠨','踃','逍','銷','销','霄','颵','驍','骁','髇','髐','魈','鴞','鴵','鷍','鸮',],'biàn pián':['便','緶','缏'],tuǐ:['俀','腿','蹆','骽'],xì:['係','匸','卌','呬','墍','屃','屓','屭','忥','怬','恄','椞','潝','潟','澙','熂','犔','磶','禊','細','綌','縘','细','绤','舃','舄','蕮','虩','衋','覤','赩','趇','郤','釳','阋','隙','隟','霼','餼','饩','鬩','黖',],cù:['促','媨','憱','猝','瘄','瘯','簇','縬','脨','蔟','誎','趗','踧','踿','蹙','蹴','蹵','醋','顣','鼀',],é:['俄','囮','娥','峉','峨','峩','涐','珴','皒','睋','磀','莪','訛','誐','譌','讹','迗','鈋','鋨','锇','頟','額','额','魤','鵝','鵞','鹅',],qiú:['俅','叴','唒','囚','崷','巯','巰','扏','梂','殏','毬','求','汓','泅','浗','湭','煪','犰','玌','球','璆','皳','盚','紌','絿','肍','芁','莍','虬','虯','蛷','裘','觓','觩','訄','訅','賕','赇','逎','逑','遒','酋','釚','釻','銶','頄','鮂','鯄','鰽','鼽','𨱇',],xú:['俆','徐','禑'],'guàng kuāng':['俇'],kù:['俈','喾','嚳','库','庫','廤','瘔','絝','绔','袴','裤','褲','酷',],wù:['俉','务','務','勿','卼','坞','塢','奦','婺','寤','屼','岉','嵨','忢','悞','悟','悮','戊','扤','晤','杌','溩','焐','熃','物','痦','矹','窹','粅','蘁','誤','误','鋈','阢','隖','雾','霚','霧','靰','騖','骛','鶩','鹜','鼿','齀',],jùn:['俊','儁','呁','埈','寯','峻','懏','捃','攟','晙','棞','燇','珺','畯','竣','箟','蜠','賐','郡','陖','餕','馂','駿','骏','鵔','鵕','鵘','䐃',],liáng:['俍','墚','梁','椋','樑','粮','粱','糧','良','輬','辌','𫟅',],zǔ:['俎','唨','爼','祖','組','组','詛','诅','鎺','阻','靻'],'qiào xiào':['俏'],yǒng:['俑','勇','勈','咏','埇','塎','嵱','彮','怺','恿','悀','惥','愑','愹','慂','柡','栐','永','泳','湧','甬','蛹','詠','踊','踴','鯒','鲬',],hùn:['俒','倱','圂','尡','慁','掍','溷','焝','睴','觨','諢','诨'],jìng:['俓','傹','境','妌','婙','婧','弪','弳','径','徑','敬','曔','桱','梷','浄','瀞','獍','痉','痙','竞','竟','竫','競','竸','胫','脛','莖','誩','踁','迳','逕','鏡','镜','靖','静','靜','鵛',],sàn:['俕','閐'],pěi:['俖'],sú:['俗'],xī:['俙','僖','兮','凞','卥','厀','吸','唏','唽','嘻','噏','嚱','夕','奚','嬆','嬉','屖','嵠','巇','希','徆','徯','息','悉','悕','惁','惜','昔','晞','晰','晳','曦','析','桸','榽','樨','橀','欷','氥','汐','浠','淅','渓','溪','烯','焁','焈','焟','熄','熈','熙','熹','熺','熻','燨','爔','牺','犀','犠','犧','琋','瘜','皙','睎','瞦','矽','硒','磎','礂','稀','穸','窸','粞','糦','緆','繥','羲','翕','翖','肸','肹','膝','舾','莃','菥','蒠','蜥','螅','蟋','蠵','西','觹','觽','觿','譆','谿','豀','豨','豯','貕','赥','邜','鄎','酅','醯','釸','錫','鏭','鐊','鑴','锡','隵','餏','饎','饻','鯑','鵗','鸂','鼷',],lǐ:['俚','娌','峢','峲','李','欚','浬','澧','理','礼','禮','粴','裏','裡','豊','逦','邐','醴','鋰','锂','鯉','鱧','鱱','鲤','鳢',],bǎo:['保','堢','媬','宝','寚','寳','寶','珤','緥','葆','藵','褓','賲','靌','飹','飽','饱','駂','鳵','鴇','鸨',],'yú shù yù':['俞'],'sì qí':['俟'],'xìn shēn':['信'],xiū:['俢','修','咻','庥','樇','烌','羞','脙','脩','臹','貅','銝','鎀','飍','饈','馐','髤','髹','鮴','鱃','鵂','鸺','䗛',],dì:['俤','偙','僀','埊','墑','墬','娣','帝','怟','旳','梊','焍','玓','甋','眱','睇','碲','祶','禘','第','締','缔','腣','菂','蒂','蔕','蝃','蝭','螮','諦','谛','踶','递','逓','遞','遰','鉪','𤧛','䗖',],chóu:['俦','儔','嬦','惆','愁','懤','栦','燽','畴','疇','皗','稠','筹','籌','絒','綢','绸','菗','詶','讎','讐','踌','躊','酧','酬','醻','雔','雠','雦',],zhì:['俧','偫','儨','制','劕','垁','娡','寘','帙','帜','幟','庢','庤','廌','彘','徏','徝','志','忮','懥','懫','挃','挚','掷','摯','擲','旘','晊','智','栉','桎','梽','櫍','櫛','治','洷','滍','滞','滯','潌','瀄','炙','熫','狾','猘','璏','瓆','痔','痣','礩','祑','秩','秷','稚','稺','穉','窒','紩','緻','置','翐','膣','至','致','芖','蛭','袟','袠','製','覟','觗','觯','觶','誌','豑','豒','貭','質','贄','质','贽','跱','踬','躓','輊','轾','郅','銍','鋕','鑕','铚','锧','陟','隲','雉','駤','騭','騺','驇','骘','鯯','鴙','鷙','鸷','𬃊',],'liǎ liǎng':['俩'],jiǎn:['俭','倹','儉','减','剪','堿','弿','彅','戩','戬','拣','挸','捡','揀','撿','枧','柬','梘','检','検','檢','減','湕','瀽','瑐','睑','瞼','硷','碱','礆','笕','筧','简','簡','絸','繭','翦','茧','藆','蠒','裥','襇','襉','襺','詃','謇','謭','譾','谫','趼','蹇','鐗','鬋','鰎','鹸','鹻','鹼',],huò:['俰','咟','嚯','嚿','奯','彠','惑','或','擭','旤','曤','檴','沎','湱','瀖','獲','癨','眓','矐','祸','禍','穫','窢','耯','臛','艧','获','蒦','藿','蠖','謋','貨','货','鍃','鑊','镬','雘','霍','靃','韄','㸌',],'jù jū':['俱','据','鋸','锯'],xiào:['俲','傚','効','咲','哮','啸','嘋','嘨','嘯','孝','效','斅','斆','歗','涍','熽','笑','詨','誟',],pái:['俳','徘','牌','犤','猅','簰','簲','輫'],biào:['俵','鰾','鳔'],'chù tì':['俶'],fèi:['俷','剕','厞','吠','屝','废','廃','廢','昲','曊','櫠','沸','濷','狒','癈','肺','萉','費','费','鐨','镄','陫','靅','鼣',],fèng:['俸','凤','奉','湗','焨','煈','賵','赗','鳯','鳳','鴌'],ǎn:['俺','唵','埯','揞','罯','銨','铵'],bèi:['俻','倍','偝','偹','備','僃','备','悖','惫','愂','憊','昁','梖','焙','牬','犕','狈','狽','珼','琲','碚','禙','糒','苝','蓓','蛽','褙','貝','贝','軰','輩','辈','邶','郥','鄁','鋇','鐾','钡','鞁','鞴','𬇙',],yù:['俼','儥','喅','喩','喻','域','堉','妪','嫗','寓','峪','嶎','庽','彧','御','愈','慾','戫','昱','棛','棜','棫','櫲','欎','欝','欲','毓','浴','淯','滪','潏','澦','灪','焴','煜','燏','燠','爩','狱','獄','玉','琙','瘉','癒','砡','硢','硲','礇','礖','礜','禦','秗','稢','稶','篽','籞','籲','粖','緎','罭','聿','肀','艈','芋','芌','茟','蒮','蓣','蓹','蕷','蘌','蜟','蜮','袬','裕','誉','諭','譽','谕','豫','軉','輍','逳','遇','遹','郁','醧','鈺','鋊','錥','鐭','钰','閾','阈','雤','霱','預','预','飫','饇','饫','馭','驈','驭','鬰','鬱','鬻','魊','鱊','鳿','鴥','鴧','鴪','鵒','鷸','鸒','鹆','鹬',],xīn:['俽','噺','妡','嬜','廞','心','忄','忻','惞','新','昕','杺','欣','歆','炘','盺','薪','訢','辛','邤','鈊','鋅','鑫','锌','馨','馫','䜣','𫷷',],'hǔ chí':['俿'],jiù:['倃','僦','匓','匛','匶','厩','咎','就','廄','廏','廐','慦','捄','救','旧','柩','柾','桕','欍','殧','疚','臼','舅','舊','鯦','鷲','鹫','麔','齨','㠇',],yáo:['倄','傜','嗂','垚','堯','姚','媱','尧','尭','峣','嶢','嶤','徭','揺','搖','摇','摿','暚','榣','烑','爻','猺','珧','瑤','瑶','磘','窑','窯','窰','肴','蘨','謠','謡','谣','軺','轺','遙','遥','邎','顤','颻','飖','餆','餚','鰩','鱙','鳐',],'cuì zú':['倅'],'liǎng liǎ':['倆'],wǎn:['倇','唍','婉','惋','挽','晚','晥','晩','晼','梚','椀','琬','畹','皖','盌','碗','綩','綰','绾','脘','萖','踠','輓','鋔',],zǒng:['倊','偬','傯','嵸','总','惣','捴','搃','摠','燪','総','緫','縂','總','蓗',],guān:['倌','关','官','棺','瘝','癏','窤','蒄','関','闗','關','鰥','鱞','鳏',],tiǎn:['倎','唺','忝','悿','晪','殄','淟','睓','腆','舔','覥','觍','賟','錪','餂',],mén:['們','扪','捫','璊','菛','虋','鍆','钔','門','閅','门','𫞩'],'dǎo dào':['倒'],'tán tàn':['倓','埮'],'juè jué':['倔'],chuí:['倕','垂','埀','捶','搥','桘','棰','槌','箠','腄','菙','錘','鎚','锤','陲','顀',],xìng:['倖','姓','婞','嬹','幸','性','悻','杏','涬','緈','臖','荇','莕','葕',],péng:['倗','傰','塜','塳','弸','憉','捀','朋','棚','椖','樥','硼','稝','竼','篷','纄','膨','芃','蓬','蘕','蟚','蟛','袶','輣','錋','鑝','韸','韼','騯','髼','鬅','鬔','鵬','鹏',],'tǎng cháng':['倘'],hòu:['候','厚','后','垕','堠','後','洉','茩','豞','逅','郈','鮜','鱟','鲎','鲘',],tì:['倜','剃','嚏','嚔','屉','屜','悌','悐','惕','惖','戻','掦','替','朑','歒','殢','涕','瓋','笹','籊','薙','褅','逖','逷','髰','鬀','鬄',],gàn:['倝','凎','幹','榦','檊','淦','灨','盰','紺','绀','詌','贑','赣','骭','㽏',],'liàng jìng':['倞','靓'],suī:['倠','哸','夊','滖','濉','眭','睢','芕','荽','荾','虽','雖','鞖',],'chàng chāng':['倡'],jié:['倢','偼','傑','刦','刧','刼','劫','劼','卩','卪','婕','媫','孑','岊','崨','嵥','嶻','巀','幯','截','捷','掶','擮','昅','杢','杰','桀','桝','楬','楶','榤','洁','滐','潔','狤','睫','礍','竭','節','羯','莭','蓵','蛣','蜐','蠘','蠞','蠽','衱','袺','訐','詰','誱','讦','踕','迼','鉣','鍻','镼','頡','鮚','鲒','㛃',],'kǒng kōng':['倥'],juàn:['倦','劵','奆','慻','桊','淃','狷','獧','眷','睊','睠','絭','絹','绢','罥','羂','腃','蔨','鄄','餋',],zōng:['倧','堫','宗','嵏','嵕','惾','朡','棕','椶','熧','猣','磫','緃','翪','腙','葼','蝬','豵','踨','踪','蹤','鍐','鑁','騌','騣','骔','鬃','鬉','鬷','鯮','鯼',],ní:['倪','坭','埿','尼','屔','怩','淣','猊','籾','聣','蚭','蜺','觬','貎','跜','輗','郳','鈮','铌','霓','馜','鯢','鲵','麑','齯','𫐐','𫠜',],zhuō:['倬','拙','捉','桌','梲','棁','棳','槕','涿','窧','鐯','䦃',],'wō wēi':['倭'],luǒ:['倮','剆','曪','瘰','癳','臝','蓏','蠃','裸','躶'],sōng:['倯','凇','娀','崧','嵩','庺','憽','松','枀','枩','柗','梥','檧','淞','濍','硹','菘','鬆',],lèng:['倰','堎','愣','睖','踜'],zì:['倳','剚','字','恣','渍','漬','牸','眥','眦','胔','胾','自','茡','荢',],bèn:['倴','坌','捹','撪','渀','笨','逩'],cǎi:['倸','啋','婇','彩','採','棌','毝','睬','綵','跴','踩'],zhài:['债','債','寨','瘵','砦'],yē:['倻','吔','噎','擨','暍','椰','歋','潱','蠮'],shà:['倽','唼','喢','歃','箑','翜','翣','萐','閯','霎'],qīng:['倾','傾','卿','圊','寈','氢','氫','淸','清','蜻','軽','輕','轻','郬','錆','鑋','靑','青','鯖',],yīng:['偀','嘤','噟','嚶','婴','媖','嫈','嬰','孆','孾','愥','撄','攖','朠','桜','樱','櫻','渶','煐','珱','瑛','璎','瓔','甇','甖','碤','礯','緓','纓','绬','缨','罂','罃','罌','膺','英','莺','蘡','蝧','蠳','褮','譻','賏','軈','鑍','锳','霙','韺','鴬','鶑','鶧','鶯','鷪','鷹','鸎','鸚','鹦','鹰','䓨',],'chēng chèn':['偁','爯'],ruǎn:['偄','朊','瑌','瓀','碝','礝','腝','軟','輭','软','阮'],'zhòng tóng':['偅'],chǔn:['偆','惷','睶','萶','蠢','賰'],'jiǎ jià':['假'],'jì jié':['偈'],'bǐng bìng':['偋'],ruò:['偌','叒','嵶','弱','楉','焫','爇','箬','篛','蒻','鄀','鰙','鰯','鶸',],tí:['偍','厗','啼','嗁','崹','漽','瑅','睼','禵','稊','緹','缇','罤','蕛','褆','謕','趧','蹄','蹏','醍','鍗','題','题','騠','鮷','鯷','鳀','鵜','鷤','鹈','𫘨',],wēi:['偎','危','喴','威','媙','嶶','巍','微','愄','揋','揻','椳','楲','溦','烓','煨','燰','癓','縅','葨','葳','薇','蜲','蝛','覣','詴','逶','隇','隈','霺','鰃','鰄','鳂',],piān:['偏','囨','媥','楄','犏','篇','翩','鍂'],yàn:['偐','厌','厭','唁','喭','嚈','嚥','堰','妟','姲','嬊','嬿','宴','彥','彦','敥','晏','暥','曕','曣','滟','灎','灔','灧','灩','焔','焰','焱','熖','燄','牪','猒','砚','硯','艳','艶','艷','覎','觃','觾','諺','讌','讞','谚','谳','豓','豔','贋','贗','赝','軅','酀','酽','醼','釅','雁','餍','饜','騐','験','騴','驗','驠','验','鬳','鳫','鴈','鴳','鷃','鷰','齞',],'tǎng dàng':['偒'],è:['偔','匎','卾','厄','呝','咢','噩','垩','堊','堮','岋','崿','廅','悪','愕','戹','扼','搤','搹','擜','櫮','歞','歺','湂','琧','砈','砐','硆','腭','苊','萼','蕚','蚅','蝁','覨','諤','讍','谔','豟','軛','軶','轭','遌','遏','遻','鄂','鈪','鍔','鑩','锷','阨','阸','頞','顎','颚','餓','餩','饿','鰐','鰪','鱷','鳄','鶚','鹗','齃','齶','𫫇','𥔲',],xié:['偕','勰','协','協','嗋','垥','奊','恊','愶','拹','携','撷','擕','擷','攜','斜','旪','熁','燲','綊','緳','縀','缬','翓','胁','脅','脇','脋','膎','蝢','衺','襭','諧','讗','谐','鞋','鞵','龤','㙦',],chě:['偖','扯','撦'],shěng:['偗','渻','眚'],chā:['偛','嗏','扠','挿','插','揷','疀','臿','艖','銟','鍤','锸','餷',],huáng:['偟','凰','喤','堭','墴','媓','崲','徨','惶','楻','湟','煌','獚','瑝','璜','癀','皇','磺','穔','篁','簧','艎','葟','蝗','蟥','諻','趪','遑','鍠','鐄','锽','隍','韹','餭','騜','鰉','鱑','鳇','鷬','黃','黄','𨱑',],yǎo:['偠','咬','婹','宎','岆','杳','柼','榚','溔','狕','窅','窈','舀','苭','闄','騕','鷕','齩',],'chǒu qiào':['偢'],yóu:['偤','尤','庮','怣','沋','油','浟','游','犹','猶','猷','由','疣','秞','肬','莜','莸','蕕','蚰','蝣','訧','輏','輶','逰','遊','邮','郵','鈾','铀','駀','魷','鮋','鱿','鲉','𬨎',],xū:['偦','墟','媭','嬃','楈','欨','歔','燸','疞','盱','綇','縃','繻','胥','蕦','虗','虚','虛','蝑','裇','訏','許','諝','譃','谞','鑐','需','須','须','顼','驉','鬚','魆','魖','𬣙','𦈡',],zhā:['偧','哳','抯','挓','揸','摣','樝','渣','皶','觰','譇','齄','齇',],cī:['偨','疵','蠀','趀','骴','髊','齹'],bī:['偪','屄','楅','毴','豍','逼','鰏','鲾','鵖'],xún:['偱','噚','寻','尋','峋','巡','廵','循','恂','揗','攳','旬','杊','栒','桪','樳','洵','浔','潯','燅','燖','珣','璕','畃','紃','荀','蟳','詢','询','鄩','鱏','鱘','鲟','𬘓','𬩽','𬍤','𬊈',],'cāi sī':['偲'],duān:['偳','媏','端','褍','鍴'],ǒu:['偶','吘','嘔','耦','腢','蕅','藕','𬉼','𠙶'],tōu:['偷','偸','鍮'],'zán zá zǎ':['偺'],'lǚ lóu':['偻','僂'],fèn:['偾','僨','奋','奮','弅','忿','愤','憤','瀵','瞓','秎','粪','糞','膹','鱝','鲼',],'kuǐ guī':['傀'],sǒu:['傁','叜','叟','嗾','櫢','瞍','薮','藪'],'zhì sī tí':['傂'],sù:['傃','僳','嗉','塐','塑','夙','嫊','愫','憟','榡','樎','樕','殐','泝','涑','溯','溸','潚','潥','玊','珟','璛','簌','粛','粟','素','縤','肃','肅','膆','蔌','藗','觫','訴','謖','诉','谡','趚','蹜','速','遡','遬','鋉','餗','驌','骕','鱐','鷫','鹔','𫗧',],xiā:['傄','煆','瞎','虲','谺','颬','鰕'],'yuàn yuán':['傆','媛'],rǒng:['傇','冗','宂','氄','軵'],nù:['傉','怒'],yùn:['傊','孕','恽','惲','愠','慍','枟','腪','蕴','薀','藴','蘊','褞','貟','运','運','郓','鄆','酝','醖','醞','韗','韞','韵','韻','餫',],'gòu jiǎng':['傋'],mà:['傌','嘜','榪','睰','祃','禡','罵','閁','駡','骂','鬕'],bàng:['傍','塝','棒','玤','稖','艕','蒡','蜯','謗','谤','鎊','镑',],diān:['傎','厧','嵮','巅','巓','巔','掂','攧','敁','槇','滇','癫','癲','蹎','顚','顛','颠','齻',],táng:['傏','唐','啺','坣','堂','塘','搪','棠','榶','溏','漟','煻','瑭','磄','禟','篖','糃','糖','糛','膅','膛','蓎','螗','螳','赯','踼','鄌','醣','鎕','隚','餹','饄','鶶','䣘',],hào:['傐','哠','恏','昊','昦','晧','暠','暤','暭','曍','浩','淏','澔','灏','灝','皓','皜','皞','皡','皥','耗','聕','薃','號','鄗','顥','颢','鰝',],'xī xì':['傒'],shān:['傓','删','刪','剼','圸','山','挻','搧','柵','檆','潸','澘','煽','狦','珊','笘','縿','羴','羶','脠','舢','芟','衫','跚','軕','邖','閊','鯅',],'qiàn jiān':['傔'],'què jué':['傕','埆'],'cāng chen':['傖'],róng:['傛','媶','嫆','嬫','容','峵','嵘','嶸','戎','搈','曧','栄','榕','榮','榵','毧','溶','瀜','烿','熔','狨','瑢','穁','絨','绒','羢','肜','茙','茸','荣','蓉','蝾','融','螎','蠑','褣','鎔','镕','駥',],'tà tàn':['傝'],suō:['傞','唆','嗍','嗦','娑','摍','桫','梭','睃','簑','簔','羧','莏','蓑','趖','鮻',],dǎi:['傣','歹'],zài:['傤','儎','再','在','扗','洅','載','酨'],gǔ:['傦','古','啒','尳','愲','榖','榾','汩','淈','濲','瀔','牯','皷','皼','盬','瞽','穀','罟','羖','股','脵','臌','薣','蛊','蠱','詁','诂','轂','逧','鈷','钴','餶','馉','鼓','鼔','𦙶',],bīn:['傧','宾','彬','斌','椕','滨','濒','濱','濵','瀕','繽','缤','虨','豩','豳','賓','賔','邠','鑌','镔','霦','顮',],chǔ:['储','儲','杵','椘','楚','楮','檚','濋','璴','础','礎','禇','處','齭','齼','𬺓',],nuó:['傩','儺','挪','梛','橠'],'cān càn':['傪'],lěi:['傫','儡','厽','垒','塁','壘','壨','櫐','灅','癗','矋','磊','礨','耒','蕌','蕾','藟','蘽','蠝','誄','讄','诔','鑸','鸓',],cuī:['催','凗','墔','崔','嵟','慛','摧','榱','獕','磪','鏙'],yōng:['傭','嗈','墉','壅','嫞','庸','廱','慵','拥','擁','滽','灉','牅','痈','癕','癰','臃','邕','郺','鄘','鏞','镛','雍','雝','饔','鱅','鳙','鷛',],'zāo cáo':['傮'],sǒng:['傱','嵷','怂','悚','愯','慫','竦','耸','聳','駷','㧐'],ào:['傲','坳','垇','墺','奡','嫯','岙','岰','嶴','懊','擙','澳','鏊','驁','骜',],'qī còu':['傶'],chuǎng:['傸','磢','闖','闯'],shǎ:['傻','儍'],hàn:['傼','垾','悍','憾','扞','捍','撖','撼','旱','晘','暵','汉','涆','漢','瀚','焊','猂','皔','睅','翰','莟','菡','蛿','蜭','螒','譀','輚','釬','銲','鋎','雗','頷','顄','颔','駻','鶾',],zhāng:['傽','嫜','张','張','彰','慞','暲','樟','漳','獐','璋','章','粻','蔁','蟑','遧','鄣','鏱','餦','騿','鱆','麞',],'yān yàn':['傿','墕','嬮'],'piào biāo':['僄','骠'],liàn:['僆','堜','媡','恋','戀','楝','殓','殮','湅','潋','澰','瀲','炼','煉','瑓','練','纞','练','萰','錬','鍊','鏈','链','鰊','𬶠',],màn:['㵘','僈','墁','幔','慢','曼','漫','澷','熳','獌','縵','缦','蔄','蘰','鄤','鏝','镘','𬜬',],'tàn tǎn':['僋'],yíng:['僌','営','塋','嬴','攍','楹','櫿','溁','溋','滢','潆','濙','濚','濴','瀅','瀛','瀠','瀯','灐','灜','熒','營','瑩','盁','盈','禜','籝','籯','縈','茔','荧','莹','萤','营','萦','萾','蓥','藀','蛍','蝇','蝿','螢','蠅','謍','贏','赢','迎','鎣',],dòng:['働','冻','凍','动','動','姛','戙','挏','栋','棟','湩','硐','胨','胴','腖','迵','霘','駧',],zhuàn:['僎','啭','囀','堟','撰','灷','瑑','篆','腞','蒃','襈','譔','饌','馔',],xiàng:['像','勨','向','嚮','姠','嶑','曏','橡','珦','缿','蟓','衖','襐','象','鐌','項','项','鱌',],shàn:['僐','善','墠','墡','嬗','擅','敾','椫','樿','歚','汕','灗','疝','磰','繕','缮','膳','蟮','蟺','訕','謆','譱','讪','贍','赡','赸','鄯','鐥','饍','騸','骟','鱓','鱔','鳝','𫮃',],'tuí tuǐ':['僓'],zǔn:['僔','噂','撙','譐'],pú:['僕','匍','圤','墣','濮','獛','璞','瞨','穙','莆','菐','菩','葡','蒱','蒲','贌','酺','鏷','镤',],láo:['僗','劳','労','勞','哰','崂','嶗','憥','朥','浶','牢','痨','癆','窂','簩','醪','鐒','铹','顟','髝','𫭼',],chǎng:['僘','厰','廠','敞','昶','氅','鋹','𬬮'],guāng:['僙','光','咣','垙','姯','洸','灮','炗','炚','炛','烡','珖','胱','茪','輄','銧','黆','𨐈',],liáo:['僚','嘹','嫽','寥','寮','尞','屪','嵺','嶚','嶛','廫','憀','敹','暸','橑','獠','璙','疗','療','竂','簝','繚','缭','聊','膋','膫','藔','蟟','豂','賿','蹘','辽','遼','飉','髎','鷯','鹩',],dèng:['僜','凳','墱','嶝','櫈','瞪','磴','覴','邓','鄧','隥'],'chán zhàn zhuàn':['僝'],bō:['僠','嶓','拨','撥','播','波','溊','玻','癶','盋','砵','碆','礡','缽','菠','袰','蹳','鉢','钵','餑','饽','驋','鱍','𬭛',],huì:['僡','匯','卉','喙','嘒','嚖','圚','嬒','寭','屶','屷','彗','彙','彚','徻','恚','恵','惠','慧','憓','懳','晦','暳','槥','橞','檅','櫘','汇','泋','滙','潓','烩','燴','獩','璤','瞺','硊','秽','穢','篲','絵','繪','绘','翙','翽','荟','蔧','蕙','薈','薉','蟪','詯','誨','諱','譓','譿','讳','诲','賄','贿','鐬','闠','阓','靧','頮','顪','颒','餯','𬤝','𬭬',],chuǎn:['僢','喘','舛','荈','踳'],'tiě jiàn':['僣'],sēng:['僧','鬙'],xiàn:['僩','僴','哯','垷','塪','姭','娊','宪','岘','峴','憲','撊','晛','橌','橺','涀','瀗','献','獻','现','現','県','睍','粯','糮','絤','綫','線','线','缐','羡','羨','腺','臔','臽','苋','莧','誢','豏','鋧','錎','限','陥','陷','霰','餡','馅','麲','鼸','𬀪','𪾢',],'yù jú':['僪'],'è wū':['僫'],'tóng zhuàng':['僮'],lǐn:['僯','凛','凜','廩','廪','懍','懔','撛','檁','檩','澟','癛','癝',],gù:['僱','凅','固','堌','崓','崮','故','梏','棝','牿','痼','祻','錮','锢','雇','顧','顾','鯝','鲴',],jiāng:['僵','壃','姜','橿','殭','江','畕','疅','礓','繮','缰','翞','茳','葁','薑','螀','螿','豇','韁','鱂','鳉',],mǐn:['僶','冺','刡','勄','悯','惽','愍','慜','憫','抿','敃','敏','敯','泯','潣','皿','笢','笽','簢','蠠','閔','閩','闵','闽','鰵','鳘','黽',],jìn:['僸','凚','噤','嚍','墐','壗','妗','嬧','搢','晉','晋','枃','殣','浕','浸','溍','濅','濜','烬','煡','燼','琎','瑨','璶','盡','祲','縉','缙','荩','藎','覲','觐','賮','贐','赆','近','进','進','靳','齽',],'jià jie':['價'],qiào:['僺','峭','帩','撬','殻','窍','竅','誚','诮','躈','陗','鞩','韒','髚',],pì:['僻','媲','嫓','屁','澼','甓','疈','譬','闢','鷿','鸊','䴙'],sài:['僿','簺','賽','赛'],'chán tǎn shàn':['儃'],'dāng dàng':['儅','当','闣'],xuān:['儇','喧','塇','媗','宣','愃','愋','揎','昍','暄','煊','煖','瑄','睻','矎','禤','箮','翧','翾','萱','萲','蓒','蕿','藼','蘐','蝖','蠉','諠','諼','譞','谖','軒','轩','鍹','駽','鰚','𫓶','𫍽',],'dān dàn':['儋','擔','瘅'],càn:['儏','澯','灿','燦','璨','粲','薒','謲'],'bīn bìn':['儐'],'án àn':['儑'],tái:['儓','坮','嬯','抬','擡','檯','炱','炲','籉','臺','薹','跆','邰','颱','鮐','鲐',],lán:['儖','兰','囒','婪','岚','嵐','幱','拦','攔','斓','斕','栏','欄','欗','澜','瀾','灆','灡','燣','燷','璼','篮','籃','籣','繿','葻','蓝','藍','蘫','蘭','褴','襕','襤','襴','襽','譋','讕','谰','躝','鑭','镧','闌','阑','韊','𬒗',],'nǐ yì ài yí':['儗'],méng:['儚','幪','曚','朦','橗','檬','氋','溕','濛','甍','甿','盟','礞','艨','莔','萌','蕄','虻','蝱','鄳','鄸','霿','靀','顭','饛','鯍','鸏','鹲','𫑡','㠓',],níng:['儜','凝','咛','嚀','嬣','柠','橣','檸','狞','獰','聍','聹','薴','鑏','鬡','鸋',],qióng:['儝','卭','宆','惸','憌','桏','橩','焪','焭','煢','熍','琼','瓊','睘','穷','穹','窮','竆','笻','筇','舼','茕','藑','藭','蛩','蛬','赹','跫','邛','銎','䓖',],liè:['儠','冽','列','劣','劽','埒','埓','姴','峛','巤','挒','捩','栵','洌','浖','烈','烮','煭','犣','猎','猟','獵','聗','脟','茢','蛚','趔','躐','迾','颲','鬛','鬣','鮤','鱲','鴷','䴕','𫚭',],kuǎng:['儣','夼','懭'],bào:['儤','勽','報','忁','报','抱','曓','爆','犦','菢','虣','蚫','豹','鉋','鑤','铇','骲','髱','鮑','鲍',],biāo:['儦','墂','幖','彪','标','標','滮','瀌','熛','爂','猋','瘭','磦','膘','臕','謤','贆','鏢','鑣','镖','镳','颮','颷','飆','飇','飈','飊','飑','飙','飚','驫','骉','髟',],zǎn:['儧','儹','噆','攅','昝','趱','趲'],háo:['儫','嗥','嘷','噑','嚎','壕','椃','毜','毫','濠','獆','獔','竓','籇','蚝','蠔','譹','豪',],qìng:['儬','凊','庆','慶','櫦','濪','碃','磬','罄','靘'],chèn:['儭','嚫','榇','櫬','疢','衬','襯','讖','谶','趁','趂','齓','齔','龀',],téng:['儯','幐','滕','漛','疼','籐','籘','縢','腾','藤','虅','螣','誊','謄','邆','駦','騰','驣','鰧','䲢',],'lǒng lóng lòng':['儱'],'chán chàn':['儳'],'ráng xiāng':['儴','勷'],'huì xié':['儶'],luó:['儸','攞','椤','欏','猡','玀','箩','籮','罗','羅','脶','腡','萝','蘿','螺','覼','逻','邏','鏍','鑼','锣','镙','饠','騾','驘','骡','鸁',],léi:['儽','嫘','檑','欙','瓃','畾','縲','纍','纝','缧','罍','羸','蔂','蘲','虆','轠','鐳','鑘','镭','雷','靁','鱩','鼺',],'nàng nāng':['儾'],'wù wū':['兀'],yǔn:['允','喗','夽','抎','殒','殞','狁','磒','荺','賱','鈗','阭','陨','隕','霣','馻','齫','齳',],zān:['兂','橵','簪','簮','糌','鐕','鐟','鵤'],yuán:['元','円','原','厡','厵','园','圆','圎','園','圓','垣','塬','媴','嫄','援','榞','榬','橼','櫞','沅','湲','源','溒','爰','猨','猿','笎','緣','縁','缘','羱','茒','薗','蝝','蝯','螈','袁','褤','謜','轅','辕','邍','邧','酛','鈨','鎱','騵','魭','鶢','鶰','黿','鼋','𫘪',],xiōng:['兄','兇','凶','匂','匈','哅','忷','恟','汹','洶','胷','胸','芎','訩','詾','讻',],chōng:['充','嘃','忡','憃','憧','摏','沖','浺','珫','罿','翀','舂','艟','茺','衝','蹖','㳘',],zhào:['兆','垗','旐','曌','枛','櫂','照','燳','狣','瞾','笊','罀','罩','羄','肁','肇','肈','詔','诏','赵','趙','鮡','𬶐',],'duì ruì yuè':['兊','兌','兑'],kè:['克','刻','勀','勊','堁','娔','客','恪','愙','氪','溘','碦','緙','缂','艐','衉','課','课','錁','锞','騍','骒',],tù:['兎','兔','堍','迌','鵵'],dǎng:['党','攩','欓','譡','讜','谠','黨','𣗋'],dōu:['兜','兠','唗','橷','篼','蔸'],huǎng:['兤','奛','幌','怳','恍','晄','炾','熀','縨','詤','謊','谎',],rù:['入','嗕','媷','扖','杁','洳','溽','縟','缛','蓐','褥','鳰'],nèi:['內','氝','氞','錗'],'yú shù':['兪'],'liù lù':['六'],han:['兯','爳'],tiān:['兲','天','婖','添','酟','靔','靝','黇'],'xīng xìng':['兴'],diǎn:['典','嚸','奌','婰','敟','椣','点','碘','蒧','蕇','踮','點',],'zī cí':['兹'],jiān:['兼','冿','囏','坚','堅','奸','姦','姧','尖','幵','惤','戋','戔','搛','椾','樫','櫼','歼','殱','殲','湔','瀐','瀸','煎','熞','熸','牋','瑊','睷','礛','礷','笺','箋','緘','縑','缄','缣','肩','艰','艱','菅','菺','葌','蒹','蔪','蕑','蕳','虃','譼','豜','鑯','雃','鞯','韀','韉','餰','馢','鰔','鰜','鰹','鲣','鳒','鵑','鵳','鶼','鹣','麉',],shòu:['兽','受','售','壽','夀','寿','授','狩','獣','獸','痩','瘦','綬','绶','膄',],jì:['兾','冀','剂','剤','劑','勣','坖','垍','塈','妓','季','寂','寄','廭','彑','徛','忌','悸','惎','懻','技','旡','既','旣','暨','暩','曁','梞','檕','檵','洎','漃','漈','瀱','痵','癠','禝','稩','稷','穄','穊','穧','紀','継','績','繋','繼','继','绩','罽','臮','芰','茍','茤','葪','蓟','蔇','薊','蘎','蘮','蘻','裚','襀','覬','觊','計','記','誋','计','记','跡','跽','蹟','迹','际','際','霁','霽','驥','骥','髻','鬾','魝','魥','鯚','鯽','鰶','鰿','鱀','鱭','鲚','鲫','鵋','鷑','齌','𪟝','𬶨','𬶭',],jiōng:['冂','冋','坰','埛','扃','蘏','蘔','駉','駫','𬳶'],mào:['冃','冐','媢','帽','愗','懋','暓','柕','楙','毷','瑁','皃','眊','瞀','耄','茂','萺','蝐','袤','覒','貌','貿','贸','鄚','鄮',],rǎn:['冄','冉','姌','媣','染','珃','苒','蒅','䎃'],'nèi nà':['内'],gāng:['冈','冮','刚','剛','堈','堽','岡','掆','摃','棡','牨','犅','疘','綱','纲','缸','罁','罡','肛','釭','鎠','㭎',],cè:['冊','册','厕','厠','夨','廁','恻','惻','憡','敇','测','測','笧','策','筞','筴','箣','荝','萗','萴','蓛',],guǎ:['冎','剐','剮','叧','寡'],'mào mò':['冒'],gòu:['冓','啂','坸','垢','够','夠','媾','彀','搆','撀','构','構','煹','覯','觏','訽','詬','诟','購','购','遘','雊',],xǔ:['冔','喣','暊','栩','珝','盨','糈','詡','諿','诩','鄦','醑'],mì:['冖','冪','嘧','塓','宻','密','峚','幂','幎','幦','怽','榓','樒','櫁','汨','淧','滵','漞','濗','熐','羃','蔤','蜜','覓','覔','覛','觅','謐','谧','鼏',],'yóu yín':['冘'],xiě:['写','冩','藛'],jūn:['军','君','均','桾','汮','皲','皸','皹','碅','莙','蚐','袀','覠','軍','鈞','銁','銞','鍕','钧','頵','鮶','鲪','麏',],mí:['冞','擟','瀰','爢','猕','獼','祢','禰','縻','蒾','藌','蘪','蘼','袮','詸','謎','迷','醚','醾','醿','釄','镾','鸍','麊','麋','麛',],'guān guàn':['冠','覌','観','觀','观'],měng:['冡','勐','懵','掹','猛','獴','艋','蜢','蠓','錳','锰','鯭','鼆',],zhǒng:['冢','塚','尰','歱','煄','瘇','肿','腫','踵'],zuì:['冣','嶵','晬','最','栬','槜','檇','檌','祽','絊','罪','蕞','辠','酔','酻','醉','錊',],yuān:['冤','剈','囦','嬽','寃','棩','淵','渁','渆','渊','渕','灁','眢','肙','葾','蒬','蜎','蜵','駌','鳶','鴛','鵷','鸢','鸳','鹓','鼘','鼝',],míng:['冥','名','明','暝','朙','榠','洺','溟','猽','眀','眳','瞑','茗','螟','覭','詺','鄍','銘','铭','鳴','鸣',],kòu:['冦','叩','宼','寇','扣','敂','滱','窛','筘','簆','蔲','蔻','釦','鷇',],tài:['冭','太','夳','忲','态','態','汰','汱','泰','溙','肽','舦','酞','鈦','钛',],'féng píng':['冯','馮'],'chōng chòng':['冲'],kuàng:['况','圹','壙','岲','懬','旷','昿','曠','框','況','爌','眖','眶','矿','砿','礦','穬','絋','絖','纊','纩','貺','贶','軦','邝','鄺','鉱','鋛','鑛','黋',],lěng:['冷'],pàn:['冸','判','叛','沜','泮','溿','炍','牉','畔','盼','聁','袢','襻','詊','鋬','鑻','頖','鵥',],fā:['冹','彂','沷','発','發'],xiǎn:['冼','尟','尠','崄','嶮','幰','攇','显','櫶','毨','灦','烍','燹','狝','猃','獫','獮','玁','禒','筅','箲','藓','蘚','蚬','蜆','譣','赻','跣','鍌','险','険','險','韅','顕','顯','㬎',],qià:['冾','圶','帢','恰','殎','洽','硈','胢','髂'],'jìng chēng':['净','凈','淨'],sōu:['凁','嗖','廀','廋','捜','搜','摉','溲','獀','艘','蒐','螋','鄋','醙','鎪','锼','颼','飕','餿','馊','騪',],měi:['凂','媄','媺','嬍','嵄','挴','毎','每','浼','渼','燘','美','躾','鎂','镁','黣',],tú:['凃','図','图','圖','圗','塗','屠','峹','嵞','庩','廜','徒','悇','揬','涂','瘏','筡','腯','荼','蒤','跿','途','酴','鈯','鍎','馟','駼','鵌','鶟','鷋','鷵','𬳿',],zhǔn:['准','凖','埻','準','𬘯'],'liáng liàng':['凉','涼','量'],diāo:['凋','刁','刟','叼','奝','弴','彫','汈','琱','碉','簓','虭','蛁','貂','錭','雕','鮉','鯛','鲷','鵰','鼦',],còu:['凑','湊','腠','輳','辏'],ái:['凒','啀','嘊','捱','溰','癌','皑','皚'],duó:['凙','剫','夺','奪','痥','踱','鈬','鐸','铎'],dú:['凟','匵','嬻','椟','櫝','殰','涜','牍','牘','犊','犢','独','獨','瓄','皾','裻','読','讀','讟','豄','贕','錖','鑟','韇','韣','韥','騳','髑','黩','黷',],'jǐ jī':['几'],fán:['凡','凢','凣','匥','墦','杋','柉','棥','樊','瀿','烦','煩','燔','璠','矾','礬','笲','籵','緐','羳','舤','舧','薠','蘩','蠜','襎','蹯','釩','鐇','鐢','钒','鷭','𫔍','𬸪',],jū:['凥','匊','娵','婮','居','崌','抅','挶','掬','梮','椐','檋','毩','毱','泃','涺','狙','琚','疽','砠','罝','腒','艍','蜛','裾','諊','跔','踘','躹','陱','雎','鞠','鞫','駒','驹','鮈','鴡','鶋','𬶋',],'chù chǔ':['処','处'],zhǐ:['凪','劧','咫','址','坧','帋','恉','扺','指','旨','枳','止','汦','沚','洔','淽','疻','砋','祉','秖','紙','纸','芷','藢','衹','襧','訨','趾','軹','轵','酯','阯','黹',],píng:['凭','凴','呯','坪','塀','岼','帡','帲','幈','平','慿','憑','枰','洴','焩','玶','瓶','甁','竮','箳','簈','缾','荓','萍','蓱','蚲','蛢','評','评','軿','輧','郱','鮃','鲆',],kǎi:['凯','凱','剀','剴','垲','塏','恺','愷','慨','暟','蒈','輆','鍇','鎧','铠','锴','闓','闿','颽',],gān:['凲','坩','尲','尴','尶','尷','柑','泔','漧','玕','甘','疳','矸','竿','筸','粓','肝','苷','迀','酐','魐',],'kǎn qiǎn':['凵'],tū:['凸','堗','嶀','捸','涋','湥','痜','禿','秃','突','葖','鋵','鵚','鼵','㻬',],'āo wā':['凹'],chū:['出','初','岀','摴','榋','樗','貙','齣','䢺','䝙'],dàng:['凼','圵','垱','壋','档','檔','氹','璗','瓽','盪','瞊','砀','碭','礑','簜','荡','菪','蕩','蘯','趤','逿','雼','𬍡',],hán:['函','凾','含','圅','娢','寒','崡','晗','梒','浛','涵','澏','焓','琀','甝','筨','蜬','邗','邯','鋡','韓','韩',],záo:['凿','鑿'],dāo:['刀','刂','忉','氘','舠','螩','釖','魛','鱽'],chuāng:['刅','摐','牎','牕','疮','瘡','窓','窗','窻'],'fēn fèn':['分'],'qiè qiē':['切'],kān:['刊','勘','堪','戡','栞','龕','龛'],cǔn:['刌','忖'],chú:['刍','厨','幮','廚','橱','櫉','櫥','滁','犓','篨','耡','芻','蒢','蒭','蜍','蟵','豠','趎','蹰','躇','躕','鉏','鋤','锄','除','雏','雛','鶵',],'huà huá':['划'],lí:['刕','剓','剺','劙','厘','喱','嚟','囄','嫠','孷','廲','悡','梨','梸','棃','漓','灕','犁','犂','狸','琍','璃','瓈','盠','睝','离','穲','竰','筣','篱','籬','糎','縭','缡','罹','艃','荲','菞','蓠','蔾','藜','蘺','蜊','蟍','蟸','蠫','褵','謧','貍','醨','鋫','錅','鏫','鑗','離','驪','骊','鯏','鯬','鱺','鲡','鵹','鸝','鹂','黎','黧','㰀',],yuè:['刖','嬳','岄','岳','嶽','恱','悅','悦','戉','抈','捳','月','樾','瀹','爚','玥','礿','禴','篗','籆','籥','籰','粤','粵','蘥','蚎','蚏','説','越','跀','跃','躍','軏','鈅','鉞','鑰','钺','閱','閲','阅','鸑','鸙','黦','龠','𫐄','𬸚',],liú:['刘','劉','嚠','媹','嵧','旈','旒','榴','橊','流','浏','瀏','琉','瑠','瑬','璢','畄','留','畱','疁','瘤','癅','硫','蒥','蓅','蟉','裗','鎏','鏐','鐂','镠','飀','飅','飗','駠','駵','騮','驑','骝','鰡','鶹','鹠','麍',],zé:['则','則','啧','嘖','嫧','帻','幘','択','樍','歵','沢','泎','溭','皟','瞔','矠','礋','箦','簀','舴','蔶','蠌','襗','謮','賾','赜','迮','鸅','齚','齰',],'chuàng chuāng':['创','創'],qù:['刞','厺','去','閴','闃','阒','麮','鼁'],'bié biè':['別','别'],'páo bào':['刨'],'chǎn chàn':['刬','剗','幝'],guā:['刮','劀','桰','歄','煱','瓜','胍','踻','颪','颳','騧','鴰','鸹',],gēng:['刯','庚','椩','浭','焿','畊','絚','羮','羹','耕','菮','賡','赓','鶊','鹒',],dào:['到','噵','悼','椡','檤','燾','瓙','盗','盜','稲','稻','纛','翿','艔','菿','衜','衟','軇','道',],chuàng:['刱','剏','剙','怆','愴'],kū:['刳','哭','圐','堀','枯','桍','矻','窟','跍','郀','骷','鮬'],duò:['刴','剁','墯','尮','惰','憜','挅','桗','舵','跥','跺','陊','陏','飿','饳','鵽',],'shuā shuà':['刷'],'quàn xuàn':['券'],'chà shā':['刹','剎'],'cì cī':['刺'],guì:['刽','刿','劊','劌','撌','攰','昋','桂','椢','槶','樻','櫃','猤','禬','筀','蓕','襘','貴','贵','跪','鐀','鑎','鞼','鱖','鱥',],lóu:['剅','娄','婁','廔','楼','樓','溇','漊','熡','耧','耬','艛','蒌','蔞','蝼','螻','謱','軁','遱','鞻','髅','髏','𪣻',],cuò:['剉','剒','厝','夎','挫','措','棤','莝','莡','蓌','逪','銼','錯','锉','错',],'xiāo xuē':['削'],'kēi kè':['剋','尅'],'là lá':['剌'],tī:['剔','梯','踢','銻','锑','鷈','鷉','䏲','䴘'],pōu:['剖'],wān:['剜','塆','壪','帵','弯','彎','湾','潫','灣','睕','蜿','豌'],'bāo bō':['剝','剥'],duō:['剟','咄','哆','嚉','多','夛','掇','毲','畓','裰','㙍'],qíng:['剠','勍','夝','情','擎','晴','暒','棾','樈','檠','氰','甠','硘','葝','黥',],'yǎn shàn':['剡'],'dū zhuó':['剢'],yān:['剦','嫣','崦','嶖','恹','懕','懨','樮','淊','淹','漹','烟','焉','焑','煙','珚','篶','胭','臙','菸','鄢','醃','閹','阉','黫',],huō:['剨','劐','吙','攉','秴','耠','锪','騞','𬴃'],shèng:['剩','剰','勝','圣','墭','嵊','晠','榺','橳','琞','聖','蕂','貹','賸',],'duān zhì':['剬'],wū:['剭','呜','嗚','圬','屋','巫','弙','杇','歍','汙','汚','污','洿','烏','窏','箼','螐','誈','誣','诬','邬','鄔','鎢','钨','鰞','鴮',],gē:['割','哥','圪','彁','戈','戓','戨','歌','滒','犵','肐','袼','謌','鎶','鴚','鴿','鸽',],'dá zhá':['剳'],chuán:['剶','暷','椽','篅','舡','舩','船','輲','遄'],'tuán zhuān':['剸','漙','篿'],'lù jiū':['剹'],pēng:['剻','匉','嘭','怦','恲','抨','梈','烹','砰','軯','駍'],piāo:['剽','勡','慓','旚','犥','翲','螵','飃','飄','飘','魒'],kōu:['剾','彄','抠','摳','眍','瞘','芤','𫸩'],'jiǎo chāo':['剿','劋','勦','摷'],qiāo:['劁','勪','墝','幧','敲','橇','毃','燆','硗','磽','繑','趬','跷','踍','蹺','蹻','郻','鄡','鄥','鍫','鍬','鐰','锹','頝',],'huá huà':['劃'],'zhā zhá':['劄'],'pī pǐ':['劈','悂'],tāng:['劏','嘡','羰','薚','蝪','蹚','鞺','鼞'],chán:['劖','嚵','壥','婵','嬋','巉','廛','棎','毚','湹','潹','潺','澶','瀍','瀺','煘','獑','磛','緾','纏','纒','缠','艬','蝉','蟐','蟬','蟾','誗','讒','谗','躔','鄽','酁','鋋','鑱','镵','饞','馋',],zuān:['劗','躜','躦','鉆','鑚'],mó:['劘','嫫','嬤','嬷','尛','摹','擵','橅','糢','膜','藦','蘑','謨','謩','谟','饃','饝','馍','髍','魔','魹',],zhú:['劚','斸','曯','欘','灟','炢','烛','燭','爥','瘃','竹','笁','笜','舳','茿','蓫','蠋','蠾','躅','逐','逫','钃','鱁',],quàn:['劝','勧','勸','牶','韏'],'jìn jìng':['劤','劲','勁'],kēng:['劥','坑','牼','硁','硜','誙','銵','鍞','鏗','铿','阬'],'xié liè':['劦'],'zhù chú':['助'],nǔ:['努','弩','砮','胬'],shào:['劭','卲','哨','潲','紹','綤','绍','袑','邵'],miǎo:['劰','杪','淼','渺','眇','秒','篎','緲','缈','藐','邈'],kǒu:['劶','口'],wā:['劸','娲','媧','屲','挖','攨','洼','溛','漥','瓾','畖','穵','窊','窪','蛙','韈','鼃',],kuāng:['劻','匡','匩','哐','恇','洭','筐','筺','誆','诓','軭','邼',],hé:['劾','咊','啝','姀','峆','敆','曷','柇','楁','毼','河','涸','渮','澕','熆','皬','盇','盉','盍','盒','禾','篕','籺','粭','翮','菏','萂','覈','訸','詥','郃','釛','鉌','鑉','閡','闔','阂','阖','鞨','頜','餄','饸','魺','鹖','麧','齕','龁','龢','𬌗',],gào:['勂','吿','告','峼','祮','祰','禞','筶','誥','诰','郜','鋯','锆',],'bó bèi':['勃'],láng:['勆','嫏','廊','斏','桹','榔','樃','欴','狼','琅','瑯','硠','稂','艆','蓈','蜋','螂','躴','郒','郞','鋃','鎯','锒',],xūn:['勋','勛','勲','勳','嚑','坃','埙','塤','壎','壦','曛','燻','獯','矄','纁','臐','薫','薰','蘍','醺','𫄸',],'juàn juān':['勌','瓹'],'lè lēi':['勒'],kài:['勓','炌','烗','鎎'],'wěng yǎng':['勜'],qín:['勤','嗪','噙','嶜','庈','懃','懄','捦','擒','斳','檎','澿','珡','琴','琹','瘽','禽','秦','耹','芩','芹','菦','螓','蠄','鈙','鈫','雂','靲','鳹','鵭',],jiàng:['勥','匞','匠','嵹','弜','弶','摾','櫤','洚','滰','犟','糡','糨','絳','绛','謽','酱','醤','醬',],fān:['勫','嬏','帆','幡','忛','憣','旙','旛','繙','翻','藩','轓','颿','飜','鱕',],juān:['勬','姢','娟','捐','涓','蠲','裐','鎸','鐫','镌','鹃'],'tóng dòng':['勭','烔','燑','狪'],lǜ:['勴','垏','嵂','律','慮','氯','滤','濾','爈','箻','綠','繂','膟','葎','虑','鑢',],chè:['勶','坼','彻','徹','掣','撤','澈','烢','爡','瞮','硩','聅','迠','頙','㬚',],sháo:['勺','玿','韶'],'gōu gòu':['勾'],cōng:['匆','囪','囱','忩','怱','悤','暰','樬','漗','瑽','璁','瞛','篵','繱','聡','聦','聪','聰','苁','茐','葱','蓯','蔥','蟌','鍯','鏓','鏦','騘','驄','骢',],'táo yáo':['匋','陶'],páo:['匏','咆','垉','庖','爮','狍','袍','褜','軳','鞄','麅'],dá:['匒','妲','怛','炟','燵','畣','笪','羍','荙','薘','蟽','詚','达','迏','迖','迚','逹','達','鐽','靼','鞑','韃','龖','龘','𫟼',],'huà huā':['化'],'běi bèi':['北'],nǎo:['匘','垴','堖','嫐','恼','悩','惱','瑙','碯','脑','脳','腦'],'chí shi':['匙'],fāng:['匚','堏','方','淓','牥','芳','邡','鈁','錺','钫','鴋'],zā:['匝','咂','帀','沞','臜','臢','迊','鉔','魳'],qiè:['匧','厒','妾','怯','悏','惬','愜','挈','穕','窃','竊','笡','箧','篋','籡','踥','鍥','锲','鯜',],'zāng cáng':['匨'],fěi:['匪','奜','悱','棐','榧','篚','翡','蕜','誹','诽'],'kuì guì':['匮','匱'],suǎn:['匴'],pǐ:['匹','噽','嚭','圮','庀','痞','癖','脴','苉','銢','鴄'],'qū ōu':['区','區'],'kē qià':['匼'],'yǎn yàn':['匽','棪'],biǎn:['匾','惼','揙','碥','稨','窆','藊','褊','貶','贬','鴘'],nì:['匿','堄','嫟','嬺','惄','愵','昵','暱','氼','眤','睨','縌','胒','腻','膩','逆','𨺙',],niàn:['卄','唸','埝','廿','念','惗','艌'],sà:['卅','櫒','脎','萨','蕯','薩','鈒','隡','颯','飒','馺'],zú:['卆','哫','崪','族','箤','足','踤','镞'],shēng:['升','呏','声','斘','昇','曻','枡','殅','泩','湦','焺','牲','珄','生','甥','竔','笙','聲','鉎','鍟','阩','陞','陹','鵿','鼪',],wàn:['卍','卐','忨','杤','瞣','脕','腕','萬','蟃','贎','輐','錽','𬇕',],'huá huà huā':['华','華'],bēi:['卑','悲','揹','杯','桮','盃','碑','藣','鵯','鹎'],'zú cù':['卒'],'dān shàn chán':['单','單'],'nán nā':['南'],'shuài lǜ':['卛'],'bǔ bo pú':['卜'],'kuàng guàn':['卝'],biàn:['卞','变','変','峅','弁','徧','忭','抃','昪','汳','汴','玣','艑','苄','覍','諚','變','辡','辧','辨','辩','辫','辮','辯','遍','釆','𨚕',],bǔ:['卟','哺','捕','补','補','鸔','𬷕'],'zhàn zhān':['占','覱'],'kǎ qiǎ':['卡'],lú:['卢','嚧','垆','壚','庐','廬','曥','枦','栌','櫨','泸','瀘','炉','爐','獹','玈','瓐','盧','矑','籚','纑','罏','胪','臚','舮','舻','艫','芦','蘆','蠦','轤','轳','鈩','鑪','顱','颅','馿','髗','魲','鱸','鲈','鸕','鸬','黸','𬬻',],lǔ:['卤','塷','掳','擄','樐','橹','櫓','氌','滷','澛','瀂','硵','磠','穞','艣','艪','蓾','虏','虜','鏀','鐪','鑥','镥','魯','鲁','鹵',],guà:['卦','啩','挂','掛','罣','褂','詿','诖'],'áng yǎng':['卬'],yìn:['印','垽','堷','廕','慭','憖','憗','懚','洕','湚','猌','癊','胤','茚','酳','鮣','䲟',],què:['却','卻','塙','崅','悫','愨','慤','搉','榷','燩','琷','皵','确','確','礭','闋','阕','鵲','鹊','𬒈',],luǎn:['卵'],'juàn juǎn':['卷','巻'],'chǎng ān hàn':['厂'],'wěi yán':['厃'],tīng:['厅','厛','听','庁','廰','廳','汀','烃','烴','綎','耓','聴','聼','聽','鞓','𬘩',],'zhé zhái':['厇'],'hàn àn':['厈','屽'],yǎ:['厊','唖','庌','痖','瘂','蕥'],shè:['厍','厙','弽','慑','慴','懾','摂','欇','涉','涻','渉','滠','灄','社','舎','蔎','蠂','設','设','赦','騇','麝',],dǐ:['厎','呧','坘','弤','抵','拞','掋','牴','砥','菧','觝','詆','诋','軧','邸','阺','骶','鯳',],'zhǎ zhǎi':['厏'],páng:['厐','嫎','庞','徬','舽','螃','逄','鰟','鳑','龎','龐'],'zhì shī':['厔'],máng:['厖','吂','哤','娏','忙','恾','杗','杧','汒','浝','牻','痝','盲','硭','笀','芒','茫','蘉','邙','釯','鋩','铓','駹',],zuī:['厜','樶','纗','蟕'],'shà xià':['厦','廈'],áo:['厫','嗷','嗸','廒','敖','滶','獒','獓','璈','翱','翶','翺','聱','蔜','螯','謷','謸','遨','鏖','隞','鰲','鳌','鷔','鼇',],'lán qiān':['厱'],'sī mǒu':['厶'],'gōng hóng':['厷'],'lín miǎo':['厸'],'qiú róu':['厹'],dū:['厾','嘟','督','醏'],'xiàn xuán':['县','縣'],'cān shēn cēn sān':['参','參','叄','叅'],'ài yǐ':['叆'],'chā chà chǎ chá':['叉'],shuāng:['双','孀','孇','欆','礵','艭','雙','霜','騻','驦','骦','鷞','鸘','鹴',],shōu:['収','收'],guái:['叏'],bá:['叐','妭','抜','拔','炦','癹','胈','茇','菝','詙','跋','軷','魃','鼥',],'fā fà':['发'],'zhuó yǐ lì jué':['叕'],qǔ:['取','娶','竬','蝺','詓','齲','龋'],'jiǎ xiá':['叚','徦'],'wèi yù':['叞','尉','蔚'],dié:['叠','垤','堞','峌','幉','恎','惵','戜','曡','殜','氎','牃','牒','瓞','畳','疂','疉','疊','碟','絰','绖','耊','耋','胅','艓','苵','蜨','蝶','褋','詄','諜','谍','跮','蹀','迭','镻','鰈','鲽','鴩','𫶇',],ruì:['叡','枘','汭','瑞','睿','芮','蚋','蜹','銳','鋭','锐'],'jù gōu':['句'],lìng:['另','呤','炩','蘦'],'dāo dáo tāo':['叨'],'zhī zhǐ':['只'],jiào:['叫','呌','嘂','嘦','噍','嬓','斍','斠','滘','漖','獥','珓','皭','窖','藠','訆','譥','趭','較','轎','轿','较','酵','醮','釂',],'zhào shào':['召'],'kě kè':['可'],'tái tāi':['台','苔'],pǒ:['叵','尀','笸','箥','鉕','钷','駊'],'yè xié':['叶'],'hào háo':['号'],tàn:['叹','嘆','探','歎','湠','炭','碳','舕'],'hōng hóng':['叿'],miē:['吀','咩','哶','孭'],'xū yū yù':['吁'],chī:['吃','哧','喫','嗤','噄','妛','媸','彨','彲','摛','攡','殦','瓻','痴','癡','眵','瞝','笞','粚','胵','蚩','螭','訵','魑','鴟','鵄','鸱','黐','齝','𫄨',],'xuān sòng':['吅'],yāo:['吆','喓','夭','妖','幺','楆','殀','祅','腰','葽','訞','邀','鴁','鴢','㙘',],zǐ:['吇','姉','姊','子','杍','梓','榟','橴','滓','矷','秭','笫','籽','紫','耔','虸','訿','釨',],'hé gě':['合','鲄'],'cùn dòu':['吋'],'tóng tòng':['同'],'tǔ tù':['吐','唋'],'zhà zhā':['吒','奓'],'xià hè':['吓'],'ā yā':['吖'],'ma má mǎ':['吗'],lìn:['吝','恡','悋','橉','焛','甐','膦','蔺','藺','賃','赁','蹸','躏','躙','躪','轥','閵',],tūn:['吞','暾','朜','焞'],'bǐ pǐ':['吡'],qìn:['吢','吣','唚','抋','揿','搇','撳','沁','瀙','菣','藽'],'jiè gè':['吤'],'fǒu pǐ':['否'],'ba bā':['吧'],dūn:['吨','噸','墩','墪','惇','撉','撴','犜','獤','礅','蜳','蹾','驐',],fēn:['吩','帉','昐','朆','梤','棻','氛','竕','紛','纷','翂','芬','衯','訜','躮','酚','鈖','雰','餴','饙','馚',],'é huā':['吪'],'kēng háng':['吭','妔'],shǔn:['吮'],'zhī zī':['吱'],'yǐn shěn':['吲'],wú:['吳','吴','呉','墲','峿','梧','橆','毋','洖','浯','無','珸','璑','祦','芜','茣','莁','蕪','蜈','蟱','譕','郚','鋙','铻','鯃','鵐','鷡','鹀','鼯',],'chǎo chāo':['吵'],'nà nè':['吶'],'xuè chuò jué':['吷'],chuī:['吹','炊','龡'],'dōu rú':['吺'],hǒu:['吼','犼'],'hōng hǒu ōu':['吽'],'wú yù':['吾'],'ya yā':['呀'],'è e':['呃'],dāi:['呆','懛','獃'],'mèn qǐ':['呇'],hōng:['呍','嚝','揈','灴','烘','焢','硡','薨','訇','谾','軣','輷','轟','轰','鍧',],nà:['呐','捺','笝','納','纳','肭','蒳','衲','豽','貀','軜','郍','鈉','钠','靹','魶',],'tūn tiān':['呑'],'fǔ ḿ':['呒','嘸'],'dāi tǎi':['呔'],'ǒu ōu òu':['呕'],'bài bei':['呗'],'yuán yún yùn':['员','員'],guō:['呙','啯','嘓','埚','堝','墎','崞','彉','彍','懖','猓','瘑','聒','蝈','蟈','郭','鈛','鍋','锅',],'huá qì':['呚'],'qiàng qiāng':['呛','跄'],shī:['呞','失','尸','屍','师','師','施','浉','湤','湿','溮','溼','濕','狮','獅','瑡','絁','葹','蒒','蓍','虱','蝨','褷','襹','詩','诗','邿','釃','鉇','鍦','鯴','鰤','鲺','鳲','鳾','鶳','鸤','䴓','𫚕',],juǎn:['呟','埍','臇','菤','錈','锩'],pěn:['呠','翸'],'wěn mǐn':['呡'],'ne ní':['呢'],'ḿ m̀ móu':['呣'],rán:['呥','嘫','然','燃','繎','肰','蚦','蚺','衻','袇','袡','髥','髯',],'tiè chè':['呫'],'qì zhī':['呮'],'zǐ cī':['呰'],'guā gū guǎ':['呱'],'cī zī':['呲'],'hǒu xǔ gòu':['呴'],'hē ā á ǎ à a':['呵'],náo:['呶','夒','峱','嶩','巎','挠','撓','猱','硇','蛲','蟯','詉','譊','鐃','铙',],'xiā gā':['呷'],pēi:['呸','怌','肧','胚','衃','醅'],'háo xiāo':['呺'],mìng:['命','掵'],'dá dàn':['呾'],'zuǐ jǔ':['咀'],'xián gān':['咁'],pǒu:['咅','哣','犃'],'yǎng yāng':['咉'],'zǎ zé zhā':['咋'],'hé hè huó huò hú':['和'],hāi:['咍'],dā:['咑','哒','噠','墶','搭','撘','耷','褡','鎝','𨱏'],'kǎ kā':['咔'],gū:['咕','唂','唃','姑','嫴','孤','巬','巭','柧','橭','沽','泒','稒','笟','箍','箛','篐','罛','苽','菇','菰','蓇','觚','軱','軲','轱','辜','酤','鈲','鮕','鴣','鸪',],'kā gā':['咖'],zuo:['咗'],lóng:['咙','嚨','嶐','巃','巄','昽','曨','朧','栊','槞','櫳','湰','滝','漋','爖','珑','瓏','癃','眬','矓','砻','礱','礲','窿','竜','聋','聾','胧','茏','蘢','蠪','蠬','襱','豅','鏧','鑨','霳','靇','驡','鸗','龍','龒','龙',],'xiàn xián':['咞'],qì:['咠','唭','噐','器','夡','弃','憇','憩','暣','棄','欫','气','気','氣','汔','汽','泣','湆','湇','炁','甈','盵','矵','碛','碶','磜','磧','罊','芞','葺','藒','蟿','訖','讫','迄','鐑',],'xì dié':['咥'],'liē liě lié lie':['咧'],zī:['咨','嗞','姕','姿','孜','孳','孶','崰','嵫','栥','椔','淄','湽','滋','澬','玆','禌','秶','粢','紎','緇','緕','纃','缁','茊','茲','葘','諮','谘','貲','資','赀','资','赼','趑','趦','輜','輺','辎','鄑','鈭','錙','鍿','鎡','锱','镃','頾','頿','髭','鯔','鰦','鲻','鶅','鼒','齍','齜','龇',],mī:['咪'],'jī xī qià':['咭'],'gē luò kǎ lo':['咯'],'shù xún':['咰'],'zán zá zǎ zan':['咱'],'hāi ké':['咳'],huī:['咴','噅','噕','婎','媈','幑','徽','恢','拻','挥','揮','晖','暉','楎','洃','瀈','灰','灳','烣','睳','禈','翚','翬','蘳','袆','褘','詼','诙','豗','輝','辉','鰴','麾','㧑',],'huài shì':['咶'],táo:['咷','啕','桃','檮','洮','淘','祹','綯','绹','萄','蜪','裪','迯','逃','醄','鋾','鞀','鞉','饀','駣','騊','鼗','𫘦',],xián:['咸','啣','娴','娹','婱','嫌','嫺','嫻','弦','挦','撏','涎','湺','澖','甉','痫','癇','癎','絃','胘','舷','藖','蚿','蛝','衔','衘','誸','諴','賢','贒','贤','輱','醎','銜','鑦','閑','闲','鷳','鷴','鷼','鹇','鹹','麙','𫍯',],'è àn':['咹'],'xuān xuǎn':['咺','烜'],'wāi hé wǒ guǎ guō':['咼'],'yàn yè yān':['咽'],āi:['哀','哎','埃','溾','銰','鎄','锿'],pǐn:['品','榀'],shěn:['哂','婶','嬸','审','宷','審','弞','曋','渖','瀋','瞫','矤','矧','覾','訠','諗','讅','谂','谉','邥','頣','魫',],'hǒng hōng hòng':['哄'],'wā wa':['哇'],'hā hǎ hà':['哈'],zāi:['哉','栽','渽','溨','災','灾','烖','睵','賳'],'dì diè':['哋'],pài:['哌','沠','派','渒','湃','蒎','鎃'],'gén hěn':['哏'],'yǎ yā':['哑','雅'],'yuě huì':['哕','噦'],nián:['哖','年','秊','秥','鮎','鯰','鲇','鲶','鵇','黏'],'huá huā':['哗','嘩'],'jì jiē zhāi':['哜','嚌'],mōu:['哞'],'yō yo':['哟','喲'],lòng:['哢','梇','贚'],'ò ó é':['哦'],'lī lǐ li':['哩'],'nǎ na nǎi né něi':['哪'],hè:['哬','垎','壑','寉','惒','焃','煂','燺','爀','癋','碋','翯','褐','謞','賀','贺','赫','靍','靎','靏','鶴','鸖','鹤',],'bō pò bā':['哱'],zhé:['哲','啠','喆','嚞','埑','悊','摺','晢','晣','歽','矺','砓','磔','籷','粍','虴','蛰','蟄','袩','詟','謫','謺','讁','讋','谪','輒','輙','轍','辄','辙','鮿',],'liàng láng':['哴'],'liè lǜ':['哷'],hān:['哻','憨','蚶','谽','酣','頇','顸','馠','魽','鼾'],'hēng hng':['哼'],gěng:['哽','埂','峺','挭','梗','綆','绠','耿','莄','郠','骾','鯁','鲠','𬒔',],'chuò yuè':['哾'],'gě jiā':['哿'],'bei bài':['唄'],'hán hàn':['唅'],chún:['唇','浱','湻','滣','漘','犉','純','纯','脣','莼','蒓','蓴','醇','醕','錞','陙','鯙','鶉','鹑','𬭚',],'ài āi':['唉'],'jiá qiǎn':['唊'],'yán dàn xián':['唌'],chē:['唓','砗','硨','莗','蛼'],'wú ńg ń':['唔'],zào:['唕','唣','噪','慥','梍','灶','煰','燥','皁','皂','竃','竈','簉','艁','譟','趮','躁','造','𥖨',],dí:['唙','啇','嘀','嚁','嫡','廸','敌','敵','梑','涤','滌','狄','笛','籴','糴','苖','荻','蔋','蔐','藡','覿','觌','豴','迪','靮','頔','馰','髢','鸐','𬱖',],'gòng hǒng gǒng':['唝','嗊'],dóu:['唞'],'lào láo':['唠','嘮','憦'],huàn:['唤','喚','奂','奐','宦','嵈','幻','患','愌','换','換','擐','攌','梙','槵','浣','涣','渙','漶','澣','烉','焕','煥','瑍','痪','瘓','睆','肒','藧','豢','轘','逭','鯇','鯶','鰀','鲩',],léng:['唥','塄','楞','碐','薐'],'wō wěi':['唩'],fěng:['唪','覂','諷','讽'],'yín jìn':['唫'],'hǔ xià':['唬'],wéi:['唯','围','圍','壝','峗','峞','嵬','帏','帷','幃','惟','桅','沩','洈','涠','湋','溈','潍','潙','潿','濰','犩','矀','維','维','蓶','覹','违','違','鄬','醀','鍏','闈','闱','韋','韦','鮠','𣲗','𬶏',],shuā:['唰'],chàng:['唱','怅','悵','暢','焻','畅','畼','誯','韔','鬯'],'ér wā':['唲'],qiàng:['唴','炝','熗','羻'],yō:['唷'],yū:['唹','淤','瘀','盓','箊','紆','纡','込','迂','迃','陓'],lài:['唻','濑','瀨','瀬','癞','癩','睐','睞','籁','籟','藾','賚','賴','赉','赖','頼','顂','鵣',],tuò:['唾','嶞','柝','毤','毻','箨','籜','萚','蘀','跅'],'zhōu zhāo tiào':['啁'],kěn:['啃','垦','墾','恳','懇','肎','肯','肻','豤','錹'],'zhuó zhào':['啅','濯'],'hēng hèng':['啈','悙'],'lín lán':['啉'],'a ā á ǎ à':['啊'],qiāng:['啌','嗴','嶈','戕','摤','斨','枪','槍','溬','牄','猐','獇','羌','羗','腔','蜣','謒','鏘','锖','锵',],'tūn zhūn xiāng duǐ':['啍'],wèn:['問','妏','揾','搵','璺','问','顐'],'cuì qi':['啐'],'dié shà jié tì':['啑'],'yuē wā':['啘'],'zǐ cǐ':['啙'],'bǐ tú':['啚'],'chuò chuài':['啜'],'yǎ yā è':['啞'],fēi:['啡','婓','婔','扉','暃','渄','猆','緋','绯','裶','霏','非','靟','飛','飝','飞','餥','馡','騑','騛','鯡','鲱','𬴂',],pí:['啤','壀','枇','毗','毘','焷','琵','疲','皮','篺','罴','羆','脾','腗','膍','蚍','蚽','蜱','螷','蠯','豼','貔','郫','鈹','阰','陴','隦','魮','鮍','鲏','鵧','鼙',],shá:['啥'],'lā la':['啦'],'yīng qíng':['啨'],pā:['啪','妑','舥','葩','趴'],'zhě shì':['啫'],sè:['啬','嗇','懎','擌','栜','歮','涩','渋','澀','澁','濇','濏','瀒','瑟','璱','瘷','穑','穡','穯','繬','譅','轖','銫','鏼','铯','飋',],niè:['啮','嗫','噛','嚙','囁','囓','圼','孼','孽','嵲','嶭','巕','帇','敜','枿','槷','櫱','涅','湼','痆','篞','籋','糱','糵','聂','聶','臬','臲','蘖','蠥','讘','踂','踗','踙','蹑','躡','錜','鎳','鑈','鑷','钀','镊','镍','闑','陧','隉','顳','颞','齧','𫔶',],'luō luó luo':['啰','囉'],'tān chǎn tuō':['啴'],bo:['啵','蔔'],dìng:['啶','定','椗','矴','碇','碠','磸','聢','腚','萣','蝊','訂','订','錠','锭','顁','飣','饤',],lāng:['啷'],'án ān':['啽'],kā:['喀','擖'],'yóng yú':['喁'],'lā lá lǎ':['喇'],jiē:['喈','喼','嗟','堦','媘','接','掲','擑','湝','煯','疖','痎','癤','皆','秸','稭','脻','蝔','街','謯','阶','階','鞂','鶛',],hóu:['喉','帿','猴','瘊','睺','篌','糇','翭','葔','鄇','鍭','餱','骺','鯸','𬭤',],'dié zhá':['喋'],wāi:['喎','歪','竵'],'nuò rě':['喏'],'xù huò guó':['喐'],zán:['喒'],'wō ō':['喔'],hú:['喖','嘝','囫','壶','壷','壺','媩','弧','搰','斛','楜','槲','湖','瀫','焀','煳','狐','猢','瑚','瓳','箶','絗','縠','胡','葫','蔛','蝴','螜','衚','觳','醐','鍸','頶','餬','鬍','魱','鰗','鵠','鶘','鶦','鹕',],'huàn yuán xuǎn hé':['喛'],xǐ:['喜','囍','壐','屣','徙','憙','枲','橲','歖','漇','玺','璽','矖','禧','縰','葈','葸','蓰','蟢','謑','蹝','躧','鈢','鉨','鉩','鱚','𬭳','𬶮',],'hē hè yè':['喝'],kuì:['喟','嘳','媿','嬇','愦','愧','憒','篑','簣','籄','聩','聭','聵','膭','蕢','謉','餽','饋','馈',],'zhǒng chuáng':['喠'],'wéi wèi':['喡','為','爲'],'duó zhà':['喥'],'sāng sàng':['喪'],'qiáo jiāo':['喬'],'pèn bēn':['喯'],'cān sūn qī':['喰'],'zhā chā':['喳'],miāo:['喵'],'pēn pèn':['喷'],kuí:['喹','夔','奎','巙','戣','揆','晆','暌','楏','楑','櫆','犪','睽','葵','藈','蘷','虁','蝰','躨','逵','鄈','鍨','鍷','頯','馗','騤','骙','魁',],'lou lóu':['喽'],'zào qiāo':['喿'],'hè xiāo xiào hù':['嗃'],'á shà':['嗄'],xiù:['嗅','岫','峀','溴','珛','琇','璓','秀','綉','繍','繡','绣','螑','袖','褎','褏','銹','鏥','鏽','锈','齅',],'qiāng qiàng':['嗆','戗','戧','蹌','蹡'],'ài yì':['嗌','艾'],'má mǎ ma':['嗎'],'kè kē':['嗑'],'dā tà':['嗒','鎉'],sǎng:['嗓','搡','磉','褬','鎟','顙','颡'],chēn:['嗔','抻','琛','瞋','諃','謓','賝','郴','𬘭'],'wā gǔ':['嗗'],'pǎng bēng':['嗙'],'xián qiǎn qiān':['嗛'],lào:['嗠','嫪','橯','涝','澇','耢','耮','躼','軂','酪'],wēng:['嗡','翁','聬','螉','鎓','鶲','鹟','𬭩'],wà:['嗢','腽','膃','袜','襪','韤'],'hēi hāi':['嗨'],hē:['嗬','欱','蠚','訶','诃'],zi:['嗭'],sǎi:['嗮'],'ǹg ńg ňg':['嗯'],gě:['嗰','舸'],ná:['嗱','拏','拿','鎿','镎'],diǎ:['嗲'],'ài ǎi āi':['嗳'],tōng:['嗵','樋','炵','蓪'],'zuī suī':['嗺'],'zhē zhè zhù zhe':['嗻'],mò:['嗼','圽','塻','墨','妺','嫼','寞','帞','昩','末','枺','歿','殁','沫','漠','爅','獏','瘼','皌','眽','眿','瞐','瞙','砞','礳','秣','絈','纆','耱','茉','莈','蓦','蛨','蟔','貃','貊','貘','銆','鏌','镆','陌','靺','驀','魩','默','黙','𬙊',],sòu:['嗽','瘶'],tǎn:['嗿','坦','忐','憳','憻','暺','毯','璮','菼','袒','襢','醓','鉭','钽',],'jiào dǎo':['嘄'],'kǎi gě':['嘅'],'shān càn':['嘇'],cáo:['嘈','嶆','曹','曺','槽','漕','艚','蓸','螬','褿','鏪','𥕢'],piào:['嘌','徱','蔈','驃'],'lóu lou':['嘍'],gǎ:['尕','玍'],'gǔ jiǎ':['嘏'],'jiāo xiāo':['嘐'],'xū shī':['嘘','噓'],pó:['嘙','嚩','婆','櫇','皤','鄱'],'dē dēi':['嘚'],'ma má':['嘛'],'lē lei':['嘞'],'gā gá gǎ':['嘠'],sāi:['嘥','噻','毢','腮','顋','鰓'],'zuō chuài':['嘬'],'cháo zhāo':['嘲','朝','鼂'],zuǐ:['嘴','噿','嶊','璻'],'qiáo qiào':['嘺','翹','谯'],'chù xù shòu':['嘼'],'tān chǎn':['嘽'],'dàn tán':['嘾','弾','彈','惔','澹'],'hēi mò':['嘿'],ě:['噁','砨','頋','騀','鵈'],'fān bo':['噃'],chuáng:['噇','床','牀'],'cù zā hé':['噈'],'tūn kuò':['噋'],'cēng chēng':['噌'],dēng:['噔','嬁','灯','燈','璒','登','竳','簦','艠','豋'],pū:['噗','扑','撲','攴','攵','潽','炇','陠'],juē:['噘','屩','屫','撧'],lū:['噜','嚕','撸','擼','謢'],zhān:['噡','岾','惉','旃','旜','枬','栴','毡','氈','氊','沾','瞻','薝','蛅','詀','詹','譫','谵','趈','邅','閚','霑','飦','饘','驙','魙','鱣','鸇','鹯','𫗴',],ō:['噢'],'zhòu zhuó':['噣'],'jiào qiào chī':['噭'],yuàn:['噮','妴','怨','愿','掾','瑗','禐','苑','衏','裫','褑','院','願',],'ǎi ài āi':['噯'],'yōng yǒng':['噰','澭'],'jué xué':['噱'],'pēn pèn fèn':['噴'],gá:['噶','尜','釓','錷','钆'],'xīn hěn hèn':['噷'],dāng:['噹','澢','珰','璫','筜','簹','艡','蟷','裆','襠'],làn:['嚂','滥','濫','烂','燗','爁','爛','爤','瓓','糷','钄'],tà:['嚃','嚺','崉','挞','搨','撻','榻','橽','毾','涾','澾','濌','禢','粏','誻','譶','蹋','蹹','躂','躢','遝','錔','闒','闥','闼','阘','鞜','鞳',],'huō huò ǒ':['嚄'],hāo:['嚆','茠','蒿','薅'],'hè xià':['嚇'],'xiù pì':['嚊'],'zhōu chóu':['嚋','盩','诪'],mē:['嚒'],'chā cā':['嚓'],'bó pào bào':['嚗'],'me mèi mò':['嚜'],'xié hái':['嚡'],'áo xiāo':['嚣'],mō:['嚤','摸'],pín:['嚬','娦','嫔','嬪','玭','矉','薲','蠙','貧','贫','顰','颦','𬞟',],mè:['嚰','濹'],'rǎng rāng':['嚷'],lá:['嚹','旯'],'jiáo jué jiào':['嚼'],chuò:['嚽','娖','擉','歠','涰','磭','踀','輟','辍','辵','辶','酫','鑡','餟','齪','龊',],'huān huàn':['嚾'],'zá cà':['囃'],chài:['囆','虿','蠆','袃','訍'],'náng nāng':['囊'],'zá zàn cān':['囋'],sū:['囌','櫯','甦','稣','穌','窣','蘇','蘓','酥','鯂'],zèng:['囎','熷','甑','贈','赠','鋥','锃'],'zá niè yàn':['囐'],nāng:['囔'],'luó luō luo':['囖'],'wéi guó':['囗'],huí:['囘','回','囬','廻','廽','恛','洄','痐','茴','蚘','蛔','蛕','蜖','迴','逥','鮰',],nín:['囜','您','脌'],'jiǎn nān':['囝'],nān:['囡'],tuán:['团','団','團','慱','抟','摶','檲','糰','鏄','鷒','鷻'],'tún dùn':['囤','坉'],guó:['囯','囶','囻','国','圀','國','帼','幗','慖','摑','漍','聝','腘','膕','蔮','虢','馘','𬇹',],kùn:['困','涃','睏'],'wéi tōng':['囲'],qūn:['囷','夋','逡'],rì:['囸','日','衵','鈤','馹','驲'],tāi:['囼','孡','胎'],pǔ:['圃','圑','擈','普','暜','樸','檏','氆','浦','溥','烳','諩','譜','谱','蹼','鐠','镨',],'quān juàn juān':['圈','圏'],'chuí chuán':['圌'],tuǎn:['圕','畽','疃'],lüè:['圙','掠','略','畧','稤','鋝','鋢','锊','䂮'],'huán yuán':['圜'],luán:['圝','圞','奱','娈','孌','孪','孿','峦','巒','挛','攣','曫','栾','欒','滦','灤','癴','癵','羉','脔','臠','虊','銮','鑾','鵉','鸞','鸾',],tǔ:['土','圡','釷','钍'],'xū wéi':['圩'],'dì de':['地','嶳'],'qiān sú':['圱'],zhèn:['圳','塦','挋','振','朕','栚','甽','眹','紖','絼','纼','誫','賑','赈','鋴','鎭','鎮','镇','阵','陣','震','鴆','鸩',],'chǎng cháng':['场','場','塲'],'qí yín':['圻'],jiá:['圿','忦','恝','戞','扴','脥','荚','莢','蛱','蛺','裌','跲','郏','郟','鋏','铗','頬','頰','颊','鴶','鵊',],'zhǐ zhì':['坁'],bǎn:['坂','岅','昄','板','版','瓪','粄','舨','蝂','鈑','钣','阪','魬',],qǐn:['坅','寑','寝','寢','昑','梫','笉','螼','赾','鋟','锓'],'méi fén':['坆'],'rǒng kēng':['坈'],'fāng fáng':['坊'],'fèn bèn':['坋'],tān:['坍','怹','摊','擹','攤','滩','灘','瘫','癱','舑','貪','贪'],'huài pēi pī péi':['坏'],'dì làn':['坔'],tán:['坛','墰','墵','壇','壜','婒','憛','昙','曇','榃','檀','潭','燂','痰','磹','罈','罎','藫','談','譚','譠','谈','谭','貚','郯','醰','錟','顃',],bà:['坝','垻','壩','弝','欛','灞','爸','矲','覇','霸','鮁','鲅'],fén:['坟','墳','妢','岎','幩','枌','棼','汾','焚','燌','燓','羒','羵','蒶','蕡','蚠','蚡','豮','豶','轒','鐼','隫','馩','魵','黂','鼖','鼢','𣸣',],zhuì:['坠','墜','惴','甀','畷','礈','綴','縋','缀','缒','腏','膇','諈','贅','赘','醊','錣','鑆',],pō:['坡','岥','泼','溌','潑','釙','鏺','钋','頗','颇','䥽'],'pǎn bàn':['坢'],kūn:['坤','堃','堒','崐','崑','昆','晜','潉','焜','熴','猑','琨','瑻','菎','蜫','裈','裩','褌','醌','錕','锟','騉','髠','髡','髨','鯤','鲲','鵾','鶤','鹍',],diàn:['坫','垫','墊','壂','奠','婝','店','惦','扂','橂','殿','淀','澱','玷','琔','电','癜','簟','蜔','鈿','電','靛','驔',],'mù mǔ':['坶'],'kē kě':['坷','軻'],xuè:['坹','岤','桖','瀥','狘','瞲','謔','谑','趐'],'dǐ chí':['坻','柢'],lā:['垃','柆','菈','邋'],lǒng:['垄','垅','壟','壠','拢','攏','竉','陇','隴','𬕂'],mín:['垊','姄','岷','崏','捪','旻','旼','民','珉','琘','琝','瑉','痻','盿','砇','緍','緡','缗','罠','苠','鈱','錉','鍲','鴖',],'dòng tóng':['垌','峒','洞'],cí:['垐','嬨','慈','柌','濨','珁','瓷','甆','磁','礠','祠','糍','茨','詞','词','辝','辞','辤','辭','雌','飺','餈','鴜','鶿','鷀','鹚',],duī:['垖','堆','塠','痽','磓','鐓','鐜','鴭'],'duò duǒ':['垛'],'duǒ duò':['垜','挆'],chá:['垞','察','嵖','搽','槎','檫','猹','茬','茶','詧','靫','𥻗'],shǎng:['垧','晌','樉','賞','贘','赏','鋿','鏛','鑜'],shǒu:['垨','守','手','扌','艏','首'],da:['垯','繨','跶'],háng:['垳','斻','杭','筕','絎','绗','航','苀','蚢','裄','貥','迒','頏','颃','魧',],'ān ǎn':['垵'],xīng:['垶','惺','星','曐','煋','猩','瑆','皨','篂','腥','興','觪','觲','謃','騂','骍','鮏','鯹',],'yuàn huán':['垸'],bāng:['垹','帮','幇','幚','幫','捠','梆','浜','邦','邫','鞤','𠳐',],'póu fú':['垺'],cén:['埁','岑','涔'],'běng fēng':['埄'],'dì fáng':['埅'],'xiá jiā':['埉'],'mái mán':['埋'],làng:['埌','崀','浪','蒗','閬','㫰'],'shān yán':['埏'],'qín jīn':['埐'],'pǔ bù':['埔'],huā:['埖','婲','椛','硴','糀','花','蒊','蘤','誮','錵'],'suì sù':['埣'],'pí pì':['埤'],'qīng zhēng':['埥','鲭'],'wǎn wān':['埦'],lǔn:['埨','稐','𫭢'],'zhēng chéng':['埩'],kōng:['埪','崆','箜','躻','錓','鵼'],'cǎi cài':['埰','寀','采'],'chù tòu':['埱'],běng:['埲','琫','菶','鞛'],'kǎn xiàn':['埳'],'yì shì':['埶','醳'],péi:['培','毰','裴','裵','賠','赔','錇','锫','阫','陪'],'sào sǎo':['埽'],'jǐn qīn jìn':['堇'],'péng bèng':['堋'],'qiàn zàn jiàn':['堑'],àn:['堓','屵','岸','按','暗','案','胺','荌','豻','貋','錌','闇','隌','黯',],'duò huī':['堕','墮'],huán:['堚','寏','寰','峘','桓','洹','澴','獂','环','環','糫','繯','缳','羦','荁','萈','萑','豲','鍰','鐶','锾','镮','闤','阛','雈','鬟','鹮','𬘫','𤩽',],'bǎo bǔ pù':['堡'],'máo móu wǔ':['堥'],ruán:['堧','壖','撋'],'ài è yè':['堨'],gèng:['堩','暅'],méi:['堳','塺','媒','嵋','徾','攗','枚','栂','梅','楣','楳','槑','湄','湈','煤','猸','玫','珻','瑂','眉','睂','禖','脄','脢','腜','苺','莓','葿','郿','酶','鎇','镅','霉','鶥','鹛','黴',],dǔ:['堵','琽','睹','笃','篤','覩','賭','赌'],féng:['堸','綘','艂','逢'],hèng:['堼'],chūn:['堾','媋','旾','春','暙','杶','椿','槆','橁','櫄','瑃','箺','萅','蝽','輴','鰆','鶞','䲠',],jiǎng:['塂','奖','奨','奬','桨','槳','獎','耩','膙','蒋','蔣','講','讲','顜',],huāng:['塃','巟','慌','肓','荒','衁'],duàn:['塅','断','斷','椴','段','毈','煅','瑖','碫','簖','籪','緞','缎','腶','葮','躖','鍛','锻',],tǎ:['塔','墖','獭','獺','鮙','鰨','鳎'],wěng:['塕','奣','嵡','攚','暡','瞈','蓊'],'sāi sài sè':['塞'],zàng:['塟','弉','臓','臟','葬','蔵','銺'],tián:['塡','屇','恬','沺','湉','璳','甛','甜','田','畋','畑','碵','磌','胋','闐','阗','鴫','鷆','鷏',],zhèng:['塣','幁','政','証','諍','證','证','诤','郑','鄭','靕','鴊',],'tián zhèn':['填'],wēn:['塭','昷','榲','殟','温','溫','瑥','瘟','蕰','豱','輼','轀','辒','鎾','饂','鰛','鰮','鳁',],liù:['塯','廇','磟','翏','雡','霤','餾','鬸','鷚','鹨'],hǎi:['塰','海','烸','酼','醢'],lǎng:['塱','朖','朗','朤','烺','蓢','㮾'],bèng:['塴','揼','泵','甏','綳','蹦','迸','逬','鏰','镚'],chén:['塵','宸','尘','忱','敐','敶','晨','曟','栕','樄','沉','煁','瘎','臣','茞','莀','莐','蔯','薼','螴','訦','諶','軙','辰','迧','鈂','陈','陳','霃','鷐','麎',],'ōu qiū':['塸'],'qiàn jiàn':['塹'],'zhuān tuán':['塼'],shuǎng:['塽','慡','漺','爽','縔','鏯'],shú:['塾','婌','孰','璹','秫','贖','赎'],lǒu:['塿','嵝','嶁','甊','篓','簍'],chí:['墀','弛','持','池','漦','竾','筂','箎','篪','茌','荎','蚳','謘','貾','赿','踟','迟','迡','遅','遟','遲','鍉','馳','驰',],shù:['墅','庶','庻','怷','恕','戍','束','树','樹','沭','漱','潄','濖','竖','竪','絉','腧','荗','蒁','虪','術','裋','豎','述','鉥','錰','鏣','霔','鶐','𬬸',],'dì zhì':['墆','疐'],kàn:['墈','崁','瞰','矙','磡','衎','鬫'],chěn:['墋','夦','硶','碜','磣','贂','趻','踸','鍖'],'zhǐ zhuó':['墌'],qiǎng:['墏','繈','繦','羥','襁'],zēng:['増','增','憎','璔','矰','磳','罾','譄','鄫','鱛','䎖'],qiáng:['墙','墻','嫱','嬙','樯','檣','漒','牆','艢','蔃','蔷','蘠',],'kuài tuí':['墤'],'tuǎn dǒng':['墥'],'qiáo què':['墧'],'zūn dūn':['墫'],'qiāo áo':['墽'],'yì tú':['墿'],'xué bó jué':['壆'],lǎn:['壈','嬾','孄','孏','懒','懶','揽','擥','攬','榄','欖','浨','漤','灠','纜','缆','罱','覧','覽','览','醂','顲',],huài:['壊','壞','蘾'],rǎng:['壌','壤','攘','爙'],'làn xiàn':['壏'],dǎo:['壔','导','導','岛','島','嶋','嶌','嶹','捣','搗','擣','槝','祷','禂','禱','蹈','陦','隝','隯',],ruǐ:['壡','桵','橤','繠','蕊','蕋','蘂','蘃'],san:['壭'],zhuàng:['壮','壯','壵','撞','焋','状','狀'],'ké qiào':['壳','殼'],kǔn:['壸','壼','悃','捆','梱','硱','祵','稇','稛','綑','裍','閫','閸','阃',],mǎng:['壾','漭','茻','莽','莾','蠎'],cún:['壿','存'],'zhǐ zhōng':['夂'],'gǔ yíng':['夃'],'jiàng xiáng':['夅','降'],'páng féng fēng':['夆'],zhāi:['夈','捚','摘','斋','斎','榸','粂','齋'],'xuàn xiòng':['夐'],wài:['外','顡'],'wǎn yuàn wān yuān':['夗'],'mǎo wǎn':['夘'],mèng:['夢','夣','孟','梦','癦','霥'],'dà dài':['大'],'fū fú':['夫','姇','枎','粰'],guài:['夬','怪','恠'],yāng:['央','姎','抰','殃','泱','秧','胦','鉠','鍈','雵','鴦','鸯',],'hāng bèn':['夯'],gǎo:['夰','搞','杲','槀','槁','檺','稁','稾','稿','縞','缟','菒','藁','藳',],'tāo běn':['夲'],'tóu tou':['头'],'yǎn tāo':['夵'],'kuā kuà':['夸','誇'],'jiá jiā gā xiá':['夹'],huà:['夻','婳','嫿','嬅','崋','摦','杹','枠','桦','槬','樺','澅','画','畫','畵','繣','舙','話','諙','譮','话','黊',],'jiā jiá gā xiá':['夾'],ēn:['奀','恩','蒽'],'dī tì':['奃'],'yǎn yān':['奄','渰'],pào:['奅','疱','皰','砲','礟','礮','靤','麭'],nài:['奈','柰','渿','耐','萘','褦','錼','鼐'],'quān juàn':['奍','弮','棬'],zòu:['奏','揍'],'qì qiè xiè':['契'],kāi:['奒','开','揩','鐦','锎','開'],'bēn bèn':['奔','泍'],tào:['套'],'zàng zhuǎng':['奘'],běn:['奙','本','楍','畚','翉','苯'],'xùn zhuì':['奞'],shē:['奢','檨','猞','畭','畲','賒','賖','赊','輋','𪨶'],'hǎ pò tǎi':['奤'],'ào yù':['奥','奧','澚'],yūn:['奫','氲','氳','蒀','蒕','蝹','贇','赟','𫖳'],'duǒ chě':['奲'],'nǚ rǔ':['女'],nú:['奴','孥','笯','駑','驽'],'dīng dǐng tiǎn':['奵'],'tā jiě':['她'],nuán:['奻'],'hǎo hào':['好'],fàn:['奿','嬎','梵','汎','泛','滼','瀪','犯','畈','盕','笵','範','范','訉','販','贩','軬','輽','飯','飰','饭',],shuò:['妁','搠','朔','槊','烁','爍','矟','蒴','鎙','鑠','铄'],'fēi pèi':['妃'],wàng:['妄','忘','旺','望','朢'],zhuāng:['妆','妝','娤','庄','庒','桩','梉','樁','粧','糚','荘','莊','装','裝',],mā:['妈','媽'],'fū yōu':['妋'],'hài jiè':['妎'],dù:['妒','妬','杜','殬','渡','秺','芏','荰','螙','蠧','蠹','鍍','镀','靯','𬭊',],miào:['妙','庙','庿','廟','玅','竗'],'fǒu pēi pī':['妚'],'yuè jué':['妜'],niū:['妞'],'nà nàn':['妠'],tuǒ:['妥','嫷','庹','椭','楕','橢','鬌','鰖','鵎'],'wàn yuán':['妧'],fáng:['妨','房','肪','防','魴','鲂'],nī:['妮'],zhóu:['妯','碡'],zhāo:['妱','巶','招','昭','釗','鉊','鍣','钊','駋','𬬿'],'nǎi nǐ':['妳'],tǒu:['妵','敨','紏','蘣','黈'],'xián xuán xù':['妶'],'zhí yì':['妷','秇'],ē:['妸','妿','婀','屙'],mèi:['妹','媚','寐','抺','旀','昧','沬','煝','痗','眛','睸','祙','篃','蝞','袂','跊','鬽','魅',],'qī qì':['妻'],'xū xǔ':['姁','稰'],'shān shàn':['姍','姗','苫','釤','钐'],mán:['姏','慲','樠','蛮','蠻','謾','饅','馒','鬗','鬘','鰻','鳗'],jiě:['姐','媎','檞','毑','飷'],'wěi wēi':['委'],pīn:['姘','拼','礗','穦','馪','驞'],'huá huó':['姡'],'jiāo xiáo':['姣'],'gòu dù':['姤'],'lǎo mǔ':['姥'],'nián niàn':['姩'],zhěn:['姫','屒','弫','抮','昣','枕','畛','疹','眕','稹','縝','縥','缜','聄','萙','袗','裖','覙','診','诊','軫','轸','辴','駗','鬒',],héng:['姮','恆','恒','烆','珩','胻','蘅','衡','鑅','鴴','鵆','鸻',],'jūn xún':['姰'],'kuā hù':['姱'],'è yà':['姶'],'xiān shēn':['姺'],wá:['娃'],'ráo rǎo':['娆','嬈'],'shào shāo':['娋'],xiē:['娎','揳','楔','歇','蝎','蠍'],'wǔ méi mǔ':['娒'],'chuò lài':['娕'],niáng:['娘','嬢','孃'],'nà nuó':['娜','𦰡'],'pōu bǐ':['娝'],'něi suī':['娞'],tuì:['娧','煺','蛻','蜕','退','駾'],mǎn:['娨','屘','満','满','滿','螨','蟎','襔','鏋'],'wú wù yú':['娪'],'xī āi':['娭'],'zhuì shuì':['娷'],'dōng dòng':['娻'],'ǎi ái è':['娾'],'ē ě':['娿'],mián:['婂','嬵','宀','杣','棉','檰','櫋','眠','矈','矊','矏','綿','緜','绵','芇','蝒',],'pǒu péi bù':['婄'],biǎo:['婊','脿','表','裱','褾','諘','錶'],'fù fàn':['婏'],wǒ:['婐','婑','我'],'ní nǐ':['婗','棿'],'quán juàn':['婘','惓'],hūn:['婚','昏','昬','棔','涽','睧','睯','碈','荤','葷','蔒','轋','閽','阍',],'qiān jǐn':['婜'],'wān wà':['婠'],'lái lài':['婡','徕','徠'],'zhōu chōu':['婤'],'chuò nào':['婥'],'nüè àn':['婩'],'hùn kūn':['婫'],'dàng yáng':['婸'],nàn:['婻'],'ruò chuò':['婼'],jiǎ:['婽','岬','斚','斝','榎','槚','檟','玾','甲','胛','鉀','钾'],'tōu yú':['婾','媮'],'yù yú':['媀'],'wéi wěi':['媁'],'dì tí':['媂','珶','苐'],róu:['媃','揉','柔','渘','煣','瑈','瓇','禸','粈','糅','脜','腬','葇','蝚','蹂','輮','鍒','鞣','騥','鰇','鶔','𫐓',],'ruǎn nèn':['媆'],miáo:['媌','嫹','描','瞄','苗','鶓','鹋'],'yí pèi':['媐'],'mián miǎn':['媔'],'tí shì':['媞','惿'],'duò tuó':['媠','沲'],ǎo:['媪','媼','艹','芺','袄','襖','镺'],'chú zòu':['媰'],yìng:['媵','映','暎','硬','膡','鱦'],'qín shēn':['嫀'],jià:['嫁','幏','架','榢','稼','駕','驾'],sǎo:['嫂'],'zhēn zhěn':['嫃'],'jiē suǒ':['嫅'],'míng mǐng':['嫇'],niǎo:['嫋','嬝','嬲','茑','蔦','袅','裊','褭','鸟'],tāo:['嫍','幍','弢','慆','掏','搯','槄','涛','滔','濤','瑫','絛','縚','縧','绦','詜','謟','轁','鞱','韜','韬','飸','饕',],biáo:['嫑'],'piáo piāo':['嫖','薸'],xuán:['嫙','悬','懸','暶','檈','漩','玄','璇','璿','痃','蜁','𫠊',],'màn mān':['嫚'],kāng:['嫝','嵻','康','慷','槺','漮','砊','穅','糠','躿','鏮','鱇','𡐓','𩾌',],'hān nǎn':['嫨'],nèn:['嫩','嫰'],zhē:['嫬','遮'],'mā má':['嫲'],piè:['嫳'],zhǎn:['嫸','展','搌','斩','斬','琖','盏','盞','輾','醆','颭','飐',],'xiān yǎn jìn':['嬐'],liǎn:['嬚','敛','斂','琏','璉','羷','脸','臉','蔹','蘝','蘞','裣','襝','鄻',],'qióng huán xuān':['嬛'],dǒng:['嬞','懂','箽','董','蕫','諌'],cān:['嬠','湌','爘','飡','餐','驂','骖'],tiǎo:['嬥','宨','晀','朓','窱','脁'],bí:['嬶','荸','鼻'],liǔ:['嬼','柳','栁','桞','桺','橮','熮','珋','綹','绺','罶','羀','鋶','锍',],'qiān xiān':['孅','欦'],'xié huī':['孈'],'huān quán':['孉'],'lí lì':['孋','麗'],'zhú chuò':['孎'],kǒng:['孔','恐'],'mā zī':['孖'],'sūn xùn':['孙','孫'],'bèi bó':['孛','誖'],'yòu niū':['孧'],zhuǎn:['孨','竱','轉'],hái:['孩','骸'],nāo:['孬'],'chán càn':['孱'],bò:['孹','檗','蘗','譒'],nái:['孻','腉'],'níng nìng':['宁','寍','寗','寜','寧','甯'],zhái:['宅'],'tū jiā':['宊'],sòng:['宋','訟','誦','讼','诵','送','鎹','頌','颂','餸'],ròu:['宍','肉','譳'],zhūn:['宒','窀','衠','諄','谆','迍'],'mì fú':['宓'],'dàng tàn':['宕'],'wǎn yuān':['宛'],chǒng:['宠','寵'],qún:['宭','峮','帬','羣','群','裙','裠'],zǎi:['宰','崽'],'bǎo shí':['宲'],'jiā jia jie':['家'],'huāng huǎng':['宺'],kuān:['宽','寛','寬','臗','鑧','髋','髖'],'sù xiǔ xiù':['宿'],'jié zǎn':['寁'],'bìng bǐng':['寎'],'jìn qǐn':['寖'],'lóu jù':['寠'],'xiě xiè':['寫'],'qīn qìn':['寴'],cùn:['寸','籿'],duì:['对','対','對','怼','憝','懟','濧','瀩','碓','祋','綐','薱','譈','譵','轛','队','陮',],'lüè luó':['寽'],'shè yè yì':['射'],'jiāng jiàng qiāng':['将'],'jiāng jiàng':['將','浆','漿','畺'],zūn:['尊','嶟','樽','罇','遵','鐏','鱒','鳟','鶎','鷷','𨱔'],'shù zhù':['尌','澍'],xiǎo:['小','晓','暁','曉','皛','皢','筱','筿','篠','謏','𫍲'],'jié jí':['尐','诘','鞊'],'shǎo shào':['少'],ěr:['尒','尓','尔','栮','毦','洱','爾','珥','耳','薾','衈','趰','迩','邇','鉺','铒','餌','饵','駬',],'wāng yóu':['尢'],wāng:['尣','尩','尪','尫','汪'],liào:['尥','尦','廖','撂','料','炓','窷','鐐','镣','𪤗'],'méng máng lóng páng':['尨'],gà:['尬','魀'],'kuì kuǐ':['尯'],tuí:['尵','弚','穨','蘈','蹪','隤','頹','頺','頽','颓','魋','𬯎'],yǐn:['尹','嶾','引','朄','檃','檼','櫽','淾','濥','瘾','癮','粌','蘟','蚓','螾','讔','赺','趛','輑','鈏','靷',],'chǐ chě':['尺'],kāo:['尻','髛'],'jìn jǐn':['尽'],'wěi yǐ':['尾'],'niào suī':['尿'],céng:['层','層','嶒','驓'],diǎo:['屌'],'píng bǐng bīng':['屏'],lòu:['屚','漏','瘘','瘺','瘻','鏤','镂','陋'],'shǔ zhǔ':['属','屬'],'xiè tì':['屟'],'chè cǎo':['屮'],'tún zhūn':['屯'],'nì jǐ':['屰'],'hóng lóng':['屸'],'qǐ kǎi':['岂','豈'],áng:['岇','昂','昻'],'gǎng gāng':['岗','崗'],kě:['岢','敤','渇','渴','炣'],gǒu:['岣','狗','玽','笱','耇','耈','耉','苟','豿'],tiáo:['岧','岹','樤','祒','笤','芀','萔','蓚','蓨','蜩','迢','鋚','鎥','鞗','髫','鯈','鰷','鲦','齠','龆',],'qū jū':['岨'],lǐng:['岭','嶺','領','领'],pò:['岶','敀','洦','湐','烞','珀','破','砶','粕','蒪','魄'],'bā kè':['峇'],luò:['峈','摞','洛','洜','犖','珞','笿','纙','荦','詻','雒','駱','骆','鵅',],'fù niè':['峊'],ěn:['峎'],'zhì shì':['峙','崻'],qiǎ:['峠','跒','酠','鞐'],'qiáo jiào':['峤','癄'],'xié yé':['峫'],bū:['峬','庯','晡','誧','逋','鈽','錻','钸','餔','鵏'],chóng:['崇','崈','爞','虫','蝩','蟲','褈','隀'],'zú cuì':['崒','椊'],'líng léng':['崚'],'dòng dōng':['崠'],xiáo:['崤','洨','淆','訤','誵'],'pí bǐ':['崥','芘'],'zhǎn chán':['崭','嶃','嶄'],'wǎi wēi':['崴'],'yáng dàng':['崵'],'shì dié':['崼'],yào:['崾','曜','熎','燿','矅','穾','窔','筄','耀','艞','药','葯','薬','藥','袎','覞','詏','讑','靿','鷂','鹞','鼼',],'kān zhàn':['嵁'],'hán dǎng':['嵅'],'qiàn kàn':['嵌'],'wù máo':['嵍'],'kě jié':['嵑','嶱'],'wēi wěi':['嵔'],kē:['嵙','柯','棵','榼','樖','牁','牱','犐','珂','疴','瞌','磕','礚','科','稞','窠','萪','薖','蚵','蝌','趷','轲','醘','鈳','钶','頦','顆','颗','髁',],'dàng táng':['嵣'],'róng yíng':['嵤','爃'],'ái kǎi':['嵦'],'kāo qiāo':['嵪'],cuó:['嵯','嵳','痤','矬','蒫','蔖','虘','鹺','鹾'],'qiǎn qīn':['嵰'],'dì dié':['嵽'],cēn:['嵾'],dǐng:['嵿','艼','薡','鐤','頂','顶','鼎','鼑'],'áo ào':['嶅'],'pǐ pèi':['嶏'],'jiào qiáo':['嶠','潐'],'jué guì':['嶡','鳜'],'zhān shàn':['嶦','鳣'],'xiè jiè':['嶰'],'guī xī juàn':['嶲'],rū:['嶿'],'lì liè':['巁','棙','爄','綟'],'xī guī juàn':['巂'],'yíng hōng':['巆'],yǐng:['巊','廮','影','摬','梬','潁','瘿','癭','矨','穎','郢','鐛','頴','颍','颕','颖',],chǎo:['巐','炒','煼','眧','麨'],cuán:['巑','櫕','欑'],chuān:['巛','川','氚','瑏','穿'],'jīng xíng':['巠'],cháo:['巢','巣','晁','漅','潮','牊','窲','罺','謿','轈','鄛','鼌',],qiǎo:['巧','愀','髜'],gǒng:['巩','廾','拱','拲','栱','汞','珙','輁','鞏'],'chà chā chāi cī':['差'],'xiàng hàng':['巷'],shuài:['帅','帥','蟀'],pà:['帊','帕','怕','袙'],'tǎng nú':['帑'],'mò wà':['帓'],'tiē tiě tiè':['帖'],zhǒu:['帚','晭','疛','睭','箒','肘','菷','鯞'],'juǎn juàn':['帣'],shuì:['帨','涗','涚','睡','稅','税','裞'],'chóu dào':['帱','幬'],'jiǎn jiān sàn':['帴'],'shà qiè':['帹'],'qí jì':['帺','荠'],'shān qiāo shēn':['幓'],'zhuàng chuáng':['幢'],'chān chàn':['幨'],miè:['幭','懱','搣','滅','灭','烕','礣','篾','蔑','薎','蠛','衊','鑖','鱴','鴓',],'gān gàn':['干'],'bìng bīng':['并','幷'],'jī jǐ':['幾'],'guǎng ān':['广'],guǎng:['広','廣','犷','獷'],me:['庅'],'dùn tún':['庉'],'bài tīng':['庍'],'yìng yīng':['应'],'dǐ de':['底'],'dù duó':['度'],'máng méng páng':['庬'],'bìng píng':['庰'],chěng:['庱','悜','睈','逞','騁','骋'],'jī cuò':['庴'],qǐng:['庼','廎','檾','漀','苘','請','謦','请','頃','顷'],'guī wěi huì':['廆'],'jǐn qín':['廑'],kuò:['廓','扩','拡','擴','濶','筈','萿','葀','蛞','闊','阔','霩','鞟','鞹','韕','頢','鬠',],'qiáng sè':['廧','薔'],'yǐn yìn':['廴','隐','隠','隱','飮','飲','饮'],'pò pǎi':['廹','迫'],'nòng lòng':['弄'],'dì tì tuí':['弟'],'jué zhāng':['弡'],'mí mǐ':['弥','彌','靡'],chāo:['弨','怊','抄','欩','訬','超','鈔','钞'],yi:['弬'],shāo:['弰','旓','烧','焼','燒','筲','艄','萷','蕱','輎','髾','鮹',],'xuān yuān':['弲'],'qiáng qiǎng jiàng':['強','强'],'tán dàn':['弹','醈'],biè:['彆'],'qiáng jiàng qiǎng':['彊'],'jì xuě':['彐'],tuàn:['彖','褖'],yuē:['彟','曰','曱','矱'],'shān xiǎn':['彡'],wén:['彣','文','炆','珳','瘒','繧','聞','芠','蚉','蚊','螡','蟁','閺','閿','闅','闦','闻','阌','雯','馼','駇','魰','鳼','鴍','鼤','𫘜',],'péng bāng':['彭'],'piāo piào':['彯'],'zhuó bó':['彴'],'tuǒ yí':['彵'],'páng fǎng':['彷'],wǎng:['彺','往','徃','惘','枉','棢','網','网','罒','罓','罔','罖','菵','蛧','蝄','誷','輞','辋','魍',],cú:['徂','殂'],'dài dāi':['待'],huái:['徊','怀','懐','懷','槐','淮','耲','蘹','褢','褱','踝'],'wā wàng jiā':['徍'],'chěng zhèng':['徎'],'dé děi de':['得'],'cóng zòng':['從'],'shì tǐ':['徥'],'tí chí':['徲','鶗','鶙'],dé:['徳','德','恴','悳','惪','淂','鍀','锝'],'zhǐ zhēng':['徴','徵'],bié:['徶','癿','莂','蛂','襒','蹩'],'chōng zhǒng':['徸'],'jiǎo jiào':['徼','笅','筊'],'lòng lǒng':['徿'],'qú jù':['忂','渠','瞿','螶'],'dìng tìng':['忊'],gǎi:['忋','改'],rěn:['忍','栠','栣','秹','稔','綛','荏','荵','躵'],chàn:['忏','懴','懺','硟','羼','韂','顫'],tè:['忑','慝','特','蟘','鋱','铽'],'tè tēi tuī':['忒'],'gān hàn':['忓','攼'],'yì qì':['忔'],'tài shì':['忕'],'xī liě':['忚'],'yīng yìng':['応','應','譍'],'mǐn wěn mín':['忞','忟'],'sōng zhōng':['忪'],'yù shū':['忬','悆'],'qí shì':['忯','耆'],'tún zhūn dùn':['忳'],'qián qín':['忴','扲'],hún:['忶','浑','渾','餛','馄','魂','鼲'],niǔ:['忸','扭','炄','狃','紐','纽','莥','鈕','钮','靵'],'kuáng wǎng':['忹'],'kāng hàng':['忼'],'kài xì':['忾','愾'],òu:['怄','慪'],'bǎo bào':['怉'],'mín mén':['怋'],'zuò zhà':['怍'],zěn:['怎'],yàng:['怏','恙','样','様','樣','漾','羕','詇'],'kòu jù':['怐'],'náo niú':['怓'],'zhēng zhèng':['怔','掙','钲','铮'],'tiē zhān':['怗'],'hù gù':['怘'],'cū jù zū':['怚'],'sī sāi':['思'],'yóu chóu':['怞'],'tū dié':['怢'],'yōu yào':['怮'],xuàn:['怰','昡','楦','泫','渲','炫','琄','眩','碹','絢','縼','繏','绚','蔙','衒','袨','贙','鉉','鏇','铉','镟','颴',],'xù xuè':['怴'],'bì pī':['怶'],'xī shù':['怸'],'nèn nín':['恁'],'tiāo yáo':['恌'],'xī qī xù':['恓'],'xiào jiǎo':['恔'],'hū kuā':['恗'],nǜ:['恧','朒','衂','衄'],hèn:['恨'],'dòng tōng':['恫'],'quán zhuān':['恮'],'è wù ě wū':['恶','惡'],tòng:['恸','慟','憅','痛','衕'],'yuān juàn':['悁'],'qiāo qiǎo':['悄'],'jiè kè':['悈'],'hào jiào':['悎'],huǐ:['悔','檓','毀','毁','毇','燬','譭'],'mán mèn':['悗','鞔'],'yī yì':['悘','衣'],quān:['悛','箞','鐉','𨟠'],'kuī lǐ':['悝'],'yì niàn':['悥'],'mèn mēn':['悶'],guàn:['悹','悺','惯','慣','掼','摜','樌','欟','泴','涫','潅','灌','爟','瓘','盥','礶','祼','罆','罐','貫','贯','躀','遦','鏆','鑵','鱹','鸛','鹳',],'kōng kǒng':['悾'],'lǔn lùn':['惀'],guǒ:['惈','果','椁','槨','粿','綶','菓','蜾','裹','褁','輠','餜','馃',],'yuān wǎn':['惌','箢'],'lán lín':['惏'],'yù xù':['惐','淢'],'chuò chuì':['惙'],'hūn mèn':['惛'],'chǎng tǎng':['惝'],'suǒ ruǐ':['惢'],cǎn:['惨','慘','憯','黪','黲','䅟'],cán:['惭','慙','慚','残','殘','蚕','蝅','蠶','蠺'],'dàn dá':['惮','憚'],rě:['惹'],'yú tōu':['愉'],'kài qì':['愒'],'dàng táng shāng yáng':['愓'],'chén xìn dān':['愖'],'kè qià':['愘'],nuò:['愞','懦','懧','掿','搦','榒','稬','穤','糑','糥','糯','諾','诺','蹃','逽','鍩','锘',],gǎn:['感','擀','敢','桿','橄','澉','澸','皯','秆','稈','笴','芉','衦','赶','趕','鱤','鳡',],'còng sōng':['愡'],'sāi sī sǐ':['愢'],'gōng gòng hǒng':['愩','慐'],'shuò sù':['愬','洬'],'yáo yào':['愮'],huàng:['愰','曂','榥','滉','皝','皩','鎤','㿠'],zhěng:['愸','抍','拯','整','晸'],cǎo:['愺','艸','草','騲'],'xì xié':['慀'],'cǎo sāo':['慅'],'xù chù':['慉'],'qiè qiàn':['慊'],'cáo cóng':['慒'],'ào áo':['慠'],'lián liǎn':['慩','梿','槤','櫣'],'jìn qín jǐn':['慬'],'dì chì':['慸'],'zhí zhé':['慹'],'lóu lǚ':['慺','鷜'],còng:['憁','謥'],'zhī zhì':['憄','知','織','织'],chēng:['憆','摚','撐','撑','晿','柽','棦','橕','檉','泟','浾','琤','瞠','碀','緽','罉','蛏','蟶','赪','赬','鏿','鐣','阷','靗','頳','饓',],biē:['憋','虌','鱉','鳖','鼈','龞'],'chéng dèng zhèng':['憕'],'xǐ xī':['憘'],'duì dùn tūn':['憞'],'xiāo jiāo':['憢'],'xián xiàn':['憪'],'liáo liǎo':['憭','燎','爎','爒'],shéng:['憴','縄','繉','繩','绳','譝'],'náo nǎo náng':['憹'],'jǐng jìng':['憼'],'jǐ jiǎo':['憿'],'xuān huān':['懁'],'cǎo sāo sào':['懆'],mèn:['懑','懣','暪','焖','燜'],'mèng méng měng':['懜'],'ài yì nǐ':['懝'],'méng měng':['懞','瞢','矒'],'qí jī jì':['懠'],mǒ:['懡'],'lán xiàn':['懢'],'yōu yǒu':['懮'],'liú liǔ':['懰','藰'],ràng:['懹','譲','讓','让'],huān:['懽','欢','歓','歡','獾','讙','貛','酄','驩','鴅','鵍'],nǎn:['戁','揇','湳','煵','腩','蝻','赧'],'mí mó':['戂'],'gàng zhuàng':['戅','戆'],'zhuàng gàng':['戇'],'xū qu':['戌'],'xì hū':['戏','戯','戲'],'jiá gā':['戛'],zéi:['戝','蠈','賊','贼','鰂','鱡','鲗'],děng:['戥','等'],'hū xì':['戱'],chuō:['戳','踔','逴'],'biǎn piān':['扁'],'shǎng jiōng':['扄'],'shàn shān':['扇'],cái:['才','材','纔','裁','財','财'],'zhā zā zhá':['扎'],'lè lì cái':['扐'],'bā pá':['扒'],'dǎ dá':['打'],rēng:['扔'],'fǎn fú':['払'],'diǎo dí yuē lì':['扚'],'káng gāng':['扛'],'yū wū':['扜'],'yū wū kū':['扝'],'tuō chǐ yǐ':['扡'],'gǔ jié xì gē':['扢'],dèn:['扥','扽'],'sǎo sào':['扫','掃'],rǎo:['扰','擾','隢'],'xī chā qì':['扱'],'bān pān':['扳'],'bā ào':['扷'],'xī zhé':['扸'],'zhì sǔn kǎn':['扻'],zhǎo:['找','沼','瑵'],'kuáng wǎng zài':['抂'],'hú gǔ':['抇','鹄','鹘'],'bǎ bà':['把'],'dǎn shěn':['抌'],'nè nì ruì nà':['抐'],zhuā:['抓','檛','簻','膼','髽'],póu:['抔','裒'],'zhé shé zhē':['折'],'póu pōu fū':['抙','捊'],pāo:['抛','拋','脬','萢'],'ǎo ào niù':['抝'],'lūn lún':['抡','掄'],'qiǎng qiāng chēng':['抢'],'zhǐ zhǎi':['抧'],'bù pū':['抪','柨'],'yǎo tāo':['抭'],'hē hè qiā':['抲'],'nǐ ní':['抳'],'pī pēi':['抷'],'mǒ mò mā':['抹'],chōu:['抽','犨','犫','瘳','篘'],'jiā yá':['拁'],'fú bì':['拂','畐','鶝'],zhǎ:['拃','眨','砟','鮺','鲝'],'dān dàn dǎn':['担'],'chāi cā':['拆'],niān:['拈','蔫'],'lā lá lǎ là':['拉'],'bàn pàn':['拌'],pāi:['拍'],līn:['拎'],guǎi:['拐','枴','柺'],'tuò tà zhí':['拓'],'ào ǎo niù':['拗'],'jū gōu':['拘'],'pīn pàn fān':['拚'],'bài bái':['拜'],bài:['拝','敗','稗','粺','薭','贁','败','韛'],qiá:['拤'],'nǐng níng nìng':['拧'],'zé zhái':['择','擇'],hén:['拫','痕','鞎'],'kuò guā':['括'],'jié jiá':['拮'],nǐn:['拰'],shuān:['拴','栓','閂','闩'],'cún zùn':['拵'],'zā zǎn':['拶','桚'],kǎo:['拷','攷','栲','烤','考'],'yí chǐ hài':['拸'],'cè sè chuò':['拺'],'zhuài zhuāi yè':['拽'],'shí shè':['拾'],bāi:['挀','掰'],'kuò guāng':['挄'],nòng:['挊','挵','齈'],'jiào jiāo':['挍','敎','教'],'kuà kū':['挎'],'ná rú':['挐'],'tiāo tiǎo':['挑'],'dié shè':['挕'],liě:['挘','毟'],'yà yǎ':['挜','掗'],'wō zhuā':['挝'],'xié jiā':['挟','挾'],'dǎng dàng':['挡','擋'],'zhèng zhēng':['挣','正','症'],'āi ái':['挨'],'tuō shuì':['挩','捝'],'tǐ tì':['挮'],'suō shā':['挱'],'sā shā suō':['挲'],'kēng qiān':['挳','摼'],'bàng péng':['挷'],'ruó ruá':['挼'],'jiǎo kù':['捁'],'wǔ wú':['捂'],tǒng:['捅','桶','筒','筩','統','綂','统','㛚'],'huò chì':['捇'],'tú shū chá':['捈'],'lǚ luō':['捋'],'shāo shào':['捎','稍'],niē:['捏','揑'],'shù sǒng sōu':['捒'],'yé yú':['捓'],'jué zhuó':['捔'],'bù pú zhì':['捗'],zùn:['捘','銌'],lāo:['捞','撈','粩'],sǔn:['损','損','榫','笋','筍','箰','鎨','隼'],'wàn wǎn wān yù':['捥'],pěng:['捧','淎','皏'],shě:['捨'],'fǔ fù bǔ':['捬'],dáo:['捯'],'luò luǒ wǒ':['捰'],'juǎn quán':['捲'],'chēn tiǎn':['捵'],'niǎn niē':['捻'],'ruó wěi ré':['捼'],zuó:['捽','昨','秨','稓','筰','莋','鈼'],'wò xiá':['捾'],'qìng qiàn':['掅'],'póu pǒu':['掊'],qiā:['掐','葜'],'pái pǎi':['排'],'qiān wàn':['掔'],'yè yē':['掖'],'niè nǐ yì':['掜'],'huò xù':['掝'],'yàn shàn yǎn':['掞'],'zhěng dìng':['掟'],kòng:['控','鞚'],tuī:['推','蓷','藬'],'zōu zhōu chōu':['掫'],tiàn:['掭','舚'],kèn:['掯','裉','褃'],pá:['掱','杷','潖','爬','琶','筢'],'guó guāi':['掴'],'dǎn shàn':['掸','撣'],'chān xiān càn shǎn':['掺'],sāo:['掻','搔','溞','繅','缫','螦','騒','騷','鰠','鱢','鳋'],pèng:['掽','椪','槰','碰','踫'],'zhēng kēng':['揁'],'jiū yóu':['揂'],'jiān jiǎn':['揃','籛'],'pì chè':['揊'],'sāi zǒng cāi':['揌'],'tí dī dǐ':['提'],'zǒng sōng':['揔'],'huáng yóng':['揘'],'zǎn zuàn':['揝'],'xū jū':['揟'],'ké qiā':['揢'],'chuāi chuǎi chuài tuán zhuī':['揣'],'dì tì':['揥'],'lá là':['揦'],là:['揧','楋','溂','瓎','瘌','翋','臘','蝋','蝲','蠟','辢','辣','鑞','镴','鬎','鯻','𬶟',],'jiē qì':['揭'],'chòng dǒng':['揰'],'dié shé yè':['揲'],'jiàn qián jiǎn':['揵'],yé:['揶','爷','爺','瑘','鋣','鎁','铘'],chān:['搀','摻','攙','裧','襜','覘','觇','辿','鋓'],'gē gé':['搁','擱'],'lǒu lōu':['搂','摟'],'chōu zǒu':['搊'],chuāi:['搋'],sūn:['搎','槂','狲','猻','荪','蓀','蕵','薞','飧','飱'],'róng náng nǎng':['搑'],'péng bàng':['搒'],cuō:['搓','瑳','磋','蹉','遳','醝'],'kē è':['搕'],'nù nuò nòu':['搙'],'lā xié xiàn':['搚'],qiǔ:['搝','糗'],'xiǎn xiān':['搟'],'jié zhé':['搩'],'pán bān pó':['搫'],bān:['搬','攽','斑','斒','班','瘢','癍','肦','螁','螌','褩','辬','頒','颁','𨭉',],'zhì nái':['搱'],'wā wǎ wà':['搲'],huá:['搳','撶','滑','猾','蕐','螖','譁','鏵','铧','驊','骅','鷨'],'qiāng qiǎng chēng':['搶'],'tián shēn':['搷'],'ná nuò':['搻'],èn:['摁'],'shè niè':['摄','攝'],bìn:['摈','擯','殡','殯','膑','臏','髌','髕','髩','鬂','鬓','鬢'],'shā sà shǎi':['摋'],'chǎn sùn':['摌'],'jiū liú liáo jiǎo náo':['摎'],'féng pěng':['摓'],shuāi:['摔'],'dì tú zhí':['摕'],'qì jì chá':['摖'],'sōu sǒng':['摗'],'liǎn liàn':['摙'],'gài xì':['摡'],'hù chū':['摢'],tàng:['摥','烫','燙','鐋'],'nái zhì':['摨'],'mó mā':['摩'],'jiāng qiàng':['摪'],'áo qiáo':['摮'],'niè chè':['摰'],'mán màn':['摱'],'chàn cán':['摲'],'sè mí sù':['摵'],'biāo biào':['摽'],'juē jué':['撅'],piē:['撆','暼','氕','瞥'],'piě piē':['撇'],'zǎn zān zēn qián':['撍'],'sā sǎ':['撒'],hòng:['撔','訌','讧','闀','鬨'],'héng guàng':['撗'],niǎn:['撚','撵','攆','涊','焾','碾','簐','蹍','蹨','躎','輦','辇',],'chéng zhěng':['撜'],'huī wéi':['撝'],cāo:['撡','操','糙'],'xiāo sōu':['撨'],'liáo liāo':['撩'],'cuō zuǒ':['撮'],'wěi tuǒ':['撱'],cuān:['撺','攛','汆','蹿','躥','鑹','镩'],'qiào yāo jī':['撽'],'zhuā wō':['撾'],'lèi léi':['擂'],nǎng:['擃','攮','曩','灢'],'qíng jǐng':['擏'],kuǎi:['擓','蒯','㧟'],'pǐ bò':['擗'],'bò bāi':['擘'],'jù jǐ':['據'],mēng:['擝'],'sǒu sòu':['擞'],xǐng:['擤','箵','醒'],cā:['擦'],'níng nǐng nìng':['擰'],'zhì jié':['擳'],'là liè':['擸','爉'],'sòu sǒu':['擻'],'lì luò yuè':['擽'],'tī zhāi zhì':['擿'],pān:['攀','潘','眅','萠'],lèi:['攂','泪','涙','淚','禷','类','纇','蘱','酹','銇','錑','頛','頪','類','颣',],'cā sǎ':['攃'],'jùn pèi':['攈'],'lì luò':['攊','躒'],'là lài':['攋','櫴'],'lú luó':['攎'],'zǎn cuán':['攒'],'xiān jiān':['攕'],'mí mǐ mó':['攠'],'zǎn cuán zàn zuān':['攢'],zuàn:['攥'],'lì shài':['攦'],'lì luǒ':['攭'],'guǐ guì':['攱'],'jī qī yǐ':['攲'],fàng:['放'],'wù móu':['敄'],'chù shōu':['敊'],'gé guó è':['敋'],'duó duì':['敓','敚'],'duō què':['敠','敪'],'sàn sǎn':['散'],'dūn duì':['敦','镦'],'qī yǐ jī':['敧'],'xiào xué':['敩'],'shù shǔ shuò':['数','數'],'ái zhú':['敱','敳'],'xiòng xuàn':['敻'],'zhuó zhú':['斀'],'yì dù':['斁'],'lí tái':['斄'],'fěi fēi':['斐'],'yǔ zhōng':['斔'],'dòu dǒu':['斗'],'wò guǎn':['斡'],'tǒu tiǎo':['斢'],dòu:['斣','梪','浢','痘','窦','竇','脰','荳','豆','逗','郖','酘','閗','闘','餖','饾','鬥','鬦','鬪','鬬','鬭',],'yín zhì':['斦'],'chǎn jiè':['斺'],'wū yū yú':['於'],'yóu liú':['斿'],'páng bàng':['旁'],'máo mào':['旄'],'pī bì':['旇'],'xuán xuàn':['旋'],'wú mó':['无'],zǎo:['早','枣','栆','棗','澡','璪','薻','藻','蚤'],gā:['旮'],'gàn hàn':['旰'],'tái yīng':['旲'],'xū xù':['旴'],'tūn zhùn':['旽'],'wù wǔ':['旿'],'pò pèi':['昢'],zòng:['昮','猔','疭','瘲','粽','糉','糭','縦'],ǎi:['昹','毐','矮','蔼','藹','譪','躷','霭','靄'],'huàng huǎng':['晃'],xuǎn:['晅','癣','癬','选','選'],'xù kuā':['晇'],hǒng:['晎'],shài:['晒','曬'],'yūn yùn':['晕','煴'],'shèng chéng':['晟','椉','盛'],'jǐng yǐng':['景'],shǎn:['晱','熌','睒','覢','閃','闪','陕','陝'],'qǐ dù':['晵'],'ǎn àn yǎn':['晻'],'wǎng wàng':['暀'],zàn:['暂','暫','瓉','瓒','瓚','禶','襸','讃','讚','賛','贊','赞','蹔','鄼','錾','鏨','饡',],'yùn yūn':['暈'],'mín mǐn':['暋'],'dǔ shǔ':['暏'],shǔ:['暑','曙','潻','癙','糬','署','薥','薯','藷','蜀','蠴','襡','襩','鱪','鱰','黍','鼠','鼡',],'jiǎn lán':['暕'],nuǎn:['暖','煗','餪'],'bào pù':['暴'],'xī xǐ':['暿'],'pù bào':['曝','瀑'],'qū qǔ':['紶'],'qǔ qū':['曲'],'gèng gēng':['更'],'hū hù':['曶','雽'],'zēng céng':['曽','橧'],'céng zēng':['曾','竲'],'cǎn qián jiàn':['朁'],'qiè hé':['朅'],'bì pí':['朇','禆','笓','裨'],'yǒu yòu':['有'],'bān fén':['朌','鳻'],'fú fù':['服','洑'],'fěi kū':['朏','胐'],'qú xù chǔn':['朐'],'juān zuī':['朘'],'huāng máng wáng':['朚'],'qī jī':['期'],'tóng chuáng':['朣','橦'],zhá:['札','牐','箚','蚻','譗','鍘','铡','閘','闸'],'zhú shù shú':['朮'],'shù shú zhú':['术'],'zhū shú':['朱'],'pǔ pò pō piáo':['朴'],'dāo tiáo mù':['朷'],'guǐ qiú':['朹'],xiǔ:['朽','滫','潃','糔'],'chéng chēng':['朾'],zá:['杂','沯','砸','襍','雑','雜','雥','韴'],'yú wū':['杅'],'gān gǎn':['杆'],'chā chà':['杈'],'shān shā':['杉'],cūn:['村','皴','竴','膥','踆','邨'],'rèn ér':['杒','梕'],'sháo biāo':['杓'],'dì duò':['杕','枤'],'gū gài':['杚'],'yí zhì lí duò':['杝'],'gàng gāng':['杠'],'tiáo tiāo':['条','條'],'mà mǎ':['杩'],'sì zhǐ xǐ':['杫'],'yuán wán':['杬','蚖'],'bèi fèi':['杮'],'shū duì':['杸'],'niǔ chǒu':['杻'],'wò yuè':['枂','臒'],máo:['枆','毛','氂','渵','牦','矛','罞','茅','茆','蝥','蟊','軞','酕','鉾','錨','锚','髦','鶜',],'pī mì':['枈'],àng:['枊','盎','醠'],'fāng bìng':['枋'],'hù dǐ':['枑'],xín:['枔','襑','鐔','鬵'],'yāo yǎo':['枖'],'ě è':['枙'],'zhī qí':['枝'],'cōng zōng':['枞','樅'],'xiān zhēn':['枮'],'tái sì':['枱'],'gǒu jǔ gōu':['枸'],'bāo fú':['枹'],'yì xiè':['枻','栧'],'tuó duò':['柁','馱','駄','驮'],'yí duò lí':['柂'],'nǐ chì':['柅'],'pán bàn':['柈','跘'],'yǎng yàng yāng yīng':['柍'],'fù fū fǔ':['柎'],'bǎi bó bò':['柏'],mǒu:['某'],'sháo shào':['柖'],zhè:['柘','樜','浙','淛','蔗','蟅','這','鷓','鹧','䗪'],'yòu yóu':['柚','櫾'],'guì jǔ':['柜'],'zhà zuò':['柞'],'dié zhì':['柣','眰'],'zhā zǔ zū':['柤'],'chá zhā':['查','査'],'āo ào':['柪','軪'],'bā fú pèi bó biē':['柭'],'duò zuó wù':['柮'],'bì bié':['柲'],'zhù chù':['柷'],'bēi pēi':['柸'],'shì fèi':['柹'],'shān zhà shi cè':['栅'],'lì yuè':['栎','櫟'],'qì qiè':['栔','砌'],'qī xī':['栖','蹊'],'guā kuò':['栝'],'bīng bēn':['栟'],'xiào jiào':['校'],'jiàn zùn':['栫','袸'],'yǒu yù':['栯'],'hé hú':['核'],gēn:['根','跟'],'zhī yì':['栺'],'gé gē':['格'],'héng háng':['桁'],'guàng guāng':['桄'],'yí tí':['桋','荑'],sāng:['桑','桒','槡'],'jú jié':['桔'],'yú móu':['桙'],'ráo náo':['桡','橈'],'guì huì':['桧','檜'],'chén zhèn':['桭'],'tīng yíng':['桯'],'bó po':['桲'],'bèn fàn':['桳'],'fēng fèng':['桻','葑'],'sù yìn':['梀'],'tǐng tìng':['梃'],'xuān juān xié':['梋'],'tú chá':['梌'],'āo yòu':['梎'],kuǎn:['梡','欵','款','歀'],'shāo sào':['梢'],'qín chén cén':['梣'],'lí sì qǐ':['梩'],'chān yán':['梴'],'bīn bīng':['梹','槟','檳'],'táo chóu dào':['梼'],'cōng sōng':['棇'],'gùn hùn':['棍'],'dé zhé':['棏'],'pái bèi pèi':['棑'],'bàng pǒu bèi bēi':['棓'],'dì dài tì':['棣'],sēn:['森','椮','槮','襂'],'rěn shěn':['棯'],'léng lēng líng':['棱'],'fú sù':['棴'],'zōu sǒu':['棷'],zōu:['棸','箃','緅','諏','诹','邹','郰','鄒','鄹','陬','騶','驺','鯫','鲰','黀','齱','齺',],'zhào zhuō':['棹'],'chēn shēn':['棽'],'jiē qiè':['椄'],'yǐ yī':['椅'],'chóu zhòu diāo':['椆'],'qiāng kōng':['椌'],'zhuī chuí':['椎'],'bēi pí':['椑'],mēn:['椚'],'quān juàn quán':['椦'],'duǒ chuán':['椯'],'wěi huī':['椲'],'jiǎ jiā':['椵'],'hán jiān':['椷'],'shèn zhēn':['椹'],'yàn yà':['椻'],'zhā chá':['楂'],'guō kuǎ':['楇'],'jí zhì':['楖'],'kǔ hù':['楛'],'yóu yǒu':['楢'],'sǒng cōng':['楤'],'yuán xuàn':['楥'],'yǎng yàng yīng':['楧'],pián:['楩','胼','腁','賆','蹁','駢','騈','骈','骿','㛹'],'dié yè':['楪'],'dùn shǔn':['楯'],'còu zòu':['楱'],'dì dǐ shì':['楴'],'kǎi jiē':['楷'],'róu ròu':['楺'],'lè yuè':['楽'],'wēn yùn':['榅','鞰'],lǘ:['榈','櫚','氀','膢','藘','閭','闾','驢','驴'],shén:['榊','神','鉮','鰰','𬬹'],'bī pi':['榌'],'zhǎn niǎn zhèn':['榐'],'fú fù bó':['榑'],'jiàn jìn':['榗'],'bǎng bàng':['榜'],'shā xiè':['榝','樧'],nòu:['槈','耨','鎒','鐞'],'qiǎn lián xiàn':['槏'],gàng:['槓','焵','焹','筻','鿍'],gāo:['槔','槹','橰','櫜','睾','篙','糕','羔','臯','韟','餻','高','髙','鷎','鷱','鼛',],'diān zhěn zhēn':['槙'],'kǎn jiàn':['槛'],'xí dié':['槢'],'jī guī':['槣'],'róng yōng':['槦'],'tuán shuàn quán':['槫'],'qì sè':['槭'],'cuī zhǐ':['槯'],'yǒu chǎo':['槱'],'màn wàn':['槾'],'lí chī':['樆'],'léi lěi':['樏','櫑','礌'],'cháo jiǎo chāo':['樔'],'chēng táng':['樘'],'jiū liáo':['樛'],'mó mú':['模'],'niǎo mù':['樢'],'héng hèng':['横','橫'],xuě:['樰','膤','艝','轌','雪','鱈','鳕'],'fá fèi':['橃'],rùn:['橍','润','潤','膶','閏','閠','闰'],'zhǎn jiǎn':['橏'],shùn:['橓','瞚','瞬','舜','蕣','順','顺','鬊'],'tuí dūn':['橔'],'táng chēng':['橖'],'sù qiū':['橚'],'tán diàn':['橝'],'fén fèn fèi':['橨'],'rǎn yān':['橪'],'cū chu':['橻'],'shū qiāo':['橾'],'píng bò':['檘'],'zhái shì tú':['檡'],'biǎo biāo':['檦'],'qiān lián':['檶'],'nǐ mí':['檷'],'jiàn kǎn':['檻'],'nòu ruǎn rú':['檽'],'jī jì':['櫅','禨'],'huǎng guǒ gǔ':['櫎'],'lǜ chū':['櫖'],'miè mèi':['櫗'],ōu:['櫙','欧','歐','殴','毆','瓯','甌','膒','藲','謳','讴','鏂','鴎','鷗','鸥',],'zhù zhuó':['櫡'],'jué jì':['櫭'],'huái guī':['櫰'],'chán zhàn':['欃'],'wéi zuì':['欈'],cáng:['欌','鑶'],'yù yì':['欥'],'chù qù xì':['欪'],'kài ài':['欬'],'yì yīn':['欭'],'xì kài':['欯'],'shuò sòu':['欶'],'ǎi ēi éi ěi èi ê̄ ế ê̌ ề':['欸'],'qī yī':['欹'],'chuā xū':['欻'],'chǐ chuài':['欼'],'kǎn qiàn':['欿'],'kǎn kè':['歁'],'chuǎn chuán':['歂'],'yīn yān':['歅'],'jìn qūn':['歏'],pēn:['歕'],'xū chuā':['歘'],'xī shè':['歙'],'liǎn hān':['歛'],'zhì chí':['歭'],'sè shà':['歰'],sǐ:['死'],'wěn mò':['歾'],piǎo:['殍','皫','瞟','醥','顠'],'qíng jìng':['殑'],'fǒu bó':['殕'],'zhí shi':['殖'],'yè yān yàn':['殗'],'hūn mèi':['殙'],chòu:['殠','臰','遚'],'kuì huì':['殨','溃','潰'],cuàn:['殩','熶','爨','窜','竄','篡','簒'],'yīn yān yǐn':['殷'],'qìng kēng shēng':['殸'],'yáo xiáo xiào':['殽'],'gū gǔ':['毂','蛄'],'guàn wān':['毌'],'dú dài':['毒'],'xún xùn':['毥'],mú:['毪','氁'],'dòu nuò':['毭'],'sāi suī':['毸'],lu:['氇'],sào:['氉','瘙','矂','髞'],'shì zhī':['氏'],'dī dǐ':['氐'],'máng méng':['氓'],'yáng rì':['氜'],shuǐ:['水','氵','氺','閖'],'zhěng chéng zhèng':['氶'],tǔn:['氽'],'fán fàn':['氾'],'guǐ jiǔ':['氿'],'bīn pà pā':['汃'],'zhuó què':['汋'],'dà tài':['汏'],pìn:['汖','牝','聘'],'hàn hán':['汗','馯'],tu:['汢'],'tāng shāng':['汤','湯'],'zhī jì':['汥'],'gàn hán cén':['汵'],'wèn mén':['汶'],'fāng pāng':['汸'],'hǔ huǎng':['汻'],'niú yóu':['汼'],hàng:['沆'],'shěn chén':['沈'],'dùn zhuàn':['沌'],'nǜ niǔ':['沑'],'méi mò':['沒','没'],'tà dá':['沓'],'mì wù':['沕'],'hóng pāng':['沗'],'shā shà':['沙'],'zhuǐ zǐ':['沝'],'ōu òu':['沤','漚'],'jǔ jù':['沮'],'tuō duó':['沰'],'mǐ lì':['沵'],'yí chí':['沶'],'xiè yì':['泄'],'bó pō':['泊'],'mì bì':['泌','秘'],'chù shè':['泏'],'yōu yòu āo':['泑'],'pēng píng':['泙','硑'],'pào pāo':['泡'],'ní nì':['泥','秜'],'yuè sà':['泧'],'jué xuè':['泬','疦'],'lóng shuāng':['泷','瀧'],'luò pō':['泺','濼'],'zé shì':['泽','澤'],'sǎ xǐ':['洒'],'sè qì zì':['洓'],'xǐ xiǎn':['洗'],'kǎo kào':['洘'],'àn yàn è':['洝'],'lěi lèi':['洡'],'qiè jié':['洯'],'qiǎn jiān':['浅'],'jì jǐ':['济','済','濟','纪'],'hǔ xǔ':['浒','滸'],'jùn xùn':['浚','濬'],'yǐng chéng yíng':['浧'],'liàn lì':['浰'],'féng hóng':['浲','溄'],'jiǒng jiōng':['浻'],'suī něi':['浽'],'yǒng chōng':['涌'],'tūn yūn':['涒'],'wō guō':['涡','渦'],hēng:['涥','脝'],'zhǎng zhàng':['涨','漲'],'shòu tāo':['涭'],shuàn:['涮','腨'],'kōng náng':['涳'],'wò wǎn yuān':['涴'],'tuō tuò':['涶'],wō:['涹','猧','窝','窩','莴','萵','蜗','蝸','踒'],'qiè jí':['淁'],'guǒ guàn':['淉'],'lín lìn':['淋','獜','疄'],'tǎng chǎng':['淌'],'nào chuò zhuō':['淖'],'péng píng':['淜'],féi:['淝','肥','腓','蜰'],'pì pèi':['淠'],'niǎn shěn':['淰'],'biāo hǔ':['淲'],'chún zhūn':['淳'],'hùn hún':['混'],qiǎn:['淺','繾','缱','肷','膁','蜸','譴','谴','遣','鑓'],'wèn mín':['渂'],'rè ruò luò':['渃'],'dú dòu':['渎','瀆','读'],'jiàn jiān':['渐','溅','漸','濺'],'miǎn shéng':['渑','澠'],'nuǎn nuán':['渜'],'qiú wù':['渞'],'tíng tīng':['渟'],'dì tí dī':['渧'],'gǎng jiǎng':['港'],'hōng qìng':['渹'],tuān:['湍','煓'],'huì mǐn xū':['湏'],'xǔ xù':['湑'],pén:['湓','瓫','盆','葐'],'mǐn hūn':['湣'],'tuàn nuǎn':['湪'],'qiū jiǎo':['湫','湬'],'yān yīn':['湮'],'bàn pán':['湴'],'zhuāng hún':['湷'],'yàn guì':['溎'],'lián liǎn nián xián xiàn':['溓'],'dá tǎ':['溚','鿎'],'liū liù':['溜','澑','蹓'],lùn:['溣'],mǎ:['溤','犸','獁','玛','瑪','码','碼','遤','鎷','馬','马','鰢','鷌',],'zhēn qín':['溱'],'nì niào':['溺'],'chù xù':['滀','畜'],'wěng wēng':['滃'],'hào xuè':['滈'],'qì xì xiē':['滊'],'xíng yíng':['滎'],'zé hào':['滜'],'piāo piào piǎo':['漂'],'cóng sǒng':['漎'],'féng péng':['漨'],'luò tà':['漯'],'pēng bēn':['漰'],'chóng shuāng':['漴'],'huǒ kuò huò':['漷'],'liáo liú':['漻'],'cuǐ cuī':['漼'],'cóng zǒng':['潀'],'cóng zōng':['潈'],'pì piē':['潎'],'dàng xiàng':['潒'],'huáng guāng':['潢'],'liáo lào lǎo':['潦'],'cōng zòng':['潨'],'zhí zhì':['潪'],'tān shàn':['潬'],'tú zhā':['潳'],'sàn sǎ':['潵'],hēi:['潶','黑','黒','𬭶'],'chéng dèng':['澄','瀓'],'cūn cún':['澊'],'péng pēng':['澎'],'hòng gǒng':['澒','銾'],'wàn màn':['澫'],'kuài huì':['澮'],'guō wō':['濄'],'pēn fén':['濆'],'jí shà':['濈'],'huì huò':['濊'],'dǐng tìng':['濎'],'mǐ nǐ':['濔'],'bì pì':['濞'],'cuì zuǐ':['濢'],'hù huò':['濩'],'ǎi kài kè':['濭'],'wěi duì':['濻','瀢'],'zàn cuán':['濽','灒'],'yǎng yàng':['瀁'],'wǎng wāng':['瀇'],'mò miè':['瀎','眜'],suǐ:['瀡','膸','髓'],'huái wāi':['瀤'],'zùn jiàn':['瀳'],'yīng yǐng yìng':['瀴'],'ráng ràng':['瀼'],shuàng:['灀'],'zhuó jiào zé':['灂'],sǎ:['灑','訯','靸'],'luán luàn':['灓'],'dǎng tǎng':['灙'],'xún quán quàn':['灥'],'huǒ biāo':['灬'],'zhà yù':['灹'],'fén bèn':['炃'],'jiǒng guì':['炅'],'pàng fēng':['炐'],quē:['炔','缺','缼','蒛'],biān:['炞','煸','甂','砭','笾','箯','籩','編','编','蝙','邉','邊','鍽','鞭','鯾','鯿','鳊',],'zhāo zhào':['炤'],'zhuō chù':['炪'],'pào páo bāo':['炮'],'páo fǒu':['炰'],'shǎn qián shān':['炶'],'zhà zhá':['炸'],'jiǎo yào':['烄'],quǎn:['烇','犬','犭','畎','綣','绻','虇'],'yàng yáng':['烊'],'lào luò':['烙'],'huí huǐ':['烠'],rè:['热','熱'],'fú páo':['烰'],'xiè chè':['烲','焎'],'yàn shān':['烻'],'hūn xūn':['焄'],kào:['焅','犒','銬','铐','靠','鮳','鯌','鲓','㸆'],'juān yè':['焆'],'jùn qū':['焌'],'tāo dào':['焘'],'chǎo jù':['焣'],'wò ài':['焥'],'zǒng cōng':['焧'],'xī yì':['焬'],'xìn xīn':['焮'],'chāo zhuō':['焯'],'xiǒng yīng':['焸','焽'],kuǐ:['煃','跬','蹞','頍','𫠆'],'huī yùn xūn':['煇'],'jiǎo qiāo':['煍'],'qián shǎn shān':['煔'],'xī yí':['煕'],'shà shā':['煞'],'yè zhá':['煠'],'yáng yàng':['煬'],'ēn yūn':['煾'],'yūn yǔn':['熅'],'hè xiāo':['熇'],xióng:['熊','熋','雄'],'xūn xùn':['熏','爋'],gòng:['熕','貢','贡'],liū:['熘'],'cōng zǒng':['熜'],'lù āo':['熝'],'shú shóu':['熟'],'fēng péng':['熢'],'cuǐ suī':['熣'],tēng:['熥','膯','鼟'],'yùn yù':['熨'],'áo āo':['熬'],'hàn rǎn':['熯'],'ōu ǒu':['熰'],'huáng huǎng':['熿'],'chǎn dǎn chàn':['燀'],'jiāo zhuó qiáo jué':['燋'],'yàn yān':['燕'],'tài liè':['燤'],āo:['爊'],'yàn xún':['爓'],'jué jiào':['爝','覐','覚','覺','觉'],'lǎn làn':['爦'],'zhuǎ zhǎo':['爪'],'zhǎo zhuǎ':['爫'],'fù fǔ':['父'],diē:['爹','褺','跌'],zāng:['牂','羘','臧','賍','賘','贓','贜','赃','髒'],'piàn piān':['片'],'biān miàn':['牑'],bǎng:['牓','綁','绑'],'yǒu yōng':['牗'],'chēng chèng':['牚','竀'],niú:['牛','牜'],'jiū lè':['牞'],'mù móu':['牟'],māng:['牤'],'gē qiú':['牫'],'yòu chōu':['牰'],'tè zhí':['犆'],bēn:['犇','錛','锛'],'jiān qián':['犍','玪'],má:['犘','痲','蔴','蟇','麻'],'máo lí':['犛'],'bá quǎn':['犮'],'zhuó bào':['犳'],'àn hān':['犴'],'kàng gǎng':['犺'],'pèi fèi':['犻'],'fān huān':['犿'],kuáng:['狂','狅','誑','诳','軖','軠','鵟','𫛭'],'yí quán chí':['狋'],'xīng shēng':['狌'],'tuó yí':['狏'],kǔ:['狜','苦'],'huán huān':['狟'],'hé mò':['狢'],'tà shì':['狧'],'máng dòu':['狵'],'xī shǐ':['狶'],suān:['狻','痠','酸'],'bài pí':['猈'],'jiān yàn':['猏','豣'],'yī yǐ':['猗'],'yá wèi':['猚'],cāi:['猜'],'māo máo':['猫','貓'],'chuàn chuān':['猭'],'tuān tuàn':['猯','貒'],'yà jiá qiè':['猰'],'hè xiē gé hài':['猲'],'biān piàn':['猵','獱'],'bó pò':['猼'],'háo gāo':['獋'],'fén fèn':['獖'],'yào xiāo':['獟'],'shuò xī':['獡'],'gé liè xiē':['獦'],'nòu rú':['獳'],'náo nǎo yōu':['獶'],ráng:['獽','瓤','禳','穣','穰','蘘','躟','鬤'],'náo yōu':['獿'],'lǜ shuài':['率'],'wáng wàng':['王'],'yáng chàng':['玚'],'mín wén':['玟'],'bīn fēn':['玢'],'mén yǔn':['玧'],'qiāng cāng':['玱','瑲','篬'],'án gān':['玵'],'xuán xián':['玹'],'cī cǐ':['玼','跐'],'yí tāi':['珆'],'zǔ jù':['珇'],fà:['珐','琺','蕟','髪','髮'],'yín kèn':['珢'],'huī hún':['珲'],'xuán qióng':['琁'],'fú fū':['琈'],'bǐng pín':['琕'],'cuì sè':['琗'],'yù wéi':['琟'],'tiǎn tiàn':['琠'],'zhuó zuó':['琢'],'běng pěi':['琣'],guǎn:['琯','璭','痯','筦','管','舘','輨','錧','館','馆','鳤'],'hún huī':['琿'],'xié jiē':['瑎'],'chàng dàng yáng':['瑒'],'tiàn zhèn':['瑱'],'bīn pián':['瑸','璸'],'tú shū':['瑹'],cuǐ:['璀','皠','趡'],'zǎo suǒ':['璅'],'jué qióng':['璚'],'lú fū':['璷'],'jì zī':['璾'],suí:['瓍','綏','绥','遀','随','隨','髄'],'mí xǐ':['瓕'],'qióng wěi wèi':['瓗'],'huán yè yà':['瓛'],'bó páo':['瓟'],'zhí hú':['瓡'],piáo:['瓢','闝'],'wǎ wà':['瓦'],'xiáng hóng':['瓨'],wèng:['瓮','甕','罋','蕹','齆'],'shèn shén':['甚'],ruí:['甤','緌','蕤'],yòng:['用','砽','苚','蒏','醟','㶲'],shuǎi:['甩'],béng:['甭','甮'],'yóu zhá':['甴'],'diàn tián shèng':['甸'],'tǐng dīng':['町','甼'],'zāi zī':['甾'],'bì qí':['畁'],'dá fú':['畗'],'cè jì':['畟'],'zāi zī tián':['畠'],'zhì chóu shì':['畤'],'fān pān':['畨','番'],'shē yú':['畬'],'dāng dàng dǎng':['當'],'jiāng qiáng':['疆'],'pǐ yǎ shū':['疋'],'jié qiè':['疌'],'yí nǐ':['疑'],nè:['疒','眲','訥','讷'],'gē yì':['疙'],'nüè yào':['疟','瘧'],'lì lài':['疠','癘'],'yǎ xiā':['疨'],xuē:['疶','蒆','薛','辥','辪','靴','鞾'],'dǎn da':['疸'],'fá biǎn':['疺'],'fèi féi':['疿','痱'],'shān diàn':['痁'],'téng chóng':['痋'],'tōng tóng':['痌'],'wěi yòu yù':['痏'],'tān shǐ':['痑'],'pū pù':['痡','鋪'],'bēng péng':['痭'],'má lìn':['痳'],'tiǎn diàn':['痶'],'ān yè è':['痷'],'kē ē':['痾'],'zhì chì':['瘈'],'jiǎ xiá xiā':['瘕'],'lěi huì':['瘣'],'chài cuó':['瘥'],'diān chēn':['瘨'],'da dá':['瘩'],'biě biē':['瘪'],qué:['瘸'],'dàn dān':['癉'],'guì wēi':['癐'],'nòng nóng':['癑'],'biē biě':['癟'],'bō bǒ':['癷'],bái:['白'],'jí bī':['皀'],'de dì dí dī':['的'],'pā bà':['皅'],'gāo háo':['皋'],'gāo yáo':['皐'],'lì luò bō':['皪'],'zhā cǔ':['皻'],'zhāo zhǎn dǎn':['皽'],'jiān jiàn':['监','監','鋻','间','鞬'],'gài gě hé':['盖'],'máng wàng':['盳'],yuǎn:['盶','逺','遠'],'tián xián':['盷'],'xiāng xiàng':['相'],dǔn:['盹','趸','躉'],'xì pǎn':['盻'],'shěng xǐng':['省'],'yún hùn':['眃'],'miǎn miàn':['眄'],'kàn kān':['看'],'yìng yāng yǎng':['眏'],'yǎo āo ǎo':['眑'],'jū xū kōu':['眗'],'yí chì':['眙'],'dié tì':['眣'],'bǐng fǎng':['眪'],'pàng pán':['眫'],'mī mí':['眯','瞇'],'xuàn shùn xún':['眴'],tiào:['眺','粜','糶','覜','趒'],'zhe zhuó zháo zhāo':['着'],'qiáo shào xiāo':['睄'],'cuó zhuài':['睉'],gùn:['睔','謴'],'suì zuì':['睟'],'pì bì':['睥','稫','辟'],'yì zé gāo':['睪'],'xǐng xìng':['睲'],'guì wèi kuì':['瞆'],'kòu jì':['瞉'],'qióng huán':['瞏'],'mán mén':['瞒','瞞'],'diāo dōu':['瞗'],'lou lóu lǘ':['瞜'],'shùn rún':['瞤'],'liào liǎo':['瞭','钌'],'jiàn xián':['瞯'],'wǔ mí':['瞴'],'guì kuì':['瞶'],'nǐng chēng':['矃'],'huò yuè':['矆'],'mēng méng':['矇'],'kuàng guō':['矌'],'guàn quán':['矔'],'mǎn mán':['矕'],'jīn guān qín':['矜'],'jīn qín guān':['矝'],'yù xù jué':['矞'],'jiǎo jiáo':['矫','矯'],duǎn:['短'],'shí dàn':['石'],'gāng qiāng kòng':['矼'],'huā xū':['砉'],'pīn bīn fēn':['砏'],'yán yàn':['研','硏'],'luǒ kē':['砢'],'fú fèi':['砩','笰'],'zhǔ zhù':['砫'],'lá lì lā':['砬'],'kuāng guāng':['硄'],'gè luò':['硌'],'shuò shí':['硕','碩'],'wèi wéi ái':['硙'],'què kè kù':['硞'],'mǎng bàng':['硥'],'luò lòng':['硦'],'yǒng tóng':['硧'],nüè:['硸','虐'],'kēng kěng':['硻'],'yān yǎn':['硽'],'zhuì chuí duǒ':['硾'],'kōng kòng':['硿'],'zòng cóng':['碂'],'jiān zhàn':['碊'],'lù liù':['碌','陆'],'què xī':['碏'],'lún lǔn lùn':['碖'],'náo gāng':['碙'],'jié yà':['碣'],'wèi wěi':['碨'],'tí dī':['碮'],'chá chā':['碴'],'qiāo què':['碻'],'sù xiè':['碿'],'liú liù':['磂','遛','鎦','馏'],'sī tí':['磃'],'bàng páng':['磅'],'huá kě gū':['磆'],'wěi kuǐ':['磈'],'xiá qià yà':['磍'],'lián qiān':['磏'],'wèi ái gài':['磑'],'lá lā':['磖'],'áo qiāo':['磝'],'pēng pèng':['磞','閛'],'yīn yǐn':['磤'],'lěi léi':['磥'],'mó mò':['磨'],'qì zhú':['磩'],'láo luò':['磱'],'pán bō':['磻'],'jí shé':['磼'],'hé qiāo qiào':['礉'],'kè huò':['礊'],'què hú':['礐'],'è qì':['礘'],cǎ:['礤','礸'],'xián xín':['礥'],'léi lěi lèi':['礧'],'yán yǎn':['礹'],'qí zhǐ':['祇','蚔'],'bēng fāng':['祊'],'bì mì':['祕'],suàn:['祘','笇','筭','算','蒜'],'piào piāo':['票'],'jì zhài':['祭'],'shuì lèi':['祱'],'jìn jīn':['禁'],'chán shàn':['禅'],'yáng shāng':['禓'],'zhī zhǐ tí':['禔'],'shàn chán':['禪'],'yú yù ǒu':['禺'],'zǐ zì':['秄'],'chá ná':['秅'],'zhǒng zhòng chóng':['种'],'hào mào':['秏'],'kù kū':['秙'],zū:['租','葅'],chèng:['秤','穪'],'huó kuò':['秮','秳'],'chēng chèn chèng':['称','稱'],'shì zhì':['秲','銴'],'fù pū':['秿'],'xùn zè':['稄'],'tú shǔ':['稌'],'zhùn zhǔn':['稕'],'jī qí':['稘','綨','觭'],'léng líng':['稜'],'zuì zú sū':['稡'],'xì qiè':['稧','郄'],'zhǒng zhòng':['種'],'zōng zǒng':['稯'],'xián jiān liàn':['稴'],'zī jiū':['稵'],'jī qǐ':['稽'],ròng:['穃'],'shān cǎn cēn':['穇'],'mén méi':['穈'],'jǐ jì':['穖'],'xiāo rào':['穘'],'zhuō bó':['穛'],'tóng zhǒng zhòng':['穜'],zuō:['穝'],'biāo pāo':['穮','藨'],'zhuō jué':['穱'],'cuán zàn':['穳'],'kōng kòng kǒng':['空'],'yū yǔ':['穻'],zhǎi:['窄','鉙'],báo:['窇','雹'],'kū zhú':['窋'],'jiào liáo liù':['窌'],'wā guī':['窐'],'tiǎo yáo':['窕'],'xūn yìn':['窨'],'yà yē':['窫'],'tián diān yǎn':['窴'],'chāo kē':['窼'],'kuǎn cuàn':['窽','窾'],'chù qì':['竐'],'qǔ kǒu':['竘'],'jìng zhěn':['竧'],'kǎn kàn':['竷'],'zhú dǔ':['竺'],'lè jīn':['竻'],'zhuì ruì':['笍'],'háng hàng':['笐'],'cén jìn hán':['笒'],'dā xiá nà':['笚'],'zé zuó':['笮'],'lóng lǒng':['笼','篭','籠','躘','龓'],'zhù zhú':['筑','築'],'dá dā':['答','荅'],shāi:['筛','篩','簁','籭'],'yún jūn':['筠'],'láng làng':['筤','郎','阆'],'zhì zhǐ':['筫'],o:['筽'],'póu bù fú pú':['箁'],'pái bēi':['箄'],gè:['箇','虼','鉻','铬'],'tái chí':['箈'],'guǎi dài':['箉'],'zhào dào':['箌'],'jīng qìng':['箐'],'lín lǐn':['箖'],'jùn qūn':['箘'],'shī yí':['箷','釶'],'yuē yào chuò':['箹'],'xiāo shuò qiào':['箾'],'gōng gǎn lǒng':['篢'],'páng péng':['篣'],'zhuó huò':['篧'],'jiǎn jiān':['篯'],'dí zhú':['篴'],'zān cēn cǎn':['篸'],'zhuàn suǎn zuàn':['篹'],'piǎo biāo':['篻'],'guó guì':['簂'],'cè jí':['簎'],'mì miè':['簚'],'shāi sī':['簛'],'sǔn zhuàn':['簨'],'gàn gǎn':['簳'],'bò bǒ':['簸'],'bó bù':['簿'],shi:['籂'],'zhēn jiān':['籈'],'zhuàn zuǎn':['籑'],'fān pān biān':['籓'],'sǒu shǔ':['籔'],zuǎn:['籫','繤','纂','纉','纘','缵'],nǚ:['籹','釹','钕'],'shā chǎo':['粆'],'kāng jīng':['粇'],fěn:['粉','黺'],cū:['粗','觕','麁','麄','麤'],'nián zhān':['粘'],'cè sè':['粣'],'zhōu yù':['粥'],'shēn sǎn':['糁'],'biān biǎn':['糄','萹'],miàn:['糆','面','靣','麪','麫','麵','麺'],'hú hū hù':['糊'],'gǔ gòu':['糓'],'mí méi':['糜'],'sǎn shēn':['糝','糣'],zāo:['糟','蹧','遭','醩'],'mì sī':['糸'],'jiū jiǔ':['糺'],'xì jì':['系','繫'],'zhēng zhěng':['糽'],'chà chǎ':['紁','衩'],'yuē yāo':['約','约'],'hóng gōng':['紅','红'],'hé gē':['紇','纥'],'wén wèn':['紋','纹'],fóu:['紑'],'jì jié jiè':['紒'],'pī pí bǐ':['紕','纰'],'jīn jìn':['紟'],'zhā zā':['紥','紮'],hā:['紦'],'fū fù':['紨'],'chōu chóu':['紬'],'lèi léi lěi':['累'],'bō bì':['紴'],'tiǎn zhěn':['紾'],'jiōng jiǒng':['絅'],'jié jiē':['結','结','节'],'guà kuā':['絓'],'bǎi mò':['絔'],'gēng huán':['絙'],'jié xié':['絜'],'quán shuān':['絟'],'gǎi ǎi':['絠'],'luò lào':['絡','络'],'bīng bēng pēng':['絣'],'gěi jǐ':['給','给'],'tóng tōng dòng':['絧'],'tiào diào dào':['絩'],'lěi lèi léi':['絫'],'gāi hài':['絯'],'chī zhǐ':['絺'],'wèn miǎn mán wàn':['絻'],'huán huàn wàn':['綄'],'qīn xiān':['綅'],'tì tí':['綈'],'yán xiàn':['綖'],'zōng zèng zòng':['綜'],'chēn lín':['綝'],'zhǔn zhùn':['綧'],'qiàn qīng zhēng':['綪'],'qìng qǐ':['綮'],'lún guān':['綸','纶'],'chuò chāo':['綽','绰'],'tián tǎn chān':['緂'],'lǜ lù':['緑','绿'],'ruǎn ruàn':['緛'],'jí qī':['緝'],'zhòng chóng':['緟','重'],'miáo máo':['緢'],'xiè yè':['緤'],huǎn:['緩','缓','㬊'],'gēng gèng':['緪','縆'],'tōu xū shū':['緰'],'zōng zòng':['緵','繌'],'yùn gǔn':['緷'],'guā wō':['緺'],'yùn yūn wēn':['緼','縕'],'bāng bàng':['縍'],'gǔ hú':['縎','鶻'],'cī cuò suǒ':['縒'],'cuī shuāi':['縗'],'róng rǒng ròng':['縙'],'zài zēng':['縡'],cài:['縩','菜','蔡'],'féng fèng':['縫'],'suō sù':['縮','缩'],'yǎn yǐn':['縯','酓'],'zòng zǒng':['縱','纵'],'zhuàn juàn':['縳'],'mò mù':['縸','莫'],'piǎo piāo':['縹','缥'],'fán pó':['繁'],'bēng bèng':['繃'],'móu miù miào liǎo':['繆'],'yáo yóu zhòu':['繇'],'zēng zèng':['繒','缯'],'jú jué':['繘'],'chuō chuò':['繛'],'zūn zǔn':['繜'],rào:['繞','绕','遶'],'chǎn chán':['繟'],'huì huí':['繢','缋','藱'],'qiāo sāo zǎo':['繰'],'jiǎo zhuó':['繳','缴'],'dàn tán chán':['繵'],nǒng:['繷'],'pú fú':['纀'],'yào lì':['纅'],'rǎng xiāng':['纕'],'lí sǎ xǐ lǐ':['纚'],'xiān qiàn':['纤'],'jīng jìng':['经'],'tí tì':['绨'],'bēng běng bèng':['绷'],'zōng zèng':['综'],'jī qī':['缉'],'wēn yùn yūn':['缊'],'fèng féng':['缝'],'shuāi cuī suī':['缞'],'miù móu liáo miào mù':['缪'],'qiāo sāo':['缲'],fǒu:['缶','缹','缻','雬','鴀'],'bà ba pí':['罢','罷'],'guà guǎi':['罫'],'yáng xiáng':['羊','羏'],'měi gāo':['羙'],'yì xī':['羛'],'qiǎng qiān':['羟'],'qiāng kòng':['羫'],'qián xián yán':['羬'],nóu:['羺'],'hóng gòng':['羾'],'pī bì pō':['翍'],'qú yù':['翑'],ké:['翗'],'qiào qiáo':['翘'],'zhái dí':['翟'],'dào zhōu':['翢'],'hóu qú':['翵'],shuǎ:['耍'],'ruǎn nuò':['耎'],'ér nài':['耏'],'zhuān duān':['耑'],'pá bà':['耙'],'chí sì':['耛'],'qù chú':['耝'],'lún lǔn':['耣'],'jí jiè':['耤'],'tāng tǎng':['耥'],pǎng:['耪','覫'],'zhá zé':['耫'],'yē yé':['耶'],'yún yíng':['耺'],'wà tuǐ zhuó':['聉'],'ér nǜ':['聏'],'tiē zhé':['聑'],'dǐ zhì':['聜'],qié:['聺'],'nǐ jiàn':['聻'],'lèi lē':['肋'],cào:['肏','襙','鄵','鼜'],'bó dí':['肑'],'xiào xiāo':['肖'],'dù dǔ':['肚'],chāi:['肞','釵','钗'],'hán qín hàn':['肣'],'pàng pán pàn':['肨','胖'],'zhūn chún':['肫'],āng:['肮','骯'],'yù yō':['育'],'pí bǐ bì':['肶'],'fèi bì':['胇'],'bèi bēi':['背'],'fèi zǐ':['胏'],'píng pēng':['胓','苹'],'fū fú zhǒu':['胕'],'shèng shēng':['胜'],kuà:['胯','跨','骻'],'gǎi hǎi':['胲'],'gē gé gā':['胳'],'néng nài':['能'],'guī kuì':['胿'],'mài mò':['脉'],'zāng zàng':['脏'],'jiǎo jué':['脚','角'],cuǒ:['脞'],'de te':['脦'],'zuī juān':['脧'],něi:['脮','腇','餒','馁','鮾','鯘'],'pú fǔ':['脯'],niào:['脲'],shuí:['脽'],guò:['腂','過','鐹'],'là xī':['腊'],'yān ā':['腌'],'gāo gào':['膏'],'lù biāo':['膔'],chuái:['膗'],'zhuān chuán chún zhuǎn':['膞'],chuài:['膪','踹'],'fán pán':['膰'],'wǔ hū':['膴'],'shān dàn':['膻'],tún:['臀','臋','蛌','豘','豚','軘','霕','飩','饨','魨','鲀','黗'],'bì bei':['臂'],'là gé':['臈'],'sào sāo':['臊'],nào:['臑','閙','闹','鬧'],'ní luán':['臡'],'qiān xián':['臤'],'guàng jiǒng':['臦'],'guǎng jiǒng':['臩'],'chòu xiù':['臭'],'mián biān':['臱'],'dié zhí':['臷'],'zhī jìn':['臸'],'shè shě':['舍'],pù:['舖','舗'],'bān bō pán':['般'],kuā:['舿'],'gèn gěn':['艮'],'sè shǎi':['色'],'fú bó':['艴'],'jiāo qiú':['艽'],'chāi chā':['芆'],'sháo què':['芍'],'hù xià':['芐'],'zì zǐ':['芓'],'huì hū':['芔'],'tún chūn':['芚'],'jiè gài':['芥'],'xù zhù':['芧'],'yuán yán':['芫'],'xīn xìn':['芯'],'lún huā':['芲'],'wù hū':['芴'],'gōu gǒu':['芶'],'mào máo':['芼'],'fèi fú':['芾'],'chán yín':['苂'],qiē:['苆'],'sū sù':['苏'],'tiáo sháo':['苕'],'lì jī':['苙'],'kē hē':['苛'],'jù qǔ':['苣'],'ruò rě':['若'],'zhù níng':['苧'],'pā bó':['苩'],xiú:['苬'],'zhǎ zuó':['苲'],'jū chá':['苴'],nié:['苶'],'shēng ruí':['苼'],'qié jiā':['茄'],'zǐ cí':['茈'],'qiàn xī':['茜'],chǎi:['茝'],'fá pèi':['茷'],ráo:['荛','蕘','襓','饒','饶'],'yíng xíng':['荥'],'qián xún':['荨','蕁'],'yìn yīn':['荫'],'hé hè':['荷'],'shā suō':['莎'],'péng fēng':['莑'],'shēn xīn':['莘'],'wǎn guān guǎn':['莞'],'yóu sù':['莤'],'shāo xiāo':['莦','蛸'],'làng liáng':['莨'],'piǎo fú':['莩'],'wèn wǎn miǎn':['莬'],'shì shí':['莳','蒔'],'tù tú':['莵'],'xiān liǎn':['莶','薟'],'wǎn yù':['菀'],'zōu chù':['菆'],'lù lǜ':['菉'],'jūn jùn':['菌'],'niè rěn':['菍'],'zī zì zāi':['菑'],'tú tù':['菟'],'jiē shà':['菨'],'qiáo zhǎo':['菬'],'tái zhī chí':['菭'],'fēi fěi':['菲','蜚'],'qín qīn jīn':['菳'],'zū jù':['菹','蒩'],'lǐn má':['菻'],'tián tiàn':['菾'],tiē:['萜','貼','贴'],'luò là lào luō':['落'],'zhù zhuó zhe':['著'],'shèn rèn':['葚'],'gě gé':['葛'],'jùn suǒ':['葰'],'kuì kuài':['蒉'],'rú ná':['蒘'],'méng mēng měng':['蒙'],'yuán huán':['蒝'],'xú shú':['蒣'],'xí xì':['蒵'],'mì míng':['蓂'],'sōu sǒu':['蓃'],'gài gě hé hài':['蓋'],'yǎo zhuó':['蓔'],'diào tiáo dí':['蓧'],'xū qiū fū':['蓲'],'zí jú':['蓻'],'liǎo lù':['蓼'],xu:['蓿'],'hàn hǎn':['蔊'],'màn wàn mán':['蔓'],'pó bò':['蔢'],'fān fán bō':['蕃'],'hóng hòng':['蕻'],'yù ào':['薁','隩'],'xí xiào':['薂'],'báo bó bò':['薄'],'cí zī':['薋'],'wàn luàn':['薍'],'kǎo hāo':['薧'],'yuǎn wěi':['薳'],'zhòu chóu':['薵'],'wō mái':['薶'],'xiāo hào':['藃'],'yù xù xū':['藇'],'jiè jí':['藉'],'diào zhuó':['藋'],'cáng zàng':['藏'],lǎ:['藞'],'chú zhū':['藸'],'pín píng':['蘋'],'gān hán':['虷'],'hóng jiàng':['虹'],'huī huǐ':['虺'],'xiā há':['虾'],'mǎ mà mā':['蚂'],'fāng bàng':['蚄'],'bàng bèng':['蚌'],'jué quē':['蚗'],'qín qián':['蚙'],'gōng zhōng':['蚣'],'fǔ fù':['蚥'],'dài dé':['蚮'],'gǒu qú xù':['蚼'],'bǒ pí':['蚾'],'shé yí':['蛇'],tiě:['蛈','鉄','銕','鐡','鐵','铁','驖'],'gé luò':['蛒'],'máng bàng':['蛖'],'yì xǔ':['蛡'],'há gé':['蛤'],'qiè ní':['蛪'],'é yǐ':['蛾'],'zhē zhé':['蜇'],'là zhà':['蜡'],suò:['蜶','逤'],'yóu qiú':['蝤'],'xiā hā':['蝦'],'xī qī':['螇'],'bī pí':['螕'],'nài něng':['螚'],'hé xiá':['螛'],'guì huǐ':['螝'],'mǎ mā mà':['螞'],'shì zhē':['螫'],'zhì dié':['螲'],'jiàn chán':['螹'],'ma má mò':['蟆'],'mǎng měng':['蟒'],'biē bié':['蟞'],'bēn fèi':['蟦'],'láo liáo':['蟧'],'yín xún':['蟫'],'lí lǐ':['蠡'],'xuè xiě':['血'],'xíng háng hàng héng':['行'],'shuāi cuī':['衰'],'tuó tuō':['袉'],'lǐng líng':['袊'],'bào páo pào':['袌'],'jù jiē':['袓'],'hè kè':['袔'],'yí yì':['袘','貤'],'nà jué':['袦'],'bèi pī':['被'],'chǐ nuǒ':['袲'],'chǐ qǐ duǒ nuǒ':['袳'],'jiá qiā jié':['袷'],'bó mò':['袹'],'guī guà':['袿'],'liè liě':['裂'],'chéng chěng':['裎'],'jiē gé':['裓'],'dāo chóu':['裯'],'shang cháng':['裳'],'yuān gǔn':['裷'],'yǎn ān':['裺'],'tì xī':['裼'],'fù fú':['褔'],'chǔ zhǔ':['褚'],'tuì tùn':['褪'],lǎi:['襰'],'yào yāo':['要'],'qín tán':['覃'],'jiàn xiàn':['見','见'],piǎn:['覑','諞','谝','貵','𡎚'],'piē miè':['覕'],'yíng yǐng':['覮'],'qù qū':['覰','覷','觑'],'jiàn biǎn':['覵'],'luó luǎn':['覶'],'zī zuǐ':['觜'],'huà xiè':['觟'],'jiě jiè xiè':['解','觧'],'xué hù':['觷'],'lì lù':['觻'],tǎo:['討','讨'],zhùn:['訰'],'zī zǐ':['訾'],'yí dài':['詒','诒'],xiòng:['詗','诇'],'diào tiǎo':['誂'],'yí chǐ chì':['誃'],'lǎng làng':['誏'],'ēi éi ěi èi xī':['誒','诶'],shuà:['誜'],'yǔ yù':['語','语','雨'],'shuō shuì yuè':['說','说'],'shuí shéi':['誰','谁'],'qū juè':['誳'],'chī lài':['誺'],'nì ná':['誽'],'diào tiáo':['調'],'pǐ bēi':['諀'],'jì jī':['諅'],'zé zuò zhǎ cuò':['諎'],'chù jí':['諔'],'háo xià':['諕'],'lùn lún':['論','论'],'shì dì':['諟'],'huà guā':['諣'],'xǐ shāi āi':['諰'],'nán nàn':['諵','難'],miù:['謬','谬'],zèn:['譖','谮'],'shí zhì':['識','识'],'juàn xuān':['讂'],'yí tuī':['讉'],zhán:['讝'],'xǔ hǔ':['许'],'xiáng yáng':['详'],'tiáo diào zhōu':['调'],'chén shèn':['谌'],'mí mèi':['谜'],'màn mán':['谩'],'gǔ yù':['谷'],'huō huò huá':['豁'],'zhì zhài':['豸'],'huān huán':['貆'],'kěn kūn':['貇'],'mò hé':['貈'],'mò hé háo':['貉'],'jù lóu':['貗'],'zé zhài':['責','责'],'dài tè':['貸'],'bì bēn':['賁'],'jiǎ gǔ jià':['賈'],'xiōng mín':['賯'],càng:['賶'],'zhuàn zuàn':['賺','赚'],'wàn zhuàn':['贃'],'gàn gòng zhuàng':['贛'],'yuán yùn':['贠'],'bēn bì':['贲'],'jiǎ gǔ':['贾'],zǒu:['走','赱','鯐'],'dié tú':['趃'],'jū qiè':['趄'],'qū cù':['趋','趨'],'jí jié':['趌'],'guā huó':['趏'],'què qì jí':['趞'],'tàng tāng':['趟'],'chuō zhuó':['趠'],'qù cù':['趣'],'yuè tì':['趯'],'bō bào':['趵'],'kuà wù':['趶'],'guì jué':['趹'],'fāng fàng páng':['趽'],'páo bà':['跁'],'qí qǐ':['跂'],'jiàn chén':['跈'],'pǎo páo':['跑'],'diǎn diē tiē':['跕'],'jū jù qiè':['跙'],bǒ:['跛'],'luò lì':['跞'],'dài duò duō chí':['跢'],zhuǎi:['跩'],'bèng pián':['跰'],'tiào táo':['跳'],'shū chōu':['跾'],'liàng liáng':['踉'],'tà tā':['踏'],chǎ:['蹅','鑔','镲'],'dí zhí':['蹢'],'dēng dèng':['蹬','鐙','镫'],cèng:['蹭'],'dūn cún':['蹲'],'juě jué':['蹶'],liāo:['蹽'],'xiè sǎ':['躠'],tǐ:['躰','軆','骵'],'yà zhá gá':['轧','軋'],'xìn xiàn':['軐'],'fàn guǐ':['軓'],'zhuàn zhuǎn':['転'],'zhóu zhòu':['軸','轴'],bú:['轐','醭','鳪'],'zhuǎn zhuàn zhuǎi':['转'],'zǎi zài':['载'],'niǎn zhǎn':['辗'],'biān bian':['边'],'dào biān':['辺'],'yǐ yí':['迆','迤','迱'],'guò guo guō':['过'],'wàng kuāng':['迋'],'hái huán':['还'],'zhè zhèi':['这'],'yuǎn yuàn':['远'],'zhì lì':['迣'],'zhù wǎng':['迬'],'zhuī duī':['追'],'shì kuò':['适'],tòu:['透'],'tōng tòng':['通'],guàng:['逛'],'dǎi dài':['逮'],'suì suí':['遂'],'tí dì':['遆'],'yí wèi':['遗'],'shì dí zhé':['適'],cà:['遪'],'huán hái':['還'],'lí chí':['邌'],'kàng háng':['邟'],'nà nèi nā':['那'],'xié yá yé yú xú':['邪'],'gāi hái':['郂'],'huán xún':['郇'],'chī xī':['郗'],hǎo:['郝'],'lì zhí':['郦'],'xiáo ǎo':['郩'],'dōu dū':['都'],liǎo:['曢','鄝','镽'],'zàn cuán cuó':['酂','酇'],'dīng dǐng':['酊'],'cù zuò':['酢'],'fā pō':['酦'],'shāi shī':['酾'],niàng:['酿','醸'],'qiú chōu':['醔'],'pō fā':['醗','醱'],'chǎn chěn':['醦'],'yàn liǎn xiān':['醶'],'niàng niáng':['釀'],'lǐ li':['里'],'lí xǐ xī':['釐'],'liǎo liào':['釕'],'dīng dìng':['釘','钉'],'qiǎo jiǎo':['釥'],'yú huá':['釪'],'huá wū':['釫'],'rì rèn jiàn':['釰','釼'],'dì dài':['釱'],'pī zhāo':['釽'],'yá yé':['釾'],'bǎ pá':['鈀','钯'],'tā tuó':['鉈','铊'],běi:['鉳'],'bǐng píng':['鉼'],'hā kē':['鉿','铪'],chòng:['銃','铳'],'xiǎng jiōng':['銄'],'yù sì':['銉'],'xù huì':['銊'],'rén rěn':['銋'],'shàn shuò':['銏'],'chì lì':['銐'],'xiǎn xǐ':['銑','铣'],'hóu xiàng':['銗'],'diào tiáo yáo':['銚'],'xiān kuò tiǎn guā':['銛','銽','铦'],'zhé niè':['銸'],'zhōng yōng':['銿'],'tōu tù dòu':['鋀'],'méi méng':['鋂'],'wàn jiǎn':['鋄','鎫'],'tǐng dìng':['鋌','铤'],'juān jiān cuān':['鋑'],'sī tuó':['鋖'],'juān xuān juàn':['鋗'],'wú huá wū':['鋘'],'zhuó chuò':['鋜'],'xíng xìng jīng':['鋞'],'jū jú':['鋦','锔'],'zuì niè':['鋷'],'yuān yuǎn wǎn wān':['鋺'],'gāng gàng':['鋼','钢'],zhuī:['錐','锥','騅','骓','鵻'],ā:['錒','锕'],'cuō chā':['鎈'],'suǒ sè':['鎍'],'yáo zú':['鎐'],'yè tà gé':['鎑'],'qiāng chēng':['鎗'],'gé lì':['鎘','镉','鬲'],'bī pī bì':['鎞'],'gǎo hào':['鎬'],'zú chuò':['鏃'],'xiū xiù':['鏅'],'shòu sōu':['鏉'],'dí dī':['鏑','镝'],'qiāo sǎn càn':['鏒'],'lù áo':['鏕'],'tāng táng':['鏜'],'jiàn zàn':['鏩'],'huì suì ruì':['鏸'],'qiǎng qiāng':['鏹','镪'],'sǎn xiàn sà':['鏾'],'jiǎn jiàn':['鐧','锏'],'dāng chēng':['鐺','铛'],'zuān zuàn':['鑽'],'sà xì':['钑'],'yào yuè':['钥'],'tǒu dǒu':['钭'],'zuàn zuān':['钻'],'qiān yán':['铅'],'pí pī':['铍'],'yáo diào tiáo':['铫'],'tāng tàng':['铴'],'pù pū':['铺'],'tán xiān':['锬'],'liù liú':['镏'],'hào gǎo':['镐'],'táng tāng':['镗'],'tán chán xín':['镡'],'huò shǎn':['閄'],'hàn bì':['閈','闬'],'kāng kàng':['閌','闶'],'xián jiàn jiān jiǎn':['閒'],'xiā xiǎ':['閕'],'xiǎ kě':['閜'],'biàn guān':['閞'],'hé gé':['閤','颌'],'hòng xiàng':['閧'],'sē xī':['閪'],'tíng tǐng':['閮'],'è yān':['閼','阏'],'hòng juǎn xiàng':['闂'],'bǎn pàn':['闆'],'dū shé':['闍','阇'],'què quē':['闕'],'tāng táng chāng':['闛'],'kàn hǎn':['闞','阚'],'xì sè tà':['闟'],'mēn mèn':['闷'],'quē què':['阙'],'yán diàn':['阽'],'ā ē':['阿'],'bēi pō pí':['陂'],'yàn yǎn':['隁'],'yú yáo shù':['隃'],'lóng lōng':['隆'],'duì zhuì':['隊'],'suí duò':['隋'],'gāi qí ái':['隑'],'huī duò':['隓','隳'],'wěi kuí':['隗'],'lì dài':['隸'],'zhuī cuī wéi':['隹'],'hè hú':['隺','鶮'],'jùn juàn':['隽','雋'],'nán nàn nuó':['难'],'què qiāo qiǎo':['雀'],'guàn huán':['雚'],'guī xī':['雟'],'sè xí':['雭'],án:['雸'],'wù méng':['雺'],tèng:['霯'],'lù lòu':['露'],mái:['霾'],'jìng liàng':['靚'],'gé jí':['革'],bǎ:['靶'],'yāng yàng':['鞅'],'gé tà sǎ':['鞈'],'biān yìng':['鞕'],'qiào shāo':['鞘'],'juān xuān':['鞙'],'shàng zhǎng':['鞝'],'pí bǐng bì bēi':['鞞'],la:['鞡'],'xiè dié':['鞢'],ēng:['鞥'],'móu mù':['鞪'],'bì bǐng':['鞸'],'mèi wà':['韎'],rǒu:['韖'],'shè xiè':['韘'],'yùn wēn':['韫'],'dùn dú':['頓','顿'],duǐ:['頧'],luō:['頱'],'bīn pín':['頻'],yóng:['顒','颙','鰫'],mān:['顢','颟'],'jǐng gěng':['颈'],'jié xié jiá':['颉'],'kē ké':['颏'],'pín bīn':['频'],'chàn zhàn':['颤'],'fēng fěng':['風','风'],'biāo diū':['颩'],'bá fú':['颰'],'sāo sōu':['颾'],'liù liáo':['飂'],'shí sì yì':['食'],'yǎng juàn':['飬'],'zhù tǒu':['飳'],'yí sì':['飴'],'zuò zé zhā':['飵'],tiè:['飻','餮'],'xiǎng náng':['饟'],'táng xíng':['饧'],'gē le':['饹'],'chā zha':['馇'],'náng nǎng':['馕'],'yūn wò':['馧'],'zhī shì':['馶'],'xìn jìn':['馸'],'kuài jué':['駃'],zǎng:['駔','驵'],'tái dài':['駘'],'xún xuān':['駨'],'liáng láng':['駺'],piàn:['騗','騙','骗','魸'],'dài tái':['骀'],'sāo sǎo':['骚'],'gǔ gū':['骨'],'bèi mó':['骳'],'xiāo qiāo':['骹'],'bǎng pǎng':['髈'],'bó jué':['髉'],'bì pǒ':['髲'],'máo méng':['髳'],'kuò yuè':['髺'],'bā bà':['魞','鲃'],'jì cǐ':['鮆'],'bó bà':['鮊'],'zhǎ zhà':['鮓','鲊'],'chóu dài':['鮘'],'luò gé':['鮥'],'guī xié wā kuí':['鮭'],'xiān xiǎn':['鮮','鲜'],'pū bū':['鯆'],'yì sī':['鯣'],'bà bó':['鲌'],'guī xié':['鲑'],'sāi xǐ':['鳃'],'niǎo diǎo':['鳥'],'diāo zhāo':['鳭'],'gān hàn yàn':['鳱'],'fū guī':['鳺'],'jiān qiān zhān':['鳽'],'hé jiè':['鶡'],'piān biǎn':['鶣'],'chuàn zhì':['鶨'],'cāng qiāng':['鶬'],'sǔn xùn':['鶽'],'biāo páo':['麃'],'zhù cū':['麆'],'jūn qún':['麇','麕'],chi:['麶'],'mó me':['麼'],'mó me ma':['麽'],'mí mǒ':['麿'],'dàn shèn':['黮'],'zhěn yān':['黰'],'dǎn zhǎn':['黵'],'miǎn mǐn měng':['黾'],hōu:['齁'],nàng:['齉'],'qí jì zī zhāi':['齐'],'yín kěn yǎn':['龂'],'yín kěn':['龈'],'gōng wò':['龏'],'guī jūn qiū':['龜','龟'],'kuí wā':['䖯'],lōu:['䁖'],'ōu qū':['𫭟'],'lóu lǘ':['𦝼'],'gǎ gā gá':['嘎'],'wā guà':['坬'],'zhǐ dǐ':['茋'],'gǒng hóng':['硔'],'yáo xiào':['滧'],};const DICT1=new FastDictFactory();Object.keys(map).forEach((key)=>{const chars=map[key];for(let char of chars){DICT1.set(char,key)}});const InitialList=['zh','ch','sh','z','c','s','b','p','m','f','d','t','n','l','g','k','h','j','q','x','r','y','w','',];const SpecialInitialList=['j','q','x'];const SpecialFinalList=['uān','uán','uǎn','uàn','uan','uē','ué','uě','uè','ue','ūn','ún','ǔn','ùn','un','ū','ú','ǔ','ù','u',];const SpecialFinalMap={uān:'üān',uán:'üán',uǎn:'üǎn',uàn:'üàn',uan:'üan',uē:'üē',ué:'üé',uě:'üě',uè:'üè',ue:'üe',ūn:'ǖn',ún:'ǘn',ǔn:'ǚn',ùn:'ǜn',un:'ün',ū:'ǖ',ú:'ǘ',ǔ:'ǚ',ù:'ǜ',u:'ü',};const doubleFinalList=['ia','ian','iang','iao','ie','iu','iong','ua','uai','uan','uang','ue','ui','uo','üan','üe','van','ve',];const Numbers={一:'yì',二:'èr',三:'sān',四:'sì',五:'wǔ',六:'liù',七:'qī',八:'bā',九:'jiǔ',十:'shí',百:'bǎi',千:'qiān',万:'wàn',亿:'yì',单:'dān',两:'liǎng',双:'shuāng',多:'duō',几:'jǐ',十一:'shí yī',零一:'líng yī',第一:'dì yī',一十:'yī shí',一十一:'yī shí yī',};const NumberWordMap={重:'chóng',行:'háng',斗:'dǒu',更:'gēng',};function genNumberDict(){const dict={零一:'líng yī',〇一:'líng yī',十一:'shí yī',一十:'yī shí',第一:'dì yī',一十一:'yī shí yī',};for(let number in Numbers){for(let key in NumberWordMap){const word=`${number}${key}`;const pinyin=`${Numbers[number]}${NumberWordMap[key]}`;dict[word]=pinyin}}return dict}const NumberDict=genNumberDict();const PatternNumberDict=Object.keys(NumberDict).map((key)=>({zh:key,pinyin:NumberDict[key],probability:1e-12,length:stringLength(key),priority:Priority.Normal,dict:Symbol('rule'),}));const toneSandhiMap={不:{bú:[4],},一:{yí:[4],yì:[1,2,3],},};const toneSandhiIgnoreSuffix={不:['的','而','之','后','也','还','地'],一:['的','而','之','后','也','还','是'],};const toneSandhiList=Object.keys(toneSandhiMap);function processToneSandhi(cur,pre,next){if(toneSandhiList.indexOf(cur)===-1){return getSingleWordPinyin(cur)}if(pre===next&&pre&&getSingleWordPinyin(pre)!==pre){return getPinyinWithoutTone(getSingleWordPinyin(cur))}if(next&&!toneSandhiIgnoreSuffix[cur].includes(next)){const nextPinyin=getSingleWordPinyin(next);if(nextPinyin!==next){const nextTone=getNumOfTone(nextPinyin);const pinyinMap=toneSandhiMap[cur];for(let pinyin in pinyinMap){const tones=pinyinMap[pinyin];if(tones.indexOf(Number(nextTone))!==-1){return pinyin}}}}}function processToneSandhiLiao(cur,pre){if(cur==='了'&&(!pre||!DICT1.get(pre))){return'liǎo'}}function processReduplicationChar(cur,pre){if(cur==='々'){if(!pre||!DICT1.get(pre)){return'tóng'}else{return DICT1.get(pre).split(' ')[0]}}}function processSepecialPinyin(cur,pre,next){return(processReduplicationChar(cur,pre)||processToneSandhiLiao(cur,pre)||processToneSandhi(cur,pre,next)||getSingleWordPinyin(cur))}const Surnames={南宫:'nán gōng',第五:'dì wǔ',万俟:'mò qí',司马:'sī mǎ',上官:'shàng guān',欧阳:'ōu yáng',夏侯:'xià hóu',诸葛:'zhū gě',闻人:'wén rén',东方:'dōng fāng',赫连:'hè lián',皇甫:'huáng fǔ',尉迟:'yù chí',公羊:'gōng yáng',澹台:'tán tái',公冶:'gōng yě',宗政:'zōng zhèng',濮阳:'pú yáng',淳于:'chún yú',太叔:'tài shū',申屠:'shēn tú',公孙:'gōng sūn',仲孙:'zhòng sūn',轩辕:'xuān yuán',令狐:'líng hú',钟离:'zhōng lí',宇文:'yǔ wén',长孙:'zhǎng sūn',慕容:'mù róng',鲜于:'xiān yú',闾丘:'lǘ qiū',司徒:'sī tú',司空:'sī kōng',亓官:'qí guān',司寇:'sī kòu',仉督:'zhǎng dū',子车:'zǐ jū',颛孙:'zhuān sūn',端木:'duān mù',巫马:'wū mǎ',公西:'gōng xī',漆雕:'qī diāo',乐正:'yuè zhèng',壤驷:'rǎng sì',公良:'gōng liáng',拓跋:'tuò bá',夹谷:'jiá gǔ',宰父:'zǎi fǔ',榖梁:'gǔ liáng',段干:'duàn gān',百里:'bǎi lǐ',东郭:'dōng guō',南门:'nán mén',呼延:'hū yán',羊舌:'yáng shé',梁丘:'liáng qiū',左丘:'zuǒ qiū',东门:'dōng mén',西门:'xī mén',句龙:'gōu lóng',毌丘:'guàn qiū',赵:'zhào',钱:'qián',孙:'sūn',李:'lǐ',周:'zhōu',吴:'wú',郑:'zhèng',王:'wáng',冯:'féng',陈:'chén',褚:'chǔ',卫:'wèi',蒋:'jiǎng',沈:'shěn',韩:'hán',杨:'yáng',朱:'zhū',秦:'qín',尤:'yóu',许:'xǔ',何:'hé',吕:'lǚ',施:'shī',张:'zhāng',孔:'kǒng',曹:'cáo',严:'yán',华:'huà',金:'jīn',魏:'wèi',陶:'táo',姜:'jiāng',戚:'qī',谢:'xiè',邹:'zōu',喻:'yù',柏:'bǎi',水:'shuǐ',窦:'dòu',章:'zhāng',云:'yún',苏:'sū',潘:'pān',葛:'gě',奚:'xī',范:'fàn',彭:'péng',郎:'láng',鲁:'lǔ',韦:'wéi',昌:'chāng',马:'mǎ',苗:'miáo',凤:'fèng',花:'huā',方:'fāng',俞:'yú',任:'rén',袁:'yuán',柳:'liǔ',酆:'fēng',鲍:'bào',史:'shǐ',唐:'táng',费:'fèi',廉:'lián',岑:'cén',薛:'xuē',雷:'léi',贺:'hè',倪:'ní',汤:'tāng',滕:'téng',殷:'yīn',罗:'luó',毕:'bì',郝:'hǎo',邬:'wū',安:'ān',常:'cháng',乐:'yuè',于:'yú',时:'shí',傅:'fù',皮:'pí',卞:'biàn',齐:'qí',康:'kāng',伍:'wǔ',余:'yú',元:'yuán',卜:'bǔ',顾:'gù',孟:'mèng',平:'píng',黄:'huáng',和:'hé',穆:'mù',萧:'xiāo',尹:'yǐn',姚:'yáo',邵:'shào',湛:'zhàn',汪:'wāng',祁:'qí',毛:'máo',禹:'yǔ',狄:'dí',米:'mǐ',贝:'bèi',明:'míng',臧:'zāng',计:'jì',伏:'fú',成:'chéng',戴:'dài',谈:'tán',宋:'sòng',茅:'máo',庞:'páng',熊:'xióng',纪:'jǐ',舒:'shū',屈:'qū',项:'xiàng',祝:'zhù',董:'dǒng',梁:'liáng',杜:'dù',阮:'ruǎn',蓝:'lán',闵:'mǐn',席:'xí',季:'jì',麻:'má',强:'qiáng',贾:'jiǎ',路:'lù',娄:'lóu',危:'wēi',江:'jiāng',童:'tóng',颜:'yán',郭:'guō',梅:'méi',盛:'shèng',林:'lín',刁:'diāo',钟:'zhōng',徐:'xú',邱:'qiū',骆:'luò',高:'gāo',夏:'xià',蔡:'cài',田:'tián',樊:'fán',胡:'hú',凌:'líng',霍:'huò',虞:'yú',万:'wàn',支:'zhī',柯:'kē',昝:'zǎn',管:'guǎn',卢:'lú',莫:'mò',经:'jīng',房:'fáng',裘:'qiú',缪:'miào',干:'gān',解:'xiè',应:'yīng',宗:'zōng',丁:'dīng',宣:'xuān',贲:'bēn',邓:'dèng',郁:'yù',单:'shàn',杭:'háng',洪:'hóng',包:'bāo',诸:'zhū',左:'zuǒ',石:'shí',崔:'cuī',吉:'jí',钮:'niǔ',龚:'gōng',程:'chéng',嵇:'jī',邢:'xíng',滑:'huá',裴:'péi',陆:'lù',荣:'róng',翁:'wēng',荀:'xún',羊:'yáng',於:'yū',惠:'huì',甄:'zhēn',曲:'qū',家:'jiā',封:'fēng',芮:'ruì',羿:'yì',储:'chǔ',靳:'jìn',汲:'jí',邴:'bǐng',糜:'mí',松:'sōng',井:'jǐng',段:'duàn',富:'fù',巫:'wū',乌:'wū',焦:'jiāo',巴:'bā',弓:'gōng',牧:'mù',隗:'wěi',山:'shān',谷:'gǔ',车:'chē',侯:'hóu',宓:'mì',蓬:'péng',全:'quán',郗:'xī',班:'bān',仰:'yǎng',秋:'qiū',仲:'zhòng',伊:'yī',宫:'gōng',宁:'nìng',仇:'qiú',栾:'luán',暴:'bào',甘:'gān',钭:'tǒu',厉:'lì',戎:'róng',祖:'zǔ',武:'wǔ',符:'fú',刘:'liú',景:'jǐng',詹:'zhān',束:'shù',龙:'lóng',叶:'yè',幸:'xìng',司:'sī',韶:'sháo',郜:'gào',黎:'lí',蓟:'jì',薄:'bó',印:'yìn',宿:'sù',白:'bái',怀:'huái',蒲:'pú',邰:'tái',从:'cóng',鄂:'è',索:'suǒ',咸:'xián',籍:'jí',赖:'lài',卓:'zhuó',蔺:'lìn',屠:'tú',蒙:'méng',池:'chí',乔:'qiáo',阴:'yīn',鬱:'yù',胥:'xū',能:'nài',苍:'cāng',双:'shuāng',闻:'wén',莘:'shēn',党:'dǎng',翟:'zhái',谭:'tán',贡:'gòng',劳:'láo',逄:'páng',姬:'jī',申:'shēn',扶:'fú',堵:'dǔ',冉:'rǎn',宰:'zǎi',郦:'lì',雍:'yōng',郤:'xì',璩:'qú',桑:'sāng',桂:'guì',濮:'pú',牛:'niú',寿:'shòu',通:'tōng',边:'biān',扈:'hù',燕:'yān',冀:'jì',郏:'jiá',浦:'pǔ',尚:'shàng',农:'nóng',温:'wēn',别:'bié',庄:'zhuāng',晏:'yàn',柴:'chái',瞿:'qú',阎:'yán',充:'chōng',慕:'mù',连:'lián',茹:'rú',习:'xí',宦:'huàn',艾:'ài',鱼:'yú',容:'róng',向:'xiàng',古:'gǔ',易:'yì',慎:'shèn',戈:'gē',廖:'liào',庾:'yǔ',终:'zhōng',暨:'jì',居:'jū',衡:'héng',步:'bù',都:'dū',耿:'gěng',满:'mǎn',弘:'hóng',匡:'kuāng',国:'guó',文:'wén',寇:'kòu',广:'guǎng',禄:'lù',阙:'quē',东:'dōng',欧:'ōu',殳:'shū',沃:'wò',利:'lì',蔚:'wèi',越:'yuè',夔:'kuí',隆:'lóng',师:'shī',巩:'gǒng',厍:'shè',聂:'niè',晁:'cháo',勾:'gōu',敖:'áo',融:'róng',冷:'lěng',訾:'zī',辛:'xīn',阚:'kàn',那:'nā',简:'jiǎn',饶:'ráo',空:'kōng',曾:'zēng',母:'mǔ',沙:'shā',乜:'niè',养:'yǎng',鞠:'jū',须:'xū',丰:'fēng',巢:'cháo',关:'guān',蒯:'kuǎi',相:'xiàng',查:'zhā',后:'hòu',荆:'jīng',红:'hóng',游:'yóu',竺:'zhú',权:'quán',逯:'lù',盖:'gě',益:'yì',桓:'huán',公:'gōng',牟:'móu',哈:'hǎ',言:'yán',福:'fú',肖:'xiāo',区:'ōu',覃:'qín',朴:'piáo',繁:'pó',员:'yùn',句:'gōu',要:'yāo',过:'guō',钻:'zuān',谌:'chén',折:'shé',召:'shào',郄:'qiè',撒:'sǎ',甯:'nìng',六:'lù',啜:'chuài',行:'xíng',};const PatternSurname=Object.keys(Surnames).map((key)=>({zh:key,pinyin:Surnames[key],probability:1+stringLength(key),length:stringLength(key),priority:Priority.Surname,dict:Symbol('surname'),}));const DICT2={这个:'zhè ge',成为:'chéng wéi',认为:'rèn wéi',作为:'zuò wéi',部分:'bù fen',要求:'yāo qiú',应该:'yīng gāi',增长:'zēng zhǎng',提供:'tí gōng',觉得:'jué de',任务:'rèn wu',那个:'nà ge',称为:'chēng wéi',为主:'wéi zhǔ',了解:'liǎo jiě',处理:'chǔ lǐ',皇上:'huáng shang',只要:'zhǐ yào',大量:'dà liàng',力量:'lì liàng',几乎:'jī hū',干部:'gàn bù',目的:'mù dì',行为:'xíng wéi',只见:'zhǐ jiàn',认识:'rèn shi',市长:'shì zhǎng',师父:'shī fu',调查:'diào chá',重新:'chóng xīn',分为:'fēn wéi',知识:'zhī shi',导弹:'dǎo dàn',质量:'zhì liàng',行款:'háng kuǎn',行列:'háng liè',行话:'háng huà',行业:'háng yè',隔行:'gé háng',在行:'zài háng',行家:'háng jia',内行:'nèi háng',外行:'wài háng',同行:'tóng háng',本行:'běn háng',行伍:'háng wǔ',洋行:'yáng háng',银行:'yín háng',商行:'shāng háng',支行:'zhī háng',总行:'zǒng háng',行情:'háng qíng',懂行:'dǒng háng',行规:'háng guī',行当:'háng dang',行货:'háng huò',太行:'tài háng',入行:'rù háng',中行:'zhōng háng',农行:'nóng háng',工行:'gōng háng',建行:'jiàn háng',各行:"gè háng",行号:'háng hào',行高:'háng gāo',行首:'háng shǒu',行尾:'háng wěi',行末:'háng mò',行长:'háng cháng',行距:'háng jù',换行:'huàn háng',行会:'háng huì',行辈:'háng bèi',行道:'háng dào',道行:'dào heng',参与:'cān yù',充分:'chōng fèn',尽管:'jǐn guǎn',生长:'shēng zhǎng',数量:'shù liàng',应当:'yīng dāng',院长:'yuàn zhǎng',强调:'qiáng diào',只能:'zhǐ néng',音乐:'yīn yuè',以为:'yǐ wéi',处于:'chǔ yú',部长:'bù zhǎng',蒙古:'měng gǔ',只有:'zhǐ yǒu',适当:'shì dàng',只好:'zhǐ hǎo',成长:'chéng zhǎng',高兴:'gāo xìng',不了:'bù liǎo',产量:'chǎn liàng',胖子:'pàng zi',显得:'xiǎn de',只是:'zhǐ shì',似的:'shì de',率领:'shuài lǐng',改为:'gǎi wéi',不禁:'bù jīn',成分:'chéng fèn',答应:'dā ying',少年:'shào nián',兴趣:'xìng qù',太监:'tài jian',休息:'xiū xi',校长:'xiào zhǎng',更新:'gēng xīn',合同:'hé tong',喝道:'hè dào',重庆:'chóng qìng',重建:'chóng jiàn',使得:'shǐ de',审查:'shěn chá',累计:'lěi jì',给予:'jǐ yǔ',极为:'jí wéi',冠军:'guàn jūn',仿佛:'fǎng fú',头发:'tóu fa',投降:'tóu xiáng',家长:'jiā zhǎng',仔细:'zǐ xì',要是:'yào shi',将领:'jiàng lǐng',含量:'hán liàng',更为:'gèng wéi',积累:'jī lěi',地处:'dì chǔ',县长:'xiàn zhǎng',少女:'shào nǚ',路上:'lù shang',只怕:'zhǐ pà',能量:'néng liàng',储量:'chǔ liàng',供应:'gōng yìng',挑战:'tiǎo zhàn',西藏:'xī zàng',记得:'jì de',总量:'zǒng liàng',当真:'dàng zhēn',将士:'jiàng shì',差别:'chā bié',较为:'jiào wéi',长老:'zhǎng lǎo',大夫:'dài fu',差异:'chā yì',懂得:'dǒng de',尽量:'jǐn liàng',模样:'mú yàng',的确:'dí què',为首:'wéi shǒu',便宜:'pián yi',更名:'gēng míng',石头:'shí tou',州长:'zhōu zhǎng',为止:'wéi zhǐ',漂亮:'piào liang',炮弹:'pào dàn',藏族:'zàng zú',角色:'jué sè',当作:'dàng zuò',尽快:'jǐn kuài',人为:'rén wéi',重复:'chóng fù',胡同:'hú tòng',差距:'chā jù',弟兄:'dì xiong',大将:'dà jiàng',睡觉:'shuì jiào',一觉:'yí jiào',团长:'tuán zhǎng',队长:'duì zhǎng',区长:'qū zhǎng',难得:'nán dé',丫头:'yā tou',会长:'huì zhǎng',弟弟:'dì di',王爷:'wáng ye',重量:'zhòng liàng',誉为:'yù wéi',家伙:'jiā huo',华山:'huà shān',椅子:'yǐ zi',流量:'liú liàng',长大:'zhǎng dà',勉强:'miǎn qiǎng',会计:'kuài jì',过分:'guò fèn',济南:'jǐ nán',调动:'diào dòng',燕京:'yān jīng',少将:'shào jiàng',中毒:'zhòng dú',晓得:'xiǎo de',变更:'biàn gēng',打更:'dǎ gēng',认得:'rèn de',苹果:'píng guǒ',念头:'niàn tou',挣扎:'zhēng zhá',三藏:'sān zàng',剥削:'bō xuē',丞相:'chéng xiàng',少量:'shǎo liàng',寻思:'xún si',夺得:'duó dé',干线:'gàn xiàn',呼吁:'hū yù',处罚:'chǔ fá',长官:'zhǎng guān',柏林:'bó lín',亲戚:'qīn qi',身分:'shēn fèn',胳膊:'gē bo',着手:'zhuó shǒu',炸弹:'zhà dàn',咳嗽:'ké sou',叶子:'yè zi',外长:'wài zhǎng',供给:'gōng jǐ',师长:'shī zhǎng',变量:'biàn liàng',应有:'yīng yǒu',下载:'xià zài',乐器:'yuè qì',间接:'jiàn jiē',底下:'dǐ xià',打扮:'dǎ bàn',子弹:'zǐ dàn',弹药:'dàn yào',热量:'rè liàng',削弱:'xuē ruò',骨干:'gǔ gàn',容量:'róng liàng',模糊:'mó hu',转动:'zhuàn dòng',称呼:'chēng hu',科长:'kē zhǎng',处置:'chǔ zhì',着重:'zhuó zhòng',着急:'zháo jí',强迫:'qiǎng pò',庭长:'tíng zhǎng',首相:'shǒu xiàng',喇嘛:'lǎ ma',镇长:'zhèn zhǎng',只管:'zhǐ guǎn',重重:'chóng chóng',免得:'miǎn de',着实:'zhuó shí',度假:'dù jià',真相:'zhēn xiàng',相貌:'xiàng mào',处分:'chǔ fèn',委屈:'wěi qu',为期:'wéi qī',伯伯:'bó bo',伯子:'bǎi zi',圈子:'quān zi',见识:'jiàn shi',笼罩:'lǒng zhào',与会:'yù huì',都督:'dū du',都市:'dū shì',成都:'chéng dū',首都:'shǒu dū',帝都:'dì dū',王都:'wáng dū',东都:'dōng dū',都护:'dū hù',都城:'dū chéng',建都:'jiàn dū',迁都:'qiān dū',故都:'gù dū',定都:'dìng dū',中都:'zhōng dū',六安:'lù ān',宰相:'zǎi xiàng',较量:'jiào liàng',对称:'duì chèn',总长:'zǒng zhǎng',相公:'xiàng gong',空白:'kòng bái',打量:'dǎ liang',水分:'shuǐ fèn',舌头:'shé tou',没收:'mò shōu',行李:'xíng li',判处:'pàn chǔ',散文:'sǎn wén',处境:'chǔ jìng',孙子:'sūn zi',拳头:'quán tou',打发:'dǎ fā',组长:'zǔ zhǎng',骨头:'gǔ tou',宁可:'nìng kě',更换:'gēng huàn',薄弱:'bó ruò',还原:'huán yuán',重修:'chóng xiū',重来:'chóng lái',只顾:'zhǐ gù',爱好:'ài hào',馒头:'mán tou',军长:'jūn zhǎng',首长:'shǒu zhǎng',厂长:'chǎng zhǎng',司长:'sī zhǎng',长子:'zhǎng zǐ',强劲:'qiáng jìng',恰当:'qià dàng',头儿:'tóu er',站长:'zhàn zhǎng',折腾:'zhē teng',相处:'xiāng chǔ',统率:'tǒng shuài',中将:'zhōng jiàng',命中:'mìng zhòng',名将:'míng jiàng',木头:'mù tou',动弹:'dòng tan',地壳:'dì qiào',干活:'gàn huó',少爷:'shào ye',水量:'shuǐ liàng',补给:'bǔ jǐ',尾巴:'wěi ba',来得:'lái de',好奇:'hào qí',钥匙:'yào shi',当做:'dàng zuò',沉着:'chén zhuó',哑巴:'yǎ ba',车子:'chē zi',上将:'shàng jiàng',恶心:'ě xīn',担子:'dàn zi',应届:'yīng jiè',主角:'zhǔ jué',运转:'yùn zhuǎn',兄长:'xiōng zhǎng',格式:'gé shì',正月:'zhēng yuè',营长:'yíng zhǎng',当成:'dàng chéng',女婿:'nǚ xu',咽喉:'yān hóu',重阳:'chóng yáng',化为:'huà wéi',吐蕃:'tǔ bō',钻进:'zuān jìn',乐队:'yuè duì',亮相:'liàng xiàng',被子:'bèi zi',舍得:'shě de',杉木:'shā mù',击中:'jī zhòng',排长:'pái zhǎng',假期:'jià qī',分量:'fèn liàng',数次:'shù cì',提防:'dī fáng',吆喝:'yāo he',查处:'chá chǔ',量子:'liàng zǐ',里头:'lǐ tou',调研:'diào yán',伺候:'cì hou',重申:'chóng shēn',枕头:'zhěn tou',拚命:'pīn mìng',社长:'shè zhǎng',归还:'guī huán',批量:'pī liàng',畜牧:'xù mù',点着:'diǎn zháo',甚为:'shèn wéi',小将:'xiǎo jiàng',着眼:'zhuó yǎn',处死:'chǔ sǐ',厌恶:'yàn wù',鼓乐:'gǔ yuè',树干:'shù gàn',秘鲁:'bì lǔ',大方:'dà fāng',外头:'wài tou',班长:'bān zhǎng',星宿:'xīng xiù',宁愿:'nìng yuàn',钦差:'qīn chāi',为数:'wéi shù',勾当:'gòu dàng',削减:'xuē jiǎn',间谍:'jiàn dié',埋怨:'mán yuàn',结实:'jiē shi',计量:'jì liáng',淹没:'yān mò',村长:'cūn zhǎng',连长:'lián zhǎng',自给:'zì jǐ',武将:'wǔ jiàng',温差:'wēn chā',直奔:'zhí bèn',供求:'gōng qiú',剂量:'jì liàng',道长:'dào zhǎng',泄露:'xiè lòu',王八:'wáng ba',切割:'qiē gē',间隔:'jiàn gé',一晃:'yì huǎng',长假:'cháng jià',令狐:'líng hú',为害:'wéi hài',句子:'jù zi',偿还:'cháng huán',疙瘩:'gē da',燕山:'yān shān',堵塞:'dǔ sè',夺冠:'duó guàn',扎实:'zhā shi',电荷:'diàn hè',看守:'kān shǒu',复辟:'fù bì',郁闷:'yù mèn',尽早:'jǐn zǎo',切断:'qiē duàn',指头:'zhǐ tou',为生:'wéi shēng',畜生:'chù sheng',切除:'qiē chú',着力:'zhuó lì',着想:'zhuó xiǎng',级差:'jí chā',投奔:'tóu bèn',棍子:'gùn zi',含糊:'hán hu',少妇:'shào fù',兴致:'xìng zhì',纳闷:'nà mèn',干流:'gàn liú',卷起:'juǎn qǐ',扇子:'shàn zi',更改:'gēng gǎi',笼络:'lǒng luò',喇叭:'lǎ ba',载荷:'zài hè',妥当:'tuǒ dàng',为难:'wéi nán',着陆:'zhuó lù',燕子:'yàn zi',干吗:'gàn má',白发:'bái fà',总得:'zǒng děi',夹击:'jiā jī',曝光:'bào guāng',曲调:'qǔ diào',相机:'xiàng jī',叫化:'jiào huà',角逐:'jué zhú',啊哟:'ā yō',载重:'zài zhòng',长辈:'zhǎng bèi',出差:'chū chāi',垛口:'duǒ kǒu',撇开:'piē kāi',厅长:'tīng zhǎng',组分:'zǔ fèn',误差:'wù chā',家当:'jiā dàng',传记:'zhuàn jì',个子:'gè zi',铺设:'pū shè',干事:'gàn shì',杆菌:'gǎn jūn',定量:'dìng liàng',运载:'yùn zài',会儿:'huì er',酋长:'qiú zhǎng',重返:'chóng fǎn',差额:'chā é',露面:'lòu miàn',钻研:'zuān yán',大城:'dài chéng',上当:'shàng dàng',销量:'xiāo liàng',作坊:'zuō fang',照相:'zhào xiàng',哎呀:'āi yā',调集:'diào jí',看中:'kàn zhòng',议长:'yì zhǎng',风筝:'fēng zheng',辟邪:'bì xié',空隙:'kòng xì',更迭:'gēng dié',偏差:'piān chā',声调:'shēng diào',适量:'shì liàng',屯子:'tún zi',无量:'wú liàng',空地:'kòng dì',调度:'diào dù',散射:'sǎn shè',创伤:'chuāng shāng',海参:'hǎi shēn',满载:'mǎn zài',重叠:'chóng dié',落差:'luò chā',单调:'dān diào',老将:'lǎo jiàng',人参:'rén shēn',间断:'jiàn duàn',重现:'chóng xiàn',夹杂:'jiā zá',调用:'diào yòng',萝卜:'luó bo',附着:'fù zhuó',应声:'yìng shēng',主将:'zhǔ jiàng',罪过:'zuì guo',咀嚼:'jǔ jué',为政:'wéi zhèng',过量:'guò liàng',乐曲:'yuè qǔ',负荷:'fù hè',枪弹:'qiāng dàn',悄然:'qiǎo rán',处方:'chǔ fāng',悄声:'qiǎo shēng',曲子:'qǔ zi',情调:'qíng diào',挑衅:'tiǎo xìn',代为:'dài wéi',了结:'liǎo jié',打中:'dǎ zhòng',酒吧:'jiǔ bā',懒得:'lǎn de',增量:'zēng liàng',衣着:'yī zhuó',部将:'bù jiàng',要塞:'yào sài',茶几:'chá jī',杠杆:'gàng gǎn',出没:'chū mò',鲜有:'xiǎn yǒu',间隙:'jiàn xì',重担:'zhòng dàn',重演:'chóng yǎn',重试:'chóng shì',应酬:'yìng chou',只当:'zhǐ dāng',毋宁:'wú nìng',包扎:'bāo zā',前头:'qián tou',卷烟:'juǎn yān',非得:'fēi děi',弹道:'dàn dào',杆子:'gān zi',门将:'mén jiàng',后头:'hòu tou',喝彩:'hè cǎi',暖和:'nuǎn huo',累积:'lěi jī',调遣:'diào qiǎn',倔强:'jué jiàng',宝藏:'bǎo zàng',丧事:'sāng shì',约莫:'yuē mo',纤夫:'qiàn fū',更替:'gēng tì',装载:'zhuāng zài',背包:'bēi bāo',帖子:'tiě zi',松散:'sōng sǎn',呼喝:'hū hè',可恶:'kě wù',自转:'zì zhuàn',供电:'gōng diàn',反省:'fǎn xǐng',坦率:'tǎn shuài',苏打:'sū dá',本分:'běn fèn',落得:'luò de',鄙薄:'bǐ bó',相间:'xiāng jiàn',单薄:'dān bó',混蛋:'hún dàn',贞观:'zhēn guān',附和:'fù hè',能耐:'néng nài',吓唬:'xià hu',未了:'wèi liǎo',引着:'yǐn zháo',抽调:'chōu diào',沙子:'shā zi',席卷:'xí juǎn',标的:'biāo dì',别扭:'biè niu',思量:'sī liang',喝采:'hè cǎi',论语:'lún yǔ',盖子:'gài zi',分外:'fèn wài',弄堂:'lòng táng',乐舞:'yuè wǔ',雨量:'yǔ liàng',毛发:'máo fà',差遣:'chāi qiǎn',背负:'bēi fù',转速:'zhuàn sù',声乐:'shēng yuè',夹攻:'jiā gōng',供水:'gōng shuǐ',主干:'zhǔ gàn',惩处:'chéng chǔ',长相:'zhǎng xiàng',公差:'gōng chāi',榴弹:'liú dàn',省得:'shěng de',条子:'tiáo zi',重围:'chóng wéi',阻塞:'zǔ sè',劲风:'jìng fēng',纠葛:'jiū gé',颠簸:'diān bǒ',点中:'diǎn zhòng',重创:'zhòng chuāng',姥姥:'lǎo lao',迷糊:'mí hu',公家:'gōng jia',几率:'jī lǜ',苦闷:'kǔ mèn',度量:'dù liàng',差错:'chā cuò',暑假:'shǔ jià',参差:'cēn cī',搭载:'dā zài',助长:'zhù zhǎng',相称:'xiāng chèn',红晕:'hóng yùn',舍命:'shě mìng',喜好:'xǐ hào',列传:'liè zhuàn',劲敌:'jìng dí',蛤蟆:'há ma',请假:'qǐng jià',钉子:'dīng zi',沉没:'chén mò',高丽:'gāo lí',休假:'xiū jià',无为:'wú wéi',巴结:'bā jie',了得:'liǎo dé',变相:'biàn xiàng',核弹:'hé dàn',亲家:'qìng jia',承载:'chéng zài',喝问:'hè wèn',还击:'huán jī',交还:'jiāo huán',将令:'jiàng lìng',单于:'chán yú',空缺:'kòng quē',绿林:'lù lín',胆量:'dǎn liàng',执着:'zhí zhuó',低调:'dī diào',闭塞:'bì sè',轻薄:'qīng bó',得当:'dé dàng',占卜:'zhān bǔ',扫帚:'sào zhou',龟兹:'qiū cí',年长:'nián zhǎng',外传:'wài zhuàn',头子:'tóu zi',裁缝:'cái feng',礼乐:'lǐ yuè',血泊:'xuè pō',散乱:'sǎn luàn',动量:'dòng liàng',倒腾:'dǎo teng',取舍:'qǔ shě',咱家:'zán jiā',长发:'cháng fà',爪哇:'zhǎo wā',弹壳:'dàn ké',省悟:'xǐng wù',嚷嚷:'rāng rang',连累:'lián lèi',应得:'yīng dé',族长:'zú zhǎng',柜子:'guì zi',擂鼓:'léi gǔ',眩晕:'xuàn yùn',调配:'tiáo pèi',躯干:'qū gàn',差役:'chāi yì',坎坷:'kǎn kě',少儿:'shào ér',乐团:'yuè tuán',养分:'yǎng fèn',退还:'tuì huán',格调:'gé diào',语调:'yǔ diào',音调:'yīn diào',乐府:'yuè fǔ',古朴:'gǔ pǔ',打点:'dǎ diǎn',差使:'chāi shǐ',匀称:'yún chèn',瘦削:'shòu xuē',膏药:'gāo yao',吞没:'tūn mò',调任:'diào rèn',散居:'sǎn jū',上头:'shàng tóu',风靡:'fēng mǐ',放假:'fàng jià',估量:'gū liang',失当:'shī dàng',中弹:'zhòng dàn',妄为:'wàng wéi',长者:'zhǎng zhě',起哄:'qǐ hòng',末了:'mò liǎo',相声:'xiàng sheng',校正:'jiào zhèng',劝降:'quàn xiáng',矢量:'shǐ liàng',沉闷:'chén mèn',给与:'jǐ yǔ',解法:'jiě fǎ',塞外:'sài wài',将校:'jiàng xiào',嗜好:'shì hào',没落:'mò luò',朴刀:'pō dāo',片子:'piān zi',切削:'qiē xiāo',弹丸:'dàn wán',稀薄:'xī bó',亏得:'kuī dé',间歇:'jiàn xiē',翘首:'qiáo shǒu',色调:'sè diào',处决:'chǔ jué',表率:'biǎo shuài',尺子:'chǐ zi',招降:'zhāo xiáng',称职:'chèn zhí',斗篷:'dǒu peng',铺子:'pù zi',底子:'dǐ zi',负载:'fù zài',干警:'gàn jǐng',倒数:'dào shǔ',将官:'jiàng guān',锄头:'chú tou',归降:'guī xiáng',疟疾:'nüè ji',唠叨:'láo dao',限量:'xiàn liàng',屏息:'bǐng xī',重逢:'chóng féng',器乐:'qì yuè',氢弹:'qīng dàn',脖颈:'bó gěng',妃子:'fēi zi',处事:'chǔ shì',参量:'cān liàng',轻率:'qīng shuài',缥缈:'piāo miǎo',中奖:'zhòng jiǎng',才干:'cái gàn',施舍:'shī shě',卷子:'juàn zi',游说:'yóu shuì',巷子:'xiàng zi',膀胱:'páng guāng',切勿:'qiè wù',看管:'kān guǎn',风头:'fēng tou',精干:'jīng gàn',高差:'gāo chā',恐吓:'kǒng hè',扁担:'biǎn dàn',给养:'jǐ yǎng',格子:'gé zi',供需:'gōng xū',反差:'fǎn chā',飞弹:'fēi dàn',微薄:'wēi bó',发型:'fà xíng',即兴:'jí xìng',攒动:'cuán dòng',间或:'jiàn huò',浅薄:'qiǎn bó',乐章:'yuè zhāng',顺差:'shùn chā',调子:'diào zi',相位:'xiàng wèi',转子:'zhuàn zǐ',劲旅:'jìng lǚ',咔嚓:'kā chā',了事:'liǎo shì',转悠:'zhuàn you',当铺:'dàng pù',爪子:'zhuǎ zi',单子:'dān zi',好战:'hào zhàn',燕麦:'yàn mài',只许:'zhǐ xǔ',干练:'gàn liàn',女将:'nǚ jiàng',酒量:'jiǔ liàng',划船:'huá chuán',伎俩:'jì liǎng',挑拨:'tiǎo bō',少校:'shào xiào',着落:'zhuó luò',憎恶:'zēng wù',刻薄:'kè bó',要挟:'yāo xié',用处:'yòng chu',还手:'huán shǒu',模具:'mú jù',执著:'zhí zhuó',喝令:'hè lìng',保长:'bǎo zhǎng',吸着:'xī zhe',症结:'zhēng jié',公转:'gōng zhuàn',校勘:'jiào kān',重提:'chóng tí',扫兴:'sǎo xìng',铺盖:'pū gài',长史:'zhǎng shǐ',差价:'chā jià',压根:'yà gēn',怔住:'zhèng zhù',应允:'yīng yǔn',切入:'qiē rù',战将:'zhàn jiàng',年少:'nián shào',舍身:'shě shēn',执拗:'zhí niù',处世:'chǔ shì',中风:'zhòng fēng',等量:'děng liàng',放量:'fàng liàng',腔调:'qiāng diào',老少:'lǎo shào',没入:'mò rù',瓜葛:'guā gé',将帅:'jiàng shuài',车载:'chē zài',窝囊:'wō nang',长进:'zhǎng jìn',可汗:'kè hán',并州:'bīng zhōu',供销:'gōng xiāo',切片:'qiē piàn',差事:'chāi shì',知会:'zhī hui',鹰爪:'yīng zhǎo',处女:'chǔ nǚ',切磋:'qiē cuō',日头:'rì tou',押解:'yā jiè',滋长:'zī zhǎng',道观:'dào guàn',脚色:'jué sè',当量:'dāng liàng',婆家:'pó jia',缘分:'yuán fèn',空闲:'kòng xián',好色:'hào sè',怒喝:'nù hè',笼统:'lǒng tǒng',边塞:'biān sài',何曾:'hé céng',重合:'chóng hé',零散:'líng sǎn',轰隆:'hōng lōng',化子:'huà zi',内蒙:'nèi měng',数落:'shǔ luò',逆差:'nì chā',牟利:'móu lì',栅栏:'zhà lan',中标:'zhòng biāo',调档:'diào dàng',佝偻:'gōu lóu',场子:'chǎng zi',甲壳:'jiǎ qiào',重温:'chóng wēn',炮制:'páo zhì',返还:'fǎn huán',自传:'zì zhuàn',高调:'gāo diào',殷红:'yān hóng',固着:'gù zhuó',强求:'qiǎng qiú',本相:'běn xiàng',骄横:'jiāo hèng',草率:'cǎo shuài',气闷:'qì mèn',着色:'zhuó sè',宁肯:'nìng kěn',兴头:'xìng tou',拘泥:'jū nì',夹角:'jiā jiǎo',发髻:'fà jì',猛将:'měng jiàng',约摸:'yuē mo',拖累:'tuō lěi',呢绒:'ní róng',钻探:'zuān tàn',夹层:'jiā céng',落魄:'luò pò',巷道:'hàng dào',运量:'yùn liàng',解闷:'jiě mèn',空儿:'kòng er',估摸:'gū mo',好客:'hào kè',钻孔:'zuān kǒng',糊弄:'hù nòng',荥阳:'xíng yáng',烦闷:'fán mèn',仓卒:'cāng cù',分叉:'fēn chà',厂子:'chǎng zi',小调:'xiǎo diào',少阳:'shào yáng',受降:'shòu xiáng',染坊:'rǎn fáng',胳臂:'gē bei',将门:'jiàng mén',模板:'mú bǎn',配给:'pèi jǐ',为伍:'wéi wǔ',跟头:'gēn tou',划算:'huá suàn',累赘:'léi zhui',哄笑:'hōng xiào',晕眩:'yūn xuàn',干掉:'gàn diào',缝制:'féng zhì',难处:'nán chù',着意:'zhuó yì',蛮横:'mán hèng',奇数:'jī shù',短发:'duǎn fà',生还:'shēng huán',还清:'huán qīng',看护:'kān hù',直率:'zhí shuài',奏乐:'zòu yuè',载客:'zài kè',专横:'zhuān hèng',湮没:'yān mò',空格:'kòng gé',铺垫:'pū diàn',良将:'liáng jiàng',哗啦:'huā lā',散漫:'sǎn màn',脱发:'tuō fà',送还:'sòng huán',埋没:'mái mò',累及:'lěi jí',薄雾:'bó wù',调离:'diào lí',舌苔:'shé tāi',机长:'jī zhǎng',栓塞:'shuān sè',配角:'pèi jué',切口:'qiē kǒu',创口:'chuāng kǒu',哈欠:'hā qian',实弹:'shí dàn',铺平:'pū píng',哈达:'hǎ dá',懒散:'lǎn sǎn',实干:'shí gàn',填空:'tián kòng',刁钻:'diāo zuān',乐师:'yuè shī',量变:'liàng biàn',诱降:'yòu xiáng',搪塞:'táng sè',征调:'zhēng diào',夹道:'jiā dào',干咳:'gān ké',止咳:'zhǐ ké',乐工:'yuè gōng',划过:'huá guò',着火:'zháo huǒ',更正:'gēng zhèng',给付:'jǐ fù',空子:'kòng zi',哪吒:'né zhā',正着:'zhèng zháo',刷子:'shuā zi',丧葬:'sāng zàng',夹带:'jiā dài',安分:'ān fèn',中意:'zhòng yì',长孙:'zhǎng sūn',校订:'jiào dìng',卷曲:'juǎn qū',载运:'zài yùn',投弹:'tóu dàn',柞蚕:'zuò cán',份量:'fèn liàng',调换:'diào huàn',了然:'liǎo rán',咧嘴:'liě zuǐ',典当:'diǎn dàng',寒假:'hán jià',长兄:'zhǎng xiōng',给水:'jǐ shuǐ',须发:'xū fà',枝干:'zhī gàn',属相:'shǔ xiàng',哄抢:'hōng qiǎng',刻划:'kè huà',塞子:'sāi zi',单干:'dān gàn',还乡:'huán xiāng',兆头:'zhào tou',寺观:'sì guàn',督率:'dū shuài',啊哈:'ā ha',割舍:'gē shě',抹布:'mā bù',好恶:'hào wù',下处:'xià chǔ',消长:'xiāo zhǎng',离间:'lí jiàn',准头:'zhǔn tou',校对:'jiào duì',什物:'shí wù',番禺:'pān yú',佛爷:'fó ye',吗啡:'mǎ fēi',盐分:'yán fèn',虎将:'hǔ jiàng',薄荷:'bò he',独处:'dú chǔ',空位:'kòng wèi',铺路:'pū lù',乌拉:'wū lā',调回:'diào huí',来头:'lái tou',闲散:'xián sǎn',胶卷:'jiāo juǎn',冒失:'mào shi',干劲:'gàn jìn',弦乐:'xián yuè',相国:'xiàng guó',丹参:'dān shēn',助兴:'zhù xìng',铺开:'pū kāi',次长:'cì zhǎng',发卡:'fà qiǎ',拮据:'jié jū',刹车:'shā chē',生发:'shēng fà',重播:'chóng bō',缝合:'féng hé',音量:'yīn liàng',少尉:'shào wèi',冲压:'chòng yā',苍劲:'cāng jìng',厚薄:'hòu báo',威吓:'wēi hè',外相:'wài xiàng',呼号:'hū háo',着迷:'zháo mí',挑担:'tiāo dàn',纹路:'wén lù',还俗:'huán sú',强横:'qiáng hèng',着数:'zhāo shù',降顺:'xiáng shùn',挑明:'tiǎo míng',眯缝:'mī feng',分内:'fèn nèi',更衣:'gēng yī',软和:'ruǎn huo',尽兴:'jìn xìng',号子:'hào zi',爪牙:'zhǎo yá',败将:'bài jiàng',猜中:'cāi zhòng',结扎:'jié zā',没空:'méi kòng',夹缝:'jiā fèng',拾掇:'shí duo',掺和:'chān huo',簸箕:'bò ji',电量:'diàn liàng',荷载:'hè zǎi',调式:'diào shì',处身:'chǔ shēn',打手:'dǎ shǒu',弹弓:'dàn gōng',横蛮:'hèng mán',能干:'néng gàn',校点:'jiào diǎn',加载:'jiā zài',干校:'gàn xiào',哄传:'hōng chuán',校注:'jiào zhù',淤塞:'yū sè',马扎:'mǎ zhá',月氏:'yuè zhī',高干:'gāo gàn',经传:'jīng zhuàn',曾孙:'zēng sūn',好斗:'hào dòu',关卡:'guān qiǎ',逃奔:'táo bèn',磨蹭:'mó ceng',牟取:'móu qǔ',颤栗:'zhàn lì',蚂蚱:'mà zha',撮合:'cuō he',趔趄:'liè qie',摔打:'shuāi dǎ',台子:'tái zi',分得:'fēn de',粘着:'nián zhuó',采邑:'cài yì',散装:'sǎn zhuāng',婀娜:'ē nuó',兴味:'xìng wèi',行头:'xíng tou',气量:'qì liàng',调运:'diào yùn',处治:'chǔ zhì',乐音:'yuè yīn',充塞:'chōng sè',恫吓:'dòng hè',论调:'lùn diào',相中:'xiāng zhòng',民乐:'mín yuè',炮仗:'pào zhang',丧服:'sāng fú',骁将:'xiāo jiàng',量刑:'liàng xíng',缝补:'féng bǔ',财会:'cái kuài',大干:'dà gàn',历数:'lì shǔ',校场:'jiào chǎng',塞北:'sài běi',识相:'shí xiàng',辱没:'rǔ mò',鲜亮:'xiān liàng',语塞:'yǔ sè',露脸:'lòu liǎn',凉快:'liáng kuai',腰杆:'yāo gǎn',溜达:'liū da',嘎嘎:'gā gā',公干:'gōng gàn',桔梗:'jié gěng',挑逗:'tiǎo dòu',看门:'kān mén',乐歌:'yuè gē',拓片:'tà piàn',挑动:'tiǎo dòng',准将:'zhǔn jiàng',遒劲:'qiú jìng',磨坊:'mò fáng',逶迤:'wēi yí',搅和:'jiǎo huo',摩挲:'mó suō',作弄:'zuò nòng',苗头:'miáo tou',打颤:'dǎ zhàn',大藏:'dà zàng',畜牲:'chù shēng',勾搭:'gōu da',树荫:'shù yīn',树杈:'shù chà',铁杆:'tiě gǎn',将相:'jiàng xiàng',份子:'fèn zi',视差:'shì chā',绿荫:'lǜ yīn',枪杆:'qiāng gǎn',缝纫:'féng rèn',愁闷:'chóu mèn',点将:'diǎn jiàng',华佗:'huà tuó',劲射:'jìng shè',箱笼:'xiāng lǒng',终了:'zhōng liǎo',鬓发:'bìn fà',结巴:'jiē ba',苦干:'kǔ gàn',看家:'kān jiā',正旦:'zhēng dàn',中肯:'zhòng kěn',厦门:'xià mén',东莞:'dōng guǎn',食量:'shí liàng',宫调:'gōng diào',间作:'jiàn zuò',弹片:'dàn piàn',差池:'chā chí',漂白:'piǎo bái',杠子:'gàng zi',调处:'tiáo chǔ',好动:'hào dòng',转炉:'zhuàn lú',屏气:'bǐng qì',夹板:'jiā bǎn',哀乐:'āi yuè',干道:'gàn dào',苦处:'kǔ chù',劈柴:'pǐ chái',长势:'zhǎng shì',天华:'tiān huá',共处:'gòng chǔ',校验:'jiào yàn',出塞:'chū sài',磨盘:'mò pán',萎靡:'wěi mǐ',奔丧:'bēn sāng',唱和:'chàng hè',大调:'dà diào',非分:'fēi fèn',钻营:'zuān yíng',夹子:'jiā zi',超载:'chāo zài',更始:'gēng shǐ',铃铛:'líng dang',披散:'pī sàn',发还:'fā huán',转轮:'zhuàn lún',横财:'hèng cái',泡桐:'pāo tóng',抛撒:'pāo sǎ',天呀:'tiān yā',糊糊:'hū hu',躯壳:'qū qiào',通量:'tōng liàng',奉还:'fèng huán',午觉:'wǔ jiào',闷棍:'mèn gùn',浪头:'làng tou',砚台:'yàn tái',油坊:'yóu fáng',学长:'xué zhǎng',过载:'guò zài',笔调:'bǐ diào',衣被:'yī bèi',畜产:'xù chǎn',调阅:'diào yuè',蛮干:'mán gàn',曾祖:'zēng zǔ',提干:'tí gàn',变调:'biàn diào',覆没:'fù mò',模子:'mú zi',乐律:'yuè lǜ',称心:'chèn xīn',木杆:'mù gān',重印:'chóng yìn',自省:'zì xǐng',提调:'tí diào',看相:'kàn xiàng',芋头:'yù tou',下切:'xià qiē',塞上:'sài shàng',铺张:'pū zhāng',藤蔓:'téng wàn',薄幸:'bó xìng',解数:'xiè shù',褪去:'tuì qù',霰弹:'xiàn dàn',柚木:'yóu mù',痕量:'hén liàng',雅乐:'yǎ yuè',号哭:'háo kū',诈降:'zhà xiáng',猪圈:'zhū juàn',咋舌:'zé shé',铣床:'xǐ chuáng',防弹:'fáng dàn',健将:'jiàn jiàng',丽水:'lí shuǐ',削发:'xuē fà',空当:'kòng dāng',多相:'duō xiàng',鲜见:'xiǎn jiàn',划桨:'huá jiǎng',载波:'zài bō',跳蚤:'tiào zao',俏皮:'qiào pí',吧嗒:'bā dā',结发:'jié fà',了断:'liǎo duàn',同调:'tóng diào',石磨:'shí mò',时差:'shí chā',鼻塞:'bí sè',挑子:'tiāo zi',推磨:'tuī mò',武侯:'wǔ hóu',抹煞:'mǒ shā',调转:'diào zhuǎn',籍没:'jí mò',还债:'huán zhài',调演:'diào yǎn',分划:'fēn huá',奇偶:'jī ǒu',断喝:'duàn hè',闷雷:'mèn léi',狼藉:'láng jí',饭量:'fàn liàng',还礼:'huán lǐ',转调:'zhuǎn diào',星相:'xīng xiàng',手相:'shǒu xiàng',配乐:'pèi yuè',盖头:'gài tou',连杆:'lián gǎn',簿记:'bù jì',刀把:'dāo bà',量词:'liàng cí',名角:'míng jué',步调:'bù diào',校本:'jiào běn',账簿:'zhàng bù',隽永:'juàn yǒng',稍为:'shāo wéi',易传:'yì zhuàn',乐谱:'yuè pǔ',牵累:'qiān lěi',答理:'dā li',喝斥:'hè chì',吟哦:'yín é',干渠:'gàn qú',海量:'hǎi liàng',精当:'jīng dàng',着床:'zhuó chuáng',月相:'yuè xiàng',庶几:'shù jī',宫观:'gōng guàn',论处:'lùn chǔ',征辟:'zhēng bì',厚朴:'hòu pò',介壳:'jiè qiào',吭哧:'kēng chī',咯血:'kǎ xiě',铺陈:'pū chén',重生:'chóng shēng',乐理:'yuè lǐ',哀号:'āi háo',藏历:'zàng lì',刚劲:'gāng jìng',削平:'xuē píng',浓荫:'nóng yīn',城垛:'chéng duǒ',当差:'dāng chāi',正传:'zhèng zhuàn',并处:'bìng chǔ',创面:'chuāng miàn',旦角:'dàn jué',薄礼:'bó lǐ',晃荡:'huàng dang',臊子:'sào zi',家什:'jiā shí',闷头:'mēn tóu',美发:'měi fà',度数:'dù shu',着凉:'zháo liáng',闯将:'chuǎng jiàng',几案:'jī àn',姘头:'pīn tou',差数:'chā shù',散碎:'sǎn suì',壅塞:'yōng sè',寒颤:'hán zhàn',牵强:'qiān qiǎng',无间:'wú jiàn',轮转:'lún zhuàn',号叫:'háo jiào',铺排:'pū pái',降伏:'xiáng fú',轧钢:'zhá gāng',东阿:'dōng ē',病假:'bìng jià',累加:'lěi jiā',梗塞:'gěng sè',弹夹:'dàn jiā',钻心:'zuān xīn',晃眼:'huǎng yǎn',魔爪:'mó zhǎo',标量:'biāo liàng',憋闷:'biē mèn',猜度:'cāi duó',处士:'chǔ shì',官差:'guān chāi',讨还:'tǎo huán',长门:'cháng mén',馏分:'liú fēn',里弄:'lǐ lòng',色相:'sè xiàng',雅兴:'yǎ xìng',角力:'jué lì',弹坑:'dàn kēng',枝杈:'zhī chà',夹具:'jiā jù',处刑:'chǔ xíng',悍将:'hàn jiàng',好学:'hào xué',好好:'hǎo hǎo',银发:'yín fà',扫把:'sào bǎ',法相:'fǎ xiàng',贵干:'guì gàn',供气:'gōng qì',空余:'kòng yú',捆扎:'kǔn zā',瘠薄:'jí bó',浆糊:'jiàng hu',嘎吱:'gā zhī',调令:'diào lìng',法帖:'fǎ tiè',淋病:'lìn bìng',调派:'diào pài',转盘:'zhuàn pán',供稿:'gōng gǎo',差官:'chāi guān',忧闷:'yōu mèn',教长:'jiào zhǎng',重唱:'chóng chàng',酒兴:'jiǔ xìng',乐坛:'yuè tán',花呢:'huā ní',叱喝:'chì hè',膀臂:'bǎng bì',得空:'dé kòng',转圈:'zhuàn quān',横暴:'hèng bào',哄抬:'hōng tái',引吭:'yǐn háng',载货:'zài huò',中计:'zhòng jì',官长:'guān zhǎng',相面:'xiàng miàn',看头:'kàn tou',盼头:'pàn tou',意兴:'yì xìng',军乐:'jūn yuè',累次:'lěi cì',骨嘟:'gǔ dū',燕赵:'yān zhào',报丧:'bào sāng',弥撒:'mí sa',挨斗:'ái dòu',扁舟:'piān zhōu',丑角:'chǒu jué',吊丧:'diào sāng',强将:'qiáng jiàng',重奏:'chóng zòu',发辫:'fà biàn',着魔:'zháo mó',着法:'zhāo fǎ',盛放:'shèng fàng',填塞:'tián sè',凶横:'xiōng hèng',稽首:'qǐ shǒu',碑帖:'bēi tiè',冲量:'chōng liàng',发菜:'fà cài',假发:'jiǎ fà',翻卷:'fān juǎn',小量:'xiǎo liàng',胶着:'jiāo zhuó',里子:'lǐ zi',调调:'diào diao',散兵:'sǎn bīng',高挑:'gāo tiǎo',播撒:'bō sǎ',夹心:'jiā xīn',扇动:'shān dòng',叨扰:'tāo rǎo',霓裳:'ní cháng',捻子:'niǎn zi',弥缝:'mí féng',撒布:'sǎ bù',场院:'cháng yuàn',省亲:'xǐng qīn',提拉:'tí lā',惯量:'guàn liàng',强逼:'qiáng bī',强征:'qiáng zhēng',晕车:'yùn chē',数道:'shù dào',带累:'dài lèi',拓本:'tà běn',嫌恶:'xián wù',宿将:'sù jiàng',龟裂:'jūn liè',缠夹:'chán jiā',发式:'fà shì',隔扇:'gé shàn',天分:'tiān fèn',癖好:'pǐ hào',四通:'sì tōng',白术:'bái zhú',划伤:'huá shāng',角斗:'jué dòu',听差:'tīng chāi',岁差:'suì chā',丧礼:'sāng lǐ',脉脉:'mò mò',削瘦:'xuē shòu',撒播:'sǎ bō',莎草:'suō cǎo',犍为:'qián wéi',调头:'diào tóu',龙卷:'lóng juǎn',外调:'wài diào',字帖:'zì tiè',卷发:'juǎn fà',揣度:'chuǎi duó',洋相:'yáng xiàng',散光:'sǎn guāng',骨碌:'gū lu',薄命:'bó mìng',笼头:'lóng tóu',咽炎:'yān yán',碌碡:'liù zhou',片儿:'piàn er',纤手:'qiàn shǒu',散体:'sǎn tǐ',内省:'nèi xǐng',强留:'qiáng liú',解送:'jiè sòng',反间:'fǎn jiàn',少壮:'shào zhuàng',留空:'liú kōng',告假:'gào jià',咳血:'ké xuè',薄暮:'bó mù',铺轨:'pū guǐ',磨削:'mó xuē',治丧:'zhì sāng',叉子:'chā zi',哄动:'hōng dòng',蛾子:'é zi',出落:'chū luò',股长:'gǔ zhǎng',贵处:'guì chù',还魂:'huán hún',例假:'lì jià',刹住:'shā zhù',身量:'shēn liàng',同好:'tóng hào',模量:'mó liàng',更生:'gēng shēng',服丧:'fú sāng',率直:'shuài zhí',字模:'zì mú',散架:'sǎn jià',答腔:'dā qiāng',交恶:'jiāo wù',薄情:'bó qíng',眼泡:'yǎn pāo',袅娜:'niǎo nuó',草垛:'cǎo duò',冲劲:'chòng jìn',呢喃:'ní nán',切中:'qiè zhòng',挑灯:'tiǎo dēng',还愿:'huán yuàn',激将:'jī jiàng',更鼓:'gēng gǔ',没药:'mò yào',败兴:'bài xìng',切面:'qiē miàn',散户:'sǎn hù',累进:'lěi jìn',背带:'bēi dài',秤杆:'chèng gǎn',碾坊:'niǎn fáng',簿子:'bù zi',扳手:'bān shǒu',铅山:'yán shān',儒将:'rú jiàng',重光:'chóng guāng',剪发:'jiǎn fà',长上:'zhǎng shàng',小传:'xiǎo zhuàn',压轴:'yā zhòu',弱冠:'ruò guàn',花卷:'huā juǎn',横祸:'hèng huò',夹克:'jiā kè',光晕:'guāng yùn',披靡:'pī mǐ',对调:'duì diào',夹持:'jiā chí',空额:'kòng é',平调:'píng diào',铺床:'pū chuáng',丧钟:'sāng zhōng',作乐:'zuò lè',少府:'shào fǔ',数数:'shuò shuò',奔头:'bèn tou',进给:'jìn jǐ',率性:'shuài xìng',乐子:'lè zi',绑扎:'bǎng zā',挑唆:'tiǎo suō',漂洗:'piǎo xǐ',夹墙:'jiā qiáng',咳喘:'ké chuǎn',乜斜:'miē xie',错处:'cuò chù',闷酒:'mèn jiǔ',时调:'shí diào',重孙:'chóng sūn',经幢:'jīng chuáng',圩场:'xū chǎng',调门:'diào mén',花头:'huā tóu',划拉:'huá la',套色:'tào shǎi',粗率:'cū shuài',相率:'xiāng shuài',款识:'kuǎn zhì',吁请:'yù qǐng',荫蔽:'yīn bì',文蛤:'wén gé',嘀嗒:'dī dā',调取:'diào qǔ',交差:'jiāo chāi',落子:'luò zǐ',相册:'xiàng cè',絮叨:'xù dao',落发:'luò fà',异相:'yì xiàng',浸没:'jìn mò',角抵:'jué dǐ',卸载:'xiè zài',春卷:'chūn juǎn',扎挣:'zhá zheng',畜养:'xù yǎng',吡咯:'bǐ luò',垛子:'duò zi',恶少:'è shào',发际:'fà jì',红苕:'hóng sháo',糨糊:'jiàng hu',哭丧:'kū sāng',稍息:'shào xī',晕船:'yùn chuán',校样:'jiào yàng',外差:'wài chā',脚爪:'jiǎo zhǎo',铺展:'pū zhǎn',芫荽:'yán sui',夹紧:'jiā jǐn',尿泡:'suī pào',丧乱:'sāng luàn',凶相:'xiōng xiàng',华发:'huá fà',打场:'dǎ cháng',云量:'yún liàng',正切:'zhèng qiē',划拳:'huá quán',划艇:'huá tǐng',评传:'píng zhuàn',拉纤:'lā qiàn',句读:'jù dòu',散剂:'sǎn jì',骨殖:'gǔ shi',塞音:'sè yīn',铺叙:'pū xù',阏氏:'yān zhī',冷颤:'lěng zhàn',煞住:'shā zhù',少男:'shào nán',管乐:'guǎn yuè',号啕:'háo táo',纳降:'nà xiáng',拥塞:'yōng sè',万乘:'wàn shèng',杆儿:'gǎn ér',葛藤:'gé téng',簿籍:'bù jí',皮夹:'pí jiā',校准:'jiào zhǔn',允当:'yǔn dàng',器量:'qì liàng',选调:'xuǎn diào',扮相:'bàn xiàng',干才:'gàn cái',基干:'jī gàn',割切:'gē qiē',国乐:'guó yuè',卡壳:'qiǎ ké',辟谷:'bì gǔ',磨房:'mò fáng',咿呀:'yī yā',芥末:'jiè mo',薄技:'bó jì',产假:'chǎn jià',诗兴:'shī xìng',重出:'chóng chū',转椅:'zhuàn yǐ',酌量:'zhuó liang',簿册:'bù cè',藏青:'zàng qīng',的士:'dī shì',调人:'diào rén',解元:'jiè yuán',茎干:'jīng gàn',巨量:'jù liàng',榔头:'láng tou',率真:'shuài zhēn',喷香:'pèn xiāng',锁钥:'suǒ yuè',虾蟆:'há má',相图:'xiàng tú',兴会:'xìng huì',灶头:'zào tóu',重婚:'chóng hūn',钻洞:'zuān dòng',忖度:'cǔn duó',党参:'dǎng shēn',调温:'diào wēn',杆塔:'gān tǎ',葛布:'gé bù',拱券:'gǒng xuàn',夹生:'jiā shēng',露馅:'lòu xiàn',恰切:'qià qiè',散见:'sǎn jiàn',哨卡:'shào qiǎ',烫发:'tàng fà',体量:'tǐ liàng',挺括:'tǐng kuò',系带:'jì dài',相士:'xiàng shì',羊圈:'yáng juàn',转矩:'zhuàn jǔ',吧台:'bā tái',苍术:'cāng zhú',菲薄:'fěi bó',蛤蚧:'gé jiè',蛤蜊:'gé lí',瓜蔓:'guā wàn',怪相:'guài xiàng',临帖:'lín tiè',女红:'nǚ gōng',刨床:'bào chuáng',翘楚:'qiáo chǔ',数九:'shǔ jiǔ',谈兴:'tán xìng',雄劲:'xióng jìng',扎染:'zā rǎn',遮荫:'zhē yīn',周正:'zhōu zhèng',赚头:'zhuàn tou',扒手:'pá shǒu',搀和:'chān huo',诚朴:'chéng pǔ',肚量:'dù liàng',干结:'gān jié',工尺:'gōng chě',家累:'jiā lěi',曲水:'qū shuǐ',沙参:'shā shēn',挑花:'tiǎo huā',阿门:'ā mén',背篓:'bēi lǒu',瘪三:'biē sān',裁处:'cái chǔ',创痛:'chuāng tòng',福相:'fú xiàng',更动:'gēng dòng',豪兴:'háo xìng',还阳:'huán yáng',还嘴:'huán zuǐ',借调:'jiè diào',卷云:'juǎn yún',流弹:'liú dàn',想头:'xiǎng tou',削价:'xuē jià',校阅:'jiào yuè',雅量:'yǎ liàng',别传:'bié zhuàn',薄酒:'bó jiǔ',春假:'chūn jià',发妻:'fà qī',哗哗:'huā huā',宽绰:'kuān chuo',了悟:'liǎo wù',切花:'qiē huā',审度:'shěn duó',应许:'yīng xǔ',转台:'zhuàn tái',仔猪:'zǐ zhū',裁量:'cái liáng',藏戏:'zàng xì',乘兴:'chéng xìng',绸缪:'chóu móu',摧折:'cuī zhé',调经:'tiáo jīng',调职:'diào zhí',缝缀:'féng zhuì',骨朵:'gū duǒ',核儿:'hú er',恒量:'héng liàng',还价:'huán jià',浑朴:'hún pǔ',苦差:'kǔ chāi',面糊:'miàn hù',煞车:'shā chē',省视:'xǐng shì',什锦:'shí jǐn',信差:'xìn chāi',余切:'yú qiē',攒眉:'cuán méi',炸糕:'zhá gāo',钻杆:'zuàn gǎn',扒灰:'pá huī',拌和:'bàn huò',长调:'cháng diào',大溜:'dà liù',抖搂:'dǒu lōu',飞转:'fēi zhuàn',干仗:'gàn zhàng',好胜:'hào shèng',画片:'huà piàn',搅混:'jiǎo hún',螺杆:'luó gǎn',木模:'mù mú',怒号:'nù háo',频数:'pín shù',无宁:'wú níng',遗少:'yí shào',邮差:'yóu chāi',占卦:'zhān guà',占星:'zhān xīng',重审:'chóng shěn',自量:'zì liàng',调防:'diào fáng',发廊:'fà láng',反调:'fǎn diào',缝子:'fèng zi',更夫:'gēng fū',骨子:'gǔ zi',光杆:'guāng gǎn',夹棍:'jiā gùn',居丧:'jū sāng',巨贾:'jù gǔ',看押:'kān yā',空转:'kōng zhuàn',量力:'liàng lì',炮烙:'páo luò',赔还:'péi huán',扑扇:'pū shān',散记:'sǎn jì',散件:'sǎn jiàn',删削:'shān xuē',射干:'shè gàn',条几:'tiáo jī',偷空:'tōu kòng',削壁:'xuē bì',校核:'jiào hé',阴干:'yīn gān',择菜:'zhái cài',重九:'chóng jiǔ',主调:'zhǔ diào',自禁:'zì jīn',吧唧:'bā jī',便溺:'biàn niào',词调:'cí diào',叨咕:'dáo gu',落枕:'lào zhěn',铺砌:'pū qì',刷白:'shuà bái',委靡:'wěi mǐ',系泊:'xì bó',相马:'xiàng mǎ',熨帖:'yù tiē',转筋:'zhuàn jīn',棒喝:'bàng hè',傧相:'bīn xiàng',镐头:'gǎo tóu',间苗:'jiàn miáo',乐池:'yuè chí',卖相:'mài xiàng',屏弃:'bǐng qì',铅弹:'qiān dàn',切变:'qiē biàn',请调:'qǐng diào',群氓:'qún méng',散板:'sǎn bǎn',省察:'xǐng chá',事假:'shì jià',纤绳:'qiàn shéng',重影:'chóng yǐng',耕种:'gēng zhòng',种地:'zhòng dì',种菜:'zhòng cài',栽种:'zāi zhòng',接种:'jiē zhòng',垦种:'kěn zhòng',种殖:'zhòng zhí',种瓜:'zhòng guā',种豆:'zhòng dòu',种树:'zhòng shù',睡着:'shuì zháo',笼子:'lóng zi',重启:'chóng qǐ',重整:'chóng zhěng',重弹:'chóng tán',重足:'chóng zú',重山:'chóng shān',重游:'chóng yóu',重峦:'chóng luán',爷爷:'yé ye',奶奶:'nǎi nai',姥爷:'lǎo ye',爸爸:'bà ba',妈妈:'mā ma',婶婶:'shěn shen',舅舅:'jiù jiu',姑姑:'gū gu',叔叔:'shū shu',姨夫:'yí fu',舅母:'jiù mu',姑父:'gū fu',姐夫:'jiě fu',婆婆:'pó po',公公:'gōng gong',舅子:'jiù zi',姐姐:'jiě jie',哥哥:'gē ge',妹妹:'mèi mei',妹夫:'mèi fu',姨子:'yí zi',宝宝:'bǎo bao',娃娃:'wá wa',孩子:'hái zi',日子:'rì zi',样子:'yàng zi',狮子:'shī zi',身子:'shēn zi',架子:'jià zi',嫂子:'sǎo zi',鼻子:'bí zi',亭子:'tíng zi',折子:'zhé zi',面子:'miàn zi',脖子:'bó zi',辈子:'bèi zi',帽子:'mào zi',拍子:'pāi zi',柱子:'zhù zi',辫子:'biàn zi',鸽子:'gē zi',房子:'fáng zi',丸子:'wán zi',摊子:'tān zi',牌子:'pái zi',胡子:'hú zi',鬼子:'guǐ zi',矮子:'ǎi zi',鸭子:'yā zi',小子:'xiǎo zi',影子:'yǐng zi',屋子:'wū zi',对子:'duì zi',点子:'diǎn zi',本子:'běn zi',种子:'zhǒng zi',儿子:'ér zi',兔子:'tù zi',骗子:'piàn zi',院子:'yuàn zi',猴子:'hóu zi',嗓子:'sǎng zi',侄子:'zhí zi',柿子:'shì zi',钳子:'qián zi',虱子:'shī zi',瓶子:'píng zi',豹子:'bào zi',筷子:'kuài zi',篮子:'lán zi',绳子:'shéng zi',嘴巴:'zuǐ ba',耳朵:'ěr duo',茄子:'qié zi',蚌埠:'bèng bù',崆峒:'kōng tóng',琵琶:'pí pa',蘑菇:'mó gu',葫芦:'hú lu',狐狸:'hú li',桔子:'jú zi',盒子:'hé zi',桌子:'zhuō zi',竹子:'zhú zi',师傅:'shī fu',衣服:'yī fu',袜子:'wà zi',杯子:'bēi zi',刺猬:'cì wei',麦子:'mài zi',队伍:'duì wu',知了:'zhī liǎo',鱼儿:'yú er',馄饨:'hún tun',灯笼:'dēng long',庄稼:'zhuāng jia',聪明:'cōng ming',镜子:'jìng zi',银子:'yín zi',盘子:'pán zi',了却:'liǎo què',力气:'lì qi',席子:'xí zi',林子:'lín zi',朝霞:'zhāo xiá',朝夕:'zhāo xī',朝气:'zhāo qì',翅膀:'chì bǎng',省长:'shěng zhǎng',臧否:'zāng pǐ',否泰:'pǐ tài',变得:'biàn de',丈夫:'zhàng fu',豆腐:'dòu fu',笔杆:'bǐ gǎn',枞阳:'zōng yáng',行人:'xíng rén',打着:'dǎ zhe',第一:'dì yī',万一:'wàn yī',之一:'zhī yī',得之:'dé zhī',统一:'tǒng yī',唯一:'wéi yī',专一:'zhuān yī',单一:'dān yī',如一:'rú yī',其一:'qí yī',合一:'hé yī',逐一:'zhú yī',周一:'zhōu yī',初一:'chū yī',研一:'yán yī',归一:'guī yī',假一:'jiǎ yī',闻一:'wén yī',了了:'liǎo liǎo',公了:'gōng liǎo',私了:'sī liǎo',一月:'yī yuè',一号:'yī hào',一级:'yī jí',一等:'yī děng',一哥:'yī gē',月一:'yuè yī',一一:'yī yī',二一:'èr yī',三一:'sān yī',四一:'sì yī',五一:'wǔ yī',六一:'liù yī',七一:'qī yī',八一:'bā yī',九一:'jiǔ yī',一〇:'yī líng',一零:'yī líng',一二:'yī èr',一三:'yī sān',一四:'yī sì',一五:'yī wǔ',一六:'yī liù',一七:'yī qī',一八:'yī bā',一九:'yī jiǔ',一又:'yī yòu',一饼:'yī bǐng',一楼:'yī lóu',为例:'wéi lì',为准:'wéi zhǔn',沧海:'cāng hǎi',难为:'nán wéi',责难:'zé nàn',患难:'huàn nàn',磨难:'mó nàn',大难:'dà nàn',刁难:'diāo nàn',殉难:'xùn nàn',落难:'luò nàn',罹难:'lí nàn',灾难:'zāi nàn',难民:'nàn mín',苦难:'kǔ nàn',危难:'wēi nàn',发难:'fā nàn',逃难:'táo nàn',避难:'bì nàn',遇难:'yù nàn',阻难:'zǔ nàn',厄难:'è nàn',徇难:'xùn nàn',空难:'kōng nàn',喜欢:'xǐ huan',朝朝:'zhāo zhāo',不行:'bù xíng',轧轧:'yà yà',弯曲:'wān qū',扭曲:'niǔ qū',曲直:'qū zhí',委曲:'wěi qū',酒曲:'jiǔ qū',曲径:'qū jìng',曲解:'qū jiě',歪曲:'wāi qū',曲线:'qū xiàn',曲阜:'qū fù',九曲:'jiǔ qū',曲折:'qū zhé',曲肱:'qū gōng',曲意:'qū yì',仡佬:'gē lǎo',};const Pattern2=Object.keys(DICT2).map((key)=>({zh:key,pinyin:DICT2[key],probability:2e-8,length:2,priority:Priority.Normal,dict:Symbol('dict2'),}));const DICT3={为什么:'wèi shén me',实际上:'shí jì shang',检察长:'jiǎn chá zhǎng',干什么:'gàn shén me',这会儿:'zhè huì er',尽可能:'jǐn kě néng',董事长:'dǒng shì zhǎng',了不起:'liǎo bù qǐ',参谋长:'cān móu zhǎng',朝鲜族:'cháo xiǎn zú',海内外:'hǎi nèi wài',禁不住:'jīn bú zhù',柏拉图:'bó lā tú',不在乎:'bú zài hu',洛杉矶:'luò shān jī',有点儿:'yǒu diǎn er',迫击炮:'pǎi jī pào',不得了:'bù dé liǎo',马尾松:'mǎ wěi sōng',运输量:'yùn shū liàng',发脾气:'fā pí qi',士大夫:'shì dà fū',鸭绿江:'yā lù jiāng',压根儿:'yà gēn er',对得起:'duì de qǐ',那会儿:'nà huì er',自个儿:'zì gě er',物理量:'wù lǐ liàng',怎么着:'zěn me zhāo',明晃晃:'míng huǎng huǎng',节假日:'jié jià rì',心里话:'xīn lǐ huà',发行量:'fā xíng liàng',兴冲冲:'xìng chōng chōng',分子量:'fēn zǐ liàng',国子监:'guó zǐ jiàn',老大难:'lǎo dà nán',党内外:'dǎng nèi wài',这么着:'zhè me zhāo',少奶奶:'shào nǎi nai',暗地里:'àn dì lǐ',更年期:'gēng nián qī',工作量:'gōng zuò liàng',背地里:'bèi dì lǐ',山里红:'shān li hóng',好好儿:'hǎo hāo er',交响乐:'jiāo xiǎng yuè',好意思:'hǎo yì si',吐谷浑:'tǔ yù hún',没意思:'méi yì si',理发师:'lǐ fà shī',塔什干:'tǎ shí gān',充其量:'chōng qí liàng',靠得住:'kào de zhù',车行道:'chē xíng dào',人行道:'rén xíng dào',中郎将:'zhōng láng jiàng',照明弹:'zhào míng dàn',烟幕弹:'yān mù dàn',没奈何:'mò nài hé',乱哄哄:'luàn hōng hōng',惠更斯:'huì gēng sī',载重量:'zài zhòng liàng',瞧得起:'qiáo de qǐ',纪传体:'jì zhuàn tǐ',阿房宫:'ē páng gōng',卷心菜:'juǎn xīn cài',戏班子:'xì bān zi',过得去:'guò de qù',花岗石:'huā gāng shí',外甥女:'wài sheng nǚ',团团转:'tuán tuán zhuàn',大堡礁:'dà bǎo jiāo',燃烧弹:'rán shāo dàn',劳什子:'láo shí zi',摇滚乐:'yáo gǔn yuè',夹竹桃:'jiā zhú táo',闹哄哄:'nào hōng hōng',三连冠:'sān lián guàn',重头戏:'zhòng tóu xì',二人转:'èr rén zhuàn',节骨眼:'jiē gǔ yǎn',知识面:'zhī shi miàn',护士长:'hù shi zhǎng',信号弹:'xìn hào dàn',干电池:'gān diàn chí',枪杆子:'qiāng gǎn zi',哭丧棒:'kū sāng bàng',鼻咽癌:'bí yān ái',瓦岗军:'wǎ gāng jūn',买得起:'mǎi de qǐ',癞蛤蟆:'lài há ma',脊梁骨:'jǐ liang gǔ',子母弹:'zǐ mǔ dàn',开小差:'kāi xiǎo chāi',女强人:'nǚ qiáng rén',英雄传:'yīng xióng zhuàn',爵士乐:'jué shì yuè',说笑话:'shuō xiào hua',碰头会:'pèng tóu huì',玻璃钢:'bō li gāng',曳光弹:'yè guāng dàn',少林拳:'shào lín quán',咏叹调:'yǒng tàn diào',少先队:'shào xiān duì',灵长目:'líng zhǎng mù',对着干:'duì zhe gàn',蒙蒙亮:'méng méng liàng',软骨头:'ruǎn gǔ tou',铺盖卷:'pū gài juǎn',和稀泥:'huò xī ní',背黑锅:'bēi hēi guō',红彤彤:'hóng tōng tōng',武侯祠:'wǔ hóu cí',打哆嗦:'dǎ duō suo',户口簿:'hù kǒu bù',马尾藻:'mǎ wěi zǎo',夜猫子:'yè māo zi',打手势:'dǎ shǒu shì',龙王爷:'lóng wáng yé',气头上:'qì tóu shang',糊涂虫:'hú tu chóng',笔杆子:'bǐ gǎn zi',占便宜:'zhàn pián yi',打主意:'dǎ zhǔ yì',多弹头:'duō dàn tóu',露一手:'lòu yì shǒu',堰塞湖:'yàn sè hú',保得住:'bǎo de zhù',趵突泉:'bào tū quán',奥得河:'ào de hé',司务长:'sī wù zhǎng',禁不起:'jīn bù qǐ',什刹海:'shí chà hǎi',莲花落:'lián huā lào',见世面:'jiàn shì miàn',豁出去:'huō chū qù',电位差:'diàn wèi chā',挨个儿:'āi gè er',那阵儿:'nà zhèn er',肺活量:'fèi huó liàng',大师傅:'dà shī fu',掷弹筒:'zhì dàn tǒng',打呼噜:'dǎ hū lu',广渠门:'ān qú mén',未见得:'wèi jiàn dé',大婶儿:'dà shěn er',谈得来:'tán de lái',脚丫子:'jiǎo yā zi',空包弹:'kōng bāo dàn',窝里斗:'wō li dòu',弹着点:'dàn zhuó diǎn',个头儿:'gè tóu er',看得起:'kàn de qǐ',糊涂账:'hú tu zhàng',大猩猩:'dà xīng xing',禁得起:'jīn de qǐ',法相宗:'fǎ xiàng zōng',可怜相:'kě lián xiàng',吃得下:'chī de xià',汉堡包:'hàn bǎo bāo',闹嚷嚷:'nào rāng rāng',数来宝:'shǔ lái bǎo',合得来:'hé de lái',干性油:'gān xìng yóu',闷葫芦:'mèn hú lu',呱呱叫:'guā guā jiào',西洋参:'xī yáng shēn',林荫道:'lín yīn dào',拉家常:'lā jiā cháng',卷铺盖:'juǎn pū gài',过得硬:'guò de yìng',飞将军:'fēi jiāng jūn',挑大梁:'tiǎo dà liáng',哈巴狗:'hǎ ba gǒu',过家家:'guò jiā jiā',催泪弹:'cuī lèi dàn',雨夹雪:'yǔ jiā xuě',敲竹杠:'qiāo zhú gàng',列车长:'liè chē zhǎng',华达呢:'huá dá ní',犯得着:'fàn de zháo',土疙瘩:'tǔ gē da',煞风景:'shā fēng jǐng',轻量级:'qīng liàng jí',羞答答:'xiū dā dā',石子儿:'shí zǐ er',达姆弹:'dá mǔ dàn',科教片:'kē jiào piān',侃大山:'kǎn dà shān',丁点儿:'dīng diǎn er',吃得消:'chī de xiāo',捋虎须:'luō hǔ xū',高丽参:'gāo lí shēn',众生相:'zhòng shēng xiàng',咽峡炎:'yān xiá yán',禁得住:'jīn de zhù',吃得开:'chī de kāi',柞丝绸:'zuò sī chóu',应声虫:'yìng shēng chóng',数得着:'shǔ de zháo',傻劲儿:'shǎ jìn er',铅玻璃:'qiān bō li',可的松:'kě dì sōng',划得来:'huá de lái',晕乎乎:'yūn hū hū',屎壳郎:'shǐ ke làng',尥蹶子:'liào juě zi',藏红花:'zàng hóng huā',闷罐车:'mèn guàn chē',卡脖子:'qiǎ bó zi',红澄澄:'hóng deng deng',赶得及:'gǎn de jí',当间儿:'dāng jiàn er',露马脚:'lòu mǎ jiǎo',鸡内金:'jī nèi jīn',犯得上:'fàn de shàng',钉齿耙:'dīng chǐ bà',饱和点:'bǎo hé diǎn',龙爪槐:'lóng zhǎo huái',喝倒彩:'hè dào cǎi',定冠词:'dìng guàn cí',担担面:'dàn dan miàn',吃得住:'chī de zhù',爪尖儿:'zhuǎ jiān er',支着儿:'zhī zhāo er',折跟头:'zhē gēn tou',阴着儿:'yīn zhāo er',烟卷儿:'yān juǎn er',宣传弹:'xuān chuán dàn',信皮儿:'xìn pí er',弦切角:'xián qiē jiǎo',缩砂密:'sù shā mì',说得来:'shuō de lái',水漂儿:'shuǐ piāo er',耍笔杆:'shuǎ bǐ gǎn',数得上:'shǔ de shàng',数不着:'shǔ bù zháo',数不清:'shǔ bù qīng',什件儿:'shí jiàn er',生死簿:'shēng sǐ bù',扇风机:'shān fēng jī',撒呓挣:'sā yì zheng',日记簿:'rì jì bù',热得快:'rè de kuài',亲家公:'qìng jia gōng',奇函数:'jī hán shù',拍纸簿:'pāi zhǐ bù',努劲儿:'nǔ jìn er',泥娃娃:'ní wá wa',内切圆:'nèi qiē yuán',哪会儿:'nǎ huì er',闷头儿:'mēn tóu er',没谱儿:'méi pǔ er',铆劲儿:'mǎo jìn er',溜肩膀:'liū jiān bǎng',了望台:'liào wàng tái',老来少:'lǎo lái shào',坤角儿:'kūn jué er',考勤簿:'kǎo qín bù',卷笔刀:'juǎn bǐ dāo',进给量:'jìn jǐ liàng',划不来:'huá bù lái',汗褂儿:'hàn guà er',鼓囊囊:'gǔ nāng nāng',够劲儿:'gòu jìn er',公切线:'gōng qiē xiàn',搁得住:'gé de zhù',赶浪头:'gǎn làng tóu',赶得上:'gǎn de shàng',干酵母:'gān jiào mǔ',嘎渣儿:'gā zhā er',嘎嘣脆:'gā bēng cuì',对得住:'duì de zhù',逗闷子:'dòu mèn zi',顶呱呱:'dǐng guā guā',滴溜儿:'dī liù er',大轴子:'dà zhòu zi',打板子:'dǎ bǎn zi',寸劲儿:'cùn jìn er',醋劲儿:'cù jìn er',揣手儿:'chuāi shǒu er',冲劲儿:'chòng jìn er',吃得来:'chī de lái',不更事:'bù gēng shì',奔头儿:'bèn tou er',百夫长:'bǎi fū zhǎng',娃娃亲:'wá wa qīn',死劲儿:'sǐ jìn er',骨朵儿:'gū duǒ er',功劳簿:'gōng láo bù',都江堰:'dū jiāng yàn',一担水:'yí dàn shuǐ',否极泰:'pǐ jí tài',泰来否:'tài lái pǐ',咳特灵:'ké tè líng',开户行:'kāi hù háng',郦食其:'lì yì jī',花事了:'huā shì liǎo',一更更:'yì gēng gēng',一重山:'yì chóng shān',风一更:'fēng yì gēng',雪一更:'xuě yì gēng',归一码:'guī yì mǎ',星期一:'xīng qī yī',礼拜一:'lǐ bài yī',一季度:'yī jì dù',一月一:'yī yuè yī',一字马:'yī zì mǎ',一是一:'yī shì yī',一次方:'yī cì fāng',一阳指:'yī yáng zhǐ',一字决:'yī zì jué',一年级:'yī nián jí',一不做:'yī bú zuò',屈戌儿:'qū qu ér',难为水:'nán wéi shuǐ',难为情:'nán wéi qíng',行一行:'xíng yì háng',别别的:'biè bié de',干哪行:'gàn nǎ háng',干一行:'gàn yì háng',曲别针:'qū bié zhēn',};const Pattern3=Object.keys(DICT3).map((key)=>({zh:key,pinyin:DICT3[key],probability:2e-8,length:3,priority:Priority.Normal,dict:Symbol('dict3'),}));const DICT4={成吉思汗:"chéng jí sī hán",四通八达:"sì tōng bā dá",一模一样:"yì mú yí yàng",青藏高原:"qīng zàng gāo yuán",阿弥陀佛:"ē mí tuó fó",解放思想:"jiè fàng sī xiǎng",所作所为:"suǒ zuò suǒ wéi",迷迷糊糊:"mí mí hu hū",荷枪实弹:"hè qiāng shí dàn",兴高采烈:"xìng gāo cǎi liè",无能为力:"wú néng wéi lì",布鲁塞尔:"bù lǔ sài ěr",为所欲为:"wéi suǒ yù wéi",克什米尔:"kè shí mǐ ěr",没完没了:"méi wán méi liǎo",不为人知:"bù wéi rén zhī",结结巴巴:"jiē jiē bā bā",前仆后继:"qián pū hòu jì",铺天盖地:"pū tiān gài dì",直截了当:"zhí jié liǎo dàng",供不应求:"gōng bú yìng qiú",御史大夫:"yù shǐ dà fū",不为瓦全:"bù wéi wǎ quán",不可收拾:"bù kě shōu shi",胡作非为:"hú zuò fēi wéi",分毫不差:"fēn háo bú chà",模模糊糊:"mó mó hu hū",不足为奇:"bù zú wéi qí",悄无声息:"qiǎo wú shēng xī",了如指掌:"liǎo rú zhǐ zhǎng",深恶痛绝:"shēn wù tòng jué",高高兴兴:"gāo gāo xìng xìng",唉声叹气:"āi shēng tàn qì",汉藏语系:"hàn zàng yǔ xì",处心积虑:"chǔ xīn jī lǜ",泣不成声:"qì bù chéng shēng",半夜三更:"bàn yè sān gēng",失魂落魄:"shī hún luò pò",二十八宿:"èr shí bā xiù",转来转去:"zhuàn lái zhuàn qù",数以万计:"shǔ yǐ wàn jì",相依为命:"xiāng yī wéi mìng",恋恋不舍:"liàn liàn bù shě",屈指可数:"qū zhǐ kě shǔ",神出鬼没:"shén chū guǐ mò",结结实实:"jiē jiē shí shí",有的放矢:"yǒu dì fàng shǐ",叽哩咕噜:"jī lǐ gū lū",调兵遣将:"diào bīng qiǎn jiàng",载歌载舞:"zài gē zài wǔ",转危为安:"zhuǎn wēi wéi ān",踏踏实实:"tā tā shi shí",桑给巴尔:"sāng jǐ bā ěr",装模作样:"zhuāng mú zuò yàng",见义勇为:"jiàn yì yǒng wéi",相差无几:"xiāng chā wú jǐ",叹为观止:"tàn wéi guān zhǐ",闷闷不乐:"mèn mèn bú lè",喜怒哀乐:"xǐ nù āi lè",鲜为人知:"xiǎn wéi rén zhī",张牙舞爪:"zhāng yá wǔ zhǎo",为非作歹:"wéi fēi zuò dǎi",含糊其辞:"hán hú qí cí",疲于奔命:"pí yú bēn mìng",勉为其难:"miǎn wéi qí nán",依依不舍:"yī yī bù shě",顶头上司:"dǐng tóu shàng si",不着边际:"bù zhuó biān jì",大模大样:"dà mú dà yàng",寻欢作乐:"xún huān zuò lè",一走了之:"yì zǒu liǎo zhī",字里行间:"zì lǐ háng jiān",含含糊糊:"hán hán hu hū",恰如其分:"qià rú qí fèn",破涕为笑:"pò tì wéi xiào",深更半夜:"shēn gēng bàn yè",千差万别:"qiān chā wàn bié",数不胜数:"shǔ bú shèng shǔ",据为己有:"jù wéi jǐ yǒu",天旋地转:"tiān xuán dì zhuàn",养尊处优:"yǎng zūn chǔ yōu",玻璃纤维:"bō li xiān wéi",吵吵闹闹:"chāo chao nào nào",晕头转向:"yūn tóu zhuàn xiàng",土生土长:"tǔ shēng tǔ zhǎng",宁死不屈:"nìng sǐ bù qū",不省人事:"bù xǐng rén shì",尽力而为:"jìn lì ér wéi",精明强干:"jīng míng qiáng gàn",唠唠叨叨:"láo lao dāo dāo",叽叽喳喳:"jī ji zhā zhā",功不可没:"gōng bù kě mò",锲而不舍:"qiè ér bù shě",排忧解难:"pái yōu jiě nàn",稀里糊涂:"xī li hú tú",各有所长:"gè yǒu suǒ cháng",的的确确:"dí dí què què",哄堂大笑:"hōng táng dà xiào",听而不闻:"tīng ér bù wén",刀耕火种:"dāo gēng huǒ zhòng",内分泌腺:"nèi fèn mì xiàn",化险为夷:"huà xiǎn wéi yí",百发百中:"bǎi fā bǎi zhòng",重见天日:"chóng jiàn tiān rì",反败为胜:"fǎn bài wéi shèng",一了百了:"yì liǎo bǎi liǎo",大大咧咧:"dà da liē liē",心急火燎:"xīn jí huǒ liǎo",粗心大意:"cū xīn dà yi",鸡皮疙瘩:"jī pí gē da",夷为平地:"yí wéi píng dì",日积月累:"rì jī yuè lěi",设身处地:"shè shēn chǔ dì",投其所好:"tóu qí suǒ hào",间不容发:"jiān bù róng fà",人满为患:"rén mǎn wéi huàn",穷追不舍:"qióng zhuī bù shě",为时已晚:"wéi shí yǐ wǎn",如数家珍:"rú shǔ jiā zhēn",心里有数:"xīn lǐ yǒu shù",以牙还牙:"yǐ yá huán yá",神不守舍:"shén bù shǒu shě",孟什维克:"mèng shí wéi kè",各自为战:"gè zì wéi zhàn",怨声载道:"yuàn shēng zài dào",救苦救难:"jiù kǔ jiù nàn",好好先生:"hǎo hǎo xiān sheng",怪模怪样:"guài mú guài yàng",抛头露面:"pāo tóu lù miàn",游手好闲:"yóu shǒu hào xián",无所不为:"wú suǒ bù wéi",调虎离山:"diào hǔ lí shān",步步为营:"bù bù wéi yíng",好大喜功:"hào dà xǐ gōng",众矢之的:"zhòng shǐ zhī dì",长生不死:"cháng shēng bù sǐ",蔚为壮观:"wèi wéi zhuàng guān",不可胜数:"bù kě shèng shǔ",鬼使神差:"guǐ shǐ shén chāi",洁身自好:"jié shēn zì hào",敢作敢为:"gǎn zuò gǎn wéi",茅塞顿开:"máo sè dùn kāi",走马换将:"zǒu mǎ huàn jiàng",为时过早:"wéi shí guò zǎo",为人师表:"wéi rén shī biǎo",阴差阳错:"yīn chā yáng cuò",油腔滑调:"yóu qiāng huá diào",重蹈覆辙:"chóng dǎo fù zhé",骂骂咧咧:"mà ma liē liē",絮絮叨叨:"xù xù dāo dāo",如履薄冰:"rú lǚ bó bīng",损兵折将:"sǔn bīng zhé jiàng",拐弯抹角:"guǎi wān mò jiǎo",像模像样:"xiàng mú xiàng yàng",供过于求:"gōng guò yú qiú",开花结果:"kāi huā jiē guǒ",仔仔细细:"zǐ zǐ xì xì",川藏公路:"chuān zàng gōng lù",河北梆子:"hé běi bāng zi",长年累月:"cháng nián lěi yuè",正儿八经:"zhèng er bā jīng",不识抬举:"bù shí tái ju",重振旗鼓:"chóng zhèn qí gǔ",气息奄奄:"qì xī yān yān",紧追不舍:"jǐn zhuī bù shě",服服帖帖:"fú fu tiē tiē",强词夺理:"qiǎng cí duó lǐ",噼里啪啦:"pī li pā lā",人才济济:"rén cái jǐ jǐ",发人深省:"fā rén shēn xǐng",不足为凭:"bù zú wéi píng",为富不仁:"wéi fù bù rén",连篇累牍:"lián piān lěi dú",呼天抢地:"hū tiān qiāng dì",落落大方:"luò luò dà fāng",自吹自擂:"zì chuī zì léi",乐善好施:"lè shàn hào shī",以攻为守:"yǐ gōng wéi shǒu",磨磨蹭蹭:"mó mó cèng cèng",削铁如泥:"xuē tiě rú ní",助纣为虐:"zhù zhòu wéi nüè",以退为进:"yǐ tuì wéi jìn",嘁嘁喳喳:"qī qī chā chā",枪林弹雨:"qiāng lín dàn yǔ",令人发指:"lìng rén fà zhǐ",转败为胜:"zhuǎn bài wéi shèng",转弯抹角:"zhuǎn wān mò jiǎo",在劫难逃:"zài jié nán táo",正当防卫:"zhèng dàng fáng wèi",不足为怪:"bù zú wéi guài",难兄难弟:"nàn xiōng nàn dì",咿咿呀呀:"yī yī yā yā",弹尽粮绝:"dàn jìn liáng jué",阿谀奉承:"ē yú fèng chéng",稀里哗啦:"xī li huā lā",返老还童:"fǎn lǎo huán tóng",好高骛远:"hào gāo wù yuǎn",鹿死谁手:"lù sǐ shéi shǒu",差强人意:"chā qiáng rén yì",大吹大擂:"dà chuī dà léi",成家立业:"chéng jiā lì yè",自怨自艾:"zì yuàn zì yì",负债累累:"fù zhài lěi lěi",古为今用:"gǔ wéi jīn yòng",入土为安:"rù tǔ wéi ān",下不为例:"xià bù wéi lì",一哄而上:"yì hōng ér shàng",没头苍蝇:"méi tóu cāng ying",天差地远:"tiān chā dì yuǎn",风卷残云:"fēng juǎn cán yún",多灾多难:"duō zāi duō nàn",乳臭未干:"rǔ xiù wèi gān",行家里手:"háng jiā lǐ shǒu",狼狈为奸:"láng bèi wéi jiān",处变不惊:"chǔ biàn bù jīng",一唱一和:"yí chàng yí hè",一念之差:"yí niàn zhī chā",金蝉脱壳:"jīn chán tuō qiào",滴滴答答:"dī dī dā dā",硕果累累:"shuò guǒ léi léi",好整以暇:"hào zhěng yǐ xiá",红得发紫:"hóng de fā zǐ",传为美谈:"chuán wéi měi tán",富商大贾:"fù shāng dà gǔ",四海为家:"sì hǎi wéi jiā",了若指掌:"liǎo ruò zhǐ zhǎng",大有可为:"dà yǒu kě wéi",出头露面:"chū tóu lù miàn",鼓鼓囊囊:"gǔ gu nāng nāng",窗明几净:"chuāng míng jī jìng",泰然处之:"tài rán chǔ zhī",怒发冲冠:"nù fà chōng guān",有机玻璃:"yǒu jī bō li",骨头架子:"gǔ tou jià zi",义薄云天:"yì bó yún tiān",一丁点儿:"yī dīng diǎn er",时来运转:"shí lái yùn zhuǎn",陈词滥调:"chén cí làn diào",化整为零:"huà zhěng wéi líng",火烧火燎:"huǒ shāo huǒ liǎo",干脆利索:"gàn cuì lì suǒ",吊儿郎当:"diào er láng dāng",广种薄收:"guǎng zhòng bó shōu",种瓜得瓜:"zhòng guā dé guā",种豆得豆:"zhòng dòu dé dòu",难舍难分:"nán shě nán fēn",歃血为盟:"shà xuè wéi méng",奋发有为:"fèn fā yǒu wéi",阴错阳差:"yīn cuò yáng chā",东躲西藏:"dōng duǒ xī cáng",烟熏火燎:"yān xūn huǒ liǎo",钻牛角尖:"zuān niú jiǎo jiān",乔装打扮:"qiáo zhuāng dǎ bàn",改弦更张:"gǎi xián gēng zhāng",河南梆子:"hé nán bāng zi",好吃懒做:"hào chī lǎn zuò",何乐不为:"hé lè bù wéi",大出风头:"dà chū fēng tóu",攻城掠地:"gōng chéng lüè dì",漂漂亮亮:"piào piào liang liang",折衷主义:"zhé zhōng zhǔ yì",大马哈鱼:"dà mǎ hǎ yú",绿树成荫:"lǜ shù chéng yīn",率先垂范:"shuài xiān chuí fàn",家长里短:"jiā cháng lǐ duǎn",宽大为怀:"kuān dà wéi huái",左膀右臂:"zuǒ bǎng yòu bì",一笑了之:"yí xiào liǎo zhī",天下为公:"tiān xià wéi gōng",还我河山:"huán wǒ hé shān",何足为奇:"hé zú wéi qí",好自为之:"hǎo zì wéi zhī",风姿绰约:"fēng zī chuò yuē",大雨滂沱:"dà yǔ pāng tuó",传为佳话:"chuán wéi jiā huà",吃里扒外:"chī lǐ pá wài",重操旧业:"chóng cāo jiù yè",小家子气:"xiǎo jiā zi qì",少不更事:"shào bù gēng shì",难分难舍:"nán fēn nán shě",添砖加瓦:"tiān zhuān jiā wǎ",是非分明:"shì fēi fēn míng",舍我其谁:"shě wǒ qí shuí",偏听偏信:"piān tīng piān xìn",量入为出:"liàng rù wéi chū",降龙伏虎:"xiáng lóng fú hǔ",钢化玻璃:"gāng huà bō li",正中下怀:"zhèng zhòng xià huái",以身许国:"yǐ shēn xǔ guó",一语中的:"yì yǔ zhòng dì",丧魂落魄:"sàng hún luò pò",三座大山:"sān zuò dà shān",济济一堂:"jǐ jǐ yì táng",好事之徒:"hào shì zhī tú",干净利索:"gàn jìng lì suǒ",出将入相:"chū jiàng rù xiàng",袅袅娜娜:"niǎo niǎo nuó nuó",狐狸尾巴:"hú li wěi ba",好逸恶劳:"hào yì wù láo",大而无当:"dà ér wú dàng",打马虎眼:"dǎ mǎ hu yǎn",板上钉钉:"bǎn shàng dìng dīng",吆五喝六:"yāo wǔ hè liù",虾兵蟹将:"xiā bīng xiè jiàng",水调歌头:"shuǐ diào gē tóu",数典忘祖:"shǔ diǎn wàng zǔ",人事不省:"rén shì bù xǐng",曲高和寡:"qǔ gāo hè guǎ",屡教不改:"lǚ jiào bù gǎi",互为因果:"hù wéi yīn guǒ",互为表里:"hù wéi biǎo lǐ",厚此薄彼:"hòu cǐ bó bǐ",过关斩将:"guò guān zhǎn jiàng",疙疙瘩瘩:"gē ge dā dā",大腹便便:"dà fù pián pián",走为上策:"zǒu wéi shàng cè",冤家对头:"yuān jia duì tóu",有隙可乘:"yǒu xì kě chèng",一鳞半爪:"yì lín bàn zhǎo",片言只语:"piàn yán zhǐ yǔ",开花结实:"kāi huā jié shí",经年累月:"jīng nián lěi yuè",含糊其词:"hán hú qí cí",寡廉鲜耻:"guǎ lián xiǎn chǐ",成年累月:"chéng nián lěi yuè",不徇私情:"bú xùn sī qíng",不当人子:"bù dāng rén zǐ",膀大腰圆:"bǎng dà yāo yuán",指腹为婚:"zhǐ fù wéi hūn",这么点儿:"zhè me diǎn er",意兴索然:"yì xīng suǒ rán",绣花枕头:"xiù huā zhěn tou",无的放矢:"wú dì fàng shǐ",望闻问切:"wàng wén wèn qiè",舍己为人:"shě jǐ wèi rén",穷年累月:"qióng nián lěi yuè",排难解纷:"pái nàn jiě fēn",处之泰然:"chǔ zhī tài rán",指鹿为马:"zhǐ lù wéi mǎ",危如累卵:"wēi rú lěi luǎn",天兵天将:"tiān bīng tiān jiàng",舍近求远:"shě jìn qiú yuǎn",南腔北调:"nán qiāng běi diào",苦中作乐:"kǔ zhōng zuò lè",厚积薄发:"hòu jī bó fā",臭味相投:"xiù wèi xiāng tóu",长幼有序:"zhǎng yòu yǒu xù",逼良为娼:"bī liáng wéi chāng",悲悲切切:"bēi bēi qiè qiē",败军之将:"bài jūn zhī jiàng",欺行霸市:"qī háng bà shì",削足适履:"xuē zú shì lǚ",先睹为快:"xiān dǔ wéi kuài",啼饥号寒:"tí jī háo hán",疏不间亲:"shū bú jiàn qīn",神差鬼使:"shén chāi guǐ shǐ",敲敲打打:"qiāo qiāo dǎ dǎ",平铺直叙:"píng pū zhí xù",没头没尾:"méi tóu mò wěi",寥寥可数:"liáo liáo kě shǔ",哼哈二将:"hēng hā èr jiàng",鹤发童颜:"hè fà tóng yán",各奔前程:"gè bèn qián chéng",弹无虚发:"dàn wú xū fā",大人先生:"dà rén xiān sheng",与民更始:"yǔ mín gēng shǐ",树碑立传:"shù bēi lì zhuàn",是非得失:"shì fēi dé shī",实逼处此:"shí bī chǔ cǐ",塞翁失马:"sài wēng shī mǎ",日薄西山:"rì bó xī shān",切身体会:"qiè shēn tǐ huì",片言只字:"piàn yán zhǐ zì",跑马卖解:"pǎo mǎ mài xiè",宁折不弯:"nìng zhé bù wān",零零散散:"líng líng sǎn sǎn",量体裁衣:"liàng tǐ cái yī",连中三元:"lián zhòng sān yuán",礼崩乐坏:"lǐ bēng yuè huài",不为已甚:"bù wéi yǐ shèn",转悲为喜:"zhuǎn bēi wéi xǐ",以眼还眼:"yǐ yǎn huán yǎn",蔚为大观:"wèi wéi dà guān",未为不可:"wèi wéi bù kě",童颜鹤发:"tóng yán hè fà",朋比为奸:"péng bǐ wéi jiān",莫此为甚:"mò cǐ wéi shèn",夹枪带棒:"jiā qiāng dài bàng",富商巨贾:"fù shāng jù jiǎ",淡然处之:"dàn rán chǔ zhī",箪食壶浆:"dān shí hú jiāng",创巨痛深:"chuāng jù tòng shēn",草长莺飞:"cǎo zhǎng yīng fēi",坐视不救:"zuò shī bú jiù",以己度人:"yǐ jǐ duó rén",随行就市:"suí háng jiù shì",文以载道:"wén yǐ zài dào",文不对题:"wén bú duì tí",铁板钉钉:"tiě bǎn dìng dīng",身体发肤:"shēn tǐ fà fū",缺吃少穿:"quē chī shǎo chuān",目无尊长:"mù wú zūn zhǎng",吉人天相:"jí rén tiān xiàng",毁家纾难:"huǐ jiā shū nàn",钢筋铁骨:"gāng jīn tiě gǔ",丢卒保车:"diū zú bǎo jū",丢三落四:"diū sān là sì",闭目塞听:"bì mù sè tīng",削尖脑袋:"xuē jiān nǎo dài",为非作恶:"wéi fēi zuò è",人才难得:"rén cái nán dé",情非得已:"qíng fēi dé yǐ",切中要害:"qiè zhòng yào hài",火急火燎:"huǒ jí huǒ liǎo",画地为牢:"huà dì wéi láo",好酒贪杯:"hào jiǔ tān bēi",长歌当哭:"cháng gē dàng kū",载沉载浮:"zài chén zài fú",遇难呈祥:"yù nàn chéng xiáng",榆木疙瘩:"yú mù gē da",以邻为壑:"yǐ lín wéi hè",洋为中用:"yáng wéi zhōng yòng",言为心声:"yán wéi xīn shēng",言必有中:"yán bì yǒu zhòng",图穷匕见:"tú qióng bǐ xiàn",滂沱大雨:"páng tuó dà yǔ",目不暇给:"mù bù xiá jǐ",量才录用:"liàng cái lù yòng",教学相长:"jiào xué xiāng zhǎng",悔不当初:"huǐ bù dāng chū",呼幺喝六:"hū yāo hè liù",不足为训:"bù zú wéi xùn",不拘形迹:"bù jū xíng jī",傍若无人:"páng ruò wú rén",罪责难逃:"zuì zé nán táo",自我吹嘘:"zì wǒ chuī xū",转祸为福:"zhuǎn huò wéi fú",勇冠三军:"yǒng guàn sān jūn",易地而处:"yì dì ér chǔ",卸磨杀驴:"xiè mò shā lǘ",玩儿不转:"wán ér bú zhuàn",天道好还:"tiān dào hǎo huán",身单力薄:"shēn dān lì bó",撒豆成兵:"sǎ dòu chéng bīng",片纸只字:"piàn zhǐ zhī zì",宁缺毋滥:"nìng quē wú làn",没没无闻:"mò mò wú wén",量力而为:"liàng lì ér wéi",历历可数:"lì lì kě shǔ",口碑载道:"kǒu bēi zài dào",君子好逑:"jūn zǐ hǎo qiú",好为人师:"hào wéi rén shī",豪商巨贾:"háo shāng jù jiǎ",各有所好:"gè yǒu suǒ hào",度德量力:"duó dé liàng lì",指天为誓:"zhǐ tiān wéi shì",逸兴遄飞:"yì xìng chuán fēi",心宽体胖:"xīn kuān tǐ pán",为德不卒:"wéi dé bù zú",天下为家:"tiān xià wéi jiā",视为畏途:"shì wéi wèi tú",三灾八难:"sān zāi bā nàn",沐猴而冠:"mù hóu ér guàn",哩哩啦啦:"lī li lā lā",见缝就钻:"jiàn fèng jiù zuān",夹层玻璃:"jiā céng bō li",急公好义:"jí gōng hào yì",积年累月:"jī nián lěi yuè",划地为牢:"huá dì wéi láo",更名改姓:"gēng míng gǎi xìng",奉为圭臬:"fèng wéi guī niè",多难兴邦:"duō nàn xīng bāng",不破不立:"bú pò bú lì",坐地自划:"zuò dì zì huá",坐不重席:"zuò bù chóng xí",坐不窥堂:"zuò bù kuī táng",作嫁衣裳:"zuò jià yī shang",左枝右梧:"zuǒ zhī yòu wú",左宜右有:"zuǒ yí yòu yǒu",钻头觅缝:"zuān tóu mì fèng",钻天打洞:"zuān tiān dǎ dòng",钻皮出羽:"zuān pí chū yǔ",钻火得冰:"zuān huǒ dé bīng",钻洞觅缝:"zuàn dòng mì féng",钻冰求火:"zuān bīng qiú huǒ",子为父隐:"zǐ wéi fù yǐn",擢发难数:"zhuó fà nán shǔ",着人先鞭:"zhuó rén xiān biān",斫雕为朴:"zhuó diāo wéi pǔ",锥处囊中:"zhuī chǔ náng zhōng",椎心饮泣:"chuí xīn yǐn qì",椎心泣血:"chuí xīn qì xuè",椎牛飨士:"chuí niú xiǎng shì",椎牛歃血:"chuí niú shà xuè",椎牛发冢:"chuí niú fà zhǒng",椎埋屠狗:"chuí mái tú gǒu",椎埋狗窃:"chuí mái gǒu qiè",壮发冲冠:"zhuàng fā chōng guàn",庄严宝相:"zhuāng yán bǎo xiàng",转愁为喜:"zhuǎn chóu wéi xǐ",转嗔为喜:"zhuǎn chēn wéi xǐ",拽巷啰街:"zhuài xiàng luó jiē",拽耙扶犁:"zhuāi pá fú lí",拽布拖麻:"zhuài bù tuō má",箸长碗短:"zhù cháng wǎn duǎn",铸剑为犁:"zhù jiàn wéi lí",杼柚其空:"zhù yòu qí kōng",杼柚空虚:"zhù yòu kōng xū",助天为虐:"zhù tiān wéi nüè",属垣有耳:"zhǔ yuán yǒu ěr",属毛离里:"zhǔ máo lí lǐ",属辞比事:"zhǔ cí bǐ shì",逐物不还:"zhú wù bù huán",铢量寸度:"zhū liáng cùn duó",铢两悉称:"zhū liǎng xī chèn",侏儒观戏:"zhū rú guān xì",朱轓皁盖:"zhū fān zào gài",昼度夜思:"zhòu duó yè sī",诪张为幻:"zhōu zhāng wéi huàn",重明继焰:"chóng míng jì yàn",众啄同音:"zhòng zhuó tóng yīn",众毛攒裘:"zhòng máo cuán qiú",众好众恶:"zhòng hào zhòng wù",擿埴索涂:"zhāi zhí suǒ tú",稚齿婑媠:"zhì chǐ wǒ tuó",至当不易:"zhì dàng bú yì",指皂为白:"zhǐ zào wéi bái",指雁为羹:"zhǐ yàn wéi gēng",指树为姓:"zhǐ shù wéi xìng",指山说磨:"zhǐ shān shuō mò",止戈为武:"zhǐ gē wéi wǔ",枝干相持:"zhī gàn xiāng chí",枝大于本:"zh dà yú běn",支吾其词:"zhī wú qí cí",正身率下:"zhèng shēn shuài xià",正冠李下:"zhèng guàn lǐ xià",整冠纳履:"zhěng guān nà lǚ",整躬率物:"zhěng gōng shuài wù",整顿干坤:"zhěng dùn gàn kūn",针头削铁:"zhēn tóu xuē tiě",贞松劲柏:"zhēn sōng jìng bǎi",赭衣塞路:"zhě yī sè lù",折箭为誓:"shé jiàn wéi shì",折而族之:"zhé ér zú zhī",昭德塞违:"zhāo dé sè wéi",章句小儒:"zhāng jù xiǎo rú",湛恩汪濊:"zhàn ēn wāng huì",占风望气:"zhān fēng wàng qì",斩将搴旗:"zhǎn jiàng qiān qí",曾母投杼:"zēng mǔ tóu zhù",曾参杀人:"zēng shēn shā rén",造谣中伤:"zào yáo zhòng shāng",早占勿药:"zǎo zhān wù yào",凿龟数策:"záo guī shǔ cè",攒三聚五:"cuán sān jù wǔ",攒眉蹙额:"cuán mei cù é",攒零合整:"cuán líng hé zhěng",攒锋聚镝:"cuán fēng jù dí",载笑载言:"zài xiào zài yán",载酒问字:"zài jiǔ wèn zì",殒身不恤:"yǔn shēn bú xù",云舒霞卷:"yún shū xiá juǎn",月中折桂:"yuè zhōng shé guì",月落参横:"yuè luò shēn héng",鬻驽窃价:"yù nú qiè jià",鬻鸡为凤:"yù jī wéi fèng",遇难成祥:"yù nàn chéng xiáng",郁郁累累:"yù yù lěi lěi",玉卮无当:"yù zhī wú dàng",语笑喧阗:"yǔ xiào xuān tián",与世沉浮:"yǔ shì chén fú",与时消息:"yǔ shí xiāo xi",逾墙钻隙:"yú qiáng zuān xì",渔夺侵牟:"yú duó qīn móu",杅穿皮蠹:"yú chuān pí dù",余勇可贾:"yú yǒng kě gǔ",予智予雄:"yú zhì yú xióng",予取予求:"yú qǔ yú qiú",于家为国:"yú jiā wéi guó",有借无还:"yǒu jiè wú huán",有加无已:"yǒu jiā wú yǐ",有国难投:"yǒu guó nán tóu",游必有方:"yóu bì yǒu fāng",油干灯尽:"yóu gàn dēng jìn",尤云殢雨:"yóu yún tì yǔ",庸中皦皦:"yōng zhōng jiǎo jiǎo",郢书燕说:"yǐng shū yān shuō",营蝇斐锦:"yíng yíng fēi jǐn",鹰心雁爪:"yīng xīn yàn zhǎo",莺吟燕儛:"yīng yín yàn wǔ",应天顺时:"yīng tiān shùn shí",印累绶若:"yìn léi shòu ruò",隐占身体:"yǐn zhàn shēn tǐ",饮犊上流:"yìn dú shàng liú",引绳切墨:"yǐn shéng qiē mò",龈齿弹舌:"yín chǐ dàn shé",因缘为市:"yīn yuán wéi shì",因树为屋:"yīn shù wéi wū",溢美溢恶:"yì měi yì wù",抑塞磊落:"yì sè lěi luò",倚闾望切:"yǐ lǘ wàng qiē",以意为之:"yǐ yì wéi zhī",以言为讳:"yǐ yán wéi huì",以疏间亲:"yǐ shū jiàn qīn",以水济水:"yǐ shuǐ jǐ shuǐ",以书为御:"yǐ shū wéi yù",以守为攻:"yǐ shǒu wéi gōng",以升量石:"yǐ shēng liáng dàn",以慎为键:"yǐ shèn wéi jiàn",以筌为鱼:"yǐ quán wéi yú",以利累形:"yǐ lì lěi xíng",以毁为罚:"yǐ huǐ wéi fá",以黑为白:"yǐ hēi wéi bái",以规为瑱:"yǐ guī wéi tiàn",以古为鉴:"yǐ gǔ wéi jiàn",以宫笑角:"yǐ gōng xiào jué",以法为教:"yǐ fǎ wéi jiào",以大恶细:"yǐ dà wù xì",遗世忘累:"yí shì wàng lěi",遗寝载怀:"yí qǐn zài huái",移的就箭:"yí dì jiù jiàn",依头缕当:"yī tóu lǚ dàng",衣租食税:"yì zū shí shuì",衣轻乘肥:"yì qīng chéng féi",衣裳之会:"yī shang zhī huì",衣单食薄:"yī dān shí bó",一还一报:"yì huán yí bào",叶公好龙:"yè gōng hào lóng",野调无腔:"yě diào wú qiāng",瑶池女使:"yáo chí nǚ shǐ",幺麽小丑:"yāo mó xiǎo chǒu",养精畜锐:"yǎng jīng xù ruì",卬首信眉:"áng shǒu shēn méi",洋洋纚纚:"yáng yáng sǎ sǎ",羊羔美酒:"yáng gāo měi jiǔ",扬风扢雅:"yáng fēng jié yǎ",燕昭市骏:"yān zhāo shì jùn",燕昭好马:"yān zhāo hǎo mǎ",燕石妄珍:"yān shí wàng zhēn",燕骏千金:"yān jùn qiān jīn",燕金募秀:"yān jīn mù xiù",燕驾越毂:"yān jià yuè gǔ",燕歌赵舞:"yān gē zhào wǔ",燕岱之石:"yān dài zhī shí",燕处危巢:"yàn chǔ wēi cháo",掞藻飞声:"shàn zǎo fēi shēng",偃革为轩:"yǎn gé wéi xuān",妍蚩好恶:"yán chī hǎo è",压良为贱:"yā liáng wéi jiàn",搀行夺市:"chān háng duó shì",泣数行下:"qì shù háng xià",当行出色:"dāng háng chū sè",秀出班行:"xiù chū bān háng",儿女成行:"ér nǚ chéng háng",大行大市:"dà háng dà shì",寻行数墨:"xún háng shǔ mò",埙篪相和:"xūn chí xiāng hè",血债累累:"xuè zhài lěi lěi",炫玉贾石:"xuàn yù gǔ shí",炫石为玉:"xuàn shí wéi yù",悬石程书:"xuán dàn chéng shū",悬狟素飡:"xuán huán sù cān",悬龟系鱼:"xuán guī xì yú",揎拳捋袖:"xuān quán luō xiù",轩鹤冠猴:"xuān hè guàn hóu",畜妻养子:"xù qī yǎng zǐ",羞人答答:"xiū rén dā dā",修鳞养爪:"xiū lín yǎng zhǎo",熊据虎跱:"xióng jù hǔ zhì",兄死弟及:"xiōng sǐ dì jí",腥闻在上:"xīng wén zài shàng",兴文匽武:"xīng wén yǎn wǔ",兴观群怨:"xìng guān qún yuàn",兴高彩烈:"xìng gāo cǎi liè",心手相应:"xīn shǒu xiāng yìng",心口相应:"xīn kǒu xiāng yīng",挟势弄权:"xié shì nòng quán",胁肩累足:"xié jiān lěi zú",校短量长:"jiào duǎn liáng cháng",小眼薄皮:"xiǎo yǎn bó pí",硝云弹雨:"xiāo yún dàn yǔ",鸮鸣鼠暴:"xiāo míng shǔ bào",削株掘根:"xuē zhū jué gēn",削铁无声:"xuē tiě wú shēng",削职为民:"xuē zhí wéi mín",削木为吏:"xuē mù wéi lì",想望风褱:"xiǎng wàng fēng huái",香培玉琢:"xiang pei yu zhuó",相鼠有皮:"xiàng shǔ yǒu pí",相时而动:"xiàng shí ér dòng",相切相磋:"xiāng qiē xiāng cuō",相女配夫:"xiàng nǚ pèi fū",相门有相:"xiàng mén yǒu xiàng",挦章撦句:"xián zhāng chě jù",先我着鞭:"xiān wǒ zhuó biān",习焉不察:"xí yān bù chá",歙漆阿胶:"shè qī ē jiāo",晰毛辨发:"xī máo biàn fà",悉索薄赋:"xī suǒ bó fù",雾鳞云爪:"wù lín yún zhǎo",物稀为贵:"wù xī wéi guì",碔砆混玉:"wǔ fū hùn yù",武断专横:"wǔ duàn zhuān héng",五石六鹢:"wǔ shí liù yì",五色相宣:"wǔ sè xiāng xuān",五侯七贵:"wǔ hóu qī guì",五侯蜡烛:"wǔ hòu là zhú",五羖大夫:"wǔ gǔ dà fū",吾自有处:"wú zì yǒu chǔ",无下箸处:"wú xià zhù chǔ",无伤无臭:"wú shāng wú xiù",无能为役:"wú néng wéi yì",无寇暴死:"wú kòu bào sǐ",无孔不钻:"wú kǒng bú zuàn",无间可乘:"wú jiān kě chéng",无间冬夏:"wú jiān dōng xià",无恶不为:"wú è bù wéi",无动为大:"wú dòng wéi dà",诬良为盗:"wū liáng wéi dào",握拳透爪:"wò quán tòu zhǎo",文武差事:"wén wǔ chāi shì",委委佗佗:"wēi wēi tuó tuó",惟日为岁:"wéi rì wéi suì",帷薄不修:"wéi bó bù xiū",为善最乐:"wéi shàn zuì lè",为山止篑:"wéi shān zhǐ kuì",为仁不富:"wéi rén bú fù",为裘为箕:"wéi qiú wéi jī",为民父母:"wéi mín fù mǔ",为虺弗摧:"wéi huǐ fú cuī",为好成歉:"wéi hǎo chéng qiàn",为鬼为蜮:"wéi guǐ wéi yù",望风响应:"wàng fēng xiǎng yīng",望尘僄声:"wàng chén piào shēng",往渚还汀:"wǎng zhǔ huán tīng",王贡弹冠:"wáng gòng dàn guàn",亡国大夫:"wáng guó dà fū",万贯家私:"wàn guàn jiā sī",晚食当肉:"wǎn shí dàng ròu",晚节不保:"wǎn jié bù bǎo",玩岁愒时:"wán suì kài shí",蛙蟆胜负:"wā má shèng fù",吞言咽理:"tūn yán yàn lǐ",颓垣断堑:"tuí yuán duàn qiàn",推干就湿:"tuī gàn jiù shī",剸繁决剧:"tuán fán jué jù",团头聚面:"tuán tóu jù miàn",兔丝燕麦:"tù sī yàn mài",兔头麞脑:"tù tóu zhāng nǎo",兔葵燕麦:"tù kuí yàn mài",吐哺握发:"tǔ bǔ wò fà",投传而去:"tóu zhuàn ér qù",头没杯案:"tóu mò bēi àn",头昏脑闷:"tóu hūn nǎo mèn",头会箕敛:"tóu kuài jī liǎn",头出头没:"tóu chū tóu mò",痛自创艾:"tòng zì chuāng yì",同恶相助:"tóng wù xiāng zhù",同恶相恤:"tóng wù xiāng xù",痌瘝在抱:"tōng guān zài bào",通文调武:"tōng wén diào wǔ",停留长智:"tíng liú zhǎng zhì",铁树开华:"tiě shù kāi huā",条贯部分:"tiáo guàn bù fēn",挑牙料唇:"tiǎo yá liào chún",挑么挑六:"tiāo yāo tiāo liù",挑唇料嘴:"tiǎo chún liào zuǐ",恬不为意:"tián bù wéi yì",恬不为怪:"tián bù wéi guài",天下为笼:"tiān xià wéi lóng",天台路迷:"tiān tái lù mí",天年不遂:"tiān nián bú suì",探囊胠箧:"tàn náng qū qiè",谭言微中:"tán yán wēi zhòng",谈言微中:"tán yán wēi zhòng",狧穅及米:"shì kāng jí mǐ",随物应机:"suí wù yīng jī",搜岩采干:"sōu yán cǎi gàn",宋斤鲁削:"sòng jīn lǔ xuē",松筠之节:"sōng yún zhī jié",四亭八当:"sì tíng bā dàng",四马攒蹄:"sì mǎ cuán tí",四不拗六:"sì bú niù liù",思所逐之:"sī suǒ zhú zhī",丝恩发怨:"sī ēn fà yuàn",硕望宿德:"shuò wàng xiǔ dé",铄古切今:"shuò gǔ qiē jīn",顺风而呼:"shùn fēng ér hū",顺风吹火:"shùn fēng chuī huǒ",水中著盐:"shuǐ zhōng zhuó yán",双柑斗酒:"shuāng gān dǒu jiǔ",数米而炊:"shǔ mǐ ér chuī",数米量柴:"shǔ mǐ liáng chái",数理逻辑:"shù lǐ luó ji",数黑论黄:"shǔ hēi lùn huáng",数白论黄:"shǔ bái lùn huáng",束缊还妇:"shù yūn huán fù",束蒲为脯:"shù pú wéi pú",束椽为柱:"shù chuán wéi zhù",书缺有间:"shū quē yǒu jiàn",手足重茧:"shǒu zú chóng jiǎn",手足异处:"shǒu zú yì chǔ",手脚干净:"shǒu jiǎo gàn jìng",手不应心:"shǒu bù yīng xīn",螫手解腕:"shì shǒu jiě wàn",释知遗形:"shì zhī yí xíng",适时应务:"shì shí yīng wù",适情率意:"shì qíng shuài yì",适当其冲:"shì dāng qí chōng",视为知己:"shì wéi zhī jǐ",使羊将狼:"shǐ yáng jiàng láng",食为民天:"shí wéi mín tiān",拾掇无遗:"shí duō wú yí",实与有力:"shí yù yǒu lì",石英玻璃:"shí yīng bō li",石室金匮:"shí shì jīn guì",什袭珍藏:"shí xí zhēn cáng",什伍东西:"shí wǔ dōng xī",什围伍攻:"shí wéi wǔ gōng",十魔九难:"shí mó jiǔ nàn",诗书发冢:"shī shū fà zhǒng",虱处裈中:"shī chǔ kūn zhōng",师直为壮:"shī zhí wéi zhuàng",尸居龙见:"shī jū lóng xiàn",圣经贤传:"shèng jīng xián zhuàn",圣君贤相:"shèng jūn xián xiàng",生拖死拽:"shēng tuō sǐ zhuài",审己度人:"shěn jǐ duó rén",神武挂冠:"shén wǔ guà guàn",神龙失埶:"shén lóng shī shì",深文曲折:"shēn wén qǔ shé",深厉浅揭:"shēn lì qiǎn qì",深谷为陵:"shēn gǔ wéi líng",深恶痛疾:"shēn wù tòng jí",深仇宿怨:"shēn chóu xiǔ yuàn",舍己为公:"shě jǐ wèi gōng",舍短取长:"shě duǎn qǔ cháng",舍策追羊:"shě cè zhuī yáng",蛇蝎为心:"shé xiē wéi xīn",少成若性:"shào chéng ruò xìng",上当学乖:"shàng dàng xué guāi",赏不当功:"shǎng bù dāng gōng",善自为谋:"shàn zì wéi móu",善为说辞:"shàn wéi shuō cí",善善恶恶:"shàn shàn wù è",善财难舍:"shàn cái nán shě",苫眼铺眉:"shān yǎn pū méi",讪牙闲嗑:"shàn yá xián kē",山阴乘兴:"shān yīn chéng xīng",山殽野湋:"shān yáo yě wéi",山溜穿石:"shān liù chuān shí",山节藻棁:"shān jié zǎo zhuō",杀鸡为黍:"shā jī wéi shǔ",色厉胆薄:"sè lì dǎn bó",桑荫未移:"sāng yīn wèi yí",桑荫不徙:"sāng yīn bù xǐ",桑土绸缪:"sāng tǔ chóu miù",桑户棬枢:"sāng hù juàn shū",三战三北:"sān zhàn sān běi",三瓦两舍:"sān wǎ liǎng shě",三人为众:"sān rén wèi zhòng",三差两错:"sān chā liǎng cuò",塞井焚舍:"sāi jǐng fén shě",洒心更始:"sǎ xīn gèng shǐ",洒扫应对:"sǎ sǎo yìng duì",软红香土:"ruǎn hóng xiāng tǔ",入吾彀中:"rù wú gòu zhōng",入铁主簿:"rù tiě zhǔ bù",入理切情:"rù lǐ qiē qíng",汝成人耶:"rǔ chéng rén yé",如水投石:"rú shuǐ tóu shí",如切如磋:"rú qiē rú cuō",如登春台:"rú dēng chūn tái",肉薄骨并:"ròu bó gǔ bìng",柔情绰态:"róu qíng chuò tài",戎马劻勷:"róng mǎ kuāng ráng",日中为市:"rì zhōng wéi shì",日月参辰:"rì yuè shēn chén",日省月修:"rì xǐng yuè xiū",日削月割:"rì xuē yuè gē",日省月试:"rì xǐng yuè shì",任达不拘:"rèn dá bù jū",人言藉藉:"rén yán jí jí",人模狗样:"rén mú gǒu yàng",人莫予毒:"rén mò yú dú",热熬翻饼:"rè áo fān bǐng",圈牢养物:"juàn láo yǎng wù",取予有节:"qǔ yǔ yǒu jié",诎要桡腘:"qū yāo ráo guó",穷形尽相:"qióng xíng jìn xiàng",情凄意切:"qíng qī yì qiè",情见势屈:"qíng xiàn shì qū",情见乎辞:"qíng xiàn hū cí",清都绛阙:"qīng dōu jiàng què",倾肠倒肚:"qīng cháng dào dǔ",青紫被体:"qīng zǐ pī tǐ",青林黑塞:"qīng lín hēi sài",螓首蛾眉:"qín shǒu é méi",琴瑟之好:"qín sè zhī hào",且住为佳:"qiě zhù wéi jiā",切树倒根:"qiē shù dǎo gēn",切理餍心:"qiē lǐ yàn xīn",切近的当:"qiē jìn de dāng",翘足引领:"qiáo zú yǐn lǐng",巧发奇中:"qiǎo fā qí zhòng",强嘴拗舌:"jiàng zuǐ niù shé",强直自遂:"qiáng zhí zì suí",强死强活:"qiǎng sǐ qiǎng huó",强食自爱:"qiǎng shí zì ài",强食靡角:"qiǎng shí mí jiǎo",强弓劲弩:"qiáng gōng jìng nǔ",强聒不舍:"qiǎng guō bù shě",强凫变鹤:"qiáng fú biàn hè",强而后可:"qiǎng ér hòu kě",强得易贫:"qiǎng dé yì pín",遣兴陶情:"qiǎn xìng táo qíng",牵羊担酒:"qiān yáng dān jiǔ",千了百当:"qiān liǎo bǎi dàng",泣下如雨:"qì xià rú yǔ",起偃为竖:"qǐ yǎn wéi shù",岂弟君子:"kǎi tì jūn zǐ",綦溪利跂:"qí xī lì qí",棋输先著:"qí shū xiān zhuó",齐王舍牛:"qí wáng shě niú",欺天诳地:"qī tiān kuáng dì",普天率土:"pǔ tiān shuài tǔ",铺胸纳地:"pū xiōng nà dì",铺锦列绣:"pū jǐn liè xiù",破家为国:"pò jiā wèi guó",破觚为圜:"pò gū wéi yuán",萍飘蓬转:"píng piāo péng zhuàn",帡天极地:"píng tiān jí dì",屏声息气:"bǐng shēng xī qì",凭几据杖:"píng jī jù zhàng",贫嘴薄舌:"pín zuǐ bó shé",片语只辞:"piàn yǔ zhī cí",披发文身:"pī fà wén shēn",烹龙炮凤:"pēng lóng páo fèng",炰鳖脍鲤:"fǒu biē kuài lǐ",庞眉皓发:"páng méi hào fà",攀花折柳:"pān huā zhé liǔ",攀蟾折桂:"pān chán shé guì",女大难留:"nǚ dà nán liú",弄玉吹箫:"nòng yù chuī xiāo",弄管调弦:"nòng guǎn tiáo xián",弄粉调朱:"nòng fěn diào zhū",浓抹淡妆:"nóng mò dàn zhuāng",捻土为香:"niǎn tǔ wéi xiāng",年谊世好:"nián yì shì hǎo",年华垂暮:"nián huá chuí mù",儗不于伦:"nǐ bù yú lún",泥而不滓:"ní ér bù zǐ",能者为师:"néng zhě wéi shī",能不称官:"néng bú chèn guān",挠直为曲:"náo zhí wéi qū",难进易退:"nán jìn yì tuì",难得糊涂:"nán dé hú tú",南蛮鴂舌:"nán mán jué shé",南贩北贾:"nán fàn běi gǔ",牧猪奴戏:"mù zhū nú xì",目眢心忳:"mù yuān xīn tún",目挑心招:"mù tiǎo xīn zhāo",目量意营:"mù liàng yì yíng",木头木脑:"mù tóu mù nǎo",木干鸟栖:"mù gàn niǎo qī",侔色揣称:"móu sè chuǎi chèn",莫予毒也:"mò yú dú yě",抹粉施脂:"mò fěn shī zhī",磨砻镌切:"mó lóng juān qiē",磨棱刓角:"mó léng wán jiǎo",摸门不着:"mō mén bù zháo",摸不着边:"mō bù zhuó biān",命中注定:"mìng zhōng zhù dìng",鸣鹤之应:"míng hè zhī yìng",明效大验:"míng xiào dà yàn",名我固当:"míng wǒ gù dāng",邈处欿视:"miǎo chǔ kǎn shì",黾穴鸲巢:"měng xué qú cháo",绵里薄材:"mián lǐ bó cái",靡有孑遗:"mǐ yǒu jié yí",靡衣偷食:"mǐ yī tōu shí",迷恋骸骨:"mí liàn hái gǔ",扪参历井:"mén shēn lì jǐng",门单户薄:"mén dān hù bó",昧旦晨兴:"mèi dàn chén xīng",冒名接脚:"mào míng jiē jiǎo",毛遂堕井:"máo suí duò jǐng",毛发倒竖:"máo fā dǎo shù",卖文为生:"mài wén wéi shēng",卖李钻核:"mài lǐ zuān hé",买椟还珠:"mǎi dú huán zhū",埋三怨四:"mán sān yuàn sì",马入华山:"mǎ rù huá shān",落魄江湖:"luò pò jiāng hú",落落难合:"luò luò nán hé",落草为寇:"luò cǎo wéi kòu",罗织构陷:"luó zhī gòu xiàn",鸾凤和鸣:"luán fèng hè míng",率由旧章:"shuài yóu jiù zhāng",率土同庆:"shuài tǔ tóng qìng",率兽食人:"shuài shòu shí rén",率土归心:"shuài tǔ guī xīn",率马以骥:"shuài mǎ yǐ jì",率尔成章:"shuài ěr chéng zhāng",鲁斤燕削:"lǔ jīn yàn xuē",漏尽更阑:"lòu jìn gēng lán",笼鸟槛猿:"lóng niǎo jiàn yuán",笼鸟池鱼:"lóng niǎo chí yú",龙游曲沼:"lóng yóu qū zhǎo",龙血玄黄:"lóng xuè xuán huáng",龙雕凤咀:"lóng diāo fèng jǔ",六尺之讬:"liù chǐ zhī tuō",令原之戚:"líng yuán zhī qī",令人捧腹:"lìng rén pěng fù",陵劲淬砺:"líng jìng cuì lì",临敌易将:"lín dí yì jiàng",裂裳衣疮:"liè shang yī chuāng",裂冠毁冕:"liè guàn huǐ miǎn",了无惧色:"liǎo wú jù sè",了身达命:"liǎo shēn dá mìng",了然无闻:"liǎo rán wú wén",了不可见:"liǎo bù kě jiàn",了不长进:"liǎo bù zhǎng jìn",燎发摧枯:"liǎo fà cuī kū",审时度势:"shěn shí duó shì",量小力微:"liàng xiǎo lì wēi",相时度力:"xiāng shí duó lì",量枘制凿:"liàng ruì zhì záo",量如江海:"liàng rú jiāng hǎi",量金买赋:"liàng jīn mǎi fù",量己审分:"liàng jǐ shěn fēn",敛骨吹魂:"liǎn gǔ chuī hún",詈夷为跖:"lì yí wéi zhí",利令志惛:"lì lìng zhì hūn",李广不侯:"lǐ guǎng bú hòu",礼为情貌:"lǐ wéi qíng mào",礼让为国:"lǐ ràng wéi guó",犁生骍角:"lí shēng xīng jiǎo",离本徼末:"lí běn jiǎo mò",楞眉横眼:"léng méi hèng yǎn",擂天倒地:"léi tiān dǎo dì",累足成步:"lěi zú chéng bù",累瓦结绳:"lěi wǎ jié shéng",累土至山:"lěi tǔ zhì shān",累土聚沙:"lěi tǔ jù shā",累卵之危:"lěi luǎn zhī wēi",累累如珠:"lěi lěi rú zhū",累块积苏:"lěi kuài jī sū",乐山乐水:"lè shān lè shuǐ",潦原浸天:"lǎo yuán jìn tiān",老师宿儒:"lǎo shī xiǔ rú",牢什古子:"láo shí gǔ zi",琅嬛福地:"láng huán fú dì",揆情度理:"kuí qíng duó lǐ",旷日累时:"kuàng rì lěi shí",匡救弥缝:"kuāng jiù mí fèng",枯树生华:"kū shù shēng huā",口轻舌薄:"kǒu qīng shé bó",口角生风:"kǒu jiǎo shēng fēng",口角春风:"kǒu jiǎo chūn fēng",口角风情:"kǒu jiǎo fēng qíng",口干舌焦:"kǒu gān shé jiāo",口腹之累:"kǒu fù zhī lěi",空腹便便:"kōng fù pián pián",嗑牙料嘴:"kē yá liào zuǐ",刻木为鹄:"kè mù wéi hú",咳珠唾玉:"ké zhū tuò yù",咳唾成珠:"ké tuò chéng zhū",抗颜为师:"kàng yán wéi shī",开华结果:"kāi huā jié guǒ",峻阪盐车:"jùn bǎn yán chē",嚼铁咀金:"jiáo tiě jǔ jīn",嚼墨喷纸:"jué mò pēn zhǐ",倔头强脑:"juè tóu jiàng nǎo",倔头倔脑:"juè tóu juè nǎo",倦鸟知还:"juàn niǎo zhī huán",卷席而葬:"juǎn xí ér zàng",卷甲倍道:"juǎn jiǎ bèi dào",聚米为山:"jù mǐ wéi shān",举手相庆:"jǔ shǒu xiāng qìng",举世混浊:"jǔ shì hún zhuó",鞠为茂草:"jū wéi mào cǎo",拘神遣将:"jū shén qiǎn jiàng",居下讪上:"jū xià shàn shàng",久要不忘:"jiǔ yāo bú wàng",九转功成:"jiǔ zhuǎn gōng chéng",九蒸三熯:"jiǔ zhēng sān hàn",敬业乐群:"jìng yè lè qún",井底虾蟆:"jǐng dǐ xiā má",旌旗卷舒:"jīng qí juǎn shū",荆棘载途:"jīng jí zài tú",禁舍开塞:"jìn shě kāi sāi",祲威盛容:"jìn wēi shèng róng",进退消长:"jìn tuì xiāo cháng",进退应矩:"jìn tuì yīng jǔ",进退触籓:"jìn tuì chù fān",进退跋疐:"jìn tuì bá zhì",尽多尽少:"jǐn duō jǐn shǎo",锦囊还矢:"jǐn náng huán shǐ",矜己自饰:"jīn jǐ zì shì",矜功负气:"jīn gōng fù qì",津关险塞:"jīn guān xiǎn sài",金吾不禁:"jīn wú bú jìn",金翅擘海:"jīn chì bāi hǎi",解衣衣人:"jiě yī yī rén",解人难得:"jiě rén nán dé",解铃系铃:"jiě líng xì líng",解发佯狂:"jiě fà yáng kuáng",诘屈磝碻:"jié qū áo qiāo",教猱升木:"jiāo náo shēng mù",较瘦量肥:"jiào shòu liàng féi",角立杰出:"jiǎo lì jié chū",焦沙烂石:"jiāo shā làn shí",骄儿騃女:"jiāo ér sì nǚ",浇风薄俗:"jiāo fēng bó sú",降妖捉怪:"xiáng yāo zhuō guài",将取固予:"jiāng qǔ gù yǔ",将门有将:"jiàng mén yǒu jiàng",将夺固与:"jiāng duó gù yǔ",槛花笼鹤:"jiàn huā lóng hè",鉴影度形:"jiàn yǐng duó xíng",渐不可长:"jiàn bù kě zhǎng",见素抱朴:"xiàn sù bào pǔ",见弃于人:"jiàn qì yú rén",简丝数米:"jiǎn sī shǔ mǐ",俭不中礼:"jiǎn bú zhòng lǐ",间见层出:"jiàn xiàn céng chū",尖嘴薄舌:"jiān zuǐ bó shé",甲冠天下:"jiǎ guàn tiān xià",葭莩之亲:"jiā fú zhī qīn",家累千金:"jiā lèi qiān jīn",家给人足:"jiā jǐ rén zú",家道从容:"jiā dào cóng róng",夹袋人物:"jiā dài rén wù",霁风朗月:"jì fēng lǎng yuè",寄兴寓情:"jì xìng yù qíng",计深虑远:"jì shēn lǜ yuǎn",计功量罪:"jì gōng liàng zuì",掎裳连襼:"jǐ shang lián yì",虮虱相吊:"jǐ shī xiāng diào",疾不可为:"jí bù kě wéi",极深研几:"jí shēn yán jī",及宾有鱼:"jí bīn yǒu yú",激薄停浇:"jī bó tíng jiāo",积素累旧:"jī sù lěi jiù",积时累日:"jī shí lěi rì",积露为波:"jī lù wéi bō",积德累功:"jī dé lěi gōng",积谗糜骨:"jī chán méi gǔ",击排冒没:"jī pái mào mò",祸为福先:"huò wéi fú xiān",祸福相依:"huò fú xiāng yī",获隽公车:"huò jùn gōng chē",混应滥应:"hùn yīng làn yīng",毁舟为杕:"huǐ zhōu wéi duò",毁钟为铎:"huǐ zhōng wéi duó",毁冠裂裳:"huǐ guān liè cháng",晦盲否塞:"huì máng pǐ sè",回船转舵:"huí chuán zhuàn duò",潢池盗弄:"huáng chí dào nòng",黄冠草履:"huáng guàn cǎo lǚ",黄发儿齿:"huáng fà ér chǐ",黄发垂髫:"huáng fà chuí tiáo",还珠返璧:"huán zhū fǎn bì",还年驻色:"huán nián zhù sè",还年却老:"huán nián què lǎo",坏裳为裤:"huài shang wéi kù",画荻和丸:"huà dí huò wán",化枭为鸠:"huà xiāo wéi jiū",化腐为奇:"huà fǔ wéi qí",化鸱为凤:"huà chī wéi fèng",花不棱登:"huā bu lēng dēng",户限为穿:"hù xiàn wéi chuān",呼卢喝雉:"hū lú hè zhì",呼来喝去:"hū lái hè qù",呼不给吸:"hū bù jǐ xī",厚味腊毒:"hòu wèi xī dú",厚德载物:"hòu dé zài wù",鸿渐于干:"hóng jiàn yú gàn",洪炉燎发:"hóng lú liáo fà",红绳系足:"hóng shéng jì zú",红不棱登:"hóng bu lēng dēng",横抢硬夺:"hèng qiǎng yìng duó",横恩滥赏:"hèng ēn làn shǎng",恨海难填:"hèn hǎi nán tián",鹤发鸡皮:"hè fà jī pí",涸思干虑:"hé sī gān lǜ",河涸海干:"hé hé hǎi gān",和颜说色:"hé yán yuè sè",合从连衡:"hé zòng lián héng",浩浩汤汤:"hào hào shāng shāng",好勇斗狠:"hào yǒng dòu hěn",好问则裕:"hào wèn zé yù",好为事端:"hào wéi shì duān",好问决疑:"hào wèn jué yí",好生之德:"hào shēng zhī dé",好奇尚异:"hǎo qí shàng yì",好恶不同:"hǎo è bù tóng",好丹非素:"hào dān fēi sù",豪干暴取:"háo gàn bào qǔ",毫发不爽:"háo fà bù shuǎng",寒酸落魄:"hán suān luò pò",含英咀华:"hán yīng jǔ huá",含糊不明:"hán hú bù míng",过为已甚:"guò wéi yǐ shèn",桂折兰摧:"guì shé lán cuī",规旋矩折:"guī xuán jǔ shé",广文先生:"guǎng wén xiān sheng",广陵散绝:"guǎng líng sǎn jué",冠山戴粒:"guàn shān dài lì",冠屦倒施:"guàn jù dǎo shī",挂席为门:"guà xí wéi mén",寡见鲜闻:"guǎ jiàn xiǎn wén",瓜葛相连:"guā gé xiāng lián",鼓吻奋爪:"gǔ wěn fèn zhǎo",古调单弹:"gǔ diào dān tán",古调不弹:"gǔ diào bù tán",姑射神人:"gū yè shén rén",苟合取容:"gǒu hé qǔ róng",狗续侯冠:"gǒu xù hòu guàn",钩爪锯牙:"gōu zhǎo jù yá",共枝别干:"gòng zhī bié gàn",共为唇齿:"gòng wéi chún chǐ",拱手而降:"gǒng shǒu ér xiáng",拱肩缩背:"gǒng jiān suō bèi",功薄蝉翼:"gōng bó chán yì",弓调马服:"gōng diào mǎ fú",更姓改物:"gēng xìng gǎi wù",更仆难数:"gēng pú nán shǔ",更令明号:"gēng lìng míng hào",更待干罢:"gèng dài gàn bà",更唱迭和:"gēng chàng dié hé",更长梦短:"gēng cháng mèng duǎn",各色名样:"gè sè míng yàng",格格不纳:"gé gé bú nà",格格不吐:"gé gé bù tǔ",告朔饩羊:"gù shuò xì yáng",膏车秣马:"gào chē mò mǎ",高义薄云:"gāo yì bó yún",岗头泽底:"gāng tóu zé dǐ",敢为敢做:"gǎn wéi gǎn zuò",甘分随时:"gān fèn suí shí",甘处下流:"gān chǔ xià liú",干啼湿哭:"gàn tí shī kū",干名犯义:"gàn míng fàn yì",干将莫邪:"gān jiāng mò yé",干城之将:"gān chéng zhī jiàng",腹载五车:"fù zài wǔ chē",父债子还:"fù zhài zǐ huán",父为子隐:"fù wéi zǐ yǐn",辅世长民:"fǔ shì zhǎng mín",福为祸始:"fú wéi huò shǐ",符号逻辑:"fú hào luó jí",浮收勒折:"fú shōu lè shé",肤受之愬:"fū shòu zhī sù",否终则泰:"pǐ zhōng zé tài",佛头著粪:"fó tóu zhuó fèn",奉为楷模:"fèng wéi kǎi mó",凤靡鸾吪:"fèng mǐ luán é",封豨修蛇:"fēng xī xiū shé",风影敷衍:"fēng yǐng fū yǎn",丰屋蔀家:"fēng wū bù jiā",粪土不如:"fèn tǔ bù rú",分风劈流:"fēn fēng pǐ liú",沸沸汤汤:"fèi fèi shāng shāng",菲食薄衣:"fěi shí bó yī",飞将数奇:"fēi jiàng shù qí",放辟邪侈:"fàng pì xié chǐ",方领圆冠:"fāng lǐng yuán guàn",犯而不校:"fàn ér bú jiào",返本还源:"fǎn běn huán yuán",反劳为逸:"fǎn láo wéi yì",法轮常转:"fǎ lún cháng zhuàn",罚不当罪:"fá bù dāng zuì",发引千钧:"fà yǐn qiān jūn",发奸擿伏:"fā jiān tī fú",发短心长:"fà duǎn xīn cháng",二竖为虐:"èr shù wéi nüè",儿女心肠:"ér nǚ xīn cháng",儿女亲家:"ér nǚ qìng jiā",遏恶扬善:"è wù yáng shàn",饿殍枕藉:"è piǎo zhěn jí",饿殍载道:"è piǎo zài dào",恶醉强酒:"wù zuì qiǎng jiǔ",恶意中伤:"è yì zhòng shāng",恶湿居下:"wù shī jū xià",恶居下流:"wù jū xià liú",恶不去善:"wù bú qù shàn",扼吭夺食:"è háng duó shí",扼襟控咽:"è jīn kòng yān",峨峨汤汤:"é é shāng shāng",屙金溺银:"ē jīn niào yín",朵颐大嚼:"duǒ yí dà jiáo",夺人所好:"duó rén suǒ hào",多言数穷:"duō yán shuò qióng",多文为富:"duō wén wéi fù",多端寡要:"duō duān guǎ yào",多财善贾:"duō cái shàn gǔ",遁世无闷:"dùn shì wú mèn",遁迹黄冠:"dùn jì huáng guàn",堆案盈几:"duī àn yíng jī",断还归宗:"duàn huán guī zōng",短见薄识:"duǎn jiàn bó shí",蠹居棊处:"dù jū qí chǔ",度己以绳:"duó jǐ yǐ shéng",杜默为诗:"dù mò wéi shī",杜鹃啼血:"dù juān tí xuè",笃近举远:"dǔ jìn jǔ yuǎn",独有千秋:"dú yǒu qiān qiū",读书得间:"dú shū dé jiàn",斗转参横:"dǒu zhuǎn shēn héng",兜肚连肠:"dōu dǔ lián cháng",洞见症结:"dòng jiàn zhèng jié",恫疑虚喝:"dòng yí xū hè",动中窾要:"dòng zhōng kuǎn yào",东鸣西应:"dōng míng xī yīng",东鳞西爪:"dōng lín xī zhǎo",东量西折:"dōng liàng xī shé",东家西舍:"dōng jiā xī shè",东扯西拽:"dōng chě xī zhuāi",鼎铛有耳:"dǐng chēng yǒu ěr",鼎铛玉石:"dǐng chēng yù shí",钉头磷磷:"dīng tóu lín lín",跌宕不羁:"diē dàng bù jī",跌弹斑鸠:"diē dàn bān jiū",雕心雁爪:"diāo xīn yàn zhǎo",颠倒衣裳:"diān dǎo yī cháng",德薄能鲜:"dé bó néng xiǎn",得马折足:"dé mǎ shé zú",蹈其覆辙:"dǎo qí fù zhé",捣虚撇抗:"dǎo xū piē kàng",倒载干戈:"dào zài gān gē",倒裳索领:"dào cháng suǒ lǐng",倒果为因:"dào guǒ wéi yīn",叨在知己:"tāo zài zhī jǐ",叨陪末座:"tāo péi mò zuò",党豺为虐:"dǎng chái wéi nüè",当轴处中:"dāng zhóu chǔ zhōng",当着不着:"dāng zhuó bù zhuó",当务始终:"dāng wù shǐ zhōng",淡汝浓抹:"dàn rǔ nóng mǒ",弹丸脱手:"tán wán tuō shǒu",弹铗无鱼:"dàn jiá wú yú",箪食瓢饮:"dān sì piáo yǐn",大璞不完:"dà pú bù wán",大明法度:"dà míng fǎ dù",大车以载:"dà chē yǐ zài",打闷葫芦:"dǎ mèn hú lu",沓来踵至:"tà lái zhǒng zhì",厝火燎原:"cuò huǒ liǎo yuán",撮科打哄:"cuō kē dǎ hòng",寸积铢累:"cùn jī zhū lěi",啛啛喳喳:"cuì cuì chā chā",摧折豪强:"cuī zhé háo qiáng",摧刚为柔:"cuī gāng wéi róu",从俗就简:"cóng sú jiù jiǎn",此发彼应:"cǐ fā bǐ yīng",此唱彼和:"cǐ chàng bǐ hè",慈悲为本:"cí bēi wéi běn",纯属骗局:"chún shǔ piàn jú",春笋怒发:"chūn sǔn nù fā",垂头搨翼:"chuí tóu tà yì",传为笑谈:"chuán wéi xiào tán",传风扇火:"chuán fēng shān huǒ",穿红着绿:"chuān hóng zhuó lǜ",触处机来:"chù chǔ jī lái",处尊居显:"chǔ zūn jū xiǎn",处堂燕雀:"chǔ táng yàn què",处实效功:"chǔ shí xiào gōng",处高临深:"chǔ gāo lín shēn",出入无间:"chū rù wú jiān",出门应辙:"chū mén yīng zhé",出处语默:"chū chǔ yǔ mò",出处殊途:"chū chǔ shū tú",出处进退:"chū chǔ jìn tuì",愁山闷海:"chóu shān mèn hǎi",冲冠眦裂:"chōng guàn zì liè",齿牙为祸:"chǐ yá wéi huò",尺二冤家:"chǐ èr yuān jia",尺短寸长:"chǐ duǎn cùn cháng",尺寸之功:"chǐ cùn zhī gōng",城北徐公:"chéng běi xú gōng",成败兴废:"chéng bài xīng fèi",趁水和泥:"chèn shuǐ huò ní",称雨道晴:"chēng yǔ dào qíng",称体载衣:"chēng tǐ zài yī",称体裁衣:"chèn tǐ cái yī",称家有无:"chèn jiā yǒu wú",称德度功:"chēng dé duó gōng",沉吟章句:"chén yín zhāng jù",沉吟不决:"chén yín bù jué",沉疴宿疾:"chén kē sù jí",扯纤拉烟:"chě qiàn lā yān",扯顺风旗:"chě shùn fēng qí",车载船装:"chē zǎi chuán zhuāng",朝升暮合:"zhāo shēng mù gě",朝攀暮折:"zhāo pān mù shé",超今冠古:"chāo jīn guàn gǔ",倡而不和:"chàng ér bú hè",畅所欲为:"chàng suǒ yù wéi",苌弘碧血:"cháng hóng bì xiě",长幼尊卑:"zhǎng yòu zūn bēi",长绳系日:"cháng shéng jì rì",长年三老:"zhǎng nián sān lǎo",长春不老:"cháng chūn bù lǎo",长傲饰非:"zhǎng ào shì fēi",昌亭旅食:"chāng tíng lǚ shí",禅絮沾泥:"chán xù zhān ní",差三错四:"chā sān cuò sì",层台累榭:"céng tái lěi xiè",层见迭出:"céng xiàn dié chū",藏踪蹑迹:"cáng zōng niè jì",苍蝇见血:"cāng yíng jiàn xiě",餐松啖柏:"cān sōng dàn bó",骖风驷霞:"cān fēng sì xiá",参伍错综:"cēn wǔ cuò zōng",参辰卯酉:"shēn chén mǎo yǒu",材优干济:"cái yōu gān jǐ",材薄质衰:"cái bó zhì shuāi",才大难用:"cái dà nán yòng",才薄智浅:"cái bó zhì qiǎn",不足为意:"bù zú wéi yì",不足为据:"bù zú wéi jù",不足为法:"bù zú wéi fǎ",不足齿数:"bù zú chǐ shǔ",不着疼热:"bù zhuó téng rè",不知薡蕫:"bù zhī dǐng dǒng",不越雷池:"bú yuè léi chí",不相为谋:"bù xiāng wéi móu",不贪为宝:"bù tān wéi bǎo",不了而了:"bù liǎo ér liǎo",不可揆度:"bù kě kuí duó",不遑启处:"bù huáng qǐ chǔ",不当不正:"bù dāng bú zhèng",不差什么:"bú chà shén me",不差累黍:"bù chā lěi shǔ",擘两分星:"bò liǎng fēn xīng",簸土扬沙:"bǒ tǔ yáng shā",薄物细故:"bó wù xì gù",薄寒中人:"bó hán zhòng rén",博文约礼:"bó wén yuē lǐ",播糠眯目:"bō kāng mí mù",剥皮抽筋:"bō pí chōu jīn",剥肤椎髓:"bō fū chuí suǐ",波属云委:"bō zhǔ yún wěi",波骇云属:"bō hài yún zhǔ",兵微将寡:"bīng wēi jiàng guǎ",兵强将勇:"bīng qiáng jiàng yǒng",兵多将广:"bīng duō jiàng guǎng",兵不由将:"bīng bù yóu jiàng",冰解的破:"bīng jiě dì pò",彬彬济济:"bīn bīn jǐ jǐ",摽梅之年:"biào méi zhī nián",表里为奸:"biǎo lǐ wéi jiān",飙发电举:"biāo fā diàn jǔ",变贪厉薄:"biàn tān lì bó",敝盖不弃:"bì gài bú qì",秕言谬说:"bǐ yán miù shuō",比物属事:"bǐ wù zhǔ shì",被山带河:"pī shān dài hé",被甲枕戈:"pī jiǎ zhěn gē",被甲据鞍:"pī jiǎ jù ān",被褐怀玉:"pī hè huái yù",被发缨冠:"pī fà yīng guàn",背曲腰躬:"bèi qǔ yāo gōng",北窗高卧:"běi chuāng gāo wò",北辰星拱:"běi chén xīng gǒng",北鄙之音:"běi bǐ zhī yīn",卑宫菲食:"bēi gōng fěi shí",暴衣露冠:"pù yī lù guàn",暴腮龙门:"pù sāi lóng mén",暴露文学:"bào lù wén xué",暴虎冯河:"bào hǔ píng hé",抱蔓摘瓜:"bào wàn zhāi guā",抱法处势:"bào fǎ chǔ shì",褒贬与夺:"bāo biǎn yǔ duó",帮闲钻懒:"bāng xián zuān lǎn",拜将封侯:"bài jiàng fēng hóu",百兽率舞:"bǎi shòu shuài wǔ",百孔千创:"bǎi kǒng qiān chuāng",白衣卿相:"bái yī qīng xiàng",白首为郎:"bái shǒu wéi láng",白首相知:"bái shǒu xiāng zhī",把玩无厌:"bǎ wán wú yàn",拔锅卷席:"bá guō juǎn xí",拔本塞源:"bá běn sè yuán",傲不可长:"ào bù kě zhǎng",熬更守夜:"áo gēng shǒu yè",安时处顺:"ān shí chǔ shùn",安身为乐:"ān shēn wéi lè",安老怀少:"ān lǎo huái shào",安步当车:"ān bù dàng chē",爱人好士:"ài rén hào shì",矮人观场:"ǎi rén guān chǎng",捱风缉缝:"ái fēng jī fèng",挨山塞海:"āi shān sè hǎi",阿家阿翁:"ā jiā ā wēng",阿党相为:"ē dǎng xiāng wéi",追亡逐北:"zhuī wáng zhú běi",竹篮打水:"zhú lán dá shuǐ",知疼着热:"zhī téng zháo rè",语不惊人:"yǔ bù jīng rén",于今为烈:"yú jīn wéi liè",一日三省:"yí rì sān xǐng",穴居野处:"xué jū yě chǔ",五脊六兽:"wǔ jǐ liù shòu",无声无臭:"wú shēng wú xiù",谓予不信:"wèi yú bú xìn",舍身为国:"shě shēn wéi guó",杀妻求将:"shā qī qiú jiàng",强作解人:"qiǎng zuò jiě rén",气冲斗牛:"qì chōng dǒu niú",临深履薄:"lín shēn lǚ bó",钧天广乐:"jūn tiān guǎng yuè",艰难竭蹶:"jiān nán jié jué",夹七夹八:"jiā qī jiā bā",混混噩噩:"hún hún è è",厚古薄今:"hòu gǔ bó jīn",鬼怕恶人:"guǐ pà è rén",伽马射线:"gā mǎ shè xiàn",佛头着粪:"fó tóu zhuó fèn",奉为至宝:"fèng wéi zhì bǎo",登坛拜将:"dēng tán bài jiàng",晨昏定省:"chén hūn dìng xǐng",察察为明:"chá chá wéi míng",博闻强识:"bó wén qiáng zhì",避难就易:"bì nán jiù yì",了无生机:'liǎo wú shēng jī',有一说一:'yǒu yī shuō yī',独一无二:'dú yī wú èr',说一不二:'shuō yī bù èr',举一反三:'jǔ yī fǎn sān',数一数二:'shǔ yī shǔ èr',杀一儆百:'shā yī jǐng bǎi',丁一卯二:'dīng yī mǎo èr',丁一确二:'dīng yī què èr',不一而止:'bù yī ér zhǐ',无一幸免:'wú yī xìng miǎn',表里不一:'biǎo lǐ bù yī',良莠不一:'liáng yǒu bù yī',心口不一:'xīn kǒu bù yī',言行不一:'yán xíng bù yī',政令不一:'zhèng lìng bù yī',参差不一:'cēn cī bù yī',纷纷不一:'fēn fēn bù yī',毁誉不一:'huǐ yù bù yī',不一而三:'bù yī ér sān',百不一遇:'bǎi bù yī yù',言行抱一:'yán xíng bào yī',瑜百瑕一:'yú bǎi xiá yī',背城借一:'bèi chéng jiè yī',凭城借一:'píng chéng jiè yī',劝百讽一:'quàn bǎi fěng yī',群居和一:'qún jū hé yī',百不获一:'bǎi bù huò yī',百不失一:'bǎi bù shī yī',百无失一:'bǎi wú shī yī',万不失一:'wàn bù shī yī',万无失一:'wàn wú shī yī',合而为一:'hé ér wéi yī',合两为一:'hé liǎng wéi yī',合二为一:'hé èr wéi yī',天下为一:'tiān xià wéi yī',相与为一:'xiāng yǔ wéi yī',较若画一:'jiào ruò huà yī',较如画一:'jiào rú huà yī',斠若画一:'jiào ruò huà yī',言行若一:'yán xíng ruò yī',始终若一:'shǐ zhōng ruò yī',终始若一:'zhōng shǐ ruò yī',惟精惟一:'wéi jīng wéi yī',众多非一:'zhòng duō fēi yī',不能赞一:'bù néng zàn yī',问一答十:'wèn yī dá shí',一不扭众:'yī bù niǔ zhòng',一以贯之:'yī yǐ guàn zhī',一以当百:'yī yǐ dāng bǎi',百不当一:'bǎi bù dāng yī',十不当一:'shí bù dāng yī',以一警百:'yǐ yī jǐng bǎi',以一奉百:'yǐ yī fèng bǎi',以一持万:'yǐ yī chí wàn',以一知万:'yǐ yī zhī wàn',百里挑一:'bǎi lǐ tiāo yī',整齐划一:'zhěng qí huà yī',一来二去:'yī lái èr qù',一路公交:'yī lù gōng jiāo',一路汽车:'yī lù qì chē',一路巴士:'yī lù bā shì',朝朝朝落:'zhāo cháo zhāo luò',曲意逢迎:'qū yì féng yíng',一行不行:'yì háng bù xíng',行行不行:'háng háng bù xíng'};const Pattern4=Object.keys(DICT4).map((key)=>({zh:key,pinyin:DICT4[key],probability:2e-8,length:4,priority:Priority.Normal,dict:Symbol('dict4'),}));const DICT5={巴尔干半岛:'bā ěr gàn bàn dǎo',巴尔喀什湖:'bā ěr kā shí hú',不幸而言中:'bú xìng ér yán zhòng',布尔什维克:'bù ěr shí wéi kè',何乐而不为:'hé lè ér bù wéi',苛政猛于虎:'kē zhèng měng yú hǔ',蒙得维的亚:'méng dé wéi dì yà',民以食为天:'mín yǐ shí wéi tiān',事后诸葛亮:'shì hòu zhū gě liàng',物以稀为贵:'wù yǐ xī wéi guì',先下手为强:'xiān xià shǒu wéi qiáng',行行出状元:'háng háng chū zhuàng yuan',亚得里亚海:'yà dé lǐ yà hǎi',眼不见为净:'yǎn bú jiàn wéi jìng',竹筒倒豆子:'zhú tǒng dào dòu zi',};const Pattern5=Object.keys(DICT5).map((key)=>({zh:key,pinyin:DICT5[key],probability:2e-8,length:5,priority:Priority.Normal,dict:Symbol('dict5'),}));function getMaxProbability(a,b){if(!a){return b}if(a.decimalb.probability?a:b}else{return b}}function checkDecimal(prob){if(prob.probability<1e-300){prob.probability*=1e300;prob.decimal+=1}}function getPatternDecimal(pattern){if(pattern.priority===Priority.Custom){return-(pattern.length*pattern.length*100)}if(pattern.priority===Priority.Surname){return-(pattern.length*pattern.length*10)}return 0}function maxProbability(patterns,length){const dp=[];let patternIndex=patterns.length-1;let pattern=patterns[patternIndex];for(let i=length-1;i>=0;i--){const suffixDP=i+1>=length?{probability:1,decimal:0,patterns:[]}:dp[i+1];while(pattern&&pattern.index+pattern.length-1===i){const startIndex=pattern.index;const curDP={probability:pattern.probability*suffixDP.probability,decimal:suffixDP.decimal+getPatternDecimal(pattern),patterns:suffixDP.patterns,concatPattern:pattern,};checkDecimal(curDP);dp[startIndex]=getMaxProbability(dp[startIndex],curDP);pattern=patterns[--patternIndex]}const iDP={probability:1e-13*suffixDP.probability,decimal:0,patterns:suffixDP.patterns,};checkDecimal(iDP);dp[i]=getMaxProbability(dp[i],iDP);if(dp[i].concatPattern){dp[i].patterns=dp[i].patterns.concat(dp[i].concatPattern);dp[i].concatPattern=undefined;delete dp[i+1]}}return dp[0].patterns.reverse()}function getMinCount(a,b){if(!a){return b}return a.count<=b.count?a:b}function getPatternCount(pattern){if(pattern.priority===Priority.Custom){return-(pattern.length*pattern.length*100000)}if(pattern.priority===Priority.Surname){return-(pattern.length*pattern.length*100)}return 1}function minTokenization(patterns,length){const dp=[];let patternIndex=patterns.length-1;let pattern=patterns[patternIndex];for(let i=length-1;i>=0;i--){const suffixDP=i+1>=length?{count:0,patterns:[]}:dp[i+1];while(pattern&&pattern.index+pattern.length-1===i){const startIndex=pattern.index;const curDP={count:getPatternCount(pattern)+suffixDP.count,patterns:suffixDP.patterns,concatPattern:pattern};dp[startIndex]=getMinCount(dp[startIndex],curDP);pattern=patterns[--patternIndex]}const iDP={count:1+suffixDP.count,patterns:suffixDP.patterns,};dp[i]=getMinCount(dp[i],iDP);if(dp[i].concatPattern){dp[i].patterns=dp[i].patterns.concat(dp[i].concatPattern);dp[i].concatPattern=undefined;delete dp[i+1]}}return dp[0].patterns.reverse()}function isIgnorablePattern(cur,pre){if(pre.index+pre.length<=cur.index){return false}if(pre.priority>cur.priority){return false}if(pre.priority===cur.priority&&pre.length>cur.length){return false}return true}function reverseMaxMatch(patterns){const filteredArr=[];for(let i=patterns.length-1;i>=0;){const{index}=patterns[i];let j=i-1;while(j>=0&&isIgnorablePattern(patterns[i],patterns[j])){j--}if(j<0||patterns[j].index+patterns[j].length<=index){filteredArr.push(patterns[i])}i=j}return filteredArr.reverse()}var TokenizationAlgorithm;(function(TokenizationAlgorithm){TokenizationAlgorithm[TokenizationAlgorithm["ReverseMaxMatch"]=1]="ReverseMaxMatch";TokenizationAlgorithm[TokenizationAlgorithm["MaxProbability"]=2]="MaxProbability";TokenizationAlgorithm[TokenizationAlgorithm["MinTokenization"]=3]="MinTokenization"})(TokenizationAlgorithm||(TokenizationAlgorithm={}));class TrieNode{constructor(parent,prefix="",key=""){this.children=new Map();this.fail=null;this.patterns=[];this.parent=parent;this.prefix=prefix;this.key=key}}class AC{constructor(){this.dictMap=new Map();this.queues=[];this.root=new TrieNode(null)}build(patternList){this.buildTrie(patternList);this.buildFailPointer()}buildTrie(patternList){for(let pattern of patternList){const zhChars=splitString(pattern.zh);let cur=this.root;for(let i=0;i{queue=queue.concat(_queue)});this.queues=[];while(queue.length>queueIndex){let node=queue[queueIndex++];let failNode=node.parent&&node.parent.fail;let key=node.key;while(failNode&&!failNode.children.has(key)){failNode=failNode.fail}if(!failNode){node.fail=this.root}else{node.fail=failNode.children.get(key)}}}addPatternToDictMap(pattern){if(!this.dictMap.has(pattern.dict)){this.dictMap.set(pattern.dict,new Set())}this.dictMap.get(pattern.dict).add(pattern)}addNodeToQueues(trieNode){if(!this.queues[stringLength(trieNode.prefix)]){this.queues[stringLength(trieNode.prefix)]=[]}this.queues[stringLength(trieNode.prefix)].push(trieNode)}insertPattern(patterns,pattern){for(let i=patterns.length-1;i>=0;i--){const _pattern=patterns[i];if(pattern.priority===_pattern.priority&&pattern.probability>=_pattern.probability){patterns[i+1]=_pattern}else if(pattern.priority>_pattern.priority){patterns[i+1]=_pattern}else{patterns[i+1]=pattern;return}}patterns[0]=pattern}removeDict(dictName){if(this.dictMap.has(dictName)){const set=this.dictMap.get(dictName);set.forEach((pattern)=>{pattern.node.patterns=pattern.node.patterns.filter((_pattern)=>_pattern!==pattern)});this.dictMap.delete(dictName)}}match(text,surname){let cur=this.root;let result=[];const zhChars=splitString(text);for(let i=0;i{if(surname==="off"){return item.priority!==Priority.Surname}else if(surname==="head"){return item.length-1-i===0}else{return true}});if(pattern){result.push(Object.assign(Object.assign({},pattern),{index:i-pattern.length+1}))}let failNode=cur.fail;while(failNode!==null){const pattern=failNode.patterns.find((item)=>{if(surname==="off"){return item.priority!==Priority.Surname}else if(surname==="head"){return item.length-1-i===0}else{return true}});if(pattern){result.push(Object.assign(Object.assign({},pattern),{index:i-pattern.length+1}))}failNode=failNode.fail}}}return result}search(text,surname,algorithm=2){const patterns=this.match(text,surname);if(algorithm===1){return reverseMaxMatch(patterns)}else if(algorithm===3){return minTokenization(patterns,stringLength(text))}return maxProbability(patterns,stringLength(text))}}const PatternsNormal=[...Pattern5,...Pattern4,...Pattern3,...Pattern2,...PatternNumberDict,...PatternSurname,];const acTree=new AC();acTree.build(PatternsNormal);let customDict={};const customMultipleDict=new FastDictFactory();const customPolyphonicDict=new FastDictFactory();const CustomDictName=Symbol('custom');function customPinyin(config={},options){const words=Object.keys(config).sort((word1,word2)=>stringLength(word2)-stringLength(word1));words.forEach((word)=>{customDict[word]=config[word]});const customPatterns=Object.keys(customDict).map((word)=>({zh:word,pinyin:customDict[word],probability:1+stringLength(word),length:stringLength(word),priority:Priority.Custom,dict:CustomDictName,}));acTree.build(customPatterns);if(options===null||options===void 0?void 0:options.multiple){addCustomConfigToDict(config,customMultipleDict,options.multiple)}if(options===null||options===void 0?void 0:options.polyphonic){addCustomConfigToDict(config,customPolyphonicDict,options.polyphonic)}}function addCustomConfigToDict(config,dict,handleType){for(let word in config){const pinyins=config[word];splitString(word).forEach((char,index)=>{const pinyin=pinyins.split(' ')[index]||'';if(handleType==='replace'||(handleType==='add'&&!dict.get(char)&&!DICT1.get(char))){dict.set(char,pinyin)}else{dict.set(char,dict.get(char)||DICT1.get(char));if(!dict.get(char).split(' ').includes(pinyin)){dict.set(char,`${dict.get(char)}${pinyin}`.trim())}}})}}const getCustomMultpileDict=()=>{return customMultipleDict};const getCustomPolyphonicDict=()=>{return customPolyphonicDict};function clearCustomDict(dict){if(dict==='pinyin'||dict.indexOf('pinyin')!==-1){Object.keys(customDict).forEach(function(word){delete customDict[word]});acTree.removeDict(CustomDictName)}if(dict==='multiple'||dict.indexOf('multiple')!==-1){customMultipleDict.clear()}if(dict==='polyphonic'||dict.indexOf('polyphonic')!==-1){customPolyphonicDict.clear()}}const getSingleWordPinyin=(char)=>{const pinyin=DICT1.get(char);return pinyin?pinyin.split(" ")[0]:char};const getPinyin=(word,list,surname,segmentit)=>{const matches=acTree.search(word,surname,segmentit);let matchIndex=0;const zhChars=splitString(word);for(let i=0;i{return pinyin.replace(/(ā|á|ǎ|à)/g,"a").replace(/(ō|ó|ǒ|ò)/g,"o").replace(/(ē|é|ě|è)/g,"e").replace(/(ī|í|ǐ|ì)/g,"i").replace(/(ū|ú|ǔ|ù)/g,"u").replace(/(ǖ|ǘ|ǚ|ǜ)/g,"ü").replace(/(n̄|ń|ň|ǹ)/g,"n").replace(/(m̄|ḿ|m̌|m̀)/g,"m").replace(/(ê̄|ế|ê̌|ề)/g,"ê")};const getAllPinyin=(char,surname="off")=>{const customMultpileDict=getCustomMultpileDict();let pinyin=DICT1.get(char)?DICT1.get(char).split(" "):[];if(customMultpileDict.get(char)){pinyin=customMultpileDict.get(char).split(" ")}else if(surname!=="off"){const surnamePinyin=Surnames[char];if(surnamePinyin){pinyin=[surnamePinyin].concat(pinyin.filter((py)=>py!==surnamePinyin))}}return pinyin};const getMultiplePinyin=(word,surname="off")=>{let pinyin=getAllPinyin(word,surname);if(pinyin.length>0){return pinyin.map((value)=>({origin:word,result:value,isZh:true,originPinyin:value,}))}else{return[{origin:word,result:word,isZh:false,originPinyin:word,},]}};const getInitialAndFinal=(pinyin,initialPattern)=>{const pinyin_arr=pinyin.split(" ");const initial_arr=[];const final_arr=[];for(let _pinyin of pinyin_arr){for(let _initial of InitialList){if(_pinyin.startsWith(_initial)){let _final=_pinyin.slice(_initial.length);if(SpecialInitialList.indexOf(_initial)!==-1&&SpecialFinalList.indexOf(_final)!==-1){_final=SpecialFinalMap[_final]}initial_arr.push(_initial);final_arr.push(_final);break}}}if(initialPattern==="standard"){initial_arr.forEach((initial,index)=>{if(initial==="y"||initial==="w"){initial_arr[index]=""}})}return{final:final_arr.join(" "),initial:initial_arr.join(" "),}};const getFinalParts=(pinyin)=>{const{final}=getInitialAndFinal(pinyin);let head="",body="",tail="";if(doubleFinalList.indexOf(getPinyinWithoutTone(final))!==-1){head=final[0];body=final[1];tail=final.slice(2)}else{body=final[0]||"";tail=final.slice(1)||""}return{head,body,tail}};const getNumOfTone=(pinyin)=>{const reg_tone1=/(ā|ō|ē|ī|ū|ǖ|n̄|m̄|ê̄)/;const reg_tone2=/(á|ó|é|í|ú|ǘ|ń|ḿ|ế)/;const reg_tone3=/(ǎ|ǒ|ě|ǐ|ǔ|ǚ|ň|m̌|ê̌)/;const reg_tone4=/(à|ò|è|ì|ù|ǜ|ǹ|m̀|ề)/;const reg_tone0=/(a|o|e|i|u|ü|ê)/;const special_tone=/(n|m)$/;const tone_num_arr=[];const pinyin_arr=pinyin.split(" ");pinyin_arr.forEach((_pinyin)=>{if(reg_tone1.test(_pinyin)){tone_num_arr.push("1")}else if(reg_tone2.test(_pinyin)){tone_num_arr.push("2")}else if(reg_tone3.test(_pinyin)){tone_num_arr.push("3")}else if(reg_tone4.test(_pinyin)){tone_num_arr.push("4")}else if(reg_tone0.test(_pinyin)){tone_num_arr.push("0")}else if(special_tone.test(_pinyin)){tone_num_arr.push("0")}else{tone_num_arr.push("")}});return tone_num_arr.join(" ")};const getPinyinWithNum=(pinyin,originPinyin)=>{const pinyin_arr=getPinyinWithoutTone(pinyin).split(" ");const tone_num_arr=getNumOfTone(originPinyin).split(" ");const res_arr=[];pinyin_arr.forEach((item,index)=>{res_arr.push(`${item}${tone_num_arr[index]}`)});return res_arr.join(" ")};const getFirstLetter=(pinyin,isZh)=>{const first_letter_arr=[];const pinyin_arr=pinyin.split(" ");pinyin_arr.forEach((pinyin)=>{first_letter_arr.push(isZh?pinyin[0]:pinyin)});return first_letter_arr.join(" ")};const validateType=(word)=>{if(typeof word!=="string"){console.error("The first param of pinyin is error: "+word+' is not assignable to type "string".');return false}else{return true}};function isNonZhScope(char,scope){if(scope instanceof RegExp){return scope.test(char)}return true}const middleWareNonZh=(list,options)=>{let nonZh=options.nonZh;if(nonZh==="removed"){return list.filter((item)=>item.isZh||!isNonZhScope(item.origin,options.nonZhScope))}else if(nonZh==="consecutive"){for(let i=list.length-2;i>=0;i--){const cur=list[i];const pre=list[i+1];if(!cur.isZh&&!pre.isZh&&isNonZhScope(cur.origin,options.nonZhScope)&&isNonZhScope(pre.origin,options.nonZhScope)){cur.origin+=pre.origin;cur.result+=pre.result;pre.delete=true}}return list.filter((item)=>!item.delete)}else{return list}};const middlewareMultiple=(word,options)=>{if(stringLength(word)===1&&options.multiple){return getMultiplePinyin(word,options.surname)}else{return false}};const middlewarePattern=(list,options)=>{switch(options.pattern){case"pinyin":break;case"num":list.forEach((item)=>{item.result=item.isZh?getNumOfTone(item.result):""});break;case"initial":list.forEach((item)=>{item.result=item.isZh?getInitialAndFinal(item.result,options.initialPattern).initial:""});break;case"final":list.forEach((item)=>{item.result=item.isZh?getInitialAndFinal(item.result,options.initialPattern).final:""});break;case"first":list.forEach((item)=>{item.result=getFirstLetter(item.result,item.isZh)});break;case"finalHead":list.forEach((item)=>{item.result=item.isZh?getFinalParts(item.result).head:""});break;case"finalBody":list.forEach((item)=>{item.result=item.isZh?getFinalParts(item.result).body:""});break;case"finalTail":list.forEach((item)=>{item.result=item.isZh?getFinalParts(item.result).tail:""});break}};const middlewareToneType=(list,options)=>{switch(options.toneType){case"symbol":break;case"none":list.forEach((item)=>{if(item.isZh){item.result=getPinyinWithoutTone(item.result)}});break;case"num":{list.forEach((item)=>{if(item.isZh){item.result=getPinyinWithNum(item.result,item.originPinyin)}});break}}};const middlewareV=(list,options)=>{if(options.v){list.forEach((item)=>{if(item.isZh){item.result=item.result.replace(/ü/g,typeof options.v==="string"?options.v:"v")}})}};const middlewareType=(list,options,word)=>{if(options.multiple&&stringLength(word)===1){let last="";list=list.filter((item)=>{const res=item.result!==last;last=item.result;return res})}if(options.type==="array"){return list.map((item)=>item.result)}if(options.type==="all"){return list.map((item)=>{const pinyin=item.isZh?item.result:"";const{initial,final}=getInitialAndFinal(pinyin,options.initialPattern);const{head,body,tail}=getFinalParts(pinyin);let polyphonic=[];if(pinyin!==""){polyphonic=[pinyin].concat(getAllPinyin(item.origin,options.surname).filter((item)=>item!==pinyin))}return{origin:item.origin,pinyin,initial,final,first:getFirstLetter(item.result,item.isZh),finalHead:head,finalBody:body,finalTail:tail,num:Number(getNumOfTone(item.originPinyin)),isZh:item.isZh,polyphonic,inZhRange:!!DICT1.get(item.origin),result:item.result,}})}return list.map((item)=>item.result).join(options.separator)};const middlewareToneSandhi=(list,toneSandhi)=>{if(toneSandhi===false){list.forEach((item)=>{if(item.origin==="一"){item.result=item.originPinyin="yī"}else if(item.origin==="不"){item.result=item.originPinyin="bù"}})}return list};const DEFAULT_OPTIONS$2={pattern:"pinyin",toneType:"symbol",type:"string",multiple:false,mode:"normal",removeNonZh:false,nonZh:"spaced",v:false,separator:" ",toneSandhi:true,segmentit:2,};function pinyin(word,options){options=Object.assign(Object.assign({},DEFAULT_OPTIONS$2),(options||{}));const legal=validateType(word);if(!legal){return word}if(word===""){return options.type==="array"||options.type==="all"?[]:""}if(options.surname===undefined){if(options.mode==="surname"){options.surname="all"}else{options.surname="off"}}if(options.type==="all"){options.pattern="pinyin"}if(options.pattern==="num"){options.toneType="none"}if(options.removeNonZh){options.nonZh="removed"}let _list=Array(stringLength(word));let{list}=getPinyin(word,_list,options.surname,options.segmentit);list=middlewareToneSandhi(list,options.toneSandhi);list=middleWareNonZh(list,options);if(middlewareMultiple(word,options)){list=middlewareMultiple(word,options)}middlewarePattern(list,options);middlewareToneType(list,options);middlewareV(list,options);return middlewareType(list,options,word)}const DefaultName=Symbol("default");const originDictMap=new Map();function addDict(dict,options){const patterns=[];const name=typeof options==="object"?options.name:options;const dictName=name||DefaultName;const dict1Handle=(options===null||options===void 0?void 0:options.dict1)||"add";for(let word in dict){const value=dict[word];const pinyin=Array.isArray(value)?value[0]:value;const wordLength=stringLength(word);if(wordLength===1){addToOriginDict(dictName,word,pinyin,dict1Handle)}if(Array.isArray(value)){patterns.push({zh:word,pinyin,probability:typeof value[1]==="number"?value[1]:2e-8*wordLength*wordLength,length:wordLength,priority:Priority.Normal,dict:dictName,pos:typeof value[2]==="string"?value[2]:"",})}else{patterns.push({zh:word,pinyin,probability:2e-8*wordLength*wordLength,length:wordLength,priority:Priority.Normal,dict:dictName,})}}acTree.build(patterns)}function removeDict(dictName){acTree.removeDict(dictName||DefaultName);removeOriginDict(dictName||DefaultName)}function addToOriginDict(dict,char,pinyin,handle="add"){if(!originDictMap.get(dict)){originDictMap.set(dict,{})}const originDict=originDictMap.get(dict);if(!originDict[char]){originDict[char]=DICT1.get(char)}if(handle==="add"){const existedPinyin=DICT1.get(char);if(existedPinyin&&!existedPinyin.split(' ').includes(pinyin)){DICT1.set(char,`${existedPinyin}${pinyin}`)}else if(!DICT1.get(char)){DICT1.set(char,pinyin)}}else if(handle==="replace"){DICT1.set(char,pinyin)}}function removeOriginDict(dict){const originDict=originDictMap.get(dict)||{};for(let char in originDict){DICT1.set(char,originDict[char]);delete originDict[char]}}const DefaultMatchOptions={precision:"first",continuous:false,space:"ignore",lastPrecision:"start",insensitive:true,v:false,};const MAX_PINYIN_LENGTH=6;const match=(text,pinyin,options)=>{if((options===null||options===void 0?void 0:options.precision)==="any"){options.lastPrecision="any"}if(options===null||options===void 0?void 0:options.v){pinyin=pinyin.replace(/ü/g,"v")}const completeOptions=Object.assign(Object.assign({},DefaultMatchOptions),(options||{}));if(completeOptions.insensitive!==false){text=text.toLowerCase();pinyin=pinyin.toLowerCase()}if(completeOptions.space==="ignore"){pinyin=pinyin.replace(/\s/g,"")}const result=(options===null||options===void 0?void 0:options.precision)==="any"?matchAny(text,pinyin,completeOptions):matchAboveStart(text,pinyin,completeOptions);return processDoubleUnicodeIndex(text,result)};const getMatchLength=(pinyin1,pinyin2)=>{let length=0;for(let i=0;i{let result=[];const words=splitString(text);const ignoreSpace=options.space==="ignore";for(let i=0;i{const length=getMatchLength(p,pinyin$1);if(length>currentLength){currentLength=length}});if(currentLength){pinyin$1=pinyin$1.slice(currentLength);result.push(i)}if(!pinyin$1){break}}if(pinyin$1){return null}if(options.continuous){const _result=result;const isNotContinuous=result.some((val,index)=>index>0&&val!==_result[index-1]+1);if(isNotContinuous){return null}}if(options.space==="ignore"){result=result.filter((i)=>words[i]!==" ")}return result.length?result:null};const matchAboveStart=(text,pinyin$1,options)=>{const words=splitString(text);const dp=Array(words.length+1);for(let i=0;idp[i][j].length){dp[i][j]=matches}if(j===pinyin$1.length){return dp[i][j]}}if(pinyin$1.length-j<=MAX_PINYIN_LENGTH){const last=muls.some((py)=>{if(options.lastPrecision==="any"){return py.includes(pinyin$1.slice(j-1,pinyin$1.length))}if(options.lastPrecision==="start"){return py.startsWith(pinyin$1.slice(j-1,pinyin$1.length))}if(options.lastPrecision==="first"){return py[0]===pinyin$1.slice(j-1,pinyin$1.length)}if(options.lastPrecision==="every"){return py===pinyin$1.slice(j-1,pinyin$1.length)}return false});if(last){return[...dp[i-1][j-1],i-1]}}const precision=options.precision;if(precision==="start"){muls.forEach((py)=>{let end=j;const matches=[...dp[i-1][j-1],i-1];while(end<=pinyin$1.length&&py.startsWith(pinyin$1.slice(j-1,end))){if(!dp[i][end]||matches.length>dp[i][end].length){dp[i][end]=matches}end++}})}if(precision==="first"){if(muls.some((py)=>py[0]===pinyin$1[j-1])){const matches=[...dp[i-1][j-1],i-1];if(!dp[i][j]||matches.length>dp[i][j].length){dp[i][j]=matches}}}const completeMatch=muls.find((py)=>py===pinyin$1.slice(j-1,j-1+py.length));if(completeMatch){const matches=[...dp[i-1][j-1],i-1];const endIndex=j-1+completeMatch.length;if(!dp[i][endIndex]||matches.length>dp[i][endIndex].length){dp[i][endIndex]=matches}}}}}return null};function processDoubleUnicodeIndex(text,indexArray){if(!indexArray){return null}const result=[];let doubleUnicodeCount=0;const words=splitString(text);let i=0;for(let j=0;j{const completeOptions=Object.assign(Object.assign({},DefaultHtmlOptions),(options||{}));const pinyinArray=pinyin(text,{type:"all",toneType:completeOptions.toneType,toneSandhi:options===null||options===void 0?void 0:options.toneSandhi,v:completeOptions.v,});const result=pinyinArray.map((item)=>{let additionalClass="";for(const classname in completeOptions.customClassMap){const dict=completeOptions.customClassMap[classname];if(dict.includes(item.origin)){additionalClass+=`${classname}`}}if(item.isZh){const resultClass=completeOptions.resultClass||DefaultHtmlOptions.resultClass;const chineseClass=completeOptions.chineseClass||DefaultHtmlOptions.chineseClass;const pinyinClass=completeOptions.pinyinClass||DefaultHtmlOptions.pinyinClass;return`${item.origin}${completeOptions.rp?"(":""}${item.pinyin}${completeOptions.rp?")":""}`}else{if(completeOptions.wrapNonChinese){const nonChineseClass=completeOptions.nonChineseClass||DefaultHtmlOptions.nonChineseClass;return`${item.origin}`}else{return item.origin}}});return result.join("")};const DEFAULT_OPTIONS$1={pattern:"pinyin",toneType:"symbol",type:"string",v:false,nonZh:"spaced",};function polyphonic(text,options=DEFAULT_OPTIONS$1){const legal=validateType(text);if(!legal){return[]}if(text===""){return[]}if(options.type==="all"){options.pattern="pinyin"}if(options.pattern==="num"){options.toneType="none"}if(options.removeNonZh){options.nonZh="removed"}let list=getPolyphonicList(text);list=middleWareNonZh(list,options);let doubleList=getSplittedPolyphonicList(list);doubleList.forEach((list)=>{middlewarePattern(list,options)});doubleList.forEach((list)=>{middlewareToneType(list,options)});doubleList.forEach((list)=>{middlewareV(list,options)});const result=doubleList.map((list)=>handleType(list,options));return result}const getPolyphonicList=(text)=>{return splitString(text).map((char)=>{const customPolyphonicDict=getCustomPolyphonicDict();const pinyin=customPolyphonicDict.get(char)||DICT1.get(char)||char;return{origin:char,result:pinyin,isZh:pinyin!==char,originPinyin:pinyin,}})};const getSplittedPolyphonicList=(list)=>{return list.map((item)=>{return item.isZh?item.result.split(" ").map((pinyin)=>({origin:item.origin,result:pinyin,isZh:true,originPinyin:pinyin,})):[item]})};const handleType=(list,options)=>{if(options.type==="array"){return Array.from(new Set(list.map((item)=>item.result)))}if(options.type==="all"){return list.map((item)=>{const pinyin=item.isZh?item.result:"";const{initial,final}=getInitialAndFinal(pinyin,options.initialPattern);const{head,body,tail}=getFinalParts(pinyin);return{origin:item.origin,pinyin,initial,final,first:getFirstLetter(item.result,item.isZh),finalHead:head,finalBody:body,finalTail:tail,num:Number(getNumOfTone(item.originPinyin)),isZh:item.isZh,inZhRange:!!DICT1.get(item.origin),}})}return Array.from(new Set(list.map((item)=>item.result))).join(" ")};const DefaultConvertOptions={separator:' ',format:'numToSymbol',};const toneMap={a:['a','ā','á','ǎ','à'],o:['o','ō','ó','ǒ','ò'],e:['e','ē','é','ě','è'],ü:['ü','ǖ','ǘ','ǚ','ǜ'],v:['ü','ǖ','ǘ','ǚ','ǜ'],ui:['ui','uī','uí','uǐ','uì'],iu:['iu','iū','iú','iǔ','iù'],i:['i','ī','í','ǐ','ì'],u:['u','ū','ú','ǔ','ù'],n:['n','n̄','ń','ň','ǹ'],m:['m','m̄','ḿ','m̌','m̀'],ê:['ê','ê̄','ế','ê̌','ề'],};function convert(pinyin,options){options=Object.assign(Object.assign({},DefaultConvertOptions),(options||{}));const originType=typeof pinyin;if(typeof pinyin==='string'){pinyin=pinyin.split(options.separator)}pinyin=pinyin.map((item)=>{const format=options.format;if(format==='numToSymbol'){return formatNumToSymbol(item)}else if(format==='symbolToNum'){return formatSymbolToNum(item)}else if(format==='toneNone'){return formatToneNone(item)}return item});if(originType==='string'){return pinyin.join(options.separator)}else{return pinyin}}function formatNumToSymbol(pinyin){const lastChar=Number(pinyin[pinyin.length-1]);if(lastChar>=0&&lastChar<=4){for(let key in toneMap){if(pinyin.includes(key)){return pinyin.slice(0,pinyin.length-1).replace(key,toneMap[key][lastChar])}}return pinyin}else{return pinyin}}function formatSymbolToNum(pinyin){return`${getPinyinWithoutTone(pinyin)}${getNumOfTone(pinyin)}`}function formatToneNone(pinyin){return getPinyinWithoutTone(pinyin)}var OutputFormat;(function(OutputFormat){OutputFormat[OutputFormat["AllSegment"]=1]="AllSegment";OutputFormat[OutputFormat["AllArray"]=2]="AllArray";OutputFormat[OutputFormat["AllString"]=3]="AllString";OutputFormat[OutputFormat["PinyinSegment"]=4]="PinyinSegment";OutputFormat[OutputFormat["PinyinArray"]=5]="PinyinArray";OutputFormat[OutputFormat["PinyinString"]=6]="PinyinString";OutputFormat[OutputFormat["ZhSegment"]=7]="ZhSegment";OutputFormat[OutputFormat["ZhArray"]=8]="ZhArray";OutputFormat[OutputFormat["ZhString"]=9]="ZhString"})(OutputFormat||(OutputFormat={}));function middlewareSegment(list,matches){const segments=[];let i=0;let j=0;while(i({origin:item.origin,result:item.result,})),isZh:true,});i+=cur-start;j++}else{segments.push({segment:[{origin:item.origin,result:item.result,}],isZh:false,});i++}}while(i{return{origin:item.segment.map(item=>item.origin).join(''),result:item.segment.map(item=>item.result).join(''),}})}else if(format===OutputFormat.AllArray){return segments.map(item=>item.segment)}else if(format===OutputFormat.AllString){const list=segments.map(item=>{return{origin:item.segment.map(item=>item.origin).join(''),result:item.segment.map(item=>item.result).join(''),}});return{origin:list.map(item=>item.origin).join(separator),result:list.map(item=>item.result).join(separator),}}else if(format===OutputFormat.PinyinSegment){return segments.map(item=>item.segment.map(item=>item.result).join(''))}else if(format===OutputFormat.PinyinArray){return segments.map(item=>item.segment.map(item=>item.result))}else if(format===OutputFormat.PinyinString){return segments.map(item=>item.segment.map(item=>item.result).join('')).join(separator)}else if(format===OutputFormat.ZhSegment){return segments.map(item=>item.segment.map(item=>item.origin).join(''))}else if(format===OutputFormat.ZhArray){return segments.map(item=>item.segment.map(item=>item.origin))}else if(format===OutputFormat.ZhString){return segments.map(item=>item.segment.map(item=>item.origin).join('')).join(separator)}}const DEFAULT_OPTIONS={toneType:"symbol",mode:"normal",nonZh:"spaced",v:false,separator:" ",toneSandhi:true,segmentit:2,format:OutputFormat.AllSegment,};function segment(word,options){options=Object.assign(Object.assign({},DEFAULT_OPTIONS),(options||{}));const legal=validateType(word);if(!legal){return word}if(options.surname===undefined){if(options.mode==="surname"){options.surname="all"}else{options.surname="off"}}let _list=Array(stringLength(word));let{list,matches}=getPinyin(word,_list,options.surname,options.segmentit);list=middlewareToneSandhi(list,options.toneSandhi);list=middleWareNonZh(list,options);middlewareToneType(list,options);middlewareV(list,options);const segments=middlewareSegment(list,matches);return middlewareOutputFormat(segments,{format:options.format,separator:options.separator})}export{OutputFormat,addDict,clearCustomDict,convert,customPinyin,getFinalParts,getInitialAndFinal,getNumOfTone,html,match,pinyin,polyphonic,removeDict,segment}; \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/unierror.uts b/uni_modules/x-chinesetopinyin-s/utssdk/unierror.uts new file mode 100644 index 0000000..ab305ed --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/unierror.uts @@ -0,0 +1,19 @@ +/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */ +import { XuiChineseToPinYinFail } from "./interface.uts" + +export const XuiErrors : Map = new Map([ + [1001, '函数内部错误'], + [1002, '参数错误,缺少char参数或者char为空'], +]); + +export class XuiChineseToPinYinFailImpl extends UniError implements XuiChineseToPinYinFail { + /** + * 错误对象构造函数 + */ + constructor(errCode : number) { + super(); + this.errSubject = "x-chinesetopinyin-s"; + this.errCode = errCode; + this.errMsg = XuiErrors.get(errCode) ?? ""; + } +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/web/index.uts b/uni_modules/x-chinesetopinyin-s/utssdk/web/index.uts new file mode 100644 index 0000000..ace3c65 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/web/index.uts @@ -0,0 +1,28 @@ +import { pinyin } from "./pinyintojs.js" +import { XuiChineseToPinYinOpts, XuiChineseToPinYinResult } from "../interface.uts" +import { XuiChineseToPinYinFailImpl } from "../unierror.uts" + +/** 中文转拼音 */ +export function toPinYin(opts : XuiChineseToPinYinOpts){ + try { + let c = opts.char; + if (c == '') { + let errorIml = new XuiChineseToPinYinFailImpl(1002) + opts?.fail?.(errorIml) + opts?.complete?.(null) + return; + } + const result = pinyin(c, { toneType: 'none', style: pinyin.STYLE_NORMAL }) + const resultZhuying = pinyin(c, { toneType: 'symbol', style: pinyin.STYLE_NORMAL }) + const ok : XuiChineseToPinYinResult = { + detail: result, + zhuyin: resultZhuying + } + opts?.success?.(ok) + opts?.complete?.(ok) + } catch (error) { + console.error(error) + opts?.fail?.(new XuiChineseToPinYinFailImpl(1001)) + opts?.complete?.(null) + } +} \ No newline at end of file diff --git a/uni_modules/x-chinesetopinyin-s/utssdk/web/pinyintojs.js b/uni_modules/x-chinesetopinyin-s/utssdk/web/pinyintojs.js new file mode 100644 index 0000000..dbcc7a1 --- /dev/null +++ b/uni_modules/x-chinesetopinyin-s/utssdk/web/pinyintojs.js @@ -0,0 +1 @@ +const DoubleUnicodePrefixReg=/^[\uD800-\uDBFF]$/;const DoubleUnicodeSuffixReg=/^[\uDC00-\uDFFF]$/;const DoubleUnicodeReg=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;var Probability;(function(Probability){Probability[Probability["Unknown"]=1e-13]="Unknown";Probability[Probability["Rule"]=1e-12]="Rule";Probability[Probability["DICT"]=2e-8]="DICT";Probability[Probability["Surname"]=1]="Surname";Probability[Probability["Custom"]=1]="Custom"})(Probability||(Probability={}));const Priority={Normal:1,Surname:10,Custom:100,};function stringLength(text){var _a;return text.length-(((_a=text.match(DoubleUnicodeReg))===null||_a===void 0?void 0:_a.length)||0)}function splitString(text){const result=[];let i=0;while(i1){return this.StringDICT.get(word)}else{const code=word.charCodeAt(0);return this.NumberDICT[code]}}set(word,pinyin){if(word.length>1){this.StringDICT.set(word,pinyin)}else{const code=word.charCodeAt(0);this.NumberDICT[code]=pinyin}}clear(){this.NumberDICT=[];this.StringDICT.clear()}}const map={'bǎng páng pāng':['膀'],líng:['〇','伶','凌','刢','囹','坽','夌','姈','婈','孁','岺','彾','掕','昤','朎','柃','棂','櫺','欞','泠','淩','澪','灵','燯','爧','狑','玲','琌','瓴','皊','砱','祾','秢','竛','笭','紷','綾','绫','羐','羚','翎','聆','舲','苓','菱','蓤','蔆','蕶','蛉','衑','裬','詅','跉','軨','輘','酃','醽','鈴','錂','铃','閝','陵','零','霊','霗','霛','霝','靈','駖','魿','鯪','鲮','鴒','鸰','鹷','麢','齡','齢','龄','龗','㥄',],yī:['一','乊','伊','依','医','吚','咿','噫','壱','壹','夁','嫛','嬄','弌','揖','撎','檹','毉','洢','渏','漪','瑿','畩','祎','禕','稦','繄','蛜','衤','譩','辷','郼','醫','銥','铱','鷖','鹥','黟','黳',],'dīng zhēng':['丁'],'kǎo qiǎo yú':['丂'],qī:['七','倛','僛','凄','嘁','墄','娸','悽','慼','慽','戚','捿','柒','桤','桼','棲','榿','欺','沏','淒','漆','紪','緀','萋','褄','諆','迉','郪','鏚','霋','魌','鶈',],shàng:['丄','尙','尚','恦','緔','绱'],xià:['丅','下','乤','圷','夏','夓','懗','梺','疜','睱','罅','鎼','鏬',],hǎn:['丆','喊','浫','罕','豃','㘎'],'wàn mò':['万'],zhàng:['丈','仗','墇','嶂','帐','帳','幛','扙','杖','涱','痮','瘬','瘴','瞕','粀','胀','脹','賬','账','障',],sān:['三','厁','叁','弎','毵','毶','毿','犙','鬖'],'shàng shǎng shang':['上'],'qí jī':['丌','其','奇'],'bù fǒu':['不'],'yǔ yù yú':['与'],miǎn:['丏','偭','免','冕','勉','勔','喕','娩','愐','汅','沔','湎','睌','緬','缅','腼','葂','靦','鮸','𩾃',],gài:['丐','乢','匃','匄','戤','概','槩','槪','溉','漑','瓂','葢','鈣','钙','𬮿',],chǒu:['丑','丒','侴','吜','杽','瞅','矁','醜','魗'],zhuān:['专','叀','嫥','専','專','瑼','甎','砖','磗','磚','蟤','諯','鄟','顓','颛','鱄','䏝',],'qiě jū':['且'],pī:['丕','伓','伾','噼','坯','岯','憵','批','披','炋','狉','狓','砒','磇','礔','礕','秛','秠','耚','豾','邳','鈚','鉟','銔','錃','錍','霹','駓','髬','魾','𬳵',],shì:['世','丗','亊','事','仕','侍','冟','势','勢','卋','呩','嗜','噬','士','奭','嬕','室','市','式','弑','弒','恀','恃','戺','拭','揓','是','昰','枾','柿','栻','澨','烒','煶','眂','眎','眡','睗','示','礻','筮','簭','舐','舓','襫','視','视','觢','試','誓','諡','謚','试','谥','貰','贳','軾','轼','逝','遾','釈','释','釋','鈰','鉃','鉽','铈','飾','餙','餝','饰','鰘','䏡','𬤊',],qiū:['丘','丠','坵','媝','恘','恷','楸','秋','秌','穐','篍','緧','萩','蘒','蚯','蝵','蟗','蠤','趥','邱','鞦','鞧','鰌','鰍','鳅','鶖','鹙','龝',],bǐng:['丙','屛','怲','抦','昞','昺','柄','棅','炳','禀','秉','稟','苪','蛃','邴','鈵','陃','鞆','餅','餠','饼',],yè:['业','亱','僷','墷','夜','嶪','嶫','抴','捙','擛','擪','擫','晔','曄','曅','曗','曳','曵','枼','枽','業','洂','液','澲','烨','燁','爗','璍','皣','瞱','瞸','礏','腋','葉','謁','谒','邺','鄴','鍱','鐷','靥','靨','頁','页','餣','饁','馌','驜','鵺','鸈',],cóng:['丛','从','叢','婃','孮','従','徔','徖','悰','樷','欉','淙','灇','爜','琮','藂','誴','賨','賩','錝',],dōng:['东','倲','冬','咚','埬','岽','崬','徚','昸','東','氡','氭','涷','笗','苳','菄','蝀','鮗','鯟','鶇','鶫','鸫','鼕','𬟽',],sī:['丝','俬','凘','厮','司','咝','嘶','噝','媤','廝','恖','撕','斯','楒','泀','澌','燍','禗','禠','私','糹','絲','緦','纟','缌','罳','蕬','虒','蛳','蜤','螄','蟖','蟴','鉰','銯','鍶','鐁','锶','颸','飔','騦','鷥','鸶','鼶','㟃',],chéng:['丞','呈','城','埕','堘','塍','塖','宬','峸','惩','懲','成','承','挰','掁','揨','枨','棖','橙','檙','洆','溗','澂','珵','珹','畻','程','窚','筬','絾','脭','荿','誠','诚','郕','酲','鋮','铖','騬','鯎',],diū:['丟','丢','銩','铥'],liǎng:['両','两','兩','唡','啢','掚','緉','脼','蜽','裲','魉','魎','𬜯',],yǒu:['丣','卣','友','梄','湵','牖','禉','羑','聈','苃','莠','蜏','酉','銪','铕','黝',],yán:['严','厳','啱','喦','嚴','塩','壛','壧','妍','姸','娫','娮','岩','嵒','嵓','巌','巖','巗','延','揅','昖','楌','檐','櫩','欕','沿','炎','炏','狿','琂','盐','碞','筵','簷','莚','蔅','虤','蜒','言','訁','訮','詽','讠','郔','閆','閻','闫','阎','顏','顔','颜','鹽','麣','𫄧',],bìng:['並','併','倂','傡','垪','摒','栤','病','窉','竝','誁','靐','鮩',],'sàng sāng':['丧'],gǔn:['丨','惃','滚','滾','磙','緄','绲','蓘','蔉','衮','袞','輥','辊','鮌','鯀','鲧',],jiū:['丩','勼','啾','揪','揫','朻','究','糾','纠','萛','赳','阄','鬏','鬮','鳩','鸠',],'gè gě':['个','個','各'],yā:['丫','圧','孲','庘','押','枒','桠','椏','錏','鐚','鴉','鴨','鵶','鸦','鸭',],pán:['丬','媻','幋','槃','洀','瀊','爿','盘','盤','磐','縏','蒰','蟠','蹒','蹣','鎜','鞶',],'zhōng zhòng':['中'],jǐ:['丮','妀','己','戟','挤','掎','撠','擠','橶','泲','犱','脊','虮','蟣','魢','鱾','麂',],jiè:['丯','介','借','唶','堺','屆','届','岕','庎','徣','戒','楐','犗','玠','琾','界','畍','疥','砎','蚧','蛶','衸','褯','誡','诫','鎅','骱','魪',],fēng:['丰','仹','偑','僼','凨','凬','凮','妦','寷','封','峯','峰','崶','枫','楓','檒','沣','沨','渢','灃','烽','犎','猦','琒','疯','瘋','盽','砜','碸','篈','蘴','蜂','蠭','豐','鄷','酆','鋒','鎽','鏠','锋','霻','靊','飌','麷',],'guàn kuàng':['丱'],chuàn:['串','汌','玔','賗','釧','钏'],chǎn:['丳','产','冁','剷','囅','嵼','旵','浐','滻','灛','產','産','簅','蒇','蕆','諂','譂','讇','谄','鏟','铲','閳','闡','阐','骣','𬊤',],lín:['临','冧','壣','崊','嶙','斴','晽','暽','林','潾','瀶','燐','琳','璘','瞵','碄','磷','粦','粼','繗','翷','臨','轔','辚','遴','邻','鄰','鏻','阾','隣','霖','驎','鱗','鳞','麐','麟','𬴊','𬭸',],zhuó:['丵','劅','卓','啄','圴','妰','娺','撯','擆','擢','斫','斮','斱','斲','斵','晫','椓','浊','浞','濁','灼','烵','琸','硺','禚','窡','籗','籱','罬','茁','蠗','蠿','諁','諑','謶','诼','酌','鐲','镯','鵫','鷟','䓬','𬸦',],zhǔ:['丶','主','劯','嘱','囑','宔','帾','拄','渚','濐','煑','煮','燝','瞩','矚','罜','詝','陼','鸀','麈','𬣞',],bā:['丷','仈','八','叭','哵','夿','岜','巴','捌','朳','玐','疤','笆','粑','羓','芭','蚆','豝','釟',],wán:['丸','刓','完','岏','抏','捖','汍','烷','玩','琓','笂','紈','纨','翫','芄','貦','頑','顽',],dān:['丹','勯','匰','単','妉','媅','殚','殫','甔','眈','砃','箪','簞','耼','耽','聃','聸','褝','襌','躭','郸','鄲','酖','頕',],'wèi wéi':['为'],'jǐng dǎn':['丼'],'lì lí':['丽'],jǔ:['举','弆','挙','擧','椇','榉','榘','櫸','欅','矩','筥','聥','舉','莒','蒟','襷','踽','齟','龃',],piě:['丿','苤','鐅','𬭯'],fú:['乀','伏','俘','凫','刜','匐','咈','哹','垘','孚','岪','巿','帗','幅','幞','弗','彿','怫','扶','柫','栿','桴','氟','泭','浮','涪','澓','炥','玸','甶','畉','癁','祓','福','稪','符','箙','紱','紼','絥','綍','绂','绋','罘','罦','翇','艀','芙','芣','苻','茀','茯','菔','葍','虙','蚨','蜉','蝠','袚','袱','襆','襥','諨','豧','踾','輻','辐','郛','鉘','鉜','韍','韨','颫','髴','鮄','鮲','鳧','鳬','鴔','鵩','黻',],'yí jí':['乁'],yì:['乂','义','亄','亦','亿','伇','伿','佾','俋','億','兿','刈','劓','劮','勚','勩','匇','呓','呭','呹','唈','囈','圛','坄','垼','埸','奕','嫕','嬑','寱','屹','峄','嶧','帟','帠','幆','廙','异','弈','弋','役','忆','怈','怿','悒','意','憶','懌','懿','抑','挹','敡','易','晹','曀','曎','杙','枍','棭','榏','槸','檍','歝','殔','殪','殹','毅','浂','浥','浳','湙','溢','潩','澺','瀷','炈','焲','熠','熤','熼','燚','燡','燱','獈','玴','異','疫','痬','瘗','瘞','瘱','癔','益','瞖','穓','竩','篒','縊','繶','繹','绎','缢','義','羿','翊','翌','翳','翼','耴','肄','肊','膉','臆','艗','艺','芅','苅','萟','蓺','薏','藙','藝','蘙','虉','蜴','螠','衪','袣','裔','裛','褹','襼','訲','訳','詍','詣','誼','譯','議','讛','议','译','诣','谊','豙','豛','豷','貖','贀','跇','轶','逸','邑','鄓','醷','釴','鈠','鎰','鐿','镒','镱','阣','隿','霬','饐','駅','驛','驿','骮','鮨','鶂','鶃','鶍','鷁','鷊','鷧','鷾','鸃','鹝','鹢','黓','齸','𬬩','㑊','𫄷','𬟁',],nǎi:['乃','倷','奶','嬭','廼','氖','疓','艿','迺','釢'],wǔ:['乄','五','仵','伍','侮','倵','儛','午','啎','妩','娬','嫵','庑','廡','忤','怃','憮','摀','武','潕','熓','牾','玝','珷','瑦','甒','碔','舞','躌','迕','逜','陚','鵡','鹉','𣲘',],jiǔ:['久','乆','九','乣','奺','杦','汣','灸','玖','紤','舏','酒','镹','韭','韮',],'tuō zhé':['乇','杔','馲'],'me mó ma yāo':['么'],zhī:['之','倁','卮','巵','搘','支','栀','梔','椥','榰','汁','泜','疷','祗','祬','秓','稙','綕','肢','胑','胝','脂','芝','蘵','蜘','衼','隻','鳷','鴲','鼅','𦭜',],'wū wù':['乌'],zhà:['乍','咤','宱','搾','榨','溠','痄','蚱','詐','诈','醡','霅','䃎',],hū:['乎','乯','匢','匫','呼','唿','嘑','垀','寣','幠','忽','惚','昒','歑','泘','淴','滹','烀','苸','虍','虖','謼','軤','轷','雐',],fá:['乏','伐','傠','坺','垡','墢','姂','栰','浌','瞂','笩','筏','罚','罰','罸','藅','閥','阀',],'lè yuè yào lào':['乐','樂'],yín:['乑','吟','噖','嚚','圁','垠','夤','婬','寅','峾','崟','崯','檭','殥','泿','淫','滛','烎','犾','狺','璌','硍','碒','荶','蔩','訔','訚','訡','誾','鄞','鈝','銀','银','霪','鷣','齦',],pīng:['乒','俜','娉','涄','甹','砯','聠','艵','頩'],pāng:['乓','滂','胮','膖','雱','霶'],qiáo:['乔','侨','僑','嫶','憔','桥','槗','樵','橋','櫵','犞','瞧','硚','礄','荍','荞','蕎','藮','譙','趫','鐈','鞒','鞽','顦',],hǔ:['乕','琥','萀','虎','虝','錿','鯱'],guāi:['乖'],'chéng shèng':['乗','乘','娍'],yǐ:['乙','乛','以','倚','偯','嬟','崺','已','庡','扆','攺','敼','旑','旖','檥','矣','礒','笖','舣','艤','苡','苢','蚁','螘','蟻','裿','踦','輢','轙','逘','酏','釔','鈘','鉯','钇','顗','鳦','齮','𫖮','𬺈',],'háo yǐ':['乚'],'niè miē':['乜'],qǐ:['乞','企','启','唘','啓','啔','啟','婍','屺','杞','棨','玘','盀','綺','绮','芑','諬','起','邔','闙',],yě:['也','冶','嘢','埜','壄','漜','野'],xí:['习','喺','媳','嶍','席','椺','檄','漝','習','蓆','袭','襲','覡','觋','謵','趘','郋','鎴','隰','霫','飁','騱','騽','驨','鰼','鳛','𠅤','𫘬',],xiāng:['乡','厢','廂','忀','楿','欀','湘','瓖','稥','箱','緗','缃','膷','芗','萫','葙','薌','襄','郷','鄉','鄊','鄕','鑲','镶','香','驤','骧','鱜','麘','𬙋',],shū:['书','倏','倐','儵','叔','姝','尗','抒','掓','摅','攄','書','枢','梳','樞','殊','殳','毹','毺','淑','瀭','焂','疎','疏','紓','綀','纾','舒','菽','蔬','踈','軗','輸','输','鄃','陎','鮛','鵨',],dǒu:['乧','抖','枓','蚪','鈄','阧','陡'],shǐ:['乨','使','兘','史','始','宩','屎','榁','矢','笶','豕','鉂','駛','驶',],jī:['乩','僟','击','刉','刏','剞','叽','唧','喞','嗘','嘰','圾','基','墼','姬','屐','嵆','嵇','撃','擊','朞','机','枅','樭','機','毄','激','犄','玑','璣','畸','畿','癪','矶','磯','积','積','笄','筓','箕','簊','緁','羁','羇','羈','耭','肌','芨','虀','覉','覊','譏','譤','讥','賫','賷','赍','跻','踑','躋','躸','銈','錤','鐖','鑇','鑙','隮','雞','鞿','韲','飢','饑','饥','魕','鳮','鶏','鶺','鷄','鸄','鸡','齎','齏','齑','𬯀','𫓯','𫓹','𫌀',],náng:['乪','嚢','欜','蠰','饢'],jiā:['乫','佳','傢','加','嘉','抸','枷','梜','毠','泇','浃','浹','犌','猳','珈','痂','笳','糘','耞','腵','葭','袈','豭','貑','跏','迦','鉫','鎵','镓','鴐','麚','𬂩',],jù:['乬','倨','倶','具','剧','劇','勮','埧','埾','壉','姖','屦','屨','岠','巨','巪','怇','惧','愳','懅','懼','拒','拠','昛','歫','洰','澽','炬','烥','犋','秬','窭','窶','簴','粔','耟','聚','虡','蚷','詎','讵','豦','距','踞','躆','遽','邭','醵','鉅','鐻','钜','颶','飓','駏','鮔',],shí:['乭','十','埘','塒','姼','实','実','寔','實','峕','嵵','时','旹','時','榯','湜','溡','炻','祏','竍','蚀','蝕','辻','遈','鉐','飠','饣','鮖','鰣','鲥','鼫','鼭',],mǎo:['乮','冇','卯','峁','戼','昴','泖','笷','蓩','鉚','铆'],mǎi:['买','嘪','荬','蕒','買','鷶'],luàn:['乱','亂','釠'],rǔ:['乳','擩','汝','肗','辱','鄏'],xué:['乴','学','學','峃','嶨','斈','泶','澩','燢','穴','茓','袕','踅','鷽','鸴',],yǎn:['䶮','乵','俨','偃','儼','兖','兗','厣','厴','噞','孍','嵃','巘','巚','弇','愝','戭','扊','抁','掩','揜','曮','椼','檿','沇','渷','演','琰','甗','眼','罨','萒','蝘','衍','褗','躽','遃','郾','隒','顩','魇','魘','鰋','鶠','黡','黤','黬','黭','黶','鼴','鼹','齴','龑','𬸘','𬙂','𪩘',],fǔ:['乶','俌','俛','俯','府','弣','抚','拊','撫','斧','椨','滏','焤','甫','盙','簠','腐','腑','蜅','輔','辅','郙','釜','釡','阝','頫','鬴','黼','㕮','𫖯',],shā:['乷','唦','杀','桬','殺','毮','猀','痧','砂','硰','紗','繺','纱','蔱','裟','鎩','铩','閷','髿','魦','鯊','鯋','鲨',],nǎ:['乸','雫'],qián:['乹','亁','仱','偂','前','墘','媊','岒','拑','掮','榩','橬','歬','潛','潜','濳','灊','箝','葥','虔','軡','鈐','鉗','銭','錢','鎆','钤','钱','钳','靬','騚','騝','鰬','黔','黚',],suǒ:['乺','唢','嗩','所','暛','溑','溹','琐','琑','瑣','索','褨','鎖','鎻','鏁','锁',],yú:['乻','于','亐','伃','余','堣','堬','妤','娛','娯','娱','嬩','崳','嵎','嵛','愚','扵','揄','旟','楡','楰','榆','欤','歈','歟','歶','渔','渝','湡','漁','澞','牏','狳','玗','玙','瑜','璵','盂','睮','窬','竽','籅','羭','腴','臾','舁','舆','艅','茰','萮','萸','蕍','蘛','虞','虶','蝓','螸','衧','褕','覦','觎','諛','謣','谀','踰','輿','轝','逾','邘','酑','鍝','隅','雓','雩','餘','馀','騟','骬','髃','魚','魣','鮽','鯲','鰅','鱼','鷠','鸆','齵',],zhù:['乼','伫','佇','住','坾','墸','壴','嵀','拀','杼','柱','樦','殶','注','炷','疰','眝','祝','祩','竚','筯','箸','篫','簗','紵','紸','纻','羜','翥','苎','莇','蛀','註','貯','贮','跓','軴','鉒','鋳','鑄','铸','馵','駐','驻',],zhě:['乽','者','褶','襵','赭','踷','鍺','锗'],'qián gān':['乾'],'zhì luàn':['乿'],guī:['亀','圭','妫','媯','嫢','嬀','帰','归','摫','椝','槻','槼','櫷','歸','珪','瑰','璝','瓌','皈','瞡','硅','茥','蘬','規','规','邽','郌','閨','闺','騩','鬶','鬹',],'lǐn lìn':['亃'],jué:['亅','决','刔','劂','匷','厥','噊','孒','孓','崛','崫','嶥','彏','憠','憰','戄','抉','挗','掘','攫','桷','橛','橜','欮','氒','決','灍','焳','熦','爑','爴','爵','獗','玃','玦','玨','珏','瑴','瘚','矍','矡','砄','絕','絶','绝','臄','芵','蕝','蕨','虳','蟨','蟩','觖','觮','觼','訣','譎','诀','谲','貜','赽','趉','蹷','躩','鈌','鐍','鐝','钁','镢','鴂','鴃','鷢','𫘝','㵐','𫔎',],'le liǎo':['了'],'gè mā':['亇'],'yǔ yú':['予','懙'],zhēng:['争','佂','凧','姃','媜','峥','崝','崢','征','徰','炡','烝','爭','狰','猙','癥','眐','睁','睜','筝','箏','篜','聇','脀','蒸','踭','鉦','錚','鏳','鬇',],èr:['二','刵','咡','弍','弐','樲','誀','貮','貳','贰','髶'],chù:['亍','傗','儊','怵','憷','搐','斶','歜','珿','琡','矗','竌','絀','绌','臅','触','觸','豖','鄐','閦','黜',],kuī:['亏','刲','岿','巋','盔','窥','窺','聧','虧','闚','顝'],yún:['云','伝','勻','匀','囩','妘','愪','抣','昀','橒','沄','涢','溳','澐','熉','畇','秐','筼','篔','紜','縜','纭','耘','芸','蒷','蕓','郧','鄖','鋆','雲',],hù:['互','冱','嗀','嚛','婟','嫭','嫮','岵','帍','弖','怙','戶','户','戸','戽','扈','护','昈','槴','沍','沪','滬','熩','瓠','祜','笏','簄','粐','綔','蔰','護','豰','鄠','鍙','頀','鱯','鳠','鳸','鸌','鹱',],qí:['亓','剘','埼','岐','岓','崎','嵜','愭','掑','斉','斊','旂','旗','棊','棋','檱','櫀','歧','淇','濝','猉','玂','琦','琪','璂','畦','疧','碁','碕','祁','祈','祺','禥','竒','簯','簱','籏','粸','綥','綦','肵','脐','臍','艩','芪','萁','萕','蕲','藄','蘄','蚑','蚚','蛴','蜝','蜞','螧','蠐','褀','軝','鄿','釮','錡','锜','陭','頎','颀','騎','騏','騹','骐','骑','鬐','鬿','鯕','鰭','鲯','鳍','鵸','鶀','麒','麡','𨙸','𬨂','䓫',],jǐng:['井','儆','刭','剄','坓','宑','幜','憬','暻','殌','汫','汬','澋','璄','璟','璥','穽','肼','蟼','警','阱','頚','頸',],sì:['亖','佀','価','儩','兕','嗣','四','姒','娰','孠','寺','巳','柶','榹','汜','泗','泤','洍','洠','涘','瀃','牭','祀','禩','竢','笥','耜','肂','肆','蕼','覗','貄','釲','鈶','鈻','飤','飼','饲','駟','騃','驷',],suì:['亗','嬘','岁','嵗','旞','檖','歲','歳','澻','煫','燧','璲','砕','碎','祟','禭','穂','穗','穟','繀','繐','繸','襚','誶','譢','谇','賥','邃','鐆','鐩','隧','韢','𫟦','𬭼',],gèn:['亘','亙','揯','搄','茛'],yà:['亚','亜','俹','冴','劜','圔','圠','埡','娅','婭','揠','氩','氬','犽','砑','稏','聐','襾','覀','訝','讶','迓','齾',],'xiē suò':['些'],'qí zhāi':['亝','齊'],'yā yà':['亞','压','垭','壓','铔'],'jí qì':['亟','焏'],tóu:['亠','投','頭','骰'],'wáng wú':['亡'],'kàng háng gāng':['亢'],dà:['亣','眔'],jiāo:['交','僬','娇','嬌','峧','嶕','嶣','憍','椒','浇','澆','焦','礁','穚','簥','胶','膠','膲','茭','茮','蕉','虠','蛟','蟭','跤','轇','郊','鐎','驕','骄','鮫','鲛','鵁','鷦','鷮','鹪','䴔',],hài:['亥','嗐','害','氦','餀','饚','駭','駴','骇'],'hēng pēng':['亨'],mǔ:['亩','姆','峔','拇','母','牡','牳','畂','畆','畒','畝','畞','畮','砪','胟','踇','鉧','𬭁','𧿹',],ye:['亪'],xiǎng:['享','亯','响','想','晑','蚃','蠁','響','飨','餉','饗','饷','鮝','鯗','鱶','鲞',],jīng:['京','亰','兢','坕','坙','婛','惊','旌','旍','晶','橸','泾','涇','猄','睛','秔','稉','粳','精','経','經','綡','聙','腈','茎','荆','荊','菁','葏','驚','鯨','鲸','鶁','鶄','麖','麠','鼱','䴖',],tíng:['亭','停','婷','嵉','庭','廷','楟','榳','筳','聤','莛','葶','蜓','蝏','諪','邒','霆','鼮','䗴',],liàng:['亮','喨','悢','晾','湸','諒','谅','輌','輛','辆','鍄'],'qīn qìng':['亲','親'],bó:['亳','仢','侼','僰','博','帛','愽','懪','挬','搏','欂','浡','淿','渤','煿','牔','狛','瓝','礴','秡','箔','簙','糪','胉','脖','膊','舶','艊','萡','葧','袯','襏','襮','謈','踣','郣','鈸','鉑','鋍','鎛','鑮','钹','铂','镈','餺','馎','馛','馞','駁','駮','驳','髆','鵓','鹁',],yòu:['亴','佑','佦','侑','又','右','哊','唀','囿','姷','宥','峟','幼','狖','祐','蚴','誘','诱','貁','迶','酭','釉','鼬',],xiè:['亵','伳','偞','偰','僁','卨','卸','噧','塮','夑','媟','屑','屧','廨','徢','懈','暬','械','榍','榭','泻','洩','渫','澥','瀉','瀣','灺','炧','炨','燮','爕','獬','祄','禼','糏','紲','絏','絬','繲','纈','绁','缷','薢','薤','蟹','蠏','褉','褻','謝','谢','躞','邂','靾','韰','齂','齘','齛','齥','𬹼','𤫉',],'dǎn dàn':['亶','馾'],lián:['亷','劆','匲','匳','嗹','噒','奁','奩','嫾','帘','廉','怜','憐','涟','漣','濂','濓','瀮','熑','燫','簾','籢','籨','縺','翴','联','聨','聫','聮','聯','臁','莲','蓮','薕','螊','蠊','裢','褳','覝','謰','蹥','连','連','鎌','鐮','镰','鬑','鰱','鲢',],duǒ:['亸','哚','嚲','埵','崜','朵','朶','綞','缍','趓','躱','躲','軃',],'wěi mén':['亹','斖'],rén:['人','亻','仁','壬','忈','忎','朲','秂','芢','魜','鵀'],jí:['亼','亽','伋','佶','偮','卙','即','卽','及','叝','吉','堲','塉','姞','嫉','岌','嵴','嶯','彶','忣','急','愱','戢','揤','极','棘','楫','極','槉','檝','殛','汲','湒','潗','疾','瘠','皍','笈','箿','籍','級','级','膌','艥','蒺','蕀','蕺','蝍','螏','襋','觙','谻','踖','蹐','躤','輯','轚','辑','郆','銡','鍓','鏶','集','雧','霵','鹡','㴔',],wáng:['亾','仼','兦','莣','蚟'],'shén shí':['什'],lè:['仂','叻','忇','氻','泐','玏','砳','簕','艻','阞','韷','餎','鰳','鱳','鳓',],dīng:['仃','叮','帄','玎','疔','盯','耵','虰','靪'],zè:['仄','崱','庂','捑','昃','昗','汄'],'jǐn jìn':['仅','僅','嫤'],'pú pū':['仆'],'chóu qiú':['仇'],zhǎng:['仉','幥','掌','礃'],jīn:['今','堻','巾','惍','斤','津','珒','琻','璡','砛','筋','荕','衿','襟','觔','金','釒','釿','钅','鹶','黅','𬬱',],bīng:['仌','仒','兵','冫','冰','掤','氷','鋲'],réng:['仍','礽','芿','辸','陾'],fó:['仏','坲','梻'],'jīn sǎn':['仐'],lún:['仑','伦','侖','倫','囵','圇','婨','崘','崙','棆','沦','淪','磮','腀','菕','蜦','踚','輪','轮','錀','陯','鯩','𬬭',],cāng:['仓','仺','倉','凔','嵢','沧','滄','濸','獊','舱','艙','苍','蒼','螥','鸧',],'zǎi zǐ zī':['仔'],tā:['他','塌','它','榙','溻','牠','祂','褟','趿','遢','闧'],fù:['付','偩','傅','冨','副','咐','坿','复','妇','婦','媍','嬔','富','復','椱','祔','禣','竎','緮','縛','缚','腹','萯','蕧','蚹','蛗','蝜','蝮','袝','複','覄','覆','訃','詂','讣','負','賦','賻','负','赋','赙','赴','輹','鍑','鍢','阜','附','馥','駙','驸','鮒','鰒','鲋','鳆','㳇',],xiān:['仙','仚','佡','僊','僲','先','嘕','奾','屳','廯','忺','憸','掀','暹','杴','氙','珗','祆','秈','籼','繊','纎','纖','苮','褼','襳','跹','蹮','躚','酰','鍁','锨','韯','韱','馦','鱻','鶱','𬸣',],'tuō chà duó':['仛'],hóng:['仜','吰','垬','妅','娂','宏','宖','弘','彋','汯','泓','洪','浤','渱','潂','玒','玜','竑','竤','篊','粠','紘','紭','綋','纮','翃','翝','耾','苰','荭','葒','葓','谹','谼','鈜','鉷','鋐','閎','闳','霐','霟','鞃','魟','鴻','鸿','黉','黌','𫟹','𬭎',],tóng:['仝','佟','哃','峂','峝','庝','彤','晍','曈','桐','氃','浵','潼','犝','獞','眮','瞳','砼','秱','童','粡','膧','茼','蚒','詷','赨','酮','鉖','鉵','銅','铜','餇','鮦','鲖','𫍣','𦒍',],rèn:['仞','仭','刃','刄','妊','姙','屻','岃','扨','牣','祍','紉','紝','絍','纫','纴','肕','腍','衽','袵','訒','認','认','讱','軔','轫','鈓','靭','靱','韌','韧','飪','餁','饪',],qiān:['仟','佥','僉','千','圲','奷','孯','岍','悭','愆','慳','扦','拪','搴','撁','攐','攑','攓','杄','櫏','汘','汧','牵','牽','竏','签','簽','籖','籤','粁','芊','茾','蚈','褰','諐','謙','谦','谸','迁','遷','釺','鈆','鉛','鏲','钎','阡','韆','顅','騫','骞','鬜','鬝','鵮','鹐',],'gǎn hàn':['仠'],'yì gē':['仡'],dài:['代','侢','叇','垈','埭','岱','帒','带','帯','帶','廗','怠','戴','曃','柋','殆','瀻','玳','瑇','甙','簤','紿','緿','绐','艜','蝳','袋','襶','貣','贷','蹛','軑','軚','軩','轪','迨','霴','靆','鴏','黛','黱',],'lìng líng lǐng':['令'],chào:['仦','耖','觘'],'cháng zhǎng':['仧','兏','長','长'],sā:['仨'],cháng:['仩','偿','償','嘗','嚐','嫦','尝','常','徜','瑺','瓺','甞','肠','腸','膓','苌','萇','镸','鱨','鲿',],yí:['仪','侇','儀','冝','匜','咦','圯','夷','姨','宐','宜','宧','寲','峓','嶬','嶷','巸','彛','彜','彝','彞','怡','恞','扅','暆','栘','椬','椸','沂','洟','熪','瓵','痍','移','簃','籎','羠','胰','萓','蛦','螔','觺','謻','貽','贻','跠','迻','遺','鏔','頉','頤','頥','顊','颐','饴','鮧','鴺',],mù:['仫','凩','募','墓','幕','幙','慔','慕','暮','暯','木','楘','毣','沐','炑','牧','狇','目','睦','穆','艒','苜','莯','蚞','鉬','钼','雮','霂',],'men mén':['们'],fǎn:['仮','反','橎','返'],'chào miǎo':['仯'],'yǎng áng':['仰'],zhòng:['仲','众','堹','妕','媑','狆','眾','祌','筗','茽','蚛','衆','衶','諥',],'pǐ pí':['仳'],wò:['仴','偓','卧','媉','幄','握','楃','沃','渥','濣','瓁','瞃','硪','肟','腛','臥','齷','龌',],jiàn:['件','俴','健','僭','剑','剣','剱','劍','劎','劒','劔','墹','寋','建','徤','擶','旔','楗','毽','洊','涧','澗','牮','珔','瞷','磵','礀','箭','糋','繝','腱','臶','舰','艦','荐','薦','覸','諓','諫','譛','谏','賎','賤','贱','趝','践','踐','踺','轞','鉴','鍳','鍵','鐱','鑑','鑒','鑬','鑳','键','間','餞','饯','𬣡',],'jià jiè jie':['价'],'yǎo fó':['仸'],'rèn rén':['任'],'fèn bīn':['份'],dī:['仾','低','啲','埞','堤','岻','彽','樀','滴','磾','秪','羝','袛','趆','隄','鞮','䃅',],fǎng:['仿','倣','旊','昉','昘','瓬','眆','紡','纺','舫','訪','访','髣','鶭',],zhōng:['伀','刣','妐','幒','彸','忠','柊','汷','泈','炂','盅','籦','終','终','舯','蔠','蜙','螤','螽','衳','衷','蹱','鈡','鍾','鐘','钟','锺','鴤','鼨',],pèi:['伂','佩','姵','帔','斾','旆','沛','浿','珮','蓜','轡','辔','配','霈','馷',],diào:['伄','吊','弔','掉','瘹','盄','窎','窵','竨','訋','釣','鈟','銱','鋽','鑃','钓','铞','雿','魡',],dùn:['伅','潡','炖','燉','盾','砘','碷','踲','逇','遁','遯','鈍','钝',],wěn:['伆','刎','吻','呅','抆','桽','稳','穏','穩','紊','肳','脗'],xǐn:['伈'],kàng:['伉','匟','囥','抗','炕','鈧','钪'],ài:['伌','僾','塧','壒','嫒','嬡','愛','懓','暧','曖','爱','瑷','璦','皧','瞹','砹','硋','碍','礙','薆','譺','賹','鑀','隘','靉','餲','馤','鱫','鴱',],'jì qí':['伎','薺'],'xiū xǔ':['休'],'jìn yín':['伒'],dǎn:['伔','刐','撢','玬','瓭','紞','胆','膽','衴','賧','赕','黕','𬘘',],fū:['伕','呋','娐','孵','尃','怤','懯','敷','旉','玞','砆','稃','筟','糐','綒','肤','膚','荂','荴','衭','趺','跗','邞','鄜','酜','鈇','麩','麬','麱','麸','𫓧',],tǎng:['伖','傥','儻','埫','戃','曭','爣','矘','躺','鎲','钂','镋',],yōu:['优','優','呦','嚘','峳','幽','忧','悠','憂','攸','櫌','滺','瀀','纋','羪','耰','逌','鄾','麀',],huǒ:['伙','夥','火','煷','邩','鈥','钬'],'huì kuài':['会','會','浍','璯'],yǔ:['伛','俁','俣','偊','傴','匬','噳','圄','圉','宇','寙','屿','嶼','庾','挧','敔','斞','楀','瑀','瘐','祤','禹','穥','窳','羽','與','萭','貐','鄅','頨','麌','齬','龉','㺄',],cuì:['伜','啛','忰','悴','毳','淬','焠','疩','瘁','竁','粋','粹','紣','綷','翆','翠','脃','脆','脺','膬','膵','臎','萃','襊','顇',],sǎn:['伞','傘','糤','繖','饊','馓'],wěi:['伟','伪','偉','偽','僞','儰','娓','寪','屗','崣','嶉','徫','愇','捤','暐','梶','洧','浘','渨','炜','煒','猥','玮','瑋','痿','緯','纬','腲','艉','芛','苇','荱','萎','葦','蒍','蔿','蜼','諉','诿','踓','鍡','韑','韙','韡','韪','頠','颹','骩','骪','骫','鮪','鲔','𫇭','𬀩','𬱟',],'chuán zhuàn':['传','傳'],'chē jū':['伡','俥','车'],'jū chē':['車'],yá:['伢','厑','厓','堐','岈','崕','崖','涯','漄','牙','玡','琊','睚','笌','芽','蚜','衙','齖',],qiàn:['伣','俔','倩','儙','刋','壍','嬱','悓','棈','椠','槧','欠','歉','皘','篏','篟','縴','芡','蒨','蔳','輤','𬘬',],shāng:['伤','傷','商','墒','慯','殇','殤','滳','漡','熵','蔏','螪','觞','觴','謪','鬺',],chāng:['伥','倀','娼','昌','椙','淐','猖','琩','菖','裮','錩','锠','閶','阊','鯧','鲳','鼚',],'chen cāng':['伧'],xùn:['伨','侚','卂','噀','巺','巽','徇','愻','殉','殾','汛','潠','狥','蕈','訊','訓','訙','训','讯','迅','迿','逊','遜','鑂','顨','馴','驯',],xìn:['伩','囟','孞','脪','舋','衅','訫','釁','阠','顖'],chǐ:['伬','侈','卶','叺','呎','垑','恥','歯','耻','肔','胣','蚇','裭','褫','豉','鉹','齒','齿',],'xián xuán':['伭'],'nú nǔ':['伮'],'bó bǎi':['伯'],'gū gù':['估'],nǐ:['伱','你','儞','孴','拟','擬','旎','晲','狔','苨','薿','隬'],'nì ní':['伲'],bàn:['伴','办','半','姅','怑','扮','瓣','秚','絆','绊','辦','鉡','靽',],xù:['伵','侐','勖','勗','卹','叙','垿','壻','婿','序','恤','敍','敘','旭','昫','朂','槒','欰','殈','汿','沀','洫','溆','漵','潊','烅','烼','煦','獝','珬','盢','瞁','稸','絮','続','緒','緖','續','绪','续','聓','聟','蓄','藚','訹','賉','酗','頊','鱮','㳚',],zhòu:['伷','僽','冑','呪','咒','咮','宙','昼','晝','甃','皱','皺','籀','籒','籕','粙','紂','縐','纣','绉','胄','荮','葤','詋','酎','駎','驟','骤','㤘','㑇',],shēn:['伸','侁','兟','呻','堔','妽','娠','屾','峷','扟','敒','曑','柛','氠','深','燊','珅','甡','甧','申','眒','砷','穼','籶','籸','糂','紳','绅','罙','罧','葠','蓡','蔘','薓','裑','訷','詵','诜','身','駪','鯓','鯵','鰺','鲹','鵢','𬳽',],qū:['伹','佉','匤','呿','坥','屈','岖','岴','嶇','憈','抾','敺','浀','煀','祛','筁','粬','胠','蛆','蛐','袪','覻','詘','诎','趍','躯','軀','阹','駆','駈','驅','驱','髷','魼','鰸','鱋','鶌','麯','麴','麹','黢','㭕','𪨰','䓛',],'sì cì':['伺'],bēng:['伻','嘣','奟','崩','嵭','閍'],'sì shì':['似'],'jiā qié gā':['伽'],'yǐ chì':['佁'],'diàn tián':['佃','钿'],'hān gàn':['佄'],mài:['佅','劢','勱','卖','唛','売','脈','衇','賣','迈','邁','霡','霢','麥','麦','鿏',],dàn:['但','僤','啖','啗','啿','噉','嚪','帎','憺','旦','柦','氮','沊','泹','淡','狚','疍','癚','禫','窞','腅','萏','蓞','蛋','蜑','觛','訑','誕','诞','贉','霮','餤','饏','駳','髧','鴠','𫢸',],bù:['佈','勏','吥','咘','埗','埠','布','廍','怖','悑','步','歨','歩','瓿','篰','荹','蔀','踄','部','郶','鈈','钚','餢',],bǐ:['佊','俾','匕','夶','妣','彼','朼','柀','比','毞','沘','疕','秕','笔','筆','粃','聛','舭','貏','鄙',],'zhāo shào':['佋'],cǐ:['佌','此','泚','皉','𫚖'],wèi:['位','卫','味','喂','墛','媦','慰','懀','未','渭','煟','熭','犚','猬','畏','緭','罻','胃','苿','菋','藯','蘶','蝟','螱','衛','衞','褽','謂','讆','讏','谓','躗','躛','軎','轊','鏏','霨','餧','餵','饖','魏','鮇','鳚',],zuǒ:['佐','左','繓'],yǎng:['佒','傟','养','坱','岟','慃','懩','攁','氧','氱','炴','痒','癢','礢','紻','蝆','軮','養','駚',],'tǐ tī':['体','體'],zhàn:['佔','偡','嶘','战','戦','戰','栈','桟','棧','湛','站','綻','绽','菚','蘸','虥','虦','譧','轏','驏',],'hé hē hè':['何'],bì:['佖','咇','哔','嗶','坒','堛','壁','奰','妼','婢','嬖','币','幣','幤','庇','庳','廦','弊','弻','弼','彃','必','怭','愊','愎','敝','斃','梐','毕','毖','毙','湢','滗','滭','潷','煏','熚','狴','獘','獙','珌','璧','畀','畢','疪','痹','痺','皕','睤','碧','筚','箅','箆','篦','篳','粊','綼','縪','繴','罼','腷','苾','荜','萆','萞','蓖','蓽','蔽','薜','蜌','袐','襅','襞','襣','觱','詖','诐','貱','贔','赑','跸','蹕','躃','躄','避','邲','鄨','鄪','鉍','鏎','鐴','铋','閇','閉','閟','闭','陛','韠','飶','饆','馝','駜','驆','髀','魓','鮅','鷝','鷩','鼊',],tuó:['佗','坨','堶','岮','槖','橐','沱','砣','砤','碢','紽','詑','跎','酡','阤','陀','陁','駝','駞','騨','驒','驝','驼','鮀','鴕','鸵','鼉','鼍','鼧','𬶍',],shé:['佘','舌','虵','蛥'],'yì dié':['佚','昳','泆','軼'],'fó fú bì bó':['佛'],'zuò zuō':['作'],gōu:['佝','沟','溝','痀','篝','簼','緱','缑','袧','褠','鈎','鉤','钩','鞲','韝',],nìng:['佞','侫','倿','寕','泞','澝','濘'],qú:['佢','劬','戵','斪','欋','欔','氍','淭','灈','爠','璖','璩','癯','磲','籧','絇','胊','臞','菃','葋','蕖','蘧','蟝','蠷','蠼','衐','衢','躣','軥','鑺','鴝','鸜','鸲','鼩',],'yōng yòng':['佣'],wǎ:['佤','咓','砙','邷'],kǎ:['佧','垰','胩','裃','鉲'],bāo:['佨','勹','包','孢','煲','笣','胞','苞','蕔','裦','褒','襃','闁','齙','龅',],'huái huí':['佪'],'gé hè':['佫'],lǎo:['佬','咾','恅','栳','狫','珯','硓','老','耂','荖','蛯','轑','銠','铑','鮱',],xiáng:['佭','庠','栙','祥','絴','翔','詳','跭'],gé:['佮','匌','呄','嗝','塥','愅','挌','搿','槅','櫊','滆','膈','臵','茖','觡','諽','輵','轕','閣','阁','隔','鞷','韐','韚','騔','骼','鮯',],yáng:['佯','劷','垟','崸','徉','扬','揚','敭','旸','昜','暘','杨','楊','洋','炀','珜','疡','瘍','眻','蛘','諹','輰','鍚','钖','阦','阳','陽','霷','颺','飏','鰑','鴹','鸉',],bǎi:['佰','捭','摆','擺','栢','百','竡','粨','襬'],fǎ:['佱','峜','法','灋','砝','鍅'],mǐng:['佲','凕','姳','慏','酩'],'èr nài':['佴'],hěn:['佷','很','狠','詪','𬣳'],huó:['佸','活'],guǐ:['佹','匦','匭','厬','垝','姽','宄','庋','庪','恑','晷','湀','癸','祪','簋','蛫','蟡','觤','詭','诡','軌','轨','陒','鬼',],quán:['佺','全','啳','埢','姾','峑','巏','拳','搼','权','楾','権','權','泉','洤','湶','牷','犈','瑔','痊','硂','筌','縓','荃','葲','蜷','蠸','觠','詮','诠','跧','踡','輇','辁','醛','銓','铨','闎','顴','颧','駩','騡','鬈','鰁','鳈','齤',],tiāo:['佻','庣','旫','祧','聎'],jiǎo:['佼','儌','孂','挢','搅','撟','撹','攪','敫','敽','敿','晈','暞','曒','灚','燞','狡','璬','皎','皦','絞','纐','绞','腳','臫','蟜','譑','賋','踋','鉸','铰','餃','饺','鱎','龣',],cì:['佽','刾','庛','朿','栨','次','絘','茦','莿','蛓','螆','賜','赐',],xíng:['侀','刑','哘','型','娙','形','洐','硎','蛵','邢','郉','鈃','鉶','銒','钘','铏','陉','陘','餳','𫰛',],tuō:['侂','咃','咜','圫','托','拕','拖','汑','脫','脱','莌','袥','託','讬','飥','饦','魠','鮵',],kǎn:['侃','偘','冚','坎','惂','砍','莰','輡','轗','顑'],zhí:['侄','値','值','埴','執','姪','嬂','戠','执','摭','植','樴','淔','漐','直','禃','絷','縶','聀','职','職','膱','蟙','跖','踯','蹠','躑','軄','釞','馽',],gāi:['侅','垓','姟','峐','晐','畡','祴','荄','該','该','豥','賅','賌','赅','陔',],lái:['來','俫','倈','崃','崍','庲','来','梾','棶','涞','淶','猍','琜','筙','箂','莱','萊','逨','郲','錸','铼','騋','鯠','鶆','麳',],kuǎ:['侉','咵','垮','銙'],gōng:['侊','公','功','匑','匔','塨','宫','宮','工','幊','弓','恭','攻','杛','碽','糼','糿','肱','觥','觵','躬','躳','髸','龔','龚','䢼',],lì:['例','俐','俪','傈','儮','儷','凓','利','力','励','勵','历','厉','厤','厯','厲','叓','吏','呖','唎','唳','嚦','囇','坜','塛','壢','娳','婯','屴','岦','悧','悷','慄','戾','搮','暦','曆','曞','朸','枥','栃','栗','栛','檪','櫔','櫪','欐','歴','歷','沥','沴','涖','溧','濿','瀝','爏','犡','猁','珕','瑮','瓅','瓑','瓥','疬','痢','癧','盭','睙','砅','砺','砾','磿','礪','礫','礰','禲','秝','立','笠','篥','粒','粝','糲','脷','苈','茘','荔','莅','莉','蒚','蒞','藶','蚸','蛎','蛠','蜧','蝷','蠇','蠣','詈','讈','赲','轢','轣','轹','酈','鉝','隶','隷','雳','靂','靋','鬁','鳨','鴗','鷅','麜','𫵷','𬍛',],yīn:['侌','凐','喑','噾','囙','因','垔','堙','姻','婣','愔','慇','栶','氤','洇','溵','濦','瘖','禋','秵','筃','絪','緸','茵','蒑','蔭','裀','諲','銦','铟','闉','阥','阴','陰','陻','隂','霒','霠','鞇','音','韾','駰','骃','齗','𬘡','𬤇','𬮱',],mǐ:['侎','孊','弭','敉','洣','渳','灖','米','粎','羋','脒','芈','葞','蔝','銤',],zhū:['侏','株','槠','橥','櫧','櫫','洙','潴','瀦','猪','珠','硃','秼','絑','茱','蕏','蛛','蝫','蠩','袾','誅','諸','诛','诸','豬','跦','邾','銖','铢','駯','鮢','鯺','鴸','鼄',],ān:['侒','偣','媕','安','峖','庵','桉','氨','盦','盫','腤','菴','萻','葊','蓭','誝','諳','谙','鞌','鞍','韽','馣','鮟','鵪','鶕','鹌','𩽾',],lù:['侓','僇','勎','勠','圥','坴','塶','娽','峍','廘','彔','录','戮','摝','椂','樚','淕','淥','渌','漉','潞','琭','璐','甪','盝','睩','硉','祿','禄','稑','穋','箓','簏','簬','簵','簶','籙','粶','蔍','蕗','虂','螰','賂','赂','趢','路','踛','蹗','輅','轆','辂','辘','逯','醁','錄','録','錴','鏴','陸','騄','騼','鯥','鴼','鵦','鵱','鷺','鹭','鹿','麓','𫘧',],móu:['侔','劺','恈','眸','蛑','謀','谋','踎','鍪','鴾','麰'],ér:['侕','儿','児','兒','峏','栭','洏','粫','而','胹','荋','袻','輀','轜','陑','隭','髵','鮞','鲕','鴯','鸸',],'dòng tǒng tóng':['侗'],chà:['侘','奼','姹','岔','汊','詫','诧'],chì:['侙','傺','勅','勑','叱','啻','彳','恜','慗','憏','懘','抶','敕','斥','杘','湁','灻','炽','烾','熾','痓','痸','瘛','翄','翅','翤','翨','腟','赤','趩','遫','鉓','雴','飭','饬','鶒','鷘',],'gòng gōng':['供','共'],zhōu:['侜','周','喌','州','徟','洲','淍','炿','烐','珘','矪','舟','謅','譸','诌','賙','赒','輈','輖','辀','週','郮','銂','霌','駲','騆','鵃','鸼',],rú:['侞','儒','嚅','如','嬬','孺','帤','曘','桇','渪','濡','筎','茹','蕠','薷','蝡','蠕','袽','襦','邚','醹','銣','铷','顬','颥','鱬','鴑','鴽',],'jiàn cún':['侟'],xiá:['侠','俠','匣','峡','峽','敮','暇','柙','炠','烚','狎','狭','狹','珨','瑕','硖','硤','碬','祫','筪','縖','翈','舝','舺','蕸','赮','轄','辖','遐','鍜','鎋','陜','陿','霞','騢','魻','鶷','黠',],lǚ:['侣','侶','儢','吕','呂','屡','屢','履','挔','捛','旅','梠','焒','祣','稆','穭','絽','縷','缕','膂','膐','褛','褸','郘','鋁','铝',],ta:['侤'],'jiǎo yáo':['侥','僥','徺'],zhēn:['侦','偵','寊','帧','帪','幀','搸','斟','桢','楨','榛','樼','殝','浈','湞','潧','澵','獉','珍','珎','瑧','甄','眞','真','砧','碪','祯','禎','禛','箴','胗','臻','葴','蒖','蓁','薽','貞','贞','轃','遉','酙','針','鉁','錱','鍼','针','鱵',],'cè zè zhāi':['侧','側'],kuài:['侩','儈','凷','哙','噲','圦','块','塊','巜','廥','快','旝','欳','狯','獪','筷','糩','脍','膾','郐','鄶','鱠','鲙',],chái:['侪','儕','喍','柴','犲','祡','豺'],nóng:['侬','儂','农','哝','噥','檂','欁','浓','濃','燶','禯','秾','穠','脓','膿','蕽','襛','譨','農','辳','醲','鬞','𬪩',],jǐn:['侭','儘','卺','厪','巹','槿','漌','瑾','紧','緊','菫','蓳','謹','谨','錦','锦','饉','馑',],'hóu hòu':['侯','矦'],jiǒng:['侰','僒','冏','囧','泂','澃','炯','烱','煚','煛','熲','燛','窘','綗','褧','迥','逈','顈','颎','䌹',],'chěng tǐng':['侱'],'zhèn zhēn':['侲','揕'],zuò:['侳','做','唑','坐','岝','岞','座','祚','糳','胙','葃','葄','蓙','袏','阼',],qīn:['侵','兓','媇','嵚','嶔','欽','衾','誛','钦','顉','駸','骎','鮼',],jú:['侷','啹','婅','局','巈','椈','橘','泦','淗','湨','焗','犑','狊','粷','菊','蘜','趜','跼','蹫','輂','郹','閰','駶','驧','鵙','鵴','鶪','鼰','鼳','䴗',],'shù dōu':['侸'],tǐng:['侹','圢','娗','挺','涏','烶','珽','脡','艇','誔','頲','颋',],shèn:['侺','愼','慎','昚','涁','渗','滲','瘆','瘮','眘','祳','肾','胂','脤','腎','蜃','蜄','鋠',],'tuì tuó':['侻'],nán:['侽','喃','娚','抩','暔','枏','柟','楠','男','畘','莮','萳','遖',],xiāo:['侾','哓','嘵','嚻','囂','婋','宯','宵','庨','彇','揱','枭','枵','梟','櫹','歊','毊','消','潇','瀟','灱','灲','烋','焇','猇','獢','痚','痟','硝','硣','窙','箫','簘','簫','綃','绡','翛','膮','萧','蕭','虈','虓','蟂','蟏','蟰','蠨','踃','逍','銷','销','霄','颵','驍','骁','髇','髐','魈','鴞','鴵','鷍','鸮',],'biàn pián':['便','緶','缏'],tuǐ:['俀','腿','蹆','骽'],xì:['係','匸','卌','呬','墍','屃','屓','屭','忥','怬','恄','椞','潝','潟','澙','熂','犔','磶','禊','細','綌','縘','细','绤','舃','舄','蕮','虩','衋','覤','赩','趇','郤','釳','阋','隙','隟','霼','餼','饩','鬩','黖',],cù:['促','媨','憱','猝','瘄','瘯','簇','縬','脨','蔟','誎','趗','踧','踿','蹙','蹴','蹵','醋','顣','鼀',],é:['俄','囮','娥','峉','峨','峩','涐','珴','皒','睋','磀','莪','訛','誐','譌','讹','迗','鈋','鋨','锇','頟','額','额','魤','鵝','鵞','鹅',],qiú:['俅','叴','唒','囚','崷','巯','巰','扏','梂','殏','毬','求','汓','泅','浗','湭','煪','犰','玌','球','璆','皳','盚','紌','絿','肍','芁','莍','虬','虯','蛷','裘','觓','觩','訄','訅','賕','赇','逎','逑','遒','酋','釚','釻','銶','頄','鮂','鯄','鰽','鼽','𨱇',],xú:['俆','徐','禑'],'guàng kuāng':['俇'],kù:['俈','喾','嚳','库','庫','廤','瘔','絝','绔','袴','裤','褲','酷',],wù:['俉','务','務','勿','卼','坞','塢','奦','婺','寤','屼','岉','嵨','忢','悞','悟','悮','戊','扤','晤','杌','溩','焐','熃','物','痦','矹','窹','粅','蘁','誤','误','鋈','阢','隖','雾','霚','霧','靰','騖','骛','鶩','鹜','鼿','齀',],jùn:['俊','儁','呁','埈','寯','峻','懏','捃','攟','晙','棞','燇','珺','畯','竣','箟','蜠','賐','郡','陖','餕','馂','駿','骏','鵔','鵕','鵘','䐃',],liáng:['俍','墚','梁','椋','樑','粮','粱','糧','良','輬','辌','𫟅',],zǔ:['俎','唨','爼','祖','組','组','詛','诅','鎺','阻','靻'],'qiào xiào':['俏'],yǒng:['俑','勇','勈','咏','埇','塎','嵱','彮','怺','恿','悀','惥','愑','愹','慂','柡','栐','永','泳','湧','甬','蛹','詠','踊','踴','鯒','鲬',],hùn:['俒','倱','圂','尡','慁','掍','溷','焝','睴','觨','諢','诨'],jìng:['俓','傹','境','妌','婙','婧','弪','弳','径','徑','敬','曔','桱','梷','浄','瀞','獍','痉','痙','竞','竟','竫','競','竸','胫','脛','莖','誩','踁','迳','逕','鏡','镜','靖','静','靜','鵛',],sàn:['俕','閐'],pěi:['俖'],sú:['俗'],xī:['俙','僖','兮','凞','卥','厀','吸','唏','唽','嘻','噏','嚱','夕','奚','嬆','嬉','屖','嵠','巇','希','徆','徯','息','悉','悕','惁','惜','昔','晞','晰','晳','曦','析','桸','榽','樨','橀','欷','氥','汐','浠','淅','渓','溪','烯','焁','焈','焟','熄','熈','熙','熹','熺','熻','燨','爔','牺','犀','犠','犧','琋','瘜','皙','睎','瞦','矽','硒','磎','礂','稀','穸','窸','粞','糦','緆','繥','羲','翕','翖','肸','肹','膝','舾','莃','菥','蒠','蜥','螅','蟋','蠵','西','觹','觽','觿','譆','谿','豀','豨','豯','貕','赥','邜','鄎','酅','醯','釸','錫','鏭','鐊','鑴','锡','隵','餏','饎','饻','鯑','鵗','鸂','鼷',],lǐ:['俚','娌','峢','峲','李','欚','浬','澧','理','礼','禮','粴','裏','裡','豊','逦','邐','醴','鋰','锂','鯉','鱧','鱱','鲤','鳢',],bǎo:['保','堢','媬','宝','寚','寳','寶','珤','緥','葆','藵','褓','賲','靌','飹','飽','饱','駂','鳵','鴇','鸨',],'yú shù yù':['俞'],'sì qí':['俟'],'xìn shēn':['信'],xiū:['俢','修','咻','庥','樇','烌','羞','脙','脩','臹','貅','銝','鎀','飍','饈','馐','髤','髹','鮴','鱃','鵂','鸺','䗛',],dì:['俤','偙','僀','埊','墑','墬','娣','帝','怟','旳','梊','焍','玓','甋','眱','睇','碲','祶','禘','第','締','缔','腣','菂','蒂','蔕','蝃','蝭','螮','諦','谛','踶','递','逓','遞','遰','鉪','𤧛','䗖',],chóu:['俦','儔','嬦','惆','愁','懤','栦','燽','畴','疇','皗','稠','筹','籌','絒','綢','绸','菗','詶','讎','讐','踌','躊','酧','酬','醻','雔','雠','雦',],zhì:['俧','偫','儨','制','劕','垁','娡','寘','帙','帜','幟','庢','庤','廌','彘','徏','徝','志','忮','懥','懫','挃','挚','掷','摯','擲','旘','晊','智','栉','桎','梽','櫍','櫛','治','洷','滍','滞','滯','潌','瀄','炙','熫','狾','猘','璏','瓆','痔','痣','礩','祑','秩','秷','稚','稺','穉','窒','紩','緻','置','翐','膣','至','致','芖','蛭','袟','袠','製','覟','觗','觯','觶','誌','豑','豒','貭','質','贄','质','贽','跱','踬','躓','輊','轾','郅','銍','鋕','鑕','铚','锧','陟','隲','雉','駤','騭','騺','驇','骘','鯯','鴙','鷙','鸷','𬃊',],'liǎ liǎng':['俩'],jiǎn:['俭','倹','儉','减','剪','堿','弿','彅','戩','戬','拣','挸','捡','揀','撿','枧','柬','梘','检','検','檢','減','湕','瀽','瑐','睑','瞼','硷','碱','礆','笕','筧','简','簡','絸','繭','翦','茧','藆','蠒','裥','襇','襉','襺','詃','謇','謭','譾','谫','趼','蹇','鐗','鬋','鰎','鹸','鹻','鹼',],huò:['俰','咟','嚯','嚿','奯','彠','惑','或','擭','旤','曤','檴','沎','湱','瀖','獲','癨','眓','矐','祸','禍','穫','窢','耯','臛','艧','获','蒦','藿','蠖','謋','貨','货','鍃','鑊','镬','雘','霍','靃','韄','㸌',],'jù jū':['俱','据','鋸','锯'],xiào:['俲','傚','効','咲','哮','啸','嘋','嘨','嘯','孝','效','斅','斆','歗','涍','熽','笑','詨','誟',],pái:['俳','徘','牌','犤','猅','簰','簲','輫'],biào:['俵','鰾','鳔'],'chù tì':['俶'],fèi:['俷','剕','厞','吠','屝','废','廃','廢','昲','曊','櫠','沸','濷','狒','癈','肺','萉','費','费','鐨','镄','陫','靅','鼣',],fèng:['俸','凤','奉','湗','焨','煈','賵','赗','鳯','鳳','鴌'],ǎn:['俺','唵','埯','揞','罯','銨','铵'],bèi:['俻','倍','偝','偹','備','僃','备','悖','惫','愂','憊','昁','梖','焙','牬','犕','狈','狽','珼','琲','碚','禙','糒','苝','蓓','蛽','褙','貝','贝','軰','輩','辈','邶','郥','鄁','鋇','鐾','钡','鞁','鞴','𬇙',],yù:['俼','儥','喅','喩','喻','域','堉','妪','嫗','寓','峪','嶎','庽','彧','御','愈','慾','戫','昱','棛','棜','棫','櫲','欎','欝','欲','毓','浴','淯','滪','潏','澦','灪','焴','煜','燏','燠','爩','狱','獄','玉','琙','瘉','癒','砡','硢','硲','礇','礖','礜','禦','秗','稢','稶','篽','籞','籲','粖','緎','罭','聿','肀','艈','芋','芌','茟','蒮','蓣','蓹','蕷','蘌','蜟','蜮','袬','裕','誉','諭','譽','谕','豫','軉','輍','逳','遇','遹','郁','醧','鈺','鋊','錥','鐭','钰','閾','阈','雤','霱','預','预','飫','饇','饫','馭','驈','驭','鬰','鬱','鬻','魊','鱊','鳿','鴥','鴧','鴪','鵒','鷸','鸒','鹆','鹬',],xīn:['俽','噺','妡','嬜','廞','心','忄','忻','惞','新','昕','杺','欣','歆','炘','盺','薪','訢','辛','邤','鈊','鋅','鑫','锌','馨','馫','䜣','𫷷',],'hǔ chí':['俿'],jiù:['倃','僦','匓','匛','匶','厩','咎','就','廄','廏','廐','慦','捄','救','旧','柩','柾','桕','欍','殧','疚','臼','舅','舊','鯦','鷲','鹫','麔','齨','㠇',],yáo:['倄','傜','嗂','垚','堯','姚','媱','尧','尭','峣','嶢','嶤','徭','揺','搖','摇','摿','暚','榣','烑','爻','猺','珧','瑤','瑶','磘','窑','窯','窰','肴','蘨','謠','謡','谣','軺','轺','遙','遥','邎','顤','颻','飖','餆','餚','鰩','鱙','鳐',],'cuì zú':['倅'],'liǎng liǎ':['倆'],wǎn:['倇','唍','婉','惋','挽','晚','晥','晩','晼','梚','椀','琬','畹','皖','盌','碗','綩','綰','绾','脘','萖','踠','輓','鋔',],zǒng:['倊','偬','傯','嵸','总','惣','捴','搃','摠','燪','総','緫','縂','總','蓗',],guān:['倌','关','官','棺','瘝','癏','窤','蒄','関','闗','關','鰥','鱞','鳏',],tiǎn:['倎','唺','忝','悿','晪','殄','淟','睓','腆','舔','覥','觍','賟','錪','餂',],mén:['們','扪','捫','璊','菛','虋','鍆','钔','門','閅','门','𫞩'],'dǎo dào':['倒'],'tán tàn':['倓','埮'],'juè jué':['倔'],chuí:['倕','垂','埀','捶','搥','桘','棰','槌','箠','腄','菙','錘','鎚','锤','陲','顀',],xìng:['倖','姓','婞','嬹','幸','性','悻','杏','涬','緈','臖','荇','莕','葕',],péng:['倗','傰','塜','塳','弸','憉','捀','朋','棚','椖','樥','硼','稝','竼','篷','纄','膨','芃','蓬','蘕','蟚','蟛','袶','輣','錋','鑝','韸','韼','騯','髼','鬅','鬔','鵬','鹏',],'tǎng cháng':['倘'],hòu:['候','厚','后','垕','堠','後','洉','茩','豞','逅','郈','鮜','鱟','鲎','鲘',],tì:['倜','剃','嚏','嚔','屉','屜','悌','悐','惕','惖','戻','掦','替','朑','歒','殢','涕','瓋','笹','籊','薙','褅','逖','逷','髰','鬀','鬄',],gàn:['倝','凎','幹','榦','檊','淦','灨','盰','紺','绀','詌','贑','赣','骭','㽏',],'liàng jìng':['倞','靓'],suī:['倠','哸','夊','滖','濉','眭','睢','芕','荽','荾','虽','雖','鞖',],'chàng chāng':['倡'],jié:['倢','偼','傑','刦','刧','刼','劫','劼','卩','卪','婕','媫','孑','岊','崨','嵥','嶻','巀','幯','截','捷','掶','擮','昅','杢','杰','桀','桝','楬','楶','榤','洁','滐','潔','狤','睫','礍','竭','節','羯','莭','蓵','蛣','蜐','蠘','蠞','蠽','衱','袺','訐','詰','誱','讦','踕','迼','鉣','鍻','镼','頡','鮚','鲒','㛃',],'kǒng kōng':['倥'],juàn:['倦','劵','奆','慻','桊','淃','狷','獧','眷','睊','睠','絭','絹','绢','罥','羂','腃','蔨','鄄','餋',],zōng:['倧','堫','宗','嵏','嵕','惾','朡','棕','椶','熧','猣','磫','緃','翪','腙','葼','蝬','豵','踨','踪','蹤','鍐','鑁','騌','騣','骔','鬃','鬉','鬷','鯮','鯼',],ní:['倪','坭','埿','尼','屔','怩','淣','猊','籾','聣','蚭','蜺','觬','貎','跜','輗','郳','鈮','铌','霓','馜','鯢','鲵','麑','齯','𫐐','𫠜',],zhuō:['倬','拙','捉','桌','梲','棁','棳','槕','涿','窧','鐯','䦃',],'wō wēi':['倭'],luǒ:['倮','剆','曪','瘰','癳','臝','蓏','蠃','裸','躶'],sōng:['倯','凇','娀','崧','嵩','庺','憽','松','枀','枩','柗','梥','檧','淞','濍','硹','菘','鬆',],lèng:['倰','堎','愣','睖','踜'],zì:['倳','剚','字','恣','渍','漬','牸','眥','眦','胔','胾','自','茡','荢',],bèn:['倴','坌','捹','撪','渀','笨','逩'],cǎi:['倸','啋','婇','彩','採','棌','毝','睬','綵','跴','踩'],zhài:['债','債','寨','瘵','砦'],yē:['倻','吔','噎','擨','暍','椰','歋','潱','蠮'],shà:['倽','唼','喢','歃','箑','翜','翣','萐','閯','霎'],qīng:['倾','傾','卿','圊','寈','氢','氫','淸','清','蜻','軽','輕','轻','郬','錆','鑋','靑','青','鯖',],yīng:['偀','嘤','噟','嚶','婴','媖','嫈','嬰','孆','孾','愥','撄','攖','朠','桜','樱','櫻','渶','煐','珱','瑛','璎','瓔','甇','甖','碤','礯','緓','纓','绬','缨','罂','罃','罌','膺','英','莺','蘡','蝧','蠳','褮','譻','賏','軈','鑍','锳','霙','韺','鴬','鶑','鶧','鶯','鷪','鷹','鸎','鸚','鹦','鹰','䓨',],'chēng chèn':['偁','爯'],ruǎn:['偄','朊','瑌','瓀','碝','礝','腝','軟','輭','软','阮'],'zhòng tóng':['偅'],chǔn:['偆','惷','睶','萶','蠢','賰'],'jiǎ jià':['假'],'jì jié':['偈'],'bǐng bìng':['偋'],ruò:['偌','叒','嵶','弱','楉','焫','爇','箬','篛','蒻','鄀','鰙','鰯','鶸',],tí:['偍','厗','啼','嗁','崹','漽','瑅','睼','禵','稊','緹','缇','罤','蕛','褆','謕','趧','蹄','蹏','醍','鍗','題','题','騠','鮷','鯷','鳀','鵜','鷤','鹈','𫘨',],wēi:['偎','危','喴','威','媙','嶶','巍','微','愄','揋','揻','椳','楲','溦','烓','煨','燰','癓','縅','葨','葳','薇','蜲','蝛','覣','詴','逶','隇','隈','霺','鰃','鰄','鳂',],piān:['偏','囨','媥','楄','犏','篇','翩','鍂'],yàn:['偐','厌','厭','唁','喭','嚈','嚥','堰','妟','姲','嬊','嬿','宴','彥','彦','敥','晏','暥','曕','曣','滟','灎','灔','灧','灩','焔','焰','焱','熖','燄','牪','猒','砚','硯','艳','艶','艷','覎','觃','觾','諺','讌','讞','谚','谳','豓','豔','贋','贗','赝','軅','酀','酽','醼','釅','雁','餍','饜','騐','験','騴','驗','驠','验','鬳','鳫','鴈','鴳','鷃','鷰','齞',],'tǎng dàng':['偒'],è:['偔','匎','卾','厄','呝','咢','噩','垩','堊','堮','岋','崿','廅','悪','愕','戹','扼','搤','搹','擜','櫮','歞','歺','湂','琧','砈','砐','硆','腭','苊','萼','蕚','蚅','蝁','覨','諤','讍','谔','豟','軛','軶','轭','遌','遏','遻','鄂','鈪','鍔','鑩','锷','阨','阸','頞','顎','颚','餓','餩','饿','鰐','鰪','鱷','鳄','鶚','鹗','齃','齶','𫫇','𥔲',],xié:['偕','勰','协','協','嗋','垥','奊','恊','愶','拹','携','撷','擕','擷','攜','斜','旪','熁','燲','綊','緳','縀','缬','翓','胁','脅','脇','脋','膎','蝢','衺','襭','諧','讗','谐','鞋','鞵','龤','㙦',],chě:['偖','扯','撦'],shěng:['偗','渻','眚'],chā:['偛','嗏','扠','挿','插','揷','疀','臿','艖','銟','鍤','锸','餷',],huáng:['偟','凰','喤','堭','墴','媓','崲','徨','惶','楻','湟','煌','獚','瑝','璜','癀','皇','磺','穔','篁','簧','艎','葟','蝗','蟥','諻','趪','遑','鍠','鐄','锽','隍','韹','餭','騜','鰉','鱑','鳇','鷬','黃','黄','𨱑',],yǎo:['偠','咬','婹','宎','岆','杳','柼','榚','溔','狕','窅','窈','舀','苭','闄','騕','鷕','齩',],'chǒu qiào':['偢'],yóu:['偤','尤','庮','怣','沋','油','浟','游','犹','猶','猷','由','疣','秞','肬','莜','莸','蕕','蚰','蝣','訧','輏','輶','逰','遊','邮','郵','鈾','铀','駀','魷','鮋','鱿','鲉','𬨎',],xū:['偦','墟','媭','嬃','楈','欨','歔','燸','疞','盱','綇','縃','繻','胥','蕦','虗','虚','虛','蝑','裇','訏','許','諝','譃','谞','鑐','需','須','须','顼','驉','鬚','魆','魖','𬣙','𦈡',],zhā:['偧','哳','抯','挓','揸','摣','樝','渣','皶','觰','譇','齄','齇',],cī:['偨','疵','蠀','趀','骴','髊','齹'],bī:['偪','屄','楅','毴','豍','逼','鰏','鲾','鵖'],xún:['偱','噚','寻','尋','峋','巡','廵','循','恂','揗','攳','旬','杊','栒','桪','樳','洵','浔','潯','燅','燖','珣','璕','畃','紃','荀','蟳','詢','询','鄩','鱏','鱘','鲟','𬘓','𬩽','𬍤','𬊈',],'cāi sī':['偲'],duān:['偳','媏','端','褍','鍴'],ǒu:['偶','吘','嘔','耦','腢','蕅','藕','𬉼','𠙶'],tōu:['偷','偸','鍮'],'zán zá zǎ':['偺'],'lǚ lóu':['偻','僂'],fèn:['偾','僨','奋','奮','弅','忿','愤','憤','瀵','瞓','秎','粪','糞','膹','鱝','鲼',],'kuǐ guī':['傀'],sǒu:['傁','叜','叟','嗾','櫢','瞍','薮','藪'],'zhì sī tí':['傂'],sù:['傃','僳','嗉','塐','塑','夙','嫊','愫','憟','榡','樎','樕','殐','泝','涑','溯','溸','潚','潥','玊','珟','璛','簌','粛','粟','素','縤','肃','肅','膆','蔌','藗','觫','訴','謖','诉','谡','趚','蹜','速','遡','遬','鋉','餗','驌','骕','鱐','鷫','鹔','𫗧',],xiā:['傄','煆','瞎','虲','谺','颬','鰕'],'yuàn yuán':['傆','媛'],rǒng:['傇','冗','宂','氄','軵'],nù:['傉','怒'],yùn:['傊','孕','恽','惲','愠','慍','枟','腪','蕴','薀','藴','蘊','褞','貟','运','運','郓','鄆','酝','醖','醞','韗','韞','韵','韻','餫',],'gòu jiǎng':['傋'],mà:['傌','嘜','榪','睰','祃','禡','罵','閁','駡','骂','鬕'],bàng:['傍','塝','棒','玤','稖','艕','蒡','蜯','謗','谤','鎊','镑',],diān:['傎','厧','嵮','巅','巓','巔','掂','攧','敁','槇','滇','癫','癲','蹎','顚','顛','颠','齻',],táng:['傏','唐','啺','坣','堂','塘','搪','棠','榶','溏','漟','煻','瑭','磄','禟','篖','糃','糖','糛','膅','膛','蓎','螗','螳','赯','踼','鄌','醣','鎕','隚','餹','饄','鶶','䣘',],hào:['傐','哠','恏','昊','昦','晧','暠','暤','暭','曍','浩','淏','澔','灏','灝','皓','皜','皞','皡','皥','耗','聕','薃','號','鄗','顥','颢','鰝',],'xī xì':['傒'],shān:['傓','删','刪','剼','圸','山','挻','搧','柵','檆','潸','澘','煽','狦','珊','笘','縿','羴','羶','脠','舢','芟','衫','跚','軕','邖','閊','鯅',],'qiàn jiān':['傔'],'què jué':['傕','埆'],'cāng chen':['傖'],róng:['傛','媶','嫆','嬫','容','峵','嵘','嶸','戎','搈','曧','栄','榕','榮','榵','毧','溶','瀜','烿','熔','狨','瑢','穁','絨','绒','羢','肜','茙','茸','荣','蓉','蝾','融','螎','蠑','褣','鎔','镕','駥',],'tà tàn':['傝'],suō:['傞','唆','嗍','嗦','娑','摍','桫','梭','睃','簑','簔','羧','莏','蓑','趖','鮻',],dǎi:['傣','歹'],zài:['傤','儎','再','在','扗','洅','載','酨'],gǔ:['傦','古','啒','尳','愲','榖','榾','汩','淈','濲','瀔','牯','皷','皼','盬','瞽','穀','罟','羖','股','脵','臌','薣','蛊','蠱','詁','诂','轂','逧','鈷','钴','餶','馉','鼓','鼔','𦙶',],bīn:['傧','宾','彬','斌','椕','滨','濒','濱','濵','瀕','繽','缤','虨','豩','豳','賓','賔','邠','鑌','镔','霦','顮',],chǔ:['储','儲','杵','椘','楚','楮','檚','濋','璴','础','礎','禇','處','齭','齼','𬺓',],nuó:['傩','儺','挪','梛','橠'],'cān càn':['傪'],lěi:['傫','儡','厽','垒','塁','壘','壨','櫐','灅','癗','矋','磊','礨','耒','蕌','蕾','藟','蘽','蠝','誄','讄','诔','鑸','鸓',],cuī:['催','凗','墔','崔','嵟','慛','摧','榱','獕','磪','鏙'],yōng:['傭','嗈','墉','壅','嫞','庸','廱','慵','拥','擁','滽','灉','牅','痈','癕','癰','臃','邕','郺','鄘','鏞','镛','雍','雝','饔','鱅','鳙','鷛',],'zāo cáo':['傮'],sǒng:['傱','嵷','怂','悚','愯','慫','竦','耸','聳','駷','㧐'],ào:['傲','坳','垇','墺','奡','嫯','岙','岰','嶴','懊','擙','澳','鏊','驁','骜',],'qī còu':['傶'],chuǎng:['傸','磢','闖','闯'],shǎ:['傻','儍'],hàn:['傼','垾','悍','憾','扞','捍','撖','撼','旱','晘','暵','汉','涆','漢','瀚','焊','猂','皔','睅','翰','莟','菡','蛿','蜭','螒','譀','輚','釬','銲','鋎','雗','頷','顄','颔','駻','鶾',],zhāng:['傽','嫜','张','張','彰','慞','暲','樟','漳','獐','璋','章','粻','蔁','蟑','遧','鄣','鏱','餦','騿','鱆','麞',],'yān yàn':['傿','墕','嬮'],'piào biāo':['僄','骠'],liàn:['僆','堜','媡','恋','戀','楝','殓','殮','湅','潋','澰','瀲','炼','煉','瑓','練','纞','练','萰','錬','鍊','鏈','链','鰊','𬶠',],màn:['㵘','僈','墁','幔','慢','曼','漫','澷','熳','獌','縵','缦','蔄','蘰','鄤','鏝','镘','𬜬',],'tàn tǎn':['僋'],yíng:['僌','営','塋','嬴','攍','楹','櫿','溁','溋','滢','潆','濙','濚','濴','瀅','瀛','瀠','瀯','灐','灜','熒','營','瑩','盁','盈','禜','籝','籯','縈','茔','荧','莹','萤','营','萦','萾','蓥','藀','蛍','蝇','蝿','螢','蠅','謍','贏','赢','迎','鎣',],dòng:['働','冻','凍','动','動','姛','戙','挏','栋','棟','湩','硐','胨','胴','腖','迵','霘','駧',],zhuàn:['僎','啭','囀','堟','撰','灷','瑑','篆','腞','蒃','襈','譔','饌','馔',],xiàng:['像','勨','向','嚮','姠','嶑','曏','橡','珦','缿','蟓','衖','襐','象','鐌','項','项','鱌',],shàn:['僐','善','墠','墡','嬗','擅','敾','椫','樿','歚','汕','灗','疝','磰','繕','缮','膳','蟮','蟺','訕','謆','譱','讪','贍','赡','赸','鄯','鐥','饍','騸','骟','鱓','鱔','鳝','𫮃',],'tuí tuǐ':['僓'],zǔn:['僔','噂','撙','譐'],pú:['僕','匍','圤','墣','濮','獛','璞','瞨','穙','莆','菐','菩','葡','蒱','蒲','贌','酺','鏷','镤',],láo:['僗','劳','労','勞','哰','崂','嶗','憥','朥','浶','牢','痨','癆','窂','簩','醪','鐒','铹','顟','髝','𫭼',],chǎng:['僘','厰','廠','敞','昶','氅','鋹','𬬮'],guāng:['僙','光','咣','垙','姯','洸','灮','炗','炚','炛','烡','珖','胱','茪','輄','銧','黆','𨐈',],liáo:['僚','嘹','嫽','寥','寮','尞','屪','嵺','嶚','嶛','廫','憀','敹','暸','橑','獠','璙','疗','療','竂','簝','繚','缭','聊','膋','膫','藔','蟟','豂','賿','蹘','辽','遼','飉','髎','鷯','鹩',],dèng:['僜','凳','墱','嶝','櫈','瞪','磴','覴','邓','鄧','隥'],'chán zhàn zhuàn':['僝'],bō:['僠','嶓','拨','撥','播','波','溊','玻','癶','盋','砵','碆','礡','缽','菠','袰','蹳','鉢','钵','餑','饽','驋','鱍','𬭛',],huì:['僡','匯','卉','喙','嘒','嚖','圚','嬒','寭','屶','屷','彗','彙','彚','徻','恚','恵','惠','慧','憓','懳','晦','暳','槥','橞','檅','櫘','汇','泋','滙','潓','烩','燴','獩','璤','瞺','硊','秽','穢','篲','絵','繪','绘','翙','翽','荟','蔧','蕙','薈','薉','蟪','詯','誨','諱','譓','譿','讳','诲','賄','贿','鐬','闠','阓','靧','頮','顪','颒','餯','𬤝','𬭬',],chuǎn:['僢','喘','舛','荈','踳'],'tiě jiàn':['僣'],sēng:['僧','鬙'],xiàn:['僩','僴','哯','垷','塪','姭','娊','宪','岘','峴','憲','撊','晛','橌','橺','涀','瀗','献','獻','现','現','県','睍','粯','糮','絤','綫','線','线','缐','羡','羨','腺','臔','臽','苋','莧','誢','豏','鋧','錎','限','陥','陷','霰','餡','馅','麲','鼸','𬀪','𪾢',],'yù jú':['僪'],'è wū':['僫'],'tóng zhuàng':['僮'],lǐn:['僯','凛','凜','廩','廪','懍','懔','撛','檁','檩','澟','癛','癝',],gù:['僱','凅','固','堌','崓','崮','故','梏','棝','牿','痼','祻','錮','锢','雇','顧','顾','鯝','鲴',],jiāng:['僵','壃','姜','橿','殭','江','畕','疅','礓','繮','缰','翞','茳','葁','薑','螀','螿','豇','韁','鱂','鳉',],mǐn:['僶','冺','刡','勄','悯','惽','愍','慜','憫','抿','敃','敏','敯','泯','潣','皿','笢','笽','簢','蠠','閔','閩','闵','闽','鰵','鳘','黽',],jìn:['僸','凚','噤','嚍','墐','壗','妗','嬧','搢','晉','晋','枃','殣','浕','浸','溍','濅','濜','烬','煡','燼','琎','瑨','璶','盡','祲','縉','缙','荩','藎','覲','觐','賮','贐','赆','近','进','進','靳','齽',],'jià jie':['價'],qiào:['僺','峭','帩','撬','殻','窍','竅','誚','诮','躈','陗','鞩','韒','髚',],pì:['僻','媲','嫓','屁','澼','甓','疈','譬','闢','鷿','鸊','䴙'],sài:['僿','簺','賽','赛'],'chán tǎn shàn':['儃'],'dāng dàng':['儅','当','闣'],xuān:['儇','喧','塇','媗','宣','愃','愋','揎','昍','暄','煊','煖','瑄','睻','矎','禤','箮','翧','翾','萱','萲','蓒','蕿','藼','蘐','蝖','蠉','諠','諼','譞','谖','軒','轩','鍹','駽','鰚','𫓶','𫍽',],'dān dàn':['儋','擔','瘅'],càn:['儏','澯','灿','燦','璨','粲','薒','謲'],'bīn bìn':['儐'],'án àn':['儑'],tái:['儓','坮','嬯','抬','擡','檯','炱','炲','籉','臺','薹','跆','邰','颱','鮐','鲐',],lán:['儖','兰','囒','婪','岚','嵐','幱','拦','攔','斓','斕','栏','欄','欗','澜','瀾','灆','灡','燣','燷','璼','篮','籃','籣','繿','葻','蓝','藍','蘫','蘭','褴','襕','襤','襴','襽','譋','讕','谰','躝','鑭','镧','闌','阑','韊','𬒗',],'nǐ yì ài yí':['儗'],méng:['儚','幪','曚','朦','橗','檬','氋','溕','濛','甍','甿','盟','礞','艨','莔','萌','蕄','虻','蝱','鄳','鄸','霿','靀','顭','饛','鯍','鸏','鹲','𫑡','㠓',],níng:['儜','凝','咛','嚀','嬣','柠','橣','檸','狞','獰','聍','聹','薴','鑏','鬡','鸋',],qióng:['儝','卭','宆','惸','憌','桏','橩','焪','焭','煢','熍','琼','瓊','睘','穷','穹','窮','竆','笻','筇','舼','茕','藑','藭','蛩','蛬','赹','跫','邛','銎','䓖',],liè:['儠','冽','列','劣','劽','埒','埓','姴','峛','巤','挒','捩','栵','洌','浖','烈','烮','煭','犣','猎','猟','獵','聗','脟','茢','蛚','趔','躐','迾','颲','鬛','鬣','鮤','鱲','鴷','䴕','𫚭',],kuǎng:['儣','夼','懭'],bào:['儤','勽','報','忁','报','抱','曓','爆','犦','菢','虣','蚫','豹','鉋','鑤','铇','骲','髱','鮑','鲍',],biāo:['儦','墂','幖','彪','标','標','滮','瀌','熛','爂','猋','瘭','磦','膘','臕','謤','贆','鏢','鑣','镖','镳','颮','颷','飆','飇','飈','飊','飑','飙','飚','驫','骉','髟',],zǎn:['儧','儹','噆','攅','昝','趱','趲'],háo:['儫','嗥','嘷','噑','嚎','壕','椃','毜','毫','濠','獆','獔','竓','籇','蚝','蠔','譹','豪',],qìng:['儬','凊','庆','慶','櫦','濪','碃','磬','罄','靘'],chèn:['儭','嚫','榇','櫬','疢','衬','襯','讖','谶','趁','趂','齓','齔','龀',],téng:['儯','幐','滕','漛','疼','籐','籘','縢','腾','藤','虅','螣','誊','謄','邆','駦','騰','驣','鰧','䲢',],'lǒng lóng lòng':['儱'],'chán chàn':['儳'],'ráng xiāng':['儴','勷'],'huì xié':['儶'],luó:['儸','攞','椤','欏','猡','玀','箩','籮','罗','羅','脶','腡','萝','蘿','螺','覼','逻','邏','鏍','鑼','锣','镙','饠','騾','驘','骡','鸁',],léi:['儽','嫘','檑','欙','瓃','畾','縲','纍','纝','缧','罍','羸','蔂','蘲','虆','轠','鐳','鑘','镭','雷','靁','鱩','鼺',],'nàng nāng':['儾'],'wù wū':['兀'],yǔn:['允','喗','夽','抎','殒','殞','狁','磒','荺','賱','鈗','阭','陨','隕','霣','馻','齫','齳',],zān:['兂','橵','簪','簮','糌','鐕','鐟','鵤'],yuán:['元','円','原','厡','厵','园','圆','圎','園','圓','垣','塬','媴','嫄','援','榞','榬','橼','櫞','沅','湲','源','溒','爰','猨','猿','笎','緣','縁','缘','羱','茒','薗','蝝','蝯','螈','袁','褤','謜','轅','辕','邍','邧','酛','鈨','鎱','騵','魭','鶢','鶰','黿','鼋','𫘪',],xiōng:['兄','兇','凶','匂','匈','哅','忷','恟','汹','洶','胷','胸','芎','訩','詾','讻',],chōng:['充','嘃','忡','憃','憧','摏','沖','浺','珫','罿','翀','舂','艟','茺','衝','蹖','㳘',],zhào:['兆','垗','旐','曌','枛','櫂','照','燳','狣','瞾','笊','罀','罩','羄','肁','肇','肈','詔','诏','赵','趙','鮡','𬶐',],'duì ruì yuè':['兊','兌','兑'],kè:['克','刻','勀','勊','堁','娔','客','恪','愙','氪','溘','碦','緙','缂','艐','衉','課','课','錁','锞','騍','骒',],tù:['兎','兔','堍','迌','鵵'],dǎng:['党','攩','欓','譡','讜','谠','黨','𣗋'],dōu:['兜','兠','唗','橷','篼','蔸'],huǎng:['兤','奛','幌','怳','恍','晄','炾','熀','縨','詤','謊','谎',],rù:['入','嗕','媷','扖','杁','洳','溽','縟','缛','蓐','褥','鳰'],nèi:['內','氝','氞','錗'],'yú shù':['兪'],'liù lù':['六'],han:['兯','爳'],tiān:['兲','天','婖','添','酟','靔','靝','黇'],'xīng xìng':['兴'],diǎn:['典','嚸','奌','婰','敟','椣','点','碘','蒧','蕇','踮','點',],'zī cí':['兹'],jiān:['兼','冿','囏','坚','堅','奸','姦','姧','尖','幵','惤','戋','戔','搛','椾','樫','櫼','歼','殱','殲','湔','瀐','瀸','煎','熞','熸','牋','瑊','睷','礛','礷','笺','箋','緘','縑','缄','缣','肩','艰','艱','菅','菺','葌','蒹','蔪','蕑','蕳','虃','譼','豜','鑯','雃','鞯','韀','韉','餰','馢','鰔','鰜','鰹','鲣','鳒','鵑','鵳','鶼','鹣','麉',],shòu:['兽','受','售','壽','夀','寿','授','狩','獣','獸','痩','瘦','綬','绶','膄',],jì:['兾','冀','剂','剤','劑','勣','坖','垍','塈','妓','季','寂','寄','廭','彑','徛','忌','悸','惎','懻','技','旡','既','旣','暨','暩','曁','梞','檕','檵','洎','漃','漈','瀱','痵','癠','禝','稩','稷','穄','穊','穧','紀','継','績','繋','繼','继','绩','罽','臮','芰','茍','茤','葪','蓟','蔇','薊','蘎','蘮','蘻','裚','襀','覬','觊','計','記','誋','计','记','跡','跽','蹟','迹','际','際','霁','霽','驥','骥','髻','鬾','魝','魥','鯚','鯽','鰶','鰿','鱀','鱭','鲚','鲫','鵋','鷑','齌','𪟝','𬶨','𬶭',],jiōng:['冂','冋','坰','埛','扃','蘏','蘔','駉','駫','𬳶'],mào:['冃','冐','媢','帽','愗','懋','暓','柕','楙','毷','瑁','皃','眊','瞀','耄','茂','萺','蝐','袤','覒','貌','貿','贸','鄚','鄮',],rǎn:['冄','冉','姌','媣','染','珃','苒','蒅','䎃'],'nèi nà':['内'],gāng:['冈','冮','刚','剛','堈','堽','岡','掆','摃','棡','牨','犅','疘','綱','纲','缸','罁','罡','肛','釭','鎠','㭎',],cè:['冊','册','厕','厠','夨','廁','恻','惻','憡','敇','测','測','笧','策','筞','筴','箣','荝','萗','萴','蓛',],guǎ:['冎','剐','剮','叧','寡'],'mào mò':['冒'],gòu:['冓','啂','坸','垢','够','夠','媾','彀','搆','撀','构','構','煹','覯','觏','訽','詬','诟','購','购','遘','雊',],xǔ:['冔','喣','暊','栩','珝','盨','糈','詡','諿','诩','鄦','醑'],mì:['冖','冪','嘧','塓','宻','密','峚','幂','幎','幦','怽','榓','樒','櫁','汨','淧','滵','漞','濗','熐','羃','蔤','蜜','覓','覔','覛','觅','謐','谧','鼏',],'yóu yín':['冘'],xiě:['写','冩','藛'],jūn:['军','君','均','桾','汮','皲','皸','皹','碅','莙','蚐','袀','覠','軍','鈞','銁','銞','鍕','钧','頵','鮶','鲪','麏',],mí:['冞','擟','瀰','爢','猕','獼','祢','禰','縻','蒾','藌','蘪','蘼','袮','詸','謎','迷','醚','醾','醿','釄','镾','鸍','麊','麋','麛',],'guān guàn':['冠','覌','観','觀','观'],měng:['冡','勐','懵','掹','猛','獴','艋','蜢','蠓','錳','锰','鯭','鼆',],zhǒng:['冢','塚','尰','歱','煄','瘇','肿','腫','踵'],zuì:['冣','嶵','晬','最','栬','槜','檇','檌','祽','絊','罪','蕞','辠','酔','酻','醉','錊',],yuān:['冤','剈','囦','嬽','寃','棩','淵','渁','渆','渊','渕','灁','眢','肙','葾','蒬','蜎','蜵','駌','鳶','鴛','鵷','鸢','鸳','鹓','鼘','鼝',],míng:['冥','名','明','暝','朙','榠','洺','溟','猽','眀','眳','瞑','茗','螟','覭','詺','鄍','銘','铭','鳴','鸣',],kòu:['冦','叩','宼','寇','扣','敂','滱','窛','筘','簆','蔲','蔻','釦','鷇',],tài:['冭','太','夳','忲','态','態','汰','汱','泰','溙','肽','舦','酞','鈦','钛',],'féng píng':['冯','馮'],'chōng chòng':['冲'],kuàng:['况','圹','壙','岲','懬','旷','昿','曠','框','況','爌','眖','眶','矿','砿','礦','穬','絋','絖','纊','纩','貺','贶','軦','邝','鄺','鉱','鋛','鑛','黋',],lěng:['冷'],pàn:['冸','判','叛','沜','泮','溿','炍','牉','畔','盼','聁','袢','襻','詊','鋬','鑻','頖','鵥',],fā:['冹','彂','沷','発','發'],xiǎn:['冼','尟','尠','崄','嶮','幰','攇','显','櫶','毨','灦','烍','燹','狝','猃','獫','獮','玁','禒','筅','箲','藓','蘚','蚬','蜆','譣','赻','跣','鍌','险','険','險','韅','顕','顯','㬎',],qià:['冾','圶','帢','恰','殎','洽','硈','胢','髂'],'jìng chēng':['净','凈','淨'],sōu:['凁','嗖','廀','廋','捜','搜','摉','溲','獀','艘','蒐','螋','鄋','醙','鎪','锼','颼','飕','餿','馊','騪',],měi:['凂','媄','媺','嬍','嵄','挴','毎','每','浼','渼','燘','美','躾','鎂','镁','黣',],tú:['凃','図','图','圖','圗','塗','屠','峹','嵞','庩','廜','徒','悇','揬','涂','瘏','筡','腯','荼','蒤','跿','途','酴','鈯','鍎','馟','駼','鵌','鶟','鷋','鷵','𬳿',],zhǔn:['准','凖','埻','準','𬘯'],'liáng liàng':['凉','涼','量'],diāo:['凋','刁','刟','叼','奝','弴','彫','汈','琱','碉','簓','虭','蛁','貂','錭','雕','鮉','鯛','鲷','鵰','鼦',],còu:['凑','湊','腠','輳','辏'],ái:['凒','啀','嘊','捱','溰','癌','皑','皚'],duó:['凙','剫','夺','奪','痥','踱','鈬','鐸','铎'],dú:['凟','匵','嬻','椟','櫝','殰','涜','牍','牘','犊','犢','独','獨','瓄','皾','裻','読','讀','讟','豄','贕','錖','鑟','韇','韣','韥','騳','髑','黩','黷',],'jǐ jī':['几'],fán:['凡','凢','凣','匥','墦','杋','柉','棥','樊','瀿','烦','煩','燔','璠','矾','礬','笲','籵','緐','羳','舤','舧','薠','蘩','蠜','襎','蹯','釩','鐇','鐢','钒','鷭','𫔍','𬸪',],jū:['凥','匊','娵','婮','居','崌','抅','挶','掬','梮','椐','檋','毩','毱','泃','涺','狙','琚','疽','砠','罝','腒','艍','蜛','裾','諊','跔','踘','躹','陱','雎','鞠','鞫','駒','驹','鮈','鴡','鶋','𬶋',],'chù chǔ':['処','处'],zhǐ:['凪','劧','咫','址','坧','帋','恉','扺','指','旨','枳','止','汦','沚','洔','淽','疻','砋','祉','秖','紙','纸','芷','藢','衹','襧','訨','趾','軹','轵','酯','阯','黹',],píng:['凭','凴','呯','坪','塀','岼','帡','帲','幈','平','慿','憑','枰','洴','焩','玶','瓶','甁','竮','箳','簈','缾','荓','萍','蓱','蚲','蛢','評','评','軿','輧','郱','鮃','鲆',],kǎi:['凯','凱','剀','剴','垲','塏','恺','愷','慨','暟','蒈','輆','鍇','鎧','铠','锴','闓','闿','颽',],gān:['凲','坩','尲','尴','尶','尷','柑','泔','漧','玕','甘','疳','矸','竿','筸','粓','肝','苷','迀','酐','魐',],'kǎn qiǎn':['凵'],tū:['凸','堗','嶀','捸','涋','湥','痜','禿','秃','突','葖','鋵','鵚','鼵','㻬',],'āo wā':['凹'],chū:['出','初','岀','摴','榋','樗','貙','齣','䢺','䝙'],dàng:['凼','圵','垱','壋','档','檔','氹','璗','瓽','盪','瞊','砀','碭','礑','簜','荡','菪','蕩','蘯','趤','逿','雼','𬍡',],hán:['函','凾','含','圅','娢','寒','崡','晗','梒','浛','涵','澏','焓','琀','甝','筨','蜬','邗','邯','鋡','韓','韩',],záo:['凿','鑿'],dāo:['刀','刂','忉','氘','舠','螩','釖','魛','鱽'],chuāng:['刅','摐','牎','牕','疮','瘡','窓','窗','窻'],'fēn fèn':['分'],'qiè qiē':['切'],kān:['刊','勘','堪','戡','栞','龕','龛'],cǔn:['刌','忖'],chú:['刍','厨','幮','廚','橱','櫉','櫥','滁','犓','篨','耡','芻','蒢','蒭','蜍','蟵','豠','趎','蹰','躇','躕','鉏','鋤','锄','除','雏','雛','鶵',],'huà huá':['划'],lí:['刕','剓','剺','劙','厘','喱','嚟','囄','嫠','孷','廲','悡','梨','梸','棃','漓','灕','犁','犂','狸','琍','璃','瓈','盠','睝','离','穲','竰','筣','篱','籬','糎','縭','缡','罹','艃','荲','菞','蓠','蔾','藜','蘺','蜊','蟍','蟸','蠫','褵','謧','貍','醨','鋫','錅','鏫','鑗','離','驪','骊','鯏','鯬','鱺','鲡','鵹','鸝','鹂','黎','黧','㰀',],yuè:['刖','嬳','岄','岳','嶽','恱','悅','悦','戉','抈','捳','月','樾','瀹','爚','玥','礿','禴','篗','籆','籥','籰','粤','粵','蘥','蚎','蚏','説','越','跀','跃','躍','軏','鈅','鉞','鑰','钺','閱','閲','阅','鸑','鸙','黦','龠','𫐄','𬸚',],liú:['刘','劉','嚠','媹','嵧','旈','旒','榴','橊','流','浏','瀏','琉','瑠','瑬','璢','畄','留','畱','疁','瘤','癅','硫','蒥','蓅','蟉','裗','鎏','鏐','鐂','镠','飀','飅','飗','駠','駵','騮','驑','骝','鰡','鶹','鹠','麍',],zé:['则','則','啧','嘖','嫧','帻','幘','択','樍','歵','沢','泎','溭','皟','瞔','矠','礋','箦','簀','舴','蔶','蠌','襗','謮','賾','赜','迮','鸅','齚','齰',],'chuàng chuāng':['创','創'],qù:['刞','厺','去','閴','闃','阒','麮','鼁'],'bié biè':['別','别'],'páo bào':['刨'],'chǎn chàn':['刬','剗','幝'],guā:['刮','劀','桰','歄','煱','瓜','胍','踻','颪','颳','騧','鴰','鸹',],gēng:['刯','庚','椩','浭','焿','畊','絚','羮','羹','耕','菮','賡','赓','鶊','鹒',],dào:['到','噵','悼','椡','檤','燾','瓙','盗','盜','稲','稻','纛','翿','艔','菿','衜','衟','軇','道',],chuàng:['刱','剏','剙','怆','愴'],kū:['刳','哭','圐','堀','枯','桍','矻','窟','跍','郀','骷','鮬'],duò:['刴','剁','墯','尮','惰','憜','挅','桗','舵','跥','跺','陊','陏','飿','饳','鵽',],'shuā shuà':['刷'],'quàn xuàn':['券'],'chà shā':['刹','剎'],'cì cī':['刺'],guì:['刽','刿','劊','劌','撌','攰','昋','桂','椢','槶','樻','櫃','猤','禬','筀','蓕','襘','貴','贵','跪','鐀','鑎','鞼','鱖','鱥',],lóu:['剅','娄','婁','廔','楼','樓','溇','漊','熡','耧','耬','艛','蒌','蔞','蝼','螻','謱','軁','遱','鞻','髅','髏','𪣻',],cuò:['剉','剒','厝','夎','挫','措','棤','莝','莡','蓌','逪','銼','錯','锉','错',],'xiāo xuē':['削'],'kēi kè':['剋','尅'],'là lá':['剌'],tī:['剔','梯','踢','銻','锑','鷈','鷉','䏲','䴘'],pōu:['剖'],wān:['剜','塆','壪','帵','弯','彎','湾','潫','灣','睕','蜿','豌'],'bāo bō':['剝','剥'],duō:['剟','咄','哆','嚉','多','夛','掇','毲','畓','裰','㙍'],qíng:['剠','勍','夝','情','擎','晴','暒','棾','樈','檠','氰','甠','硘','葝','黥',],'yǎn shàn':['剡'],'dū zhuó':['剢'],yān:['剦','嫣','崦','嶖','恹','懕','懨','樮','淊','淹','漹','烟','焉','焑','煙','珚','篶','胭','臙','菸','鄢','醃','閹','阉','黫',],huō:['剨','劐','吙','攉','秴','耠','锪','騞','𬴃'],shèng:['剩','剰','勝','圣','墭','嵊','晠','榺','橳','琞','聖','蕂','貹','賸',],'duān zhì':['剬'],wū:['剭','呜','嗚','圬','屋','巫','弙','杇','歍','汙','汚','污','洿','烏','窏','箼','螐','誈','誣','诬','邬','鄔','鎢','钨','鰞','鴮',],gē:['割','哥','圪','彁','戈','戓','戨','歌','滒','犵','肐','袼','謌','鎶','鴚','鴿','鸽',],'dá zhá':['剳'],chuán:['剶','暷','椽','篅','舡','舩','船','輲','遄'],'tuán zhuān':['剸','漙','篿'],'lù jiū':['剹'],pēng:['剻','匉','嘭','怦','恲','抨','梈','烹','砰','軯','駍'],piāo:['剽','勡','慓','旚','犥','翲','螵','飃','飄','飘','魒'],kōu:['剾','彄','抠','摳','眍','瞘','芤','𫸩'],'jiǎo chāo':['剿','劋','勦','摷'],qiāo:['劁','勪','墝','幧','敲','橇','毃','燆','硗','磽','繑','趬','跷','踍','蹺','蹻','郻','鄡','鄥','鍫','鍬','鐰','锹','頝',],'huá huà':['劃'],'zhā zhá':['劄'],'pī pǐ':['劈','悂'],tāng:['劏','嘡','羰','薚','蝪','蹚','鞺','鼞'],chán:['劖','嚵','壥','婵','嬋','巉','廛','棎','毚','湹','潹','潺','澶','瀍','瀺','煘','獑','磛','緾','纏','纒','缠','艬','蝉','蟐','蟬','蟾','誗','讒','谗','躔','鄽','酁','鋋','鑱','镵','饞','馋',],zuān:['劗','躜','躦','鉆','鑚'],mó:['劘','嫫','嬤','嬷','尛','摹','擵','橅','糢','膜','藦','蘑','謨','謩','谟','饃','饝','馍','髍','魔','魹',],zhú:['劚','斸','曯','欘','灟','炢','烛','燭','爥','瘃','竹','笁','笜','舳','茿','蓫','蠋','蠾','躅','逐','逫','钃','鱁',],quàn:['劝','勧','勸','牶','韏'],'jìn jìng':['劤','劲','勁'],kēng:['劥','坑','牼','硁','硜','誙','銵','鍞','鏗','铿','阬'],'xié liè':['劦'],'zhù chú':['助'],nǔ:['努','弩','砮','胬'],shào:['劭','卲','哨','潲','紹','綤','绍','袑','邵'],miǎo:['劰','杪','淼','渺','眇','秒','篎','緲','缈','藐','邈'],kǒu:['劶','口'],wā:['劸','娲','媧','屲','挖','攨','洼','溛','漥','瓾','畖','穵','窊','窪','蛙','韈','鼃',],kuāng:['劻','匡','匩','哐','恇','洭','筐','筺','誆','诓','軭','邼',],hé:['劾','咊','啝','姀','峆','敆','曷','柇','楁','毼','河','涸','渮','澕','熆','皬','盇','盉','盍','盒','禾','篕','籺','粭','翮','菏','萂','覈','訸','詥','郃','釛','鉌','鑉','閡','闔','阂','阖','鞨','頜','餄','饸','魺','鹖','麧','齕','龁','龢','𬌗',],gào:['勂','吿','告','峼','祮','祰','禞','筶','誥','诰','郜','鋯','锆',],'bó bèi':['勃'],láng:['勆','嫏','廊','斏','桹','榔','樃','欴','狼','琅','瑯','硠','稂','艆','蓈','蜋','螂','躴','郒','郞','鋃','鎯','锒',],xūn:['勋','勛','勲','勳','嚑','坃','埙','塤','壎','壦','曛','燻','獯','矄','纁','臐','薫','薰','蘍','醺','𫄸',],'juàn juān':['勌','瓹'],'lè lēi':['勒'],kài:['勓','炌','烗','鎎'],'wěng yǎng':['勜'],qín:['勤','嗪','噙','嶜','庈','懃','懄','捦','擒','斳','檎','澿','珡','琴','琹','瘽','禽','秦','耹','芩','芹','菦','螓','蠄','鈙','鈫','雂','靲','鳹','鵭',],jiàng:['勥','匞','匠','嵹','弜','弶','摾','櫤','洚','滰','犟','糡','糨','絳','绛','謽','酱','醤','醬',],fān:['勫','嬏','帆','幡','忛','憣','旙','旛','繙','翻','藩','轓','颿','飜','鱕',],juān:['勬','姢','娟','捐','涓','蠲','裐','鎸','鐫','镌','鹃'],'tóng dòng':['勭','烔','燑','狪'],lǜ:['勴','垏','嵂','律','慮','氯','滤','濾','爈','箻','綠','繂','膟','葎','虑','鑢',],chè:['勶','坼','彻','徹','掣','撤','澈','烢','爡','瞮','硩','聅','迠','頙','㬚',],sháo:['勺','玿','韶'],'gōu gòu':['勾'],cōng:['匆','囪','囱','忩','怱','悤','暰','樬','漗','瑽','璁','瞛','篵','繱','聡','聦','聪','聰','苁','茐','葱','蓯','蔥','蟌','鍯','鏓','鏦','騘','驄','骢',],'táo yáo':['匋','陶'],páo:['匏','咆','垉','庖','爮','狍','袍','褜','軳','鞄','麅'],dá:['匒','妲','怛','炟','燵','畣','笪','羍','荙','薘','蟽','詚','达','迏','迖','迚','逹','達','鐽','靼','鞑','韃','龖','龘','𫟼',],'huà huā':['化'],'běi bèi':['北'],nǎo:['匘','垴','堖','嫐','恼','悩','惱','瑙','碯','脑','脳','腦'],'chí shi':['匙'],fāng:['匚','堏','方','淓','牥','芳','邡','鈁','錺','钫','鴋'],zā:['匝','咂','帀','沞','臜','臢','迊','鉔','魳'],qiè:['匧','厒','妾','怯','悏','惬','愜','挈','穕','窃','竊','笡','箧','篋','籡','踥','鍥','锲','鯜',],'zāng cáng':['匨'],fěi:['匪','奜','悱','棐','榧','篚','翡','蕜','誹','诽'],'kuì guì':['匮','匱'],suǎn:['匴'],pǐ:['匹','噽','嚭','圮','庀','痞','癖','脴','苉','銢','鴄'],'qū ōu':['区','區'],'kē qià':['匼'],'yǎn yàn':['匽','棪'],biǎn:['匾','惼','揙','碥','稨','窆','藊','褊','貶','贬','鴘'],nì:['匿','堄','嫟','嬺','惄','愵','昵','暱','氼','眤','睨','縌','胒','腻','膩','逆','𨺙',],niàn:['卄','唸','埝','廿','念','惗','艌'],sà:['卅','櫒','脎','萨','蕯','薩','鈒','隡','颯','飒','馺'],zú:['卆','哫','崪','族','箤','足','踤','镞'],shēng:['升','呏','声','斘','昇','曻','枡','殅','泩','湦','焺','牲','珄','生','甥','竔','笙','聲','鉎','鍟','阩','陞','陹','鵿','鼪',],wàn:['卍','卐','忨','杤','瞣','脕','腕','萬','蟃','贎','輐','錽','𬇕',],'huá huà huā':['华','華'],bēi:['卑','悲','揹','杯','桮','盃','碑','藣','鵯','鹎'],'zú cù':['卒'],'dān shàn chán':['单','單'],'nán nā':['南'],'shuài lǜ':['卛'],'bǔ bo pú':['卜'],'kuàng guàn':['卝'],biàn:['卞','变','変','峅','弁','徧','忭','抃','昪','汳','汴','玣','艑','苄','覍','諚','變','辡','辧','辨','辩','辫','辮','辯','遍','釆','𨚕',],bǔ:['卟','哺','捕','补','補','鸔','𬷕'],'zhàn zhān':['占','覱'],'kǎ qiǎ':['卡'],lú:['卢','嚧','垆','壚','庐','廬','曥','枦','栌','櫨','泸','瀘','炉','爐','獹','玈','瓐','盧','矑','籚','纑','罏','胪','臚','舮','舻','艫','芦','蘆','蠦','轤','轳','鈩','鑪','顱','颅','馿','髗','魲','鱸','鲈','鸕','鸬','黸','𬬻',],lǔ:['卤','塷','掳','擄','樐','橹','櫓','氌','滷','澛','瀂','硵','磠','穞','艣','艪','蓾','虏','虜','鏀','鐪','鑥','镥','魯','鲁','鹵',],guà:['卦','啩','挂','掛','罣','褂','詿','诖'],'áng yǎng':['卬'],yìn:['印','垽','堷','廕','慭','憖','憗','懚','洕','湚','猌','癊','胤','茚','酳','鮣','䲟',],què:['却','卻','塙','崅','悫','愨','慤','搉','榷','燩','琷','皵','确','確','礭','闋','阕','鵲','鹊','𬒈',],luǎn:['卵'],'juàn juǎn':['卷','巻'],'chǎng ān hàn':['厂'],'wěi yán':['厃'],tīng:['厅','厛','听','庁','廰','廳','汀','烃','烴','綎','耓','聴','聼','聽','鞓','𬘩',],'zhé zhái':['厇'],'hàn àn':['厈','屽'],yǎ:['厊','唖','庌','痖','瘂','蕥'],shè:['厍','厙','弽','慑','慴','懾','摂','欇','涉','涻','渉','滠','灄','社','舎','蔎','蠂','設','设','赦','騇','麝',],dǐ:['厎','呧','坘','弤','抵','拞','掋','牴','砥','菧','觝','詆','诋','軧','邸','阺','骶','鯳',],'zhǎ zhǎi':['厏'],páng:['厐','嫎','庞','徬','舽','螃','逄','鰟','鳑','龎','龐'],'zhì shī':['厔'],máng:['厖','吂','哤','娏','忙','恾','杗','杧','汒','浝','牻','痝','盲','硭','笀','芒','茫','蘉','邙','釯','鋩','铓','駹',],zuī:['厜','樶','纗','蟕'],'shà xià':['厦','廈'],áo:['厫','嗷','嗸','廒','敖','滶','獒','獓','璈','翱','翶','翺','聱','蔜','螯','謷','謸','遨','鏖','隞','鰲','鳌','鷔','鼇',],'lán qiān':['厱'],'sī mǒu':['厶'],'gōng hóng':['厷'],'lín miǎo':['厸'],'qiú róu':['厹'],dū:['厾','嘟','督','醏'],'xiàn xuán':['县','縣'],'cān shēn cēn sān':['参','參','叄','叅'],'ài yǐ':['叆'],'chā chà chǎ chá':['叉'],shuāng:['双','孀','孇','欆','礵','艭','雙','霜','騻','驦','骦','鷞','鸘','鹴',],shōu:['収','收'],guái:['叏'],bá:['叐','妭','抜','拔','炦','癹','胈','茇','菝','詙','跋','軷','魃','鼥',],'fā fà':['发'],'zhuó yǐ lì jué':['叕'],qǔ:['取','娶','竬','蝺','詓','齲','龋'],'jiǎ xiá':['叚','徦'],'wèi yù':['叞','尉','蔚'],dié:['叠','垤','堞','峌','幉','恎','惵','戜','曡','殜','氎','牃','牒','瓞','畳','疂','疉','疊','碟','絰','绖','耊','耋','胅','艓','苵','蜨','蝶','褋','詄','諜','谍','跮','蹀','迭','镻','鰈','鲽','鴩','𫶇',],ruì:['叡','枘','汭','瑞','睿','芮','蚋','蜹','銳','鋭','锐'],'jù gōu':['句'],lìng:['另','呤','炩','蘦'],'dāo dáo tāo':['叨'],'zhī zhǐ':['只'],jiào:['叫','呌','嘂','嘦','噍','嬓','斍','斠','滘','漖','獥','珓','皭','窖','藠','訆','譥','趭','較','轎','轿','较','酵','醮','釂',],'zhào shào':['召'],'kě kè':['可'],'tái tāi':['台','苔'],pǒ:['叵','尀','笸','箥','鉕','钷','駊'],'yè xié':['叶'],'hào háo':['号'],tàn:['叹','嘆','探','歎','湠','炭','碳','舕'],'hōng hóng':['叿'],miē:['吀','咩','哶','孭'],'xū yū yù':['吁'],chī:['吃','哧','喫','嗤','噄','妛','媸','彨','彲','摛','攡','殦','瓻','痴','癡','眵','瞝','笞','粚','胵','蚩','螭','訵','魑','鴟','鵄','鸱','黐','齝','𫄨',],'xuān sòng':['吅'],yāo:['吆','喓','夭','妖','幺','楆','殀','祅','腰','葽','訞','邀','鴁','鴢','㙘',],zǐ:['吇','姉','姊','子','杍','梓','榟','橴','滓','矷','秭','笫','籽','紫','耔','虸','訿','釨',],'hé gě':['合','鲄'],'cùn dòu':['吋'],'tóng tòng':['同'],'tǔ tù':['吐','唋'],'zhà zhā':['吒','奓'],'xià hè':['吓'],'ā yā':['吖'],'ma má mǎ':['吗'],lìn:['吝','恡','悋','橉','焛','甐','膦','蔺','藺','賃','赁','蹸','躏','躙','躪','轥','閵',],tūn:['吞','暾','朜','焞'],'bǐ pǐ':['吡'],qìn:['吢','吣','唚','抋','揿','搇','撳','沁','瀙','菣','藽'],'jiè gè':['吤'],'fǒu pǐ':['否'],'ba bā':['吧'],dūn:['吨','噸','墩','墪','惇','撉','撴','犜','獤','礅','蜳','蹾','驐',],fēn:['吩','帉','昐','朆','梤','棻','氛','竕','紛','纷','翂','芬','衯','訜','躮','酚','鈖','雰','餴','饙','馚',],'é huā':['吪'],'kēng háng':['吭','妔'],shǔn:['吮'],'zhī zī':['吱'],'yǐn shěn':['吲'],wú:['吳','吴','呉','墲','峿','梧','橆','毋','洖','浯','無','珸','璑','祦','芜','茣','莁','蕪','蜈','蟱','譕','郚','鋙','铻','鯃','鵐','鷡','鹀','鼯',],'chǎo chāo':['吵'],'nà nè':['吶'],'xuè chuò jué':['吷'],chuī:['吹','炊','龡'],'dōu rú':['吺'],hǒu:['吼','犼'],'hōng hǒu ōu':['吽'],'wú yù':['吾'],'ya yā':['呀'],'è e':['呃'],dāi:['呆','懛','獃'],'mèn qǐ':['呇'],hōng:['呍','嚝','揈','灴','烘','焢','硡','薨','訇','谾','軣','輷','轟','轰','鍧',],nà:['呐','捺','笝','納','纳','肭','蒳','衲','豽','貀','軜','郍','鈉','钠','靹','魶',],'tūn tiān':['呑'],'fǔ ḿ':['呒','嘸'],'dāi tǎi':['呔'],'ǒu ōu òu':['呕'],'bài bei':['呗'],'yuán yún yùn':['员','員'],guō:['呙','啯','嘓','埚','堝','墎','崞','彉','彍','懖','猓','瘑','聒','蝈','蟈','郭','鈛','鍋','锅',],'huá qì':['呚'],'qiàng qiāng':['呛','跄'],shī:['呞','失','尸','屍','师','師','施','浉','湤','湿','溮','溼','濕','狮','獅','瑡','絁','葹','蒒','蓍','虱','蝨','褷','襹','詩','诗','邿','釃','鉇','鍦','鯴','鰤','鲺','鳲','鳾','鶳','鸤','䴓','𫚕',],juǎn:['呟','埍','臇','菤','錈','锩'],pěn:['呠','翸'],'wěn mǐn':['呡'],'ne ní':['呢'],'ḿ m̀ móu':['呣'],rán:['呥','嘫','然','燃','繎','肰','蚦','蚺','衻','袇','袡','髥','髯',],'tiè chè':['呫'],'qì zhī':['呮'],'zǐ cī':['呰'],'guā gū guǎ':['呱'],'cī zī':['呲'],'hǒu xǔ gòu':['呴'],'hē ā á ǎ à a':['呵'],náo:['呶','夒','峱','嶩','巎','挠','撓','猱','硇','蛲','蟯','詉','譊','鐃','铙',],'xiā gā':['呷'],pēi:['呸','怌','肧','胚','衃','醅'],'háo xiāo':['呺'],mìng:['命','掵'],'dá dàn':['呾'],'zuǐ jǔ':['咀'],'xián gān':['咁'],pǒu:['咅','哣','犃'],'yǎng yāng':['咉'],'zǎ zé zhā':['咋'],'hé hè huó huò hú':['和'],hāi:['咍'],dā:['咑','哒','噠','墶','搭','撘','耷','褡','鎝','𨱏'],'kǎ kā':['咔'],gū:['咕','唂','唃','姑','嫴','孤','巬','巭','柧','橭','沽','泒','稒','笟','箍','箛','篐','罛','苽','菇','菰','蓇','觚','軱','軲','轱','辜','酤','鈲','鮕','鴣','鸪',],'kā gā':['咖'],zuo:['咗'],lóng:['咙','嚨','嶐','巃','巄','昽','曨','朧','栊','槞','櫳','湰','滝','漋','爖','珑','瓏','癃','眬','矓','砻','礱','礲','窿','竜','聋','聾','胧','茏','蘢','蠪','蠬','襱','豅','鏧','鑨','霳','靇','驡','鸗','龍','龒','龙',],'xiàn xián':['咞'],qì:['咠','唭','噐','器','夡','弃','憇','憩','暣','棄','欫','气','気','氣','汔','汽','泣','湆','湇','炁','甈','盵','矵','碛','碶','磜','磧','罊','芞','葺','藒','蟿','訖','讫','迄','鐑',],'xì dié':['咥'],'liē liě lié lie':['咧'],zī:['咨','嗞','姕','姿','孜','孳','孶','崰','嵫','栥','椔','淄','湽','滋','澬','玆','禌','秶','粢','紎','緇','緕','纃','缁','茊','茲','葘','諮','谘','貲','資','赀','资','赼','趑','趦','輜','輺','辎','鄑','鈭','錙','鍿','鎡','锱','镃','頾','頿','髭','鯔','鰦','鲻','鶅','鼒','齍','齜','龇',],mī:['咪'],'jī xī qià':['咭'],'gē luò kǎ lo':['咯'],'shù xún':['咰'],'zán zá zǎ zan':['咱'],'hāi ké':['咳'],huī:['咴','噅','噕','婎','媈','幑','徽','恢','拻','挥','揮','晖','暉','楎','洃','瀈','灰','灳','烣','睳','禈','翚','翬','蘳','袆','褘','詼','诙','豗','輝','辉','鰴','麾','㧑',],'huài shì':['咶'],táo:['咷','啕','桃','檮','洮','淘','祹','綯','绹','萄','蜪','裪','迯','逃','醄','鋾','鞀','鞉','饀','駣','騊','鼗','𫘦',],xián:['咸','啣','娴','娹','婱','嫌','嫺','嫻','弦','挦','撏','涎','湺','澖','甉','痫','癇','癎','絃','胘','舷','藖','蚿','蛝','衔','衘','誸','諴','賢','贒','贤','輱','醎','銜','鑦','閑','闲','鷳','鷴','鷼','鹇','鹹','麙','𫍯',],'è àn':['咹'],'xuān xuǎn':['咺','烜'],'wāi hé wǒ guǎ guō':['咼'],'yàn yè yān':['咽'],āi:['哀','哎','埃','溾','銰','鎄','锿'],pǐn:['品','榀'],shěn:['哂','婶','嬸','审','宷','審','弞','曋','渖','瀋','瞫','矤','矧','覾','訠','諗','讅','谂','谉','邥','頣','魫',],'hǒng hōng hòng':['哄'],'wā wa':['哇'],'hā hǎ hà':['哈'],zāi:['哉','栽','渽','溨','災','灾','烖','睵','賳'],'dì diè':['哋'],pài:['哌','沠','派','渒','湃','蒎','鎃'],'gén hěn':['哏'],'yǎ yā':['哑','雅'],'yuě huì':['哕','噦'],nián:['哖','年','秊','秥','鮎','鯰','鲇','鲶','鵇','黏'],'huá huā':['哗','嘩'],'jì jiē zhāi':['哜','嚌'],mōu:['哞'],'yō yo':['哟','喲'],lòng:['哢','梇','贚'],'ò ó é':['哦'],'lī lǐ li':['哩'],'nǎ na nǎi né něi':['哪'],hè:['哬','垎','壑','寉','惒','焃','煂','燺','爀','癋','碋','翯','褐','謞','賀','贺','赫','靍','靎','靏','鶴','鸖','鹤',],'bō pò bā':['哱'],zhé:['哲','啠','喆','嚞','埑','悊','摺','晢','晣','歽','矺','砓','磔','籷','粍','虴','蛰','蟄','袩','詟','謫','謺','讁','讋','谪','輒','輙','轍','辄','辙','鮿',],'liàng láng':['哴'],'liè lǜ':['哷'],hān:['哻','憨','蚶','谽','酣','頇','顸','馠','魽','鼾'],'hēng hng':['哼'],gěng:['哽','埂','峺','挭','梗','綆','绠','耿','莄','郠','骾','鯁','鲠','𬒔',],'chuò yuè':['哾'],'gě jiā':['哿'],'bei bài':['唄'],'hán hàn':['唅'],chún:['唇','浱','湻','滣','漘','犉','純','纯','脣','莼','蒓','蓴','醇','醕','錞','陙','鯙','鶉','鹑','𬭚',],'ài āi':['唉'],'jiá qiǎn':['唊'],'yán dàn xián':['唌'],chē:['唓','砗','硨','莗','蛼'],'wú ńg ń':['唔'],zào:['唕','唣','噪','慥','梍','灶','煰','燥','皁','皂','竃','竈','簉','艁','譟','趮','躁','造','𥖨',],dí:['唙','啇','嘀','嚁','嫡','廸','敌','敵','梑','涤','滌','狄','笛','籴','糴','苖','荻','蔋','蔐','藡','覿','觌','豴','迪','靮','頔','馰','髢','鸐','𬱖',],'gòng hǒng gǒng':['唝','嗊'],dóu:['唞'],'lào láo':['唠','嘮','憦'],huàn:['唤','喚','奂','奐','宦','嵈','幻','患','愌','换','換','擐','攌','梙','槵','浣','涣','渙','漶','澣','烉','焕','煥','瑍','痪','瘓','睆','肒','藧','豢','轘','逭','鯇','鯶','鰀','鲩',],léng:['唥','塄','楞','碐','薐'],'wō wěi':['唩'],fěng:['唪','覂','諷','讽'],'yín jìn':['唫'],'hǔ xià':['唬'],wéi:['唯','围','圍','壝','峗','峞','嵬','帏','帷','幃','惟','桅','沩','洈','涠','湋','溈','潍','潙','潿','濰','犩','矀','維','维','蓶','覹','违','違','鄬','醀','鍏','闈','闱','韋','韦','鮠','𣲗','𬶏',],shuā:['唰'],chàng:['唱','怅','悵','暢','焻','畅','畼','誯','韔','鬯'],'ér wā':['唲'],qiàng:['唴','炝','熗','羻'],yō:['唷'],yū:['唹','淤','瘀','盓','箊','紆','纡','込','迂','迃','陓'],lài:['唻','濑','瀨','瀬','癞','癩','睐','睞','籁','籟','藾','賚','賴','赉','赖','頼','顂','鵣',],tuò:['唾','嶞','柝','毤','毻','箨','籜','萚','蘀','跅'],'zhōu zhāo tiào':['啁'],kěn:['啃','垦','墾','恳','懇','肎','肯','肻','豤','錹'],'zhuó zhào':['啅','濯'],'hēng hèng':['啈','悙'],'lín lán':['啉'],'a ā á ǎ à':['啊'],qiāng:['啌','嗴','嶈','戕','摤','斨','枪','槍','溬','牄','猐','獇','羌','羗','腔','蜣','謒','鏘','锖','锵',],'tūn zhūn xiāng duǐ':['啍'],wèn:['問','妏','揾','搵','璺','问','顐'],'cuì qi':['啐'],'dié shà jié tì':['啑'],'yuē wā':['啘'],'zǐ cǐ':['啙'],'bǐ tú':['啚'],'chuò chuài':['啜'],'yǎ yā è':['啞'],fēi:['啡','婓','婔','扉','暃','渄','猆','緋','绯','裶','霏','非','靟','飛','飝','飞','餥','馡','騑','騛','鯡','鲱','𬴂',],pí:['啤','壀','枇','毗','毘','焷','琵','疲','皮','篺','罴','羆','脾','腗','膍','蚍','蚽','蜱','螷','蠯','豼','貔','郫','鈹','阰','陴','隦','魮','鮍','鲏','鵧','鼙',],shá:['啥'],'lā la':['啦'],'yīng qíng':['啨'],pā:['啪','妑','舥','葩','趴'],'zhě shì':['啫'],sè:['啬','嗇','懎','擌','栜','歮','涩','渋','澀','澁','濇','濏','瀒','瑟','璱','瘷','穑','穡','穯','繬','譅','轖','銫','鏼','铯','飋',],niè:['啮','嗫','噛','嚙','囁','囓','圼','孼','孽','嵲','嶭','巕','帇','敜','枿','槷','櫱','涅','湼','痆','篞','籋','糱','糵','聂','聶','臬','臲','蘖','蠥','讘','踂','踗','踙','蹑','躡','錜','鎳','鑈','鑷','钀','镊','镍','闑','陧','隉','顳','颞','齧','𫔶',],'luō luó luo':['啰','囉'],'tān chǎn tuō':['啴'],bo:['啵','蔔'],dìng:['啶','定','椗','矴','碇','碠','磸','聢','腚','萣','蝊','訂','订','錠','锭','顁','飣','饤',],lāng:['啷'],'án ān':['啽'],kā:['喀','擖'],'yóng yú':['喁'],'lā lá lǎ':['喇'],jiē:['喈','喼','嗟','堦','媘','接','掲','擑','湝','煯','疖','痎','癤','皆','秸','稭','脻','蝔','街','謯','阶','階','鞂','鶛',],hóu:['喉','帿','猴','瘊','睺','篌','糇','翭','葔','鄇','鍭','餱','骺','鯸','𬭤',],'dié zhá':['喋'],wāi:['喎','歪','竵'],'nuò rě':['喏'],'xù huò guó':['喐'],zán:['喒'],'wō ō':['喔'],hú:['喖','嘝','囫','壶','壷','壺','媩','弧','搰','斛','楜','槲','湖','瀫','焀','煳','狐','猢','瑚','瓳','箶','絗','縠','胡','葫','蔛','蝴','螜','衚','觳','醐','鍸','頶','餬','鬍','魱','鰗','鵠','鶘','鶦','鹕',],'huàn yuán xuǎn hé':['喛'],xǐ:['喜','囍','壐','屣','徙','憙','枲','橲','歖','漇','玺','璽','矖','禧','縰','葈','葸','蓰','蟢','謑','蹝','躧','鈢','鉨','鉩','鱚','𬭳','𬶮',],'hē hè yè':['喝'],kuì:['喟','嘳','媿','嬇','愦','愧','憒','篑','簣','籄','聩','聭','聵','膭','蕢','謉','餽','饋','馈',],'zhǒng chuáng':['喠'],'wéi wèi':['喡','為','爲'],'duó zhà':['喥'],'sāng sàng':['喪'],'qiáo jiāo':['喬'],'pèn bēn':['喯'],'cān sūn qī':['喰'],'zhā chā':['喳'],miāo:['喵'],'pēn pèn':['喷'],kuí:['喹','夔','奎','巙','戣','揆','晆','暌','楏','楑','櫆','犪','睽','葵','藈','蘷','虁','蝰','躨','逵','鄈','鍨','鍷','頯','馗','騤','骙','魁',],'lou lóu':['喽'],'zào qiāo':['喿'],'hè xiāo xiào hù':['嗃'],'á shà':['嗄'],xiù:['嗅','岫','峀','溴','珛','琇','璓','秀','綉','繍','繡','绣','螑','袖','褎','褏','銹','鏥','鏽','锈','齅',],'qiāng qiàng':['嗆','戗','戧','蹌','蹡'],'ài yì':['嗌','艾'],'má mǎ ma':['嗎'],'kè kē':['嗑'],'dā tà':['嗒','鎉'],sǎng:['嗓','搡','磉','褬','鎟','顙','颡'],chēn:['嗔','抻','琛','瞋','諃','謓','賝','郴','𬘭'],'wā gǔ':['嗗'],'pǎng bēng':['嗙'],'xián qiǎn qiān':['嗛'],lào:['嗠','嫪','橯','涝','澇','耢','耮','躼','軂','酪'],wēng:['嗡','翁','聬','螉','鎓','鶲','鹟','𬭩'],wà:['嗢','腽','膃','袜','襪','韤'],'hēi hāi':['嗨'],hē:['嗬','欱','蠚','訶','诃'],zi:['嗭'],sǎi:['嗮'],'ǹg ńg ňg':['嗯'],gě:['嗰','舸'],ná:['嗱','拏','拿','鎿','镎'],diǎ:['嗲'],'ài ǎi āi':['嗳'],tōng:['嗵','樋','炵','蓪'],'zuī suī':['嗺'],'zhē zhè zhù zhe':['嗻'],mò:['嗼','圽','塻','墨','妺','嫼','寞','帞','昩','末','枺','歿','殁','沫','漠','爅','獏','瘼','皌','眽','眿','瞐','瞙','砞','礳','秣','絈','纆','耱','茉','莈','蓦','蛨','蟔','貃','貊','貘','銆','鏌','镆','陌','靺','驀','魩','默','黙','𬙊',],sòu:['嗽','瘶'],tǎn:['嗿','坦','忐','憳','憻','暺','毯','璮','菼','袒','襢','醓','鉭','钽',],'jiào dǎo':['嘄'],'kǎi gě':['嘅'],'shān càn':['嘇'],cáo:['嘈','嶆','曹','曺','槽','漕','艚','蓸','螬','褿','鏪','𥕢'],piào:['嘌','徱','蔈','驃'],'lóu lou':['嘍'],gǎ:['尕','玍'],'gǔ jiǎ':['嘏'],'jiāo xiāo':['嘐'],'xū shī':['嘘','噓'],pó:['嘙','嚩','婆','櫇','皤','鄱'],'dē dēi':['嘚'],'ma má':['嘛'],'lē lei':['嘞'],'gā gá gǎ':['嘠'],sāi:['嘥','噻','毢','腮','顋','鰓'],'zuō chuài':['嘬'],'cháo zhāo':['嘲','朝','鼂'],zuǐ:['嘴','噿','嶊','璻'],'qiáo qiào':['嘺','翹','谯'],'chù xù shòu':['嘼'],'tān chǎn':['嘽'],'dàn tán':['嘾','弾','彈','惔','澹'],'hēi mò':['嘿'],ě:['噁','砨','頋','騀','鵈'],'fān bo':['噃'],chuáng:['噇','床','牀'],'cù zā hé':['噈'],'tūn kuò':['噋'],'cēng chēng':['噌'],dēng:['噔','嬁','灯','燈','璒','登','竳','簦','艠','豋'],pū:['噗','扑','撲','攴','攵','潽','炇','陠'],juē:['噘','屩','屫','撧'],lū:['噜','嚕','撸','擼','謢'],zhān:['噡','岾','惉','旃','旜','枬','栴','毡','氈','氊','沾','瞻','薝','蛅','詀','詹','譫','谵','趈','邅','閚','霑','飦','饘','驙','魙','鱣','鸇','鹯','𫗴',],ō:['噢'],'zhòu zhuó':['噣'],'jiào qiào chī':['噭'],yuàn:['噮','妴','怨','愿','掾','瑗','禐','苑','衏','裫','褑','院','願',],'ǎi ài āi':['噯'],'yōng yǒng':['噰','澭'],'jué xué':['噱'],'pēn pèn fèn':['噴'],gá:['噶','尜','釓','錷','钆'],'xīn hěn hèn':['噷'],dāng:['噹','澢','珰','璫','筜','簹','艡','蟷','裆','襠'],làn:['嚂','滥','濫','烂','燗','爁','爛','爤','瓓','糷','钄'],tà:['嚃','嚺','崉','挞','搨','撻','榻','橽','毾','涾','澾','濌','禢','粏','誻','譶','蹋','蹹','躂','躢','遝','錔','闒','闥','闼','阘','鞜','鞳',],'huō huò ǒ':['嚄'],hāo:['嚆','茠','蒿','薅'],'hè xià':['嚇'],'xiù pì':['嚊'],'zhōu chóu':['嚋','盩','诪'],mē:['嚒'],'chā cā':['嚓'],'bó pào bào':['嚗'],'me mèi mò':['嚜'],'xié hái':['嚡'],'áo xiāo':['嚣'],mō:['嚤','摸'],pín:['嚬','娦','嫔','嬪','玭','矉','薲','蠙','貧','贫','顰','颦','𬞟',],mè:['嚰','濹'],'rǎng rāng':['嚷'],lá:['嚹','旯'],'jiáo jué jiào':['嚼'],chuò:['嚽','娖','擉','歠','涰','磭','踀','輟','辍','辵','辶','酫','鑡','餟','齪','龊',],'huān huàn':['嚾'],'zá cà':['囃'],chài:['囆','虿','蠆','袃','訍'],'náng nāng':['囊'],'zá zàn cān':['囋'],sū:['囌','櫯','甦','稣','穌','窣','蘇','蘓','酥','鯂'],zèng:['囎','熷','甑','贈','赠','鋥','锃'],'zá niè yàn':['囐'],nāng:['囔'],'luó luō luo':['囖'],'wéi guó':['囗'],huí:['囘','回','囬','廻','廽','恛','洄','痐','茴','蚘','蛔','蛕','蜖','迴','逥','鮰',],nín:['囜','您','脌'],'jiǎn nān':['囝'],nān:['囡'],tuán:['团','団','團','慱','抟','摶','檲','糰','鏄','鷒','鷻'],'tún dùn':['囤','坉'],guó:['囯','囶','囻','国','圀','國','帼','幗','慖','摑','漍','聝','腘','膕','蔮','虢','馘','𬇹',],kùn:['困','涃','睏'],'wéi tōng':['囲'],qūn:['囷','夋','逡'],rì:['囸','日','衵','鈤','馹','驲'],tāi:['囼','孡','胎'],pǔ:['圃','圑','擈','普','暜','樸','檏','氆','浦','溥','烳','諩','譜','谱','蹼','鐠','镨',],'quān juàn juān':['圈','圏'],'chuí chuán':['圌'],tuǎn:['圕','畽','疃'],lüè:['圙','掠','略','畧','稤','鋝','鋢','锊','䂮'],'huán yuán':['圜'],luán:['圝','圞','奱','娈','孌','孪','孿','峦','巒','挛','攣','曫','栾','欒','滦','灤','癴','癵','羉','脔','臠','虊','銮','鑾','鵉','鸞','鸾',],tǔ:['土','圡','釷','钍'],'xū wéi':['圩'],'dì de':['地','嶳'],'qiān sú':['圱'],zhèn:['圳','塦','挋','振','朕','栚','甽','眹','紖','絼','纼','誫','賑','赈','鋴','鎭','鎮','镇','阵','陣','震','鴆','鸩',],'chǎng cháng':['场','場','塲'],'qí yín':['圻'],jiá:['圿','忦','恝','戞','扴','脥','荚','莢','蛱','蛺','裌','跲','郏','郟','鋏','铗','頬','頰','颊','鴶','鵊',],'zhǐ zhì':['坁'],bǎn:['坂','岅','昄','板','版','瓪','粄','舨','蝂','鈑','钣','阪','魬',],qǐn:['坅','寑','寝','寢','昑','梫','笉','螼','赾','鋟','锓'],'méi fén':['坆'],'rǒng kēng':['坈'],'fāng fáng':['坊'],'fèn bèn':['坋'],tān:['坍','怹','摊','擹','攤','滩','灘','瘫','癱','舑','貪','贪'],'huài pēi pī péi':['坏'],'dì làn':['坔'],tán:['坛','墰','墵','壇','壜','婒','憛','昙','曇','榃','檀','潭','燂','痰','磹','罈','罎','藫','談','譚','譠','谈','谭','貚','郯','醰','錟','顃',],bà:['坝','垻','壩','弝','欛','灞','爸','矲','覇','霸','鮁','鲅'],fén:['坟','墳','妢','岎','幩','枌','棼','汾','焚','燌','燓','羒','羵','蒶','蕡','蚠','蚡','豮','豶','轒','鐼','隫','馩','魵','黂','鼖','鼢','𣸣',],zhuì:['坠','墜','惴','甀','畷','礈','綴','縋','缀','缒','腏','膇','諈','贅','赘','醊','錣','鑆',],pō:['坡','岥','泼','溌','潑','釙','鏺','钋','頗','颇','䥽'],'pǎn bàn':['坢'],kūn:['坤','堃','堒','崐','崑','昆','晜','潉','焜','熴','猑','琨','瑻','菎','蜫','裈','裩','褌','醌','錕','锟','騉','髠','髡','髨','鯤','鲲','鵾','鶤','鹍',],diàn:['坫','垫','墊','壂','奠','婝','店','惦','扂','橂','殿','淀','澱','玷','琔','电','癜','簟','蜔','鈿','電','靛','驔',],'mù mǔ':['坶'],'kē kě':['坷','軻'],xuè:['坹','岤','桖','瀥','狘','瞲','謔','谑','趐'],'dǐ chí':['坻','柢'],lā:['垃','柆','菈','邋'],lǒng:['垄','垅','壟','壠','拢','攏','竉','陇','隴','𬕂'],mín:['垊','姄','岷','崏','捪','旻','旼','民','珉','琘','琝','瑉','痻','盿','砇','緍','緡','缗','罠','苠','鈱','錉','鍲','鴖',],'dòng tóng':['垌','峒','洞'],cí:['垐','嬨','慈','柌','濨','珁','瓷','甆','磁','礠','祠','糍','茨','詞','词','辝','辞','辤','辭','雌','飺','餈','鴜','鶿','鷀','鹚',],duī:['垖','堆','塠','痽','磓','鐓','鐜','鴭'],'duò duǒ':['垛'],'duǒ duò':['垜','挆'],chá:['垞','察','嵖','搽','槎','檫','猹','茬','茶','詧','靫','𥻗'],shǎng:['垧','晌','樉','賞','贘','赏','鋿','鏛','鑜'],shǒu:['垨','守','手','扌','艏','首'],da:['垯','繨','跶'],háng:['垳','斻','杭','筕','絎','绗','航','苀','蚢','裄','貥','迒','頏','颃','魧',],'ān ǎn':['垵'],xīng:['垶','惺','星','曐','煋','猩','瑆','皨','篂','腥','興','觪','觲','謃','騂','骍','鮏','鯹',],'yuàn huán':['垸'],bāng:['垹','帮','幇','幚','幫','捠','梆','浜','邦','邫','鞤','𠳐',],'póu fú':['垺'],cén:['埁','岑','涔'],'běng fēng':['埄'],'dì fáng':['埅'],'xiá jiā':['埉'],'mái mán':['埋'],làng:['埌','崀','浪','蒗','閬','㫰'],'shān yán':['埏'],'qín jīn':['埐'],'pǔ bù':['埔'],huā:['埖','婲','椛','硴','糀','花','蒊','蘤','誮','錵'],'suì sù':['埣'],'pí pì':['埤'],'qīng zhēng':['埥','鲭'],'wǎn wān':['埦'],lǔn:['埨','稐','𫭢'],'zhēng chéng':['埩'],kōng:['埪','崆','箜','躻','錓','鵼'],'cǎi cài':['埰','寀','采'],'chù tòu':['埱'],běng:['埲','琫','菶','鞛'],'kǎn xiàn':['埳'],'yì shì':['埶','醳'],péi:['培','毰','裴','裵','賠','赔','錇','锫','阫','陪'],'sào sǎo':['埽'],'jǐn qīn jìn':['堇'],'péng bèng':['堋'],'qiàn zàn jiàn':['堑'],àn:['堓','屵','岸','按','暗','案','胺','荌','豻','貋','錌','闇','隌','黯',],'duò huī':['堕','墮'],huán:['堚','寏','寰','峘','桓','洹','澴','獂','环','環','糫','繯','缳','羦','荁','萈','萑','豲','鍰','鐶','锾','镮','闤','阛','雈','鬟','鹮','𬘫','𤩽',],'bǎo bǔ pù':['堡'],'máo móu wǔ':['堥'],ruán:['堧','壖','撋'],'ài è yè':['堨'],gèng:['堩','暅'],méi:['堳','塺','媒','嵋','徾','攗','枚','栂','梅','楣','楳','槑','湄','湈','煤','猸','玫','珻','瑂','眉','睂','禖','脄','脢','腜','苺','莓','葿','郿','酶','鎇','镅','霉','鶥','鹛','黴',],dǔ:['堵','琽','睹','笃','篤','覩','賭','赌'],féng:['堸','綘','艂','逢'],hèng:['堼'],chūn:['堾','媋','旾','春','暙','杶','椿','槆','橁','櫄','瑃','箺','萅','蝽','輴','鰆','鶞','䲠',],jiǎng:['塂','奖','奨','奬','桨','槳','獎','耩','膙','蒋','蔣','講','讲','顜',],huāng:['塃','巟','慌','肓','荒','衁'],duàn:['塅','断','斷','椴','段','毈','煅','瑖','碫','簖','籪','緞','缎','腶','葮','躖','鍛','锻',],tǎ:['塔','墖','獭','獺','鮙','鰨','鳎'],wěng:['塕','奣','嵡','攚','暡','瞈','蓊'],'sāi sài sè':['塞'],zàng:['塟','弉','臓','臟','葬','蔵','銺'],tián:['塡','屇','恬','沺','湉','璳','甛','甜','田','畋','畑','碵','磌','胋','闐','阗','鴫','鷆','鷏',],zhèng:['塣','幁','政','証','諍','證','证','诤','郑','鄭','靕','鴊',],'tián zhèn':['填'],wēn:['塭','昷','榲','殟','温','溫','瑥','瘟','蕰','豱','輼','轀','辒','鎾','饂','鰛','鰮','鳁',],liù:['塯','廇','磟','翏','雡','霤','餾','鬸','鷚','鹨'],hǎi:['塰','海','烸','酼','醢'],lǎng:['塱','朖','朗','朤','烺','蓢','㮾'],bèng:['塴','揼','泵','甏','綳','蹦','迸','逬','鏰','镚'],chén:['塵','宸','尘','忱','敐','敶','晨','曟','栕','樄','沉','煁','瘎','臣','茞','莀','莐','蔯','薼','螴','訦','諶','軙','辰','迧','鈂','陈','陳','霃','鷐','麎',],'ōu qiū':['塸'],'qiàn jiàn':['塹'],'zhuān tuán':['塼'],shuǎng:['塽','慡','漺','爽','縔','鏯'],shú:['塾','婌','孰','璹','秫','贖','赎'],lǒu:['塿','嵝','嶁','甊','篓','簍'],chí:['墀','弛','持','池','漦','竾','筂','箎','篪','茌','荎','蚳','謘','貾','赿','踟','迟','迡','遅','遟','遲','鍉','馳','驰',],shù:['墅','庶','庻','怷','恕','戍','束','树','樹','沭','漱','潄','濖','竖','竪','絉','腧','荗','蒁','虪','術','裋','豎','述','鉥','錰','鏣','霔','鶐','𬬸',],'dì zhì':['墆','疐'],kàn:['墈','崁','瞰','矙','磡','衎','鬫'],chěn:['墋','夦','硶','碜','磣','贂','趻','踸','鍖'],'zhǐ zhuó':['墌'],qiǎng:['墏','繈','繦','羥','襁'],zēng:['増','增','憎','璔','矰','磳','罾','譄','鄫','鱛','䎖'],qiáng:['墙','墻','嫱','嬙','樯','檣','漒','牆','艢','蔃','蔷','蘠',],'kuài tuí':['墤'],'tuǎn dǒng':['墥'],'qiáo què':['墧'],'zūn dūn':['墫'],'qiāo áo':['墽'],'yì tú':['墿'],'xué bó jué':['壆'],lǎn:['壈','嬾','孄','孏','懒','懶','揽','擥','攬','榄','欖','浨','漤','灠','纜','缆','罱','覧','覽','览','醂','顲',],huài:['壊','壞','蘾'],rǎng:['壌','壤','攘','爙'],'làn xiàn':['壏'],dǎo:['壔','导','導','岛','島','嶋','嶌','嶹','捣','搗','擣','槝','祷','禂','禱','蹈','陦','隝','隯',],ruǐ:['壡','桵','橤','繠','蕊','蕋','蘂','蘃'],san:['壭'],zhuàng:['壮','壯','壵','撞','焋','状','狀'],'ké qiào':['壳','殼'],kǔn:['壸','壼','悃','捆','梱','硱','祵','稇','稛','綑','裍','閫','閸','阃',],mǎng:['壾','漭','茻','莽','莾','蠎'],cún:['壿','存'],'zhǐ zhōng':['夂'],'gǔ yíng':['夃'],'jiàng xiáng':['夅','降'],'páng féng fēng':['夆'],zhāi:['夈','捚','摘','斋','斎','榸','粂','齋'],'xuàn xiòng':['夐'],wài:['外','顡'],'wǎn yuàn wān yuān':['夗'],'mǎo wǎn':['夘'],mèng:['夢','夣','孟','梦','癦','霥'],'dà dài':['大'],'fū fú':['夫','姇','枎','粰'],guài:['夬','怪','恠'],yāng:['央','姎','抰','殃','泱','秧','胦','鉠','鍈','雵','鴦','鸯',],'hāng bèn':['夯'],gǎo:['夰','搞','杲','槀','槁','檺','稁','稾','稿','縞','缟','菒','藁','藳',],'tāo běn':['夲'],'tóu tou':['头'],'yǎn tāo':['夵'],'kuā kuà':['夸','誇'],'jiá jiā gā xiá':['夹'],huà:['夻','婳','嫿','嬅','崋','摦','杹','枠','桦','槬','樺','澅','画','畫','畵','繣','舙','話','諙','譮','话','黊',],'jiā jiá gā xiá':['夾'],ēn:['奀','恩','蒽'],'dī tì':['奃'],'yǎn yān':['奄','渰'],pào:['奅','疱','皰','砲','礟','礮','靤','麭'],nài:['奈','柰','渿','耐','萘','褦','錼','鼐'],'quān juàn':['奍','弮','棬'],zòu:['奏','揍'],'qì qiè xiè':['契'],kāi:['奒','开','揩','鐦','锎','開'],'bēn bèn':['奔','泍'],tào:['套'],'zàng zhuǎng':['奘'],běn:['奙','本','楍','畚','翉','苯'],'xùn zhuì':['奞'],shē:['奢','檨','猞','畭','畲','賒','賖','赊','輋','𪨶'],'hǎ pò tǎi':['奤'],'ào yù':['奥','奧','澚'],yūn:['奫','氲','氳','蒀','蒕','蝹','贇','赟','𫖳'],'duǒ chě':['奲'],'nǚ rǔ':['女'],nú:['奴','孥','笯','駑','驽'],'dīng dǐng tiǎn':['奵'],'tā jiě':['她'],nuán:['奻'],'hǎo hào':['好'],fàn:['奿','嬎','梵','汎','泛','滼','瀪','犯','畈','盕','笵','範','范','訉','販','贩','軬','輽','飯','飰','饭',],shuò:['妁','搠','朔','槊','烁','爍','矟','蒴','鎙','鑠','铄'],'fēi pèi':['妃'],wàng:['妄','忘','旺','望','朢'],zhuāng:['妆','妝','娤','庄','庒','桩','梉','樁','粧','糚','荘','莊','装','裝',],mā:['妈','媽'],'fū yōu':['妋'],'hài jiè':['妎'],dù:['妒','妬','杜','殬','渡','秺','芏','荰','螙','蠧','蠹','鍍','镀','靯','𬭊',],miào:['妙','庙','庿','廟','玅','竗'],'fǒu pēi pī':['妚'],'yuè jué':['妜'],niū:['妞'],'nà nàn':['妠'],tuǒ:['妥','嫷','庹','椭','楕','橢','鬌','鰖','鵎'],'wàn yuán':['妧'],fáng:['妨','房','肪','防','魴','鲂'],nī:['妮'],zhóu:['妯','碡'],zhāo:['妱','巶','招','昭','釗','鉊','鍣','钊','駋','𬬿'],'nǎi nǐ':['妳'],tǒu:['妵','敨','紏','蘣','黈'],'xián xuán xù':['妶'],'zhí yì':['妷','秇'],ē:['妸','妿','婀','屙'],mèi:['妹','媚','寐','抺','旀','昧','沬','煝','痗','眛','睸','祙','篃','蝞','袂','跊','鬽','魅',],'qī qì':['妻'],'xū xǔ':['姁','稰'],'shān shàn':['姍','姗','苫','釤','钐'],mán:['姏','慲','樠','蛮','蠻','謾','饅','馒','鬗','鬘','鰻','鳗'],jiě:['姐','媎','檞','毑','飷'],'wěi wēi':['委'],pīn:['姘','拼','礗','穦','馪','驞'],'huá huó':['姡'],'jiāo xiáo':['姣'],'gòu dù':['姤'],'lǎo mǔ':['姥'],'nián niàn':['姩'],zhěn:['姫','屒','弫','抮','昣','枕','畛','疹','眕','稹','縝','縥','缜','聄','萙','袗','裖','覙','診','诊','軫','轸','辴','駗','鬒',],héng:['姮','恆','恒','烆','珩','胻','蘅','衡','鑅','鴴','鵆','鸻',],'jūn xún':['姰'],'kuā hù':['姱'],'è yà':['姶'],'xiān shēn':['姺'],wá:['娃'],'ráo rǎo':['娆','嬈'],'shào shāo':['娋'],xiē:['娎','揳','楔','歇','蝎','蠍'],'wǔ méi mǔ':['娒'],'chuò lài':['娕'],niáng:['娘','嬢','孃'],'nà nuó':['娜','𦰡'],'pōu bǐ':['娝'],'něi suī':['娞'],tuì:['娧','煺','蛻','蜕','退','駾'],mǎn:['娨','屘','満','满','滿','螨','蟎','襔','鏋'],'wú wù yú':['娪'],'xī āi':['娭'],'zhuì shuì':['娷'],'dōng dòng':['娻'],'ǎi ái è':['娾'],'ē ě':['娿'],mián:['婂','嬵','宀','杣','棉','檰','櫋','眠','矈','矊','矏','綿','緜','绵','芇','蝒',],'pǒu péi bù':['婄'],biǎo:['婊','脿','表','裱','褾','諘','錶'],'fù fàn':['婏'],wǒ:['婐','婑','我'],'ní nǐ':['婗','棿'],'quán juàn':['婘','惓'],hūn:['婚','昏','昬','棔','涽','睧','睯','碈','荤','葷','蔒','轋','閽','阍',],'qiān jǐn':['婜'],'wān wà':['婠'],'lái lài':['婡','徕','徠'],'zhōu chōu':['婤'],'chuò nào':['婥'],'nüè àn':['婩'],'hùn kūn':['婫'],'dàng yáng':['婸'],nàn:['婻'],'ruò chuò':['婼'],jiǎ:['婽','岬','斚','斝','榎','槚','檟','玾','甲','胛','鉀','钾'],'tōu yú':['婾','媮'],'yù yú':['媀'],'wéi wěi':['媁'],'dì tí':['媂','珶','苐'],róu:['媃','揉','柔','渘','煣','瑈','瓇','禸','粈','糅','脜','腬','葇','蝚','蹂','輮','鍒','鞣','騥','鰇','鶔','𫐓',],'ruǎn nèn':['媆'],miáo:['媌','嫹','描','瞄','苗','鶓','鹋'],'yí pèi':['媐'],'mián miǎn':['媔'],'tí shì':['媞','惿'],'duò tuó':['媠','沲'],ǎo:['媪','媼','艹','芺','袄','襖','镺'],'chú zòu':['媰'],yìng:['媵','映','暎','硬','膡','鱦'],'qín shēn':['嫀'],jià:['嫁','幏','架','榢','稼','駕','驾'],sǎo:['嫂'],'zhēn zhěn':['嫃'],'jiē suǒ':['嫅'],'míng mǐng':['嫇'],niǎo:['嫋','嬝','嬲','茑','蔦','袅','裊','褭','鸟'],tāo:['嫍','幍','弢','慆','掏','搯','槄','涛','滔','濤','瑫','絛','縚','縧','绦','詜','謟','轁','鞱','韜','韬','飸','饕',],biáo:['嫑'],'piáo piāo':['嫖','薸'],xuán:['嫙','悬','懸','暶','檈','漩','玄','璇','璿','痃','蜁','𫠊',],'màn mān':['嫚'],kāng:['嫝','嵻','康','慷','槺','漮','砊','穅','糠','躿','鏮','鱇','𡐓','𩾌',],'hān nǎn':['嫨'],nèn:['嫩','嫰'],zhē:['嫬','遮'],'mā má':['嫲'],piè:['嫳'],zhǎn:['嫸','展','搌','斩','斬','琖','盏','盞','輾','醆','颭','飐',],'xiān yǎn jìn':['嬐'],liǎn:['嬚','敛','斂','琏','璉','羷','脸','臉','蔹','蘝','蘞','裣','襝','鄻',],'qióng huán xuān':['嬛'],dǒng:['嬞','懂','箽','董','蕫','諌'],cān:['嬠','湌','爘','飡','餐','驂','骖'],tiǎo:['嬥','宨','晀','朓','窱','脁'],bí:['嬶','荸','鼻'],liǔ:['嬼','柳','栁','桞','桺','橮','熮','珋','綹','绺','罶','羀','鋶','锍',],'qiān xiān':['孅','欦'],'xié huī':['孈'],'huān quán':['孉'],'lí lì':['孋','麗'],'zhú chuò':['孎'],kǒng:['孔','恐'],'mā zī':['孖'],'sūn xùn':['孙','孫'],'bèi bó':['孛','誖'],'yòu niū':['孧'],zhuǎn:['孨','竱','轉'],hái:['孩','骸'],nāo:['孬'],'chán càn':['孱'],bò:['孹','檗','蘗','譒'],nái:['孻','腉'],'níng nìng':['宁','寍','寗','寜','寧','甯'],zhái:['宅'],'tū jiā':['宊'],sòng:['宋','訟','誦','讼','诵','送','鎹','頌','颂','餸'],ròu:['宍','肉','譳'],zhūn:['宒','窀','衠','諄','谆','迍'],'mì fú':['宓'],'dàng tàn':['宕'],'wǎn yuān':['宛'],chǒng:['宠','寵'],qún:['宭','峮','帬','羣','群','裙','裠'],zǎi:['宰','崽'],'bǎo shí':['宲'],'jiā jia jie':['家'],'huāng huǎng':['宺'],kuān:['宽','寛','寬','臗','鑧','髋','髖'],'sù xiǔ xiù':['宿'],'jié zǎn':['寁'],'bìng bǐng':['寎'],'jìn qǐn':['寖'],'lóu jù':['寠'],'xiě xiè':['寫'],'qīn qìn':['寴'],cùn:['寸','籿'],duì:['对','対','對','怼','憝','懟','濧','瀩','碓','祋','綐','薱','譈','譵','轛','队','陮',],'lüè luó':['寽'],'shè yè yì':['射'],'jiāng jiàng qiāng':['将'],'jiāng jiàng':['將','浆','漿','畺'],zūn:['尊','嶟','樽','罇','遵','鐏','鱒','鳟','鶎','鷷','𨱔'],'shù zhù':['尌','澍'],xiǎo:['小','晓','暁','曉','皛','皢','筱','筿','篠','謏','𫍲'],'jié jí':['尐','诘','鞊'],'shǎo shào':['少'],ěr:['尒','尓','尔','栮','毦','洱','爾','珥','耳','薾','衈','趰','迩','邇','鉺','铒','餌','饵','駬',],'wāng yóu':['尢'],wāng:['尣','尩','尪','尫','汪'],liào:['尥','尦','廖','撂','料','炓','窷','鐐','镣','𪤗'],'méng máng lóng páng':['尨'],gà:['尬','魀'],'kuì kuǐ':['尯'],tuí:['尵','弚','穨','蘈','蹪','隤','頹','頺','頽','颓','魋','𬯎'],yǐn:['尹','嶾','引','朄','檃','檼','櫽','淾','濥','瘾','癮','粌','蘟','蚓','螾','讔','赺','趛','輑','鈏','靷',],'chǐ chě':['尺'],kāo:['尻','髛'],'jìn jǐn':['尽'],'wěi yǐ':['尾'],'niào suī':['尿'],céng:['层','層','嶒','驓'],diǎo:['屌'],'píng bǐng bīng':['屏'],lòu:['屚','漏','瘘','瘺','瘻','鏤','镂','陋'],'shǔ zhǔ':['属','屬'],'xiè tì':['屟'],'chè cǎo':['屮'],'tún zhūn':['屯'],'nì jǐ':['屰'],'hóng lóng':['屸'],'qǐ kǎi':['岂','豈'],áng:['岇','昂','昻'],'gǎng gāng':['岗','崗'],kě:['岢','敤','渇','渴','炣'],gǒu:['岣','狗','玽','笱','耇','耈','耉','苟','豿'],tiáo:['岧','岹','樤','祒','笤','芀','萔','蓚','蓨','蜩','迢','鋚','鎥','鞗','髫','鯈','鰷','鲦','齠','龆',],'qū jū':['岨'],lǐng:['岭','嶺','領','领'],pò:['岶','敀','洦','湐','烞','珀','破','砶','粕','蒪','魄'],'bā kè':['峇'],luò:['峈','摞','洛','洜','犖','珞','笿','纙','荦','詻','雒','駱','骆','鵅',],'fù niè':['峊'],ěn:['峎'],'zhì shì':['峙','崻'],qiǎ:['峠','跒','酠','鞐'],'qiáo jiào':['峤','癄'],'xié yé':['峫'],bū:['峬','庯','晡','誧','逋','鈽','錻','钸','餔','鵏'],chóng:['崇','崈','爞','虫','蝩','蟲','褈','隀'],'zú cuì':['崒','椊'],'líng léng':['崚'],'dòng dōng':['崠'],xiáo:['崤','洨','淆','訤','誵'],'pí bǐ':['崥','芘'],'zhǎn chán':['崭','嶃','嶄'],'wǎi wēi':['崴'],'yáng dàng':['崵'],'shì dié':['崼'],yào:['崾','曜','熎','燿','矅','穾','窔','筄','耀','艞','药','葯','薬','藥','袎','覞','詏','讑','靿','鷂','鹞','鼼',],'kān zhàn':['嵁'],'hán dǎng':['嵅'],'qiàn kàn':['嵌'],'wù máo':['嵍'],'kě jié':['嵑','嶱'],'wēi wěi':['嵔'],kē:['嵙','柯','棵','榼','樖','牁','牱','犐','珂','疴','瞌','磕','礚','科','稞','窠','萪','薖','蚵','蝌','趷','轲','醘','鈳','钶','頦','顆','颗','髁',],'dàng táng':['嵣'],'róng yíng':['嵤','爃'],'ái kǎi':['嵦'],'kāo qiāo':['嵪'],cuó:['嵯','嵳','痤','矬','蒫','蔖','虘','鹺','鹾'],'qiǎn qīn':['嵰'],'dì dié':['嵽'],cēn:['嵾'],dǐng:['嵿','艼','薡','鐤','頂','顶','鼎','鼑'],'áo ào':['嶅'],'pǐ pèi':['嶏'],'jiào qiáo':['嶠','潐'],'jué guì':['嶡','鳜'],'zhān shàn':['嶦','鳣'],'xiè jiè':['嶰'],'guī xī juàn':['嶲'],rū:['嶿'],'lì liè':['巁','棙','爄','綟'],'xī guī juàn':['巂'],'yíng hōng':['巆'],yǐng:['巊','廮','影','摬','梬','潁','瘿','癭','矨','穎','郢','鐛','頴','颍','颕','颖',],chǎo:['巐','炒','煼','眧','麨'],cuán:['巑','櫕','欑'],chuān:['巛','川','氚','瑏','穿'],'jīng xíng':['巠'],cháo:['巢','巣','晁','漅','潮','牊','窲','罺','謿','轈','鄛','鼌',],qiǎo:['巧','愀','髜'],gǒng:['巩','廾','拱','拲','栱','汞','珙','輁','鞏'],'chà chā chāi cī':['差'],'xiàng hàng':['巷'],shuài:['帅','帥','蟀'],pà:['帊','帕','怕','袙'],'tǎng nú':['帑'],'mò wà':['帓'],'tiē tiě tiè':['帖'],zhǒu:['帚','晭','疛','睭','箒','肘','菷','鯞'],'juǎn juàn':['帣'],shuì:['帨','涗','涚','睡','稅','税','裞'],'chóu dào':['帱','幬'],'jiǎn jiān sàn':['帴'],'shà qiè':['帹'],'qí jì':['帺','荠'],'shān qiāo shēn':['幓'],'zhuàng chuáng':['幢'],'chān chàn':['幨'],miè:['幭','懱','搣','滅','灭','烕','礣','篾','蔑','薎','蠛','衊','鑖','鱴','鴓',],'gān gàn':['干'],'bìng bīng':['并','幷'],'jī jǐ':['幾'],'guǎng ān':['广'],guǎng:['広','廣','犷','獷'],me:['庅'],'dùn tún':['庉'],'bài tīng':['庍'],'yìng yīng':['应'],'dǐ de':['底'],'dù duó':['度'],'máng méng páng':['庬'],'bìng píng':['庰'],chěng:['庱','悜','睈','逞','騁','骋'],'jī cuò':['庴'],qǐng:['庼','廎','檾','漀','苘','請','謦','请','頃','顷'],'guī wěi huì':['廆'],'jǐn qín':['廑'],kuò:['廓','扩','拡','擴','濶','筈','萿','葀','蛞','闊','阔','霩','鞟','鞹','韕','頢','鬠',],'qiáng sè':['廧','薔'],'yǐn yìn':['廴','隐','隠','隱','飮','飲','饮'],'pò pǎi':['廹','迫'],'nòng lòng':['弄'],'dì tì tuí':['弟'],'jué zhāng':['弡'],'mí mǐ':['弥','彌','靡'],chāo:['弨','怊','抄','欩','訬','超','鈔','钞'],yi:['弬'],shāo:['弰','旓','烧','焼','燒','筲','艄','萷','蕱','輎','髾','鮹',],'xuān yuān':['弲'],'qiáng qiǎng jiàng':['強','强'],'tán dàn':['弹','醈'],biè:['彆'],'qiáng jiàng qiǎng':['彊'],'jì xuě':['彐'],tuàn:['彖','褖'],yuē:['彟','曰','曱','矱'],'shān xiǎn':['彡'],wén:['彣','文','炆','珳','瘒','繧','聞','芠','蚉','蚊','螡','蟁','閺','閿','闅','闦','闻','阌','雯','馼','駇','魰','鳼','鴍','鼤','𫘜',],'péng bāng':['彭'],'piāo piào':['彯'],'zhuó bó':['彴'],'tuǒ yí':['彵'],'páng fǎng':['彷'],wǎng:['彺','往','徃','惘','枉','棢','網','网','罒','罓','罔','罖','菵','蛧','蝄','誷','輞','辋','魍',],cú:['徂','殂'],'dài dāi':['待'],huái:['徊','怀','懐','懷','槐','淮','耲','蘹','褢','褱','踝'],'wā wàng jiā':['徍'],'chěng zhèng':['徎'],'dé děi de':['得'],'cóng zòng':['從'],'shì tǐ':['徥'],'tí chí':['徲','鶗','鶙'],dé:['徳','德','恴','悳','惪','淂','鍀','锝'],'zhǐ zhēng':['徴','徵'],bié:['徶','癿','莂','蛂','襒','蹩'],'chōng zhǒng':['徸'],'jiǎo jiào':['徼','笅','筊'],'lòng lǒng':['徿'],'qú jù':['忂','渠','瞿','螶'],'dìng tìng':['忊'],gǎi:['忋','改'],rěn:['忍','栠','栣','秹','稔','綛','荏','荵','躵'],chàn:['忏','懴','懺','硟','羼','韂','顫'],tè:['忑','慝','特','蟘','鋱','铽'],'tè tēi tuī':['忒'],'gān hàn':['忓','攼'],'yì qì':['忔'],'tài shì':['忕'],'xī liě':['忚'],'yīng yìng':['応','應','譍'],'mǐn wěn mín':['忞','忟'],'sōng zhōng':['忪'],'yù shū':['忬','悆'],'qí shì':['忯','耆'],'tún zhūn dùn':['忳'],'qián qín':['忴','扲'],hún:['忶','浑','渾','餛','馄','魂','鼲'],niǔ:['忸','扭','炄','狃','紐','纽','莥','鈕','钮','靵'],'kuáng wǎng':['忹'],'kāng hàng':['忼'],'kài xì':['忾','愾'],òu:['怄','慪'],'bǎo bào':['怉'],'mín mén':['怋'],'zuò zhà':['怍'],zěn:['怎'],yàng:['怏','恙','样','様','樣','漾','羕','詇'],'kòu jù':['怐'],'náo niú':['怓'],'zhēng zhèng':['怔','掙','钲','铮'],'tiē zhān':['怗'],'hù gù':['怘'],'cū jù zū':['怚'],'sī sāi':['思'],'yóu chóu':['怞'],'tū dié':['怢'],'yōu yào':['怮'],xuàn:['怰','昡','楦','泫','渲','炫','琄','眩','碹','絢','縼','繏','绚','蔙','衒','袨','贙','鉉','鏇','铉','镟','颴',],'xù xuè':['怴'],'bì pī':['怶'],'xī shù':['怸'],'nèn nín':['恁'],'tiāo yáo':['恌'],'xī qī xù':['恓'],'xiào jiǎo':['恔'],'hū kuā':['恗'],nǜ:['恧','朒','衂','衄'],hèn:['恨'],'dòng tōng':['恫'],'quán zhuān':['恮'],'è wù ě wū':['恶','惡'],tòng:['恸','慟','憅','痛','衕'],'yuān juàn':['悁'],'qiāo qiǎo':['悄'],'jiè kè':['悈'],'hào jiào':['悎'],huǐ:['悔','檓','毀','毁','毇','燬','譭'],'mán mèn':['悗','鞔'],'yī yì':['悘','衣'],quān:['悛','箞','鐉','𨟠'],'kuī lǐ':['悝'],'yì niàn':['悥'],'mèn mēn':['悶'],guàn:['悹','悺','惯','慣','掼','摜','樌','欟','泴','涫','潅','灌','爟','瓘','盥','礶','祼','罆','罐','貫','贯','躀','遦','鏆','鑵','鱹','鸛','鹳',],'kōng kǒng':['悾'],'lǔn lùn':['惀'],guǒ:['惈','果','椁','槨','粿','綶','菓','蜾','裹','褁','輠','餜','馃',],'yuān wǎn':['惌','箢'],'lán lín':['惏'],'yù xù':['惐','淢'],'chuò chuì':['惙'],'hūn mèn':['惛'],'chǎng tǎng':['惝'],'suǒ ruǐ':['惢'],cǎn:['惨','慘','憯','黪','黲','䅟'],cán:['惭','慙','慚','残','殘','蚕','蝅','蠶','蠺'],'dàn dá':['惮','憚'],rě:['惹'],'yú tōu':['愉'],'kài qì':['愒'],'dàng táng shāng yáng':['愓'],'chén xìn dān':['愖'],'kè qià':['愘'],nuò:['愞','懦','懧','掿','搦','榒','稬','穤','糑','糥','糯','諾','诺','蹃','逽','鍩','锘',],gǎn:['感','擀','敢','桿','橄','澉','澸','皯','秆','稈','笴','芉','衦','赶','趕','鱤','鳡',],'còng sōng':['愡'],'sāi sī sǐ':['愢'],'gōng gòng hǒng':['愩','慐'],'shuò sù':['愬','洬'],'yáo yào':['愮'],huàng:['愰','曂','榥','滉','皝','皩','鎤','㿠'],zhěng:['愸','抍','拯','整','晸'],cǎo:['愺','艸','草','騲'],'xì xié':['慀'],'cǎo sāo':['慅'],'xù chù':['慉'],'qiè qiàn':['慊'],'cáo cóng':['慒'],'ào áo':['慠'],'lián liǎn':['慩','梿','槤','櫣'],'jìn qín jǐn':['慬'],'dì chì':['慸'],'zhí zhé':['慹'],'lóu lǚ':['慺','鷜'],còng:['憁','謥'],'zhī zhì':['憄','知','織','织'],chēng:['憆','摚','撐','撑','晿','柽','棦','橕','檉','泟','浾','琤','瞠','碀','緽','罉','蛏','蟶','赪','赬','鏿','鐣','阷','靗','頳','饓',],biē:['憋','虌','鱉','鳖','鼈','龞'],'chéng dèng zhèng':['憕'],'xǐ xī':['憘'],'duì dùn tūn':['憞'],'xiāo jiāo':['憢'],'xián xiàn':['憪'],'liáo liǎo':['憭','燎','爎','爒'],shéng:['憴','縄','繉','繩','绳','譝'],'náo nǎo náng':['憹'],'jǐng jìng':['憼'],'jǐ jiǎo':['憿'],'xuān huān':['懁'],'cǎo sāo sào':['懆'],mèn:['懑','懣','暪','焖','燜'],'mèng méng měng':['懜'],'ài yì nǐ':['懝'],'méng měng':['懞','瞢','矒'],'qí jī jì':['懠'],mǒ:['懡'],'lán xiàn':['懢'],'yōu yǒu':['懮'],'liú liǔ':['懰','藰'],ràng:['懹','譲','讓','让'],huān:['懽','欢','歓','歡','獾','讙','貛','酄','驩','鴅','鵍'],nǎn:['戁','揇','湳','煵','腩','蝻','赧'],'mí mó':['戂'],'gàng zhuàng':['戅','戆'],'zhuàng gàng':['戇'],'xū qu':['戌'],'xì hū':['戏','戯','戲'],'jiá gā':['戛'],zéi:['戝','蠈','賊','贼','鰂','鱡','鲗'],děng:['戥','等'],'hū xì':['戱'],chuō:['戳','踔','逴'],'biǎn piān':['扁'],'shǎng jiōng':['扄'],'shàn shān':['扇'],cái:['才','材','纔','裁','財','财'],'zhā zā zhá':['扎'],'lè lì cái':['扐'],'bā pá':['扒'],'dǎ dá':['打'],rēng:['扔'],'fǎn fú':['払'],'diǎo dí yuē lì':['扚'],'káng gāng':['扛'],'yū wū':['扜'],'yū wū kū':['扝'],'tuō chǐ yǐ':['扡'],'gǔ jié xì gē':['扢'],dèn:['扥','扽'],'sǎo sào':['扫','掃'],rǎo:['扰','擾','隢'],'xī chā qì':['扱'],'bān pān':['扳'],'bā ào':['扷'],'xī zhé':['扸'],'zhì sǔn kǎn':['扻'],zhǎo:['找','沼','瑵'],'kuáng wǎng zài':['抂'],'hú gǔ':['抇','鹄','鹘'],'bǎ bà':['把'],'dǎn shěn':['抌'],'nè nì ruì nà':['抐'],zhuā:['抓','檛','簻','膼','髽'],póu:['抔','裒'],'zhé shé zhē':['折'],'póu pōu fū':['抙','捊'],pāo:['抛','拋','脬','萢'],'ǎo ào niù':['抝'],'lūn lún':['抡','掄'],'qiǎng qiāng chēng':['抢'],'zhǐ zhǎi':['抧'],'bù pū':['抪','柨'],'yǎo tāo':['抭'],'hē hè qiā':['抲'],'nǐ ní':['抳'],'pī pēi':['抷'],'mǒ mò mā':['抹'],chōu:['抽','犨','犫','瘳','篘'],'jiā yá':['拁'],'fú bì':['拂','畐','鶝'],zhǎ:['拃','眨','砟','鮺','鲝'],'dān dàn dǎn':['担'],'chāi cā':['拆'],niān:['拈','蔫'],'lā lá lǎ là':['拉'],'bàn pàn':['拌'],pāi:['拍'],līn:['拎'],guǎi:['拐','枴','柺'],'tuò tà zhí':['拓'],'ào ǎo niù':['拗'],'jū gōu':['拘'],'pīn pàn fān':['拚'],'bài bái':['拜'],bài:['拝','敗','稗','粺','薭','贁','败','韛'],qiá:['拤'],'nǐng níng nìng':['拧'],'zé zhái':['择','擇'],hén:['拫','痕','鞎'],'kuò guā':['括'],'jié jiá':['拮'],nǐn:['拰'],shuān:['拴','栓','閂','闩'],'cún zùn':['拵'],'zā zǎn':['拶','桚'],kǎo:['拷','攷','栲','烤','考'],'yí chǐ hài':['拸'],'cè sè chuò':['拺'],'zhuài zhuāi yè':['拽'],'shí shè':['拾'],bāi:['挀','掰'],'kuò guāng':['挄'],nòng:['挊','挵','齈'],'jiào jiāo':['挍','敎','教'],'kuà kū':['挎'],'ná rú':['挐'],'tiāo tiǎo':['挑'],'dié shè':['挕'],liě:['挘','毟'],'yà yǎ':['挜','掗'],'wō zhuā':['挝'],'xié jiā':['挟','挾'],'dǎng dàng':['挡','擋'],'zhèng zhēng':['挣','正','症'],'āi ái':['挨'],'tuō shuì':['挩','捝'],'tǐ tì':['挮'],'suō shā':['挱'],'sā shā suō':['挲'],'kēng qiān':['挳','摼'],'bàng péng':['挷'],'ruó ruá':['挼'],'jiǎo kù':['捁'],'wǔ wú':['捂'],tǒng:['捅','桶','筒','筩','統','綂','统','㛚'],'huò chì':['捇'],'tú shū chá':['捈'],'lǚ luō':['捋'],'shāo shào':['捎','稍'],niē:['捏','揑'],'shù sǒng sōu':['捒'],'yé yú':['捓'],'jué zhuó':['捔'],'bù pú zhì':['捗'],zùn:['捘','銌'],lāo:['捞','撈','粩'],sǔn:['损','損','榫','笋','筍','箰','鎨','隼'],'wàn wǎn wān yù':['捥'],pěng:['捧','淎','皏'],shě:['捨'],'fǔ fù bǔ':['捬'],dáo:['捯'],'luò luǒ wǒ':['捰'],'juǎn quán':['捲'],'chēn tiǎn':['捵'],'niǎn niē':['捻'],'ruó wěi ré':['捼'],zuó:['捽','昨','秨','稓','筰','莋','鈼'],'wò xiá':['捾'],'qìng qiàn':['掅'],'póu pǒu':['掊'],qiā:['掐','葜'],'pái pǎi':['排'],'qiān wàn':['掔'],'yè yē':['掖'],'niè nǐ yì':['掜'],'huò xù':['掝'],'yàn shàn yǎn':['掞'],'zhěng dìng':['掟'],kòng:['控','鞚'],tuī:['推','蓷','藬'],'zōu zhōu chōu':['掫'],tiàn:['掭','舚'],kèn:['掯','裉','褃'],pá:['掱','杷','潖','爬','琶','筢'],'guó guāi':['掴'],'dǎn shàn':['掸','撣'],'chān xiān càn shǎn':['掺'],sāo:['掻','搔','溞','繅','缫','螦','騒','騷','鰠','鱢','鳋'],pèng:['掽','椪','槰','碰','踫'],'zhēng kēng':['揁'],'jiū yóu':['揂'],'jiān jiǎn':['揃','籛'],'pì chè':['揊'],'sāi zǒng cāi':['揌'],'tí dī dǐ':['提'],'zǒng sōng':['揔'],'huáng yóng':['揘'],'zǎn zuàn':['揝'],'xū jū':['揟'],'ké qiā':['揢'],'chuāi chuǎi chuài tuán zhuī':['揣'],'dì tì':['揥'],'lá là':['揦'],là:['揧','楋','溂','瓎','瘌','翋','臘','蝋','蝲','蠟','辢','辣','鑞','镴','鬎','鯻','𬶟',],'jiē qì':['揭'],'chòng dǒng':['揰'],'dié shé yè':['揲'],'jiàn qián jiǎn':['揵'],yé:['揶','爷','爺','瑘','鋣','鎁','铘'],chān:['搀','摻','攙','裧','襜','覘','觇','辿','鋓'],'gē gé':['搁','擱'],'lǒu lōu':['搂','摟'],'chōu zǒu':['搊'],chuāi:['搋'],sūn:['搎','槂','狲','猻','荪','蓀','蕵','薞','飧','飱'],'róng náng nǎng':['搑'],'péng bàng':['搒'],cuō:['搓','瑳','磋','蹉','遳','醝'],'kē è':['搕'],'nù nuò nòu':['搙'],'lā xié xiàn':['搚'],qiǔ:['搝','糗'],'xiǎn xiān':['搟'],'jié zhé':['搩'],'pán bān pó':['搫'],bān:['搬','攽','斑','斒','班','瘢','癍','肦','螁','螌','褩','辬','頒','颁','𨭉',],'zhì nái':['搱'],'wā wǎ wà':['搲'],huá:['搳','撶','滑','猾','蕐','螖','譁','鏵','铧','驊','骅','鷨'],'qiāng qiǎng chēng':['搶'],'tián shēn':['搷'],'ná nuò':['搻'],èn:['摁'],'shè niè':['摄','攝'],bìn:['摈','擯','殡','殯','膑','臏','髌','髕','髩','鬂','鬓','鬢'],'shā sà shǎi':['摋'],'chǎn sùn':['摌'],'jiū liú liáo jiǎo náo':['摎'],'féng pěng':['摓'],shuāi:['摔'],'dì tú zhí':['摕'],'qì jì chá':['摖'],'sōu sǒng':['摗'],'liǎn liàn':['摙'],'gài xì':['摡'],'hù chū':['摢'],tàng:['摥','烫','燙','鐋'],'nái zhì':['摨'],'mó mā':['摩'],'jiāng qiàng':['摪'],'áo qiáo':['摮'],'niè chè':['摰'],'mán màn':['摱'],'chàn cán':['摲'],'sè mí sù':['摵'],'biāo biào':['摽'],'juē jué':['撅'],piē:['撆','暼','氕','瞥'],'piě piē':['撇'],'zǎn zān zēn qián':['撍'],'sā sǎ':['撒'],hòng:['撔','訌','讧','闀','鬨'],'héng guàng':['撗'],niǎn:['撚','撵','攆','涊','焾','碾','簐','蹍','蹨','躎','輦','辇',],'chéng zhěng':['撜'],'huī wéi':['撝'],cāo:['撡','操','糙'],'xiāo sōu':['撨'],'liáo liāo':['撩'],'cuō zuǒ':['撮'],'wěi tuǒ':['撱'],cuān:['撺','攛','汆','蹿','躥','鑹','镩'],'qiào yāo jī':['撽'],'zhuā wō':['撾'],'lèi léi':['擂'],nǎng:['擃','攮','曩','灢'],'qíng jǐng':['擏'],kuǎi:['擓','蒯','㧟'],'pǐ bò':['擗'],'bò bāi':['擘'],'jù jǐ':['據'],mēng:['擝'],'sǒu sòu':['擞'],xǐng:['擤','箵','醒'],cā:['擦'],'níng nǐng nìng':['擰'],'zhì jié':['擳'],'là liè':['擸','爉'],'sòu sǒu':['擻'],'lì luò yuè':['擽'],'tī zhāi zhì':['擿'],pān:['攀','潘','眅','萠'],lèi:['攂','泪','涙','淚','禷','类','纇','蘱','酹','銇','錑','頛','頪','類','颣',],'cā sǎ':['攃'],'jùn pèi':['攈'],'lì luò':['攊','躒'],'là lài':['攋','櫴'],'lú luó':['攎'],'zǎn cuán':['攒'],'xiān jiān':['攕'],'mí mǐ mó':['攠'],'zǎn cuán zàn zuān':['攢'],zuàn:['攥'],'lì shài':['攦'],'lì luǒ':['攭'],'guǐ guì':['攱'],'jī qī yǐ':['攲'],fàng:['放'],'wù móu':['敄'],'chù shōu':['敊'],'gé guó è':['敋'],'duó duì':['敓','敚'],'duō què':['敠','敪'],'sàn sǎn':['散'],'dūn duì':['敦','镦'],'qī yǐ jī':['敧'],'xiào xué':['敩'],'shù shǔ shuò':['数','數'],'ái zhú':['敱','敳'],'xiòng xuàn':['敻'],'zhuó zhú':['斀'],'yì dù':['斁'],'lí tái':['斄'],'fěi fēi':['斐'],'yǔ zhōng':['斔'],'dòu dǒu':['斗'],'wò guǎn':['斡'],'tǒu tiǎo':['斢'],dòu:['斣','梪','浢','痘','窦','竇','脰','荳','豆','逗','郖','酘','閗','闘','餖','饾','鬥','鬦','鬪','鬬','鬭',],'yín zhì':['斦'],'chǎn jiè':['斺'],'wū yū yú':['於'],'yóu liú':['斿'],'páng bàng':['旁'],'máo mào':['旄'],'pī bì':['旇'],'xuán xuàn':['旋'],'wú mó':['无'],zǎo:['早','枣','栆','棗','澡','璪','薻','藻','蚤'],gā:['旮'],'gàn hàn':['旰'],'tái yīng':['旲'],'xū xù':['旴'],'tūn zhùn':['旽'],'wù wǔ':['旿'],'pò pèi':['昢'],zòng:['昮','猔','疭','瘲','粽','糉','糭','縦'],ǎi:['昹','毐','矮','蔼','藹','譪','躷','霭','靄'],'huàng huǎng':['晃'],xuǎn:['晅','癣','癬','选','選'],'xù kuā':['晇'],hǒng:['晎'],shài:['晒','曬'],'yūn yùn':['晕','煴'],'shèng chéng':['晟','椉','盛'],'jǐng yǐng':['景'],shǎn:['晱','熌','睒','覢','閃','闪','陕','陝'],'qǐ dù':['晵'],'ǎn àn yǎn':['晻'],'wǎng wàng':['暀'],zàn:['暂','暫','瓉','瓒','瓚','禶','襸','讃','讚','賛','贊','赞','蹔','鄼','錾','鏨','饡',],'yùn yūn':['暈'],'mín mǐn':['暋'],'dǔ shǔ':['暏'],shǔ:['暑','曙','潻','癙','糬','署','薥','薯','藷','蜀','蠴','襡','襩','鱪','鱰','黍','鼠','鼡',],'jiǎn lán':['暕'],nuǎn:['暖','煗','餪'],'bào pù':['暴'],'xī xǐ':['暿'],'pù bào':['曝','瀑'],'qū qǔ':['紶'],'qǔ qū':['曲'],'gèng gēng':['更'],'hū hù':['曶','雽'],'zēng céng':['曽','橧'],'céng zēng':['曾','竲'],'cǎn qián jiàn':['朁'],'qiè hé':['朅'],'bì pí':['朇','禆','笓','裨'],'yǒu yòu':['有'],'bān fén':['朌','鳻'],'fú fù':['服','洑'],'fěi kū':['朏','胐'],'qú xù chǔn':['朐'],'juān zuī':['朘'],'huāng máng wáng':['朚'],'qī jī':['期'],'tóng chuáng':['朣','橦'],zhá:['札','牐','箚','蚻','譗','鍘','铡','閘','闸'],'zhú shù shú':['朮'],'shù shú zhú':['术'],'zhū shú':['朱'],'pǔ pò pō piáo':['朴'],'dāo tiáo mù':['朷'],'guǐ qiú':['朹'],xiǔ:['朽','滫','潃','糔'],'chéng chēng':['朾'],zá:['杂','沯','砸','襍','雑','雜','雥','韴'],'yú wū':['杅'],'gān gǎn':['杆'],'chā chà':['杈'],'shān shā':['杉'],cūn:['村','皴','竴','膥','踆','邨'],'rèn ér':['杒','梕'],'sháo biāo':['杓'],'dì duò':['杕','枤'],'gū gài':['杚'],'yí zhì lí duò':['杝'],'gàng gāng':['杠'],'tiáo tiāo':['条','條'],'mà mǎ':['杩'],'sì zhǐ xǐ':['杫'],'yuán wán':['杬','蚖'],'bèi fèi':['杮'],'shū duì':['杸'],'niǔ chǒu':['杻'],'wò yuè':['枂','臒'],máo:['枆','毛','氂','渵','牦','矛','罞','茅','茆','蝥','蟊','軞','酕','鉾','錨','锚','髦','鶜',],'pī mì':['枈'],àng:['枊','盎','醠'],'fāng bìng':['枋'],'hù dǐ':['枑'],xín:['枔','襑','鐔','鬵'],'yāo yǎo':['枖'],'ě è':['枙'],'zhī qí':['枝'],'cōng zōng':['枞','樅'],'xiān zhēn':['枮'],'tái sì':['枱'],'gǒu jǔ gōu':['枸'],'bāo fú':['枹'],'yì xiè':['枻','栧'],'tuó duò':['柁','馱','駄','驮'],'yí duò lí':['柂'],'nǐ chì':['柅'],'pán bàn':['柈','跘'],'yǎng yàng yāng yīng':['柍'],'fù fū fǔ':['柎'],'bǎi bó bò':['柏'],mǒu:['某'],'sháo shào':['柖'],zhè:['柘','樜','浙','淛','蔗','蟅','這','鷓','鹧','䗪'],'yòu yóu':['柚','櫾'],'guì jǔ':['柜'],'zhà zuò':['柞'],'dié zhì':['柣','眰'],'zhā zǔ zū':['柤'],'chá zhā':['查','査'],'āo ào':['柪','軪'],'bā fú pèi bó biē':['柭'],'duò zuó wù':['柮'],'bì bié':['柲'],'zhù chù':['柷'],'bēi pēi':['柸'],'shì fèi':['柹'],'shān zhà shi cè':['栅'],'lì yuè':['栎','櫟'],'qì qiè':['栔','砌'],'qī xī':['栖','蹊'],'guā kuò':['栝'],'bīng bēn':['栟'],'xiào jiào':['校'],'jiàn zùn':['栫','袸'],'yǒu yù':['栯'],'hé hú':['核'],gēn:['根','跟'],'zhī yì':['栺'],'gé gē':['格'],'héng háng':['桁'],'guàng guāng':['桄'],'yí tí':['桋','荑'],sāng:['桑','桒','槡'],'jú jié':['桔'],'yú móu':['桙'],'ráo náo':['桡','橈'],'guì huì':['桧','檜'],'chén zhèn':['桭'],'tīng yíng':['桯'],'bó po':['桲'],'bèn fàn':['桳'],'fēng fèng':['桻','葑'],'sù yìn':['梀'],'tǐng tìng':['梃'],'xuān juān xié':['梋'],'tú chá':['梌'],'āo yòu':['梎'],kuǎn:['梡','欵','款','歀'],'shāo sào':['梢'],'qín chén cén':['梣'],'lí sì qǐ':['梩'],'chān yán':['梴'],'bīn bīng':['梹','槟','檳'],'táo chóu dào':['梼'],'cōng sōng':['棇'],'gùn hùn':['棍'],'dé zhé':['棏'],'pái bèi pèi':['棑'],'bàng pǒu bèi bēi':['棓'],'dì dài tì':['棣'],sēn:['森','椮','槮','襂'],'rěn shěn':['棯'],'léng lēng líng':['棱'],'fú sù':['棴'],'zōu sǒu':['棷'],zōu:['棸','箃','緅','諏','诹','邹','郰','鄒','鄹','陬','騶','驺','鯫','鲰','黀','齱','齺',],'zhào zhuō':['棹'],'chēn shēn':['棽'],'jiē qiè':['椄'],'yǐ yī':['椅'],'chóu zhòu diāo':['椆'],'qiāng kōng':['椌'],'zhuī chuí':['椎'],'bēi pí':['椑'],mēn:['椚'],'quān juàn quán':['椦'],'duǒ chuán':['椯'],'wěi huī':['椲'],'jiǎ jiā':['椵'],'hán jiān':['椷'],'shèn zhēn':['椹'],'yàn yà':['椻'],'zhā chá':['楂'],'guō kuǎ':['楇'],'jí zhì':['楖'],'kǔ hù':['楛'],'yóu yǒu':['楢'],'sǒng cōng':['楤'],'yuán xuàn':['楥'],'yǎng yàng yīng':['楧'],pián:['楩','胼','腁','賆','蹁','駢','騈','骈','骿','㛹'],'dié yè':['楪'],'dùn shǔn':['楯'],'còu zòu':['楱'],'dì dǐ shì':['楴'],'kǎi jiē':['楷'],'róu ròu':['楺'],'lè yuè':['楽'],'wēn yùn':['榅','鞰'],lǘ:['榈','櫚','氀','膢','藘','閭','闾','驢','驴'],shén:['榊','神','鉮','鰰','𬬹'],'bī pi':['榌'],'zhǎn niǎn zhèn':['榐'],'fú fù bó':['榑'],'jiàn jìn':['榗'],'bǎng bàng':['榜'],'shā xiè':['榝','樧'],nòu:['槈','耨','鎒','鐞'],'qiǎn lián xiàn':['槏'],gàng:['槓','焵','焹','筻','鿍'],gāo:['槔','槹','橰','櫜','睾','篙','糕','羔','臯','韟','餻','高','髙','鷎','鷱','鼛',],'diān zhěn zhēn':['槙'],'kǎn jiàn':['槛'],'xí dié':['槢'],'jī guī':['槣'],'róng yōng':['槦'],'tuán shuàn quán':['槫'],'qì sè':['槭'],'cuī zhǐ':['槯'],'yǒu chǎo':['槱'],'màn wàn':['槾'],'lí chī':['樆'],'léi lěi':['樏','櫑','礌'],'cháo jiǎo chāo':['樔'],'chēng táng':['樘'],'jiū liáo':['樛'],'mó mú':['模'],'niǎo mù':['樢'],'héng hèng':['横','橫'],xuě:['樰','膤','艝','轌','雪','鱈','鳕'],'fá fèi':['橃'],rùn:['橍','润','潤','膶','閏','閠','闰'],'zhǎn jiǎn':['橏'],shùn:['橓','瞚','瞬','舜','蕣','順','顺','鬊'],'tuí dūn':['橔'],'táng chēng':['橖'],'sù qiū':['橚'],'tán diàn':['橝'],'fén fèn fèi':['橨'],'rǎn yān':['橪'],'cū chu':['橻'],'shū qiāo':['橾'],'píng bò':['檘'],'zhái shì tú':['檡'],'biǎo biāo':['檦'],'qiān lián':['檶'],'nǐ mí':['檷'],'jiàn kǎn':['檻'],'nòu ruǎn rú':['檽'],'jī jì':['櫅','禨'],'huǎng guǒ gǔ':['櫎'],'lǜ chū':['櫖'],'miè mèi':['櫗'],ōu:['櫙','欧','歐','殴','毆','瓯','甌','膒','藲','謳','讴','鏂','鴎','鷗','鸥',],'zhù zhuó':['櫡'],'jué jì':['櫭'],'huái guī':['櫰'],'chán zhàn':['欃'],'wéi zuì':['欈'],cáng:['欌','鑶'],'yù yì':['欥'],'chù qù xì':['欪'],'kài ài':['欬'],'yì yīn':['欭'],'xì kài':['欯'],'shuò sòu':['欶'],'ǎi ēi éi ěi èi ê̄ ế ê̌ ề':['欸'],'qī yī':['欹'],'chuā xū':['欻'],'chǐ chuài':['欼'],'kǎn qiàn':['欿'],'kǎn kè':['歁'],'chuǎn chuán':['歂'],'yīn yān':['歅'],'jìn qūn':['歏'],pēn:['歕'],'xū chuā':['歘'],'xī shè':['歙'],'liǎn hān':['歛'],'zhì chí':['歭'],'sè shà':['歰'],sǐ:['死'],'wěn mò':['歾'],piǎo:['殍','皫','瞟','醥','顠'],'qíng jìng':['殑'],'fǒu bó':['殕'],'zhí shi':['殖'],'yè yān yàn':['殗'],'hūn mèi':['殙'],chòu:['殠','臰','遚'],'kuì huì':['殨','溃','潰'],cuàn:['殩','熶','爨','窜','竄','篡','簒'],'yīn yān yǐn':['殷'],'qìng kēng shēng':['殸'],'yáo xiáo xiào':['殽'],'gū gǔ':['毂','蛄'],'guàn wān':['毌'],'dú dài':['毒'],'xún xùn':['毥'],mú:['毪','氁'],'dòu nuò':['毭'],'sāi suī':['毸'],lu:['氇'],sào:['氉','瘙','矂','髞'],'shì zhī':['氏'],'dī dǐ':['氐'],'máng méng':['氓'],'yáng rì':['氜'],shuǐ:['水','氵','氺','閖'],'zhěng chéng zhèng':['氶'],tǔn:['氽'],'fán fàn':['氾'],'guǐ jiǔ':['氿'],'bīn pà pā':['汃'],'zhuó què':['汋'],'dà tài':['汏'],pìn:['汖','牝','聘'],'hàn hán':['汗','馯'],tu:['汢'],'tāng shāng':['汤','湯'],'zhī jì':['汥'],'gàn hán cén':['汵'],'wèn mén':['汶'],'fāng pāng':['汸'],'hǔ huǎng':['汻'],'niú yóu':['汼'],hàng:['沆'],'shěn chén':['沈'],'dùn zhuàn':['沌'],'nǜ niǔ':['沑'],'méi mò':['沒','没'],'tà dá':['沓'],'mì wù':['沕'],'hóng pāng':['沗'],'shā shà':['沙'],'zhuǐ zǐ':['沝'],'ōu òu':['沤','漚'],'jǔ jù':['沮'],'tuō duó':['沰'],'mǐ lì':['沵'],'yí chí':['沶'],'xiè yì':['泄'],'bó pō':['泊'],'mì bì':['泌','秘'],'chù shè':['泏'],'yōu yòu āo':['泑'],'pēng píng':['泙','硑'],'pào pāo':['泡'],'ní nì':['泥','秜'],'yuè sà':['泧'],'jué xuè':['泬','疦'],'lóng shuāng':['泷','瀧'],'luò pō':['泺','濼'],'zé shì':['泽','澤'],'sǎ xǐ':['洒'],'sè qì zì':['洓'],'xǐ xiǎn':['洗'],'kǎo kào':['洘'],'àn yàn è':['洝'],'lěi lèi':['洡'],'qiè jié':['洯'],'qiǎn jiān':['浅'],'jì jǐ':['济','済','濟','纪'],'hǔ xǔ':['浒','滸'],'jùn xùn':['浚','濬'],'yǐng chéng yíng':['浧'],'liàn lì':['浰'],'féng hóng':['浲','溄'],'jiǒng jiōng':['浻'],'suī něi':['浽'],'yǒng chōng':['涌'],'tūn yūn':['涒'],'wō guō':['涡','渦'],hēng:['涥','脝'],'zhǎng zhàng':['涨','漲'],'shòu tāo':['涭'],shuàn:['涮','腨'],'kōng náng':['涳'],'wò wǎn yuān':['涴'],'tuō tuò':['涶'],wō:['涹','猧','窝','窩','莴','萵','蜗','蝸','踒'],'qiè jí':['淁'],'guǒ guàn':['淉'],'lín lìn':['淋','獜','疄'],'tǎng chǎng':['淌'],'nào chuò zhuō':['淖'],'péng píng':['淜'],féi:['淝','肥','腓','蜰'],'pì pèi':['淠'],'niǎn shěn':['淰'],'biāo hǔ':['淲'],'chún zhūn':['淳'],'hùn hún':['混'],qiǎn:['淺','繾','缱','肷','膁','蜸','譴','谴','遣','鑓'],'wèn mín':['渂'],'rè ruò luò':['渃'],'dú dòu':['渎','瀆','读'],'jiàn jiān':['渐','溅','漸','濺'],'miǎn shéng':['渑','澠'],'nuǎn nuán':['渜'],'qiú wù':['渞'],'tíng tīng':['渟'],'dì tí dī':['渧'],'gǎng jiǎng':['港'],'hōng qìng':['渹'],tuān:['湍','煓'],'huì mǐn xū':['湏'],'xǔ xù':['湑'],pén:['湓','瓫','盆','葐'],'mǐn hūn':['湣'],'tuàn nuǎn':['湪'],'qiū jiǎo':['湫','湬'],'yān yīn':['湮'],'bàn pán':['湴'],'zhuāng hún':['湷'],'yàn guì':['溎'],'lián liǎn nián xián xiàn':['溓'],'dá tǎ':['溚','鿎'],'liū liù':['溜','澑','蹓'],lùn:['溣'],mǎ:['溤','犸','獁','玛','瑪','码','碼','遤','鎷','馬','马','鰢','鷌',],'zhēn qín':['溱'],'nì niào':['溺'],'chù xù':['滀','畜'],'wěng wēng':['滃'],'hào xuè':['滈'],'qì xì xiē':['滊'],'xíng yíng':['滎'],'zé hào':['滜'],'piāo piào piǎo':['漂'],'cóng sǒng':['漎'],'féng péng':['漨'],'luò tà':['漯'],'pēng bēn':['漰'],'chóng shuāng':['漴'],'huǒ kuò huò':['漷'],'liáo liú':['漻'],'cuǐ cuī':['漼'],'cóng zǒng':['潀'],'cóng zōng':['潈'],'pì piē':['潎'],'dàng xiàng':['潒'],'huáng guāng':['潢'],'liáo lào lǎo':['潦'],'cōng zòng':['潨'],'zhí zhì':['潪'],'tān shàn':['潬'],'tú zhā':['潳'],'sàn sǎ':['潵'],hēi:['潶','黑','黒','𬭶'],'chéng dèng':['澄','瀓'],'cūn cún':['澊'],'péng pēng':['澎'],'hòng gǒng':['澒','銾'],'wàn màn':['澫'],'kuài huì':['澮'],'guō wō':['濄'],'pēn fén':['濆'],'jí shà':['濈'],'huì huò':['濊'],'dǐng tìng':['濎'],'mǐ nǐ':['濔'],'bì pì':['濞'],'cuì zuǐ':['濢'],'hù huò':['濩'],'ǎi kài kè':['濭'],'wěi duì':['濻','瀢'],'zàn cuán':['濽','灒'],'yǎng yàng':['瀁'],'wǎng wāng':['瀇'],'mò miè':['瀎','眜'],suǐ:['瀡','膸','髓'],'huái wāi':['瀤'],'zùn jiàn':['瀳'],'yīng yǐng yìng':['瀴'],'ráng ràng':['瀼'],shuàng:['灀'],'zhuó jiào zé':['灂'],sǎ:['灑','訯','靸'],'luán luàn':['灓'],'dǎng tǎng':['灙'],'xún quán quàn':['灥'],'huǒ biāo':['灬'],'zhà yù':['灹'],'fén bèn':['炃'],'jiǒng guì':['炅'],'pàng fēng':['炐'],quē:['炔','缺','缼','蒛'],biān:['炞','煸','甂','砭','笾','箯','籩','編','编','蝙','邉','邊','鍽','鞭','鯾','鯿','鳊',],'zhāo zhào':['炤'],'zhuō chù':['炪'],'pào páo bāo':['炮'],'páo fǒu':['炰'],'shǎn qián shān':['炶'],'zhà zhá':['炸'],'jiǎo yào':['烄'],quǎn:['烇','犬','犭','畎','綣','绻','虇'],'yàng yáng':['烊'],'lào luò':['烙'],'huí huǐ':['烠'],rè:['热','熱'],'fú páo':['烰'],'xiè chè':['烲','焎'],'yàn shān':['烻'],'hūn xūn':['焄'],kào:['焅','犒','銬','铐','靠','鮳','鯌','鲓','㸆'],'juān yè':['焆'],'jùn qū':['焌'],'tāo dào':['焘'],'chǎo jù':['焣'],'wò ài':['焥'],'zǒng cōng':['焧'],'xī yì':['焬'],'xìn xīn':['焮'],'chāo zhuō':['焯'],'xiǒng yīng':['焸','焽'],kuǐ:['煃','跬','蹞','頍','𫠆'],'huī yùn xūn':['煇'],'jiǎo qiāo':['煍'],'qián shǎn shān':['煔'],'xī yí':['煕'],'shà shā':['煞'],'yè zhá':['煠'],'yáng yàng':['煬'],'ēn yūn':['煾'],'yūn yǔn':['熅'],'hè xiāo':['熇'],xióng:['熊','熋','雄'],'xūn xùn':['熏','爋'],gòng:['熕','貢','贡'],liū:['熘'],'cōng zǒng':['熜'],'lù āo':['熝'],'shú shóu':['熟'],'fēng péng':['熢'],'cuǐ suī':['熣'],tēng:['熥','膯','鼟'],'yùn yù':['熨'],'áo āo':['熬'],'hàn rǎn':['熯'],'ōu ǒu':['熰'],'huáng huǎng':['熿'],'chǎn dǎn chàn':['燀'],'jiāo zhuó qiáo jué':['燋'],'yàn yān':['燕'],'tài liè':['燤'],āo:['爊'],'yàn xún':['爓'],'jué jiào':['爝','覐','覚','覺','觉'],'lǎn làn':['爦'],'zhuǎ zhǎo':['爪'],'zhǎo zhuǎ':['爫'],'fù fǔ':['父'],diē:['爹','褺','跌'],zāng:['牂','羘','臧','賍','賘','贓','贜','赃','髒'],'piàn piān':['片'],'biān miàn':['牑'],bǎng:['牓','綁','绑'],'yǒu yōng':['牗'],'chēng chèng':['牚','竀'],niú:['牛','牜'],'jiū lè':['牞'],'mù móu':['牟'],māng:['牤'],'gē qiú':['牫'],'yòu chōu':['牰'],'tè zhí':['犆'],bēn:['犇','錛','锛'],'jiān qián':['犍','玪'],má:['犘','痲','蔴','蟇','麻'],'máo lí':['犛'],'bá quǎn':['犮'],'zhuó bào':['犳'],'àn hān':['犴'],'kàng gǎng':['犺'],'pèi fèi':['犻'],'fān huān':['犿'],kuáng:['狂','狅','誑','诳','軖','軠','鵟','𫛭'],'yí quán chí':['狋'],'xīng shēng':['狌'],'tuó yí':['狏'],kǔ:['狜','苦'],'huán huān':['狟'],'hé mò':['狢'],'tà shì':['狧'],'máng dòu':['狵'],'xī shǐ':['狶'],suān:['狻','痠','酸'],'bài pí':['猈'],'jiān yàn':['猏','豣'],'yī yǐ':['猗'],'yá wèi':['猚'],cāi:['猜'],'māo máo':['猫','貓'],'chuàn chuān':['猭'],'tuān tuàn':['猯','貒'],'yà jiá qiè':['猰'],'hè xiē gé hài':['猲'],'biān piàn':['猵','獱'],'bó pò':['猼'],'háo gāo':['獋'],'fén fèn':['獖'],'yào xiāo':['獟'],'shuò xī':['獡'],'gé liè xiē':['獦'],'nòu rú':['獳'],'náo nǎo yōu':['獶'],ráng:['獽','瓤','禳','穣','穰','蘘','躟','鬤'],'náo yōu':['獿'],'lǜ shuài':['率'],'wáng wàng':['王'],'yáng chàng':['玚'],'mín wén':['玟'],'bīn fēn':['玢'],'mén yǔn':['玧'],'qiāng cāng':['玱','瑲','篬'],'án gān':['玵'],'xuán xián':['玹'],'cī cǐ':['玼','跐'],'yí tāi':['珆'],'zǔ jù':['珇'],fà:['珐','琺','蕟','髪','髮'],'yín kèn':['珢'],'huī hún':['珲'],'xuán qióng':['琁'],'fú fū':['琈'],'bǐng pín':['琕'],'cuì sè':['琗'],'yù wéi':['琟'],'tiǎn tiàn':['琠'],'zhuó zuó':['琢'],'běng pěi':['琣'],guǎn:['琯','璭','痯','筦','管','舘','輨','錧','館','馆','鳤'],'hún huī':['琿'],'xié jiē':['瑎'],'chàng dàng yáng':['瑒'],'tiàn zhèn':['瑱'],'bīn pián':['瑸','璸'],'tú shū':['瑹'],cuǐ:['璀','皠','趡'],'zǎo suǒ':['璅'],'jué qióng':['璚'],'lú fū':['璷'],'jì zī':['璾'],suí:['瓍','綏','绥','遀','随','隨','髄'],'mí xǐ':['瓕'],'qióng wěi wèi':['瓗'],'huán yè yà':['瓛'],'bó páo':['瓟'],'zhí hú':['瓡'],piáo:['瓢','闝'],'wǎ wà':['瓦'],'xiáng hóng':['瓨'],wèng:['瓮','甕','罋','蕹','齆'],'shèn shén':['甚'],ruí:['甤','緌','蕤'],yòng:['用','砽','苚','蒏','醟','㶲'],shuǎi:['甩'],béng:['甭','甮'],'yóu zhá':['甴'],'diàn tián shèng':['甸'],'tǐng dīng':['町','甼'],'zāi zī':['甾'],'bì qí':['畁'],'dá fú':['畗'],'cè jì':['畟'],'zāi zī tián':['畠'],'zhì chóu shì':['畤'],'fān pān':['畨','番'],'shē yú':['畬'],'dāng dàng dǎng':['當'],'jiāng qiáng':['疆'],'pǐ yǎ shū':['疋'],'jié qiè':['疌'],'yí nǐ':['疑'],nè:['疒','眲','訥','讷'],'gē yì':['疙'],'nüè yào':['疟','瘧'],'lì lài':['疠','癘'],'yǎ xiā':['疨'],xuē:['疶','蒆','薛','辥','辪','靴','鞾'],'dǎn da':['疸'],'fá biǎn':['疺'],'fèi féi':['疿','痱'],'shān diàn':['痁'],'téng chóng':['痋'],'tōng tóng':['痌'],'wěi yòu yù':['痏'],'tān shǐ':['痑'],'pū pù':['痡','鋪'],'bēng péng':['痭'],'má lìn':['痳'],'tiǎn diàn':['痶'],'ān yè è':['痷'],'kē ē':['痾'],'zhì chì':['瘈'],'jiǎ xiá xiā':['瘕'],'lěi huì':['瘣'],'chài cuó':['瘥'],'diān chēn':['瘨'],'da dá':['瘩'],'biě biē':['瘪'],qué:['瘸'],'dàn dān':['癉'],'guì wēi':['癐'],'nòng nóng':['癑'],'biē biě':['癟'],'bō bǒ':['癷'],bái:['白'],'jí bī':['皀'],'de dì dí dī':['的'],'pā bà':['皅'],'gāo háo':['皋'],'gāo yáo':['皐'],'lì luò bō':['皪'],'zhā cǔ':['皻'],'zhāo zhǎn dǎn':['皽'],'jiān jiàn':['监','監','鋻','间','鞬'],'gài gě hé':['盖'],'máng wàng':['盳'],yuǎn:['盶','逺','遠'],'tián xián':['盷'],'xiāng xiàng':['相'],dǔn:['盹','趸','躉'],'xì pǎn':['盻'],'shěng xǐng':['省'],'yún hùn':['眃'],'miǎn miàn':['眄'],'kàn kān':['看'],'yìng yāng yǎng':['眏'],'yǎo āo ǎo':['眑'],'jū xū kōu':['眗'],'yí chì':['眙'],'dié tì':['眣'],'bǐng fǎng':['眪'],'pàng pán':['眫'],'mī mí':['眯','瞇'],'xuàn shùn xún':['眴'],tiào:['眺','粜','糶','覜','趒'],'zhe zhuó zháo zhāo':['着'],'qiáo shào xiāo':['睄'],'cuó zhuài':['睉'],gùn:['睔','謴'],'suì zuì':['睟'],'pì bì':['睥','稫','辟'],'yì zé gāo':['睪'],'xǐng xìng':['睲'],'guì wèi kuì':['瞆'],'kòu jì':['瞉'],'qióng huán':['瞏'],'mán mén':['瞒','瞞'],'diāo dōu':['瞗'],'lou lóu lǘ':['瞜'],'shùn rún':['瞤'],'liào liǎo':['瞭','钌'],'jiàn xián':['瞯'],'wǔ mí':['瞴'],'guì kuì':['瞶'],'nǐng chēng':['矃'],'huò yuè':['矆'],'mēng méng':['矇'],'kuàng guō':['矌'],'guàn quán':['矔'],'mǎn mán':['矕'],'jīn guān qín':['矜'],'jīn qín guān':['矝'],'yù xù jué':['矞'],'jiǎo jiáo':['矫','矯'],duǎn:['短'],'shí dàn':['石'],'gāng qiāng kòng':['矼'],'huā xū':['砉'],'pīn bīn fēn':['砏'],'yán yàn':['研','硏'],'luǒ kē':['砢'],'fú fèi':['砩','笰'],'zhǔ zhù':['砫'],'lá lì lā':['砬'],'kuāng guāng':['硄'],'gè luò':['硌'],'shuò shí':['硕','碩'],'wèi wéi ái':['硙'],'què kè kù':['硞'],'mǎng bàng':['硥'],'luò lòng':['硦'],'yǒng tóng':['硧'],nüè:['硸','虐'],'kēng kěng':['硻'],'yān yǎn':['硽'],'zhuì chuí duǒ':['硾'],'kōng kòng':['硿'],'zòng cóng':['碂'],'jiān zhàn':['碊'],'lù liù':['碌','陆'],'què xī':['碏'],'lún lǔn lùn':['碖'],'náo gāng':['碙'],'jié yà':['碣'],'wèi wěi':['碨'],'tí dī':['碮'],'chá chā':['碴'],'qiāo què':['碻'],'sù xiè':['碿'],'liú liù':['磂','遛','鎦','馏'],'sī tí':['磃'],'bàng páng':['磅'],'huá kě gū':['磆'],'wěi kuǐ':['磈'],'xiá qià yà':['磍'],'lián qiān':['磏'],'wèi ái gài':['磑'],'lá lā':['磖'],'áo qiāo':['磝'],'pēng pèng':['磞','閛'],'yīn yǐn':['磤'],'lěi léi':['磥'],'mó mò':['磨'],'qì zhú':['磩'],'láo luò':['磱'],'pán bō':['磻'],'jí shé':['磼'],'hé qiāo qiào':['礉'],'kè huò':['礊'],'què hú':['礐'],'è qì':['礘'],cǎ:['礤','礸'],'xián xín':['礥'],'léi lěi lèi':['礧'],'yán yǎn':['礹'],'qí zhǐ':['祇','蚔'],'bēng fāng':['祊'],'bì mì':['祕'],suàn:['祘','笇','筭','算','蒜'],'piào piāo':['票'],'jì zhài':['祭'],'shuì lèi':['祱'],'jìn jīn':['禁'],'chán shàn':['禅'],'yáng shāng':['禓'],'zhī zhǐ tí':['禔'],'shàn chán':['禪'],'yú yù ǒu':['禺'],'zǐ zì':['秄'],'chá ná':['秅'],'zhǒng zhòng chóng':['种'],'hào mào':['秏'],'kù kū':['秙'],zū:['租','葅'],chèng:['秤','穪'],'huó kuò':['秮','秳'],'chēng chèn chèng':['称','稱'],'shì zhì':['秲','銴'],'fù pū':['秿'],'xùn zè':['稄'],'tú shǔ':['稌'],'zhùn zhǔn':['稕'],'jī qí':['稘','綨','觭'],'léng líng':['稜'],'zuì zú sū':['稡'],'xì qiè':['稧','郄'],'zhǒng zhòng':['種'],'zōng zǒng':['稯'],'xián jiān liàn':['稴'],'zī jiū':['稵'],'jī qǐ':['稽'],ròng:['穃'],'shān cǎn cēn':['穇'],'mén méi':['穈'],'jǐ jì':['穖'],'xiāo rào':['穘'],'zhuō bó':['穛'],'tóng zhǒng zhòng':['穜'],zuō:['穝'],'biāo pāo':['穮','藨'],'zhuō jué':['穱'],'cuán zàn':['穳'],'kōng kòng kǒng':['空'],'yū yǔ':['穻'],zhǎi:['窄','鉙'],báo:['窇','雹'],'kū zhú':['窋'],'jiào liáo liù':['窌'],'wā guī':['窐'],'tiǎo yáo':['窕'],'xūn yìn':['窨'],'yà yē':['窫'],'tián diān yǎn':['窴'],'chāo kē':['窼'],'kuǎn cuàn':['窽','窾'],'chù qì':['竐'],'qǔ kǒu':['竘'],'jìng zhěn':['竧'],'kǎn kàn':['竷'],'zhú dǔ':['竺'],'lè jīn':['竻'],'zhuì ruì':['笍'],'háng hàng':['笐'],'cén jìn hán':['笒'],'dā xiá nà':['笚'],'zé zuó':['笮'],'lóng lǒng':['笼','篭','籠','躘','龓'],'zhù zhú':['筑','築'],'dá dā':['答','荅'],shāi:['筛','篩','簁','籭'],'yún jūn':['筠'],'láng làng':['筤','郎','阆'],'zhì zhǐ':['筫'],o:['筽'],'póu bù fú pú':['箁'],'pái bēi':['箄'],gè:['箇','虼','鉻','铬'],'tái chí':['箈'],'guǎi dài':['箉'],'zhào dào':['箌'],'jīng qìng':['箐'],'lín lǐn':['箖'],'jùn qūn':['箘'],'shī yí':['箷','釶'],'yuē yào chuò':['箹'],'xiāo shuò qiào':['箾'],'gōng gǎn lǒng':['篢'],'páng péng':['篣'],'zhuó huò':['篧'],'jiǎn jiān':['篯'],'dí zhú':['篴'],'zān cēn cǎn':['篸'],'zhuàn suǎn zuàn':['篹'],'piǎo biāo':['篻'],'guó guì':['簂'],'cè jí':['簎'],'mì miè':['簚'],'shāi sī':['簛'],'sǔn zhuàn':['簨'],'gàn gǎn':['簳'],'bò bǒ':['簸'],'bó bù':['簿'],shi:['籂'],'zhēn jiān':['籈'],'zhuàn zuǎn':['籑'],'fān pān biān':['籓'],'sǒu shǔ':['籔'],zuǎn:['籫','繤','纂','纉','纘','缵'],nǚ:['籹','釹','钕'],'shā chǎo':['粆'],'kāng jīng':['粇'],fěn:['粉','黺'],cū:['粗','觕','麁','麄','麤'],'nián zhān':['粘'],'cè sè':['粣'],'zhōu yù':['粥'],'shēn sǎn':['糁'],'biān biǎn':['糄','萹'],miàn:['糆','面','靣','麪','麫','麵','麺'],'hú hū hù':['糊'],'gǔ gòu':['糓'],'mí méi':['糜'],'sǎn shēn':['糝','糣'],zāo:['糟','蹧','遭','醩'],'mì sī':['糸'],'jiū jiǔ':['糺'],'xì jì':['系','繫'],'zhēng zhěng':['糽'],'chà chǎ':['紁','衩'],'yuē yāo':['約','约'],'hóng gōng':['紅','红'],'hé gē':['紇','纥'],'wén wèn':['紋','纹'],fóu:['紑'],'jì jié jiè':['紒'],'pī pí bǐ':['紕','纰'],'jīn jìn':['紟'],'zhā zā':['紥','紮'],hā:['紦'],'fū fù':['紨'],'chōu chóu':['紬'],'lèi léi lěi':['累'],'bō bì':['紴'],'tiǎn zhěn':['紾'],'jiōng jiǒng':['絅'],'jié jiē':['結','结','节'],'guà kuā':['絓'],'bǎi mò':['絔'],'gēng huán':['絙'],'jié xié':['絜'],'quán shuān':['絟'],'gǎi ǎi':['絠'],'luò lào':['絡','络'],'bīng bēng pēng':['絣'],'gěi jǐ':['給','给'],'tóng tōng dòng':['絧'],'tiào diào dào':['絩'],'lěi lèi léi':['絫'],'gāi hài':['絯'],'chī zhǐ':['絺'],'wèn miǎn mán wàn':['絻'],'huán huàn wàn':['綄'],'qīn xiān':['綅'],'tì tí':['綈'],'yán xiàn':['綖'],'zōng zèng zòng':['綜'],'chēn lín':['綝'],'zhǔn zhùn':['綧'],'qiàn qīng zhēng':['綪'],'qìng qǐ':['綮'],'lún guān':['綸','纶'],'chuò chāo':['綽','绰'],'tián tǎn chān':['緂'],'lǜ lù':['緑','绿'],'ruǎn ruàn':['緛'],'jí qī':['緝'],'zhòng chóng':['緟','重'],'miáo máo':['緢'],'xiè yè':['緤'],huǎn:['緩','缓','㬊'],'gēng gèng':['緪','縆'],'tōu xū shū':['緰'],'zōng zòng':['緵','繌'],'yùn gǔn':['緷'],'guā wō':['緺'],'yùn yūn wēn':['緼','縕'],'bāng bàng':['縍'],'gǔ hú':['縎','鶻'],'cī cuò suǒ':['縒'],'cuī shuāi':['縗'],'róng rǒng ròng':['縙'],'zài zēng':['縡'],cài:['縩','菜','蔡'],'féng fèng':['縫'],'suō sù':['縮','缩'],'yǎn yǐn':['縯','酓'],'zòng zǒng':['縱','纵'],'zhuàn juàn':['縳'],'mò mù':['縸','莫'],'piǎo piāo':['縹','缥'],'fán pó':['繁'],'bēng bèng':['繃'],'móu miù miào liǎo':['繆'],'yáo yóu zhòu':['繇'],'zēng zèng':['繒','缯'],'jú jué':['繘'],'chuō chuò':['繛'],'zūn zǔn':['繜'],rào:['繞','绕','遶'],'chǎn chán':['繟'],'huì huí':['繢','缋','藱'],'qiāo sāo zǎo':['繰'],'jiǎo zhuó':['繳','缴'],'dàn tán chán':['繵'],nǒng:['繷'],'pú fú':['纀'],'yào lì':['纅'],'rǎng xiāng':['纕'],'lí sǎ xǐ lǐ':['纚'],'xiān qiàn':['纤'],'jīng jìng':['经'],'tí tì':['绨'],'bēng běng bèng':['绷'],'zōng zèng':['综'],'jī qī':['缉'],'wēn yùn yūn':['缊'],'fèng féng':['缝'],'shuāi cuī suī':['缞'],'miù móu liáo miào mù':['缪'],'qiāo sāo':['缲'],fǒu:['缶','缹','缻','雬','鴀'],'bà ba pí':['罢','罷'],'guà guǎi':['罫'],'yáng xiáng':['羊','羏'],'měi gāo':['羙'],'yì xī':['羛'],'qiǎng qiān':['羟'],'qiāng kòng':['羫'],'qián xián yán':['羬'],nóu:['羺'],'hóng gòng':['羾'],'pī bì pō':['翍'],'qú yù':['翑'],ké:['翗'],'qiào qiáo':['翘'],'zhái dí':['翟'],'dào zhōu':['翢'],'hóu qú':['翵'],shuǎ:['耍'],'ruǎn nuò':['耎'],'ér nài':['耏'],'zhuān duān':['耑'],'pá bà':['耙'],'chí sì':['耛'],'qù chú':['耝'],'lún lǔn':['耣'],'jí jiè':['耤'],'tāng tǎng':['耥'],pǎng:['耪','覫'],'zhá zé':['耫'],'yē yé':['耶'],'yún yíng':['耺'],'wà tuǐ zhuó':['聉'],'ér nǜ':['聏'],'tiē zhé':['聑'],'dǐ zhì':['聜'],qié:['聺'],'nǐ jiàn':['聻'],'lèi lē':['肋'],cào:['肏','襙','鄵','鼜'],'bó dí':['肑'],'xiào xiāo':['肖'],'dù dǔ':['肚'],chāi:['肞','釵','钗'],'hán qín hàn':['肣'],'pàng pán pàn':['肨','胖'],'zhūn chún':['肫'],āng:['肮','骯'],'yù yō':['育'],'pí bǐ bì':['肶'],'fèi bì':['胇'],'bèi bēi':['背'],'fèi zǐ':['胏'],'píng pēng':['胓','苹'],'fū fú zhǒu':['胕'],'shèng shēng':['胜'],kuà:['胯','跨','骻'],'gǎi hǎi':['胲'],'gē gé gā':['胳'],'néng nài':['能'],'guī kuì':['胿'],'mài mò':['脉'],'zāng zàng':['脏'],'jiǎo jué':['脚','角'],cuǒ:['脞'],'de te':['脦'],'zuī juān':['脧'],něi:['脮','腇','餒','馁','鮾','鯘'],'pú fǔ':['脯'],niào:['脲'],shuí:['脽'],guò:['腂','過','鐹'],'là xī':['腊'],'yān ā':['腌'],'gāo gào':['膏'],'lù biāo':['膔'],chuái:['膗'],'zhuān chuán chún zhuǎn':['膞'],chuài:['膪','踹'],'fán pán':['膰'],'wǔ hū':['膴'],'shān dàn':['膻'],tún:['臀','臋','蛌','豘','豚','軘','霕','飩','饨','魨','鲀','黗'],'bì bei':['臂'],'là gé':['臈'],'sào sāo':['臊'],nào:['臑','閙','闹','鬧'],'ní luán':['臡'],'qiān xián':['臤'],'guàng jiǒng':['臦'],'guǎng jiǒng':['臩'],'chòu xiù':['臭'],'mián biān':['臱'],'dié zhí':['臷'],'zhī jìn':['臸'],'shè shě':['舍'],pù:['舖','舗'],'bān bō pán':['般'],kuā:['舿'],'gèn gěn':['艮'],'sè shǎi':['色'],'fú bó':['艴'],'jiāo qiú':['艽'],'chāi chā':['芆'],'sháo què':['芍'],'hù xià':['芐'],'zì zǐ':['芓'],'huì hū':['芔'],'tún chūn':['芚'],'jiè gài':['芥'],'xù zhù':['芧'],'yuán yán':['芫'],'xīn xìn':['芯'],'lún huā':['芲'],'wù hū':['芴'],'gōu gǒu':['芶'],'mào máo':['芼'],'fèi fú':['芾'],'chán yín':['苂'],qiē:['苆'],'sū sù':['苏'],'tiáo sháo':['苕'],'lì jī':['苙'],'kē hē':['苛'],'jù qǔ':['苣'],'ruò rě':['若'],'zhù níng':['苧'],'pā bó':['苩'],xiú:['苬'],'zhǎ zuó':['苲'],'jū chá':['苴'],nié:['苶'],'shēng ruí':['苼'],'qié jiā':['茄'],'zǐ cí':['茈'],'qiàn xī':['茜'],chǎi:['茝'],'fá pèi':['茷'],ráo:['荛','蕘','襓','饒','饶'],'yíng xíng':['荥'],'qián xún':['荨','蕁'],'yìn yīn':['荫'],'hé hè':['荷'],'shā suō':['莎'],'péng fēng':['莑'],'shēn xīn':['莘'],'wǎn guān guǎn':['莞'],'yóu sù':['莤'],'shāo xiāo':['莦','蛸'],'làng liáng':['莨'],'piǎo fú':['莩'],'wèn wǎn miǎn':['莬'],'shì shí':['莳','蒔'],'tù tú':['莵'],'xiān liǎn':['莶','薟'],'wǎn yù':['菀'],'zōu chù':['菆'],'lù lǜ':['菉'],'jūn jùn':['菌'],'niè rěn':['菍'],'zī zì zāi':['菑'],'tú tù':['菟'],'jiē shà':['菨'],'qiáo zhǎo':['菬'],'tái zhī chí':['菭'],'fēi fěi':['菲','蜚'],'qín qīn jīn':['菳'],'zū jù':['菹','蒩'],'lǐn má':['菻'],'tián tiàn':['菾'],tiē:['萜','貼','贴'],'luò là lào luō':['落'],'zhù zhuó zhe':['著'],'shèn rèn':['葚'],'gě gé':['葛'],'jùn suǒ':['葰'],'kuì kuài':['蒉'],'rú ná':['蒘'],'méng mēng měng':['蒙'],'yuán huán':['蒝'],'xú shú':['蒣'],'xí xì':['蒵'],'mì míng':['蓂'],'sōu sǒu':['蓃'],'gài gě hé hài':['蓋'],'yǎo zhuó':['蓔'],'diào tiáo dí':['蓧'],'xū qiū fū':['蓲'],'zí jú':['蓻'],'liǎo lù':['蓼'],xu:['蓿'],'hàn hǎn':['蔊'],'màn wàn mán':['蔓'],'pó bò':['蔢'],'fān fán bō':['蕃'],'hóng hòng':['蕻'],'yù ào':['薁','隩'],'xí xiào':['薂'],'báo bó bò':['薄'],'cí zī':['薋'],'wàn luàn':['薍'],'kǎo hāo':['薧'],'yuǎn wěi':['薳'],'zhòu chóu':['薵'],'wō mái':['薶'],'xiāo hào':['藃'],'yù xù xū':['藇'],'jiè jí':['藉'],'diào zhuó':['藋'],'cáng zàng':['藏'],lǎ:['藞'],'chú zhū':['藸'],'pín píng':['蘋'],'gān hán':['虷'],'hóng jiàng':['虹'],'huī huǐ':['虺'],'xiā há':['虾'],'mǎ mà mā':['蚂'],'fāng bàng':['蚄'],'bàng bèng':['蚌'],'jué quē':['蚗'],'qín qián':['蚙'],'gōng zhōng':['蚣'],'fǔ fù':['蚥'],'dài dé':['蚮'],'gǒu qú xù':['蚼'],'bǒ pí':['蚾'],'shé yí':['蛇'],tiě:['蛈','鉄','銕','鐡','鐵','铁','驖'],'gé luò':['蛒'],'máng bàng':['蛖'],'yì xǔ':['蛡'],'há gé':['蛤'],'qiè ní':['蛪'],'é yǐ':['蛾'],'zhē zhé':['蜇'],'là zhà':['蜡'],suò:['蜶','逤'],'yóu qiú':['蝤'],'xiā hā':['蝦'],'xī qī':['螇'],'bī pí':['螕'],'nài něng':['螚'],'hé xiá':['螛'],'guì huǐ':['螝'],'mǎ mā mà':['螞'],'shì zhē':['螫'],'zhì dié':['螲'],'jiàn chán':['螹'],'ma má mò':['蟆'],'mǎng měng':['蟒'],'biē bié':['蟞'],'bēn fèi':['蟦'],'láo liáo':['蟧'],'yín xún':['蟫'],'lí lǐ':['蠡'],'xuè xiě':['血'],'xíng háng hàng héng':['行'],'shuāi cuī':['衰'],'tuó tuō':['袉'],'lǐng líng':['袊'],'bào páo pào':['袌'],'jù jiē':['袓'],'hè kè':['袔'],'yí yì':['袘','貤'],'nà jué':['袦'],'bèi pī':['被'],'chǐ nuǒ':['袲'],'chǐ qǐ duǒ nuǒ':['袳'],'jiá qiā jié':['袷'],'bó mò':['袹'],'guī guà':['袿'],'liè liě':['裂'],'chéng chěng':['裎'],'jiē gé':['裓'],'dāo chóu':['裯'],'shang cháng':['裳'],'yuān gǔn':['裷'],'yǎn ān':['裺'],'tì xī':['裼'],'fù fú':['褔'],'chǔ zhǔ':['褚'],'tuì tùn':['褪'],lǎi:['襰'],'yào yāo':['要'],'qín tán':['覃'],'jiàn xiàn':['見','见'],piǎn:['覑','諞','谝','貵','𡎚'],'piē miè':['覕'],'yíng yǐng':['覮'],'qù qū':['覰','覷','觑'],'jiàn biǎn':['覵'],'luó luǎn':['覶'],'zī zuǐ':['觜'],'huà xiè':['觟'],'jiě jiè xiè':['解','觧'],'xué hù':['觷'],'lì lù':['觻'],tǎo:['討','讨'],zhùn:['訰'],'zī zǐ':['訾'],'yí dài':['詒','诒'],xiòng:['詗','诇'],'diào tiǎo':['誂'],'yí chǐ chì':['誃'],'lǎng làng':['誏'],'ēi éi ěi èi xī':['誒','诶'],shuà:['誜'],'yǔ yù':['語','语','雨'],'shuō shuì yuè':['說','说'],'shuí shéi':['誰','谁'],'qū juè':['誳'],'chī lài':['誺'],'nì ná':['誽'],'diào tiáo':['調'],'pǐ bēi':['諀'],'jì jī':['諅'],'zé zuò zhǎ cuò':['諎'],'chù jí':['諔'],'háo xià':['諕'],'lùn lún':['論','论'],'shì dì':['諟'],'huà guā':['諣'],'xǐ shāi āi':['諰'],'nán nàn':['諵','難'],miù:['謬','谬'],zèn:['譖','谮'],'shí zhì':['識','识'],'juàn xuān':['讂'],'yí tuī':['讉'],zhán:['讝'],'xǔ hǔ':['许'],'xiáng yáng':['详'],'tiáo diào zhōu':['调'],'chén shèn':['谌'],'mí mèi':['谜'],'màn mán':['谩'],'gǔ yù':['谷'],'huō huò huá':['豁'],'zhì zhài':['豸'],'huān huán':['貆'],'kěn kūn':['貇'],'mò hé':['貈'],'mò hé háo':['貉'],'jù lóu':['貗'],'zé zhài':['責','责'],'dài tè':['貸'],'bì bēn':['賁'],'jiǎ gǔ jià':['賈'],'xiōng mín':['賯'],càng:['賶'],'zhuàn zuàn':['賺','赚'],'wàn zhuàn':['贃'],'gàn gòng zhuàng':['贛'],'yuán yùn':['贠'],'bēn bì':['贲'],'jiǎ gǔ':['贾'],zǒu:['走','赱','鯐'],'dié tú':['趃'],'jū qiè':['趄'],'qū cù':['趋','趨'],'jí jié':['趌'],'guā huó':['趏'],'què qì jí':['趞'],'tàng tāng':['趟'],'chuō zhuó':['趠'],'qù cù':['趣'],'yuè tì':['趯'],'bō bào':['趵'],'kuà wù':['趶'],'guì jué':['趹'],'fāng fàng páng':['趽'],'páo bà':['跁'],'qí qǐ':['跂'],'jiàn chén':['跈'],'pǎo páo':['跑'],'diǎn diē tiē':['跕'],'jū jù qiè':['跙'],bǒ:['跛'],'luò lì':['跞'],'dài duò duō chí':['跢'],zhuǎi:['跩'],'bèng pián':['跰'],'tiào táo':['跳'],'shū chōu':['跾'],'liàng liáng':['踉'],'tà tā':['踏'],chǎ:['蹅','鑔','镲'],'dí zhí':['蹢'],'dēng dèng':['蹬','鐙','镫'],cèng:['蹭'],'dūn cún':['蹲'],'juě jué':['蹶'],liāo:['蹽'],'xiè sǎ':['躠'],tǐ:['躰','軆','骵'],'yà zhá gá':['轧','軋'],'xìn xiàn':['軐'],'fàn guǐ':['軓'],'zhuàn zhuǎn':['転'],'zhóu zhòu':['軸','轴'],bú:['轐','醭','鳪'],'zhuǎn zhuàn zhuǎi':['转'],'zǎi zài':['载'],'niǎn zhǎn':['辗'],'biān bian':['边'],'dào biān':['辺'],'yǐ yí':['迆','迤','迱'],'guò guo guō':['过'],'wàng kuāng':['迋'],'hái huán':['还'],'zhè zhèi':['这'],'yuǎn yuàn':['远'],'zhì lì':['迣'],'zhù wǎng':['迬'],'zhuī duī':['追'],'shì kuò':['适'],tòu:['透'],'tōng tòng':['通'],guàng:['逛'],'dǎi dài':['逮'],'suì suí':['遂'],'tí dì':['遆'],'yí wèi':['遗'],'shì dí zhé':['適'],cà:['遪'],'huán hái':['還'],'lí chí':['邌'],'kàng háng':['邟'],'nà nèi nā':['那'],'xié yá yé yú xú':['邪'],'gāi hái':['郂'],'huán xún':['郇'],'chī xī':['郗'],hǎo:['郝'],'lì zhí':['郦'],'xiáo ǎo':['郩'],'dōu dū':['都'],liǎo:['曢','鄝','镽'],'zàn cuán cuó':['酂','酇'],'dīng dǐng':['酊'],'cù zuò':['酢'],'fā pō':['酦'],'shāi shī':['酾'],niàng:['酿','醸'],'qiú chōu':['醔'],'pō fā':['醗','醱'],'chǎn chěn':['醦'],'yàn liǎn xiān':['醶'],'niàng niáng':['釀'],'lǐ li':['里'],'lí xǐ xī':['釐'],'liǎo liào':['釕'],'dīng dìng':['釘','钉'],'qiǎo jiǎo':['釥'],'yú huá':['釪'],'huá wū':['釫'],'rì rèn jiàn':['釰','釼'],'dì dài':['釱'],'pī zhāo':['釽'],'yá yé':['釾'],'bǎ pá':['鈀','钯'],'tā tuó':['鉈','铊'],běi:['鉳'],'bǐng píng':['鉼'],'hā kē':['鉿','铪'],chòng:['銃','铳'],'xiǎng jiōng':['銄'],'yù sì':['銉'],'xù huì':['銊'],'rén rěn':['銋'],'shàn shuò':['銏'],'chì lì':['銐'],'xiǎn xǐ':['銑','铣'],'hóu xiàng':['銗'],'diào tiáo yáo':['銚'],'xiān kuò tiǎn guā':['銛','銽','铦'],'zhé niè':['銸'],'zhōng yōng':['銿'],'tōu tù dòu':['鋀'],'méi méng':['鋂'],'wàn jiǎn':['鋄','鎫'],'tǐng dìng':['鋌','铤'],'juān jiān cuān':['鋑'],'sī tuó':['鋖'],'juān xuān juàn':['鋗'],'wú huá wū':['鋘'],'zhuó chuò':['鋜'],'xíng xìng jīng':['鋞'],'jū jú':['鋦','锔'],'zuì niè':['鋷'],'yuān yuǎn wǎn wān':['鋺'],'gāng gàng':['鋼','钢'],zhuī:['錐','锥','騅','骓','鵻'],ā:['錒','锕'],'cuō chā':['鎈'],'suǒ sè':['鎍'],'yáo zú':['鎐'],'yè tà gé':['鎑'],'qiāng chēng':['鎗'],'gé lì':['鎘','镉','鬲'],'bī pī bì':['鎞'],'gǎo hào':['鎬'],'zú chuò':['鏃'],'xiū xiù':['鏅'],'shòu sōu':['鏉'],'dí dī':['鏑','镝'],'qiāo sǎn càn':['鏒'],'lù áo':['鏕'],'tāng táng':['鏜'],'jiàn zàn':['鏩'],'huì suì ruì':['鏸'],'qiǎng qiāng':['鏹','镪'],'sǎn xiàn sà':['鏾'],'jiǎn jiàn':['鐧','锏'],'dāng chēng':['鐺','铛'],'zuān zuàn':['鑽'],'sà xì':['钑'],'yào yuè':['钥'],'tǒu dǒu':['钭'],'zuàn zuān':['钻'],'qiān yán':['铅'],'pí pī':['铍'],'yáo diào tiáo':['铫'],'tāng tàng':['铴'],'pù pū':['铺'],'tán xiān':['锬'],'liù liú':['镏'],'hào gǎo':['镐'],'táng tāng':['镗'],'tán chán xín':['镡'],'huò shǎn':['閄'],'hàn bì':['閈','闬'],'kāng kàng':['閌','闶'],'xián jiàn jiān jiǎn':['閒'],'xiā xiǎ':['閕'],'xiǎ kě':['閜'],'biàn guān':['閞'],'hé gé':['閤','颌'],'hòng xiàng':['閧'],'sē xī':['閪'],'tíng tǐng':['閮'],'è yān':['閼','阏'],'hòng juǎn xiàng':['闂'],'bǎn pàn':['闆'],'dū shé':['闍','阇'],'què quē':['闕'],'tāng táng chāng':['闛'],'kàn hǎn':['闞','阚'],'xì sè tà':['闟'],'mēn mèn':['闷'],'quē què':['阙'],'yán diàn':['阽'],'ā ē':['阿'],'bēi pō pí':['陂'],'yàn yǎn':['隁'],'yú yáo shù':['隃'],'lóng lōng':['隆'],'duì zhuì':['隊'],'suí duò':['隋'],'gāi qí ái':['隑'],'huī duò':['隓','隳'],'wěi kuí':['隗'],'lì dài':['隸'],'zhuī cuī wéi':['隹'],'hè hú':['隺','鶮'],'jùn juàn':['隽','雋'],'nán nàn nuó':['难'],'què qiāo qiǎo':['雀'],'guàn huán':['雚'],'guī xī':['雟'],'sè xí':['雭'],án:['雸'],'wù méng':['雺'],tèng:['霯'],'lù lòu':['露'],mái:['霾'],'jìng liàng':['靚'],'gé jí':['革'],bǎ:['靶'],'yāng yàng':['鞅'],'gé tà sǎ':['鞈'],'biān yìng':['鞕'],'qiào shāo':['鞘'],'juān xuān':['鞙'],'shàng zhǎng':['鞝'],'pí bǐng bì bēi':['鞞'],la:['鞡'],'xiè dié':['鞢'],ēng:['鞥'],'móu mù':['鞪'],'bì bǐng':['鞸'],'mèi wà':['韎'],rǒu:['韖'],'shè xiè':['韘'],'yùn wēn':['韫'],'dùn dú':['頓','顿'],duǐ:['頧'],luō:['頱'],'bīn pín':['頻'],yóng:['顒','颙','鰫'],mān:['顢','颟'],'jǐng gěng':['颈'],'jié xié jiá':['颉'],'kē ké':['颏'],'pín bīn':['频'],'chàn zhàn':['颤'],'fēng fěng':['風','风'],'biāo diū':['颩'],'bá fú':['颰'],'sāo sōu':['颾'],'liù liáo':['飂'],'shí sì yì':['食'],'yǎng juàn':['飬'],'zhù tǒu':['飳'],'yí sì':['飴'],'zuò zé zhā':['飵'],tiè:['飻','餮'],'xiǎng náng':['饟'],'táng xíng':['饧'],'gē le':['饹'],'chā zha':['馇'],'náng nǎng':['馕'],'yūn wò':['馧'],'zhī shì':['馶'],'xìn jìn':['馸'],'kuài jué':['駃'],zǎng:['駔','驵'],'tái dài':['駘'],'xún xuān':['駨'],'liáng láng':['駺'],piàn:['騗','騙','骗','魸'],'dài tái':['骀'],'sāo sǎo':['骚'],'gǔ gū':['骨'],'bèi mó':['骳'],'xiāo qiāo':['骹'],'bǎng pǎng':['髈'],'bó jué':['髉'],'bì pǒ':['髲'],'máo méng':['髳'],'kuò yuè':['髺'],'bā bà':['魞','鲃'],'jì cǐ':['鮆'],'bó bà':['鮊'],'zhǎ zhà':['鮓','鲊'],'chóu dài':['鮘'],'luò gé':['鮥'],'guī xié wā kuí':['鮭'],'xiān xiǎn':['鮮','鲜'],'pū bū':['鯆'],'yì sī':['鯣'],'bà bó':['鲌'],'guī xié':['鲑'],'sāi xǐ':['鳃'],'niǎo diǎo':['鳥'],'diāo zhāo':['鳭'],'gān hàn yàn':['鳱'],'fū guī':['鳺'],'jiān qiān zhān':['鳽'],'hé jiè':['鶡'],'piān biǎn':['鶣'],'chuàn zhì':['鶨'],'cāng qiāng':['鶬'],'sǔn xùn':['鶽'],'biāo páo':['麃'],'zhù cū':['麆'],'jūn qún':['麇','麕'],chi:['麶'],'mó me':['麼'],'mó me ma':['麽'],'mí mǒ':['麿'],'dàn shèn':['黮'],'zhěn yān':['黰'],'dǎn zhǎn':['黵'],'miǎn mǐn měng':['黾'],hōu:['齁'],nàng:['齉'],'qí jì zī zhāi':['齐'],'yín kěn yǎn':['龂'],'yín kěn':['龈'],'gōng wò':['龏'],'guī jūn qiū':['龜','龟'],'kuí wā':['䖯'],lōu:['䁖'],'ōu qū':['𫭟'],'lóu lǘ':['𦝼'],'gǎ gā gá':['嘎'],'wā guà':['坬'],'zhǐ dǐ':['茋'],'gǒng hóng':['硔'],'yáo xiào':['滧'],};const DICT1=new FastDictFactory();Object.keys(map).forEach((key)=>{const chars=map[key];for(let char of chars){DICT1.set(char,key)}});const InitialList=['zh','ch','sh','z','c','s','b','p','m','f','d','t','n','l','g','k','h','j','q','x','r','y','w','',];const SpecialInitialList=['j','q','x'];const SpecialFinalList=['uān','uán','uǎn','uàn','uan','uē','ué','uě','uè','ue','ūn','ún','ǔn','ùn','un','ū','ú','ǔ','ù','u',];const SpecialFinalMap={uān:'üān',uán:'üán',uǎn:'üǎn',uàn:'üàn',uan:'üan',uē:'üē',ué:'üé',uě:'üě',uè:'üè',ue:'üe',ūn:'ǖn',ún:'ǘn',ǔn:'ǚn',ùn:'ǜn',un:'ün',ū:'ǖ',ú:'ǘ',ǔ:'ǚ',ù:'ǜ',u:'ü',};const doubleFinalList=['ia','ian','iang','iao','ie','iu','iong','ua','uai','uan','uang','ue','ui','uo','üan','üe','van','ve',];const Numbers={一:'yì',二:'èr',三:'sān',四:'sì',五:'wǔ',六:'liù',七:'qī',八:'bā',九:'jiǔ',十:'shí',百:'bǎi',千:'qiān',万:'wàn',亿:'yì',单:'dān',两:'liǎng',双:'shuāng',多:'duō',几:'jǐ',十一:'shí yī',零一:'líng yī',第一:'dì yī',一十:'yī shí',一十一:'yī shí yī',};const NumberWordMap={重:'chóng',行:'háng',斗:'dǒu',更:'gēng',};function genNumberDict(){const dict={零一:'líng yī',〇一:'líng yī',十一:'shí yī',一十:'yī shí',第一:'dì yī',一十一:'yī shí yī',};for(let number in Numbers){for(let key in NumberWordMap){const word=`${number}${key}`;const pinyin=`${Numbers[number]}${NumberWordMap[key]}`;dict[word]=pinyin}}return dict}const NumberDict=genNumberDict();const PatternNumberDict=Object.keys(NumberDict).map((key)=>({zh:key,pinyin:NumberDict[key],probability:1e-12,length:stringLength(key),priority:Priority.Normal,dict:Symbol('rule'),}));const toneSandhiMap={不:{bú:[4],},一:{yí:[4],yì:[1,2,3],},};const toneSandhiIgnoreSuffix={不:['的','而','之','后','也','还','地'],一:['的','而','之','后','也','还','是'],};const toneSandhiList=Object.keys(toneSandhiMap);function processToneSandhi(cur,pre,next){if(toneSandhiList.indexOf(cur)===-1){return getSingleWordPinyin(cur)}if(pre===next&&pre&&getSingleWordPinyin(pre)!==pre){return getPinyinWithoutTone(getSingleWordPinyin(cur))}if(next&&!toneSandhiIgnoreSuffix[cur].includes(next)){const nextPinyin=getSingleWordPinyin(next);if(nextPinyin!==next){const nextTone=getNumOfTone(nextPinyin);const pinyinMap=toneSandhiMap[cur];for(let pinyin in pinyinMap){const tones=pinyinMap[pinyin];if(tones.indexOf(Number(nextTone))!==-1){return pinyin}}}}}function processToneSandhiLiao(cur,pre){if(cur==='了'&&(!pre||!DICT1.get(pre))){return'liǎo'}}function processReduplicationChar(cur,pre){if(cur==='々'){if(!pre||!DICT1.get(pre)){return'tóng'}else{return DICT1.get(pre).split(' ')[0]}}}function processSepecialPinyin(cur,pre,next){return(processReduplicationChar(cur,pre)||processToneSandhiLiao(cur,pre)||processToneSandhi(cur,pre,next)||getSingleWordPinyin(cur))}const Surnames={南宫:'nán gōng',第五:'dì wǔ',万俟:'mò qí',司马:'sī mǎ',上官:'shàng guān',欧阳:'ōu yáng',夏侯:'xià hóu',诸葛:'zhū gě',闻人:'wén rén',东方:'dōng fāng',赫连:'hè lián',皇甫:'huáng fǔ',尉迟:'yù chí',公羊:'gōng yáng',澹台:'tán tái',公冶:'gōng yě',宗政:'zōng zhèng',濮阳:'pú yáng',淳于:'chún yú',太叔:'tài shū',申屠:'shēn tú',公孙:'gōng sūn',仲孙:'zhòng sūn',轩辕:'xuān yuán',令狐:'líng hú',钟离:'zhōng lí',宇文:'yǔ wén',长孙:'zhǎng sūn',慕容:'mù róng',鲜于:'xiān yú',闾丘:'lǘ qiū',司徒:'sī tú',司空:'sī kōng',亓官:'qí guān',司寇:'sī kòu',仉督:'zhǎng dū',子车:'zǐ jū',颛孙:'zhuān sūn',端木:'duān mù',巫马:'wū mǎ',公西:'gōng xī',漆雕:'qī diāo',乐正:'yuè zhèng',壤驷:'rǎng sì',公良:'gōng liáng',拓跋:'tuò bá',夹谷:'jiá gǔ',宰父:'zǎi fǔ',榖梁:'gǔ liáng',段干:'duàn gān',百里:'bǎi lǐ',东郭:'dōng guō',南门:'nán mén',呼延:'hū yán',羊舌:'yáng shé',梁丘:'liáng qiū',左丘:'zuǒ qiū',东门:'dōng mén',西门:'xī mén',句龙:'gōu lóng',毌丘:'guàn qiū',赵:'zhào',钱:'qián',孙:'sūn',李:'lǐ',周:'zhōu',吴:'wú',郑:'zhèng',王:'wáng',冯:'féng',陈:'chén',褚:'chǔ',卫:'wèi',蒋:'jiǎng',沈:'shěn',韩:'hán',杨:'yáng',朱:'zhū',秦:'qín',尤:'yóu',许:'xǔ',何:'hé',吕:'lǚ',施:'shī',张:'zhāng',孔:'kǒng',曹:'cáo',严:'yán',华:'huà',金:'jīn',魏:'wèi',陶:'táo',姜:'jiāng',戚:'qī',谢:'xiè',邹:'zōu',喻:'yù',柏:'bǎi',水:'shuǐ',窦:'dòu',章:'zhāng',云:'yún',苏:'sū',潘:'pān',葛:'gě',奚:'xī',范:'fàn',彭:'péng',郎:'láng',鲁:'lǔ',韦:'wéi',昌:'chāng',马:'mǎ',苗:'miáo',凤:'fèng',花:'huā',方:'fāng',俞:'yú',任:'rén',袁:'yuán',柳:'liǔ',酆:'fēng',鲍:'bào',史:'shǐ',唐:'táng',费:'fèi',廉:'lián',岑:'cén',薛:'xuē',雷:'léi',贺:'hè',倪:'ní',汤:'tāng',滕:'téng',殷:'yīn',罗:'luó',毕:'bì',郝:'hǎo',邬:'wū',安:'ān',常:'cháng',乐:'yuè',于:'yú',时:'shí',傅:'fù',皮:'pí',卞:'biàn',齐:'qí',康:'kāng',伍:'wǔ',余:'yú',元:'yuán',卜:'bǔ',顾:'gù',孟:'mèng',平:'píng',黄:'huáng',和:'hé',穆:'mù',萧:'xiāo',尹:'yǐn',姚:'yáo',邵:'shào',湛:'zhàn',汪:'wāng',祁:'qí',毛:'máo',禹:'yǔ',狄:'dí',米:'mǐ',贝:'bèi',明:'míng',臧:'zāng',计:'jì',伏:'fú',成:'chéng',戴:'dài',谈:'tán',宋:'sòng',茅:'máo',庞:'páng',熊:'xióng',纪:'jǐ',舒:'shū',屈:'qū',项:'xiàng',祝:'zhù',董:'dǒng',梁:'liáng',杜:'dù',阮:'ruǎn',蓝:'lán',闵:'mǐn',席:'xí',季:'jì',麻:'má',强:'qiáng',贾:'jiǎ',路:'lù',娄:'lóu',危:'wēi',江:'jiāng',童:'tóng',颜:'yán',郭:'guō',梅:'méi',盛:'shèng',林:'lín',刁:'diāo',钟:'zhōng',徐:'xú',邱:'qiū',骆:'luò',高:'gāo',夏:'xià',蔡:'cài',田:'tián',樊:'fán',胡:'hú',凌:'líng',霍:'huò',虞:'yú',万:'wàn',支:'zhī',柯:'kē',昝:'zǎn',管:'guǎn',卢:'lú',莫:'mò',经:'jīng',房:'fáng',裘:'qiú',缪:'miào',干:'gān',解:'xiè',应:'yīng',宗:'zōng',丁:'dīng',宣:'xuān',贲:'bēn',邓:'dèng',郁:'yù',单:'shàn',杭:'háng',洪:'hóng',包:'bāo',诸:'zhū',左:'zuǒ',石:'shí',崔:'cuī',吉:'jí',钮:'niǔ',龚:'gōng',程:'chéng',嵇:'jī',邢:'xíng',滑:'huá',裴:'péi',陆:'lù',荣:'róng',翁:'wēng',荀:'xún',羊:'yáng',於:'yū',惠:'huì',甄:'zhēn',曲:'qū',家:'jiā',封:'fēng',芮:'ruì',羿:'yì',储:'chǔ',靳:'jìn',汲:'jí',邴:'bǐng',糜:'mí',松:'sōng',井:'jǐng',段:'duàn',富:'fù',巫:'wū',乌:'wū',焦:'jiāo',巴:'bā',弓:'gōng',牧:'mù',隗:'wěi',山:'shān',谷:'gǔ',车:'chē',侯:'hóu',宓:'mì',蓬:'péng',全:'quán',郗:'xī',班:'bān',仰:'yǎng',秋:'qiū',仲:'zhòng',伊:'yī',宫:'gōng',宁:'nìng',仇:'qiú',栾:'luán',暴:'bào',甘:'gān',钭:'tǒu',厉:'lì',戎:'róng',祖:'zǔ',武:'wǔ',符:'fú',刘:'liú',景:'jǐng',詹:'zhān',束:'shù',龙:'lóng',叶:'yè',幸:'xìng',司:'sī',韶:'sháo',郜:'gào',黎:'lí',蓟:'jì',薄:'bó',印:'yìn',宿:'sù',白:'bái',怀:'huái',蒲:'pú',邰:'tái',从:'cóng',鄂:'è',索:'suǒ',咸:'xián',籍:'jí',赖:'lài',卓:'zhuó',蔺:'lìn',屠:'tú',蒙:'méng',池:'chí',乔:'qiáo',阴:'yīn',鬱:'yù',胥:'xū',能:'nài',苍:'cāng',双:'shuāng',闻:'wén',莘:'shēn',党:'dǎng',翟:'zhái',谭:'tán',贡:'gòng',劳:'láo',逄:'páng',姬:'jī',申:'shēn',扶:'fú',堵:'dǔ',冉:'rǎn',宰:'zǎi',郦:'lì',雍:'yōng',郤:'xì',璩:'qú',桑:'sāng',桂:'guì',濮:'pú',牛:'niú',寿:'shòu',通:'tōng',边:'biān',扈:'hù',燕:'yān',冀:'jì',郏:'jiá',浦:'pǔ',尚:'shàng',农:'nóng',温:'wēn',别:'bié',庄:'zhuāng',晏:'yàn',柴:'chái',瞿:'qú',阎:'yán',充:'chōng',慕:'mù',连:'lián',茹:'rú',习:'xí',宦:'huàn',艾:'ài',鱼:'yú',容:'róng',向:'xiàng',古:'gǔ',易:'yì',慎:'shèn',戈:'gē',廖:'liào',庾:'yǔ',终:'zhōng',暨:'jì',居:'jū',衡:'héng',步:'bù',都:'dū',耿:'gěng',满:'mǎn',弘:'hóng',匡:'kuāng',国:'guó',文:'wén',寇:'kòu',广:'guǎng',禄:'lù',阙:'quē',东:'dōng',欧:'ōu',殳:'shū',沃:'wò',利:'lì',蔚:'wèi',越:'yuè',夔:'kuí',隆:'lóng',师:'shī',巩:'gǒng',厍:'shè',聂:'niè',晁:'cháo',勾:'gōu',敖:'áo',融:'róng',冷:'lěng',訾:'zī',辛:'xīn',阚:'kàn',那:'nā',简:'jiǎn',饶:'ráo',空:'kōng',曾:'zēng',母:'mǔ',沙:'shā',乜:'niè',养:'yǎng',鞠:'jū',须:'xū',丰:'fēng',巢:'cháo',关:'guān',蒯:'kuǎi',相:'xiàng',查:'zhā',后:'hòu',荆:'jīng',红:'hóng',游:'yóu',竺:'zhú',权:'quán',逯:'lù',盖:'gě',益:'yì',桓:'huán',公:'gōng',牟:'móu',哈:'hǎ',言:'yán',福:'fú',肖:'xiāo',区:'ōu',覃:'qín',朴:'piáo',繁:'pó',员:'yùn',句:'gōu',要:'yāo',过:'guō',钻:'zuān',谌:'chén',折:'shé',召:'shào',郄:'qiè',撒:'sǎ',甯:'nìng',六:'lù',啜:'chuài',行:'xíng',};const PatternSurname=Object.keys(Surnames).map((key)=>({zh:key,pinyin:Surnames[key],probability:1+stringLength(key),length:stringLength(key),priority:Priority.Surname,dict:Symbol('surname'),}));const DICT2={这个:'zhè ge',成为:'chéng wéi',认为:'rèn wéi',作为:'zuò wéi',部分:'bù fen',要求:'yāo qiú',应该:'yīng gāi',增长:'zēng zhǎng',提供:'tí gōng',觉得:'jué de',任务:'rèn wu',那个:'nà ge',称为:'chēng wéi',为主:'wéi zhǔ',了解:'liǎo jiě',处理:'chǔ lǐ',皇上:'huáng shang',只要:'zhǐ yào',大量:'dà liàng',力量:'lì liàng',几乎:'jī hū',干部:'gàn bù',目的:'mù dì',行为:'xíng wéi',只见:'zhǐ jiàn',认识:'rèn shi',市长:'shì zhǎng',师父:'shī fu',调查:'diào chá',重新:'chóng xīn',分为:'fēn wéi',知识:'zhī shi',导弹:'dǎo dàn',质量:'zhì liàng',行款:'háng kuǎn',行列:'háng liè',行话:'háng huà',行业:'háng yè',隔行:'gé háng',在行:'zài háng',行家:'háng jia',内行:'nèi háng',外行:'wài háng',同行:'tóng háng',本行:'běn háng',行伍:'háng wǔ',洋行:'yáng háng',银行:'yín háng',商行:'shāng háng',支行:'zhī háng',总行:'zǒng háng',行情:'háng qíng',懂行:'dǒng háng',行规:'háng guī',行当:'háng dang',行货:'háng huò',太行:'tài háng',入行:'rù háng',中行:'zhōng háng',农行:'nóng háng',工行:'gōng háng',建行:'jiàn háng',各行:"gè háng",行号:'háng hào',行高:'háng gāo',行首:'háng shǒu',行尾:'háng wěi',行末:'háng mò',行长:'háng cháng',行距:'háng jù',换行:'huàn háng',行会:'háng huì',行辈:'háng bèi',行道:'háng dào',道行:'dào heng',参与:'cān yù',充分:'chōng fèn',尽管:'jǐn guǎn',生长:'shēng zhǎng',数量:'shù liàng',应当:'yīng dāng',院长:'yuàn zhǎng',强调:'qiáng diào',只能:'zhǐ néng',音乐:'yīn yuè',以为:'yǐ wéi',处于:'chǔ yú',部长:'bù zhǎng',蒙古:'měng gǔ',只有:'zhǐ yǒu',适当:'shì dàng',只好:'zhǐ hǎo',成长:'chéng zhǎng',高兴:'gāo xìng',不了:'bù liǎo',产量:'chǎn liàng',胖子:'pàng zi',显得:'xiǎn de',只是:'zhǐ shì',似的:'shì de',率领:'shuài lǐng',改为:'gǎi wéi',不禁:'bù jīn',成分:'chéng fèn',答应:'dā ying',少年:'shào nián',兴趣:'xìng qù',太监:'tài jian',休息:'xiū xi',校长:'xiào zhǎng',更新:'gēng xīn',合同:'hé tong',喝道:'hè dào',重庆:'chóng qìng',重建:'chóng jiàn',使得:'shǐ de',审查:'shěn chá',累计:'lěi jì',给予:'jǐ yǔ',极为:'jí wéi',冠军:'guàn jūn',仿佛:'fǎng fú',头发:'tóu fa',投降:'tóu xiáng',家长:'jiā zhǎng',仔细:'zǐ xì',要是:'yào shi',将领:'jiàng lǐng',含量:'hán liàng',更为:'gèng wéi',积累:'jī lěi',地处:'dì chǔ',县长:'xiàn zhǎng',少女:'shào nǚ',路上:'lù shang',只怕:'zhǐ pà',能量:'néng liàng',储量:'chǔ liàng',供应:'gōng yìng',挑战:'tiǎo zhàn',西藏:'xī zàng',记得:'jì de',总量:'zǒng liàng',当真:'dàng zhēn',将士:'jiàng shì',差别:'chā bié',较为:'jiào wéi',长老:'zhǎng lǎo',大夫:'dài fu',差异:'chā yì',懂得:'dǒng de',尽量:'jǐn liàng',模样:'mú yàng',的确:'dí què',为首:'wéi shǒu',便宜:'pián yi',更名:'gēng míng',石头:'shí tou',州长:'zhōu zhǎng',为止:'wéi zhǐ',漂亮:'piào liang',炮弹:'pào dàn',藏族:'zàng zú',角色:'jué sè',当作:'dàng zuò',尽快:'jǐn kuài',人为:'rén wéi',重复:'chóng fù',胡同:'hú tòng',差距:'chā jù',弟兄:'dì xiong',大将:'dà jiàng',睡觉:'shuì jiào',一觉:'yí jiào',团长:'tuán zhǎng',队长:'duì zhǎng',区长:'qū zhǎng',难得:'nán dé',丫头:'yā tou',会长:'huì zhǎng',弟弟:'dì di',王爷:'wáng ye',重量:'zhòng liàng',誉为:'yù wéi',家伙:'jiā huo',华山:'huà shān',椅子:'yǐ zi',流量:'liú liàng',长大:'zhǎng dà',勉强:'miǎn qiǎng',会计:'kuài jì',过分:'guò fèn',济南:'jǐ nán',调动:'diào dòng',燕京:'yān jīng',少将:'shào jiàng',中毒:'zhòng dú',晓得:'xiǎo de',变更:'biàn gēng',打更:'dǎ gēng',认得:'rèn de',苹果:'píng guǒ',念头:'niàn tou',挣扎:'zhēng zhá',三藏:'sān zàng',剥削:'bō xuē',丞相:'chéng xiàng',少量:'shǎo liàng',寻思:'xún si',夺得:'duó dé',干线:'gàn xiàn',呼吁:'hū yù',处罚:'chǔ fá',长官:'zhǎng guān',柏林:'bó lín',亲戚:'qīn qi',身分:'shēn fèn',胳膊:'gē bo',着手:'zhuó shǒu',炸弹:'zhà dàn',咳嗽:'ké sou',叶子:'yè zi',外长:'wài zhǎng',供给:'gōng jǐ',师长:'shī zhǎng',变量:'biàn liàng',应有:'yīng yǒu',下载:'xià zài',乐器:'yuè qì',间接:'jiàn jiē',底下:'dǐ xià',打扮:'dǎ bàn',子弹:'zǐ dàn',弹药:'dàn yào',热量:'rè liàng',削弱:'xuē ruò',骨干:'gǔ gàn',容量:'róng liàng',模糊:'mó hu',转动:'zhuàn dòng',称呼:'chēng hu',科长:'kē zhǎng',处置:'chǔ zhì',着重:'zhuó zhòng',着急:'zháo jí',强迫:'qiǎng pò',庭长:'tíng zhǎng',首相:'shǒu xiàng',喇嘛:'lǎ ma',镇长:'zhèn zhǎng',只管:'zhǐ guǎn',重重:'chóng chóng',免得:'miǎn de',着实:'zhuó shí',度假:'dù jià',真相:'zhēn xiàng',相貌:'xiàng mào',处分:'chǔ fèn',委屈:'wěi qu',为期:'wéi qī',伯伯:'bó bo',伯子:'bǎi zi',圈子:'quān zi',见识:'jiàn shi',笼罩:'lǒng zhào',与会:'yù huì',都督:'dū du',都市:'dū shì',成都:'chéng dū',首都:'shǒu dū',帝都:'dì dū',王都:'wáng dū',东都:'dōng dū',都护:'dū hù',都城:'dū chéng',建都:'jiàn dū',迁都:'qiān dū',故都:'gù dū',定都:'dìng dū',中都:'zhōng dū',六安:'lù ān',宰相:'zǎi xiàng',较量:'jiào liàng',对称:'duì chèn',总长:'zǒng zhǎng',相公:'xiàng gong',空白:'kòng bái',打量:'dǎ liang',水分:'shuǐ fèn',舌头:'shé tou',没收:'mò shōu',行李:'xíng li',判处:'pàn chǔ',散文:'sǎn wén',处境:'chǔ jìng',孙子:'sūn zi',拳头:'quán tou',打发:'dǎ fā',组长:'zǔ zhǎng',骨头:'gǔ tou',宁可:'nìng kě',更换:'gēng huàn',薄弱:'bó ruò',还原:'huán yuán',重修:'chóng xiū',重来:'chóng lái',只顾:'zhǐ gù',爱好:'ài hào',馒头:'mán tou',军长:'jūn zhǎng',首长:'shǒu zhǎng',厂长:'chǎng zhǎng',司长:'sī zhǎng',长子:'zhǎng zǐ',强劲:'qiáng jìng',恰当:'qià dàng',头儿:'tóu er',站长:'zhàn zhǎng',折腾:'zhē teng',相处:'xiāng chǔ',统率:'tǒng shuài',中将:'zhōng jiàng',命中:'mìng zhòng',名将:'míng jiàng',木头:'mù tou',动弹:'dòng tan',地壳:'dì qiào',干活:'gàn huó',少爷:'shào ye',水量:'shuǐ liàng',补给:'bǔ jǐ',尾巴:'wěi ba',来得:'lái de',好奇:'hào qí',钥匙:'yào shi',当做:'dàng zuò',沉着:'chén zhuó',哑巴:'yǎ ba',车子:'chē zi',上将:'shàng jiàng',恶心:'ě xīn',担子:'dàn zi',应届:'yīng jiè',主角:'zhǔ jué',运转:'yùn zhuǎn',兄长:'xiōng zhǎng',格式:'gé shì',正月:'zhēng yuè',营长:'yíng zhǎng',当成:'dàng chéng',女婿:'nǚ xu',咽喉:'yān hóu',重阳:'chóng yáng',化为:'huà wéi',吐蕃:'tǔ bō',钻进:'zuān jìn',乐队:'yuè duì',亮相:'liàng xiàng',被子:'bèi zi',舍得:'shě de',杉木:'shā mù',击中:'jī zhòng',排长:'pái zhǎng',假期:'jià qī',分量:'fèn liàng',数次:'shù cì',提防:'dī fáng',吆喝:'yāo he',查处:'chá chǔ',量子:'liàng zǐ',里头:'lǐ tou',调研:'diào yán',伺候:'cì hou',重申:'chóng shēn',枕头:'zhěn tou',拚命:'pīn mìng',社长:'shè zhǎng',归还:'guī huán',批量:'pī liàng',畜牧:'xù mù',点着:'diǎn zháo',甚为:'shèn wéi',小将:'xiǎo jiàng',着眼:'zhuó yǎn',处死:'chǔ sǐ',厌恶:'yàn wù',鼓乐:'gǔ yuè',树干:'shù gàn',秘鲁:'bì lǔ',大方:'dà fāng',外头:'wài tou',班长:'bān zhǎng',星宿:'xīng xiù',宁愿:'nìng yuàn',钦差:'qīn chāi',为数:'wéi shù',勾当:'gòu dàng',削减:'xuē jiǎn',间谍:'jiàn dié',埋怨:'mán yuàn',结实:'jiē shi',计量:'jì liáng',淹没:'yān mò',村长:'cūn zhǎng',连长:'lián zhǎng',自给:'zì jǐ',武将:'wǔ jiàng',温差:'wēn chā',直奔:'zhí bèn',供求:'gōng qiú',剂量:'jì liàng',道长:'dào zhǎng',泄露:'xiè lòu',王八:'wáng ba',切割:'qiē gē',间隔:'jiàn gé',一晃:'yì huǎng',长假:'cháng jià',令狐:'líng hú',为害:'wéi hài',句子:'jù zi',偿还:'cháng huán',疙瘩:'gē da',燕山:'yān shān',堵塞:'dǔ sè',夺冠:'duó guàn',扎实:'zhā shi',电荷:'diàn hè',看守:'kān shǒu',复辟:'fù bì',郁闷:'yù mèn',尽早:'jǐn zǎo',切断:'qiē duàn',指头:'zhǐ tou',为生:'wéi shēng',畜生:'chù sheng',切除:'qiē chú',着力:'zhuó lì',着想:'zhuó xiǎng',级差:'jí chā',投奔:'tóu bèn',棍子:'gùn zi',含糊:'hán hu',少妇:'shào fù',兴致:'xìng zhì',纳闷:'nà mèn',干流:'gàn liú',卷起:'juǎn qǐ',扇子:'shàn zi',更改:'gēng gǎi',笼络:'lǒng luò',喇叭:'lǎ ba',载荷:'zài hè',妥当:'tuǒ dàng',为难:'wéi nán',着陆:'zhuó lù',燕子:'yàn zi',干吗:'gàn má',白发:'bái fà',总得:'zǒng děi',夹击:'jiā jī',曝光:'bào guāng',曲调:'qǔ diào',相机:'xiàng jī',叫化:'jiào huà',角逐:'jué zhú',啊哟:'ā yō',载重:'zài zhòng',长辈:'zhǎng bèi',出差:'chū chāi',垛口:'duǒ kǒu',撇开:'piē kāi',厅长:'tīng zhǎng',组分:'zǔ fèn',误差:'wù chā',家当:'jiā dàng',传记:'zhuàn jì',个子:'gè zi',铺设:'pū shè',干事:'gàn shì',杆菌:'gǎn jūn',定量:'dìng liàng',运载:'yùn zài',会儿:'huì er',酋长:'qiú zhǎng',重返:'chóng fǎn',差额:'chā é',露面:'lòu miàn',钻研:'zuān yán',大城:'dài chéng',上当:'shàng dàng',销量:'xiāo liàng',作坊:'zuō fang',照相:'zhào xiàng',哎呀:'āi yā',调集:'diào jí',看中:'kàn zhòng',议长:'yì zhǎng',风筝:'fēng zheng',辟邪:'bì xié',空隙:'kòng xì',更迭:'gēng dié',偏差:'piān chā',声调:'shēng diào',适量:'shì liàng',屯子:'tún zi',无量:'wú liàng',空地:'kòng dì',调度:'diào dù',散射:'sǎn shè',创伤:'chuāng shāng',海参:'hǎi shēn',满载:'mǎn zài',重叠:'chóng dié',落差:'luò chā',单调:'dān diào',老将:'lǎo jiàng',人参:'rén shēn',间断:'jiàn duàn',重现:'chóng xiàn',夹杂:'jiā zá',调用:'diào yòng',萝卜:'luó bo',附着:'fù zhuó',应声:'yìng shēng',主将:'zhǔ jiàng',罪过:'zuì guo',咀嚼:'jǔ jué',为政:'wéi zhèng',过量:'guò liàng',乐曲:'yuè qǔ',负荷:'fù hè',枪弹:'qiāng dàn',悄然:'qiǎo rán',处方:'chǔ fāng',悄声:'qiǎo shēng',曲子:'qǔ zi',情调:'qíng diào',挑衅:'tiǎo xìn',代为:'dài wéi',了结:'liǎo jié',打中:'dǎ zhòng',酒吧:'jiǔ bā',懒得:'lǎn de',增量:'zēng liàng',衣着:'yī zhuó',部将:'bù jiàng',要塞:'yào sài',茶几:'chá jī',杠杆:'gàng gǎn',出没:'chū mò',鲜有:'xiǎn yǒu',间隙:'jiàn xì',重担:'zhòng dàn',重演:'chóng yǎn',重试:'chóng shì',应酬:'yìng chou',只当:'zhǐ dāng',毋宁:'wú nìng',包扎:'bāo zā',前头:'qián tou',卷烟:'juǎn yān',非得:'fēi děi',弹道:'dàn dào',杆子:'gān zi',门将:'mén jiàng',后头:'hòu tou',喝彩:'hè cǎi',暖和:'nuǎn huo',累积:'lěi jī',调遣:'diào qiǎn',倔强:'jué jiàng',宝藏:'bǎo zàng',丧事:'sāng shì',约莫:'yuē mo',纤夫:'qiàn fū',更替:'gēng tì',装载:'zhuāng zài',背包:'bēi bāo',帖子:'tiě zi',松散:'sōng sǎn',呼喝:'hū hè',可恶:'kě wù',自转:'zì zhuàn',供电:'gōng diàn',反省:'fǎn xǐng',坦率:'tǎn shuài',苏打:'sū dá',本分:'běn fèn',落得:'luò de',鄙薄:'bǐ bó',相间:'xiāng jiàn',单薄:'dān bó',混蛋:'hún dàn',贞观:'zhēn guān',附和:'fù hè',能耐:'néng nài',吓唬:'xià hu',未了:'wèi liǎo',引着:'yǐn zháo',抽调:'chōu diào',沙子:'shā zi',席卷:'xí juǎn',标的:'biāo dì',别扭:'biè niu',思量:'sī liang',喝采:'hè cǎi',论语:'lún yǔ',盖子:'gài zi',分外:'fèn wài',弄堂:'lòng táng',乐舞:'yuè wǔ',雨量:'yǔ liàng',毛发:'máo fà',差遣:'chāi qiǎn',背负:'bēi fù',转速:'zhuàn sù',声乐:'shēng yuè',夹攻:'jiā gōng',供水:'gōng shuǐ',主干:'zhǔ gàn',惩处:'chéng chǔ',长相:'zhǎng xiàng',公差:'gōng chāi',榴弹:'liú dàn',省得:'shěng de',条子:'tiáo zi',重围:'chóng wéi',阻塞:'zǔ sè',劲风:'jìng fēng',纠葛:'jiū gé',颠簸:'diān bǒ',点中:'diǎn zhòng',重创:'zhòng chuāng',姥姥:'lǎo lao',迷糊:'mí hu',公家:'gōng jia',几率:'jī lǜ',苦闷:'kǔ mèn',度量:'dù liàng',差错:'chā cuò',暑假:'shǔ jià',参差:'cēn cī',搭载:'dā zài',助长:'zhù zhǎng',相称:'xiāng chèn',红晕:'hóng yùn',舍命:'shě mìng',喜好:'xǐ hào',列传:'liè zhuàn',劲敌:'jìng dí',蛤蟆:'há ma',请假:'qǐng jià',钉子:'dīng zi',沉没:'chén mò',高丽:'gāo lí',休假:'xiū jià',无为:'wú wéi',巴结:'bā jie',了得:'liǎo dé',变相:'biàn xiàng',核弹:'hé dàn',亲家:'qìng jia',承载:'chéng zài',喝问:'hè wèn',还击:'huán jī',交还:'jiāo huán',将令:'jiàng lìng',单于:'chán yú',空缺:'kòng quē',绿林:'lù lín',胆量:'dǎn liàng',执着:'zhí zhuó',低调:'dī diào',闭塞:'bì sè',轻薄:'qīng bó',得当:'dé dàng',占卜:'zhān bǔ',扫帚:'sào zhou',龟兹:'qiū cí',年长:'nián zhǎng',外传:'wài zhuàn',头子:'tóu zi',裁缝:'cái feng',礼乐:'lǐ yuè',血泊:'xuè pō',散乱:'sǎn luàn',动量:'dòng liàng',倒腾:'dǎo teng',取舍:'qǔ shě',咱家:'zán jiā',长发:'cháng fà',爪哇:'zhǎo wā',弹壳:'dàn ké',省悟:'xǐng wù',嚷嚷:'rāng rang',连累:'lián lèi',应得:'yīng dé',族长:'zú zhǎng',柜子:'guì zi',擂鼓:'léi gǔ',眩晕:'xuàn yùn',调配:'tiáo pèi',躯干:'qū gàn',差役:'chāi yì',坎坷:'kǎn kě',少儿:'shào ér',乐团:'yuè tuán',养分:'yǎng fèn',退还:'tuì huán',格调:'gé diào',语调:'yǔ diào',音调:'yīn diào',乐府:'yuè fǔ',古朴:'gǔ pǔ',打点:'dǎ diǎn',差使:'chāi shǐ',匀称:'yún chèn',瘦削:'shòu xuē',膏药:'gāo yao',吞没:'tūn mò',调任:'diào rèn',散居:'sǎn jū',上头:'shàng tóu',风靡:'fēng mǐ',放假:'fàng jià',估量:'gū liang',失当:'shī dàng',中弹:'zhòng dàn',妄为:'wàng wéi',长者:'zhǎng zhě',起哄:'qǐ hòng',末了:'mò liǎo',相声:'xiàng sheng',校正:'jiào zhèng',劝降:'quàn xiáng',矢量:'shǐ liàng',沉闷:'chén mèn',给与:'jǐ yǔ',解法:'jiě fǎ',塞外:'sài wài',将校:'jiàng xiào',嗜好:'shì hào',没落:'mò luò',朴刀:'pō dāo',片子:'piān zi',切削:'qiē xiāo',弹丸:'dàn wán',稀薄:'xī bó',亏得:'kuī dé',间歇:'jiàn xiē',翘首:'qiáo shǒu',色调:'sè diào',处决:'chǔ jué',表率:'biǎo shuài',尺子:'chǐ zi',招降:'zhāo xiáng',称职:'chèn zhí',斗篷:'dǒu peng',铺子:'pù zi',底子:'dǐ zi',负载:'fù zài',干警:'gàn jǐng',倒数:'dào shǔ',将官:'jiàng guān',锄头:'chú tou',归降:'guī xiáng',疟疾:'nüè ji',唠叨:'láo dao',限量:'xiàn liàng',屏息:'bǐng xī',重逢:'chóng féng',器乐:'qì yuè',氢弹:'qīng dàn',脖颈:'bó gěng',妃子:'fēi zi',处事:'chǔ shì',参量:'cān liàng',轻率:'qīng shuài',缥缈:'piāo miǎo',中奖:'zhòng jiǎng',才干:'cái gàn',施舍:'shī shě',卷子:'juàn zi',游说:'yóu shuì',巷子:'xiàng zi',膀胱:'páng guāng',切勿:'qiè wù',看管:'kān guǎn',风头:'fēng tou',精干:'jīng gàn',高差:'gāo chā',恐吓:'kǒng hè',扁担:'biǎn dàn',给养:'jǐ yǎng',格子:'gé zi',供需:'gōng xū',反差:'fǎn chā',飞弹:'fēi dàn',微薄:'wēi bó',发型:'fà xíng',即兴:'jí xìng',攒动:'cuán dòng',间或:'jiàn huò',浅薄:'qiǎn bó',乐章:'yuè zhāng',顺差:'shùn chā',调子:'diào zi',相位:'xiàng wèi',转子:'zhuàn zǐ',劲旅:'jìng lǚ',咔嚓:'kā chā',了事:'liǎo shì',转悠:'zhuàn you',当铺:'dàng pù',爪子:'zhuǎ zi',单子:'dān zi',好战:'hào zhàn',燕麦:'yàn mài',只许:'zhǐ xǔ',干练:'gàn liàn',女将:'nǚ jiàng',酒量:'jiǔ liàng',划船:'huá chuán',伎俩:'jì liǎng',挑拨:'tiǎo bō',少校:'shào xiào',着落:'zhuó luò',憎恶:'zēng wù',刻薄:'kè bó',要挟:'yāo xié',用处:'yòng chu',还手:'huán shǒu',模具:'mú jù',执著:'zhí zhuó',喝令:'hè lìng',保长:'bǎo zhǎng',吸着:'xī zhe',症结:'zhēng jié',公转:'gōng zhuàn',校勘:'jiào kān',重提:'chóng tí',扫兴:'sǎo xìng',铺盖:'pū gài',长史:'zhǎng shǐ',差价:'chā jià',压根:'yà gēn',怔住:'zhèng zhù',应允:'yīng yǔn',切入:'qiē rù',战将:'zhàn jiàng',年少:'nián shào',舍身:'shě shēn',执拗:'zhí niù',处世:'chǔ shì',中风:'zhòng fēng',等量:'děng liàng',放量:'fàng liàng',腔调:'qiāng diào',老少:'lǎo shào',没入:'mò rù',瓜葛:'guā gé',将帅:'jiàng shuài',车载:'chē zài',窝囊:'wō nang',长进:'zhǎng jìn',可汗:'kè hán',并州:'bīng zhōu',供销:'gōng xiāo',切片:'qiē piàn',差事:'chāi shì',知会:'zhī hui',鹰爪:'yīng zhǎo',处女:'chǔ nǚ',切磋:'qiē cuō',日头:'rì tou',押解:'yā jiè',滋长:'zī zhǎng',道观:'dào guàn',脚色:'jué sè',当量:'dāng liàng',婆家:'pó jia',缘分:'yuán fèn',空闲:'kòng xián',好色:'hào sè',怒喝:'nù hè',笼统:'lǒng tǒng',边塞:'biān sài',何曾:'hé céng',重合:'chóng hé',零散:'líng sǎn',轰隆:'hōng lōng',化子:'huà zi',内蒙:'nèi měng',数落:'shǔ luò',逆差:'nì chā',牟利:'móu lì',栅栏:'zhà lan',中标:'zhòng biāo',调档:'diào dàng',佝偻:'gōu lóu',场子:'chǎng zi',甲壳:'jiǎ qiào',重温:'chóng wēn',炮制:'páo zhì',返还:'fǎn huán',自传:'zì zhuàn',高调:'gāo diào',殷红:'yān hóng',固着:'gù zhuó',强求:'qiǎng qiú',本相:'běn xiàng',骄横:'jiāo hèng',草率:'cǎo shuài',气闷:'qì mèn',着色:'zhuó sè',宁肯:'nìng kěn',兴头:'xìng tou',拘泥:'jū nì',夹角:'jiā jiǎo',发髻:'fà jì',猛将:'měng jiàng',约摸:'yuē mo',拖累:'tuō lěi',呢绒:'ní róng',钻探:'zuān tàn',夹层:'jiā céng',落魄:'luò pò',巷道:'hàng dào',运量:'yùn liàng',解闷:'jiě mèn',空儿:'kòng er',估摸:'gū mo',好客:'hào kè',钻孔:'zuān kǒng',糊弄:'hù nòng',荥阳:'xíng yáng',烦闷:'fán mèn',仓卒:'cāng cù',分叉:'fēn chà',厂子:'chǎng zi',小调:'xiǎo diào',少阳:'shào yáng',受降:'shòu xiáng',染坊:'rǎn fáng',胳臂:'gē bei',将门:'jiàng mén',模板:'mú bǎn',配给:'pèi jǐ',为伍:'wéi wǔ',跟头:'gēn tou',划算:'huá suàn',累赘:'léi zhui',哄笑:'hōng xiào',晕眩:'yūn xuàn',干掉:'gàn diào',缝制:'féng zhì',难处:'nán chù',着意:'zhuó yì',蛮横:'mán hèng',奇数:'jī shù',短发:'duǎn fà',生还:'shēng huán',还清:'huán qīng',看护:'kān hù',直率:'zhí shuài',奏乐:'zòu yuè',载客:'zài kè',专横:'zhuān hèng',湮没:'yān mò',空格:'kòng gé',铺垫:'pū diàn',良将:'liáng jiàng',哗啦:'huā lā',散漫:'sǎn màn',脱发:'tuō fà',送还:'sòng huán',埋没:'mái mò',累及:'lěi jí',薄雾:'bó wù',调离:'diào lí',舌苔:'shé tāi',机长:'jī zhǎng',栓塞:'shuān sè',配角:'pèi jué',切口:'qiē kǒu',创口:'chuāng kǒu',哈欠:'hā qian',实弹:'shí dàn',铺平:'pū píng',哈达:'hǎ dá',懒散:'lǎn sǎn',实干:'shí gàn',填空:'tián kòng',刁钻:'diāo zuān',乐师:'yuè shī',量变:'liàng biàn',诱降:'yòu xiáng',搪塞:'táng sè',征调:'zhēng diào',夹道:'jiā dào',干咳:'gān ké',止咳:'zhǐ ké',乐工:'yuè gōng',划过:'huá guò',着火:'zháo huǒ',更正:'gēng zhèng',给付:'jǐ fù',空子:'kòng zi',哪吒:'né zhā',正着:'zhèng zháo',刷子:'shuā zi',丧葬:'sāng zàng',夹带:'jiā dài',安分:'ān fèn',中意:'zhòng yì',长孙:'zhǎng sūn',校订:'jiào dìng',卷曲:'juǎn qū',载运:'zài yùn',投弹:'tóu dàn',柞蚕:'zuò cán',份量:'fèn liàng',调换:'diào huàn',了然:'liǎo rán',咧嘴:'liě zuǐ',典当:'diǎn dàng',寒假:'hán jià',长兄:'zhǎng xiōng',给水:'jǐ shuǐ',须发:'xū fà',枝干:'zhī gàn',属相:'shǔ xiàng',哄抢:'hōng qiǎng',刻划:'kè huà',塞子:'sāi zi',单干:'dān gàn',还乡:'huán xiāng',兆头:'zhào tou',寺观:'sì guàn',督率:'dū shuài',啊哈:'ā ha',割舍:'gē shě',抹布:'mā bù',好恶:'hào wù',下处:'xià chǔ',消长:'xiāo zhǎng',离间:'lí jiàn',准头:'zhǔn tou',校对:'jiào duì',什物:'shí wù',番禺:'pān yú',佛爷:'fó ye',吗啡:'mǎ fēi',盐分:'yán fèn',虎将:'hǔ jiàng',薄荷:'bò he',独处:'dú chǔ',空位:'kòng wèi',铺路:'pū lù',乌拉:'wū lā',调回:'diào huí',来头:'lái tou',闲散:'xián sǎn',胶卷:'jiāo juǎn',冒失:'mào shi',干劲:'gàn jìn',弦乐:'xián yuè',相国:'xiàng guó',丹参:'dān shēn',助兴:'zhù xìng',铺开:'pū kāi',次长:'cì zhǎng',发卡:'fà qiǎ',拮据:'jié jū',刹车:'shā chē',生发:'shēng fà',重播:'chóng bō',缝合:'féng hé',音量:'yīn liàng',少尉:'shào wèi',冲压:'chòng yā',苍劲:'cāng jìng',厚薄:'hòu báo',威吓:'wēi hè',外相:'wài xiàng',呼号:'hū háo',着迷:'zháo mí',挑担:'tiāo dàn',纹路:'wén lù',还俗:'huán sú',强横:'qiáng hèng',着数:'zhāo shù',降顺:'xiáng shùn',挑明:'tiǎo míng',眯缝:'mī feng',分内:'fèn nèi',更衣:'gēng yī',软和:'ruǎn huo',尽兴:'jìn xìng',号子:'hào zi',爪牙:'zhǎo yá',败将:'bài jiàng',猜中:'cāi zhòng',结扎:'jié zā',没空:'méi kòng',夹缝:'jiā fèng',拾掇:'shí duo',掺和:'chān huo',簸箕:'bò ji',电量:'diàn liàng',荷载:'hè zǎi',调式:'diào shì',处身:'chǔ shēn',打手:'dǎ shǒu',弹弓:'dàn gōng',横蛮:'hèng mán',能干:'néng gàn',校点:'jiào diǎn',加载:'jiā zài',干校:'gàn xiào',哄传:'hōng chuán',校注:'jiào zhù',淤塞:'yū sè',马扎:'mǎ zhá',月氏:'yuè zhī',高干:'gāo gàn',经传:'jīng zhuàn',曾孙:'zēng sūn',好斗:'hào dòu',关卡:'guān qiǎ',逃奔:'táo bèn',磨蹭:'mó ceng',牟取:'móu qǔ',颤栗:'zhàn lì',蚂蚱:'mà zha',撮合:'cuō he',趔趄:'liè qie',摔打:'shuāi dǎ',台子:'tái zi',分得:'fēn de',粘着:'nián zhuó',采邑:'cài yì',散装:'sǎn zhuāng',婀娜:'ē nuó',兴味:'xìng wèi',行头:'xíng tou',气量:'qì liàng',调运:'diào yùn',处治:'chǔ zhì',乐音:'yuè yīn',充塞:'chōng sè',恫吓:'dòng hè',论调:'lùn diào',相中:'xiāng zhòng',民乐:'mín yuè',炮仗:'pào zhang',丧服:'sāng fú',骁将:'xiāo jiàng',量刑:'liàng xíng',缝补:'féng bǔ',财会:'cái kuài',大干:'dà gàn',历数:'lì shǔ',校场:'jiào chǎng',塞北:'sài běi',识相:'shí xiàng',辱没:'rǔ mò',鲜亮:'xiān liàng',语塞:'yǔ sè',露脸:'lòu liǎn',凉快:'liáng kuai',腰杆:'yāo gǎn',溜达:'liū da',嘎嘎:'gā gā',公干:'gōng gàn',桔梗:'jié gěng',挑逗:'tiǎo dòu',看门:'kān mén',乐歌:'yuè gē',拓片:'tà piàn',挑动:'tiǎo dòng',准将:'zhǔn jiàng',遒劲:'qiú jìng',磨坊:'mò fáng',逶迤:'wēi yí',搅和:'jiǎo huo',摩挲:'mó suō',作弄:'zuò nòng',苗头:'miáo tou',打颤:'dǎ zhàn',大藏:'dà zàng',畜牲:'chù shēng',勾搭:'gōu da',树荫:'shù yīn',树杈:'shù chà',铁杆:'tiě gǎn',将相:'jiàng xiàng',份子:'fèn zi',视差:'shì chā',绿荫:'lǜ yīn',枪杆:'qiāng gǎn',缝纫:'féng rèn',愁闷:'chóu mèn',点将:'diǎn jiàng',华佗:'huà tuó',劲射:'jìng shè',箱笼:'xiāng lǒng',终了:'zhōng liǎo',鬓发:'bìn fà',结巴:'jiē ba',苦干:'kǔ gàn',看家:'kān jiā',正旦:'zhēng dàn',中肯:'zhòng kěn',厦门:'xià mén',东莞:'dōng guǎn',食量:'shí liàng',宫调:'gōng diào',间作:'jiàn zuò',弹片:'dàn piàn',差池:'chā chí',漂白:'piǎo bái',杠子:'gàng zi',调处:'tiáo chǔ',好动:'hào dòng',转炉:'zhuàn lú',屏气:'bǐng qì',夹板:'jiā bǎn',哀乐:'āi yuè',干道:'gàn dào',苦处:'kǔ chù',劈柴:'pǐ chái',长势:'zhǎng shì',天华:'tiān huá',共处:'gòng chǔ',校验:'jiào yàn',出塞:'chū sài',磨盘:'mò pán',萎靡:'wěi mǐ',奔丧:'bēn sāng',唱和:'chàng hè',大调:'dà diào',非分:'fēi fèn',钻营:'zuān yíng',夹子:'jiā zi',超载:'chāo zài',更始:'gēng shǐ',铃铛:'líng dang',披散:'pī sàn',发还:'fā huán',转轮:'zhuàn lún',横财:'hèng cái',泡桐:'pāo tóng',抛撒:'pāo sǎ',天呀:'tiān yā',糊糊:'hū hu',躯壳:'qū qiào',通量:'tōng liàng',奉还:'fèng huán',午觉:'wǔ jiào',闷棍:'mèn gùn',浪头:'làng tou',砚台:'yàn tái',油坊:'yóu fáng',学长:'xué zhǎng',过载:'guò zài',笔调:'bǐ diào',衣被:'yī bèi',畜产:'xù chǎn',调阅:'diào yuè',蛮干:'mán gàn',曾祖:'zēng zǔ',提干:'tí gàn',变调:'biàn diào',覆没:'fù mò',模子:'mú zi',乐律:'yuè lǜ',称心:'chèn xīn',木杆:'mù gān',重印:'chóng yìn',自省:'zì xǐng',提调:'tí diào',看相:'kàn xiàng',芋头:'yù tou',下切:'xià qiē',塞上:'sài shàng',铺张:'pū zhāng',藤蔓:'téng wàn',薄幸:'bó xìng',解数:'xiè shù',褪去:'tuì qù',霰弹:'xiàn dàn',柚木:'yóu mù',痕量:'hén liàng',雅乐:'yǎ yuè',号哭:'háo kū',诈降:'zhà xiáng',猪圈:'zhū juàn',咋舌:'zé shé',铣床:'xǐ chuáng',防弹:'fáng dàn',健将:'jiàn jiàng',丽水:'lí shuǐ',削发:'xuē fà',空当:'kòng dāng',多相:'duō xiàng',鲜见:'xiǎn jiàn',划桨:'huá jiǎng',载波:'zài bō',跳蚤:'tiào zao',俏皮:'qiào pí',吧嗒:'bā dā',结发:'jié fà',了断:'liǎo duàn',同调:'tóng diào',石磨:'shí mò',时差:'shí chā',鼻塞:'bí sè',挑子:'tiāo zi',推磨:'tuī mò',武侯:'wǔ hóu',抹煞:'mǒ shā',调转:'diào zhuǎn',籍没:'jí mò',还债:'huán zhài',调演:'diào yǎn',分划:'fēn huá',奇偶:'jī ǒu',断喝:'duàn hè',闷雷:'mèn léi',狼藉:'láng jí',饭量:'fàn liàng',还礼:'huán lǐ',转调:'zhuǎn diào',星相:'xīng xiàng',手相:'shǒu xiàng',配乐:'pèi yuè',盖头:'gài tou',连杆:'lián gǎn',簿记:'bù jì',刀把:'dāo bà',量词:'liàng cí',名角:'míng jué',步调:'bù diào',校本:'jiào běn',账簿:'zhàng bù',隽永:'juàn yǒng',稍为:'shāo wéi',易传:'yì zhuàn',乐谱:'yuè pǔ',牵累:'qiān lěi',答理:'dā li',喝斥:'hè chì',吟哦:'yín é',干渠:'gàn qú',海量:'hǎi liàng',精当:'jīng dàng',着床:'zhuó chuáng',月相:'yuè xiàng',庶几:'shù jī',宫观:'gōng guàn',论处:'lùn chǔ',征辟:'zhēng bì',厚朴:'hòu pò',介壳:'jiè qiào',吭哧:'kēng chī',咯血:'kǎ xiě',铺陈:'pū chén',重生:'chóng shēng',乐理:'yuè lǐ',哀号:'āi háo',藏历:'zàng lì',刚劲:'gāng jìng',削平:'xuē píng',浓荫:'nóng yīn',城垛:'chéng duǒ',当差:'dāng chāi',正传:'zhèng zhuàn',并处:'bìng chǔ',创面:'chuāng miàn',旦角:'dàn jué',薄礼:'bó lǐ',晃荡:'huàng dang',臊子:'sào zi',家什:'jiā shí',闷头:'mēn tóu',美发:'měi fà',度数:'dù shu',着凉:'zháo liáng',闯将:'chuǎng jiàng',几案:'jī àn',姘头:'pīn tou',差数:'chā shù',散碎:'sǎn suì',壅塞:'yōng sè',寒颤:'hán zhàn',牵强:'qiān qiǎng',无间:'wú jiàn',轮转:'lún zhuàn',号叫:'háo jiào',铺排:'pū pái',降伏:'xiáng fú',轧钢:'zhá gāng',东阿:'dōng ē',病假:'bìng jià',累加:'lěi jiā',梗塞:'gěng sè',弹夹:'dàn jiā',钻心:'zuān xīn',晃眼:'huǎng yǎn',魔爪:'mó zhǎo',标量:'biāo liàng',憋闷:'biē mèn',猜度:'cāi duó',处士:'chǔ shì',官差:'guān chāi',讨还:'tǎo huán',长门:'cháng mén',馏分:'liú fēn',里弄:'lǐ lòng',色相:'sè xiàng',雅兴:'yǎ xìng',角力:'jué lì',弹坑:'dàn kēng',枝杈:'zhī chà',夹具:'jiā jù',处刑:'chǔ xíng',悍将:'hàn jiàng',好学:'hào xué',好好:'hǎo hǎo',银发:'yín fà',扫把:'sào bǎ',法相:'fǎ xiàng',贵干:'guì gàn',供气:'gōng qì',空余:'kòng yú',捆扎:'kǔn zā',瘠薄:'jí bó',浆糊:'jiàng hu',嘎吱:'gā zhī',调令:'diào lìng',法帖:'fǎ tiè',淋病:'lìn bìng',调派:'diào pài',转盘:'zhuàn pán',供稿:'gōng gǎo',差官:'chāi guān',忧闷:'yōu mèn',教长:'jiào zhǎng',重唱:'chóng chàng',酒兴:'jiǔ xìng',乐坛:'yuè tán',花呢:'huā ní',叱喝:'chì hè',膀臂:'bǎng bì',得空:'dé kòng',转圈:'zhuàn quān',横暴:'hèng bào',哄抬:'hōng tái',引吭:'yǐn háng',载货:'zài huò',中计:'zhòng jì',官长:'guān zhǎng',相面:'xiàng miàn',看头:'kàn tou',盼头:'pàn tou',意兴:'yì xìng',军乐:'jūn yuè',累次:'lěi cì',骨嘟:'gǔ dū',燕赵:'yān zhào',报丧:'bào sāng',弥撒:'mí sa',挨斗:'ái dòu',扁舟:'piān zhōu',丑角:'chǒu jué',吊丧:'diào sāng',强将:'qiáng jiàng',重奏:'chóng zòu',发辫:'fà biàn',着魔:'zháo mó',着法:'zhāo fǎ',盛放:'shèng fàng',填塞:'tián sè',凶横:'xiōng hèng',稽首:'qǐ shǒu',碑帖:'bēi tiè',冲量:'chōng liàng',发菜:'fà cài',假发:'jiǎ fà',翻卷:'fān juǎn',小量:'xiǎo liàng',胶着:'jiāo zhuó',里子:'lǐ zi',调调:'diào diao',散兵:'sǎn bīng',高挑:'gāo tiǎo',播撒:'bō sǎ',夹心:'jiā xīn',扇动:'shān dòng',叨扰:'tāo rǎo',霓裳:'ní cháng',捻子:'niǎn zi',弥缝:'mí féng',撒布:'sǎ bù',场院:'cháng yuàn',省亲:'xǐng qīn',提拉:'tí lā',惯量:'guàn liàng',强逼:'qiáng bī',强征:'qiáng zhēng',晕车:'yùn chē',数道:'shù dào',带累:'dài lèi',拓本:'tà běn',嫌恶:'xián wù',宿将:'sù jiàng',龟裂:'jūn liè',缠夹:'chán jiā',发式:'fà shì',隔扇:'gé shàn',天分:'tiān fèn',癖好:'pǐ hào',四通:'sì tōng',白术:'bái zhú',划伤:'huá shāng',角斗:'jué dòu',听差:'tīng chāi',岁差:'suì chā',丧礼:'sāng lǐ',脉脉:'mò mò',削瘦:'xuē shòu',撒播:'sǎ bō',莎草:'suō cǎo',犍为:'qián wéi',调头:'diào tóu',龙卷:'lóng juǎn',外调:'wài diào',字帖:'zì tiè',卷发:'juǎn fà',揣度:'chuǎi duó',洋相:'yáng xiàng',散光:'sǎn guāng',骨碌:'gū lu',薄命:'bó mìng',笼头:'lóng tóu',咽炎:'yān yán',碌碡:'liù zhou',片儿:'piàn er',纤手:'qiàn shǒu',散体:'sǎn tǐ',内省:'nèi xǐng',强留:'qiáng liú',解送:'jiè sòng',反间:'fǎn jiàn',少壮:'shào zhuàng',留空:'liú kōng',告假:'gào jià',咳血:'ké xuè',薄暮:'bó mù',铺轨:'pū guǐ',磨削:'mó xuē',治丧:'zhì sāng',叉子:'chā zi',哄动:'hōng dòng',蛾子:'é zi',出落:'chū luò',股长:'gǔ zhǎng',贵处:'guì chù',还魂:'huán hún',例假:'lì jià',刹住:'shā zhù',身量:'shēn liàng',同好:'tóng hào',模量:'mó liàng',更生:'gēng shēng',服丧:'fú sāng',率直:'shuài zhí',字模:'zì mú',散架:'sǎn jià',答腔:'dā qiāng',交恶:'jiāo wù',薄情:'bó qíng',眼泡:'yǎn pāo',袅娜:'niǎo nuó',草垛:'cǎo duò',冲劲:'chòng jìn',呢喃:'ní nán',切中:'qiè zhòng',挑灯:'tiǎo dēng',还愿:'huán yuàn',激将:'jī jiàng',更鼓:'gēng gǔ',没药:'mò yào',败兴:'bài xìng',切面:'qiē miàn',散户:'sǎn hù',累进:'lěi jìn',背带:'bēi dài',秤杆:'chèng gǎn',碾坊:'niǎn fáng',簿子:'bù zi',扳手:'bān shǒu',铅山:'yán shān',儒将:'rú jiàng',重光:'chóng guāng',剪发:'jiǎn fà',长上:'zhǎng shàng',小传:'xiǎo zhuàn',压轴:'yā zhòu',弱冠:'ruò guàn',花卷:'huā juǎn',横祸:'hèng huò',夹克:'jiā kè',光晕:'guāng yùn',披靡:'pī mǐ',对调:'duì diào',夹持:'jiā chí',空额:'kòng é',平调:'píng diào',铺床:'pū chuáng',丧钟:'sāng zhōng',作乐:'zuò lè',少府:'shào fǔ',数数:'shuò shuò',奔头:'bèn tou',进给:'jìn jǐ',率性:'shuài xìng',乐子:'lè zi',绑扎:'bǎng zā',挑唆:'tiǎo suō',漂洗:'piǎo xǐ',夹墙:'jiā qiáng',咳喘:'ké chuǎn',乜斜:'miē xie',错处:'cuò chù',闷酒:'mèn jiǔ',时调:'shí diào',重孙:'chóng sūn',经幢:'jīng chuáng',圩场:'xū chǎng',调门:'diào mén',花头:'huā tóu',划拉:'huá la',套色:'tào shǎi',粗率:'cū shuài',相率:'xiāng shuài',款识:'kuǎn zhì',吁请:'yù qǐng',荫蔽:'yīn bì',文蛤:'wén gé',嘀嗒:'dī dā',调取:'diào qǔ',交差:'jiāo chāi',落子:'luò zǐ',相册:'xiàng cè',絮叨:'xù dao',落发:'luò fà',异相:'yì xiàng',浸没:'jìn mò',角抵:'jué dǐ',卸载:'xiè zài',春卷:'chūn juǎn',扎挣:'zhá zheng',畜养:'xù yǎng',吡咯:'bǐ luò',垛子:'duò zi',恶少:'è shào',发际:'fà jì',红苕:'hóng sháo',糨糊:'jiàng hu',哭丧:'kū sāng',稍息:'shào xī',晕船:'yùn chuán',校样:'jiào yàng',外差:'wài chā',脚爪:'jiǎo zhǎo',铺展:'pū zhǎn',芫荽:'yán sui',夹紧:'jiā jǐn',尿泡:'suī pào',丧乱:'sāng luàn',凶相:'xiōng xiàng',华发:'huá fà',打场:'dǎ cháng',云量:'yún liàng',正切:'zhèng qiē',划拳:'huá quán',划艇:'huá tǐng',评传:'píng zhuàn',拉纤:'lā qiàn',句读:'jù dòu',散剂:'sǎn jì',骨殖:'gǔ shi',塞音:'sè yīn',铺叙:'pū xù',阏氏:'yān zhī',冷颤:'lěng zhàn',煞住:'shā zhù',少男:'shào nán',管乐:'guǎn yuè',号啕:'háo táo',纳降:'nà xiáng',拥塞:'yōng sè',万乘:'wàn shèng',杆儿:'gǎn ér',葛藤:'gé téng',簿籍:'bù jí',皮夹:'pí jiā',校准:'jiào zhǔn',允当:'yǔn dàng',器量:'qì liàng',选调:'xuǎn diào',扮相:'bàn xiàng',干才:'gàn cái',基干:'jī gàn',割切:'gē qiē',国乐:'guó yuè',卡壳:'qiǎ ké',辟谷:'bì gǔ',磨房:'mò fáng',咿呀:'yī yā',芥末:'jiè mo',薄技:'bó jì',产假:'chǎn jià',诗兴:'shī xìng',重出:'chóng chū',转椅:'zhuàn yǐ',酌量:'zhuó liang',簿册:'bù cè',藏青:'zàng qīng',的士:'dī shì',调人:'diào rén',解元:'jiè yuán',茎干:'jīng gàn',巨量:'jù liàng',榔头:'láng tou',率真:'shuài zhēn',喷香:'pèn xiāng',锁钥:'suǒ yuè',虾蟆:'há má',相图:'xiàng tú',兴会:'xìng huì',灶头:'zào tóu',重婚:'chóng hūn',钻洞:'zuān dòng',忖度:'cǔn duó',党参:'dǎng shēn',调温:'diào wēn',杆塔:'gān tǎ',葛布:'gé bù',拱券:'gǒng xuàn',夹生:'jiā shēng',露馅:'lòu xiàn',恰切:'qià qiè',散见:'sǎn jiàn',哨卡:'shào qiǎ',烫发:'tàng fà',体量:'tǐ liàng',挺括:'tǐng kuò',系带:'jì dài',相士:'xiàng shì',羊圈:'yáng juàn',转矩:'zhuàn jǔ',吧台:'bā tái',苍术:'cāng zhú',菲薄:'fěi bó',蛤蚧:'gé jiè',蛤蜊:'gé lí',瓜蔓:'guā wàn',怪相:'guài xiàng',临帖:'lín tiè',女红:'nǚ gōng',刨床:'bào chuáng',翘楚:'qiáo chǔ',数九:'shǔ jiǔ',谈兴:'tán xìng',雄劲:'xióng jìng',扎染:'zā rǎn',遮荫:'zhē yīn',周正:'zhōu zhèng',赚头:'zhuàn tou',扒手:'pá shǒu',搀和:'chān huo',诚朴:'chéng pǔ',肚量:'dù liàng',干结:'gān jié',工尺:'gōng chě',家累:'jiā lěi',曲水:'qū shuǐ',沙参:'shā shēn',挑花:'tiǎo huā',阿门:'ā mén',背篓:'bēi lǒu',瘪三:'biē sān',裁处:'cái chǔ',创痛:'chuāng tòng',福相:'fú xiàng',更动:'gēng dòng',豪兴:'háo xìng',还阳:'huán yáng',还嘴:'huán zuǐ',借调:'jiè diào',卷云:'juǎn yún',流弹:'liú dàn',想头:'xiǎng tou',削价:'xuē jià',校阅:'jiào yuè',雅量:'yǎ liàng',别传:'bié zhuàn',薄酒:'bó jiǔ',春假:'chūn jià',发妻:'fà qī',哗哗:'huā huā',宽绰:'kuān chuo',了悟:'liǎo wù',切花:'qiē huā',审度:'shěn duó',应许:'yīng xǔ',转台:'zhuàn tái',仔猪:'zǐ zhū',裁量:'cái liáng',藏戏:'zàng xì',乘兴:'chéng xìng',绸缪:'chóu móu',摧折:'cuī zhé',调经:'tiáo jīng',调职:'diào zhí',缝缀:'féng zhuì',骨朵:'gū duǒ',核儿:'hú er',恒量:'héng liàng',还价:'huán jià',浑朴:'hún pǔ',苦差:'kǔ chāi',面糊:'miàn hù',煞车:'shā chē',省视:'xǐng shì',什锦:'shí jǐn',信差:'xìn chāi',余切:'yú qiē',攒眉:'cuán méi',炸糕:'zhá gāo',钻杆:'zuàn gǎn',扒灰:'pá huī',拌和:'bàn huò',长调:'cháng diào',大溜:'dà liù',抖搂:'dǒu lōu',飞转:'fēi zhuàn',干仗:'gàn zhàng',好胜:'hào shèng',画片:'huà piàn',搅混:'jiǎo hún',螺杆:'luó gǎn',木模:'mù mú',怒号:'nù háo',频数:'pín shù',无宁:'wú níng',遗少:'yí shào',邮差:'yóu chāi',占卦:'zhān guà',占星:'zhān xīng',重审:'chóng shěn',自量:'zì liàng',调防:'diào fáng',发廊:'fà láng',反调:'fǎn diào',缝子:'fèng zi',更夫:'gēng fū',骨子:'gǔ zi',光杆:'guāng gǎn',夹棍:'jiā gùn',居丧:'jū sāng',巨贾:'jù gǔ',看押:'kān yā',空转:'kōng zhuàn',量力:'liàng lì',炮烙:'páo luò',赔还:'péi huán',扑扇:'pū shān',散记:'sǎn jì',散件:'sǎn jiàn',删削:'shān xuē',射干:'shè gàn',条几:'tiáo jī',偷空:'tōu kòng',削壁:'xuē bì',校核:'jiào hé',阴干:'yīn gān',择菜:'zhái cài',重九:'chóng jiǔ',主调:'zhǔ diào',自禁:'zì jīn',吧唧:'bā jī',便溺:'biàn niào',词调:'cí diào',叨咕:'dáo gu',落枕:'lào zhěn',铺砌:'pū qì',刷白:'shuà bái',委靡:'wěi mǐ',系泊:'xì bó',相马:'xiàng mǎ',熨帖:'yù tiē',转筋:'zhuàn jīn',棒喝:'bàng hè',傧相:'bīn xiàng',镐头:'gǎo tóu',间苗:'jiàn miáo',乐池:'yuè chí',卖相:'mài xiàng',屏弃:'bǐng qì',铅弹:'qiān dàn',切变:'qiē biàn',请调:'qǐng diào',群氓:'qún méng',散板:'sǎn bǎn',省察:'xǐng chá',事假:'shì jià',纤绳:'qiàn shéng',重影:'chóng yǐng',耕种:'gēng zhòng',种地:'zhòng dì',种菜:'zhòng cài',栽种:'zāi zhòng',接种:'jiē zhòng',垦种:'kěn zhòng',种殖:'zhòng zhí',种瓜:'zhòng guā',种豆:'zhòng dòu',种树:'zhòng shù',睡着:'shuì zháo',笼子:'lóng zi',重启:'chóng qǐ',重整:'chóng zhěng',重弹:'chóng tán',重足:'chóng zú',重山:'chóng shān',重游:'chóng yóu',重峦:'chóng luán',爷爷:'yé ye',奶奶:'nǎi nai',姥爷:'lǎo ye',爸爸:'bà ba',妈妈:'mā ma',婶婶:'shěn shen',舅舅:'jiù jiu',姑姑:'gū gu',叔叔:'shū shu',姨夫:'yí fu',舅母:'jiù mu',姑父:'gū fu',姐夫:'jiě fu',婆婆:'pó po',公公:'gōng gong',舅子:'jiù zi',姐姐:'jiě jie',哥哥:'gē ge',妹妹:'mèi mei',妹夫:'mèi fu',姨子:'yí zi',宝宝:'bǎo bao',娃娃:'wá wa',孩子:'hái zi',日子:'rì zi',样子:'yàng zi',狮子:'shī zi',身子:'shēn zi',架子:'jià zi',嫂子:'sǎo zi',鼻子:'bí zi',亭子:'tíng zi',折子:'zhé zi',面子:'miàn zi',脖子:'bó zi',辈子:'bèi zi',帽子:'mào zi',拍子:'pāi zi',柱子:'zhù zi',辫子:'biàn zi',鸽子:'gē zi',房子:'fáng zi',丸子:'wán zi',摊子:'tān zi',牌子:'pái zi',胡子:'hú zi',鬼子:'guǐ zi',矮子:'ǎi zi',鸭子:'yā zi',小子:'xiǎo zi',影子:'yǐng zi',屋子:'wū zi',对子:'duì zi',点子:'diǎn zi',本子:'běn zi',种子:'zhǒng zi',儿子:'ér zi',兔子:'tù zi',骗子:'piàn zi',院子:'yuàn zi',猴子:'hóu zi',嗓子:'sǎng zi',侄子:'zhí zi',柿子:'shì zi',钳子:'qián zi',虱子:'shī zi',瓶子:'píng zi',豹子:'bào zi',筷子:'kuài zi',篮子:'lán zi',绳子:'shéng zi',嘴巴:'zuǐ ba',耳朵:'ěr duo',茄子:'qié zi',蚌埠:'bèng bù',崆峒:'kōng tóng',琵琶:'pí pa',蘑菇:'mó gu',葫芦:'hú lu',狐狸:'hú li',桔子:'jú zi',盒子:'hé zi',桌子:'zhuō zi',竹子:'zhú zi',师傅:'shī fu',衣服:'yī fu',袜子:'wà zi',杯子:'bēi zi',刺猬:'cì wei',麦子:'mài zi',队伍:'duì wu',知了:'zhī liǎo',鱼儿:'yú er',馄饨:'hún tun',灯笼:'dēng long',庄稼:'zhuāng jia',聪明:'cōng ming',镜子:'jìng zi',银子:'yín zi',盘子:'pán zi',了却:'liǎo què',力气:'lì qi',席子:'xí zi',林子:'lín zi',朝霞:'zhāo xiá',朝夕:'zhāo xī',朝气:'zhāo qì',翅膀:'chì bǎng',省长:'shěng zhǎng',臧否:'zāng pǐ',否泰:'pǐ tài',变得:'biàn de',丈夫:'zhàng fu',豆腐:'dòu fu',笔杆:'bǐ gǎn',枞阳:'zōng yáng',行人:'xíng rén',打着:'dǎ zhe',第一:'dì yī',万一:'wàn yī',之一:'zhī yī',得之:'dé zhī',统一:'tǒng yī',唯一:'wéi yī',专一:'zhuān yī',单一:'dān yī',如一:'rú yī',其一:'qí yī',合一:'hé yī',逐一:'zhú yī',周一:'zhōu yī',初一:'chū yī',研一:'yán yī',归一:'guī yī',假一:'jiǎ yī',闻一:'wén yī',了了:'liǎo liǎo',公了:'gōng liǎo',私了:'sī liǎo',一月:'yī yuè',一号:'yī hào',一级:'yī jí',一等:'yī děng',一哥:'yī gē',月一:'yuè yī',一一:'yī yī',二一:'èr yī',三一:'sān yī',四一:'sì yī',五一:'wǔ yī',六一:'liù yī',七一:'qī yī',八一:'bā yī',九一:'jiǔ yī',一〇:'yī líng',一零:'yī líng',一二:'yī èr',一三:'yī sān',一四:'yī sì',一五:'yī wǔ',一六:'yī liù',一七:'yī qī',一八:'yī bā',一九:'yī jiǔ',一又:'yī yòu',一饼:'yī bǐng',一楼:'yī lóu',为例:'wéi lì',为准:'wéi zhǔn',沧海:'cāng hǎi',难为:'nán wéi',责难:'zé nàn',患难:'huàn nàn',磨难:'mó nàn',大难:'dà nàn',刁难:'diāo nàn',殉难:'xùn nàn',落难:'luò nàn',罹难:'lí nàn',灾难:'zāi nàn',难民:'nàn mín',苦难:'kǔ nàn',危难:'wēi nàn',发难:'fā nàn',逃难:'táo nàn',避难:'bì nàn',遇难:'yù nàn',阻难:'zǔ nàn',厄难:'è nàn',徇难:'xùn nàn',空难:'kōng nàn',喜欢:'xǐ huan',朝朝:'zhāo zhāo',不行:'bù xíng',轧轧:'yà yà',弯曲:'wān qū',扭曲:'niǔ qū',曲直:'qū zhí',委曲:'wěi qū',酒曲:'jiǔ qū',曲径:'qū jìng',曲解:'qū jiě',歪曲:'wāi qū',曲线:'qū xiàn',曲阜:'qū fù',九曲:'jiǔ qū',曲折:'qū zhé',曲肱:'qū gōng',曲意:'qū yì',仡佬:'gē lǎo',};const Pattern2=Object.keys(DICT2).map((key)=>({zh:key,pinyin:DICT2[key],probability:2e-8,length:2,priority:Priority.Normal,dict:Symbol('dict2'),}));const DICT3={为什么:'wèi shén me',实际上:'shí jì shang',检察长:'jiǎn chá zhǎng',干什么:'gàn shén me',这会儿:'zhè huì er',尽可能:'jǐn kě néng',董事长:'dǒng shì zhǎng',了不起:'liǎo bù qǐ',参谋长:'cān móu zhǎng',朝鲜族:'cháo xiǎn zú',海内外:'hǎi nèi wài',禁不住:'jīn bú zhù',柏拉图:'bó lā tú',不在乎:'bú zài hu',洛杉矶:'luò shān jī',有点儿:'yǒu diǎn er',迫击炮:'pǎi jī pào',不得了:'bù dé liǎo',马尾松:'mǎ wěi sōng',运输量:'yùn shū liàng',发脾气:'fā pí qi',士大夫:'shì dà fū',鸭绿江:'yā lù jiāng',压根儿:'yà gēn er',对得起:'duì de qǐ',那会儿:'nà huì er',自个儿:'zì gě er',物理量:'wù lǐ liàng',怎么着:'zěn me zhāo',明晃晃:'míng huǎng huǎng',节假日:'jié jià rì',心里话:'xīn lǐ huà',发行量:'fā xíng liàng',兴冲冲:'xìng chōng chōng',分子量:'fēn zǐ liàng',国子监:'guó zǐ jiàn',老大难:'lǎo dà nán',党内外:'dǎng nèi wài',这么着:'zhè me zhāo',少奶奶:'shào nǎi nai',暗地里:'àn dì lǐ',更年期:'gēng nián qī',工作量:'gōng zuò liàng',背地里:'bèi dì lǐ',山里红:'shān li hóng',好好儿:'hǎo hāo er',交响乐:'jiāo xiǎng yuè',好意思:'hǎo yì si',吐谷浑:'tǔ yù hún',没意思:'méi yì si',理发师:'lǐ fà shī',塔什干:'tǎ shí gān',充其量:'chōng qí liàng',靠得住:'kào de zhù',车行道:'chē xíng dào',人行道:'rén xíng dào',中郎将:'zhōng láng jiàng',照明弹:'zhào míng dàn',烟幕弹:'yān mù dàn',没奈何:'mò nài hé',乱哄哄:'luàn hōng hōng',惠更斯:'huì gēng sī',载重量:'zài zhòng liàng',瞧得起:'qiáo de qǐ',纪传体:'jì zhuàn tǐ',阿房宫:'ē páng gōng',卷心菜:'juǎn xīn cài',戏班子:'xì bān zi',过得去:'guò de qù',花岗石:'huā gāng shí',外甥女:'wài sheng nǚ',团团转:'tuán tuán zhuàn',大堡礁:'dà bǎo jiāo',燃烧弹:'rán shāo dàn',劳什子:'láo shí zi',摇滚乐:'yáo gǔn yuè',夹竹桃:'jiā zhú táo',闹哄哄:'nào hōng hōng',三连冠:'sān lián guàn',重头戏:'zhòng tóu xì',二人转:'èr rén zhuàn',节骨眼:'jiē gǔ yǎn',知识面:'zhī shi miàn',护士长:'hù shi zhǎng',信号弹:'xìn hào dàn',干电池:'gān diàn chí',枪杆子:'qiāng gǎn zi',哭丧棒:'kū sāng bàng',鼻咽癌:'bí yān ái',瓦岗军:'wǎ gāng jūn',买得起:'mǎi de qǐ',癞蛤蟆:'lài há ma',脊梁骨:'jǐ liang gǔ',子母弹:'zǐ mǔ dàn',开小差:'kāi xiǎo chāi',女强人:'nǚ qiáng rén',英雄传:'yīng xióng zhuàn',爵士乐:'jué shì yuè',说笑话:'shuō xiào hua',碰头会:'pèng tóu huì',玻璃钢:'bō li gāng',曳光弹:'yè guāng dàn',少林拳:'shào lín quán',咏叹调:'yǒng tàn diào',少先队:'shào xiān duì',灵长目:'líng zhǎng mù',对着干:'duì zhe gàn',蒙蒙亮:'méng méng liàng',软骨头:'ruǎn gǔ tou',铺盖卷:'pū gài juǎn',和稀泥:'huò xī ní',背黑锅:'bēi hēi guō',红彤彤:'hóng tōng tōng',武侯祠:'wǔ hóu cí',打哆嗦:'dǎ duō suo',户口簿:'hù kǒu bù',马尾藻:'mǎ wěi zǎo',夜猫子:'yè māo zi',打手势:'dǎ shǒu shì',龙王爷:'lóng wáng yé',气头上:'qì tóu shang',糊涂虫:'hú tu chóng',笔杆子:'bǐ gǎn zi',占便宜:'zhàn pián yi',打主意:'dǎ zhǔ yì',多弹头:'duō dàn tóu',露一手:'lòu yì shǒu',堰塞湖:'yàn sè hú',保得住:'bǎo de zhù',趵突泉:'bào tū quán',奥得河:'ào de hé',司务长:'sī wù zhǎng',禁不起:'jīn bù qǐ',什刹海:'shí chà hǎi',莲花落:'lián huā lào',见世面:'jiàn shì miàn',豁出去:'huō chū qù',电位差:'diàn wèi chā',挨个儿:'āi gè er',那阵儿:'nà zhèn er',肺活量:'fèi huó liàng',大师傅:'dà shī fu',掷弹筒:'zhì dàn tǒng',打呼噜:'dǎ hū lu',广渠门:'ān qú mén',未见得:'wèi jiàn dé',大婶儿:'dà shěn er',谈得来:'tán de lái',脚丫子:'jiǎo yā zi',空包弹:'kōng bāo dàn',窝里斗:'wō li dòu',弹着点:'dàn zhuó diǎn',个头儿:'gè tóu er',看得起:'kàn de qǐ',糊涂账:'hú tu zhàng',大猩猩:'dà xīng xing',禁得起:'jīn de qǐ',法相宗:'fǎ xiàng zōng',可怜相:'kě lián xiàng',吃得下:'chī de xià',汉堡包:'hàn bǎo bāo',闹嚷嚷:'nào rāng rāng',数来宝:'shǔ lái bǎo',合得来:'hé de lái',干性油:'gān xìng yóu',闷葫芦:'mèn hú lu',呱呱叫:'guā guā jiào',西洋参:'xī yáng shēn',林荫道:'lín yīn dào',拉家常:'lā jiā cháng',卷铺盖:'juǎn pū gài',过得硬:'guò de yìng',飞将军:'fēi jiāng jūn',挑大梁:'tiǎo dà liáng',哈巴狗:'hǎ ba gǒu',过家家:'guò jiā jiā',催泪弹:'cuī lèi dàn',雨夹雪:'yǔ jiā xuě',敲竹杠:'qiāo zhú gàng',列车长:'liè chē zhǎng',华达呢:'huá dá ní',犯得着:'fàn de zháo',土疙瘩:'tǔ gē da',煞风景:'shā fēng jǐng',轻量级:'qīng liàng jí',羞答答:'xiū dā dā',石子儿:'shí zǐ er',达姆弹:'dá mǔ dàn',科教片:'kē jiào piān',侃大山:'kǎn dà shān',丁点儿:'dīng diǎn er',吃得消:'chī de xiāo',捋虎须:'luō hǔ xū',高丽参:'gāo lí shēn',众生相:'zhòng shēng xiàng',咽峡炎:'yān xiá yán',禁得住:'jīn de zhù',吃得开:'chī de kāi',柞丝绸:'zuò sī chóu',应声虫:'yìng shēng chóng',数得着:'shǔ de zháo',傻劲儿:'shǎ jìn er',铅玻璃:'qiān bō li',可的松:'kě dì sōng',划得来:'huá de lái',晕乎乎:'yūn hū hū',屎壳郎:'shǐ ke làng',尥蹶子:'liào juě zi',藏红花:'zàng hóng huā',闷罐车:'mèn guàn chē',卡脖子:'qiǎ bó zi',红澄澄:'hóng deng deng',赶得及:'gǎn de jí',当间儿:'dāng jiàn er',露马脚:'lòu mǎ jiǎo',鸡内金:'jī nèi jīn',犯得上:'fàn de shàng',钉齿耙:'dīng chǐ bà',饱和点:'bǎo hé diǎn',龙爪槐:'lóng zhǎo huái',喝倒彩:'hè dào cǎi',定冠词:'dìng guàn cí',担担面:'dàn dan miàn',吃得住:'chī de zhù',爪尖儿:'zhuǎ jiān er',支着儿:'zhī zhāo er',折跟头:'zhē gēn tou',阴着儿:'yīn zhāo er',烟卷儿:'yān juǎn er',宣传弹:'xuān chuán dàn',信皮儿:'xìn pí er',弦切角:'xián qiē jiǎo',缩砂密:'sù shā mì',说得来:'shuō de lái',水漂儿:'shuǐ piāo er',耍笔杆:'shuǎ bǐ gǎn',数得上:'shǔ de shàng',数不着:'shǔ bù zháo',数不清:'shǔ bù qīng',什件儿:'shí jiàn er',生死簿:'shēng sǐ bù',扇风机:'shān fēng jī',撒呓挣:'sā yì zheng',日记簿:'rì jì bù',热得快:'rè de kuài',亲家公:'qìng jia gōng',奇函数:'jī hán shù',拍纸簿:'pāi zhǐ bù',努劲儿:'nǔ jìn er',泥娃娃:'ní wá wa',内切圆:'nèi qiē yuán',哪会儿:'nǎ huì er',闷头儿:'mēn tóu er',没谱儿:'méi pǔ er',铆劲儿:'mǎo jìn er',溜肩膀:'liū jiān bǎng',了望台:'liào wàng tái',老来少:'lǎo lái shào',坤角儿:'kūn jué er',考勤簿:'kǎo qín bù',卷笔刀:'juǎn bǐ dāo',进给量:'jìn jǐ liàng',划不来:'huá bù lái',汗褂儿:'hàn guà er',鼓囊囊:'gǔ nāng nāng',够劲儿:'gòu jìn er',公切线:'gōng qiē xiàn',搁得住:'gé de zhù',赶浪头:'gǎn làng tóu',赶得上:'gǎn de shàng',干酵母:'gān jiào mǔ',嘎渣儿:'gā zhā er',嘎嘣脆:'gā bēng cuì',对得住:'duì de zhù',逗闷子:'dòu mèn zi',顶呱呱:'dǐng guā guā',滴溜儿:'dī liù er',大轴子:'dà zhòu zi',打板子:'dǎ bǎn zi',寸劲儿:'cùn jìn er',醋劲儿:'cù jìn er',揣手儿:'chuāi shǒu er',冲劲儿:'chòng jìn er',吃得来:'chī de lái',不更事:'bù gēng shì',奔头儿:'bèn tou er',百夫长:'bǎi fū zhǎng',娃娃亲:'wá wa qīn',死劲儿:'sǐ jìn er',骨朵儿:'gū duǒ er',功劳簿:'gōng láo bù',都江堰:'dū jiāng yàn',一担水:'yí dàn shuǐ',否极泰:'pǐ jí tài',泰来否:'tài lái pǐ',咳特灵:'ké tè líng',开户行:'kāi hù háng',郦食其:'lì yì jī',花事了:'huā shì liǎo',一更更:'yì gēng gēng',一重山:'yì chóng shān',风一更:'fēng yì gēng',雪一更:'xuě yì gēng',归一码:'guī yì mǎ',星期一:'xīng qī yī',礼拜一:'lǐ bài yī',一季度:'yī jì dù',一月一:'yī yuè yī',一字马:'yī zì mǎ',一是一:'yī shì yī',一次方:'yī cì fāng',一阳指:'yī yáng zhǐ',一字决:'yī zì jué',一年级:'yī nián jí',一不做:'yī bú zuò',屈戌儿:'qū qu ér',难为水:'nán wéi shuǐ',难为情:'nán wéi qíng',行一行:'xíng yì háng',别别的:'biè bié de',干哪行:'gàn nǎ háng',干一行:'gàn yì háng',曲别针:'qū bié zhēn',};const Pattern3=Object.keys(DICT3).map((key)=>({zh:key,pinyin:DICT3[key],probability:2e-8,length:3,priority:Priority.Normal,dict:Symbol('dict3'),}));const DICT4={成吉思汗:"chéng jí sī hán",四通八达:"sì tōng bā dá",一模一样:"yì mú yí yàng",青藏高原:"qīng zàng gāo yuán",阿弥陀佛:"ē mí tuó fó",解放思想:"jiè fàng sī xiǎng",所作所为:"suǒ zuò suǒ wéi",迷迷糊糊:"mí mí hu hū",荷枪实弹:"hè qiāng shí dàn",兴高采烈:"xìng gāo cǎi liè",无能为力:"wú néng wéi lì",布鲁塞尔:"bù lǔ sài ěr",为所欲为:"wéi suǒ yù wéi",克什米尔:"kè shí mǐ ěr",没完没了:"méi wán méi liǎo",不为人知:"bù wéi rén zhī",结结巴巴:"jiē jiē bā bā",前仆后继:"qián pū hòu jì",铺天盖地:"pū tiān gài dì",直截了当:"zhí jié liǎo dàng",供不应求:"gōng bú yìng qiú",御史大夫:"yù shǐ dà fū",不为瓦全:"bù wéi wǎ quán",不可收拾:"bù kě shōu shi",胡作非为:"hú zuò fēi wéi",分毫不差:"fēn háo bú chà",模模糊糊:"mó mó hu hū",不足为奇:"bù zú wéi qí",悄无声息:"qiǎo wú shēng xī",了如指掌:"liǎo rú zhǐ zhǎng",深恶痛绝:"shēn wù tòng jué",高高兴兴:"gāo gāo xìng xìng",唉声叹气:"āi shēng tàn qì",汉藏语系:"hàn zàng yǔ xì",处心积虑:"chǔ xīn jī lǜ",泣不成声:"qì bù chéng shēng",半夜三更:"bàn yè sān gēng",失魂落魄:"shī hún luò pò",二十八宿:"èr shí bā xiù",转来转去:"zhuàn lái zhuàn qù",数以万计:"shǔ yǐ wàn jì",相依为命:"xiāng yī wéi mìng",恋恋不舍:"liàn liàn bù shě",屈指可数:"qū zhǐ kě shǔ",神出鬼没:"shén chū guǐ mò",结结实实:"jiē jiē shí shí",有的放矢:"yǒu dì fàng shǐ",叽哩咕噜:"jī lǐ gū lū",调兵遣将:"diào bīng qiǎn jiàng",载歌载舞:"zài gē zài wǔ",转危为安:"zhuǎn wēi wéi ān",踏踏实实:"tā tā shi shí",桑给巴尔:"sāng jǐ bā ěr",装模作样:"zhuāng mú zuò yàng",见义勇为:"jiàn yì yǒng wéi",相差无几:"xiāng chā wú jǐ",叹为观止:"tàn wéi guān zhǐ",闷闷不乐:"mèn mèn bú lè",喜怒哀乐:"xǐ nù āi lè",鲜为人知:"xiǎn wéi rén zhī",张牙舞爪:"zhāng yá wǔ zhǎo",为非作歹:"wéi fēi zuò dǎi",含糊其辞:"hán hú qí cí",疲于奔命:"pí yú bēn mìng",勉为其难:"miǎn wéi qí nán",依依不舍:"yī yī bù shě",顶头上司:"dǐng tóu shàng si",不着边际:"bù zhuó biān jì",大模大样:"dà mú dà yàng",寻欢作乐:"xún huān zuò lè",一走了之:"yì zǒu liǎo zhī",字里行间:"zì lǐ háng jiān",含含糊糊:"hán hán hu hū",恰如其分:"qià rú qí fèn",破涕为笑:"pò tì wéi xiào",深更半夜:"shēn gēng bàn yè",千差万别:"qiān chā wàn bié",数不胜数:"shǔ bú shèng shǔ",据为己有:"jù wéi jǐ yǒu",天旋地转:"tiān xuán dì zhuàn",养尊处优:"yǎng zūn chǔ yōu",玻璃纤维:"bō li xiān wéi",吵吵闹闹:"chāo chao nào nào",晕头转向:"yūn tóu zhuàn xiàng",土生土长:"tǔ shēng tǔ zhǎng",宁死不屈:"nìng sǐ bù qū",不省人事:"bù xǐng rén shì",尽力而为:"jìn lì ér wéi",精明强干:"jīng míng qiáng gàn",唠唠叨叨:"láo lao dāo dāo",叽叽喳喳:"jī ji zhā zhā",功不可没:"gōng bù kě mò",锲而不舍:"qiè ér bù shě",排忧解难:"pái yōu jiě nàn",稀里糊涂:"xī li hú tú",各有所长:"gè yǒu suǒ cháng",的的确确:"dí dí què què",哄堂大笑:"hōng táng dà xiào",听而不闻:"tīng ér bù wén",刀耕火种:"dāo gēng huǒ zhòng",内分泌腺:"nèi fèn mì xiàn",化险为夷:"huà xiǎn wéi yí",百发百中:"bǎi fā bǎi zhòng",重见天日:"chóng jiàn tiān rì",反败为胜:"fǎn bài wéi shèng",一了百了:"yì liǎo bǎi liǎo",大大咧咧:"dà da liē liē",心急火燎:"xīn jí huǒ liǎo",粗心大意:"cū xīn dà yi",鸡皮疙瘩:"jī pí gē da",夷为平地:"yí wéi píng dì",日积月累:"rì jī yuè lěi",设身处地:"shè shēn chǔ dì",投其所好:"tóu qí suǒ hào",间不容发:"jiān bù róng fà",人满为患:"rén mǎn wéi huàn",穷追不舍:"qióng zhuī bù shě",为时已晚:"wéi shí yǐ wǎn",如数家珍:"rú shǔ jiā zhēn",心里有数:"xīn lǐ yǒu shù",以牙还牙:"yǐ yá huán yá",神不守舍:"shén bù shǒu shě",孟什维克:"mèng shí wéi kè",各自为战:"gè zì wéi zhàn",怨声载道:"yuàn shēng zài dào",救苦救难:"jiù kǔ jiù nàn",好好先生:"hǎo hǎo xiān sheng",怪模怪样:"guài mú guài yàng",抛头露面:"pāo tóu lù miàn",游手好闲:"yóu shǒu hào xián",无所不为:"wú suǒ bù wéi",调虎离山:"diào hǔ lí shān",步步为营:"bù bù wéi yíng",好大喜功:"hào dà xǐ gōng",众矢之的:"zhòng shǐ zhī dì",长生不死:"cháng shēng bù sǐ",蔚为壮观:"wèi wéi zhuàng guān",不可胜数:"bù kě shèng shǔ",鬼使神差:"guǐ shǐ shén chāi",洁身自好:"jié shēn zì hào",敢作敢为:"gǎn zuò gǎn wéi",茅塞顿开:"máo sè dùn kāi",走马换将:"zǒu mǎ huàn jiàng",为时过早:"wéi shí guò zǎo",为人师表:"wéi rén shī biǎo",阴差阳错:"yīn chā yáng cuò",油腔滑调:"yóu qiāng huá diào",重蹈覆辙:"chóng dǎo fù zhé",骂骂咧咧:"mà ma liē liē",絮絮叨叨:"xù xù dāo dāo",如履薄冰:"rú lǚ bó bīng",损兵折将:"sǔn bīng zhé jiàng",拐弯抹角:"guǎi wān mò jiǎo",像模像样:"xiàng mú xiàng yàng",供过于求:"gōng guò yú qiú",开花结果:"kāi huā jiē guǒ",仔仔细细:"zǐ zǐ xì xì",川藏公路:"chuān zàng gōng lù",河北梆子:"hé běi bāng zi",长年累月:"cháng nián lěi yuè",正儿八经:"zhèng er bā jīng",不识抬举:"bù shí tái ju",重振旗鼓:"chóng zhèn qí gǔ",气息奄奄:"qì xī yān yān",紧追不舍:"jǐn zhuī bù shě",服服帖帖:"fú fu tiē tiē",强词夺理:"qiǎng cí duó lǐ",噼里啪啦:"pī li pā lā",人才济济:"rén cái jǐ jǐ",发人深省:"fā rén shēn xǐng",不足为凭:"bù zú wéi píng",为富不仁:"wéi fù bù rén",连篇累牍:"lián piān lěi dú",呼天抢地:"hū tiān qiāng dì",落落大方:"luò luò dà fāng",自吹自擂:"zì chuī zì léi",乐善好施:"lè shàn hào shī",以攻为守:"yǐ gōng wéi shǒu",磨磨蹭蹭:"mó mó cèng cèng",削铁如泥:"xuē tiě rú ní",助纣为虐:"zhù zhòu wéi nüè",以退为进:"yǐ tuì wéi jìn",嘁嘁喳喳:"qī qī chā chā",枪林弹雨:"qiāng lín dàn yǔ",令人发指:"lìng rén fà zhǐ",转败为胜:"zhuǎn bài wéi shèng",转弯抹角:"zhuǎn wān mò jiǎo",在劫难逃:"zài jié nán táo",正当防卫:"zhèng dàng fáng wèi",不足为怪:"bù zú wéi guài",难兄难弟:"nàn xiōng nàn dì",咿咿呀呀:"yī yī yā yā",弹尽粮绝:"dàn jìn liáng jué",阿谀奉承:"ē yú fèng chéng",稀里哗啦:"xī li huā lā",返老还童:"fǎn lǎo huán tóng",好高骛远:"hào gāo wù yuǎn",鹿死谁手:"lù sǐ shéi shǒu",差强人意:"chā qiáng rén yì",大吹大擂:"dà chuī dà léi",成家立业:"chéng jiā lì yè",自怨自艾:"zì yuàn zì yì",负债累累:"fù zhài lěi lěi",古为今用:"gǔ wéi jīn yòng",入土为安:"rù tǔ wéi ān",下不为例:"xià bù wéi lì",一哄而上:"yì hōng ér shàng",没头苍蝇:"méi tóu cāng ying",天差地远:"tiān chā dì yuǎn",风卷残云:"fēng juǎn cán yún",多灾多难:"duō zāi duō nàn",乳臭未干:"rǔ xiù wèi gān",行家里手:"háng jiā lǐ shǒu",狼狈为奸:"láng bèi wéi jiān",处变不惊:"chǔ biàn bù jīng",一唱一和:"yí chàng yí hè",一念之差:"yí niàn zhī chā",金蝉脱壳:"jīn chán tuō qiào",滴滴答答:"dī dī dā dā",硕果累累:"shuò guǒ léi léi",好整以暇:"hào zhěng yǐ xiá",红得发紫:"hóng de fā zǐ",传为美谈:"chuán wéi měi tán",富商大贾:"fù shāng dà gǔ",四海为家:"sì hǎi wéi jiā",了若指掌:"liǎo ruò zhǐ zhǎng",大有可为:"dà yǒu kě wéi",出头露面:"chū tóu lù miàn",鼓鼓囊囊:"gǔ gu nāng nāng",窗明几净:"chuāng míng jī jìng",泰然处之:"tài rán chǔ zhī",怒发冲冠:"nù fà chōng guān",有机玻璃:"yǒu jī bō li",骨头架子:"gǔ tou jià zi",义薄云天:"yì bó yún tiān",一丁点儿:"yī dīng diǎn er",时来运转:"shí lái yùn zhuǎn",陈词滥调:"chén cí làn diào",化整为零:"huà zhěng wéi líng",火烧火燎:"huǒ shāo huǒ liǎo",干脆利索:"gàn cuì lì suǒ",吊儿郎当:"diào er láng dāng",广种薄收:"guǎng zhòng bó shōu",种瓜得瓜:"zhòng guā dé guā",种豆得豆:"zhòng dòu dé dòu",难舍难分:"nán shě nán fēn",歃血为盟:"shà xuè wéi méng",奋发有为:"fèn fā yǒu wéi",阴错阳差:"yīn cuò yáng chā",东躲西藏:"dōng duǒ xī cáng",烟熏火燎:"yān xūn huǒ liǎo",钻牛角尖:"zuān niú jiǎo jiān",乔装打扮:"qiáo zhuāng dǎ bàn",改弦更张:"gǎi xián gēng zhāng",河南梆子:"hé nán bāng zi",好吃懒做:"hào chī lǎn zuò",何乐不为:"hé lè bù wéi",大出风头:"dà chū fēng tóu",攻城掠地:"gōng chéng lüè dì",漂漂亮亮:"piào piào liang liang",折衷主义:"zhé zhōng zhǔ yì",大马哈鱼:"dà mǎ hǎ yú",绿树成荫:"lǜ shù chéng yīn",率先垂范:"shuài xiān chuí fàn",家长里短:"jiā cháng lǐ duǎn",宽大为怀:"kuān dà wéi huái",左膀右臂:"zuǒ bǎng yòu bì",一笑了之:"yí xiào liǎo zhī",天下为公:"tiān xià wéi gōng",还我河山:"huán wǒ hé shān",何足为奇:"hé zú wéi qí",好自为之:"hǎo zì wéi zhī",风姿绰约:"fēng zī chuò yuē",大雨滂沱:"dà yǔ pāng tuó",传为佳话:"chuán wéi jiā huà",吃里扒外:"chī lǐ pá wài",重操旧业:"chóng cāo jiù yè",小家子气:"xiǎo jiā zi qì",少不更事:"shào bù gēng shì",难分难舍:"nán fēn nán shě",添砖加瓦:"tiān zhuān jiā wǎ",是非分明:"shì fēi fēn míng",舍我其谁:"shě wǒ qí shuí",偏听偏信:"piān tīng piān xìn",量入为出:"liàng rù wéi chū",降龙伏虎:"xiáng lóng fú hǔ",钢化玻璃:"gāng huà bō li",正中下怀:"zhèng zhòng xià huái",以身许国:"yǐ shēn xǔ guó",一语中的:"yì yǔ zhòng dì",丧魂落魄:"sàng hún luò pò",三座大山:"sān zuò dà shān",济济一堂:"jǐ jǐ yì táng",好事之徒:"hào shì zhī tú",干净利索:"gàn jìng lì suǒ",出将入相:"chū jiàng rù xiàng",袅袅娜娜:"niǎo niǎo nuó nuó",狐狸尾巴:"hú li wěi ba",好逸恶劳:"hào yì wù láo",大而无当:"dà ér wú dàng",打马虎眼:"dǎ mǎ hu yǎn",板上钉钉:"bǎn shàng dìng dīng",吆五喝六:"yāo wǔ hè liù",虾兵蟹将:"xiā bīng xiè jiàng",水调歌头:"shuǐ diào gē tóu",数典忘祖:"shǔ diǎn wàng zǔ",人事不省:"rén shì bù xǐng",曲高和寡:"qǔ gāo hè guǎ",屡教不改:"lǚ jiào bù gǎi",互为因果:"hù wéi yīn guǒ",互为表里:"hù wéi biǎo lǐ",厚此薄彼:"hòu cǐ bó bǐ",过关斩将:"guò guān zhǎn jiàng",疙疙瘩瘩:"gē ge dā dā",大腹便便:"dà fù pián pián",走为上策:"zǒu wéi shàng cè",冤家对头:"yuān jia duì tóu",有隙可乘:"yǒu xì kě chèng",一鳞半爪:"yì lín bàn zhǎo",片言只语:"piàn yán zhǐ yǔ",开花结实:"kāi huā jié shí",经年累月:"jīng nián lěi yuè",含糊其词:"hán hú qí cí",寡廉鲜耻:"guǎ lián xiǎn chǐ",成年累月:"chéng nián lěi yuè",不徇私情:"bú xùn sī qíng",不当人子:"bù dāng rén zǐ",膀大腰圆:"bǎng dà yāo yuán",指腹为婚:"zhǐ fù wéi hūn",这么点儿:"zhè me diǎn er",意兴索然:"yì xīng suǒ rán",绣花枕头:"xiù huā zhěn tou",无的放矢:"wú dì fàng shǐ",望闻问切:"wàng wén wèn qiè",舍己为人:"shě jǐ wèi rén",穷年累月:"qióng nián lěi yuè",排难解纷:"pái nàn jiě fēn",处之泰然:"chǔ zhī tài rán",指鹿为马:"zhǐ lù wéi mǎ",危如累卵:"wēi rú lěi luǎn",天兵天将:"tiān bīng tiān jiàng",舍近求远:"shě jìn qiú yuǎn",南腔北调:"nán qiāng běi diào",苦中作乐:"kǔ zhōng zuò lè",厚积薄发:"hòu jī bó fā",臭味相投:"xiù wèi xiāng tóu",长幼有序:"zhǎng yòu yǒu xù",逼良为娼:"bī liáng wéi chāng",悲悲切切:"bēi bēi qiè qiē",败军之将:"bài jūn zhī jiàng",欺行霸市:"qī háng bà shì",削足适履:"xuē zú shì lǚ",先睹为快:"xiān dǔ wéi kuài",啼饥号寒:"tí jī háo hán",疏不间亲:"shū bú jiàn qīn",神差鬼使:"shén chāi guǐ shǐ",敲敲打打:"qiāo qiāo dǎ dǎ",平铺直叙:"píng pū zhí xù",没头没尾:"méi tóu mò wěi",寥寥可数:"liáo liáo kě shǔ",哼哈二将:"hēng hā èr jiàng",鹤发童颜:"hè fà tóng yán",各奔前程:"gè bèn qián chéng",弹无虚发:"dàn wú xū fā",大人先生:"dà rén xiān sheng",与民更始:"yǔ mín gēng shǐ",树碑立传:"shù bēi lì zhuàn",是非得失:"shì fēi dé shī",实逼处此:"shí bī chǔ cǐ",塞翁失马:"sài wēng shī mǎ",日薄西山:"rì bó xī shān",切身体会:"qiè shēn tǐ huì",片言只字:"piàn yán zhǐ zì",跑马卖解:"pǎo mǎ mài xiè",宁折不弯:"nìng zhé bù wān",零零散散:"líng líng sǎn sǎn",量体裁衣:"liàng tǐ cái yī",连中三元:"lián zhòng sān yuán",礼崩乐坏:"lǐ bēng yuè huài",不为已甚:"bù wéi yǐ shèn",转悲为喜:"zhuǎn bēi wéi xǐ",以眼还眼:"yǐ yǎn huán yǎn",蔚为大观:"wèi wéi dà guān",未为不可:"wèi wéi bù kě",童颜鹤发:"tóng yán hè fà",朋比为奸:"péng bǐ wéi jiān",莫此为甚:"mò cǐ wéi shèn",夹枪带棒:"jiā qiāng dài bàng",富商巨贾:"fù shāng jù jiǎ",淡然处之:"dàn rán chǔ zhī",箪食壶浆:"dān shí hú jiāng",创巨痛深:"chuāng jù tòng shēn",草长莺飞:"cǎo zhǎng yīng fēi",坐视不救:"zuò shī bú jiù",以己度人:"yǐ jǐ duó rén",随行就市:"suí háng jiù shì",文以载道:"wén yǐ zài dào",文不对题:"wén bú duì tí",铁板钉钉:"tiě bǎn dìng dīng",身体发肤:"shēn tǐ fà fū",缺吃少穿:"quē chī shǎo chuān",目无尊长:"mù wú zūn zhǎng",吉人天相:"jí rén tiān xiàng",毁家纾难:"huǐ jiā shū nàn",钢筋铁骨:"gāng jīn tiě gǔ",丢卒保车:"diū zú bǎo jū",丢三落四:"diū sān là sì",闭目塞听:"bì mù sè tīng",削尖脑袋:"xuē jiān nǎo dài",为非作恶:"wéi fēi zuò è",人才难得:"rén cái nán dé",情非得已:"qíng fēi dé yǐ",切中要害:"qiè zhòng yào hài",火急火燎:"huǒ jí huǒ liǎo",画地为牢:"huà dì wéi láo",好酒贪杯:"hào jiǔ tān bēi",长歌当哭:"cháng gē dàng kū",载沉载浮:"zài chén zài fú",遇难呈祥:"yù nàn chéng xiáng",榆木疙瘩:"yú mù gē da",以邻为壑:"yǐ lín wéi hè",洋为中用:"yáng wéi zhōng yòng",言为心声:"yán wéi xīn shēng",言必有中:"yán bì yǒu zhòng",图穷匕见:"tú qióng bǐ xiàn",滂沱大雨:"páng tuó dà yǔ",目不暇给:"mù bù xiá jǐ",量才录用:"liàng cái lù yòng",教学相长:"jiào xué xiāng zhǎng",悔不当初:"huǐ bù dāng chū",呼幺喝六:"hū yāo hè liù",不足为训:"bù zú wéi xùn",不拘形迹:"bù jū xíng jī",傍若无人:"páng ruò wú rén",罪责难逃:"zuì zé nán táo",自我吹嘘:"zì wǒ chuī xū",转祸为福:"zhuǎn huò wéi fú",勇冠三军:"yǒng guàn sān jūn",易地而处:"yì dì ér chǔ",卸磨杀驴:"xiè mò shā lǘ",玩儿不转:"wán ér bú zhuàn",天道好还:"tiān dào hǎo huán",身单力薄:"shēn dān lì bó",撒豆成兵:"sǎ dòu chéng bīng",片纸只字:"piàn zhǐ zhī zì",宁缺毋滥:"nìng quē wú làn",没没无闻:"mò mò wú wén",量力而为:"liàng lì ér wéi",历历可数:"lì lì kě shǔ",口碑载道:"kǒu bēi zài dào",君子好逑:"jūn zǐ hǎo qiú",好为人师:"hào wéi rén shī",豪商巨贾:"háo shāng jù jiǎ",各有所好:"gè yǒu suǒ hào",度德量力:"duó dé liàng lì",指天为誓:"zhǐ tiān wéi shì",逸兴遄飞:"yì xìng chuán fēi",心宽体胖:"xīn kuān tǐ pán",为德不卒:"wéi dé bù zú",天下为家:"tiān xià wéi jiā",视为畏途:"shì wéi wèi tú",三灾八难:"sān zāi bā nàn",沐猴而冠:"mù hóu ér guàn",哩哩啦啦:"lī li lā lā",见缝就钻:"jiàn fèng jiù zuān",夹层玻璃:"jiā céng bō li",急公好义:"jí gōng hào yì",积年累月:"jī nián lěi yuè",划地为牢:"huá dì wéi láo",更名改姓:"gēng míng gǎi xìng",奉为圭臬:"fèng wéi guī niè",多难兴邦:"duō nàn xīng bāng",不破不立:"bú pò bú lì",坐地自划:"zuò dì zì huá",坐不重席:"zuò bù chóng xí",坐不窥堂:"zuò bù kuī táng",作嫁衣裳:"zuò jià yī shang",左枝右梧:"zuǒ zhī yòu wú",左宜右有:"zuǒ yí yòu yǒu",钻头觅缝:"zuān tóu mì fèng",钻天打洞:"zuān tiān dǎ dòng",钻皮出羽:"zuān pí chū yǔ",钻火得冰:"zuān huǒ dé bīng",钻洞觅缝:"zuàn dòng mì féng",钻冰求火:"zuān bīng qiú huǒ",子为父隐:"zǐ wéi fù yǐn",擢发难数:"zhuó fà nán shǔ",着人先鞭:"zhuó rén xiān biān",斫雕为朴:"zhuó diāo wéi pǔ",锥处囊中:"zhuī chǔ náng zhōng",椎心饮泣:"chuí xīn yǐn qì",椎心泣血:"chuí xīn qì xuè",椎牛飨士:"chuí niú xiǎng shì",椎牛歃血:"chuí niú shà xuè",椎牛发冢:"chuí niú fà zhǒng",椎埋屠狗:"chuí mái tú gǒu",椎埋狗窃:"chuí mái gǒu qiè",壮发冲冠:"zhuàng fā chōng guàn",庄严宝相:"zhuāng yán bǎo xiàng",转愁为喜:"zhuǎn chóu wéi xǐ",转嗔为喜:"zhuǎn chēn wéi xǐ",拽巷啰街:"zhuài xiàng luó jiē",拽耙扶犁:"zhuāi pá fú lí",拽布拖麻:"zhuài bù tuō má",箸长碗短:"zhù cháng wǎn duǎn",铸剑为犁:"zhù jiàn wéi lí",杼柚其空:"zhù yòu qí kōng",杼柚空虚:"zhù yòu kōng xū",助天为虐:"zhù tiān wéi nüè",属垣有耳:"zhǔ yuán yǒu ěr",属毛离里:"zhǔ máo lí lǐ",属辞比事:"zhǔ cí bǐ shì",逐物不还:"zhú wù bù huán",铢量寸度:"zhū liáng cùn duó",铢两悉称:"zhū liǎng xī chèn",侏儒观戏:"zhū rú guān xì",朱轓皁盖:"zhū fān zào gài",昼度夜思:"zhòu duó yè sī",诪张为幻:"zhōu zhāng wéi huàn",重明继焰:"chóng míng jì yàn",众啄同音:"zhòng zhuó tóng yīn",众毛攒裘:"zhòng máo cuán qiú",众好众恶:"zhòng hào zhòng wù",擿埴索涂:"zhāi zhí suǒ tú",稚齿婑媠:"zhì chǐ wǒ tuó",至当不易:"zhì dàng bú yì",指皂为白:"zhǐ zào wéi bái",指雁为羹:"zhǐ yàn wéi gēng",指树为姓:"zhǐ shù wéi xìng",指山说磨:"zhǐ shān shuō mò",止戈为武:"zhǐ gē wéi wǔ",枝干相持:"zhī gàn xiāng chí",枝大于本:"zh dà yú běn",支吾其词:"zhī wú qí cí",正身率下:"zhèng shēn shuài xià",正冠李下:"zhèng guàn lǐ xià",整冠纳履:"zhěng guān nà lǚ",整躬率物:"zhěng gōng shuài wù",整顿干坤:"zhěng dùn gàn kūn",针头削铁:"zhēn tóu xuē tiě",贞松劲柏:"zhēn sōng jìng bǎi",赭衣塞路:"zhě yī sè lù",折箭为誓:"shé jiàn wéi shì",折而族之:"zhé ér zú zhī",昭德塞违:"zhāo dé sè wéi",章句小儒:"zhāng jù xiǎo rú",湛恩汪濊:"zhàn ēn wāng huì",占风望气:"zhān fēng wàng qì",斩将搴旗:"zhǎn jiàng qiān qí",曾母投杼:"zēng mǔ tóu zhù",曾参杀人:"zēng shēn shā rén",造谣中伤:"zào yáo zhòng shāng",早占勿药:"zǎo zhān wù yào",凿龟数策:"záo guī shǔ cè",攒三聚五:"cuán sān jù wǔ",攒眉蹙额:"cuán mei cù é",攒零合整:"cuán líng hé zhěng",攒锋聚镝:"cuán fēng jù dí",载笑载言:"zài xiào zài yán",载酒问字:"zài jiǔ wèn zì",殒身不恤:"yǔn shēn bú xù",云舒霞卷:"yún shū xiá juǎn",月中折桂:"yuè zhōng shé guì",月落参横:"yuè luò shēn héng",鬻驽窃价:"yù nú qiè jià",鬻鸡为凤:"yù jī wéi fèng",遇难成祥:"yù nàn chéng xiáng",郁郁累累:"yù yù lěi lěi",玉卮无当:"yù zhī wú dàng",语笑喧阗:"yǔ xiào xuān tián",与世沉浮:"yǔ shì chén fú",与时消息:"yǔ shí xiāo xi",逾墙钻隙:"yú qiáng zuān xì",渔夺侵牟:"yú duó qīn móu",杅穿皮蠹:"yú chuān pí dù",余勇可贾:"yú yǒng kě gǔ",予智予雄:"yú zhì yú xióng",予取予求:"yú qǔ yú qiú",于家为国:"yú jiā wéi guó",有借无还:"yǒu jiè wú huán",有加无已:"yǒu jiā wú yǐ",有国难投:"yǒu guó nán tóu",游必有方:"yóu bì yǒu fāng",油干灯尽:"yóu gàn dēng jìn",尤云殢雨:"yóu yún tì yǔ",庸中皦皦:"yōng zhōng jiǎo jiǎo",郢书燕说:"yǐng shū yān shuō",营蝇斐锦:"yíng yíng fēi jǐn",鹰心雁爪:"yīng xīn yàn zhǎo",莺吟燕儛:"yīng yín yàn wǔ",应天顺时:"yīng tiān shùn shí",印累绶若:"yìn léi shòu ruò",隐占身体:"yǐn zhàn shēn tǐ",饮犊上流:"yìn dú shàng liú",引绳切墨:"yǐn shéng qiē mò",龈齿弹舌:"yín chǐ dàn shé",因缘为市:"yīn yuán wéi shì",因树为屋:"yīn shù wéi wū",溢美溢恶:"yì měi yì wù",抑塞磊落:"yì sè lěi luò",倚闾望切:"yǐ lǘ wàng qiē",以意为之:"yǐ yì wéi zhī",以言为讳:"yǐ yán wéi huì",以疏间亲:"yǐ shū jiàn qīn",以水济水:"yǐ shuǐ jǐ shuǐ",以书为御:"yǐ shū wéi yù",以守为攻:"yǐ shǒu wéi gōng",以升量石:"yǐ shēng liáng dàn",以慎为键:"yǐ shèn wéi jiàn",以筌为鱼:"yǐ quán wéi yú",以利累形:"yǐ lì lěi xíng",以毁为罚:"yǐ huǐ wéi fá",以黑为白:"yǐ hēi wéi bái",以规为瑱:"yǐ guī wéi tiàn",以古为鉴:"yǐ gǔ wéi jiàn",以宫笑角:"yǐ gōng xiào jué",以法为教:"yǐ fǎ wéi jiào",以大恶细:"yǐ dà wù xì",遗世忘累:"yí shì wàng lěi",遗寝载怀:"yí qǐn zài huái",移的就箭:"yí dì jiù jiàn",依头缕当:"yī tóu lǚ dàng",衣租食税:"yì zū shí shuì",衣轻乘肥:"yì qīng chéng féi",衣裳之会:"yī shang zhī huì",衣单食薄:"yī dān shí bó",一还一报:"yì huán yí bào",叶公好龙:"yè gōng hào lóng",野调无腔:"yě diào wú qiāng",瑶池女使:"yáo chí nǚ shǐ",幺麽小丑:"yāo mó xiǎo chǒu",养精畜锐:"yǎng jīng xù ruì",卬首信眉:"áng shǒu shēn méi",洋洋纚纚:"yáng yáng sǎ sǎ",羊羔美酒:"yáng gāo měi jiǔ",扬风扢雅:"yáng fēng jié yǎ",燕昭市骏:"yān zhāo shì jùn",燕昭好马:"yān zhāo hǎo mǎ",燕石妄珍:"yān shí wàng zhēn",燕骏千金:"yān jùn qiān jīn",燕金募秀:"yān jīn mù xiù",燕驾越毂:"yān jià yuè gǔ",燕歌赵舞:"yān gē zhào wǔ",燕岱之石:"yān dài zhī shí",燕处危巢:"yàn chǔ wēi cháo",掞藻飞声:"shàn zǎo fēi shēng",偃革为轩:"yǎn gé wéi xuān",妍蚩好恶:"yán chī hǎo è",压良为贱:"yā liáng wéi jiàn",搀行夺市:"chān háng duó shì",泣数行下:"qì shù háng xià",当行出色:"dāng háng chū sè",秀出班行:"xiù chū bān háng",儿女成行:"ér nǚ chéng háng",大行大市:"dà háng dà shì",寻行数墨:"xún háng shǔ mò",埙篪相和:"xūn chí xiāng hè",血债累累:"xuè zhài lěi lěi",炫玉贾石:"xuàn yù gǔ shí",炫石为玉:"xuàn shí wéi yù",悬石程书:"xuán dàn chéng shū",悬狟素飡:"xuán huán sù cān",悬龟系鱼:"xuán guī xì yú",揎拳捋袖:"xuān quán luō xiù",轩鹤冠猴:"xuān hè guàn hóu",畜妻养子:"xù qī yǎng zǐ",羞人答答:"xiū rén dā dā",修鳞养爪:"xiū lín yǎng zhǎo",熊据虎跱:"xióng jù hǔ zhì",兄死弟及:"xiōng sǐ dì jí",腥闻在上:"xīng wén zài shàng",兴文匽武:"xīng wén yǎn wǔ",兴观群怨:"xìng guān qún yuàn",兴高彩烈:"xìng gāo cǎi liè",心手相应:"xīn shǒu xiāng yìng",心口相应:"xīn kǒu xiāng yīng",挟势弄权:"xié shì nòng quán",胁肩累足:"xié jiān lěi zú",校短量长:"jiào duǎn liáng cháng",小眼薄皮:"xiǎo yǎn bó pí",硝云弹雨:"xiāo yún dàn yǔ",鸮鸣鼠暴:"xiāo míng shǔ bào",削株掘根:"xuē zhū jué gēn",削铁无声:"xuē tiě wú shēng",削职为民:"xuē zhí wéi mín",削木为吏:"xuē mù wéi lì",想望风褱:"xiǎng wàng fēng huái",香培玉琢:"xiang pei yu zhuó",相鼠有皮:"xiàng shǔ yǒu pí",相时而动:"xiàng shí ér dòng",相切相磋:"xiāng qiē xiāng cuō",相女配夫:"xiàng nǚ pèi fū",相门有相:"xiàng mén yǒu xiàng",挦章撦句:"xián zhāng chě jù",先我着鞭:"xiān wǒ zhuó biān",习焉不察:"xí yān bù chá",歙漆阿胶:"shè qī ē jiāo",晰毛辨发:"xī máo biàn fà",悉索薄赋:"xī suǒ bó fù",雾鳞云爪:"wù lín yún zhǎo",物稀为贵:"wù xī wéi guì",碔砆混玉:"wǔ fū hùn yù",武断专横:"wǔ duàn zhuān héng",五石六鹢:"wǔ shí liù yì",五色相宣:"wǔ sè xiāng xuān",五侯七贵:"wǔ hóu qī guì",五侯蜡烛:"wǔ hòu là zhú",五羖大夫:"wǔ gǔ dà fū",吾自有处:"wú zì yǒu chǔ",无下箸处:"wú xià zhù chǔ",无伤无臭:"wú shāng wú xiù",无能为役:"wú néng wéi yì",无寇暴死:"wú kòu bào sǐ",无孔不钻:"wú kǒng bú zuàn",无间可乘:"wú jiān kě chéng",无间冬夏:"wú jiān dōng xià",无恶不为:"wú è bù wéi",无动为大:"wú dòng wéi dà",诬良为盗:"wū liáng wéi dào",握拳透爪:"wò quán tòu zhǎo",文武差事:"wén wǔ chāi shì",委委佗佗:"wēi wēi tuó tuó",惟日为岁:"wéi rì wéi suì",帷薄不修:"wéi bó bù xiū",为善最乐:"wéi shàn zuì lè",为山止篑:"wéi shān zhǐ kuì",为仁不富:"wéi rén bú fù",为裘为箕:"wéi qiú wéi jī",为民父母:"wéi mín fù mǔ",为虺弗摧:"wéi huǐ fú cuī",为好成歉:"wéi hǎo chéng qiàn",为鬼为蜮:"wéi guǐ wéi yù",望风响应:"wàng fēng xiǎng yīng",望尘僄声:"wàng chén piào shēng",往渚还汀:"wǎng zhǔ huán tīng",王贡弹冠:"wáng gòng dàn guàn",亡国大夫:"wáng guó dà fū",万贯家私:"wàn guàn jiā sī",晚食当肉:"wǎn shí dàng ròu",晚节不保:"wǎn jié bù bǎo",玩岁愒时:"wán suì kài shí",蛙蟆胜负:"wā má shèng fù",吞言咽理:"tūn yán yàn lǐ",颓垣断堑:"tuí yuán duàn qiàn",推干就湿:"tuī gàn jiù shī",剸繁决剧:"tuán fán jué jù",团头聚面:"tuán tóu jù miàn",兔丝燕麦:"tù sī yàn mài",兔头麞脑:"tù tóu zhāng nǎo",兔葵燕麦:"tù kuí yàn mài",吐哺握发:"tǔ bǔ wò fà",投传而去:"tóu zhuàn ér qù",头没杯案:"tóu mò bēi àn",头昏脑闷:"tóu hūn nǎo mèn",头会箕敛:"tóu kuài jī liǎn",头出头没:"tóu chū tóu mò",痛自创艾:"tòng zì chuāng yì",同恶相助:"tóng wù xiāng zhù",同恶相恤:"tóng wù xiāng xù",痌瘝在抱:"tōng guān zài bào",通文调武:"tōng wén diào wǔ",停留长智:"tíng liú zhǎng zhì",铁树开华:"tiě shù kāi huā",条贯部分:"tiáo guàn bù fēn",挑牙料唇:"tiǎo yá liào chún",挑么挑六:"tiāo yāo tiāo liù",挑唇料嘴:"tiǎo chún liào zuǐ",恬不为意:"tián bù wéi yì",恬不为怪:"tián bù wéi guài",天下为笼:"tiān xià wéi lóng",天台路迷:"tiān tái lù mí",天年不遂:"tiān nián bú suì",探囊胠箧:"tàn náng qū qiè",谭言微中:"tán yán wēi zhòng",谈言微中:"tán yán wēi zhòng",狧穅及米:"shì kāng jí mǐ",随物应机:"suí wù yīng jī",搜岩采干:"sōu yán cǎi gàn",宋斤鲁削:"sòng jīn lǔ xuē",松筠之节:"sōng yún zhī jié",四亭八当:"sì tíng bā dàng",四马攒蹄:"sì mǎ cuán tí",四不拗六:"sì bú niù liù",思所逐之:"sī suǒ zhú zhī",丝恩发怨:"sī ēn fà yuàn",硕望宿德:"shuò wàng xiǔ dé",铄古切今:"shuò gǔ qiē jīn",顺风而呼:"shùn fēng ér hū",顺风吹火:"shùn fēng chuī huǒ",水中著盐:"shuǐ zhōng zhuó yán",双柑斗酒:"shuāng gān dǒu jiǔ",数米而炊:"shǔ mǐ ér chuī",数米量柴:"shǔ mǐ liáng chái",数理逻辑:"shù lǐ luó ji",数黑论黄:"shǔ hēi lùn huáng",数白论黄:"shǔ bái lùn huáng",束缊还妇:"shù yūn huán fù",束蒲为脯:"shù pú wéi pú",束椽为柱:"shù chuán wéi zhù",书缺有间:"shū quē yǒu jiàn",手足重茧:"shǒu zú chóng jiǎn",手足异处:"shǒu zú yì chǔ",手脚干净:"shǒu jiǎo gàn jìng",手不应心:"shǒu bù yīng xīn",螫手解腕:"shì shǒu jiě wàn",释知遗形:"shì zhī yí xíng",适时应务:"shì shí yīng wù",适情率意:"shì qíng shuài yì",适当其冲:"shì dāng qí chōng",视为知己:"shì wéi zhī jǐ",使羊将狼:"shǐ yáng jiàng láng",食为民天:"shí wéi mín tiān",拾掇无遗:"shí duō wú yí",实与有力:"shí yù yǒu lì",石英玻璃:"shí yīng bō li",石室金匮:"shí shì jīn guì",什袭珍藏:"shí xí zhēn cáng",什伍东西:"shí wǔ dōng xī",什围伍攻:"shí wéi wǔ gōng",十魔九难:"shí mó jiǔ nàn",诗书发冢:"shī shū fà zhǒng",虱处裈中:"shī chǔ kūn zhōng",师直为壮:"shī zhí wéi zhuàng",尸居龙见:"shī jū lóng xiàn",圣经贤传:"shèng jīng xián zhuàn",圣君贤相:"shèng jūn xián xiàng",生拖死拽:"shēng tuō sǐ zhuài",审己度人:"shěn jǐ duó rén",神武挂冠:"shén wǔ guà guàn",神龙失埶:"shén lóng shī shì",深文曲折:"shēn wén qǔ shé",深厉浅揭:"shēn lì qiǎn qì",深谷为陵:"shēn gǔ wéi líng",深恶痛疾:"shēn wù tòng jí",深仇宿怨:"shēn chóu xiǔ yuàn",舍己为公:"shě jǐ wèi gōng",舍短取长:"shě duǎn qǔ cháng",舍策追羊:"shě cè zhuī yáng",蛇蝎为心:"shé xiē wéi xīn",少成若性:"shào chéng ruò xìng",上当学乖:"shàng dàng xué guāi",赏不当功:"shǎng bù dāng gōng",善自为谋:"shàn zì wéi móu",善为说辞:"shàn wéi shuō cí",善善恶恶:"shàn shàn wù è",善财难舍:"shàn cái nán shě",苫眼铺眉:"shān yǎn pū méi",讪牙闲嗑:"shàn yá xián kē",山阴乘兴:"shān yīn chéng xīng",山殽野湋:"shān yáo yě wéi",山溜穿石:"shān liù chuān shí",山节藻棁:"shān jié zǎo zhuō",杀鸡为黍:"shā jī wéi shǔ",色厉胆薄:"sè lì dǎn bó",桑荫未移:"sāng yīn wèi yí",桑荫不徙:"sāng yīn bù xǐ",桑土绸缪:"sāng tǔ chóu miù",桑户棬枢:"sāng hù juàn shū",三战三北:"sān zhàn sān běi",三瓦两舍:"sān wǎ liǎng shě",三人为众:"sān rén wèi zhòng",三差两错:"sān chā liǎng cuò",塞井焚舍:"sāi jǐng fén shě",洒心更始:"sǎ xīn gèng shǐ",洒扫应对:"sǎ sǎo yìng duì",软红香土:"ruǎn hóng xiāng tǔ",入吾彀中:"rù wú gòu zhōng",入铁主簿:"rù tiě zhǔ bù",入理切情:"rù lǐ qiē qíng",汝成人耶:"rǔ chéng rén yé",如水投石:"rú shuǐ tóu shí",如切如磋:"rú qiē rú cuō",如登春台:"rú dēng chūn tái",肉薄骨并:"ròu bó gǔ bìng",柔情绰态:"róu qíng chuò tài",戎马劻勷:"róng mǎ kuāng ráng",日中为市:"rì zhōng wéi shì",日月参辰:"rì yuè shēn chén",日省月修:"rì xǐng yuè xiū",日削月割:"rì xuē yuè gē",日省月试:"rì xǐng yuè shì",任达不拘:"rèn dá bù jū",人言藉藉:"rén yán jí jí",人模狗样:"rén mú gǒu yàng",人莫予毒:"rén mò yú dú",热熬翻饼:"rè áo fān bǐng",圈牢养物:"juàn láo yǎng wù",取予有节:"qǔ yǔ yǒu jié",诎要桡腘:"qū yāo ráo guó",穷形尽相:"qióng xíng jìn xiàng",情凄意切:"qíng qī yì qiè",情见势屈:"qíng xiàn shì qū",情见乎辞:"qíng xiàn hū cí",清都绛阙:"qīng dōu jiàng què",倾肠倒肚:"qīng cháng dào dǔ",青紫被体:"qīng zǐ pī tǐ",青林黑塞:"qīng lín hēi sài",螓首蛾眉:"qín shǒu é méi",琴瑟之好:"qín sè zhī hào",且住为佳:"qiě zhù wéi jiā",切树倒根:"qiē shù dǎo gēn",切理餍心:"qiē lǐ yàn xīn",切近的当:"qiē jìn de dāng",翘足引领:"qiáo zú yǐn lǐng",巧发奇中:"qiǎo fā qí zhòng",强嘴拗舌:"jiàng zuǐ niù shé",强直自遂:"qiáng zhí zì suí",强死强活:"qiǎng sǐ qiǎng huó",强食自爱:"qiǎng shí zì ài",强食靡角:"qiǎng shí mí jiǎo",强弓劲弩:"qiáng gōng jìng nǔ",强聒不舍:"qiǎng guō bù shě",强凫变鹤:"qiáng fú biàn hè",强而后可:"qiǎng ér hòu kě",强得易贫:"qiǎng dé yì pín",遣兴陶情:"qiǎn xìng táo qíng",牵羊担酒:"qiān yáng dān jiǔ",千了百当:"qiān liǎo bǎi dàng",泣下如雨:"qì xià rú yǔ",起偃为竖:"qǐ yǎn wéi shù",岂弟君子:"kǎi tì jūn zǐ",綦溪利跂:"qí xī lì qí",棋输先著:"qí shū xiān zhuó",齐王舍牛:"qí wáng shě niú",欺天诳地:"qī tiān kuáng dì",普天率土:"pǔ tiān shuài tǔ",铺胸纳地:"pū xiōng nà dì",铺锦列绣:"pū jǐn liè xiù",破家为国:"pò jiā wèi guó",破觚为圜:"pò gū wéi yuán",萍飘蓬转:"píng piāo péng zhuàn",帡天极地:"píng tiān jí dì",屏声息气:"bǐng shēng xī qì",凭几据杖:"píng jī jù zhàng",贫嘴薄舌:"pín zuǐ bó shé",片语只辞:"piàn yǔ zhī cí",披发文身:"pī fà wén shēn",烹龙炮凤:"pēng lóng páo fèng",炰鳖脍鲤:"fǒu biē kuài lǐ",庞眉皓发:"páng méi hào fà",攀花折柳:"pān huā zhé liǔ",攀蟾折桂:"pān chán shé guì",女大难留:"nǚ dà nán liú",弄玉吹箫:"nòng yù chuī xiāo",弄管调弦:"nòng guǎn tiáo xián",弄粉调朱:"nòng fěn diào zhū",浓抹淡妆:"nóng mò dàn zhuāng",捻土为香:"niǎn tǔ wéi xiāng",年谊世好:"nián yì shì hǎo",年华垂暮:"nián huá chuí mù",儗不于伦:"nǐ bù yú lún",泥而不滓:"ní ér bù zǐ",能者为师:"néng zhě wéi shī",能不称官:"néng bú chèn guān",挠直为曲:"náo zhí wéi qū",难进易退:"nán jìn yì tuì",难得糊涂:"nán dé hú tú",南蛮鴂舌:"nán mán jué shé",南贩北贾:"nán fàn běi gǔ",牧猪奴戏:"mù zhū nú xì",目眢心忳:"mù yuān xīn tún",目挑心招:"mù tiǎo xīn zhāo",目量意营:"mù liàng yì yíng",木头木脑:"mù tóu mù nǎo",木干鸟栖:"mù gàn niǎo qī",侔色揣称:"móu sè chuǎi chèn",莫予毒也:"mò yú dú yě",抹粉施脂:"mò fěn shī zhī",磨砻镌切:"mó lóng juān qiē",磨棱刓角:"mó léng wán jiǎo",摸门不着:"mō mén bù zháo",摸不着边:"mō bù zhuó biān",命中注定:"mìng zhōng zhù dìng",鸣鹤之应:"míng hè zhī yìng",明效大验:"míng xiào dà yàn",名我固当:"míng wǒ gù dāng",邈处欿视:"miǎo chǔ kǎn shì",黾穴鸲巢:"měng xué qú cháo",绵里薄材:"mián lǐ bó cái",靡有孑遗:"mǐ yǒu jié yí",靡衣偷食:"mǐ yī tōu shí",迷恋骸骨:"mí liàn hái gǔ",扪参历井:"mén shēn lì jǐng",门单户薄:"mén dān hù bó",昧旦晨兴:"mèi dàn chén xīng",冒名接脚:"mào míng jiē jiǎo",毛遂堕井:"máo suí duò jǐng",毛发倒竖:"máo fā dǎo shù",卖文为生:"mài wén wéi shēng",卖李钻核:"mài lǐ zuān hé",买椟还珠:"mǎi dú huán zhū",埋三怨四:"mán sān yuàn sì",马入华山:"mǎ rù huá shān",落魄江湖:"luò pò jiāng hú",落落难合:"luò luò nán hé",落草为寇:"luò cǎo wéi kòu",罗织构陷:"luó zhī gòu xiàn",鸾凤和鸣:"luán fèng hè míng",率由旧章:"shuài yóu jiù zhāng",率土同庆:"shuài tǔ tóng qìng",率兽食人:"shuài shòu shí rén",率土归心:"shuài tǔ guī xīn",率马以骥:"shuài mǎ yǐ jì",率尔成章:"shuài ěr chéng zhāng",鲁斤燕削:"lǔ jīn yàn xuē",漏尽更阑:"lòu jìn gēng lán",笼鸟槛猿:"lóng niǎo jiàn yuán",笼鸟池鱼:"lóng niǎo chí yú",龙游曲沼:"lóng yóu qū zhǎo",龙血玄黄:"lóng xuè xuán huáng",龙雕凤咀:"lóng diāo fèng jǔ",六尺之讬:"liù chǐ zhī tuō",令原之戚:"líng yuán zhī qī",令人捧腹:"lìng rén pěng fù",陵劲淬砺:"líng jìng cuì lì",临敌易将:"lín dí yì jiàng",裂裳衣疮:"liè shang yī chuāng",裂冠毁冕:"liè guàn huǐ miǎn",了无惧色:"liǎo wú jù sè",了身达命:"liǎo shēn dá mìng",了然无闻:"liǎo rán wú wén",了不可见:"liǎo bù kě jiàn",了不长进:"liǎo bù zhǎng jìn",燎发摧枯:"liǎo fà cuī kū",审时度势:"shěn shí duó shì",量小力微:"liàng xiǎo lì wēi",相时度力:"xiāng shí duó lì",量枘制凿:"liàng ruì zhì záo",量如江海:"liàng rú jiāng hǎi",量金买赋:"liàng jīn mǎi fù",量己审分:"liàng jǐ shěn fēn",敛骨吹魂:"liǎn gǔ chuī hún",詈夷为跖:"lì yí wéi zhí",利令志惛:"lì lìng zhì hūn",李广不侯:"lǐ guǎng bú hòu",礼为情貌:"lǐ wéi qíng mào",礼让为国:"lǐ ràng wéi guó",犁生骍角:"lí shēng xīng jiǎo",离本徼末:"lí běn jiǎo mò",楞眉横眼:"léng méi hèng yǎn",擂天倒地:"léi tiān dǎo dì",累足成步:"lěi zú chéng bù",累瓦结绳:"lěi wǎ jié shéng",累土至山:"lěi tǔ zhì shān",累土聚沙:"lěi tǔ jù shā",累卵之危:"lěi luǎn zhī wēi",累累如珠:"lěi lěi rú zhū",累块积苏:"lěi kuài jī sū",乐山乐水:"lè shān lè shuǐ",潦原浸天:"lǎo yuán jìn tiān",老师宿儒:"lǎo shī xiǔ rú",牢什古子:"láo shí gǔ zi",琅嬛福地:"láng huán fú dì",揆情度理:"kuí qíng duó lǐ",旷日累时:"kuàng rì lěi shí",匡救弥缝:"kuāng jiù mí fèng",枯树生华:"kū shù shēng huā",口轻舌薄:"kǒu qīng shé bó",口角生风:"kǒu jiǎo shēng fēng",口角春风:"kǒu jiǎo chūn fēng",口角风情:"kǒu jiǎo fēng qíng",口干舌焦:"kǒu gān shé jiāo",口腹之累:"kǒu fù zhī lěi",空腹便便:"kōng fù pián pián",嗑牙料嘴:"kē yá liào zuǐ",刻木为鹄:"kè mù wéi hú",咳珠唾玉:"ké zhū tuò yù",咳唾成珠:"ké tuò chéng zhū",抗颜为师:"kàng yán wéi shī",开华结果:"kāi huā jié guǒ",峻阪盐车:"jùn bǎn yán chē",嚼铁咀金:"jiáo tiě jǔ jīn",嚼墨喷纸:"jué mò pēn zhǐ",倔头强脑:"juè tóu jiàng nǎo",倔头倔脑:"juè tóu juè nǎo",倦鸟知还:"juàn niǎo zhī huán",卷席而葬:"juǎn xí ér zàng",卷甲倍道:"juǎn jiǎ bèi dào",聚米为山:"jù mǐ wéi shān",举手相庆:"jǔ shǒu xiāng qìng",举世混浊:"jǔ shì hún zhuó",鞠为茂草:"jū wéi mào cǎo",拘神遣将:"jū shén qiǎn jiàng",居下讪上:"jū xià shàn shàng",久要不忘:"jiǔ yāo bú wàng",九转功成:"jiǔ zhuǎn gōng chéng",九蒸三熯:"jiǔ zhēng sān hàn",敬业乐群:"jìng yè lè qún",井底虾蟆:"jǐng dǐ xiā má",旌旗卷舒:"jīng qí juǎn shū",荆棘载途:"jīng jí zài tú",禁舍开塞:"jìn shě kāi sāi",祲威盛容:"jìn wēi shèng róng",进退消长:"jìn tuì xiāo cháng",进退应矩:"jìn tuì yīng jǔ",进退触籓:"jìn tuì chù fān",进退跋疐:"jìn tuì bá zhì",尽多尽少:"jǐn duō jǐn shǎo",锦囊还矢:"jǐn náng huán shǐ",矜己自饰:"jīn jǐ zì shì",矜功负气:"jīn gōng fù qì",津关险塞:"jīn guān xiǎn sài",金吾不禁:"jīn wú bú jìn",金翅擘海:"jīn chì bāi hǎi",解衣衣人:"jiě yī yī rén",解人难得:"jiě rén nán dé",解铃系铃:"jiě líng xì líng",解发佯狂:"jiě fà yáng kuáng",诘屈磝碻:"jié qū áo qiāo",教猱升木:"jiāo náo shēng mù",较瘦量肥:"jiào shòu liàng féi",角立杰出:"jiǎo lì jié chū",焦沙烂石:"jiāo shā làn shí",骄儿騃女:"jiāo ér sì nǚ",浇风薄俗:"jiāo fēng bó sú",降妖捉怪:"xiáng yāo zhuō guài",将取固予:"jiāng qǔ gù yǔ",将门有将:"jiàng mén yǒu jiàng",将夺固与:"jiāng duó gù yǔ",槛花笼鹤:"jiàn huā lóng hè",鉴影度形:"jiàn yǐng duó xíng",渐不可长:"jiàn bù kě zhǎng",见素抱朴:"xiàn sù bào pǔ",见弃于人:"jiàn qì yú rén",简丝数米:"jiǎn sī shǔ mǐ",俭不中礼:"jiǎn bú zhòng lǐ",间见层出:"jiàn xiàn céng chū",尖嘴薄舌:"jiān zuǐ bó shé",甲冠天下:"jiǎ guàn tiān xià",葭莩之亲:"jiā fú zhī qīn",家累千金:"jiā lèi qiān jīn",家给人足:"jiā jǐ rén zú",家道从容:"jiā dào cóng róng",夹袋人物:"jiā dài rén wù",霁风朗月:"jì fēng lǎng yuè",寄兴寓情:"jì xìng yù qíng",计深虑远:"jì shēn lǜ yuǎn",计功量罪:"jì gōng liàng zuì",掎裳连襼:"jǐ shang lián yì",虮虱相吊:"jǐ shī xiāng diào",疾不可为:"jí bù kě wéi",极深研几:"jí shēn yán jī",及宾有鱼:"jí bīn yǒu yú",激薄停浇:"jī bó tíng jiāo",积素累旧:"jī sù lěi jiù",积时累日:"jī shí lěi rì",积露为波:"jī lù wéi bō",积德累功:"jī dé lěi gōng",积谗糜骨:"jī chán méi gǔ",击排冒没:"jī pái mào mò",祸为福先:"huò wéi fú xiān",祸福相依:"huò fú xiāng yī",获隽公车:"huò jùn gōng chē",混应滥应:"hùn yīng làn yīng",毁舟为杕:"huǐ zhōu wéi duò",毁钟为铎:"huǐ zhōng wéi duó",毁冠裂裳:"huǐ guān liè cháng",晦盲否塞:"huì máng pǐ sè",回船转舵:"huí chuán zhuàn duò",潢池盗弄:"huáng chí dào nòng",黄冠草履:"huáng guàn cǎo lǚ",黄发儿齿:"huáng fà ér chǐ",黄发垂髫:"huáng fà chuí tiáo",还珠返璧:"huán zhū fǎn bì",还年驻色:"huán nián zhù sè",还年却老:"huán nián què lǎo",坏裳为裤:"huài shang wéi kù",画荻和丸:"huà dí huò wán",化枭为鸠:"huà xiāo wéi jiū",化腐为奇:"huà fǔ wéi qí",化鸱为凤:"huà chī wéi fèng",花不棱登:"huā bu lēng dēng",户限为穿:"hù xiàn wéi chuān",呼卢喝雉:"hū lú hè zhì",呼来喝去:"hū lái hè qù",呼不给吸:"hū bù jǐ xī",厚味腊毒:"hòu wèi xī dú",厚德载物:"hòu dé zài wù",鸿渐于干:"hóng jiàn yú gàn",洪炉燎发:"hóng lú liáo fà",红绳系足:"hóng shéng jì zú",红不棱登:"hóng bu lēng dēng",横抢硬夺:"hèng qiǎng yìng duó",横恩滥赏:"hèng ēn làn shǎng",恨海难填:"hèn hǎi nán tián",鹤发鸡皮:"hè fà jī pí",涸思干虑:"hé sī gān lǜ",河涸海干:"hé hé hǎi gān",和颜说色:"hé yán yuè sè",合从连衡:"hé zòng lián héng",浩浩汤汤:"hào hào shāng shāng",好勇斗狠:"hào yǒng dòu hěn",好问则裕:"hào wèn zé yù",好为事端:"hào wéi shì duān",好问决疑:"hào wèn jué yí",好生之德:"hào shēng zhī dé",好奇尚异:"hǎo qí shàng yì",好恶不同:"hǎo è bù tóng",好丹非素:"hào dān fēi sù",豪干暴取:"háo gàn bào qǔ",毫发不爽:"háo fà bù shuǎng",寒酸落魄:"hán suān luò pò",含英咀华:"hán yīng jǔ huá",含糊不明:"hán hú bù míng",过为已甚:"guò wéi yǐ shèn",桂折兰摧:"guì shé lán cuī",规旋矩折:"guī xuán jǔ shé",广文先生:"guǎng wén xiān sheng",广陵散绝:"guǎng líng sǎn jué",冠山戴粒:"guàn shān dài lì",冠屦倒施:"guàn jù dǎo shī",挂席为门:"guà xí wéi mén",寡见鲜闻:"guǎ jiàn xiǎn wén",瓜葛相连:"guā gé xiāng lián",鼓吻奋爪:"gǔ wěn fèn zhǎo",古调单弹:"gǔ diào dān tán",古调不弹:"gǔ diào bù tán",姑射神人:"gū yè shén rén",苟合取容:"gǒu hé qǔ róng",狗续侯冠:"gǒu xù hòu guàn",钩爪锯牙:"gōu zhǎo jù yá",共枝别干:"gòng zhī bié gàn",共为唇齿:"gòng wéi chún chǐ",拱手而降:"gǒng shǒu ér xiáng",拱肩缩背:"gǒng jiān suō bèi",功薄蝉翼:"gōng bó chán yì",弓调马服:"gōng diào mǎ fú",更姓改物:"gēng xìng gǎi wù",更仆难数:"gēng pú nán shǔ",更令明号:"gēng lìng míng hào",更待干罢:"gèng dài gàn bà",更唱迭和:"gēng chàng dié hé",更长梦短:"gēng cháng mèng duǎn",各色名样:"gè sè míng yàng",格格不纳:"gé gé bú nà",格格不吐:"gé gé bù tǔ",告朔饩羊:"gù shuò xì yáng",膏车秣马:"gào chē mò mǎ",高义薄云:"gāo yì bó yún",岗头泽底:"gāng tóu zé dǐ",敢为敢做:"gǎn wéi gǎn zuò",甘分随时:"gān fèn suí shí",甘处下流:"gān chǔ xià liú",干啼湿哭:"gàn tí shī kū",干名犯义:"gàn míng fàn yì",干将莫邪:"gān jiāng mò yé",干城之将:"gān chéng zhī jiàng",腹载五车:"fù zài wǔ chē",父债子还:"fù zhài zǐ huán",父为子隐:"fù wéi zǐ yǐn",辅世长民:"fǔ shì zhǎng mín",福为祸始:"fú wéi huò shǐ",符号逻辑:"fú hào luó jí",浮收勒折:"fú shōu lè shé",肤受之愬:"fū shòu zhī sù",否终则泰:"pǐ zhōng zé tài",佛头著粪:"fó tóu zhuó fèn",奉为楷模:"fèng wéi kǎi mó",凤靡鸾吪:"fèng mǐ luán é",封豨修蛇:"fēng xī xiū shé",风影敷衍:"fēng yǐng fū yǎn",丰屋蔀家:"fēng wū bù jiā",粪土不如:"fèn tǔ bù rú",分风劈流:"fēn fēng pǐ liú",沸沸汤汤:"fèi fèi shāng shāng",菲食薄衣:"fěi shí bó yī",飞将数奇:"fēi jiàng shù qí",放辟邪侈:"fàng pì xié chǐ",方领圆冠:"fāng lǐng yuán guàn",犯而不校:"fàn ér bú jiào",返本还源:"fǎn běn huán yuán",反劳为逸:"fǎn láo wéi yì",法轮常转:"fǎ lún cháng zhuàn",罚不当罪:"fá bù dāng zuì",发引千钧:"fà yǐn qiān jūn",发奸擿伏:"fā jiān tī fú",发短心长:"fà duǎn xīn cháng",二竖为虐:"èr shù wéi nüè",儿女心肠:"ér nǚ xīn cháng",儿女亲家:"ér nǚ qìng jiā",遏恶扬善:"è wù yáng shàn",饿殍枕藉:"è piǎo zhěn jí",饿殍载道:"è piǎo zài dào",恶醉强酒:"wù zuì qiǎng jiǔ",恶意中伤:"è yì zhòng shāng",恶湿居下:"wù shī jū xià",恶居下流:"wù jū xià liú",恶不去善:"wù bú qù shàn",扼吭夺食:"è háng duó shí",扼襟控咽:"è jīn kòng yān",峨峨汤汤:"é é shāng shāng",屙金溺银:"ē jīn niào yín",朵颐大嚼:"duǒ yí dà jiáo",夺人所好:"duó rén suǒ hào",多言数穷:"duō yán shuò qióng",多文为富:"duō wén wéi fù",多端寡要:"duō duān guǎ yào",多财善贾:"duō cái shàn gǔ",遁世无闷:"dùn shì wú mèn",遁迹黄冠:"dùn jì huáng guàn",堆案盈几:"duī àn yíng jī",断还归宗:"duàn huán guī zōng",短见薄识:"duǎn jiàn bó shí",蠹居棊处:"dù jū qí chǔ",度己以绳:"duó jǐ yǐ shéng",杜默为诗:"dù mò wéi shī",杜鹃啼血:"dù juān tí xuè",笃近举远:"dǔ jìn jǔ yuǎn",独有千秋:"dú yǒu qiān qiū",读书得间:"dú shū dé jiàn",斗转参横:"dǒu zhuǎn shēn héng",兜肚连肠:"dōu dǔ lián cháng",洞见症结:"dòng jiàn zhèng jié",恫疑虚喝:"dòng yí xū hè",动中窾要:"dòng zhōng kuǎn yào",东鸣西应:"dōng míng xī yīng",东鳞西爪:"dōng lín xī zhǎo",东量西折:"dōng liàng xī shé",东家西舍:"dōng jiā xī shè",东扯西拽:"dōng chě xī zhuāi",鼎铛有耳:"dǐng chēng yǒu ěr",鼎铛玉石:"dǐng chēng yù shí",钉头磷磷:"dīng tóu lín lín",跌宕不羁:"diē dàng bù jī",跌弹斑鸠:"diē dàn bān jiū",雕心雁爪:"diāo xīn yàn zhǎo",颠倒衣裳:"diān dǎo yī cháng",德薄能鲜:"dé bó néng xiǎn",得马折足:"dé mǎ shé zú",蹈其覆辙:"dǎo qí fù zhé",捣虚撇抗:"dǎo xū piē kàng",倒载干戈:"dào zài gān gē",倒裳索领:"dào cháng suǒ lǐng",倒果为因:"dào guǒ wéi yīn",叨在知己:"tāo zài zhī jǐ",叨陪末座:"tāo péi mò zuò",党豺为虐:"dǎng chái wéi nüè",当轴处中:"dāng zhóu chǔ zhōng",当着不着:"dāng zhuó bù zhuó",当务始终:"dāng wù shǐ zhōng",淡汝浓抹:"dàn rǔ nóng mǒ",弹丸脱手:"tán wán tuō shǒu",弹铗无鱼:"dàn jiá wú yú",箪食瓢饮:"dān sì piáo yǐn",大璞不完:"dà pú bù wán",大明法度:"dà míng fǎ dù",大车以载:"dà chē yǐ zài",打闷葫芦:"dǎ mèn hú lu",沓来踵至:"tà lái zhǒng zhì",厝火燎原:"cuò huǒ liǎo yuán",撮科打哄:"cuō kē dǎ hòng",寸积铢累:"cùn jī zhū lěi",啛啛喳喳:"cuì cuì chā chā",摧折豪强:"cuī zhé háo qiáng",摧刚为柔:"cuī gāng wéi róu",从俗就简:"cóng sú jiù jiǎn",此发彼应:"cǐ fā bǐ yīng",此唱彼和:"cǐ chàng bǐ hè",慈悲为本:"cí bēi wéi běn",纯属骗局:"chún shǔ piàn jú",春笋怒发:"chūn sǔn nù fā",垂头搨翼:"chuí tóu tà yì",传为笑谈:"chuán wéi xiào tán",传风扇火:"chuán fēng shān huǒ",穿红着绿:"chuān hóng zhuó lǜ",触处机来:"chù chǔ jī lái",处尊居显:"chǔ zūn jū xiǎn",处堂燕雀:"chǔ táng yàn què",处实效功:"chǔ shí xiào gōng",处高临深:"chǔ gāo lín shēn",出入无间:"chū rù wú jiān",出门应辙:"chū mén yīng zhé",出处语默:"chū chǔ yǔ mò",出处殊途:"chū chǔ shū tú",出处进退:"chū chǔ jìn tuì",愁山闷海:"chóu shān mèn hǎi",冲冠眦裂:"chōng guàn zì liè",齿牙为祸:"chǐ yá wéi huò",尺二冤家:"chǐ èr yuān jia",尺短寸长:"chǐ duǎn cùn cháng",尺寸之功:"chǐ cùn zhī gōng",城北徐公:"chéng běi xú gōng",成败兴废:"chéng bài xīng fèi",趁水和泥:"chèn shuǐ huò ní",称雨道晴:"chēng yǔ dào qíng",称体载衣:"chēng tǐ zài yī",称体裁衣:"chèn tǐ cái yī",称家有无:"chèn jiā yǒu wú",称德度功:"chēng dé duó gōng",沉吟章句:"chén yín zhāng jù",沉吟不决:"chén yín bù jué",沉疴宿疾:"chén kē sù jí",扯纤拉烟:"chě qiàn lā yān",扯顺风旗:"chě shùn fēng qí",车载船装:"chē zǎi chuán zhuāng",朝升暮合:"zhāo shēng mù gě",朝攀暮折:"zhāo pān mù shé",超今冠古:"chāo jīn guàn gǔ",倡而不和:"chàng ér bú hè",畅所欲为:"chàng suǒ yù wéi",苌弘碧血:"cháng hóng bì xiě",长幼尊卑:"zhǎng yòu zūn bēi",长绳系日:"cháng shéng jì rì",长年三老:"zhǎng nián sān lǎo",长春不老:"cháng chūn bù lǎo",长傲饰非:"zhǎng ào shì fēi",昌亭旅食:"chāng tíng lǚ shí",禅絮沾泥:"chán xù zhān ní",差三错四:"chā sān cuò sì",层台累榭:"céng tái lěi xiè",层见迭出:"céng xiàn dié chū",藏踪蹑迹:"cáng zōng niè jì",苍蝇见血:"cāng yíng jiàn xiě",餐松啖柏:"cān sōng dàn bó",骖风驷霞:"cān fēng sì xiá",参伍错综:"cēn wǔ cuò zōng",参辰卯酉:"shēn chén mǎo yǒu",材优干济:"cái yōu gān jǐ",材薄质衰:"cái bó zhì shuāi",才大难用:"cái dà nán yòng",才薄智浅:"cái bó zhì qiǎn",不足为意:"bù zú wéi yì",不足为据:"bù zú wéi jù",不足为法:"bù zú wéi fǎ",不足齿数:"bù zú chǐ shǔ",不着疼热:"bù zhuó téng rè",不知薡蕫:"bù zhī dǐng dǒng",不越雷池:"bú yuè léi chí",不相为谋:"bù xiāng wéi móu",不贪为宝:"bù tān wéi bǎo",不了而了:"bù liǎo ér liǎo",不可揆度:"bù kě kuí duó",不遑启处:"bù huáng qǐ chǔ",不当不正:"bù dāng bú zhèng",不差什么:"bú chà shén me",不差累黍:"bù chā lěi shǔ",擘两分星:"bò liǎng fēn xīng",簸土扬沙:"bǒ tǔ yáng shā",薄物细故:"bó wù xì gù",薄寒中人:"bó hán zhòng rén",博文约礼:"bó wén yuē lǐ",播糠眯目:"bō kāng mí mù",剥皮抽筋:"bō pí chōu jīn",剥肤椎髓:"bō fū chuí suǐ",波属云委:"bō zhǔ yún wěi",波骇云属:"bō hài yún zhǔ",兵微将寡:"bīng wēi jiàng guǎ",兵强将勇:"bīng qiáng jiàng yǒng",兵多将广:"bīng duō jiàng guǎng",兵不由将:"bīng bù yóu jiàng",冰解的破:"bīng jiě dì pò",彬彬济济:"bīn bīn jǐ jǐ",摽梅之年:"biào méi zhī nián",表里为奸:"biǎo lǐ wéi jiān",飙发电举:"biāo fā diàn jǔ",变贪厉薄:"biàn tān lì bó",敝盖不弃:"bì gài bú qì",秕言谬说:"bǐ yán miù shuō",比物属事:"bǐ wù zhǔ shì",被山带河:"pī shān dài hé",被甲枕戈:"pī jiǎ zhěn gē",被甲据鞍:"pī jiǎ jù ān",被褐怀玉:"pī hè huái yù",被发缨冠:"pī fà yīng guàn",背曲腰躬:"bèi qǔ yāo gōng",北窗高卧:"běi chuāng gāo wò",北辰星拱:"běi chén xīng gǒng",北鄙之音:"běi bǐ zhī yīn",卑宫菲食:"bēi gōng fěi shí",暴衣露冠:"pù yī lù guàn",暴腮龙门:"pù sāi lóng mén",暴露文学:"bào lù wén xué",暴虎冯河:"bào hǔ píng hé",抱蔓摘瓜:"bào wàn zhāi guā",抱法处势:"bào fǎ chǔ shì",褒贬与夺:"bāo biǎn yǔ duó",帮闲钻懒:"bāng xián zuān lǎn",拜将封侯:"bài jiàng fēng hóu",百兽率舞:"bǎi shòu shuài wǔ",百孔千创:"bǎi kǒng qiān chuāng",白衣卿相:"bái yī qīng xiàng",白首为郎:"bái shǒu wéi láng",白首相知:"bái shǒu xiāng zhī",把玩无厌:"bǎ wán wú yàn",拔锅卷席:"bá guō juǎn xí",拔本塞源:"bá běn sè yuán",傲不可长:"ào bù kě zhǎng",熬更守夜:"áo gēng shǒu yè",安时处顺:"ān shí chǔ shùn",安身为乐:"ān shēn wéi lè",安老怀少:"ān lǎo huái shào",安步当车:"ān bù dàng chē",爱人好士:"ài rén hào shì",矮人观场:"ǎi rén guān chǎng",捱风缉缝:"ái fēng jī fèng",挨山塞海:"āi shān sè hǎi",阿家阿翁:"ā jiā ā wēng",阿党相为:"ē dǎng xiāng wéi",追亡逐北:"zhuī wáng zhú běi",竹篮打水:"zhú lán dá shuǐ",知疼着热:"zhī téng zháo rè",语不惊人:"yǔ bù jīng rén",于今为烈:"yú jīn wéi liè",一日三省:"yí rì sān xǐng",穴居野处:"xué jū yě chǔ",五脊六兽:"wǔ jǐ liù shòu",无声无臭:"wú shēng wú xiù",谓予不信:"wèi yú bú xìn",舍身为国:"shě shēn wéi guó",杀妻求将:"shā qī qiú jiàng",强作解人:"qiǎng zuò jiě rén",气冲斗牛:"qì chōng dǒu niú",临深履薄:"lín shēn lǚ bó",钧天广乐:"jūn tiān guǎng yuè",艰难竭蹶:"jiān nán jié jué",夹七夹八:"jiā qī jiā bā",混混噩噩:"hún hún è è",厚古薄今:"hòu gǔ bó jīn",鬼怕恶人:"guǐ pà è rén",伽马射线:"gā mǎ shè xiàn",佛头着粪:"fó tóu zhuó fèn",奉为至宝:"fèng wéi zhì bǎo",登坛拜将:"dēng tán bài jiàng",晨昏定省:"chén hūn dìng xǐng",察察为明:"chá chá wéi míng",博闻强识:"bó wén qiáng zhì",避难就易:"bì nán jiù yì",了无生机:'liǎo wú shēng jī',有一说一:'yǒu yī shuō yī',独一无二:'dú yī wú èr',说一不二:'shuō yī bù èr',举一反三:'jǔ yī fǎn sān',数一数二:'shǔ yī shǔ èr',杀一儆百:'shā yī jǐng bǎi',丁一卯二:'dīng yī mǎo èr',丁一确二:'dīng yī què èr',不一而止:'bù yī ér zhǐ',无一幸免:'wú yī xìng miǎn',表里不一:'biǎo lǐ bù yī',良莠不一:'liáng yǒu bù yī',心口不一:'xīn kǒu bù yī',言行不一:'yán xíng bù yī',政令不一:'zhèng lìng bù yī',参差不一:'cēn cī bù yī',纷纷不一:'fēn fēn bù yī',毁誉不一:'huǐ yù bù yī',不一而三:'bù yī ér sān',百不一遇:'bǎi bù yī yù',言行抱一:'yán xíng bào yī',瑜百瑕一:'yú bǎi xiá yī',背城借一:'bèi chéng jiè yī',凭城借一:'píng chéng jiè yī',劝百讽一:'quàn bǎi fěng yī',群居和一:'qún jū hé yī',百不获一:'bǎi bù huò yī',百不失一:'bǎi bù shī yī',百无失一:'bǎi wú shī yī',万不失一:'wàn bù shī yī',万无失一:'wàn wú shī yī',合而为一:'hé ér wéi yī',合两为一:'hé liǎng wéi yī',合二为一:'hé èr wéi yī',天下为一:'tiān xià wéi yī',相与为一:'xiāng yǔ wéi yī',较若画一:'jiào ruò huà yī',较如画一:'jiào rú huà yī',斠若画一:'jiào ruò huà yī',言行若一:'yán xíng ruò yī',始终若一:'shǐ zhōng ruò yī',终始若一:'zhōng shǐ ruò yī',惟精惟一:'wéi jīng wéi yī',众多非一:'zhòng duō fēi yī',不能赞一:'bù néng zàn yī',问一答十:'wèn yī dá shí',一不扭众:'yī bù niǔ zhòng',一以贯之:'yī yǐ guàn zhī',一以当百:'yī yǐ dāng bǎi',百不当一:'bǎi bù dāng yī',十不当一:'shí bù dāng yī',以一警百:'yǐ yī jǐng bǎi',以一奉百:'yǐ yī fèng bǎi',以一持万:'yǐ yī chí wàn',以一知万:'yǐ yī zhī wàn',百里挑一:'bǎi lǐ tiāo yī',整齐划一:'zhěng qí huà yī',一来二去:'yī lái èr qù',一路公交:'yī lù gōng jiāo',一路汽车:'yī lù qì chē',一路巴士:'yī lù bā shì',朝朝朝落:'zhāo cháo zhāo luò',曲意逢迎:'qū yì féng yíng',一行不行:'yì háng bù xíng',行行不行:'háng háng bù xíng'};const Pattern4=Object.keys(DICT4).map((key)=>({zh:key,pinyin:DICT4[key],probability:2e-8,length:4,priority:Priority.Normal,dict:Symbol('dict4'),}));const DICT5={巴尔干半岛:'bā ěr gàn bàn dǎo',巴尔喀什湖:'bā ěr kā shí hú',不幸而言中:'bú xìng ér yán zhòng',布尔什维克:'bù ěr shí wéi kè',何乐而不为:'hé lè ér bù wéi',苛政猛于虎:'kē zhèng měng yú hǔ',蒙得维的亚:'méng dé wéi dì yà',民以食为天:'mín yǐ shí wéi tiān',事后诸葛亮:'shì hòu zhū gě liàng',物以稀为贵:'wù yǐ xī wéi guì',先下手为强:'xiān xià shǒu wéi qiáng',行行出状元:'háng háng chū zhuàng yuan',亚得里亚海:'yà dé lǐ yà hǎi',眼不见为净:'yǎn bú jiàn wéi jìng',竹筒倒豆子:'zhú tǒng dào dòu zi',};const Pattern5=Object.keys(DICT5).map((key)=>({zh:key,pinyin:DICT5[key],probability:2e-8,length:5,priority:Priority.Normal,dict:Symbol('dict5'),}));function getMaxProbability(a,b){if(!a){return b}if(a.decimalb.probability?a:b}else{return b}}function checkDecimal(prob){if(prob.probability<1e-300){prob.probability*=1e300;prob.decimal+=1}}function getPatternDecimal(pattern){if(pattern.priority===Priority.Custom){return-(pattern.length*pattern.length*100)}if(pattern.priority===Priority.Surname){return-(pattern.length*pattern.length*10)}return 0}function maxProbability(patterns,length){const dp=[];let patternIndex=patterns.length-1;let pattern=patterns[patternIndex];for(let i=length-1;i>=0;i--){const suffixDP=i+1>=length?{probability:1,decimal:0,patterns:[]}:dp[i+1];while(pattern&&pattern.index+pattern.length-1===i){const startIndex=pattern.index;const curDP={probability:pattern.probability*suffixDP.probability,decimal:suffixDP.decimal+getPatternDecimal(pattern),patterns:suffixDP.patterns,concatPattern:pattern,};checkDecimal(curDP);dp[startIndex]=getMaxProbability(dp[startIndex],curDP);pattern=patterns[--patternIndex]}const iDP={probability:1e-13*suffixDP.probability,decimal:0,patterns:suffixDP.patterns,};checkDecimal(iDP);dp[i]=getMaxProbability(dp[i],iDP);if(dp[i].concatPattern){dp[i].patterns=dp[i].patterns.concat(dp[i].concatPattern);dp[i].concatPattern=undefined;delete dp[i+1]}}return dp[0].patterns.reverse()}function getMinCount(a,b){if(!a){return b}return a.count<=b.count?a:b}function getPatternCount(pattern){if(pattern.priority===Priority.Custom){return-(pattern.length*pattern.length*100000)}if(pattern.priority===Priority.Surname){return-(pattern.length*pattern.length*100)}return 1}function minTokenization(patterns,length){const dp=[];let patternIndex=patterns.length-1;let pattern=patterns[patternIndex];for(let i=length-1;i>=0;i--){const suffixDP=i+1>=length?{count:0,patterns:[]}:dp[i+1];while(pattern&&pattern.index+pattern.length-1===i){const startIndex=pattern.index;const curDP={count:getPatternCount(pattern)+suffixDP.count,patterns:suffixDP.patterns,concatPattern:pattern};dp[startIndex]=getMinCount(dp[startIndex],curDP);pattern=patterns[--patternIndex]}const iDP={count:1+suffixDP.count,patterns:suffixDP.patterns,};dp[i]=getMinCount(dp[i],iDP);if(dp[i].concatPattern){dp[i].patterns=dp[i].patterns.concat(dp[i].concatPattern);dp[i].concatPattern=undefined;delete dp[i+1]}}return dp[0].patterns.reverse()}function isIgnorablePattern(cur,pre){if(pre.index+pre.length<=cur.index){return false}if(pre.priority>cur.priority){return false}if(pre.priority===cur.priority&&pre.length>cur.length){return false}return true}function reverseMaxMatch(patterns){const filteredArr=[];for(let i=patterns.length-1;i>=0;){const{index}=patterns[i];let j=i-1;while(j>=0&&isIgnorablePattern(patterns[i],patterns[j])){j--}if(j<0||patterns[j].index+patterns[j].length<=index){filteredArr.push(patterns[i])}i=j}return filteredArr.reverse()}var TokenizationAlgorithm;(function(TokenizationAlgorithm){TokenizationAlgorithm[TokenizationAlgorithm["ReverseMaxMatch"]=1]="ReverseMaxMatch";TokenizationAlgorithm[TokenizationAlgorithm["MaxProbability"]=2]="MaxProbability";TokenizationAlgorithm[TokenizationAlgorithm["MinTokenization"]=3]="MinTokenization"})(TokenizationAlgorithm||(TokenizationAlgorithm={}));class TrieNode{constructor(parent,prefix="",key=""){this.children=new Map();this.fail=null;this.patterns=[];this.parent=parent;this.prefix=prefix;this.key=key}}class AC{constructor(){this.dictMap=new Map();this.queues=[];this.root=new TrieNode(null)}build(patternList){this.buildTrie(patternList);this.buildFailPointer()}buildTrie(patternList){for(let pattern of patternList){const zhChars=splitString(pattern.zh);let cur=this.root;for(let i=0;i{queue=queue.concat(_queue)});this.queues=[];while(queue.length>queueIndex){let node=queue[queueIndex++];let failNode=node.parent&&node.parent.fail;let key=node.key;while(failNode&&!failNode.children.has(key)){failNode=failNode.fail}if(!failNode){node.fail=this.root}else{node.fail=failNode.children.get(key)}}}addPatternToDictMap(pattern){if(!this.dictMap.has(pattern.dict)){this.dictMap.set(pattern.dict,new Set())}this.dictMap.get(pattern.dict).add(pattern)}addNodeToQueues(trieNode){if(!this.queues[stringLength(trieNode.prefix)]){this.queues[stringLength(trieNode.prefix)]=[]}this.queues[stringLength(trieNode.prefix)].push(trieNode)}insertPattern(patterns,pattern){for(let i=patterns.length-1;i>=0;i--){const _pattern=patterns[i];if(pattern.priority===_pattern.priority&&pattern.probability>=_pattern.probability){patterns[i+1]=_pattern}else if(pattern.priority>_pattern.priority){patterns[i+1]=_pattern}else{patterns[i+1]=pattern;return}}patterns[0]=pattern}removeDict(dictName){if(this.dictMap.has(dictName)){const set=this.dictMap.get(dictName);set.forEach((pattern)=>{pattern.node.patterns=pattern.node.patterns.filter((_pattern)=>_pattern!==pattern)});this.dictMap.delete(dictName)}}match(text,surname){let cur=this.root;let result=[];const zhChars=splitString(text);for(let i=0;i{if(surname==="off"){return item.priority!==Priority.Surname}else if(surname==="head"){return item.length-1-i===0}else{return true}});if(pattern){result.push(Object.assign(Object.assign({},pattern),{index:i-pattern.length+1}))}let failNode=cur.fail;while(failNode!==null){const pattern=failNode.patterns.find((item)=>{if(surname==="off"){return item.priority!==Priority.Surname}else if(surname==="head"){return item.length-1-i===0}else{return true}});if(pattern){result.push(Object.assign(Object.assign({},pattern),{index:i-pattern.length+1}))}failNode=failNode.fail}}}return result}search(text,surname,algorithm=2){const patterns=this.match(text,surname);if(algorithm===1){return reverseMaxMatch(patterns)}else if(algorithm===3){return minTokenization(patterns,stringLength(text))}return maxProbability(patterns,stringLength(text))}}const PatternsNormal=[...Pattern5,...Pattern4,...Pattern3,...Pattern2,...PatternNumberDict,...PatternSurname,];const acTree=new AC();acTree.build(PatternsNormal);let customDict={};const customMultipleDict=new FastDictFactory();const customPolyphonicDict=new FastDictFactory();const CustomDictName=Symbol('custom');function customPinyin(config={},options){const words=Object.keys(config).sort((word1,word2)=>stringLength(word2)-stringLength(word1));words.forEach((word)=>{customDict[word]=config[word]});const customPatterns=Object.keys(customDict).map((word)=>({zh:word,pinyin:customDict[word],probability:1+stringLength(word),length:stringLength(word),priority:Priority.Custom,dict:CustomDictName,}));acTree.build(customPatterns);if(options===null||options===void 0?void 0:options.multiple){addCustomConfigToDict(config,customMultipleDict,options.multiple)}if(options===null||options===void 0?void 0:options.polyphonic){addCustomConfigToDict(config,customPolyphonicDict,options.polyphonic)}}function addCustomConfigToDict(config,dict,handleType){for(let word in config){const pinyins=config[word];splitString(word).forEach((char,index)=>{const pinyin=pinyins.split(' ')[index]||'';if(handleType==='replace'||(handleType==='add'&&!dict.get(char)&&!DICT1.get(char))){dict.set(char,pinyin)}else{dict.set(char,dict.get(char)||DICT1.get(char));if(!dict.get(char).split(' ').includes(pinyin)){dict.set(char,`${dict.get(char)}${pinyin}`.trim())}}})}}const getCustomMultpileDict=()=>{return customMultipleDict};const getCustomPolyphonicDict=()=>{return customPolyphonicDict};function clearCustomDict(dict){if(dict==='pinyin'||dict.indexOf('pinyin')!==-1){Object.keys(customDict).forEach(function(word){delete customDict[word]});acTree.removeDict(CustomDictName)}if(dict==='multiple'||dict.indexOf('multiple')!==-1){customMultipleDict.clear()}if(dict==='polyphonic'||dict.indexOf('polyphonic')!==-1){customPolyphonicDict.clear()}}const getSingleWordPinyin=(char)=>{const pinyin=DICT1.get(char);return pinyin?pinyin.split(" ")[0]:char};const getPinyin=(word,list,surname,segmentit)=>{const matches=acTree.search(word,surname,segmentit);let matchIndex=0;const zhChars=splitString(word);for(let i=0;i{return pinyin.replace(/(ā|á|ǎ|à)/g,"a").replace(/(ō|ó|ǒ|ò)/g,"o").replace(/(ē|é|ě|è)/g,"e").replace(/(ī|í|ǐ|ì)/g,"i").replace(/(ū|ú|ǔ|ù)/g,"u").replace(/(ǖ|ǘ|ǚ|ǜ)/g,"ü").replace(/(n̄|ń|ň|ǹ)/g,"n").replace(/(m̄|ḿ|m̌|m̀)/g,"m").replace(/(ê̄|ế|ê̌|ề)/g,"ê")};const getAllPinyin=(char,surname="off")=>{const customMultpileDict=getCustomMultpileDict();let pinyin=DICT1.get(char)?DICT1.get(char).split(" "):[];if(customMultpileDict.get(char)){pinyin=customMultpileDict.get(char).split(" ")}else if(surname!=="off"){const surnamePinyin=Surnames[char];if(surnamePinyin){pinyin=[surnamePinyin].concat(pinyin.filter((py)=>py!==surnamePinyin))}}return pinyin};const getMultiplePinyin=(word,surname="off")=>{let pinyin=getAllPinyin(word,surname);if(pinyin.length>0){return pinyin.map((value)=>({origin:word,result:value,isZh:true,originPinyin:value,}))}else{return[{origin:word,result:word,isZh:false,originPinyin:word,},]}};const getInitialAndFinal=(pinyin,initialPattern)=>{const pinyin_arr=pinyin.split(" ");const initial_arr=[];const final_arr=[];for(let _pinyin of pinyin_arr){for(let _initial of InitialList){if(_pinyin.startsWith(_initial)){let _final=_pinyin.slice(_initial.length);if(SpecialInitialList.indexOf(_initial)!==-1&&SpecialFinalList.indexOf(_final)!==-1){_final=SpecialFinalMap[_final]}initial_arr.push(_initial);final_arr.push(_final);break}}}if(initialPattern==="standard"){initial_arr.forEach((initial,index)=>{if(initial==="y"||initial==="w"){initial_arr[index]=""}})}return{final:final_arr.join(" "),initial:initial_arr.join(" "),}};const getFinalParts=(pinyin)=>{const{final}=getInitialAndFinal(pinyin);let head="",body="",tail="";if(doubleFinalList.indexOf(getPinyinWithoutTone(final))!==-1){head=final[0];body=final[1];tail=final.slice(2)}else{body=final[0]||"";tail=final.slice(1)||""}return{head,body,tail}};const getNumOfTone=(pinyin)=>{const reg_tone1=/(ā|ō|ē|ī|ū|ǖ|n̄|m̄|ê̄)/;const reg_tone2=/(á|ó|é|í|ú|ǘ|ń|ḿ|ế)/;const reg_tone3=/(ǎ|ǒ|ě|ǐ|ǔ|ǚ|ň|m̌|ê̌)/;const reg_tone4=/(à|ò|è|ì|ù|ǜ|ǹ|m̀|ề)/;const reg_tone0=/(a|o|e|i|u|ü|ê)/;const special_tone=/(n|m)$/;const tone_num_arr=[];const pinyin_arr=pinyin.split(" ");pinyin_arr.forEach((_pinyin)=>{if(reg_tone1.test(_pinyin)){tone_num_arr.push("1")}else if(reg_tone2.test(_pinyin)){tone_num_arr.push("2")}else if(reg_tone3.test(_pinyin)){tone_num_arr.push("3")}else if(reg_tone4.test(_pinyin)){tone_num_arr.push("4")}else if(reg_tone0.test(_pinyin)){tone_num_arr.push("0")}else if(special_tone.test(_pinyin)){tone_num_arr.push("0")}else{tone_num_arr.push("")}});return tone_num_arr.join(" ")};const getPinyinWithNum=(pinyin,originPinyin)=>{const pinyin_arr=getPinyinWithoutTone(pinyin).split(" ");const tone_num_arr=getNumOfTone(originPinyin).split(" ");const res_arr=[];pinyin_arr.forEach((item,index)=>{res_arr.push(`${item}${tone_num_arr[index]}`)});return res_arr.join(" ")};const getFirstLetter=(pinyin,isZh)=>{const first_letter_arr=[];const pinyin_arr=pinyin.split(" ");pinyin_arr.forEach((pinyin)=>{first_letter_arr.push(isZh?pinyin[0]:pinyin)});return first_letter_arr.join(" ")};const validateType=(word)=>{if(typeof word!=="string"){console.error("The first param of pinyin is error: "+word+' is not assignable to type "string".');return false}else{return true}};function isNonZhScope(char,scope){if(scope instanceof RegExp){return scope.test(char)}return true}const middleWareNonZh=(list,options)=>{let nonZh=options.nonZh;if(nonZh==="removed"){return list.filter((item)=>item.isZh||!isNonZhScope(item.origin,options.nonZhScope))}else if(nonZh==="consecutive"){for(let i=list.length-2;i>=0;i--){const cur=list[i];const pre=list[i+1];if(!cur.isZh&&!pre.isZh&&isNonZhScope(cur.origin,options.nonZhScope)&&isNonZhScope(pre.origin,options.nonZhScope)){cur.origin+=pre.origin;cur.result+=pre.result;pre.delete=true}}return list.filter((item)=>!item.delete)}else{return list}};const middlewareMultiple=(word,options)=>{if(stringLength(word)===1&&options.multiple){return getMultiplePinyin(word,options.surname)}else{return false}};const middlewarePattern=(list,options)=>{switch(options.pattern){case"pinyin":break;case"num":list.forEach((item)=>{item.result=item.isZh?getNumOfTone(item.result):""});break;case"initial":list.forEach((item)=>{item.result=item.isZh?getInitialAndFinal(item.result,options.initialPattern).initial:""});break;case"final":list.forEach((item)=>{item.result=item.isZh?getInitialAndFinal(item.result,options.initialPattern).final:""});break;case"first":list.forEach((item)=>{item.result=getFirstLetter(item.result,item.isZh)});break;case"finalHead":list.forEach((item)=>{item.result=item.isZh?getFinalParts(item.result).head:""});break;case"finalBody":list.forEach((item)=>{item.result=item.isZh?getFinalParts(item.result).body:""});break;case"finalTail":list.forEach((item)=>{item.result=item.isZh?getFinalParts(item.result).tail:""});break}};const middlewareToneType=(list,options)=>{switch(options.toneType){case"symbol":break;case"none":list.forEach((item)=>{if(item.isZh){item.result=getPinyinWithoutTone(item.result)}});break;case"num":{list.forEach((item)=>{if(item.isZh){item.result=getPinyinWithNum(item.result,item.originPinyin)}});break}}};const middlewareV=(list,options)=>{if(options.v){list.forEach((item)=>{if(item.isZh){item.result=item.result.replace(/ü/g,typeof options.v==="string"?options.v:"v")}})}};const middlewareType=(list,options,word)=>{if(options.multiple&&stringLength(word)===1){let last="";list=list.filter((item)=>{const res=item.result!==last;last=item.result;return res})}if(options.type==="array"){return list.map((item)=>item.result)}if(options.type==="all"){return list.map((item)=>{const pinyin=item.isZh?item.result:"";const{initial,final}=getInitialAndFinal(pinyin,options.initialPattern);const{head,body,tail}=getFinalParts(pinyin);let polyphonic=[];if(pinyin!==""){polyphonic=[pinyin].concat(getAllPinyin(item.origin,options.surname).filter((item)=>item!==pinyin))}return{origin:item.origin,pinyin,initial,final,first:getFirstLetter(item.result,item.isZh),finalHead:head,finalBody:body,finalTail:tail,num:Number(getNumOfTone(item.originPinyin)),isZh:item.isZh,polyphonic,inZhRange:!!DICT1.get(item.origin),result:item.result,}})}return list.map((item)=>item.result).join(options.separator)};const middlewareToneSandhi=(list,toneSandhi)=>{if(toneSandhi===false){list.forEach((item)=>{if(item.origin==="一"){item.result=item.originPinyin="yī"}else if(item.origin==="不"){item.result=item.originPinyin="bù"}})}return list};const DEFAULT_OPTIONS$2={pattern:"pinyin",toneType:"symbol",type:"string",multiple:false,mode:"normal",removeNonZh:false,nonZh:"spaced",v:false,separator:" ",toneSandhi:true,segmentit:2,};function pinyin(word,options){options=Object.assign(Object.assign({},DEFAULT_OPTIONS$2),(options||{}));const legal=validateType(word);if(!legal){return word}if(word===""){return options.type==="array"||options.type==="all"?[]:""}if(options.surname===undefined){if(options.mode==="surname"){options.surname="all"}else{options.surname="off"}}if(options.type==="all"){options.pattern="pinyin"}if(options.pattern==="num"){options.toneType="none"}if(options.removeNonZh){options.nonZh="removed"}let _list=Array(stringLength(word));let{list}=getPinyin(word,_list,options.surname,options.segmentit);list=middlewareToneSandhi(list,options.toneSandhi);list=middleWareNonZh(list,options);if(middlewareMultiple(word,options)){list=middlewareMultiple(word,options)}middlewarePattern(list,options);middlewareToneType(list,options);middlewareV(list,options);return middlewareType(list,options,word)}const DefaultName=Symbol("default");const originDictMap=new Map();function addDict(dict,options){const patterns=[];const name=typeof options==="object"?options.name:options;const dictName=name||DefaultName;const dict1Handle=(options===null||options===void 0?void 0:options.dict1)||"add";for(let word in dict){const value=dict[word];const pinyin=Array.isArray(value)?value[0]:value;const wordLength=stringLength(word);if(wordLength===1){addToOriginDict(dictName,word,pinyin,dict1Handle)}if(Array.isArray(value)){patterns.push({zh:word,pinyin,probability:typeof value[1]==="number"?value[1]:2e-8*wordLength*wordLength,length:wordLength,priority:Priority.Normal,dict:dictName,pos:typeof value[2]==="string"?value[2]:"",})}else{patterns.push({zh:word,pinyin,probability:2e-8*wordLength*wordLength,length:wordLength,priority:Priority.Normal,dict:dictName,})}}acTree.build(patterns)}function removeDict(dictName){acTree.removeDict(dictName||DefaultName);removeOriginDict(dictName||DefaultName)}function addToOriginDict(dict,char,pinyin,handle="add"){if(!originDictMap.get(dict)){originDictMap.set(dict,{})}const originDict=originDictMap.get(dict);if(!originDict[char]){originDict[char]=DICT1.get(char)}if(handle==="add"){const existedPinyin=DICT1.get(char);if(existedPinyin&&!existedPinyin.split(' ').includes(pinyin)){DICT1.set(char,`${existedPinyin}${pinyin}`)}else if(!DICT1.get(char)){DICT1.set(char,pinyin)}}else if(handle==="replace"){DICT1.set(char,pinyin)}}function removeOriginDict(dict){const originDict=originDictMap.get(dict)||{};for(let char in originDict){DICT1.set(char,originDict[char]);delete originDict[char]}}const DefaultMatchOptions={precision:"first",continuous:false,space:"ignore",lastPrecision:"start",insensitive:true,v:false,};const MAX_PINYIN_LENGTH=6;const match=(text,pinyin,options)=>{if((options===null||options===void 0?void 0:options.precision)==="any"){options.lastPrecision="any"}if(options===null||options===void 0?void 0:options.v){pinyin=pinyin.replace(/ü/g,"v")}const completeOptions=Object.assign(Object.assign({},DefaultMatchOptions),(options||{}));if(completeOptions.insensitive!==false){text=text.toLowerCase();pinyin=pinyin.toLowerCase()}if(completeOptions.space==="ignore"){pinyin=pinyin.replace(/\s/g,"")}const result=(options===null||options===void 0?void 0:options.precision)==="any"?matchAny(text,pinyin,completeOptions):matchAboveStart(text,pinyin,completeOptions);return processDoubleUnicodeIndex(text,result)};const getMatchLength=(pinyin1,pinyin2)=>{let length=0;for(let i=0;i{let result=[];const words=splitString(text);const ignoreSpace=options.space==="ignore";for(let i=0;i{const length=getMatchLength(p,pinyin$1);if(length>currentLength){currentLength=length}});if(currentLength){pinyin$1=pinyin$1.slice(currentLength);result.push(i)}if(!pinyin$1){break}}if(pinyin$1){return null}if(options.continuous){const _result=result;const isNotContinuous=result.some((val,index)=>index>0&&val!==_result[index-1]+1);if(isNotContinuous){return null}}if(options.space==="ignore"){result=result.filter((i)=>words[i]!==" ")}return result.length?result:null};const matchAboveStart=(text,pinyin$1,options)=>{const words=splitString(text);const dp=Array(words.length+1);for(let i=0;idp[i][j].length){dp[i][j]=matches}if(j===pinyin$1.length){return dp[i][j]}}if(pinyin$1.length-j<=MAX_PINYIN_LENGTH){const last=muls.some((py)=>{if(options.lastPrecision==="any"){return py.includes(pinyin$1.slice(j-1,pinyin$1.length))}if(options.lastPrecision==="start"){return py.startsWith(pinyin$1.slice(j-1,pinyin$1.length))}if(options.lastPrecision==="first"){return py[0]===pinyin$1.slice(j-1,pinyin$1.length)}if(options.lastPrecision==="every"){return py===pinyin$1.slice(j-1,pinyin$1.length)}return false});if(last){return[...dp[i-1][j-1],i-1]}}const precision=options.precision;if(precision==="start"){muls.forEach((py)=>{let end=j;const matches=[...dp[i-1][j-1],i-1];while(end<=pinyin$1.length&&py.startsWith(pinyin$1.slice(j-1,end))){if(!dp[i][end]||matches.length>dp[i][end].length){dp[i][end]=matches}end++}})}if(precision==="first"){if(muls.some((py)=>py[0]===pinyin$1[j-1])){const matches=[...dp[i-1][j-1],i-1];if(!dp[i][j]||matches.length>dp[i][j].length){dp[i][j]=matches}}}const completeMatch=muls.find((py)=>py===pinyin$1.slice(j-1,j-1+py.length));if(completeMatch){const matches=[...dp[i-1][j-1],i-1];const endIndex=j-1+completeMatch.length;if(!dp[i][endIndex]||matches.length>dp[i][endIndex].length){dp[i][endIndex]=matches}}}}}return null};function processDoubleUnicodeIndex(text,indexArray){if(!indexArray){return null}const result=[];let doubleUnicodeCount=0;const words=splitString(text);let i=0;for(let j=0;j{const completeOptions=Object.assign(Object.assign({},DefaultHtmlOptions),(options||{}));const pinyinArray=pinyin(text,{type:"all",toneType:completeOptions.toneType,toneSandhi:options===null||options===void 0?void 0:options.toneSandhi,v:completeOptions.v,});const result=pinyinArray.map((item)=>{let additionalClass="";for(const classname in completeOptions.customClassMap){const dict=completeOptions.customClassMap[classname];if(dict.includes(item.origin)){additionalClass+=`${classname}`}}if(item.isZh){const resultClass=completeOptions.resultClass||DefaultHtmlOptions.resultClass;const chineseClass=completeOptions.chineseClass||DefaultHtmlOptions.chineseClass;const pinyinClass=completeOptions.pinyinClass||DefaultHtmlOptions.pinyinClass;return`${item.origin}${completeOptions.rp?"(":""}${item.pinyin}${completeOptions.rp?")":""}`}else{if(completeOptions.wrapNonChinese){const nonChineseClass=completeOptions.nonChineseClass||DefaultHtmlOptions.nonChineseClass;return`${item.origin}`}else{return item.origin}}});return result.join("")};const DEFAULT_OPTIONS$1={pattern:"pinyin",toneType:"symbol",type:"string",v:false,nonZh:"spaced",};function polyphonic(text,options=DEFAULT_OPTIONS$1){const legal=validateType(text);if(!legal){return[]}if(text===""){return[]}if(options.type==="all"){options.pattern="pinyin"}if(options.pattern==="num"){options.toneType="none"}if(options.removeNonZh){options.nonZh="removed"}let list=getPolyphonicList(text);list=middleWareNonZh(list,options);let doubleList=getSplittedPolyphonicList(list);doubleList.forEach((list)=>{middlewarePattern(list,options)});doubleList.forEach((list)=>{middlewareToneType(list,options)});doubleList.forEach((list)=>{middlewareV(list,options)});const result=doubleList.map((list)=>handleType(list,options));return result}const getPolyphonicList=(text)=>{return splitString(text).map((char)=>{const customPolyphonicDict=getCustomPolyphonicDict();const pinyin=customPolyphonicDict.get(char)||DICT1.get(char)||char;return{origin:char,result:pinyin,isZh:pinyin!==char,originPinyin:pinyin,}})};const getSplittedPolyphonicList=(list)=>{return list.map((item)=>{return item.isZh?item.result.split(" ").map((pinyin)=>({origin:item.origin,result:pinyin,isZh:true,originPinyin:pinyin,})):[item]})};const handleType=(list,options)=>{if(options.type==="array"){return Array.from(new Set(list.map((item)=>item.result)))}if(options.type==="all"){return list.map((item)=>{const pinyin=item.isZh?item.result:"";const{initial,final}=getInitialAndFinal(pinyin,options.initialPattern);const{head,body,tail}=getFinalParts(pinyin);return{origin:item.origin,pinyin,initial,final,first:getFirstLetter(item.result,item.isZh),finalHead:head,finalBody:body,finalTail:tail,num:Number(getNumOfTone(item.originPinyin)),isZh:item.isZh,inZhRange:!!DICT1.get(item.origin),}})}return Array.from(new Set(list.map((item)=>item.result))).join(" ")};const DefaultConvertOptions={separator:' ',format:'numToSymbol',};const toneMap={a:['a','ā','á','ǎ','à'],o:['o','ō','ó','ǒ','ò'],e:['e','ē','é','ě','è'],ü:['ü','ǖ','ǘ','ǚ','ǜ'],v:['ü','ǖ','ǘ','ǚ','ǜ'],ui:['ui','uī','uí','uǐ','uì'],iu:['iu','iū','iú','iǔ','iù'],i:['i','ī','í','ǐ','ì'],u:['u','ū','ú','ǔ','ù'],n:['n','n̄','ń','ň','ǹ'],m:['m','m̄','ḿ','m̌','m̀'],ê:['ê','ê̄','ế','ê̌','ề'],};function convert(pinyin,options){options=Object.assign(Object.assign({},DefaultConvertOptions),(options||{}));const originType=typeof pinyin;if(typeof pinyin==='string'){pinyin=pinyin.split(options.separator)}pinyin=pinyin.map((item)=>{const format=options.format;if(format==='numToSymbol'){return formatNumToSymbol(item)}else if(format==='symbolToNum'){return formatSymbolToNum(item)}else if(format==='toneNone'){return formatToneNone(item)}return item});if(originType==='string'){return pinyin.join(options.separator)}else{return pinyin}}function formatNumToSymbol(pinyin){const lastChar=Number(pinyin[pinyin.length-1]);if(lastChar>=0&&lastChar<=4){for(let key in toneMap){if(pinyin.includes(key)){return pinyin.slice(0,pinyin.length-1).replace(key,toneMap[key][lastChar])}}return pinyin}else{return pinyin}}function formatSymbolToNum(pinyin){return`${getPinyinWithoutTone(pinyin)}${getNumOfTone(pinyin)}`}function formatToneNone(pinyin){return getPinyinWithoutTone(pinyin)}var OutputFormat;(function(OutputFormat){OutputFormat[OutputFormat["AllSegment"]=1]="AllSegment";OutputFormat[OutputFormat["AllArray"]=2]="AllArray";OutputFormat[OutputFormat["AllString"]=3]="AllString";OutputFormat[OutputFormat["PinyinSegment"]=4]="PinyinSegment";OutputFormat[OutputFormat["PinyinArray"]=5]="PinyinArray";OutputFormat[OutputFormat["PinyinString"]=6]="PinyinString";OutputFormat[OutputFormat["ZhSegment"]=7]="ZhSegment";OutputFormat[OutputFormat["ZhArray"]=8]="ZhArray";OutputFormat[OutputFormat["ZhString"]=9]="ZhString"})(OutputFormat||(OutputFormat={}));function middlewareSegment(list,matches){const segments=[];let i=0;let j=0;while(i({origin:item.origin,result:item.result,})),isZh:true,});i+=cur-start;j++}else{segments.push({segment:[{origin:item.origin,result:item.result,}],isZh:false,});i++}}while(i{return{origin:item.segment.map(item=>item.origin).join(''),result:item.segment.map(item=>item.result).join(''),}})}else if(format===OutputFormat.AllArray){return segments.map(item=>item.segment)}else if(format===OutputFormat.AllString){const list=segments.map(item=>{return{origin:item.segment.map(item=>item.origin).join(''),result:item.segment.map(item=>item.result).join(''),}});return{origin:list.map(item=>item.origin).join(separator),result:list.map(item=>item.result).join(separator),}}else if(format===OutputFormat.PinyinSegment){return segments.map(item=>item.segment.map(item=>item.result).join(''))}else if(format===OutputFormat.PinyinArray){return segments.map(item=>item.segment.map(item=>item.result))}else if(format===OutputFormat.PinyinString){return segments.map(item=>item.segment.map(item=>item.result).join('')).join(separator)}else if(format===OutputFormat.ZhSegment){return segments.map(item=>item.segment.map(item=>item.origin).join(''))}else if(format===OutputFormat.ZhArray){return segments.map(item=>item.segment.map(item=>item.origin))}else if(format===OutputFormat.ZhString){return segments.map(item=>item.segment.map(item=>item.origin).join('')).join(separator)}}const DEFAULT_OPTIONS={toneType:"symbol",mode:"normal",nonZh:"spaced",v:false,separator:" ",toneSandhi:true,segmentit:2,format:OutputFormat.AllSegment,};function segment(word,options){options=Object.assign(Object.assign({},DEFAULT_OPTIONS),(options||{}));const legal=validateType(word);if(!legal){return word}if(options.surname===undefined){if(options.mode==="surname"){options.surname="all"}else{options.surname="off"}}let _list=Array(stringLength(word));let{list,matches}=getPinyin(word,_list,options.surname,options.segmentit);list=middlewareToneSandhi(list,options.toneSandhi);list=middleWareNonZh(list,options);middlewareToneType(list,options);middlewareV(list,options);const segments=middlewareSegment(list,matches);return middlewareOutputFormat(segments,{format:options.format,separator:options.separator})}export{OutputFormat,addDict,clearCustomDict,convert,customPinyin,getFinalParts,getInitialAndFinal,getNumOfTone,html,match,pinyin,polyphonic,removeDict,segment}; \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/changelog.md b/uni_modules/x-clipboard-s/changelog.md new file mode 100644 index 0000000..db1a39b --- /dev/null +++ b/uni_modules/x-clipboard-s/changelog.md @@ -0,0 +1,6 @@ +## 1.0.2(2025-08-03) +* 兼容鸿蒙原生,使用时请自行申请权限使用。 +## 1.0.1(2025-02-10) +* 兼容微信 +## 1.0.0(2025-01-08) +* 剪切板操作 diff --git a/uni_modules/x-clipboard-s/package.json b/uni_modules/x-clipboard-s/package.json new file mode 100644 index 0000000..5e0ce21 --- /dev/null +++ b/uni_modules/x-clipboard-s/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-clipboard-s", + "displayName": "x-clipboard-s", + "version": "1.0.1", + "description": "x-clipboard-s", + "keywords": [ + "x-clipboard-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/readme.md b/uni_modules/x-clipboard-s/readme.md new file mode 100644 index 0000000..eefba34 --- /dev/null +++ b/uni_modules/x-clipboard-s/readme.md @@ -0,0 +1,90 @@ +# x-clipboard-s + +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +### 介绍 +这是tmui4.0|XUI的原生插件附赠插件,提供了跨平台的剪贴板操作功能。支持在Android、iOS、Web和小程序平台上进行文本内容的复制和获取操作。 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + + +```json +"requestPermissions": [ + { + "name": "ohos.permission.READ_PASTEBOARD", + "reason": "$string:permission_read_pasteboard" + } +] +``` + +### 注意事项 +- Web平台:新版浏览器会自动请求剪贴板权限 +- Android平台:使用系统ClipboardManager服务实现 +- iOS平台:使用UIPasteboard实现 +- 小程序:使用平台原生API实现 + +### API接口 + +#### setClipboardData +`setClipboardData(data: string): Promise` +设置剪贴板内容 + +**参数说明:** +- data:要设置的文本内容 + +**返回值:** +- `Promise`:操作成功返回true,失败返回false + +#### getClipboardData() +`getClipboardData(): Promise` +获取剪贴板内容 + +**返回值:** +- `Promise`:成功返回剪贴板文本内容,失败返回错误信息 + +### 使用示例 + +```ts +import { setClipboardData, getClipboardData } from "@/uni_modules/x-clipboard-s" + +// 设置剪贴板内容 +const setText = () => { + setClipboardData("要复制的文本").then(ok => { + if (ok) { + uni.showToast({ title: "复制成功", icon: "success" }) + } + }).catch(err => { + uni.showToast({ title: "复制失败", icon: "error" }) + }) +} + +// 获取剪贴板内容 +const getText = () => { + getClipboardData().then((text: string) => { + uni.showToast({ + title: text, + icon: "none" + }) + }).catch(err => { + uni.showToast({ + title: "获取剪贴板内容失败", + icon: "error" + }) + }) +} +``` + +### 常见问题 +1. Web端获取剪贴板内容失败? + - 检查浏览器是否授予了剪贴板访问权限 + - 确保在HTTPS环境下运行 + +2. Android/iOS端操作失败? + - 检查应用是否具有剪贴板权限 + - 确保传入的是文本内容 diff --git a/uni_modules/x-clipboard-s/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-clipboard-s/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..7af9db1 --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/utssdk/app-android/config.json b/uni_modules/x-clipboard-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/utssdk/app-android/index.uts b/uni_modules/x-clipboard-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..b71c85a --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-android/index.uts @@ -0,0 +1,26 @@ +import ClipData from "android.content.ClipData"; +import ClipboardManager from "android.content.ClipboardManager"; +import Context from "android.content.Context"; + +export const setClipboardData = (data : string):Promise => { + let context = UTSAndroid.getAppContext()! + let clipboard : ClipboardManager | null = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager; + let clip : ClipData | null = ClipData.newPlainText("label", data); + if (clip != null && clipboard != null) { + clipboard.setPrimaryClip(clip); + return Promise.resolve(true) + } else { + return Promise.reject(false) as Promise + } +} + +export const getClipboardData = ():Promise => { + let context = UTSAndroid.getAppContext()! + let clipboard : ClipboardManager | null = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager; + if (clipboard != null) { + if (clipboard.hasText()) { + return Promise.resolve(clipboard.getText().toString()) + } + } + return Promise.reject('未知错误') as Promise +} \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/utssdk/app-harmony/index.uts b/uni_modules/x-clipboard-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..4ed94f5 --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-harmony/index.uts @@ -0,0 +1,36 @@ +import { BusinessError, pasteboard } from '@kit.BasicServicesKit'; + + +export const setClipboardData = (data : string) : Promise => { + let pasteData : pasteboard.PasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, data); + let systemPasteboard : pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard(); + return new Promise((res, rej) => { + + systemPasteboard.setData(pasteData).then(() => { + console.info("成功") + res(true) + }) + .catch((e) => { + const err = e as BusinessError + console.error(err.message) + rej(false) + }) + }) + +} + +export const getClipboardData = () : Promise => { + let systemPasteboard : pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard(); + // return new Promise((res, rej) => { + // systemPasteboard.getData((err, data) => { + // if (err) { + // console.error(err.message) + // return rej(err.message); + // } + // res(data.getPrimaryText()) + // }) + // }) + + return Promise.resolve('') + +} \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/utssdk/app-harmony/module.json5 b/uni_modules/x-clipboard-s/utssdk/app-harmony/module.json5 new file mode 100644 index 0000000..c901b4f --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-harmony/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "uni_modules__x_clipboard_s", + "type":"har", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ] + } +} diff --git a/uni_modules/x-clipboard-s/utssdk/app-harmony/resources/base/element/string.json b/uni_modules/x-clipboard-s/utssdk/app-harmony/resources/base/element/string.json new file mode 100644 index 0000000..dfd9663 --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-harmony/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "permission_read_pasteboard", + "value": "应用需要读取剪粘板进行应用的个性化需要" + } + ] +} diff --git a/uni_modules/x-clipboard-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-clipboard-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-clipboard-s/utssdk/app-ios/config.json b/uni_modules/x-clipboard-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-clipboard-s/utssdk/app-ios/index.uts b/uni_modules/x-clipboard-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..a59604e --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/app-ios/index.uts @@ -0,0 +1,23 @@ +import { UIPasteboard } from 'UIKit'; + +export const setClipboardData = (data : string):Promise => { + try { + let borad : UIPasteboard = UIPasteboard.general + borad.string = data; + return Promise.resolve(true) as Promise + } catch (errors) { + return Promise.reject(false) as Promise + } +} + +export const getClipboardData = ():Promise => { + try { + let borad : UIPasteboard = UIPasteboard.general + if(borad.string == null){ + return Promise.reject('未知错误') as Promise + } + return Promise.resolve(borad.string!) + } catch (errors) { + return Promise.reject('未知错误') as Promise + } +} \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/utssdk/interface.uts b/uni_modules/x-clipboard-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-clipboard-s/utssdk/mp-weixin/index.uts b/uni_modules/x-clipboard-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..01d9898 --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,27 @@ + +export const setClipboardData = (data : string):Promise => { + return new Promise((resl,rejl)=>{ + wx.setClipboardData({ + data: data, + success(res) { + resl(true) + }, + fail(res) { + rejl(false) + } + }) + }) +} +export const getClipboardData = ():Promise => { + return new Promise((resl,rejl)=>{ + wx.getClipboardData({ + success(res) { + resl(res.data) + }, + fail(res) { + rejl('未知错误') + } + }) + }) + +} \ No newline at end of file diff --git a/uni_modules/x-clipboard-s/utssdk/unierror.uts b/uni_modules/x-clipboard-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-clipboard-s/utssdk/web/index.uts b/uni_modules/x-clipboard-s/utssdk/web/index.uts new file mode 100644 index 0000000..3925eac --- /dev/null +++ b/uni_modules/x-clipboard-s/utssdk/web/index.uts @@ -0,0 +1,37 @@ +export const setClipboardData = (data : string):Promise => { + // 设置剪切板内容 + return new Promise((resl,rejl)=>{ + navigator.clipboard.writeText(data) + .then(() => { + resl(true) + }) + .catch(err => { + rejl(false) + console.error('无法设置剪切板数据', err); + }); + }) +} +export const getClipboardData = ():Promise => { + let inputdom = document.createElement("input") as HTMLInputElement; + inputdom.style.setProperty('opacity', '0') + inputdom.style.setProperty('position', 'absolute') + document.body.appendChild(inputdom) + inputdom.focus(); + document.execCommand('paste'); + return new Promise((resl,rejl)=>{ + if (!document.execCommand('paste')) { + navigator.clipboard.readText() + .then(text => { + resl(text) + }) + .catch(err => { + rejl('没有权限') + console.error('无法读取剪切板内容: ', err); + }); + } else { + resl(inputdom.value) + } + inputdom.remove() + }) + +} \ No newline at end of file diff --git a/uni_modules/x-crypto-s/changelog.md b/uni_modules/x-crypto-s/changelog.md new file mode 100644 index 0000000..63eb336 --- /dev/null +++ b/uni_modules/x-crypto-s/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2025-08-17) +* 兼容支持鸿蒙 Next +## 1.0.2(2025-03-15) +* 更新所有端都支持同样的加密方案。 +## 1.0.1(2025-02-28) +* 补齐hmacSha512,sha512,aesEncrypt,aesDecrypt增加keySize加密位,增加了generateRSAKeyPair生成RSA密钥对. +## 1.0.0(2024-12-24) +* 常用 加密 三端可用.暂不支持sm2,sm3,sm4,下个版本提供. \ No newline at end of file diff --git a/uni_modules/x-crypto-s/package.json b/uni_modules/x-crypto-s/package.json new file mode 100644 index 0000000..41bf432 --- /dev/null +++ b/uni_modules/x-crypto-s/package.json @@ -0,0 +1,82 @@ +{ + "id": "x-crypto-s", + "displayName": "x-crypto-s", + "version": "1.0.0", + "description": "x-crypto-s", + "keywords": [ + "x-crypto-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-crypto-s/readme.md b/uni_modules/x-crypto-s/readme.md new file mode 100644 index 0000000..c479a45 --- /dev/null +++ b/uni_modules/x-crypto-s/readme.md @@ -0,0 +1,146 @@ +# x-crypto-s +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +加密插件 + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件,提供了多种加密算法的实现,包括MD5、Base64、SHA系列、AES、DES、RSA和RC4等。所有加密算法均采用原生加密代码实现,与CryptoJS加密结果完全一致。 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### API说明 + +#### MD5加密 +```ts +function md5(str: string): string +``` +- 参数: + - str: 待加密的字符串 +- 返回值:MD5加密后的字符串 + +#### Base64编解码 +```ts +function base64Encode(str: string): string +function base64Decode(str: string): string +``` +- 参数: + - str: 待编码/解码的字符串 +- 返回值:Base64编码/解码后的字符串 +- 注意:在Web端加密中文字符时,需要先使用encodeURI处理 + +#### SHA系列加密 +```ts +function sha256(str: string): string +function sha512(str: string): string +function sha1(str: string): string +function hmacSha256(key: string, data: string): string +function hmacSha512(key: string, data: string): string +``` +- 参数: + - str/data: 待加密的字符串 + - key: HMAC加密的密钥 +- 返回值:对应算法加密后的字符串 + +#### AES加密 +```ts +function aesEncrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null, keySize: number|null = null): string +function aesDecrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null, keySize: number|null = null): string +``` +- 参数: + - key: 加密密钥(UTF-8字符串,根据keySize截取和补足) + - data: 待加密/解密的数据 + - mode: 加密模式,支持ECB和CBC + - iv: 初始化向量 + - keySize: 密钥长度(16=128位, 24=192位, 32=256位) +- 返回值:加密/解密后的字符串 + +#### DES加密 +```ts +function desEncrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null): string +function desDecrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null): string +``` +- 参数: + - key: 加密密钥 + - data: 待加密/解密的数据 + - mode: 加密模式,支持ECB和CBC + - iv: 初始化向量 +- 返回值:加密/解密后的字符串 + +#### RSA加密 +```ts +function generateRSAKeyPair(keySize: number = 2048): RSARANDOMKEY +function rsaEncrypt(publicKey: string, data: string): string +function rsaDecrypt(privateKey: string, data: string): string +``` +- 参数: + - keySize: RSA密钥长度 + - publicKey: 公钥 + - privateKey: 私钥 + - data: 待加密/解密的数据 +- 返回值: + - generateRSAKeyPair: 返回包含publicKey和privateKey的对象 + - rsaEncrypt/rsaDecrypt: 加密/解密后的字符串 + +#### RC4加密 +```ts +function rc4Encrypt(key: string, data: string): string +function rc4Decrypt(key: string, data: string): string +``` +- 参数: + - key: 加密密钥 + - data: 待加密/解密的数据 +- 返回值:加密/解密后的字符串(hex格式) + +### 使用示例 + +```ts +import { + md5, sha256, sha512, sha1, hmacSha256, hmacSha512, + base64Encode, base64Decode, + aesEncrypt, aesDecrypt, + desEncrypt, desDecrypt, + rsaEncrypt, rsaDecrypt, + rc4Encrypt, rc4Decrypt, + generateRSAKeyPair +} from '@/uni_modules/x-crypto-s' + +// MD5加密 +const md5Result = md5("TMUI4.0X") + +// Base64编解码 +const base64Result = base64Encode("TMUI4.0X") +const decodedText = base64Decode(base64Result) + +// SHA系列加密 +const sha256Result = sha256("TMUI4.0X") +const hmacResult = hmacSha256("密钥", "TMUI4.0X") + +// AES加密(CBC模式) +const aesResult = aesEncrypt( + "1234567890abcdef", + "TMUI4.0X", + "CBC", + "1234567890abcdef" +) +const aesDecrypted = aesDecrypt( + "1234567890abcdef", + aesResult, + "CBC", + "1234567890abcdef" +) + +// RSA加密 +const rsaKeys = generateRSAKeyPair() +const encrypted = rsaEncrypt(rsaKeys.publicKey, "TMUI4.0X") +const decrypted = rsaDecrypt(rsaKeys.privateKey, encrypted) +``` + +更多使用示例和在线加密对比工具: +- MD5/SHA对比:https://www.mklab.cn/utils/md5 +- DES对比:https://www.mklab.cn/utils/des \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/app-android/config.json b/uni_modules/x-crypto-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/app-android/crypto.kt b/uni_modules/x-crypto-s/utssdk/app-android/crypto.kt new file mode 100644 index 0000000..90a3e26 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/app-android/crypto.kt @@ -0,0 +1,393 @@ +package uts.sdk.modules.utsXcryptoS + +import java.security.* +import java.security.spec.X509EncodedKeySpec +import java.security.spec.PKCS8EncodedKeySpec +import javax.crypto.* +import javax.crypto.spec.SecretKeySpec +import javax.crypto.spec.IvParameterSpec +import android.util.Base64 +import java.nio.charset.Charset +import io.dcloud.uts.console +import java.security.KeyPair +import java.security.KeyPairGenerator +import java.security.spec.RSAKeyGenParameterSpec + + +import java.security.KeyFactory + + + + +// 定义支持的输出长度枚举 +enum class OutputLength(val length: Int) { + LENGTH_16(8), // 8 bytes = 16 hex chars + LENGTH_32(16), // 16 bytes = 32 hex chars + LENGTH_64(32) // 32 bytes = 64 hex chars +} +data class RSARandomKey(val publicKey: String, val privateKey: String) + + +class UniversalCryptoHelper { + companion object { + // MD5 Encryption ,32位加密 + fun md5(input: String): String { + val md = MessageDigest.getInstance("MD5") + val digest = md.digest(input.toByteArray()) + return digest.joinToString("") { "%02x".format(it) } + } + + // BASE64 Encoding and Decoding + fun base64Encode(input: String): String = Base64.encodeToString(input.toByteArray(), android.util.Base64.NO_WRAP) + fun base64Decode(input: String): String = String(Base64.decode(input, Base64.DEFAULT)) + + // HMAC with SHA-256 + fun hmacSha256(key: String, data: String): String { + val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256") + val mac = Mac.getInstance("HmacSHA256") + mac.init(secretKey) + val hash = mac.doFinal(data.toByteArray()) + return hash.joinToString("") { "%02x".format(it) } + } + + // SHA-1 and SHA-256 Hashing + fun sha1(input: String): String { + val md = MessageDigest.getInstance("SHA-1") + val digest = md.digest(input.toByteArray()) + return digest.joinToString("") { "%02x".format(it) } + } + + fun sha256(input: String): String { + val md = MessageDigest.getInstance("SHA-256") + val digest = md.digest(input.toByteArray()) + return digest.joinToString("") { "%02x".format(it) } + } + + /** + * 计算SHA-512哈希值 + * @param input 需要计算哈希的字符串 + * @return 哈希值的十六进制字符串 + */ + fun sha512(input: String): String { + val md = MessageDigest.getInstance("SHA-512") + val digest = md.digest(input.toByteArray()) + return digest.joinToString("") { "%02x".format(it) } + } + + /** + * 使用HMAC-SHA512算法计算消息认证码 + * @param key 密钥 + * @param data 需要认证的数据 + * @return HMAC值的十六进制字符串 + */ + fun hmacSha512(key: String, data: String): String { + val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA512") + val mac = Mac.getInstance("HmacSHA512") + mac.init(secretKey) + val hmacBytes = mac.doFinal(data.toByteArray()) + return hmacBytes.joinToString("") { "%02x".format(it) } + } + + fun generateAesKey(key: String, keySize: Int = 16): ByteArray { + val fixedKey = key.padEnd(keySize, '0') // 填充到 16 字节(128 位) + return fixedKey.toByteArray().copyOf(keySize) // 截断或扩展为 16 字节 + } + + fun generateDesKey(key: String,keySize: Int = 24): ByteArray { + // 确保密钥长度为24字节,不足时用0填充,过长时截断 + val keyBytes = key.toByteArray() + val paddedKey = ByteArray(keySize) + if (keyBytes.size < keySize) { + System.arraycopy(keyBytes, 0, paddedKey, 0, keyBytes.size) + } else { + System.arraycopy(keyBytes, 0, paddedKey, 0, keySize) + } + return paddedKey + } + fun generateDesKey2(key: ByteArray,keySize: Int = 24): ByteArray { + // 确保密钥长度为24字节,不足时用0填充,过长时截断 + val keyBytes = key + val paddedKey = ByteArray(keySize) + if (keyBytes.size < keySize) { + System.arraycopy(keyBytes, 0, paddedKey, 0, keyBytes.size) + } else { + System.arraycopy(keyBytes, 0, paddedKey, 0, keySize) + } + return paddedKey + } + /** + * 返回编码为base64,cbc或者ecb,填充这pkcs5/pkdcs7,密钥和iv偏移均为16位 + */ + fun aesEncrypt(input: String, key: String,mode:String,iv: String? = null,keySize:Int?=16): String { + + if(mode=="ECB"){ + val secretKey = SecretKeySpec(generateDesKey(key,keySize?:16), "AES") + val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") + cipher.init(Cipher.ENCRYPT_MODE, secretKey) + val encrypted = cipher.doFinal(input.toByteArray()) + return Base64.encodeToString(encrypted, Base64.NO_WRAP) + } + // cbc + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + val keySpec = SecretKeySpec(generateDesKey(key,keySize?:16), "AES") + + val ivSpecBz = generateDesKey(iv?:"",16) + val ivSpec = IvParameterSpec(ivSpecBz) + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec) + val encrypted = cipher.doFinal(input.toByteArray()) + return Base64.encodeToString(encrypted, Base64.NO_WRAP) + } + fun aesEncrypt2(input: ByteArray, key: ByteArray,mode:String,iv: ByteArray? = null,keySize:Int?=16): ByteArray { + + if(mode=="ECB"){ + val secretKey = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES") + val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") + cipher.init(Cipher.ENCRYPT_MODE, secretKey) + val encrypted = cipher.doFinal(input) + return encrypted + } + // cbc + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + val keySpec = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES") + + val ivSpecBz = generateDesKey2(iv?:ByteArray(keySize?:16),16) + val ivSpec = IvParameterSpec(ivSpecBz) + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec) + val encrypted = cipher.doFinal(input) + + return encrypted + } + /** + * 加密文本为base64,cbc或者ecb,填充这pkcs5/pkdcs7,密钥和iv偏移均为16位,返回字符串. + */ + fun aesDecrypt(input: String, key: String,mode:String,iv: String? = null,keySize:Int?=16): String { + if(mode=="ECB"){ + val secretKey = SecretKeySpec(generateDesKey(key,keySize?:16), "AES") + val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") + cipher.init(Cipher.DECRYPT_MODE, secretKey) + val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT)) + return String(decrypted) + } + // cbc + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + val keySpec = SecretKeySpec(generateDesKey(key,keySize?:16), "AES") + // val ivSpec = adjustIV(iv?:"":iv,keySize?:16) + // val ivSpec = IvParameterSpec(iv!!.toByteArray()) + val ivSpecBz = generateDesKey(iv?:"",16) + val ivSpec = IvParameterSpec(ivSpecBz) + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec) + val decodedBytes = Base64.decode(input, Base64.DEFAULT) + val decrypted = cipher.doFinal(decodedBytes) + return String(decrypted) + + } + + + fun aesDecrypt2(input: ByteArray, key: ByteArray,mode:String,iv: ByteArray? = null,keySize:Int?=16): ByteArray { + if(mode=="ECB"){ + val secretKey = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES") + val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") + cipher.init(Cipher.DECRYPT_MODE, secretKey) + val decrypted = cipher.doFinal(input) + // val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT)) + return decrypted + } + // cbc + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + val keySpec = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES") + // val ivSpec = adjustIV(iv?:"":iv,keySize?:16) + // val ivSpec = IvParameterSpec(iv!!.toByteArray()) + val ivSpecBz = generateDesKey2(iv?:ByteArray(keySize?:16),16) + val ivSpec = IvParameterSpec(ivSpecBz) + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec) + // val decodedBytes = Base64.decode(input, Base64.DEFAULT) + val decrypted = cipher.doFinal(input) + return decrypted + + } + + + + // DES Encryption and Decryption + fun desEncrypt(input: String, key: String,mode:String,iv: String? = null): String { + val secretKey = SecretKeySpec(generateDesKey(key), "DESede") + val cipher: Cipher = when (mode) { + "ECB" -> Cipher.getInstance("DESede/ECB/PKCS5Padding") + "CBC" -> Cipher.getInstance("DESede/CBC/PKCS5Padding") + else -> throw IllegalArgumentException("Unsupported mode: $mode") + } + + if (mode == "CBC" && iv == null) { + throw IllegalArgumentException("IV must not be null for CBC mode") + } + + if (mode == "CBC") { + val ivSpec = IvParameterSpec(iv!!.toByteArray()) + cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec) + } else { + cipher.init(Cipher.ENCRYPT_MODE, secretKey) + } + + val encrypted = cipher.doFinal(input.toByteArray()) + return Base64.encodeToString(encrypted, android.util.Base64.NO_WRAP) + } + + fun desDecrypt(input: String, key: String,mode:String,iv: String? = null): String { + val secretKey = SecretKeySpec(generateDesKey(key), "DESede") + val cipher: Cipher = when (mode) { + "ECB" -> Cipher.getInstance("DESede/ECB/PKCS5Padding") + "CBC" -> Cipher.getInstance("DESede/CBC/PKCS5Padding") + else -> throw IllegalArgumentException("Unsupported mode: $mode") + } + + if (mode == "CBC" && iv == null) { + throw IllegalArgumentException("IV must not be null for CBC mode") + } + + if (mode == "CBC") { + val ivSpec = IvParameterSpec(iv!!.toByteArray()) + cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec) + } else { + cipher.init(Cipher.DECRYPT_MODE, secretKey) + } + + val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT)) + return String(decrypted) + } + + + + // Convert String to PublicKey + fun stringToPublicKey(publicKeyStr: String): PublicKey { + + val keyBytes = Base64 + .decode(publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replace("\r", "") + .replace("\n", "") + .replace("\t", "") + .replace(" ", "") + , Base64.DEFAULT + ) + + val keySpec = X509EncodedKeySpec(keyBytes) + val keyFactory = KeyFactory.getInstance("RSA") + return keyFactory.generatePublic(keySpec) + } + + // Convert String to PrivateKey + fun stringToPrivateKey(privateKeyStr: String): PrivateKey { + val keyBytes = Base64.decode(privateKeyStr.replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replace("\r", "") + .replace("\n", "") + .replace("\t", "") + .replace(" ", "") + , Base64.DEFAULT + ) + val keySpec = PKCS8EncodedKeySpec(keyBytes) + val keyFactory = KeyFactory.getInstance("RSA") + return keyFactory.generatePrivate(keySpec) + } + + + fun generateRSAKeyPair(keySize: Int = 2048): RSARandomKey { + val keyPairGenerator = KeyPairGenerator.getInstance("RSA") + keyPairGenerator.initialize(RSAKeyGenParameterSpec(keySize, RSAKeyGenParameterSpec.F4)) + val keyPair: KeyPair = keyPairGenerator.generateKeyPair() + + // 将公钥转换为X.509格式 + val x509EncodedPublicKey = keyPair.public.encoded + val publicKeyString = Base64.encodeToString(x509EncodedPublicKey, Base64.NO_WRAP) + + // 将私钥转换为PKCS#8格式 + val pkcs8EncodedPrivateKey = keyPair.private.encoded + val privateKeyString = Base64.encodeToString(pkcs8EncodedPrivateKey, Base64.NO_WRAP) + + return RSARandomKey(publicKeyString, privateKeyString) + } + + + // 默认是PKCS1,填充:(OAEP)RSA/ECB/OAEPWithSHA-1AndMGF1Padding或者(PKCS1)RSA/ECB/PKCS1Padding + fun rsaEncrypt(input: String, publicKeyStr: String): String { + val publicKey = stringToPublicKey(publicKeyStr) + val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding") + cipher.init(Cipher.ENCRYPT_MODE, publicKey) + val encrypted = cipher.doFinal(input.toByteArray()) + return Base64.encodeToString(encrypted, Base64.NO_WRAP) + + } + // input是base64,PKCS1填充生成的加密内容 + fun rsaDecrypt(input: String, privateKeyStr: String): String { + val privateKey = stringToPrivateKey(privateKeyStr) + val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding") + cipher.init(Cipher.DECRYPT_MODE, privateKey) + val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT)) + return String(decrypted) + } + + + + + fun rc4Init(key: ByteArray): ByteArray { + val s = ByteArray(256) { it.toByte() } + var j = 0 + + for (i in 0..255) { + j = (j + s[i].toInt() + key[i % key.size].toInt() and 0xFF) and 0xFF + val temp = s[i] + s[i] = s[j] + s[j] = temp + } + + return s + } + + fun rc4Process(data: ByteArray, key: ByteArray, outputLength: OutputLength): ByteArray { + val s = rc4Init(key) + val result = ByteArray(outputLength.length) // 使用指定的字节长度 + var i = 0 + var j = 0 + + for (n in result.indices) { + i = (i + 1) and 0xFF + j = (j + s[i].toInt() and 0xFF) and 0xFF + + val temp = s[i] + s[i] = s[j] + s[j] = temp + + val t = (s[i].toInt() + s[j].toInt() and 0xFF) and 0xFF + val k = s[t].toInt() and 0xFF + + result[n] = if (n < data.size) { + (data[n].toInt() xor k).toByte() + } else { + k.toByte() + } + } + + return result + } + //输出是hex字符串,密钥是8位字符 + fun rc4Encrypt(data: String, key: String): String { + val dataBytes = data.toByteArray() + val keyBytes = key.toByteArray() + val encrypted = rc4Process(dataBytes, keyBytes, OutputLength.LENGTH_16) + return encrypted.joinToString("") { "%02x".format(it) } + } + //输入encryptedHex是hex字符串,返回是string,密钥是8位字符 + fun rc4Decrypt(encryptedHex: String, key: String): String { + val encryptedBytes = encryptedHex.chunked(2) + .map { it.toInt(16).toByte() } + .toByteArray() + val keyBytes = key.toByteArray() + val decrypted = rc4Process(encryptedBytes, keyBytes, OutputLength.LENGTH_16) + return decrypted.toString(Charset.defaultCharset()).trim('\u0000') + } + + + + + } +} diff --git a/uni_modules/x-crypto-s/utssdk/app-android/index.uts b/uni_modules/x-crypto-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..6f5256d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/app-android/index.uts @@ -0,0 +1,134 @@ +import UniversalCryptoHelper from 'uts.sdk.modules.utsXcryptoS.UniversalCryptoHelper'; +import { RSARANDOMKEY } from "../interface.uts" + +export function md5(str : string) : string { + return UniversalCryptoHelper.md5(str); +} +export function base64Encode(str : string) : string { + return UniversalCryptoHelper.base64Encode(str); +} +export function base64Decode(str : string) : string { + return UniversalCryptoHelper.base64Decode(str); +} +export function sha256(str : string) : string { + return UniversalCryptoHelper.sha256(str); +} +export function hmacSha256(key:string,data : string) : string { + return UniversalCryptoHelper.hmacSha256(key,data); +} + +export function sha512(str : string) : string { + return UniversalCryptoHelper.sha512(str) +} + +export function hmacSha512(key : string, data : string) : string { + return UniversalCryptoHelper.hmacSha512(key,data) +} + +export function sha1(str : string) : string { + return UniversalCryptoHelper.sha1(str); +} +/** + * Aes + * @param {string} key utf8字符串它会根据keySize来截取和补足0 + * @param {string} data 待加密的字符 + * @param {string} mode ECB,CBC + * @param {string} iv 固定是16位,不足会补齐0 + * @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + */ +export function aesEncrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null,keySize:number|null=null) : string { + console.log("长度:",(keySize==null?16:keySize).toInt()) + return UniversalCryptoHelper.aesEncrypt(data,key,mode,iv,(keySize==null?16:keySize).toInt()); +} +/** + * Aes + * @param {Uint8Array} key Uint8Array数据它会根据keySize来截取和补足0 + * @param {Uint8Array} data 待加密的Uint8Array + * @param {string} mode ECB,CBC + * @param {Uint8Array} iv 固定是16位,不足会补齐0 + * @param {number} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + * @returns {Uint8Array} 数据 + */ +export function aesEncrypt2(key:Uint8Array,data : Uint8Array,mode:string = "ECB",iv:Uint8Array|null = null,keySize:number|null=null) : Uint8Array { + + function u8tbr(d:Uint8Array):ByteArray{ + let bar = new ByteArray(d.length.toInt()) + for(let i = 0;i + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-crypto-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources b/uni_modules/x-crypto-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources new file mode 100644 index 0000000..9c4c16a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources @@ -0,0 +1,212 @@ + + + + + files + + Headers/unimoduleXCryptoS-Swift.h + + sYrSn+RyBIFDQBszO3/P8xJljp8= + + Headers/unimoduleXCryptoS.h + + FH2SRnQAHIO8AbDZPa5/Bz/CcdA= + + Info.plist + + IVoTM86XmFTSTQOc3nqKLlrf+g4= + + Modules/module.modulemap + + Mb2Zqns/19tDjbGpiH3LGGA1fQA= + + Modules/unimoduleXCryptoS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + LrNVXN9SxWbowabgwHEhjXGtoM8= + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.abi.json + + u+u1y6eK8UyQLdXF+asiH9J61zw= + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + TBpJmMJe82pwDjT2PuqjFG0QOgo= + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + vAWogVlQ2acSpes+rngJqaHu53s= + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + TBpJmMJe82pwDjT2PuqjFG0QOgo= + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + DYmcbJn2Wta9ChJfVGlUIOckdl0= + + config.json + + /sqVTWYkSC3IKjeGGZtJQnx8PC0= + + + files2 + + Headers/unimoduleXCryptoS-Swift.h + + hash2 + + bTRltszQF3+fsDE5fSoWA2h4RJFMjgJiooCIolmygdk= + + + Headers/unimoduleXCryptoS.h + + hash2 + + XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY= + + + Modules/module.modulemap + + hash2 + + W0XF/xxiculnRfXzfkaeT5qgc+qCLcZzsOzHUDmxshc= + + + Modules/unimoduleXCryptoS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + hash2 + + l63MWC0FBuCg1jbWMzXhOYlbdgWWib9kANlDZQDhvOQ= + + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.abi.json + + hash2 + + LjfbpG0RJlR1dLq/DxB3kwt6X4B0pQQmnw5Obt8VOhU= + + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + hash2 + + tYzzmU2An+2B2UBi/H0Qkz+BkR6fVGyq0IKlEcdMCxk= + + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + hash2 + + NXc6efR/rQre4hYKBGOWCStcK9AsMK9pnXXvCFoiq4c= + + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + hash2 + + tYzzmU2An+2B2UBi/H0Qkz+BkR6fVGyq0IKlEcdMCxk= + + + Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + hash2 + + NAmTbjwY/t547ARB7gCdhKUdLuBnd/8815n5YixIHB8= + + + config.json + + hash2 + + aW1+rl6/vnHObZ31RQBG9uwopiZhbmvup1CuOkP3aZo= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/uni_modules/x-crypto-s/utssdk/app-ios/UniversalCryptoHelper.swift b/uni_modules/x-crypto-s/utssdk/app-ios/UniversalCryptoHelper.swift new file mode 100644 index 0000000..9ef8668 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/app-ios/UniversalCryptoHelper.swift @@ -0,0 +1,1295 @@ + +import Foundation +import CryptoSwift +import Security +import CommonCrypto +// UTS内置对象的引用 +import DCloudUTSFoundation +enum OutputLength: Int { + case LENGTH_16 = 8 // 8 bytes = 16 hex chars + case LENGTH_32 = 16 // 16 bytes = 32 hex chars + case LENGTH_64 = 32 // 32 bytes = 64 hex chars +} + + +struct RSARandomKey { + let publicKey: String + let privateKey: String +} + +enum RSAError: Error { + case keyExtractionFailed + + case invalidKeyFormat + case invalidInput + case keyGenerationFailed(status: OSStatus) + case publicKeyConversionFailed + case privateKeyConversionFailed + + case keyCreationFailed + case encryptionFailed + case decryptionFailed + case dataConversionFailed + case base64DecodingFailed +} + +// 生成指定长度的密钥,类似于Android版本 +func generateKey(key: String, keySize: Int = 16) -> [UInt8] { + let keyBytes = Array(key.utf8) + var paddedKey = [UInt8](repeating: 0, count: keySize) + + if keyBytes.count < keySize { + // 不足时用0填充 + paddedKey.replaceSubrange(0.. [UInt8] { + var paddedKey = [UInt8](repeating: 0, count: keySize) + + if key.count < keySize { + // 不足时用0填充 + paddedKey.replaceSubrange(0.. Data? { + let secKey = addPrivateKey(privateKey) + if secKey == nil { + return nil + } + return encrypt(data, with: secKey!, and: true) + } + + /// 使用私钥字符串加密String + /// - Parameters: + /// - string: 需加密的String + /// - privateKey: 私钥字符串 + /// - Returns: 加密后String + public static func encryptString(_ string: String, privateKey: String) -> String? { + guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKey: privateKey) else { + return nil + } + return base64_encode_data(data) + } + + /// 使用私钥字符串解密Data + /// - Parameters: + /// - data: 需解密的Data + /// - privateKey: 私钥字符串 + /// - Returns: 解密后Data + public static func decryptData(_ data: Data, privateKey: String) -> Data? { + let secKey = addPrivateKey(privateKey) + if secKey == nil { + return nil + } + return decrypt(data, with: secKey!) + } + + /// 使用私钥字符串解密String + /// - Parameters: + /// - string: 需解密的String + /// - privateKey: 私钥字符串 + /// - Returns: 解密后String + public static func decryptString(_ string: String, privateKey: String) -> String? { + var data = base64_decode(string) + data = decryptData(data!, privateKey: privateKey) + if data == nil { + return nil + } + return String.init(data: data!, encoding: String.Encoding.utf8) + } + + /// 使用公钥字符串加密Data + /// - Parameters: + /// - data: 需加密的Data + /// - publicKey: 公钥字符串 + /// - Returns: 加密后Data + public static func encryptData(_ data: Data, publicKey: String) -> Data? { + let secKey = addPublicKey(publicKey) + if secKey == nil { + return nil + } + return encrypt(data, with: secKey!, and: false) + } + + /// 使用公钥字符串加密String + /// - Parameters: + /// - string: 需加密的String + /// - publicKey: 公钥字符串 + /// - Returns: 加密后String + public static func encryptString(_ string: String, publicKey: String) -> String? { + guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKey: publicKey) else { + return nil + } + return base64_encode_data(data) + } + + /// 使用公钥字符串解密Data + /// - Parameters: + /// - data: 需解密的Data + /// - publicKey: 公钥字符串 + /// - Returns: 解密后Data + public static func decryptData(_ data: Data, publicKey: String) -> Data? { + let secKey = addPublicKey(publicKey) + if secKey == nil { + return nil + } + return decrypt(data, with: secKey!) + } + + /// 使用公钥字符串解密String + /// - Parameters: + /// - string: 需解密的String + /// - publicKey: 公钥字符串 + /// - Returns: 解密后String + public static func decryptString(_ string: String, publicKey: String) -> String? { + var data = base64_decode(string) + data = decryptData(data!, publicKey: publicKey) + if data == nil { + return nil + } + return String.init(data: data!, encoding: String.Encoding.utf8) + } + + //MARK:- encrypt or decrypt by SecKey data + + /// 使用私钥Data加密Data + /// - Parameters: + /// - data: 需加密的Data + /// - privateKeyData: 私钥Data + /// - Returns: 加密后的Data + public static func encryptData(_ data: Data, privateKeyData: Data) -> Data? { + let secKey = addPrivateKey(privateKeyData) + if secKey == nil { + return nil + } + return encrypt(data, with: secKey!, and: true) + } + + /// 使用私钥Data加密String + /// - Parameters: + /// - string: 需加密的String + /// - privateKeyData: 私钥Data + /// - Returns: 加密后的String + public static func encryptString(_ string: String, privateKeyData: Data) -> String? { + guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKeyData: privateKeyData) else { + return nil + } + return base64_encode_data(data) + } + + /// 用私钥Data解密Data + /// - Parameters: + /// - data: 需解密的Data + /// - privateKeyData: 私钥Data + /// - Returns: 解密后的Data + public static func decryptData(_ data: Data, privateKeyData: Data) -> Data? { + let secKey = addPrivateKey(privateKeyData) + if secKey == nil { + return nil + } + return decrypt(data, with: secKey!) + } + + /// 用私钥Data解密String + /// - Parameters: + /// - string: 需解密的String + /// - privateKeyData: 私钥Data + /// - Returns: 解密后的String + public static func decryptString(_ string: String, privateKeyData: Data) -> String? { + var data = base64_decode(string) + data = decryptData(data!, privateKeyData: privateKeyData) + if data == nil { + return nil + } + return String.init(data: data!, encoding: String.Encoding.utf8) + } + + /// 使用公钥Data加密Data + /// - Parameters: + /// - data: 需加密的Data + /// - publicKeyData: 公钥Data + /// - Returns: 加密后Data + public static func encryptData(_ data: Data, publicKeyData: Data) -> Data? { + let secKey = addPublicKey(publicKeyData) + if secKey == nil { + return nil + } + return encrypt(data, with: secKey!, and: false) + } + + /// 使用公钥Data加密String + /// - Parameters: + /// - string: 需加密的String + /// - publicKeyData: 公钥Data + /// - Returns: 加密后String + public static func encryptString(_ string: String, publicKeyData: Data) -> String? { + guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKeyData: publicKeyData) else { + return nil + } + return base64_encode_data(data) + } + + /// 使用公钥Data解密Data + /// - Parameters: + /// - data: 需解密的Data + /// - publicKeyData: 公钥Data + /// - Returns: 解密后Data + public static func decryptData(_ data: Data, publicKeyData: Data) -> Data? { + let secKey = addPublicKey(publicKeyData) + if secKey == nil { + return nil + } + return decrypt(data, with: secKey!) + } + + /// 使用公钥Data解密String + /// - Parameters: + /// - string: 需解密的String + /// - publicKeyData: 公钥Data + /// - Returns: 解密后String + public static func decryptString(_ string: String, publicKeyData: Data) -> String? { + var data = base64_decode(string) + data = decryptData(data!, publicKeyData: publicKeyData) + if data == nil { + return nil + } + return String.init(data: data!, encoding: String.Encoding.utf8) + } + + //MARK:- encrypt or decrypt by SecKey path + + + /// 使用私钥证书路径加密Data + /// - Parameters: + /// - data: 需加密的Data + /// - privateKeyPath: 私钥证书路径 + /// - Returns: 加密后Data + public static func encryptData(_ data: Data, privateKeyPath: String) -> Data? { + let secKey = loadPrivateKey(privateKeyPath) + if secKey == nil { + return nil + } + return encrypt(data, with: secKey!, and: true) + } + + /// 使用私钥证书路径加密String + /// - Parameters: + /// - string: 需加密的String + /// - privateKeyPath: 私钥证书路径 + /// - Returns: 加密后String + public static func encryptString(_ string: String, privateKeyPath: String) -> String? { + guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKeyPath: privateKeyPath) else { + return nil + } + return base64_encode_data(data) + } + + /// 使用私钥证书路径解密Data + /// - Parameters: + /// - data: 需解密的Data + /// - privateKeyPath: 私钥证书路径 + /// - Returns: 解密后Data + public static func decryptData(_ data: Data, privateKeyPath: String) -> Data? { + let secKey = loadPrivateKey(privateKeyPath) + if secKey == nil { + return nil + } + return decrypt(data, with: secKey!) + } + + /// 使用私钥证书路径解密String + /// - Parameters: + /// - string: 需解密的String + /// - privateKeyPath: 私钥证书路径 + /// - Returns: 解密后String + public static func decryptString(_ string: String, privateKeyPath: String) -> String? { + var data = base64_decode(string) + data = decryptData(data!, privateKeyPath: privateKeyPath) + if data == nil { + return nil + } + return String.init(data: data!, encoding: String.Encoding.utf8) + } + + /// 使用公钥证书路径加密Data + /// - Parameters: + /// - data: 需加密的Data + /// - publicKeyPath: 公钥证书路径 + /// - Returns: 加密后Data + public static func encryptData(_ data: Data, publicKeyPath: String) -> Data? { + let secKey = loadPublicKey(publicKeyPath) + if secKey == nil { + return nil + } + return encrypt(data, with: secKey!, and: false) + } + + /// 使用公钥证书路径加密String + /// - Parameters: + /// - string: 需加密的String + /// - publicKeyPath: 公钥证书路径 + /// - Returns: 加密后String + public static func encryptString(_ string: String, publicKeyPath: String) -> String? { + guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKeyPath: publicKeyPath) else { + return nil + } + return base64_encode_data(data) + } + + /// 使用公钥证书路径解密Data + /// - Parameters: + /// - data: 需解密的Data + /// - publicKeyPath: 公钥证书路径 + /// - Returns: 解密后Data + public static func decryptData(_ data: Data, publicKeyPath: String) -> Data? { + let secKey = loadPublicKey(publicKeyPath) + if secKey == nil { + return nil + } + return decrypt(data, with: secKey!) + } + + /// 使用公钥证书路径解密String + /// - Parameters: + /// - string: 需解密的String + /// - publicKeyPath: 公钥证书路径 + /// - Returns: 解密后String + public static func decryptString(_ string: String, publicKeyPath: String) -> String? { + var data = base64_decode(string) + data = decryptData(data!, publicKeyPath: publicKeyPath) + if data == nil { + return nil + } + return String.init(data: data!, encoding: String.Encoding.utf8) + } + + + //MARK:- OTHER + + private static func base64_encode_data(_ data: Data) -> String? { + let newData = data.base64EncodedData(options: Data.Base64EncodingOptions.lineLength64Characters) + return String.init(data: newData, encoding: String.Encoding.utf8) + } + + private static func base64_decode(_ string: String) -> Data? { + return Data.init(base64Encoded: string, options: Data.Base64DecodingOptions.ignoreUnknownCharacters) + } + + private static func stripPublicKeyHeader(_ d_key: Data?) -> Data? { + guard let dKey = d_key else { + return nil + } + let len = dKey.count + if len == 0 { + return nil + } + + var cKey = dataToBytes(dKey) + var index = 0 + + if cKey[index] != 0x30 { + return nil + } + index += 1 + + if cKey[index] > 0x80 { + index += Int(cKey[index]) - 0x80 + 1 + } else { + index += 1 + } + + let swqiod:[CUnsignedChar] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00] + if (memcmp(&cKey[index], swqiod, 15) == 1) { + return nil + } + + index += 15 + + if cKey[index] != 0x03 { + return nil + } + index += 1 + + if cKey[index] > 0x80 { + index += Int(cKey[index]) - 0x80 + 1 + } else { + index += 1 + } + + if cKey[index] != Unicode.Scalar.init("\0").value { + return nil + } + + index += 1 + + return Data.init(cKey).advanced(by: index) + } + + private static func stripPrivateKeyHeader(_ d_key: Data?) -> Data? { + guard let dKey = d_key else { + return nil + } + let len = dKey.count + if len == 0 { + return nil + } + + var cKey = dataToBytes(dKey) + var index = 22 + + if cKey[index] != 0x04 { + return nil + } + index += 1 + + var cLen = Int(cKey[index]) + index += 1 + let det = cLen & 0x80 + if det == 0 { + cLen = cLen & 0x7f + } else { + var byteCount = Int(cLen & 0x7f) + if Int(byteCount) + index > len { + return nil + } + var accum = 0 + var ptr = withUnsafePointer(to: &cKey[index]) { $0 } + index += Int(byteCount) + while byteCount > 0 { + accum = (accum << 8) + Int(ptr.pointee) + ptr = ptr.advanced(by: 1) + byteCount -= 1 + } + cLen = accum + } + + return dKey.subdata(in: Range.init(_NSRange.init(location: index, length: Int(cLen)))!) + } + + /// 公钥字符串转SecKey + /// - Parameter key: 公钥字符串 + /// - Returns: SecKey + private static func addPublicKey(_ key: String) -> SecKey? { + var newKey = key + let spos = newKey.range(of: "-----BEGIN PUBLIC KEY-----") + let epos = newKey.range(of: "-----END PUBLIC KEY-----") + if spos != nil && epos != nil { + newKey = String(newKey[spos!.upperBound.. SecKey? { + let tag = "RSAUtil_PubKey" + let d_tag = tag.data(using: String.Encoding.utf8) + + var publicKey = Dictionary.init() + publicKey[kSecClass as String] = kSecClassKey + publicKey[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA + publicKey[kSecAttrApplicationTag as String] = d_tag + SecItemDelete(publicKey as CFDictionary) + + publicKey[kSecValueData as String] = data + publicKey[kSecAttrKeyClass as String] = kSecAttrKeyClassPublic + publicKey[kSecReturnPersistentRef as String] = true + + var status = SecItemAdd(publicKey as CFDictionary, nil) + + if status != noErr && status != errSecDuplicateItem { + return nil + } + + publicKey.removeValue(forKey: kSecValueData as String) + publicKey.removeValue(forKey: kSecReturnPersistentRef as String) + publicKey[kSecReturnRef as String] = NSNumber(value: true) + publicKey[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA + + var keyRef: CFTypeRef? + status = SecItemCopyMatching(publicKey as CFDictionary, &keyRef) + if status != noErr { + return nil + } + return (keyRef as! SecKey) + } + + /// 私钥字符串转SecKey + /// - Parameter key: 私钥字符串     /// - Returns: SecKey + private static func addPrivateKey(_ key: String) -> SecKey? { + var newKey = key + var spos: Range? + var epos: Range? + spos = newKey.range(of: "-----BEGIN RSA PRIVATE KEY-----") + if spos != nil { + epos = newKey.range(of: "-----END RSA PRIVATE KEY-----") + } else { + spos = newKey.range(of: "-----BEGIN PRIVATE KEY-----") + epos = newKey.range(of: "-----END PRIVATE KEY-----") + } + if spos != nil && epos != nil { + newKey = String(newKey[spos!.upperBound.. SecKey? { + let tag = "RSAUtil_PrivKey" + let d_tag = tag.data(using: String.Encoding.utf8) + + var privateKey = Dictionary.init() + privateKey[kSecClass] = kSecClassKey + privateKey[kSecAttrKeyType] = kSecAttrKeyTypeRSA + privateKey[kSecAttrApplicationTag] = d_tag + SecItemDelete(privateKey as CFDictionary) + + privateKey[kSecValueData] = data + privateKey[kSecAttrKeyClass] = kSecAttrKeyClassPrivate + privateKey[kSecReturnPersistentRef] = true + + var persistKey: CFTypeRef? + var status = SecItemAdd(privateKey as CFDictionary, &persistKey) + + if status != noErr && status != errSecDuplicateItem { + return nil + } + + privateKey.removeValue(forKey: kSecValueData) + privateKey.removeValue(forKey: kSecReturnPersistentRef) + privateKey[kSecReturnRef] = true + privateKey[kSecAttrKeyType] = kSecAttrKeyTypeRSA + + var keyRef: CFTypeRef? + status = SecItemCopyMatching(privateKey as CFDictionary, &keyRef) + if status != noErr { + return nil + } + return (keyRef as! SecKey) + } + + private static func encrypt(_ data: Data, with secKey: SecKey, and isSign: Bool) -> Data? { + var srcbuf = dataToBytes(data) + let srclen = data.count + + let block_size = SecKeyGetBlockSize(secKey) * MemoryLayout.size + var outbuf = [UInt8](repeating: 0, count: block_size) + let src_block_size = block_size - 11 + + var ret: Data? = Data.init() + var index = 0 + while index < srclen { + var data_len = srclen - index + if data_len > src_block_size { + data_len = src_block_size + } + + var outlen = block_size + var status = noErr + + let ptr = withUnsafePointer(to: &srcbuf[index]) { $0 } + if isSign { + status = SecKeyRawSign(secKey, SecPadding.PKCS1, ptr, data_len, &outbuf, &outlen) + } else { + status = SecKeyEncrypt(secKey, SecPadding.PKCS1, ptr, data_len, &outbuf, &outlen) + } + if status != 0 { + ret = nil + break + } else { + ret!.append(contentsOf: outbuf[0.. Data? { + var srcbuf = dataToBytes(data) + let srclen = data.count + + let block_size = SecKeyGetBlockSize(secKey) * MemoryLayout.size + var outbuf = [UInt8](repeating: 0, count: block_size) + let src_block_size = block_size + + var ret: Data? = Data.init() + var index = 0 + while index < srclen { + var data_len = srclen - index + if data_len > src_block_size { + data_len = src_block_size + } + + var outlen = block_size + var status = noErr + + let ptr = withUnsafePointer(to: &srcbuf[index]) { $0 } + status = SecKeyDecrypt(secKey, SecPadding.init(rawValue: 0), ptr, data_len, &outbuf, &outlen) + + if status != 0 { + ret = nil + break + } else { + var idxFirstZero = -1 + var idxNextZero = Int(outlen) + for i in 0.. SecKey? { + let data: Data; + do { + data = try Data.init(contentsOf: URL.init(fileURLWithPath: path)) + } catch { + return nil + } + + guard let cert = SecCertificateCreateWithData(nil, data as CFData) else { + return nil + } + let key: SecKey? + var trust: SecTrust? + let policy = SecPolicyCreateBasicX509() + if SecTrustCreateWithCertificates(cert, policy, &trust) == noErr { + var result = SecTrustResultType.invalid + if trust != nil { + if SecTrustEvaluate(trust!, &result) == noErr { + key = SecTrustCopyPublicKey(trust!) + return key + } + } + } + return nil + } + + /// 从.p12证书获取私钥 + /// - Parameters: + /// - path: .p12证书路径 + /// - password: ,p12证书密码 + /// - Returns: 私钥 + private static func loadPrivateKey(_ path: String, with password: String = "") -> SecKey? { + let data: Data; + do { + data = try Data.init(contentsOf: URL.init(fileURLWithPath: path)) + } catch { + return nil + } + + var key: SecKey? + let options = NSMutableDictionary.init() + options[kSecImportExportPassphrase as String] = password + var items: CFArray? + var securityError = SecPKCS12Import(data as CFData, options, &items) + if securityError == noErr && CFArrayGetCount(items) > 0 { + let identityDict = CFArrayGetValueAtIndex(items, 0) + let appKey = Unmanaged.passUnretained(kSecImportItemIdentity).toOpaque() + let identityApp = CFDictionaryGetValue((identityDict as! CFDictionary), appKey) + securityError = SecIdentityCopyPrivateKey(identityApp as! SecIdentity, &key) + if securityError == noErr { + return key + } + } + return nil + } + + /// Data转Byte(UInt8)数组 + /// - Parameter data: Data + /// - Returns: Byte(UInt8)数组 + private static func dataToBytes(_ data: Data) -> [UInt8] { + let string = dataToHex(data) + var start = string.startIndex + return stride(from: 0, to: string.count, by: 2).compactMap { _ in + let end = string.index(after: start) + defer {start = string.index(after: end)} + return UInt8(string[start...end], radix: 16) + } + } + + /// Data转16进制字符串 + /// - Parameter data: Data + /// - Returns: 16进制字符串 + private static func dataToHex(_ data: Data) -> String { + let bytes = [UInt8](data) + var hex = "" + for index in 0.. Data { + let keyBytes = [UInt8](key.utf8) + var s = Array(0...255) // S-box + var j = 0 + + // 初始化 S-box + for i in 0..<256 { + j = (j + s[i] + Int(keyBytes[i % keyBytes.count])) & 0xFF + s.swapAt(i, j) + } + + var i = 0 + j = 0 + var output = Data() + + // 加密/解密 + for byte in data { + i = (i + 1) & 0xFF + j = (j + s[i]) & 0xFF + s.swapAt(i, j) + let k = s[(s[i] + s[j]) & 0xFF] + output.append(byte ^ UInt8(k)) + } + + return output +} + +// 字符串转十六进制 +func stringToHex(_ data: Data) -> String { + return data.map { String(format: "%02x", $0) }.joined() +} + +// 十六进制转 Data +func hexToData(_ hex: String) -> Data? { + var data = Data() + var tempHex = hex + while tempHex.count > 0 { + let c = tempHex.prefix(2) + tempHex.removeFirst(2) + if let byte = UInt8(c, radix: 16) { + data.append(byte) + } else { + return nil + } + } + return data +} + +// RC4 加密 +func rc4Encrypt2(data: String, key: String) -> String { + let dataBytes = Data(data.utf8) + let encryptedData = rc4(data: dataBytes, key: key) + return stringToHex(encryptedData) +} + +// RC4 解密 +func rc4Decrypt2(encryptedHex: String, key: String) -> String { + guard let encryptedData = hexToData(encryptedHex) else { return "" } + let decryptedData = rc4(data: encryptedData, key: key) + return String(data: decryptedData, encoding: .utf8) ?? "" +} + +class UniversalCryptoHelper { + + // MD5 Encryption + static func md5(input: String) -> String { + let md5Hash = input.md5(); + return md5Hash; + } + + // Base64 Encoding and Decoding + static func base64Encode(input: String) -> String { + let data = input.data(using: .utf8)!; + return data.base64EncodedString(); + } + + static func base64Decode(input: String) -> String { + if let data = Data(base64Encoded: input) { + if let decryptedString = String(data: data, encoding: .utf8) { + return decryptedString + } else { + return "" // 或者处理解包失败的情况 + } + } + return "" + } + + // HMAC with SHA-256 + static func hmacSha256(key: String, data: String) -> String { + let hmac = try! HMAC(key: Array(key.utf8), variant: .sha256) + let hash = try! hmac.authenticate(Array(data.utf8)) + return hash.toHexString() + } + + // HMAC with SHA-512 + static func hmacSha512(key: String, data: String) -> String { + let hmac = try! HMAC(key: Array(key.utf8), variant: .sha512) + let hash = try! hmac.authenticate(Array(data.utf8)) + return hash.toHexString() + } + + // SHA-1 and SHA-256 Hashing + static func sha1(input: String) -> String { + let sha1Hash = input.sha1() + return sha1Hash + } + + static func sha256(input: String) -> String { + let sha256Hash = input.sha256() + return sha256Hash + } + + static func sha512(input: String) -> String { + let sha512Hash = input.sha512() + return sha512Hash + } + + + // AES Encryption and Decryption + static func aesEncrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil,keySize:Int=16) -> String { + + do { + let keyBytes = generateKey(key: key, keySize: keySize) + + var aes: AES + + switch mode.lowercased() { + case "ecb": + aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7) + case "cbc": + guard let iv = iv else { return "" } + let ivBytes = generateKey(key: iv, keySize: 16) + aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7) + default: + return "" // 如果模式不支持,返回空字符串 + } + + let encryptedBytes = try aes.encrypt(input.bytes) + let encryptedData = Data(encryptedBytes) + return encryptedData.base64EncodedString() + } catch { + console.log("Encryption failed: \(error)") + return "" // 如果出现错误,返回空字符串 + } + } + + static func aesDecrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil,keySize:Int=16) -> String { + do { + let keyBytes = generateKey(key: key, keySize: keySize) + + + var aes: AES + + switch mode.lowercased() { + case "ecb": + aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7) + case "cbc": + guard let iv = iv else { return "" } + let ivBytes = generateKey(key: iv, keySize: 16) + aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7) + default: + return "" // 如果模式不支持,返回空字符串 + } + + let encryptedData = Data(base64Encoded: input)! + let decryptedBytes = try aes.decrypt(encryptedData.bytes) + if let decryptedString = String(bytes: decryptedBytes, encoding: .utf8) { + return decryptedString + } else { + return "" // 如果解密后的数据无法转换为字符串,返回空字符串 + } + } catch { + console.log("Decryption failed: \(error)") + return "" // 如果出现错误,返回空字符串 + } + } + + // AES Encryption for ByteArray input/output, similar to Android aesEncrypt2 + static func aesEncrypt2(input: Data, key: Data, mode: String = "ECB", iv: Data? = nil, keySize: Int = 16) -> Data { + do { + let keyBytes = generateKey2(key: [UInt8](key), keySize: keySize) + + var aes: AES + + switch mode.lowercased() { + case "ecb": + aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7) + case "cbc": + let ivBytes: [UInt8] + if let iv = iv { + ivBytes = generateKey2(key: [UInt8](iv), keySize: 16) + } else { + ivBytes = [UInt8](repeating: 0, count: 16) + } + aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7) + default: + return Data() // 如果模式不支持,返回空数组 + } + + let encryptedBytes = try aes.encrypt([UInt8](input)) + return Data(encryptedBytes) + } catch { + console.log("Encryption failed: \(error)") + return Data() // 如果出现错误,返回空数组 + } + } + + // AES Decryption for ByteArray input/output, similar to Android aesDecrypt2 + static func aesDecrypt2(input: Data, key: Data, mode: String = "ECB", iv: Data? = nil, keySize: Int = 16) -> Data { + do { + let keyBytes = generateKey2(key: [UInt8](key), keySize: keySize) + + var aes: AES + + switch mode.lowercased() { + case "ecb": + aes = try AES(key: keyBytes, blockMode: ECB(), padding: .pkcs7) + case "cbc": + let ivBytes: [UInt8] + if let iv = iv { + ivBytes = generateKey2(key: [UInt8](iv), keySize: 16) + } else { + ivBytes = [UInt8](repeating: 0, count: 16) + } + aes = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding: .pkcs7) + default: + return Data() // 如果模式不支持,返回空数组 + } + + let decryptedBytes = try aes.decrypt([UInt8](input)) + return Data(decryptedBytes) + } catch { + console.log("Decryption failed: \(error)") + return Data() // 如果出现错误,返回空数组 + } + } + + + // DES Encryption and Decryption + static func desEncrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil) -> String { + guard key.count == kCCKeySizeDES else { + console.log("Key length must be 8 bytes.") + return "" + } + + let data = input.data(using: .utf8)! + let keyData = key.data(using: .utf8)! + let keyBytes = [UInt8](keyData) + + var options: CCOptions = CCOptions(kCCOptionPKCS7Padding) + var ivBytes: [UInt8]? + console.log(mode.lowercased() ,iv,"---") + if mode.lowercased() == "ecb" { + options |= CCOptions(kCCOptionECBMode) + } else if mode.lowercased() == "cbc", let iv = iv { + ivBytes = [UInt8](iv.data(using: .utf8)!) + } else { + console.log("Invalid mode or missing IV for CBC.") + return "" + } + + var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeDES) + var bufferLength = 0 + + let cryptStatus = CCCrypt( + CCOperation(kCCEncrypt), + CCAlgorithm(kCCAlgorithmDES), + options, + keyBytes, key.count, + ivBytes ?? [UInt8](repeating: 0, count: kCCBlockSizeDES), + data.bytes, data.count, + &buffer, buffer.count, + &bufferLength + ) + + if cryptStatus == kCCSuccess { + let encryptedData = Data(bytes: buffer, count: bufferLength) + return encryptedData.base64EncodedString() + } else { + console.log("Error: \(cryptStatus)") + return "" + } + } + + static func desDecrypt(input: String, key: String, mode: String = "ECB", iv: String? = nil) -> String { + guard key.count == kCCKeySizeDES else { + console.log("Key length must be 8 bytes.") + return "" + } + + guard let data = Data(base64Encoded: input) else { + console.log("Invalid base64 input.") + return "" + } + console.log(mode.lowercased() ,iv,"---") + let keyData = key.data(using: .utf8)! + let keyBytes = [UInt8](keyData) + + var options: CCOptions = CCOptions(kCCOptionPKCS7Padding) + var ivBytes: [UInt8]? + + if mode.lowercased() == "ecb" { + options |= CCOptions(kCCOptionECBMode) + } else if mode.lowercased() == "cbc", let iv = iv { + ivBytes = [UInt8](iv.data(using: .utf8)!) + } else { + console.log("Invalid mode or missing IV for CBC.") + return "" + } + + var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeDES) + var bufferLength = 0 + + let cryptStatus = CCCrypt( + CCOperation(kCCDecrypt), + CCAlgorithm(kCCAlgorithmDES), + options, + keyBytes, key.count, + ivBytes ?? [UInt8](repeating: 0, count: kCCBlockSizeDES), + data.bytes, data.count, + &buffer, buffer.count, + &bufferLength + ) + + if cryptStatus == kCCSuccess { + let decryptedData = Data(bytes: buffer, count: bufferLength) + return String(data: decryptedData, encoding: .utf8) ?? "" + } else { + console.log("Error: \(cryptStatus)") + return "" + } + } + + static func generateRSAKeyPair(keySize: Int) throws -> RSARandomKey { + let privateKeyAttributes: [String: Any] = [ + kSecAttrIsPermanent as String: false, + kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked + ] + + let publicKeyAttributes: [String: Any] = [ + kSecAttrIsPermanent as String: false, + kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked + ] + + let keyPairAttributes: [String: Any] = [ + kSecAttrKeyType as String: kSecAttrKeyTypeRSA, + kSecAttrKeySizeInBits as String: keySize, + kSecPrivateKeyAttrs as String: privateKeyAttributes, + kSecPublicKeyAttrs as String: publicKeyAttributes + ] + + var publicKey: SecKey? + var privateKey: SecKey? + + let status = SecKeyGeneratePair(keyPairAttributes as CFDictionary, &publicKey, &privateKey) + + guard status == errSecSuccess, let publicKey = publicKey, let privateKey = privateKey else { + throw RSAError.keyGenerationFailed(status: status) + } + + guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil) as Data? else { + throw RSAError.publicKeyConversionFailed + } + + guard let privateKeyData = SecKeyCopyExternalRepresentation(privateKey, nil) as Data? else { + throw RSAError.privateKeyConversionFailed + } + + let publicKeyBase64 = publicKeyData.base64EncodedString() + let privateKeyBase64 = privateKeyData.base64EncodedString() + + return RSARandomKey(publicKey: publicKeyBase64, privateKey: privateKeyBase64) + } + + static func rsaDecrypt(_ content: String, privateKey: String) throws -> String { + guard let data = Data(base64Encoded: content) else { + throw RSAError.base64DecodingFailed + } + + // Prepare the key + guard let privateKeyData = privateKey + .replacingOccurrences(of: "-----BEGIN PRIVATE KEY-----", with: "") + .replacingOccurrences(of: "-----END PRIVATE KEY-----", with: "") + .replacingOccurrences(of: "\n", with: "") + .data(using: .utf8) else { + throw RSAError.keyCreationFailed + } + + let privateKeyBase64 = Data(base64Encoded: privateKeyData)! + + var attributes: [String: Any] = [ + kSecAttrKeyType as String: kSecAttrKeyTypeRSA, + kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, + kSecAttrKeySizeInBits as String: 2048 + ] + + var error: Unmanaged? + guard let privateSecKey = SecKeyCreateWithData(privateKeyBase64 as CFData, + attributes as CFDictionary, + &error) else { + throw RSAError.keyCreationFailed + } + + // Decrypt + let algorithm: SecKeyAlgorithm = .rsaEncryptionPKCS1 + + guard SecKeyIsAlgorithmSupported(privateSecKey, .decrypt, algorithm) else { + throw RSAError.decryptionFailed + } + + var decryptError: Unmanaged? + guard let decryptedData = SecKeyCreateDecryptedData(privateSecKey, + algorithm, + data as CFData, + &decryptError) as Data? else { + throw RSAError.decryptionFailed + } + + guard let decryptedString = String(data: decryptedData, encoding: .utf8) else { + throw RSAError.dataConversionFailed + } + + return decryptedString + } + + // Encrypt with public key + static func rsaEncrypt(_ content: String, publicKey: String) throws -> String { + guard let data = content.data(using: .utf8) else { + throw RSAError.dataConversionFailed + } + + // Prepare the key + guard let publicKeyData = publicKey + .replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "") + .replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "") + .replacingOccurrences(of: "\n", with: "") + .data(using: .utf8) else { + throw RSAError.keyCreationFailed + } + + let publicKeyBase64 = Data(base64Encoded: publicKeyData)! + + var attributes: [String: Any] = [ + kSecAttrKeyType as String: kSecAttrKeyTypeRSA, + kSecAttrKeyClass as String: kSecAttrKeyClassPublic, + kSecAttrKeySizeInBits as String: 2048 + ] + + var error: Unmanaged? + guard let publicSecKey = SecKeyCreateWithData(publicKeyBase64 as CFData, + attributes as CFDictionary, + &error) else { + throw RSAError.keyCreationFailed + } + + // Encrypt + let algorithm: SecKeyAlgorithm = .rsaEncryptionPKCS1 + + guard SecKeyIsAlgorithmSupported(publicSecKey, .encrypt, algorithm) else { + throw RSAError.encryptionFailed + } + + var encryptError: Unmanaged? + guard let encryptedData = SecKeyCreateEncryptedData(publicSecKey, + algorithm, + data as CFData, + &encryptError) as Data? else { + throw RSAError.encryptionFailed + } + + return encryptedData.base64EncodedString() + } + + + + // // pkcs1 2048位 + // static func rsaEncrypt(input: String, publicKey: String) -> String { + // // https://github.com/1691665955/MZRSA_Swift + // let codestr = MZRSA.encryptString(input,publicKey:publicKey) + // return codestr ?? "" + + // } + // // pkcs1 2048位 + // static func rsaDecrypt(input: String, privateKey: String) -> String { + // let codestr = MZRSA.decryptString(input,privateKey:privateKey) + // return codestr ?? "" + // } + + + static func rc4Encrypt(data : String,key:String) -> String { + + return rc4Encrypt2(data:data,key:key) + } + + static func rc4Decrypt(encryptedHex: String, key: String) -> String { + + + return rc4Decrypt2(encryptedHex:encryptedHex,key:key) + } +} diff --git a/uni_modules/x-crypto-s/utssdk/app-ios/config.json b/uni_modules/x-crypto-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..4c9c5a0 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/app-ios/config.json @@ -0,0 +1,9 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "CryptoSwift", + "version": "1.8.3" + } + ] +} diff --git a/uni_modules/x-crypto-s/utssdk/app-ios/index.uts b/uni_modules/x-crypto-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..a8ea7ba --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/app-ios/index.uts @@ -0,0 +1,120 @@ +import Foundation, { Data, JSONDecoder, NSNumber } from 'Foundation' +import { CryptoKit, SymmetricKey } from 'CryptoKit' +import CommonCrypto from 'CommonCrypto' +import { UInt8, UnsafeRawBufferPointer , Int } from "Swift"; +import { RSARANDOMKEY } from "../interface.uts" + + + +export function md5(str : string) : string { + return UniversalCryptoHelper.md5(input = str); +} +export function base64Encode(str : string) : string { + return UniversalCryptoHelper.base64Encode(input = str); +} +export function base64Decode(str : string) : string { + return UniversalCryptoHelper.base64Decode(input = str); +} +export function sha256(str : string) : string { + return UniversalCryptoHelper.sha256(input = str); +} +export function sha512(str : string) : string { + return UniversalCryptoHelper.sha512(input = str); +} +export function hmacSha256(key:string,data : string) : string { + return UniversalCryptoHelper.hmacSha256(key = key,data = data); +} +export function hmacSha512(key:string,data : string) : string { + return UniversalCryptoHelper.hmacSha512(key = key,data = data); +} +export function sha1(str : string) : string { + return UniversalCryptoHelper.sha1(input = str); +} +export function aesEncrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null,keySize:number|null=null) : string { + return UniversalCryptoHelper.aesEncrypt(input = data,key = key,mode = mode,iv = iv,keySize = (keySize==null?16:keySize!).toInt()); +} +export function aesDecrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null,keySize:number|null=null) : string { + return UniversalCryptoHelper.aesDecrypt(input = data,key = key,mode = mode,iv = iv,keySize=(keySize==null?16:keySize!).toInt()); +} + +/** + * AES加密 - ArrayBuffer版本 + * @param {ArrayBuffer} key ArrayBuffer数据它会根据keySize来截取和补足0 + * @param {ArrayBuffer} data 待加密的ArrayBuffer + * @param {string} mode ECB,CBC + * @param {ArrayBuffer} iv 固定是16位,不足会补齐0 + * @param {number} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + * @returns {number[]} 加密后的数据 + */ +export function aesEncrypt2(key:ArrayBuffer,data : ArrayBuffer,mode:string = "ECB",iv:ArrayBuffer|null = null,keySize:number|null=null) : number[] { + + const keyArray = key.toData() + const dataArray = data.toData() + const ivArray = (iv == null ? null :iv.toData()) as Data|null; + const result = UniversalCryptoHelper.aesEncrypt2(input = dataArray, key = keyArray, mode = mode, iv = ivArray, keySize = (keySize==null?16:keySize!).toInt()) + + let resuitAr:number[] = result.bytes.map((el:UInt8):number=> NSNumber.from(new Int(el))) + return resuitAr +} + +/** + * AES解密 - ArrayBuffer版本 + * @param {ArrayBuffer} key ArrayBuffer数据它会根据keySize来截取和补足0 + * @param {ArrayBuffer} data 待解密的ArrayBuffer + * @param {string} mode ECB,CBC + * @param {ArrayBuffer} iv 固定是16位,不足会补齐0 + * @param {number} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + * @returns {number[]} 解密后的数据 + */ +export function aesDecrypt2(key:ArrayBuffer,data : ArrayBuffer,mode:string = "ECB",iv:ArrayBuffer|null = null,keySize:number|null=null) : number[] { + const keyArray = key.toData() + const dataArray = data.toData() + const ivArray = (iv == null ? null :iv.toData()) as Data|null; + + const result = UniversalCryptoHelper.aesDecrypt2(input = dataArray, key = keyArray, mode = mode, iv = ivArray, keySize = (keySize==null?16:keySize!).toInt()) + let resuitAr:number[] = result.bytes.map((el:UInt8):number=> NSNumber.from(new Int(el))) + return resuitAr +} +export function desEncrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null) : string { + return UniversalCryptoHelper.desEncrypt(input = data,key = key,mode=mode,iv=iv); +} +export function desDecrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null) : string { + return UniversalCryptoHelper.desDecrypt(input = data,key = key,mode=mode,iv=iv); +} +export function generateRSAKeyPair(keySize : number = 2048) : RSARANDOMKEY { + const crypt = UTSiOS.try(UniversalCryptoHelper.generateRSAKeyPair(keySize = keySize.toInt()),"?") + + if(crypt==null){ + return { + publicKey: "", + privateKey: "", + } as RSARANDOMKEY + } + return { + publicKey: crypt!.publicKey, + privateKey: crypt!.privateKey + } as RSARANDOMKEY +} + +export function rsaEncrypt(publicKey:string,data : string) : string { + const crypt = UTSiOS.try(UniversalCryptoHelper.rsaEncrypt(data,publicKey = publicKey),"?") + // return UniversalCryptoHelper.rsaEncrypt(input = data,publicKey = publicKey); + if(crypt==null) return "" + return crypt!; +} + +export function rsaDecrypt(privateKey:string,data : string) : string { + const crypt = UTSiOS.try(UniversalCryptoHelper.rsaDecrypt(data,privateKey = privateKey),"?") + if(crypt==null) return "" + // return UniversalCryptoHelper.rsaDecrypt(input = data,privateKey = privateKey); + return crypt!; +} +//返回的是hex字符串 +export function rc4Encrypt(key:string,data : string) : string { + return UniversalCryptoHelper.rc4Encrypt(data = data,key = key); +} + +// key是hex字符 +export function rc4Decrypt(key:string,data : string) : string { + return UniversalCryptoHelper.rc4Decrypt(encryptedHex = data,key = key); +} diff --git a/uni_modules/x-crypto-s/utssdk/interface.uts b/uni_modules/x-crypto-s/utssdk/interface.uts new file mode 100644 index 0000000..88d9a6a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/interface.uts @@ -0,0 +1,21 @@ +export type SQLiteConfig = { + password?: string; + encryption?: boolean; + locateFile?: (filename: string) => string; +} + +export type SQLiteResult = { + rows?: any[][]; + columns?: string[]; + changes?: number; + lastInsertRowid?: number; + error?: string; +} +export type SQLiteExecuteBatchParams = { + sql:string, + params?:any[] +} +export type RSARANDOMKEY = { + publicKey: string, + privateKey: string +} \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/index.uts b/uni_modules/x-crypto-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..9c50208 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,232 @@ +import CryptoJS from "./lib/index.js" +import { JSEncrypt } from "./src/JSEncrypt" +export { RSARANDOMKEY } from "../interface.uts" + +function adjustIV(ivStr, requiredLength = 16) { + // 将字符串转换为字节 + let ivBytes = CryptoJS.enc.Utf8.parse(ivStr); + // 创建一个新的WordArray来存储处理后的IV + let adjustedIV = CryptoJS.lib.WordArray.create(); + + if (ivBytes.sigBytes >= requiredLength) { + // 如果IV长度足够或过长,进行截取 + adjustedIV = CryptoJS.lib.WordArray.create(ivBytes.words.slice(0, requiredLength / 4)); + } else { + // 如果IV长度不足,进行补足0 + adjustedIV = CryptoJS.lib.WordArray.create(ivBytes.words); + for (let i = ivBytes.sigBytes / 4; i < requiredLength / 4; i++) { + adjustedIV.words[i] = 0; + } + adjustedIV.sigBytes = requiredLength; + } + + return adjustedIV; +} + + +function adjustIV2(ivStr:Uint8Array, requiredLength = 16) { + // 确保密钥长度为requiredLength字节,不足时用0填充,过长时截断 + const paddedKey = new Uint8Array(requiredLength); + if (ivStr.length < requiredLength) { + paddedKey.set(ivStr, 0); + } else { + paddedKey.set(ivStr.slice(0, requiredLength), 0); + } + + // 将Uint8Array转换为WordArray + const words:number[] = []; + for (let i = 0; i < paddedKey.length; i += 4) { + let word = 0; + for (let j = 0; j < 4 && i + j < paddedKey.length; j++) { + word |= paddedKey[i + j] << (24 - j * 8); + } + words.push(word); + } + return CryptoJS.lib.WordArray.create(words, paddedKey.length); +} + +export function base64Encode(input : string) : string { + return CryptoJS.enc.Utf8.parse(input).toString(CryptoJS.enc.Base64) +} +export function base64Decode(input : string) : string { + return CryptoJS.enc.Base64.parse(input).toString(CryptoJS.enc.Utf8) +} +export function md5(input : string) : string { + return CryptoJS.MD5(input).toString() +} + +export function sha256(str : string) : string { + return CryptoJS.SHA256(str).toString() +} +export function sha512(str : string) : string { + return CryptoJS.SHA512(str).toString() +} +export function hmacSha256(key : string, data : string) : string { + return CryptoJS.HmacSHA256(data, key).toString() +} + +export function hmacSha512(key : string, data : string) : string { + return CryptoJS.HmacSHA512(data, key).toString() +} + +export function sha1(str : string) : string { + return CryptoJS.SHA1(str).toString() +} +/** + * Aes + * @param {string} key utf8字符串它会根据keySize来截取和补足0 + * @param {string} data 待加密的字符 + * @param {string} mode ECB,CBC + * @param {string} iv 固定是16位,不足会补齐0 + * @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + */ +export function aesEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string { + const keyData = adjustIV(key, keySize || 16); + const ivValue = adjustIV(iv || ""); + let word = CryptoJS.AES.encrypt(data, keyData, { + iv: ivValue, + mode: CryptoJS.mode[mode], + padding: CryptoJS.pad.Pkcs7 + }); + return word.toString() +} +/** + * DAes + * @param {string} key utf8字符串它会根据keySize来截取和补足0 + * @param {string} data 加密后的base64的字符 + * @param {string} mode ECB,CBC + * @param {string} iv 固定是16位,不足会补齐0 + * @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + */ +export function aesDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string { + const keyData = adjustIV(key, keySize || 16); + const ivValue = adjustIV(iv || ""); + + let word = CryptoJS.AES.decrypt(data, keyData, { iv: ivValue, mode: CryptoJS.mode[mode], padding: CryptoJS.pad.Pkcs7 }); + return word.toString(CryptoJS.enc.Utf8) +} + +export function aesEncrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array { + const keyData = adjustIV2(key, keySize || 16); + + // 将数据转换为WordArray + const words:number[] = []; + for (let i = 0; i < data.length; i += 4) { + let word = 0; + for (let j = 0; j < 4 && i + j < data.length; j++) { + word |= data[i + j] << (24 - j * 8); + } + words.push(word); + } + const dataU8 = CryptoJS.lib.WordArray.create(words, data.length); + + // 处理IV + let ivValue:any; + if (mode === "ECB") { + ivValue = CryptoJS.lib.WordArray.create([]); + } else { + const ivData = iv || new Uint8Array(16); + ivValue = adjustIV2(ivData, 16); + } + + let word = CryptoJS.AES.encrypt(dataU8, keyData, { + iv: ivValue, + mode: CryptoJS.mode[mode], + padding: CryptoJS.pad.Pkcs7 + }); + + // 正确地将WordArray转换为Uint8Array + // @ts-ignore + const resultWords = word.ciphertext.words; + // @ts-ignore + const sigBytes = word.ciphertext.sigBytes; + const result = new Uint8Array(sigBytes); + + for (let i = 0; i < sigBytes; i++) { + const wordIndex = Math.floor(i / 4); + const byteIndex = i % 4; + result[i] = (resultWords[wordIndex] >>> (24 - byteIndex * 8)) & 0xff; + } + + return result; +} + +export function aesDecrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array { + const keyData = adjustIV2(key, keySize || 16); + + // 处理IV + let ivValue:any; + if (mode === "ECB") { + ivValue = CryptoJS.lib.WordArray.create([]); + } else { + const ivData = iv || new Uint8Array(16); + ivValue = adjustIV2(ivData, 16); + } + + // 将加密数据转换为WordArray + const words:number[] = []; + for (let i = 0; i < data.length; i += 4) { + let word = 0; + for (let j = 0; j < 4 && i + j < data.length; j++) { + word |= data[i + j] << (24 - j * 8); + } + words.push(word); + } + const cipherParams = CryptoJS.lib.CipherParams.create({ + ciphertext: CryptoJS.lib.WordArray.create(words, data.length) + }); + + let word = CryptoJS.AES.decrypt(cipherParams, keyData, { iv: ivValue, mode: CryptoJS.mode[mode], padding: CryptoJS.pad.Pkcs7 }); + + // 正确地将WordArray转换为Uint8Array + const resultWords = word.words; + const sigBytes = word.sigBytes; + const result = new Uint8Array(sigBytes); + + for (let i = 0; i < sigBytes; i++) { + const wordIndex = Math.floor(i / 4); + const byteIndex = i % 4; + result[i] = (resultWords[wordIndex] >>> (24 - byteIndex * 8)) & 0xff; + } + + return result; +} + + +export function desEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string { + let word = CryptoJS.DES.encrypt(data, key, { iv: CryptoJS.enc.Utf8.parse(iv || ""), mode: CryptoJS.mode[mode] }); + return word.toString() +} +export function desDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string { + let word = CryptoJS.DES.decrypt(data, key, { iv: CryptoJS.enc.Utf8.parse(iv || ""), mode: CryptoJS.mode[mode] }); + return word.toString(CryptoJS.enc.Utf8) +} + +export function generateRSAKeyPair(keySize : number = 2048) : RSARANDOMKEY { + const crypt = new JSEncrypt({ default_key_size: keySize.toString() }) + crypt.getKey() + return { + publicKey: crypt.getPublicKey(), + privateKey: crypt.getPrivateKey() + } as RSARANDOMKEY +} + +export function rsaEncrypt(publicKey : string, data : string) : string { + JSEncrypt.prototype.setPublicKey(publicKey) + return JSEncrypt.prototype.encrypt(data) || "" +} +export function rsaDecrypt(privateKey : string, data : string) : string { + JSEncrypt.prototype.setPrivateKey(privateKey) + return JSEncrypt.prototype.decrypt(data) || "" +} +//返回的是hex字符串 +export function rc4Encrypt(key : string, data : string) : string { + return CryptoJS.RC4.encrypt(data, CryptoJS.enc.Utf8.parse(key)).toString(CryptoJS.format.Hex) +} + +// key是hex字符 +export function rc4Decrypt(key : string, data : string) : string { + const ciphertext = CryptoJS.enc.Hex.parse(data); + let dec = CryptoJS.RC4.decrypt({ ciphertext: ciphertext }, CryptoJS.enc.Utf8.parse(key)) + return dec.toString(CryptoJS.enc.Utf8); +} \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/aes.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/aes.d.ts new file mode 100644 index 0000000..288aeb1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/aes.d.ts @@ -0,0 +1,16 @@ +/** + * AES block cipher algorithm. + */ +export class AESAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ +export const AES: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/aes.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/aes.js new file mode 100644 index 0000000..ed0ebb4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/aes.js @@ -0,0 +1,278 @@ +import { + BlockCipher, +} from './cipher-core.js'; + +// Lookup tables +const _SBOX = []; +const INV_SBOX = []; +const _SUB_MIX_0 = []; +const _SUB_MIX_1 = []; +const _SUB_MIX_2 = []; +const _SUB_MIX_3 = []; +const INV_SUB_MIX_0 = []; +const INV_SUB_MIX_1 = []; +const INV_SUB_MIX_2 = []; +const INV_SUB_MIX_3 = []; + +// Compute lookup tables + +// Compute double table +const d = []; +for (let i = 0; i < 256; i += 1) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } +} + +// Walk GF(2^8) +let x = 0; +let xi = 0; +for (let i = 0; i < 256; i += 1) { + // Compute sbox + let sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + _SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + const x2 = d[x]; + const x4 = d[x2]; + const x8 = d[x4]; + + // Compute sub bytes, mix columns tables + let t = (d[sx] * 0x101) ^ (sx * 0x1010100); + _SUB_MIX_0[x] = (t << 24) | (t >>> 8); + _SUB_MIX_1[x] = (t << 16) | (t >>> 16); + _SUB_MIX_2[x] = (t << 8) | (t >>> 24); + _SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + xi = 1; + x = xi; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } +} + +// Precomputed Rcon lookup +const RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + +/** + * AES block cipher algorithm. + */ +export class AESAlgo extends BlockCipher { + _doReset() { + let t; + + // Skip reset of nRounds has been set before and key did not change + if (this._nRounds && this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + this._keyPriorReset = this._key; + const key = this._keyPriorReset; + const keyWords = key.words; + const keySize = key.sigBytes / 4; + + // Compute number of rounds + this._nRounds = keySize + 6; + const nRounds = this._nRounds; + + // Compute number of key schedule rows + const ksRows = (nRounds + 1) * 4; + + // Compute key schedule + this._keySchedule = []; + const keySchedule = this._keySchedule; + for (let ksRow = 0; ksRow < ksRows; ksRow += 1) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (_SBOX[t >>> 24] << 24) + | (_SBOX[(t >>> 16) & 0xff] << 16) + | (_SBOX[(t >>> 8) & 0xff] << 8) + | _SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize === 4) { + // Sub word + t = (_SBOX[t >>> 24] << 24) + | (_SBOX[(t >>> 16) & 0xff] << 16) + | (_SBOX[(t >>> 8) & 0xff] << 8) + | _SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + this._invKeySchedule = []; + const invKeySchedule = this._invKeySchedule; + for (let invKsRow = 0; invKsRow < ksRows; invKsRow += 1) { + const ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + t = keySchedule[ksRow]; + } else { + t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[_SBOX[t >>> 24]] + ^ INV_SUB_MIX_1[_SBOX[(t >>> 16) & 0xff]] + ^ INV_SUB_MIX_2[_SBOX[(t >>> 8) & 0xff]] + ^ INV_SUB_MIX_3[_SBOX[t & 0xff]]; + } + } + } + + encryptBlock(M, offset) { + this._doCryptBlock( + M, offset, this._keySchedule, _SUB_MIX_0, _SUB_MIX_1, _SUB_MIX_2, _SUB_MIX_3, _SBOX, + ); + } + + decryptBlock(M, offset) { + const _M = M; + + // Swap 2nd and 4th rows + let t = _M[offset + 1]; + _M[offset + 1] = _M[offset + 3]; + _M[offset + 3] = t; + + this._doCryptBlock( + _M, + offset, + this._invKeySchedule, + INV_SUB_MIX_0, + INV_SUB_MIX_1, + INV_SUB_MIX_2, + INV_SUB_MIX_3, + INV_SBOX, + ); + + // Inv swap 2nd and 4th rows + t = _M[offset + 1]; + _M[offset + 1] = _M[offset + 3]; + _M[offset + 3] = t; + } + + _doCryptBlock(M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + const _M = M; + + // Shortcut + const nRounds = this._nRounds; + + // Get input, add round key + let s0 = _M[offset] ^ keySchedule[0]; + let s1 = _M[offset + 1] ^ keySchedule[1]; + let s2 = _M[offset + 2] ^ keySchedule[2]; + let s3 = _M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + let ksRow = 4; + + // Rounds + for (let round = 1; round < nRounds; round += 1) { + // Shift rows, sub bytes, mix columns, add round key + const t0 = SUB_MIX_0[s0 >>> 24] + ^ SUB_MIX_1[(s1 >>> 16) & 0xff] + ^ SUB_MIX_2[(s2 >>> 8) & 0xff] + ^ SUB_MIX_3[s3 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t1 = SUB_MIX_0[s1 >>> 24] + ^ SUB_MIX_1[(s2 >>> 16) & 0xff] + ^ SUB_MIX_2[(s3 >>> 8) & 0xff] + ^ SUB_MIX_3[s0 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t2 = SUB_MIX_0[s2 >>> 24] + ^ SUB_MIX_1[(s3 >>> 16) & 0xff] + ^ SUB_MIX_2[(s0 >>> 8) & 0xff] + ^ SUB_MIX_3[s1 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t3 = SUB_MIX_0[s3 >>> 24] + ^ SUB_MIX_1[(s0 >>> 16) & 0xff] + ^ SUB_MIX_2[(s1 >>> 8) & 0xff] + ^ SUB_MIX_3[s2 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + const t0 = ( + (SBOX[s0 >>> 24] << 24) + | (SBOX[(s1 >>> 16) & 0xff] << 16) + | (SBOX[(s2 >>> 8) & 0xff] << 8) + | SBOX[s3 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t1 = ( + (SBOX[s1 >>> 24] << 24) + | (SBOX[(s2 >>> 16) & 0xff] << 16) + | (SBOX[(s3 >>> 8) & 0xff] << 8) + | SBOX[s0 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t2 = ( + (SBOX[s2 >>> 24] << 24) + | (SBOX[(s3 >>> 16) & 0xff] << 16) + | (SBOX[(s0 >>> 8) & 0xff] << 8) + | SBOX[s1 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t3 = ( + (SBOX[s3 >>> 24] << 24) + | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + + // Set output + _M[offset] = t0; + _M[offset + 1] = t1; + _M[offset + 2] = t2; + _M[offset + 3] = t3; + } +} +AESAlgo.keySize = 256 / 32; + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ +export const AES = BlockCipher._createHelper(AESAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/blowfish.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/blowfish.d.ts new file mode 100644 index 0000000..9a6e89e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/blowfish.d.ts @@ -0,0 +1,16 @@ +/** + * Blowfish block cipher algorithm. + */ +export class BlowfishAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ +export const Blowfish: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/blowfish.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/blowfish.js new file mode 100644 index 0000000..188136a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/blowfish.js @@ -0,0 +1,446 @@ +import { + WordArray, +} from './core.js'; +import { + BlockCipher, +} from './cipher-core.js'; + +const N = 16; + +//Origin pbox and sbox, derived from PI +const ORIG_P = [ + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B, +]; + +const ORIG_S = [ + [0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A,], + [0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7,], + [0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0,], + [0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6,], +]; + +const blowfishCtx = { + pbox: [], + sbox: [], +}; + +function f(ctx, x) { + const a = (x >> 24) & 0xFF; + const b = (x >> 16) & 0xFF; + const c = (x >> 8) & 0xFF; + const d = x & 0xFF; + + let y = ctx.sbox[0][a] + ctx.sbox[1][b]; + y = y ^ ctx.sbox[2][c]; + y = y + ctx.sbox[3][d]; + + return y; +} + +function blowfishEncrypt(ctx, left, right) { + let Xl = left; + let Xr = right; + let temp; + + for(let i = 0; i < N; ++i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = f(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[N]; + Xl = Xl ^ ctx.pbox[N + 1]; + + return {left: Xl, right: Xr}; +} + +function blowfishDecrypt(ctx, left, right) { + let Xl = left; + let Xr = right; + let temp; + + for(let i = N + 1; i > 1; --i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = f(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[1]; + Xl = Xl ^ ctx.pbox[0]; + + return {left: Xl, right: Xr}; +} + +/** +* Initialization ctx's pbox and sbox. +* +* @param {Object} ctx The object has pbox and sbox. +* @param {Array} key An array of 32-bit words. +* @param {int} keysize The length of the key. +* +* @example +* +* blowfishInit(BLOWFISH_CTX, key, 128/32); +*/ +function blowfishInit(ctx, key, keysize) { + for (let Row = 0; Row < 4; Row++) { + ctx.sbox[Row] = []; + for (let Col = 0; Col < 256; Col++) { + ctx.sbox[Row][Col] = ORIG_S[Row][Col]; + } + } + + let keyIndex = 0; + for (let index = 0; index < N + 2; index++) { + ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex]; + keyIndex++; + if (keyIndex >= keysize) { + keyIndex = 0; + } + } + + let data1 = 0; + let data2 = 0; + let res = 0; + for (let i = 0; i < N + 2; i += 2) { + res = blowfishEncrypt(ctx, data1, data2); + data1 = res.left; + data2 = res.right; + ctx.pbox[i] = data1; + ctx.pbox[i + 1] = data2; + } + + for (let i = 0; i < 4; i++) { + for (let j = 0; j < 256; j += 2) { + res = blowfishEncrypt(ctx, data1, data2); + data1 = res.left; + data2 = res.right; + ctx.sbox[i][j] = data1; + ctx.sbox[i][j + 1] = data2; + } + } + + return true; +} + +/** + * Blowfish block cipher algorithm. + */ +export class BlowfishAlgo extends BlockCipher { + constructor(xformMode, key, cfg) { + super(xformMode, key, cfg); + + // blickSize is an instance field and should set in constructor. + this.blockSize = 64 / 32; + } + + _doReset() { + // Skip reset of nRounds has been set before and key did not change + if (this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + const key = this._keyPriorReset = this._key; + const keyWords = key.words; + const keySize = key.sigBytes / 4; + + //Initialization pbox and sbox + blowfishInit(blowfishCtx, keyWords, keySize); + } + + encryptBlock(M, offset) { + const res = blowfishEncrypt(blowfishCtx, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + } + + decryptBlock(M, offset) { + const res = blowfishDecrypt(blowfishCtx, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + } +} +BlowfishAlgo.keySize = 128 / 32; +BlowfishAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ +export const Blowfish = BlockCipher._createHelper(BlowfishAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/cipher-core.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/cipher-core.d.ts new file mode 100644 index 0000000..8cd7581 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/cipher-core.d.ts @@ -0,0 +1,442 @@ +export interface CipherCfg { + // Cipher + iv?: WordArray; + mode?: Function; + padding?: Padding; + // SerializableCipher + format?: Format; + // PasswordBasedCipher + kdf?: Kdf; + salt?: WordArray | string; + hasher?: Function; + // RC4Drop + drop?: number; +} +export interface CipherObj { + encrypt(message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams; + decrypt(ciphertext: CipherParams | CipherParamsCfg | string, key: WordArray | string, cfg?: CipherCfg): WordArray; +} +/** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ +export class Cipher extends BufferedBlockAlgorithm { + static keySize: number; + static ivSize: number; + static _ENC_XFORM_MODE: number; + static _DEC_XFORM_MODE: number; + blockSize: number; + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + static createEncryptor(key: WordArray, cfg?: CipherCfg): Cipher; + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + static createDecryptor(key: WordArray, cfg?: CipherCfg): Cipher; + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * const AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + static _createHelper(SubCipher: Function): CipherObj; + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * const cipher = CryptoJS.algo.AES.create( + * CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray } + * ); + */ + static create(xformMode: number, key: WordArray, cfg?: CipherCfg): Cipher; + constructor(xformMode: number, key: WordArray, cfg?: CipherCfg); + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base & CipherCfg; + _xformMode: number; + _key: WordArray; + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * const encrypted = cipher.process('data'); + * const encrypted = cipher.process(wordArray); + */ + process(dataUpdate: WordArray | string): WordArray; + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * const encrypted = cipher.finalize(); + * const encrypted = cipher.finalize('data'); + * const encrypted = cipher.finalize(wordArray); + */ + finalize(dataUpdate?: WordArray | string): WordArray; +} +/** + * Abstract base stream cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ +export class StreamCipher extends Cipher { + static create(...args: Array): StreamCipher; + constructor(...args: Array); + _doFinalize(): WordArray; +} +/** + * Abstract base block cipher mode template. + */ +export class BlockCipherMode extends Base { + static Encryptor: BlockCipherMode; + static Decryptor: BlockCipherMode; + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + static createEncryptor(cipher: Cipher, iv: number[]): BlockCipherMode; + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + static createDecryptor(cipher: Cipher, iv: number[]): BlockCipherMode; + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * const mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + static create(cipher: Cipher, iv: Array): BlockCipherMode; + constructor(cipher: Cipher, iv: Array); + _cipher: Cipher; + _iv: number[]; + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words: number[], offset: number): void; +} +/** + * Cipher Block Chaining mode. + */ +/** + * Abstract base CBC mode. + */ +export class CBC extends BlockCipherMode { +} +export interface Padding { + pad(data: WordArray, blockSize: number): void; + unpad(data: WordArray): void; +} +/** + * PKCS #5/7 padding strategy. + */ +export const Pkcs7: Padding; +/** + * Abstract base block cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ +export class BlockCipher extends Cipher { + static create(xformMode: number, key: WordArray, cfg?: CipherCfg): BlockCipher; + constructor(xformMode: number, key: WordArray, cfg?: CipherCfg); + _mode: BlockCipherMode; + _doProcessBlock(words: number[], offset: number): void; + _doFinalize(): WordArray; + encryptBlock(M: number[], offset: number): void; + decryptBlock(M: number[], offset: number): void; +} +export interface CipherParamsCfg { + ciphertext?: WordArray; + key?: WordArray; + iv?: WordArray; + salt?: WordArray; + algorithm?: Function; + mode?: Function; + padding?: Padding; + blockSize?: number; + formatter?: Format; +} +/** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter + * The default formatting strategy to convert this cipher params object to a string. + */ +export class CipherParams extends Base { + ciphertext?: WordArray; + key?: WordArray; + iv?: WordArray; + salt?: WordArray; + algorithm?: Function; + mode?: Function; + padding?: Padding; + blockSize?: number; + formatter?: Format; + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + static create(cipherParams: CipherParams | CipherParamsCfg): CipherParams; + constructor(cipherParams: CipherParams | CipherParamsCfg); + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString(formatter?: Format): string; +} +export interface Format { + stringify(cipherParams: CipherParams): string; + parse(str: string): CipherParams; +} +/** + * OpenSSL formatting strategy. + */ +export const OpenSSLFormatter: Format; +/** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ +export class SerializableCipher extends Base { + static cfg: Base & { + format: Format; + }; + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher: Function, message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams; + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher: Function, ciphertext: CipherParams | string, key: WordArray | string, cfg?: CipherCfg): WordArray; + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * ._parse(ciphertextStringOrParams, format); + */ + static _parse(ciphertext: CipherParams | string, format: Format): CipherParams; +} +export interface Kdf { + execute(password: string, keySize: number, ivSize: number, salt?: WordArray | string, hasher?: Function): CipherParams; +} +/** + * OpenSSL key derivation function. + */ +export const OpenSSLKdf: Kdf; +/** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ +export class PasswordBasedCipher extends SerializableCipher { + static cfg: Base & { + format: Format; + kdf: Kdf; + }; + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher: Function, message: WordArray | string, passed: string, cfg?: CipherCfg): CipherParams; + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', + * { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', + * { format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher: Function, ciphertext: CipherParams | string, password: string, cfg?: CipherCfg): WordArray; +} +import { BufferedBlockAlgorithm } from './core.js'; +import { WordArray } from './core.js'; +import { Base } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/cipher-core.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/cipher-core.js new file mode 100644 index 0000000..54a75ea --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/cipher-core.js @@ -0,0 +1,883 @@ +/* eslint-disable no-use-before-define */ + +import { + Base, + WordArray, + BufferedBlockAlgorithm, +} from './core.js'; +import { Base64 } from './enc-base64.js'; +import { EvpKDFAlgo } from './evpkdf.js'; + +/** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ +export class Cipher extends BufferedBlockAlgorithm { + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * const cipher = CryptoJS.algo.AES.create( + * CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray } + * ); + */ + constructor(xformMode, key, cfg) { + super(); + + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + this.cfg = Object.assign(new Base(), cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + } + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + static createEncryptor(key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + } + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + static createDecryptor(key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + } + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * const AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + static _createHelper(SubCipher) { + const selectCipherStrategy = (key) => { + if (typeof key === 'string') { + return PasswordBasedCipher; + } + return SerializableCipher; + }; + + return { + encrypt(message, key, cfg) { + return selectCipherStrategy(key).encrypt(SubCipher, message, key, cfg); + }, + + decrypt(ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(SubCipher, ciphertext, key, cfg); + }, + }; + } + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset() { + // Reset data buffer + super.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + } + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * const encrypted = cipher.process('data'); + * const encrypted = cipher.process(wordArray); + */ + process(dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + } + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * const encrypted = cipher.finalize(); + * const encrypted = cipher.finalize('data'); + * const encrypted = cipher.finalize(wordArray); + */ + finalize(dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + const finalProcessedData = this._doFinalize(); + + return finalProcessedData; + } +} +Cipher._ENC_XFORM_MODE = 1; +Cipher._DEC_XFORM_MODE = 2; +Cipher.keySize = 128 / 32; +Cipher.ivSize = 128 / 32; + +/** + * Abstract base stream cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ +export class StreamCipher extends Cipher { + constructor(...args) { + super(...args); + + this.blockSize = 1; + } + + _doFinalize() { + // Process partial blocks + const finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + } +} + +/** + * Abstract base block cipher mode template. + */ +export class BlockCipherMode extends Base { + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * const mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + constructor(cipher, iv) { + super(); + + this._cipher = cipher; + this._iv = iv; + } + + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + static createEncryptor(cipher, iv) { + return this.Encryptor.create(cipher, iv); + } + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + static createDecryptor(cipher, iv) { + return this.Decryptor.create(cipher, iv); + } +} + +function xorBlock(words, offset, blockSize) { + const _words = words; + let block; + + // Shortcut + const iv = this._iv; + + // Choose mixing block + if (iv) { + block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + block = this._prevBlock; + } + + // XOR blocks + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= block[i]; + } +} + +/** + * Cipher Block Chaining mode. + */ + +/** + * Abstract base CBC mode. + */ +export class CBC extends BlockCipherMode { +} +/** + * CBC encryptor. + */ +CBC.Encryptor = class extends CBC { + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } +}; +/** + * CBC decryptor. + */ +CBC.Decryptor = class extends CBC { + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // Remember this block to use with next block + const thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } +}; + +/** + * PKCS #5/7 padding strategy. + */ +export const Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad(data, blockSize) { + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); + + // Create padding word + const paddingWord = (nPaddingBytes << 24) + | (nPaddingBytes << 16) + | (nPaddingBytes << 8) + | nPaddingBytes; + + // Create padding + const paddingWords = []; + for (let i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + const padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad(data) { + const _data = data; + + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; + +/** + * Abstract base block cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ +export class BlockCipher extends Cipher { + constructor(xformMode, key, cfg) { + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + super(xformMode, key, Object.assign( + { + mode: CBC, + padding: Pkcs7, + }, + cfg, + )); + + this.blockSize = 128 / 32; + } + + reset() { + let modeCreator; + + // Reset cipher + super.reset.call(this); + + // Shortcuts + const { cfg } = this; + const { iv, mode } = cfg; + + // Reset block mode + if (this._xformMode === this.constructor._ENC_XFORM_MODE) { + modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + modeCreator = mode.createDecryptor; + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + + this._mode = modeCreator.call(mode, this, iv && iv.words); + this._mode.__creator = modeCreator; + } + + _doProcessBlock(words, offset) { + this._mode.processBlock(words, offset); + } + + _doFinalize() { + let finalProcessedBlocks; + + // Shortcut + const { padding } = this.cfg; + + // Finalize + if (this._xformMode === this.constructor._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + } +} + +/** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter + * The default formatting strategy to convert this cipher params object to a string. + */ +export class CipherParams extends Base { + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + constructor(cipherParams) { + super(); + + this.mixIn(cipherParams); + } + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString(formatter) { + return (formatter || this.formatter).stringify(this); + } +} + +/** + * OpenSSL formatting strategy. + */ +export const OpenSSLFormatter = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify(cipherParams) { + let wordArray; + + // Shortcuts + const { ciphertext, salt } = cipherParams; + + // Format + if (salt) { + wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse(openSSLStr) { + let salt; + + // Parse base64 + const ciphertext = Base64.parse(openSSLStr); + + // Shortcut + const ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] === 0x53616c74 && ciphertextWords[1] === 0x65645f5f) { + // Extract salt + salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext, salt }); + }, +}; + +/** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ +export class SerializableCipher extends Base { + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher, message, key, cfg) { + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Encrypt + const encryptor = cipher.createEncryptor(key, _cfg); + const ciphertext = encryptor.finalize(message); + + // Shortcut + const cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext, + key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: encryptor.blockSize, + formatter: _cfg.format, + }); + } + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher, ciphertext, key, cfg) { + let _ciphertext = ciphertext; + + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Convert string to CipherParams + _ciphertext = this._parse(_ciphertext, _cfg.format); + + // Decrypt + const plaintext = cipher.createDecryptor(key, _cfg).finalize(_ciphertext.ciphertext); + + return plaintext; + } + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * ._parse(ciphertextStringOrParams, format); + */ + static _parse(ciphertext, format) { + if (typeof ciphertext === 'string') { + return format.parse(ciphertext, this); + } + return ciphertext; + } +} +/** + * Configuration options. + * + * @property {Formatter} format + * + * The formatting strategy to convert cipher param objects to and from a string. + * Default: OpenSSL + */ +SerializableCipher.cfg = Object.assign( + new Base(), + { format: OpenSSLFormatter }, +); + +/** + * OpenSSL key derivation function. + */ +export const OpenSSLKdf = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt + * (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute(password, keySize, ivSize, salt, hasher) { + let _salt = salt; + + // Generate random salt + if (!_salt) { + _salt = WordArray.random(64 / 8); + } + + // Derive key and IV + let key; + if (!hasher) { + key = EvpKDFAlgo.create({ keySize: keySize + ivSize }).compute(password, _salt); + } else { + key = EvpKDFAlgo.create({ keySize: keySize + ivSize, hasher }).compute(password, _salt); + } + + // Separate key and IV + const iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key, iv, salt: _salt }); + }, +}; + +/** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ +export class PasswordBasedCipher extends SerializableCipher { + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher, message, password, cfg) { + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Derive key and other params + const derivedParams = _cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, _cfg.salt, _cfg.hasher); + + // Add IV to config + _cfg.iv = derivedParams.iv; + + // Encrypt + const ciphertext = SerializableCipher.encrypt + .call(this, cipher, message, derivedParams.key, _cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + } + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', + * { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', + * { format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher, ciphertext, password, cfg) { + let _ciphertext = ciphertext; + + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Convert string to CipherParams + _ciphertext = this._parse(_ciphertext, _cfg.format); + + // Derive key and other params + const derivedParams = _cfg.kdf + .execute(password, cipher.keySize, cipher.ivSize, _ciphertext.salt, _cfg.hasher); + + // Add IV to config + _cfg.iv = derivedParams.iv; + + // Decrypt + const plaintext = SerializableCipher.decrypt + .call(this, cipher, _ciphertext, derivedParams.key, _cfg); + + return plaintext; + } +} +/** + * Configuration options. + * + * @property {KDF} kdf + * The key derivation function to use to generate a key and IV from a password. + * Default: OpenSSL + */ +PasswordBasedCipher.cfg = Object.assign(SerializableCipher.cfg, { kdf: OpenSSLKdf }); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/core.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/core.d.ts new file mode 100644 index 0000000..02a870c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/core.d.ts @@ -0,0 +1,342 @@ +/** + * Base class for inheritance. + */ +export class Base { + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + static create(...args: any[]): Base; + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn(properties: object): Base; + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone(): Base; +} +/** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class WordArray extends Base { + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + static random(nBytes: number): WordArray; + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + static create( + words?: Array | ArrayBuffer | Uint8Array | Int8Array | Uint8ClampedArray + | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, + sigBytes?: number, + ): WordArray; + constructor( + words?: Array | ArrayBuffer | Uint8Array | Int8Array | Uint8ClampedArray + | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, + sigBytes?: number, + ); + words: Array; + sigBytes: number; + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString(encoder?: Encoder): string; + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat(wordArray: WordArray): WordArray; + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp(): void; + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone(): WordArray; +} +export interface Encoder { + stringify(wordArray: WordArray): string; + parse(str: string): WordArray; +} +export const Hex: Encoder; +export const Latin1: Encoder; +export const Utf8: Encoder; +/** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize + * + * The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ +export class BufferedBlockAlgorithm extends Base { + _minBufferSize: number; + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset(): void; + _data: WordArray; + _nDataBytes: number; + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data + * + * The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append(data: WordArray | string): void; + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process(doFlush?: boolean): WordArray; + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone(): BufferedBlockAlgorithm; +} +export interface HasherCfg { + // SHA3 + outputLength?: number +} +export type HashFn = (message: WordArray | string, cfg?: HasherCfg) => WordArray; +export type HMACHashFn = (message: WordArray | string, key: WordArray | string) => WordArray; +/** + * Abstract hasher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ +export class Hasher extends BufferedBlockAlgorithm { + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} SubHasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + static _createHelper(SubHasher: Hasher): HashFn; + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} SubHasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + static _createHmacHelper(SubHasher: Hasher): HMACHashFn; + static create(cfg?: HasherCfg): Hasher; + constructor(cfg?: HasherCfg); + blockSize: number; + /** + * Configuration options. + */ + cfg: Base; + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update(messageUpdate: WordArray | string): Hasher; + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize(messageUpdate?: WordArray | string): WordArray; + _doReset(): void; + _hash: WordArray; + _doProcessBlock(M: number[], offset: number): void; + _doFinalize(): WordArray; +} +/** + * HMAC algorithm. + */ +export class HMAC extends Base { + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} SubHasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + static create(SubHasher: Function, key: WordArray | string): HMAC; + constructor(SubHasher: Function, key: WordArray | string); + _hasher: Hasher; + _oKey: WordArray; + _iKey: WordArray; + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset(): void; + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update(messageUpdate: WordArray | string): HMAC; + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize(messageUpdate?: WordArray | string): WordArray; +} +export interface KDFCfg { + // EvpKDF + keySize?: number; + hasher?: Function; + iterations?: number; +} +export type KDFFn = (password: WordArray | string, salt: WordArray | string, cfg?: KDFCfg) => WordArray; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/core.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/core.js new file mode 100644 index 0000000..a7454c9 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/core.js @@ -0,0 +1,800 @@ +/* eslint-disable no-use-before-define */ + +const crypto = + (typeof globalThis != 'undefined' ? globalThis : void 0)?.crypto || + (typeof global != 'undefined' ? global : void 0)?.crypto || + (typeof window != 'undefined' ? window : void 0)?.crypto || + (typeof self != 'undefined' ? self : void 0)?.crypto || + (typeof frames != 'undefined' ? frames : void 0)?.[0]?.crypto; + +let randomWordArray; + +if (crypto) { + randomWordArray = (nBytes) => { + const words = []; + + for (let i = 0, rcache; i < nBytes; i += 4) { + words.push(crypto.getRandomValues(new Uint32Array(1))[0]); + } + + return new WordArray(words, nBytes); + } +} else { + // Because there is no global crypto property in this context, cryptographically unsafe Math.random() is used. + + randomWordArray = (nBytes) => { + const words = []; + + const r = (m_w) => { + let _m_w = m_w; + let _m_z = 0x3ade68b1; + const mask = 0xffffffff; + + return () => { + _m_z = (0x9069 * (_m_z & 0xFFFF) + (_m_z >> 0x10)) & mask; + _m_w = (0x4650 * (_m_w & 0xFFFF) + (_m_w >> 0x10)) & mask; + let result = ((_m_z << 0x10) + _m_w) & mask; + result /= 0x100000000; + result += 0.5; + return result * (Math.random() > 0.5 ? 1 : -1); + }; + }; + + for (let i = 0, rcache; i < nBytes; i += 4) { + const _r = r((rcache || Math.random()) * 0x100000000); + + rcache = _r() * 0x3ade67b7; + words.push((_r() * 0x100000000) | 0); + } + + return new WordArray(words, nBytes); + } +} + +/** + * Base class for inheritance. + */ +export class Base { + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + static create(...args) { + return new this(...args); + } + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn(properties) { + return Object.assign(this, properties); + } + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone() { + const clone = new this.constructor(); + Object.assign(clone, this); + return clone; + } +} + +/** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + constructor(words = [], sigBytes = words.length * 4) { + super(); + + let typedArray = words; + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array + || typedArray instanceof Uint8ClampedArray + || typedArray instanceof Int16Array + || typedArray instanceof Uint16Array + || typedArray instanceof Int32Array + || typedArray instanceof Uint32Array + || typedArray instanceof Float32Array + || typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + const typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + const _words = []; + for (let i = 0; i < typedArrayByteLength; i += 1) { + _words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + this.words = _words; + this.sigBytes = typedArrayByteLength; + } else { + // Else call normal init + this.words = words; + this.sigBytes = sigBytes; + } + } + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + static random = randomWordArray; + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString(encoder = Hex) { + return encoder.stringify(this); + } + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat(wordArray) { + // Shortcuts + const thisWords = this.words; + const thatWords = wordArray.words; + const thisSigBytes = this.sigBytes; + const thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (let i = 0; i < thatSigBytes; i += 1) { + const thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (let i = 0; i < thatSigBytes; i += 4) { + thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + } + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp() { + // Shortcuts + const { words, sigBytes } = this; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + } + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone() { + const clone = super.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + } +} + +/** + * Hex encoding strategy. + */ +export const Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const hexChars = []; + for (let i = 0; i < sigBytes; i += 1) { + const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse(hexStr) { + // Shortcut + const hexStrLength = hexStr.length; + + // Convert + const words = []; + for (let i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray(words, hexStrLength / 2); + }, +}; + +/** + * Latin1 encoding strategy. + */ +export const Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const latin1Chars = []; + for (let i = 0; i < sigBytes; i += 1) { + const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse(latin1Str) { + // Shortcut + const latin1StrLength = latin1Str.length; + + // Convert + const words = []; + for (let i = 0; i < latin1StrLength; i += 1) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray(words, latin1StrLength); + }, +}; + +/** + * UTF-8 encoding strategy. + */ +export const Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify(wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse(utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + }, +}; + +/** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize + * + * The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ +export class BufferedBlockAlgorithm extends Base { + constructor() { + super(); + this._minBufferSize = 0; + } + + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset() { + // Initial values + this._data = new WordArray(); + this._nDataBytes = 0; + } + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data + * + * The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append(data) { + let m_data = data; + + // Convert string to WordArray, else assume WordArray already + if (typeof m_data === 'string') { + m_data = Utf8.parse(m_data); + } + + // Append + this._data.concat(m_data); + this._nDataBytes += m_data.sigBytes; + } + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process(doFlush) { + let processedWords; + + // Shortcuts + const { _data: data, blockSize } = this; + const dataWords = data.words; + const dataSigBytes = data.sigBytes; + const blockSizeBytes = blockSize * 4; + + // Count blocks ready + let nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + const nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (let offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray(processedWords, nBytesReady); + } + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone() { + const clone = super.clone.call(this); + clone._data = this._data.clone(); + + return clone; + } +} + +/** + * Abstract hasher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ +export class Hasher extends BufferedBlockAlgorithm { + constructor(cfg) { + super(); + + this.blockSize = 512 / 32; + + /** + * Configuration options. + */ + this.cfg = Object.assign(new Base(), cfg); + + // Set initial values + this.reset(); + } + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} SubHasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + static _createHelper(SubHasher) { + return (message, cfg) => new SubHasher(cfg).finalize(message); + } + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} SubHasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + static _createHmacHelper(SubHasher) { + return (message, key) => new HMAC(SubHasher, key).finalize(message); + } + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset() { + // Reset data buffer + super.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + } + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update(messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + } + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize(messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + const hash = this._doFinalize(); + + return hash; + } +} + +/** + * HMAC algorithm. + */ +export class HMAC extends Base { + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} SubHasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + constructor(SubHasher, key) { + super(); + + const hasher = new SubHasher(); + this._hasher = hasher; + + // Convert string to WordArray, else assume WordArray already + let _key = key; + if (typeof _key === 'string') { + _key = Utf8.parse(_key); + } + + // Shortcuts + const hasherBlockSize = hasher.blockSize; + const hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (_key.sigBytes > hasherBlockSizeBytes) { + _key = hasher.finalize(key); + } + + // Clamp excess bits + _key.clamp(); + + // Clone key for inner and outer pads + const oKey = _key.clone(); + this._oKey = oKey; + const iKey = _key.clone(); + this._iKey = iKey; + + // Shortcuts + const oKeyWords = oKey.words; + const iKeyWords = iKey.words; + + // XOR keys with pad constants + for (let i = 0; i < hasherBlockSize; i += 1) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = hasherBlockSizeBytes; + iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + } + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset() { + // Shortcut + const hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + } + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update(messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + } + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize(messageUpdate) { + // Shortcut + const hasher = this._hasher; + + // Compute HMAC + const innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + const hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } +} diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64.d.ts new file mode 100644 index 0000000..be1e5c6 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64.d.ts @@ -0,0 +1,7 @@ +export function parseLoop(base64Str: string, base64StrLength: number, reverseMap: number[]): WordArray; +/** + * Base64 encoding strategy. + */ +export const Base64: Encoder; +import { Encoder } from './core.js'; +import { WordArray } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64.js new file mode 100644 index 0000000..fe45de5 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64.js @@ -0,0 +1,111 @@ +import { + WordArray, +} from './core.js'; + +export const parseLoop = (base64Str, base64StrLength, reverseMap) => { + const words = []; + let nBytes = 0; + for (let i = 0; i < base64StrLength; i += 1) { + if (i % 4) { + const bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + const bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + const bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes += 1; + } + } + return WordArray.create(words, nBytes); +}; + +/** + * Base64 encoding strategy. + */ +export const Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * const base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + const map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + const base64Chars = []; + for (let i = 0; i < sigBytes; i += 3) { + const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + const triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + const paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse(base64Str) { + // Shortcuts + let base64StrLength = base64Str.length; + const map = this._map; + let reverseMap = this._reverseMap; + + if (!reverseMap) { + this._reverseMap = []; + reverseMap = this._reverseMap; + for (let j = 0; j < map.length; j += 1) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + const paddingChar = map.charAt(64); + if (paddingChar) { + const paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64url.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64url.d.ts new file mode 100644 index 0000000..d16ffc4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64url.d.ts @@ -0,0 +1,5 @@ +/** + * Base64url encoding strategy. + */ +export const Base64url: Encoder; +import { Encoder } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64url.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64url.js new file mode 100644 index 0000000..eff6701 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-base64url.js @@ -0,0 +1,105 @@ +import { + WordArray, +} from './core.js'; +import { + parseLoop, +} from './enc-base64.js' + +/** + * Base64url encoding strategy. + */ +export const Base64url = { + /** + * Converts a word array to a Base64url string. + * + * @param {WordArray} wordArray The word array. + * + * @param {boolean} urlSafe Whether to use url safe. + * + * @return {string} The Base64url string. + * + * @static + * + * @example + * + * const base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify(wordArray, urlSafe = true) { + // Shortcuts + const { words, sigBytes } = wordArray; + const map = urlSafe ? this._safeMap : this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + const base64Chars = []; + for (let i = 0; i < sigBytes; i += 3) { + const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + const triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + const paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64url string to a word array. + * + * @param {string} base64Str The Base64url string. + * + * @param {boolean} urlSafe Whether to use url safe. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse(base64Str, urlSafe = true) { + // Shortcuts + let base64StrLength = base64Str.length; + const map = urlSafe ? this._safeMap : this._map; + let reverseMap = this._reverseMap; + + if (!reverseMap) { + this._reverseMap = []; + reverseMap = this._reverseMap; + for (let j = 0; j < map.length; j += 1) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + const paddingChar = map.charAt(64); + if (paddingChar) { + const paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + + _safeMap: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-utf16.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-utf16.d.ts new file mode 100644 index 0000000..dc32723 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-utf16.d.ts @@ -0,0 +1,10 @@ +export const Utf16: Encoder; +/** + * UTF-16 BE encoding strategy. + */ +export const Utf16BE: Encoder; +/** + * UTF-16 LE encoding strategy. + */ +export const Utf16LE: Encoder; +import { Encoder } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-utf16.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-utf16.js new file mode 100644 index 0000000..7fe0da4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/enc-utf16.js @@ -0,0 +1,122 @@ +import { + WordArray, +} from './core.js'; + +const swapEndian = word => ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + +/** + * UTF-16 BE encoding strategy. + */ +export const Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * const utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const utf16Chars = []; + for (let i = 0; i < sigBytes; i += 2) { + const codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse(utf16Str) { + // Shortcut + const utf16StrLength = utf16Str.length; + + // Convert + const words = []; + for (let i = 0; i < utf16StrLength; i += 1) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + }, +}; +export const Utf16 = Utf16BE; + +/** + * UTF-16 LE encoding strategy. + */ +export const Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * const utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const utf16Chars = []; + for (let i = 0; i < sigBytes; i += 2) { + const codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse(utf16Str) { + // Shortcut + const utf16StrLength = utf16Str.length; + + // Convert + const words = []; + for (let i = 0; i < utf16StrLength; i += 1) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/evpkdf.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/evpkdf.d.ts new file mode 100644 index 0000000..f653274 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/evpkdf.d.ts @@ -0,0 +1,31 @@ +/** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ +export class EvpKDFAlgo extends Base { + static create(cfg?: KDFCfg): EvpKDFAlgo; + constructor(cfg?: KDFCfg); + compute(password: WordArray | string, salt: WordArray | string): WordArray; +} +/** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const EvpKDF: KDFFn; +import { Base } from './core.js'; +import { WordArray } from './core.js'; +import { KDFCfg } from './core.js'; +import { KDFFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/evpkdf.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/evpkdf.js new file mode 100644 index 0000000..be7bb6d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/evpkdf.js @@ -0,0 +1,111 @@ +import { + Base, + WordArray, +} from './core.js'; +import { MD5Algo } from './md5.js'; + +/** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ +export class EvpKDFAlgo extends Base { + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * const kdf = CryptoJS.algo.EvpKDF.create(); + * const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + constructor(cfg) { + super(); + + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + this.cfg = Object.assign( + new Base(), + { + keySize: 128 / 32, + hasher: MD5Algo, + iterations: 1, + }, + cfg, + ); + } + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * const key = kdf.compute(password, salt); + */ + compute(password, salt) { + let block; + + // Shortcut + const { cfg } = this; + + // Init hasher + const hasher = cfg.hasher.create(); + + // Initial values + const derivedKey = WordArray.create(); + + // Shortcuts + const derivedKeyWords = derivedKey.words; + const { keySize, iterations } = cfg; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (let i = 1; i < iterations; i += 1) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } +} + +/** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const EvpKDF = (password, salt, cfg) => EvpKDFAlgo.create(cfg).compute(password, salt); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/format-hex.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/format-hex.d.ts new file mode 100644 index 0000000..f950a51 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/format-hex.d.ts @@ -0,0 +1,2 @@ +export const HexFormatter: Format; +import { Format } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/format-hex.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/format-hex.js new file mode 100644 index 0000000..9c44463 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/format-hex.js @@ -0,0 +1,43 @@ +import { + CipherParams, +} from './cipher-core.js'; +import { + Hex, +} from './core.js'; + +export const HexFormatter = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify(cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse(input) { + const ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext }); + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/hmac.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/hmac.d.ts new file mode 100644 index 0000000..0238847 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/hmac.d.ts @@ -0,0 +1 @@ +export { HMAC } from "./core.js"; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/hmac.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/hmac.js new file mode 100644 index 0000000..0beb0a4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/hmac.js @@ -0,0 +1,3 @@ +export { + HMAC, +} from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/index.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/index.d.ts new file mode 100644 index 0000000..29ef9c1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/index.d.ts @@ -0,0 +1,181 @@ +declare namespace _default { + export namespace lib { + export { Base }; + export { WordArray }; + export { BufferedBlockAlgorithm }; + export { Hasher }; + export { Cipher }; + export { StreamCipher }; + export { BlockCipherMode }; + export { BlockCipher }; + export { CipherParams }; + export { SerializableCipher }; + export { PasswordBasedCipher }; + } + export namespace x64 { + export { X64Word as Word }; + export { X64WordArray as WordArray }; + } + export namespace enc { + export { Hex }; + export { Latin1 }; + export { Utf8 }; + export { Utf16 }; + export { Utf16BE }; + export { Utf16LE }; + export { Base64 }; + export { Base64url }; + } + export namespace algo { + export { HMAC }; + export { MD5Algo as MD5 }; + export { SHA1Algo as SHA1 }; + export { SHA224Algo as SHA224 }; + export { SHA256Algo as SHA256 }; + export { SHA384Algo as SHA384 }; + export { SHA512Algo as SHA512 }; + export { SHA3Algo as SHA3 }; + export { RIPEMD160Algo as RIPEMD160 }; + export { PBKDF2Algo as PBKDF2 }; + export { EvpKDFAlgo as EvpKDF }; + export { AESAlgo as AES }; + export { DESAlgo as DES }; + export { TripleDESAlgo as TripleDES }; + export { RabbitAlgo as Rabbit }; + export { RabbitLegacyAlgo as RabbitLegacy }; + export { RC4Algo as RC4 }; + export { RC4DropAlgo as RC4Drop }; + export { BlowfishAlgo as Blowfish }; + } + export namespace mode { + export { CBC }; + export { CFB }; + export { CTR }; + export { CTRGladman }; + export { ECB }; + export { OFB }; + } + export namespace pad { + export { Pkcs7 }; + export { AnsiX923 }; + export { Iso10126 }; + export { Iso97971 }; + export { NoPadding }; + export { ZeroPadding }; + } + export namespace format { + export { OpenSSLFormatter as OpenSSL }; + export { HexFormatter as Hex }; + } + export namespace kdf { + export { OpenSSLKdf as OpenSSL }; + } + export { MD5 }; + export { HmacMD5 }; + export { SHA1 }; + export { HmacSHA1 }; + export { SHA224 }; + export { HmacSHA224 }; + export { SHA256 }; + export { HmacSHA256 }; + export { SHA384 }; + export { HmacSHA384 }; + export { SHA512 }; + export { HmacSHA512 }; + export { SHA3 }; + export { HmacSHA3 }; + export { RIPEMD160 }; + export { HmacRIPEMD160 }; + export { PBKDF2 }; + export { EvpKDF }; + export { AES }; + export { DES }; + export { TripleDES }; + export { Rabbit }; + export { RabbitLegacy }; + export { RC4 }; + export { RC4Drop }; + export { Blowfish }; +} +export default _default; +import { Base } from './core.js'; +import { WordArray } from './core.js'; +import { BufferedBlockAlgorithm } from './core.js'; +import { Hasher } from './core.js'; +import { Cipher } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; +import { BlockCipherMode } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; +import { CipherParams } from './cipher-core.js'; +import { SerializableCipher } from './cipher-core.js'; +import { PasswordBasedCipher } from './cipher-core.js'; +import { X64Word } from './x64-core.js'; +import { X64WordArray } from './x64-core.js'; +import { Hex } from './core.js'; +import { Latin1 } from './core.js'; +import { Utf8 } from './core.js'; +import { Utf16 } from './enc-utf16.js'; +import { Utf16BE } from './enc-utf16.js'; +import { Utf16LE } from './enc-utf16.js'; +import { Base64 } from './enc-base64.js'; +import { Base64url } from './enc-base64url.js'; +import { HMAC } from './hmac.js'; +import { MD5Algo } from './md5.js'; +import { SHA1Algo } from './sha1.js'; +import { SHA224Algo } from './sha224.js'; +import { SHA256Algo } from './sha256.js'; +import { SHA384Algo } from './sha384.js'; +import { SHA512Algo } from './sha512.js'; +import { SHA3Algo } from './sha3.js'; +import { RIPEMD160Algo } from './ripemd160.js'; +import { PBKDF2Algo } from './pbkdf2.js'; +import { EvpKDFAlgo } from './evpkdf.js'; +import { AESAlgo } from './aes.js'; +import { DESAlgo } from './tripledes.js'; +import { TripleDESAlgo } from './tripledes.js'; +import { RabbitAlgo } from './rabbit.js'; +import { RabbitLegacyAlgo } from './rabbit-legacy.js'; +import { RC4Algo } from './rc4.js'; +import { RC4DropAlgo } from './rc4.js'; +import { BlowfishAlgo } from './blowfish.js'; +import { CBC } from './cipher-core.js'; +import { CFB } from './mode-cfb.js'; +import { CTR } from './mode-ctr.js'; +import { CTRGladman } from './mode-ctr-gladman.js'; +import { ECB } from './mode-ecb.js'; +import { OFB } from './mode-ofb.js'; +import { Pkcs7 } from './cipher-core.js'; +import { AnsiX923 } from './pad-ansix923.js'; +import { Iso10126 } from './pad-iso10126.js'; +import { Iso97971 } from './pad-iso97971.js'; +import { NoPadding } from './pad-nopadding.js'; +import { ZeroPadding } from './pad-zeropadding.js'; +import { OpenSSLFormatter } from './cipher-core.js'; +import { HexFormatter } from './format-hex.js'; +import { OpenSSLKdf } from './cipher-core.js'; +import { MD5 } from './md5.js'; +import { HmacMD5 } from './md5.js'; +import { SHA1 } from './sha1.js'; +import { HmacSHA1 } from './sha1.js'; +import { SHA224 } from './sha224.js'; +import { HmacSHA224 } from './sha224.js'; +import { SHA256 } from './sha256.js'; +import { HmacSHA256 } from './sha256.js'; +import { SHA384 } from './sha384.js'; +import { HmacSHA384 } from './sha384.js'; +import { SHA512 } from './sha512.js'; +import { HmacSHA512 } from './sha512.js'; +import { SHA3 } from './sha3.js'; +import { HmacSHA3 } from './sha3.js'; +import { RIPEMD160 } from './ripemd160.js'; +import { HmacRIPEMD160 } from './ripemd160.js'; +import { PBKDF2 } from './pbkdf2.js'; +import { EvpKDF } from './evpkdf.js'; +import { AES } from './aes.js'; +import { DES } from './tripledes.js'; +import { TripleDES } from './tripledes.js'; +import { Rabbit } from './rabbit.js'; +import { RabbitLegacy } from './rabbit-legacy.js'; +import { RC4 } from './rc4.js'; +import { RC4Drop } from './rc4.js'; +import { Blowfish } from './blowfish.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/index.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/index.js new file mode 100644 index 0000000..ce5f2a1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/index.js @@ -0,0 +1,180 @@ +import { + Base, + WordArray, + Hex, + Latin1, + Utf8, + BufferedBlockAlgorithm, + Hasher, +} from './core.js'; +import { + X64Word, + X64WordArray, +} from './x64-core.js'; +import { + Cipher, + StreamCipher, + BlockCipherMode, + CBC, + Pkcs7, + BlockCipher, + CipherParams, + OpenSSLFormatter, + SerializableCipher, + OpenSSLKdf, + PasswordBasedCipher, +} from './cipher-core.js'; + +import { Utf16, Utf16BE, Utf16LE } from './enc-utf16.js'; +import { Base64 } from './enc-base64.js'; +import { Base64url } from './enc-base64url.js'; +import { HMAC } from './hmac.js'; +import { MD5Algo, MD5, HmacMD5 } from './md5.js'; +import { SHA1Algo, SHA1, HmacSHA1 } from './sha1.js'; +import { SHA224Algo, SHA224, HmacSHA224 } from './sha224.js'; +import { SHA256Algo, SHA256, HmacSHA256 } from './sha256.js'; +import { SHA384Algo, SHA384, HmacSHA384 } from './sha384.js'; +import { SHA512Algo, SHA512, HmacSHA512 } from './sha512.js'; +import { SHA3Algo, SHA3, HmacSHA3 } from './sha3.js'; +import { RIPEMD160Algo, RIPEMD160, HmacRIPEMD160 } from './ripemd160.js'; +import { PBKDF2Algo, PBKDF2 } from './pbkdf2.js'; +import { EvpKDFAlgo, EvpKDF } from './evpkdf.js'; +import { AESAlgo, AES } from './aes.js'; +import { + DESAlgo, + DES, + TripleDESAlgo, + TripleDES, +} from './tripledes.js'; +import { RabbitAlgo, Rabbit } from './rabbit.js'; +import { RabbitLegacyAlgo, RabbitLegacy } from './rabbit-legacy.js'; +import { + RC4Algo, + RC4, + RC4DropAlgo, + RC4Drop, +} from './rc4.js'; +import { BlowfishAlgo, Blowfish } from './blowfish.js'; +import { CFB } from './mode-cfb.js'; +import { CTR } from './mode-ctr.js'; +import { CTRGladman } from './mode-ctr-gladman.js'; +import { ECB } from './mode-ecb.js'; +import { OFB } from './mode-ofb.js'; +import { AnsiX923 } from './pad-ansix923.js'; +import { Iso10126 } from './pad-iso10126.js'; +import { Iso97971 } from './pad-iso97971.js'; +import { NoPadding } from './pad-nopadding.js'; +import { ZeroPadding } from './pad-zeropadding.js'; +import { HexFormatter } from './format-hex.js'; + +export default { + lib: { + Base, + WordArray, + BufferedBlockAlgorithm, + Hasher, + Cipher, + StreamCipher, + BlockCipherMode, + BlockCipher, + CipherParams, + SerializableCipher, + PasswordBasedCipher, + }, + + x64: { + Word: X64Word, + WordArray: X64WordArray, + }, + + enc: { + Hex, + Latin1, + Utf8, + Utf16, + Utf16BE, + Utf16LE, + Base64, + Base64url, + }, + + algo: { + HMAC, + MD5: MD5Algo, + SHA1: SHA1Algo, + SHA224: SHA224Algo, + SHA256: SHA256Algo, + SHA384: SHA384Algo, + SHA512: SHA512Algo, + SHA3: SHA3Algo, + RIPEMD160: RIPEMD160Algo, + + PBKDF2: PBKDF2Algo, + EvpKDF: EvpKDFAlgo, + + AES: AESAlgo, + DES: DESAlgo, + TripleDES: TripleDESAlgo, + Rabbit: RabbitAlgo, + RabbitLegacy: RabbitLegacyAlgo, + RC4: RC4Algo, + RC4Drop: RC4DropAlgo, + Blowfish: BlowfishAlgo, + }, + + mode: { + CBC, + CFB, + CTR, + CTRGladman, + ECB, + OFB, + }, + + pad: { + Pkcs7, + AnsiX923, + Iso10126, + Iso97971, + NoPadding, + ZeroPadding, + }, + + format: { + OpenSSL: OpenSSLFormatter, + Hex: HexFormatter, + }, + + kdf: { + OpenSSL: OpenSSLKdf, + }, + + MD5, + HmacMD5, + SHA1, + HmacSHA1, + SHA224, + HmacSHA224, + SHA256, + HmacSHA256, + SHA384, + HmacSHA384, + SHA512, + HmacSHA512, + SHA3, + HmacSHA3, + RIPEMD160, + HmacRIPEMD160, + + PBKDF2, + EvpKDF, + + AES, + DES, + TripleDES, + Rabbit, + RabbitLegacy, + RC4, + RC4Drop, + Blowfish, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/md5.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/md5.d.ts new file mode 100644 index 0000000..2c8f211 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/md5.d.ts @@ -0,0 +1,37 @@ +/** + * MD5 hash algorithm. + */ +export class MD5Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ +export const MD5: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ +export const HmacMD5: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/md5.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/md5.js new file mode 100644 index 0000000..927900e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/md5.js @@ -0,0 +1,247 @@ +import { + WordArray, + Hasher, +} from './core.js'; + +// Constants table +const T = []; + +// Compute constants +for (let i = 0; i < 64; i += 1) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; +} + +const FF = (a, b, c, d, x, s, t) => { + const n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const GG = (a, b, c, d, x, s, t) => { + const n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const HH = (a, b, c, d, x, s, t) => { + const n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const II = (a, b, c, d, x, s, t) => { + const n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +/** + * MD5 hash algorithm. + */ +export class MD5Algo extends Hasher { + _doReset() { + this._hash = new WordArray([ + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + ]); + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Swap endian + for (let i = 0; i < 16; i += 1) { + // Shortcuts + const offset_i = offset + i; + const M_offset_i = M[offset_i]; + + _M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) + | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + const H = this._hash.words; + + const M_offset_0 = _M[offset + 0]; + const M_offset_1 = _M[offset + 1]; + const M_offset_2 = _M[offset + 2]; + const M_offset_3 = _M[offset + 3]; + const M_offset_4 = _M[offset + 4]; + const M_offset_5 = _M[offset + 5]; + const M_offset_6 = _M[offset + 6]; + const M_offset_7 = _M[offset + 7]; + const M_offset_8 = _M[offset + 8]; + const M_offset_9 = _M[offset + 9]; + const M_offset_10 = _M[offset + 10]; + const M_offset_11 = _M[offset + 11]; + const M_offset_12 = _M[offset + 12]; + const M_offset_13 = _M[offset + 13]; + const M_offset_14 = _M[offset + 14]; + const M_offset_15 = _M[offset + 15]; + + // Working varialbes + let a = H[0]; + let b = H[1]; + let c = H[2]; + let d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + } + /* eslint-ensable no-param-reassign */ + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + + const nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + const nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) + | (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) + | (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const hash = this._hash; + const H = hash.words; + + // Swap endian + for (let i = 0; i < 4; i += 1) { + // Shortcut + const H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) + | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ +export const MD5 = Hasher._createHelper(MD5Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ +export const HmacMD5 = Hasher._createHmacHelper(MD5Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-cfb.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-cfb.d.ts new file mode 100644 index 0000000..f33e10f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-cfb.d.ts @@ -0,0 +1,6 @@ +/** + * Cipher Feedback block mode. + */ +export class CFB extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-cfb.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-cfb.js new file mode 100644 index 0000000..27444e5 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-cfb.js @@ -0,0 +1,60 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + const _words = words; + let keystream; + + // Shortcut + const iv = this._iv; + + // Generate keystream + if (iv) { + keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } +} + +/** + * Cipher Feedback block mode. + */ +export class CFB extends BlockCipherMode { +} +CFB.Encryptor = class extends CFB { + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } +}; +CFB.Decryptor = class extends CFB { + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // Remember this block to use with next block + const thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr-gladman.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr-gladman.d.ts new file mode 100644 index 0000000..d313d08 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr-gladman.d.ts @@ -0,0 +1,8 @@ +/** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ +export class CTRGladman extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr-gladman.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr-gladman.js new file mode 100644 index 0000000..4481084 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr-gladman.js @@ -0,0 +1,87 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +const incWord = (word) => { + let _word = word; + + if (((word >> 24) & 0xff) === 0xff) { // overflow + let b1 = (word >> 16) & 0xff; + let b2 = (word >> 8) & 0xff; + let b3 = word & 0xff; + + if (b1 === 0xff) { // overflow b1 + b1 = 0; + if (b2 === 0xff) { + b2 = 0; + if (b3 === 0xff) { + b3 = 0; + } else { + b3 += 1; + } + } else { + b2 += 1; + } + } else { + b1 += 1; + } + + _word = 0; + _word += (b1 << 16); + _word += (b2 << 8); + _word += b3; + } else { + _word += (0x01 << 24); + } + return _word; +}; + +const incCounter = (counter) => { + const _counter = counter; + _counter[0] = incWord(_counter[0]); + + if (_counter[0] === 0) { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + _counter[1] = incWord(_counter[1]); + } + return _counter; +}; + +/** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ +export class CTRGladman extends BlockCipherMode { +} +CTRGladman.Encryptor = class extends CTRGladman { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let counter = this._counter; + + // Generate keystream + if (iv) { + this._counter = iv.slice(0); + counter = this._counter; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + const keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +CTRGladman.Decryptor = CTRGladman.Encryptor; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr.d.ts new file mode 100644 index 0000000..83c8c2f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr.d.ts @@ -0,0 +1,6 @@ +/** + * Counter block mode. + */ +export class CTR extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr.js new file mode 100644 index 0000000..dfce6cf --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ctr.js @@ -0,0 +1,40 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +/** + * Counter block mode. + */ +export class CTR extends BlockCipherMode { +} +CTR.Encryptor = class extends CTR { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let counter = this._counter; + + // Generate keystream + if (iv) { + this._counter = iv.slice(0); + counter = this._counter; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + const keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0; + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +CTR.Decryptor = CTR.Encryptor; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ecb.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ecb.d.ts new file mode 100644 index 0000000..e0439bc --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ecb.d.ts @@ -0,0 +1,6 @@ +/** + * Electronic Codebook block mode. + */ +export class ECB extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ecb.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ecb.js new file mode 100644 index 0000000..7ad54a6 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ecb.js @@ -0,0 +1,19 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +/** + * Electronic Codebook block mode. + */ +export class ECB extends BlockCipherMode { +} +ECB.Encryptor = class extends ECB { + processBlock(words, offset) { + this._cipher.encryptBlock(words, offset); + } +}; +ECB.Decryptor = class extends ECB { + processBlock(words, offset) { + this._cipher.decryptBlock(words, offset); + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ofb.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ofb.d.ts new file mode 100644 index 0000000..ec66be0 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ofb.d.ts @@ -0,0 +1,6 @@ +/** + * Output Feedback block mode. + */ +export class OFB extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ofb.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ofb.js new file mode 100644 index 0000000..5c8cfe1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/mode-ofb.js @@ -0,0 +1,36 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +/** + * Output Feedback block mode. + */ +export class OFB extends BlockCipherMode { +} +OFB.Encryptor = class extends OFB { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let keystream = this._keystream; + + // Generate keystream + if (iv) { + this._keystream = iv.slice(0); + keystream = this._keystream; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +OFB.Decryptor = OFB.Encryptor; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-ansix923.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-ansix923.d.ts new file mode 100644 index 0000000..863ed98 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-ansix923.d.ts @@ -0,0 +1,5 @@ +/** + * ANSI X.923 padding strategy. + */ +export const AnsiX923: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-ansix923.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-ansix923.js new file mode 100644 index 0000000..fab067b --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-ansix923.js @@ -0,0 +1,33 @@ +/** + * ANSI X.923 padding strategy. + */ +export const AnsiX923 = { + pad(data, blockSize) { + const _data = data; + + // Shortcuts + const dataSigBytes = _data.sigBytes; + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (dataSigBytes % blockSizeBytes); + + // Compute last byte position + const lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + _data.clamp(); + _data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + _data.sigBytes += nPaddingBytes; + }, + + unpad(data) { + const _data = data; + + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso10126.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso10126.d.ts new file mode 100644 index 0000000..098068a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso10126.d.ts @@ -0,0 +1,5 @@ +/** + * ISO 10126 padding strategy. + */ +export const Iso10126: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso10126.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso10126.js new file mode 100644 index 0000000..26e3449 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso10126.js @@ -0,0 +1,30 @@ +import { + WordArray, +} from './core.js'; + +/** + * ISO 10126 padding strategy. + */ +export const Iso10126 = { + pad(data, blockSize) { + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); + + // Pad + data + .concat(WordArray.random(nPaddingBytes - 1)) + .concat(WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad(data) { + const _data = data; + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso97971.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso97971.d.ts new file mode 100644 index 0000000..101a14c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso97971.d.ts @@ -0,0 +1,5 @@ +/** + * ISO/IEC 9797-1 Padding Method 2. + */ +export const Iso97971: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso97971.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso97971.js new file mode 100644 index 0000000..73eea6e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-iso97971.js @@ -0,0 +1,29 @@ +import { + WordArray, +} from './core.js'; +import { + ZeroPadding, +} from './pad-zeropadding.js'; + +/** + * ISO/IEC 9797-1 Padding Method 2. + */ +export const Iso97971 = { + pad(data, blockSize) { + // Add 0x80 byte + data.concat(WordArray.create([0x80000000], 1)); + + // Zero pad the rest + ZeroPadding.pad(data, blockSize); + }, + + unpad(data) { + const _data = data; + + // Remove zero padding + ZeroPadding.unpad(_data); + + // Remove one more byte -- the 0x80 byte + _data.sigBytes -= 1; + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-nopadding.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-nopadding.d.ts new file mode 100644 index 0000000..f38a01d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-nopadding.d.ts @@ -0,0 +1,5 @@ +/** + * A noop padding strategy. + */ +export const NoPadding: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-nopadding.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-nopadding.js new file mode 100644 index 0000000..b0fbf4c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-nopadding.js @@ -0,0 +1,10 @@ +/** + * A noop padding strategy. + */ +export const NoPadding = { + pad() { + }, + + unpad() { + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-zeropadding.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-zeropadding.d.ts new file mode 100644 index 0000000..2abb331 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-zeropadding.d.ts @@ -0,0 +1,5 @@ +/** + * Zero padding strategy. + */ +export const ZeroPadding: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-zeropadding.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-zeropadding.js new file mode 100644 index 0000000..00db18c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pad-zeropadding.js @@ -0,0 +1,30 @@ +/** + * Zero padding strategy. + */ +export const ZeroPadding = { + pad(data, blockSize) { + const _data = data; + + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Pad + _data.clamp(); + _data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad(data) { + const _data = data; + + // Shortcut + const dataWords = _data.words; + + // Unpad + for (let i = _data.sigBytes - 1; i >= 0; i -= 1) { + if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + _data.sigBytes = i + 1; + break; + } + } + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pbkdf2.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pbkdf2.d.ts new file mode 100644 index 0000000..2906673 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pbkdf2.d.ts @@ -0,0 +1,30 @@ +/** + * Password-Based Key Derivation Function 2 algorithm. + */ +export class PBKDF2Algo extends Base { + static create(cfg?: KDFCfg): PBKDF2Algo; + constructor(cfg?: KDFCfg); + compute(password: WordArray | string, salt: WordArray | string): WordArray; +} +/** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const PBKDF2: KDFFn; +import { Base } from './core.js'; +import { WordArray } from './core.js'; +import { KDFCfg } from './core.js'; +import { KDFFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pbkdf2.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pbkdf2.js new file mode 100644 index 0000000..6b9dd51 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/pbkdf2.js @@ -0,0 +1,125 @@ +import { + Base, + WordArray, +} from './core.js'; +import { SHA256Algo } from './sha256.js'; +import { HMAC } from './hmac.js'; + +/** + * Password-Based Key Derivation Function 2 algorithm. + */ +export class PBKDF2Algo extends Base { + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * const kdf = CryptoJS.algo.PBKDF2.create(); + * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + constructor(cfg) { + super(); + + /** + * Configuration options. + * + * The default `hasher` and `interations` is different from CryptoJs to enhance security: + * https://github.com/entronad/crypto-es/security/advisories/GHSA-mpj8-q39x-wq5h + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA256 + * @property {number} iterations The number of iterations to perform. Default: 250000 + */ + this.cfg = Object.assign( + new Base(), + { + keySize: 128 / 32, + hasher: SHA256Algo, + iterations: 250000, + }, + cfg, + ); + } + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * const key = kdf.compute(password, salt); + */ + compute(password, salt) { + // Shortcut + const { cfg } = this; + + // Init HMAC + const hmac = HMAC.create(cfg.hasher, password); + + // Initial values + const derivedKey = WordArray.create(); + const blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + const derivedKeyWords = derivedKey.words; + const blockIndexWords = blockIndex.words; + const { keySize, iterations } = cfg; + + // Generate key + while (derivedKeyWords.length < keySize) { + const block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + const blockWords = block.words; + const blockWordsLength = blockWords.length; + + // Iterations + let intermediate = block; + for (let i = 1; i < iterations; i += 1) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + const intermediateWords = intermediate.words; + + // XOR intermediate with block + for (let j = 0; j < blockWordsLength; j += 1) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0] += 1; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } +} + +/** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const PBKDF2 = (password, salt, cfg) => PBKDF2Algo.create(cfg).compute(password, salt); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit-legacy.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit-legacy.d.ts new file mode 100644 index 0000000..baa73e0 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit-legacy.d.ts @@ -0,0 +1,20 @@ +/** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ +export class RabbitLegacyAlgo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ +export const RabbitLegacy: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit-legacy.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit-legacy.js new file mode 100644 index 0000000..e9fc26a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit-legacy.js @@ -0,0 +1,175 @@ +import { + StreamCipher, +} from './cipher-core.js'; + +// Reusable objects +const S = []; +const C_ = []; +const G = []; + +function nextState() { + // Shortcuts + const X = this._X; + const C = this._C; + + // Save old counter values + for (let i = 0; i < 8; i += 1) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (let i = 0; i < 8; i += 1) { + const gx = X[i] + C[i]; + + // Construct high and low argument for squaring + const ga = gx & 0xffff; + const gb = gx >>> 16; + + // Calculate high and low result of squaring + const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; +} + +/** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ +export class RabbitLegacyAlgo extends StreamCipher { + constructor(...args) { + super(...args); + + this.blockSize = 128 / 32; + this.ivSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const K = this._key.words; + const { iv } = this.cfg; + + // Generate initial state values + this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16), + ]; + const X = this._X; + + // Generate initial counter values + this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff), + ]; + const C = this._C; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + + // Modify the counters + for (let i = 0; i < 8; i += 1) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + const IV = iv.words; + const IV_0 = IV[0]; + const IV_1 = IV[1]; + + // Generate four subvectors + const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) + | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) + | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + const i1 = (i0 >>> 16) | (i2 & 0xffff0000); + const i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + } + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Shortcut + const X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (let i = 0; i < 4; i += 1) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) + | (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + _M[offset + i] ^= S[i]; + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ +export const RabbitLegacy = StreamCipher._createHelper(RabbitLegacyAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit.d.ts new file mode 100644 index 0000000..da0bcf4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit.d.ts @@ -0,0 +1,16 @@ +/** + * Rabbit stream cipher algorithm + */ +export class RabbitAlgo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ +export const Rabbit: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit.js new file mode 100644 index 0000000..35f09bb --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rabbit.js @@ -0,0 +1,177 @@ +import { + StreamCipher, +} from './cipher-core.js'; + +// Reusable objects +const S = []; +const C_ = []; +const G = []; + +function nextState() { + // Shortcuts + const X = this._X; + const C = this._C; + + // Save old counter values + for (let i = 0; i < 8; i += 1) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (let i = 0; i < 8; i += 1) { + const gx = X[i] + C[i]; + + // Construct high and low argument for squaring + const ga = gx & 0xffff; + const gb = gx >>> 16; + + // Calculate high and low result of squaring + const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; +} + +/** + * Rabbit stream cipher algorithm + */ +export class RabbitAlgo extends StreamCipher { + constructor(...args) { + super(...args); + + this.blockSize = 128 / 32; + this.ivSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const K = this._key.words; + const { iv } = this.cfg; + + // Swap endian + for (let i = 0; i < 4; i += 1) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) + | (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16), + ]; + const X = this._X; + + // Generate initial counter values + this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff), + ]; + const C = this._C; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + + // Modify the counters + for (let i = 0; i < 8; i += 1) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + const IV = iv.words; + const IV_0 = IV[0]; + const IV_1 = IV[1]; + + // Generate four subvectors + const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) + | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) + | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + const i1 = (i0 >>> 16) | (i2 & 0xffff0000); + const i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + } + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Shortcut + const X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (let i = 0; i < 4; i += 1) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) + | (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + _M[offset + i] ^= S[i]; + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ +export const Rabbit = StreamCipher._createHelper(RabbitAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rc4.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rc4.d.ts new file mode 100644 index 0000000..bd26f1d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rc4.d.ts @@ -0,0 +1,31 @@ + +/** + * RC4 stream cipher algorithm. + */ +export class RC4Algo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ +export const RC4: CipherObj; +/** + * Modified RC4 stream cipher algorithm. + */ +export class RC4DropAlgo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ +export const RC4Drop: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rc4.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rc4.js new file mode 100644 index 0000000..3357e17 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/rc4.js @@ -0,0 +1,119 @@ +import { + StreamCipher, +} from './cipher-core.js'; + +function generateKeystreamWord() { + // Shortcuts + const S = this._S; + let i = this._i; + let j = this._j; + + // Generate keystream word + let keystreamWord = 0; + for (let n = 0; n < 4; n += 1) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + const t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; +} + +/** + * RC4 stream cipher algorithm. + */ +export class RC4Algo extends StreamCipher { + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + const keySigBytes = key.sigBytes; + + // Init sbox + this._S = []; + const S = this._S; + for (let i = 0; i < 256; i += 1) { + S[i] = i; + } + + // Key setup + for (let i = 0, j = 0; i < 256; i += 1) { + const keyByteIndex = i % keySigBytes; + const keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + const t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._j = 0; + this._i = this._j; + } + + _doProcessBlock(M, offset) { + const _M = M; + + _M[offset] ^= generateKeystreamWord.call(this); + } +} +RC4Algo.keySize = 256 / 32; +RC4Algo.ivSize = 0; + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ +export const RC4 = StreamCipher._createHelper(RC4Algo); + +/** + * Modified RC4 stream cipher algorithm. + */ +export class RC4DropAlgo extends RC4Algo { + constructor(...args) { + super(...args); + + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + Object.assign(this.cfg, { drop: 192 }); + } + + _doReset() { + super._doReset.call(this); + + // Drop + for (let i = this.cfg.drop; i > 0; i -= 1) { + generateKeystreamWord.call(this); + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ +export const RC4Drop = StreamCipher._createHelper(RC4DropAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/ripemd160.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/ripemd160.d.ts new file mode 100644 index 0000000..3b479b8 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/ripemd160.d.ts @@ -0,0 +1,37 @@ +/** + * RIPEMD160 hash algorithm. + */ +export class RIPEMD160Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ +export const RIPEMD160: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ +export const HmacRIPEMD160: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/ripemd160.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/ripemd160.js new file mode 100644 index 0000000..c578def --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/ripemd160.js @@ -0,0 +1,242 @@ +/** @preserve +(c) 2012 by Cédric Mesnil. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import { + WordArray, + Hasher, +} from './core.js'; + +// Constants table +const _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); +const _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); +const _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]); +const _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]); + +const _hl = WordArray.create([0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); +const _hr = WordArray.create([0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + +const f1 = (x, y, z) => (x) ^ (y) ^ (z); + +const f2 = (x, y, z) => ((x) & (y)) | ((~x) & (z)); + +const f3 = (x, y, z) => ((x) | (~(y))) ^ (z); + +const f4 = (x, y, z) => ((x) & (z)) | ((y) & (~(z))); + +const f5 = (x, y, z) => (x) ^ ((y) | (~(z))); + +const rotl = (x, n) => (x << n) | (x >>> (32 - n)); + +/** + * RIPEMD160 hash algorithm. + */ +export class RIPEMD160Algo extends Hasher { + _doReset() { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Swap endian + for (let i = 0; i < 16; i += 1) { + // Shortcuts + const offset_i = offset + i; + const M_offset_i = _M[offset_i]; + + // Swap + _M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) + | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + const H = this._hash.words; + const hl = _hl.words; + const hr = _hr.words; + const zl = _zl.words; + const zr = _zr.words; + const sl = _sl.words; + const sr = _sr.words; + + // Working variables + let al = H[0]; + let bl = H[1]; + let cl = H[2]; + let dl = H[3]; + let el = H[4]; + let ar = H[0]; + let br = H[1]; + let cr = H[2]; + let dr = H[3]; + let er = H[4]; + + // Computation + let t; + for (let i = 0; i < 80; i += 1) { + t = (al + _M[offset + zl[i]]) | 0; + if (i < 16) { + t += f1(bl, cl, dl) + hl[0]; + } else if (i < 32) { + t += f2(bl, cl, dl) + hl[1]; + } else if (i < 48) { + t += f3(bl, cl, dl) + hl[2]; + } else if (i < 64) { + t += f4(bl, cl, dl) + hl[3]; + } else { // if (i<80) { + t += f5(bl, cl, dl) + hl[4]; + } + t |= 0; + t = rotl(t, sl[i]); + t = (t + el) | 0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + _M[offset + zr[i]]) | 0; + if (i < 16) { + t += f5(br, cr, dr) + hr[0]; + } else if (i < 32) { + t += f4(br, cr, dr) + hr[1]; + } else if (i < 48) { + t += f3(br, cr, dr) + hr[2]; + } else if (i < 64) { + t += f2(br, cr, dr) + hr[3]; + } else { // if (i<80) { + t += f1(br, cr, dr) + hr[4]; + } + t |= 0; + t = rotl(t, sr[i]); + t = (t + er) | 0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr) | 0; + H[1] = (H[2] + dl + er) | 0; + H[2] = (H[3] + el + ar) | 0; + H[3] = (H[4] + al + br) | 0; + H[4] = (H[0] + bl + cr) | 0; + H[0] = t; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) + | (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const hash = this._hash; + const H = hash.words; + + // Swap endian + for (let i = 0; i < 5; i += 1) { + // Shortcut + const H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) + | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ +export const RIPEMD160 = Hasher._createHelper(RIPEMD160Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ +export const HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha1.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha1.d.ts new file mode 100644 index 0000000..8d02a31 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha1.d.ts @@ -0,0 +1,37 @@ +/** + * SHA1 hash algorithm. + */ +export class SHA1Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ +export const SHA1: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ +export const HmacSHA1: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha1.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha1.js new file mode 100644 index 0000000..d831b8e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha1.js @@ -0,0 +1,128 @@ +import { + WordArray, + Hasher, +} from './core.js'; + +// Reusable object +const W = []; + +/** + * SHA-1 hash algorithm. + */ +export class SHA1Algo extends Hasher { + _doReset() { + this._hash = new WordArray([ + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + 0xc3d2e1f0, + ]); + } + + _doProcessBlock(M, offset) { + // Shortcut + const H = this._hash.words; + + // Working variables + let a = H[0]; + let b = H[1]; + let c = H[2]; + let d = H[3]; + let e = H[4]; + + // Computation + for (let i = 0; i < 80; i += 1) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + const n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + let t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ +export const SHA1 = Hasher._createHelper(SHA1Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ +export const HmacSHA1 = Hasher._createHmacHelper(SHA1Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha224.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha224.d.ts new file mode 100644 index 0000000..c0f8724 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha224.d.ts @@ -0,0 +1,37 @@ +/** + * SHA224 hash algorithm. + */ +export class SHA224Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ +export const SHA224: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ +export const HmacSHA224: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha224.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha224.js new file mode 100644 index 0000000..5a6cafc --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha224.js @@ -0,0 +1,60 @@ +import { WordArray } from './core.js'; +import { SHA256Algo } from './sha256.js'; + +/** + * SHA-224 hash algorithm. + */ +export class SHA224Algo extends SHA256Algo { + _doReset() { + this._hash = new WordArray([ + 0xc1059ed8, + 0x367cd507, + 0x3070dd17, + 0xf70e5939, + 0xffc00b31, + 0x68581511, + 0x64f98fa7, + 0xbefa4fa4, + ]); + } + + _doFinalize() { + const hash = super._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ +export const SHA224 = SHA256Algo._createHelper(SHA224Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ +export const HmacSHA224 = SHA256Algo._createHmacHelper(SHA224Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha256.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha256.d.ts new file mode 100644 index 0000000..782a702 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha256.d.ts @@ -0,0 +1,37 @@ +/** + * SHA256 hash algorithm. + */ +export class SHA256Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ +export const SHA256: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ +export const HmacSHA256: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha256.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha256.js new file mode 100644 index 0000000..2a13c4c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha256.js @@ -0,0 +1,171 @@ +import { + WordArray, + Hasher, +} from './core.js'; + +// Initialization and round constants tables +const H = []; +const K = []; + +// Compute constants +const isPrime = (n) => { + const sqrtN = Math.sqrt(n); + for (let factor = 2; factor <= sqrtN; factor += 1) { + if (!(n % factor)) { + return false; + } + } + + return true; +}; + +const getFractionalBits = n => ((n - (n | 0)) * 0x100000000) | 0; + +let n = 2; +let nPrime = 0; +while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(n ** (1 / 2)); + } + K[nPrime] = getFractionalBits(n ** (1 / 3)); + + nPrime += 1; + } + + n += 1; +} + +// Reusable object +const W = []; + +/** + * SHA-256 hash algorithm. + */ +export class SHA256Algo extends Hasher { + _doReset() { + this._hash = new WordArray(H.slice(0)); + } + + _doProcessBlock(M, offset) { + // Shortcut + const _H = this._hash.words; + + // Working variables + let a = _H[0]; + let b = _H[1]; + let c = _H[2]; + let d = _H[3]; + let e = _H[4]; + let f = _H[5]; + let g = _H[6]; + let h = _H[7]; + + // Computation + for (let i = 0; i < 64; i += 1) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + const gamma0x = W[i - 15]; + const gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) + ^ ((gamma0x << 14) | (gamma0x >>> 18)) + ^ (gamma0x >>> 3); + + const gamma1x = W[i - 2]; + const gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) + ^ ((gamma1x << 13) | (gamma1x >>> 19)) + ^ (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + const ch = (e & f) ^ (~e & g); + const maj = (a & b) ^ (a & c) ^ (b & c); + + const sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + const sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + const t1 = h + sigma1 + ch + K[i] + W[i]; + const t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + _H[0] = (_H[0] + a) | 0; + _H[1] = (_H[1] + b) | 0; + _H[2] = (_H[2] + c) | 0; + _H[3] = (_H[3] + d) | 0; + _H[4] = (_H[4] + e) | 0; + _H[5] = (_H[5] + f) | 0; + _H[6] = (_H[6] + g) | 0; + _H[7] = (_H[7] + h) | 0; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ +export const SHA256 = Hasher._createHelper(SHA256Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ +export const HmacSHA256 = Hasher._createHmacHelper(SHA256Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha3.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha3.d.ts new file mode 100644 index 0000000..4ed9f60 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha3.d.ts @@ -0,0 +1,37 @@ +/** + * SHA3 hash algorithm. + */ +export class SHA3Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ +export const SHA3: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ +export const HmacSHA3: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha3.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha3.js new file mode 100644 index 0000000..488446d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha3.js @@ -0,0 +1,295 @@ +import { + WordArray, + Hasher, +} from './core.js'; +import { X64Word } from './x64-core.js'; + +// Constants tables +const RHO_OFFSETS = []; +const PI_INDEXES = []; +const ROUND_CONSTANTS = []; + +// Compute Constants +// Compute rho offset constants +let _x = 1; +let _y = 0; +for (let t = 0; t < 24; t += 1) { + RHO_OFFSETS[_x + 5 * _y] = ((t + 1) * (t + 2) / 2) % 64; + + const newX = _y % 5; + const newY = (2 * _x + 3 * _y) % 5; + _x = newX; + _y = newY; +} + +// Compute pi index constants +for (let x = 0; x < 5; x += 1) { + for (let y = 0; y < 5; y += 1) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } +} + +// Compute round constants +let LFSR = 0x01; +for (let i = 0; i < 24; i += 1) { + let roundConstantMsw = 0; + let roundConstantLsw = 0; + + for (let j = 0; j < 7; j += 1) { + if (LFSR & 0x01) { + const bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); +} + +// Reusable objects for temporary values +const T = []; +for (let i = 0; i < 25; i += 1) { + T[i] = X64Word.create(); +} + +/** + * SHA-3 hash algorithm. + */ +export class SHA3Algo extends Hasher { + constructor(cfg) { + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + super(Object.assign( + { outputLength: 512 }, + cfg, + )); + } + + _doReset() { + this._state = []; + const state = this._state; + for (let i = 0; i < 25; i += 1) { + state[i] = new X64Word(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + } + + _doProcessBlock(M, offset) { + // Shortcuts + const state = this._state; + const nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (let i = 0; i < nBlockSizeLanes; i += 1) { + // Shortcuts + let M2i = M[offset + 2 * i]; + let M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) + | (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00); + M2i1 = (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) + | (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00); + + // Absorb message into state + const lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (let round = 0; round < 24; round += 1) { + // Theta + for (let x = 0; x < 5; x += 1) { + // Mix column lanes + let tMsw = 0; + let tLsw = 0; + for (let y = 0; y < 5; y += 1) { + const lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + const Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (let x = 0; x < 5; x += 1) { + // Shortcuts + const Tx4 = T[(x + 4) % 5]; + const Tx1 = T[(x + 1) % 5]; + const Tx1Msw = Tx1.high; + const Tx1Lsw = Tx1.low; + + // Mix surrounding columns + const tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + const tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (let y = 0; y < 5; y += 1) { + const lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (let laneIndex = 1; laneIndex < 25; laneIndex += 1) { + let tMsw; + let tLsw; + + // Shortcuts + const lane = state[laneIndex]; + const laneMsw = lane.high; + const laneLsw = lane.low; + const rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + const TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + const T0 = T[0]; + const state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (let x = 0; x < 5; x += 1) { + for (let y = 0; y < 5; y += 1) { + // Shortcuts + const laneIndex = x + 5 * y; + const lane = state[laneIndex]; + const TLane = T[laneIndex]; + const Tx1Lane = T[((x + 1) % 5) + 5 * y]; + const Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + const lane = state[0]; + const roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low; + } + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + const nBitsLeft = data.sigBytes * 8; + const blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - (nBitsLeft % 32)); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const state = this._state; + const outputLengthBytes = this.cfg.outputLength / 8; + const outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + const hashWords = []; + for (let i = 0; i < outputLengthLanes; i += 1) { + // Shortcuts + const lane = state[i]; + let laneMsw = lane.high; + let laneLsw = lane.low; + + // Swap endian + laneMsw = (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) + | (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00); + laneLsw = (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) + | (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray(hashWords, outputLengthBytes); + } + + clone() { + const clone = super.clone.call(this); + + clone._state = this._state.slice(0); + const state = clone._state; + for (let i = 0; i < 25; i += 1) { + state[i] = state[i].clone(); + } + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ +export const SHA3 = Hasher._createHelper(SHA3Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ +export const HmacSHA3 = Hasher._createHmacHelper(SHA3Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha384.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha384.d.ts new file mode 100644 index 0000000..e386048 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha384.d.ts @@ -0,0 +1,37 @@ +/** + * SHA384 hash algorithm. + */ +export class SHA384Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ +export const SHA384: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ +export const HmacSHA384: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha384.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha384.js new file mode 100644 index 0000000..9b96a0b --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha384.js @@ -0,0 +1,63 @@ +import { + X64Word, + X64WordArray, +} from './x64-core.js'; +import { SHA512Algo } from './sha512.js'; + +/** + * SHA-384 hash algorithm. + */ +export class SHA384Algo extends SHA512Algo { + _doReset() { + this._hash = new X64WordArray([ + new X64Word(0xcbbb9d5d, 0xc1059ed8), + new X64Word(0x629a292a, 0x367cd507), + new X64Word(0x9159015a, 0x3070dd17), + new X64Word(0x152fecd8, 0xf70e5939), + new X64Word(0x67332667, 0xffc00b31), + new X64Word(0x8eb44a87, 0x68581511), + new X64Word(0xdb0c2e0d, 0x64f98fa7), + new X64Word(0x47b5481d, 0xbefa4fa4), + ]); + } + + _doFinalize() { + const hash = super._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ +export const SHA384 = SHA512Algo._createHelper(SHA384Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ +export const HmacSHA384 = SHA512Algo._createHmacHelper(SHA384Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha512.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha512.d.ts new file mode 100644 index 0000000..d75cb39 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha512.d.ts @@ -0,0 +1,37 @@ +/** + * SHA512 hash algorithm. + */ +export class SHA512Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ +export const SHA512: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ +export const HmacSHA512: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha512.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha512.js new file mode 100644 index 0000000..738804d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/sha512.js @@ -0,0 +1,369 @@ +import { Hasher } from './core.js'; +import { + X64Word, + X64WordArray, +} from './x64-core.js'; + +// Constants +const K = [ + new X64Word(0x428a2f98, 0xd728ae22), + new X64Word(0x71374491, 0x23ef65cd), + new X64Word(0xb5c0fbcf, 0xec4d3b2f), + new X64Word(0xe9b5dba5, 0x8189dbbc), + new X64Word(0x3956c25b, 0xf348b538), + new X64Word(0x59f111f1, 0xb605d019), + new X64Word(0x923f82a4, 0xaf194f9b), + new X64Word(0xab1c5ed5, 0xda6d8118), + new X64Word(0xd807aa98, 0xa3030242), + new X64Word(0x12835b01, 0x45706fbe), + new X64Word(0x243185be, 0x4ee4b28c), + new X64Word(0x550c7dc3, 0xd5ffb4e2), + new X64Word(0x72be5d74, 0xf27b896f), + new X64Word(0x80deb1fe, 0x3b1696b1), + new X64Word(0x9bdc06a7, 0x25c71235), + new X64Word(0xc19bf174, 0xcf692694), + new X64Word(0xe49b69c1, 0x9ef14ad2), + new X64Word(0xefbe4786, 0x384f25e3), + new X64Word(0x0fc19dc6, 0x8b8cd5b5), + new X64Word(0x240ca1cc, 0x77ac9c65), + new X64Word(0x2de92c6f, 0x592b0275), + new X64Word(0x4a7484aa, 0x6ea6e483), + new X64Word(0x5cb0a9dc, 0xbd41fbd4), + new X64Word(0x76f988da, 0x831153b5), + new X64Word(0x983e5152, 0xee66dfab), + new X64Word(0xa831c66d, 0x2db43210), + new X64Word(0xb00327c8, 0x98fb213f), + new X64Word(0xbf597fc7, 0xbeef0ee4), + new X64Word(0xc6e00bf3, 0x3da88fc2), + new X64Word(0xd5a79147, 0x930aa725), + new X64Word(0x06ca6351, 0xe003826f), + new X64Word(0x14292967, 0x0a0e6e70), + new X64Word(0x27b70a85, 0x46d22ffc), + new X64Word(0x2e1b2138, 0x5c26c926), + new X64Word(0x4d2c6dfc, 0x5ac42aed), + new X64Word(0x53380d13, 0x9d95b3df), + new X64Word(0x650a7354, 0x8baf63de), + new X64Word(0x766a0abb, 0x3c77b2a8), + new X64Word(0x81c2c92e, 0x47edaee6), + new X64Word(0x92722c85, 0x1482353b), + new X64Word(0xa2bfe8a1, 0x4cf10364), + new X64Word(0xa81a664b, 0xbc423001), + new X64Word(0xc24b8b70, 0xd0f89791), + new X64Word(0xc76c51a3, 0x0654be30), + new X64Word(0xd192e819, 0xd6ef5218), + new X64Word(0xd6990624, 0x5565a910), + new X64Word(0xf40e3585, 0x5771202a), + new X64Word(0x106aa070, 0x32bbd1b8), + new X64Word(0x19a4c116, 0xb8d2d0c8), + new X64Word(0x1e376c08, 0x5141ab53), + new X64Word(0x2748774c, 0xdf8eeb99), + new X64Word(0x34b0bcb5, 0xe19b48a8), + new X64Word(0x391c0cb3, 0xc5c95a63), + new X64Word(0x4ed8aa4a, 0xe3418acb), + new X64Word(0x5b9cca4f, 0x7763e373), + new X64Word(0x682e6ff3, 0xd6b2b8a3), + new X64Word(0x748f82ee, 0x5defb2fc), + new X64Word(0x78a5636f, 0x43172f60), + new X64Word(0x84c87814, 0xa1f0ab72), + new X64Word(0x8cc70208, 0x1a6439ec), + new X64Word(0x90befffa, 0x23631e28), + new X64Word(0xa4506ceb, 0xde82bde9), + new X64Word(0xbef9a3f7, 0xb2c67915), + new X64Word(0xc67178f2, 0xe372532b), + new X64Word(0xca273ece, 0xea26619c), + new X64Word(0xd186b8c7, 0x21c0c207), + new X64Word(0xeada7dd6, 0xcde0eb1e), + new X64Word(0xf57d4f7f, 0xee6ed178), + new X64Word(0x06f067aa, 0x72176fba), + new X64Word(0x0a637dc5, 0xa2c898a6), + new X64Word(0x113f9804, 0xbef90dae), + new X64Word(0x1b710b35, 0x131c471b), + new X64Word(0x28db77f5, 0x23047d84), + new X64Word(0x32caab7b, 0x40c72493), + new X64Word(0x3c9ebe0a, 0x15c9bebc), + new X64Word(0x431d67c4, 0x9c100d4c), + new X64Word(0x4cc5d4be, 0xcb3e42b6), + new X64Word(0x597f299c, 0xfc657e2a), + new X64Word(0x5fcb6fab, 0x3ad6faec), + new X64Word(0x6c44198c, 0x4a475817), +]; + +// Reusable objects +const W = []; +for (let i = 0; i < 80; i += 1) { + W[i] = new X64Word(); +} + +/** + * SHA-512 hash algorithm. + */ +export class SHA512Algo extends Hasher { + constructor() { + super(); + + this.blockSize = 1024 / 32; + } + + _doReset() { + this._hash = new X64WordArray([ + new X64Word(0x6a09e667, 0xf3bcc908), + new X64Word(0xbb67ae85, 0x84caa73b), + new X64Word(0x3c6ef372, 0xfe94f82b), + new X64Word(0xa54ff53a, 0x5f1d36f1), + new X64Word(0x510e527f, 0xade682d1), + new X64Word(0x9b05688c, 0x2b3e6c1f), + new X64Word(0x1f83d9ab, 0xfb41bd6b), + new X64Word(0x5be0cd19, 0x137e2179), + ]); + } + + _doProcessBlock(M, offset) { + // Shortcuts + const H = this._hash.words; + + const H0 = H[0]; + const H1 = H[1]; + const H2 = H[2]; + const H3 = H[3]; + const H4 = H[4]; + const H5 = H[5]; + const H6 = H[6]; + const H7 = H[7]; + + const H0h = H0.high; + let H0l = H0.low; + const H1h = H1.high; + let H1l = H1.low; + const H2h = H2.high; + let H2l = H2.low; + const H3h = H3.high; + let H3l = H3.low; + const H4h = H4.high; + let H4l = H4.low; + const H5h = H5.high; + let H5l = H5.low; + const H6h = H6.high; + let H6l = H6.low; + const H7h = H7.high; + let H7l = H7.low; + + // Working variables + let ah = H0h; + let al = H0l; + let bh = H1h; + let bl = H1l; + let ch = H2h; + let cl = H2l; + let dh = H3h; + let dl = H3l; + let eh = H4h; + let el = H4l; + let fh = H5h; + let fl = H5l; + let gh = H6h; + let gl = H6l; + let hh = H7h; + let hl = H7l; + + // Rounds + for (let i = 0; i < 80; i += 1) { + let Wil; + let Wih; + + // Shortcut + const Wi = W[i]; + + // Extend message + if (i < 16) { + Wi.high = M[offset + i * 2] | 0; + Wih = Wi.high; + Wi.low = M[offset + i * 2 + 1] | 0; + Wil = Wi.low; + } else { + // Gamma0 + const gamma0x = W[i - 15]; + const gamma0xh = gamma0x.high; + const gamma0xl = gamma0x.low; + const gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) + ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) + ^ (gamma0xh >>> 7); + const gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) + ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) + ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + const gamma1x = W[i - 2]; + const gamma1xh = gamma1x.high; + const gamma1xl = gamma1x.low; + const gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) + ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) + ^ (gamma1xh >>> 6); + const gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) + ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) + ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + const Wi7 = W[i - 7]; + const Wi7h = Wi7.high; + const Wi7l = Wi7.low; + + const Wi16 = W[i - 16]; + const Wi16h = Wi16.high; + const Wi16l = Wi16.low; + + Wil = gamma0l + Wi7l; + Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + Wil += gamma1l; + Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + Wil += Wi16l; + Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + const chh = (eh & fh) ^ (~eh & gh); + const chl = (el & fl) ^ (~el & gl); + const majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + const majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + const sigma0h = ((ah >>> 28) | (al << 4)) + ^ ((ah << 30) | (al >>> 2)) + ^ ((ah << 25) | (al >>> 7)); + const sigma0l = ((al >>> 28) | (ah << 4)) + ^ ((al << 30) | (ah >>> 2)) + ^ ((al << 25) | (ah >>> 7)); + const sigma1h = ((eh >>> 14) | (el << 18)) + ^ ((eh >>> 18) | (el << 14)) + ^ ((eh << 23) | (el >>> 9)); + const sigma1l = ((el >>> 14) | (eh << 18)) + ^ ((el >>> 18) | (eh << 14)) + ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + const Ki = K[i]; + const Kih = Ki.high; + const Kil = Ki.low; + + let t1l = hl + sigma1l; + let t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + t1l += chl; + t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + t1l += Kil; + t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + t1l += Wil; + t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + const t2l = sigma0l + majl; + const t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0.low = (H0l + al); + H0l = H0.low; + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1.low = (H1l + bl); + H1l = H1.low; + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2.low = (H2l + cl); + H2l = H2.low; + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3.low = (H3l + dl); + H3l = H3.low; + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4.low = (H4l + el); + H4l = H4.low; + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5.low = (H5l + fl); + H5l = H5.low; + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6.low = (H6l + gl); + H6l = H6.low; + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7.low = (H7l + hl); + H7l = H7.low; + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + const hash = this._hash.toX32(); + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ +export const SHA512 = Hasher._createHelper(SHA512Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ +export const HmacSHA512 = Hasher._createHmacHelper(SHA512Algo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/tripledes.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/tripledes.d.ts new file mode 100644 index 0000000..459f854 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/tripledes.d.ts @@ -0,0 +1,30 @@ +/** + * DES block cipher algorithm. + */ +export class DESAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ +export const DES: CipherObj; +/** + * Triple-DES block cipher algorithm. + */ +export class TripleDESAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ +export const TripleDES: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/tripledes.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/tripledes.js new file mode 100644 index 0000000..6d1c4e6 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/tripledes.js @@ -0,0 +1,766 @@ +import { + WordArray, +} from './core.js'; +import { + BlockCipher, +} from './cipher-core.js'; + +// Permuted Choice 1 constants +const PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4, +]; + +// Permuted Choice 2 constants +const PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32, +]; + +// Cumulative bit shift constants +const BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + +// SBOXes and round permutation constants +const SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002, + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000, + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100, + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040, + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080, + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008, + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001, + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800, + }, +]; + +// Masks that select the SBOX input +const SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f, +]; + +// Swap bits across the left and right words +function exchangeLR(offset, mask) { + const t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; +} + +function exchangeRL(offset, mask) { + const t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; +} + +/** + * DES block cipher algorithm. + */ +export class DESAlgo extends BlockCipher { + constructor(xformMode, key, cfg) { + super(xformMode, key, cfg); + + // blickSize is an instance field and should set in constructor. + // Both DESAlgo and TripleDESAlgo. + this.blockSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + + // Select 56 bits according to PC1 + const keyBits = []; + for (let i = 0; i < 56; i += 1) { + const keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - (keyBitPos % 32))) & 1; + } + + // Assemble 16 subkeys + this._subKeys = []; + const subKeys = this._subKeys; + for (let nSubKey = 0; nSubKey < 16; nSubKey += 1) { + // Create subkey + subKeys[nSubKey] = []; + const subKey = subKeys[nSubKey]; + + // Shortcut + const bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (let i = 0; i < 24; i += 1) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - (i % 6)); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] + |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] + << (31 - (i % 6)); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (let i = 1; i < 7; i += 1) { + subKey[i] >>>= ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + this._invSubKeys = []; + const invSubKeys = this._invSubKeys; + for (let i = 0; i < 16; i += 1) { + invSubKeys[i] = subKeys[15 - i]; + } + } + + encryptBlock(M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + } + + decryptBlock(M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + } + + _doCryptBlock(M, offset, subKeys) { + const _M = M; + + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (let round = 0; round < 16; round += 1) { + // Shortcuts + const subKey = subKeys[round]; + const lBlock = this._lBlock; + const rBlock = this._rBlock; + + // Feistel function + let f = 0; + for (let i = 0; i < 8; i += 1) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + const t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + _M[offset] = this._lBlock; + _M[offset + 1] = this._rBlock; + } +} +DESAlgo.keySize = 64 / 32; +DESAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ +export const DES = BlockCipher._createHelper(DESAlgo); + +/** + * Triple-DES block cipher algorithm. + */ +export class TripleDESAlgo extends BlockCipher { + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + // Make sure the key length is valid (64, 128 or >= 192 bit) + if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) { + throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.'); + } + + // Extend the key according to the keying options defined in 3DES standard + const key1 = keyWords.slice(0, 2); + const key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4); + const key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6); + + // Create DES instances + this._des1 = DESAlgo.createEncryptor(WordArray.create(key1)); + this._des2 = DESAlgo.createEncryptor(WordArray.create(key2)); + this._des3 = DESAlgo.createEncryptor(WordArray.create(key3)); + } + + encryptBlock(M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + } + + decryptBlock(M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + } +} +TripleDESAlgo.keySize = 192 / 32; +TripleDESAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ +export const TripleDES = BlockCipher._createHelper(TripleDESAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/x64-core.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/x64-core.d.ts new file mode 100644 index 0000000..09d0e48 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/x64-core.d.ts @@ -0,0 +1,73 @@ +/** + * A 64-bit word. + */ +export class X64Word extends Base { + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + static create(high: number, low: number): X64Word; + constructor(high: number, low: number); + high: number; + low: number; +} +/** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class X64WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + static create(words?: Array, sigBytes?: number): X64WordArray; + constructor(words?: Array, sigBytes?: number); + words: X64Word[]; + sigBytes: number; + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32(): WordArray; + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone(): X64WordArray; +} +import { Base } from './core.js'; +import { WordArray } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/x64-core.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/x64-core.js new file mode 100644 index 0000000..cee568d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/lib/x64-core.js @@ -0,0 +1,113 @@ +import { + Base, + WordArray, +} from './core.js'; + +const X32WordArray = WordArray; + +/** + * A 64-bit word. + */ +export class X64Word extends Base { + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + constructor(high, low) { + super(); + + this.high = high; + this.low = low; + } +} + +/** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class X64WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + constructor(words = [], sigBytes = words.length * 8) { + super(); + + this.words = words; + this.sigBytes = sigBytes; + } + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32() { + // Shortcuts + const x64Words = this.words; + const x64WordsLength = x64Words.length; + + // Convert + const x32Words = []; + for (let i = 0; i < x64WordsLength; i += 1) { + const x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + } + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone() { + const clone = super.clone.call(this); + + // Clone "words" array + clone.words = this.words.slice(0); + const { words } = clone; + + // Clone each X64Word object + const wordsLength = words.length; + for (let i = 0; i < wordsLength; i += 1) { + words[i] = words[i].clone(); + } + + return clone; + } +} diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/JSEncrypt.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/JSEncrypt.ts new file mode 100644 index 0000000..5f618a7 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/JSEncrypt.ts @@ -0,0 +1,220 @@ +import { b64tohex, hex2b64 } from "./lib/jsbn/base64"; +import { JSEncryptRSAKey } from "./JSEncryptRSAKey"; +const version = typeof process !== 'undefined' + ? process.env?.npm_package_version + : undefined; + +export interface IJSEncryptOptions { + default_key_size?: string; + default_public_exponent?: string; + log?: boolean; +} + +/** + * + * @param {Object} [options = {}] - An object to customize JSEncrypt behaviour + * possible parameters are: + * - default_key_size {number} default: 1024 the key size in bit + * - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent + * - log {boolean} default: false whether log warn/error or not + * @constructor + */ +export class JSEncrypt { + constructor(options: IJSEncryptOptions = {}) { + options = options || {}; + this.default_key_size = options.default_key_size + ? parseInt(options.default_key_size, 10) + : 1024; + this.default_public_exponent = options.default_public_exponent || "010001"; // 65537 default openssl public exponent for rsa key type + this.log = options.log || false; + // The private and public key. + this.key = null; + } + + private default_key_size: number; + private default_public_exponent: string; + private log: boolean; + private key: JSEncryptRSAKey; + public static version: string = version; + + /** + * Method to set the rsa key parameter (one method is enough to set both the public + * and the private key, since the private key contains the public key paramenters) + * Log a warning if logs are enabled + * @param {Object|string} key the pem encoded string or an object (with or without header/footer) + * @public + */ + public setKey(key: string) { + if (this.log && this.key) { + console.warn("A key was already set, overriding existing."); + } + this.key = new JSEncryptRSAKey(key); + } + + /** + * Proxy method for setKey, for api compatibility + * @see setKey + * @public + */ + public setPrivateKey(privkey: string) { + // Create the key. + this.setKey(privkey); + } + + /** + * Proxy method for setKey, for api compatibility + * @see setKey + * @public + */ + public setPublicKey(pubkey: string) { + // Sets the public key. + this.setKey(pubkey); + } + + /** + * Proxy method for RSAKey object's decrypt, decrypt the string using the private + * components of the rsa key object. Note that if the object was not set will be created + * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor + * @param {string} str base64 encoded crypted string to decrypt + * @return {string} the decrypted string + * @public + */ + public decrypt(str: string) { + // Return the decrypted string. + try { + return this.getKey().decrypt(b64tohex(str)); + } catch (ex) { + return false; + } + } + + /** + * Proxy method for RSAKey object's encrypt, encrypt the string using the public + * components of the rsa key object. Note that if the object was not set will be created + * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor + * @param {string} str the string to encrypt + * @return {string} the encrypted string encoded in base64 + * @public + */ + public encrypt(str: string) { + // Return the encrypted string. + try { + return hex2b64(this.getKey().encrypt(str)); + } catch (ex) { + return false; + } + } + + /** + * Proxy method for RSAKey object's sign. + * @param {string} str the string to sign + * @param {function} digestMethod hash method + * @param {string} digestName the name of the hash algorithm + * @return {string} the signature encoded in base64 + * @public + */ + public sign( + str: string, + digestMethod: (str: string) => string, + digestName: string, + ): string | false { + // return the RSA signature of 'str' in 'hex' format. + try { + return hex2b64(this.getKey().sign(str, digestMethod, digestName)); + } catch (ex) { + return false; + } + } + + /** + * Proxy method for RSAKey object's verify. + * @param {string} str the string to verify + * @param {string} signature the signature encoded in base64 to compare the string to + * @param {function} digestMethod hash method + * @return {boolean} whether the data and signature match + * @public + */ + public verify( + str: string, + signature: string, + digestMethod: (str: string) => string, + ): boolean { + // Return the decrypted 'digest' of the signature. + try { + return this.getKey().verify(str, b64tohex(signature), digestMethod); + } catch (ex) { + return false; + } + } + + /** + * Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object + * will be created and returned + * @param {callback} [cb] the callback to be called if we want the key to be generated + * in an async fashion + * @returns {JSEncryptRSAKey} the JSEncryptRSAKey object + * @public + */ + public getKey(cb?: () => void) { + // Only create new if it does not exist. + if (!this.key) { + // Get a new private key. + this.key = new JSEncryptRSAKey(); + if (cb && {}.toString.call(cb) === "[object Function]") { + this.key.generateAsync( + this.default_key_size, + this.default_public_exponent, + cb, + ); + return; + } + // Generate the key. + this.key.generate(this.default_key_size, this.default_public_exponent); + } + return this.key; + } + + /** + * Returns the pem encoded representation of the private key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the private key WITH header and footer + * @public + */ + public getPrivateKey() { + // Return the private representation of this key. + return this.getKey().getPrivateKey(); + } + + /** + * Returns the pem encoded representation of the private key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the private key WITHOUT header and footer + * @public + */ + public getPrivateKeyB64() { + // Return the private representation of this key. + return this.getKey().getPrivateBaseKeyB64(); + } + + /** + * Returns the pem encoded representation of the public key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the public key WITH header and footer + * @public + */ + public getPublicKey() { + // Return the private representation of this key. + return this.getKey().getPublicKey(); + } + + /** + * Returns the pem encoded representation of the public key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the public key WITHOUT header and footer + * @public + */ + public getPublicKeyB64() { + // Return the private representation of this key. + return this.getKey().getPublicBaseKeyB64(); + } +} diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/JSEncryptRSAKey.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/JSEncryptRSAKey.ts new file mode 100644 index 0000000..10ca569 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/JSEncryptRSAKey.ts @@ -0,0 +1,324 @@ +import { hex2b64 } from "./lib/jsbn/base64"; +import { Hex } from "./lib/asn1js/hex"; +import { Base64 } from "./lib/asn1js/base64"; +import { ASN1 } from "./lib/asn1js/asn1"; +import { RSAKey } from "./lib/jsbn/rsa"; +import { parseBigInt } from "./lib/jsbn/jsbn"; +import { KJUR } from "./lib/jsrsasign/asn1-1.0"; + +/** + * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object. + * This object is just a decorator for parsing the key parameter + * @param {string|Object} key - The key in string format, or an object containing + * the parameters needed to build a RSAKey object. + * @constructor + */ +export class JSEncryptRSAKey extends RSAKey { + constructor(key?: string) { + super(); + // Call the super constructor. + // RSAKey.call(this); + // If a key key was provided. + if (key) { + // If this is a string... + if (typeof key === "string") { + this.parseKey(key); + } else if ( + JSEncryptRSAKey.hasPrivateKeyProperty(key) || + JSEncryptRSAKey.hasPublicKeyProperty(key) + ) { + // Set the values for the key. + this.parsePropertiesFrom(key); + } + } + } + + /** + * Method to parse a pem encoded string containing both a public or private key. + * The method will translate the pem encoded string in a der encoded string and + * will parse private key and public key parameters. This method accepts public key + * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1). + * + * @todo Check how many rsa formats use the same format of pkcs #1. + * + * The format is defined as: + * PublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * PublicKey BIT STRING + * } + * Where AlgorithmIdentifier is: + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm + * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) + * } + * and PublicKey is a SEQUENCE encapsulated in a BIT STRING + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + * it's possible to examine the structure of the keys obtained from openssl using + * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/ + * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer + * @private + */ + public parseKey(pem: string) { + try { + let modulus: string | number = 0; + let public_exponent: string | number = 0; + const reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/; + const der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem); + let asn1 = ASN1.decode(der); + + // Fixes a bug with OpenSSL 1.0+ private keys + if (asn1.sub.length === 3) { + asn1 = asn1.sub[2].sub[0]; + } + if (asn1.sub.length === 9) { + // Parse the private key. + modulus = asn1.sub[1].getHexStringValue(); // bigint + this.n = parseBigInt(modulus, 16); + + public_exponent = asn1.sub[2].getHexStringValue(); // int + this.e = parseInt(public_exponent, 16); + + const private_exponent = asn1.sub[3].getHexStringValue(); // bigint + this.d = parseBigInt(private_exponent, 16); + + const prime1 = asn1.sub[4].getHexStringValue(); // bigint + this.p = parseBigInt(prime1, 16); + + const prime2 = asn1.sub[5].getHexStringValue(); // bigint + this.q = parseBigInt(prime2, 16); + + const exponent1 = asn1.sub[6].getHexStringValue(); // bigint + this.dmp1 = parseBigInt(exponent1, 16); + + const exponent2 = asn1.sub[7].getHexStringValue(); // bigint + this.dmq1 = parseBigInt(exponent2, 16); + + const coefficient = asn1.sub[8].getHexStringValue(); // bigint + this.coeff = parseBigInt(coefficient, 16); + } else if (asn1.sub.length === 2) { + if (asn1.sub[0].sub) { + // Parse ASN.1 SubjectPublicKeyInfo type as defined by X.509 + var bit_string = asn1.sub[1]; + var sequence = bit_string.sub[0]; + modulus = sequence.sub[0].getHexStringValue(); + this.n = parseBigInt(modulus, 16); + public_exponent = sequence.sub[1].getHexStringValue(); + this.e = parseInt(public_exponent, 16); + } else { + // Parse ASN.1 RSAPublicKey type as defined by PKCS #1 + modulus = asn1.sub[0].getHexStringValue(); + this.n = parseBigInt(modulus, 16); + public_exponent = asn1.sub[1].getHexStringValue(); + this.e = parseInt(public_exponent, 16); + } + } else { + return false; + } + return true; + } catch (ex) { + return false; + } + } + + /** + * Translate rsa parameters in a hex encoded string representing the rsa key. + * + * The translation follow the ASN.1 notation : + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * @returns {string} DER Encoded String representing the rsa private key + * @private + */ + public getPrivateBaseKey() { + const options = { + array: [ + new KJUR.asn1.DERInteger({ int: 0 }), + new KJUR.asn1.DERInteger({ bigint: this.n }), + new KJUR.asn1.DERInteger({ int: this.e }), + new KJUR.asn1.DERInteger({ bigint: this.d }), + new KJUR.asn1.DERInteger({ bigint: this.p }), + new KJUR.asn1.DERInteger({ bigint: this.q }), + new KJUR.asn1.DERInteger({ bigint: this.dmp1 }), + new KJUR.asn1.DERInteger({ bigint: this.dmq1 }), + new KJUR.asn1.DERInteger({ bigint: this.coeff }), + ], + }; + const seq = new KJUR.asn1.DERSequence(options); + return seq.getEncodedHex(); + } + + /** + * base64 (pem) encoded version of the DER encoded representation + * @returns {string} pem encoded representation without header and footer + * @public + */ + public getPrivateBaseKeyB64() { + return hex2b64(this.getPrivateBaseKey()); + } + + /** + * Translate rsa parameters in a hex encoded string representing the rsa public key. + * The representation follow the ASN.1 notation : + * PublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * PublicKey BIT STRING + * } + * Where AlgorithmIdentifier is: + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm + * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) + * } + * and PublicKey is a SEQUENCE encapsulated in a BIT STRING + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + * @returns {string} DER Encoded String representing the rsa public key + * @private + */ + public getPublicBaseKey() { + const first_sequence = new KJUR.asn1.DERSequence({ + array: [ + new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.1" }), // RSA Encryption pkcs #1 oid + new KJUR.asn1.DERNull(), + ], + }); + + const second_sequence = new KJUR.asn1.DERSequence({ + array: [ + new KJUR.asn1.DERInteger({ bigint: this.n }), + new KJUR.asn1.DERInteger({ int: this.e }), + ], + }); + + const bit_string = new KJUR.asn1.DERBitString({ + hex: "00" + second_sequence.getEncodedHex(), + }); + + const seq = new KJUR.asn1.DERSequence({ + array: [first_sequence, bit_string], + }); + return seq.getEncodedHex(); + } + + /** + * base64 (pem) encoded version of the DER encoded representation + * @returns {string} pem encoded representation without header and footer + * @public + */ + public getPublicBaseKeyB64() { + return hex2b64(this.getPublicBaseKey()); + } + + /** + * wrap the string in block of width chars. The default value for rsa keys is 64 + * characters. + * @param {string} str the pem encoded string without header and footer + * @param {Number} [width=64] - the length the string has to be wrapped at + * @returns {string} + * @private + */ + public static wordwrap(str: string, width?: number) { + width = width || 64; + if (!str) { + return str; + } + const regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})"; + return str.match(RegExp(regex, "g")).join("\n"); + } + + /** + * Retrieve the pem encoded private key + * @returns {string} the pem encoded private key with header/footer + * @public + */ + public getPrivateKey() { + let key = "-----BEGIN RSA PRIVATE KEY-----\n"; + key += JSEncryptRSAKey.wordwrap(this.getPrivateBaseKeyB64()) + "\n"; + key += "-----END RSA PRIVATE KEY-----"; + return key; + } + + /** + * Retrieve the pem encoded public key + * @returns {string} the pem encoded public key with header/footer + * @public + */ + public getPublicKey() { + let key = "-----BEGIN PUBLIC KEY-----\n"; + key += JSEncryptRSAKey.wordwrap(this.getPublicBaseKeyB64()) + "\n"; + key += "-----END PUBLIC KEY-----"; + return key; + } + + /** + * Check if the object contains the necessary parameters to populate the rsa modulus + * and public exponent parameters. + * @param {Object} [obj={}] - An object that may contain the two public key + * parameters + * @returns {boolean} true if the object contains both the modulus and the public exponent + * properties (n and e) + * @todo check for types of n and e. N should be a parseable bigInt object, E should + * be a parseable integer number + * @private + */ + public static hasPublicKeyProperty(obj: object) { + obj = obj || {}; + return obj.hasOwnProperty("n") && obj.hasOwnProperty("e"); + } + + /** + * Check if the object contains ALL the parameters of an RSA key. + * @param {Object} [obj={}] - An object that may contain nine rsa key + * parameters + * @returns {boolean} true if the object contains all the parameters needed + * @todo check for types of the parameters all the parameters but the public exponent + * should be parseable bigint objects, the public exponent should be a parseable integer number + * @private + */ + public static hasPrivateKeyProperty(obj: object) { + obj = obj || {}; + return ( + obj.hasOwnProperty("n") && + obj.hasOwnProperty("e") && + obj.hasOwnProperty("d") && + obj.hasOwnProperty("p") && + obj.hasOwnProperty("q") && + obj.hasOwnProperty("dmp1") && + obj.hasOwnProperty("dmq1") && + obj.hasOwnProperty("coeff") + ); + } + + /** + * Parse the properties of obj in the current rsa object. Obj should AT LEAST + * include the modulus and public exponent (n, e) parameters. + * @param {Object} obj - the object containing rsa parameters + * @private + */ + public parsePropertiesFrom(obj: any) { + this.n = obj.n; + this.e = obj.e; + + if (obj.hasOwnProperty("d")) { + this.d = obj.d; + this.p = obj.p; + this.q = obj.q; + this.dmp1 = obj.dmp1; + this.dmq1 = obj.dmq1; + this.coeff = obj.coeff; + } + } +} diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/LICENSE.txt new file mode 100644 index 0000000..89ac13f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/LICENSE.txt @@ -0,0 +1,19 @@ +The MIT License (MIT) +Copyright (c) 2015 Form.io + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/index.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/index.ts new file mode 100644 index 0000000..9c50867 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/index.ts @@ -0,0 +1,3 @@ +import { JSEncrypt } from './JSEncrypt'; +export { JSEncrypt } +export default JSEncrypt; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/LICENSE.txt new file mode 100644 index 0000000..6d61d73 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/LICENSE.txt @@ -0,0 +1,16 @@ + + +ASN.1 JavaScript decoder +Copyright (c) 2008-2013 Lapo Luchini + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +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. \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/asn1.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/asn1.ts new file mode 100644 index 0000000..7331026 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/asn1.ts @@ -0,0 +1,598 @@ +// ASN.1 JavaScript decoder +// Copyright (c) 2008-2014 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ +/*global oids */ + +import {Int10} from "./int10"; + +const ellipsis = "\u2026"; +const reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; +const reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; + +function stringCut(str:string, len:number) { + if (str.length > len) { + str = str.substring(0, len) + ellipsis; + } + return str; +} + +export class Stream { + constructor(enc:Stream|number[], pos?:number) { + if (enc instanceof Stream) { + this.enc = enc.enc; + this.pos = enc.pos; + } else { + // enc should be an array or a binary string + this.enc = enc; + this.pos = pos; + } + } + + private enc:string|number[]; + public pos:number; + + public get(pos?:number) { + if (pos === undefined) { + pos = this.pos++; + } + if (pos >= this.enc.length) { + throw new Error(`Requesting byte offset ${pos} on a stream of length ${this.enc.length}`); + } + return ("string" === typeof this.enc) ? this.enc.charCodeAt(pos) : this.enc[pos]; + } + + public hexDigits = "0123456789ABCDEF"; + + public hexByte(b:number) { + return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF); + } + + public hexDump(start:number, end:number, raw:boolean) { + let s = ""; + for (let i = start; i < end; ++i) { + s += this.hexByte(this.get(i)); + if (raw !== true) { + switch (i & 0xF) { + case 0x7: + s += " "; + break; + case 0xF: + s += "\n"; + break; + default: + s += " "; + } + } + } + return s; + } + + public isASCII(start:number, end:number) { + for (let i = start; i < end; ++i) { + const c = this.get(i); + if (c < 32 || c > 176) { + return false; + } + } + return true; + } + + public parseStringISO(start:number, end:number) { + let s = ""; + for (let i = start; i < end; ++i) { + s += String.fromCharCode(this.get(i)); + } + return s; + } + + public parseStringUTF(start:number, end:number) { + let s = ""; + for (let i = start; i < end;) { + const c = this.get(i++); + if (c < 128) { + s += String.fromCharCode(c); + } else if ((c > 191) && (c < 224)) { + s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F)); + } else { + s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F)); + } + } + return s; + } + + public parseStringBMP(start:number, end:number) { + let str = ""; + let hi; + let lo; + for (let i = start; i < end;) { + hi = this.get(i++); + lo = this.get(i++); + str += String.fromCharCode((hi << 8) | lo); + } + return str; + } + + public parseTime(start:number, end:number, shortYear:boolean) { + let s = this.parseStringISO(start, end); + const m:Array = (shortYear ? reTimeS : reTimeL).exec(s); + if (!m) { + return "Unrecognized time: " + s; + } + if (shortYear) { + // to avoid querying the timer, use the fixed range [1970, 2069] + // it will conform with ITU X.400 [-10, +40] sliding window until 2030 + m[1] = +m[1]; + (m[1] as number) += (+m[1] < 70) ? 2000 : 1900; + } + s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4]; + if (m[5]) { + s += ":" + m[5]; + if (m[6]) { + s += ":" + m[6]; + if (m[7]) { + s += "." + m[7]; + } + } + } + if (m[8]) { + s += " UTC"; + if (m[8] != "Z") { + s += m[8]; + if (m[9]) { + s += ":" + m[9]; + } + } + } + return s; + } + + public parseInteger(start:number, end:number) { + let v = this.get(start); + const neg = (v > 127); + const pad = neg ? 255 : 0; + let len; + let s:string | number = ""; + // skip unuseful bits (not allowed in DER) + while (v == pad && ++start < end) { + v = this.get(start); + } + len = end - start; + if (len === 0) { + return neg ? -1 : 0; + } + // show bit length of huge integers + if (len > 4) { + s = v; + len <<= 3; + while (((+s ^ pad) & 0x80) == 0) { + s = +s << 1; + --len; + } + s = "(" + len + " bit)\n"; + } + // decode the integer + if (neg) { + v = v - 256; + } + const n = new Int10(v); + for (let i = start + 1; i < end; ++i) { + n.mulAdd(256, this.get(i)); + } + return s + n.toString(); + } + + public parseBitString(start:number, end:number, maxLength:number) { + const unusedBit = this.get(start); + const lenBit = ((end - start - 1) << 3) - unusedBit; + const intro = "(" + lenBit + " bit)\n"; + let s = ""; + for (let i = start + 1; i < end; ++i) { + const b = this.get(i); + const skip = (i == end - 1) ? unusedBit : 0; + for (let j = 7; j >= skip; --j) { + s += (b >> j) & 1 ? "1" : "0"; + } + if (s.length > maxLength) { + return intro + stringCut(s, maxLength); + } + } + return intro + s; + } + + public parseOctetString(start:number, end:number, maxLength:number) { + if (this.isASCII(start, end)) { + return stringCut(this.parseStringISO(start, end), maxLength); + } + const len = end - start; + let s = "(" + len + " byte)\n"; + maxLength /= 2; // we work in bytes + if (len > maxLength) { + end = start + maxLength; + } + for (let i = start; i < end; ++i) { + s += this.hexByte(this.get(i)); + } + if (len > maxLength) { + s += ellipsis; + } + return s; + } + + public parseOID(start:number, end:number, maxLength:number) { + let s = ""; + let n:number|Int10 = new Int10(); + let bits = 0; + for (let i = start; i < end; ++i) { + const v = this.get(i); + n.mulAdd(128, v & 0x7F); + bits += 7; + if (!(v & 0x80)) { // finished + if (s === "") { + n = n.simplify(); + if (n instanceof Int10) { + n.sub(80); + s = "2." + n.toString(); + } else { + const m = n < 80 ? n < 40 ? 0 : 1 : 2; + s = m + "." + (n - m * 40); + } + } else { + s += "." + n.toString(); + } + if (s.length > maxLength) { + return stringCut(s, maxLength); + } + n = new Int10(); + bits = 0; + } + } + if (bits > 0) { + s += ".incomplete"; + } + return s; + } +} +export class ASN1 { + constructor(stream:Stream, header:number, length:number, tag:ASN1Tag, sub:ASN1[]) { + if (!(tag instanceof ASN1Tag)) { + throw new Error("Invalid tag value."); + } + this.stream = stream; + this.header = header; + this.length = length; + this.tag = tag; + this.sub = sub; + } + + private stream:Stream; + private header:number; + private length:number; + private tag:ASN1Tag; + public sub:ASN1[]; + + public typeName() { + switch (this.tag.tagClass) { + case 0: // universal + switch (this.tag.tagNumber) { + case 0x00: + return "EOC"; + case 0x01: + return "BOOLEAN"; + case 0x02: + return "INTEGER"; + case 0x03: + return "BIT_STRING"; + case 0x04: + return "OCTET_STRING"; + case 0x05: + return "NULL"; + case 0x06: + return "OBJECT_IDENTIFIER"; + case 0x07: + return "ObjectDescriptor"; + case 0x08: + return "EXTERNAL"; + case 0x09: + return "REAL"; + case 0x0A: + return "ENUMERATED"; + case 0x0B: + return "EMBEDDED_PDV"; + case 0x0C: + return "UTF8String"; + case 0x10: + return "SEQUENCE"; + case 0x11: + return "SET"; + case 0x12: + return "NumericString"; + case 0x13: + return "PrintableString"; // ASCII subset + case 0x14: + return "TeletexString"; // aka T61String + case 0x15: + return "VideotexString"; + case 0x16: + return "IA5String"; // ASCII + case 0x17: + return "UTCTime"; + case 0x18: + return "GeneralizedTime"; + case 0x19: + return "GraphicString"; + case 0x1A: + return "VisibleString"; // ASCII subset + case 0x1B: + return "GeneralString"; + case 0x1C: + return "UniversalString"; + case 0x1E: + return "BMPString"; + } + return "Universal_" + this.tag.tagNumber.toString(); + case 1: + return "Application_" + this.tag.tagNumber.toString(); + case 2: + return "[" + this.tag.tagNumber.toString() + "]"; // Context + case 3: + return "Private_" + this.tag.tagNumber.toString(); + } + } + + public content(maxLength:number) { // a preview of the content (intended for humans) + if (this.tag === undefined) { + return null; + } + if (maxLength === undefined) { + maxLength = Infinity; + } + const content = this.posContent(); + const len = Math.abs(this.length); + if (!this.tag.isUniversal()) { + if (this.sub !== null) { + return "(" + this.sub.length + " elem)"; + } + return this.stream.parseOctetString(content, content + len, maxLength); + } + switch (this.tag.tagNumber) { + case 0x01: // BOOLEAN + return (this.stream.get(content) === 0) ? "false" : "true"; + case 0x02: // INTEGER + return this.stream.parseInteger(content, content + len); + case 0x03: // BIT_STRING + return this.sub ? "(" + this.sub.length + " elem)" : + this.stream.parseBitString(content, content + len, maxLength); + case 0x04: // OCTET_STRING + return this.sub ? "(" + this.sub.length + " elem)" : + this.stream.parseOctetString(content, content + len, maxLength); + // case 0x05: // NULL + case 0x06: // OBJECT_IDENTIFIER + return this.stream.parseOID(content, content + len, maxLength); + // case 0x07: // ObjectDescriptor + // case 0x08: // EXTERNAL + // case 0x09: // REAL + // case 0x0A: // ENUMERATED + // case 0x0B: // EMBEDDED_PDV + case 0x10: // SEQUENCE + case 0x11: // SET + if (this.sub !== null) { + return "(" + this.sub.length + " elem)"; + } else { + return "(no elem)"; + } + case 0x0C: // UTF8String + return stringCut(this.stream.parseStringUTF(content, content + len), maxLength); + case 0x12: // NumericString + case 0x13: // PrintableString + case 0x14: // TeletexString + case 0x15: // VideotexString + case 0x16: // IA5String + // case 0x19: // GraphicString + case 0x1A: // VisibleString + // case 0x1B: // GeneralString + // case 0x1C: // UniversalString + return stringCut(this.stream.parseStringISO(content, content + len), maxLength); + case 0x1E: // BMPString + return stringCut(this.stream.parseStringBMP(content, content + len), maxLength); + case 0x17: // UTCTime + case 0x18: // GeneralizedTime + return this.stream.parseTime(content, content + len, (this.tag.tagNumber == 0x17)); + } + return null; + } + + public toString() { + return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? "null" : this.sub.length) + "]"; + } + + public toPrettyString(indent:string) { + if (indent === undefined) { + indent = ""; + } + let s = indent + this.typeName() + " @" + this.stream.pos; + if (this.length >= 0) { + s += "+"; + } + s += this.length; + if (this.tag.tagConstructed) { + s += " (constructed)"; + } else if ((this.tag.isUniversal() && ((this.tag.tagNumber == 0x03) || (this.tag.tagNumber == 0x04))) && (this.sub !== null)) { + s += " (encapsulates)"; + } + s += "\n"; + if (this.sub !== null) { + indent += " "; + for (let i = 0, max = this.sub.length; i < max; ++i) { + s += this.sub[i].toPrettyString(indent); + } + } + return s; + } + + public posStart() { + return this.stream.pos; + } + + public posContent() { + return this.stream.pos + this.header; + } + + public posEnd() { + return this.stream.pos + this.header + Math.abs(this.length); + } + + public toHexString() { + return this.stream.hexDump(this.posStart(), this.posEnd(), true); + } + + public static decodeLength(stream:Stream):number { + let buf = stream.get(); + const len = buf & 0x7F; + if (len == buf) { + return len; + } + + // no reason to use Int10, as it would be a huge buffer anyways + if (len > 6) { + throw new Error("Length over 48 bits not supported at position " + (stream.pos - 1)); + } + if (len === 0) { + return null; + } // undefined + buf = 0; + for (let i = 0; i < len; ++i) { + buf = (buf * 256) + stream.get(); + } + return buf; + } + + /** + * Retrieve the hexadecimal value (as a string) of the current ASN.1 element + * @returns {string} + * @public + */ + public getHexStringValue():string { + const hexString = this.toHexString(); + const offset = this.header * 2; + const length = this.length * 2; + return hexString.substr(offset, length); + } + + public static decode(str:Stream|number[]) { + let stream:Stream; + + if (!(str instanceof Stream)) { + stream = new Stream(str, 0); + } else { + stream = str; + } + + const streamStart = new Stream(stream); + const tag = new ASN1Tag(stream); + let len = ASN1.decodeLength(stream); + const start = stream.pos; + const header = start - streamStart.pos; + let sub = null; + const getSub:() => ASN1[] = function () { + const ret = []; + if (len !== null) { + // definite length + const end = start + len; + while (stream.pos < end) { + ret[ret.length] = ASN1.decode(stream); + } + if (stream.pos != end) { + throw new Error("Content size is not correct for container starting at offset " + start); + } + } else { + // undefined length + try { + for (; ;) { + const s = ASN1.decode(stream); + if (s.tag.isEOC()) { + break; + } + ret[ret.length] = s; + } + len = start - stream.pos; // undefined lengths are represented as negative values + } catch (e) { + throw new Error("Exception while decoding undefined length content: " + e); + } + } + + return ret; + }; + if (tag.tagConstructed) { + // must have valid content + sub = getSub(); + } else if (tag.isUniversal() && ((tag.tagNumber == 0x03) || (tag.tagNumber == 0x04))) { + // sometimes BitString and OctetString are used to encapsulate ASN.1 + try { + if (tag.tagNumber == 0x03) { + if (stream.get() != 0) { + throw new Error("BIT STRINGs with unused bits cannot encapsulate."); + } + } + sub = getSub(); + for (let i = 0; i < sub.length; ++i) { + if (sub[i].tag.isEOC()) { + throw new Error("EOC is not supposed to be actual content."); + } + } + } catch (e) { + // but silently ignore when they don't + sub = null; + } + } + if (sub === null) { + if (len === null) { + throw new Error("We can't skip over an invalid tag with undefined length at offset " + start); + } + stream.pos = start + Math.abs(len); + } + return new ASN1(streamStart, header, len, tag, sub); + } +} + + +export class ASN1Tag { + constructor(stream:Stream) { + let buf = stream.get(); + this.tagClass = buf >> 6; + this.tagConstructed = ((buf & 0x20) !== 0); + this.tagNumber = buf & 0x1F; + if (this.tagNumber == 0x1F) { // long tag + const n = new Int10(); + do { + buf = stream.get(); + n.mulAdd(128, buf & 0x7F); + } while (buf & 0x80); + this.tagNumber = n.simplify(); + } + } + + public tagClass:number; + public tagConstructed:boolean; + public tagNumber:number | Int10; + + public isUniversal() { + return this.tagClass === 0x00; + } + + public isEOC() { + return this.tagClass === 0x00 && this.tagNumber === 0x00; + } +} diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/base64.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/base64.ts new file mode 100644 index 0000000..3a3f2aa --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/base64.ts @@ -0,0 +1,87 @@ +// Base64 JavaScript decoder +// Copyright (c) 2008-2013 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ +let decoder:{ [index:string]:number | string }; +export const Base64 = { + decode(a:string) { + let i; + if (decoder === undefined) { + const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const ignore = "= \f\n\r\t\u00A0\u2028\u2029"; + decoder = Object.create(null); + for (i = 0; i < 64; ++i) { + decoder[b64.charAt(i)] = i; + } + decoder['-'] = 62;//+ + decoder['_'] = 63;//- + for (i = 0; i < ignore.length; ++i) { + decoder[ignore.charAt(i)] = -1; + } + } + const out = []; + let bits = 0; + let char_count = 0; + for (i = 0; i < a.length; ++i) { + let c:string|number = a.charAt(i); + if (c == "=") { + break; + } + c = decoder[c]; + if (c == -1) { + continue; + } + if (c === undefined) { + throw new Error("Illegal character at offset " + i); + } + bits |= c as number; + if (++char_count >= 4) { + out[out.length] = (bits >> 16); + out[out.length] = (bits >> 8) & 0xFF; + out[out.length] = bits & 0xFF; + bits = 0; + char_count = 0; + } else { + bits <<= 6; + } + } + switch (char_count) { + case 1: + throw new Error("Base64 encoding incomplete: at least 2 bits missing"); + case 2: + out[out.length] = (bits >> 10); + break; + case 3: + out[out.length] = (bits >> 16); + out[out.length] = (bits >> 8) & 0xFF; + break; + } + return out; + }, + re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/, + unarmor(a:string):number[] { + const m = Base64.re.exec(a); + if (m) { + if (m[1]) { + a = m[1]; + } else if (m[2]) { + a = m[2]; + } else { + throw new Error("RegExp out of sync"); + } + } + return Base64.decode(a); + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/hex.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/hex.ts new file mode 100644 index 0000000..5bc6aa9 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/hex.ts @@ -0,0 +1,66 @@ +// Hex JavaScript decoder +// Copyright (c) 2008-2013 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ + +let decoder:{ [index:string]:number }; +export const Hex = { + decode(a:string):number[] { + let i; + if (decoder === undefined) { + let hex = "0123456789ABCDEF"; + const ignore = " \f\n\r\t\u00A0\u2028\u2029"; + decoder = {}; + for (i = 0; i < 16; ++i) { + decoder[hex.charAt(i)] = i; + } + hex = hex.toLowerCase(); + for (i = 10; i < 16; ++i) { + decoder[hex.charAt(i)] = i; + } + for (i = 0; i < ignore.length; ++i) { + decoder[ignore.charAt(i)] = -1; + } + } + const out = []; + let bits = 0; + let char_count = 0; + for (i = 0; i < a.length; ++i) { + let c:number|string = a.charAt(i); + if (c == "=") { + break; + } + c = decoder[c]; + if (c == -1) { + continue; + } + if (c === undefined) { + throw new Error("Illegal character at offset " + i); + } + bits |= c; + if (++char_count >= 2) { + out[out.length] = bits; + bits = 0; + char_count = 0; + } else { + bits <<= 4; + } + } + if (char_count) { + throw new Error("Hex encoding incomplete: 4 bits missing"); + } + return out; + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/int10.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/int10.ts new file mode 100644 index 0000000..7f9dd0f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/int10.ts @@ -0,0 +1,97 @@ +// Big integer base-10 printing library +// Copyright (c) 2014 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ + + +const max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256 + +export class Int10 { + constructor(value?:string | number) { + this.buf = [+value || 0]; + } + + + public mulAdd(m:number, c:number) { + // assert(m <= 256) + const b = this.buf; + const l = b.length; + let i; + let t; + for (i = 0; i < l; ++i) { + t = b[i] * m + c; + if (t < max) { + c = 0; + } else { + c = 0 | (t / max); + t -= c * max; + } + b[i] = t; + } + if (c > 0) { + b[i] = c; + } + } + + public sub(c:number) { + // assert(m <= 256) + const b = this.buf; + const l = b.length; + let i; + let t; + for (i = 0; i < l; ++i) { + t = b[i] - c; + if (t < 0) { + t += max; + c = 1; + } else { + c = 0; + } + b[i] = t; + } + while (b[b.length - 1] === 0) { + b.pop(); + } + } + + public toString(base?:number) { + if ((base || 10) != 10) { + throw new Error("only base 10 is supported"); + } + const b = this.buf; + let s = b[b.length - 1].toString(); + for (let i = b.length - 2; i >= 0; --i) { + s += (max + b[i]).toString().substring(1); + } + return s; + } + + public valueOf() { + const b = this.buf; + let v = 0; + for (let i = b.length - 1; i >= 0; --i) { + v = v * max + b[i]; + } + return v; + } + + public simplify() { + const b = this.buf; + return (b.length == 1) ? b[0] : this; + } + + private buf:number[]; +} + diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/oids.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/oids.ts new file mode 100644 index 0000000..b418cfa --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/asn1js/oids.ts @@ -0,0 +1,1962 @@ +// Converted from: http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg +// which is made by Peter Gutmann and whose license states: +// You can use this code in whatever way you want, +// as long as you don't try to claim you wrote it. +export const oids = { +"0.2.262.1.10": { "d": "Telesec", "c": "Deutsche Telekom", "w": false }, +"0.2.262.1.10.0": { "d": "extension", "c": "Telesec", "w": false }, +"0.2.262.1.10.1": { "d": "mechanism", "c": "Telesec", "w": false }, +"0.2.262.1.10.1.0": { "d": "authentication", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.0.1": { "d": "passwordAuthentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.2": { "d": "protectedPasswordAuthentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.3": { "d": "oneWayX509Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.4": { "d": "twoWayX509Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.5": { "d": "threeWayX509Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.6": { "d": "oneWayISO9798Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.7": { "d": "twoWayISO9798Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.8": { "d": "telekomAuthentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.1": { "d": "signature", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.1": { "d": "md4WithRSAAndISO9697", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.2": { "d": "md4WithRSAAndTelesecSignatureStandard", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.3": { "d": "md5WithRSAAndISO9697", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.4": { "d": "md5WithRSAAndTelesecSignatureStandard", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.5": { "d": "ripemd160WithRSAAndTelekomSignatureStandard", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.9": { "d": "hbciRsaSignature", "c": "Telesec signature", "w": false }, +"0.2.262.1.10.1.2": { "d": "encryption", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.2.0": { "d": "none", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.1": { "d": "rsaTelesec", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2": { "d": "des", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.1": { "d": "desECB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.2": { "d": "desCBC", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.3": { "d": "desOFB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.4": { "d": "desCFB8", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.5": { "d": "desCFB64", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3": { "d": "des3", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.1": { "d": "des3ECB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.2": { "d": "des3CBC", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.3": { "d": "des3OFB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.4": { "d": "des3CFB8", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.5": { "d": "des3CFB64", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.4": { "d": "magenta", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5": { "d": "idea", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.1": { "d": "ideaECB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.2": { "d": "ideaCBC", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.3": { "d": "ideaOFB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.4": { "d": "ideaCFB8", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.5": { "d": "ideaCFB64", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.3": { "d": "oneWayFunction", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.3.1": { "d": "md4", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.2": { "d": "md5", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.3": { "d": "sqModNX509", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.4": { "d": "sqModNISO", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.5": { "d": "ripemd128", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.6": { "d": "hashUsingBlockCipher", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.7": { "d": "mac", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.8": { "d": "ripemd160", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.4": { "d": "fecFunction", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.4.1": { "d": "reedSolomon", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.2": { "d": "module", "c": "Telesec", "w": false }, +"0.2.262.1.10.2.0": { "d": "algorithms", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.1": { "d": "attributeTypes", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.2": { "d": "certificateTypes", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.3": { "d": "messageTypes", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.4": { "d": "plProtocol", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.5": { "d": "smeAndComponentsOfSme", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.6": { "d": "fec", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.7": { "d": "usefulDefinitions", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.8": { "d": "stefiles", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.9": { "d": "sadmib", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.10": { "d": "electronicOrder", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.11": { "d": "telesecTtpAsymmetricApplication", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.12": { "d": "telesecTtpBasisApplication", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.13": { "d": "telesecTtpMessages", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.14": { "d": "telesecTtpTimeStampApplication", "c": "Telesec module", "w": false }, +"0.2.262.1.10.3": { "d": "objectClass", "c": "Telesec", "w": false }, +"0.2.262.1.10.3.0": { "d": "telesecOtherName", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.1": { "d": "directory", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.2": { "d": "directoryType", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.3": { "d": "directoryGroup", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.4": { "d": "directoryUser", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.5": { "d": "symmetricKeyEntry", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.4": { "d": "package", "c": "Telesec", "w": false }, +"0.2.262.1.10.5": { "d": "parameter", "c": "Telesec", "w": false }, +"0.2.262.1.10.6": { "d": "nameBinding", "c": "Telesec", "w": false }, +"0.2.262.1.10.7": { "d": "attribute", "c": "Telesec", "w": false }, +"0.2.262.1.10.7.0": { "d": "applicationGroupIdentifier", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.1": { "d": "certificateType", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.2": { "d": "telesecCertificate", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.3": { "d": "certificateNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.4": { "d": "certificateRevocationList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.5": { "d": "creationDate", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.6": { "d": "issuer", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.7": { "d": "namingAuthority", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.8": { "d": "publicKeyDirectory", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.9": { "d": "securityDomain", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.10": { "d": "subject", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.11": { "d": "timeOfRevocation", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.12": { "d": "userGroupReference", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.13": { "d": "validity", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.14": { "d": "zert93", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.15": { "d": "securityMessEnv", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.16": { "d": "anonymizedPublicKeyDirectory", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.17": { "d": "telesecGivenName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.18": { "d": "nameAdditions", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.19": { "d": "telesecPostalCode", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.20": { "d": "nameDistinguisher", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.21": { "d": "telesecCertificateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.22": { "d": "teletrustCertificateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.23": { "d": "x509CertificateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.24": { "d": "timeOfIssue", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.25": { "d": "physicalCardNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.26": { "d": "fileType", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.27": { "d": "ctlFileIsArchive", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.28": { "d": "emailAddress", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.29": { "d": "certificateTemplateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.30": { "d": "directoryName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.31": { "d": "directoryTypeName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.32": { "d": "directoryGroupName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.33": { "d": "directoryUserName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.34": { "d": "revocationFlag", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.35": { "d": "symmetricKeyEntryName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.36": { "d": "glNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.37": { "d": "goNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.38": { "d": "gKeyData", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.39": { "d": "zKeyData", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.40": { "d": "ktKeyData", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.41": { "d": "ktKeyNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.51": { "d": "timeOfRevocationGen", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.52": { "d": "liabilityText", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.8": { "d": "attributeGroup", "c": "Telesec", "w": false }, +"0.2.262.1.10.9": { "d": "action", "c": "Telesec", "w": false }, +"0.2.262.1.10.10": { "d": "notification", "c": "Telesec", "w": false }, +"0.2.262.1.10.11": { "d": "snmp-mibs", "c": "Telesec", "w": false }, +"0.2.262.1.10.11.1": { "d": "securityApplication", "c": "Telesec SNMP MIBs", "w": false }, +"0.2.262.1.10.12": { "d": "certAndCrlExtensionDefinitions", "c": "Telesec", "w": false }, +"0.2.262.1.10.12.0": { "d": "liabilityLimitationFlag", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.1": { "d": "telesecCertIdExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.2": { "d": "Telesec policyIdentifier", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.3": { "d": "telesecPolicyQualifierID", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.4": { "d": "telesecCRLFilteredExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.5": { "d": "telesecCRLFilterExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.6": { "d": "telesecNamingAuthorityExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.4.0.127.0.7": { "d": "bsi", "c": "BSI TR-03110/TR-03111", "w": false }, +"0.4.0.127.0.7.1": { "d": "bsiEcc", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1": { "d": "bsifieldType", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.1": { "d": "bsiPrimeField", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2": { "d": "bsiCharacteristicTwoField", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3": { "d": "bsiCharacteristicTwoBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3.1": { "d": "bsiGnBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3.2": { "d": "bsiTpBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3.3": { "d": "bsiPpBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1": { "d": "bsiEcdsaSignatures", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.1": { "d": "bsiEcdsaWithSHA1", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.2": { "d": "bsiEcdsaWithSHA224", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.3": { "d": "bsiEcdsaWithSHA256", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.4": { "d": "bsiEcdsaWithSHA384", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.5": { "d": "bsiEcdsaWithSHA512", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.6": { "d": "bsiEcdsaWithRIPEMD160", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.2": { "d": "bsiEcKeyType", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.2.1": { "d": "bsiEcPublicKey", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.5.1": { "d": "bsiKaeg", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.5.1.1": { "d": "bsiKaegWithX963KDF", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.5.1.2": { "d": "bsiKaegWith3DESKDF", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.2.2.1": { "d": "bsiPK", "c": "BSI TR-03110. Formerly known as bsiCA, now moved to ...2.2.3.x", "w": false }, +"0.4.0.127.0.7.2.2.1.1": { "d": "bsiPK_DH", "c": "BSI TR-03110. Formerly known as bsiCA_DH, now moved to ...2.2.3.x", "w": false }, +"0.4.0.127.0.7.2.2.1.2": { "d": "bsiPK_ECDH", "c": "BSI TR-03110. Formerly known as bsiCA_ECDH, now moved to ...2.2.3.x", "w": false }, +"0.4.0.127.0.7.2.2.2": { "d": "bsiTA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1": { "d": "bsiTA_RSA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.1": { "d": "bsiTA_RSAv1_5_SHA1", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.2": { "d": "bsiTA_RSAv1_5_SHA256", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.3": { "d": "bsiTA_RSAPSS_SHA1", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.4": { "d": "bsiTA_RSAPSS_SHA256", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2": { "d": "bsiTA_ECDSA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2.1": { "d": "bsiTA_ECDSA_SHA1", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2.2": { "d": "bsiTA_ECDSA_SHA224", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2.3": { "d": "bsiTA_ECDSA_SHA256", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.3": { "d": "bsiCA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.3.1": { "d": "bsiCA_DH", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.3.2": { "d": "bsiCA_ECDH", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.3.1.2.1": { "d": "bsiRoleEAC", "c": "BSI TR-03110", "w": false }, +"0.4.0.1862": { "d": "etsiQcsProfile", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1": { "d": "etsiQcs", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.1": { "d": "etsiQcsCompliance", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.2": { "d": "etsiQcsLimitValue", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.3": { "d": "etsiQcsRetentionPeriod", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.4": { "d": "etsiQcsQcSSCD", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.9.2342.19200300.100.1.1": { "d": "userID", "c": "Some oddball X.500 attribute collection", "w": false }, +"0.9.2342.19200300.100.1.3": { "d": "rfc822Mailbox", "c": "Some oddball X.500 attribute collection", "w": false }, +"0.9.2342.19200300.100.1.25": { "d": "domainComponent", "c": "Men are from Mars, this OID is from Pluto", "w": false }, +"1.0.10118.3.0.49": { "d": "ripemd160", "c": "ISO 10118-3 hash function", "w": false }, +"1.0.10118.3.0.50": { "d": "ripemd128", "c": "ISO 10118-3 hash function", "w": false }, +"1.0.10118.3.0.55": { "d": "whirlpool", "c": "ISO 10118-3 hash function", "w": false }, +"1.2.36.1.3.1.1.1": { "d": "qgpki", "c": "Queensland Government PKI", "w": false }, +"1.2.36.1.3.1.1.1.1": { "d": "qgpkiPolicies", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.1.1": { "d": "qgpkiMedIntermedCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.1": { "d": "qgpkiMedIntermedIndividual", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.2": { "d": "qgpkiMedIntermedDeviceControl", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.3": { "d": "qgpkiMedIntermedDevice", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.4": { "d": "qgpkiMedIntermedAuthorisedParty", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.5": { "d": "qgpkiMedIntermedDeviceSystem", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2": { "d": "qgpkiMedIssuingCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.1": { "d": "qgpkiMedIssuingIndividual", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.2": { "d": "qgpkiMedIssuingDeviceControl", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.3": { "d": "qgpkiMedIssuingDevice", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.4": { "d": "qgpkiMedIssuingAuthorisedParty", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.5": { "d": "qgpkiMedIssuingClientAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.6": { "d": "qgpkiMedIssuingServerAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.7": { "d": "qgpkiMedIssuingDataProt", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.8": { "d": "qgpkiMedIssuingTokenAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.3": { "d": "qgpkiBasicIntermedCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.3.1": { "d": "qgpkiBasicIntermedDeviceSystem", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4": { "d": "qgpkiBasicIssuingCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4.1": { "d": "qgpkiBasicIssuingClientAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4.2": { "d": "qgpkiBasicIssuingServerAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4.3": { "d": "qgpkiBasicIssuingDataSigning", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.2": { "d": "qgpkiAssuranceLevel", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.1": { "d": "qgpkiAssuranceRudimentary", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.2": { "d": "qgpkiAssuranceBasic", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.3": { "d": "qgpkiAssuranceMedium", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.4": { "d": "qgpkiAssuranceHigh", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.3": { "d": "qgpkiCertFunction", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.1": { "d": "qgpkiFunctionIndividual", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.2": { "d": "qgpkiFunctionDevice", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.3": { "d": "qgpkiFunctionAuthorisedParty", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.4": { "d": "qgpkiFunctionDeviceControl", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.2": { "d": "qpspki", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1": { "d": "qpspkiPolicies", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1.2": { "d": "qpspkiPolicyBasic", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1.3": { "d": "qpspkiPolicyMedium", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1.4": { "d": "qpspkiPolicyHigh", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.3.2": { "d": "qtmrpki", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.1": { "d": "qtmrpkiPolicies", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.2": { "d": "qtmrpkiPurpose", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.2.1": { "d": "qtmrpkiIndividual", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.2": { "d": "qtmrpkiDeviceControl", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.3": { "d": "qtmrpkiDevice", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.4": { "d": "qtmrpkiAuthorisedParty", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.5": { "d": "qtmrpkiDeviceSystem", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.3": { "d": "qtmrpkiDevice", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.3.1": { "d": "qtmrpkiDriverLicense", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.2": { "d": "qtmrpkiIndustryAuthority", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.3": { "d": "qtmrpkiMarineLicense", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.4": { "d": "qtmrpkiAdultProofOfAge", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.5": { "d": "qtmrpkiSam", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.4": { "d": "qtmrpkiAuthorisedParty", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.4.1": { "d": "qtmrpkiTransportInspector", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.2": { "d": "qtmrpkiPoliceOfficer", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.3": { "d": "qtmrpkiSystem", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.4": { "d": "qtmrpkiLiquorLicensingInspector", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.5": { "d": "qtmrpkiMarineEnforcementOfficer", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.333.1": { "d": "australianBusinessNumber", "c": "Australian Government corporate taxpayer ID", "w": false }, +"1.2.36.68980861.1.1.2": { "d": "signetPersonal", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.3": { "d": "signetBusiness", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.4": { "d": "signetLegal", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.10": { "d": "signetPilot", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.11": { "d": "signetIntraNet", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.20": { "d": "signetPolicy", "c": "Signet CA", "w": false }, +"1.2.36.75878867.1.100.1.1": { "d": "certificatesAustraliaPolicy", "c": "Certificates Australia CA", "w": false }, +"1.2.392.200011.61.1.1.1": { "d": "mitsubishiSecurityAlgorithm", "c": "Mitsubishi security algorithm", "w": false }, +"1.2.392.200011.61.1.1.1.1": { "d": "misty1-cbc", "c": "Mitsubishi security algorithm", "w": false }, +"1.2.410.200004.1": { "d": "kisaAlgorithm", "c": "KISA algorithm", "w": false }, +"1.2.410.200004.1.1": { "d": "kcdsa", "c": "Korean DSA", "w": false }, +"1.2.410.200004.1.2": { "d": "has160", "c": "Korean hash algorithm", "w": false }, +"1.2.410.200004.1.3": { "d": "seedECB", "c": "Korean SEED algorithm, ECB mode", "w": false }, +"1.2.410.200004.1.4": { "d": "seedCBC", "c": "Korean SEED algorithm, CBC mode", "w": false }, +"1.2.410.200004.1.5": { "d": "seedOFB", "c": "Korean SEED algorithm, OFB mode", "w": false }, +"1.2.410.200004.1.6": { "d": "seedCFB", "c": "Korean SEED algorithm, CFB mode", "w": false }, +"1.2.410.200004.1.7": { "d": "seedMAC", "c": "Korean SEED algorithm, MAC mode", "w": false }, +"1.2.410.200004.1.8": { "d": "kcdsaWithHAS160", "c": "Korean signature algorithm", "w": false }, +"1.2.410.200004.1.9": { "d": "kcdsaWithSHA1", "c": "Korean signature algorithm", "w": false }, +"1.2.410.200004.1.10": { "d": "pbeWithHAS160AndSEED-ECB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.11": { "d": "pbeWithHAS160AndSEED-CBC", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.12": { "d": "pbeWithHAS160AndSEED-CFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.13": { "d": "pbeWithHAS160AndSEED-OFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.14": { "d": "pbeWithSHA1AndSEED-ECB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.15": { "d": "pbeWithSHA1AndSEED-CBC", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.16": { "d": "pbeWithSHA1AndSEED-CFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.17": { "d": "pbeWithSHA1AndSEED-OFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.20": { "d": "rsaWithHAS160", "c": "Korean signature algorithm", "w": false }, +"1.2.410.200004.1.21": { "d": "kcdsa1", "c": "Korean DSA", "w": false }, +"1.2.410.200004.2": { "d": "npkiCP", "c": "KISA NPKI certificate policies", "w": false }, +"1.2.410.200004.2.1": { "d": "npkiSignaturePolicy", "c": "KISA NPKI certificate policies", "w": false }, +"1.2.410.200004.3": { "d": "npkiKP", "c": "KISA NPKI key usage", "w": false }, +"1.2.410.200004.4": { "d": "npkiAT", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.5": { "d": "npkiLCA", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.5.1": { "d": "npkiSignKorea", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.5.2": { "d": "npkiSignGate", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.5.3": { "d": "npkiNcaSign", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.6": { "d": "npkiON", "c": "KISA NPKI otherName", "w": false }, +"1.2.410.200004.7": { "d": "npkiAPP", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.7.1": { "d": "npkiSMIME", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.7.1.1": { "d": "npkiSMIMEAlgo", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.7.1.1.1": { "d": "npkiCmsSEEDWrap", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.10": { "d": "npki", "c": "KISA NPKI", "w": false }, +"1.2.410.200004.10.1": { "d": "npkiAttribute", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1": { "d": "npkiIdentifyData", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.1": { "d": "npkiVID", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.2": { "d": "npkiEncryptedVID", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.3": { "d": "npkiRandomNum", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.4": { "d": "npkiVID", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200046.1.1": { "d": "aria1AlgorithmModes", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.1": { "d": "aria128-ecb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.2": { "d": "aria128-cbc", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.3": { "d": "aria128-cfb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.4": { "d": "aria128-ofb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.5": { "d": "aria128-ctr", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.6": { "d": "aria192-ecb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.7": { "d": "aria192-cbc", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.8": { "d": "aria192-cfb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.9": { "d": "aria192-ofb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.10": { "d": "aria192-ctr", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.11": { "d": "aria256-ecb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.12": { "d": "aria256-cbc", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.13": { "d": "aria256-cfb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.21": { "d": "aria128-cmac", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.22": { "d": "aria192-cmac", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.23": { "d": "aria256-cmac", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.31": { "d": "aria128-ocb2", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.32": { "d": "aria192-ocb2", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.33": { "d": "aria256-ocb2", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.34": { "d": "aria128-gcm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.35": { "d": "aria192-gcm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.36": { "d": "aria256-gcm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.37": { "d": "aria128-ccm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.38": { "d": "aria192-ccm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.39": { "d": "aria256-ccm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.40": { "d": "aria128-keywrap", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.41": { "d": "aria192-keywrap", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.42": { "d": "aria256-keywrap", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.43": { "d": "aria128-keywrapWithPad", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.44": { "d": "aria192-keywrapWithPad", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.45": { "d": "aria256-keywrapWithPad", "c": "ARIA algorithm modes", "w": false }, +"1.2.643.2.2.3": { "d": "gostSignature", "c": "GOST R 34.10-2001 + GOST R 34.11-94 signature", "w": false }, +"1.2.643.2.2.4": { "d": "gost94Signature", "c": "GOST R 34.10-94 + GOST R 34.11-94 signature. Obsoleted by GOST R 34.10-2001", "w": true }, +"1.2.643.2.2.19": { "d": "gostPublicKey", "c": "GOST R 34.10-2001 (ECC) public key", "w": false }, +"1.2.643.2.2.20": { "d": "gost94PublicKey", "c": "GOST R 34.10-94 public key. Obsoleted by GOST R 34.10-2001", "w": true }, +"1.2.643.2.2.21": { "d": "gostCipher", "c": "GOST 28147-89 (symmetric key block cipher)", "w": false }, +"1.2.643.2.2.31.0": { "d": "testCipherParams", "c": "Test params for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.1": { "d": "cryptoProCipherA", "c": "CryptoPro params A for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.2": { "d": "cryptoProCipherB", "c": "CryptoPro params B for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.3": { "d": "cryptoProCipherC", "c": "CryptoPro params C for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.4": { "d": "cryptoProCipherD", "c": "CryptoPro params D for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.5": { "d": "oscar11Cipher", "c": "Oscar-1.1 params for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.6": { "d": "oscar10Cipher", "c": "Oscar-1.0 params for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.7": { "d": "ric1Cipher", "c": "RIC-1 params for GOST 28147-89", "w": false }, +"1.2.643.2.2.9": { "d": "gostDigest", "c": "GOST R 34.11-94 digest", "w": false }, +"1.2.643.2.2.30.0": { "d": "testDigestParams", "c": "Test params for GOST R 34.11-94", "w": false }, +"1.2.643.2.2.30.1": { "d": "cryptoProDigestA", "c": "CryptoPro digest params for GOST R 34.11-94", "w": false }, +"1.2.643.2.2.35.0": { "d": "testSignParams", "c": "Test elliptic curve for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.35.1": { "d": "cryptoProSignA", "c": "CryptoPro ell.curve A for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.35.2": { "d": "cryptoProSignB", "c": "CryptoPro ell.curve B for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.35.3": { "d": "cryptoProSignC", "c": "CryptoPro ell.curve C for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.36.0": { "d": "cryptoProSignXA", "c": "CryptoPro ell.curve XA for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.36.1": { "d": "cryptoProSignXB", "c": "CryptoPro ell.curve XB for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.14.0": { "d": "nullMeshing", "c": "Do not mesh state of GOST 28147-89 cipher", "w": false }, +"1.2.643.2.2.14.1": { "d": "cryptoProMeshing", "c": "CryptoPro meshing of state of GOST 28147-89 cipher", "w": false }, +"1.2.643.2.2.10": { "d": "hmacGost", "c": "HMAC with GOST R 34.11-94", "w": false }, +"1.2.643.2.2.13.0": { "d": "gostWrap", "c": "Wrap key using GOST 28147-89 key", "w": false }, +"1.2.643.2.2.13.1": { "d": "cryptoProWrap", "c": "Wrap key using diversified GOST 28147-89 key", "w": false }, +"1.2.643.2.2.96": { "d": "cryptoProECDHWrap", "c": "Wrap key using ECC DH on GOST R 34.10-2001 keys (VKO)", "w": false }, +"1.2.752.34.1": { "d": "seis-cp", "c": "SEIS Project", "w": false }, +"1.2.752.34.1.1": { "d": "SEIS high-assurance policyIdentifier", "c": "SEIS Project certificate policies", "w": false }, +"1.2.752.34.1.2": { "d": "SEIS GAK policyIdentifier", "c": "SEIS Project certificate policies", "w": false }, +"1.2.752.34.2": { "d": "SEIS pe", "c": "SEIS Project", "w": false }, +"1.2.752.34.3": { "d": "SEIS at", "c": "SEIS Project", "w": false }, +"1.2.752.34.3.1": { "d": "SEIS at-personalIdentifier", "c": "SEIS Project attribute", "w": false }, +"1.2.840.10040.1": { "d": "module", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.1.1": { "d": "x9f1-cert-mgmt", "c": "ANSI X9.57 module", "w": false }, +"1.2.840.10040.2": { "d": "holdinstruction", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.2.1": { "d": "holdinstruction-none", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.2.2": { "d": "callissuer", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.2.3": { "d": "reject", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.2.4": { "d": "pickupToken", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.3": { "d": "attribute", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.3.1": { "d": "countersignature", "c": "ANSI X9.57 attribute", "w": false }, +"1.2.840.10040.3.2": { "d": "attribute-cert", "c": "ANSI X9.57 attribute", "w": false }, +"1.2.840.10040.4": { "d": "algorithm", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.4.1": { "d": "dsa", "c": "ANSI X9.57 algorithm", "w": false }, +"1.2.840.10040.4.2": { "d": "dsa-match", "c": "ANSI X9.57 algorithm", "w": false }, +"1.2.840.10040.4.3": { "d": "dsaWithSha1", "c": "ANSI X9.57 algorithm", "w": false }, +"1.2.840.10045.1": { "d": "fieldType", "c": "ANSI X9.62. This OID is also assigned as ecdsa-with-SHA1", "w": false }, +"1.2.840.10045.1.1": { "d": "prime-field", "c": "ANSI X9.62 field type", "w": false }, +"1.2.840.10045.1.2": { "d": "characteristic-two-field", "c": "ANSI X9.62 field type", "w": false }, +"1.2.840.10045.1.2.3": { "d": "characteristic-two-basis", "c": "ANSI X9.62 field type", "w": false }, +"1.2.840.10045.1.2.3.1": { "d": "onBasis", "c": "ANSI X9.62 field basis", "w": false }, +"1.2.840.10045.1.2.3.2": { "d": "tpBasis", "c": "ANSI X9.62 field basis", "w": false }, +"1.2.840.10045.1.2.3.3": { "d": "ppBasis", "c": "ANSI X9.62 field basis", "w": false }, +"1.2.840.10045.2": { "d": "publicKeyType", "c": "ANSI X9.62", "w": false }, +"1.2.840.10045.2.1": { "d": "ecPublicKey", "c": "ANSI X9.62 public key type", "w": false }, +"1.2.840.10045.3.0.1": { "d": "c2pnb163v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.2": { "d": "c2pnb163v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.3": { "d": "c2pnb163v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.5": { "d": "c2tnb191v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.6": { "d": "c2tnb191v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.7": { "d": "c2tnb191v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.10": { "d": "c2pnb208w1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.11": { "d": "c2tnb239v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.12": { "d": "c2tnb239v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.13": { "d": "c2tnb239v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.16": { "d": "c2pnb272w1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.18": { "d": "c2tnb359v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.19": { "d": "c2pnb368w1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.20": { "d": "c2tnb431r1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.1": { "d": "prime192v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.2": { "d": "prime192v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.3": { "d": "prime192v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.4": { "d": "prime239v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.5": { "d": "prime239v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.6": { "d": "prime239v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.7": { "d": "prime256v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.4.1": { "d": "ecdsaWithSHA1", "c": "ANSI X9.62 ECDSA algorithm with SHA1", "w": false }, +"1.2.840.10045.4.2": { "d": "ecdsaWithRecommended", "c": "ANSI X9.62 ECDSA algorithm with Recommended", "w": false }, +"1.2.840.10045.4.3": { "d": "ecdsaWithSpecified", "c": "ANSI X9.62 ECDSA algorithm with Specified", "w": false }, +"1.2.840.10045.4.3.1": { "d": "ecdsaWithSHA224", "c": "ANSI X9.62 ECDSA algorithm with SHA224", "w": false }, +"1.2.840.10045.4.3.2": { "d": "ecdsaWithSHA256", "c": "ANSI X9.62 ECDSA algorithm with SHA256", "w": false }, +"1.2.840.10045.4.3.3": { "d": "ecdsaWithSHA384", "c": "ANSI X9.62 ECDSA algorithm with SHA384", "w": false }, +"1.2.840.10045.4.3.4": { "d": "ecdsaWithSHA512", "c": "ANSI X9.62 ECDSA algorithm with SHA512", "w": false }, +"1.2.840.10046.1": { "d": "fieldType", "c": "ANSI X9.42", "w": false }, +"1.2.840.10046.1.1": { "d": "gf-prime", "c": "ANSI X9.42 field type", "w": false }, +"1.2.840.10046.2": { "d": "numberType", "c": "ANSI X9.42", "w": false }, +"1.2.840.10046.2.1": { "d": "dhPublicKey", "c": "ANSI X9.42 number type", "w": false }, +"1.2.840.10046.3": { "d": "scheme", "c": "ANSI X9.42", "w": false }, +"1.2.840.10046.3.1": { "d": "dhStatic", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.2": { "d": "dhEphem", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.3": { "d": "dhHybrid1", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.4": { "d": "dhHybrid2", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.5": { "d": "mqv2", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.6": { "d": "mqv1", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10065.2.2": { "d": "?", "c": "ASTM 31.20", "w": false }, +"1.2.840.10065.2.3": { "d": "healthcareLicense", "c": "ASTM 31.20", "w": false }, +"1.2.840.10065.2.3.1.1": { "d": "license?", "c": "ASTM 31.20 healthcare license type", "w": false }, +"1.2.840.113533.7": { "d": "nsn", "c": "", "w": false }, +"1.2.840.113533.7.65": { "d": "nsn-ce", "c": "", "w": false }, +"1.2.840.113533.7.65.0": { "d": "entrustVersInfo", "c": "Nortel Secure Networks ce", "w": false }, +"1.2.840.113533.7.66": { "d": "nsn-alg", "c": "", "w": false }, +"1.2.840.113533.7.66.3": { "d": "cast3CBC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.10": { "d": "cast5CBC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.11": { "d": "cast5MAC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.12": { "d": "pbeWithMD5AndCAST5-CBC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.13": { "d": "passwordBasedMac", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.67": { "d": "nsn-oc", "c": "", "w": false }, +"1.2.840.113533.7.67.0": { "d": "entrustUser", "c": "Nortel Secure Networks oc", "w": false }, +"1.2.840.113533.7.68": { "d": "nsn-at", "c": "", "w": false }, +"1.2.840.113533.7.68.0": { "d": "entrustCAInfo", "c": "Nortel Secure Networks at", "w": false }, +"1.2.840.113533.7.68.10": { "d": "attributeCertificate", "c": "Nortel Secure Networks at", "w": false }, +"1.2.840.113549.1.1": { "d": "pkcs-1", "c": "", "w": false }, +"1.2.840.113549.1.1.1": { "d": "rsaEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.2": { "d": "md2WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.3": { "d": "md4WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.4": { "d": "md5WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.5": { "d": "sha1WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.7": { "d": "rsaOAEP", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.8": { "d": "pkcs1-MGF", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.9": { "d": "rsaOAEP-pSpecified", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.10": { "d": "rsaPSS", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.11": { "d": "sha256WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.12": { "d": "sha384WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.13": { "d": "sha512WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.14": { "d": "sha224WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.6": { "d": "rsaOAEPEncryptionSET", "c": "PKCS #1. This OID may also be assigned as ripemd160WithRSAEncryption", "w": false }, +"1.2.840.113549.1.2": { "d": "bsafeRsaEncr", "c": "Obsolete BSAFE OID", "w": true }, +"1.2.840.113549.1.3": { "d": "pkcs-3", "c": "", "w": false }, +"1.2.840.113549.1.3.1": { "d": "dhKeyAgreement", "c": "PKCS #3", "w": false }, +"1.2.840.113549.1.5": { "d": "pkcs-5", "c": "", "w": false }, +"1.2.840.113549.1.5.1": { "d": "pbeWithMD2AndDES-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.3": { "d": "pbeWithMD5AndDES-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.4": { "d": "pbeWithMD2AndRC2-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.6": { "d": "pbeWithMD5AndRC2-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.9": { "d": "pbeWithMD5AndXOR", "c": "PKCS #5, used in BSAFE only", "w": true }, +"1.2.840.113549.1.5.10": { "d": "pbeWithSHAAndDES-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.12": { "d": "pkcs5PBKDF2", "c": "PKCS #5 v2.0", "w": false }, +"1.2.840.113549.1.5.13": { "d": "pkcs5PBES2", "c": "PKCS #5 v2.0", "w": false }, +"1.2.840.113549.1.5.14": { "d": "pkcs5PBMAC1", "c": "PKCS #5 v2.0", "w": false }, +"1.2.840.113549.1.7": { "d": "pkcs-7", "c": "", "w": false }, +"1.2.840.113549.1.7.1": { "d": "data", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.2": { "d": "signedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.3": { "d": "envelopedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.4": { "d": "signedAndEnvelopedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.5": { "d": "digestedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.6": { "d": "encryptedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.7": { "d": "dataWithAttributes", "c": "PKCS #7 experimental", "w": true }, +"1.2.840.113549.1.7.8": { "d": "encryptedPrivateKeyInfo", "c": "PKCS #7 experimental", "w": true }, +"1.2.840.113549.1.9": { "d": "pkcs-9", "c": "", "w": false }, +"1.2.840.113549.1.9.1": { "d": "emailAddress", "c": "PKCS #9. Deprecated, use an altName extension instead", "w": false }, +"1.2.840.113549.1.9.2": { "d": "unstructuredName", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.3": { "d": "contentType", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.4": { "d": "messageDigest", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.5": { "d": "signingTime", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.6": { "d": "countersignature", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.7": { "d": "challengePassword", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.8": { "d": "unstructuredAddress", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.9": { "d": "extendedCertificateAttributes", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.10": { "d": "issuerAndSerialNumber", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.11": { "d": "passwordCheck", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.12": { "d": "publicKey", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.13": { "d": "signingDescription", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.14": { "d": "extensionRequest", "c": "PKCS #9 via CRMF", "w": false }, +"1.2.840.113549.1.9.15": { "d": "sMIMECapabilities", "c": "PKCS #9. This OID was formerly assigned as symmetricCapabilities, then reassigned as SMIMECapabilities, then renamed to the current name", "w": false }, +"1.2.840.113549.1.9.15.1": { "d": "preferSignedData", "c": "sMIMECapabilities", "w": false }, +"1.2.840.113549.1.9.15.2": { "d": "canNotDecryptAny", "c": "sMIMECapabilities", "w": false }, +"1.2.840.113549.1.9.15.3": { "d": "receiptRequest", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 1) instead", "w": true }, +"1.2.840.113549.1.9.15.4": { "d": "receipt", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 1 1) instead", "w": true }, +"1.2.840.113549.1.9.15.5": { "d": "contentHints", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 4) instead", "w": true }, +"1.2.840.113549.1.9.15.6": { "d": "mlExpansionHistory", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 3) instead", "w": true }, +"1.2.840.113549.1.9.16": { "d": "id-sMIME", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.16.0": { "d": "id-mod", "c": "id-sMIME", "w": false }, +"1.2.840.113549.1.9.16.0.1": { "d": "id-mod-cms", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.2": { "d": "id-mod-ess", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.3": { "d": "id-mod-oid", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.4": { "d": "id-mod-msg-v3", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.5": { "d": "id-mod-ets-eSignature-88", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.6": { "d": "id-mod-ets-eSignature-97", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.7": { "d": "id-mod-ets-eSigPolicy-88", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.8": { "d": "id-mod-ets-eSigPolicy-88", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.1": { "d": "contentType", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.1.1": { "d": "receipt", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.2": { "d": "authData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.3": { "d": "publishCert", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.4": { "d": "tSTInfo", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.5": { "d": "tDTInfo", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.6": { "d": "contentInfo", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.7": { "d": "dVCSRequestData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.8": { "d": "dVCSResponseData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.9": { "d": "compressedData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.10": { "d": "scvpCertValRequest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.11": { "d": "scvpCertValResponse", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.12": { "d": "scvpValPolRequest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.13": { "d": "scvpValPolResponse", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.14": { "d": "attrCertEncAttrs", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.15": { "d": "tSReq", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.16": { "d": "firmwarePackage", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.17": { "d": "firmwareLoadReceipt", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.18": { "d": "firmwareLoadError", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.19": { "d": "contentCollection", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.20": { "d": "contentWithAttrs", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.21": { "d": "encKeyWithID", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.22": { "d": "encPEPSI", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.23": { "d": "authEnvelopedData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.24": { "d": "routeOriginAttest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.25": { "d": "symmetricKeyPackage", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.26": { "d": "rpkiManifest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.27": { "d": "asciiTextWithCRLF", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.28": { "d": "xml", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.29": { "d": "pdf", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.30": { "d": "postscript", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.31": { "d": "timestampedData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.32": { "d": "asAdjacencyAttest", "c": "S/MIME Content Types", "w": true }, +"1.2.840.113549.1.9.16.1.33": { "d": "rpkiTrustAnchor", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.34": { "d": "trustAnchorList", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.2": { "d": "authenticatedAttributes", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.2.1": { "d": "receiptRequest", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.2": { "d": "securityLabel", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.3": { "d": "mlExpandHistory", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.4": { "d": "contentHint", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.5": { "d": "msgSigDigest", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.6": { "d": "encapContentType", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.7": { "d": "contentIdentifier", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.8": { "d": "macValue", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.9": { "d": "equivalentLabels", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.10": { "d": "contentReference", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.11": { "d": "encrypKeyPref", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.12": { "d": "signingCertificate", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.13": { "d": "smimeEncryptCerts", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.14": { "d": "timeStampToken", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.15": { "d": "sigPolicyId", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.16": { "d": "commitmentType", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.17": { "d": "signerLocation", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.18": { "d": "signerAttr", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.19": { "d": "otherSigCert", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.20": { "d": "contentTimestamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.21": { "d": "certificateRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.22": { "d": "revocationRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.23": { "d": "certValues", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.24": { "d": "revocationValues", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.25": { "d": "escTimeStamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.26": { "d": "certCRLTimestamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.27": { "d": "archiveTimeStamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.28": { "d": "signatureType", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.29": { "d": "dvcsDvc", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.30": { "d": "cekReference", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.31": { "d": "maxCEKDecrypts", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.32": { "d": "kekDerivationAlg", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.33": { "d": "intendedRecipients", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.34": { "d": "cmcUnsignedData", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.35": { "d": "fwPackageID", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.36": { "d": "fwTargetHardwareIDs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.37": { "d": "fwDecryptKeyID", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.38": { "d": "fwImplCryptAlgs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.39": { "d": "fwWrappedFirmwareKey", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.40": { "d": "fwCommunityIdentifiers", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.41": { "d": "fwPkgMessageDigest", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.42": { "d": "fwPackageInfo", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.43": { "d": "fwImplCompressAlgs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.44": { "d": "etsAttrCertificateRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.45": { "d": "etsAttrRevocationRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.46": { "d": "binarySigningTime", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.47": { "d": "signingCertificateV2", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.48": { "d": "etsArchiveTimeStampV2", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.49": { "d": "erInternal", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.50": { "d": "erExternal", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.51": { "d": "multipleSignatures", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.3.1": { "d": "esDHwith3DES", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.2": { "d": "esDHwithRC2", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.3": { "d": "3desWrap", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.4": { "d": "rc2Wrap", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.5": { "d": "esDH", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.6": { "d": "cms3DESwrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.7": { "d": "cmsRC2wrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.8": { "d": "zlib", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.9": { "d": "pwriKEK", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.10": { "d": "ssDH", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.11": { "d": "hmacWith3DESwrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.12": { "d": "hmacWithAESwrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.13": { "d": "md5XorExperiment", "c": "S/MIME Algorithms. Experimental", "w": true }, +"1.2.840.113549.1.9.16.3.14": { "d": "rsaKEM", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.15": { "d": "authEnc128", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.16": { "d": "authEnc256", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.4.1": { "d": "certDist-ldap", "c": "S/MIME Certificate Distribution", "w": false }, +"1.2.840.113549.1.9.16.5.1": { "d": "sigPolicyQualifier-spuri x", "c": "S/MIME Signature Policy Qualifiers", "w": false }, +"1.2.840.113549.1.9.16.5.2": { "d": "sigPolicyQualifier-spUserNotice", "c": "S/MIME Signature Policy Qualifiers", "w": false }, +"1.2.840.113549.1.9.16.6.1": { "d": "proofOfOrigin", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.2": { "d": "proofOfReceipt", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.3": { "d": "proofOfDelivery", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.4": { "d": "proofOfSender", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.5": { "d": "proofOfApproval", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.6": { "d": "proofOfCreation", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.8.1": { "d": "glUseKEK", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.2": { "d": "glDelete", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.3": { "d": "glAddMember", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.4": { "d": "glDeleteMember", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.5": { "d": "glRekey", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.6": { "d": "glAddOwner", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.7": { "d": "glRemoveOwner", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.8": { "d": "glkCompromise", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.9": { "d": "glkRefresh", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.10": { "d": "glFailInfo", "c": "S/MIME Symmetric Key Distribution Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.8.11": { "d": "glaQueryRequest", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.12": { "d": "glaQueryResponse", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.13": { "d": "glProvideCert", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.14": { "d": "glUpdateCert", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.15": { "d": "glKey", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.9": { "d": "signatureTypeIdentifier", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.9.1": { "d": "originatorSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.9.2": { "d": "domainSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.9.3": { "d": "additionalAttributesSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.9.4": { "d": "reviewSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.11": { "d": "capabilities", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.11.1": { "d": "preferBinaryInside", "c": "S/MIME Capability", "w": false }, +"1.2.840.113549.1.9.20": { "d": "friendlyName (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.21": { "d": "localKeyID (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.22": { "d": "certTypes (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.22.1": { "d": "x509Certificate (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.22.2": { "d": "sdsiCertificate (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.23": { "d": "crlTypes (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.23.1": { "d": "x509Crl (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.24": { "d": "pkcs9objectClass", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.9.25": { "d": "pkcs9attributes", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.9.25.1": { "d": "pkcs15Token", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.2": { "d": "encryptedPrivateKeyInfo", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.3": { "d": "randomNonce", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.4": { "d": "sequenceNumber", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.5": { "d": "pkcs7PDU", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.26": { "d": "pkcs9syntax", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.9.27": { "d": "pkcs9matchingRules", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.12": { "d": "pkcs-12", "c": "", "w": false }, +"1.2.840.113549.1.12.1": { "d": "pkcs-12-PbeIds", "c": "This OID was formerly assigned as PKCS #12 modeID", "w": false }, +"1.2.840.113549.1.12.1.1": { "d": "pbeWithSHAAnd128BitRC4", "c": "PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OfflineTransportMode", "w": false }, +"1.2.840.113549.1.12.1.2": { "d": "pbeWithSHAAnd40BitRC4", "c": "PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OnlineTransportMode", "w": false }, +"1.2.840.113549.1.12.1.3": { "d": "pbeWithSHAAnd3-KeyTripleDES-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.1.4": { "d": "pbeWithSHAAnd2-KeyTripleDES-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.1.5": { "d": "pbeWithSHAAnd128BitRC2-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.1.6": { "d": "pbeWithSHAAnd40BitRC2-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.2": { "d": "pkcs-12-ESPVKID", "c": "Deprecated", "w": true }, +"1.2.840.113549.1.12.2.1": { "d": "pkcs-12-PKCS8KeyShrouding", "c": "PKCS #12 ESPVKID. Deprecated, use (1 2 840 113549 1 12 3 5) instead", "w": true }, +"1.2.840.113549.1.12.3": { "d": "pkcs-12-BagIds", "c": "", "w": false }, +"1.2.840.113549.1.12.3.1": { "d": "pkcs-12-keyBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.2": { "d": "pkcs-12-certAndCRLBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.3": { "d": "pkcs-12-secretBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.4": { "d": "pkcs-12-safeContentsId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.5": { "d": "pkcs-12-pkcs-8ShroudedKeyBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.4": { "d": "pkcs-12-CertBagID", "c": "Deprecated", "w": true }, +"1.2.840.113549.1.12.4.1": { "d": "pkcs-12-X509CertCRLBagID", "c": "PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-X509CertCRLBag", "w": false }, +"1.2.840.113549.1.12.4.2": { "d": "pkcs-12-SDSICertBagID", "c": "PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-SDSICertBag", "w": false }, +"1.2.840.113549.1.12.5": { "d": "pkcs-12-OID", "c": "", "w": true }, +"1.2.840.113549.1.12.5.1": { "d": "pkcs-12-PBEID", "c": "PKCS #12 OID. Deprecated, use the partially compatible (1 2 840 113549 1 12 1) OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.1.1": { "d": "pkcs-12-PBEWithSha1And128BitRC4", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 1) instead", "w": true }, +"1.2.840.113549.1.12.5.1.2": { "d": "pkcs-12-PBEWithSha1And40BitRC4", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 2) instead", "w": true }, +"1.2.840.113549.1.12.5.1.3": { "d": "pkcs-12-PBEWithSha1AndTripleDESCBC", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 3) or (1 2 840 113549 1 12 1 4) instead", "w": true }, +"1.2.840.113549.1.12.5.1.4": { "d": "pkcs-12-PBEWithSha1And128BitRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 5) instead", "w": true }, +"1.2.840.113549.1.12.5.1.5": { "d": "pkcs-12-PBEWithSha1And40BitRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 6) instead", "w": true }, +"1.2.840.113549.1.12.5.1.6": { "d": "pkcs-12-PBEWithSha1AndRC4", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 1) or (1 2 840 113549 1 12 1 2) instead", "w": true }, +"1.2.840.113549.1.12.5.1.7": { "d": "pkcs-12-PBEWithSha1AndRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 5) or (1 2 840 113549 1 12 1 6) instead", "w": true }, +"1.2.840.113549.1.12.5.2": { "d": "pkcs-12-EnvelopingID", "c": "PKCS #12 OID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": false }, +"1.2.840.113549.1.12.5.2.1": { "d": "pkcs-12-RSAEncryptionWith128BitRC4", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.2.2": { "d": "pkcs-12-RSAEncryptionWith40BitRC4", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.2.3": { "d": "pkcs-12-RSAEncryptionWithTripleDES", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.3": { "d": "pkcs-12-SignatureID", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.3.1": { "d": "pkcs-12-RSASignatureWithSHA1Digest", "c": "PKCS #12 OID SignatureID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.10": { "d": "pkcs-12Version1", "c": "", "w": false }, +"1.2.840.113549.1.12.10.1": { "d": "pkcs-12BadIds", "c": "", "w": false }, +"1.2.840.113549.1.12.10.1.1": { "d": "pkcs-12-keyBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.2": { "d": "pkcs-12-pkcs-8ShroudedKeyBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.3": { "d": "pkcs-12-certBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.4": { "d": "pkcs-12-crlBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.5": { "d": "pkcs-12-secretBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.6": { "d": "pkcs-12-safeContentsBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.15.1": { "d": "pkcs15modules", "c": "PKCS #15", "w": false }, +"1.2.840.113549.1.15.2": { "d": "pkcs15attributes", "c": "PKCS #15", "w": false }, +"1.2.840.113549.1.15.3": { "d": "pkcs15contentType", "c": "PKCS #15", "w": false }, +"1.2.840.113549.1.15.3.1": { "d": "pkcs15content", "c": "PKCS #15 content type", "w": false }, +"1.2.840.113549.2": { "d": "digestAlgorithm", "c": "", "w": false }, +"1.2.840.113549.2.2": { "d": "md2", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.4": { "d": "md4", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.5": { "d": "md5", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.7": { "d": "hmacWithSHA1", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.8": { "d": "hmacWithSHA224", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.9": { "d": "hmacWithSHA256", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.10": { "d": "hmacWithSHA384", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.11": { "d": "hmacWithSHA512", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.3": { "d": "encryptionAlgorithm", "c": "", "w": false }, +"1.2.840.113549.3.2": { "d": "rc2CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.3": { "d": "rc2ECB", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.4": { "d": "rc4", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.5": { "d": "rc4WithMAC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.6": { "d": "desx-CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.7": { "d": "des-EDE3-CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.8": { "d": "rc5CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.9": { "d": "rc5-CBCPad", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.10": { "d": "desCDMF", "c": "RSADSI encryptionAlgorithm. Formerly called CDMFCBCPad", "w": false }, +"1.2.840.114021.1.6.1": { "d": "Identrus unknown policyIdentifier", "c": "Identrus", "w": false }, +"1.2.840.114021.4.1": { "d": "identrusOCSP", "c": "Identrus", "w": false }, +"1.2.840.113556.1.2.241": { "d": "deliveryMechanism", "c": "Microsoft Exchange Server - attribute", "w": false }, +"1.2.840.113556.1.3.0": { "d": "site-Addressing", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.13": { "d": "classSchema", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.14": { "d": "attributeSchema", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.17": { "d": "mailbox-Agent", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.22": { "d": "mailbox", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.23": { "d": "container", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.46": { "d": "mailRecipient", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.2.281": { "d": "ntSecurityDescriptor", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.145": { "d": "revision", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1327": { "d": "pKIDefaultKeySpec", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1328": { "d": "pKIKeyUsage", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1329": { "d": "pKIMaxIssuingDepth", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1330": { "d": "pKICriticalExtensions", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1331": { "d": "pKIExpirationPeriod", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1332": { "d": "pKIOverlapPeriod", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1333": { "d": "pKIExtendedKeyUsage", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1334": { "d": "pKIDefaultCSPs", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1335": { "d": "pKIEnrollmentAccess", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1429": { "d": "msPKI-RA-Signature", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1430": { "d": "msPKI-Enrollment-Flag", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1431": { "d": "msPKI-Private-Key-Flag", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1432": { "d": "msPKI-Certificate-Name-Flag", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1433": { "d": "msPKI-Minimal-Key-Size", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1434": { "d": "msPKI-Template-Schema-Version", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1435": { "d": "msPKI-Template-Minor-Revision", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1436": { "d": "msPKI-Cert-Template-OID", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1437": { "d": "msPKI-Supersede-Templates", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1438": { "d": "msPKI-RA-Policies", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1439": { "d": "msPKI-Certificate-Policy", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1674": { "d": "msPKI-Certificate-Application-Policy", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1675": { "d": "msPKI-RA-Application-Policies", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.4.3": { "d": "microsoftExcel", "c": "Microsoft", "w": false }, +"1.2.840.113556.4.4": { "d": "titledWithOID", "c": "Microsoft", "w": false }, +"1.2.840.113556.4.5": { "d": "microsoftPowerPoint", "c": "Microsoft", "w": false }, +"1.2.840.113628.114.1.7": { "d": "adobePKCS7", "c": "Adobe", "w": false }, +"1.2.840.113635.100": { "d": "appleDataSecurity", "c": "Apple", "w": false }, +"1.2.840.113635.100.1": { "d": "appleTrustPolicy", "c": "Apple", "w": false }, +"1.2.840.113635.100.1.1": { "d": "appleISignTP", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.2": { "d": "appleX509Basic", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.3": { "d": "appleSSLPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.4": { "d": "appleLocalCertGenPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.5": { "d": "appleCSRGenPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.6": { "d": "appleCRLPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.7": { "d": "appleOCSPPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.8": { "d": "appleSMIMEPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.9": { "d": "appleEAPPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.10": { "d": "appleSWUpdateSigningPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.11": { "d": "appleIPSecPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.12": { "d": "appleIChatPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.13": { "d": "appleResourceSignPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.14": { "d": "applePKINITClientPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.15": { "d": "applePKINITServerPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.16": { "d": "appleCodeSigningPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.17": { "d": "applePackageSigningPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.2": { "d": "appleSecurityAlgorithm", "c": "Apple", "w": false }, +"1.2.840.113635.100.2.1": { "d": "appleFEE", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.2": { "d": "appleASC", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.3": { "d": "appleFEE_MD5", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.4": { "d": "appleFEE_SHA1", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.5": { "d": "appleFEED", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.6": { "d": "appleFEEDEXP", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.7": { "d": "appleECDSA", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.3": { "d": "appleDotMacCertificate", "c": "Apple", "w": false }, +"1.2.840.113635.100.3.1": { "d": "appleDotMacCertificateRequest", "c": "Apple dotMac certificate", "w": false }, +"1.2.840.113635.100.3.2": { "d": "appleDotMacCertificateExtension", "c": "Apple dotMac certificate", "w": false }, +"1.2.840.113635.100.3.3": { "d": "appleDotMacCertificateRequestValues", "c": "Apple dotMac certificate", "w": false }, +"1.2.840.113635.100.4": { "d": "appleExtendedKeyUsage", "c": "Apple", "w": false }, +"1.2.840.113635.100.4.1": { "d": "appleCodeSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.1": { "d": "appleCodeSigningDevelopment", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.2": { "d": "appleSoftwareUpdateSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.3": { "d": "appleCodeSigningThirdParty", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.4": { "d": "appleResourceSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.2": { "d": "appleIChatSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.3": { "d": "appleIChatEncryption", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.4": { "d": "appleSystemIdentity", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5": { "d": "appleCryptoEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.1": { "d": "appleCryptoProductionEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.2": { "d": "appleCryptoMaintenanceEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.3": { "d": "appleCryptoTestEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.4": { "d": "appleCryptoDevelopmentEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6": { "d": "appleCryptoQoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.1": { "d": "appleCryptoTier0QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.2": { "d": "appleCryptoTier1QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.3": { "d": "appleCryptoTier2QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.4": { "d": "appleCryptoTier3QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.5": { "d": "appleCertificatePolicies", "c": "Apple", "w": false }, +"1.2.840.113635.100.5.1": { "d": "appleCertificatePolicyID", "c": "Apple", "w": false }, +"1.2.840.113635.100.5.2": { "d": "appleDotMacCertificatePolicyID", "c": "Apple", "w": false }, +"1.2.840.113635.100.5.3": { "d": "appleADCCertificatePolicyID", "c": "Apple", "w": false }, +"1.2.840.113635.100.6": { "d": "appleCertificateExtensions", "c": "Apple", "w": false }, +"1.2.840.113635.100.6.1": { "d": "appleCertificateExtensionCodeSigning", "c": "Apple certificate extension", "w": false }, +"1.2.840.113635.100.6.1.1": { "d": "appleCertificateExtensionAppleSigning", "c": "Apple certificate extension", "w": false }, +"1.2.840.113635.100.6.1.2": { "d": "appleCertificateExtensionADCDeveloperSigning", "c": "Apple certificate extension", "w": false }, +"1.2.840.113635.100.6.1.3": { "d": "appleCertificateExtensionADCAppleSigning", "c": "Apple certificate extension", "w": false }, +"1.3.6.1.4.1.311.2.1.4": { "d": "spcIndirectDataContext", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.10": { "d": "spcAgencyInfo", "c": "Microsoft code signing. Also known as policyLink", "w": false }, +"1.3.6.1.4.1.311.2.1.11": { "d": "spcStatementType", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.12": { "d": "spcSpOpusInfo", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.14": { "d": "certReqExtensions", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.2.1.15": { "d": "spcPEImageData", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.18": { "d": "spcRawFileData", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.19": { "d": "spcStructuredStorageData", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.20": { "d": "spcJavaClassData (type 1)", "c": "Microsoft code signing. Formerly \"link extension\" aka \"glue extension\"", "w": false }, +"1.3.6.1.4.1.311.2.1.21": { "d": "individualCodeSigning", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.2.1.22": { "d": "commercialCodeSigning", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.2.1.25": { "d": "spcLink (type 2)", "c": "Microsoft code signing. Also known as \"glue extension\"", "w": false }, +"1.3.6.1.4.1.311.2.1.26": { "d": "spcMinimalCriteriaInfo", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.27": { "d": "spcFinancialCriteriaInfo", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.28": { "d": "spcLink (type 3)", "c": "Microsoft code signing. Also known as \"glue extension\"", "w": false }, +"1.3.6.1.4.1.311.3.2.1": { "d": "timestampRequest", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.10.1": { "d": "certTrustList", "c": "Microsoft contentType", "w": false }, +"1.3.6.1.4.1.311.10.1.1": { "d": "sortedCtl", "c": "Microsoft contentType", "w": false }, +"1.3.6.1.4.1.311.10.2": { "d": "nextUpdateLocation", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.3.1": { "d": "certTrustListSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.2": { "d": "timeStampSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.3": { "d": "serverGatedCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.3.1": { "d": "serialized", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.3.4": { "d": "encryptedFileSystem", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.5": { "d": "whqlCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.6": { "d": "nt5Crypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.7": { "d": "oemWHQLCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.8": { "d": "embeddedNTCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.9": { "d": "rootListSigner", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.10": { "d": "qualifiedSubordination", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.11": { "d": "keyRecovery", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.12": { "d": "documentSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.13": { "d": "lifetimeSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.14": { "d": "mobileDeviceSoftware", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.15": { "d": "smartDisplay", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.16": { "d": "cspSignature", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.4.1": { "d": "efsRecovery", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.4.1": { "d": "yesnoTrustAttr", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.5.1": { "d": "drm", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.5.2": { "d": "drmIndividualization", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.6.1": { "d": "licenses", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.6.2": { "d": "licenseServer", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.7.1": { "d": "keyidRdn", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.8.1": { "d": "removeCertificate", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.9.1": { "d": "crossCertDistPoints", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.10.1": { "d": "cmcAddAttributes", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11": { "d": "certPropIdPrefix", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.4": { "d": "certMd5HashPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.20": { "d": "certKeyIdentifierPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.28": { "d": "certIssuerSerialNumberMd5HashPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.29": { "d": "certSubjectNameMd5HashPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.12.1": { "d": "anyApplicationPolicy", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.1": { "d": "renewalCertificate", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.2.1": { "d": "enrolmentNameValuePair", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.2.2": { "d": "enrolmentCSP", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.2.3": { "d": "osVersion", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.16.4": { "d": "microsoftRecipientInfo", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.17.1": { "d": "pkcs12KeyProviderNameAttr", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.17.2": { "d": "localMachineKeyset", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.17.3": { "d": "pkcs12ExtendedAttributes", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.20.1": { "d": "autoEnrollCtlUsage", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.20.2": { "d": "enrollCerttypeExtension", "c": "Microsoft CAPICOM certificate template, V1", "w": false }, +"1.3.6.1.4.1.311.20.2.1": { "d": "enrollmentAgent", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.20.2.2": { "d": "smartcardLogon", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.20.2.3": { "d": "universalPrincipalName", "c": "Microsoft UPN", "w": false }, +"1.3.6.1.4.1.311.20.3": { "d": "certManifold", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.1": { "d": "cAKeyCertIndexPair", "c": "Microsoft attribute. Also known as certsrvCaVersion", "w": false }, +"1.3.6.1.4.1.311.21.5": { "d": "caExchange", "c": "Microsoft extended key usage", "w": true }, +"1.3.6.1.4.1.311.21.2": { "d": "certSrvPreviousCertHash", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.3": { "d": "crlVirtualBase", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.4": { "d": "crlNextPublish", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.6": { "d": "keyRecovery", "c": "Microsoft extended key usage", "w": true }, +"1.3.6.1.4.1.311.21.7": { "d": "certificateTemplate", "c": "Microsoft CAPICOM certificate template, V2", "w": false }, +"1.3.6.1.4.1.311.21.9": { "d": "rdnDummySigner", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.10": { "d": "applicationCertPolicies", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.11": { "d": "applicationPolicyMappings", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.12": { "d": "applicationPolicyConstraints", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.13": { "d": "archivedKey", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.21.14": { "d": "crlSelfCDP", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.15": { "d": "requireCertChainPolicy", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.16": { "d": "archivedKeyCertHash", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.17": { "d": "issuedCertHash", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.19": { "d": "dsEmailReplication", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.20": { "d": "requestClientInfo", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.21.21": { "d": "encryptedKeyHash", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.21.22": { "d": "certsrvCrossCaVersion", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.25.1": { "d": "ntdsReplication", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.31.1": { "d": "productUpdate", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.47.1.1": { "d": "systemHealth", "c": "Microsoft extended key usage", "w": false }, +"1.3.6.1.4.1.311.47.1.3": { "d": "systemHealthLoophole", "c": "Microsoft extended key usage", "w": false }, +"1.3.6.1.4.1.311.60.1.1": { "d": "rootProgramFlags", "c": "Microsoft policy attribute", "w": false }, +"1.3.6.1.4.1.311.61.1.1": { "d": "kernelModeCodeSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.60.2.1.1": { "d": "jurisdictionOfIncorporationL", "c": "Microsoft (???)", "w": false }, +"1.3.6.1.4.1.311.60.2.1.2": { "d": "jurisdictionOfIncorporationSP", "c": "Microsoft (???)", "w": false }, +"1.3.6.1.4.1.311.60.2.1.3": { "d": "jurisdictionOfIncorporationC", "c": "Microsoft (???)", "w": false }, +"1.3.6.1.4.1.311.88.2.1": { "d": "originalFilename", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.188.7.1.1": { "d": "ascom", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.1": { "d": "ideaECB", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.2": { "d": "ideaCBC", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.3": { "d": "ideaCFB", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.4": { "d": "ideaOFB", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.2428.10.1.1": { "d": "UNINETT policyIdentifier", "c": "UNINETT PCA", "w": false }, +"1.3.6.1.4.1.2712.10": { "d": "ICE-TEL policyIdentifier", "c": "ICE-TEL CA", "w": false }, +"1.3.6.1.4.1.2786.1.1.1": { "d": "ICE-TEL Italian policyIdentifier", "c": "ICE-TEL CA policy", "w": false }, +"1.3.6.1.4.1.3029.1.1.1": { "d": "blowfishECB", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.1.2": { "d": "blowfishCBC", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.1.3": { "d": "blowfishCFB", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.1.4": { "d": "blowfishOFB", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.2.1": { "d": "elgamal", "c": "cryptlib public-key algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.2.1.1": { "d": "elgamalWithSHA-1", "c": "cryptlib public-key algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.2.1.2": { "d": "elgamalWithRIPEMD-160", "c": "cryptlib public-key algorithm", "w": false }, +"1.3.6.1.4.1.3029.3.1.1": { "d": "cryptlibPresenceCheck", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.3.1.2": { "d": "pkiBoot", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.3.1.4": { "d": "crlExtReason", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.3.1.5": { "d": "keyFeatures", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.4.1": { "d": "cryptlibContent", "c": "cryptlib", "w": false }, +"1.3.6.1.4.1.3029.4.1.1": { "d": "cryptlibConfigData", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.2": { "d": "cryptlibUserIndex", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.3": { "d": "cryptlibUserInfo", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.4": { "d": "rtcsRequest", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.5": { "d": "rtcsResponse", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.6": { "d": "rtcsResponseExt", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.42.11172.1": { "d": "mpeg-1", "c": "cryptlib special MPEG-of-cat OID", "w": false }, +"1.3.6.1.4.1.3029.54.11940.54": { "d": "TSA policy \"Anything that arrives, we sign\"", "c": "cryptlib TSA policy", "w": false }, +"1.3.6.1.4.1.3029.88.89.90.90.89": { "d": "xYZZY policyIdentifier", "c": "cryptlib certificate policy", "w": false }, +"1.3.6.1.4.1.3401.8.1.1": { "d": "pgpExtension", "c": "PGP key information", "w": false }, +"1.3.6.1.4.1.3576.7": { "d": "eciaAscX12Edi", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.1": { "d": "plainEDImessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.2": { "d": "signedEDImessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.5": { "d": "integrityEDImessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.65": { "d": "iaReceiptMessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.97": { "d": "iaStatusMessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.8": { "d": "eciaEdifact", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.9": { "d": "eciaNonEdi", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.4146": { "d": "Globalsign", "c": "Globalsign", "w": false }, +"1.3.6.1.4.1.4146.1": { "d": "globalsignPolicy", "c": "Globalsign", "w": false }, +"1.3.6.1.4.1.4146.1.10": { "d": "globalsignDVPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.20": { "d": "globalsignOVPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.30": { "d": "globalsignTSAPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.40": { "d": "globalsignClientCertPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.50": { "d": "globalsignCodeSignPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.60": { "d": "globalsignRootSignPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.70": { "d": "globalsignTrustedRootPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.80": { "d": "globalsignEDIClientPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.81": { "d": "globalsignEDIServerPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.90": { "d": "globalsignTPMRootPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.95": { "d": "globalsignOCSPPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.5309.1": { "d": "edelWebPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2": { "d": "edelWebCustomerPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2.1": { "d": "edelWebClepsydrePolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2.2": { "d": "edelWebExperimentalTSAPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2.3": { "d": "edelWebOpenEvidenceTSAPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5472": { "d": "timeproof", "c": "enterprise", "w": false }, +"1.3.6.1.4.1.5472.1": { "d": "tss", "c": "timeproof", "w": false }, +"1.3.6.1.4.1.5472.1.1": { "d": "tss80", "c": "timeproof TSS", "w": false }, +"1.3.6.1.4.1.5472.1.2": { "d": "tss380", "c": "timeproof TSS", "w": false }, +"1.3.6.1.4.1.5472.1.3": { "d": "tss400", "c": "timeproof TSS", "w": false }, +"1.3.6.1.4.1.5770.0.3": { "d": "secondaryPractices", "c": "MEDePass", "w": false }, +"1.3.6.1.4.1.5770.0.4": { "d": "physicianIdentifiers", "c": "MEDePass", "w": false }, +"1.3.6.1.4.1.6449.1.2.1.3.1": { "d": "comodoPolicy", "c": "Comodo CA", "w": false }, +"1.3.6.1.4.1.6449.1.2.2.15": { "d": "wotrustPolicy", "c": "WoTrust (Comodo) CA", "w": false }, +"1.3.6.1.4.1.6449.1.3.5.2": { "d": "comodoCertifiedDeliveryService", "c": "Comodo CA", "w": false }, +"1.3.6.1.4.1.6449.2.1.1": { "d": "comodoTimestampingPolicy", "c": "Comodo CA", "w": false }, +"1.3.6.1.4.1.8301.3.5.1": { "d": "validityModelChain", "c": "TU Darmstadt ValidityModel", "w": false }, +"1.3.6.1.4.1.8301.3.5.2": { "d": "validityModelShell", "c": "ValidityModel", "w": false }, +"1.3.6.1.4.1.8231.1": { "d": "rolUnicoNacional", "c": "Chilean Government national unique roll number", "w": false }, +"1.3.6.1.4.1.11591": { "d": "gnu", "c": "GNU Project (see http://www.gnupg.org/oids.html)", "w": false }, +"1.3.6.1.4.1.11591.1": { "d": "gnuRadius", "c": "GNU Radius", "w": false }, +"1.3.6.1.4.1.11591.3": { "d": "gnuRadar", "c": "GNU Radar", "w": false }, +"1.3.6.1.4.1.11591.12": { "d": "gnuDigestAlgorithm", "c": "GNU digest algorithm", "w": false }, +"1.3.6.1.4.1.11591.12.2": { "d": "tiger", "c": "GNU digest algorithm", "w": false }, +"1.3.6.1.4.1.11591.13": { "d": "gnuEncryptionAlgorithm", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2": { "d": "serpent", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.1": { "d": "serpent128_ECB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.2": { "d": "serpent128_CBC", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.3": { "d": "serpent128_OFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.4": { "d": "serpent128_CFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.21": { "d": "serpent192_ECB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.22": { "d": "serpent192_CBC", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.23": { "d": "serpent192_OFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.24": { "d": "serpent192_CFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.41": { "d": "serpent256_ECB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.42": { "d": "serpent256_CBC", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.43": { "d": "serpent256_OFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.44": { "d": "serpent256_CFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.16334.509.1.1": { "d": "Northrop Grumman extKeyUsage?", "c": "Northrop Grumman extended key usage", "w": false }, +"1.3.6.1.4.1.16334.509.2.1": { "d": "ngcClass1", "c": "Northrop Grumman policy", "w": false }, +"1.3.6.1.4.1.16334.509.2.2": { "d": "ngcClass2", "c": "Northrop Grumman policy", "w": false }, +"1.3.6.1.4.1.16334.509.2.3": { "d": "ngcClass3", "c": "Northrop Grumman policy", "w": false }, +"1.3.6.1.5.5.7": { "d": "pkix", "c": "", "w": false }, +"1.3.6.1.5.5.7.0.12": { "d": "attributeCert", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.1": { "d": "privateExtension", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.1.1": { "d": "authorityInfoAccess", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.2": { "d": "biometricInfo", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.3": { "d": "qcStatements", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.4": { "d": "acAuditIdentity", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.5": { "d": "acTargeting", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.6": { "d": "acAaControls", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.7": { "d": "ipAddrBlocks", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.8": { "d": "autonomousSysIds", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.9": { "d": "routerIdentifier", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.10": { "d": "acProxying", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.11": { "d": "subjectInfoAccess", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.12": { "d": "logoType", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.13": { "d": "wlanSSID", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.2": { "d": "policyQualifierIds", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.2.1": { "d": "cps", "c": "PKIX policy qualifier", "w": false }, +"1.3.6.1.5.5.7.2.2": { "d": "unotice", "c": "PKIX policy qualifier", "w": false }, +"1.3.6.1.5.5.7.2.3": { "d": "textNotice", "c": "PKIX policy qualifier", "w": false }, +"1.3.6.1.5.5.7.3": { "d": "keyPurpose", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.3.1": { "d": "serverAuth", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.2": { "d": "clientAuth", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.3": { "d": "codeSigning", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.4": { "d": "emailProtection", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.5": { "d": "ipsecEndSystem", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.6": { "d": "ipsecTunnel", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.7": { "d": "ipsecUser", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.8": { "d": "timeStamping", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.9": { "d": "ocspSigning", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.10": { "d": "dvcs", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.11": { "d": "sbgpCertAAServerAuth", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.13": { "d": "eapOverPPP", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.14": { "d": "eapOverLAN", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.4": { "d": "cmpInformationTypes", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.4.1": { "d": "caProtEncCert", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.2": { "d": "signKeyPairTypes", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.3": { "d": "encKeyPairTypes", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.4": { "d": "preferredSymmAlg", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.5": { "d": "caKeyUpdateInfo", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.6": { "d": "currentCRL", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.7": { "d": "unsupportedOIDs", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.10": { "d": "keyPairParamReq", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.11": { "d": "keyPairParamRep", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.12": { "d": "revPassphrase", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.13": { "d": "implicitConfirm", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.14": { "d": "confirmWaitTime", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.15": { "d": "origPKIMessage", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.16": { "d": "suppLangTags", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.5": { "d": "crmfRegistration", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.5.1": { "d": "regCtrl", "c": "PKIX CRMF registration", "w": false }, +"1.3.6.1.5.5.7.5.1.1": { "d": "regToken", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.2": { "d": "authenticator", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.3": { "d": "pkiPublicationInfo", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.4": { "d": "pkiArchiveOptions", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.5": { "d": "oldCertID", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.6": { "d": "protocolEncrKey", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.7": { "d": "altCertTemplate", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.8": { "d": "wtlsTemplate", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.2": { "d": "utf8Pairs", "c": "PKIX CRMF registration", "w": false }, +"1.3.6.1.5.5.7.5.2.1": { "d": "utf8Pairs", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.2.2": { "d": "certReq", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.6": { "d": "algorithms", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.6.1": { "d": "des40", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.6.2": { "d": "noSignature", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.6.3": { "d": "dh-sig-hmac-sha1", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.6.4": { "d": "dh-pop", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.7": { "d": "cmcControls", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.8": { "d": "otherNames", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.8.1": { "d": "personalData", "c": "PKIX other name", "w": false }, +"1.3.6.1.5.5.7.8.2": { "d": "userGroup", "c": "PKIX other name", "w": false }, +"1.3.6.1.5.5.7.8.5": { "d": "xmppAddr", "c": "PKIX other name", "w": false }, +"1.3.6.1.5.5.7.9": { "d": "personalData", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.9.1": { "d": "dateOfBirth", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.2": { "d": "placeOfBirth", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.3": { "d": "gender", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.4": { "d": "countryOfCitizenship", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.5": { "d": "countryOfResidence", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.10": { "d": "attributeCertificate", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.10.1": { "d": "authenticationInfo", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.2": { "d": "accessIdentity", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.3": { "d": "chargingIdentity", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.4": { "d": "group", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.5": { "d": "role", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.6": { "d": "wlanSSID", "c": "PKIX attribute-certificate extension", "w": false }, +"1.3.6.1.5.5.7.11": { "d": "personalData", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.11.1": { "d": "pkixQCSyntax-v1", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.14.2": { "d": "resourceCertificatePolicy", "c": "PKIX policies", "w": false }, +"1.3.6.1.5.5.7.20": { "d": "logo", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.20.1": { "d": "logoLoyalty", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.20.2": { "d": "logoBackground", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.48.1": { "d": "ocsp", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.48.1.1": { "d": "ocspBasic", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.2": { "d": "ocspNonce", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.3": { "d": "ocspCRL", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.4": { "d": "ocspResponse", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.5": { "d": "ocspNoCheck", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.6": { "d": "ocspArchiveCutoff", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.7": { "d": "ocspServiceLocator", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.2": { "d": "caIssuers", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.3": { "d": "timeStamping", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.4": { "d": "dvcs", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.5": { "d": "caRepository", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.7": { "d": "signedObjectRepository", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.10": { "d": "rpkiManifest", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.11": { "d": "signedObject", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.8.1.1": { "d": "hmacMD5", "c": "ISAKMP HMAC algorithm", "w": false }, +"1.3.6.1.5.5.8.1.2": { "d": "hmacSHA", "c": "ISAKMP HMAC algorithm", "w": false }, +"1.3.6.1.5.5.8.1.3": { "d": "hmacTiger", "c": "ISAKMP HMAC algorithm", "w": false }, +"1.3.6.1.5.5.8.2.2": { "d": "iKEIntermediate", "c": "IKE ???", "w": false }, +"1.3.12.2.1011.7.1": { "d": "decEncryptionAlgorithm", "c": "DASS algorithm", "w": false }, +"1.3.12.2.1011.7.1.2": { "d": "decDEA", "c": "DASS encryption algorithm", "w": false }, +"1.3.12.2.1011.7.2": { "d": "decHashAlgorithm", "c": "DASS algorithm", "w": false }, +"1.3.12.2.1011.7.2.1": { "d": "decMD2", "c": "DASS hash algorithm", "w": false }, +"1.3.12.2.1011.7.2.2": { "d": "decMD4", "c": "DASS hash algorithm", "w": false }, +"1.3.12.2.1011.7.3": { "d": "decSignatureAlgorithm", "c": "DASS algorithm", "w": false }, +"1.3.12.2.1011.7.3.1": { "d": "decMD2withRSA", "c": "DASS signature algorithm", "w": false }, +"1.3.12.2.1011.7.3.2": { "d": "decMD4withRSA", "c": "DASS signature algorithm", "w": false }, +"1.3.12.2.1011.7.3.3": { "d": "decDEAMAC", "c": "DASS signature algorithm", "w": false }, +"1.3.14.2.26.5": { "d": "sha", "c": "Unsure about this OID", "w": false }, +"1.3.14.3.2.1.1": { "d": "rsa", "c": "X.509. Unsure about this OID", "w": false }, +"1.3.14.3.2.2": { "d": "md4WitRSA", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.3": { "d": "md5WithRSA", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.4": { "d": "md4WithRSAEncryption", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.2.1": { "d": "sqmod-N", "c": "X.509. Deprecated", "w": true }, +"1.3.14.3.2.3.1": { "d": "sqmod-NwithRSA", "c": "X.509. Deprecated", "w": true }, +"1.3.14.3.2.6": { "d": "desECB", "c": "", "w": false }, +"1.3.14.3.2.7": { "d": "desCBC", "c": "", "w": false }, +"1.3.14.3.2.8": { "d": "desOFB", "c": "", "w": false }, +"1.3.14.3.2.9": { "d": "desCFB", "c": "", "w": false }, +"1.3.14.3.2.10": { "d": "desMAC", "c": "", "w": false }, +"1.3.14.3.2.11": { "d": "rsaSignature", "c": "ISO 9796-2, also X9.31 Part 1", "w": false }, +"1.3.14.3.2.12": { "d": "dsa", "c": "OIW?, supposedly from an incomplete version of SDN.701 (doesn't match final SDN.701)", "w": true }, +"1.3.14.3.2.13": { "d": "dsaWithSHA", "c": "Oddball OIW OID. Incorrectly used by JDK 1.1 in place of (1 3 14 3 2 27)", "w": true }, +"1.3.14.3.2.14": { "d": "mdc2WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.15": { "d": "shaWithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.16": { "d": "dhWithCommonModulus", "c": "Oddball OIW OID. Deprecated, use a plain DH OID instead", "w": true }, +"1.3.14.3.2.17": { "d": "desEDE", "c": "Oddball OIW OID. Mode is ECB", "w": false }, +"1.3.14.3.2.18": { "d": "sha", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.19": { "d": "mdc-2", "c": "Oddball OIW OID, DES-based hash, planned for X9.31 Part 2", "w": false }, +"1.3.14.3.2.20": { "d": "dsaCommon", "c": "Oddball OIW OID. Deprecated, use a plain DSA OID instead", "w": true }, +"1.3.14.3.2.21": { "d": "dsaCommonWithSHA", "c": "Oddball OIW OID. Deprecated, use a plain dsaWithSHA OID instead", "w": true }, +"1.3.14.3.2.22": { "d": "rsaKeyTransport", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.23": { "d": "keyed-hash-seal", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.24": { "d": "md2WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.25": { "d": "md5WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.26": { "d": "sha1", "c": "OIW", "w": false }, +"1.3.14.3.2.27": { "d": "dsaWithSHA1", "c": "OIW. This OID may also be assigned as ripemd-160", "w": false }, +"1.3.14.3.2.28": { "d": "dsaWithCommonSHA1", "c": "OIW", "w": false }, +"1.3.14.3.2.29": { "d": "sha-1WithRSAEncryption", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.3.1": { "d": "simple-strong-auth-mechanism", "c": "Oddball OIW OID", "w": false }, +"1.3.14.7.2.1.1": { "d": "ElGamal", "c": "Unsure about this OID", "w": false }, +"1.3.14.7.2.3.1": { "d": "md2WithRSA", "c": "Unsure about this OID", "w": false }, +"1.3.14.7.2.3.2": { "d": "md2WithElGamal", "c": "Unsure about this OID", "w": false }, +"1.3.36.1": { "d": "document", "c": "Teletrust document", "w": false }, +"1.3.36.1.1": { "d": "finalVersion", "c": "Teletrust document", "w": false }, +"1.3.36.1.2": { "d": "draft", "c": "Teletrust document", "w": false }, +"1.3.36.2": { "d": "sio", "c": "Teletrust sio", "w": false }, +"1.3.36.2.1": { "d": "sedu", "c": "Teletrust sio", "w": false }, +"1.3.36.3": { "d": "algorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.1": { "d": "encryptionAlgorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.1.1": { "d": "des", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.1": { "d": "desECB_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.1.1": { "d": "desECB_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.2.1": { "d": "desCBC_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.2.1.1": { "d": "desCBC_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.3": { "d": "des_3", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.3.1.1": { "d": "des_3ECB_pad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.3.1.1.1": { "d": "des_3ECB_ISOpad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.3.2.1": { "d": "des_3CBC_pad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.3.2.1.1": { "d": "des_3CBC_ISOpad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.2": { "d": "idea", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.1": { "d": "ideaECB", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.1.1": { "d": "ideaECB_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.1.1.1": { "d": "ideaECB_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.2": { "d": "ideaCBC", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.2.1": { "d": "ideaCBC_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.2.1.1": { "d": "ideaCBC_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.3": { "d": "ideaOFB", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.4": { "d": "ideaCFB", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.4": { "d": "rsaEncryption", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.4.512.17": { "d": "rsaEncryptionWithlmod512expe17", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5": { "d": "bsi-1", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5.1": { "d": "bsi_1ECB_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5.2": { "d": "bsi_1CBC_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5.2.1": { "d": "bsi_1CBC_PEMpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.2": { "d": "hashAlgorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.2.1": { "d": "ripemd160", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.2": { "d": "ripemd128", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.3": { "d": "ripemd256", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.4": { "d": "mdc2singleLength", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.5": { "d": "mdc2doubleLength", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.3": { "d": "signatureAlgorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.3.1": { "d": "rsaSignature", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.1": { "d": "rsaSignatureWithsha1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.1.1024.11": { "d": "rsaSignatureWithsha1_l1024_l11", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.2": { "d": "rsaSignatureWithripemd160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.2.1024.11": { "d": "rsaSignatureWithripemd160_l1024_l11", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.3": { "d": "rsaSignatureWithrimpemd128", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.4": { "d": "rsaSignatureWithrimpemd256", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2": { "d": "ecsieSign", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.1": { "d": "ecsieSignWithsha1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.2": { "d": "ecsieSignWithripemd160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.3": { "d": "ecsieSignWithmd2", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.4": { "d": "ecsieSignWithmd5", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.8.1.1.1": { "d": "brainpoolP160r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.2": { "d": "brainpoolP160t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.3": { "d": "brainpoolP192r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.4": { "d": "brainpoolP192t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.5": { "d": "brainpoolP224r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.6": { "d": "brainpoolP224t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.7": { "d": "brainpoolP256r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.8": { "d": "brainpoolP256t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.9": { "d": "brainpoolP320r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.10": { "d": "brainpoolP320t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.11": { "d": "brainpoolP384r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.12": { "d": "brainpoolP384t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.13": { "d": "brainpoolP512r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.14": { "d": "brainpoolP512t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.4": { "d": "signatureScheme", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.4.1": { "d": "sigS_ISO9796-1", "c": "Teletrust signature scheme", "w": false }, +"1.3.36.3.4.2": { "d": "sigS_ISO9796-2", "c": "Teletrust signature scheme", "w": false }, +"1.3.36.3.4.2.1": { "d": "sigS_ISO9796-2Withred", "c": "Teletrust signature scheme. Unsure what this is supposed to be", "w": false }, +"1.3.36.3.4.2.2": { "d": "sigS_ISO9796-2Withrsa", "c": "Teletrust signature scheme. Unsure what this is supposed to be", "w": false }, +"1.3.36.3.4.2.3": { "d": "sigS_ISO9796-2Withrnd", "c": "Teletrust signature scheme. 9796-2 with random number in padding field", "w": false }, +"1.3.36.4": { "d": "attribute", "c": "Teletrust attribute", "w": false }, +"1.3.36.5": { "d": "policy", "c": "Teletrust policy", "w": false }, +"1.3.36.6": { "d": "api", "c": "Teletrust API", "w": false }, +"1.3.36.6.1": { "d": "manufacturer-specific_api", "c": "Teletrust API", "w": false }, +"1.3.36.6.1.1": { "d": "utimaco-api", "c": "Teletrust API", "w": false }, +"1.3.36.6.2": { "d": "functionality-specific_api", "c": "Teletrust API", "w": false }, +"1.3.36.7": { "d": "keymgmnt", "c": "Teletrust key management", "w": false }, +"1.3.36.7.1": { "d": "keyagree", "c": "Teletrust key management", "w": false }, +"1.3.36.7.1.1": { "d": "bsiPKE", "c": "Teletrust key management", "w": false }, +"1.3.36.7.2": { "d": "keytrans", "c": "Teletrust key management", "w": false }, +"1.3.36.7.2.1": { "d": "encISO9796-2Withrsa", "c": "Teletrust key management. 9796-2 with key stored in hash field", "w": false }, +"1.3.36.8.1.1": { "d": "Teletrust SigGConform policyIdentifier", "c": "Teletrust policy", "w": false }, +"1.3.36.8.2.1": { "d": "directoryService", "c": "Teletrust extended key usage", "w": false }, +"1.3.36.8.3.1": { "d": "dateOfCertGen", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.2": { "d": "procuration", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.3": { "d": "admission", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.4": { "d": "monetaryLimit", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.5": { "d": "declarationOfMajority", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.6": { "d": "integratedCircuitCardSerialNumber", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.7": { "d": "pKReference", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.8": { "d": "restriction", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.9": { "d": "retrieveIfAllowed", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.10": { "d": "requestedCertificate", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.11": { "d": "namingAuthorities", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.11.1": { "d": "rechtWirtschaftSteuern", "c": "Teletrust naming authorities", "w": false }, +"1.3.36.8.3.11.1.1": { "d": "rechtsanwaeltin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.2": { "d": "rechtsanwalt", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.3": { "d": "rechtsBeistand", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.4": { "d": "steuerBeraterin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.5": { "d": "steuerBerater", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.6": { "d": "steuerBevollmaechtigte", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.7": { "d": "steuerBevollmaechtigter", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.8": { "d": "notarin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.9": { "d": "notar", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.10": { "d": "notarVertreterin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.11": { "d": "notarVertreter", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.12": { "d": "notariatsVerwalterin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.13": { "d": "notariatsVerwalter", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.14": { "d": "wirtschaftsPrueferin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.15": { "d": "wirtschaftsPruefer", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.16": { "d": "vereidigteBuchprueferin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.17": { "d": "vereidigterBuchpruefer", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.18": { "d": "patentAnwaeltin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.19": { "d": "patentAnwalt", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.12": { "d": "certInDirSince", "c": "Teletrust OCSP attribute (obsolete)", "w": true }, +"1.3.36.8.3.13": { "d": "certHash", "c": "Teletrust OCSP attribute", "w": false }, +"1.3.36.8.3.14": { "d": "nameAtBirth", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.15": { "d": "additionalInformation", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.4.1": { "d": "personalData", "c": "Teletrust OtherName attribute", "w": false }, +"1.3.36.8.4.8": { "d": "restriction", "c": "Teletrust attribute certificate attribute", "w": false }, +"1.3.36.8.5.1.1.1": { "d": "rsaIndicateSHA1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.1.2": { "d": "rsaIndicateRIPEMD160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.1.3": { "d": "rsaWithSHA1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.1.4": { "d": "rsaWithRIPEMD160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.2.1": { "d": "dsaExtended", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.2.2": { "d": "dsaWithRIPEMD160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.6.1": { "d": "cert", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.2": { "d": "certRef", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.3": { "d": "attrCert", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.4": { "d": "attrRef", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.5": { "d": "fileName", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.6": { "d": "storageTime", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.7": { "d": "fileSize", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.8": { "d": "location", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.9": { "d": "sigNumber", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.10": { "d": "autoGen", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.7.1.1": { "d": "ptAdobeILL", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.2": { "d": "ptAmiPro", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.3": { "d": "ptAutoCAD", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.4": { "d": "ptBinary", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.5": { "d": "ptBMP", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.6": { "d": "ptCGM", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.7": { "d": "ptCorelCRT", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.8": { "d": "ptCorelDRW", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.9": { "d": "ptCorelEXC", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.10": { "d": "ptCorelPHT", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.11": { "d": "ptDraw", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.12": { "d": "ptDVI", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.13": { "d": "ptEPS", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.14": { "d": "ptExcel", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.15": { "d": "ptGEM", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.16": { "d": "ptGIF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.17": { "d": "ptHPGL", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.18": { "d": "ptJPEG", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.19": { "d": "ptKodak", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.20": { "d": "ptLaTeX", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.21": { "d": "ptLotus", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.22": { "d": "ptLotusPIC", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.23": { "d": "ptMacPICT", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.24": { "d": "ptMacWord", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.25": { "d": "ptMSWfD", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.26": { "d": "ptMSWord", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.27": { "d": "ptMSWord2", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.28": { "d": "ptMSWord6", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.29": { "d": "ptMSWord8", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.30": { "d": "ptPDF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.31": { "d": "ptPIF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.32": { "d": "ptPostscript", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.33": { "d": "ptRTF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.34": { "d": "ptSCITEX", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.35": { "d": "ptTAR", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.36": { "d": "ptTarga", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.37": { "d": "ptTeX", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.38": { "d": "ptText", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.39": { "d": "ptTIFF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.40": { "d": "ptTIFF-FC", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.41": { "d": "ptUID", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.42": { "d": "ptUUEncode", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.43": { "d": "ptWMF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.45": { "d": "ptWPGrph", "c": "Teletrust presentation types", "w": false }, +"1.3.101.1.4": { "d": "thawte-ce", "c": "Thawte", "w": false }, +"1.3.101.1.4.1": { "d": "strongExtranet", "c": "Thawte certificate extension", "w": false }, +"1.3.132.0.1": { "d": "sect163k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.2": { "d": "sect163r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.3": { "d": "sect239k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.4": { "d": "sect113r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.5": { "d": "sect113r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.6": { "d": "secp112r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.7": { "d": "secp112r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.8": { "d": "secp160r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.9": { "d": "secp160k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.10": { "d": "secp256k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.15": { "d": "sect163r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.16": { "d": "sect283k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.17": { "d": "sect283r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.22": { "d": "sect131r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.23": { "d": "sect131r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.24": { "d": "sect193r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.25": { "d": "sect193r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.26": { "d": "sect233k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.27": { "d": "sect233r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.28": { "d": "secp128r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.29": { "d": "secp128r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.30": { "d": "secp160r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.31": { "d": "secp192k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.32": { "d": "secp224k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.33": { "d": "secp224r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.34": { "d": "secp384r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.35": { "d": "secp521r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.36": { "d": "sect409k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.37": { "d": "sect409r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.38": { "d": "sect571k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.39": { "d": "sect571r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"2.5.4.0": { "d": "objectClass", "c": "X.520 DN component", "w": false }, +"2.5.4.1": { "d": "aliasedEntryName", "c": "X.520 DN component", "w": false }, +"2.5.4.2": { "d": "knowledgeInformation", "c": "X.520 DN component", "w": false }, +"2.5.4.3": { "d": "commonName", "c": "X.520 DN component", "w": false }, +"2.5.4.4": { "d": "surname", "c": "X.520 DN component", "w": false }, +"2.5.4.5": { "d": "serialNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.6": { "d": "countryName", "c": "X.520 DN component", "w": false }, +"2.5.4.7": { "d": "localityName", "c": "X.520 DN component", "w": false }, +"2.5.4.7.1": { "d": "collectiveLocalityName", "c": "X.520 DN component", "w": false }, +"2.5.4.8": { "d": "stateOrProvinceName", "c": "X.520 DN component", "w": false }, +"2.5.4.8.1": { "d": "collectiveStateOrProvinceName", "c": "X.520 DN component", "w": false }, +"2.5.4.9": { "d": "streetAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.9.1": { "d": "collectiveStreetAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.10": { "d": "organizationName", "c": "X.520 DN component", "w": false }, +"2.5.4.10.1": { "d": "collectiveOrganizationName", "c": "X.520 DN component", "w": false }, +"2.5.4.11": { "d": "organizationalUnitName", "c": "X.520 DN component", "w": false }, +"2.5.4.11.1": { "d": "collectiveOrganizationalUnitName", "c": "X.520 DN component", "w": false }, +"2.5.4.12": { "d": "title", "c": "X.520 DN component", "w": false }, +"2.5.4.13": { "d": "description", "c": "X.520 DN component", "w": false }, +"2.5.4.14": { "d": "searchGuide", "c": "X.520 DN component", "w": false }, +"2.5.4.15": { "d": "businessCategory", "c": "X.520 DN component", "w": false }, +"2.5.4.16": { "d": "postalAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.16.1": { "d": "collectivePostalAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.17": { "d": "postalCode", "c": "X.520 DN component", "w": false }, +"2.5.4.17.1": { "d": "collectivePostalCode", "c": "X.520 DN component", "w": false }, +"2.5.4.18": { "d": "postOfficeBox", "c": "X.520 DN component", "w": false }, +"2.5.4.18.1": { "d": "collectivePostOfficeBox", "c": "X.520 DN component", "w": false }, +"2.5.4.19": { "d": "physicalDeliveryOfficeName", "c": "X.520 DN component", "w": false }, +"2.5.4.19.1": { "d": "collectivePhysicalDeliveryOfficeName", "c": "X.520 DN component", "w": false }, +"2.5.4.20": { "d": "telephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.20.1": { "d": "collectiveTelephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.21": { "d": "telexNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.21.1": { "d": "collectiveTelexNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.22": { "d": "teletexTerminalIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.22.1": { "d": "collectiveTeletexTerminalIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.23": { "d": "facsimileTelephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.23.1": { "d": "collectiveFacsimileTelephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.24": { "d": "x121Address", "c": "X.520 DN component", "w": false }, +"2.5.4.25": { "d": "internationalISDNNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.25.1": { "d": "collectiveInternationalISDNNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.26": { "d": "registeredAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.27": { "d": "destinationIndicator", "c": "X.520 DN component", "w": false }, +"2.5.4.28": { "d": "preferredDeliveryMehtod", "c": "X.520 DN component", "w": false }, +"2.5.4.29": { "d": "presentationAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.30": { "d": "supportedApplicationContext", "c": "X.520 DN component", "w": false }, +"2.5.4.31": { "d": "member", "c": "X.520 DN component", "w": false }, +"2.5.4.32": { "d": "owner", "c": "X.520 DN component", "w": false }, +"2.5.4.33": { "d": "roleOccupant", "c": "X.520 DN component", "w": false }, +"2.5.4.34": { "d": "seeAlso", "c": "X.520 DN component", "w": false }, +"2.5.4.35": { "d": "userPassword", "c": "X.520 DN component", "w": false }, +"2.5.4.36": { "d": "userCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.37": { "d": "caCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.38": { "d": "authorityRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.39": { "d": "certificateRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.40": { "d": "crossCertificatePair", "c": "X.520 DN component", "w": false }, +"2.5.4.41": { "d": "name", "c": "X.520 DN component", "w": false }, +"2.5.4.42": { "d": "givenName", "c": "X.520 DN component", "w": false }, +"2.5.4.43": { "d": "initials", "c": "X.520 DN component", "w": false }, +"2.5.4.44": { "d": "generationQualifier", "c": "X.520 DN component", "w": false }, +"2.5.4.45": { "d": "uniqueIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.46": { "d": "dnQualifier", "c": "X.520 DN component", "w": false }, +"2.5.4.47": { "d": "enhancedSearchGuide", "c": "X.520 DN component", "w": false }, +"2.5.4.48": { "d": "protocolInformation", "c": "X.520 DN component", "w": false }, +"2.5.4.49": { "d": "distinguishedName", "c": "X.520 DN component", "w": false }, +"2.5.4.50": { "d": "uniqueMember", "c": "X.520 DN component", "w": false }, +"2.5.4.51": { "d": "houseIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.52": { "d": "supportedAlgorithms", "c": "X.520 DN component", "w": false }, +"2.5.4.53": { "d": "deltaRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.54": { "d": "dmdName", "c": "X.520 DN component", "w": false }, +"2.5.4.55": { "d": "clearance", "c": "X.520 DN component", "w": false }, +"2.5.4.56": { "d": "defaultDirQop", "c": "X.520 DN component", "w": false }, +"2.5.4.57": { "d": "attributeIntegrityInfo", "c": "X.520 DN component", "w": false }, +"2.5.4.58": { "d": "attributeCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.59": { "d": "attributeCertificateRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.60": { "d": "confKeyInfo", "c": "X.520 DN component", "w": false }, +"2.5.4.61": { "d": "aACertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.62": { "d": "attributeDescriptorCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.63": { "d": "attributeAuthorityRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.64": { "d": "familyInformation", "c": "X.520 DN component", "w": false }, +"2.5.4.65": { "d": "pseudonym", "c": "X.520 DN component", "w": false }, +"2.5.4.66": { "d": "communicationsService", "c": "X.520 DN component", "w": false }, +"2.5.4.67": { "d": "communicationsNetwork", "c": "X.520 DN component", "w": false }, +"2.5.4.68": { "d": "certificationPracticeStmt", "c": "X.520 DN component", "w": false }, +"2.5.4.69": { "d": "certificatePolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.70": { "d": "pkiPath", "c": "X.520 DN component", "w": false }, +"2.5.4.71": { "d": "privPolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.72": { "d": "role", "c": "X.520 DN component", "w": false }, +"2.5.4.73": { "d": "delegationPath", "c": "X.520 DN component", "w": false }, +"2.5.4.74": { "d": "protPrivPolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.75": { "d": "xMLPrivilegeInfo", "c": "X.520 DN component", "w": false }, +"2.5.4.76": { "d": "xmlPrivPolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.82": { "d": "permission", "c": "X.520 DN component", "w": false }, +"2.5.6.0": { "d": "top", "c": "X.520 objectClass", "w": false }, +"2.5.6.1": { "d": "alias", "c": "X.520 objectClass", "w": false }, +"2.5.6.2": { "d": "country", "c": "X.520 objectClass", "w": false }, +"2.5.6.3": { "d": "locality", "c": "X.520 objectClass", "w": false }, +"2.5.6.4": { "d": "organization", "c": "X.520 objectClass", "w": false }, +"2.5.6.5": { "d": "organizationalUnit", "c": "X.520 objectClass", "w": false }, +"2.5.6.6": { "d": "person", "c": "X.520 objectClass", "w": false }, +"2.5.6.7": { "d": "organizationalPerson", "c": "X.520 objectClass", "w": false }, +"2.5.6.8": { "d": "organizationalRole", "c": "X.520 objectClass", "w": false }, +"2.5.6.9": { "d": "groupOfNames", "c": "X.520 objectClass", "w": false }, +"2.5.6.10": { "d": "residentialPerson", "c": "X.520 objectClass", "w": false }, +"2.5.6.11": { "d": "applicationProcess", "c": "X.520 objectClass", "w": false }, +"2.5.6.12": { "d": "applicationEntity", "c": "X.520 objectClass", "w": false }, +"2.5.6.13": { "d": "dSA", "c": "X.520 objectClass", "w": false }, +"2.5.6.14": { "d": "device", "c": "X.520 objectClass", "w": false }, +"2.5.6.15": { "d": "strongAuthenticationUser", "c": "X.520 objectClass", "w": false }, +"2.5.6.16": { "d": "certificateAuthority", "c": "X.520 objectClass", "w": false }, +"2.5.6.17": { "d": "groupOfUniqueNames", "c": "X.520 objectClass", "w": false }, +"2.5.6.21": { "d": "pkiUser", "c": "X.520 objectClass", "w": false }, +"2.5.6.22": { "d": "pkiCA", "c": "X.520 objectClass", "w": false }, +"2.5.8.1.1": { "d": "rsa", "c": "X.500 algorithms. Ambiguous, since no padding rules specified", "w": true }, +"2.5.29.1": { "d": "authorityKeyIdentifier", "c": "X.509 extension. Deprecated, use 2 5 29 35 instead", "w": true }, +"2.5.29.2": { "d": "keyAttributes", "c": "X.509 extension. Obsolete, use keyUsage/extKeyUsage instead", "w": true }, +"2.5.29.3": { "d": "certificatePolicies", "c": "X.509 extension. Deprecated, use 2 5 29 32 instead", "w": true }, +"2.5.29.4": { "d": "keyUsageRestriction", "c": "X.509 extension. Obsolete, use keyUsage/extKeyUsage instead", "w": true }, +"2.5.29.5": { "d": "policyMapping", "c": "X.509 extension. Deprecated, use 2 5 29 33 instead", "w": true }, +"2.5.29.6": { "d": "subtreesConstraint", "c": "X.509 extension. Obsolete, use nameConstraints instead", "w": true }, +"2.5.29.7": { "d": "subjectAltName", "c": "X.509 extension. Deprecated, use 2 5 29 17 instead", "w": true }, +"2.5.29.8": { "d": "issuerAltName", "c": "X.509 extension. Deprecated, use 2 5 29 18 instead", "w": true }, +"2.5.29.9": { "d": "subjectDirectoryAttributes", "c": "X.509 extension", "w": false }, +"2.5.29.10": { "d": "basicConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 19 instead", "w": true }, +"2.5.29.11": { "d": "nameConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 30 instead", "w": true }, +"2.5.29.12": { "d": "policyConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 36 instead", "w": true }, +"2.5.29.13": { "d": "basicConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 19 instead", "w": true }, +"2.5.29.14": { "d": "subjectKeyIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.15": { "d": "keyUsage", "c": "X.509 extension", "w": false }, +"2.5.29.16": { "d": "privateKeyUsagePeriod", "c": "X.509 extension", "w": false }, +"2.5.29.17": { "d": "subjectAltName", "c": "X.509 extension", "w": false }, +"2.5.29.18": { "d": "issuerAltName", "c": "X.509 extension", "w": false }, +"2.5.29.19": { "d": "basicConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.20": { "d": "cRLNumber", "c": "X.509 extension", "w": false }, +"2.5.29.21": { "d": "cRLReason", "c": "X.509 extension", "w": false }, +"2.5.29.22": { "d": "expirationDate", "c": "X.509 extension. Deprecated, alternative OID uncertain", "w": true }, +"2.5.29.23": { "d": "instructionCode", "c": "X.509 extension", "w": false }, +"2.5.29.24": { "d": "invalidityDate", "c": "X.509 extension", "w": false }, +"2.5.29.25": { "d": "cRLDistributionPoints", "c": "X.509 extension. Deprecated, use 2 5 29 31 instead", "w": true }, +"2.5.29.26": { "d": "issuingDistributionPoint", "c": "X.509 extension. Deprecated, use 2 5 29 28 instead", "w": true }, +"2.5.29.27": { "d": "deltaCRLIndicator", "c": "X.509 extension", "w": false }, +"2.5.29.28": { "d": "issuingDistributionPoint", "c": "X.509 extension", "w": false }, +"2.5.29.29": { "d": "certificateIssuer", "c": "X.509 extension", "w": false }, +"2.5.29.30": { "d": "nameConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.31": { "d": "cRLDistributionPoints", "c": "X.509 extension", "w": false }, +"2.5.29.32": { "d": "certificatePolicies", "c": "X.509 extension", "w": false }, +"2.5.29.32.0": { "d": "anyPolicy", "c": "X.509 certificate policy", "w": false }, +"2.5.29.33": { "d": "policyMappings", "c": "X.509 extension", "w": false }, +"2.5.29.34": { "d": "policyConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 36 instead", "w": true }, +"2.5.29.35": { "d": "authorityKeyIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.36": { "d": "policyConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.37": { "d": "extKeyUsage", "c": "X.509 extension", "w": false }, +"2.5.29.37.0": { "d": "anyExtendedKeyUsage", "c": "X.509 extended key usage", "w": false }, +"2.5.29.38": { "d": "authorityAttributeIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.39": { "d": "roleSpecCertIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.40": { "d": "cRLStreamIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.41": { "d": "basicAttConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.42": { "d": "delegatedNameConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.43": { "d": "timeSpecification", "c": "X.509 extension", "w": false }, +"2.5.29.44": { "d": "cRLScope", "c": "X.509 extension", "w": false }, +"2.5.29.45": { "d": "statusReferrals", "c": "X.509 extension", "w": false }, +"2.5.29.46": { "d": "freshestCRL", "c": "X.509 extension", "w": false }, +"2.5.29.47": { "d": "orderedList", "c": "X.509 extension", "w": false }, +"2.5.29.48": { "d": "attributeDescriptor", "c": "X.509 extension", "w": false }, +"2.5.29.49": { "d": "userNotice", "c": "X.509 extension", "w": false }, +"2.5.29.50": { "d": "sOAIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.51": { "d": "baseUpdateTime", "c": "X.509 extension", "w": false }, +"2.5.29.52": { "d": "acceptableCertPolicies", "c": "X.509 extension", "w": false }, +"2.5.29.53": { "d": "deltaInfo", "c": "X.509 extension", "w": false }, +"2.5.29.54": { "d": "inhibitAnyPolicy", "c": "X.509 extension", "w": false }, +"2.5.29.55": { "d": "targetInformation", "c": "X.509 extension", "w": false }, +"2.5.29.56": { "d": "noRevAvail", "c": "X.509 extension", "w": false }, +"2.5.29.57": { "d": "acceptablePrivilegePolicies", "c": "X.509 extension", "w": false }, +"2.5.29.58": { "d": "toBeRevoked", "c": "X.509 extension", "w": false }, +"2.5.29.59": { "d": "revokedGroups", "c": "X.509 extension", "w": false }, +"2.5.29.60": { "d": "expiredCertsOnCRL", "c": "X.509 extension", "w": false }, +"2.5.29.61": { "d": "indirectIssuer", "c": "X.509 extension", "w": false }, +"2.5.29.62": { "d": "noAssertion", "c": "X.509 extension", "w": false }, +"2.5.29.63": { "d": "aAissuingDistributionPoint", "c": "X.509 extension", "w": false }, +"2.5.29.64": { "d": "issuedOnBehalfOf", "c": "X.509 extension", "w": false }, +"2.5.29.65": { "d": "singleUse", "c": "X.509 extension", "w": false }, +"2.5.29.66": { "d": "groupAC", "c": "X.509 extension", "w": false }, +"2.5.29.67": { "d": "allowedAttAss", "c": "X.509 extension", "w": false }, +"2.5.29.68": { "d": "attributeMappings", "c": "X.509 extension", "w": false }, +"2.5.29.69": { "d": "holderNameConstraints", "c": "X.509 extension", "w": false }, +"2.16.724.1.2.2.4.1": { "d": "personalDataInfo", "c": "Spanish Government PKI?", "w": false }, +"2.16.840.1.101.2.1.1.1": { "d": "sdnsSignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.2": { "d": "fortezzaSignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicSignatureAlgorithm, this OID is better known as dsaWithSHA-1.", "w": false }, +"2.16.840.1.101.2.1.1.3": { "d": "sdnsConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.4": { "d": "fortezzaConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicConfidentialityAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.5": { "d": "sdnsIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.6": { "d": "fortezzaIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicIntegrityAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.7": { "d": "sdnsTokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.8": { "d": "fortezzaTokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly know as mosaicTokenProtectionAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.9": { "d": "sdnsKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.10": { "d": "fortezzaKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKeyManagementAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.11": { "d": "sdnsKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.12": { "d": "fortezzaKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKMandSigAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.13": { "d": "suiteASignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.14": { "d": "suiteAConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.15": { "d": "suiteAIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.16": { "d": "suiteATokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.17": { "d": "suiteAKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.18": { "d": "suiteAKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.19": { "d": "fortezzaUpdatedSigAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicUpdatedSigAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.20": { "d": "fortezzaKMandUpdSigAlgorithms", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKMandUpdSigAlgorithms", "w": false }, +"2.16.840.1.101.2.1.1.21": { "d": "fortezzaUpdatedIntegAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicUpdatedIntegAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.22": { "d": "keyExchangeAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKeyEncryptionAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.23": { "d": "fortezzaWrap80Algorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.24": { "d": "kEAKeyEncryptionAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.2.1": { "d": "rfc822MessageFormat", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.2": { "d": "emptyContent", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.3": { "d": "cspContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.42": { "d": "mspRev3ContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.48": { "d": "mspContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.49": { "d": "mspRekeyAgentProtocol", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.50": { "d": "mspMMP", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.66": { "d": "mspRev3-1ContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.72": { "d": "forwardedMSPMessageBodyPart", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.73": { "d": "mspForwardedMessageParameters", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.74": { "d": "forwardedCSPMsgBodyPart", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.75": { "d": "cspForwardedMessageParameters", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.76": { "d": "mspMMP2", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.3.1": { "d": "sdnsSecurityPolicy", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.2": { "d": "sdnsPRBAC", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.3": { "d": "mosaicPRBAC", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.10": { "d": "siSecurityPolicy", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.10.0": { "d": "siNASP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.1": { "d": "siELCO", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.2": { "d": "siTK", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.3": { "d": "siDSAP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.4": { "d": "siSSSS", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.5": { "d": "siDNASP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.6": { "d": "siBYEMAN", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.7": { "d": "siREL-US", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.8": { "d": "siREL-AUS", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.9": { "d": "siREL-CAN", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.10": { "d": "siREL_UK", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.11": { "d": "siREL-NZ", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.12": { "d": "siGeneric", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11": { "d": "genser", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.11.0": { "d": "genserNations", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.1": { "d": "genserComsec", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.2": { "d": "genserAcquisition", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.3": { "d": "genserSecurityCategories", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.11.3.0": { "d": "genserTagSetName", "c": "SDN.700 INFOSEC GENSER policy", "w": false }, +"2.16.840.1.101.2.1.3.12": { "d": "defaultSecurityPolicy", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.13": { "d": "capcoMarkings", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.13.0": { "d": "capcoSecurityCategories", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.1": { "d": "capcoTagSetName1", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.2": { "d": "capcoTagSetName2", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.3": { "d": "capcoTagSetName3", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.4": { "d": "capcoTagSetName4", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.5.1": { "d": "sdnsKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.2": { "d": "sdnsUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.3": { "d": "sdnsKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.4": { "d": "fortezzaKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.5": { "d": "fortezzaKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.6": { "d": "fortezzaUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.7": { "d": "fortezzaCASignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.8": { "d": "sdnsCASignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.10": { "d": "auxiliaryVector", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.11": { "d": "mlReceiptPolicy", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.12": { "d": "mlMembership", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.13": { "d": "mlAdministrators", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.14": { "d": "alid", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.20": { "d": "janUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.21": { "d": "febUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.22": { "d": "marUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.23": { "d": "aprUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.24": { "d": "mayUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.25": { "d": "junUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.26": { "d": "julUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.27": { "d": "augUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.28": { "d": "sepUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.29": { "d": "octUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.30": { "d": "novUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.31": { "d": "decUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.40": { "d": "metaSDNSckl", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.41": { "d": "sdnsCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.42": { "d": "metaSDNSsignatureCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.43": { "d": "sdnsSignatureCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.44": { "d": "sdnsCertificateRevocationList", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.45": { "d": "fortezzaCertificateRevocationList", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.46": { "d": "fortezzaCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.47": { "d": "alExemptedAddressProcessor", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.48": { "d": "guard", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.49": { "d": "algorithmsSupported", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.50": { "d": "suiteAKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.51": { "d": "suiteAKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.52": { "d": "suiteAUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.53": { "d": "prbacInfo", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.54": { "d": "prbacCAConstraints", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.55": { "d": "sigOrKMPrivileges", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.56": { "d": "commPrivileges", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.57": { "d": "labeledAttribute", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.58": { "d": "policyInformationFile", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.59": { "d": "secPolicyInformationFile", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.60": { "d": "cAClearanceConstraint", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.7.1": { "d": "cspExtns", "c": "SDN.700 INFOSEC extensions", "w": false }, +"2.16.840.1.101.2.1.7.1.0": { "d": "cspCsExtn", "c": "SDN.700 INFOSEC extensions", "w": false }, +"2.16.840.1.101.2.1.8.1": { "d": "mISSISecurityCategories", "c": "SDN.700 INFOSEC security category", "w": false }, +"2.16.840.1.101.2.1.8.2": { "d": "standardSecurityLabelPrivileges", "c": "SDN.700 INFOSEC security category", "w": false }, +"2.16.840.1.101.2.1.10.1": { "d": "sigPrivileges", "c": "SDN.700 INFOSEC privileges", "w": false }, +"2.16.840.1.101.2.1.10.2": { "d": "kmPrivileges", "c": "SDN.700 INFOSEC privileges", "w": false }, +"2.16.840.1.101.2.1.10.3": { "d": "namedTagSetPrivilege", "c": "SDN.700 INFOSEC privileges", "w": false }, +"2.16.840.1.101.2.1.11.1": { "d": "ukDemo", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.2": { "d": "usDODClass2", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.3": { "d": "usMediumPilot", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.4": { "d": "usDODClass4", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.5": { "d": "usDODClass3", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.6": { "d": "usDODClass5", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.12.0": { "d": "testSecurityPolicy", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1": { "d": "tsp1", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0": { "d": "tsp1SecurityCategories", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0.0": { "d": "tsp1TagSetZero", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0.1": { "d": "tsp1TagSetOne", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0.2": { "d": "tsp1TagSetTwo", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2": { "d": "tsp2", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0": { "d": "tsp2SecurityCategories", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0.0": { "d": "tsp2TagSetZero", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0.1": { "d": "tsp2TagSetOne", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0.2": { "d": "tsp2TagSetTwo", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3": { "d": "kafka", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0": { "d": "kafkaSecurityCategories", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0.1": { "d": "kafkaTagSetName1", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0.2": { "d": "kafkaTagSetName2", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0.3": { "d": "kafkaTagSetName3", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.1.1": { "d": "tcp1", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.3.1": { "d": "slabel", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.2": { "d": "pki", "c": "NIST", "w": true }, +"2.16.840.1.101.3.2.1": { "d": "NIST policyIdentifier", "c": "NIST policies", "w": true }, +"2.16.840.1.101.3.2.1.3.1": { "d": "fbcaRudimentaryPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.3.2": { "d": "fbcaBasicPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.3.3": { "d": "fbcaMediumPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.3.4": { "d": "fbcaHighPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.48.1": { "d": "nistTestPolicy1", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.2": { "d": "nistTestPolicy2", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.3": { "d": "nistTestPolicy3", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.4": { "d": "nistTestPolicy4", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.5": { "d": "nistTestPolicy5", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.6": { "d": "nistTestPolicy6", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.2": { "d": "gak", "c": "CSOR GAK extended key usage", "w": true }, +"2.16.840.1.101.3.2.2.1": { "d": "kRAKey", "c": "CSOR GAK extended key usage", "w": true }, +"2.16.840.1.101.3.2.3": { "d": "extensions", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.1": { "d": "kRTechnique", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.2": { "d": "kRecoveryCapable", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.3": { "d": "kR", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.4": { "d": "keyRecoverySchemes", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.2.5": { "d": "krapola", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.3": { "d": "arpa", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.4": { "d": "nistAlgorithm", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1": { "d": "aes", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.1": { "d": "aes128-ECB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.2": { "d": "aes128-CBC", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.3": { "d": "aes128-OFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.4": { "d": "aes128-CFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.5": { "d": "aes128-wrap", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.6": { "d": "aes128-GCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.7": { "d": "aes128-CCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.8": { "d": "aes128-wrap-pad", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.21": { "d": "aes192-ECB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.22": { "d": "aes192-CBC", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.23": { "d": "aes192-OFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.24": { "d": "aes192-CFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.25": { "d": "aes192-wrap", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.26": { "d": "aes192-GCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.27": { "d": "aes192-CCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.28": { "d": "aes192-wrap-pad", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.41": { "d": "aes256-ECB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.42": { "d": "aes256-CBC", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.43": { "d": "aes256-OFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.44": { "d": "aes256-CFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.45": { "d": "aes256-wrap", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.46": { "d": "aes256-GCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.47": { "d": "aes256-CCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.48": { "d": "aes256-wrap-pad", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2": { "d": "hashAlgos", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.1": { "d": "sha-256", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.2": { "d": "sha-384", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.3": { "d": "sha-512", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.4": { "d": "sha-224", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.3.1": { "d": "dsaWithSha224", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.3.2": { "d": "dsaWithSha256", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.113719.1.2.8": { "d": "novellAlgorithm", "c": "Novell", "w": false }, +"2.16.840.1.113719.1.2.8.22": { "d": "desCbcIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.23": { "d": "desCbcPadIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.24": { "d": "desEDE2CbcIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.25": { "d": "desEDE2CbcPadIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.26": { "d": "desEDE3CbcIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.27": { "d": "desEDE3CbcPadIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.28": { "d": "rc5CbcPad", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.29": { "d": "md2WithRSAEncryptionBSafe1", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.30": { "d": "md5WithRSAEncryptionBSafe1", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.31": { "d": "sha1WithRSAEncryptionBSafe1", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.32": { "d": "lmDigest", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.40": { "d": "md2", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.50": { "d": "md5", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.51": { "d": "ikeHmacWithSHA1-RSA", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.52": { "d": "ikeHmacWithMD5-RSA", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.69": { "d": "rc2CbcPad", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.82": { "d": "sha-1", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.92": { "d": "rc2BSafe1Cbc", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.95": { "d": "md4", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.130": { "d": "md4Packet", "c": "Novell keyed hash", "w": false }, +"2.16.840.1.113719.1.2.8.131": { "d": "rsaEncryptionBsafe1", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.132": { "d": "nwPassword", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.133": { "d": "novellObfuscate-1", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.9": { "d": "pki", "c": "Novell", "w": false }, +"2.16.840.1.113719.1.9.4": { "d": "pkiAttributeType", "c": "Novell PKI", "w": false }, +"2.16.840.1.113719.1.9.4.1": { "d": "securityAttributes", "c": "Novell PKI attribute type", "w": false }, +"2.16.840.1.113719.1.9.4.2": { "d": "relianceLimit", "c": "Novell PKI attribute type", "w": false }, +"2.16.840.1.113730.1": { "d": "cert-extension", "c": "Netscape", "w": false }, +"2.16.840.1.113730.1.1": { "d": "netscape-cert-type", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.2": { "d": "netscape-base-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.3": { "d": "netscape-revocation-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.4": { "d": "netscape-ca-revocation-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.7": { "d": "netscape-cert-renewal-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.8": { "d": "netscape-ca-policy-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.9": { "d": "HomePage-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.10": { "d": "EntityLogo", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.11": { "d": "UserPicture", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.12": { "d": "netscape-ssl-server-name", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.13": { "d": "netscape-comment", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.2": { "d": "data-type", "c": "Netscape", "w": false }, +"2.16.840.1.113730.2.1": { "d": "dataGIF", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.2": { "d": "dataJPEG", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.3": { "d": "dataURL", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.4": { "d": "dataHTML", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.5": { "d": "certSequence", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.6": { "d": "certURL", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.3": { "d": "directory", "c": "Netscape", "w": false }, +"2.16.840.1.113730.3.1": { "d": "ldapDefinitions", "c": "Netscape directory", "w": false }, +"2.16.840.1.113730.3.1.1": { "d": "carLicense", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.1.2": { "d": "departmentNumber", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.1.3": { "d": "employeeNumber", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.1.4": { "d": "employeeType", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.2.2": { "d": "inetOrgPerson", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.4.1": { "d": "serverGatedCrypto", "c": "Netscape", "w": false }, +"2.16.840.1.113733.1.6.3": { "d": "verisignCZAG", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.6": { "d": "verisignInBox", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.11": { "d": "verisignOnsiteJurisdictionHash", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.13": { "d": "Unknown Verisign VPN extension", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.15": { "d": "verisignServerID", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.7.1.1": { "d": "verisignCertPolicies95Qualifier1", "c": "Verisign policy", "w": false }, +"2.16.840.1.113733.1.7.1.1.1": { "d": "verisignCPSv1notice", "c": "Verisign policy (obsolete)", "w": false }, +"2.16.840.1.113733.1.7.1.1.2": { "d": "verisignCPSv1nsi", "c": "Verisign policy (obsolete)", "w": false }, +"2.16.840.1.113733.1.7.23.6": { "d": "verisignEVPolicy", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.8.1": { "d": "verisignISSStrongCrypto", "c": "Verisign", "w": false }, +"2.16.840.1.113733.1": { "d": "pki", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.9": { "d": "pkcs7Attribute", "c": "Verisign PKI extension", "w": false }, +"2.16.840.1.113733.1.9.2": { "d": "messageType", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.3": { "d": "pkiStatus", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.4": { "d": "failInfo", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.5": { "d": "senderNonce", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.6": { "d": "recipientNonce", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.7": { "d": "transID", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.8": { "d": "extensionReq", "c": "Verisign PKCS #7 attribute. Use PKCS #9 extensionRequest instead", "w": true }, +"2.16.840.1.114412.1.3.0.1": { "d": "digiCertGlobalCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.16.840.1.114412.1.3.0.2": { "d": "digiCertHighAssuranceEVCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.16.840.1.114412.1.3.0.3": { "d": "digiCertGlobalRootCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.16.840.1.114412.1.3.0.4": { "d": "digiCertAssuredIDRootCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.23.42.0": { "d": "contentType", "c": "SET", "w": false }, +"2.23.42.0.0": { "d": "panData", "c": "SET contentType", "w": false }, +"2.23.42.0.1": { "d": "panToken", "c": "SET contentType", "w": false }, +"2.23.42.0.2": { "d": "panOnly", "c": "SET contentType", "w": false }, +"2.23.42.1": { "d": "msgExt", "c": "SET", "w": false }, +"2.23.42.2": { "d": "field", "c": "SET", "w": false }, +"2.23.42.2.0": { "d": "fullName", "c": "SET field", "w": false }, +"2.23.42.2.1": { "d": "givenName", "c": "SET field", "w": false }, +"2.23.42.2.2": { "d": "familyName", "c": "SET field", "w": false }, +"2.23.42.2.3": { "d": "birthFamilyName", "c": "SET field", "w": false }, +"2.23.42.2.4": { "d": "placeName", "c": "SET field", "w": false }, +"2.23.42.2.5": { "d": "identificationNumber", "c": "SET field", "w": false }, +"2.23.42.2.6": { "d": "month", "c": "SET field", "w": false }, +"2.23.42.2.7": { "d": "date", "c": "SET field", "w": false }, +"2.23.42.2.8": { "d": "address", "c": "SET field", "w": false }, +"2.23.42.2.9": { "d": "telephone", "c": "SET field", "w": false }, +"2.23.42.2.10": { "d": "amount", "c": "SET field", "w": false }, +"2.23.42.2.11": { "d": "accountNumber", "c": "SET field", "w": false }, +"2.23.42.2.12": { "d": "passPhrase", "c": "SET field", "w": false }, +"2.23.42.3": { "d": "attribute", "c": "SET", "w": false }, +"2.23.42.3.0": { "d": "cert", "c": "SET attribute", "w": false }, +"2.23.42.3.0.0": { "d": "rootKeyThumb", "c": "SET cert attribute", "w": false }, +"2.23.42.3.0.1": { "d": "additionalPolicy", "c": "SET cert attribute", "w": false }, +"2.23.42.4": { "d": "algorithm", "c": "SET", "w": false }, +"2.23.42.5": { "d": "policy", "c": "SET", "w": false }, +"2.23.42.5.0": { "d": "root", "c": "SET policy", "w": false }, +"2.23.42.6": { "d": "module", "c": "SET", "w": false }, +"2.23.42.7": { "d": "certExt", "c": "SET", "w": false }, +"2.23.42.7.0": { "d": "hashedRootKey", "c": "SET cert extension", "w": false }, +"2.23.42.7.1": { "d": "certificateType", "c": "SET cert extension", "w": false }, +"2.23.42.7.2": { "d": "merchantData", "c": "SET cert extension", "w": false }, +"2.23.42.7.3": { "d": "cardCertRequired", "c": "SET cert extension", "w": false }, +"2.23.42.7.4": { "d": "tunneling", "c": "SET cert extension", "w": false }, +"2.23.42.7.5": { "d": "setExtensions", "c": "SET cert extension", "w": false }, +"2.23.42.7.6": { "d": "setQualifier", "c": "SET cert extension", "w": false }, +"2.23.42.8": { "d": "brand", "c": "SET", "w": false }, +"2.23.42.8.1": { "d": "IATA-ATA", "c": "SET brand", "w": false }, +"2.23.42.8.4": { "d": "VISA", "c": "SET brand", "w": false }, +"2.23.42.8.5": { "d": "MasterCard", "c": "SET brand", "w": false }, +"2.23.42.8.30": { "d": "Diners", "c": "SET brand", "w": false }, +"2.23.42.8.34": { "d": "AmericanExpress", "c": "SET brand", "w": false }, +"2.23.42.8.6011": { "d": "Novus", "c": "SET brand", "w": false }, +"2.23.42.9": { "d": "vendor", "c": "SET", "w": false }, +"2.23.42.9.0": { "d": "GlobeSet", "c": "SET vendor", "w": false }, +"2.23.42.9.1": { "d": "IBM", "c": "SET vendor", "w": false }, +"2.23.42.9.2": { "d": "CyberCash", "c": "SET vendor", "w": false }, +"2.23.42.9.3": { "d": "Terisa", "c": "SET vendor", "w": false }, +"2.23.42.9.4": { "d": "RSADSI", "c": "SET vendor", "w": false }, +"2.23.42.9.5": { "d": "VeriFone", "c": "SET vendor", "w": false }, +"2.23.42.9.6": { "d": "TrinTech", "c": "SET vendor", "w": false }, +"2.23.42.9.7": { "d": "BankGate", "c": "SET vendor", "w": false }, +"2.23.42.9.8": { "d": "GTE", "c": "SET vendor", "w": false }, +"2.23.42.9.9": { "d": "CompuSource", "c": "SET vendor", "w": false }, +"2.23.42.9.10": { "d": "Griffin", "c": "SET vendor", "w": false }, +"2.23.42.9.11": { "d": "Certicom", "c": "SET vendor", "w": false }, +"2.23.42.9.12": { "d": "OSS", "c": "SET vendor", "w": false }, +"2.23.42.9.13": { "d": "TenthMountain", "c": "SET vendor", "w": false }, +"2.23.42.9.14": { "d": "Antares", "c": "SET vendor", "w": false }, +"2.23.42.9.15": { "d": "ECC", "c": "SET vendor", "w": false }, +"2.23.42.9.16": { "d": "Maithean", "c": "SET vendor", "w": false }, +"2.23.42.9.17": { "d": "Netscape", "c": "SET vendor", "w": false }, +"2.23.42.9.18": { "d": "Verisign", "c": "SET vendor", "w": false }, +"2.23.42.9.19": { "d": "BlueMoney", "c": "SET vendor", "w": false }, +"2.23.42.9.20": { "d": "Lacerte", "c": "SET vendor", "w": false }, +"2.23.42.9.21": { "d": "Fujitsu", "c": "SET vendor", "w": false }, +"2.23.42.9.22": { "d": "eLab", "c": "SET vendor", "w": false }, +"2.23.42.9.23": { "d": "Entrust", "c": "SET vendor", "w": false }, +"2.23.42.9.24": { "d": "VIAnet", "c": "SET vendor", "w": false }, +"2.23.42.9.25": { "d": "III", "c": "SET vendor", "w": false }, +"2.23.42.9.26": { "d": "OpenMarket", "c": "SET vendor", "w": false }, +"2.23.42.9.27": { "d": "Lexem", "c": "SET vendor", "w": false }, +"2.23.42.9.28": { "d": "Intertrader", "c": "SET vendor", "w": false }, +"2.23.42.9.29": { "d": "Persimmon", "c": "SET vendor", "w": false }, +"2.23.42.9.30": { "d": "NABLE", "c": "SET vendor", "w": false }, +"2.23.42.9.31": { "d": "espace-net", "c": "SET vendor", "w": false }, +"2.23.42.9.32": { "d": "Hitachi", "c": "SET vendor", "w": false }, +"2.23.42.9.33": { "d": "Microsoft", "c": "SET vendor", "w": false }, +"2.23.42.9.34": { "d": "NEC", "c": "SET vendor", "w": false }, +"2.23.42.9.35": { "d": "Mitsubishi", "c": "SET vendor", "w": false }, +"2.23.42.9.36": { "d": "NCR", "c": "SET vendor", "w": false }, +"2.23.42.9.37": { "d": "e-COMM", "c": "SET vendor", "w": false }, +"2.23.42.9.38": { "d": "Gemplus", "c": "SET vendor", "w": false }, +"2.23.42.10": { "d": "national", "c": "SET", "w": false }, +"2.23.42.10.392": { "d": "Japan", "c": "SET national", "w": false }, +"2.23.136.1.1.1": { "d": "mRTDSignatureData", "c": "ICAO MRTD", "w": false }, +"2.54.1775.2": { "d": "hashedRootKey", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.3": { "d": "certificateType", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.4": { "d": "merchantData", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.5": { "d": "cardCertRequired", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.6": { "d": "tunneling", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.7": { "d": "setQualifier", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.99": { "d": "setData", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"1.3.6.1.4.1.6449.1.2.1.5.1": { "d": "AddTrust EV policy", "c": "AddTrust External CA Root", "w": false }, +"1.3.6.1.4.1.34697.2.1": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Commercial", "w": false }, +"1.3.6.1.4.1.34697.2.2": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Networking", "w": false }, +"1.3.6.1.4.1.34697.2.3": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Premium", "w": false }, +"1.3.6.1.4.1.34697.2.4": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Premium ECC", "w": false }, +"2.16.578.1.26.1.3.3": { "d": "BuyPass EV policy", "c": "BuyPass Class 3 EV", "w": false }, +"1.3.6.1.4.1.22234.2.5.2.3.1": { "d": "CertPlus EV policy", "c": "CertPlus Class 2 Primary CA (KEYNECTIS)", "w": false }, +"1.3.6.1.4.1.6334.1.100.1": { "d": "Cybertrust EV policy", "c": "Cybertrust Global Root", "w": false }, +"2.16.840.1.114412.2.1": { "d": "DigiCert EV policy", "c": "DigiCert High Assurance EV Root CA", "w": false }, +"2.16.528.1.1001.1.1.1.12.6.1.1.1": { "d": "DigiNotar EV policy", "c": "DigiNotar Root CA", "w": false }, +"2.16.840.1.114028.10.1.2": { "d": "Entrust EV policy", "c": "Entrust Net Secure Server Certification Authority", "w": false }, +"1.3.6.1.4.1.14370.1.6": { "d": "Equifax EV policy", "c": "Equifax Secure Certificate Authority (GeoTrust)", "w": false }, +"1.3.6.1.4.1.4146.1.1": { "d": "GlobalSign EV policy", "c": "GlobalSign", "w": false }, +"2.16.840.1.114413.1.7.23.3": { "d": "GoDaddy EV policy", "c": "GoDaddy Class 2 Certification Authority", "w": false }, +"1.3.6.1.4.1.14777.6.1.1": { "d": "Izenpe EV policy", "c": "Certificado de Servidor Seguro SSL EV", "w": false }, +"1.3.6.1.4.1.14777.6.1.2": { "d": "Izenpe EV policy", "c": "Certificado de Sede Electronica EV", "w": false }, +"1.3.6.1.4.1.782.1.2.1.8.1": { "d": "Network Solutions EV policy", "c": "Network Solutions Certificate Authority", "w": false }, +"1.3.6.1.4.1.8024.0.2.100.1.2": { "d": "QuoVadis EV policy", "c": "QuoVadis Root CA 2", "w": false }, +"1.2.392.200091.100.721.1": { "d": "SECOM EV policy", "c": "SECOM Trust Systems EV", "w": false }, +"2.16.840.1.114404.1.1.2.4.1": { "d": "SecureTrust EV policy", "c": "SecureTrust CA, SecureTrust Corporation", "w": false }, +"1.3.6.1.4.1.23223.1.1.1": { "d": "StartCom EV policy", "c": "StartCom Certification Authority", "w": false }, +"2.16.840.1.114414.1.7.23.3": { "d": "Starfield EV policy", "c": "Starfield Class 2 Certification Authority", "w": false }, +"2.16.756.1.89.1.2.1.1": { "d": "SwissSign EV policy", "c": "SwissSign Gold CA - G2", "w": false }, +"2.16.840.1.113733.1.7.48.1": { "d": "Thawte EV policy", "c": "Thawte Premium Server CA", "w": false }, +"2.16.840.1.114171.500.9": { "d": "Wells Fargo EV policy", "c": "Wells Fargo WellsSecure Public Root Certificate Authority", "w": false }, +"END": "" +}; \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/LICENSE.txt new file mode 100644 index 0000000..e37d457 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/LICENSE.txt @@ -0,0 +1,42 @@ + + +Licensing +--------- + +This software is covered under the following copyright: + +/* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + +Address all questions regarding this license to: + + Tom Wu + tjw@cs.Stanford.EDU \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/README.md b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/README.md new file mode 100644 index 0000000..9ed2a96 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/README.md @@ -0,0 +1,6 @@ +These files are downloaded from http://www-cs-students.stanford.edu/~tjw/jsbn/ + +Here is a list of changes made to this library: + + - https://github.com/travist/jsencrypt/pull/6 + diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/base64.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/base64.ts new file mode 100644 index 0000000..424b880 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/base64.ts @@ -0,0 +1,76 @@ +import {int2char} from "./util"; + +const b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const b64pad = "="; + +export function hex2b64(h:string) { + let i; + let c; + let ret = ""; + for (i = 0; i + 3 <= h.length; i += 3) { + c = parseInt(h.substring(i, i + 3), 16); + ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63); + } + if (i + 1 == h.length) { + c = parseInt(h.substring(i, i + 1), 16); + ret += b64map.charAt(c << 2); + } else if (i + 2 == h.length) { + c = parseInt(h.substring(i, i + 2), 16); + ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); + } + while ((ret.length & 3) > 0) { + ret += b64pad; + } + return ret; +} + +// convert a base64 string to hex +export function b64tohex(s:string) { + let ret = ""; + let i; + let k = 0; // b64 state, 0-3 + let slop = 0; + for (i = 0; i < s.length; ++i) { + if (s.charAt(i) == b64pad) { + break; + } + const v = b64map.indexOf(s.charAt(i)); + if (v < 0) { + continue; + } + if (k == 0) { + ret += int2char(v >> 2); + slop = v & 3; + k = 1; + } else if (k == 1) { + ret += int2char((slop << 2) | (v >> 4)); + slop = v & 0xf; + k = 2; + } else if (k == 2) { + ret += int2char(slop); + ret += int2char(v >> 2); + slop = v & 3; + k = 3; + } else { + ret += int2char((slop << 2) | (v >> 4)); + ret += int2char(v & 0xf); + k = 0; + } + } + if (k == 1) { + ret += int2char(slop << 2); + } + return ret; +} + +// convert a base64 string to a byte/number array +export function b64toBA(s:string) { + // piggyback on b64tohex for now, optimize later + const h = b64tohex(s); + let i; + const a = []; + for (i = 0; 2 * i < h.length; ++i) { + a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16); + } + return a; +} diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/jsbn.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/jsbn.ts new file mode 100644 index 0000000..9fdb7d3 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/jsbn.ts @@ -0,0 +1,1928 @@ +// Copyright (c) 2005 Tom Wu +// All Rights Reserved. +// See "LICENSE" for details. + +// Basic JavaScript BN library - subset useful for RSA encryption. + +import {cbit, int2char, lbit, op_and, op_andnot, op_or, op_xor} from "./util"; +import {SecureRandom} from "./rng"; +// Bits per digit +let dbits; + +// JavaScript engine analysis +const canary = 0xdeadbeefcafe; +const j_lm = ((canary & 0xffffff) == 0xefcafe); + + +//#region +const lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]; +const lplim = (1 << 26) / lowprimes[lowprimes.length - 1]; +//#endregion + +// (public) Constructor +export class BigInteger { + constructor(a:number|number[]|string, b?:number|SecureRandom, c?:number|SecureRandom) { + if (a != null) { + if ("number" == typeof a) { + this.fromNumber(a, b, c); + } else if (b == null && "string" != typeof a) { + this.fromString(a, 256); + } else { + this.fromString(a, b as number); + } + } + } + + //#region PUBLIC + + // BigInteger.prototype.toString = bnToString; + // (public) return string representation in given radix + public toString(b:number):string { + if (this.s < 0) { + return "-" + this.negate().toString(b); + } + let k; + if (b == 16) { + k = 4; + } else if (b == 8) { + k = 3; + } else if (b == 2) { + k = 1; + } else if (b == 32) { + k = 5; + } else if (b == 4) { + k = 2; + } else { + return this.toRadix(b); + } + const km = (1 << k) - 1; + let d; + let m = false; + let r = ""; + let i = this.t; + let p = this.DB - (i * this.DB) % k; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) > 0) { + m = true; + r = int2char(d); + } + while (i >= 0) { + if (p < k) { + d = (this[i] & ((1 << p) - 1)) << (k - p); + d |= this[--i] >> (p += this.DB - k); + } else { + d = (this[i] >> (p -= k)) & km; + if (p <= 0) { + p += this.DB; + --i; + } + } + if (d > 0) { + m = true; + } + if (m) { + r += int2char(d); + } + } + } + return m ? r : "0"; + } + + + // BigInteger.prototype.negate = bnNegate; + // (public) -this + protected negate():BigInteger { + const r = nbi(); + BigInteger.ZERO.subTo(this, r); + return r; + } + + + // BigInteger.prototype.abs = bnAbs; + // (public) |this| + public abs() { + return (this.s < 0) ? this.negate() : this; + } + + + // BigInteger.prototype.compareTo = bnCompareTo; + // (public) return + if this > a, - if this < a, 0 if equal + public compareTo(a:BigInteger):number { + let r = this.s - a.s; + if (r != 0) { + return r; + } + let i = this.t; + r = i - a.t; + if (r != 0) { + return (this.s < 0) ? -r : r; + } + while (--i >= 0) { + if ((r = this[i] - a[i]) != 0) { + return r; + } + } + return 0; + } + + + // BigInteger.prototype.bitLength = bnBitLength; + // (public) return the number of bits in "this" + public bitLength() { + if (this.t <= 0) { + return 0; + } + return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM)); + } + + + // BigInteger.prototype.mod = bnMod; + // (public) this mod a + public mod(a:BigInteger):BigInteger { + const r = nbi(); + this.abs().divRemTo(a, null, r); + if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { + a.subTo(r, r); + } + return r; + } + + + // BigInteger.prototype.modPowInt = bnModPowInt; + // (public) this^e % m, 0 <= e < 2^32 + public modPowInt(e:number, m:BigInteger):BigInteger { + let z; + if (e < 256 || m.isEven()) { + z = new Classic(m); + } else { + z = new Montgomery(m); + } + return this.exp(e, z); + } + + + // BigInteger.prototype.clone = bnClone; + // (public) + protected clone():BigInteger { + const r = nbi(); + this.copyTo(r); + return r; + } + + + // BigInteger.prototype.intValue = bnIntValue; + // (public) return value as integer + protected intValue() { + if (this.s < 0) { + if (this.t == 1) { + return this[0] - this.DV; + } else if (this.t == 0) { + return -1; + } + } else if (this.t == 1) { + return this[0]; + } else if (this.t == 0) { + return 0; + } + // assumes 16 < DB < 32 + return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0]; + } + + + // BigInteger.prototype.byteValue = bnByteValue; + // (public) return value as byte + protected byteValue() { + return (this.t == 0) ? this.s : (this[0] << 24) >> 24; + } + + + // BigInteger.prototype.shortValue = bnShortValue; + // (public) return value as short (assumes DB>=16) + protected shortValue() { + return (this.t == 0) ? this.s : (this[0] << 16) >> 16; + } + + + // BigInteger.prototype.signum = bnSigNum; + // (public) 0 if this == 0, 1 if this > 0 + protected signum() { + if (this.s < 0) { + return -1; + } else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) { + return 0; + } else { + return 1; + } + } + + + // BigInteger.prototype.toByteArray = bnToByteArray; + // (public) convert to bigendian byte array + public toByteArray():number[] { + let i = this.t; + const r = []; + r[0] = this.s; + let p = this.DB - (i * this.DB) % 8; + let d; + let k = 0; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p) { + r[k++] = d | (this.s << (this.DB - p)); + } + while (i >= 0) { + if (p < 8) { + d = (this[i] & ((1 << p) - 1)) << (8 - p); + d |= this[--i] >> (p += this.DB - 8); + } else { + d = (this[i] >> (p -= 8)) & 0xff; + if (p <= 0) { + p += this.DB; + --i; + } + } + if ((d & 0x80) != 0) { + d |= -256; + } + if (k == 0 && (this.s & 0x80) != (d & 0x80)) { + ++k; + } + if (k > 0 || d != this.s) { + r[k++] = d; + } + } + } + return r; + } + + + // BigInteger.prototype.equals = bnEquals; + protected equals(a:BigInteger):boolean { + return (this.compareTo(a) == 0); + } + + + // BigInteger.prototype.min = bnMin; + protected min(a:BigInteger):BigInteger { + return (this.compareTo(a) < 0) ? this : a; + } + + + // BigInteger.prototype.max = bnMax; + protected max(a:BigInteger):BigInteger { + return (this.compareTo(a) > 0) ? this : a; + } + + + // BigInteger.prototype.and = bnAnd; + protected and(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_and, r); + return r; + } + + + // BigInteger.prototype.or = bnOr; + protected or(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_or, r); + return r; + } + + + // BigInteger.prototype.xor = bnXor; + protected xor(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_xor, r); + return r; + } + + + // BigInteger.prototype.andNot = bnAndNot; + protected andNot(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_andnot, r); + return r; + } + + + // BigInteger.prototype.not = bnNot; + // (public) ~this + protected not():BigInteger { + const r = nbi(); + for (let i = 0; i < this.t; ++i) { + r[i] = this.DM & ~this[i]; + } + r.t = this.t; + r.s = ~this.s; + return r; + } + + + // BigInteger.prototype.shiftLeft = bnShiftLeft; + // (public) this << n + protected shiftLeft(n:number) { + const r = nbi(); + if (n < 0) { + this.rShiftTo(-n, r); + } else { + this.lShiftTo(n, r); + } + return r; + } + + + // BigInteger.prototype.shiftRight = bnShiftRight; + // (public) this >> n + protected shiftRight(n:number) { + const r = nbi(); + if (n < 0) { + this.lShiftTo(-n, r); + } else { + this.rShiftTo(n, r); + } + return r; + } + + + // BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; + // (public) returns index of lowest 1-bit (or -1 if none) + protected getLowestSetBit() { + for (let i = 0; i < this.t; ++i) { + if (this[i] != 0) { + return i * this.DB + lbit(this[i]); + } + } + if (this.s < 0) { + return this.t * this.DB; + } + return -1; + } + + + // BigInteger.prototype.bitCount = bnBitCount; + // (public) return number of set bits + protected bitCount() { + let r = 0; + const x = this.s & this.DM; + for (let i = 0; i < this.t; ++i) { + r += cbit(this[i] ^ x); + } + return r; + } + + + // BigInteger.prototype.testBit = bnTestBit; + // (public) true iff nth bit is set + protected testBit(n:number) { + const j = Math.floor(n / this.DB); + if (j >= this.t) { + return (this.s != 0); + } + return ((this[j] & (1 << (n % this.DB))) != 0); + } + + + // BigInteger.prototype.setBit = bnSetBit; + // (public) this | (1< 1) { + const g2 = nbi(); + z.sqrTo(g[1], g2); + while (n <= km) { + g[n] = nbi(); + z.mulTo(g2, g[n - 2], g[n]); + n += 2; + } + } + + let j = e.t - 1; + let w; + let is1 = true; + let r2 = nbi(); + let t; + i = nbits(e[j]) - 1; + while (j >= 0) { + if (i >= k1) { + w = (e[j] >> (i - k1)) & km; + } else { + w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i); + if (j > 0) { + w |= e[j - 1] >> (this.DB + i - k1); + } + } + + n = k; + while ((w & 1) == 0) { + w >>= 1; + --n; + } + if ((i -= n) < 0) { + i += this.DB; + --j; + } + if (is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r); + is1 = false; + } else { + while (n > 1) { + z.sqrTo(r, r2); + z.sqrTo(r2, r); + n -= 2; + } + if (n > 0) { + z.sqrTo(r, r2); + } else { + t = r; + r = r2; + r2 = t; + } + z.mulTo(r2, g[w], r); + } + + while (j >= 0 && (e[j] & (1 << i)) == 0) { + z.sqrTo(r, r2); + t = r; + r = r2; + r2 = t; + if (--i < 0) { + i = this.DB - 1; + --j; + } + } + } + return z.revert(r); + } + + + // BigInteger.prototype.modInverse = bnModInverse; + // (public) 1/this % m (HAC 14.61) + public modInverse(m:BigInteger) { + const ac = m.isEven(); + if ((this.isEven() && ac) || m.signum() == 0) { + return BigInteger.ZERO; + } + const u = m.clone(); + const v = this.clone(); + const a = nbv(1); + const b = nbv(0); + const c = nbv(0); + const d = nbv(1); + while (u.signum() != 0) { + while (u.isEven()) { + u.rShiftTo(1, u); + if (ac) { + if (!a.isEven() || !b.isEven()) { + a.addTo(this, a); + b.subTo(m, b); + } + a.rShiftTo(1, a); + } else if (!b.isEven()) { + b.subTo(m, b); + } + b.rShiftTo(1, b); + } + while (v.isEven()) { + v.rShiftTo(1, v); + if (ac) { + if (!c.isEven() || !d.isEven()) { + c.addTo(this, c); + d.subTo(m, d); + } + c.rShiftTo(1, c); + } else if (!d.isEven()) { + d.subTo(m, d); + } + d.rShiftTo(1, d); + } + if (u.compareTo(v) >= 0) { + u.subTo(v, u); + if (ac) { + a.subTo(c, a); + } + b.subTo(d, b); + } else { + v.subTo(u, v); + if (ac) { c.subTo(a, c); } + d.subTo(b, d); + } + } + if (v.compareTo(BigInteger.ONE) != 0) { + return BigInteger.ZERO; + } + if (d.compareTo(m) >= 0) { + return d.subtract(m); + } + if (d.signum() < 0) { + d.addTo(m, d); + } else { + return d; + } + if (d.signum() < 0) { + return d.add(m); + } else { + return d; + } + } + + + // BigInteger.prototype.pow = bnPow; + // (public) this^e + protected pow(e:number) { + return this.exp(e, new NullExp()); + } + + + // BigInteger.prototype.gcd = bnGCD; + // (public) gcd(this,a) (HAC 14.54) + public gcd(a:BigInteger) { + let x = (this.s < 0) ? this.negate() : this.clone(); + let y = (a.s < 0) ? a.negate() : a.clone(); + if (x.compareTo(y) < 0) { + const t = x; + x = y; + y = t; + } + let i = x.getLowestSetBit(); + let g = y.getLowestSetBit(); + if (g < 0) { + return x; + } + if (i < g) { + g = i; + } + if (g > 0) { + x.rShiftTo(g, x); + y.rShiftTo(g, y); + } + while (x.signum() > 0) { + if ((i = x.getLowestSetBit()) > 0) { + x.rShiftTo(i, x); + } + if ((i = y.getLowestSetBit()) > 0) { + y.rShiftTo(i, y); + } + if (x.compareTo(y) >= 0) { + x.subTo(y, x); + x.rShiftTo(1, x); + } else { + y.subTo(x, y); + y.rShiftTo(1, y); + } + } + if (g > 0) { + y.lShiftTo(g, y); + } + return y; + } + + + // BigInteger.prototype.isProbablePrime = bnIsProbablePrime; + // (public) test primality with certainty >= 1-.5^t + public isProbablePrime(t:number) { + let i; + const x = this.abs(); + if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) { + for (i = 0; i < lowprimes.length; ++i) { + if (x[0] == lowprimes[i]) { + return true; + } + } + return false; + } + if (x.isEven()) { + return false; + } + i = 1; + while (i < lowprimes.length) { + let m = lowprimes[i]; + let j = i + 1; + while (j < lowprimes.length && m < lplim) { + m *= lowprimes[j++]; + } + m = x.modInt(m); + while (i < j) { + if (m % lowprimes[i++] == 0) { + return false; + } + } + } + return x.millerRabin(t); + } + + + //#endregion PUBLIC + + //#region PROTECTED + + // BigInteger.prototype.copyTo = bnpCopyTo; + // (protected) copy this to r + public copyTo(r:BigInteger) { + for (let i = this.t - 1; i >= 0; --i) { + r[i] = this[i]; + } + r.t = this.t; + r.s = this.s; + } + + + // BigInteger.prototype.fromInt = bnpFromInt; + // (protected) set from integer value x, -DV <= x < DV + public fromInt(x:number) { + this.t = 1; + this.s = (x < 0) ? -1 : 0; + if (x > 0) { + this[0] = x; + } else if (x < -1) { + this[0] = x + this.DV; + } else { + this.t = 0; + } + } + + + // BigInteger.prototype.fromString = bnpFromString; + // (protected) set from string and radix + protected fromString(s:string|number[], b:number) { + let k; + if (b == 16) { + k = 4; + } else if (b == 8) { + k = 3; + } else if (b == 256) { + k = 8; + /* byte array */ + } else if (b == 2) { + k = 1; + } else if (b == 32) { + k = 5; + } else if (b == 4) { + k = 2; + } else { + this.fromRadix(s as string, b); + return; + } + this.t = 0; + this.s = 0; + let i = s.length; + let mi = false; + let sh = 0; + while (--i >= 0) { + const x = (k == 8) ? (+s[i]) & 0xff : intAt(s as string, i); + if (x < 0) { + if ((s as string).charAt(i) == "-") { + mi = true; + } + continue; + } + mi = false; + if (sh == 0) { + this[this.t++] = x; + } else if (sh + k > this.DB) { + this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh; + this[this.t++] = (x >> (this.DB - sh)); + } else { + this[this.t - 1] |= x << sh; + } + sh += k; + if (sh >= this.DB) { + sh -= this.DB; + } + } + if (k == 8 && ((+s[0]) & 0x80) != 0) { + this.s = -1; + if (sh > 0) { + this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh; + } + } + this.clamp(); + if (mi) { + BigInteger.ZERO.subTo(this, this); + } + } + + + // BigInteger.prototype.clamp = bnpClamp; + // (protected) clamp off excess high words + public clamp() { + const c = this.s & this.DM; + while (this.t > 0 && this[this.t - 1] == c) { + --this.t; + } + } + + + // BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + // (protected) r = this << n*DB + public dlShiftTo(n:number, r:BigInteger) { + let i; + for (i = this.t - 1; i >= 0; --i) { + r[i + n] = this[i]; + } + for (i = n - 1; i >= 0; --i) { + r[i] = 0; + } + r.t = this.t + n; + r.s = this.s; + } + + + // BigInteger.prototype.drShiftTo = bnpDRShiftTo; + // (protected) r = this >> n*DB + public drShiftTo(n:number, r:BigInteger) { + for (let i = n; i < this.t; ++i) { + r[i - n] = this[i]; + } + r.t = Math.max(this.t - n, 0); + r.s = this.s; + } + + + // BigInteger.prototype.lShiftTo = bnpLShiftTo; + // (protected) r = this << n + protected lShiftTo(n:number, r:BigInteger) { + const bs = n % this.DB; + const cbs = this.DB - bs; + const bm = (1 << cbs) - 1; + const ds = Math.floor(n / this.DB); + let c = (this.s << bs) & this.DM; + + for (let i = this.t - 1; i >= 0; --i) { + r[i + ds + 1] = (this[i] >> cbs) | c; + c = (this[i] & bm) << bs; + } + for (let i = ds - 1; i >= 0; --i) { + r[i] = 0; + } + r[ds] = c; + r.t = this.t + ds + 1; + r.s = this.s; + r.clamp(); + } + + + // BigInteger.prototype.rShiftTo = bnpRShiftTo; + // (protected) r = this >> n + protected rShiftTo(n:number, r:BigInteger) { + r.s = this.s; + const ds = Math.floor(n / this.DB); + if (ds >= this.t) { + r.t = 0; + return; + } + const bs = n % this.DB; + const cbs = this.DB - bs; + const bm = (1 << bs) - 1; + r[0] = this[ds] >> bs; + for (let i = ds + 1; i < this.t; ++i) { + r[i - ds - 1] |= (this[i] & bm) << cbs; + r[i - ds] = this[i] >> bs; + } + if (bs > 0) { + r[this.t - ds - 1] |= (this.s & bm) << cbs; + } + r.t = this.t - ds; + r.clamp(); + } + + + // BigInteger.prototype.subTo = bnpSubTo; + // (protected) r = this - a + public subTo(a:BigInteger, r:BigInteger) { + let i = 0; + let c = 0; + const m = Math.min(a.t, this.t); + while (i < m) { + c += this[i] - a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + if (a.t < this.t) { + c -= a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } else { + c += this.s; + while (i < a.t) { + c -= a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c < -1) { + r[i++] = this.DV + c; + } else if (c > 0) { + r[i++] = c; + } + r.t = i; + r.clamp(); + } + + + // BigInteger.prototype.multiplyTo = bnpMultiplyTo; + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + public multiplyTo(a:BigInteger, r:BigInteger) { + const x = this.abs(); + const y = a.abs(); + let i = x.t; + r.t = i + y.t; + while (--i >= 0) { + r[i] = 0; + } + for (i = 0; i < y.t; ++i) { + r[i + x.t] = x.am(0, y[i], r, i, 0, x.t); + } + r.s = 0; + r.clamp(); + if (this.s != a.s) { + BigInteger.ZERO.subTo(r, r); + } + } + + + // BigInteger.prototype.squareTo = bnpSquareTo; + // (protected) r = this^2, r != this (HAC 14.16) + public squareTo(r:BigInteger) { + const x = this.abs(); + let i = r.t = 2 * x.t; + while (--i >= 0) { + r[i] = 0; + } + for (i = 0; i < x.t - 1; ++i) { + const c = x.am(i, x[i], r, 2 * i, 0, 1); + if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { + r[i + x.t] -= x.DV; + r[i + x.t + 1] = 1; + } + } + if (r.t > 0) { + r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1); + } + r.s = 0; + r.clamp(); + } + + + // BigInteger.prototype.divRemTo = bnpDivRemTo; + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + public divRemTo(m:BigInteger, q:BigInteger, r:BigInteger) { + const pm = m.abs(); + if (pm.t <= 0) { + return; + } + const pt = this.abs(); + if (pt.t < pm.t) { + if (q != null) { + q.fromInt(0); + } + if (r != null) { + this.copyTo(r); + } + return; + } + if (r == null) { + r = nbi(); + } + const y = nbi(); + const ts = this.s; + const ms = m.s; + const nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus + if (nsh > 0) { + pm.lShiftTo(nsh, y); + pt.lShiftTo(nsh, r); + } else { + pm.copyTo(y); + pt.copyTo(r); + } + const ys = y.t; + const y0 = y[ys - 1]; + if (y0 == 0) { + return; + } + const yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0); + const d1 = this.FV / yt; + const d2 = (1 << this.F1) / yt; + const e = 1 << this.F2; + let i = r.t; + let j = i - ys; + const t = (q == null) ? nbi() : q; + y.dlShiftTo(j, t); + if (r.compareTo(t) >= 0) { + r[r.t++] = 1; + r.subTo(t, r); + } + BigInteger.ONE.dlShiftTo(ys, t); + t.subTo(y, y); // "negative" y so we can replace sub with am later + while (y.t < ys) { + y[y.t++] = 0; + } + while (--j >= 0) { + // Estimate quotient digit + let qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2); + if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out + y.dlShiftTo(j, t); + r.subTo(t, r); + while (r[i] < --qd) { + r.subTo(t, r); + } + } + } + if (q != null) { + r.drShiftTo(ys, q); + if (ts != ms) { + BigInteger.ZERO.subTo(q, q); + } + } + r.t = ys; + r.clamp(); + if (nsh > 0) { + r.rShiftTo(nsh, r); + } // Denormalize remainder + if (ts < 0) { + BigInteger.ZERO.subTo(r, r); + } + } + + + // BigInteger.prototype.invDigit = bnpInvDigit; + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + public invDigit():number { + if (this.t < 1) { + return 0; + } + const x = this[0]; + if ((x & 1) == 0) { + return 0; + } + let y = x & 3; // y == 1/x mod 2^2 + y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 + y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 + y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y > 0) ? this.DV - y : -y; + } + + + // BigInteger.prototype.isEven = bnpIsEven; + // (protected) true iff this is even + protected isEven() { + return ((this.t > 0) ? (this[0] & 1) : this.s) == 0; + } + + + // BigInteger.prototype.exp = bnpExp; + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + protected exp(e:number, z:IReduction) { + if (e > 0xffffffff || e < 1) { + return BigInteger.ONE; + } + let r = nbi(); + let r2 = nbi(); + const g = z.convert(this); + let i = nbits(e) - 1; + g.copyTo(r); + while (--i >= 0) { + z.sqrTo(r, r2); + if ((e & (1 << i)) > 0) { + z.mulTo(r2, g, r); + } else { + const t = r; + r = r2; + r2 = t; + } + } + return z.revert(r); + } + + + // BigInteger.prototype.chunkSize = bnpChunkSize; + // (protected) return x s.t. r^x < DV + protected chunkSize(r:number) { + return Math.floor(Math.LN2 * this.DB / Math.log(r)); + } + + + // BigInteger.prototype.toRadix = bnpToRadix; + // (protected) convert to radix string + protected toRadix(b:number) { + if (b == null) { + b = 10; + } + if (this.signum() == 0 || b < 2 || b > 36) { + return "0"; + } + const cs = this.chunkSize(b); + const a = Math.pow(b, cs); + const d = nbv(a); + const y = nbi(); + const z = nbi(); + let r = ""; + this.divRemTo(d, y, z); + while (y.signum() > 0) { + r = (a + z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d, y, z); + } + return z.intValue().toString(b) + r; + } + + + // BigInteger.prototype.fromRadix = bnpFromRadix; + // (protected) convert from radix string + public fromRadix(s:string, b:number) { + this.fromInt(0); + if (b == null) { + b = 10; + } + const cs = this.chunkSize(b); + const d = Math.pow(b, cs); + let mi = false; + let j = 0; + let w = 0; + for (let i = 0; i < s.length; ++i) { + const x = intAt(s, i); + if (x < 0) { + if (s.charAt(i) == "-" && this.signum() == 0) { + mi = true; + } + continue; + } + w = b * w + x; + if (++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w, 0); + j = 0; + w = 0; + } + } + if (j > 0) { + this.dMultiply(Math.pow(b, j)); + this.dAddOffset(w, 0); + } + if (mi) { + BigInteger.ZERO.subTo(this, this); + } + } + + + // BigInteger.prototype.fromNumber = bnpFromNumber; + // (protected) alternate constructor + protected fromNumber(a:number, b:number|SecureRandom, c?:number|SecureRandom) { + if ("number" == typeof b) { + // new BigInteger(int,int,RNG) + if (a < 2) { + this.fromInt(1); + } else { + this.fromNumber(a, c); + if (!this.testBit(a - 1)) { + // force MSB set + this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this); + } + if (this.isEven()) { + this.dAddOffset(1, 0); + } // force odd + while (!this.isProbablePrime(b)) { + this.dAddOffset(2, 0); + if (this.bitLength() > a) { + this.subTo(BigInteger.ONE.shiftLeft(a - 1), this); + } + } + } + } else { + // new BigInteger(int,RNG) + const x:number[] = []; + const t = a & 7; + x.length = (a >> 3) + 1; + b.nextBytes(x); + if (t > 0) { + x[0] &= ((1 << t) - 1); + } else { + x[0] = 0; + } + this.fromString(x, 256); + } + } + + + // BigInteger.prototype.bitwiseTo = bnpBitwiseTo; + // (protected) r = this op a (bitwise) + protected bitwiseTo(a:BigInteger, op:(a:number, b:number) => number, r:BigInteger) { + let i; + let f; + const m = Math.min(a.t, this.t); + for (i = 0; i < m; ++i) { + r[i] = op(this[i], a[i]); + } + if (a.t < this.t) { + f = a.s & this.DM; + for (i = m; i < this.t; ++i) { + r[i] = op(this[i], f); + } + r.t = this.t; + } else { + f = this.s & this.DM; + for (i = m; i < a.t; ++i) { + r[i] = op(f, a[i]); + } + r.t = a.t; + } + r.s = op(this.s, a.s); + r.clamp(); + } + + + // BigInteger.prototype.changeBit = bnpChangeBit; + // (protected) this op (1< number) { + const r = BigInteger.ONE.shiftLeft(n); + this.bitwiseTo(r, op, r); + return r; + } + + + // BigInteger.prototype.addTo = bnpAddTo; + // (protected) r = this + a + protected addTo(a:BigInteger, r:BigInteger) { + let i = 0; + let c = 0; + const m = Math.min(a.t, this.t); + while (i < m) { + c += this[i] + a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + if (a.t < this.t) { + c += a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } else { + c += this.s; + while (i < a.t) { + c += a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c > 0) { + r[i++] = c; + } else if (c < -1) { + r[i++] = this.DV + c; + } + r.t = i; + r.clamp(); + } + + + // BigInteger.prototype.dMultiply = bnpDMultiply; + // (protected) this *= n, this >= 0, 1 < n < DV + protected dMultiply(n:number) { + this[this.t] = this.am(0, n - 1, this, 0, 0, this.t); + ++this.t; + this.clamp(); + } + + + // BigInteger.prototype.dAddOffset = bnpDAddOffset; + // (protected) this += n << w words, this >= 0 + public dAddOffset(n:number, w:number) { + if (n == 0) { + return; + } + while (this.t <= w) { + this[this.t++] = 0; + } + this[w] += n; + while (this[w] >= this.DV) { + this[w] -= this.DV; + if (++w >= this.t) { + this[this.t++] = 0; + } + ++this[w]; + } + } + + + // BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; + // (protected) r = lower n words of "this * a", a.t <= n + // "this" should be the larger one if appropriate. + public multiplyLowerTo(a:BigInteger, n:number, r:BigInteger) { + let i = Math.min(this.t + a.t, n); + r.s = 0; // assumes a,this >= 0 + r.t = i; + while (i > 0) { + r[--i] = 0; + } + for (const j = r.t - this.t; i < j; ++i) { + r[i + this.t] = this.am(0, a[i], r, i, 0, this.t); + } + for (const j = Math.min(a.t, n); i < j; ++i) { + this.am(0, a[i], r, i, 0, n - i); + } + r.clamp(); + } + + + // BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; + // (protected) r = "this * a" without lower n words, n > 0 + // "this" should be the larger one if appropriate. + public multiplyUpperTo(a:BigInteger, n:number, r:BigInteger) { + --n; + let i = r.t = this.t + a.t - n; + r.s = 0; // assumes a,this >= 0 + while (--i >= 0) { + r[i] = 0; + } + for (i = Math.max(n - this.t, 0); i < a.t; ++i) { + r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n); + } + r.clamp(); + r.drShiftTo(1, r); + } + + + // BigInteger.prototype.modInt = bnpModInt; + // (protected) this % n, n < 2^26 + protected modInt(n:number) { + if (n <= 0) { + return 0; + } + const d = this.DV % n; + let r = (this.s < 0) ? n - 1 : 0; + if (this.t > 0) { + if (d == 0) { + r = this[0] % n; + } else { + for (let i = this.t - 1; i >= 0; --i) { + r = (d * r + this[i]) % n; + } + } + } + return r; + } + + + // BigInteger.prototype.millerRabin = bnpMillerRabin; + // (protected) true if probably prime (HAC 4.24, Miller-Rabin) + protected millerRabin(t:number) { + const n1 = this.subtract(BigInteger.ONE); + const k = n1.getLowestSetBit(); + if (k <= 0) { + return false; + } + const r = n1.shiftRight(k); + t = (t + 1) >> 1; + if (t > lowprimes.length) { + t = lowprimes.length; + } + const a = nbi(); + for (let i = 0; i < t; ++i) { + // Pick bases at random, instead of starting at 2 + a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]); + let y = a.modPow(r, this); + if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + let j = 1; + while (j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2, this); + if (y.compareTo(BigInteger.ONE) == 0) { + return false; + } + } + if (y.compareTo(n1) != 0) { + return false; + } + } + } + return true; + } + + // BigInteger.prototype.square = bnSquare; + // (public) this^2 + protected square() { + const r = nbi(); + this.squareTo(r); + return r; + } + + //#region ASYNC + + // Public API method + public gcda(a:BigInteger, callback:(x:BigInteger) => void) { + let x = (this.s < 0) ? this.negate() : this.clone(); + let y = (a.s < 0) ? a.negate() : a.clone(); + if (x.compareTo(y) < 0) { + const t = x; + x = y; + y = t; + } + let i = x.getLowestSetBit(); + let g = y.getLowestSetBit(); + if (g < 0) { + callback(x); + return; + } + if (i < g) { g = i; } + if (g > 0) { + x.rShiftTo(g, x); + y.rShiftTo(g, y); + } + // Workhorse of the algorithm, gets called 200 - 800 times per 512 bit keygen. + const gcda1 = function () { + if ((i = x.getLowestSetBit()) > 0) { x.rShiftTo(i, x); } + if ((i = y.getLowestSetBit()) > 0) { y.rShiftTo(i, y); } + if (x.compareTo(y) >= 0) { + x.subTo(y, x); + x.rShiftTo(1, x); + } else { + y.subTo(x, y); + y.rShiftTo(1, y); + } + if (!(x.signum() > 0)) { + if (g > 0) { y.lShiftTo(g, y); } + setTimeout(function () {callback(y); }, 0); // escape + } else { + setTimeout(gcda1, 0); + } + }; + setTimeout(gcda1, 10); + } + + // (protected) alternate constructor + public fromNumberAsync(a:number, b:number|SecureRandom, c:number|SecureRandom, callback:() => void) { + if ("number" == typeof b) { + if (a < 2) { + this.fromInt(1); + } else { + this.fromNumber(a, c); + if (!this.testBit(a - 1)) { + this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this); + } + if (this.isEven()) { + this.dAddOffset(1, 0); + } + const bnp = this; + const bnpfn1 = function () { + bnp.dAddOffset(2, 0); + if (bnp.bitLength() > a) { bnp.subTo(BigInteger.ONE.shiftLeft(a - 1), bnp); } + if (bnp.isProbablePrime(b)) { + setTimeout(function () {callback(); }, 0); // escape + } else { + setTimeout(bnpfn1, 0); + } + }; + setTimeout(bnpfn1, 0); + } + } else { + const x:number[] = []; + const t = a & 7; + x.length = (a >> 3) + 1; + b.nextBytes(x); + if (t > 0) { x[0] &= ((1 << t) - 1); } else { x[0] = 0; } + this.fromString(x, 256); + } + } + + //#endregion ASYNC + + //#endregion PROTECTED + + //#region FIELDS + + public s:number; + public t:number; + + + public DB:number; + public DM:number; + public DV:number; + + public FV:number; + public F1:number; + public F2:number; + + public am:(i:number, x:number, w:BigInteger, j:number, c:number, n:number) => number; + + [index:number]:number; + + public static ONE:BigInteger; + public static ZERO:BigInteger; + + //#endregion FIELDS +} + +//#region REDUCERS + +//#region NullExp + +class NullExp { + constructor() { + + } + + // NullExp.prototype.convert = nNop; + public convert(x:BigInteger) { + return x; + } + + + // NullExp.prototype.revert = nNop; + public revert(x:BigInteger) { + return x; + } + + + // NullExp.prototype.mulTo = nMulTo; + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + } + + + // NullExp.prototype.sqrTo = nSqrTo; + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + } +} + +//#endregion NullExp + +//#region Classic + +export interface IReduction { + convert(x:BigInteger):BigInteger; + + revert(x:BigInteger):BigInteger; + + // reduce?(x:BigInteger):void; + + mulTo(x:BigInteger, y:BigInteger, r:BigInteger):void; + + sqrTo(x:BigInteger, r:BigInteger):void; +} + +// Modular reduction using "classic" algorithm +class Classic implements IReduction { + constructor(protected m:BigInteger) { + } + + // Classic.prototype.convert = cConvert; + public convert(x:BigInteger) { + if (x.s < 0 || x.compareTo(this.m) >= 0) { + return x.mod(this.m); + } else { + return x; + } + } + + + // Classic.prototype.revert = cRevert; + public revert(x:BigInteger) { + return x; + } + + + // Classic.prototype.reduce = cReduce; + public reduce(x:BigInteger) { + x.divRemTo(this.m, null, x); + } + + + // Classic.prototype.mulTo = cMulTo; + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + this.reduce(r); + } + + + // Classic.prototype.sqrTo = cSqrTo; + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + this.reduce(r); + } +} + +//#endregion + +//#region Montgomery + +// Montgomery reduction +class Montgomery implements IReduction { + constructor(protected m:BigInteger) { + this.mp = m.invDigit(); + this.mpl = this.mp & 0x7fff; + this.mph = this.mp >> 15; + this.um = (1 << (m.DB - 15)) - 1; + this.mt2 = 2 * m.t; + } + + protected mp:number; + protected mpl:number; + protected mph:number; + protected um:number; + protected mt2:number; + + // Montgomery.prototype.convert = montConvert; + // xR mod m + public convert(x:BigInteger) { + const r = nbi(); + x.abs().dlShiftTo(this.m.t, r); + r.divRemTo(this.m, null, r); + if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { + this.m.subTo(r, r); + } + return r; + } + + // Montgomery.prototype.revert = montRevert; + // x/R mod m + public revert(x:BigInteger) { + const r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // Montgomery.prototype.reduce = montReduce; + // x = x/R mod m (HAC 14.32) + public reduce(x:BigInteger) { + while (x.t <= this.mt2) { + // pad x so am has enough room later + x[x.t++] = 0; + } + for (let i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + let j = x[i] & 0x7fff; + const u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM; + // use am to combine the multiply-shift-add into one call + j = i + this.m.t; + x[j] += this.m.am(0, u0, x, i, 0, this.m.t); + // propagate carry + while (x[j] >= x.DV) { + x[j] -= x.DV; + x[++j]++; + } + } + x.clamp(); + x.drShiftTo(this.m.t, x); + if (x.compareTo(this.m) >= 0) { + x.subTo(this.m, x); + } + } + + + // Montgomery.prototype.mulTo = montMulTo; + // r = "xy/R mod m"; x,y != r + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + this.reduce(r); + } + + + // Montgomery.prototype.sqrTo = montSqrTo; + // r = "x^2/R mod m"; x != r + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + this.reduce(r); + } + +} + +//#endregion Montgomery + + +//#region Barrett + +// Barrett modular reduction +class Barrett implements IReduction { + constructor(protected m:BigInteger) { + // setup Barrett + this.r2 = nbi(); + this.q3 = nbi(); + BigInteger.ONE.dlShiftTo(2 * m.t, this.r2); + this.mu = this.r2.divide(m); + } + + protected r2:BigInteger; + protected q3:BigInteger; + protected mu:BigInteger; + + // Barrett.prototype.convert = barrettConvert; + public convert(x:BigInteger) { + if (x.s < 0 || x.t > 2 * this.m.t) { + return x.mod(this.m); + } else if (x.compareTo(this.m) < 0) { + return x; + } else { + const r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + } + + // Barrett.prototype.revert = barrettRevert; + public revert(x:BigInteger) { + return x; + } + + // Barrett.prototype.reduce = barrettReduce; + // x = x mod m (HAC 14.42) + public reduce(x:BigInteger) { + x.drShiftTo(this.m.t - 1, this.r2); + if (x.t > this.m.t + 1) { + x.t = this.m.t + 1; + x.clamp(); + } + this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3); + this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2); + while (x.compareTo(this.r2) < 0) { + x.dAddOffset(1, this.m.t + 1); + } + x.subTo(this.r2, x); + while (x.compareTo(this.m) >= 0) { + x.subTo(this.m, x); + } + } + + + // Barrett.prototype.mulTo = barrettMulTo; + // r = x*y mod m; x,y != r + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + this.reduce(r); + } + + + // Barrett.prototype.sqrTo = barrettSqrTo; + // r = x^2 mod m; x != r + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + this.reduce(r); + } +} + +//#endregion + +//#endregion REDUCERS + +// return new, unset BigInteger +export function nbi() { return new BigInteger(null); } + +export function parseBigInt(str:string, r:number) { + return new BigInteger(str, r); +} + +// am: Compute w_j += (x*this_i), propagate carries, +// c is initial carry, returns final carry. +// c < 3*dvalue, x < 2*dvalue, this_i < dvalue +// We need to select the fastest one that works in this environment. +const inBrowser = typeof navigator !== "undefined"; +if (inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + BigInteger.prototype.am = function am2(i:number, x:number, w:BigInteger, j:number, c:number, n:number) { + const xl = x & 0x7fff; + const xh = x >> 15; + while (--n >= 0) { + let l = this[i] & 0x7fff; + const h = this[i++] >> 15; + const m = xh * l + h * xl; + l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff); + c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30); + w[j++] = l & 0x3fffffff; + } + return c; + }; + dbits = 30; +} else if (inBrowser && j_lm && (navigator.appName != "Netscape")) { + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + BigInteger.prototype.am = function am1(i:number, x:number, w:BigInteger, j:number, c:number, n:number) { + while (--n >= 0) { + const v = x * this[i++] + w[j] + c; + c = Math.floor(v / 0x4000000); + w[j++] = v & 0x3ffffff; + } + return c; + }; + dbits = 26; +} else { // Mozilla/Netscape seems to prefer am3 + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + BigInteger.prototype.am = function am3(i:number, x:number, w:BigInteger, j:number, c:number, n:number) { + const xl = x & 0x3fff; + const xh = x >> 14; + while (--n >= 0) { + let l = this[i] & 0x3fff; + const h = this[i++] >> 14; + const m = xh * l + h * xl; + l = xl * l + ((m & 0x3fff) << 14) + w[j] + c; + c = (l >> 28) + (m >> 14) + xh * h; + w[j++] = l & 0xfffffff; + } + return c; + }; + dbits = 28; +} + +BigInteger.prototype.DB = dbits; +BigInteger.prototype.DM = ((1 << dbits) - 1); +BigInteger.prototype.DV = (1 << dbits); + +const BI_FP = 52; +BigInteger.prototype.FV = Math.pow(2, BI_FP); +BigInteger.prototype.F1 = BI_FP - dbits; +BigInteger.prototype.F2 = 2 * dbits - BI_FP; + +// Digit conversions +const BI_RC:number[] = []; +let rr; +let vv; +rr = "0".charCodeAt(0); +for (vv = 0; vv <= 9; ++vv) { + BI_RC[rr++] = vv; +} +rr = "a".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) { + BI_RC[rr++] = vv; +} +rr = "A".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) { + BI_RC[rr++] = vv; +} + + +export function intAt(s:string, i:number) { + const c = BI_RC[s.charCodeAt(i)]; + return (c == null) ? -1 : c; +} + + +// return bigint initialized to value +export function nbv(i:number) { + const r = nbi(); + r.fromInt(i); + return r; +} + +// returns bit length of the integer x +export function nbits(x:number) { + let r = 1; + let t; + if ((t = x >>> 16) != 0) { + x = t; + r += 16; + } + if ((t = x >> 8) != 0) { + x = t; + r += 8; + } + if ((t = x >> 4) != 0) { + x = t; + r += 4; + } + if ((t = x >> 2) != 0) { + x = t; + r += 2; + } + if ((t = x >> 1) != 0) { + x = t; + r += 1; + } + return r; +} + +// "constants" +BigInteger.ZERO = nbv(0); +BigInteger.ONE = nbv(1); diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/prng4.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/prng4.ts new file mode 100644 index 0000000..38aa161 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/prng4.ts @@ -0,0 +1,54 @@ +// prng4.js - uses Arcfour as a PRNG + +export class Arcfour { + constructor() { + this.i = 0; + this.j = 0; + this.S = []; + } + + // Arcfour.prototype.init = ARC4init; + // Initialize arcfour context from key, an array of ints, each from [0..255] + public init(key:number[]) { + let i; + let j; + let t; + for (i = 0; i < 256; ++i) { + this.S[i] = i; + } + j = 0; + for (i = 0; i < 256; ++i) { + j = (j + this.S[i] + key[i % key.length]) & 255; + t = this.S[i]; + this.S[i] = this.S[j]; + this.S[j] = t; + } + this.i = 0; + this.j = 0; + } + + // Arcfour.prototype.next = ARC4next; + public next() { + let t; + this.i = (this.i + 1) & 255; + this.j = (this.j + this.S[this.i]) & 255; + t = this.S[this.i]; + this.S[this.i] = this.S[this.j]; + this.S[this.j] = t; + return this.S[(t + this.S[this.i]) & 255]; + } + + private i:number; + private j:number; + private S:number[]; +} + + +// Plug in your RNG constructor here +export function prng_newstate() { + return new Arcfour(); +} + +// Pool size must be a multiple of 4 and greater than 32. +// An array of bytes the size of the pool will be passed to init() +export let rng_psize = 256; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/rng.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/rng.ts new file mode 100644 index 0000000..2ab7930 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/rng.ts @@ -0,0 +1,79 @@ +// Random number generator - requires a PRNG backend, e.g. prng4.js +import {Arcfour, prng_newstate, rng_psize} from "./prng4"; + +let rng_state:Arcfour; +let rng_pool:number[] = null; +let rng_pptr:number; + +// Initialize the pool with junk if needed. +if (rng_pool == null) { + rng_pool = []; + rng_pptr = 0; + let t; + if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) { + // Extract entropy (2048 bits) from RNG if available + const z = new Uint32Array(256); + window.crypto.getRandomValues(z); + for (t = 0; t < z.length; ++t) { + rng_pool[rng_pptr++] = z[t] & 255; + } + } + + // Use mouse events for entropy, if we do not have enough entropy by the time + // we need it, entropy will be generated by Math.random. + var count = 0; + const onMouseMoveListener = function (ev:Event & {x:number; y:number; }) { + count = count || 0; + if (count >= 256 || rng_pptr >= rng_psize) { + if (window.removeEventListener) { + window.removeEventListener("mousemove", onMouseMoveListener, false); + } else if ((window as any).detachEvent) { + (window as any).detachEvent("onmousemove", onMouseMoveListener); + } + return; + } + try { + const mouseCoordinates = ev.x + ev.y; + rng_pool[rng_pptr++] = mouseCoordinates & 255; + count += 1; + } catch (e) { + // Sometimes Firefox will deny permission to access event properties for some reason. Ignore. + } + }; + if (typeof window !== 'undefined') { + if (window.addEventListener) { + window.addEventListener("mousemove", onMouseMoveListener, false); + } else if ((window as any).attachEvent) { + (window as any).attachEvent("onmousemove", onMouseMoveListener); + } + } + +} + +function rng_get_byte() { + if (rng_state == null) { + rng_state = prng_newstate(); + // At this point, we may not have collected enough entropy. If not, fall back to Math.random + while (rng_pptr < rng_psize) { + const random = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = random & 255; + } + rng_state.init(rng_pool); + for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) { + rng_pool[rng_pptr] = 0; + } + rng_pptr = 0; + } + // TODO: allow reseeding after first request + return rng_state.next(); +} + + +export class SecureRandom { + + public nextBytes(ba:number[]) { + for (let i = 0; i < ba.length; ++i) { + ba[i] = rng_get_byte(); + } + } +} diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/rsa.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/rsa.ts new file mode 100644 index 0000000..6c3ffa2 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/rsa.ts @@ -0,0 +1,406 @@ +// Depends on jsbn.js and rng.js + +// Version 1.1: support utf-8 encoding in pkcs1pad2 + +// convert a (hex) string to a bignum object + +import {BigInteger, nbi, parseBigInt} from "./jsbn"; +import {SecureRandom} from "./rng"; + + +// function linebrk(s,n) { +// var ret = ""; +// var i = 0; +// while(i + n < s.length) { +// ret += s.substring(i,i+n) + "\n"; +// i += n; +// } +// return ret + s.substring(i,s.length); +// } + +// function byte2Hex(b) { +// if(b < 0x10) +// return "0" + b.toString(16); +// else +// return b.toString(16); +// } + +function pkcs1pad1(s:string, n:number) { + if (n < s.length + 22) { + console.error("Message too long for RSA"); + return null; + } + const len = n - s.length - 6; + let filler = ""; + for (let f = 0; f < len; f += 2) { + filler += "ff"; + } + const m = "0001" + filler + "00" + s; + return parseBigInt(m, 16); +} + +// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint +function pkcs1pad2(s:string, n:number) { + if (n < s.length + 11) { // TODO: fix for utf-8 + + console.error("Message too long for RSA"); + return null; + } + const ba = []; + let i = s.length - 1; + while (i >= 0 && n > 0) { + const c = s.charCodeAt(i--); + if (c < 128) { // encode using utf-8 + ba[--n] = c; + } else if ((c > 127) && (c < 2048)) { + ba[--n] = (c & 63) | 128; + ba[--n] = (c >> 6) | 192; + } else { + ba[--n] = (c & 63) | 128; + ba[--n] = ((c >> 6) & 63) | 128; + ba[--n] = (c >> 12) | 224; + } + } + ba[--n] = 0; + const rng = new SecureRandom(); + const x = []; + while (n > 2) { // random non-zero pad + x[0] = 0; + while (x[0] == 0) { + rng.nextBytes(x); + } + ba[--n] = x[0]; + } + ba[--n] = 2; + ba[--n] = 0; + return new BigInteger(ba); +} + +// "empty" RSA key constructor +export class RSAKey { + constructor() { + this.n = null; + this.e = 0; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; + } + + //#region PROTECTED + // protected + // RSAKey.prototype.doPublic = RSADoPublic; + // Perform raw public operation on "x": return x^e (mod n) + public doPublic(x:BigInteger) { + return x.modPowInt(this.e, this.n); + } + + + // RSAKey.prototype.doPrivate = RSADoPrivate; + // Perform raw private operation on "x": return x^d (mod n) + public doPrivate(x:BigInteger) { + if (this.p == null || this.q == null) { + return x.modPow(this.d, this.n); + } + + // TODO: re-calculate any missing CRT params + let xp = x.mod(this.p).modPow(this.dmp1, this.p); + const xq = x.mod(this.q).modPow(this.dmq1, this.q); + + while (xp.compareTo(xq) < 0) { + xp = xp.add(this.p); + } + return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq); + } + + //#endregion PROTECTED + + //#region PUBLIC + + // RSAKey.prototype.setPublic = RSASetPublic; + // Set the public key fields N and e from hex strings + public setPublic(N:string, E:string) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + } else { + console.error("Invalid RSA public key"); + } + } + + + // RSAKey.prototype.encrypt = RSAEncrypt; + // Return the PKCS#1 RSA encryption of "text" as an even-length hex string + public encrypt(text:string) { + const maxLength = (this.n.bitLength() + 7) >> 3; + const m = pkcs1pad2(text, maxLength); + + if (m == null) { + return null; + } + const c = this.doPublic(m); + if (c == null) { + return null; + } + + let h = c.toString(16); + let length = h.length; + + // fix zero before result + for (let i = 0; i < maxLength * 2 - length; i++) { + h = "0" + h; + } + + return h + } + + + // RSAKey.prototype.setPrivate = RSASetPrivate; + // Set the private key fields N, e, and d from hex strings + public setPrivate(N:string, E:string, D:string) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + this.d = parseBigInt(D, 16); + } else { + console.error("Invalid RSA private key"); + } + } + + + // RSAKey.prototype.setPrivateEx = RSASetPrivateEx; + // Set the private key fields N, e, d and CRT params from hex strings + public setPrivateEx(N:string, E:string, D:string, P:string, Q:string, DP:string, DQ:string, C:string) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + this.d = parseBigInt(D, 16); + this.p = parseBigInt(P, 16); + this.q = parseBigInt(Q, 16); + this.dmp1 = parseBigInt(DP, 16); + this.dmq1 = parseBigInt(DQ, 16); + this.coeff = parseBigInt(C, 16); + } else { + console.error("Invalid RSA private key"); + } + } + + + // RSAKey.prototype.generate = RSAGenerate; + // Generate a new random private key B bits long, using public expt E + public generate(B:number, E:string) { + const rng = new SecureRandom(); + const qs = B >> 1; + this.e = parseInt(E, 16); + const ee = new BigInteger(E, 16); + for (;;) { + for (;;) { + this.p = new BigInteger(B - qs, 1, rng); + if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) { break; } + } + for (;;) { + this.q = new BigInteger(qs, 1, rng); + if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) { break; } + } + if (this.p.compareTo(this.q) <= 0) { + const t = this.p; + this.p = this.q; + this.q = t; + } + const p1 = this.p.subtract(BigInteger.ONE); + const q1 = this.q.subtract(BigInteger.ONE); + const phi = p1.multiply(q1); + if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { + this.n = this.p.multiply(this.q); + this.d = ee.modInverse(phi); + this.dmp1 = this.d.mod(p1); + this.dmq1 = this.d.mod(q1); + this.coeff = this.q.modInverse(this.p); + break; + } + } + } + + // RSAKey.prototype.decrypt = RSADecrypt; + // Return the PKCS#1 RSA decryption of "ctext". + // "ctext" is an even-length hex string and the output is a plain string. + public decrypt(ctext:string) { + const c = parseBigInt(ctext, 16); + const m = this.doPrivate(c); + if (m == null) { return null; } + return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3); + } + + // Generate a new random private key B bits long, using public expt E + public generateAsync(B:number, E:string, callback:() => void) { + const rng = new SecureRandom(); + const qs = B >> 1; + this.e = parseInt(E, 16); + const ee = new BigInteger(E, 16); + const rsa = this; + // These functions have non-descript names because they were originally for(;;) loops. + // I don't know about cryptography to give them better names than loop1-4. + const loop1 = function () { + const loop4 = function () { + if (rsa.p.compareTo(rsa.q) <= 0) { + const t = rsa.p; + rsa.p = rsa.q; + rsa.q = t; + } + const p1 = rsa.p.subtract(BigInteger.ONE); + const q1 = rsa.q.subtract(BigInteger.ONE); + const phi = p1.multiply(q1); + if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { + rsa.n = rsa.p.multiply(rsa.q); + rsa.d = ee.modInverse(phi); + rsa.dmp1 = rsa.d.mod(p1); + rsa.dmq1 = rsa.d.mod(q1); + rsa.coeff = rsa.q.modInverse(rsa.p); + setTimeout(function () {callback(); }, 0); // escape + } else { + setTimeout(loop1, 0); + } + }; + const loop3 = function () { + rsa.q = nbi(); + rsa.q.fromNumberAsync(qs, 1, rng, function () { + rsa.q.subtract(BigInteger.ONE).gcda(ee, function (r) { + if (r.compareTo(BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) { + setTimeout(loop4, 0); + } else { + setTimeout(loop3, 0); + } + }); + }); + }; + const loop2 = function () { + rsa.p = nbi(); + rsa.p.fromNumberAsync(B - qs, 1, rng, function () { + rsa.p.subtract(BigInteger.ONE).gcda(ee, function (r) { + if (r.compareTo(BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) { + setTimeout(loop3, 0); + } else { + setTimeout(loop2, 0); + } + }); + }); + }; + setTimeout(loop2, 0); + }; + setTimeout(loop1, 0); + } + + public sign(text:string, digestMethod:(str:string) => string, digestName:string):string { + const header = getDigestHeader(digestName); + const digest = header + digestMethod(text).toString(); + const m = pkcs1pad1(digest, this.n.bitLength() / 4); + if (m == null) { + return null; + } + const c = this.doPrivate(m); + if (c == null) { + return null; + } + const h = c.toString(16); + if ((h.length & 1) == 0) { + return h; + } else { + return "0" + h; + } + } + + public verify(text:string, signature:string, digestMethod:(str:string) => string):boolean { + const c = parseBigInt(signature, 16); + const m = this.doPublic(c); + if (m == null) { + return null; + } + const unpadded = m.toString(16).replace(/^1f+00/, ""); + const digest = removeDigestHeader(unpadded); + return digest == digestMethod(text).toString(); + } + + //#endregion PUBLIC + + protected n:BigInteger; + protected e:number; + protected d:BigInteger; + protected p:BigInteger; + protected q:BigInteger; + protected dmp1:BigInteger; + protected dmq1:BigInteger; + protected coeff:BigInteger; + +} + + +// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext +function pkcs1unpad2(d:BigInteger, n:number):string { + const b = d.toByteArray(); + let i = 0; + while (i < b.length && b[i] == 0) { ++i; } + if (b.length - i != n - 1 || b[i] != 2) { + return null; + } + ++i; + while (b[i] != 0) { + if (++i >= b.length) { return null; } + } + let ret = ""; + while (++i < b.length) { + const c = b[i] & 255; + if (c < 128) { // utf-8 decode + ret += String.fromCharCode(c); + } else if ((c > 191) && (c < 224)) { + ret += String.fromCharCode(((c & 31) << 6) | (b[i + 1] & 63)); + ++i; + } else { + ret += String.fromCharCode(((c & 15) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63)); + i += 2; + } + } + return ret; +} + +// https://tools.ietf.org/html/rfc3447#page-43 +const DIGEST_HEADERS:{ [name:string]:string } = { + md2: "3020300c06082a864886f70d020205000410", + md5: "3020300c06082a864886f70d020505000410", + sha1: "3021300906052b0e03021a05000414", + sha224: "302d300d06096086480165030402040500041c", + sha256: "3031300d060960864801650304020105000420", + sha384: "3041300d060960864801650304020205000430", + sha512: "3051300d060960864801650304020305000440", + ripemd160: "3021300906052b2403020105000414" +}; + +function getDigestHeader(name:string):string { + return DIGEST_HEADERS[name] || ""; +} + +function removeDigestHeader(str:string):string { + for (const name in DIGEST_HEADERS) { + if (DIGEST_HEADERS.hasOwnProperty(name)) { + const header = DIGEST_HEADERS[name]; + const len = header.length; + if (str.substr(0, len) == header) { + return str.substr(len); + } + } + } + return str; +} + + +// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string +// function RSAEncryptB64(text) { +// var h = this.encrypt(text); +// if(h) return hex2b64(h); else return null; +// } + + +// public + +// RSAKey.prototype.encrypt_b64 = RSAEncryptB64; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/util.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/util.ts new file mode 100644 index 0000000..943be83 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsbn/util.ts @@ -0,0 +1,69 @@ +const BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; + +export function int2char(n:number) { + return BI_RM.charAt(n); +} + +//#region BIT_OPERATIONS + +// (public) this & a +export function op_and(x:number, y:number):number { + return x & y; +} + + +// (public) this | a +export function op_or(x:number, y:number):number { + return x | y; +} + +// (public) this ^ a +export function op_xor(x:number, y:number):number { + return x ^ y; +} + + +// (public) this & ~a +export function op_andnot(x:number, y:number):number { + return x & ~y; +} + +// return index of lowest 1-bit in x, x < 2^31 +export function lbit(x:number) { + if (x == 0) { + return -1; + } + let r = 0; + if ((x & 0xffff) == 0) { + x >>= 16; + r += 16; + } + if ((x & 0xff) == 0) { + x >>= 8; + r += 8; + } + if ((x & 0xf) == 0) { + x >>= 4; + r += 4; + } + if ((x & 3) == 0) { + x >>= 2; + r += 2; + } + if ((x & 1) == 0) { + ++r; + } + return r; +} + +// return number of 1 bits in x +export function cbit(x:number) { + let r = 0; + while (x != 0) { + x &= x - 1; + ++r; + } + return r; +} + +//#endregion BIT_OPERATIONS diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/LICENSE.txt new file mode 100644 index 0000000..e660fc8 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/LICENSE.txt @@ -0,0 +1,25 @@ + + +CONTAINS CODE FROM YUI LIBRARY SEE LICENSE @ http://yuilibrary.com/license/ + +The 'jsrsasign'(RSA-Sign JavaScript Library) License + +Copyright (c) 2010-2013 Kenji Urushima + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/asn1-1.0.d.ts b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/asn1-1.0.d.ts new file mode 100644 index 0000000..f680d28 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/asn1-1.0.d.ts @@ -0,0 +1,77 @@ + + +declare interface IDERIntegerParams { + bigint?:any; + int?:number; + hex?:number; +} + +declare class DERInteger { + /**/ +} + +declare interface IDERIntegerConstructor { + new(params:IDERIntegerParams):DERInteger; +} + +declare class DERSequence { + /**/ + public getEncodedHex():string; +} +declare interface IDERSequenceConstructor { + new(params:{ + array:DERInteger[]; + }):DERSequence; +} + + +declare class DERObjectIdentifier { + /**/ +} +declare interface IDERObjectIdentifierConstructor { + new(params:{ + oid?:string; + hex?:string; + name?:string; + }|string):DERObjectIdentifier; +} + + +declare class DERNull { + /**/ +} +declare interface IDERNullConstructor { + new():DERNull; +} + + +declare class DERBitString { + /**/ +} +declare interface IDERBitStringConstructor { + new(params:{ + hex?:string; + array?:boolean[]; + bin?:string; + }|string):DERBitString; +} + + +declare interface Iasn1 { + readonly DERInteger:IDERIntegerConstructor; + + readonly DERSequence:IDERSequenceConstructor; + + readonly DERObjectIdentifier:IDERObjectIdentifierConstructor; + + readonly DERNull:IDERNullConstructor; + + readonly DERBitString:IDERBitStringConstructor; +} + +declare interface IKJUR { + readonly asn1:Iasn1; +} + + +export const KJUR:IKJUR; diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/asn1-1.0.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/asn1-1.0.js new file mode 100644 index 0000000..8fa04c8 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/asn1-1.0.js @@ -0,0 +1,1651 @@ +/* asn1-1.0.13.js (c) 2013-2017 Kenji Urushima | kjur.github.com/jsrsasign/license + */ +/* + * asn1.js - ASN.1 DER encoder classes + * + * Copyright (c) 2013-2017 Kenji Urushima (kenji.urushima@gmail.com) + * + * This software is licensed under the terms of the MIT License. + * https://kjur.github.io/jsrsasign/license + * + * The above copyright and license notice shall be + * included in all copies or substantial portions of the Software. + */ + +import { BigInteger } from "../jsbn/jsbn"; +import { YAHOO } from "./yahoo"; + +/** + * @fileOverview + * @name asn1-1.0.js + * @author Kenji Urushima kenji.urushima@gmail.com + * @version asn1 1.0.13 (2017-Jun-02) + * @since jsrsasign 2.1 + * @license
    MIT License + */ + +/** + * kjur's class library name space + *

    + * This name space provides following name spaces: + *

      + *
    • {@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder
    • + *
    • {@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL
    • + *
    • {@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature + * class and utilities
    • + *
    + *

    + * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2. + * @name KJUR + * @namespace kjur's class library name space + */ +export var KJUR = {}; + +/** + * kjur's ASN.1 class library name space + *

    + * This is ITU-T X.690 ASN.1 DER encoder class library and + * class structure and methods is very similar to + * org.bouncycastle.asn1 package of + * well known BouncyCaslte Cryptography Library. + *

    PROVIDING ASN.1 PRIMITIVES

    + * Here are ASN.1 DER primitive classes. + *
      + *
    • 0x01 {@link KJUR.asn1.DERBoolean}
    • + *
    • 0x02 {@link KJUR.asn1.DERInteger}
    • + *
    • 0x03 {@link KJUR.asn1.DERBitString}
    • + *
    • 0x04 {@link KJUR.asn1.DEROctetString}
    • + *
    • 0x05 {@link KJUR.asn1.DERNull}
    • + *
    • 0x06 {@link KJUR.asn1.DERObjectIdentifier}
    • + *
    • 0x0a {@link KJUR.asn1.DEREnumerated}
    • + *
    • 0x0c {@link KJUR.asn1.DERUTF8String}
    • + *
    • 0x12 {@link KJUR.asn1.DERNumericString}
    • + *
    • 0x13 {@link KJUR.asn1.DERPrintableString}
    • + *
    • 0x14 {@link KJUR.asn1.DERTeletexString}
    • + *
    • 0x16 {@link KJUR.asn1.DERIA5String}
    • + *
    • 0x17 {@link KJUR.asn1.DERUTCTime}
    • + *
    • 0x18 {@link KJUR.asn1.DERGeneralizedTime}
    • + *
    • 0x30 {@link KJUR.asn1.DERSequence}
    • + *
    • 0x31 {@link KJUR.asn1.DERSet}
    • + *
    + *

    OTHER ASN.1 CLASSES

    + *
      + *
    • {@link KJUR.asn1.ASN1Object}
    • + *
    • {@link KJUR.asn1.DERAbstractString}
    • + *
    • {@link KJUR.asn1.DERAbstractTime}
    • + *
    • {@link KJUR.asn1.DERAbstractStructured}
    • + *
    • {@link KJUR.asn1.DERTaggedObject}
    • + *
    + *

    SUB NAME SPACES

    + *
      + *
    • {@link KJUR.asn1.cades} - CAdES long term signature format
    • + *
    • {@link KJUR.asn1.cms} - Cryptographic Message Syntax
    • + *
    • {@link KJUR.asn1.csr} - Certificate Signing Request (CSR/PKCS#10)
    • + *
    • {@link KJUR.asn1.tsp} - RFC 3161 Timestamping Protocol Format
    • + *
    • {@link KJUR.asn1.x509} - RFC 5280 X.509 certificate and CRL
    • + *
    + *

    + * NOTE: Please ignore method summary and document of this namespace. + * This caused by a bug of jsdoc2. + * @name KJUR.asn1 + * @namespace + */ +if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {}; + +/** + * ASN1 utilities class + * @name KJUR.asn1.ASN1Util + * @class ASN1 utilities class + * @since asn1 1.0.2 + */ +KJUR.asn1.ASN1Util = new function() { + this.integerToByteHex = function(i) { + var h = i.toString(16); + if ((h.length % 2) == 1) h = '0' + h; + return h; + }; + this.bigIntToMinTwosComplementsHex = function(bigIntegerValue) { + var h = bigIntegerValue.toString(16); + if (h.substr(0, 1) != '-') { + if (h.length % 2 == 1) { + h = '0' + h; + } else { + if (! h.match(/^[0-7]/)) { + h = '00' + h; + } + } + } else { + var hPos = h.substr(1); + var xorLen = hPos.length; + if (xorLen % 2 == 1) { + xorLen += 1; + } else { + if (! h.match(/^[0-7]/)) { + xorLen += 2; + } + } + var hMask = ''; + for (var i = 0; i < xorLen; i++) { + hMask += 'f'; + } + var biMask = new BigInteger(hMask, 16); + var biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE); + h = biNeg.toString(16).replace(/^-/, ''); + } + return h; + }; + /** + * get PEM string from hexadecimal data and header string + * @name getPEMStringFromHex + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} dataHex hexadecimal string of PEM body + * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY') + * @return {String} PEM formatted string of input data + * @description + * This method converts a hexadecimal string to a PEM string with + * a specified header. Its line break will be CRLF("\r\n"). + * @example + * var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex('616161', 'RSA PRIVATE KEY'); + * // value of pem will be: + * -----BEGIN PRIVATE KEY----- + * YWFh + * -----END PRIVATE KEY----- + */ + this.getPEMStringFromHex = function(dataHex, pemHeader) { + return hextopem(dataHex, pemHeader); + }; + + /** + * generate ASN1Object specifed by JSON parameters + * @name newObject + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {Array} param JSON parameter to generate ASN1Object + * @return {KJUR.asn1.ASN1Object} generated object + * @since asn1 1.0.3 + * @description + * generate any ASN1Object specified by JSON param + * including ASN.1 primitive or structured. + * Generally 'param' can be described as follows: + *
    + * {TYPE-OF-ASNOBJ: ASN1OBJ-PARAMETER} + *
    + * 'TYPE-OF-ASN1OBJ' can be one of following symbols: + *
      + *
    • 'bool' - DERBoolean
    • + *
    • 'int' - DERInteger
    • + *
    • 'bitstr' - DERBitString
    • + *
    • 'octstr' - DEROctetString
    • + *
    • 'null' - DERNull
    • + *
    • 'oid' - DERObjectIdentifier
    • + *
    • 'enum' - DEREnumerated
    • + *
    • 'utf8str' - DERUTF8String
    • + *
    • 'numstr' - DERNumericString
    • + *
    • 'prnstr' - DERPrintableString
    • + *
    • 'telstr' - DERTeletexString
    • + *
    • 'ia5str' - DERIA5String
    • + *
    • 'utctime' - DERUTCTime
    • + *
    • 'gentime' - DERGeneralizedTime
    • + *
    • 'seq' - DERSequence
    • + *
    • 'set' - DERSet
    • + *
    • 'tag' - DERTaggedObject
    • + *
    + * @example + * newObject({'prnstr': 'aaa'}); + * newObject({'seq': [{'int': 3}, {'prnstr': 'aaa'}]}) + * // ASN.1 Tagged Object + * newObject({'tag': {'tag': 'a1', + * 'explicit': true, + * 'obj': {'seq': [{'int': 3}, {'prnstr': 'aaa'}]}}}); + * // more simple representation of ASN.1 Tagged Object + * newObject({'tag': ['a1', + * true, + * {'seq': [ + * {'int': 3}, + * {'prnstr': 'aaa'}]} + * ]}); + */ + this.newObject = function(param) { + var _KJUR = KJUR, + _KJUR_asn1 = _KJUR.asn1, + _DERBoolean = _KJUR_asn1.DERBoolean, + _DERInteger = _KJUR_asn1.DERInteger, + _DERBitString = _KJUR_asn1.DERBitString, + _DEROctetString = _KJUR_asn1.DEROctetString, + _DERNull = _KJUR_asn1.DERNull, + _DERObjectIdentifier = _KJUR_asn1.DERObjectIdentifier, + _DEREnumerated = _KJUR_asn1.DEREnumerated, + _DERUTF8String = _KJUR_asn1.DERUTF8String, + _DERNumericString = _KJUR_asn1.DERNumericString, + _DERPrintableString = _KJUR_asn1.DERPrintableString, + _DERTeletexString = _KJUR_asn1.DERTeletexString, + _DERIA5String = _KJUR_asn1.DERIA5String, + _DERUTCTime = _KJUR_asn1.DERUTCTime, + _DERGeneralizedTime = _KJUR_asn1.DERGeneralizedTime, + _DERSequence = _KJUR_asn1.DERSequence, + _DERSet = _KJUR_asn1.DERSet, + _DERTaggedObject = _KJUR_asn1.DERTaggedObject, + _newObject = _KJUR_asn1.ASN1Util.newObject; + + var keys = Object.keys(param); + if (keys.length != 1) + throw "key of param shall be only one."; + var key = keys[0]; + + if (":bool:int:bitstr:octstr:null:oid:enum:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + key + ":") == -1) + throw "undefined key: " + key; + + if (key == "bool") return new _DERBoolean(param[key]); + if (key == "int") return new _DERInteger(param[key]); + if (key == "bitstr") return new _DERBitString(param[key]); + if (key == "octstr") return new _DEROctetString(param[key]); + if (key == "null") return new _DERNull(param[key]); + if (key == "oid") return new _DERObjectIdentifier(param[key]); + if (key == "enum") return new _DEREnumerated(param[key]); + if (key == "utf8str") return new _DERUTF8String(param[key]); + if (key == "numstr") return new _DERNumericString(param[key]); + if (key == "prnstr") return new _DERPrintableString(param[key]); + if (key == "telstr") return new _DERTeletexString(param[key]); + if (key == "ia5str") return new _DERIA5String(param[key]); + if (key == "utctime") return new _DERUTCTime(param[key]); + if (key == "gentime") return new _DERGeneralizedTime(param[key]); + + if (key == "seq") { + var paramList = param[key]; + var a = []; + for (var i = 0; i < paramList.length; i++) { + var asn1Obj = _newObject(paramList[i]); + a.push(asn1Obj); + } + return new _DERSequence({'array': a}); + } + + if (key == "set") { + var paramList = param[key]; + var a = []; + for (var i = 0; i < paramList.length; i++) { + var asn1Obj = _newObject(paramList[i]); + a.push(asn1Obj); + } + return new _DERSet({'array': a}); + } + + if (key == "tag") { + var tagParam = param[key]; + if (Object.prototype.toString.call(tagParam) === '[object Array]' && + tagParam.length == 3) { + var obj = _newObject(tagParam[2]); + return new _DERTaggedObject({tag: tagParam[0], + explicit: tagParam[1], + obj: obj}); + } else { + var newParam = {}; + if (tagParam.explicit !== undefined) + newParam.explicit = tagParam.explicit; + if (tagParam.tag !== undefined) + newParam.tag = tagParam.tag; + if (tagParam.obj === undefined) + throw "obj shall be specified for 'tag'."; + newParam.obj = _newObject(tagParam.obj); + return new _DERTaggedObject(newParam); + } + } + }; + + /** + * get encoded hexadecimal string of ASN1Object specifed by JSON parameters + * @name jsonToASN1HEX + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {Array} param JSON parameter to generate ASN1Object + * @return hexadecimal string of ASN1Object + * @since asn1 1.0.4 + * @description + * As for ASN.1 object representation of JSON object, + * please see {@link newObject}. + * @example + * jsonToASN1HEX({'prnstr': 'aaa'}); + */ + this.jsonToASN1HEX = function(param) { + var asn1Obj = this.newObject(param); + return asn1Obj.getEncodedHex(); + }; +}; + +/** + * get dot noted oid number string from hexadecimal value of OID + * @name oidHexToInt + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} hex hexadecimal value of object identifier + * @return {String} dot noted string of object identifier + * @since jsrsasign 4.8.3 asn1 1.0.7 + * @description + * This static method converts from hexadecimal string representation of + * ASN.1 value of object identifier to oid number string. + * @example + * KJUR.asn1.ASN1Util.oidHexToInt('550406') → "2.5.4.6" + */ +KJUR.asn1.ASN1Util.oidHexToInt = function(hex) { + var s = ""; + var i01 = parseInt(hex.substr(0, 2), 16); + var i0 = Math.floor(i01 / 40); + var i1 = i01 % 40; + var s = i0 + "." + i1; + + var binbuf = ""; + for (var i = 2; i < hex.length; i += 2) { + var value = parseInt(hex.substr(i, 2), 16); + var bin = ("00000000" + value.toString(2)).slice(- 8); + binbuf = binbuf + bin.substr(1, 7); + if (bin.substr(0, 1) == "0") { + var bi = new BigInteger(binbuf, 2); + s = s + "." + bi.toString(10); + binbuf = ""; + } + }; + + return s; +}; + +/** + * get hexadecimal value of object identifier from dot noted oid value + * @name oidIntToHex + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} oidString dot noted string of object identifier + * @return {String} hexadecimal value of object identifier + * @since jsrsasign 4.8.3 asn1 1.0.7 + * @description + * This static method converts from object identifier value string. + * to hexadecimal string representation of it. + * @example + * KJUR.asn1.ASN1Util.oidIntToHex("2.5.4.6") → "550406" + */ +KJUR.asn1.ASN1Util.oidIntToHex = function(oidString) { + var itox = function(i) { + var h = i.toString(16); + if (h.length == 1) h = '0' + h; + return h; + }; + + var roidtox = function(roid) { + var h = ''; + var bi = new BigInteger(roid, 10); + var b = bi.toString(2); + var padLen = 7 - b.length % 7; + if (padLen == 7) padLen = 0; + var bPad = ''; + for (var i = 0; i < padLen; i++) bPad += '0'; + b = bPad + b; + for (var i = 0; i < b.length - 1; i += 7) { + var b8 = b.substr(i, 7); + if (i != b.length - 7) b8 = '1' + b8; + h += itox(parseInt(b8, 2)); + } + return h; + }; + + if (! oidString.match(/^[0-9.]+$/)) { + throw "malformed oid string: " + oidString; + } + var h = ''; + var a = oidString.split('.'); + var i0 = parseInt(a[0]) * 40 + parseInt(a[1]); + h += itox(i0); + a.splice(0, 2); + for (var i = 0; i < a.length; i++) { + h += roidtox(a[i]); + } + return h; +}; + + +// ******************************************************************** +// Abstract ASN.1 Classes +// ******************************************************************** + +// ******************************************************************** + +/** + * base class for ASN.1 DER encoder object + * @name KJUR.asn1.ASN1Object + * @class base class for ASN.1 DER encoder object + * @property {Boolean} isModified flag whether internal data was changed + * @property {String} hTLV hexadecimal string of ASN.1 TLV + * @property {String} hT hexadecimal string of ASN.1 TLV tag(T) + * @property {String} hL hexadecimal string of ASN.1 TLV length(L) + * @property {String} hV hexadecimal string of ASN.1 TLV value(V) + * @description + */ +KJUR.asn1.ASN1Object = function() { + var isModified = true; + var hTLV = null; + var hT = '00'; + var hL = '00'; + var hV = ''; + + /** + * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V) + * @name getLengthHexFromValue + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV length(L) + */ + this.getLengthHexFromValue = function() { + if (typeof this.hV == "undefined" || this.hV == null) { + throw "this.hV is null or undefined."; + } + if (this.hV.length % 2 == 1) { + throw "value hex must be even length: n=" + hV.length + ",v=" + this.hV; + } + var n = this.hV.length / 2; + var hN = n.toString(16); + if (hN.length % 2 == 1) { + hN = "0" + hN; + } + if (n < 128) { + return hN; + } else { + var hNlen = hN.length / 2; + if (hNlen > 15) { + throw "ASN.1 length too long to represent by 8x: n = " + n.toString(16); + } + var head = 128 + hNlen; + return head.toString(16) + hN; + } + }; + + /** + * get hexadecimal string of ASN.1 TLV bytes + * @name getEncodedHex + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV + */ + this.getEncodedHex = function() { + if (this.hTLV == null || this.isModified) { + this.hV = this.getFreshValueHex(); + this.hL = this.getLengthHexFromValue(); + this.hTLV = this.hT + this.hL + this.hV; + this.isModified = false; + //alert("first time: " + this.hTLV); + } + return this.hTLV; + }; + + /** + * get hexadecimal string of ASN.1 TLV value(V) bytes + * @name getValueHex + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV value(V) bytes + */ + this.getValueHex = function() { + this.getEncodedHex(); + return this.hV; + } + + this.getFreshValueHex = function() { + return ''; + }; +}; + +// == BEGIN DERAbstractString ================================================ +/** + * base class for ASN.1 DER string classes + * @name KJUR.asn1.DERAbstractString + * @class base class for ASN.1 DER string classes + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @property {String} s internal string of value + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • str - specify initial ASN.1 value(V) by a string
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERAbstractString = function(params) { + KJUR.asn1.DERAbstractString.superclass.constructor.call(this); + var s = null; + var hV = null; + + /** + * get string value of this string object + * @name getString + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @return {String} string value of this string object + */ + this.getString = function() { + return this.s; + }; + + /** + * set value by a string + * @name setString + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @param {String} newS value by a string to set + */ + this.setString = function(newS) { + this.hTLV = null; + this.isModified = true; + this.s = newS; + this.hV = stohex(this.s); + }; + + /** + * set value by a hexadecimal string + * @name setStringHex + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @param {String} newHexString value by a hexadecimal string to set + */ + this.setStringHex = function(newHexString) { + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params == "string") { + this.setString(params); + } else if (typeof params['str'] != "undefined") { + this.setString(params['str']); + } else if (typeof params['hex'] != "undefined") { + this.setStringHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractString, KJUR.asn1.ASN1Object); +// == END DERAbstractString ================================================ + +// == BEGIN DERAbstractTime ================================================== +/** + * base class for ASN.1 DER Generalized/UTCTime class + * @name KJUR.asn1.DERAbstractTime + * @class base class for ASN.1 DER Generalized/UTCTime class + * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERAbstractTime = function(params) { + KJUR.asn1.DERAbstractTime.superclass.constructor.call(this); + var s = null; + var date = null; + + // --- PRIVATE METHODS -------------------- + this.localDateToUTC = function(d) { + utc = d.getTime() + (d.getTimezoneOffset() * 60000); + var utcDate = new Date(utc); + return utcDate; + }; + + /* + * format date string by Data object + * @name formatDate + * @memberOf KJUR.asn1.AbstractTime; + * @param {Date} dateObject + * @param {string} type 'utc' or 'gen' + * @param {boolean} withMillis flag for with millisections or not + * @description + * 'withMillis' flag is supported from asn1 1.0.6. + */ + this.formatDate = function(dateObject, type, withMillis) { + var pad = this.zeroPadding; + var d = this.localDateToUTC(dateObject); + var year = String(d.getFullYear()); + if (type == 'utc') year = year.substr(2, 2); + var month = pad(String(d.getMonth() + 1), 2); + var day = pad(String(d.getDate()), 2); + var hour = pad(String(d.getHours()), 2); + var min = pad(String(d.getMinutes()), 2); + var sec = pad(String(d.getSeconds()), 2); + var s = year + month + day + hour + min + sec; + if (withMillis === true) { + var millis = d.getMilliseconds(); + if (millis != 0) { + var sMillis = pad(String(millis), 3); + sMillis = sMillis.replace(/[0]+$/, ""); + s = s + "." + sMillis; + } + } + return s + "Z"; + }; + + this.zeroPadding = function(s, len) { + if (s.length >= len) return s; + return new Array(len - s.length + 1).join('0') + s; + }; + + // --- PUBLIC METHODS -------------------- + /** + * get string value of this string object + * @name getString + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @return {String} string value of this time object + */ + this.getString = function() { + return this.s; + }; + + /** + * set value by a string + * @name setString + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @param {String} newS value by a string to set such like "130430235959Z" + */ + this.setString = function(newS) { + this.hTLV = null; + this.isModified = true; + this.s = newS; + this.hV = stohex(newS); + }; + + /** + * set value by a Date object + * @name setByDateValue + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @param {Integer} year year of date (ex. 2013) + * @param {Integer} month month of date between 1 and 12 (ex. 12) + * @param {Integer} day day of month + * @param {Integer} hour hours of date + * @param {Integer} min minutes of date + * @param {Integer} sec seconds of date + */ + this.setByDateValue = function(year, month, day, hour, min, sec) { + var dateObject = new Date(Date.UTC(year, month - 1, day, hour, min, sec, 0)); + this.setByDate(dateObject); + }; + + this.getFreshValueHex = function() { + return this.hV; + }; +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractTime, KJUR.asn1.ASN1Object); +// == END DERAbstractTime ================================================== + +// == BEGIN DERAbstractStructured ============================================ +/** + * base class for ASN.1 DER structured class + * @name KJUR.asn1.DERAbstractStructured + * @class base class for ASN.1 DER structured class + * @property {Array} asn1Array internal array of ASN1Object + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERAbstractStructured = function(params) { + KJUR.asn1.DERAbstractString.superclass.constructor.call(this); + var asn1Array = null; + + /** + * set value by array of ASN1Object + * @name setByASN1ObjectArray + * @memberOf KJUR.asn1.DERAbstractStructured# + * @function + * @param {array} asn1ObjectArray array of ASN1Object to set + */ + this.setByASN1ObjectArray = function(asn1ObjectArray) { + this.hTLV = null; + this.isModified = true; + this.asn1Array = asn1ObjectArray; + }; + + /** + * append an ASN1Object to internal array + * @name appendASN1Object + * @memberOf KJUR.asn1.DERAbstractStructured# + * @function + * @param {ASN1Object} asn1Object to add + */ + this.appendASN1Object = function(asn1Object) { + this.hTLV = null; + this.isModified = true; + this.asn1Array.push(asn1Object); + }; + + this.asn1Array = new Array(); + if (typeof params != "undefined") { + if (typeof params['array'] != "undefined") { + this.asn1Array = params['array']; + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractStructured, KJUR.asn1.ASN1Object); + + +// ******************************************************************** +// ASN.1 Object Classes +// ******************************************************************** + +// ******************************************************************** +/** + * class for ASN.1 DER Boolean + * @name KJUR.asn1.DERBoolean + * @class class for ASN.1 DER Boolean + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERBoolean = function() { + KJUR.asn1.DERBoolean.superclass.constructor.call(this); + this.hT = "01"; + this.hTLV = "0101ff"; +}; +YAHOO.lang.extend(KJUR.asn1.DERBoolean, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER Integer + * @name KJUR.asn1.DERInteger + * @class class for ASN.1 DER Integer + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • int - specify initial ASN.1 value(V) by integer value
    • + *
    • bigint - specify initial ASN.1 value(V) by BigInteger object
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERInteger = function(params) { + KJUR.asn1.DERInteger.superclass.constructor.call(this); + this.hT = "02"; + + /** + * set value by Tom Wu's BigInteger object + * @name setByBigInteger + * @memberOf KJUR.asn1.DERInteger# + * @function + * @param {BigInteger} bigIntegerValue to set + */ + this.setByBigInteger = function(bigIntegerValue) { + this.hTLV = null; + this.isModified = true; + this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue); + }; + + /** + * set value by integer value + * @name setByInteger + * @memberOf KJUR.asn1.DERInteger + * @function + * @param {Integer} integer value to set + */ + this.setByInteger = function(intValue) { + var bi = new BigInteger(String(intValue), 10); + this.setByBigInteger(bi); + }; + + /** + * set value by integer value + * @name setValueHex + * @memberOf KJUR.asn1.DERInteger# + * @function + * @param {String} hexadecimal string of integer value + * @description + *
    + * NOTE: Value shall be represented by minimum octet length of + * two's complement representation. + * @example + * new KJUR.asn1.DERInteger(123); + * new KJUR.asn1.DERInteger({'int': 123}); + * new KJUR.asn1.DERInteger({'hex': '1fad'}); + */ + this.setValueHex = function(newHexString) { + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['bigint'] != "undefined") { + this.setByBigInteger(params['bigint']); + } else if (typeof params['int'] != "undefined") { + this.setByInteger(params['int']); + } else if (typeof params == "number") { + this.setByInteger(params); + } else if (typeof params['hex'] != "undefined") { + this.setValueHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERInteger, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER encoded BitString primitive + * @name KJUR.asn1.DERBitString + * @class class for ASN.1 DER encoded BitString primitive + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • bin - specify binary string (ex. '10111')
    • + *
    • array - specify array of boolean (ex. [true,false,true,true])
    • + *
    • hex - specify hexadecimal string of ASN.1 value(V) including unused bits
    • + *
    • obj - specify {@link KJUR.asn1.ASN1Util.newObject} + * argument for "BitString encapsulates" structure.
    • + *
    + * NOTE1: 'params' can be omitted.
    + * NOTE2: 'obj' parameter have been supported since + * asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25).
    + * @example + * // default constructor + * o = new KJUR.asn1.DERBitString(); + * // initialize with binary string + * o = new KJUR.asn1.DERBitString({bin: "1011"}); + * // initialize with boolean array + * o = new KJUR.asn1.DERBitString({array: [true,false,true,true]}); + * // initialize with hexadecimal string (04 is unused bits) + * o = new KJUR.asn1.DEROctetString({hex: "04bac0"}); + * // initialize with ASN1Util.newObject argument for encapsulated + * o = new KJUR.asn1.DERBitString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}}); + * // above generates a ASN.1 data like this: + * // BIT STRING, encapsulates { + * // SEQUENCE { + * // INTEGER 3 + * // PrintableString 'aaa' + * // } + * // } + */ +KJUR.asn1.DERBitString = function(params) { + if (params !== undefined && typeof params.obj !== "undefined") { + var o = KJUR.asn1.ASN1Util.newObject(params.obj); + params.hex = "00" + o.getEncodedHex(); + } + KJUR.asn1.DERBitString.superclass.constructor.call(this); + this.hT = "03"; + + /** + * set ASN.1 value(V) by a hexadecimal string including unused bits + * @name setHexValueIncludingUnusedBits + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {String} newHexStringIncludingUnusedBits + */ + this.setHexValueIncludingUnusedBits = function(newHexStringIncludingUnusedBits) { + this.hTLV = null; + this.isModified = true; + this.hV = newHexStringIncludingUnusedBits; + }; + + /** + * set ASN.1 value(V) by unused bit and hexadecimal string of value + * @name setUnusedBitsAndHexValue + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {Integer} unusedBits + * @param {String} hValue + */ + this.setUnusedBitsAndHexValue = function(unusedBits, hValue) { + if (unusedBits < 0 || 7 < unusedBits) { + throw "unused bits shall be from 0 to 7: u = " + unusedBits; + } + var hUnusedBits = "0" + unusedBits; + this.hTLV = null; + this.isModified = true; + this.hV = hUnusedBits + hValue; + }; + + /** + * set ASN.1 DER BitString by binary string
    + * @name setByBinaryString + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {String} binaryString binary value string (i.e. '10111') + * @description + * Its unused bits will be calculated automatically by length of + * 'binaryValue'.
    + * NOTE: Trailing zeros '0' will be ignored. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.setByBooleanArray("01011"); + */ + this.setByBinaryString = function(binaryString) { + binaryString = binaryString.replace(/0+$/, ''); + var unusedBits = 8 - binaryString.length % 8; + if (unusedBits == 8) unusedBits = 0; + for (var i = 0; i <= unusedBits; i++) { + binaryString += '0'; + } + var h = ''; + for (var i = 0; i < binaryString.length - 1; i += 8) { + var b = binaryString.substr(i, 8); + var x = parseInt(b, 2).toString(16); + if (x.length == 1) x = '0' + x; + h += x; + } + this.hTLV = null; + this.isModified = true; + this.hV = '0' + unusedBits + h; + }; + + /** + * set ASN.1 TLV value(V) by an array of boolean
    + * @name setByBooleanArray + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {array} booleanArray array of boolean (ex. [true, false, true]) + * @description + * NOTE: Trailing falses will be ignored in the ASN.1 DER Object. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.setByBooleanArray([false, true, false, true, true]); + */ + this.setByBooleanArray = function(booleanArray) { + var s = ''; + for (var i = 0; i < booleanArray.length; i++) { + if (booleanArray[i] == true) { + s += '1'; + } else { + s += '0'; + } + } + this.setByBinaryString(s); + }; + + /** + * generate an array of falses with specified length
    + * @name newFalseArray + * @memberOf KJUR.asn1.DERBitString + * @function + * @param {Integer} nLength length of array to generate + * @return {array} array of boolean falses + * @description + * This static method may be useful to initialize boolean array. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.newFalseArray(3) → [false, false, false] + */ + this.newFalseArray = function(nLength) { + var a = new Array(nLength); + for (var i = 0; i < nLength; i++) { + a[i] = false; + } + return a; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params == "string" && params.toLowerCase().match(/^[0-9a-f]+$/)) { + this.setHexValueIncludingUnusedBits(params); + } else if (typeof params['hex'] != "undefined") { + this.setHexValueIncludingUnusedBits(params['hex']); + } else if (typeof params['bin'] != "undefined") { + this.setByBinaryString(params['bin']); + } else if (typeof params['array'] != "undefined") { + this.setByBooleanArray(params['array']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERBitString, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER OctetString
    + * @name KJUR.asn1.DEROctetString + * @class class for ASN.1 DER OctetString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * This class provides ASN.1 OctetString simple type.
    + * Supported "params" attributes are: + *
      + *
    • str - to set a string as a value
    • + *
    • hex - to set a hexadecimal string as a value
    • + *
    • obj - to set a encapsulated ASN.1 value by JSON object + * which is defined in {@link KJUR.asn1.ASN1Util.newObject}
    • + *
    + * NOTE: A parameter 'obj' have been supported + * for "OCTET STRING, encapsulates" structure. + * since asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25). + * @see KJUR.asn1.DERAbstractString - superclass + * @example + * // default constructor + * o = new KJUR.asn1.DEROctetString(); + * // initialize with string + * o = new KJUR.asn1.DEROctetString({str: "aaa"}); + * // initialize with hexadecimal string + * o = new KJUR.asn1.DEROctetString({hex: "616161"}); + * // initialize with ASN1Util.newObject argument + * o = new KJUR.asn1.DEROctetString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}}); + * // above generates a ASN.1 data like this: + * // OCTET STRING, encapsulates { + * // SEQUENCE { + * // INTEGER 3 + * // PrintableString 'aaa' + * // } + * // } + */ +KJUR.asn1.DEROctetString = function(params) { + if (params !== undefined && typeof params.obj !== "undefined") { + var o = KJUR.asn1.ASN1Util.newObject(params.obj); + params.hex = o.getEncodedHex(); + } + KJUR.asn1.DEROctetString.superclass.constructor.call(this, params); + this.hT = "04"; +}; +YAHOO.lang.extend(KJUR.asn1.DEROctetString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER Null + * @name KJUR.asn1.DERNull + * @class class for ASN.1 DER Null + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERNull = function() { + KJUR.asn1.DERNull.superclass.constructor.call(this); + this.hT = "05"; + this.hTLV = "0500"; +}; +YAHOO.lang.extend(KJUR.asn1.DERNull, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER ObjectIdentifier + * @name KJUR.asn1.DERObjectIdentifier + * @class class for ASN.1 DER ObjectIdentifier + * @param {Array} params associative array of parameters (ex. {'oid': '2.5.4.5'}) + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • oid - specify initial ASN.1 value(V) by a oid string (ex. 2.5.4.13)
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERObjectIdentifier = function(params) { + var itox = function(i) { + var h = i.toString(16); + if (h.length == 1) h = '0' + h; + return h; + }; + var roidtox = function(roid) { + var h = ''; + var bi = new BigInteger(roid, 10); + var b = bi.toString(2); + var padLen = 7 - b.length % 7; + if (padLen == 7) padLen = 0; + var bPad = ''; + for (var i = 0; i < padLen; i++) bPad += '0'; + b = bPad + b; + for (var i = 0; i < b.length - 1; i += 7) { + var b8 = b.substr(i, 7); + if (i != b.length - 7) b8 = '1' + b8; + h += itox(parseInt(b8, 2)); + } + return h; + } + + KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this); + this.hT = "06"; + + /** + * set value by a hexadecimal string + * @name setValueHex + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} newHexString hexadecimal value of OID bytes + */ + this.setValueHex = function(newHexString) { + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = newHexString; + }; + + /** + * set value by a OID string
    + * @name setValueOidString + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} oidString OID string (ex. 2.5.4.13) + * @example + * o = new KJUR.asn1.DERObjectIdentifier(); + * o.setValueOidString("2.5.4.13"); + */ + this.setValueOidString = function(oidString) { + if (! oidString.match(/^[0-9.]+$/)) { + throw "malformed oid string: " + oidString; + } + var h = ''; + var a = oidString.split('.'); + var i0 = parseInt(a[0]) * 40 + parseInt(a[1]); + h += itox(i0); + a.splice(0, 2); + for (var i = 0; i < a.length; i++) { + h += roidtox(a[i]); + } + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = h; + }; + + /** + * set value by a OID name + * @name setValueName + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} oidName OID name (ex. 'serverAuth') + * @since 1.0.1 + * @description + * OID name shall be defined in 'KJUR.asn1.x509.OID.name2oidList'. + * Otherwise raise error. + * @example + * o = new KJUR.asn1.DERObjectIdentifier(); + * o.setValueName("serverAuth"); + */ + this.setValueName = function(oidName) { + var oid = KJUR.asn1.x509.OID.name2oid(oidName); + if (oid !== '') { + this.setValueOidString(oid); + } else { + throw "DERObjectIdentifier oidName undefined: " + oidName; + } + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (params !== undefined) { + if (typeof params === "string") { + if (params.match(/^[0-2].[0-9.]+$/)) { + this.setValueOidString(params); + } else { + this.setValueName(params); + } + } else if (params.oid !== undefined) { + this.setValueOidString(params.oid); + } else if (params.hex !== undefined) { + this.setValueHex(params.hex); + } else if (params.name !== undefined) { + this.setValueName(params.name); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER Enumerated + * @name KJUR.asn1.DEREnumerated + * @class class for ASN.1 DER Enumerated + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • int - specify initial ASN.1 value(V) by integer value
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + * @example + * new KJUR.asn1.DEREnumerated(123); + * new KJUR.asn1.DEREnumerated({int: 123}); + * new KJUR.asn1.DEREnumerated({hex: '1fad'}); + */ +KJUR.asn1.DEREnumerated = function(params) { + KJUR.asn1.DEREnumerated.superclass.constructor.call(this); + this.hT = "0a"; + + /** + * set value by Tom Wu's BigInteger object + * @name setByBigInteger + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {BigInteger} bigIntegerValue to set + */ + this.setByBigInteger = function(bigIntegerValue) { + this.hTLV = null; + this.isModified = true; + this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue); + }; + + /** + * set value by integer value + * @name setByInteger + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {Integer} integer value to set + */ + this.setByInteger = function(intValue) { + var bi = new BigInteger(String(intValue), 10); + this.setByBigInteger(bi); + }; + + /** + * set value by integer value + * @name setValueHex + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {String} hexadecimal string of integer value + * @description + *
    + * NOTE: Value shall be represented by minimum octet length of + * two's complement representation. + */ + this.setValueHex = function(newHexString) { + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['int'] != "undefined") { + this.setByInteger(params['int']); + } else if (typeof params == "number") { + this.setByInteger(params); + } else if (typeof params['hex'] != "undefined") { + this.setValueHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DEREnumerated, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER UTF8String + * @name KJUR.asn1.DERUTF8String + * @class class for ASN.1 DER UTF8String + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERUTF8String = function(params) { + KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params); + this.hT = "0c"; +}; +YAHOO.lang.extend(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER NumericString + * @name KJUR.asn1.DERNumericString + * @class class for ASN.1 DER NumericString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERNumericString = function(params) { + KJUR.asn1.DERNumericString.superclass.constructor.call(this, params); + this.hT = "12"; +}; +YAHOO.lang.extend(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER PrintableString + * @name KJUR.asn1.DERPrintableString + * @class class for ASN.1 DER PrintableString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERPrintableString = function(params) { + KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params); + this.hT = "13"; +}; +YAHOO.lang.extend(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER TeletexString + * @name KJUR.asn1.DERTeletexString + * @class class for ASN.1 DER TeletexString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERTeletexString = function(params) { + KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params); + this.hT = "14"; +}; +YAHOO.lang.extend(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER IA5String + * @name KJUR.asn1.DERIA5String + * @class class for ASN.1 DER IA5String + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERIA5String = function(params) { + KJUR.asn1.DERIA5String.superclass.constructor.call(this, params); + this.hT = "16"; +}; +YAHOO.lang.extend(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER UTCTime + * @name KJUR.asn1.DERUTCTime + * @class class for ASN.1 DER UTCTime + * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) + * @extends KJUR.asn1.DERAbstractTime + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • str - specify initial ASN.1 value(V) by a string (ex.'130430235959Z')
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    • date - specify Date object.
    • + *
    + * NOTE: 'params' can be omitted. + *

    EXAMPLES

    + * @example + * d1 = new KJUR.asn1.DERUTCTime(); + * d1.setString('130430125959Z'); + * + * d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'}); + * d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))}); + * d4 = new KJUR.asn1.DERUTCTime('130430125959Z'); + */ +KJUR.asn1.DERUTCTime = function(params) { + KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params); + this.hT = "17"; + + /** + * set value by a Date object
    + * @name setByDate + * @memberOf KJUR.asn1.DERUTCTime# + * @function + * @param {Date} dateObject Date object to set ASN.1 value(V) + * @example + * o = new KJUR.asn1.DERUTCTime(); + * o.setByDate(new Date("2016/12/31")); + */ + this.setByDate = function(dateObject) { + this.hTLV = null; + this.isModified = true; + this.date = dateObject; + this.s = this.formatDate(this.date, 'utc'); + this.hV = stohex(this.s); + }; + + this.getFreshValueHex = function() { + if (typeof this.date == "undefined" && typeof this.s == "undefined") { + this.date = new Date(); + this.s = this.formatDate(this.date, 'utc'); + this.hV = stohex(this.s); + } + return this.hV; + }; + + if (params !== undefined) { + if (params.str !== undefined) { + this.setString(params.str); + } else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) { + this.setString(params); + } else if (params.hex !== undefined) { + this.setStringHex(params.hex); + } else if (params.date !== undefined) { + this.setByDate(params.date); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime); + +// ******************************************************************** +/** + * class for ASN.1 DER GeneralizedTime + * @name KJUR.asn1.DERGeneralizedTime + * @class class for ASN.1 DER GeneralizedTime + * @param {Array} params associative array of parameters (ex. {'str': '20130430235959Z'}) + * @property {Boolean} withMillis flag to show milliseconds or not + * @extends KJUR.asn1.DERAbstractTime + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • str - specify initial ASN.1 value(V) by a string (ex.'20130430235959Z')
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    • date - specify Date object.
    • + *
    • millis - specify flag to show milliseconds (from 1.0.6)
    • + *
    + * NOTE1: 'params' can be omitted. + * NOTE2: 'withMillis' property is supported from asn1 1.0.6. + */ +KJUR.asn1.DERGeneralizedTime = function(params) { + KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params); + this.hT = "18"; + this.withMillis = false; + + /** + * set value by a Date object + * @name setByDate + * @memberOf KJUR.asn1.DERGeneralizedTime# + * @function + * @param {Date} dateObject Date object to set ASN.1 value(V) + * @example + * When you specify UTC time, use 'Date.UTC' method like this:
    + * o1 = new DERUTCTime(); + * o1.setByDate(date); + * + * date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59 + */ + this.setByDate = function(dateObject) { + this.hTLV = null; + this.isModified = true; + this.date = dateObject; + this.s = this.formatDate(this.date, 'gen', this.withMillis); + this.hV = stohex(this.s); + }; + + this.getFreshValueHex = function() { + if (this.date === undefined && this.s === undefined) { + this.date = new Date(); + this.s = this.formatDate(this.date, 'gen', this.withMillis); + this.hV = stohex(this.s); + } + return this.hV; + }; + + if (params !== undefined) { + if (params.str !== undefined) { + this.setString(params.str); + } else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) { + this.setString(params); + } else if (params.hex !== undefined) { + this.setStringHex(params.hex); + } else if (params.date !== undefined) { + this.setByDate(params.date); + } + if (params.millis === true) { + this.withMillis = true; + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime); + +// ******************************************************************** +/** + * class for ASN.1 DER Sequence + * @name KJUR.asn1.DERSequence + * @class class for ASN.1 DER Sequence + * @extends KJUR.asn1.DERAbstractStructured + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • array - specify array of ASN1Object to set elements of content
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERSequence = function(params) { + KJUR.asn1.DERSequence.superclass.constructor.call(this, params); + this.hT = "30"; + this.getFreshValueHex = function() { + var h = ''; + for (var i = 0; i < this.asn1Array.length; i++) { + var asn1Obj = this.asn1Array[i]; + h += asn1Obj.getEncodedHex(); + } + this.hV = h; + return this.hV; + }; +}; +YAHOO.lang.extend(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured); + +// ******************************************************************** +/** + * class for ASN.1 DER Set + * @name KJUR.asn1.DERSet + * @class class for ASN.1 DER Set + * @extends KJUR.asn1.DERAbstractStructured + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • array - specify array of ASN1Object to set elements of content
    • + *
    • sortflag - flag for sort (default: true). ASN.1 BER is not sorted in 'SET OF'.
    • + *
    + * NOTE1: 'params' can be omitted.
    + * NOTE2: sortflag is supported since 1.0.5. + */ +KJUR.asn1.DERSet = function(params) { + KJUR.asn1.DERSet.superclass.constructor.call(this, params); + this.hT = "31"; + this.sortFlag = true; // item shall be sorted only in ASN.1 DER + this.getFreshValueHex = function() { + var a = new Array(); + for (var i = 0; i < this.asn1Array.length; i++) { + var asn1Obj = this.asn1Array[i]; + a.push(asn1Obj.getEncodedHex()); + } + if (this.sortFlag == true) a.sort(); + this.hV = a.join(''); + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params.sortflag != "undefined" && + params.sortflag == false) + this.sortFlag = false; + } +}; +YAHOO.lang.extend(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured); + +// ******************************************************************** +/** + * class for ASN.1 DER TaggedObject + * @name KJUR.asn1.DERTaggedObject + * @class class for ASN.1 DER TaggedObject + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * Parameter 'tagNoNex' is ASN.1 tag(T) value for this object. + * For example, if you find '[1]' tag in a ASN.1 dump, + * 'tagNoHex' will be 'a1'. + *
    + * As for optional argument 'params' for constructor, you can specify *ANY* of + * following properties: + *
      + *
    • explicit - specify true if this is explicit tag otherwise false + * (default is 'true').
    • + *
    • tag - specify tag (default is 'a0' which means [0])
    • + *
    • obj - specify ASN1Object which is tagged
    • + *
    + * @example + * d1 = new KJUR.asn1.DERUTF8String({'str':'a'}); + * d2 = new KJUR.asn1.DERTaggedObject({'obj': d1}); + * hex = d2.getEncodedHex(); + */ +KJUR.asn1.DERTaggedObject = function(params) { + KJUR.asn1.DERTaggedObject.superclass.constructor.call(this); + this.hT = "a0"; + this.hV = ''; + this.isExplicit = true; + this.asn1Object = null; + + /** + * set value by an ASN1Object + * @name setString + * @memberOf KJUR.asn1.DERTaggedObject# + * @function + * @param {Boolean} isExplicitFlag flag for explicit/implicit tag + * @param {Integer} tagNoHex hexadecimal string of ASN.1 tag + * @param {ASN1Object} asn1Object ASN.1 to encapsulate + */ + this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) { + this.hT = tagNoHex; + this.isExplicit = isExplicitFlag; + this.asn1Object = asn1Object; + if (this.isExplicit) { + this.hV = this.asn1Object.getEncodedHex(); + this.hTLV = null; + this.isModified = true; + } else { + this.hV = null; + this.hTLV = asn1Object.getEncodedHex(); + this.hTLV = this.hTLV.replace(/^../, tagNoHex); + this.isModified = false; + } + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['tag'] != "undefined") { + this.hT = params['tag']; + } + if (typeof params['explicit'] != "undefined") { + this.isExplicit = params['explicit']; + } + if (typeof params['obj'] != "undefined") { + this.asn1Object = params['obj']; + this.setASN1Object(this.isExplicit, this.hT, this.asn1Object); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object); \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/yahoo.js b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/yahoo.js new file mode 100644 index 0000000..fca3b26 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/mp-weixin/src/lib/jsrsasign/yahoo.js @@ -0,0 +1,72 @@ +/*! +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +export var YAHOO = {}; +YAHOO.lang = { + /** + * Utility to set up the prototype, constructor and superclass properties to + * support an inheritance strategy that can chain constructors and methods. + * Static members will not be inherited. + * + * @method extend + * @static + * @param {Function} subc the object to modify + * @param {Function} superc the object to inherit + * @param {Object} overrides additional properties/methods to add to the + * subclass prototype. These will override the + * matching items obtained from the superclass + * if present. + */ + extend: function(subc, superc, overrides) { + if (! superc || ! subc) { + throw new Error("YAHOO.lang.extend failed, please check that " + + "all dependencies are included."); + } + + var F = function() {}; + F.prototype = superc.prototype; + subc.prototype = new F(); + subc.prototype.constructor = subc; + subc.superclass = superc.prototype; + + if (superc.prototype.constructor == Object.prototype.constructor) { + superc.prototype.constructor = superc; + } + + if (overrides) { + var i; + for (i in overrides) { + subc.prototype[i] = overrides[i]; + } + + /* + * IE will not enumerate native functions in a derived object even if the + * function was overridden. This is a workaround for specific functions + * we care about on the Object prototype. + * @property _IEEnumFix + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @static + * @private + */ + var _IEEnumFix = function() {}, + ADD = ["toString", "valueOf"]; + try { + if (/MSIE/.test(navigator.userAgent)) { + _IEEnumFix = function(r, s) { + for (i = 0; i < ADD.length; i = i + 1) { + var fname = ADD[i], f = s[fname]; + if (typeof f === 'function' && f != Object.prototype[fname]) { + r[fname] = f; + } + } + }; + } + } catch (ex) {}; + _IEEnumFix(subc.prototype, overrides); + } + } +}; \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/unierror.uts b/uni_modules/x-crypto-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-crypto-s/utssdk/web/index.uts b/uni_modules/x-crypto-s/utssdk/web/index.uts new file mode 100644 index 0000000..9104347 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/index.uts @@ -0,0 +1,232 @@ +import CryptoJS from "./lib/index.js" +import { JSEncrypt } from "./src/JSEncrypt" +export { RSARANDOMKEY } from "../interface.uts" + +function adjustIV(ivStr, requiredLength = 16) { + // 将字符串转换为字节 + let ivBytes = CryptoJS.enc.Utf8.parse(ivStr); + // 创建一个新的WordArray来存储处理后的IV + let adjustedIV = CryptoJS.lib.WordArray.create(); + + if (ivBytes.sigBytes >= requiredLength) { + // 如果IV长度足够或过长,进行截取 + adjustedIV = CryptoJS.lib.WordArray.create(ivBytes.words.slice(0, requiredLength / 4)); + } else { + // 如果IV长度不足,进行补足0 + adjustedIV = CryptoJS.lib.WordArray.create(ivBytes.words); + for (let i = ivBytes.sigBytes / 4; i < requiredLength / 4; i++) { + adjustedIV.words[i] = 0; + } + adjustedIV.sigBytes = requiredLength; + } + + return adjustedIV; +} + +function adjustIV2(ivStr:Uint8Array, requiredLength = 16) { + // 确保密钥长度为requiredLength字节,不足时用0填充,过长时截断 + const paddedKey = new Uint8Array(requiredLength); + if (ivStr.length < requiredLength) { + paddedKey.set(ivStr, 0); + } else { + paddedKey.set(ivStr.slice(0, requiredLength), 0); + } + + // 将Uint8Array转换为WordArray + const words:number[] = []; + for (let i = 0; i < paddedKey.length; i += 4) { + let word = 0; + for (let j = 0; j < 4 && i + j < paddedKey.length; j++) { + word |= paddedKey[i + j] << (24 - j * 8); + } + words.push(word); + } + return CryptoJS.lib.WordArray.create(words, paddedKey.length); +} + +export function base64Encode(input : string) : string { + return CryptoJS.enc.Utf8.parse(input).toString(CryptoJS.enc.Base64) +} +export function base64Decode(input : string) : string { + return CryptoJS.enc.Base64.parse(input).toString(CryptoJS.enc.Utf8) +} +export function md5(input : string) : string { + return CryptoJS.MD5(input).toString() +} + +export function sha256(str : string) : string { + return CryptoJS.SHA256(str).toString() +} +export function sha512(str : string) : string { + return CryptoJS.SHA512(str).toString() +} +export function hmacSha256(key : string, data : string) : string { + return CryptoJS.HmacSHA256(data, key).toString() +} + +export function hmacSha512(key : string, data : string) : string { + return CryptoJS.HmacSHA512(data, key).toString() +} + +export function sha1(str : string) : string { + return CryptoJS.SHA1(str).toString() +} +/** + * Aes + * @param {string} key utf8字符串它会根据keySize来截取和补足0 + * @param {string} data 待加密的字符 + * @param {string} mode ECB,CBC + * @param {string} iv 固定是16位,不足会补齐0 + * @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + */ +export function aesEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string { + const keyData = adjustIV(key, keySize || 16); + const ivValue = adjustIV(iv || ""); + let word = CryptoJS.AES.encrypt(data, keyData, { + iv: ivValue, + mode: CryptoJS.mode[mode], + padding: CryptoJS.pad.Pkcs7 + }); + return word.toString() +} +/** + * DAes + * @param {string} key utf8字符串它会根据keySize来截取和补足0 + * @param {string} data 加密后的base64的字符 + * @param {string} mode ECB,CBC + * @param {string} iv 固定是16位,不足会补齐0 + * @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256 + */ +export function aesDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string { + const keyData = adjustIV(key, keySize || 16); + const ivValue = adjustIV(iv || ""); + + let word = CryptoJS.AES.decrypt(data, keyData, { iv: ivValue, mode: CryptoJS.mode[mode], padding: CryptoJS.pad.Pkcs7 }); + return word.toString(CryptoJS.enc.Utf8) +} + +export function aesEncrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array { + const keyData = adjustIV2(key, keySize || 16); + + // 将数据转换为WordArray + const words:number[] = []; + for (let i = 0; i < data.length; i += 4) { + let word = 0; + for (let j = 0; j < 4 && i + j < data.length; j++) { + word |= data[i + j] << (24 - j * 8); + } + words.push(word); + } + const dataU8 = CryptoJS.lib.WordArray.create(words, data.length); + + // 处理IV + let ivValue:any; + if (mode === "ECB") { + ivValue = CryptoJS.lib.WordArray.create([]); + } else { + const ivData = iv || new Uint8Array(16); + ivValue = adjustIV2(ivData, 16); + } + + let word = CryptoJS.AES.encrypt(dataU8, keyData, { + iv: ivValue, + mode: CryptoJS.mode[mode], + padding: CryptoJS.pad.Pkcs7 + }); + + // 正确地将WordArray转换为Uint8Array + // @ts-ignore + const resultWords = word.ciphertext.words; + // @ts-ignore + const sigBytes = word.ciphertext.sigBytes; + const result = new Uint8Array(sigBytes); + + for (let i = 0; i < sigBytes; i++) { + const wordIndex = Math.floor(i / 4); + const byteIndex = i % 4; + result[i] = (resultWords[wordIndex] >>> (24 - byteIndex * 8)) & 0xff; + } + + return result; +} + +export function aesDecrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array { + const keyData = adjustIV2(key, keySize || 16); + + // 处理IV + let ivValue:any; + if (mode === "ECB") { + ivValue = CryptoJS.lib.WordArray.create([]); + } else { + const ivData = iv || new Uint8Array(16); + ivValue = adjustIV2(ivData, 16); + } + + // 将加密数据转换为WordArray + const words:number[] = []; + for (let i = 0; i < data.length; i += 4) { + let word = 0; + for (let j = 0; j < 4 && i + j < data.length; j++) { + word |= data[i + j] << (24 - j * 8); + } + words.push(word); + } + const cipherParams = CryptoJS.lib.CipherParams.create({ + ciphertext: CryptoJS.lib.WordArray.create(words, data.length) + }); + + let word = CryptoJS.AES.decrypt(cipherParams, keyData, { iv: ivValue, mode: CryptoJS.mode[mode], padding: CryptoJS.pad.Pkcs7 }); + + // 正确地将WordArray转换为Uint8Array + const resultWords = word.words; + const sigBytes = word.sigBytes; + const result = new Uint8Array(sigBytes); + + for (let i = 0; i < sigBytes; i++) { + const wordIndex = Math.floor(i / 4); + const byteIndex = i % 4; + result[i] = (resultWords[wordIndex] >>> (24 - byteIndex * 8)) & 0xff; + } + + return result; +} + +export function desEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string { + let word = CryptoJS.DES.encrypt(data, key, { iv: CryptoJS.enc.Utf8.parse(iv || ""), mode: CryptoJS.mode[mode] }); + return word.toString() +} + + +export function desDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string { + let word = CryptoJS.DES.decrypt(data, key, { iv: CryptoJS.enc.Utf8.parse(iv || ""), mode: CryptoJS.mode[mode] }); + return word.toString(CryptoJS.enc.Utf8) +} + +export function generateRSAKeyPair(keySize : number = 2048) : RSARANDOMKEY { + const crypt = new JSEncrypt({ default_key_size: keySize.toString() }) + crypt.getKey() + return { + publicKey: crypt.getPublicKey(), + privateKey: crypt.getPrivateKey() + } as RSARANDOMKEY +} + +export function rsaEncrypt(publicKey : string, data : string) : string { + JSEncrypt.prototype.setPublicKey(publicKey) + return JSEncrypt.prototype.encrypt(data) || "" +} +export function rsaDecrypt(privateKey : string, data : string) : string { + JSEncrypt.prototype.setPrivateKey(privateKey) + return JSEncrypt.prototype.decrypt(data) || "" +} +//返回的是hex字符串 +export function rc4Encrypt(key : string, data : string) : string { + return CryptoJS.RC4.encrypt(data, CryptoJS.enc.Utf8.parse(key)).toString(CryptoJS.format.Hex) +} + +// key是hex字符 +export function rc4Decrypt(key : string, data : string) : string { + const ciphertext = CryptoJS.enc.Hex.parse(data); + let dec = CryptoJS.RC4.decrypt({ ciphertext: ciphertext }, CryptoJS.enc.Utf8.parse(key)) + return dec.toString(CryptoJS.enc.Utf8); +} \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/aes.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/aes.d.ts new file mode 100644 index 0000000..288aeb1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/aes.d.ts @@ -0,0 +1,16 @@ +/** + * AES block cipher algorithm. + */ +export class AESAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ +export const AES: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/aes.js b/uni_modules/x-crypto-s/utssdk/web/lib/aes.js new file mode 100644 index 0000000..ed0ebb4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/aes.js @@ -0,0 +1,278 @@ +import { + BlockCipher, +} from './cipher-core.js'; + +// Lookup tables +const _SBOX = []; +const INV_SBOX = []; +const _SUB_MIX_0 = []; +const _SUB_MIX_1 = []; +const _SUB_MIX_2 = []; +const _SUB_MIX_3 = []; +const INV_SUB_MIX_0 = []; +const INV_SUB_MIX_1 = []; +const INV_SUB_MIX_2 = []; +const INV_SUB_MIX_3 = []; + +// Compute lookup tables + +// Compute double table +const d = []; +for (let i = 0; i < 256; i += 1) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } +} + +// Walk GF(2^8) +let x = 0; +let xi = 0; +for (let i = 0; i < 256; i += 1) { + // Compute sbox + let sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + _SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + const x2 = d[x]; + const x4 = d[x2]; + const x8 = d[x4]; + + // Compute sub bytes, mix columns tables + let t = (d[sx] * 0x101) ^ (sx * 0x1010100); + _SUB_MIX_0[x] = (t << 24) | (t >>> 8); + _SUB_MIX_1[x] = (t << 16) | (t >>> 16); + _SUB_MIX_2[x] = (t << 8) | (t >>> 24); + _SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + xi = 1; + x = xi; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } +} + +// Precomputed Rcon lookup +const RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + +/** + * AES block cipher algorithm. + */ +export class AESAlgo extends BlockCipher { + _doReset() { + let t; + + // Skip reset of nRounds has been set before and key did not change + if (this._nRounds && this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + this._keyPriorReset = this._key; + const key = this._keyPriorReset; + const keyWords = key.words; + const keySize = key.sigBytes / 4; + + // Compute number of rounds + this._nRounds = keySize + 6; + const nRounds = this._nRounds; + + // Compute number of key schedule rows + const ksRows = (nRounds + 1) * 4; + + // Compute key schedule + this._keySchedule = []; + const keySchedule = this._keySchedule; + for (let ksRow = 0; ksRow < ksRows; ksRow += 1) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (_SBOX[t >>> 24] << 24) + | (_SBOX[(t >>> 16) & 0xff] << 16) + | (_SBOX[(t >>> 8) & 0xff] << 8) + | _SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize === 4) { + // Sub word + t = (_SBOX[t >>> 24] << 24) + | (_SBOX[(t >>> 16) & 0xff] << 16) + | (_SBOX[(t >>> 8) & 0xff] << 8) + | _SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + this._invKeySchedule = []; + const invKeySchedule = this._invKeySchedule; + for (let invKsRow = 0; invKsRow < ksRows; invKsRow += 1) { + const ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + t = keySchedule[ksRow]; + } else { + t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[_SBOX[t >>> 24]] + ^ INV_SUB_MIX_1[_SBOX[(t >>> 16) & 0xff]] + ^ INV_SUB_MIX_2[_SBOX[(t >>> 8) & 0xff]] + ^ INV_SUB_MIX_3[_SBOX[t & 0xff]]; + } + } + } + + encryptBlock(M, offset) { + this._doCryptBlock( + M, offset, this._keySchedule, _SUB_MIX_0, _SUB_MIX_1, _SUB_MIX_2, _SUB_MIX_3, _SBOX, + ); + } + + decryptBlock(M, offset) { + const _M = M; + + // Swap 2nd and 4th rows + let t = _M[offset + 1]; + _M[offset + 1] = _M[offset + 3]; + _M[offset + 3] = t; + + this._doCryptBlock( + _M, + offset, + this._invKeySchedule, + INV_SUB_MIX_0, + INV_SUB_MIX_1, + INV_SUB_MIX_2, + INV_SUB_MIX_3, + INV_SBOX, + ); + + // Inv swap 2nd and 4th rows + t = _M[offset + 1]; + _M[offset + 1] = _M[offset + 3]; + _M[offset + 3] = t; + } + + _doCryptBlock(M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + const _M = M; + + // Shortcut + const nRounds = this._nRounds; + + // Get input, add round key + let s0 = _M[offset] ^ keySchedule[0]; + let s1 = _M[offset + 1] ^ keySchedule[1]; + let s2 = _M[offset + 2] ^ keySchedule[2]; + let s3 = _M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + let ksRow = 4; + + // Rounds + for (let round = 1; round < nRounds; round += 1) { + // Shift rows, sub bytes, mix columns, add round key + const t0 = SUB_MIX_0[s0 >>> 24] + ^ SUB_MIX_1[(s1 >>> 16) & 0xff] + ^ SUB_MIX_2[(s2 >>> 8) & 0xff] + ^ SUB_MIX_3[s3 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t1 = SUB_MIX_0[s1 >>> 24] + ^ SUB_MIX_1[(s2 >>> 16) & 0xff] + ^ SUB_MIX_2[(s3 >>> 8) & 0xff] + ^ SUB_MIX_3[s0 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t2 = SUB_MIX_0[s2 >>> 24] + ^ SUB_MIX_1[(s3 >>> 16) & 0xff] + ^ SUB_MIX_2[(s0 >>> 8) & 0xff] + ^ SUB_MIX_3[s1 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + const t3 = SUB_MIX_0[s3 >>> 24] + ^ SUB_MIX_1[(s0 >>> 16) & 0xff] + ^ SUB_MIX_2[(s1 >>> 8) & 0xff] + ^ SUB_MIX_3[s2 & 0xff] + ^ keySchedule[ksRow]; + ksRow += 1; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + const t0 = ( + (SBOX[s0 >>> 24] << 24) + | (SBOX[(s1 >>> 16) & 0xff] << 16) + | (SBOX[(s2 >>> 8) & 0xff] << 8) + | SBOX[s3 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t1 = ( + (SBOX[s1 >>> 24] << 24) + | (SBOX[(s2 >>> 16) & 0xff] << 16) + | (SBOX[(s3 >>> 8) & 0xff] << 8) + | SBOX[s0 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t2 = ( + (SBOX[s2 >>> 24] << 24) + | (SBOX[(s3 >>> 16) & 0xff] << 16) + | (SBOX[(s0 >>> 8) & 0xff] << 8) + | SBOX[s1 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + const t3 = ( + (SBOX[s3 >>> 24] << 24) + | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff] + ) ^ keySchedule[ksRow]; + ksRow += 1; + + // Set output + _M[offset] = t0; + _M[offset + 1] = t1; + _M[offset + 2] = t2; + _M[offset + 3] = t3; + } +} +AESAlgo.keySize = 256 / 32; + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ +export const AES = BlockCipher._createHelper(AESAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/blowfish.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/blowfish.d.ts new file mode 100644 index 0000000..9a6e89e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/blowfish.d.ts @@ -0,0 +1,16 @@ +/** + * Blowfish block cipher algorithm. + */ +export class BlowfishAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ +export const Blowfish: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/blowfish.js b/uni_modules/x-crypto-s/utssdk/web/lib/blowfish.js new file mode 100644 index 0000000..188136a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/blowfish.js @@ -0,0 +1,446 @@ +import { + WordArray, +} from './core.js'; +import { + BlockCipher, +} from './cipher-core.js'; + +const N = 16; + +//Origin pbox and sbox, derived from PI +const ORIG_P = [ + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B, +]; + +const ORIG_S = [ + [0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A,], + [0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7,], + [0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0,], + [0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6,], +]; + +const blowfishCtx = { + pbox: [], + sbox: [], +}; + +function f(ctx, x) { + const a = (x >> 24) & 0xFF; + const b = (x >> 16) & 0xFF; + const c = (x >> 8) & 0xFF; + const d = x & 0xFF; + + let y = ctx.sbox[0][a] + ctx.sbox[1][b]; + y = y ^ ctx.sbox[2][c]; + y = y + ctx.sbox[3][d]; + + return y; +} + +function blowfishEncrypt(ctx, left, right) { + let Xl = left; + let Xr = right; + let temp; + + for(let i = 0; i < N; ++i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = f(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[N]; + Xl = Xl ^ ctx.pbox[N + 1]; + + return {left: Xl, right: Xr}; +} + +function blowfishDecrypt(ctx, left, right) { + let Xl = left; + let Xr = right; + let temp; + + for(let i = N + 1; i > 1; --i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = f(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[1]; + Xl = Xl ^ ctx.pbox[0]; + + return {left: Xl, right: Xr}; +} + +/** +* Initialization ctx's pbox and sbox. +* +* @param {Object} ctx The object has pbox and sbox. +* @param {Array} key An array of 32-bit words. +* @param {int} keysize The length of the key. +* +* @example +* +* blowfishInit(BLOWFISH_CTX, key, 128/32); +*/ +function blowfishInit(ctx, key, keysize) { + for (let Row = 0; Row < 4; Row++) { + ctx.sbox[Row] = []; + for (let Col = 0; Col < 256; Col++) { + ctx.sbox[Row][Col] = ORIG_S[Row][Col]; + } + } + + let keyIndex = 0; + for (let index = 0; index < N + 2; index++) { + ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex]; + keyIndex++; + if (keyIndex >= keysize) { + keyIndex = 0; + } + } + + let data1 = 0; + let data2 = 0; + let res = 0; + for (let i = 0; i < N + 2; i += 2) { + res = blowfishEncrypt(ctx, data1, data2); + data1 = res.left; + data2 = res.right; + ctx.pbox[i] = data1; + ctx.pbox[i + 1] = data2; + } + + for (let i = 0; i < 4; i++) { + for (let j = 0; j < 256; j += 2) { + res = blowfishEncrypt(ctx, data1, data2); + data1 = res.left; + data2 = res.right; + ctx.sbox[i][j] = data1; + ctx.sbox[i][j + 1] = data2; + } + } + + return true; +} + +/** + * Blowfish block cipher algorithm. + */ +export class BlowfishAlgo extends BlockCipher { + constructor(xformMode, key, cfg) { + super(xformMode, key, cfg); + + // blickSize is an instance field and should set in constructor. + this.blockSize = 64 / 32; + } + + _doReset() { + // Skip reset of nRounds has been set before and key did not change + if (this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + const key = this._keyPriorReset = this._key; + const keyWords = key.words; + const keySize = key.sigBytes / 4; + + //Initialization pbox and sbox + blowfishInit(blowfishCtx, keyWords, keySize); + } + + encryptBlock(M, offset) { + const res = blowfishEncrypt(blowfishCtx, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + } + + decryptBlock(M, offset) { + const res = blowfishDecrypt(blowfishCtx, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + } +} +BlowfishAlgo.keySize = 128 / 32; +BlowfishAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ +export const Blowfish = BlockCipher._createHelper(BlowfishAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/cipher-core.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/cipher-core.d.ts new file mode 100644 index 0000000..8cd7581 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/cipher-core.d.ts @@ -0,0 +1,442 @@ +export interface CipherCfg { + // Cipher + iv?: WordArray; + mode?: Function; + padding?: Padding; + // SerializableCipher + format?: Format; + // PasswordBasedCipher + kdf?: Kdf; + salt?: WordArray | string; + hasher?: Function; + // RC4Drop + drop?: number; +} +export interface CipherObj { + encrypt(message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams; + decrypt(ciphertext: CipherParams | CipherParamsCfg | string, key: WordArray | string, cfg?: CipherCfg): WordArray; +} +/** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ +export class Cipher extends BufferedBlockAlgorithm { + static keySize: number; + static ivSize: number; + static _ENC_XFORM_MODE: number; + static _DEC_XFORM_MODE: number; + blockSize: number; + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + static createEncryptor(key: WordArray, cfg?: CipherCfg): Cipher; + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + static createDecryptor(key: WordArray, cfg?: CipherCfg): Cipher; + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * const AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + static _createHelper(SubCipher: Function): CipherObj; + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * const cipher = CryptoJS.algo.AES.create( + * CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray } + * ); + */ + static create(xformMode: number, key: WordArray, cfg?: CipherCfg): Cipher; + constructor(xformMode: number, key: WordArray, cfg?: CipherCfg); + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base & CipherCfg; + _xformMode: number; + _key: WordArray; + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * const encrypted = cipher.process('data'); + * const encrypted = cipher.process(wordArray); + */ + process(dataUpdate: WordArray | string): WordArray; + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * const encrypted = cipher.finalize(); + * const encrypted = cipher.finalize('data'); + * const encrypted = cipher.finalize(wordArray); + */ + finalize(dataUpdate?: WordArray | string): WordArray; +} +/** + * Abstract base stream cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ +export class StreamCipher extends Cipher { + static create(...args: Array): StreamCipher; + constructor(...args: Array); + _doFinalize(): WordArray; +} +/** + * Abstract base block cipher mode template. + */ +export class BlockCipherMode extends Base { + static Encryptor: BlockCipherMode; + static Decryptor: BlockCipherMode; + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + static createEncryptor(cipher: Cipher, iv: number[]): BlockCipherMode; + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + static createDecryptor(cipher: Cipher, iv: number[]): BlockCipherMode; + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * const mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + static create(cipher: Cipher, iv: Array): BlockCipherMode; + constructor(cipher: Cipher, iv: Array); + _cipher: Cipher; + _iv: number[]; + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words: number[], offset: number): void; +} +/** + * Cipher Block Chaining mode. + */ +/** + * Abstract base CBC mode. + */ +export class CBC extends BlockCipherMode { +} +export interface Padding { + pad(data: WordArray, blockSize: number): void; + unpad(data: WordArray): void; +} +/** + * PKCS #5/7 padding strategy. + */ +export const Pkcs7: Padding; +/** + * Abstract base block cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ +export class BlockCipher extends Cipher { + static create(xformMode: number, key: WordArray, cfg?: CipherCfg): BlockCipher; + constructor(xformMode: number, key: WordArray, cfg?: CipherCfg); + _mode: BlockCipherMode; + _doProcessBlock(words: number[], offset: number): void; + _doFinalize(): WordArray; + encryptBlock(M: number[], offset: number): void; + decryptBlock(M: number[], offset: number): void; +} +export interface CipherParamsCfg { + ciphertext?: WordArray; + key?: WordArray; + iv?: WordArray; + salt?: WordArray; + algorithm?: Function; + mode?: Function; + padding?: Padding; + blockSize?: number; + formatter?: Format; +} +/** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter + * The default formatting strategy to convert this cipher params object to a string. + */ +export class CipherParams extends Base { + ciphertext?: WordArray; + key?: WordArray; + iv?: WordArray; + salt?: WordArray; + algorithm?: Function; + mode?: Function; + padding?: Padding; + blockSize?: number; + formatter?: Format; + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + static create(cipherParams: CipherParams | CipherParamsCfg): CipherParams; + constructor(cipherParams: CipherParams | CipherParamsCfg); + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString(formatter?: Format): string; +} +export interface Format { + stringify(cipherParams: CipherParams): string; + parse(str: string): CipherParams; +} +/** + * OpenSSL formatting strategy. + */ +export const OpenSSLFormatter: Format; +/** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ +export class SerializableCipher extends Base { + static cfg: Base & { + format: Format; + }; + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher: Function, message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams; + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher: Function, ciphertext: CipherParams | string, key: WordArray | string, cfg?: CipherCfg): WordArray; + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * ._parse(ciphertextStringOrParams, format); + */ + static _parse(ciphertext: CipherParams | string, format: Format): CipherParams; +} +export interface Kdf { + execute(password: string, keySize: number, ivSize: number, salt?: WordArray | string, hasher?: Function): CipherParams; +} +/** + * OpenSSL key derivation function. + */ +export const OpenSSLKdf: Kdf; +/** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ +export class PasswordBasedCipher extends SerializableCipher { + static cfg: Base & { + format: Format; + kdf: Kdf; + }; + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher: Function, message: WordArray | string, passed: string, cfg?: CipherCfg): CipherParams; + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', + * { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', + * { format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher: Function, ciphertext: CipherParams | string, password: string, cfg?: CipherCfg): WordArray; +} +import { BufferedBlockAlgorithm } from './core.js'; +import { WordArray } from './core.js'; +import { Base } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/cipher-core.js b/uni_modules/x-crypto-s/utssdk/web/lib/cipher-core.js new file mode 100644 index 0000000..54a75ea --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/cipher-core.js @@ -0,0 +1,883 @@ +/* eslint-disable no-use-before-define */ + +import { + Base, + WordArray, + BufferedBlockAlgorithm, +} from './core.js'; +import { Base64 } from './enc-base64.js'; +import { EvpKDFAlgo } from './evpkdf.js'; + +/** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ +export class Cipher extends BufferedBlockAlgorithm { + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * const cipher = CryptoJS.algo.AES.create( + * CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray } + * ); + */ + constructor(xformMode, key, cfg) { + super(); + + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + this.cfg = Object.assign(new Base(), cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + } + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + static createEncryptor(key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + } + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * const cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + static createDecryptor(key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + } + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * const AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + static _createHelper(SubCipher) { + const selectCipherStrategy = (key) => { + if (typeof key === 'string') { + return PasswordBasedCipher; + } + return SerializableCipher; + }; + + return { + encrypt(message, key, cfg) { + return selectCipherStrategy(key).encrypt(SubCipher, message, key, cfg); + }, + + decrypt(ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(SubCipher, ciphertext, key, cfg); + }, + }; + } + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset() { + // Reset data buffer + super.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + } + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * const encrypted = cipher.process('data'); + * const encrypted = cipher.process(wordArray); + */ + process(dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + } + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * const encrypted = cipher.finalize(); + * const encrypted = cipher.finalize('data'); + * const encrypted = cipher.finalize(wordArray); + */ + finalize(dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + const finalProcessedData = this._doFinalize(); + + return finalProcessedData; + } +} +Cipher._ENC_XFORM_MODE = 1; +Cipher._DEC_XFORM_MODE = 2; +Cipher.keySize = 128 / 32; +Cipher.ivSize = 128 / 32; + +/** + * Abstract base stream cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ +export class StreamCipher extends Cipher { + constructor(...args) { + super(...args); + + this.blockSize = 1; + } + + _doFinalize() { + // Process partial blocks + const finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + } +} + +/** + * Abstract base block cipher mode template. + */ +export class BlockCipherMode extends Base { + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * const mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + constructor(cipher, iv) { + super(); + + this._cipher = cipher; + this._iv = iv; + } + + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + static createEncryptor(cipher, iv) { + return this.Encryptor.create(cipher, iv); + } + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * const mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + static createDecryptor(cipher, iv) { + return this.Decryptor.create(cipher, iv); + } +} + +function xorBlock(words, offset, blockSize) { + const _words = words; + let block; + + // Shortcut + const iv = this._iv; + + // Choose mixing block + if (iv) { + block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + block = this._prevBlock; + } + + // XOR blocks + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= block[i]; + } +} + +/** + * Cipher Block Chaining mode. + */ + +/** + * Abstract base CBC mode. + */ +export class CBC extends BlockCipherMode { +} +/** + * CBC encryptor. + */ +CBC.Encryptor = class extends CBC { + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } +}; +/** + * CBC decryptor. + */ +CBC.Decryptor = class extends CBC { + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // Remember this block to use with next block + const thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } +}; + +/** + * PKCS #5/7 padding strategy. + */ +export const Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad(data, blockSize) { + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); + + // Create padding word + const paddingWord = (nPaddingBytes << 24) + | (nPaddingBytes << 16) + | (nPaddingBytes << 8) + | nPaddingBytes; + + // Create padding + const paddingWords = []; + for (let i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + const padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad(data) { + const _data = data; + + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; + +/** + * Abstract base block cipher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ +export class BlockCipher extends Cipher { + constructor(xformMode, key, cfg) { + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + super(xformMode, key, Object.assign( + { + mode: CBC, + padding: Pkcs7, + }, + cfg, + )); + + this.blockSize = 128 / 32; + } + + reset() { + let modeCreator; + + // Reset cipher + super.reset.call(this); + + // Shortcuts + const { cfg } = this; + const { iv, mode } = cfg; + + // Reset block mode + if (this._xformMode === this.constructor._ENC_XFORM_MODE) { + modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + modeCreator = mode.createDecryptor; + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + + this._mode = modeCreator.call(mode, this, iv && iv.words); + this._mode.__creator = modeCreator; + } + + _doProcessBlock(words, offset) { + this._mode.processBlock(words, offset); + } + + _doFinalize() { + let finalProcessedBlocks; + + // Shortcut + const { padding } = this.cfg; + + // Finalize + if (this._xformMode === this.constructor._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + } +} + +/** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter + * The default formatting strategy to convert this cipher params object to a string. + */ +export class CipherParams extends Base { + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + constructor(cipherParams) { + super(); + + this.mixIn(cipherParams); + } + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString(formatter) { + return (formatter || this.formatter).stringify(this); + } +} + +/** + * OpenSSL formatting strategy. + */ +export const OpenSSLFormatter = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify(cipherParams) { + let wordArray; + + // Shortcuts + const { ciphertext, salt } = cipherParams; + + // Format + if (salt) { + wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse(openSSLStr) { + let salt; + + // Parse base64 + const ciphertext = Base64.parse(openSSLStr); + + // Shortcut + const ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] === 0x53616c74 && ciphertextWords[1] === 0x65645f5f) { + // Extract salt + salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext, salt }); + }, +}; + +/** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ +export class SerializableCipher extends Base { + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * .encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher, message, key, cfg) { + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Encrypt + const encryptor = cipher.createEncryptor(key, _cfg); + const ciphertext = encryptor.finalize(message); + + // Shortcut + const cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext, + key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: encryptor.blockSize, + formatter: _cfg.format, + }); + } + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, key, + * { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher, ciphertext, key, cfg) { + let _ciphertext = ciphertext; + + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Convert string to CipherParams + _ciphertext = this._parse(_ciphertext, _cfg.format); + + // Decrypt + const plaintext = cipher.createDecryptor(key, _cfg).finalize(_ciphertext.ciphertext); + + return plaintext; + } + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher + * ._parse(ciphertextStringOrParams, format); + */ + static _parse(ciphertext, format) { + if (typeof ciphertext === 'string') { + return format.parse(ciphertext, this); + } + return ciphertext; + } +} +/** + * Configuration options. + * + * @property {Formatter} format + * + * The formatting strategy to convert cipher param objects to and from a string. + * Default: OpenSSL + */ +SerializableCipher.cfg = Object.assign( + new Base(), + { format: OpenSSLFormatter }, +); + +/** + * OpenSSL key derivation function. + */ +export const OpenSSLKdf = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt + * (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute(password, keySize, ivSize, salt, hasher) { + let _salt = salt; + + // Generate random salt + if (!_salt) { + _salt = WordArray.random(64 / 8); + } + + // Derive key and IV + let key; + if (!hasher) { + key = EvpKDFAlgo.create({ keySize: keySize + ivSize }).compute(password, _salt); + } else { + key = EvpKDFAlgo.create({ keySize: keySize + ivSize, hasher }).compute(password, _salt); + } + + // Separate key and IV + const iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key, iv, salt: _salt }); + }, +}; + +/** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ +export class PasswordBasedCipher extends SerializableCipher { + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher + * .encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + static encrypt(cipher, message, password, cfg) { + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Derive key and other params + const derivedParams = _cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, _cfg.salt, _cfg.hasher); + + // Add IV to config + _cfg.iv = derivedParams.iv; + + // Encrypt + const ciphertext = SerializableCipher.encrypt + .call(this, cipher, message, derivedParams.key, _cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + } + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', + * { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher + * .decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', + * { format: CryptoJS.format.OpenSSL }); + */ + static decrypt(cipher, ciphertext, password, cfg) { + let _ciphertext = ciphertext; + + // Apply config defaults + const _cfg = Object.assign(new Base(), this.cfg, cfg); + + // Convert string to CipherParams + _ciphertext = this._parse(_ciphertext, _cfg.format); + + // Derive key and other params + const derivedParams = _cfg.kdf + .execute(password, cipher.keySize, cipher.ivSize, _ciphertext.salt, _cfg.hasher); + + // Add IV to config + _cfg.iv = derivedParams.iv; + + // Decrypt + const plaintext = SerializableCipher.decrypt + .call(this, cipher, _ciphertext, derivedParams.key, _cfg); + + return plaintext; + } +} +/** + * Configuration options. + * + * @property {KDF} kdf + * The key derivation function to use to generate a key and IV from a password. + * Default: OpenSSL + */ +PasswordBasedCipher.cfg = Object.assign(SerializableCipher.cfg, { kdf: OpenSSLKdf }); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/core.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/core.d.ts new file mode 100644 index 0000000..02a870c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/core.d.ts @@ -0,0 +1,342 @@ +/** + * Base class for inheritance. + */ +export class Base { + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + static create(...args: any[]): Base; + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn(properties: object): Base; + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone(): Base; +} +/** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class WordArray extends Base { + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + static random(nBytes: number): WordArray; + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + static create( + words?: Array | ArrayBuffer | Uint8Array | Int8Array | Uint8ClampedArray + | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, + sigBytes?: number, + ): WordArray; + constructor( + words?: Array | ArrayBuffer | Uint8Array | Int8Array | Uint8ClampedArray + | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, + sigBytes?: number, + ); + words: Array; + sigBytes: number; + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString(encoder?: Encoder): string; + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat(wordArray: WordArray): WordArray; + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp(): void; + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone(): WordArray; +} +export interface Encoder { + stringify(wordArray: WordArray): string; + parse(str: string): WordArray; +} +export const Hex: Encoder; +export const Latin1: Encoder; +export const Utf8: Encoder; +/** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize + * + * The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ +export class BufferedBlockAlgorithm extends Base { + _minBufferSize: number; + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset(): void; + _data: WordArray; + _nDataBytes: number; + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data + * + * The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append(data: WordArray | string): void; + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process(doFlush?: boolean): WordArray; + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone(): BufferedBlockAlgorithm; +} +export interface HasherCfg { + // SHA3 + outputLength?: number +} +export type HashFn = (message: WordArray | string, cfg?: HasherCfg) => WordArray; +export type HMACHashFn = (message: WordArray | string, key: WordArray | string) => WordArray; +/** + * Abstract hasher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ +export class Hasher extends BufferedBlockAlgorithm { + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} SubHasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + static _createHelper(SubHasher: Hasher): HashFn; + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} SubHasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + static _createHmacHelper(SubHasher: Hasher): HMACHashFn; + static create(cfg?: HasherCfg): Hasher; + constructor(cfg?: HasherCfg); + blockSize: number; + /** + * Configuration options. + */ + cfg: Base; + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update(messageUpdate: WordArray | string): Hasher; + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize(messageUpdate?: WordArray | string): WordArray; + _doReset(): void; + _hash: WordArray; + _doProcessBlock(M: number[], offset: number): void; + _doFinalize(): WordArray; +} +/** + * HMAC algorithm. + */ +export class HMAC extends Base { + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} SubHasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + static create(SubHasher: Function, key: WordArray | string): HMAC; + constructor(SubHasher: Function, key: WordArray | string); + _hasher: Hasher; + _oKey: WordArray; + _iKey: WordArray; + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset(): void; + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update(messageUpdate: WordArray | string): HMAC; + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize(messageUpdate?: WordArray | string): WordArray; +} +export interface KDFCfg { + // EvpKDF + keySize?: number; + hasher?: Function; + iterations?: number; +} +export type KDFFn = (password: WordArray | string, salt: WordArray | string, cfg?: KDFCfg) => WordArray; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/core.js b/uni_modules/x-crypto-s/utssdk/web/lib/core.js new file mode 100644 index 0000000..a7454c9 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/core.js @@ -0,0 +1,800 @@ +/* eslint-disable no-use-before-define */ + +const crypto = + (typeof globalThis != 'undefined' ? globalThis : void 0)?.crypto || + (typeof global != 'undefined' ? global : void 0)?.crypto || + (typeof window != 'undefined' ? window : void 0)?.crypto || + (typeof self != 'undefined' ? self : void 0)?.crypto || + (typeof frames != 'undefined' ? frames : void 0)?.[0]?.crypto; + +let randomWordArray; + +if (crypto) { + randomWordArray = (nBytes) => { + const words = []; + + for (let i = 0, rcache; i < nBytes; i += 4) { + words.push(crypto.getRandomValues(new Uint32Array(1))[0]); + } + + return new WordArray(words, nBytes); + } +} else { + // Because there is no global crypto property in this context, cryptographically unsafe Math.random() is used. + + randomWordArray = (nBytes) => { + const words = []; + + const r = (m_w) => { + let _m_w = m_w; + let _m_z = 0x3ade68b1; + const mask = 0xffffffff; + + return () => { + _m_z = (0x9069 * (_m_z & 0xFFFF) + (_m_z >> 0x10)) & mask; + _m_w = (0x4650 * (_m_w & 0xFFFF) + (_m_w >> 0x10)) & mask; + let result = ((_m_z << 0x10) + _m_w) & mask; + result /= 0x100000000; + result += 0.5; + return result * (Math.random() > 0.5 ? 1 : -1); + }; + }; + + for (let i = 0, rcache; i < nBytes; i += 4) { + const _r = r((rcache || Math.random()) * 0x100000000); + + rcache = _r() * 0x3ade67b7; + words.push((_r() * 0x100000000) | 0); + } + + return new WordArray(words, nBytes); + } +} + +/** + * Base class for inheritance. + */ +export class Base { + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + static create(...args) { + return new this(...args); + } + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn(properties) { + return Object.assign(this, properties); + } + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone() { + const clone = new this.constructor(); + Object.assign(clone, this); + return clone; + } +} + +/** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + constructor(words = [], sigBytes = words.length * 4) { + super(); + + let typedArray = words; + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array + || typedArray instanceof Uint8ClampedArray + || typedArray instanceof Int16Array + || typedArray instanceof Uint16Array + || typedArray instanceof Int32Array + || typedArray instanceof Uint32Array + || typedArray instanceof Float32Array + || typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + const typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + const _words = []; + for (let i = 0; i < typedArrayByteLength; i += 1) { + _words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + this.words = _words; + this.sigBytes = typedArrayByteLength; + } else { + // Else call normal init + this.words = words; + this.sigBytes = sigBytes; + } + } + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + static random = randomWordArray; + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString(encoder = Hex) { + return encoder.stringify(this); + } + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat(wordArray) { + // Shortcuts + const thisWords = this.words; + const thatWords = wordArray.words; + const thisSigBytes = this.sigBytes; + const thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (let i = 0; i < thatSigBytes; i += 1) { + const thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (let i = 0; i < thatSigBytes; i += 4) { + thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + } + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp() { + // Shortcuts + const { words, sigBytes } = this; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + } + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone() { + const clone = super.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + } +} + +/** + * Hex encoding strategy. + */ +export const Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const hexChars = []; + for (let i = 0; i < sigBytes; i += 1) { + const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse(hexStr) { + // Shortcut + const hexStrLength = hexStr.length; + + // Convert + const words = []; + for (let i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray(words, hexStrLength / 2); + }, +}; + +/** + * Latin1 encoding strategy. + */ +export const Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const latin1Chars = []; + for (let i = 0; i < sigBytes; i += 1) { + const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse(latin1Str) { + // Shortcut + const latin1StrLength = latin1Str.length; + + // Convert + const words = []; + for (let i = 0; i < latin1StrLength; i += 1) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray(words, latin1StrLength); + }, +}; + +/** + * UTF-8 encoding strategy. + */ +export const Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify(wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse(utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + }, +}; + +/** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize + * + * The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ +export class BufferedBlockAlgorithm extends Base { + constructor() { + super(); + this._minBufferSize = 0; + } + + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset() { + // Initial values + this._data = new WordArray(); + this._nDataBytes = 0; + } + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data + * + * The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append(data) { + let m_data = data; + + // Convert string to WordArray, else assume WordArray already + if (typeof m_data === 'string') { + m_data = Utf8.parse(m_data); + } + + // Append + this._data.concat(m_data); + this._nDataBytes += m_data.sigBytes; + } + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process(doFlush) { + let processedWords; + + // Shortcuts + const { _data: data, blockSize } = this; + const dataWords = data.words; + const dataSigBytes = data.sigBytes; + const blockSizeBytes = blockSize * 4; + + // Count blocks ready + let nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + const nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (let offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray(processedWords, nBytesReady); + } + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone() { + const clone = super.clone.call(this); + clone._data = this._data.clone(); + + return clone; + } +} + +/** + * Abstract hasher template. + * + * @property {number} blockSize + * + * The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ +export class Hasher extends BufferedBlockAlgorithm { + constructor(cfg) { + super(); + + this.blockSize = 512 / 32; + + /** + * Configuration options. + */ + this.cfg = Object.assign(new Base(), cfg); + + // Set initial values + this.reset(); + } + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} SubHasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + static _createHelper(SubHasher) { + return (message, cfg) => new SubHasher(cfg).finalize(message); + } + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} SubHasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + static _createHmacHelper(SubHasher) { + return (message, key) => new HMAC(SubHasher, key).finalize(message); + } + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset() { + // Reset data buffer + super.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + } + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update(messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + } + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize(messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + const hash = this._doFinalize(); + + return hash; + } +} + +/** + * HMAC algorithm. + */ +export class HMAC extends Base { + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} SubHasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + constructor(SubHasher, key) { + super(); + + const hasher = new SubHasher(); + this._hasher = hasher; + + // Convert string to WordArray, else assume WordArray already + let _key = key; + if (typeof _key === 'string') { + _key = Utf8.parse(_key); + } + + // Shortcuts + const hasherBlockSize = hasher.blockSize; + const hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (_key.sigBytes > hasherBlockSizeBytes) { + _key = hasher.finalize(key); + } + + // Clamp excess bits + _key.clamp(); + + // Clone key for inner and outer pads + const oKey = _key.clone(); + this._oKey = oKey; + const iKey = _key.clone(); + this._iKey = iKey; + + // Shortcuts + const oKeyWords = oKey.words; + const iKeyWords = iKey.words; + + // XOR keys with pad constants + for (let i = 0; i < hasherBlockSize; i += 1) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = hasherBlockSizeBytes; + iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + } + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset() { + // Shortcut + const hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + } + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update(messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + } + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize(messageUpdate) { + // Shortcut + const hasher = this._hasher; + + // Compute HMAC + const innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + const hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } +} diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64.d.ts new file mode 100644 index 0000000..be1e5c6 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64.d.ts @@ -0,0 +1,7 @@ +export function parseLoop(base64Str: string, base64StrLength: number, reverseMap: number[]): WordArray; +/** + * Base64 encoding strategy. + */ +export const Base64: Encoder; +import { Encoder } from './core.js'; +import { WordArray } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64.js b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64.js new file mode 100644 index 0000000..fe45de5 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64.js @@ -0,0 +1,111 @@ +import { + WordArray, +} from './core.js'; + +export const parseLoop = (base64Str, base64StrLength, reverseMap) => { + const words = []; + let nBytes = 0; + for (let i = 0; i < base64StrLength; i += 1) { + if (i % 4) { + const bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + const bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + const bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes += 1; + } + } + return WordArray.create(words, nBytes); +}; + +/** + * Base64 encoding strategy. + */ +export const Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * const base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + const map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + const base64Chars = []; + for (let i = 0; i < sigBytes; i += 3) { + const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + const triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + const paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse(base64Str) { + // Shortcuts + let base64StrLength = base64Str.length; + const map = this._map; + let reverseMap = this._reverseMap; + + if (!reverseMap) { + this._reverseMap = []; + reverseMap = this._reverseMap; + for (let j = 0; j < map.length; j += 1) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + const paddingChar = map.charAt(64); + if (paddingChar) { + const paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64url.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64url.d.ts new file mode 100644 index 0000000..d16ffc4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64url.d.ts @@ -0,0 +1,5 @@ +/** + * Base64url encoding strategy. + */ +export const Base64url: Encoder; +import { Encoder } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64url.js b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64url.js new file mode 100644 index 0000000..eff6701 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/enc-base64url.js @@ -0,0 +1,105 @@ +import { + WordArray, +} from './core.js'; +import { + parseLoop, +} from './enc-base64.js' + +/** + * Base64url encoding strategy. + */ +export const Base64url = { + /** + * Converts a word array to a Base64url string. + * + * @param {WordArray} wordArray The word array. + * + * @param {boolean} urlSafe Whether to use url safe. + * + * @return {string} The Base64url string. + * + * @static + * + * @example + * + * const base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify(wordArray, urlSafe = true) { + // Shortcuts + const { words, sigBytes } = wordArray; + const map = urlSafe ? this._safeMap : this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + const base64Chars = []; + for (let i = 0; i < sigBytes; i += 3) { + const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + const triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + const paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64url string to a word array. + * + * @param {string} base64Str The Base64url string. + * + * @param {boolean} urlSafe Whether to use url safe. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse(base64Str, urlSafe = true) { + // Shortcuts + let base64StrLength = base64Str.length; + const map = urlSafe ? this._safeMap : this._map; + let reverseMap = this._reverseMap; + + if (!reverseMap) { + this._reverseMap = []; + reverseMap = this._reverseMap; + for (let j = 0; j < map.length; j += 1) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + const paddingChar = map.charAt(64); + if (paddingChar) { + const paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + + _safeMap: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/enc-utf16.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/enc-utf16.d.ts new file mode 100644 index 0000000..dc32723 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/enc-utf16.d.ts @@ -0,0 +1,10 @@ +export const Utf16: Encoder; +/** + * UTF-16 BE encoding strategy. + */ +export const Utf16BE: Encoder; +/** + * UTF-16 LE encoding strategy. + */ +export const Utf16LE: Encoder; +import { Encoder } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/enc-utf16.js b/uni_modules/x-crypto-s/utssdk/web/lib/enc-utf16.js new file mode 100644 index 0000000..7fe0da4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/enc-utf16.js @@ -0,0 +1,122 @@ +import { + WordArray, +} from './core.js'; + +const swapEndian = word => ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + +/** + * UTF-16 BE encoding strategy. + */ +export const Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * const utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const utf16Chars = []; + for (let i = 0; i < sigBytes; i += 2) { + const codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse(utf16Str) { + // Shortcut + const utf16StrLength = utf16Str.length; + + // Convert + const words = []; + for (let i = 0; i < utf16StrLength; i += 1) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + }, +}; +export const Utf16 = Utf16BE; + +/** + * UTF-16 LE encoding strategy. + */ +export const Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * const utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify(wordArray) { + // Shortcuts + const { words, sigBytes } = wordArray; + + // Convert + const utf16Chars = []; + for (let i = 0; i < sigBytes; i += 2) { + const codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * const wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse(utf16Str) { + // Shortcut + const utf16StrLength = utf16Str.length; + + // Convert + const words = []; + for (let i = 0; i < utf16StrLength; i += 1) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/evpkdf.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/evpkdf.d.ts new file mode 100644 index 0000000..f653274 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/evpkdf.d.ts @@ -0,0 +1,31 @@ +/** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ +export class EvpKDFAlgo extends Base { + static create(cfg?: KDFCfg): EvpKDFAlgo; + constructor(cfg?: KDFCfg); + compute(password: WordArray | string, salt: WordArray | string): WordArray; +} +/** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const EvpKDF: KDFFn; +import { Base } from './core.js'; +import { WordArray } from './core.js'; +import { KDFCfg } from './core.js'; +import { KDFFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/evpkdf.js b/uni_modules/x-crypto-s/utssdk/web/lib/evpkdf.js new file mode 100644 index 0000000..be7bb6d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/evpkdf.js @@ -0,0 +1,111 @@ +import { + Base, + WordArray, +} from './core.js'; +import { MD5Algo } from './md5.js'; + +/** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ +export class EvpKDFAlgo extends Base { + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * const kdf = CryptoJS.algo.EvpKDF.create(); + * const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + constructor(cfg) { + super(); + + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + this.cfg = Object.assign( + new Base(), + { + keySize: 128 / 32, + hasher: MD5Algo, + iterations: 1, + }, + cfg, + ); + } + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * const key = kdf.compute(password, salt); + */ + compute(password, salt) { + let block; + + // Shortcut + const { cfg } = this; + + // Init hasher + const hasher = cfg.hasher.create(); + + // Initial values + const derivedKey = WordArray.create(); + + // Shortcuts + const derivedKeyWords = derivedKey.words; + const { keySize, iterations } = cfg; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (let i = 1; i < iterations; i += 1) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } +} + +/** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const EvpKDF = (password, salt, cfg) => EvpKDFAlgo.create(cfg).compute(password, salt); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/format-hex.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/format-hex.d.ts new file mode 100644 index 0000000..f950a51 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/format-hex.d.ts @@ -0,0 +1,2 @@ +export const HexFormatter: Format; +import { Format } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/format-hex.js b/uni_modules/x-crypto-s/utssdk/web/lib/format-hex.js new file mode 100644 index 0000000..9c44463 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/format-hex.js @@ -0,0 +1,43 @@ +import { + CipherParams, +} from './cipher-core.js'; +import { + Hex, +} from './core.js'; + +export const HexFormatter = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify(cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse(input) { + const ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext }); + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/hmac.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/hmac.d.ts new file mode 100644 index 0000000..0238847 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/hmac.d.ts @@ -0,0 +1 @@ +export { HMAC } from "./core.js"; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/hmac.js b/uni_modules/x-crypto-s/utssdk/web/lib/hmac.js new file mode 100644 index 0000000..0beb0a4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/hmac.js @@ -0,0 +1,3 @@ +export { + HMAC, +} from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/index.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/index.d.ts new file mode 100644 index 0000000..29ef9c1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/index.d.ts @@ -0,0 +1,181 @@ +declare namespace _default { + export namespace lib { + export { Base }; + export { WordArray }; + export { BufferedBlockAlgorithm }; + export { Hasher }; + export { Cipher }; + export { StreamCipher }; + export { BlockCipherMode }; + export { BlockCipher }; + export { CipherParams }; + export { SerializableCipher }; + export { PasswordBasedCipher }; + } + export namespace x64 { + export { X64Word as Word }; + export { X64WordArray as WordArray }; + } + export namespace enc { + export { Hex }; + export { Latin1 }; + export { Utf8 }; + export { Utf16 }; + export { Utf16BE }; + export { Utf16LE }; + export { Base64 }; + export { Base64url }; + } + export namespace algo { + export { HMAC }; + export { MD5Algo as MD5 }; + export { SHA1Algo as SHA1 }; + export { SHA224Algo as SHA224 }; + export { SHA256Algo as SHA256 }; + export { SHA384Algo as SHA384 }; + export { SHA512Algo as SHA512 }; + export { SHA3Algo as SHA3 }; + export { RIPEMD160Algo as RIPEMD160 }; + export { PBKDF2Algo as PBKDF2 }; + export { EvpKDFAlgo as EvpKDF }; + export { AESAlgo as AES }; + export { DESAlgo as DES }; + export { TripleDESAlgo as TripleDES }; + export { RabbitAlgo as Rabbit }; + export { RabbitLegacyAlgo as RabbitLegacy }; + export { RC4Algo as RC4 }; + export { RC4DropAlgo as RC4Drop }; + export { BlowfishAlgo as Blowfish }; + } + export namespace mode { + export { CBC }; + export { CFB }; + export { CTR }; + export { CTRGladman }; + export { ECB }; + export { OFB }; + } + export namespace pad { + export { Pkcs7 }; + export { AnsiX923 }; + export { Iso10126 }; + export { Iso97971 }; + export { NoPadding }; + export { ZeroPadding }; + } + export namespace format { + export { OpenSSLFormatter as OpenSSL }; + export { HexFormatter as Hex }; + } + export namespace kdf { + export { OpenSSLKdf as OpenSSL }; + } + export { MD5 }; + export { HmacMD5 }; + export { SHA1 }; + export { HmacSHA1 }; + export { SHA224 }; + export { HmacSHA224 }; + export { SHA256 }; + export { HmacSHA256 }; + export { SHA384 }; + export { HmacSHA384 }; + export { SHA512 }; + export { HmacSHA512 }; + export { SHA3 }; + export { HmacSHA3 }; + export { RIPEMD160 }; + export { HmacRIPEMD160 }; + export { PBKDF2 }; + export { EvpKDF }; + export { AES }; + export { DES }; + export { TripleDES }; + export { Rabbit }; + export { RabbitLegacy }; + export { RC4 }; + export { RC4Drop }; + export { Blowfish }; +} +export default _default; +import { Base } from './core.js'; +import { WordArray } from './core.js'; +import { BufferedBlockAlgorithm } from './core.js'; +import { Hasher } from './core.js'; +import { Cipher } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; +import { BlockCipherMode } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; +import { CipherParams } from './cipher-core.js'; +import { SerializableCipher } from './cipher-core.js'; +import { PasswordBasedCipher } from './cipher-core.js'; +import { X64Word } from './x64-core.js'; +import { X64WordArray } from './x64-core.js'; +import { Hex } from './core.js'; +import { Latin1 } from './core.js'; +import { Utf8 } from './core.js'; +import { Utf16 } from './enc-utf16.js'; +import { Utf16BE } from './enc-utf16.js'; +import { Utf16LE } from './enc-utf16.js'; +import { Base64 } from './enc-base64.js'; +import { Base64url } from './enc-base64url.js'; +import { HMAC } from './hmac.js'; +import { MD5Algo } from './md5.js'; +import { SHA1Algo } from './sha1.js'; +import { SHA224Algo } from './sha224.js'; +import { SHA256Algo } from './sha256.js'; +import { SHA384Algo } from './sha384.js'; +import { SHA512Algo } from './sha512.js'; +import { SHA3Algo } from './sha3.js'; +import { RIPEMD160Algo } from './ripemd160.js'; +import { PBKDF2Algo } from './pbkdf2.js'; +import { EvpKDFAlgo } from './evpkdf.js'; +import { AESAlgo } from './aes.js'; +import { DESAlgo } from './tripledes.js'; +import { TripleDESAlgo } from './tripledes.js'; +import { RabbitAlgo } from './rabbit.js'; +import { RabbitLegacyAlgo } from './rabbit-legacy.js'; +import { RC4Algo } from './rc4.js'; +import { RC4DropAlgo } from './rc4.js'; +import { BlowfishAlgo } from './blowfish.js'; +import { CBC } from './cipher-core.js'; +import { CFB } from './mode-cfb.js'; +import { CTR } from './mode-ctr.js'; +import { CTRGladman } from './mode-ctr-gladman.js'; +import { ECB } from './mode-ecb.js'; +import { OFB } from './mode-ofb.js'; +import { Pkcs7 } from './cipher-core.js'; +import { AnsiX923 } from './pad-ansix923.js'; +import { Iso10126 } from './pad-iso10126.js'; +import { Iso97971 } from './pad-iso97971.js'; +import { NoPadding } from './pad-nopadding.js'; +import { ZeroPadding } from './pad-zeropadding.js'; +import { OpenSSLFormatter } from './cipher-core.js'; +import { HexFormatter } from './format-hex.js'; +import { OpenSSLKdf } from './cipher-core.js'; +import { MD5 } from './md5.js'; +import { HmacMD5 } from './md5.js'; +import { SHA1 } from './sha1.js'; +import { HmacSHA1 } from './sha1.js'; +import { SHA224 } from './sha224.js'; +import { HmacSHA224 } from './sha224.js'; +import { SHA256 } from './sha256.js'; +import { HmacSHA256 } from './sha256.js'; +import { SHA384 } from './sha384.js'; +import { HmacSHA384 } from './sha384.js'; +import { SHA512 } from './sha512.js'; +import { HmacSHA512 } from './sha512.js'; +import { SHA3 } from './sha3.js'; +import { HmacSHA3 } from './sha3.js'; +import { RIPEMD160 } from './ripemd160.js'; +import { HmacRIPEMD160 } from './ripemd160.js'; +import { PBKDF2 } from './pbkdf2.js'; +import { EvpKDF } from './evpkdf.js'; +import { AES } from './aes.js'; +import { DES } from './tripledes.js'; +import { TripleDES } from './tripledes.js'; +import { Rabbit } from './rabbit.js'; +import { RabbitLegacy } from './rabbit-legacy.js'; +import { RC4 } from './rc4.js'; +import { RC4Drop } from './rc4.js'; +import { Blowfish } from './blowfish.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/index.js b/uni_modules/x-crypto-s/utssdk/web/lib/index.js new file mode 100644 index 0000000..ce5f2a1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/index.js @@ -0,0 +1,180 @@ +import { + Base, + WordArray, + Hex, + Latin1, + Utf8, + BufferedBlockAlgorithm, + Hasher, +} from './core.js'; +import { + X64Word, + X64WordArray, +} from './x64-core.js'; +import { + Cipher, + StreamCipher, + BlockCipherMode, + CBC, + Pkcs7, + BlockCipher, + CipherParams, + OpenSSLFormatter, + SerializableCipher, + OpenSSLKdf, + PasswordBasedCipher, +} from './cipher-core.js'; + +import { Utf16, Utf16BE, Utf16LE } from './enc-utf16.js'; +import { Base64 } from './enc-base64.js'; +import { Base64url } from './enc-base64url.js'; +import { HMAC } from './hmac.js'; +import { MD5Algo, MD5, HmacMD5 } from './md5.js'; +import { SHA1Algo, SHA1, HmacSHA1 } from './sha1.js'; +import { SHA224Algo, SHA224, HmacSHA224 } from './sha224.js'; +import { SHA256Algo, SHA256, HmacSHA256 } from './sha256.js'; +import { SHA384Algo, SHA384, HmacSHA384 } from './sha384.js'; +import { SHA512Algo, SHA512, HmacSHA512 } from './sha512.js'; +import { SHA3Algo, SHA3, HmacSHA3 } from './sha3.js'; +import { RIPEMD160Algo, RIPEMD160, HmacRIPEMD160 } from './ripemd160.js'; +import { PBKDF2Algo, PBKDF2 } from './pbkdf2.js'; +import { EvpKDFAlgo, EvpKDF } from './evpkdf.js'; +import { AESAlgo, AES } from './aes.js'; +import { + DESAlgo, + DES, + TripleDESAlgo, + TripleDES, +} from './tripledes.js'; +import { RabbitAlgo, Rabbit } from './rabbit.js'; +import { RabbitLegacyAlgo, RabbitLegacy } from './rabbit-legacy.js'; +import { + RC4Algo, + RC4, + RC4DropAlgo, + RC4Drop, +} from './rc4.js'; +import { BlowfishAlgo, Blowfish } from './blowfish.js'; +import { CFB } from './mode-cfb.js'; +import { CTR } from './mode-ctr.js'; +import { CTRGladman } from './mode-ctr-gladman.js'; +import { ECB } from './mode-ecb.js'; +import { OFB } from './mode-ofb.js'; +import { AnsiX923 } from './pad-ansix923.js'; +import { Iso10126 } from './pad-iso10126.js'; +import { Iso97971 } from './pad-iso97971.js'; +import { NoPadding } from './pad-nopadding.js'; +import { ZeroPadding } from './pad-zeropadding.js'; +import { HexFormatter } from './format-hex.js'; + +export default { + lib: { + Base, + WordArray, + BufferedBlockAlgorithm, + Hasher, + Cipher, + StreamCipher, + BlockCipherMode, + BlockCipher, + CipherParams, + SerializableCipher, + PasswordBasedCipher, + }, + + x64: { + Word: X64Word, + WordArray: X64WordArray, + }, + + enc: { + Hex, + Latin1, + Utf8, + Utf16, + Utf16BE, + Utf16LE, + Base64, + Base64url, + }, + + algo: { + HMAC, + MD5: MD5Algo, + SHA1: SHA1Algo, + SHA224: SHA224Algo, + SHA256: SHA256Algo, + SHA384: SHA384Algo, + SHA512: SHA512Algo, + SHA3: SHA3Algo, + RIPEMD160: RIPEMD160Algo, + + PBKDF2: PBKDF2Algo, + EvpKDF: EvpKDFAlgo, + + AES: AESAlgo, + DES: DESAlgo, + TripleDES: TripleDESAlgo, + Rabbit: RabbitAlgo, + RabbitLegacy: RabbitLegacyAlgo, + RC4: RC4Algo, + RC4Drop: RC4DropAlgo, + Blowfish: BlowfishAlgo, + }, + + mode: { + CBC, + CFB, + CTR, + CTRGladman, + ECB, + OFB, + }, + + pad: { + Pkcs7, + AnsiX923, + Iso10126, + Iso97971, + NoPadding, + ZeroPadding, + }, + + format: { + OpenSSL: OpenSSLFormatter, + Hex: HexFormatter, + }, + + kdf: { + OpenSSL: OpenSSLKdf, + }, + + MD5, + HmacMD5, + SHA1, + HmacSHA1, + SHA224, + HmacSHA224, + SHA256, + HmacSHA256, + SHA384, + HmacSHA384, + SHA512, + HmacSHA512, + SHA3, + HmacSHA3, + RIPEMD160, + HmacRIPEMD160, + + PBKDF2, + EvpKDF, + + AES, + DES, + TripleDES, + Rabbit, + RabbitLegacy, + RC4, + RC4Drop, + Blowfish, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/md5.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/md5.d.ts new file mode 100644 index 0000000..2c8f211 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/md5.d.ts @@ -0,0 +1,37 @@ +/** + * MD5 hash algorithm. + */ +export class MD5Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ +export const MD5: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ +export const HmacMD5: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/md5.js b/uni_modules/x-crypto-s/utssdk/web/lib/md5.js new file mode 100644 index 0000000..927900e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/md5.js @@ -0,0 +1,247 @@ +import { + WordArray, + Hasher, +} from './core.js'; + +// Constants table +const T = []; + +// Compute constants +for (let i = 0; i < 64; i += 1) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; +} + +const FF = (a, b, c, d, x, s, t) => { + const n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const GG = (a, b, c, d, x, s, t) => { + const n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const HH = (a, b, c, d, x, s, t) => { + const n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +const II = (a, b, c, d, x, s, t) => { + const n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; +}; + +/** + * MD5 hash algorithm. + */ +export class MD5Algo extends Hasher { + _doReset() { + this._hash = new WordArray([ + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + ]); + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Swap endian + for (let i = 0; i < 16; i += 1) { + // Shortcuts + const offset_i = offset + i; + const M_offset_i = M[offset_i]; + + _M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) + | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + const H = this._hash.words; + + const M_offset_0 = _M[offset + 0]; + const M_offset_1 = _M[offset + 1]; + const M_offset_2 = _M[offset + 2]; + const M_offset_3 = _M[offset + 3]; + const M_offset_4 = _M[offset + 4]; + const M_offset_5 = _M[offset + 5]; + const M_offset_6 = _M[offset + 6]; + const M_offset_7 = _M[offset + 7]; + const M_offset_8 = _M[offset + 8]; + const M_offset_9 = _M[offset + 9]; + const M_offset_10 = _M[offset + 10]; + const M_offset_11 = _M[offset + 11]; + const M_offset_12 = _M[offset + 12]; + const M_offset_13 = _M[offset + 13]; + const M_offset_14 = _M[offset + 14]; + const M_offset_15 = _M[offset + 15]; + + // Working varialbes + let a = H[0]; + let b = H[1]; + let c = H[2]; + let d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + } + /* eslint-ensable no-param-reassign */ + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + + const nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + const nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) + | (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) + | (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const hash = this._hash; + const H = hash.words; + + // Swap endian + for (let i = 0; i < 4; i += 1) { + // Shortcut + const H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) + | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ +export const MD5 = Hasher._createHelper(MD5Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ +export const HmacMD5 = Hasher._createHmacHelper(MD5Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-cfb.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/mode-cfb.d.ts new file mode 100644 index 0000000..f33e10f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-cfb.d.ts @@ -0,0 +1,6 @@ +/** + * Cipher Feedback block mode. + */ +export class CFB extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-cfb.js b/uni_modules/x-crypto-s/utssdk/web/lib/mode-cfb.js new file mode 100644 index 0000000..27444e5 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-cfb.js @@ -0,0 +1,60 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + const _words = words; + let keystream; + + // Shortcut + const iv = this._iv; + + // Generate keystream + if (iv) { + keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } +} + +/** + * Cipher Feedback block mode. + */ +export class CFB extends BlockCipherMode { +} +CFB.Encryptor = class extends CFB { + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } +}; +CFB.Decryptor = class extends CFB { + processBlock(words, offset) { + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + + // Remember this block to use with next block + const thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr-gladman.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr-gladman.d.ts new file mode 100644 index 0000000..d313d08 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr-gladman.d.ts @@ -0,0 +1,8 @@ +/** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ +export class CTRGladman extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr-gladman.js b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr-gladman.js new file mode 100644 index 0000000..4481084 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr-gladman.js @@ -0,0 +1,87 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +const incWord = (word) => { + let _word = word; + + if (((word >> 24) & 0xff) === 0xff) { // overflow + let b1 = (word >> 16) & 0xff; + let b2 = (word >> 8) & 0xff; + let b3 = word & 0xff; + + if (b1 === 0xff) { // overflow b1 + b1 = 0; + if (b2 === 0xff) { + b2 = 0; + if (b3 === 0xff) { + b3 = 0; + } else { + b3 += 1; + } + } else { + b2 += 1; + } + } else { + b1 += 1; + } + + _word = 0; + _word += (b1 << 16); + _word += (b2 << 8); + _word += b3; + } else { + _word += (0x01 << 24); + } + return _word; +}; + +const incCounter = (counter) => { + const _counter = counter; + _counter[0] = incWord(_counter[0]); + + if (_counter[0] === 0) { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + _counter[1] = incWord(_counter[1]); + } + return _counter; +}; + +/** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ +export class CTRGladman extends BlockCipherMode { +} +CTRGladman.Encryptor = class extends CTRGladman { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let counter = this._counter; + + // Generate keystream + if (iv) { + this._counter = iv.slice(0); + counter = this._counter; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + const keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +CTRGladman.Decryptor = CTRGladman.Encryptor; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr.d.ts new file mode 100644 index 0000000..83c8c2f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr.d.ts @@ -0,0 +1,6 @@ +/** + * Counter block mode. + */ +export class CTR extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr.js b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr.js new file mode 100644 index 0000000..dfce6cf --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ctr.js @@ -0,0 +1,40 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +/** + * Counter block mode. + */ +export class CTR extends BlockCipherMode { +} +CTR.Encryptor = class extends CTR { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let counter = this._counter; + + // Generate keystream + if (iv) { + this._counter = iv.slice(0); + counter = this._counter; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + const keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0; + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +CTR.Decryptor = CTR.Encryptor; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ecb.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ecb.d.ts new file mode 100644 index 0000000..e0439bc --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ecb.d.ts @@ -0,0 +1,6 @@ +/** + * Electronic Codebook block mode. + */ +export class ECB extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ecb.js b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ecb.js new file mode 100644 index 0000000..7ad54a6 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ecb.js @@ -0,0 +1,19 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +/** + * Electronic Codebook block mode. + */ +export class ECB extends BlockCipherMode { +} +ECB.Encryptor = class extends ECB { + processBlock(words, offset) { + this._cipher.encryptBlock(words, offset); + } +}; +ECB.Decryptor = class extends ECB { + processBlock(words, offset) { + this._cipher.decryptBlock(words, offset); + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ofb.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ofb.d.ts new file mode 100644 index 0000000..ec66be0 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ofb.d.ts @@ -0,0 +1,6 @@ +/** + * Output Feedback block mode. + */ +export class OFB extends BlockCipherMode { +} +import { BlockCipherMode } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/mode-ofb.js b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ofb.js new file mode 100644 index 0000000..5c8cfe1 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/mode-ofb.js @@ -0,0 +1,36 @@ +import { + BlockCipherMode, +} from './cipher-core.js'; + +/** + * Output Feedback block mode. + */ +export class OFB extends BlockCipherMode { +} +OFB.Encryptor = class extends OFB { + processBlock(words, offset) { + const _words = words; + + // Shortcuts + const cipher = this._cipher; + const { blockSize } = cipher; + const iv = this._iv; + let keystream = this._keystream; + + // Generate keystream + if (iv) { + this._keystream = iv.slice(0); + keystream = this._keystream; + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (let i = 0; i < blockSize; i += 1) { + _words[offset + i] ^= keystream[i]; + } + } +}; +OFB.Decryptor = OFB.Encryptor; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-ansix923.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/pad-ansix923.d.ts new file mode 100644 index 0000000..863ed98 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-ansix923.d.ts @@ -0,0 +1,5 @@ +/** + * ANSI X.923 padding strategy. + */ +export const AnsiX923: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-ansix923.js b/uni_modules/x-crypto-s/utssdk/web/lib/pad-ansix923.js new file mode 100644 index 0000000..fab067b --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-ansix923.js @@ -0,0 +1,33 @@ +/** + * ANSI X.923 padding strategy. + */ +export const AnsiX923 = { + pad(data, blockSize) { + const _data = data; + + // Shortcuts + const dataSigBytes = _data.sigBytes; + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (dataSigBytes % blockSizeBytes); + + // Compute last byte position + const lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + _data.clamp(); + _data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + _data.sigBytes += nPaddingBytes; + }, + + unpad(data) { + const _data = data; + + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso10126.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso10126.d.ts new file mode 100644 index 0000000..098068a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso10126.d.ts @@ -0,0 +1,5 @@ +/** + * ISO 10126 padding strategy. + */ +export const Iso10126: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso10126.js b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso10126.js new file mode 100644 index 0000000..26e3449 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso10126.js @@ -0,0 +1,30 @@ +import { + WordArray, +} from './core.js'; + +/** + * ISO 10126 padding strategy. + */ +export const Iso10126 = { + pad(data, blockSize) { + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Count padding bytes + const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); + + // Pad + data + .concat(WordArray.random(nPaddingBytes - 1)) + .concat(WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad(data) { + const _data = data; + // Get number of padding bytes from last byte + const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + _data.sigBytes -= nPaddingBytes; + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso97971.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso97971.d.ts new file mode 100644 index 0000000..101a14c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso97971.d.ts @@ -0,0 +1,5 @@ +/** + * ISO/IEC 9797-1 Padding Method 2. + */ +export const Iso97971: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso97971.js b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso97971.js new file mode 100644 index 0000000..73eea6e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-iso97971.js @@ -0,0 +1,29 @@ +import { + WordArray, +} from './core.js'; +import { + ZeroPadding, +} from './pad-zeropadding.js'; + +/** + * ISO/IEC 9797-1 Padding Method 2. + */ +export const Iso97971 = { + pad(data, blockSize) { + // Add 0x80 byte + data.concat(WordArray.create([0x80000000], 1)); + + // Zero pad the rest + ZeroPadding.pad(data, blockSize); + }, + + unpad(data) { + const _data = data; + + // Remove zero padding + ZeroPadding.unpad(_data); + + // Remove one more byte -- the 0x80 byte + _data.sigBytes -= 1; + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-nopadding.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/pad-nopadding.d.ts new file mode 100644 index 0000000..f38a01d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-nopadding.d.ts @@ -0,0 +1,5 @@ +/** + * A noop padding strategy. + */ +export const NoPadding: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-nopadding.js b/uni_modules/x-crypto-s/utssdk/web/lib/pad-nopadding.js new file mode 100644 index 0000000..b0fbf4c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-nopadding.js @@ -0,0 +1,10 @@ +/** + * A noop padding strategy. + */ +export const NoPadding = { + pad() { + }, + + unpad() { + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-zeropadding.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/pad-zeropadding.d.ts new file mode 100644 index 0000000..2abb331 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-zeropadding.d.ts @@ -0,0 +1,5 @@ +/** + * Zero padding strategy. + */ +export const ZeroPadding: Padding; +import { Padding } from './cipher-core'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pad-zeropadding.js b/uni_modules/x-crypto-s/utssdk/web/lib/pad-zeropadding.js new file mode 100644 index 0000000..00db18c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pad-zeropadding.js @@ -0,0 +1,30 @@ +/** + * Zero padding strategy. + */ +export const ZeroPadding = { + pad(data, blockSize) { + const _data = data; + + // Shortcut + const blockSizeBytes = blockSize * 4; + + // Pad + _data.clamp(); + _data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad(data) { + const _data = data; + + // Shortcut + const dataWords = _data.words; + + // Unpad + for (let i = _data.sigBytes - 1; i >= 0; i -= 1) { + if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + _data.sigBytes = i + 1; + break; + } + } + }, +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pbkdf2.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/pbkdf2.d.ts new file mode 100644 index 0000000..2906673 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pbkdf2.d.ts @@ -0,0 +1,30 @@ +/** + * Password-Based Key Derivation Function 2 algorithm. + */ +export class PBKDF2Algo extends Base { + static create(cfg?: KDFCfg): PBKDF2Algo; + constructor(cfg?: KDFCfg); + compute(password: WordArray | string, salt: WordArray | string): WordArray; +} +/** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const PBKDF2: KDFFn; +import { Base } from './core.js'; +import { WordArray } from './core.js'; +import { KDFCfg } from './core.js'; +import { KDFFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/pbkdf2.js b/uni_modules/x-crypto-s/utssdk/web/lib/pbkdf2.js new file mode 100644 index 0000000..6b9dd51 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/pbkdf2.js @@ -0,0 +1,125 @@ +import { + Base, + WordArray, +} from './core.js'; +import { SHA256Algo } from './sha256.js'; +import { HMAC } from './hmac.js'; + +/** + * Password-Based Key Derivation Function 2 algorithm. + */ +export class PBKDF2Algo extends Base { + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * const kdf = CryptoJS.algo.PBKDF2.create(); + * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + constructor(cfg) { + super(); + + /** + * Configuration options. + * + * The default `hasher` and `interations` is different from CryptoJs to enhance security: + * https://github.com/entronad/crypto-es/security/advisories/GHSA-mpj8-q39x-wq5h + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA256 + * @property {number} iterations The number of iterations to perform. Default: 250000 + */ + this.cfg = Object.assign( + new Base(), + { + keySize: 128 / 32, + hasher: SHA256Algo, + iterations: 250000, + }, + cfg, + ); + } + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * const key = kdf.compute(password, salt); + */ + compute(password, salt) { + // Shortcut + const { cfg } = this; + + // Init HMAC + const hmac = HMAC.create(cfg.hasher, password); + + // Initial values + const derivedKey = WordArray.create(); + const blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + const derivedKeyWords = derivedKey.words; + const blockIndexWords = blockIndex.words; + const { keySize, iterations } = cfg; + + // Generate key + while (derivedKeyWords.length < keySize) { + const block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + const blockWords = block.words; + const blockWordsLength = blockWords.length; + + // Iterations + let intermediate = block; + for (let i = 1; i < iterations; i += 1) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + const intermediateWords = intermediate.words; + + // XOR intermediate with block + for (let j = 0; j < blockWordsLength; j += 1) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0] += 1; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } +} + +/** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ +export const PBKDF2 = (password, salt, cfg) => PBKDF2Algo.create(cfg).compute(password, salt); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/rabbit-legacy.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit-legacy.d.ts new file mode 100644 index 0000000..baa73e0 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit-legacy.d.ts @@ -0,0 +1,20 @@ +/** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ +export class RabbitLegacyAlgo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ +export const RabbitLegacy: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/rabbit-legacy.js b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit-legacy.js new file mode 100644 index 0000000..e9fc26a --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit-legacy.js @@ -0,0 +1,175 @@ +import { + StreamCipher, +} from './cipher-core.js'; + +// Reusable objects +const S = []; +const C_ = []; +const G = []; + +function nextState() { + // Shortcuts + const X = this._X; + const C = this._C; + + // Save old counter values + for (let i = 0; i < 8; i += 1) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (let i = 0; i < 8; i += 1) { + const gx = X[i] + C[i]; + + // Construct high and low argument for squaring + const ga = gx & 0xffff; + const gb = gx >>> 16; + + // Calculate high and low result of squaring + const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; +} + +/** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ +export class RabbitLegacyAlgo extends StreamCipher { + constructor(...args) { + super(...args); + + this.blockSize = 128 / 32; + this.ivSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const K = this._key.words; + const { iv } = this.cfg; + + // Generate initial state values + this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16), + ]; + const X = this._X; + + // Generate initial counter values + this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff), + ]; + const C = this._C; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + + // Modify the counters + for (let i = 0; i < 8; i += 1) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + const IV = iv.words; + const IV_0 = IV[0]; + const IV_1 = IV[1]; + + // Generate four subvectors + const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) + | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) + | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + const i1 = (i0 >>> 16) | (i2 & 0xffff0000); + const i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + } + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Shortcut + const X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (let i = 0; i < 4; i += 1) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) + | (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + _M[offset + i] ^= S[i]; + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ +export const RabbitLegacy = StreamCipher._createHelper(RabbitLegacyAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/rabbit.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit.d.ts new file mode 100644 index 0000000..da0bcf4 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit.d.ts @@ -0,0 +1,16 @@ +/** + * Rabbit stream cipher algorithm + */ +export class RabbitAlgo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ +export const Rabbit: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/rabbit.js b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit.js new file mode 100644 index 0000000..35f09bb --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/rabbit.js @@ -0,0 +1,177 @@ +import { + StreamCipher, +} from './cipher-core.js'; + +// Reusable objects +const S = []; +const C_ = []; +const G = []; + +function nextState() { + // Shortcuts + const X = this._X; + const C = this._C; + + // Save old counter values + for (let i = 0; i < 8; i += 1) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (let i = 0; i < 8; i += 1) { + const gx = X[i] + C[i]; + + // Construct high and low argument for squaring + const ga = gx & 0xffff; + const gb = gx >>> 16; + + // Calculate high and low result of squaring + const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; +} + +/** + * Rabbit stream cipher algorithm + */ +export class RabbitAlgo extends StreamCipher { + constructor(...args) { + super(...args); + + this.blockSize = 128 / 32; + this.ivSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const K = this._key.words; + const { iv } = this.cfg; + + // Swap endian + for (let i = 0; i < 4; i += 1) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) + | (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16), + ]; + const X = this._X; + + // Generate initial counter values + this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff), + ]; + const C = this._C; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + + // Modify the counters + for (let i = 0; i < 8; i += 1) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + const IV = iv.words; + const IV_0 = IV[0]; + const IV_1 = IV[1]; + + // Generate four subvectors + const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) + | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) + | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + const i1 = (i0 >>> 16) | (i2 & 0xffff0000); + const i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (let i = 0; i < 4; i += 1) { + nextState.call(this); + } + } + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Shortcut + const X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (let i = 0; i < 4; i += 1) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) + | (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + _M[offset + i] ^= S[i]; + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ +export const Rabbit = StreamCipher._createHelper(RabbitAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/rc4.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/rc4.d.ts new file mode 100644 index 0000000..bd26f1d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/rc4.d.ts @@ -0,0 +1,31 @@ + +/** + * RC4 stream cipher algorithm. + */ +export class RC4Algo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ +export const RC4: CipherObj; +/** + * Modified RC4 stream cipher algorithm. + */ +export class RC4DropAlgo extends StreamCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ +export const RC4Drop: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { StreamCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/rc4.js b/uni_modules/x-crypto-s/utssdk/web/lib/rc4.js new file mode 100644 index 0000000..3357e17 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/rc4.js @@ -0,0 +1,119 @@ +import { + StreamCipher, +} from './cipher-core.js'; + +function generateKeystreamWord() { + // Shortcuts + const S = this._S; + let i = this._i; + let j = this._j; + + // Generate keystream word + let keystreamWord = 0; + for (let n = 0; n < 4; n += 1) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + const t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; +} + +/** + * RC4 stream cipher algorithm. + */ +export class RC4Algo extends StreamCipher { + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + const keySigBytes = key.sigBytes; + + // Init sbox + this._S = []; + const S = this._S; + for (let i = 0; i < 256; i += 1) { + S[i] = i; + } + + // Key setup + for (let i = 0, j = 0; i < 256; i += 1) { + const keyByteIndex = i % keySigBytes; + const keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + const t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._j = 0; + this._i = this._j; + } + + _doProcessBlock(M, offset) { + const _M = M; + + _M[offset] ^= generateKeystreamWord.call(this); + } +} +RC4Algo.keySize = 256 / 32; +RC4Algo.ivSize = 0; + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ +export const RC4 = StreamCipher._createHelper(RC4Algo); + +/** + * Modified RC4 stream cipher algorithm. + */ +export class RC4DropAlgo extends RC4Algo { + constructor(...args) { + super(...args); + + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + Object.assign(this.cfg, { drop: 192 }); + } + + _doReset() { + super._doReset.call(this); + + // Drop + for (let i = this.cfg.drop; i > 0; i -= 1) { + generateKeystreamWord.call(this); + } + } +} + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ +export const RC4Drop = StreamCipher._createHelper(RC4DropAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/ripemd160.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/ripemd160.d.ts new file mode 100644 index 0000000..3b479b8 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/ripemd160.d.ts @@ -0,0 +1,37 @@ +/** + * RIPEMD160 hash algorithm. + */ +export class RIPEMD160Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ +export const RIPEMD160: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ +export const HmacRIPEMD160: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/ripemd160.js b/uni_modules/x-crypto-s/utssdk/web/lib/ripemd160.js new file mode 100644 index 0000000..c578def --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/ripemd160.js @@ -0,0 +1,242 @@ +/** @preserve +(c) 2012 by Cédric Mesnil. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import { + WordArray, + Hasher, +} from './core.js'; + +// Constants table +const _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); +const _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); +const _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]); +const _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]); + +const _hl = WordArray.create([0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); +const _hr = WordArray.create([0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + +const f1 = (x, y, z) => (x) ^ (y) ^ (z); + +const f2 = (x, y, z) => ((x) & (y)) | ((~x) & (z)); + +const f3 = (x, y, z) => ((x) | (~(y))) ^ (z); + +const f4 = (x, y, z) => ((x) & (z)) | ((y) & (~(z))); + +const f5 = (x, y, z) => (x) ^ ((y) | (~(z))); + +const rotl = (x, n) => (x << n) | (x >>> (32 - n)); + +/** + * RIPEMD160 hash algorithm. + */ +export class RIPEMD160Algo extends Hasher { + _doReset() { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + } + + _doProcessBlock(M, offset) { + const _M = M; + + // Swap endian + for (let i = 0; i < 16; i += 1) { + // Shortcuts + const offset_i = offset + i; + const M_offset_i = _M[offset_i]; + + // Swap + _M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) + | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + const H = this._hash.words; + const hl = _hl.words; + const hr = _hr.words; + const zl = _zl.words; + const zr = _zr.words; + const sl = _sl.words; + const sr = _sr.words; + + // Working variables + let al = H[0]; + let bl = H[1]; + let cl = H[2]; + let dl = H[3]; + let el = H[4]; + let ar = H[0]; + let br = H[1]; + let cr = H[2]; + let dr = H[3]; + let er = H[4]; + + // Computation + let t; + for (let i = 0; i < 80; i += 1) { + t = (al + _M[offset + zl[i]]) | 0; + if (i < 16) { + t += f1(bl, cl, dl) + hl[0]; + } else if (i < 32) { + t += f2(bl, cl, dl) + hl[1]; + } else if (i < 48) { + t += f3(bl, cl, dl) + hl[2]; + } else if (i < 64) { + t += f4(bl, cl, dl) + hl[3]; + } else { // if (i<80) { + t += f5(bl, cl, dl) + hl[4]; + } + t |= 0; + t = rotl(t, sl[i]); + t = (t + el) | 0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + _M[offset + zr[i]]) | 0; + if (i < 16) { + t += f5(br, cr, dr) + hr[0]; + } else if (i < 32) { + t += f4(br, cr, dr) + hr[1]; + } else if (i < 48) { + t += f3(br, cr, dr) + hr[2]; + } else if (i < 64) { + t += f2(br, cr, dr) + hr[3]; + } else { // if (i<80) { + t += f1(br, cr, dr) + hr[4]; + } + t |= 0; + t = rotl(t, sr[i]); + t = (t + er) | 0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr) | 0; + H[1] = (H[2] + dl + er) | 0; + H[2] = (H[3] + el + ar) | 0; + H[3] = (H[4] + al + br) | 0; + H[4] = (H[0] + bl + cr) | 0; + H[0] = t; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) + | (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const hash = this._hash; + const H = hash.words; + + // Swap endian + for (let i = 0; i < 5; i += 1) { + // Shortcut + const H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) + | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ +export const RIPEMD160 = Hasher._createHelper(RIPEMD160Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ +export const HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha1.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/sha1.d.ts new file mode 100644 index 0000000..8d02a31 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha1.d.ts @@ -0,0 +1,37 @@ +/** + * SHA1 hash algorithm. + */ +export class SHA1Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ +export const SHA1: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ +export const HmacSHA1: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha1.js b/uni_modules/x-crypto-s/utssdk/web/lib/sha1.js new file mode 100644 index 0000000..d831b8e --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha1.js @@ -0,0 +1,128 @@ +import { + WordArray, + Hasher, +} from './core.js'; + +// Reusable object +const W = []; + +/** + * SHA-1 hash algorithm. + */ +export class SHA1Algo extends Hasher { + _doReset() { + this._hash = new WordArray([ + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + 0xc3d2e1f0, + ]); + } + + _doProcessBlock(M, offset) { + // Shortcut + const H = this._hash.words; + + // Working variables + let a = H[0]; + let b = H[1]; + let c = H[2]; + let d = H[3]; + let e = H[4]; + + // Computation + for (let i = 0; i < 80; i += 1) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + const n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + let t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ +export const SHA1 = Hasher._createHelper(SHA1Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ +export const HmacSHA1 = Hasher._createHmacHelper(SHA1Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha224.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/sha224.d.ts new file mode 100644 index 0000000..c0f8724 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha224.d.ts @@ -0,0 +1,37 @@ +/** + * SHA224 hash algorithm. + */ +export class SHA224Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ +export const SHA224: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ +export const HmacSHA224: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha224.js b/uni_modules/x-crypto-s/utssdk/web/lib/sha224.js new file mode 100644 index 0000000..5a6cafc --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha224.js @@ -0,0 +1,60 @@ +import { WordArray } from './core.js'; +import { SHA256Algo } from './sha256.js'; + +/** + * SHA-224 hash algorithm. + */ +export class SHA224Algo extends SHA256Algo { + _doReset() { + this._hash = new WordArray([ + 0xc1059ed8, + 0x367cd507, + 0x3070dd17, + 0xf70e5939, + 0xffc00b31, + 0x68581511, + 0x64f98fa7, + 0xbefa4fa4, + ]); + } + + _doFinalize() { + const hash = super._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ +export const SHA224 = SHA256Algo._createHelper(SHA224Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ +export const HmacSHA224 = SHA256Algo._createHmacHelper(SHA224Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha256.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/sha256.d.ts new file mode 100644 index 0000000..782a702 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha256.d.ts @@ -0,0 +1,37 @@ +/** + * SHA256 hash algorithm. + */ +export class SHA256Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ +export const SHA256: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ +export const HmacSHA256: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha256.js b/uni_modules/x-crypto-s/utssdk/web/lib/sha256.js new file mode 100644 index 0000000..2a13c4c --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha256.js @@ -0,0 +1,171 @@ +import { + WordArray, + Hasher, +} from './core.js'; + +// Initialization and round constants tables +const H = []; +const K = []; + +// Compute constants +const isPrime = (n) => { + const sqrtN = Math.sqrt(n); + for (let factor = 2; factor <= sqrtN; factor += 1) { + if (!(n % factor)) { + return false; + } + } + + return true; +}; + +const getFractionalBits = n => ((n - (n | 0)) * 0x100000000) | 0; + +let n = 2; +let nPrime = 0; +while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(n ** (1 / 2)); + } + K[nPrime] = getFractionalBits(n ** (1 / 3)); + + nPrime += 1; + } + + n += 1; +} + +// Reusable object +const W = []; + +/** + * SHA-256 hash algorithm. + */ +export class SHA256Algo extends Hasher { + _doReset() { + this._hash = new WordArray(H.slice(0)); + } + + _doProcessBlock(M, offset) { + // Shortcut + const _H = this._hash.words; + + // Working variables + let a = _H[0]; + let b = _H[1]; + let c = _H[2]; + let d = _H[3]; + let e = _H[4]; + let f = _H[5]; + let g = _H[6]; + let h = _H[7]; + + // Computation + for (let i = 0; i < 64; i += 1) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + const gamma0x = W[i - 15]; + const gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) + ^ ((gamma0x << 14) | (gamma0x >>> 18)) + ^ (gamma0x >>> 3); + + const gamma1x = W[i - 2]; + const gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) + ^ ((gamma1x << 13) | (gamma1x >>> 19)) + ^ (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + const ch = (e & f) ^ (~e & g); + const maj = (a & b) ^ (a & c) ^ (b & c); + + const sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + const sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + const t1 = h + sigma1 + ch + K[i] + W[i]; + const t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + _H[0] = (_H[0] + a) | 0; + _H[1] = (_H[1] + b) | 0; + _H[2] = (_H[2] + c) | 0; + _H[3] = (_H[3] + d) | 0; + _H[4] = (_H[4] + e) | 0; + _H[5] = (_H[5] + f) | 0; + _H[6] = (_H[6] + g) | 0; + _H[7] = (_H[7] + h) | 0; + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ +export const SHA256 = Hasher._createHelper(SHA256Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ +export const HmacSHA256 = Hasher._createHmacHelper(SHA256Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha3.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/sha3.d.ts new file mode 100644 index 0000000..4ed9f60 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha3.d.ts @@ -0,0 +1,37 @@ +/** + * SHA3 hash algorithm. + */ +export class SHA3Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ +export const SHA3: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ +export const HmacSHA3: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha3.js b/uni_modules/x-crypto-s/utssdk/web/lib/sha3.js new file mode 100644 index 0000000..488446d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha3.js @@ -0,0 +1,295 @@ +import { + WordArray, + Hasher, +} from './core.js'; +import { X64Word } from './x64-core.js'; + +// Constants tables +const RHO_OFFSETS = []; +const PI_INDEXES = []; +const ROUND_CONSTANTS = []; + +// Compute Constants +// Compute rho offset constants +let _x = 1; +let _y = 0; +for (let t = 0; t < 24; t += 1) { + RHO_OFFSETS[_x + 5 * _y] = ((t + 1) * (t + 2) / 2) % 64; + + const newX = _y % 5; + const newY = (2 * _x + 3 * _y) % 5; + _x = newX; + _y = newY; +} + +// Compute pi index constants +for (let x = 0; x < 5; x += 1) { + for (let y = 0; y < 5; y += 1) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } +} + +// Compute round constants +let LFSR = 0x01; +for (let i = 0; i < 24; i += 1) { + let roundConstantMsw = 0; + let roundConstantLsw = 0; + + for (let j = 0; j < 7; j += 1) { + if (LFSR & 0x01) { + const bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); +} + +// Reusable objects for temporary values +const T = []; +for (let i = 0; i < 25; i += 1) { + T[i] = X64Word.create(); +} + +/** + * SHA-3 hash algorithm. + */ +export class SHA3Algo extends Hasher { + constructor(cfg) { + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + super(Object.assign( + { outputLength: 512 }, + cfg, + )); + } + + _doReset() { + this._state = []; + const state = this._state; + for (let i = 0; i < 25; i += 1) { + state[i] = new X64Word(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + } + + _doProcessBlock(M, offset) { + // Shortcuts + const state = this._state; + const nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (let i = 0; i < nBlockSizeLanes; i += 1) { + // Shortcuts + let M2i = M[offset + 2 * i]; + let M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) + | (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00); + M2i1 = (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) + | (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00); + + // Absorb message into state + const lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (let round = 0; round < 24; round += 1) { + // Theta + for (let x = 0; x < 5; x += 1) { + // Mix column lanes + let tMsw = 0; + let tLsw = 0; + for (let y = 0; y < 5; y += 1) { + const lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + const Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (let x = 0; x < 5; x += 1) { + // Shortcuts + const Tx4 = T[(x + 4) % 5]; + const Tx1 = T[(x + 1) % 5]; + const Tx1Msw = Tx1.high; + const Tx1Lsw = Tx1.low; + + // Mix surrounding columns + const tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + const tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (let y = 0; y < 5; y += 1) { + const lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (let laneIndex = 1; laneIndex < 25; laneIndex += 1) { + let tMsw; + let tLsw; + + // Shortcuts + const lane = state[laneIndex]; + const laneMsw = lane.high; + const laneLsw = lane.low; + const rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + const TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + const T0 = T[0]; + const state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (let x = 0; x < 5; x += 1) { + for (let y = 0; y < 5; y += 1) { + // Shortcuts + const laneIndex = x + 5 * y; + const lane = state[laneIndex]; + const TLane = T[laneIndex]; + const Tx1Lane = T[((x + 1) % 5) + 5 * y]; + const Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + const lane = state[0]; + const roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low; + } + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + const nBitsLeft = data.sigBytes * 8; + const blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - (nBitsLeft % 32)); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + const state = this._state; + const outputLengthBytes = this.cfg.outputLength / 8; + const outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + const hashWords = []; + for (let i = 0; i < outputLengthLanes; i += 1) { + // Shortcuts + const lane = state[i]; + let laneMsw = lane.high; + let laneLsw = lane.low; + + // Swap endian + laneMsw = (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) + | (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00); + laneLsw = (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) + | (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray(hashWords, outputLengthBytes); + } + + clone() { + const clone = super.clone.call(this); + + clone._state = this._state.slice(0); + const state = clone._state; + for (let i = 0; i < 25; i += 1) { + state[i] = state[i].clone(); + } + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ +export const SHA3 = Hasher._createHelper(SHA3Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ +export const HmacSHA3 = Hasher._createHmacHelper(SHA3Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha384.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/sha384.d.ts new file mode 100644 index 0000000..e386048 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha384.d.ts @@ -0,0 +1,37 @@ +/** + * SHA384 hash algorithm. + */ +export class SHA384Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ +export const SHA384: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ +export const HmacSHA384: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha384.js b/uni_modules/x-crypto-s/utssdk/web/lib/sha384.js new file mode 100644 index 0000000..9b96a0b --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha384.js @@ -0,0 +1,63 @@ +import { + X64Word, + X64WordArray, +} from './x64-core.js'; +import { SHA512Algo } from './sha512.js'; + +/** + * SHA-384 hash algorithm. + */ +export class SHA384Algo extends SHA512Algo { + _doReset() { + this._hash = new X64WordArray([ + new X64Word(0xcbbb9d5d, 0xc1059ed8), + new X64Word(0x629a292a, 0x367cd507), + new X64Word(0x9159015a, 0x3070dd17), + new X64Word(0x152fecd8, 0xf70e5939), + new X64Word(0x67332667, 0xffc00b31), + new X64Word(0x8eb44a87, 0x68581511), + new X64Word(0xdb0c2e0d, 0x64f98fa7), + new X64Word(0x47b5481d, 0xbefa4fa4), + ]); + } + + _doFinalize() { + const hash = super._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ +export const SHA384 = SHA512Algo._createHelper(SHA384Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ +export const HmacSHA384 = SHA512Algo._createHmacHelper(SHA384Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha512.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/sha512.d.ts new file mode 100644 index 0000000..d75cb39 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha512.d.ts @@ -0,0 +1,37 @@ +/** + * SHA512 hash algorithm. + */ +export class SHA512Algo extends Hasher {} +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ +export const SHA512: HashFn; +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ +export const HmacSHA512: HMACHashFn; +import { Hasher } from './core.js'; +import { HashFn } from './core.js'; +import { HMACHashFn } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/sha512.js b/uni_modules/x-crypto-s/utssdk/web/lib/sha512.js new file mode 100644 index 0000000..738804d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/sha512.js @@ -0,0 +1,369 @@ +import { Hasher } from './core.js'; +import { + X64Word, + X64WordArray, +} from './x64-core.js'; + +// Constants +const K = [ + new X64Word(0x428a2f98, 0xd728ae22), + new X64Word(0x71374491, 0x23ef65cd), + new X64Word(0xb5c0fbcf, 0xec4d3b2f), + new X64Word(0xe9b5dba5, 0x8189dbbc), + new X64Word(0x3956c25b, 0xf348b538), + new X64Word(0x59f111f1, 0xb605d019), + new X64Word(0x923f82a4, 0xaf194f9b), + new X64Word(0xab1c5ed5, 0xda6d8118), + new X64Word(0xd807aa98, 0xa3030242), + new X64Word(0x12835b01, 0x45706fbe), + new X64Word(0x243185be, 0x4ee4b28c), + new X64Word(0x550c7dc3, 0xd5ffb4e2), + new X64Word(0x72be5d74, 0xf27b896f), + new X64Word(0x80deb1fe, 0x3b1696b1), + new X64Word(0x9bdc06a7, 0x25c71235), + new X64Word(0xc19bf174, 0xcf692694), + new X64Word(0xe49b69c1, 0x9ef14ad2), + new X64Word(0xefbe4786, 0x384f25e3), + new X64Word(0x0fc19dc6, 0x8b8cd5b5), + new X64Word(0x240ca1cc, 0x77ac9c65), + new X64Word(0x2de92c6f, 0x592b0275), + new X64Word(0x4a7484aa, 0x6ea6e483), + new X64Word(0x5cb0a9dc, 0xbd41fbd4), + new X64Word(0x76f988da, 0x831153b5), + new X64Word(0x983e5152, 0xee66dfab), + new X64Word(0xa831c66d, 0x2db43210), + new X64Word(0xb00327c8, 0x98fb213f), + new X64Word(0xbf597fc7, 0xbeef0ee4), + new X64Word(0xc6e00bf3, 0x3da88fc2), + new X64Word(0xd5a79147, 0x930aa725), + new X64Word(0x06ca6351, 0xe003826f), + new X64Word(0x14292967, 0x0a0e6e70), + new X64Word(0x27b70a85, 0x46d22ffc), + new X64Word(0x2e1b2138, 0x5c26c926), + new X64Word(0x4d2c6dfc, 0x5ac42aed), + new X64Word(0x53380d13, 0x9d95b3df), + new X64Word(0x650a7354, 0x8baf63de), + new X64Word(0x766a0abb, 0x3c77b2a8), + new X64Word(0x81c2c92e, 0x47edaee6), + new X64Word(0x92722c85, 0x1482353b), + new X64Word(0xa2bfe8a1, 0x4cf10364), + new X64Word(0xa81a664b, 0xbc423001), + new X64Word(0xc24b8b70, 0xd0f89791), + new X64Word(0xc76c51a3, 0x0654be30), + new X64Word(0xd192e819, 0xd6ef5218), + new X64Word(0xd6990624, 0x5565a910), + new X64Word(0xf40e3585, 0x5771202a), + new X64Word(0x106aa070, 0x32bbd1b8), + new X64Word(0x19a4c116, 0xb8d2d0c8), + new X64Word(0x1e376c08, 0x5141ab53), + new X64Word(0x2748774c, 0xdf8eeb99), + new X64Word(0x34b0bcb5, 0xe19b48a8), + new X64Word(0x391c0cb3, 0xc5c95a63), + new X64Word(0x4ed8aa4a, 0xe3418acb), + new X64Word(0x5b9cca4f, 0x7763e373), + new X64Word(0x682e6ff3, 0xd6b2b8a3), + new X64Word(0x748f82ee, 0x5defb2fc), + new X64Word(0x78a5636f, 0x43172f60), + new X64Word(0x84c87814, 0xa1f0ab72), + new X64Word(0x8cc70208, 0x1a6439ec), + new X64Word(0x90befffa, 0x23631e28), + new X64Word(0xa4506ceb, 0xde82bde9), + new X64Word(0xbef9a3f7, 0xb2c67915), + new X64Word(0xc67178f2, 0xe372532b), + new X64Word(0xca273ece, 0xea26619c), + new X64Word(0xd186b8c7, 0x21c0c207), + new X64Word(0xeada7dd6, 0xcde0eb1e), + new X64Word(0xf57d4f7f, 0xee6ed178), + new X64Word(0x06f067aa, 0x72176fba), + new X64Word(0x0a637dc5, 0xa2c898a6), + new X64Word(0x113f9804, 0xbef90dae), + new X64Word(0x1b710b35, 0x131c471b), + new X64Word(0x28db77f5, 0x23047d84), + new X64Word(0x32caab7b, 0x40c72493), + new X64Word(0x3c9ebe0a, 0x15c9bebc), + new X64Word(0x431d67c4, 0x9c100d4c), + new X64Word(0x4cc5d4be, 0xcb3e42b6), + new X64Word(0x597f299c, 0xfc657e2a), + new X64Word(0x5fcb6fab, 0x3ad6faec), + new X64Word(0x6c44198c, 0x4a475817), +]; + +// Reusable objects +const W = []; +for (let i = 0; i < 80; i += 1) { + W[i] = new X64Word(); +} + +/** + * SHA-512 hash algorithm. + */ +export class SHA512Algo extends Hasher { + constructor() { + super(); + + this.blockSize = 1024 / 32; + } + + _doReset() { + this._hash = new X64WordArray([ + new X64Word(0x6a09e667, 0xf3bcc908), + new X64Word(0xbb67ae85, 0x84caa73b), + new X64Word(0x3c6ef372, 0xfe94f82b), + new X64Word(0xa54ff53a, 0x5f1d36f1), + new X64Word(0x510e527f, 0xade682d1), + new X64Word(0x9b05688c, 0x2b3e6c1f), + new X64Word(0x1f83d9ab, 0xfb41bd6b), + new X64Word(0x5be0cd19, 0x137e2179), + ]); + } + + _doProcessBlock(M, offset) { + // Shortcuts + const H = this._hash.words; + + const H0 = H[0]; + const H1 = H[1]; + const H2 = H[2]; + const H3 = H[3]; + const H4 = H[4]; + const H5 = H[5]; + const H6 = H[6]; + const H7 = H[7]; + + const H0h = H0.high; + let H0l = H0.low; + const H1h = H1.high; + let H1l = H1.low; + const H2h = H2.high; + let H2l = H2.low; + const H3h = H3.high; + let H3l = H3.low; + const H4h = H4.high; + let H4l = H4.low; + const H5h = H5.high; + let H5l = H5.low; + const H6h = H6.high; + let H6l = H6.low; + const H7h = H7.high; + let H7l = H7.low; + + // Working variables + let ah = H0h; + let al = H0l; + let bh = H1h; + let bl = H1l; + let ch = H2h; + let cl = H2l; + let dh = H3h; + let dl = H3l; + let eh = H4h; + let el = H4l; + let fh = H5h; + let fl = H5l; + let gh = H6h; + let gl = H6l; + let hh = H7h; + let hl = H7l; + + // Rounds + for (let i = 0; i < 80; i += 1) { + let Wil; + let Wih; + + // Shortcut + const Wi = W[i]; + + // Extend message + if (i < 16) { + Wi.high = M[offset + i * 2] | 0; + Wih = Wi.high; + Wi.low = M[offset + i * 2 + 1] | 0; + Wil = Wi.low; + } else { + // Gamma0 + const gamma0x = W[i - 15]; + const gamma0xh = gamma0x.high; + const gamma0xl = gamma0x.low; + const gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) + ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) + ^ (gamma0xh >>> 7); + const gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) + ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) + ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + const gamma1x = W[i - 2]; + const gamma1xh = gamma1x.high; + const gamma1xl = gamma1x.low; + const gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) + ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) + ^ (gamma1xh >>> 6); + const gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) + ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) + ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + const Wi7 = W[i - 7]; + const Wi7h = Wi7.high; + const Wi7l = Wi7.low; + + const Wi16 = W[i - 16]; + const Wi16h = Wi16.high; + const Wi16l = Wi16.low; + + Wil = gamma0l + Wi7l; + Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + Wil += gamma1l; + Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + Wil += Wi16l; + Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + const chh = (eh & fh) ^ (~eh & gh); + const chl = (el & fl) ^ (~el & gl); + const majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + const majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + const sigma0h = ((ah >>> 28) | (al << 4)) + ^ ((ah << 30) | (al >>> 2)) + ^ ((ah << 25) | (al >>> 7)); + const sigma0l = ((al >>> 28) | (ah << 4)) + ^ ((al << 30) | (ah >>> 2)) + ^ ((al << 25) | (ah >>> 7)); + const sigma1h = ((eh >>> 14) | (el << 18)) + ^ ((eh >>> 18) | (el << 14)) + ^ ((eh << 23) | (el >>> 9)); + const sigma1l = ((el >>> 14) | (eh << 18)) + ^ ((el >>> 18) | (eh << 14)) + ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + const Ki = K[i]; + const Kih = Ki.high; + const Kil = Ki.low; + + let t1l = hl + sigma1l; + let t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + t1l += chl; + t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + t1l += Kil; + t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + t1l += Wil; + t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + const t2l = sigma0l + majl; + const t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0.low = (H0l + al); + H0l = H0.low; + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1.low = (H1l + bl); + H1l = H1.low; + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2.low = (H2l + cl); + H2l = H2.low; + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3.low = (H3l + dl); + H3l = H3.low; + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4.low = (H4l + el); + H4l = H4.low; + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5.low = (H5l + fl); + H5l = H5.low; + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6.low = (H6l + gl); + H6l = H6.low; + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7.low = (H7l + hl); + H7l = H7.low; + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + } + + _doFinalize() { + // Shortcuts + const data = this._data; + const dataWords = data.words; + + const nBitsTotal = this._nDataBytes * 8; + const nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32)); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + const hash = this._hash.toX32(); + + // Return final computed hash + return hash; + } + + clone() { + const clone = super.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } +} + +/** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ +export const SHA512 = Hasher._createHelper(SHA512Algo); + +/** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ +export const HmacSHA512 = Hasher._createHmacHelper(SHA512Algo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/tripledes.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/tripledes.d.ts new file mode 100644 index 0000000..459f854 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/tripledes.d.ts @@ -0,0 +1,30 @@ +/** + * DES block cipher algorithm. + */ +export class DESAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ +export const DES: CipherObj; +/** + * Triple-DES block cipher algorithm. + */ +export class TripleDESAlgo extends BlockCipher { +} +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ +export const TripleDES: CipherObj; +import { CipherObj } from './cipher-core.js'; +import { BlockCipher } from './cipher-core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/tripledes.js b/uni_modules/x-crypto-s/utssdk/web/lib/tripledes.js new file mode 100644 index 0000000..6d1c4e6 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/tripledes.js @@ -0,0 +1,766 @@ +import { + WordArray, +} from './core.js'; +import { + BlockCipher, +} from './cipher-core.js'; + +// Permuted Choice 1 constants +const PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4, +]; + +// Permuted Choice 2 constants +const PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32, +]; + +// Cumulative bit shift constants +const BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + +// SBOXes and round permutation constants +const SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002, + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000, + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100, + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040, + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080, + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008, + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001, + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800, + }, +]; + +// Masks that select the SBOX input +const SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f, +]; + +// Swap bits across the left and right words +function exchangeLR(offset, mask) { + const t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; +} + +function exchangeRL(offset, mask) { + const t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; +} + +/** + * DES block cipher algorithm. + */ +export class DESAlgo extends BlockCipher { + constructor(xformMode, key, cfg) { + super(xformMode, key, cfg); + + // blickSize is an instance field and should set in constructor. + // Both DESAlgo and TripleDESAlgo. + this.blockSize = 64 / 32; + } + + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + + // Select 56 bits according to PC1 + const keyBits = []; + for (let i = 0; i < 56; i += 1) { + const keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - (keyBitPos % 32))) & 1; + } + + // Assemble 16 subkeys + this._subKeys = []; + const subKeys = this._subKeys; + for (let nSubKey = 0; nSubKey < 16; nSubKey += 1) { + // Create subkey + subKeys[nSubKey] = []; + const subKey = subKeys[nSubKey]; + + // Shortcut + const bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (let i = 0; i < 24; i += 1) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - (i % 6)); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] + |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] + << (31 - (i % 6)); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (let i = 1; i < 7; i += 1) { + subKey[i] >>>= ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + this._invSubKeys = []; + const invSubKeys = this._invSubKeys; + for (let i = 0; i < 16; i += 1) { + invSubKeys[i] = subKeys[15 - i]; + } + } + + encryptBlock(M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + } + + decryptBlock(M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + } + + _doCryptBlock(M, offset, subKeys) { + const _M = M; + + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (let round = 0; round < 16; round += 1) { + // Shortcuts + const subKey = subKeys[round]; + const lBlock = this._lBlock; + const rBlock = this._rBlock; + + // Feistel function + let f = 0; + for (let i = 0; i < 8; i += 1) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + const t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + _M[offset] = this._lBlock; + _M[offset + 1] = this._rBlock; + } +} +DESAlgo.keySize = 64 / 32; +DESAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ +export const DES = BlockCipher._createHelper(DESAlgo); + +/** + * Triple-DES block cipher algorithm. + */ +export class TripleDESAlgo extends BlockCipher { + _doReset() { + // Shortcuts + const key = this._key; + const keyWords = key.words; + // Make sure the key length is valid (64, 128 or >= 192 bit) + if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) { + throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.'); + } + + // Extend the key according to the keying options defined in 3DES standard + const key1 = keyWords.slice(0, 2); + const key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4); + const key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6); + + // Create DES instances + this._des1 = DESAlgo.createEncryptor(WordArray.create(key1)); + this._des2 = DESAlgo.createEncryptor(WordArray.create(key2)); + this._des3 = DESAlgo.createEncryptor(WordArray.create(key3)); + } + + encryptBlock(M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + } + + decryptBlock(M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + } +} +TripleDESAlgo.keySize = 192 / 32; +TripleDESAlgo.ivSize = 64 / 32; +// blickSize is an instance field and should set in constructor. + +/** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ +export const TripleDES = BlockCipher._createHelper(TripleDESAlgo); diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/x64-core.d.ts b/uni_modules/x-crypto-s/utssdk/web/lib/x64-core.d.ts new file mode 100644 index 0000000..09d0e48 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/x64-core.d.ts @@ -0,0 +1,73 @@ +/** + * A 64-bit word. + */ +export class X64Word extends Base { + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + static create(high: number, low: number): X64Word; + constructor(high: number, low: number); + high: number; + low: number; +} +/** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class X64WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + static create(words?: Array, sigBytes?: number): X64WordArray; + constructor(words?: Array, sigBytes?: number); + words: X64Word[]; + sigBytes: number; + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32(): WordArray; + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone(): X64WordArray; +} +import { Base } from './core.js'; +import { WordArray } from './core.js'; diff --git a/uni_modules/x-crypto-s/utssdk/web/lib/x64-core.js b/uni_modules/x-crypto-s/utssdk/web/lib/x64-core.js new file mode 100644 index 0000000..cee568d --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/lib/x64-core.js @@ -0,0 +1,113 @@ +import { + Base, + WordArray, +} from './core.js'; + +const X32WordArray = WordArray; + +/** + * A 64-bit word. + */ +export class X64Word extends Base { + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + constructor(high, low) { + super(); + + this.high = high; + this.low = low; + } +} + +/** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ +export class X64WordArray extends Base { + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + constructor(words = [], sigBytes = words.length * 8) { + super(); + + this.words = words; + this.sigBytes = sigBytes; + } + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32() { + // Shortcuts + const x64Words = this.words; + const x64WordsLength = x64Words.length; + + // Convert + const x32Words = []; + for (let i = 0; i < x64WordsLength; i += 1) { + const x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + } + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone() { + const clone = super.clone.call(this); + + // Clone "words" array + clone.words = this.words.slice(0); + const { words } = clone; + + // Clone each X64Word object + const wordsLength = words.length; + for (let i = 0; i < wordsLength; i += 1) { + words[i] = words[i].clone(); + } + + return clone; + } +} diff --git a/uni_modules/x-crypto-s/utssdk/web/src/JSEncrypt.ts b/uni_modules/x-crypto-s/utssdk/web/src/JSEncrypt.ts new file mode 100644 index 0000000..5f618a7 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/JSEncrypt.ts @@ -0,0 +1,220 @@ +import { b64tohex, hex2b64 } from "./lib/jsbn/base64"; +import { JSEncryptRSAKey } from "./JSEncryptRSAKey"; +const version = typeof process !== 'undefined' + ? process.env?.npm_package_version + : undefined; + +export interface IJSEncryptOptions { + default_key_size?: string; + default_public_exponent?: string; + log?: boolean; +} + +/** + * + * @param {Object} [options = {}] - An object to customize JSEncrypt behaviour + * possible parameters are: + * - default_key_size {number} default: 1024 the key size in bit + * - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent + * - log {boolean} default: false whether log warn/error or not + * @constructor + */ +export class JSEncrypt { + constructor(options: IJSEncryptOptions = {}) { + options = options || {}; + this.default_key_size = options.default_key_size + ? parseInt(options.default_key_size, 10) + : 1024; + this.default_public_exponent = options.default_public_exponent || "010001"; // 65537 default openssl public exponent for rsa key type + this.log = options.log || false; + // The private and public key. + this.key = null; + } + + private default_key_size: number; + private default_public_exponent: string; + private log: boolean; + private key: JSEncryptRSAKey; + public static version: string = version; + + /** + * Method to set the rsa key parameter (one method is enough to set both the public + * and the private key, since the private key contains the public key paramenters) + * Log a warning if logs are enabled + * @param {Object|string} key the pem encoded string or an object (with or without header/footer) + * @public + */ + public setKey(key: string) { + if (this.log && this.key) { + console.warn("A key was already set, overriding existing."); + } + this.key = new JSEncryptRSAKey(key); + } + + /** + * Proxy method for setKey, for api compatibility + * @see setKey + * @public + */ + public setPrivateKey(privkey: string) { + // Create the key. + this.setKey(privkey); + } + + /** + * Proxy method for setKey, for api compatibility + * @see setKey + * @public + */ + public setPublicKey(pubkey: string) { + // Sets the public key. + this.setKey(pubkey); + } + + /** + * Proxy method for RSAKey object's decrypt, decrypt the string using the private + * components of the rsa key object. Note that if the object was not set will be created + * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor + * @param {string} str base64 encoded crypted string to decrypt + * @return {string} the decrypted string + * @public + */ + public decrypt(str: string) { + // Return the decrypted string. + try { + return this.getKey().decrypt(b64tohex(str)); + } catch (ex) { + return false; + } + } + + /** + * Proxy method for RSAKey object's encrypt, encrypt the string using the public + * components of the rsa key object. Note that if the object was not set will be created + * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor + * @param {string} str the string to encrypt + * @return {string} the encrypted string encoded in base64 + * @public + */ + public encrypt(str: string) { + // Return the encrypted string. + try { + return hex2b64(this.getKey().encrypt(str)); + } catch (ex) { + return false; + } + } + + /** + * Proxy method for RSAKey object's sign. + * @param {string} str the string to sign + * @param {function} digestMethod hash method + * @param {string} digestName the name of the hash algorithm + * @return {string} the signature encoded in base64 + * @public + */ + public sign( + str: string, + digestMethod: (str: string) => string, + digestName: string, + ): string | false { + // return the RSA signature of 'str' in 'hex' format. + try { + return hex2b64(this.getKey().sign(str, digestMethod, digestName)); + } catch (ex) { + return false; + } + } + + /** + * Proxy method for RSAKey object's verify. + * @param {string} str the string to verify + * @param {string} signature the signature encoded in base64 to compare the string to + * @param {function} digestMethod hash method + * @return {boolean} whether the data and signature match + * @public + */ + public verify( + str: string, + signature: string, + digestMethod: (str: string) => string, + ): boolean { + // Return the decrypted 'digest' of the signature. + try { + return this.getKey().verify(str, b64tohex(signature), digestMethod); + } catch (ex) { + return false; + } + } + + /** + * Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object + * will be created and returned + * @param {callback} [cb] the callback to be called if we want the key to be generated + * in an async fashion + * @returns {JSEncryptRSAKey} the JSEncryptRSAKey object + * @public + */ + public getKey(cb?: () => void) { + // Only create new if it does not exist. + if (!this.key) { + // Get a new private key. + this.key = new JSEncryptRSAKey(); + if (cb && {}.toString.call(cb) === "[object Function]") { + this.key.generateAsync( + this.default_key_size, + this.default_public_exponent, + cb, + ); + return; + } + // Generate the key. + this.key.generate(this.default_key_size, this.default_public_exponent); + } + return this.key; + } + + /** + * Returns the pem encoded representation of the private key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the private key WITH header and footer + * @public + */ + public getPrivateKey() { + // Return the private representation of this key. + return this.getKey().getPrivateKey(); + } + + /** + * Returns the pem encoded representation of the private key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the private key WITHOUT header and footer + * @public + */ + public getPrivateKeyB64() { + // Return the private representation of this key. + return this.getKey().getPrivateBaseKeyB64(); + } + + /** + * Returns the pem encoded representation of the public key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the public key WITH header and footer + * @public + */ + public getPublicKey() { + // Return the private representation of this key. + return this.getKey().getPublicKey(); + } + + /** + * Returns the pem encoded representation of the public key + * If the key doesn't exists a new key will be created + * @returns {string} pem encoded representation of the public key WITHOUT header and footer + * @public + */ + public getPublicKeyB64() { + // Return the private representation of this key. + return this.getKey().getPublicBaseKeyB64(); + } +} diff --git a/uni_modules/x-crypto-s/utssdk/web/src/JSEncryptRSAKey.ts b/uni_modules/x-crypto-s/utssdk/web/src/JSEncryptRSAKey.ts new file mode 100644 index 0000000..10ca569 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/JSEncryptRSAKey.ts @@ -0,0 +1,324 @@ +import { hex2b64 } from "./lib/jsbn/base64"; +import { Hex } from "./lib/asn1js/hex"; +import { Base64 } from "./lib/asn1js/base64"; +import { ASN1 } from "./lib/asn1js/asn1"; +import { RSAKey } from "./lib/jsbn/rsa"; +import { parseBigInt } from "./lib/jsbn/jsbn"; +import { KJUR } from "./lib/jsrsasign/asn1-1.0"; + +/** + * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object. + * This object is just a decorator for parsing the key parameter + * @param {string|Object} key - The key in string format, or an object containing + * the parameters needed to build a RSAKey object. + * @constructor + */ +export class JSEncryptRSAKey extends RSAKey { + constructor(key?: string) { + super(); + // Call the super constructor. + // RSAKey.call(this); + // If a key key was provided. + if (key) { + // If this is a string... + if (typeof key === "string") { + this.parseKey(key); + } else if ( + JSEncryptRSAKey.hasPrivateKeyProperty(key) || + JSEncryptRSAKey.hasPublicKeyProperty(key) + ) { + // Set the values for the key. + this.parsePropertiesFrom(key); + } + } + } + + /** + * Method to parse a pem encoded string containing both a public or private key. + * The method will translate the pem encoded string in a der encoded string and + * will parse private key and public key parameters. This method accepts public key + * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1). + * + * @todo Check how many rsa formats use the same format of pkcs #1. + * + * The format is defined as: + * PublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * PublicKey BIT STRING + * } + * Where AlgorithmIdentifier is: + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm + * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) + * } + * and PublicKey is a SEQUENCE encapsulated in a BIT STRING + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + * it's possible to examine the structure of the keys obtained from openssl using + * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/ + * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer + * @private + */ + public parseKey(pem: string) { + try { + let modulus: string | number = 0; + let public_exponent: string | number = 0; + const reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/; + const der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem); + let asn1 = ASN1.decode(der); + + // Fixes a bug with OpenSSL 1.0+ private keys + if (asn1.sub.length === 3) { + asn1 = asn1.sub[2].sub[0]; + } + if (asn1.sub.length === 9) { + // Parse the private key. + modulus = asn1.sub[1].getHexStringValue(); // bigint + this.n = parseBigInt(modulus, 16); + + public_exponent = asn1.sub[2].getHexStringValue(); // int + this.e = parseInt(public_exponent, 16); + + const private_exponent = asn1.sub[3].getHexStringValue(); // bigint + this.d = parseBigInt(private_exponent, 16); + + const prime1 = asn1.sub[4].getHexStringValue(); // bigint + this.p = parseBigInt(prime1, 16); + + const prime2 = asn1.sub[5].getHexStringValue(); // bigint + this.q = parseBigInt(prime2, 16); + + const exponent1 = asn1.sub[6].getHexStringValue(); // bigint + this.dmp1 = parseBigInt(exponent1, 16); + + const exponent2 = asn1.sub[7].getHexStringValue(); // bigint + this.dmq1 = parseBigInt(exponent2, 16); + + const coefficient = asn1.sub[8].getHexStringValue(); // bigint + this.coeff = parseBigInt(coefficient, 16); + } else if (asn1.sub.length === 2) { + if (asn1.sub[0].sub) { + // Parse ASN.1 SubjectPublicKeyInfo type as defined by X.509 + var bit_string = asn1.sub[1]; + var sequence = bit_string.sub[0]; + modulus = sequence.sub[0].getHexStringValue(); + this.n = parseBigInt(modulus, 16); + public_exponent = sequence.sub[1].getHexStringValue(); + this.e = parseInt(public_exponent, 16); + } else { + // Parse ASN.1 RSAPublicKey type as defined by PKCS #1 + modulus = asn1.sub[0].getHexStringValue(); + this.n = parseBigInt(modulus, 16); + public_exponent = asn1.sub[1].getHexStringValue(); + this.e = parseInt(public_exponent, 16); + } + } else { + return false; + } + return true; + } catch (ex) { + return false; + } + } + + /** + * Translate rsa parameters in a hex encoded string representing the rsa key. + * + * The translation follow the ASN.1 notation : + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * @returns {string} DER Encoded String representing the rsa private key + * @private + */ + public getPrivateBaseKey() { + const options = { + array: [ + new KJUR.asn1.DERInteger({ int: 0 }), + new KJUR.asn1.DERInteger({ bigint: this.n }), + new KJUR.asn1.DERInteger({ int: this.e }), + new KJUR.asn1.DERInteger({ bigint: this.d }), + new KJUR.asn1.DERInteger({ bigint: this.p }), + new KJUR.asn1.DERInteger({ bigint: this.q }), + new KJUR.asn1.DERInteger({ bigint: this.dmp1 }), + new KJUR.asn1.DERInteger({ bigint: this.dmq1 }), + new KJUR.asn1.DERInteger({ bigint: this.coeff }), + ], + }; + const seq = new KJUR.asn1.DERSequence(options); + return seq.getEncodedHex(); + } + + /** + * base64 (pem) encoded version of the DER encoded representation + * @returns {string} pem encoded representation without header and footer + * @public + */ + public getPrivateBaseKeyB64() { + return hex2b64(this.getPrivateBaseKey()); + } + + /** + * Translate rsa parameters in a hex encoded string representing the rsa public key. + * The representation follow the ASN.1 notation : + * PublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * PublicKey BIT STRING + * } + * Where AlgorithmIdentifier is: + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm + * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) + * } + * and PublicKey is a SEQUENCE encapsulated in a BIT STRING + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + * @returns {string} DER Encoded String representing the rsa public key + * @private + */ + public getPublicBaseKey() { + const first_sequence = new KJUR.asn1.DERSequence({ + array: [ + new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.1" }), // RSA Encryption pkcs #1 oid + new KJUR.asn1.DERNull(), + ], + }); + + const second_sequence = new KJUR.asn1.DERSequence({ + array: [ + new KJUR.asn1.DERInteger({ bigint: this.n }), + new KJUR.asn1.DERInteger({ int: this.e }), + ], + }); + + const bit_string = new KJUR.asn1.DERBitString({ + hex: "00" + second_sequence.getEncodedHex(), + }); + + const seq = new KJUR.asn1.DERSequence({ + array: [first_sequence, bit_string], + }); + return seq.getEncodedHex(); + } + + /** + * base64 (pem) encoded version of the DER encoded representation + * @returns {string} pem encoded representation without header and footer + * @public + */ + public getPublicBaseKeyB64() { + return hex2b64(this.getPublicBaseKey()); + } + + /** + * wrap the string in block of width chars. The default value for rsa keys is 64 + * characters. + * @param {string} str the pem encoded string without header and footer + * @param {Number} [width=64] - the length the string has to be wrapped at + * @returns {string} + * @private + */ + public static wordwrap(str: string, width?: number) { + width = width || 64; + if (!str) { + return str; + } + const regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})"; + return str.match(RegExp(regex, "g")).join("\n"); + } + + /** + * Retrieve the pem encoded private key + * @returns {string} the pem encoded private key with header/footer + * @public + */ + public getPrivateKey() { + let key = "-----BEGIN RSA PRIVATE KEY-----\n"; + key += JSEncryptRSAKey.wordwrap(this.getPrivateBaseKeyB64()) + "\n"; + key += "-----END RSA PRIVATE KEY-----"; + return key; + } + + /** + * Retrieve the pem encoded public key + * @returns {string} the pem encoded public key with header/footer + * @public + */ + public getPublicKey() { + let key = "-----BEGIN PUBLIC KEY-----\n"; + key += JSEncryptRSAKey.wordwrap(this.getPublicBaseKeyB64()) + "\n"; + key += "-----END PUBLIC KEY-----"; + return key; + } + + /** + * Check if the object contains the necessary parameters to populate the rsa modulus + * and public exponent parameters. + * @param {Object} [obj={}] - An object that may contain the two public key + * parameters + * @returns {boolean} true if the object contains both the modulus and the public exponent + * properties (n and e) + * @todo check for types of n and e. N should be a parseable bigInt object, E should + * be a parseable integer number + * @private + */ + public static hasPublicKeyProperty(obj: object) { + obj = obj || {}; + return obj.hasOwnProperty("n") && obj.hasOwnProperty("e"); + } + + /** + * Check if the object contains ALL the parameters of an RSA key. + * @param {Object} [obj={}] - An object that may contain nine rsa key + * parameters + * @returns {boolean} true if the object contains all the parameters needed + * @todo check for types of the parameters all the parameters but the public exponent + * should be parseable bigint objects, the public exponent should be a parseable integer number + * @private + */ + public static hasPrivateKeyProperty(obj: object) { + obj = obj || {}; + return ( + obj.hasOwnProperty("n") && + obj.hasOwnProperty("e") && + obj.hasOwnProperty("d") && + obj.hasOwnProperty("p") && + obj.hasOwnProperty("q") && + obj.hasOwnProperty("dmp1") && + obj.hasOwnProperty("dmq1") && + obj.hasOwnProperty("coeff") + ); + } + + /** + * Parse the properties of obj in the current rsa object. Obj should AT LEAST + * include the modulus and public exponent (n, e) parameters. + * @param {Object} obj - the object containing rsa parameters + * @private + */ + public parsePropertiesFrom(obj: any) { + this.n = obj.n; + this.e = obj.e; + + if (obj.hasOwnProperty("d")) { + this.d = obj.d; + this.p = obj.p; + this.q = obj.q; + this.dmp1 = obj.dmp1; + this.dmq1 = obj.dmq1; + this.coeff = obj.coeff; + } + } +} diff --git a/uni_modules/x-crypto-s/utssdk/web/src/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/web/src/LICENSE.txt new file mode 100644 index 0000000..89ac13f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/LICENSE.txt @@ -0,0 +1,19 @@ +The MIT License (MIT) +Copyright (c) 2015 Form.io + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/uni_modules/x-crypto-s/utssdk/web/src/index.ts b/uni_modules/x-crypto-s/utssdk/web/src/index.ts new file mode 100644 index 0000000..9c50867 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/index.ts @@ -0,0 +1,3 @@ +import { JSEncrypt } from './JSEncrypt'; +export { JSEncrypt } +export default JSEncrypt; diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/LICENSE.txt new file mode 100644 index 0000000..6d61d73 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/LICENSE.txt @@ -0,0 +1,16 @@ + + +ASN.1 JavaScript decoder +Copyright (c) 2008-2013 Lapo Luchini + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +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. \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/asn1.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/asn1.ts new file mode 100644 index 0000000..7331026 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/asn1.ts @@ -0,0 +1,598 @@ +// ASN.1 JavaScript decoder +// Copyright (c) 2008-2014 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ +/*global oids */ + +import {Int10} from "./int10"; + +const ellipsis = "\u2026"; +const reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; +const reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; + +function stringCut(str:string, len:number) { + if (str.length > len) { + str = str.substring(0, len) + ellipsis; + } + return str; +} + +export class Stream { + constructor(enc:Stream|number[], pos?:number) { + if (enc instanceof Stream) { + this.enc = enc.enc; + this.pos = enc.pos; + } else { + // enc should be an array or a binary string + this.enc = enc; + this.pos = pos; + } + } + + private enc:string|number[]; + public pos:number; + + public get(pos?:number) { + if (pos === undefined) { + pos = this.pos++; + } + if (pos >= this.enc.length) { + throw new Error(`Requesting byte offset ${pos} on a stream of length ${this.enc.length}`); + } + return ("string" === typeof this.enc) ? this.enc.charCodeAt(pos) : this.enc[pos]; + } + + public hexDigits = "0123456789ABCDEF"; + + public hexByte(b:number) { + return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF); + } + + public hexDump(start:number, end:number, raw:boolean) { + let s = ""; + for (let i = start; i < end; ++i) { + s += this.hexByte(this.get(i)); + if (raw !== true) { + switch (i & 0xF) { + case 0x7: + s += " "; + break; + case 0xF: + s += "\n"; + break; + default: + s += " "; + } + } + } + return s; + } + + public isASCII(start:number, end:number) { + for (let i = start; i < end; ++i) { + const c = this.get(i); + if (c < 32 || c > 176) { + return false; + } + } + return true; + } + + public parseStringISO(start:number, end:number) { + let s = ""; + for (let i = start; i < end; ++i) { + s += String.fromCharCode(this.get(i)); + } + return s; + } + + public parseStringUTF(start:number, end:number) { + let s = ""; + for (let i = start; i < end;) { + const c = this.get(i++); + if (c < 128) { + s += String.fromCharCode(c); + } else if ((c > 191) && (c < 224)) { + s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F)); + } else { + s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F)); + } + } + return s; + } + + public parseStringBMP(start:number, end:number) { + let str = ""; + let hi; + let lo; + for (let i = start; i < end;) { + hi = this.get(i++); + lo = this.get(i++); + str += String.fromCharCode((hi << 8) | lo); + } + return str; + } + + public parseTime(start:number, end:number, shortYear:boolean) { + let s = this.parseStringISO(start, end); + const m:Array = (shortYear ? reTimeS : reTimeL).exec(s); + if (!m) { + return "Unrecognized time: " + s; + } + if (shortYear) { + // to avoid querying the timer, use the fixed range [1970, 2069] + // it will conform with ITU X.400 [-10, +40] sliding window until 2030 + m[1] = +m[1]; + (m[1] as number) += (+m[1] < 70) ? 2000 : 1900; + } + s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4]; + if (m[5]) { + s += ":" + m[5]; + if (m[6]) { + s += ":" + m[6]; + if (m[7]) { + s += "." + m[7]; + } + } + } + if (m[8]) { + s += " UTC"; + if (m[8] != "Z") { + s += m[8]; + if (m[9]) { + s += ":" + m[9]; + } + } + } + return s; + } + + public parseInteger(start:number, end:number) { + let v = this.get(start); + const neg = (v > 127); + const pad = neg ? 255 : 0; + let len; + let s:string | number = ""; + // skip unuseful bits (not allowed in DER) + while (v == pad && ++start < end) { + v = this.get(start); + } + len = end - start; + if (len === 0) { + return neg ? -1 : 0; + } + // show bit length of huge integers + if (len > 4) { + s = v; + len <<= 3; + while (((+s ^ pad) & 0x80) == 0) { + s = +s << 1; + --len; + } + s = "(" + len + " bit)\n"; + } + // decode the integer + if (neg) { + v = v - 256; + } + const n = new Int10(v); + for (let i = start + 1; i < end; ++i) { + n.mulAdd(256, this.get(i)); + } + return s + n.toString(); + } + + public parseBitString(start:number, end:number, maxLength:number) { + const unusedBit = this.get(start); + const lenBit = ((end - start - 1) << 3) - unusedBit; + const intro = "(" + lenBit + " bit)\n"; + let s = ""; + for (let i = start + 1; i < end; ++i) { + const b = this.get(i); + const skip = (i == end - 1) ? unusedBit : 0; + for (let j = 7; j >= skip; --j) { + s += (b >> j) & 1 ? "1" : "0"; + } + if (s.length > maxLength) { + return intro + stringCut(s, maxLength); + } + } + return intro + s; + } + + public parseOctetString(start:number, end:number, maxLength:number) { + if (this.isASCII(start, end)) { + return stringCut(this.parseStringISO(start, end), maxLength); + } + const len = end - start; + let s = "(" + len + " byte)\n"; + maxLength /= 2; // we work in bytes + if (len > maxLength) { + end = start + maxLength; + } + for (let i = start; i < end; ++i) { + s += this.hexByte(this.get(i)); + } + if (len > maxLength) { + s += ellipsis; + } + return s; + } + + public parseOID(start:number, end:number, maxLength:number) { + let s = ""; + let n:number|Int10 = new Int10(); + let bits = 0; + for (let i = start; i < end; ++i) { + const v = this.get(i); + n.mulAdd(128, v & 0x7F); + bits += 7; + if (!(v & 0x80)) { // finished + if (s === "") { + n = n.simplify(); + if (n instanceof Int10) { + n.sub(80); + s = "2." + n.toString(); + } else { + const m = n < 80 ? n < 40 ? 0 : 1 : 2; + s = m + "." + (n - m * 40); + } + } else { + s += "." + n.toString(); + } + if (s.length > maxLength) { + return stringCut(s, maxLength); + } + n = new Int10(); + bits = 0; + } + } + if (bits > 0) { + s += ".incomplete"; + } + return s; + } +} +export class ASN1 { + constructor(stream:Stream, header:number, length:number, tag:ASN1Tag, sub:ASN1[]) { + if (!(tag instanceof ASN1Tag)) { + throw new Error("Invalid tag value."); + } + this.stream = stream; + this.header = header; + this.length = length; + this.tag = tag; + this.sub = sub; + } + + private stream:Stream; + private header:number; + private length:number; + private tag:ASN1Tag; + public sub:ASN1[]; + + public typeName() { + switch (this.tag.tagClass) { + case 0: // universal + switch (this.tag.tagNumber) { + case 0x00: + return "EOC"; + case 0x01: + return "BOOLEAN"; + case 0x02: + return "INTEGER"; + case 0x03: + return "BIT_STRING"; + case 0x04: + return "OCTET_STRING"; + case 0x05: + return "NULL"; + case 0x06: + return "OBJECT_IDENTIFIER"; + case 0x07: + return "ObjectDescriptor"; + case 0x08: + return "EXTERNAL"; + case 0x09: + return "REAL"; + case 0x0A: + return "ENUMERATED"; + case 0x0B: + return "EMBEDDED_PDV"; + case 0x0C: + return "UTF8String"; + case 0x10: + return "SEQUENCE"; + case 0x11: + return "SET"; + case 0x12: + return "NumericString"; + case 0x13: + return "PrintableString"; // ASCII subset + case 0x14: + return "TeletexString"; // aka T61String + case 0x15: + return "VideotexString"; + case 0x16: + return "IA5String"; // ASCII + case 0x17: + return "UTCTime"; + case 0x18: + return "GeneralizedTime"; + case 0x19: + return "GraphicString"; + case 0x1A: + return "VisibleString"; // ASCII subset + case 0x1B: + return "GeneralString"; + case 0x1C: + return "UniversalString"; + case 0x1E: + return "BMPString"; + } + return "Universal_" + this.tag.tagNumber.toString(); + case 1: + return "Application_" + this.tag.tagNumber.toString(); + case 2: + return "[" + this.tag.tagNumber.toString() + "]"; // Context + case 3: + return "Private_" + this.tag.tagNumber.toString(); + } + } + + public content(maxLength:number) { // a preview of the content (intended for humans) + if (this.tag === undefined) { + return null; + } + if (maxLength === undefined) { + maxLength = Infinity; + } + const content = this.posContent(); + const len = Math.abs(this.length); + if (!this.tag.isUniversal()) { + if (this.sub !== null) { + return "(" + this.sub.length + " elem)"; + } + return this.stream.parseOctetString(content, content + len, maxLength); + } + switch (this.tag.tagNumber) { + case 0x01: // BOOLEAN + return (this.stream.get(content) === 0) ? "false" : "true"; + case 0x02: // INTEGER + return this.stream.parseInteger(content, content + len); + case 0x03: // BIT_STRING + return this.sub ? "(" + this.sub.length + " elem)" : + this.stream.parseBitString(content, content + len, maxLength); + case 0x04: // OCTET_STRING + return this.sub ? "(" + this.sub.length + " elem)" : + this.stream.parseOctetString(content, content + len, maxLength); + // case 0x05: // NULL + case 0x06: // OBJECT_IDENTIFIER + return this.stream.parseOID(content, content + len, maxLength); + // case 0x07: // ObjectDescriptor + // case 0x08: // EXTERNAL + // case 0x09: // REAL + // case 0x0A: // ENUMERATED + // case 0x0B: // EMBEDDED_PDV + case 0x10: // SEQUENCE + case 0x11: // SET + if (this.sub !== null) { + return "(" + this.sub.length + " elem)"; + } else { + return "(no elem)"; + } + case 0x0C: // UTF8String + return stringCut(this.stream.parseStringUTF(content, content + len), maxLength); + case 0x12: // NumericString + case 0x13: // PrintableString + case 0x14: // TeletexString + case 0x15: // VideotexString + case 0x16: // IA5String + // case 0x19: // GraphicString + case 0x1A: // VisibleString + // case 0x1B: // GeneralString + // case 0x1C: // UniversalString + return stringCut(this.stream.parseStringISO(content, content + len), maxLength); + case 0x1E: // BMPString + return stringCut(this.stream.parseStringBMP(content, content + len), maxLength); + case 0x17: // UTCTime + case 0x18: // GeneralizedTime + return this.stream.parseTime(content, content + len, (this.tag.tagNumber == 0x17)); + } + return null; + } + + public toString() { + return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? "null" : this.sub.length) + "]"; + } + + public toPrettyString(indent:string) { + if (indent === undefined) { + indent = ""; + } + let s = indent + this.typeName() + " @" + this.stream.pos; + if (this.length >= 0) { + s += "+"; + } + s += this.length; + if (this.tag.tagConstructed) { + s += " (constructed)"; + } else if ((this.tag.isUniversal() && ((this.tag.tagNumber == 0x03) || (this.tag.tagNumber == 0x04))) && (this.sub !== null)) { + s += " (encapsulates)"; + } + s += "\n"; + if (this.sub !== null) { + indent += " "; + for (let i = 0, max = this.sub.length; i < max; ++i) { + s += this.sub[i].toPrettyString(indent); + } + } + return s; + } + + public posStart() { + return this.stream.pos; + } + + public posContent() { + return this.stream.pos + this.header; + } + + public posEnd() { + return this.stream.pos + this.header + Math.abs(this.length); + } + + public toHexString() { + return this.stream.hexDump(this.posStart(), this.posEnd(), true); + } + + public static decodeLength(stream:Stream):number { + let buf = stream.get(); + const len = buf & 0x7F; + if (len == buf) { + return len; + } + + // no reason to use Int10, as it would be a huge buffer anyways + if (len > 6) { + throw new Error("Length over 48 bits not supported at position " + (stream.pos - 1)); + } + if (len === 0) { + return null; + } // undefined + buf = 0; + for (let i = 0; i < len; ++i) { + buf = (buf * 256) + stream.get(); + } + return buf; + } + + /** + * Retrieve the hexadecimal value (as a string) of the current ASN.1 element + * @returns {string} + * @public + */ + public getHexStringValue():string { + const hexString = this.toHexString(); + const offset = this.header * 2; + const length = this.length * 2; + return hexString.substr(offset, length); + } + + public static decode(str:Stream|number[]) { + let stream:Stream; + + if (!(str instanceof Stream)) { + stream = new Stream(str, 0); + } else { + stream = str; + } + + const streamStart = new Stream(stream); + const tag = new ASN1Tag(stream); + let len = ASN1.decodeLength(stream); + const start = stream.pos; + const header = start - streamStart.pos; + let sub = null; + const getSub:() => ASN1[] = function () { + const ret = []; + if (len !== null) { + // definite length + const end = start + len; + while (stream.pos < end) { + ret[ret.length] = ASN1.decode(stream); + } + if (stream.pos != end) { + throw new Error("Content size is not correct for container starting at offset " + start); + } + } else { + // undefined length + try { + for (; ;) { + const s = ASN1.decode(stream); + if (s.tag.isEOC()) { + break; + } + ret[ret.length] = s; + } + len = start - stream.pos; // undefined lengths are represented as negative values + } catch (e) { + throw new Error("Exception while decoding undefined length content: " + e); + } + } + + return ret; + }; + if (tag.tagConstructed) { + // must have valid content + sub = getSub(); + } else if (tag.isUniversal() && ((tag.tagNumber == 0x03) || (tag.tagNumber == 0x04))) { + // sometimes BitString and OctetString are used to encapsulate ASN.1 + try { + if (tag.tagNumber == 0x03) { + if (stream.get() != 0) { + throw new Error("BIT STRINGs with unused bits cannot encapsulate."); + } + } + sub = getSub(); + for (let i = 0; i < sub.length; ++i) { + if (sub[i].tag.isEOC()) { + throw new Error("EOC is not supposed to be actual content."); + } + } + } catch (e) { + // but silently ignore when they don't + sub = null; + } + } + if (sub === null) { + if (len === null) { + throw new Error("We can't skip over an invalid tag with undefined length at offset " + start); + } + stream.pos = start + Math.abs(len); + } + return new ASN1(streamStart, header, len, tag, sub); + } +} + + +export class ASN1Tag { + constructor(stream:Stream) { + let buf = stream.get(); + this.tagClass = buf >> 6; + this.tagConstructed = ((buf & 0x20) !== 0); + this.tagNumber = buf & 0x1F; + if (this.tagNumber == 0x1F) { // long tag + const n = new Int10(); + do { + buf = stream.get(); + n.mulAdd(128, buf & 0x7F); + } while (buf & 0x80); + this.tagNumber = n.simplify(); + } + } + + public tagClass:number; + public tagConstructed:boolean; + public tagNumber:number | Int10; + + public isUniversal() { + return this.tagClass === 0x00; + } + + public isEOC() { + return this.tagClass === 0x00 && this.tagNumber === 0x00; + } +} diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/base64.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/base64.ts new file mode 100644 index 0000000..3a3f2aa --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/base64.ts @@ -0,0 +1,87 @@ +// Base64 JavaScript decoder +// Copyright (c) 2008-2013 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ +let decoder:{ [index:string]:number | string }; +export const Base64 = { + decode(a:string) { + let i; + if (decoder === undefined) { + const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const ignore = "= \f\n\r\t\u00A0\u2028\u2029"; + decoder = Object.create(null); + for (i = 0; i < 64; ++i) { + decoder[b64.charAt(i)] = i; + } + decoder['-'] = 62;//+ + decoder['_'] = 63;//- + for (i = 0; i < ignore.length; ++i) { + decoder[ignore.charAt(i)] = -1; + } + } + const out = []; + let bits = 0; + let char_count = 0; + for (i = 0; i < a.length; ++i) { + let c:string|number = a.charAt(i); + if (c == "=") { + break; + } + c = decoder[c]; + if (c == -1) { + continue; + } + if (c === undefined) { + throw new Error("Illegal character at offset " + i); + } + bits |= c as number; + if (++char_count >= 4) { + out[out.length] = (bits >> 16); + out[out.length] = (bits >> 8) & 0xFF; + out[out.length] = bits & 0xFF; + bits = 0; + char_count = 0; + } else { + bits <<= 6; + } + } + switch (char_count) { + case 1: + throw new Error("Base64 encoding incomplete: at least 2 bits missing"); + case 2: + out[out.length] = (bits >> 10); + break; + case 3: + out[out.length] = (bits >> 16); + out[out.length] = (bits >> 8) & 0xFF; + break; + } + return out; + }, + re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/, + unarmor(a:string):number[] { + const m = Base64.re.exec(a); + if (m) { + if (m[1]) { + a = m[1]; + } else if (m[2]) { + a = m[2]; + } else { + throw new Error("RegExp out of sync"); + } + } + return Base64.decode(a); + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/hex.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/hex.ts new file mode 100644 index 0000000..5bc6aa9 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/hex.ts @@ -0,0 +1,66 @@ +// Hex JavaScript decoder +// Copyright (c) 2008-2013 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ + +let decoder:{ [index:string]:number }; +export const Hex = { + decode(a:string):number[] { + let i; + if (decoder === undefined) { + let hex = "0123456789ABCDEF"; + const ignore = " \f\n\r\t\u00A0\u2028\u2029"; + decoder = {}; + for (i = 0; i < 16; ++i) { + decoder[hex.charAt(i)] = i; + } + hex = hex.toLowerCase(); + for (i = 10; i < 16; ++i) { + decoder[hex.charAt(i)] = i; + } + for (i = 0; i < ignore.length; ++i) { + decoder[ignore.charAt(i)] = -1; + } + } + const out = []; + let bits = 0; + let char_count = 0; + for (i = 0; i < a.length; ++i) { + let c:number|string = a.charAt(i); + if (c == "=") { + break; + } + c = decoder[c]; + if (c == -1) { + continue; + } + if (c === undefined) { + throw new Error("Illegal character at offset " + i); + } + bits |= c; + if (++char_count >= 2) { + out[out.length] = bits; + bits = 0; + char_count = 0; + } else { + bits <<= 4; + } + } + if (char_count) { + throw new Error("Hex encoding incomplete: 4 bits missing"); + } + return out; + } +}; diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/int10.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/int10.ts new file mode 100644 index 0000000..7f9dd0f --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/int10.ts @@ -0,0 +1,97 @@ +// Big integer base-10 printing library +// Copyright (c) 2014 Lapo Luchini + +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// 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. + +/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ + + +const max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256 + +export class Int10 { + constructor(value?:string | number) { + this.buf = [+value || 0]; + } + + + public mulAdd(m:number, c:number) { + // assert(m <= 256) + const b = this.buf; + const l = b.length; + let i; + let t; + for (i = 0; i < l; ++i) { + t = b[i] * m + c; + if (t < max) { + c = 0; + } else { + c = 0 | (t / max); + t -= c * max; + } + b[i] = t; + } + if (c > 0) { + b[i] = c; + } + } + + public sub(c:number) { + // assert(m <= 256) + const b = this.buf; + const l = b.length; + let i; + let t; + for (i = 0; i < l; ++i) { + t = b[i] - c; + if (t < 0) { + t += max; + c = 1; + } else { + c = 0; + } + b[i] = t; + } + while (b[b.length - 1] === 0) { + b.pop(); + } + } + + public toString(base?:number) { + if ((base || 10) != 10) { + throw new Error("only base 10 is supported"); + } + const b = this.buf; + let s = b[b.length - 1].toString(); + for (let i = b.length - 2; i >= 0; --i) { + s += (max + b[i]).toString().substring(1); + } + return s; + } + + public valueOf() { + const b = this.buf; + let v = 0; + for (let i = b.length - 1; i >= 0; --i) { + v = v * max + b[i]; + } + return v; + } + + public simplify() { + const b = this.buf; + return (b.length == 1) ? b[0] : this; + } + + private buf:number[]; +} + diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/oids.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/oids.ts new file mode 100644 index 0000000..b418cfa --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/asn1js/oids.ts @@ -0,0 +1,1962 @@ +// Converted from: http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg +// which is made by Peter Gutmann and whose license states: +// You can use this code in whatever way you want, +// as long as you don't try to claim you wrote it. +export const oids = { +"0.2.262.1.10": { "d": "Telesec", "c": "Deutsche Telekom", "w": false }, +"0.2.262.1.10.0": { "d": "extension", "c": "Telesec", "w": false }, +"0.2.262.1.10.1": { "d": "mechanism", "c": "Telesec", "w": false }, +"0.2.262.1.10.1.0": { "d": "authentication", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.0.1": { "d": "passwordAuthentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.2": { "d": "protectedPasswordAuthentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.3": { "d": "oneWayX509Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.4": { "d": "twoWayX509Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.5": { "d": "threeWayX509Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.6": { "d": "oneWayISO9798Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.7": { "d": "twoWayISO9798Authentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.0.8": { "d": "telekomAuthentication", "c": "Telesec authentication", "w": false }, +"0.2.262.1.10.1.1": { "d": "signature", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.1": { "d": "md4WithRSAAndISO9697", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.2": { "d": "md4WithRSAAndTelesecSignatureStandard", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.3": { "d": "md5WithRSAAndISO9697", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.4": { "d": "md5WithRSAAndTelesecSignatureStandard", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.5": { "d": "ripemd160WithRSAAndTelekomSignatureStandard", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.1.9": { "d": "hbciRsaSignature", "c": "Telesec signature", "w": false }, +"0.2.262.1.10.1.2": { "d": "encryption", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.2.0": { "d": "none", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.1": { "d": "rsaTelesec", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2": { "d": "des", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.1": { "d": "desECB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.2": { "d": "desCBC", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.3": { "d": "desOFB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.4": { "d": "desCFB8", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.2.5": { "d": "desCFB64", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3": { "d": "des3", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.1": { "d": "des3ECB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.2": { "d": "des3CBC", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.3": { "d": "des3OFB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.4": { "d": "des3CFB8", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.3.5": { "d": "des3CFB64", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.4": { "d": "magenta", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5": { "d": "idea", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.1": { "d": "ideaECB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.2": { "d": "ideaCBC", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.3": { "d": "ideaOFB", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.4": { "d": "ideaCFB8", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.2.5.5": { "d": "ideaCFB64", "c": "Telesec encryption", "w": false }, +"0.2.262.1.10.1.3": { "d": "oneWayFunction", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.3.1": { "d": "md4", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.2": { "d": "md5", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.3": { "d": "sqModNX509", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.4": { "d": "sqModNISO", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.5": { "d": "ripemd128", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.6": { "d": "hashUsingBlockCipher", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.7": { "d": "mac", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.3.8": { "d": "ripemd160", "c": "Telesec one-way function", "w": false }, +"0.2.262.1.10.1.4": { "d": "fecFunction", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.1.4.1": { "d": "reedSolomon", "c": "Telesec mechanism", "w": false }, +"0.2.262.1.10.2": { "d": "module", "c": "Telesec", "w": false }, +"0.2.262.1.10.2.0": { "d": "algorithms", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.1": { "d": "attributeTypes", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.2": { "d": "certificateTypes", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.3": { "d": "messageTypes", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.4": { "d": "plProtocol", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.5": { "d": "smeAndComponentsOfSme", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.6": { "d": "fec", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.7": { "d": "usefulDefinitions", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.8": { "d": "stefiles", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.9": { "d": "sadmib", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.10": { "d": "electronicOrder", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.11": { "d": "telesecTtpAsymmetricApplication", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.12": { "d": "telesecTtpBasisApplication", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.13": { "d": "telesecTtpMessages", "c": "Telesec module", "w": false }, +"0.2.262.1.10.2.14": { "d": "telesecTtpTimeStampApplication", "c": "Telesec module", "w": false }, +"0.2.262.1.10.3": { "d": "objectClass", "c": "Telesec", "w": false }, +"0.2.262.1.10.3.0": { "d": "telesecOtherName", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.1": { "d": "directory", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.2": { "d": "directoryType", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.3": { "d": "directoryGroup", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.4": { "d": "directoryUser", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.3.5": { "d": "symmetricKeyEntry", "c": "Telesec object class", "w": false }, +"0.2.262.1.10.4": { "d": "package", "c": "Telesec", "w": false }, +"0.2.262.1.10.5": { "d": "parameter", "c": "Telesec", "w": false }, +"0.2.262.1.10.6": { "d": "nameBinding", "c": "Telesec", "w": false }, +"0.2.262.1.10.7": { "d": "attribute", "c": "Telesec", "w": false }, +"0.2.262.1.10.7.0": { "d": "applicationGroupIdentifier", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.1": { "d": "certificateType", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.2": { "d": "telesecCertificate", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.3": { "d": "certificateNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.4": { "d": "certificateRevocationList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.5": { "d": "creationDate", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.6": { "d": "issuer", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.7": { "d": "namingAuthority", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.8": { "d": "publicKeyDirectory", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.9": { "d": "securityDomain", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.10": { "d": "subject", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.11": { "d": "timeOfRevocation", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.12": { "d": "userGroupReference", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.13": { "d": "validity", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.14": { "d": "zert93", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.15": { "d": "securityMessEnv", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.16": { "d": "anonymizedPublicKeyDirectory", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.17": { "d": "telesecGivenName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.18": { "d": "nameAdditions", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.19": { "d": "telesecPostalCode", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.20": { "d": "nameDistinguisher", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.21": { "d": "telesecCertificateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.22": { "d": "teletrustCertificateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.23": { "d": "x509CertificateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.24": { "d": "timeOfIssue", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.25": { "d": "physicalCardNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.26": { "d": "fileType", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.27": { "d": "ctlFileIsArchive", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.28": { "d": "emailAddress", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.29": { "d": "certificateTemplateList", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.30": { "d": "directoryName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.31": { "d": "directoryTypeName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.32": { "d": "directoryGroupName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.33": { "d": "directoryUserName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.34": { "d": "revocationFlag", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.35": { "d": "symmetricKeyEntryName", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.36": { "d": "glNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.37": { "d": "goNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.38": { "d": "gKeyData", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.39": { "d": "zKeyData", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.40": { "d": "ktKeyData", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.41": { "d": "ktKeyNumber", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.51": { "d": "timeOfRevocationGen", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.7.52": { "d": "liabilityText", "c": "Telesec attribute", "w": false }, +"0.2.262.1.10.8": { "d": "attributeGroup", "c": "Telesec", "w": false }, +"0.2.262.1.10.9": { "d": "action", "c": "Telesec", "w": false }, +"0.2.262.1.10.10": { "d": "notification", "c": "Telesec", "w": false }, +"0.2.262.1.10.11": { "d": "snmp-mibs", "c": "Telesec", "w": false }, +"0.2.262.1.10.11.1": { "d": "securityApplication", "c": "Telesec SNMP MIBs", "w": false }, +"0.2.262.1.10.12": { "d": "certAndCrlExtensionDefinitions", "c": "Telesec", "w": false }, +"0.2.262.1.10.12.0": { "d": "liabilityLimitationFlag", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.1": { "d": "telesecCertIdExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.2": { "d": "Telesec policyIdentifier", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.3": { "d": "telesecPolicyQualifierID", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.4": { "d": "telesecCRLFilteredExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.5": { "d": "telesecCRLFilterExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.2.262.1.10.12.6": { "d": "telesecNamingAuthorityExt", "c": "Telesec cert/CRL extension", "w": false }, +"0.4.0.127.0.7": { "d": "bsi", "c": "BSI TR-03110/TR-03111", "w": false }, +"0.4.0.127.0.7.1": { "d": "bsiEcc", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1": { "d": "bsifieldType", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.1": { "d": "bsiPrimeField", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2": { "d": "bsiCharacteristicTwoField", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3": { "d": "bsiCharacteristicTwoBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3.1": { "d": "bsiGnBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3.2": { "d": "bsiTpBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.2.3.3": { "d": "bsiPpBasis", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1": { "d": "bsiEcdsaSignatures", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.1": { "d": "bsiEcdsaWithSHA1", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.2": { "d": "bsiEcdsaWithSHA224", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.3": { "d": "bsiEcdsaWithSHA256", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.4": { "d": "bsiEcdsaWithSHA384", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.5": { "d": "bsiEcdsaWithSHA512", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.1.4.1.6": { "d": "bsiEcdsaWithRIPEMD160", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.2": { "d": "bsiEcKeyType", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.2.1": { "d": "bsiEcPublicKey", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.5.1": { "d": "bsiKaeg", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.5.1.1": { "d": "bsiKaegWithX963KDF", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.1.5.1.2": { "d": "bsiKaegWith3DESKDF", "c": "BSI TR-03111", "w": false }, +"0.4.0.127.0.7.2.2.1": { "d": "bsiPK", "c": "BSI TR-03110. Formerly known as bsiCA, now moved to ...2.2.3.x", "w": false }, +"0.4.0.127.0.7.2.2.1.1": { "d": "bsiPK_DH", "c": "BSI TR-03110. Formerly known as bsiCA_DH, now moved to ...2.2.3.x", "w": false }, +"0.4.0.127.0.7.2.2.1.2": { "d": "bsiPK_ECDH", "c": "BSI TR-03110. Formerly known as bsiCA_ECDH, now moved to ...2.2.3.x", "w": false }, +"0.4.0.127.0.7.2.2.2": { "d": "bsiTA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1": { "d": "bsiTA_RSA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.1": { "d": "bsiTA_RSAv1_5_SHA1", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.2": { "d": "bsiTA_RSAv1_5_SHA256", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.3": { "d": "bsiTA_RSAPSS_SHA1", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.1.4": { "d": "bsiTA_RSAPSS_SHA256", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2": { "d": "bsiTA_ECDSA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2.1": { "d": "bsiTA_ECDSA_SHA1", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2.2": { "d": "bsiTA_ECDSA_SHA224", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.2.2.3": { "d": "bsiTA_ECDSA_SHA256", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.3": { "d": "bsiCA", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.3.1": { "d": "bsiCA_DH", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.2.2.3.2": { "d": "bsiCA_ECDH", "c": "BSI TR-03110", "w": false }, +"0.4.0.127.0.7.3.1.2.1": { "d": "bsiRoleEAC", "c": "BSI TR-03110", "w": false }, +"0.4.0.1862": { "d": "etsiQcsProfile", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1": { "d": "etsiQcs", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.1": { "d": "etsiQcsCompliance", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.2": { "d": "etsiQcsLimitValue", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.3": { "d": "etsiQcsRetentionPeriod", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.4.0.1862.1.4": { "d": "etsiQcsQcSSCD", "c": "ETSI TS 101 862 qualified certificates", "w": false }, +"0.9.2342.19200300.100.1.1": { "d": "userID", "c": "Some oddball X.500 attribute collection", "w": false }, +"0.9.2342.19200300.100.1.3": { "d": "rfc822Mailbox", "c": "Some oddball X.500 attribute collection", "w": false }, +"0.9.2342.19200300.100.1.25": { "d": "domainComponent", "c": "Men are from Mars, this OID is from Pluto", "w": false }, +"1.0.10118.3.0.49": { "d": "ripemd160", "c": "ISO 10118-3 hash function", "w": false }, +"1.0.10118.3.0.50": { "d": "ripemd128", "c": "ISO 10118-3 hash function", "w": false }, +"1.0.10118.3.0.55": { "d": "whirlpool", "c": "ISO 10118-3 hash function", "w": false }, +"1.2.36.1.3.1.1.1": { "d": "qgpki", "c": "Queensland Government PKI", "w": false }, +"1.2.36.1.3.1.1.1.1": { "d": "qgpkiPolicies", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.1.1": { "d": "qgpkiMedIntermedCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.1": { "d": "qgpkiMedIntermedIndividual", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.2": { "d": "qgpkiMedIntermedDeviceControl", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.3": { "d": "qgpkiMedIntermedDevice", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.4": { "d": "qgpkiMedIntermedAuthorisedParty", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.1.5": { "d": "qgpkiMedIntermedDeviceSystem", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2": { "d": "qgpkiMedIssuingCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.1": { "d": "qgpkiMedIssuingIndividual", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.2": { "d": "qgpkiMedIssuingDeviceControl", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.3": { "d": "qgpkiMedIssuingDevice", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.4": { "d": "qgpkiMedIssuingAuthorisedParty", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.5": { "d": "qgpkiMedIssuingClientAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.6": { "d": "qgpkiMedIssuingServerAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.7": { "d": "qgpkiMedIssuingDataProt", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.2.8": { "d": "qgpkiMedIssuingTokenAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.3": { "d": "qgpkiBasicIntermedCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.3.1": { "d": "qgpkiBasicIntermedDeviceSystem", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4": { "d": "qgpkiBasicIssuingCA", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4.1": { "d": "qgpkiBasicIssuingClientAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4.2": { "d": "qgpkiBasicIssuingServerAuth", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.1.4.3": { "d": "qgpkiBasicIssuingDataSigning", "c": "QGPKI policy", "w": false }, +"1.2.36.1.3.1.1.1.2": { "d": "qgpkiAssuranceLevel", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.1": { "d": "qgpkiAssuranceRudimentary", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.2": { "d": "qgpkiAssuranceBasic", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.3": { "d": "qgpkiAssuranceMedium", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.2.4": { "d": "qgpkiAssuranceHigh", "c": "QGPKI assurance level", "w": false }, +"1.2.36.1.3.1.1.1.3": { "d": "qgpkiCertFunction", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.1": { "d": "qgpkiFunctionIndividual", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.2": { "d": "qgpkiFunctionDevice", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.3": { "d": "qgpkiFunctionAuthorisedParty", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.1.1.3.4": { "d": "qgpkiFunctionDeviceControl", "c": "QGPKI policies", "w": false }, +"1.2.36.1.3.1.2": { "d": "qpspki", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1": { "d": "qpspkiPolicies", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1.2": { "d": "qpspkiPolicyBasic", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1.3": { "d": "qpspkiPolicyMedium", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.2.1.4": { "d": "qpspkiPolicyHigh", "c": "Queensland Police PKI", "w": false }, +"1.2.36.1.3.1.3.2": { "d": "qtmrpki", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.1": { "d": "qtmrpkiPolicies", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.2": { "d": "qtmrpkiPurpose", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.2.1": { "d": "qtmrpkiIndividual", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.2": { "d": "qtmrpkiDeviceControl", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.3": { "d": "qtmrpkiDevice", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.4": { "d": "qtmrpkiAuthorisedParty", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.2.5": { "d": "qtmrpkiDeviceSystem", "c": "Queensland Transport PKI purpose", "w": false }, +"1.2.36.1.3.1.3.2.3": { "d": "qtmrpkiDevice", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.3.1": { "d": "qtmrpkiDriverLicense", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.2": { "d": "qtmrpkiIndustryAuthority", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.3": { "d": "qtmrpkiMarineLicense", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.4": { "d": "qtmrpkiAdultProofOfAge", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.3.5": { "d": "qtmrpkiSam", "c": "Queensland Transport PKI device", "w": false }, +"1.2.36.1.3.1.3.2.4": { "d": "qtmrpkiAuthorisedParty", "c": "Queensland Transport PKI", "w": false }, +"1.2.36.1.3.1.3.2.4.1": { "d": "qtmrpkiTransportInspector", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.2": { "d": "qtmrpkiPoliceOfficer", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.3": { "d": "qtmrpkiSystem", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.4": { "d": "qtmrpkiLiquorLicensingInspector", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.3.1.3.2.4.5": { "d": "qtmrpkiMarineEnforcementOfficer", "c": "Queensland Transport PKI authorised party", "w": false }, +"1.2.36.1.333.1": { "d": "australianBusinessNumber", "c": "Australian Government corporate taxpayer ID", "w": false }, +"1.2.36.68980861.1.1.2": { "d": "signetPersonal", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.3": { "d": "signetBusiness", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.4": { "d": "signetLegal", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.10": { "d": "signetPilot", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.11": { "d": "signetIntraNet", "c": "Signet CA", "w": false }, +"1.2.36.68980861.1.1.20": { "d": "signetPolicy", "c": "Signet CA", "w": false }, +"1.2.36.75878867.1.100.1.1": { "d": "certificatesAustraliaPolicy", "c": "Certificates Australia CA", "w": false }, +"1.2.392.200011.61.1.1.1": { "d": "mitsubishiSecurityAlgorithm", "c": "Mitsubishi security algorithm", "w": false }, +"1.2.392.200011.61.1.1.1.1": { "d": "misty1-cbc", "c": "Mitsubishi security algorithm", "w": false }, +"1.2.410.200004.1": { "d": "kisaAlgorithm", "c": "KISA algorithm", "w": false }, +"1.2.410.200004.1.1": { "d": "kcdsa", "c": "Korean DSA", "w": false }, +"1.2.410.200004.1.2": { "d": "has160", "c": "Korean hash algorithm", "w": false }, +"1.2.410.200004.1.3": { "d": "seedECB", "c": "Korean SEED algorithm, ECB mode", "w": false }, +"1.2.410.200004.1.4": { "d": "seedCBC", "c": "Korean SEED algorithm, CBC mode", "w": false }, +"1.2.410.200004.1.5": { "d": "seedOFB", "c": "Korean SEED algorithm, OFB mode", "w": false }, +"1.2.410.200004.1.6": { "d": "seedCFB", "c": "Korean SEED algorithm, CFB mode", "w": false }, +"1.2.410.200004.1.7": { "d": "seedMAC", "c": "Korean SEED algorithm, MAC mode", "w": false }, +"1.2.410.200004.1.8": { "d": "kcdsaWithHAS160", "c": "Korean signature algorithm", "w": false }, +"1.2.410.200004.1.9": { "d": "kcdsaWithSHA1", "c": "Korean signature algorithm", "w": false }, +"1.2.410.200004.1.10": { "d": "pbeWithHAS160AndSEED-ECB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.11": { "d": "pbeWithHAS160AndSEED-CBC", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.12": { "d": "pbeWithHAS160AndSEED-CFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.13": { "d": "pbeWithHAS160AndSEED-OFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.14": { "d": "pbeWithSHA1AndSEED-ECB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.15": { "d": "pbeWithSHA1AndSEED-CBC", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.16": { "d": "pbeWithSHA1AndSEED-CFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.17": { "d": "pbeWithSHA1AndSEED-OFB", "c": "Korean SEED algorithm, PBE key derivation", "w": false }, +"1.2.410.200004.1.20": { "d": "rsaWithHAS160", "c": "Korean signature algorithm", "w": false }, +"1.2.410.200004.1.21": { "d": "kcdsa1", "c": "Korean DSA", "w": false }, +"1.2.410.200004.2": { "d": "npkiCP", "c": "KISA NPKI certificate policies", "w": false }, +"1.2.410.200004.2.1": { "d": "npkiSignaturePolicy", "c": "KISA NPKI certificate policies", "w": false }, +"1.2.410.200004.3": { "d": "npkiKP", "c": "KISA NPKI key usage", "w": false }, +"1.2.410.200004.4": { "d": "npkiAT", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.5": { "d": "npkiLCA", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.5.1": { "d": "npkiSignKorea", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.5.2": { "d": "npkiSignGate", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.5.3": { "d": "npkiNcaSign", "c": "KISA NPKI licensed CA", "w": false }, +"1.2.410.200004.6": { "d": "npkiON", "c": "KISA NPKI otherName", "w": false }, +"1.2.410.200004.7": { "d": "npkiAPP", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.7.1": { "d": "npkiSMIME", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.7.1.1": { "d": "npkiSMIMEAlgo", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.7.1.1.1": { "d": "npkiCmsSEEDWrap", "c": "KISA NPKI application", "w": false }, +"1.2.410.200004.10": { "d": "npki", "c": "KISA NPKI", "w": false }, +"1.2.410.200004.10.1": { "d": "npkiAttribute", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1": { "d": "npkiIdentifyData", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.1": { "d": "npkiVID", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.2": { "d": "npkiEncryptedVID", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.3": { "d": "npkiRandomNum", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200004.10.1.1.4": { "d": "npkiVID", "c": "KISA NPKI attribute", "w": false }, +"1.2.410.200046.1.1": { "d": "aria1AlgorithmModes", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.1": { "d": "aria128-ecb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.2": { "d": "aria128-cbc", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.3": { "d": "aria128-cfb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.4": { "d": "aria128-ofb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.5": { "d": "aria128-ctr", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.6": { "d": "aria192-ecb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.7": { "d": "aria192-cbc", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.8": { "d": "aria192-cfb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.9": { "d": "aria192-ofb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.10": { "d": "aria192-ctr", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.11": { "d": "aria256-ecb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.12": { "d": "aria256-cbc", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.13": { "d": "aria256-cfb", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.21": { "d": "aria128-cmac", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.22": { "d": "aria192-cmac", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.23": { "d": "aria256-cmac", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.31": { "d": "aria128-ocb2", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.32": { "d": "aria192-ocb2", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.33": { "d": "aria256-ocb2", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.34": { "d": "aria128-gcm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.35": { "d": "aria192-gcm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.36": { "d": "aria256-gcm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.37": { "d": "aria128-ccm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.38": { "d": "aria192-ccm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.39": { "d": "aria256-ccm", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.40": { "d": "aria128-keywrap", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.41": { "d": "aria192-keywrap", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.42": { "d": "aria256-keywrap", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.43": { "d": "aria128-keywrapWithPad", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.44": { "d": "aria192-keywrapWithPad", "c": "ARIA algorithm modes", "w": false }, +"1.2.410.200046.1.1.45": { "d": "aria256-keywrapWithPad", "c": "ARIA algorithm modes", "w": false }, +"1.2.643.2.2.3": { "d": "gostSignature", "c": "GOST R 34.10-2001 + GOST R 34.11-94 signature", "w": false }, +"1.2.643.2.2.4": { "d": "gost94Signature", "c": "GOST R 34.10-94 + GOST R 34.11-94 signature. Obsoleted by GOST R 34.10-2001", "w": true }, +"1.2.643.2.2.19": { "d": "gostPublicKey", "c": "GOST R 34.10-2001 (ECC) public key", "w": false }, +"1.2.643.2.2.20": { "d": "gost94PublicKey", "c": "GOST R 34.10-94 public key. Obsoleted by GOST R 34.10-2001", "w": true }, +"1.2.643.2.2.21": { "d": "gostCipher", "c": "GOST 28147-89 (symmetric key block cipher)", "w": false }, +"1.2.643.2.2.31.0": { "d": "testCipherParams", "c": "Test params for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.1": { "d": "cryptoProCipherA", "c": "CryptoPro params A for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.2": { "d": "cryptoProCipherB", "c": "CryptoPro params B for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.3": { "d": "cryptoProCipherC", "c": "CryptoPro params C for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.4": { "d": "cryptoProCipherD", "c": "CryptoPro params D for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.5": { "d": "oscar11Cipher", "c": "Oscar-1.1 params for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.6": { "d": "oscar10Cipher", "c": "Oscar-1.0 params for GOST 28147-89", "w": false }, +"1.2.643.2.2.31.7": { "d": "ric1Cipher", "c": "RIC-1 params for GOST 28147-89", "w": false }, +"1.2.643.2.2.9": { "d": "gostDigest", "c": "GOST R 34.11-94 digest", "w": false }, +"1.2.643.2.2.30.0": { "d": "testDigestParams", "c": "Test params for GOST R 34.11-94", "w": false }, +"1.2.643.2.2.30.1": { "d": "cryptoProDigestA", "c": "CryptoPro digest params for GOST R 34.11-94", "w": false }, +"1.2.643.2.2.35.0": { "d": "testSignParams", "c": "Test elliptic curve for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.35.1": { "d": "cryptoProSignA", "c": "CryptoPro ell.curve A for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.35.2": { "d": "cryptoProSignB", "c": "CryptoPro ell.curve B for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.35.3": { "d": "cryptoProSignC", "c": "CryptoPro ell.curve C for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.36.0": { "d": "cryptoProSignXA", "c": "CryptoPro ell.curve XA for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.36.1": { "d": "cryptoProSignXB", "c": "CryptoPro ell.curve XB for GOST R 34.11-2001", "w": false }, +"1.2.643.2.2.14.0": { "d": "nullMeshing", "c": "Do not mesh state of GOST 28147-89 cipher", "w": false }, +"1.2.643.2.2.14.1": { "d": "cryptoProMeshing", "c": "CryptoPro meshing of state of GOST 28147-89 cipher", "w": false }, +"1.2.643.2.2.10": { "d": "hmacGost", "c": "HMAC with GOST R 34.11-94", "w": false }, +"1.2.643.2.2.13.0": { "d": "gostWrap", "c": "Wrap key using GOST 28147-89 key", "w": false }, +"1.2.643.2.2.13.1": { "d": "cryptoProWrap", "c": "Wrap key using diversified GOST 28147-89 key", "w": false }, +"1.2.643.2.2.96": { "d": "cryptoProECDHWrap", "c": "Wrap key using ECC DH on GOST R 34.10-2001 keys (VKO)", "w": false }, +"1.2.752.34.1": { "d": "seis-cp", "c": "SEIS Project", "w": false }, +"1.2.752.34.1.1": { "d": "SEIS high-assurance policyIdentifier", "c": "SEIS Project certificate policies", "w": false }, +"1.2.752.34.1.2": { "d": "SEIS GAK policyIdentifier", "c": "SEIS Project certificate policies", "w": false }, +"1.2.752.34.2": { "d": "SEIS pe", "c": "SEIS Project", "w": false }, +"1.2.752.34.3": { "d": "SEIS at", "c": "SEIS Project", "w": false }, +"1.2.752.34.3.1": { "d": "SEIS at-personalIdentifier", "c": "SEIS Project attribute", "w": false }, +"1.2.840.10040.1": { "d": "module", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.1.1": { "d": "x9f1-cert-mgmt", "c": "ANSI X9.57 module", "w": false }, +"1.2.840.10040.2": { "d": "holdinstruction", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.2.1": { "d": "holdinstruction-none", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.2.2": { "d": "callissuer", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.2.3": { "d": "reject", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.2.4": { "d": "pickupToken", "c": "ANSI X9.57 hold instruction", "w": false }, +"1.2.840.10040.3": { "d": "attribute", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.3.1": { "d": "countersignature", "c": "ANSI X9.57 attribute", "w": false }, +"1.2.840.10040.3.2": { "d": "attribute-cert", "c": "ANSI X9.57 attribute", "w": false }, +"1.2.840.10040.4": { "d": "algorithm", "c": "ANSI X9.57", "w": false }, +"1.2.840.10040.4.1": { "d": "dsa", "c": "ANSI X9.57 algorithm", "w": false }, +"1.2.840.10040.4.2": { "d": "dsa-match", "c": "ANSI X9.57 algorithm", "w": false }, +"1.2.840.10040.4.3": { "d": "dsaWithSha1", "c": "ANSI X9.57 algorithm", "w": false }, +"1.2.840.10045.1": { "d": "fieldType", "c": "ANSI X9.62. This OID is also assigned as ecdsa-with-SHA1", "w": false }, +"1.2.840.10045.1.1": { "d": "prime-field", "c": "ANSI X9.62 field type", "w": false }, +"1.2.840.10045.1.2": { "d": "characteristic-two-field", "c": "ANSI X9.62 field type", "w": false }, +"1.2.840.10045.1.2.3": { "d": "characteristic-two-basis", "c": "ANSI X9.62 field type", "w": false }, +"1.2.840.10045.1.2.3.1": { "d": "onBasis", "c": "ANSI X9.62 field basis", "w": false }, +"1.2.840.10045.1.2.3.2": { "d": "tpBasis", "c": "ANSI X9.62 field basis", "w": false }, +"1.2.840.10045.1.2.3.3": { "d": "ppBasis", "c": "ANSI X9.62 field basis", "w": false }, +"1.2.840.10045.2": { "d": "publicKeyType", "c": "ANSI X9.62", "w": false }, +"1.2.840.10045.2.1": { "d": "ecPublicKey", "c": "ANSI X9.62 public key type", "w": false }, +"1.2.840.10045.3.0.1": { "d": "c2pnb163v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.2": { "d": "c2pnb163v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.3": { "d": "c2pnb163v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.5": { "d": "c2tnb191v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.6": { "d": "c2tnb191v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.7": { "d": "c2tnb191v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.10": { "d": "c2pnb208w1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.11": { "d": "c2tnb239v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.12": { "d": "c2tnb239v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.13": { "d": "c2tnb239v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.16": { "d": "c2pnb272w1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.18": { "d": "c2tnb359v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.19": { "d": "c2pnb368w1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.0.20": { "d": "c2tnb431r1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.1": { "d": "prime192v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.2": { "d": "prime192v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.3": { "d": "prime192v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.4": { "d": "prime239v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.5": { "d": "prime239v2", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.6": { "d": "prime239v3", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.3.1.7": { "d": "prime256v1", "c": "ANSI X9.62 named elliptic curve", "w": false }, +"1.2.840.10045.4.1": { "d": "ecdsaWithSHA1", "c": "ANSI X9.62 ECDSA algorithm with SHA1", "w": false }, +"1.2.840.10045.4.2": { "d": "ecdsaWithRecommended", "c": "ANSI X9.62 ECDSA algorithm with Recommended", "w": false }, +"1.2.840.10045.4.3": { "d": "ecdsaWithSpecified", "c": "ANSI X9.62 ECDSA algorithm with Specified", "w": false }, +"1.2.840.10045.4.3.1": { "d": "ecdsaWithSHA224", "c": "ANSI X9.62 ECDSA algorithm with SHA224", "w": false }, +"1.2.840.10045.4.3.2": { "d": "ecdsaWithSHA256", "c": "ANSI X9.62 ECDSA algorithm with SHA256", "w": false }, +"1.2.840.10045.4.3.3": { "d": "ecdsaWithSHA384", "c": "ANSI X9.62 ECDSA algorithm with SHA384", "w": false }, +"1.2.840.10045.4.3.4": { "d": "ecdsaWithSHA512", "c": "ANSI X9.62 ECDSA algorithm with SHA512", "w": false }, +"1.2.840.10046.1": { "d": "fieldType", "c": "ANSI X9.42", "w": false }, +"1.2.840.10046.1.1": { "d": "gf-prime", "c": "ANSI X9.42 field type", "w": false }, +"1.2.840.10046.2": { "d": "numberType", "c": "ANSI X9.42", "w": false }, +"1.2.840.10046.2.1": { "d": "dhPublicKey", "c": "ANSI X9.42 number type", "w": false }, +"1.2.840.10046.3": { "d": "scheme", "c": "ANSI X9.42", "w": false }, +"1.2.840.10046.3.1": { "d": "dhStatic", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.2": { "d": "dhEphem", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.3": { "d": "dhHybrid1", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.4": { "d": "dhHybrid2", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.5": { "d": "mqv2", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10046.3.6": { "d": "mqv1", "c": "ANSI X9.42 scheme", "w": false }, +"1.2.840.10065.2.2": { "d": "?", "c": "ASTM 31.20", "w": false }, +"1.2.840.10065.2.3": { "d": "healthcareLicense", "c": "ASTM 31.20", "w": false }, +"1.2.840.10065.2.3.1.1": { "d": "license?", "c": "ASTM 31.20 healthcare license type", "w": false }, +"1.2.840.113533.7": { "d": "nsn", "c": "", "w": false }, +"1.2.840.113533.7.65": { "d": "nsn-ce", "c": "", "w": false }, +"1.2.840.113533.7.65.0": { "d": "entrustVersInfo", "c": "Nortel Secure Networks ce", "w": false }, +"1.2.840.113533.7.66": { "d": "nsn-alg", "c": "", "w": false }, +"1.2.840.113533.7.66.3": { "d": "cast3CBC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.10": { "d": "cast5CBC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.11": { "d": "cast5MAC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.12": { "d": "pbeWithMD5AndCAST5-CBC", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.66.13": { "d": "passwordBasedMac", "c": "Nortel Secure Networks alg", "w": false }, +"1.2.840.113533.7.67": { "d": "nsn-oc", "c": "", "w": false }, +"1.2.840.113533.7.67.0": { "d": "entrustUser", "c": "Nortel Secure Networks oc", "w": false }, +"1.2.840.113533.7.68": { "d": "nsn-at", "c": "", "w": false }, +"1.2.840.113533.7.68.0": { "d": "entrustCAInfo", "c": "Nortel Secure Networks at", "w": false }, +"1.2.840.113533.7.68.10": { "d": "attributeCertificate", "c": "Nortel Secure Networks at", "w": false }, +"1.2.840.113549.1.1": { "d": "pkcs-1", "c": "", "w": false }, +"1.2.840.113549.1.1.1": { "d": "rsaEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.2": { "d": "md2WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.3": { "d": "md4WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.4": { "d": "md5WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.5": { "d": "sha1WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.7": { "d": "rsaOAEP", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.8": { "d": "pkcs1-MGF", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.9": { "d": "rsaOAEP-pSpecified", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.10": { "d": "rsaPSS", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.11": { "d": "sha256WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.12": { "d": "sha384WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.13": { "d": "sha512WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.14": { "d": "sha224WithRSAEncryption", "c": "PKCS #1", "w": false }, +"1.2.840.113549.1.1.6": { "d": "rsaOAEPEncryptionSET", "c": "PKCS #1. This OID may also be assigned as ripemd160WithRSAEncryption", "w": false }, +"1.2.840.113549.1.2": { "d": "bsafeRsaEncr", "c": "Obsolete BSAFE OID", "w": true }, +"1.2.840.113549.1.3": { "d": "pkcs-3", "c": "", "w": false }, +"1.2.840.113549.1.3.1": { "d": "dhKeyAgreement", "c": "PKCS #3", "w": false }, +"1.2.840.113549.1.5": { "d": "pkcs-5", "c": "", "w": false }, +"1.2.840.113549.1.5.1": { "d": "pbeWithMD2AndDES-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.3": { "d": "pbeWithMD5AndDES-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.4": { "d": "pbeWithMD2AndRC2-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.6": { "d": "pbeWithMD5AndRC2-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.9": { "d": "pbeWithMD5AndXOR", "c": "PKCS #5, used in BSAFE only", "w": true }, +"1.2.840.113549.1.5.10": { "d": "pbeWithSHAAndDES-CBC", "c": "PKCS #5", "w": false }, +"1.2.840.113549.1.5.12": { "d": "pkcs5PBKDF2", "c": "PKCS #5 v2.0", "w": false }, +"1.2.840.113549.1.5.13": { "d": "pkcs5PBES2", "c": "PKCS #5 v2.0", "w": false }, +"1.2.840.113549.1.5.14": { "d": "pkcs5PBMAC1", "c": "PKCS #5 v2.0", "w": false }, +"1.2.840.113549.1.7": { "d": "pkcs-7", "c": "", "w": false }, +"1.2.840.113549.1.7.1": { "d": "data", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.2": { "d": "signedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.3": { "d": "envelopedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.4": { "d": "signedAndEnvelopedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.5": { "d": "digestedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.6": { "d": "encryptedData", "c": "PKCS #7", "w": false }, +"1.2.840.113549.1.7.7": { "d": "dataWithAttributes", "c": "PKCS #7 experimental", "w": true }, +"1.2.840.113549.1.7.8": { "d": "encryptedPrivateKeyInfo", "c": "PKCS #7 experimental", "w": true }, +"1.2.840.113549.1.9": { "d": "pkcs-9", "c": "", "w": false }, +"1.2.840.113549.1.9.1": { "d": "emailAddress", "c": "PKCS #9. Deprecated, use an altName extension instead", "w": false }, +"1.2.840.113549.1.9.2": { "d": "unstructuredName", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.3": { "d": "contentType", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.4": { "d": "messageDigest", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.5": { "d": "signingTime", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.6": { "d": "countersignature", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.7": { "d": "challengePassword", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.8": { "d": "unstructuredAddress", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.9": { "d": "extendedCertificateAttributes", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.10": { "d": "issuerAndSerialNumber", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.11": { "d": "passwordCheck", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.12": { "d": "publicKey", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.13": { "d": "signingDescription", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.14": { "d": "extensionRequest", "c": "PKCS #9 via CRMF", "w": false }, +"1.2.840.113549.1.9.15": { "d": "sMIMECapabilities", "c": "PKCS #9. This OID was formerly assigned as symmetricCapabilities, then reassigned as SMIMECapabilities, then renamed to the current name", "w": false }, +"1.2.840.113549.1.9.15.1": { "d": "preferSignedData", "c": "sMIMECapabilities", "w": false }, +"1.2.840.113549.1.9.15.2": { "d": "canNotDecryptAny", "c": "sMIMECapabilities", "w": false }, +"1.2.840.113549.1.9.15.3": { "d": "receiptRequest", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 1) instead", "w": true }, +"1.2.840.113549.1.9.15.4": { "d": "receipt", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 1 1) instead", "w": true }, +"1.2.840.113549.1.9.15.5": { "d": "contentHints", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 4) instead", "w": true }, +"1.2.840.113549.1.9.15.6": { "d": "mlExpansionHistory", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 3) instead", "w": true }, +"1.2.840.113549.1.9.16": { "d": "id-sMIME", "c": "PKCS #9", "w": false }, +"1.2.840.113549.1.9.16.0": { "d": "id-mod", "c": "id-sMIME", "w": false }, +"1.2.840.113549.1.9.16.0.1": { "d": "id-mod-cms", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.2": { "d": "id-mod-ess", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.3": { "d": "id-mod-oid", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.4": { "d": "id-mod-msg-v3", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.5": { "d": "id-mod-ets-eSignature-88", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.6": { "d": "id-mod-ets-eSignature-97", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.7": { "d": "id-mod-ets-eSigPolicy-88", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.0.8": { "d": "id-mod-ets-eSigPolicy-88", "c": "S/MIME Modules", "w": false }, +"1.2.840.113549.1.9.16.1": { "d": "contentType", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.1.1": { "d": "receipt", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.2": { "d": "authData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.3": { "d": "publishCert", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.4": { "d": "tSTInfo", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.5": { "d": "tDTInfo", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.6": { "d": "contentInfo", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.7": { "d": "dVCSRequestData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.8": { "d": "dVCSResponseData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.9": { "d": "compressedData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.10": { "d": "scvpCertValRequest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.11": { "d": "scvpCertValResponse", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.12": { "d": "scvpValPolRequest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.13": { "d": "scvpValPolResponse", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.14": { "d": "attrCertEncAttrs", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.15": { "d": "tSReq", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.16": { "d": "firmwarePackage", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.17": { "d": "firmwareLoadReceipt", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.18": { "d": "firmwareLoadError", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.19": { "d": "contentCollection", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.20": { "d": "contentWithAttrs", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.21": { "d": "encKeyWithID", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.22": { "d": "encPEPSI", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.23": { "d": "authEnvelopedData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.24": { "d": "routeOriginAttest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.25": { "d": "symmetricKeyPackage", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.26": { "d": "rpkiManifest", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.27": { "d": "asciiTextWithCRLF", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.28": { "d": "xml", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.29": { "d": "pdf", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.30": { "d": "postscript", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.31": { "d": "timestampedData", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.32": { "d": "asAdjacencyAttest", "c": "S/MIME Content Types", "w": true }, +"1.2.840.113549.1.9.16.1.33": { "d": "rpkiTrustAnchor", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.1.34": { "d": "trustAnchorList", "c": "S/MIME Content Types", "w": false }, +"1.2.840.113549.1.9.16.2": { "d": "authenticatedAttributes", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.2.1": { "d": "receiptRequest", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.2": { "d": "securityLabel", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.3": { "d": "mlExpandHistory", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.4": { "d": "contentHint", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.5": { "d": "msgSigDigest", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.6": { "d": "encapContentType", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.7": { "d": "contentIdentifier", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.8": { "d": "macValue", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.9": { "d": "equivalentLabels", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.10": { "d": "contentReference", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.11": { "d": "encrypKeyPref", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.12": { "d": "signingCertificate", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.13": { "d": "smimeEncryptCerts", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.14": { "d": "timeStampToken", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.15": { "d": "sigPolicyId", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.16": { "d": "commitmentType", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.17": { "d": "signerLocation", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.18": { "d": "signerAttr", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.19": { "d": "otherSigCert", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.20": { "d": "contentTimestamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.21": { "d": "certificateRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.22": { "d": "revocationRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.23": { "d": "certValues", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.24": { "d": "revocationValues", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.25": { "d": "escTimeStamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.26": { "d": "certCRLTimestamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.27": { "d": "archiveTimeStamp", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.28": { "d": "signatureType", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.29": { "d": "dvcsDvc", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.30": { "d": "cekReference", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.31": { "d": "maxCEKDecrypts", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.32": { "d": "kekDerivationAlg", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.33": { "d": "intendedRecipients", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.34": { "d": "cmcUnsignedData", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.35": { "d": "fwPackageID", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.36": { "d": "fwTargetHardwareIDs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.37": { "d": "fwDecryptKeyID", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.38": { "d": "fwImplCryptAlgs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.39": { "d": "fwWrappedFirmwareKey", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.40": { "d": "fwCommunityIdentifiers", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.41": { "d": "fwPkgMessageDigest", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.42": { "d": "fwPackageInfo", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.43": { "d": "fwImplCompressAlgs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.44": { "d": "etsAttrCertificateRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.45": { "d": "etsAttrRevocationRefs", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.46": { "d": "binarySigningTime", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.47": { "d": "signingCertificateV2", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.48": { "d": "etsArchiveTimeStampV2", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.49": { "d": "erInternal", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.50": { "d": "erExternal", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.2.51": { "d": "multipleSignatures", "c": "S/MIME Authenticated Attributes", "w": false }, +"1.2.840.113549.1.9.16.3.1": { "d": "esDHwith3DES", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.2": { "d": "esDHwithRC2", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.3": { "d": "3desWrap", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.4": { "d": "rc2Wrap", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.5": { "d": "esDH", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.6": { "d": "cms3DESwrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.7": { "d": "cmsRC2wrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.8": { "d": "zlib", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.9": { "d": "pwriKEK", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.10": { "d": "ssDH", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.11": { "d": "hmacWith3DESwrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.12": { "d": "hmacWithAESwrap", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.13": { "d": "md5XorExperiment", "c": "S/MIME Algorithms. Experimental", "w": true }, +"1.2.840.113549.1.9.16.3.14": { "d": "rsaKEM", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.15": { "d": "authEnc128", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.3.16": { "d": "authEnc256", "c": "S/MIME Algorithms", "w": false }, +"1.2.840.113549.1.9.16.4.1": { "d": "certDist-ldap", "c": "S/MIME Certificate Distribution", "w": false }, +"1.2.840.113549.1.9.16.5.1": { "d": "sigPolicyQualifier-spuri x", "c": "S/MIME Signature Policy Qualifiers", "w": false }, +"1.2.840.113549.1.9.16.5.2": { "d": "sigPolicyQualifier-spUserNotice", "c": "S/MIME Signature Policy Qualifiers", "w": false }, +"1.2.840.113549.1.9.16.6.1": { "d": "proofOfOrigin", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.2": { "d": "proofOfReceipt", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.3": { "d": "proofOfDelivery", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.4": { "d": "proofOfSender", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.5": { "d": "proofOfApproval", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.6.6": { "d": "proofOfCreation", "c": "S/MIME Commitment Type Identifiers", "w": false }, +"1.2.840.113549.1.9.16.8.1": { "d": "glUseKEK", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.2": { "d": "glDelete", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.3": { "d": "glAddMember", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.4": { "d": "glDeleteMember", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.5": { "d": "glRekey", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.6": { "d": "glAddOwner", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.7": { "d": "glRemoveOwner", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.8": { "d": "glkCompromise", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.9": { "d": "glkRefresh", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.10": { "d": "glFailInfo", "c": "S/MIME Symmetric Key Distribution Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.8.11": { "d": "glaQueryRequest", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.12": { "d": "glaQueryResponse", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.13": { "d": "glProvideCert", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.14": { "d": "glUpdateCert", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.8.15": { "d": "glKey", "c": "S/MIME Symmetric Key Distribution Attributes", "w": false }, +"1.2.840.113549.1.9.16.9": { "d": "signatureTypeIdentifier", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.9.1": { "d": "originatorSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.9.2": { "d": "domainSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.9.3": { "d": "additionalAttributesSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.9.4": { "d": "reviewSig", "c": "S/MIME Signature Type Identifier", "w": false }, +"1.2.840.113549.1.9.16.11": { "d": "capabilities", "c": "S/MIME", "w": false }, +"1.2.840.113549.1.9.16.11.1": { "d": "preferBinaryInside", "c": "S/MIME Capability", "w": false }, +"1.2.840.113549.1.9.20": { "d": "friendlyName (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.21": { "d": "localKeyID (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.22": { "d": "certTypes (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.22.1": { "d": "x509Certificate (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.22.2": { "d": "sdsiCertificate (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.23": { "d": "crlTypes (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.23.1": { "d": "x509Crl (for PKCS #12)", "c": "PKCS #9 via PKCS #12", "w": false }, +"1.2.840.113549.1.9.24": { "d": "pkcs9objectClass", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.9.25": { "d": "pkcs9attributes", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.9.25.1": { "d": "pkcs15Token", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.2": { "d": "encryptedPrivateKeyInfo", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.3": { "d": "randomNonce", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.4": { "d": "sequenceNumber", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.25.5": { "d": "pkcs7PDU", "c": "PKCS #9/RFC 2985 attribute", "w": false }, +"1.2.840.113549.1.9.26": { "d": "pkcs9syntax", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.9.27": { "d": "pkcs9matchingRules", "c": "PKCS #9/RFC 2985", "w": false }, +"1.2.840.113549.1.12": { "d": "pkcs-12", "c": "", "w": false }, +"1.2.840.113549.1.12.1": { "d": "pkcs-12-PbeIds", "c": "This OID was formerly assigned as PKCS #12 modeID", "w": false }, +"1.2.840.113549.1.12.1.1": { "d": "pbeWithSHAAnd128BitRC4", "c": "PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OfflineTransportMode", "w": false }, +"1.2.840.113549.1.12.1.2": { "d": "pbeWithSHAAnd40BitRC4", "c": "PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OnlineTransportMode", "w": false }, +"1.2.840.113549.1.12.1.3": { "d": "pbeWithSHAAnd3-KeyTripleDES-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.1.4": { "d": "pbeWithSHAAnd2-KeyTripleDES-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.1.5": { "d": "pbeWithSHAAnd128BitRC2-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.1.6": { "d": "pbeWithSHAAnd40BitRC2-CBC", "c": "PKCS #12 PbeIds", "w": false }, +"1.2.840.113549.1.12.2": { "d": "pkcs-12-ESPVKID", "c": "Deprecated", "w": true }, +"1.2.840.113549.1.12.2.1": { "d": "pkcs-12-PKCS8KeyShrouding", "c": "PKCS #12 ESPVKID. Deprecated, use (1 2 840 113549 1 12 3 5) instead", "w": true }, +"1.2.840.113549.1.12.3": { "d": "pkcs-12-BagIds", "c": "", "w": false }, +"1.2.840.113549.1.12.3.1": { "d": "pkcs-12-keyBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.2": { "d": "pkcs-12-certAndCRLBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.3": { "d": "pkcs-12-secretBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.4": { "d": "pkcs-12-safeContentsId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.3.5": { "d": "pkcs-12-pkcs-8ShroudedKeyBagId", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.4": { "d": "pkcs-12-CertBagID", "c": "Deprecated", "w": true }, +"1.2.840.113549.1.12.4.1": { "d": "pkcs-12-X509CertCRLBagID", "c": "PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-X509CertCRLBag", "w": false }, +"1.2.840.113549.1.12.4.2": { "d": "pkcs-12-SDSICertBagID", "c": "PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-SDSICertBag", "w": false }, +"1.2.840.113549.1.12.5": { "d": "pkcs-12-OID", "c": "", "w": true }, +"1.2.840.113549.1.12.5.1": { "d": "pkcs-12-PBEID", "c": "PKCS #12 OID. Deprecated, use the partially compatible (1 2 840 113549 1 12 1) OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.1.1": { "d": "pkcs-12-PBEWithSha1And128BitRC4", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 1) instead", "w": true }, +"1.2.840.113549.1.12.5.1.2": { "d": "pkcs-12-PBEWithSha1And40BitRC4", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 2) instead", "w": true }, +"1.2.840.113549.1.12.5.1.3": { "d": "pkcs-12-PBEWithSha1AndTripleDESCBC", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 3) or (1 2 840 113549 1 12 1 4) instead", "w": true }, +"1.2.840.113549.1.12.5.1.4": { "d": "pkcs-12-PBEWithSha1And128BitRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 5) instead", "w": true }, +"1.2.840.113549.1.12.5.1.5": { "d": "pkcs-12-PBEWithSha1And40BitRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 6) instead", "w": true }, +"1.2.840.113549.1.12.5.1.6": { "d": "pkcs-12-PBEWithSha1AndRC4", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 1) or (1 2 840 113549 1 12 1 2) instead", "w": true }, +"1.2.840.113549.1.12.5.1.7": { "d": "pkcs-12-PBEWithSha1AndRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 5) or (1 2 840 113549 1 12 1 6) instead", "w": true }, +"1.2.840.113549.1.12.5.2": { "d": "pkcs-12-EnvelopingID", "c": "PKCS #12 OID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": false }, +"1.2.840.113549.1.12.5.2.1": { "d": "pkcs-12-RSAEncryptionWith128BitRC4", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.2.2": { "d": "pkcs-12-RSAEncryptionWith40BitRC4", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.2.3": { "d": "pkcs-12-RSAEncryptionWithTripleDES", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.3": { "d": "pkcs-12-SignatureID", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.3.1": { "d": "pkcs-12-RSASignatureWithSHA1Digest", "c": "PKCS #12 OID SignatureID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.10": { "d": "pkcs-12Version1", "c": "", "w": false }, +"1.2.840.113549.1.12.10.1": { "d": "pkcs-12BadIds", "c": "", "w": false }, +"1.2.840.113549.1.12.10.1.1": { "d": "pkcs-12-keyBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.2": { "d": "pkcs-12-pkcs-8ShroudedKeyBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.3": { "d": "pkcs-12-certBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.4": { "d": "pkcs-12-crlBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.5": { "d": "pkcs-12-secretBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.12.10.1.6": { "d": "pkcs-12-safeContentsBag", "c": "PKCS #12 BagIds", "w": false }, +"1.2.840.113549.1.15.1": { "d": "pkcs15modules", "c": "PKCS #15", "w": false }, +"1.2.840.113549.1.15.2": { "d": "pkcs15attributes", "c": "PKCS #15", "w": false }, +"1.2.840.113549.1.15.3": { "d": "pkcs15contentType", "c": "PKCS #15", "w": false }, +"1.2.840.113549.1.15.3.1": { "d": "pkcs15content", "c": "PKCS #15 content type", "w": false }, +"1.2.840.113549.2": { "d": "digestAlgorithm", "c": "", "w": false }, +"1.2.840.113549.2.2": { "d": "md2", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.4": { "d": "md4", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.5": { "d": "md5", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.7": { "d": "hmacWithSHA1", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.8": { "d": "hmacWithSHA224", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.9": { "d": "hmacWithSHA256", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.10": { "d": "hmacWithSHA384", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.2.11": { "d": "hmacWithSHA512", "c": "RSADSI digestAlgorithm", "w": false }, +"1.2.840.113549.3": { "d": "encryptionAlgorithm", "c": "", "w": false }, +"1.2.840.113549.3.2": { "d": "rc2CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.3": { "d": "rc2ECB", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.4": { "d": "rc4", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.5": { "d": "rc4WithMAC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.6": { "d": "desx-CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.7": { "d": "des-EDE3-CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.8": { "d": "rc5CBC", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.9": { "d": "rc5-CBCPad", "c": "RSADSI encryptionAlgorithm", "w": false }, +"1.2.840.113549.3.10": { "d": "desCDMF", "c": "RSADSI encryptionAlgorithm. Formerly called CDMFCBCPad", "w": false }, +"1.2.840.114021.1.6.1": { "d": "Identrus unknown policyIdentifier", "c": "Identrus", "w": false }, +"1.2.840.114021.4.1": { "d": "identrusOCSP", "c": "Identrus", "w": false }, +"1.2.840.113556.1.2.241": { "d": "deliveryMechanism", "c": "Microsoft Exchange Server - attribute", "w": false }, +"1.2.840.113556.1.3.0": { "d": "site-Addressing", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.13": { "d": "classSchema", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.14": { "d": "attributeSchema", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.17": { "d": "mailbox-Agent", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.22": { "d": "mailbox", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.23": { "d": "container", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.3.46": { "d": "mailRecipient", "c": "Microsoft Exchange Server - object class", "w": false }, +"1.2.840.113556.1.2.281": { "d": "ntSecurityDescriptor", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.145": { "d": "revision", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1327": { "d": "pKIDefaultKeySpec", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1328": { "d": "pKIKeyUsage", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1329": { "d": "pKIMaxIssuingDepth", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1330": { "d": "pKICriticalExtensions", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1331": { "d": "pKIExpirationPeriod", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1332": { "d": "pKIOverlapPeriod", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1333": { "d": "pKIExtendedKeyUsage", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1334": { "d": "pKIDefaultCSPs", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1335": { "d": "pKIEnrollmentAccess", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1429": { "d": "msPKI-RA-Signature", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1430": { "d": "msPKI-Enrollment-Flag", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1431": { "d": "msPKI-Private-Key-Flag", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1432": { "d": "msPKI-Certificate-Name-Flag", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1433": { "d": "msPKI-Minimal-Key-Size", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1434": { "d": "msPKI-Template-Schema-Version", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1435": { "d": "msPKI-Template-Minor-Revision", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1436": { "d": "msPKI-Cert-Template-OID", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1437": { "d": "msPKI-Supersede-Templates", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1438": { "d": "msPKI-RA-Policies", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1439": { "d": "msPKI-Certificate-Policy", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1674": { "d": "msPKI-Certificate-Application-Policy", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.1.4.1675": { "d": "msPKI-RA-Application-Policies", "c": "Microsoft Cert Template - attribute", "w": false }, +"1.2.840.113556.4.3": { "d": "microsoftExcel", "c": "Microsoft", "w": false }, +"1.2.840.113556.4.4": { "d": "titledWithOID", "c": "Microsoft", "w": false }, +"1.2.840.113556.4.5": { "d": "microsoftPowerPoint", "c": "Microsoft", "w": false }, +"1.2.840.113628.114.1.7": { "d": "adobePKCS7", "c": "Adobe", "w": false }, +"1.2.840.113635.100": { "d": "appleDataSecurity", "c": "Apple", "w": false }, +"1.2.840.113635.100.1": { "d": "appleTrustPolicy", "c": "Apple", "w": false }, +"1.2.840.113635.100.1.1": { "d": "appleISignTP", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.2": { "d": "appleX509Basic", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.3": { "d": "appleSSLPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.4": { "d": "appleLocalCertGenPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.5": { "d": "appleCSRGenPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.6": { "d": "appleCRLPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.7": { "d": "appleOCSPPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.8": { "d": "appleSMIMEPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.9": { "d": "appleEAPPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.10": { "d": "appleSWUpdateSigningPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.11": { "d": "appleIPSecPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.12": { "d": "appleIChatPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.13": { "d": "appleResourceSignPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.14": { "d": "applePKINITClientPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.15": { "d": "applePKINITServerPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.16": { "d": "appleCodeSigningPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.1.17": { "d": "applePackageSigningPolicy", "c": "Apple trust policy", "w": false }, +"1.2.840.113635.100.2": { "d": "appleSecurityAlgorithm", "c": "Apple", "w": false }, +"1.2.840.113635.100.2.1": { "d": "appleFEE", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.2": { "d": "appleASC", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.3": { "d": "appleFEE_MD5", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.4": { "d": "appleFEE_SHA1", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.5": { "d": "appleFEED", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.6": { "d": "appleFEEDEXP", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.2.7": { "d": "appleECDSA", "c": "Apple security algorithm", "w": false }, +"1.2.840.113635.100.3": { "d": "appleDotMacCertificate", "c": "Apple", "w": false }, +"1.2.840.113635.100.3.1": { "d": "appleDotMacCertificateRequest", "c": "Apple dotMac certificate", "w": false }, +"1.2.840.113635.100.3.2": { "d": "appleDotMacCertificateExtension", "c": "Apple dotMac certificate", "w": false }, +"1.2.840.113635.100.3.3": { "d": "appleDotMacCertificateRequestValues", "c": "Apple dotMac certificate", "w": false }, +"1.2.840.113635.100.4": { "d": "appleExtendedKeyUsage", "c": "Apple", "w": false }, +"1.2.840.113635.100.4.1": { "d": "appleCodeSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.1": { "d": "appleCodeSigningDevelopment", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.2": { "d": "appleSoftwareUpdateSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.3": { "d": "appleCodeSigningThirdParty", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.1.4": { "d": "appleResourceSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.2": { "d": "appleIChatSigning", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.3": { "d": "appleIChatEncryption", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.4": { "d": "appleSystemIdentity", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5": { "d": "appleCryptoEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.1": { "d": "appleCryptoProductionEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.2": { "d": "appleCryptoMaintenanceEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.3": { "d": "appleCryptoTestEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.5.4": { "d": "appleCryptoDevelopmentEnv", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6": { "d": "appleCryptoQoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.1": { "d": "appleCryptoTier0QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.2": { "d": "appleCryptoTier1QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.3": { "d": "appleCryptoTier2QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.4.6.4": { "d": "appleCryptoTier3QoS", "c": "Apple extended key usage", "w": false }, +"1.2.840.113635.100.5": { "d": "appleCertificatePolicies", "c": "Apple", "w": false }, +"1.2.840.113635.100.5.1": { "d": "appleCertificatePolicyID", "c": "Apple", "w": false }, +"1.2.840.113635.100.5.2": { "d": "appleDotMacCertificatePolicyID", "c": "Apple", "w": false }, +"1.2.840.113635.100.5.3": { "d": "appleADCCertificatePolicyID", "c": "Apple", "w": false }, +"1.2.840.113635.100.6": { "d": "appleCertificateExtensions", "c": "Apple", "w": false }, +"1.2.840.113635.100.6.1": { "d": "appleCertificateExtensionCodeSigning", "c": "Apple certificate extension", "w": false }, +"1.2.840.113635.100.6.1.1": { "d": "appleCertificateExtensionAppleSigning", "c": "Apple certificate extension", "w": false }, +"1.2.840.113635.100.6.1.2": { "d": "appleCertificateExtensionADCDeveloperSigning", "c": "Apple certificate extension", "w": false }, +"1.2.840.113635.100.6.1.3": { "d": "appleCertificateExtensionADCAppleSigning", "c": "Apple certificate extension", "w": false }, +"1.3.6.1.4.1.311.2.1.4": { "d": "spcIndirectDataContext", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.10": { "d": "spcAgencyInfo", "c": "Microsoft code signing. Also known as policyLink", "w": false }, +"1.3.6.1.4.1.311.2.1.11": { "d": "spcStatementType", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.12": { "d": "spcSpOpusInfo", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.14": { "d": "certReqExtensions", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.2.1.15": { "d": "spcPEImageData", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.18": { "d": "spcRawFileData", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.19": { "d": "spcStructuredStorageData", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.20": { "d": "spcJavaClassData (type 1)", "c": "Microsoft code signing. Formerly \"link extension\" aka \"glue extension\"", "w": false }, +"1.3.6.1.4.1.311.2.1.21": { "d": "individualCodeSigning", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.2.1.22": { "d": "commercialCodeSigning", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.2.1.25": { "d": "spcLink (type 2)", "c": "Microsoft code signing. Also known as \"glue extension\"", "w": false }, +"1.3.6.1.4.1.311.2.1.26": { "d": "spcMinimalCriteriaInfo", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.27": { "d": "spcFinancialCriteriaInfo", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.2.1.28": { "d": "spcLink (type 3)", "c": "Microsoft code signing. Also known as \"glue extension\"", "w": false }, +"1.3.6.1.4.1.311.3.2.1": { "d": "timestampRequest", "c": "Microsoft code signing", "w": false }, +"1.3.6.1.4.1.311.10.1": { "d": "certTrustList", "c": "Microsoft contentType", "w": false }, +"1.3.6.1.4.1.311.10.1.1": { "d": "sortedCtl", "c": "Microsoft contentType", "w": false }, +"1.3.6.1.4.1.311.10.2": { "d": "nextUpdateLocation", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.3.1": { "d": "certTrustListSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.2": { "d": "timeStampSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.3": { "d": "serverGatedCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.3.1": { "d": "serialized", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.3.4": { "d": "encryptedFileSystem", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.5": { "d": "whqlCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.6": { "d": "nt5Crypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.7": { "d": "oemWHQLCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.8": { "d": "embeddedNTCrypto", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.9": { "d": "rootListSigner", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.10": { "d": "qualifiedSubordination", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.11": { "d": "keyRecovery", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.12": { "d": "documentSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.13": { "d": "lifetimeSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.14": { "d": "mobileDeviceSoftware", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.15": { "d": "smartDisplay", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.16": { "d": "cspSignature", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.3.4.1": { "d": "efsRecovery", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.4.1": { "d": "yesnoTrustAttr", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.5.1": { "d": "drm", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.5.2": { "d": "drmIndividualization", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.6.1": { "d": "licenses", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.6.2": { "d": "licenseServer", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.10.7.1": { "d": "keyidRdn", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.8.1": { "d": "removeCertificate", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.9.1": { "d": "crossCertDistPoints", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.10.10.1": { "d": "cmcAddAttributes", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11": { "d": "certPropIdPrefix", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.4": { "d": "certMd5HashPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.20": { "d": "certKeyIdentifierPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.28": { "d": "certIssuerSerialNumberMd5HashPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.11.29": { "d": "certSubjectNameMd5HashPropId", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.10.12.1": { "d": "anyApplicationPolicy", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.1": { "d": "renewalCertificate", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.2.1": { "d": "enrolmentNameValuePair", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.2.2": { "d": "enrolmentCSP", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.13.2.3": { "d": "osVersion", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.16.4": { "d": "microsoftRecipientInfo", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.17.1": { "d": "pkcs12KeyProviderNameAttr", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.17.2": { "d": "localMachineKeyset", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.17.3": { "d": "pkcs12ExtendedAttributes", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.20.1": { "d": "autoEnrollCtlUsage", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.20.2": { "d": "enrollCerttypeExtension", "c": "Microsoft CAPICOM certificate template, V1", "w": false }, +"1.3.6.1.4.1.311.20.2.1": { "d": "enrollmentAgent", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.20.2.2": { "d": "smartcardLogon", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.20.2.3": { "d": "universalPrincipalName", "c": "Microsoft UPN", "w": false }, +"1.3.6.1.4.1.311.20.3": { "d": "certManifold", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.1": { "d": "cAKeyCertIndexPair", "c": "Microsoft attribute. Also known as certsrvCaVersion", "w": false }, +"1.3.6.1.4.1.311.21.5": { "d": "caExchange", "c": "Microsoft extended key usage", "w": true }, +"1.3.6.1.4.1.311.21.2": { "d": "certSrvPreviousCertHash", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.3": { "d": "crlVirtualBase", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.4": { "d": "crlNextPublish", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.6": { "d": "keyRecovery", "c": "Microsoft extended key usage", "w": true }, +"1.3.6.1.4.1.311.21.7": { "d": "certificateTemplate", "c": "Microsoft CAPICOM certificate template, V2", "w": false }, +"1.3.6.1.4.1.311.21.9": { "d": "rdnDummySigner", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.10": { "d": "applicationCertPolicies", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.11": { "d": "applicationPolicyMappings", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.12": { "d": "applicationPolicyConstraints", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.13": { "d": "archivedKey", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.21.14": { "d": "crlSelfCDP", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.15": { "d": "requireCertChainPolicy", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.16": { "d": "archivedKeyCertHash", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.17": { "d": "issuedCertHash", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.19": { "d": "dsEmailReplication", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.21.20": { "d": "requestClientInfo", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.21.21": { "d": "encryptedKeyHash", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.21.22": { "d": "certsrvCrossCaVersion", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.25.1": { "d": "ntdsReplication", "c": "Microsoft", "w": false }, +"1.3.6.1.4.1.311.31.1": { "d": "productUpdate", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.311.47.1.1": { "d": "systemHealth", "c": "Microsoft extended key usage", "w": false }, +"1.3.6.1.4.1.311.47.1.3": { "d": "systemHealthLoophole", "c": "Microsoft extended key usage", "w": false }, +"1.3.6.1.4.1.311.60.1.1": { "d": "rootProgramFlags", "c": "Microsoft policy attribute", "w": false }, +"1.3.6.1.4.1.311.61.1.1": { "d": "kernelModeCodeSigning", "c": "Microsoft enhanced key usage", "w": false }, +"1.3.6.1.4.1.311.60.2.1.1": { "d": "jurisdictionOfIncorporationL", "c": "Microsoft (???)", "w": false }, +"1.3.6.1.4.1.311.60.2.1.2": { "d": "jurisdictionOfIncorporationSP", "c": "Microsoft (???)", "w": false }, +"1.3.6.1.4.1.311.60.2.1.3": { "d": "jurisdictionOfIncorporationC", "c": "Microsoft (???)", "w": false }, +"1.3.6.1.4.1.311.88.2.1": { "d": "originalFilename", "c": "Microsoft attribute", "w": false }, +"1.3.6.1.4.1.188.7.1.1": { "d": "ascom", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.1": { "d": "ideaECB", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.2": { "d": "ideaCBC", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.3": { "d": "ideaCFB", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.188.7.1.1.4": { "d": "ideaOFB", "c": "Ascom Systech", "w": false }, +"1.3.6.1.4.1.2428.10.1.1": { "d": "UNINETT policyIdentifier", "c": "UNINETT PCA", "w": false }, +"1.3.6.1.4.1.2712.10": { "d": "ICE-TEL policyIdentifier", "c": "ICE-TEL CA", "w": false }, +"1.3.6.1.4.1.2786.1.1.1": { "d": "ICE-TEL Italian policyIdentifier", "c": "ICE-TEL CA policy", "w": false }, +"1.3.6.1.4.1.3029.1.1.1": { "d": "blowfishECB", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.1.2": { "d": "blowfishCBC", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.1.3": { "d": "blowfishCFB", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.1.4": { "d": "blowfishOFB", "c": "cryptlib encryption algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.2.1": { "d": "elgamal", "c": "cryptlib public-key algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.2.1.1": { "d": "elgamalWithSHA-1", "c": "cryptlib public-key algorithm", "w": false }, +"1.3.6.1.4.1.3029.1.2.1.2": { "d": "elgamalWithRIPEMD-160", "c": "cryptlib public-key algorithm", "w": false }, +"1.3.6.1.4.1.3029.3.1.1": { "d": "cryptlibPresenceCheck", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.3.1.2": { "d": "pkiBoot", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.3.1.4": { "d": "crlExtReason", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.3.1.5": { "d": "keyFeatures", "c": "cryptlib attribute type", "w": false }, +"1.3.6.1.4.1.3029.4.1": { "d": "cryptlibContent", "c": "cryptlib", "w": false }, +"1.3.6.1.4.1.3029.4.1.1": { "d": "cryptlibConfigData", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.2": { "d": "cryptlibUserIndex", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.3": { "d": "cryptlibUserInfo", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.4": { "d": "rtcsRequest", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.5": { "d": "rtcsResponse", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.4.1.6": { "d": "rtcsResponseExt", "c": "cryptlib content type", "w": false }, +"1.3.6.1.4.1.3029.42.11172.1": { "d": "mpeg-1", "c": "cryptlib special MPEG-of-cat OID", "w": false }, +"1.3.6.1.4.1.3029.54.11940.54": { "d": "TSA policy \"Anything that arrives, we sign\"", "c": "cryptlib TSA policy", "w": false }, +"1.3.6.1.4.1.3029.88.89.90.90.89": { "d": "xYZZY policyIdentifier", "c": "cryptlib certificate policy", "w": false }, +"1.3.6.1.4.1.3401.8.1.1": { "d": "pgpExtension", "c": "PGP key information", "w": false }, +"1.3.6.1.4.1.3576.7": { "d": "eciaAscX12Edi", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.1": { "d": "plainEDImessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.2": { "d": "signedEDImessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.5": { "d": "integrityEDImessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.65": { "d": "iaReceiptMessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.7.97": { "d": "iaStatusMessage", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.8": { "d": "eciaEdifact", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.3576.9": { "d": "eciaNonEdi", "c": "TMN EDI for Interactive Agents", "w": false }, +"1.3.6.1.4.1.4146": { "d": "Globalsign", "c": "Globalsign", "w": false }, +"1.3.6.1.4.1.4146.1": { "d": "globalsignPolicy", "c": "Globalsign", "w": false }, +"1.3.6.1.4.1.4146.1.10": { "d": "globalsignDVPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.20": { "d": "globalsignOVPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.30": { "d": "globalsignTSAPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.40": { "d": "globalsignClientCertPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.50": { "d": "globalsignCodeSignPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.60": { "d": "globalsignRootSignPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.70": { "d": "globalsignTrustedRootPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.80": { "d": "globalsignEDIClientPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.81": { "d": "globalsignEDIServerPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.90": { "d": "globalsignTPMRootPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.4146.1.95": { "d": "globalsignOCSPPolicy", "c": "Globalsign policy", "w": false }, +"1.3.6.1.4.1.5309.1": { "d": "edelWebPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2": { "d": "edelWebCustomerPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2.1": { "d": "edelWebClepsydrePolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2.2": { "d": "edelWebExperimentalTSAPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5309.1.2.3": { "d": "edelWebOpenEvidenceTSAPolicy", "c": "EdelWeb policy", "w": false }, +"1.3.6.1.4.1.5472": { "d": "timeproof", "c": "enterprise", "w": false }, +"1.3.6.1.4.1.5472.1": { "d": "tss", "c": "timeproof", "w": false }, +"1.3.6.1.4.1.5472.1.1": { "d": "tss80", "c": "timeproof TSS", "w": false }, +"1.3.6.1.4.1.5472.1.2": { "d": "tss380", "c": "timeproof TSS", "w": false }, +"1.3.6.1.4.1.5472.1.3": { "d": "tss400", "c": "timeproof TSS", "w": false }, +"1.3.6.1.4.1.5770.0.3": { "d": "secondaryPractices", "c": "MEDePass", "w": false }, +"1.3.6.1.4.1.5770.0.4": { "d": "physicianIdentifiers", "c": "MEDePass", "w": false }, +"1.3.6.1.4.1.6449.1.2.1.3.1": { "d": "comodoPolicy", "c": "Comodo CA", "w": false }, +"1.3.6.1.4.1.6449.1.2.2.15": { "d": "wotrustPolicy", "c": "WoTrust (Comodo) CA", "w": false }, +"1.3.6.1.4.1.6449.1.3.5.2": { "d": "comodoCertifiedDeliveryService", "c": "Comodo CA", "w": false }, +"1.3.6.1.4.1.6449.2.1.1": { "d": "comodoTimestampingPolicy", "c": "Comodo CA", "w": false }, +"1.3.6.1.4.1.8301.3.5.1": { "d": "validityModelChain", "c": "TU Darmstadt ValidityModel", "w": false }, +"1.3.6.1.4.1.8301.3.5.2": { "d": "validityModelShell", "c": "ValidityModel", "w": false }, +"1.3.6.1.4.1.8231.1": { "d": "rolUnicoNacional", "c": "Chilean Government national unique roll number", "w": false }, +"1.3.6.1.4.1.11591": { "d": "gnu", "c": "GNU Project (see http://www.gnupg.org/oids.html)", "w": false }, +"1.3.6.1.4.1.11591.1": { "d": "gnuRadius", "c": "GNU Radius", "w": false }, +"1.3.6.1.4.1.11591.3": { "d": "gnuRadar", "c": "GNU Radar", "w": false }, +"1.3.6.1.4.1.11591.12": { "d": "gnuDigestAlgorithm", "c": "GNU digest algorithm", "w": false }, +"1.3.6.1.4.1.11591.12.2": { "d": "tiger", "c": "GNU digest algorithm", "w": false }, +"1.3.6.1.4.1.11591.13": { "d": "gnuEncryptionAlgorithm", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2": { "d": "serpent", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.1": { "d": "serpent128_ECB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.2": { "d": "serpent128_CBC", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.3": { "d": "serpent128_OFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.4": { "d": "serpent128_CFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.21": { "d": "serpent192_ECB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.22": { "d": "serpent192_CBC", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.23": { "d": "serpent192_OFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.24": { "d": "serpent192_CFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.41": { "d": "serpent256_ECB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.42": { "d": "serpent256_CBC", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.43": { "d": "serpent256_OFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.11591.13.2.44": { "d": "serpent256_CFB", "c": "GNU encryption algorithm", "w": false }, +"1.3.6.1.4.1.16334.509.1.1": { "d": "Northrop Grumman extKeyUsage?", "c": "Northrop Grumman extended key usage", "w": false }, +"1.3.6.1.4.1.16334.509.2.1": { "d": "ngcClass1", "c": "Northrop Grumman policy", "w": false }, +"1.3.6.1.4.1.16334.509.2.2": { "d": "ngcClass2", "c": "Northrop Grumman policy", "w": false }, +"1.3.6.1.4.1.16334.509.2.3": { "d": "ngcClass3", "c": "Northrop Grumman policy", "w": false }, +"1.3.6.1.5.5.7": { "d": "pkix", "c": "", "w": false }, +"1.3.6.1.5.5.7.0.12": { "d": "attributeCert", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.1": { "d": "privateExtension", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.1.1": { "d": "authorityInfoAccess", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.2": { "d": "biometricInfo", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.3": { "d": "qcStatements", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.4": { "d": "acAuditIdentity", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.5": { "d": "acTargeting", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.6": { "d": "acAaControls", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.7": { "d": "ipAddrBlocks", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.8": { "d": "autonomousSysIds", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.9": { "d": "routerIdentifier", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.10": { "d": "acProxying", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.11": { "d": "subjectInfoAccess", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.12": { "d": "logoType", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.1.13": { "d": "wlanSSID", "c": "PKIX private extension", "w": false }, +"1.3.6.1.5.5.7.2": { "d": "policyQualifierIds", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.2.1": { "d": "cps", "c": "PKIX policy qualifier", "w": false }, +"1.3.6.1.5.5.7.2.2": { "d": "unotice", "c": "PKIX policy qualifier", "w": false }, +"1.3.6.1.5.5.7.2.3": { "d": "textNotice", "c": "PKIX policy qualifier", "w": false }, +"1.3.6.1.5.5.7.3": { "d": "keyPurpose", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.3.1": { "d": "serverAuth", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.2": { "d": "clientAuth", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.3": { "d": "codeSigning", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.4": { "d": "emailProtection", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.5": { "d": "ipsecEndSystem", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.6": { "d": "ipsecTunnel", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.7": { "d": "ipsecUser", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.8": { "d": "timeStamping", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.9": { "d": "ocspSigning", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.10": { "d": "dvcs", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.11": { "d": "sbgpCertAAServerAuth", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.13": { "d": "eapOverPPP", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.3.14": { "d": "eapOverLAN", "c": "PKIX key purpose", "w": false }, +"1.3.6.1.5.5.7.4": { "d": "cmpInformationTypes", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.4.1": { "d": "caProtEncCert", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.2": { "d": "signKeyPairTypes", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.3": { "d": "encKeyPairTypes", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.4": { "d": "preferredSymmAlg", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.5": { "d": "caKeyUpdateInfo", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.6": { "d": "currentCRL", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.7": { "d": "unsupportedOIDs", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.10": { "d": "keyPairParamReq", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.11": { "d": "keyPairParamRep", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.12": { "d": "revPassphrase", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.13": { "d": "implicitConfirm", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.14": { "d": "confirmWaitTime", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.15": { "d": "origPKIMessage", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.4.16": { "d": "suppLangTags", "c": "PKIX CMP information", "w": false }, +"1.3.6.1.5.5.7.5": { "d": "crmfRegistration", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.5.1": { "d": "regCtrl", "c": "PKIX CRMF registration", "w": false }, +"1.3.6.1.5.5.7.5.1.1": { "d": "regToken", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.2": { "d": "authenticator", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.3": { "d": "pkiPublicationInfo", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.4": { "d": "pkiArchiveOptions", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.5": { "d": "oldCertID", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.6": { "d": "protocolEncrKey", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.7": { "d": "altCertTemplate", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.1.8": { "d": "wtlsTemplate", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.2": { "d": "utf8Pairs", "c": "PKIX CRMF registration", "w": false }, +"1.3.6.1.5.5.7.5.2.1": { "d": "utf8Pairs", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.5.2.2": { "d": "certReq", "c": "PKIX CRMF registration control", "w": false }, +"1.3.6.1.5.5.7.6": { "d": "algorithms", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.6.1": { "d": "des40", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.6.2": { "d": "noSignature", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.6.3": { "d": "dh-sig-hmac-sha1", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.6.4": { "d": "dh-pop", "c": "PKIX algorithm", "w": false }, +"1.3.6.1.5.5.7.7": { "d": "cmcControls", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.8": { "d": "otherNames", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.8.1": { "d": "personalData", "c": "PKIX other name", "w": false }, +"1.3.6.1.5.5.7.8.2": { "d": "userGroup", "c": "PKIX other name", "w": false }, +"1.3.6.1.5.5.7.8.5": { "d": "xmppAddr", "c": "PKIX other name", "w": false }, +"1.3.6.1.5.5.7.9": { "d": "personalData", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.9.1": { "d": "dateOfBirth", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.2": { "d": "placeOfBirth", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.3": { "d": "gender", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.4": { "d": "countryOfCitizenship", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.9.5": { "d": "countryOfResidence", "c": "PKIX personal data", "w": false }, +"1.3.6.1.5.5.7.10": { "d": "attributeCertificate", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.10.1": { "d": "authenticationInfo", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.2": { "d": "accessIdentity", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.3": { "d": "chargingIdentity", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.4": { "d": "group", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.5": { "d": "role", "c": "PKIX attribute certificate extension", "w": false }, +"1.3.6.1.5.5.7.10.6": { "d": "wlanSSID", "c": "PKIX attribute-certificate extension", "w": false }, +"1.3.6.1.5.5.7.11": { "d": "personalData", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.11.1": { "d": "pkixQCSyntax-v1", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.14.2": { "d": "resourceCertificatePolicy", "c": "PKIX policies", "w": false }, +"1.3.6.1.5.5.7.20": { "d": "logo", "c": "PKIX qualified certificates", "w": false }, +"1.3.6.1.5.5.7.20.1": { "d": "logoLoyalty", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.20.2": { "d": "logoBackground", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.48.1": { "d": "ocsp", "c": "PKIX", "w": false }, +"1.3.6.1.5.5.7.48.1.1": { "d": "ocspBasic", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.2": { "d": "ocspNonce", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.3": { "d": "ocspCRL", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.4": { "d": "ocspResponse", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.5": { "d": "ocspNoCheck", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.6": { "d": "ocspArchiveCutoff", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.1.7": { "d": "ocspServiceLocator", "c": "OCSP", "w": false }, +"1.3.6.1.5.5.7.48.2": { "d": "caIssuers", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.3": { "d": "timeStamping", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.4": { "d": "dvcs", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.5": { "d": "caRepository", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.7": { "d": "signedObjectRepository", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.10": { "d": "rpkiManifest", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.7.48.11": { "d": "signedObject", "c": "PKIX subject/authority info access descriptor", "w": false }, +"1.3.6.1.5.5.8.1.1": { "d": "hmacMD5", "c": "ISAKMP HMAC algorithm", "w": false }, +"1.3.6.1.5.5.8.1.2": { "d": "hmacSHA", "c": "ISAKMP HMAC algorithm", "w": false }, +"1.3.6.1.5.5.8.1.3": { "d": "hmacTiger", "c": "ISAKMP HMAC algorithm", "w": false }, +"1.3.6.1.5.5.8.2.2": { "d": "iKEIntermediate", "c": "IKE ???", "w": false }, +"1.3.12.2.1011.7.1": { "d": "decEncryptionAlgorithm", "c": "DASS algorithm", "w": false }, +"1.3.12.2.1011.7.1.2": { "d": "decDEA", "c": "DASS encryption algorithm", "w": false }, +"1.3.12.2.1011.7.2": { "d": "decHashAlgorithm", "c": "DASS algorithm", "w": false }, +"1.3.12.2.1011.7.2.1": { "d": "decMD2", "c": "DASS hash algorithm", "w": false }, +"1.3.12.2.1011.7.2.2": { "d": "decMD4", "c": "DASS hash algorithm", "w": false }, +"1.3.12.2.1011.7.3": { "d": "decSignatureAlgorithm", "c": "DASS algorithm", "w": false }, +"1.3.12.2.1011.7.3.1": { "d": "decMD2withRSA", "c": "DASS signature algorithm", "w": false }, +"1.3.12.2.1011.7.3.2": { "d": "decMD4withRSA", "c": "DASS signature algorithm", "w": false }, +"1.3.12.2.1011.7.3.3": { "d": "decDEAMAC", "c": "DASS signature algorithm", "w": false }, +"1.3.14.2.26.5": { "d": "sha", "c": "Unsure about this OID", "w": false }, +"1.3.14.3.2.1.1": { "d": "rsa", "c": "X.509. Unsure about this OID", "w": false }, +"1.3.14.3.2.2": { "d": "md4WitRSA", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.3": { "d": "md5WithRSA", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.4": { "d": "md4WithRSAEncryption", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.2.1": { "d": "sqmod-N", "c": "X.509. Deprecated", "w": true }, +"1.3.14.3.2.3.1": { "d": "sqmod-NwithRSA", "c": "X.509. Deprecated", "w": true }, +"1.3.14.3.2.6": { "d": "desECB", "c": "", "w": false }, +"1.3.14.3.2.7": { "d": "desCBC", "c": "", "w": false }, +"1.3.14.3.2.8": { "d": "desOFB", "c": "", "w": false }, +"1.3.14.3.2.9": { "d": "desCFB", "c": "", "w": false }, +"1.3.14.3.2.10": { "d": "desMAC", "c": "", "w": false }, +"1.3.14.3.2.11": { "d": "rsaSignature", "c": "ISO 9796-2, also X9.31 Part 1", "w": false }, +"1.3.14.3.2.12": { "d": "dsa", "c": "OIW?, supposedly from an incomplete version of SDN.701 (doesn't match final SDN.701)", "w": true }, +"1.3.14.3.2.13": { "d": "dsaWithSHA", "c": "Oddball OIW OID. Incorrectly used by JDK 1.1 in place of (1 3 14 3 2 27)", "w": true }, +"1.3.14.3.2.14": { "d": "mdc2WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.15": { "d": "shaWithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.16": { "d": "dhWithCommonModulus", "c": "Oddball OIW OID. Deprecated, use a plain DH OID instead", "w": true }, +"1.3.14.3.2.17": { "d": "desEDE", "c": "Oddball OIW OID. Mode is ECB", "w": false }, +"1.3.14.3.2.18": { "d": "sha", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.19": { "d": "mdc-2", "c": "Oddball OIW OID, DES-based hash, planned for X9.31 Part 2", "w": false }, +"1.3.14.3.2.20": { "d": "dsaCommon", "c": "Oddball OIW OID. Deprecated, use a plain DSA OID instead", "w": true }, +"1.3.14.3.2.21": { "d": "dsaCommonWithSHA", "c": "Oddball OIW OID. Deprecated, use a plain dsaWithSHA OID instead", "w": true }, +"1.3.14.3.2.22": { "d": "rsaKeyTransport", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.23": { "d": "keyed-hash-seal", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.2.24": { "d": "md2WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.25": { "d": "md5WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules", "w": false }, +"1.3.14.3.2.26": { "d": "sha1", "c": "OIW", "w": false }, +"1.3.14.3.2.27": { "d": "dsaWithSHA1", "c": "OIW. This OID may also be assigned as ripemd-160", "w": false }, +"1.3.14.3.2.28": { "d": "dsaWithCommonSHA1", "c": "OIW", "w": false }, +"1.3.14.3.2.29": { "d": "sha-1WithRSAEncryption", "c": "Oddball OIW OID", "w": false }, +"1.3.14.3.3.1": { "d": "simple-strong-auth-mechanism", "c": "Oddball OIW OID", "w": false }, +"1.3.14.7.2.1.1": { "d": "ElGamal", "c": "Unsure about this OID", "w": false }, +"1.3.14.7.2.3.1": { "d": "md2WithRSA", "c": "Unsure about this OID", "w": false }, +"1.3.14.7.2.3.2": { "d": "md2WithElGamal", "c": "Unsure about this OID", "w": false }, +"1.3.36.1": { "d": "document", "c": "Teletrust document", "w": false }, +"1.3.36.1.1": { "d": "finalVersion", "c": "Teletrust document", "w": false }, +"1.3.36.1.2": { "d": "draft", "c": "Teletrust document", "w": false }, +"1.3.36.2": { "d": "sio", "c": "Teletrust sio", "w": false }, +"1.3.36.2.1": { "d": "sedu", "c": "Teletrust sio", "w": false }, +"1.3.36.3": { "d": "algorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.1": { "d": "encryptionAlgorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.1.1": { "d": "des", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.1": { "d": "desECB_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.1.1": { "d": "desECB_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.2.1": { "d": "desCBC_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.1.2.1.1": { "d": "desCBC_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.3": { "d": "des_3", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.3.1.1": { "d": "des_3ECB_pad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.3.1.1.1": { "d": "des_3ECB_ISOpad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.3.2.1": { "d": "des_3CBC_pad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.3.2.1.1": { "d": "des_3CBC_ISOpad", "c": "Teletrust encryption algorithm. EDE triple DES", "w": false }, +"1.3.36.3.1.2": { "d": "idea", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.1": { "d": "ideaECB", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.1.1": { "d": "ideaECB_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.1.1.1": { "d": "ideaECB_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.2": { "d": "ideaCBC", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.2.1": { "d": "ideaCBC_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.2.1.1": { "d": "ideaCBC_ISOpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.3": { "d": "ideaOFB", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.2.4": { "d": "ideaCFB", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.4": { "d": "rsaEncryption", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.4.512.17": { "d": "rsaEncryptionWithlmod512expe17", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5": { "d": "bsi-1", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5.1": { "d": "bsi_1ECB_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5.2": { "d": "bsi_1CBC_pad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.1.5.2.1": { "d": "bsi_1CBC_PEMpad", "c": "Teletrust encryption algorithm", "w": false }, +"1.3.36.3.2": { "d": "hashAlgorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.2.1": { "d": "ripemd160", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.2": { "d": "ripemd128", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.3": { "d": "ripemd256", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.4": { "d": "mdc2singleLength", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.2.5": { "d": "mdc2doubleLength", "c": "Teletrust hash algorithm", "w": false }, +"1.3.36.3.3": { "d": "signatureAlgorithm", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.3.1": { "d": "rsaSignature", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.1": { "d": "rsaSignatureWithsha1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.1.1024.11": { "d": "rsaSignatureWithsha1_l1024_l11", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.2": { "d": "rsaSignatureWithripemd160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.2.1024.11": { "d": "rsaSignatureWithripemd160_l1024_l11", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.3": { "d": "rsaSignatureWithrimpemd128", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.1.4": { "d": "rsaSignatureWithrimpemd256", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2": { "d": "ecsieSign", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.1": { "d": "ecsieSignWithsha1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.2": { "d": "ecsieSignWithripemd160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.3": { "d": "ecsieSignWithmd2", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.4": { "d": "ecsieSignWithmd5", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.3.3.2.8.1.1.1": { "d": "brainpoolP160r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.2": { "d": "brainpoolP160t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.3": { "d": "brainpoolP192r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.4": { "d": "brainpoolP192t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.5": { "d": "brainpoolP224r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.6": { "d": "brainpoolP224t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.7": { "d": "brainpoolP256r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.8": { "d": "brainpoolP256t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.9": { "d": "brainpoolP320r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.10": { "d": "brainpoolP320t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.11": { "d": "brainpoolP384r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.12": { "d": "brainpoolP384t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.13": { "d": "brainpoolP512r1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.3.2.8.1.1.14": { "d": "brainpoolP512t1", "c": "ECC Brainpool Standard Curves and Curve Generation", "w": false }, +"1.3.36.3.4": { "d": "signatureScheme", "c": "Teletrust algorithm", "w": false }, +"1.3.36.3.4.1": { "d": "sigS_ISO9796-1", "c": "Teletrust signature scheme", "w": false }, +"1.3.36.3.4.2": { "d": "sigS_ISO9796-2", "c": "Teletrust signature scheme", "w": false }, +"1.3.36.3.4.2.1": { "d": "sigS_ISO9796-2Withred", "c": "Teletrust signature scheme. Unsure what this is supposed to be", "w": false }, +"1.3.36.3.4.2.2": { "d": "sigS_ISO9796-2Withrsa", "c": "Teletrust signature scheme. Unsure what this is supposed to be", "w": false }, +"1.3.36.3.4.2.3": { "d": "sigS_ISO9796-2Withrnd", "c": "Teletrust signature scheme. 9796-2 with random number in padding field", "w": false }, +"1.3.36.4": { "d": "attribute", "c": "Teletrust attribute", "w": false }, +"1.3.36.5": { "d": "policy", "c": "Teletrust policy", "w": false }, +"1.3.36.6": { "d": "api", "c": "Teletrust API", "w": false }, +"1.3.36.6.1": { "d": "manufacturer-specific_api", "c": "Teletrust API", "w": false }, +"1.3.36.6.1.1": { "d": "utimaco-api", "c": "Teletrust API", "w": false }, +"1.3.36.6.2": { "d": "functionality-specific_api", "c": "Teletrust API", "w": false }, +"1.3.36.7": { "d": "keymgmnt", "c": "Teletrust key management", "w": false }, +"1.3.36.7.1": { "d": "keyagree", "c": "Teletrust key management", "w": false }, +"1.3.36.7.1.1": { "d": "bsiPKE", "c": "Teletrust key management", "w": false }, +"1.3.36.7.2": { "d": "keytrans", "c": "Teletrust key management", "w": false }, +"1.3.36.7.2.1": { "d": "encISO9796-2Withrsa", "c": "Teletrust key management. 9796-2 with key stored in hash field", "w": false }, +"1.3.36.8.1.1": { "d": "Teletrust SigGConform policyIdentifier", "c": "Teletrust policy", "w": false }, +"1.3.36.8.2.1": { "d": "directoryService", "c": "Teletrust extended key usage", "w": false }, +"1.3.36.8.3.1": { "d": "dateOfCertGen", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.2": { "d": "procuration", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.3": { "d": "admission", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.4": { "d": "monetaryLimit", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.5": { "d": "declarationOfMajority", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.6": { "d": "integratedCircuitCardSerialNumber", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.7": { "d": "pKReference", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.8": { "d": "restriction", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.9": { "d": "retrieveIfAllowed", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.10": { "d": "requestedCertificate", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.11": { "d": "namingAuthorities", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.11.1": { "d": "rechtWirtschaftSteuern", "c": "Teletrust naming authorities", "w": false }, +"1.3.36.8.3.11.1.1": { "d": "rechtsanwaeltin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.2": { "d": "rechtsanwalt", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.3": { "d": "rechtsBeistand", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.4": { "d": "steuerBeraterin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.5": { "d": "steuerBerater", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.6": { "d": "steuerBevollmaechtigte", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.7": { "d": "steuerBevollmaechtigter", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.8": { "d": "notarin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.9": { "d": "notar", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.10": { "d": "notarVertreterin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.11": { "d": "notarVertreter", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.12": { "d": "notariatsVerwalterin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.13": { "d": "notariatsVerwalter", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.14": { "d": "wirtschaftsPrueferin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.15": { "d": "wirtschaftsPruefer", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.16": { "d": "vereidigteBuchprueferin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.17": { "d": "vereidigterBuchpruefer", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.18": { "d": "patentAnwaeltin", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.11.1.19": { "d": "patentAnwalt", "c": "Teletrust ProfessionInfo", "w": false }, +"1.3.36.8.3.12": { "d": "certInDirSince", "c": "Teletrust OCSP attribute (obsolete)", "w": true }, +"1.3.36.8.3.13": { "d": "certHash", "c": "Teletrust OCSP attribute", "w": false }, +"1.3.36.8.3.14": { "d": "nameAtBirth", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.3.15": { "d": "additionalInformation", "c": "Teletrust attribute", "w": false }, +"1.3.36.8.4.1": { "d": "personalData", "c": "Teletrust OtherName attribute", "w": false }, +"1.3.36.8.4.8": { "d": "restriction", "c": "Teletrust attribute certificate attribute", "w": false }, +"1.3.36.8.5.1.1.1": { "d": "rsaIndicateSHA1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.1.2": { "d": "rsaIndicateRIPEMD160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.1.3": { "d": "rsaWithSHA1", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.1.4": { "d": "rsaWithRIPEMD160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.2.1": { "d": "dsaExtended", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.5.1.2.2": { "d": "dsaWithRIPEMD160", "c": "Teletrust signature algorithm", "w": false }, +"1.3.36.8.6.1": { "d": "cert", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.2": { "d": "certRef", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.3": { "d": "attrCert", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.4": { "d": "attrRef", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.5": { "d": "fileName", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.6": { "d": "storageTime", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.7": { "d": "fileSize", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.8": { "d": "location", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.9": { "d": "sigNumber", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.6.10": { "d": "autoGen", "c": "Teletrust signature attributes", "w": false }, +"1.3.36.8.7.1.1": { "d": "ptAdobeILL", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.2": { "d": "ptAmiPro", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.3": { "d": "ptAutoCAD", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.4": { "d": "ptBinary", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.5": { "d": "ptBMP", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.6": { "d": "ptCGM", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.7": { "d": "ptCorelCRT", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.8": { "d": "ptCorelDRW", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.9": { "d": "ptCorelEXC", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.10": { "d": "ptCorelPHT", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.11": { "d": "ptDraw", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.12": { "d": "ptDVI", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.13": { "d": "ptEPS", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.14": { "d": "ptExcel", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.15": { "d": "ptGEM", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.16": { "d": "ptGIF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.17": { "d": "ptHPGL", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.18": { "d": "ptJPEG", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.19": { "d": "ptKodak", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.20": { "d": "ptLaTeX", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.21": { "d": "ptLotus", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.22": { "d": "ptLotusPIC", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.23": { "d": "ptMacPICT", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.24": { "d": "ptMacWord", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.25": { "d": "ptMSWfD", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.26": { "d": "ptMSWord", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.27": { "d": "ptMSWord2", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.28": { "d": "ptMSWord6", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.29": { "d": "ptMSWord8", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.30": { "d": "ptPDF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.31": { "d": "ptPIF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.32": { "d": "ptPostscript", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.33": { "d": "ptRTF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.34": { "d": "ptSCITEX", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.35": { "d": "ptTAR", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.36": { "d": "ptTarga", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.37": { "d": "ptTeX", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.38": { "d": "ptText", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.39": { "d": "ptTIFF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.40": { "d": "ptTIFF-FC", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.41": { "d": "ptUID", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.42": { "d": "ptUUEncode", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.43": { "d": "ptWMF", "c": "Teletrust presentation types", "w": false }, +"1.3.36.8.7.1.45": { "d": "ptWPGrph", "c": "Teletrust presentation types", "w": false }, +"1.3.101.1.4": { "d": "thawte-ce", "c": "Thawte", "w": false }, +"1.3.101.1.4.1": { "d": "strongExtranet", "c": "Thawte certificate extension", "w": false }, +"1.3.132.0.1": { "d": "sect163k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.2": { "d": "sect163r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.3": { "d": "sect239k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.4": { "d": "sect113r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.5": { "d": "sect113r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.6": { "d": "secp112r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.7": { "d": "secp112r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.8": { "d": "secp160r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.9": { "d": "secp160k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.10": { "d": "secp256k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.15": { "d": "sect163r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.16": { "d": "sect283k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.17": { "d": "sect283r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.22": { "d": "sect131r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.23": { "d": "sect131r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.24": { "d": "sect193r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.25": { "d": "sect193r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.26": { "d": "sect233k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.27": { "d": "sect233r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.28": { "d": "secp128r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.29": { "d": "secp128r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.30": { "d": "secp160r2", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.31": { "d": "secp192k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.32": { "d": "secp224k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.33": { "d": "secp224r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.34": { "d": "secp384r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.35": { "d": "secp521r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.36": { "d": "sect409k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.37": { "d": "sect409r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.38": { "d": "sect571k1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"1.3.132.0.39": { "d": "sect571r1", "c": "SECG (Certicom) named elliptic curve", "w": false }, +"2.5.4.0": { "d": "objectClass", "c": "X.520 DN component", "w": false }, +"2.5.4.1": { "d": "aliasedEntryName", "c": "X.520 DN component", "w": false }, +"2.5.4.2": { "d": "knowledgeInformation", "c": "X.520 DN component", "w": false }, +"2.5.4.3": { "d": "commonName", "c": "X.520 DN component", "w": false }, +"2.5.4.4": { "d": "surname", "c": "X.520 DN component", "w": false }, +"2.5.4.5": { "d": "serialNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.6": { "d": "countryName", "c": "X.520 DN component", "w": false }, +"2.5.4.7": { "d": "localityName", "c": "X.520 DN component", "w": false }, +"2.5.4.7.1": { "d": "collectiveLocalityName", "c": "X.520 DN component", "w": false }, +"2.5.4.8": { "d": "stateOrProvinceName", "c": "X.520 DN component", "w": false }, +"2.5.4.8.1": { "d": "collectiveStateOrProvinceName", "c": "X.520 DN component", "w": false }, +"2.5.4.9": { "d": "streetAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.9.1": { "d": "collectiveStreetAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.10": { "d": "organizationName", "c": "X.520 DN component", "w": false }, +"2.5.4.10.1": { "d": "collectiveOrganizationName", "c": "X.520 DN component", "w": false }, +"2.5.4.11": { "d": "organizationalUnitName", "c": "X.520 DN component", "w": false }, +"2.5.4.11.1": { "d": "collectiveOrganizationalUnitName", "c": "X.520 DN component", "w": false }, +"2.5.4.12": { "d": "title", "c": "X.520 DN component", "w": false }, +"2.5.4.13": { "d": "description", "c": "X.520 DN component", "w": false }, +"2.5.4.14": { "d": "searchGuide", "c": "X.520 DN component", "w": false }, +"2.5.4.15": { "d": "businessCategory", "c": "X.520 DN component", "w": false }, +"2.5.4.16": { "d": "postalAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.16.1": { "d": "collectivePostalAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.17": { "d": "postalCode", "c": "X.520 DN component", "w": false }, +"2.5.4.17.1": { "d": "collectivePostalCode", "c": "X.520 DN component", "w": false }, +"2.5.4.18": { "d": "postOfficeBox", "c": "X.520 DN component", "w": false }, +"2.5.4.18.1": { "d": "collectivePostOfficeBox", "c": "X.520 DN component", "w": false }, +"2.5.4.19": { "d": "physicalDeliveryOfficeName", "c": "X.520 DN component", "w": false }, +"2.5.4.19.1": { "d": "collectivePhysicalDeliveryOfficeName", "c": "X.520 DN component", "w": false }, +"2.5.4.20": { "d": "telephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.20.1": { "d": "collectiveTelephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.21": { "d": "telexNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.21.1": { "d": "collectiveTelexNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.22": { "d": "teletexTerminalIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.22.1": { "d": "collectiveTeletexTerminalIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.23": { "d": "facsimileTelephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.23.1": { "d": "collectiveFacsimileTelephoneNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.24": { "d": "x121Address", "c": "X.520 DN component", "w": false }, +"2.5.4.25": { "d": "internationalISDNNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.25.1": { "d": "collectiveInternationalISDNNumber", "c": "X.520 DN component", "w": false }, +"2.5.4.26": { "d": "registeredAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.27": { "d": "destinationIndicator", "c": "X.520 DN component", "w": false }, +"2.5.4.28": { "d": "preferredDeliveryMehtod", "c": "X.520 DN component", "w": false }, +"2.5.4.29": { "d": "presentationAddress", "c": "X.520 DN component", "w": false }, +"2.5.4.30": { "d": "supportedApplicationContext", "c": "X.520 DN component", "w": false }, +"2.5.4.31": { "d": "member", "c": "X.520 DN component", "w": false }, +"2.5.4.32": { "d": "owner", "c": "X.520 DN component", "w": false }, +"2.5.4.33": { "d": "roleOccupant", "c": "X.520 DN component", "w": false }, +"2.5.4.34": { "d": "seeAlso", "c": "X.520 DN component", "w": false }, +"2.5.4.35": { "d": "userPassword", "c": "X.520 DN component", "w": false }, +"2.5.4.36": { "d": "userCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.37": { "d": "caCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.38": { "d": "authorityRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.39": { "d": "certificateRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.40": { "d": "crossCertificatePair", "c": "X.520 DN component", "w": false }, +"2.5.4.41": { "d": "name", "c": "X.520 DN component", "w": false }, +"2.5.4.42": { "d": "givenName", "c": "X.520 DN component", "w": false }, +"2.5.4.43": { "d": "initials", "c": "X.520 DN component", "w": false }, +"2.5.4.44": { "d": "generationQualifier", "c": "X.520 DN component", "w": false }, +"2.5.4.45": { "d": "uniqueIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.46": { "d": "dnQualifier", "c": "X.520 DN component", "w": false }, +"2.5.4.47": { "d": "enhancedSearchGuide", "c": "X.520 DN component", "w": false }, +"2.5.4.48": { "d": "protocolInformation", "c": "X.520 DN component", "w": false }, +"2.5.4.49": { "d": "distinguishedName", "c": "X.520 DN component", "w": false }, +"2.5.4.50": { "d": "uniqueMember", "c": "X.520 DN component", "w": false }, +"2.5.4.51": { "d": "houseIdentifier", "c": "X.520 DN component", "w": false }, +"2.5.4.52": { "d": "supportedAlgorithms", "c": "X.520 DN component", "w": false }, +"2.5.4.53": { "d": "deltaRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.54": { "d": "dmdName", "c": "X.520 DN component", "w": false }, +"2.5.4.55": { "d": "clearance", "c": "X.520 DN component", "w": false }, +"2.5.4.56": { "d": "defaultDirQop", "c": "X.520 DN component", "w": false }, +"2.5.4.57": { "d": "attributeIntegrityInfo", "c": "X.520 DN component", "w": false }, +"2.5.4.58": { "d": "attributeCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.59": { "d": "attributeCertificateRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.60": { "d": "confKeyInfo", "c": "X.520 DN component", "w": false }, +"2.5.4.61": { "d": "aACertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.62": { "d": "attributeDescriptorCertificate", "c": "X.520 DN component", "w": false }, +"2.5.4.63": { "d": "attributeAuthorityRevocationList", "c": "X.520 DN component", "w": false }, +"2.5.4.64": { "d": "familyInformation", "c": "X.520 DN component", "w": false }, +"2.5.4.65": { "d": "pseudonym", "c": "X.520 DN component", "w": false }, +"2.5.4.66": { "d": "communicationsService", "c": "X.520 DN component", "w": false }, +"2.5.4.67": { "d": "communicationsNetwork", "c": "X.520 DN component", "w": false }, +"2.5.4.68": { "d": "certificationPracticeStmt", "c": "X.520 DN component", "w": false }, +"2.5.4.69": { "d": "certificatePolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.70": { "d": "pkiPath", "c": "X.520 DN component", "w": false }, +"2.5.4.71": { "d": "privPolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.72": { "d": "role", "c": "X.520 DN component", "w": false }, +"2.5.4.73": { "d": "delegationPath", "c": "X.520 DN component", "w": false }, +"2.5.4.74": { "d": "protPrivPolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.75": { "d": "xMLPrivilegeInfo", "c": "X.520 DN component", "w": false }, +"2.5.4.76": { "d": "xmlPrivPolicy", "c": "X.520 DN component", "w": false }, +"2.5.4.82": { "d": "permission", "c": "X.520 DN component", "w": false }, +"2.5.6.0": { "d": "top", "c": "X.520 objectClass", "w": false }, +"2.5.6.1": { "d": "alias", "c": "X.520 objectClass", "w": false }, +"2.5.6.2": { "d": "country", "c": "X.520 objectClass", "w": false }, +"2.5.6.3": { "d": "locality", "c": "X.520 objectClass", "w": false }, +"2.5.6.4": { "d": "organization", "c": "X.520 objectClass", "w": false }, +"2.5.6.5": { "d": "organizationalUnit", "c": "X.520 objectClass", "w": false }, +"2.5.6.6": { "d": "person", "c": "X.520 objectClass", "w": false }, +"2.5.6.7": { "d": "organizationalPerson", "c": "X.520 objectClass", "w": false }, +"2.5.6.8": { "d": "organizationalRole", "c": "X.520 objectClass", "w": false }, +"2.5.6.9": { "d": "groupOfNames", "c": "X.520 objectClass", "w": false }, +"2.5.6.10": { "d": "residentialPerson", "c": "X.520 objectClass", "w": false }, +"2.5.6.11": { "d": "applicationProcess", "c": "X.520 objectClass", "w": false }, +"2.5.6.12": { "d": "applicationEntity", "c": "X.520 objectClass", "w": false }, +"2.5.6.13": { "d": "dSA", "c": "X.520 objectClass", "w": false }, +"2.5.6.14": { "d": "device", "c": "X.520 objectClass", "w": false }, +"2.5.6.15": { "d": "strongAuthenticationUser", "c": "X.520 objectClass", "w": false }, +"2.5.6.16": { "d": "certificateAuthority", "c": "X.520 objectClass", "w": false }, +"2.5.6.17": { "d": "groupOfUniqueNames", "c": "X.520 objectClass", "w": false }, +"2.5.6.21": { "d": "pkiUser", "c": "X.520 objectClass", "w": false }, +"2.5.6.22": { "d": "pkiCA", "c": "X.520 objectClass", "w": false }, +"2.5.8.1.1": { "d": "rsa", "c": "X.500 algorithms. Ambiguous, since no padding rules specified", "w": true }, +"2.5.29.1": { "d": "authorityKeyIdentifier", "c": "X.509 extension. Deprecated, use 2 5 29 35 instead", "w": true }, +"2.5.29.2": { "d": "keyAttributes", "c": "X.509 extension. Obsolete, use keyUsage/extKeyUsage instead", "w": true }, +"2.5.29.3": { "d": "certificatePolicies", "c": "X.509 extension. Deprecated, use 2 5 29 32 instead", "w": true }, +"2.5.29.4": { "d": "keyUsageRestriction", "c": "X.509 extension. Obsolete, use keyUsage/extKeyUsage instead", "w": true }, +"2.5.29.5": { "d": "policyMapping", "c": "X.509 extension. Deprecated, use 2 5 29 33 instead", "w": true }, +"2.5.29.6": { "d": "subtreesConstraint", "c": "X.509 extension. Obsolete, use nameConstraints instead", "w": true }, +"2.5.29.7": { "d": "subjectAltName", "c": "X.509 extension. Deprecated, use 2 5 29 17 instead", "w": true }, +"2.5.29.8": { "d": "issuerAltName", "c": "X.509 extension. Deprecated, use 2 5 29 18 instead", "w": true }, +"2.5.29.9": { "d": "subjectDirectoryAttributes", "c": "X.509 extension", "w": false }, +"2.5.29.10": { "d": "basicConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 19 instead", "w": true }, +"2.5.29.11": { "d": "nameConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 30 instead", "w": true }, +"2.5.29.12": { "d": "policyConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 36 instead", "w": true }, +"2.5.29.13": { "d": "basicConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 19 instead", "w": true }, +"2.5.29.14": { "d": "subjectKeyIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.15": { "d": "keyUsage", "c": "X.509 extension", "w": false }, +"2.5.29.16": { "d": "privateKeyUsagePeriod", "c": "X.509 extension", "w": false }, +"2.5.29.17": { "d": "subjectAltName", "c": "X.509 extension", "w": false }, +"2.5.29.18": { "d": "issuerAltName", "c": "X.509 extension", "w": false }, +"2.5.29.19": { "d": "basicConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.20": { "d": "cRLNumber", "c": "X.509 extension", "w": false }, +"2.5.29.21": { "d": "cRLReason", "c": "X.509 extension", "w": false }, +"2.5.29.22": { "d": "expirationDate", "c": "X.509 extension. Deprecated, alternative OID uncertain", "w": true }, +"2.5.29.23": { "d": "instructionCode", "c": "X.509 extension", "w": false }, +"2.5.29.24": { "d": "invalidityDate", "c": "X.509 extension", "w": false }, +"2.5.29.25": { "d": "cRLDistributionPoints", "c": "X.509 extension. Deprecated, use 2 5 29 31 instead", "w": true }, +"2.5.29.26": { "d": "issuingDistributionPoint", "c": "X.509 extension. Deprecated, use 2 5 29 28 instead", "w": true }, +"2.5.29.27": { "d": "deltaCRLIndicator", "c": "X.509 extension", "w": false }, +"2.5.29.28": { "d": "issuingDistributionPoint", "c": "X.509 extension", "w": false }, +"2.5.29.29": { "d": "certificateIssuer", "c": "X.509 extension", "w": false }, +"2.5.29.30": { "d": "nameConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.31": { "d": "cRLDistributionPoints", "c": "X.509 extension", "w": false }, +"2.5.29.32": { "d": "certificatePolicies", "c": "X.509 extension", "w": false }, +"2.5.29.32.0": { "d": "anyPolicy", "c": "X.509 certificate policy", "w": false }, +"2.5.29.33": { "d": "policyMappings", "c": "X.509 extension", "w": false }, +"2.5.29.34": { "d": "policyConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 36 instead", "w": true }, +"2.5.29.35": { "d": "authorityKeyIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.36": { "d": "policyConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.37": { "d": "extKeyUsage", "c": "X.509 extension", "w": false }, +"2.5.29.37.0": { "d": "anyExtendedKeyUsage", "c": "X.509 extended key usage", "w": false }, +"2.5.29.38": { "d": "authorityAttributeIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.39": { "d": "roleSpecCertIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.40": { "d": "cRLStreamIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.41": { "d": "basicAttConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.42": { "d": "delegatedNameConstraints", "c": "X.509 extension", "w": false }, +"2.5.29.43": { "d": "timeSpecification", "c": "X.509 extension", "w": false }, +"2.5.29.44": { "d": "cRLScope", "c": "X.509 extension", "w": false }, +"2.5.29.45": { "d": "statusReferrals", "c": "X.509 extension", "w": false }, +"2.5.29.46": { "d": "freshestCRL", "c": "X.509 extension", "w": false }, +"2.5.29.47": { "d": "orderedList", "c": "X.509 extension", "w": false }, +"2.5.29.48": { "d": "attributeDescriptor", "c": "X.509 extension", "w": false }, +"2.5.29.49": { "d": "userNotice", "c": "X.509 extension", "w": false }, +"2.5.29.50": { "d": "sOAIdentifier", "c": "X.509 extension", "w": false }, +"2.5.29.51": { "d": "baseUpdateTime", "c": "X.509 extension", "w": false }, +"2.5.29.52": { "d": "acceptableCertPolicies", "c": "X.509 extension", "w": false }, +"2.5.29.53": { "d": "deltaInfo", "c": "X.509 extension", "w": false }, +"2.5.29.54": { "d": "inhibitAnyPolicy", "c": "X.509 extension", "w": false }, +"2.5.29.55": { "d": "targetInformation", "c": "X.509 extension", "w": false }, +"2.5.29.56": { "d": "noRevAvail", "c": "X.509 extension", "w": false }, +"2.5.29.57": { "d": "acceptablePrivilegePolicies", "c": "X.509 extension", "w": false }, +"2.5.29.58": { "d": "toBeRevoked", "c": "X.509 extension", "w": false }, +"2.5.29.59": { "d": "revokedGroups", "c": "X.509 extension", "w": false }, +"2.5.29.60": { "d": "expiredCertsOnCRL", "c": "X.509 extension", "w": false }, +"2.5.29.61": { "d": "indirectIssuer", "c": "X.509 extension", "w": false }, +"2.5.29.62": { "d": "noAssertion", "c": "X.509 extension", "w": false }, +"2.5.29.63": { "d": "aAissuingDistributionPoint", "c": "X.509 extension", "w": false }, +"2.5.29.64": { "d": "issuedOnBehalfOf", "c": "X.509 extension", "w": false }, +"2.5.29.65": { "d": "singleUse", "c": "X.509 extension", "w": false }, +"2.5.29.66": { "d": "groupAC", "c": "X.509 extension", "w": false }, +"2.5.29.67": { "d": "allowedAttAss", "c": "X.509 extension", "w": false }, +"2.5.29.68": { "d": "attributeMappings", "c": "X.509 extension", "w": false }, +"2.5.29.69": { "d": "holderNameConstraints", "c": "X.509 extension", "w": false }, +"2.16.724.1.2.2.4.1": { "d": "personalDataInfo", "c": "Spanish Government PKI?", "w": false }, +"2.16.840.1.101.2.1.1.1": { "d": "sdnsSignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.2": { "d": "fortezzaSignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicSignatureAlgorithm, this OID is better known as dsaWithSHA-1.", "w": false }, +"2.16.840.1.101.2.1.1.3": { "d": "sdnsConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.4": { "d": "fortezzaConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicConfidentialityAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.5": { "d": "sdnsIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.6": { "d": "fortezzaIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicIntegrityAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.7": { "d": "sdnsTokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.8": { "d": "fortezzaTokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly know as mosaicTokenProtectionAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.9": { "d": "sdnsKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.10": { "d": "fortezzaKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKeyManagementAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.11": { "d": "sdnsKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.12": { "d": "fortezzaKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKMandSigAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.13": { "d": "suiteASignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.14": { "d": "suiteAConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.15": { "d": "suiteAIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.16": { "d": "suiteATokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.17": { "d": "suiteAKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.18": { "d": "suiteAKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.19": { "d": "fortezzaUpdatedSigAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicUpdatedSigAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.20": { "d": "fortezzaKMandUpdSigAlgorithms", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKMandUpdSigAlgorithms", "w": false }, +"2.16.840.1.101.2.1.1.21": { "d": "fortezzaUpdatedIntegAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicUpdatedIntegAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.22": { "d": "keyExchangeAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKeyEncryptionAlgorithm", "w": false }, +"2.16.840.1.101.2.1.1.23": { "d": "fortezzaWrap80Algorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.1.24": { "d": "kEAKeyEncryptionAlgorithm", "c": "SDN.700 INFOSEC algorithms", "w": false }, +"2.16.840.1.101.2.1.2.1": { "d": "rfc822MessageFormat", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.2": { "d": "emptyContent", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.3": { "d": "cspContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.42": { "d": "mspRev3ContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.48": { "d": "mspContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.49": { "d": "mspRekeyAgentProtocol", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.50": { "d": "mspMMP", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.66": { "d": "mspRev3-1ContentType", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.72": { "d": "forwardedMSPMessageBodyPart", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.73": { "d": "mspForwardedMessageParameters", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.74": { "d": "forwardedCSPMsgBodyPart", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.75": { "d": "cspForwardedMessageParameters", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.2.76": { "d": "mspMMP2", "c": "SDN.700 INFOSEC format", "w": false }, +"2.16.840.1.101.2.1.3.1": { "d": "sdnsSecurityPolicy", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.2": { "d": "sdnsPRBAC", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.3": { "d": "mosaicPRBAC", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.10": { "d": "siSecurityPolicy", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.10.0": { "d": "siNASP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.1": { "d": "siELCO", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.2": { "d": "siTK", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.3": { "d": "siDSAP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.4": { "d": "siSSSS", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.5": { "d": "siDNASP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.6": { "d": "siBYEMAN", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.7": { "d": "siREL-US", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.8": { "d": "siREL-AUS", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.9": { "d": "siREL-CAN", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.10": { "d": "siREL_UK", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.11": { "d": "siREL-NZ", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.12": { "d": "siGeneric", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11": { "d": "genser", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.11.0": { "d": "genserNations", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.1": { "d": "genserComsec", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.2": { "d": "genserAcquisition", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.3": { "d": "genserSecurityCategories", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.11.3.0": { "d": "genserTagSetName", "c": "SDN.700 INFOSEC GENSER policy", "w": false }, +"2.16.840.1.101.2.1.3.12": { "d": "defaultSecurityPolicy", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.13": { "d": "capcoMarkings", "c": "SDN.700 INFOSEC policy", "w": false }, +"2.16.840.1.101.2.1.3.13.0": { "d": "capcoSecurityCategories", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.1": { "d": "capcoTagSetName1", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.2": { "d": "capcoTagSetName2", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.3": { "d": "capcoTagSetName3", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.3.13.0.4": { "d": "capcoTagSetName4", "c": "SDN.700 INFOSEC policy CAPCO markings", "w": false }, +"2.16.840.1.101.2.1.5.1": { "d": "sdnsKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.2": { "d": "sdnsUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.3": { "d": "sdnsKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.4": { "d": "fortezzaKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.5": { "d": "fortezzaKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.6": { "d": "fortezzaUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.7": { "d": "fortezzaCASignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.8": { "d": "sdnsCASignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.10": { "d": "auxiliaryVector", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.11": { "d": "mlReceiptPolicy", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.12": { "d": "mlMembership", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.13": { "d": "mlAdministrators", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.14": { "d": "alid", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.20": { "d": "janUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.21": { "d": "febUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.22": { "d": "marUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.23": { "d": "aprUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.24": { "d": "mayUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.25": { "d": "junUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.26": { "d": "julUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.27": { "d": "augUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.28": { "d": "sepUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.29": { "d": "octUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.30": { "d": "novUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.31": { "d": "decUKMs", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.40": { "d": "metaSDNSckl", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.41": { "d": "sdnsCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.42": { "d": "metaSDNSsignatureCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.43": { "d": "sdnsSignatureCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.44": { "d": "sdnsCertificateRevocationList", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.45": { "d": "fortezzaCertificateRevocationList", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.46": { "d": "fortezzaCKL", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.47": { "d": "alExemptedAddressProcessor", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.48": { "d": "guard", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.49": { "d": "algorithmsSupported", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.50": { "d": "suiteAKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.51": { "d": "suiteAKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.52": { "d": "suiteAUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.53": { "d": "prbacInfo", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.54": { "d": "prbacCAConstraints", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.55": { "d": "sigOrKMPrivileges", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.56": { "d": "commPrivileges", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.57": { "d": "labeledAttribute", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.58": { "d": "policyInformationFile", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.59": { "d": "secPolicyInformationFile", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.5.60": { "d": "cAClearanceConstraint", "c": "SDN.700 INFOSEC attributes", "w": false }, +"2.16.840.1.101.2.1.7.1": { "d": "cspExtns", "c": "SDN.700 INFOSEC extensions", "w": false }, +"2.16.840.1.101.2.1.7.1.0": { "d": "cspCsExtn", "c": "SDN.700 INFOSEC extensions", "w": false }, +"2.16.840.1.101.2.1.8.1": { "d": "mISSISecurityCategories", "c": "SDN.700 INFOSEC security category", "w": false }, +"2.16.840.1.101.2.1.8.2": { "d": "standardSecurityLabelPrivileges", "c": "SDN.700 INFOSEC security category", "w": false }, +"2.16.840.1.101.2.1.10.1": { "d": "sigPrivileges", "c": "SDN.700 INFOSEC privileges", "w": false }, +"2.16.840.1.101.2.1.10.2": { "d": "kmPrivileges", "c": "SDN.700 INFOSEC privileges", "w": false }, +"2.16.840.1.101.2.1.10.3": { "d": "namedTagSetPrivilege", "c": "SDN.700 INFOSEC privileges", "w": false }, +"2.16.840.1.101.2.1.11.1": { "d": "ukDemo", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.2": { "d": "usDODClass2", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.3": { "d": "usMediumPilot", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.4": { "d": "usDODClass4", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.5": { "d": "usDODClass3", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.11.6": { "d": "usDODClass5", "c": "SDN.700 INFOSEC certificate policy", "w": false }, +"2.16.840.1.101.2.1.12.0": { "d": "testSecurityPolicy", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1": { "d": "tsp1", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0": { "d": "tsp1SecurityCategories", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0.0": { "d": "tsp1TagSetZero", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0.1": { "d": "tsp1TagSetOne", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.1.0.2": { "d": "tsp1TagSetTwo", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2": { "d": "tsp2", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0": { "d": "tsp2SecurityCategories", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0.0": { "d": "tsp2TagSetZero", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0.1": { "d": "tsp2TagSetOne", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.2.0.2": { "d": "tsp2TagSetTwo", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3": { "d": "kafka", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0": { "d": "kafkaSecurityCategories", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0.1": { "d": "kafkaTagSetName1", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0.2": { "d": "kafkaTagSetName2", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.0.3.0.3": { "d": "kafkaTagSetName3", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.2.1.12.1.1": { "d": "tcp1", "c": "SDN.700 INFOSEC test objects", "w": false }, +"2.16.840.1.101.3.1": { "d": "slabel", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.2": { "d": "pki", "c": "NIST", "w": true }, +"2.16.840.1.101.3.2.1": { "d": "NIST policyIdentifier", "c": "NIST policies", "w": true }, +"2.16.840.1.101.3.2.1.3.1": { "d": "fbcaRudimentaryPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.3.2": { "d": "fbcaBasicPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.3.3": { "d": "fbcaMediumPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.3.4": { "d": "fbcaHighPolicy", "c": "Federal Bridge CA Policy", "w": false }, +"2.16.840.1.101.3.2.1.48.1": { "d": "nistTestPolicy1", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.2": { "d": "nistTestPolicy2", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.3": { "d": "nistTestPolicy3", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.4": { "d": "nistTestPolicy4", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.5": { "d": "nistTestPolicy5", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.1.48.6": { "d": "nistTestPolicy6", "c": "NIST PKITS policies", "w": false }, +"2.16.840.1.101.3.2.2": { "d": "gak", "c": "CSOR GAK extended key usage", "w": true }, +"2.16.840.1.101.3.2.2.1": { "d": "kRAKey", "c": "CSOR GAK extended key usage", "w": true }, +"2.16.840.1.101.3.2.3": { "d": "extensions", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.1": { "d": "kRTechnique", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.2": { "d": "kRecoveryCapable", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.3": { "d": "kR", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.4": { "d": "keyRecoverySchemes", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.2.5": { "d": "krapola", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.3": { "d": "arpa", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.4": { "d": "nistAlgorithm", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1": { "d": "aes", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.1": { "d": "aes128-ECB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.2": { "d": "aes128-CBC", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.3": { "d": "aes128-OFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.4": { "d": "aes128-CFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.5": { "d": "aes128-wrap", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.6": { "d": "aes128-GCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.7": { "d": "aes128-CCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.8": { "d": "aes128-wrap-pad", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.21": { "d": "aes192-ECB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.22": { "d": "aes192-CBC", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.23": { "d": "aes192-OFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.24": { "d": "aes192-CFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.25": { "d": "aes192-wrap", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.26": { "d": "aes192-GCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.27": { "d": "aes192-CCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.28": { "d": "aes192-wrap-pad", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.41": { "d": "aes256-ECB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.42": { "d": "aes256-CBC", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.43": { "d": "aes256-OFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.44": { "d": "aes256-CFB", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.45": { "d": "aes256-wrap", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.46": { "d": "aes256-GCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.47": { "d": "aes256-CCM", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.1.48": { "d": "aes256-wrap-pad", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2": { "d": "hashAlgos", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.1": { "d": "sha-256", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.2": { "d": "sha-384", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.3": { "d": "sha-512", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.2.4": { "d": "sha-224", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.3.1": { "d": "dsaWithSha224", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.101.3.4.3.2": { "d": "dsaWithSha256", "c": "NIST Algorithm", "w": false }, +"2.16.840.1.113719.1.2.8": { "d": "novellAlgorithm", "c": "Novell", "w": false }, +"2.16.840.1.113719.1.2.8.22": { "d": "desCbcIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.23": { "d": "desCbcPadIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.24": { "d": "desEDE2CbcIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.25": { "d": "desEDE2CbcPadIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.26": { "d": "desEDE3CbcIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.27": { "d": "desEDE3CbcPadIV8", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.28": { "d": "rc5CbcPad", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.29": { "d": "md2WithRSAEncryptionBSafe1", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.30": { "d": "md5WithRSAEncryptionBSafe1", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.31": { "d": "sha1WithRSAEncryptionBSafe1", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.32": { "d": "lmDigest", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.40": { "d": "md2", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.50": { "d": "md5", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.51": { "d": "ikeHmacWithSHA1-RSA", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.52": { "d": "ikeHmacWithMD5-RSA", "c": "Novell signature algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.69": { "d": "rc2CbcPad", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.82": { "d": "sha-1", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.92": { "d": "rc2BSafe1Cbc", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.95": { "d": "md4", "c": "Novell digest algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.130": { "d": "md4Packet", "c": "Novell keyed hash", "w": false }, +"2.16.840.1.113719.1.2.8.131": { "d": "rsaEncryptionBsafe1", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.132": { "d": "nwPassword", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.2.8.133": { "d": "novellObfuscate-1", "c": "Novell encryption algorithm", "w": false }, +"2.16.840.1.113719.1.9": { "d": "pki", "c": "Novell", "w": false }, +"2.16.840.1.113719.1.9.4": { "d": "pkiAttributeType", "c": "Novell PKI", "w": false }, +"2.16.840.1.113719.1.9.4.1": { "d": "securityAttributes", "c": "Novell PKI attribute type", "w": false }, +"2.16.840.1.113719.1.9.4.2": { "d": "relianceLimit", "c": "Novell PKI attribute type", "w": false }, +"2.16.840.1.113730.1": { "d": "cert-extension", "c": "Netscape", "w": false }, +"2.16.840.1.113730.1.1": { "d": "netscape-cert-type", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.2": { "d": "netscape-base-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.3": { "d": "netscape-revocation-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.4": { "d": "netscape-ca-revocation-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.7": { "d": "netscape-cert-renewal-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.8": { "d": "netscape-ca-policy-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.9": { "d": "HomePage-url", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.10": { "d": "EntityLogo", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.11": { "d": "UserPicture", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.12": { "d": "netscape-ssl-server-name", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.1.13": { "d": "netscape-comment", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.2": { "d": "data-type", "c": "Netscape", "w": false }, +"2.16.840.1.113730.2.1": { "d": "dataGIF", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.2": { "d": "dataJPEG", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.3": { "d": "dataURL", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.4": { "d": "dataHTML", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.5": { "d": "certSequence", "c": "Netscape data type", "w": false }, +"2.16.840.1.113730.2.6": { "d": "certURL", "c": "Netscape certificate extension", "w": false }, +"2.16.840.1.113730.3": { "d": "directory", "c": "Netscape", "w": false }, +"2.16.840.1.113730.3.1": { "d": "ldapDefinitions", "c": "Netscape directory", "w": false }, +"2.16.840.1.113730.3.1.1": { "d": "carLicense", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.1.2": { "d": "departmentNumber", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.1.3": { "d": "employeeNumber", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.1.4": { "d": "employeeType", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.3.2.2": { "d": "inetOrgPerson", "c": "Netscape LDAP definitions", "w": false }, +"2.16.840.1.113730.4.1": { "d": "serverGatedCrypto", "c": "Netscape", "w": false }, +"2.16.840.1.113733.1.6.3": { "d": "verisignCZAG", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.6": { "d": "verisignInBox", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.11": { "d": "verisignOnsiteJurisdictionHash", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.13": { "d": "Unknown Verisign VPN extension", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.6.15": { "d": "verisignServerID", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.7.1.1": { "d": "verisignCertPolicies95Qualifier1", "c": "Verisign policy", "w": false }, +"2.16.840.1.113733.1.7.1.1.1": { "d": "verisignCPSv1notice", "c": "Verisign policy (obsolete)", "w": false }, +"2.16.840.1.113733.1.7.1.1.2": { "d": "verisignCPSv1nsi", "c": "Verisign policy (obsolete)", "w": false }, +"2.16.840.1.113733.1.7.23.6": { "d": "verisignEVPolicy", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.8.1": { "d": "verisignISSStrongCrypto", "c": "Verisign", "w": false }, +"2.16.840.1.113733.1": { "d": "pki", "c": "Verisign extension", "w": false }, +"2.16.840.1.113733.1.9": { "d": "pkcs7Attribute", "c": "Verisign PKI extension", "w": false }, +"2.16.840.1.113733.1.9.2": { "d": "messageType", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.3": { "d": "pkiStatus", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.4": { "d": "failInfo", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.5": { "d": "senderNonce", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.6": { "d": "recipientNonce", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.7": { "d": "transID", "c": "Verisign PKCS #7 attribute", "w": false }, +"2.16.840.1.113733.1.9.8": { "d": "extensionReq", "c": "Verisign PKCS #7 attribute. Use PKCS #9 extensionRequest instead", "w": true }, +"2.16.840.1.114412.1.3.0.1": { "d": "digiCertGlobalCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.16.840.1.114412.1.3.0.2": { "d": "digiCertHighAssuranceEVCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.16.840.1.114412.1.3.0.3": { "d": "digiCertGlobalRootCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.16.840.1.114412.1.3.0.4": { "d": "digiCertAssuredIDRootCAPolicy", "c": "Digicert CA policy", "w": false }, +"2.23.42.0": { "d": "contentType", "c": "SET", "w": false }, +"2.23.42.0.0": { "d": "panData", "c": "SET contentType", "w": false }, +"2.23.42.0.1": { "d": "panToken", "c": "SET contentType", "w": false }, +"2.23.42.0.2": { "d": "panOnly", "c": "SET contentType", "w": false }, +"2.23.42.1": { "d": "msgExt", "c": "SET", "w": false }, +"2.23.42.2": { "d": "field", "c": "SET", "w": false }, +"2.23.42.2.0": { "d": "fullName", "c": "SET field", "w": false }, +"2.23.42.2.1": { "d": "givenName", "c": "SET field", "w": false }, +"2.23.42.2.2": { "d": "familyName", "c": "SET field", "w": false }, +"2.23.42.2.3": { "d": "birthFamilyName", "c": "SET field", "w": false }, +"2.23.42.2.4": { "d": "placeName", "c": "SET field", "w": false }, +"2.23.42.2.5": { "d": "identificationNumber", "c": "SET field", "w": false }, +"2.23.42.2.6": { "d": "month", "c": "SET field", "w": false }, +"2.23.42.2.7": { "d": "date", "c": "SET field", "w": false }, +"2.23.42.2.8": { "d": "address", "c": "SET field", "w": false }, +"2.23.42.2.9": { "d": "telephone", "c": "SET field", "w": false }, +"2.23.42.2.10": { "d": "amount", "c": "SET field", "w": false }, +"2.23.42.2.11": { "d": "accountNumber", "c": "SET field", "w": false }, +"2.23.42.2.12": { "d": "passPhrase", "c": "SET field", "w": false }, +"2.23.42.3": { "d": "attribute", "c": "SET", "w": false }, +"2.23.42.3.0": { "d": "cert", "c": "SET attribute", "w": false }, +"2.23.42.3.0.0": { "d": "rootKeyThumb", "c": "SET cert attribute", "w": false }, +"2.23.42.3.0.1": { "d": "additionalPolicy", "c": "SET cert attribute", "w": false }, +"2.23.42.4": { "d": "algorithm", "c": "SET", "w": false }, +"2.23.42.5": { "d": "policy", "c": "SET", "w": false }, +"2.23.42.5.0": { "d": "root", "c": "SET policy", "w": false }, +"2.23.42.6": { "d": "module", "c": "SET", "w": false }, +"2.23.42.7": { "d": "certExt", "c": "SET", "w": false }, +"2.23.42.7.0": { "d": "hashedRootKey", "c": "SET cert extension", "w": false }, +"2.23.42.7.1": { "d": "certificateType", "c": "SET cert extension", "w": false }, +"2.23.42.7.2": { "d": "merchantData", "c": "SET cert extension", "w": false }, +"2.23.42.7.3": { "d": "cardCertRequired", "c": "SET cert extension", "w": false }, +"2.23.42.7.4": { "d": "tunneling", "c": "SET cert extension", "w": false }, +"2.23.42.7.5": { "d": "setExtensions", "c": "SET cert extension", "w": false }, +"2.23.42.7.6": { "d": "setQualifier", "c": "SET cert extension", "w": false }, +"2.23.42.8": { "d": "brand", "c": "SET", "w": false }, +"2.23.42.8.1": { "d": "IATA-ATA", "c": "SET brand", "w": false }, +"2.23.42.8.4": { "d": "VISA", "c": "SET brand", "w": false }, +"2.23.42.8.5": { "d": "MasterCard", "c": "SET brand", "w": false }, +"2.23.42.8.30": { "d": "Diners", "c": "SET brand", "w": false }, +"2.23.42.8.34": { "d": "AmericanExpress", "c": "SET brand", "w": false }, +"2.23.42.8.6011": { "d": "Novus", "c": "SET brand", "w": false }, +"2.23.42.9": { "d": "vendor", "c": "SET", "w": false }, +"2.23.42.9.0": { "d": "GlobeSet", "c": "SET vendor", "w": false }, +"2.23.42.9.1": { "d": "IBM", "c": "SET vendor", "w": false }, +"2.23.42.9.2": { "d": "CyberCash", "c": "SET vendor", "w": false }, +"2.23.42.9.3": { "d": "Terisa", "c": "SET vendor", "w": false }, +"2.23.42.9.4": { "d": "RSADSI", "c": "SET vendor", "w": false }, +"2.23.42.9.5": { "d": "VeriFone", "c": "SET vendor", "w": false }, +"2.23.42.9.6": { "d": "TrinTech", "c": "SET vendor", "w": false }, +"2.23.42.9.7": { "d": "BankGate", "c": "SET vendor", "w": false }, +"2.23.42.9.8": { "d": "GTE", "c": "SET vendor", "w": false }, +"2.23.42.9.9": { "d": "CompuSource", "c": "SET vendor", "w": false }, +"2.23.42.9.10": { "d": "Griffin", "c": "SET vendor", "w": false }, +"2.23.42.9.11": { "d": "Certicom", "c": "SET vendor", "w": false }, +"2.23.42.9.12": { "d": "OSS", "c": "SET vendor", "w": false }, +"2.23.42.9.13": { "d": "TenthMountain", "c": "SET vendor", "w": false }, +"2.23.42.9.14": { "d": "Antares", "c": "SET vendor", "w": false }, +"2.23.42.9.15": { "d": "ECC", "c": "SET vendor", "w": false }, +"2.23.42.9.16": { "d": "Maithean", "c": "SET vendor", "w": false }, +"2.23.42.9.17": { "d": "Netscape", "c": "SET vendor", "w": false }, +"2.23.42.9.18": { "d": "Verisign", "c": "SET vendor", "w": false }, +"2.23.42.9.19": { "d": "BlueMoney", "c": "SET vendor", "w": false }, +"2.23.42.9.20": { "d": "Lacerte", "c": "SET vendor", "w": false }, +"2.23.42.9.21": { "d": "Fujitsu", "c": "SET vendor", "w": false }, +"2.23.42.9.22": { "d": "eLab", "c": "SET vendor", "w": false }, +"2.23.42.9.23": { "d": "Entrust", "c": "SET vendor", "w": false }, +"2.23.42.9.24": { "d": "VIAnet", "c": "SET vendor", "w": false }, +"2.23.42.9.25": { "d": "III", "c": "SET vendor", "w": false }, +"2.23.42.9.26": { "d": "OpenMarket", "c": "SET vendor", "w": false }, +"2.23.42.9.27": { "d": "Lexem", "c": "SET vendor", "w": false }, +"2.23.42.9.28": { "d": "Intertrader", "c": "SET vendor", "w": false }, +"2.23.42.9.29": { "d": "Persimmon", "c": "SET vendor", "w": false }, +"2.23.42.9.30": { "d": "NABLE", "c": "SET vendor", "w": false }, +"2.23.42.9.31": { "d": "espace-net", "c": "SET vendor", "w": false }, +"2.23.42.9.32": { "d": "Hitachi", "c": "SET vendor", "w": false }, +"2.23.42.9.33": { "d": "Microsoft", "c": "SET vendor", "w": false }, +"2.23.42.9.34": { "d": "NEC", "c": "SET vendor", "w": false }, +"2.23.42.9.35": { "d": "Mitsubishi", "c": "SET vendor", "w": false }, +"2.23.42.9.36": { "d": "NCR", "c": "SET vendor", "w": false }, +"2.23.42.9.37": { "d": "e-COMM", "c": "SET vendor", "w": false }, +"2.23.42.9.38": { "d": "Gemplus", "c": "SET vendor", "w": false }, +"2.23.42.10": { "d": "national", "c": "SET", "w": false }, +"2.23.42.10.392": { "d": "Japan", "c": "SET national", "w": false }, +"2.23.136.1.1.1": { "d": "mRTDSignatureData", "c": "ICAO MRTD", "w": false }, +"2.54.1775.2": { "d": "hashedRootKey", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.3": { "d": "certificateType", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.4": { "d": "merchantData", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.5": { "d": "cardCertRequired", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.6": { "d": "tunneling", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.7": { "d": "setQualifier", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.99": { "d": "setData", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"1.3.6.1.4.1.6449.1.2.1.5.1": { "d": "AddTrust EV policy", "c": "AddTrust External CA Root", "w": false }, +"1.3.6.1.4.1.34697.2.1": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Commercial", "w": false }, +"1.3.6.1.4.1.34697.2.2": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Networking", "w": false }, +"1.3.6.1.4.1.34697.2.3": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Premium", "w": false }, +"1.3.6.1.4.1.34697.2.4": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Premium ECC", "w": false }, +"2.16.578.1.26.1.3.3": { "d": "BuyPass EV policy", "c": "BuyPass Class 3 EV", "w": false }, +"1.3.6.1.4.1.22234.2.5.2.3.1": { "d": "CertPlus EV policy", "c": "CertPlus Class 2 Primary CA (KEYNECTIS)", "w": false }, +"1.3.6.1.4.1.6334.1.100.1": { "d": "Cybertrust EV policy", "c": "Cybertrust Global Root", "w": false }, +"2.16.840.1.114412.2.1": { "d": "DigiCert EV policy", "c": "DigiCert High Assurance EV Root CA", "w": false }, +"2.16.528.1.1001.1.1.1.12.6.1.1.1": { "d": "DigiNotar EV policy", "c": "DigiNotar Root CA", "w": false }, +"2.16.840.1.114028.10.1.2": { "d": "Entrust EV policy", "c": "Entrust Net Secure Server Certification Authority", "w": false }, +"1.3.6.1.4.1.14370.1.6": { "d": "Equifax EV policy", "c": "Equifax Secure Certificate Authority (GeoTrust)", "w": false }, +"1.3.6.1.4.1.4146.1.1": { "d": "GlobalSign EV policy", "c": "GlobalSign", "w": false }, +"2.16.840.1.114413.1.7.23.3": { "d": "GoDaddy EV policy", "c": "GoDaddy Class 2 Certification Authority", "w": false }, +"1.3.6.1.4.1.14777.6.1.1": { "d": "Izenpe EV policy", "c": "Certificado de Servidor Seguro SSL EV", "w": false }, +"1.3.6.1.4.1.14777.6.1.2": { "d": "Izenpe EV policy", "c": "Certificado de Sede Electronica EV", "w": false }, +"1.3.6.1.4.1.782.1.2.1.8.1": { "d": "Network Solutions EV policy", "c": "Network Solutions Certificate Authority", "w": false }, +"1.3.6.1.4.1.8024.0.2.100.1.2": { "d": "QuoVadis EV policy", "c": "QuoVadis Root CA 2", "w": false }, +"1.2.392.200091.100.721.1": { "d": "SECOM EV policy", "c": "SECOM Trust Systems EV", "w": false }, +"2.16.840.1.114404.1.1.2.4.1": { "d": "SecureTrust EV policy", "c": "SecureTrust CA, SecureTrust Corporation", "w": false }, +"1.3.6.1.4.1.23223.1.1.1": { "d": "StartCom EV policy", "c": "StartCom Certification Authority", "w": false }, +"2.16.840.1.114414.1.7.23.3": { "d": "Starfield EV policy", "c": "Starfield Class 2 Certification Authority", "w": false }, +"2.16.756.1.89.1.2.1.1": { "d": "SwissSign EV policy", "c": "SwissSign Gold CA - G2", "w": false }, +"2.16.840.1.113733.1.7.48.1": { "d": "Thawte EV policy", "c": "Thawte Premium Server CA", "w": false }, +"2.16.840.1.114171.500.9": { "d": "Wells Fargo EV policy", "c": "Wells Fargo WellsSecure Public Root Certificate Authority", "w": false }, +"END": "" +}; \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/LICENSE.txt new file mode 100644 index 0000000..e37d457 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/LICENSE.txt @@ -0,0 +1,42 @@ + + +Licensing +--------- + +This software is covered under the following copyright: + +/* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + +Address all questions regarding this license to: + + Tom Wu + tjw@cs.Stanford.EDU \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/README.md b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/README.md new file mode 100644 index 0000000..9ed2a96 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/README.md @@ -0,0 +1,6 @@ +These files are downloaded from http://www-cs-students.stanford.edu/~tjw/jsbn/ + +Here is a list of changes made to this library: + + - https://github.com/travist/jsencrypt/pull/6 + diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/base64.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/base64.ts new file mode 100644 index 0000000..424b880 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/base64.ts @@ -0,0 +1,76 @@ +import {int2char} from "./util"; + +const b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const b64pad = "="; + +export function hex2b64(h:string) { + let i; + let c; + let ret = ""; + for (i = 0; i + 3 <= h.length; i += 3) { + c = parseInt(h.substring(i, i + 3), 16); + ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63); + } + if (i + 1 == h.length) { + c = parseInt(h.substring(i, i + 1), 16); + ret += b64map.charAt(c << 2); + } else if (i + 2 == h.length) { + c = parseInt(h.substring(i, i + 2), 16); + ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); + } + while ((ret.length & 3) > 0) { + ret += b64pad; + } + return ret; +} + +// convert a base64 string to hex +export function b64tohex(s:string) { + let ret = ""; + let i; + let k = 0; // b64 state, 0-3 + let slop = 0; + for (i = 0; i < s.length; ++i) { + if (s.charAt(i) == b64pad) { + break; + } + const v = b64map.indexOf(s.charAt(i)); + if (v < 0) { + continue; + } + if (k == 0) { + ret += int2char(v >> 2); + slop = v & 3; + k = 1; + } else if (k == 1) { + ret += int2char((slop << 2) | (v >> 4)); + slop = v & 0xf; + k = 2; + } else if (k == 2) { + ret += int2char(slop); + ret += int2char(v >> 2); + slop = v & 3; + k = 3; + } else { + ret += int2char((slop << 2) | (v >> 4)); + ret += int2char(v & 0xf); + k = 0; + } + } + if (k == 1) { + ret += int2char(slop << 2); + } + return ret; +} + +// convert a base64 string to a byte/number array +export function b64toBA(s:string) { + // piggyback on b64tohex for now, optimize later + const h = b64tohex(s); + let i; + const a = []; + for (i = 0; 2 * i < h.length; ++i) { + a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16); + } + return a; +} diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/jsbn.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/jsbn.ts new file mode 100644 index 0000000..9fdb7d3 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/jsbn.ts @@ -0,0 +1,1928 @@ +// Copyright (c) 2005 Tom Wu +// All Rights Reserved. +// See "LICENSE" for details. + +// Basic JavaScript BN library - subset useful for RSA encryption. + +import {cbit, int2char, lbit, op_and, op_andnot, op_or, op_xor} from "./util"; +import {SecureRandom} from "./rng"; +// Bits per digit +let dbits; + +// JavaScript engine analysis +const canary = 0xdeadbeefcafe; +const j_lm = ((canary & 0xffffff) == 0xefcafe); + + +//#region +const lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]; +const lplim = (1 << 26) / lowprimes[lowprimes.length - 1]; +//#endregion + +// (public) Constructor +export class BigInteger { + constructor(a:number|number[]|string, b?:number|SecureRandom, c?:number|SecureRandom) { + if (a != null) { + if ("number" == typeof a) { + this.fromNumber(a, b, c); + } else if (b == null && "string" != typeof a) { + this.fromString(a, 256); + } else { + this.fromString(a, b as number); + } + } + } + + //#region PUBLIC + + // BigInteger.prototype.toString = bnToString; + // (public) return string representation in given radix + public toString(b:number):string { + if (this.s < 0) { + return "-" + this.negate().toString(b); + } + let k; + if (b == 16) { + k = 4; + } else if (b == 8) { + k = 3; + } else if (b == 2) { + k = 1; + } else if (b == 32) { + k = 5; + } else if (b == 4) { + k = 2; + } else { + return this.toRadix(b); + } + const km = (1 << k) - 1; + let d; + let m = false; + let r = ""; + let i = this.t; + let p = this.DB - (i * this.DB) % k; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) > 0) { + m = true; + r = int2char(d); + } + while (i >= 0) { + if (p < k) { + d = (this[i] & ((1 << p) - 1)) << (k - p); + d |= this[--i] >> (p += this.DB - k); + } else { + d = (this[i] >> (p -= k)) & km; + if (p <= 0) { + p += this.DB; + --i; + } + } + if (d > 0) { + m = true; + } + if (m) { + r += int2char(d); + } + } + } + return m ? r : "0"; + } + + + // BigInteger.prototype.negate = bnNegate; + // (public) -this + protected negate():BigInteger { + const r = nbi(); + BigInteger.ZERO.subTo(this, r); + return r; + } + + + // BigInteger.prototype.abs = bnAbs; + // (public) |this| + public abs() { + return (this.s < 0) ? this.negate() : this; + } + + + // BigInteger.prototype.compareTo = bnCompareTo; + // (public) return + if this > a, - if this < a, 0 if equal + public compareTo(a:BigInteger):number { + let r = this.s - a.s; + if (r != 0) { + return r; + } + let i = this.t; + r = i - a.t; + if (r != 0) { + return (this.s < 0) ? -r : r; + } + while (--i >= 0) { + if ((r = this[i] - a[i]) != 0) { + return r; + } + } + return 0; + } + + + // BigInteger.prototype.bitLength = bnBitLength; + // (public) return the number of bits in "this" + public bitLength() { + if (this.t <= 0) { + return 0; + } + return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM)); + } + + + // BigInteger.prototype.mod = bnMod; + // (public) this mod a + public mod(a:BigInteger):BigInteger { + const r = nbi(); + this.abs().divRemTo(a, null, r); + if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { + a.subTo(r, r); + } + return r; + } + + + // BigInteger.prototype.modPowInt = bnModPowInt; + // (public) this^e % m, 0 <= e < 2^32 + public modPowInt(e:number, m:BigInteger):BigInteger { + let z; + if (e < 256 || m.isEven()) { + z = new Classic(m); + } else { + z = new Montgomery(m); + } + return this.exp(e, z); + } + + + // BigInteger.prototype.clone = bnClone; + // (public) + protected clone():BigInteger { + const r = nbi(); + this.copyTo(r); + return r; + } + + + // BigInteger.prototype.intValue = bnIntValue; + // (public) return value as integer + protected intValue() { + if (this.s < 0) { + if (this.t == 1) { + return this[0] - this.DV; + } else if (this.t == 0) { + return -1; + } + } else if (this.t == 1) { + return this[0]; + } else if (this.t == 0) { + return 0; + } + // assumes 16 < DB < 32 + return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0]; + } + + + // BigInteger.prototype.byteValue = bnByteValue; + // (public) return value as byte + protected byteValue() { + return (this.t == 0) ? this.s : (this[0] << 24) >> 24; + } + + + // BigInteger.prototype.shortValue = bnShortValue; + // (public) return value as short (assumes DB>=16) + protected shortValue() { + return (this.t == 0) ? this.s : (this[0] << 16) >> 16; + } + + + // BigInteger.prototype.signum = bnSigNum; + // (public) 0 if this == 0, 1 if this > 0 + protected signum() { + if (this.s < 0) { + return -1; + } else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) { + return 0; + } else { + return 1; + } + } + + + // BigInteger.prototype.toByteArray = bnToByteArray; + // (public) convert to bigendian byte array + public toByteArray():number[] { + let i = this.t; + const r = []; + r[0] = this.s; + let p = this.DB - (i * this.DB) % 8; + let d; + let k = 0; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p) { + r[k++] = d | (this.s << (this.DB - p)); + } + while (i >= 0) { + if (p < 8) { + d = (this[i] & ((1 << p) - 1)) << (8 - p); + d |= this[--i] >> (p += this.DB - 8); + } else { + d = (this[i] >> (p -= 8)) & 0xff; + if (p <= 0) { + p += this.DB; + --i; + } + } + if ((d & 0x80) != 0) { + d |= -256; + } + if (k == 0 && (this.s & 0x80) != (d & 0x80)) { + ++k; + } + if (k > 0 || d != this.s) { + r[k++] = d; + } + } + } + return r; + } + + + // BigInteger.prototype.equals = bnEquals; + protected equals(a:BigInteger):boolean { + return (this.compareTo(a) == 0); + } + + + // BigInteger.prototype.min = bnMin; + protected min(a:BigInteger):BigInteger { + return (this.compareTo(a) < 0) ? this : a; + } + + + // BigInteger.prototype.max = bnMax; + protected max(a:BigInteger):BigInteger { + return (this.compareTo(a) > 0) ? this : a; + } + + + // BigInteger.prototype.and = bnAnd; + protected and(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_and, r); + return r; + } + + + // BigInteger.prototype.or = bnOr; + protected or(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_or, r); + return r; + } + + + // BigInteger.prototype.xor = bnXor; + protected xor(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_xor, r); + return r; + } + + + // BigInteger.prototype.andNot = bnAndNot; + protected andNot(a:BigInteger):BigInteger { + const r = nbi(); + this.bitwiseTo(a, op_andnot, r); + return r; + } + + + // BigInteger.prototype.not = bnNot; + // (public) ~this + protected not():BigInteger { + const r = nbi(); + for (let i = 0; i < this.t; ++i) { + r[i] = this.DM & ~this[i]; + } + r.t = this.t; + r.s = ~this.s; + return r; + } + + + // BigInteger.prototype.shiftLeft = bnShiftLeft; + // (public) this << n + protected shiftLeft(n:number) { + const r = nbi(); + if (n < 0) { + this.rShiftTo(-n, r); + } else { + this.lShiftTo(n, r); + } + return r; + } + + + // BigInteger.prototype.shiftRight = bnShiftRight; + // (public) this >> n + protected shiftRight(n:number) { + const r = nbi(); + if (n < 0) { + this.lShiftTo(-n, r); + } else { + this.rShiftTo(n, r); + } + return r; + } + + + // BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; + // (public) returns index of lowest 1-bit (or -1 if none) + protected getLowestSetBit() { + for (let i = 0; i < this.t; ++i) { + if (this[i] != 0) { + return i * this.DB + lbit(this[i]); + } + } + if (this.s < 0) { + return this.t * this.DB; + } + return -1; + } + + + // BigInteger.prototype.bitCount = bnBitCount; + // (public) return number of set bits + protected bitCount() { + let r = 0; + const x = this.s & this.DM; + for (let i = 0; i < this.t; ++i) { + r += cbit(this[i] ^ x); + } + return r; + } + + + // BigInteger.prototype.testBit = bnTestBit; + // (public) true iff nth bit is set + protected testBit(n:number) { + const j = Math.floor(n / this.DB); + if (j >= this.t) { + return (this.s != 0); + } + return ((this[j] & (1 << (n % this.DB))) != 0); + } + + + // BigInteger.prototype.setBit = bnSetBit; + // (public) this | (1< 1) { + const g2 = nbi(); + z.sqrTo(g[1], g2); + while (n <= km) { + g[n] = nbi(); + z.mulTo(g2, g[n - 2], g[n]); + n += 2; + } + } + + let j = e.t - 1; + let w; + let is1 = true; + let r2 = nbi(); + let t; + i = nbits(e[j]) - 1; + while (j >= 0) { + if (i >= k1) { + w = (e[j] >> (i - k1)) & km; + } else { + w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i); + if (j > 0) { + w |= e[j - 1] >> (this.DB + i - k1); + } + } + + n = k; + while ((w & 1) == 0) { + w >>= 1; + --n; + } + if ((i -= n) < 0) { + i += this.DB; + --j; + } + if (is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r); + is1 = false; + } else { + while (n > 1) { + z.sqrTo(r, r2); + z.sqrTo(r2, r); + n -= 2; + } + if (n > 0) { + z.sqrTo(r, r2); + } else { + t = r; + r = r2; + r2 = t; + } + z.mulTo(r2, g[w], r); + } + + while (j >= 0 && (e[j] & (1 << i)) == 0) { + z.sqrTo(r, r2); + t = r; + r = r2; + r2 = t; + if (--i < 0) { + i = this.DB - 1; + --j; + } + } + } + return z.revert(r); + } + + + // BigInteger.prototype.modInverse = bnModInverse; + // (public) 1/this % m (HAC 14.61) + public modInverse(m:BigInteger) { + const ac = m.isEven(); + if ((this.isEven() && ac) || m.signum() == 0) { + return BigInteger.ZERO; + } + const u = m.clone(); + const v = this.clone(); + const a = nbv(1); + const b = nbv(0); + const c = nbv(0); + const d = nbv(1); + while (u.signum() != 0) { + while (u.isEven()) { + u.rShiftTo(1, u); + if (ac) { + if (!a.isEven() || !b.isEven()) { + a.addTo(this, a); + b.subTo(m, b); + } + a.rShiftTo(1, a); + } else if (!b.isEven()) { + b.subTo(m, b); + } + b.rShiftTo(1, b); + } + while (v.isEven()) { + v.rShiftTo(1, v); + if (ac) { + if (!c.isEven() || !d.isEven()) { + c.addTo(this, c); + d.subTo(m, d); + } + c.rShiftTo(1, c); + } else if (!d.isEven()) { + d.subTo(m, d); + } + d.rShiftTo(1, d); + } + if (u.compareTo(v) >= 0) { + u.subTo(v, u); + if (ac) { + a.subTo(c, a); + } + b.subTo(d, b); + } else { + v.subTo(u, v); + if (ac) { c.subTo(a, c); } + d.subTo(b, d); + } + } + if (v.compareTo(BigInteger.ONE) != 0) { + return BigInteger.ZERO; + } + if (d.compareTo(m) >= 0) { + return d.subtract(m); + } + if (d.signum() < 0) { + d.addTo(m, d); + } else { + return d; + } + if (d.signum() < 0) { + return d.add(m); + } else { + return d; + } + } + + + // BigInteger.prototype.pow = bnPow; + // (public) this^e + protected pow(e:number) { + return this.exp(e, new NullExp()); + } + + + // BigInteger.prototype.gcd = bnGCD; + // (public) gcd(this,a) (HAC 14.54) + public gcd(a:BigInteger) { + let x = (this.s < 0) ? this.negate() : this.clone(); + let y = (a.s < 0) ? a.negate() : a.clone(); + if (x.compareTo(y) < 0) { + const t = x; + x = y; + y = t; + } + let i = x.getLowestSetBit(); + let g = y.getLowestSetBit(); + if (g < 0) { + return x; + } + if (i < g) { + g = i; + } + if (g > 0) { + x.rShiftTo(g, x); + y.rShiftTo(g, y); + } + while (x.signum() > 0) { + if ((i = x.getLowestSetBit()) > 0) { + x.rShiftTo(i, x); + } + if ((i = y.getLowestSetBit()) > 0) { + y.rShiftTo(i, y); + } + if (x.compareTo(y) >= 0) { + x.subTo(y, x); + x.rShiftTo(1, x); + } else { + y.subTo(x, y); + y.rShiftTo(1, y); + } + } + if (g > 0) { + y.lShiftTo(g, y); + } + return y; + } + + + // BigInteger.prototype.isProbablePrime = bnIsProbablePrime; + // (public) test primality with certainty >= 1-.5^t + public isProbablePrime(t:number) { + let i; + const x = this.abs(); + if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) { + for (i = 0; i < lowprimes.length; ++i) { + if (x[0] == lowprimes[i]) { + return true; + } + } + return false; + } + if (x.isEven()) { + return false; + } + i = 1; + while (i < lowprimes.length) { + let m = lowprimes[i]; + let j = i + 1; + while (j < lowprimes.length && m < lplim) { + m *= lowprimes[j++]; + } + m = x.modInt(m); + while (i < j) { + if (m % lowprimes[i++] == 0) { + return false; + } + } + } + return x.millerRabin(t); + } + + + //#endregion PUBLIC + + //#region PROTECTED + + // BigInteger.prototype.copyTo = bnpCopyTo; + // (protected) copy this to r + public copyTo(r:BigInteger) { + for (let i = this.t - 1; i >= 0; --i) { + r[i] = this[i]; + } + r.t = this.t; + r.s = this.s; + } + + + // BigInteger.prototype.fromInt = bnpFromInt; + // (protected) set from integer value x, -DV <= x < DV + public fromInt(x:number) { + this.t = 1; + this.s = (x < 0) ? -1 : 0; + if (x > 0) { + this[0] = x; + } else if (x < -1) { + this[0] = x + this.DV; + } else { + this.t = 0; + } + } + + + // BigInteger.prototype.fromString = bnpFromString; + // (protected) set from string and radix + protected fromString(s:string|number[], b:number) { + let k; + if (b == 16) { + k = 4; + } else if (b == 8) { + k = 3; + } else if (b == 256) { + k = 8; + /* byte array */ + } else if (b == 2) { + k = 1; + } else if (b == 32) { + k = 5; + } else if (b == 4) { + k = 2; + } else { + this.fromRadix(s as string, b); + return; + } + this.t = 0; + this.s = 0; + let i = s.length; + let mi = false; + let sh = 0; + while (--i >= 0) { + const x = (k == 8) ? (+s[i]) & 0xff : intAt(s as string, i); + if (x < 0) { + if ((s as string).charAt(i) == "-") { + mi = true; + } + continue; + } + mi = false; + if (sh == 0) { + this[this.t++] = x; + } else if (sh + k > this.DB) { + this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh; + this[this.t++] = (x >> (this.DB - sh)); + } else { + this[this.t - 1] |= x << sh; + } + sh += k; + if (sh >= this.DB) { + sh -= this.DB; + } + } + if (k == 8 && ((+s[0]) & 0x80) != 0) { + this.s = -1; + if (sh > 0) { + this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh; + } + } + this.clamp(); + if (mi) { + BigInteger.ZERO.subTo(this, this); + } + } + + + // BigInteger.prototype.clamp = bnpClamp; + // (protected) clamp off excess high words + public clamp() { + const c = this.s & this.DM; + while (this.t > 0 && this[this.t - 1] == c) { + --this.t; + } + } + + + // BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + // (protected) r = this << n*DB + public dlShiftTo(n:number, r:BigInteger) { + let i; + for (i = this.t - 1; i >= 0; --i) { + r[i + n] = this[i]; + } + for (i = n - 1; i >= 0; --i) { + r[i] = 0; + } + r.t = this.t + n; + r.s = this.s; + } + + + // BigInteger.prototype.drShiftTo = bnpDRShiftTo; + // (protected) r = this >> n*DB + public drShiftTo(n:number, r:BigInteger) { + for (let i = n; i < this.t; ++i) { + r[i - n] = this[i]; + } + r.t = Math.max(this.t - n, 0); + r.s = this.s; + } + + + // BigInteger.prototype.lShiftTo = bnpLShiftTo; + // (protected) r = this << n + protected lShiftTo(n:number, r:BigInteger) { + const bs = n % this.DB; + const cbs = this.DB - bs; + const bm = (1 << cbs) - 1; + const ds = Math.floor(n / this.DB); + let c = (this.s << bs) & this.DM; + + for (let i = this.t - 1; i >= 0; --i) { + r[i + ds + 1] = (this[i] >> cbs) | c; + c = (this[i] & bm) << bs; + } + for (let i = ds - 1; i >= 0; --i) { + r[i] = 0; + } + r[ds] = c; + r.t = this.t + ds + 1; + r.s = this.s; + r.clamp(); + } + + + // BigInteger.prototype.rShiftTo = bnpRShiftTo; + // (protected) r = this >> n + protected rShiftTo(n:number, r:BigInteger) { + r.s = this.s; + const ds = Math.floor(n / this.DB); + if (ds >= this.t) { + r.t = 0; + return; + } + const bs = n % this.DB; + const cbs = this.DB - bs; + const bm = (1 << bs) - 1; + r[0] = this[ds] >> bs; + for (let i = ds + 1; i < this.t; ++i) { + r[i - ds - 1] |= (this[i] & bm) << cbs; + r[i - ds] = this[i] >> bs; + } + if (bs > 0) { + r[this.t - ds - 1] |= (this.s & bm) << cbs; + } + r.t = this.t - ds; + r.clamp(); + } + + + // BigInteger.prototype.subTo = bnpSubTo; + // (protected) r = this - a + public subTo(a:BigInteger, r:BigInteger) { + let i = 0; + let c = 0; + const m = Math.min(a.t, this.t); + while (i < m) { + c += this[i] - a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + if (a.t < this.t) { + c -= a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } else { + c += this.s; + while (i < a.t) { + c -= a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c < -1) { + r[i++] = this.DV + c; + } else if (c > 0) { + r[i++] = c; + } + r.t = i; + r.clamp(); + } + + + // BigInteger.prototype.multiplyTo = bnpMultiplyTo; + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + public multiplyTo(a:BigInteger, r:BigInteger) { + const x = this.abs(); + const y = a.abs(); + let i = x.t; + r.t = i + y.t; + while (--i >= 0) { + r[i] = 0; + } + for (i = 0; i < y.t; ++i) { + r[i + x.t] = x.am(0, y[i], r, i, 0, x.t); + } + r.s = 0; + r.clamp(); + if (this.s != a.s) { + BigInteger.ZERO.subTo(r, r); + } + } + + + // BigInteger.prototype.squareTo = bnpSquareTo; + // (protected) r = this^2, r != this (HAC 14.16) + public squareTo(r:BigInteger) { + const x = this.abs(); + let i = r.t = 2 * x.t; + while (--i >= 0) { + r[i] = 0; + } + for (i = 0; i < x.t - 1; ++i) { + const c = x.am(i, x[i], r, 2 * i, 0, 1); + if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { + r[i + x.t] -= x.DV; + r[i + x.t + 1] = 1; + } + } + if (r.t > 0) { + r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1); + } + r.s = 0; + r.clamp(); + } + + + // BigInteger.prototype.divRemTo = bnpDivRemTo; + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + public divRemTo(m:BigInteger, q:BigInteger, r:BigInteger) { + const pm = m.abs(); + if (pm.t <= 0) { + return; + } + const pt = this.abs(); + if (pt.t < pm.t) { + if (q != null) { + q.fromInt(0); + } + if (r != null) { + this.copyTo(r); + } + return; + } + if (r == null) { + r = nbi(); + } + const y = nbi(); + const ts = this.s; + const ms = m.s; + const nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus + if (nsh > 0) { + pm.lShiftTo(nsh, y); + pt.lShiftTo(nsh, r); + } else { + pm.copyTo(y); + pt.copyTo(r); + } + const ys = y.t; + const y0 = y[ys - 1]; + if (y0 == 0) { + return; + } + const yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0); + const d1 = this.FV / yt; + const d2 = (1 << this.F1) / yt; + const e = 1 << this.F2; + let i = r.t; + let j = i - ys; + const t = (q == null) ? nbi() : q; + y.dlShiftTo(j, t); + if (r.compareTo(t) >= 0) { + r[r.t++] = 1; + r.subTo(t, r); + } + BigInteger.ONE.dlShiftTo(ys, t); + t.subTo(y, y); // "negative" y so we can replace sub with am later + while (y.t < ys) { + y[y.t++] = 0; + } + while (--j >= 0) { + // Estimate quotient digit + let qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2); + if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out + y.dlShiftTo(j, t); + r.subTo(t, r); + while (r[i] < --qd) { + r.subTo(t, r); + } + } + } + if (q != null) { + r.drShiftTo(ys, q); + if (ts != ms) { + BigInteger.ZERO.subTo(q, q); + } + } + r.t = ys; + r.clamp(); + if (nsh > 0) { + r.rShiftTo(nsh, r); + } // Denormalize remainder + if (ts < 0) { + BigInteger.ZERO.subTo(r, r); + } + } + + + // BigInteger.prototype.invDigit = bnpInvDigit; + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + public invDigit():number { + if (this.t < 1) { + return 0; + } + const x = this[0]; + if ((x & 1) == 0) { + return 0; + } + let y = x & 3; // y == 1/x mod 2^2 + y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 + y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 + y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y > 0) ? this.DV - y : -y; + } + + + // BigInteger.prototype.isEven = bnpIsEven; + // (protected) true iff this is even + protected isEven() { + return ((this.t > 0) ? (this[0] & 1) : this.s) == 0; + } + + + // BigInteger.prototype.exp = bnpExp; + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + protected exp(e:number, z:IReduction) { + if (e > 0xffffffff || e < 1) { + return BigInteger.ONE; + } + let r = nbi(); + let r2 = nbi(); + const g = z.convert(this); + let i = nbits(e) - 1; + g.copyTo(r); + while (--i >= 0) { + z.sqrTo(r, r2); + if ((e & (1 << i)) > 0) { + z.mulTo(r2, g, r); + } else { + const t = r; + r = r2; + r2 = t; + } + } + return z.revert(r); + } + + + // BigInteger.prototype.chunkSize = bnpChunkSize; + // (protected) return x s.t. r^x < DV + protected chunkSize(r:number) { + return Math.floor(Math.LN2 * this.DB / Math.log(r)); + } + + + // BigInteger.prototype.toRadix = bnpToRadix; + // (protected) convert to radix string + protected toRadix(b:number) { + if (b == null) { + b = 10; + } + if (this.signum() == 0 || b < 2 || b > 36) { + return "0"; + } + const cs = this.chunkSize(b); + const a = Math.pow(b, cs); + const d = nbv(a); + const y = nbi(); + const z = nbi(); + let r = ""; + this.divRemTo(d, y, z); + while (y.signum() > 0) { + r = (a + z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d, y, z); + } + return z.intValue().toString(b) + r; + } + + + // BigInteger.prototype.fromRadix = bnpFromRadix; + // (protected) convert from radix string + public fromRadix(s:string, b:number) { + this.fromInt(0); + if (b == null) { + b = 10; + } + const cs = this.chunkSize(b); + const d = Math.pow(b, cs); + let mi = false; + let j = 0; + let w = 0; + for (let i = 0; i < s.length; ++i) { + const x = intAt(s, i); + if (x < 0) { + if (s.charAt(i) == "-" && this.signum() == 0) { + mi = true; + } + continue; + } + w = b * w + x; + if (++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w, 0); + j = 0; + w = 0; + } + } + if (j > 0) { + this.dMultiply(Math.pow(b, j)); + this.dAddOffset(w, 0); + } + if (mi) { + BigInteger.ZERO.subTo(this, this); + } + } + + + // BigInteger.prototype.fromNumber = bnpFromNumber; + // (protected) alternate constructor + protected fromNumber(a:number, b:number|SecureRandom, c?:number|SecureRandom) { + if ("number" == typeof b) { + // new BigInteger(int,int,RNG) + if (a < 2) { + this.fromInt(1); + } else { + this.fromNumber(a, c); + if (!this.testBit(a - 1)) { + // force MSB set + this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this); + } + if (this.isEven()) { + this.dAddOffset(1, 0); + } // force odd + while (!this.isProbablePrime(b)) { + this.dAddOffset(2, 0); + if (this.bitLength() > a) { + this.subTo(BigInteger.ONE.shiftLeft(a - 1), this); + } + } + } + } else { + // new BigInteger(int,RNG) + const x:number[] = []; + const t = a & 7; + x.length = (a >> 3) + 1; + b.nextBytes(x); + if (t > 0) { + x[0] &= ((1 << t) - 1); + } else { + x[0] = 0; + } + this.fromString(x, 256); + } + } + + + // BigInteger.prototype.bitwiseTo = bnpBitwiseTo; + // (protected) r = this op a (bitwise) + protected bitwiseTo(a:BigInteger, op:(a:number, b:number) => number, r:BigInteger) { + let i; + let f; + const m = Math.min(a.t, this.t); + for (i = 0; i < m; ++i) { + r[i] = op(this[i], a[i]); + } + if (a.t < this.t) { + f = a.s & this.DM; + for (i = m; i < this.t; ++i) { + r[i] = op(this[i], f); + } + r.t = this.t; + } else { + f = this.s & this.DM; + for (i = m; i < a.t; ++i) { + r[i] = op(f, a[i]); + } + r.t = a.t; + } + r.s = op(this.s, a.s); + r.clamp(); + } + + + // BigInteger.prototype.changeBit = bnpChangeBit; + // (protected) this op (1< number) { + const r = BigInteger.ONE.shiftLeft(n); + this.bitwiseTo(r, op, r); + return r; + } + + + // BigInteger.prototype.addTo = bnpAddTo; + // (protected) r = this + a + protected addTo(a:BigInteger, r:BigInteger) { + let i = 0; + let c = 0; + const m = Math.min(a.t, this.t); + while (i < m) { + c += this[i] + a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + if (a.t < this.t) { + c += a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } else { + c += this.s; + while (i < a.t) { + c += a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c > 0) { + r[i++] = c; + } else if (c < -1) { + r[i++] = this.DV + c; + } + r.t = i; + r.clamp(); + } + + + // BigInteger.prototype.dMultiply = bnpDMultiply; + // (protected) this *= n, this >= 0, 1 < n < DV + protected dMultiply(n:number) { + this[this.t] = this.am(0, n - 1, this, 0, 0, this.t); + ++this.t; + this.clamp(); + } + + + // BigInteger.prototype.dAddOffset = bnpDAddOffset; + // (protected) this += n << w words, this >= 0 + public dAddOffset(n:number, w:number) { + if (n == 0) { + return; + } + while (this.t <= w) { + this[this.t++] = 0; + } + this[w] += n; + while (this[w] >= this.DV) { + this[w] -= this.DV; + if (++w >= this.t) { + this[this.t++] = 0; + } + ++this[w]; + } + } + + + // BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; + // (protected) r = lower n words of "this * a", a.t <= n + // "this" should be the larger one if appropriate. + public multiplyLowerTo(a:BigInteger, n:number, r:BigInteger) { + let i = Math.min(this.t + a.t, n); + r.s = 0; // assumes a,this >= 0 + r.t = i; + while (i > 0) { + r[--i] = 0; + } + for (const j = r.t - this.t; i < j; ++i) { + r[i + this.t] = this.am(0, a[i], r, i, 0, this.t); + } + for (const j = Math.min(a.t, n); i < j; ++i) { + this.am(0, a[i], r, i, 0, n - i); + } + r.clamp(); + } + + + // BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; + // (protected) r = "this * a" without lower n words, n > 0 + // "this" should be the larger one if appropriate. + public multiplyUpperTo(a:BigInteger, n:number, r:BigInteger) { + --n; + let i = r.t = this.t + a.t - n; + r.s = 0; // assumes a,this >= 0 + while (--i >= 0) { + r[i] = 0; + } + for (i = Math.max(n - this.t, 0); i < a.t; ++i) { + r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n); + } + r.clamp(); + r.drShiftTo(1, r); + } + + + // BigInteger.prototype.modInt = bnpModInt; + // (protected) this % n, n < 2^26 + protected modInt(n:number) { + if (n <= 0) { + return 0; + } + const d = this.DV % n; + let r = (this.s < 0) ? n - 1 : 0; + if (this.t > 0) { + if (d == 0) { + r = this[0] % n; + } else { + for (let i = this.t - 1; i >= 0; --i) { + r = (d * r + this[i]) % n; + } + } + } + return r; + } + + + // BigInteger.prototype.millerRabin = bnpMillerRabin; + // (protected) true if probably prime (HAC 4.24, Miller-Rabin) + protected millerRabin(t:number) { + const n1 = this.subtract(BigInteger.ONE); + const k = n1.getLowestSetBit(); + if (k <= 0) { + return false; + } + const r = n1.shiftRight(k); + t = (t + 1) >> 1; + if (t > lowprimes.length) { + t = lowprimes.length; + } + const a = nbi(); + for (let i = 0; i < t; ++i) { + // Pick bases at random, instead of starting at 2 + a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]); + let y = a.modPow(r, this); + if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + let j = 1; + while (j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2, this); + if (y.compareTo(BigInteger.ONE) == 0) { + return false; + } + } + if (y.compareTo(n1) != 0) { + return false; + } + } + } + return true; + } + + // BigInteger.prototype.square = bnSquare; + // (public) this^2 + protected square() { + const r = nbi(); + this.squareTo(r); + return r; + } + + //#region ASYNC + + // Public API method + public gcda(a:BigInteger, callback:(x:BigInteger) => void) { + let x = (this.s < 0) ? this.negate() : this.clone(); + let y = (a.s < 0) ? a.negate() : a.clone(); + if (x.compareTo(y) < 0) { + const t = x; + x = y; + y = t; + } + let i = x.getLowestSetBit(); + let g = y.getLowestSetBit(); + if (g < 0) { + callback(x); + return; + } + if (i < g) { g = i; } + if (g > 0) { + x.rShiftTo(g, x); + y.rShiftTo(g, y); + } + // Workhorse of the algorithm, gets called 200 - 800 times per 512 bit keygen. + const gcda1 = function () { + if ((i = x.getLowestSetBit()) > 0) { x.rShiftTo(i, x); } + if ((i = y.getLowestSetBit()) > 0) { y.rShiftTo(i, y); } + if (x.compareTo(y) >= 0) { + x.subTo(y, x); + x.rShiftTo(1, x); + } else { + y.subTo(x, y); + y.rShiftTo(1, y); + } + if (!(x.signum() > 0)) { + if (g > 0) { y.lShiftTo(g, y); } + setTimeout(function () {callback(y); }, 0); // escape + } else { + setTimeout(gcda1, 0); + } + }; + setTimeout(gcda1, 10); + } + + // (protected) alternate constructor + public fromNumberAsync(a:number, b:number|SecureRandom, c:number|SecureRandom, callback:() => void) { + if ("number" == typeof b) { + if (a < 2) { + this.fromInt(1); + } else { + this.fromNumber(a, c); + if (!this.testBit(a - 1)) { + this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this); + } + if (this.isEven()) { + this.dAddOffset(1, 0); + } + const bnp = this; + const bnpfn1 = function () { + bnp.dAddOffset(2, 0); + if (bnp.bitLength() > a) { bnp.subTo(BigInteger.ONE.shiftLeft(a - 1), bnp); } + if (bnp.isProbablePrime(b)) { + setTimeout(function () {callback(); }, 0); // escape + } else { + setTimeout(bnpfn1, 0); + } + }; + setTimeout(bnpfn1, 0); + } + } else { + const x:number[] = []; + const t = a & 7; + x.length = (a >> 3) + 1; + b.nextBytes(x); + if (t > 0) { x[0] &= ((1 << t) - 1); } else { x[0] = 0; } + this.fromString(x, 256); + } + } + + //#endregion ASYNC + + //#endregion PROTECTED + + //#region FIELDS + + public s:number; + public t:number; + + + public DB:number; + public DM:number; + public DV:number; + + public FV:number; + public F1:number; + public F2:number; + + public am:(i:number, x:number, w:BigInteger, j:number, c:number, n:number) => number; + + [index:number]:number; + + public static ONE:BigInteger; + public static ZERO:BigInteger; + + //#endregion FIELDS +} + +//#region REDUCERS + +//#region NullExp + +class NullExp { + constructor() { + + } + + // NullExp.prototype.convert = nNop; + public convert(x:BigInteger) { + return x; + } + + + // NullExp.prototype.revert = nNop; + public revert(x:BigInteger) { + return x; + } + + + // NullExp.prototype.mulTo = nMulTo; + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + } + + + // NullExp.prototype.sqrTo = nSqrTo; + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + } +} + +//#endregion NullExp + +//#region Classic + +export interface IReduction { + convert(x:BigInteger):BigInteger; + + revert(x:BigInteger):BigInteger; + + // reduce?(x:BigInteger):void; + + mulTo(x:BigInteger, y:BigInteger, r:BigInteger):void; + + sqrTo(x:BigInteger, r:BigInteger):void; +} + +// Modular reduction using "classic" algorithm +class Classic implements IReduction { + constructor(protected m:BigInteger) { + } + + // Classic.prototype.convert = cConvert; + public convert(x:BigInteger) { + if (x.s < 0 || x.compareTo(this.m) >= 0) { + return x.mod(this.m); + } else { + return x; + } + } + + + // Classic.prototype.revert = cRevert; + public revert(x:BigInteger) { + return x; + } + + + // Classic.prototype.reduce = cReduce; + public reduce(x:BigInteger) { + x.divRemTo(this.m, null, x); + } + + + // Classic.prototype.mulTo = cMulTo; + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + this.reduce(r); + } + + + // Classic.prototype.sqrTo = cSqrTo; + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + this.reduce(r); + } +} + +//#endregion + +//#region Montgomery + +// Montgomery reduction +class Montgomery implements IReduction { + constructor(protected m:BigInteger) { + this.mp = m.invDigit(); + this.mpl = this.mp & 0x7fff; + this.mph = this.mp >> 15; + this.um = (1 << (m.DB - 15)) - 1; + this.mt2 = 2 * m.t; + } + + protected mp:number; + protected mpl:number; + protected mph:number; + protected um:number; + protected mt2:number; + + // Montgomery.prototype.convert = montConvert; + // xR mod m + public convert(x:BigInteger) { + const r = nbi(); + x.abs().dlShiftTo(this.m.t, r); + r.divRemTo(this.m, null, r); + if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { + this.m.subTo(r, r); + } + return r; + } + + // Montgomery.prototype.revert = montRevert; + // x/R mod m + public revert(x:BigInteger) { + const r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // Montgomery.prototype.reduce = montReduce; + // x = x/R mod m (HAC 14.32) + public reduce(x:BigInteger) { + while (x.t <= this.mt2) { + // pad x so am has enough room later + x[x.t++] = 0; + } + for (let i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + let j = x[i] & 0x7fff; + const u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM; + // use am to combine the multiply-shift-add into one call + j = i + this.m.t; + x[j] += this.m.am(0, u0, x, i, 0, this.m.t); + // propagate carry + while (x[j] >= x.DV) { + x[j] -= x.DV; + x[++j]++; + } + } + x.clamp(); + x.drShiftTo(this.m.t, x); + if (x.compareTo(this.m) >= 0) { + x.subTo(this.m, x); + } + } + + + // Montgomery.prototype.mulTo = montMulTo; + // r = "xy/R mod m"; x,y != r + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + this.reduce(r); + } + + + // Montgomery.prototype.sqrTo = montSqrTo; + // r = "x^2/R mod m"; x != r + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + this.reduce(r); + } + +} + +//#endregion Montgomery + + +//#region Barrett + +// Barrett modular reduction +class Barrett implements IReduction { + constructor(protected m:BigInteger) { + // setup Barrett + this.r2 = nbi(); + this.q3 = nbi(); + BigInteger.ONE.dlShiftTo(2 * m.t, this.r2); + this.mu = this.r2.divide(m); + } + + protected r2:BigInteger; + protected q3:BigInteger; + protected mu:BigInteger; + + // Barrett.prototype.convert = barrettConvert; + public convert(x:BigInteger) { + if (x.s < 0 || x.t > 2 * this.m.t) { + return x.mod(this.m); + } else if (x.compareTo(this.m) < 0) { + return x; + } else { + const r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + } + + // Barrett.prototype.revert = barrettRevert; + public revert(x:BigInteger) { + return x; + } + + // Barrett.prototype.reduce = barrettReduce; + // x = x mod m (HAC 14.42) + public reduce(x:BigInteger) { + x.drShiftTo(this.m.t - 1, this.r2); + if (x.t > this.m.t + 1) { + x.t = this.m.t + 1; + x.clamp(); + } + this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3); + this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2); + while (x.compareTo(this.r2) < 0) { + x.dAddOffset(1, this.m.t + 1); + } + x.subTo(this.r2, x); + while (x.compareTo(this.m) >= 0) { + x.subTo(this.m, x); + } + } + + + // Barrett.prototype.mulTo = barrettMulTo; + // r = x*y mod m; x,y != r + public mulTo(x:BigInteger, y:BigInteger, r:BigInteger) { + x.multiplyTo(y, r); + this.reduce(r); + } + + + // Barrett.prototype.sqrTo = barrettSqrTo; + // r = x^2 mod m; x != r + public sqrTo(x:BigInteger, r:BigInteger) { + x.squareTo(r); + this.reduce(r); + } +} + +//#endregion + +//#endregion REDUCERS + +// return new, unset BigInteger +export function nbi() { return new BigInteger(null); } + +export function parseBigInt(str:string, r:number) { + return new BigInteger(str, r); +} + +// am: Compute w_j += (x*this_i), propagate carries, +// c is initial carry, returns final carry. +// c < 3*dvalue, x < 2*dvalue, this_i < dvalue +// We need to select the fastest one that works in this environment. +const inBrowser = typeof navigator !== "undefined"; +if (inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + BigInteger.prototype.am = function am2(i:number, x:number, w:BigInteger, j:number, c:number, n:number) { + const xl = x & 0x7fff; + const xh = x >> 15; + while (--n >= 0) { + let l = this[i] & 0x7fff; + const h = this[i++] >> 15; + const m = xh * l + h * xl; + l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff); + c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30); + w[j++] = l & 0x3fffffff; + } + return c; + }; + dbits = 30; +} else if (inBrowser && j_lm && (navigator.appName != "Netscape")) { + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + BigInteger.prototype.am = function am1(i:number, x:number, w:BigInteger, j:number, c:number, n:number) { + while (--n >= 0) { + const v = x * this[i++] + w[j] + c; + c = Math.floor(v / 0x4000000); + w[j++] = v & 0x3ffffff; + } + return c; + }; + dbits = 26; +} else { // Mozilla/Netscape seems to prefer am3 + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + BigInteger.prototype.am = function am3(i:number, x:number, w:BigInteger, j:number, c:number, n:number) { + const xl = x & 0x3fff; + const xh = x >> 14; + while (--n >= 0) { + let l = this[i] & 0x3fff; + const h = this[i++] >> 14; + const m = xh * l + h * xl; + l = xl * l + ((m & 0x3fff) << 14) + w[j] + c; + c = (l >> 28) + (m >> 14) + xh * h; + w[j++] = l & 0xfffffff; + } + return c; + }; + dbits = 28; +} + +BigInteger.prototype.DB = dbits; +BigInteger.prototype.DM = ((1 << dbits) - 1); +BigInteger.prototype.DV = (1 << dbits); + +const BI_FP = 52; +BigInteger.prototype.FV = Math.pow(2, BI_FP); +BigInteger.prototype.F1 = BI_FP - dbits; +BigInteger.prototype.F2 = 2 * dbits - BI_FP; + +// Digit conversions +const BI_RC:number[] = []; +let rr; +let vv; +rr = "0".charCodeAt(0); +for (vv = 0; vv <= 9; ++vv) { + BI_RC[rr++] = vv; +} +rr = "a".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) { + BI_RC[rr++] = vv; +} +rr = "A".charCodeAt(0); +for (vv = 10; vv < 36; ++vv) { + BI_RC[rr++] = vv; +} + + +export function intAt(s:string, i:number) { + const c = BI_RC[s.charCodeAt(i)]; + return (c == null) ? -1 : c; +} + + +// return bigint initialized to value +export function nbv(i:number) { + const r = nbi(); + r.fromInt(i); + return r; +} + +// returns bit length of the integer x +export function nbits(x:number) { + let r = 1; + let t; + if ((t = x >>> 16) != 0) { + x = t; + r += 16; + } + if ((t = x >> 8) != 0) { + x = t; + r += 8; + } + if ((t = x >> 4) != 0) { + x = t; + r += 4; + } + if ((t = x >> 2) != 0) { + x = t; + r += 2; + } + if ((t = x >> 1) != 0) { + x = t; + r += 1; + } + return r; +} + +// "constants" +BigInteger.ZERO = nbv(0); +BigInteger.ONE = nbv(1); diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/prng4.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/prng4.ts new file mode 100644 index 0000000..38aa161 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/prng4.ts @@ -0,0 +1,54 @@ +// prng4.js - uses Arcfour as a PRNG + +export class Arcfour { + constructor() { + this.i = 0; + this.j = 0; + this.S = []; + } + + // Arcfour.prototype.init = ARC4init; + // Initialize arcfour context from key, an array of ints, each from [0..255] + public init(key:number[]) { + let i; + let j; + let t; + for (i = 0; i < 256; ++i) { + this.S[i] = i; + } + j = 0; + for (i = 0; i < 256; ++i) { + j = (j + this.S[i] + key[i % key.length]) & 255; + t = this.S[i]; + this.S[i] = this.S[j]; + this.S[j] = t; + } + this.i = 0; + this.j = 0; + } + + // Arcfour.prototype.next = ARC4next; + public next() { + let t; + this.i = (this.i + 1) & 255; + this.j = (this.j + this.S[this.i]) & 255; + t = this.S[this.i]; + this.S[this.i] = this.S[this.j]; + this.S[this.j] = t; + return this.S[(t + this.S[this.i]) & 255]; + } + + private i:number; + private j:number; + private S:number[]; +} + + +// Plug in your RNG constructor here +export function prng_newstate() { + return new Arcfour(); +} + +// Pool size must be a multiple of 4 and greater than 32. +// An array of bytes the size of the pool will be passed to init() +export let rng_psize = 256; diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/rng.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/rng.ts new file mode 100644 index 0000000..2ab7930 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/rng.ts @@ -0,0 +1,79 @@ +// Random number generator - requires a PRNG backend, e.g. prng4.js +import {Arcfour, prng_newstate, rng_psize} from "./prng4"; + +let rng_state:Arcfour; +let rng_pool:number[] = null; +let rng_pptr:number; + +// Initialize the pool with junk if needed. +if (rng_pool == null) { + rng_pool = []; + rng_pptr = 0; + let t; + if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) { + // Extract entropy (2048 bits) from RNG if available + const z = new Uint32Array(256); + window.crypto.getRandomValues(z); + for (t = 0; t < z.length; ++t) { + rng_pool[rng_pptr++] = z[t] & 255; + } + } + + // Use mouse events for entropy, if we do not have enough entropy by the time + // we need it, entropy will be generated by Math.random. + var count = 0; + const onMouseMoveListener = function (ev:Event & {x:number; y:number; }) { + count = count || 0; + if (count >= 256 || rng_pptr >= rng_psize) { + if (window.removeEventListener) { + window.removeEventListener("mousemove", onMouseMoveListener, false); + } else if ((window as any).detachEvent) { + (window as any).detachEvent("onmousemove", onMouseMoveListener); + } + return; + } + try { + const mouseCoordinates = ev.x + ev.y; + rng_pool[rng_pptr++] = mouseCoordinates & 255; + count += 1; + } catch (e) { + // Sometimes Firefox will deny permission to access event properties for some reason. Ignore. + } + }; + if (typeof window !== 'undefined') { + if (window.addEventListener) { + window.addEventListener("mousemove", onMouseMoveListener, false); + } else if ((window as any).attachEvent) { + (window as any).attachEvent("onmousemove", onMouseMoveListener); + } + } + +} + +function rng_get_byte() { + if (rng_state == null) { + rng_state = prng_newstate(); + // At this point, we may not have collected enough entropy. If not, fall back to Math.random + while (rng_pptr < rng_psize) { + const random = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = random & 255; + } + rng_state.init(rng_pool); + for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) { + rng_pool[rng_pptr] = 0; + } + rng_pptr = 0; + } + // TODO: allow reseeding after first request + return rng_state.next(); +} + + +export class SecureRandom { + + public nextBytes(ba:number[]) { + for (let i = 0; i < ba.length; ++i) { + ba[i] = rng_get_byte(); + } + } +} diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/rsa.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/rsa.ts new file mode 100644 index 0000000..6c3ffa2 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/rsa.ts @@ -0,0 +1,406 @@ +// Depends on jsbn.js and rng.js + +// Version 1.1: support utf-8 encoding in pkcs1pad2 + +// convert a (hex) string to a bignum object + +import {BigInteger, nbi, parseBigInt} from "./jsbn"; +import {SecureRandom} from "./rng"; + + +// function linebrk(s,n) { +// var ret = ""; +// var i = 0; +// while(i + n < s.length) { +// ret += s.substring(i,i+n) + "\n"; +// i += n; +// } +// return ret + s.substring(i,s.length); +// } + +// function byte2Hex(b) { +// if(b < 0x10) +// return "0" + b.toString(16); +// else +// return b.toString(16); +// } + +function pkcs1pad1(s:string, n:number) { + if (n < s.length + 22) { + console.error("Message too long for RSA"); + return null; + } + const len = n - s.length - 6; + let filler = ""; + for (let f = 0; f < len; f += 2) { + filler += "ff"; + } + const m = "0001" + filler + "00" + s; + return parseBigInt(m, 16); +} + +// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint +function pkcs1pad2(s:string, n:number) { + if (n < s.length + 11) { // TODO: fix for utf-8 + + console.error("Message too long for RSA"); + return null; + } + const ba = []; + let i = s.length - 1; + while (i >= 0 && n > 0) { + const c = s.charCodeAt(i--); + if (c < 128) { // encode using utf-8 + ba[--n] = c; + } else if ((c > 127) && (c < 2048)) { + ba[--n] = (c & 63) | 128; + ba[--n] = (c >> 6) | 192; + } else { + ba[--n] = (c & 63) | 128; + ba[--n] = ((c >> 6) & 63) | 128; + ba[--n] = (c >> 12) | 224; + } + } + ba[--n] = 0; + const rng = new SecureRandom(); + const x = []; + while (n > 2) { // random non-zero pad + x[0] = 0; + while (x[0] == 0) { + rng.nextBytes(x); + } + ba[--n] = x[0]; + } + ba[--n] = 2; + ba[--n] = 0; + return new BigInteger(ba); +} + +// "empty" RSA key constructor +export class RSAKey { + constructor() { + this.n = null; + this.e = 0; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; + } + + //#region PROTECTED + // protected + // RSAKey.prototype.doPublic = RSADoPublic; + // Perform raw public operation on "x": return x^e (mod n) + public doPublic(x:BigInteger) { + return x.modPowInt(this.e, this.n); + } + + + // RSAKey.prototype.doPrivate = RSADoPrivate; + // Perform raw private operation on "x": return x^d (mod n) + public doPrivate(x:BigInteger) { + if (this.p == null || this.q == null) { + return x.modPow(this.d, this.n); + } + + // TODO: re-calculate any missing CRT params + let xp = x.mod(this.p).modPow(this.dmp1, this.p); + const xq = x.mod(this.q).modPow(this.dmq1, this.q); + + while (xp.compareTo(xq) < 0) { + xp = xp.add(this.p); + } + return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq); + } + + //#endregion PROTECTED + + //#region PUBLIC + + // RSAKey.prototype.setPublic = RSASetPublic; + // Set the public key fields N and e from hex strings + public setPublic(N:string, E:string) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + } else { + console.error("Invalid RSA public key"); + } + } + + + // RSAKey.prototype.encrypt = RSAEncrypt; + // Return the PKCS#1 RSA encryption of "text" as an even-length hex string + public encrypt(text:string) { + const maxLength = (this.n.bitLength() + 7) >> 3; + const m = pkcs1pad2(text, maxLength); + + if (m == null) { + return null; + } + const c = this.doPublic(m); + if (c == null) { + return null; + } + + let h = c.toString(16); + let length = h.length; + + // fix zero before result + for (let i = 0; i < maxLength * 2 - length; i++) { + h = "0" + h; + } + + return h + } + + + // RSAKey.prototype.setPrivate = RSASetPrivate; + // Set the private key fields N, e, and d from hex strings + public setPrivate(N:string, E:string, D:string) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + this.d = parseBigInt(D, 16); + } else { + console.error("Invalid RSA private key"); + } + } + + + // RSAKey.prototype.setPrivateEx = RSASetPrivateEx; + // Set the private key fields N, e, d and CRT params from hex strings + public setPrivateEx(N:string, E:string, D:string, P:string, Q:string, DP:string, DQ:string, C:string) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + this.d = parseBigInt(D, 16); + this.p = parseBigInt(P, 16); + this.q = parseBigInt(Q, 16); + this.dmp1 = parseBigInt(DP, 16); + this.dmq1 = parseBigInt(DQ, 16); + this.coeff = parseBigInt(C, 16); + } else { + console.error("Invalid RSA private key"); + } + } + + + // RSAKey.prototype.generate = RSAGenerate; + // Generate a new random private key B bits long, using public expt E + public generate(B:number, E:string) { + const rng = new SecureRandom(); + const qs = B >> 1; + this.e = parseInt(E, 16); + const ee = new BigInteger(E, 16); + for (;;) { + for (;;) { + this.p = new BigInteger(B - qs, 1, rng); + if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) { break; } + } + for (;;) { + this.q = new BigInteger(qs, 1, rng); + if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) { break; } + } + if (this.p.compareTo(this.q) <= 0) { + const t = this.p; + this.p = this.q; + this.q = t; + } + const p1 = this.p.subtract(BigInteger.ONE); + const q1 = this.q.subtract(BigInteger.ONE); + const phi = p1.multiply(q1); + if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { + this.n = this.p.multiply(this.q); + this.d = ee.modInverse(phi); + this.dmp1 = this.d.mod(p1); + this.dmq1 = this.d.mod(q1); + this.coeff = this.q.modInverse(this.p); + break; + } + } + } + + // RSAKey.prototype.decrypt = RSADecrypt; + // Return the PKCS#1 RSA decryption of "ctext". + // "ctext" is an even-length hex string and the output is a plain string. + public decrypt(ctext:string) { + const c = parseBigInt(ctext, 16); + const m = this.doPrivate(c); + if (m == null) { return null; } + return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3); + } + + // Generate a new random private key B bits long, using public expt E + public generateAsync(B:number, E:string, callback:() => void) { + const rng = new SecureRandom(); + const qs = B >> 1; + this.e = parseInt(E, 16); + const ee = new BigInteger(E, 16); + const rsa = this; + // These functions have non-descript names because they were originally for(;;) loops. + // I don't know about cryptography to give them better names than loop1-4. + const loop1 = function () { + const loop4 = function () { + if (rsa.p.compareTo(rsa.q) <= 0) { + const t = rsa.p; + rsa.p = rsa.q; + rsa.q = t; + } + const p1 = rsa.p.subtract(BigInteger.ONE); + const q1 = rsa.q.subtract(BigInteger.ONE); + const phi = p1.multiply(q1); + if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { + rsa.n = rsa.p.multiply(rsa.q); + rsa.d = ee.modInverse(phi); + rsa.dmp1 = rsa.d.mod(p1); + rsa.dmq1 = rsa.d.mod(q1); + rsa.coeff = rsa.q.modInverse(rsa.p); + setTimeout(function () {callback(); }, 0); // escape + } else { + setTimeout(loop1, 0); + } + }; + const loop3 = function () { + rsa.q = nbi(); + rsa.q.fromNumberAsync(qs, 1, rng, function () { + rsa.q.subtract(BigInteger.ONE).gcda(ee, function (r) { + if (r.compareTo(BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) { + setTimeout(loop4, 0); + } else { + setTimeout(loop3, 0); + } + }); + }); + }; + const loop2 = function () { + rsa.p = nbi(); + rsa.p.fromNumberAsync(B - qs, 1, rng, function () { + rsa.p.subtract(BigInteger.ONE).gcda(ee, function (r) { + if (r.compareTo(BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) { + setTimeout(loop3, 0); + } else { + setTimeout(loop2, 0); + } + }); + }); + }; + setTimeout(loop2, 0); + }; + setTimeout(loop1, 0); + } + + public sign(text:string, digestMethod:(str:string) => string, digestName:string):string { + const header = getDigestHeader(digestName); + const digest = header + digestMethod(text).toString(); + const m = pkcs1pad1(digest, this.n.bitLength() / 4); + if (m == null) { + return null; + } + const c = this.doPrivate(m); + if (c == null) { + return null; + } + const h = c.toString(16); + if ((h.length & 1) == 0) { + return h; + } else { + return "0" + h; + } + } + + public verify(text:string, signature:string, digestMethod:(str:string) => string):boolean { + const c = parseBigInt(signature, 16); + const m = this.doPublic(c); + if (m == null) { + return null; + } + const unpadded = m.toString(16).replace(/^1f+00/, ""); + const digest = removeDigestHeader(unpadded); + return digest == digestMethod(text).toString(); + } + + //#endregion PUBLIC + + protected n:BigInteger; + protected e:number; + protected d:BigInteger; + protected p:BigInteger; + protected q:BigInteger; + protected dmp1:BigInteger; + protected dmq1:BigInteger; + protected coeff:BigInteger; + +} + + +// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext +function pkcs1unpad2(d:BigInteger, n:number):string { + const b = d.toByteArray(); + let i = 0; + while (i < b.length && b[i] == 0) { ++i; } + if (b.length - i != n - 1 || b[i] != 2) { + return null; + } + ++i; + while (b[i] != 0) { + if (++i >= b.length) { return null; } + } + let ret = ""; + while (++i < b.length) { + const c = b[i] & 255; + if (c < 128) { // utf-8 decode + ret += String.fromCharCode(c); + } else if ((c > 191) && (c < 224)) { + ret += String.fromCharCode(((c & 31) << 6) | (b[i + 1] & 63)); + ++i; + } else { + ret += String.fromCharCode(((c & 15) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63)); + i += 2; + } + } + return ret; +} + +// https://tools.ietf.org/html/rfc3447#page-43 +const DIGEST_HEADERS:{ [name:string]:string } = { + md2: "3020300c06082a864886f70d020205000410", + md5: "3020300c06082a864886f70d020505000410", + sha1: "3021300906052b0e03021a05000414", + sha224: "302d300d06096086480165030402040500041c", + sha256: "3031300d060960864801650304020105000420", + sha384: "3041300d060960864801650304020205000430", + sha512: "3051300d060960864801650304020305000440", + ripemd160: "3021300906052b2403020105000414" +}; + +function getDigestHeader(name:string):string { + return DIGEST_HEADERS[name] || ""; +} + +function removeDigestHeader(str:string):string { + for (const name in DIGEST_HEADERS) { + if (DIGEST_HEADERS.hasOwnProperty(name)) { + const header = DIGEST_HEADERS[name]; + const len = header.length; + if (str.substr(0, len) == header) { + return str.substr(len); + } + } + } + return str; +} + + +// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string +// function RSAEncryptB64(text) { +// var h = this.encrypt(text); +// if(h) return hex2b64(h); else return null; +// } + + +// public + +// RSAKey.prototype.encrypt_b64 = RSAEncryptB64; diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/util.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/util.ts new file mode 100644 index 0000000..943be83 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsbn/util.ts @@ -0,0 +1,69 @@ +const BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; + +export function int2char(n:number) { + return BI_RM.charAt(n); +} + +//#region BIT_OPERATIONS + +// (public) this & a +export function op_and(x:number, y:number):number { + return x & y; +} + + +// (public) this | a +export function op_or(x:number, y:number):number { + return x | y; +} + +// (public) this ^ a +export function op_xor(x:number, y:number):number { + return x ^ y; +} + + +// (public) this & ~a +export function op_andnot(x:number, y:number):number { + return x & ~y; +} + +// return index of lowest 1-bit in x, x < 2^31 +export function lbit(x:number) { + if (x == 0) { + return -1; + } + let r = 0; + if ((x & 0xffff) == 0) { + x >>= 16; + r += 16; + } + if ((x & 0xff) == 0) { + x >>= 8; + r += 8; + } + if ((x & 0xf) == 0) { + x >>= 4; + r += 4; + } + if ((x & 3) == 0) { + x >>= 2; + r += 2; + } + if ((x & 1) == 0) { + ++r; + } + return r; +} + +// return number of 1 bits in x +export function cbit(x:number) { + let r = 0; + while (x != 0) { + x &= x - 1; + ++r; + } + return r; +} + +//#endregion BIT_OPERATIONS diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/LICENSE.txt b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/LICENSE.txt new file mode 100644 index 0000000..e660fc8 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/LICENSE.txt @@ -0,0 +1,25 @@ + + +CONTAINS CODE FROM YUI LIBRARY SEE LICENSE @ http://yuilibrary.com/license/ + +The 'jsrsasign'(RSA-Sign JavaScript Library) License + +Copyright (c) 2010-2013 Kenji Urushima + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/asn1-1.0.d.ts b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/asn1-1.0.d.ts new file mode 100644 index 0000000..f680d28 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/asn1-1.0.d.ts @@ -0,0 +1,77 @@ + + +declare interface IDERIntegerParams { + bigint?:any; + int?:number; + hex?:number; +} + +declare class DERInteger { + /**/ +} + +declare interface IDERIntegerConstructor { + new(params:IDERIntegerParams):DERInteger; +} + +declare class DERSequence { + /**/ + public getEncodedHex():string; +} +declare interface IDERSequenceConstructor { + new(params:{ + array:DERInteger[]; + }):DERSequence; +} + + +declare class DERObjectIdentifier { + /**/ +} +declare interface IDERObjectIdentifierConstructor { + new(params:{ + oid?:string; + hex?:string; + name?:string; + }|string):DERObjectIdentifier; +} + + +declare class DERNull { + /**/ +} +declare interface IDERNullConstructor { + new():DERNull; +} + + +declare class DERBitString { + /**/ +} +declare interface IDERBitStringConstructor { + new(params:{ + hex?:string; + array?:boolean[]; + bin?:string; + }|string):DERBitString; +} + + +declare interface Iasn1 { + readonly DERInteger:IDERIntegerConstructor; + + readonly DERSequence:IDERSequenceConstructor; + + readonly DERObjectIdentifier:IDERObjectIdentifierConstructor; + + readonly DERNull:IDERNullConstructor; + + readonly DERBitString:IDERBitStringConstructor; +} + +declare interface IKJUR { + readonly asn1:Iasn1; +} + + +export const KJUR:IKJUR; diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/asn1-1.0.js b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/asn1-1.0.js new file mode 100644 index 0000000..8fa04c8 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/asn1-1.0.js @@ -0,0 +1,1651 @@ +/* asn1-1.0.13.js (c) 2013-2017 Kenji Urushima | kjur.github.com/jsrsasign/license + */ +/* + * asn1.js - ASN.1 DER encoder classes + * + * Copyright (c) 2013-2017 Kenji Urushima (kenji.urushima@gmail.com) + * + * This software is licensed under the terms of the MIT License. + * https://kjur.github.io/jsrsasign/license + * + * The above copyright and license notice shall be + * included in all copies or substantial portions of the Software. + */ + +import { BigInteger } from "../jsbn/jsbn"; +import { YAHOO } from "./yahoo"; + +/** + * @fileOverview + * @name asn1-1.0.js + * @author Kenji Urushima kenji.urushima@gmail.com + * @version asn1 1.0.13 (2017-Jun-02) + * @since jsrsasign 2.1 + * @license MIT License + */ + +/** + * kjur's class library name space + *

    + * This name space provides following name spaces: + *

      + *
    • {@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder
    • + *
    • {@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL
    • + *
    • {@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature + * class and utilities
    • + *
    + *

    + * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2. + * @name KJUR + * @namespace kjur's class library name space + */ +export var KJUR = {}; + +/** + * kjur's ASN.1 class library name space + *

    + * This is ITU-T X.690 ASN.1 DER encoder class library and + * class structure and methods is very similar to + * org.bouncycastle.asn1 package of + * well known BouncyCaslte Cryptography Library. + *

    PROVIDING ASN.1 PRIMITIVES

    + * Here are ASN.1 DER primitive classes. + *
      + *
    • 0x01 {@link KJUR.asn1.DERBoolean}
    • + *
    • 0x02 {@link KJUR.asn1.DERInteger}
    • + *
    • 0x03 {@link KJUR.asn1.DERBitString}
    • + *
    • 0x04 {@link KJUR.asn1.DEROctetString}
    • + *
    • 0x05 {@link KJUR.asn1.DERNull}
    • + *
    • 0x06 {@link KJUR.asn1.DERObjectIdentifier}
    • + *
    • 0x0a {@link KJUR.asn1.DEREnumerated}
    • + *
    • 0x0c {@link KJUR.asn1.DERUTF8String}
    • + *
    • 0x12 {@link KJUR.asn1.DERNumericString}
    • + *
    • 0x13 {@link KJUR.asn1.DERPrintableString}
    • + *
    • 0x14 {@link KJUR.asn1.DERTeletexString}
    • + *
    • 0x16 {@link KJUR.asn1.DERIA5String}
    • + *
    • 0x17 {@link KJUR.asn1.DERUTCTime}
    • + *
    • 0x18 {@link KJUR.asn1.DERGeneralizedTime}
    • + *
    • 0x30 {@link KJUR.asn1.DERSequence}
    • + *
    • 0x31 {@link KJUR.asn1.DERSet}
    • + *
    + *

    OTHER ASN.1 CLASSES

    + *
      + *
    • {@link KJUR.asn1.ASN1Object}
    • + *
    • {@link KJUR.asn1.DERAbstractString}
    • + *
    • {@link KJUR.asn1.DERAbstractTime}
    • + *
    • {@link KJUR.asn1.DERAbstractStructured}
    • + *
    • {@link KJUR.asn1.DERTaggedObject}
    • + *
    + *

    SUB NAME SPACES

    + *
      + *
    • {@link KJUR.asn1.cades} - CAdES long term signature format
    • + *
    • {@link KJUR.asn1.cms} - Cryptographic Message Syntax
    • + *
    • {@link KJUR.asn1.csr} - Certificate Signing Request (CSR/PKCS#10)
    • + *
    • {@link KJUR.asn1.tsp} - RFC 3161 Timestamping Protocol Format
    • + *
    • {@link KJUR.asn1.x509} - RFC 5280 X.509 certificate and CRL
    • + *
    + *

    + * NOTE: Please ignore method summary and document of this namespace. + * This caused by a bug of jsdoc2. + * @name KJUR.asn1 + * @namespace + */ +if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {}; + +/** + * ASN1 utilities class + * @name KJUR.asn1.ASN1Util + * @class ASN1 utilities class + * @since asn1 1.0.2 + */ +KJUR.asn1.ASN1Util = new function() { + this.integerToByteHex = function(i) { + var h = i.toString(16); + if ((h.length % 2) == 1) h = '0' + h; + return h; + }; + this.bigIntToMinTwosComplementsHex = function(bigIntegerValue) { + var h = bigIntegerValue.toString(16); + if (h.substr(0, 1) != '-') { + if (h.length % 2 == 1) { + h = '0' + h; + } else { + if (! h.match(/^[0-7]/)) { + h = '00' + h; + } + } + } else { + var hPos = h.substr(1); + var xorLen = hPos.length; + if (xorLen % 2 == 1) { + xorLen += 1; + } else { + if (! h.match(/^[0-7]/)) { + xorLen += 2; + } + } + var hMask = ''; + for (var i = 0; i < xorLen; i++) { + hMask += 'f'; + } + var biMask = new BigInteger(hMask, 16); + var biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE); + h = biNeg.toString(16).replace(/^-/, ''); + } + return h; + }; + /** + * get PEM string from hexadecimal data and header string + * @name getPEMStringFromHex + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} dataHex hexadecimal string of PEM body + * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY') + * @return {String} PEM formatted string of input data + * @description + * This method converts a hexadecimal string to a PEM string with + * a specified header. Its line break will be CRLF("\r\n"). + * @example + * var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex('616161', 'RSA PRIVATE KEY'); + * // value of pem will be: + * -----BEGIN PRIVATE KEY----- + * YWFh + * -----END PRIVATE KEY----- + */ + this.getPEMStringFromHex = function(dataHex, pemHeader) { + return hextopem(dataHex, pemHeader); + }; + + /** + * generate ASN1Object specifed by JSON parameters + * @name newObject + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {Array} param JSON parameter to generate ASN1Object + * @return {KJUR.asn1.ASN1Object} generated object + * @since asn1 1.0.3 + * @description + * generate any ASN1Object specified by JSON param + * including ASN.1 primitive or structured. + * Generally 'param' can be described as follows: + *
    + * {TYPE-OF-ASNOBJ: ASN1OBJ-PARAMETER} + *
    + * 'TYPE-OF-ASN1OBJ' can be one of following symbols: + *
      + *
    • 'bool' - DERBoolean
    • + *
    • 'int' - DERInteger
    • + *
    • 'bitstr' - DERBitString
    • + *
    • 'octstr' - DEROctetString
    • + *
    • 'null' - DERNull
    • + *
    • 'oid' - DERObjectIdentifier
    • + *
    • 'enum' - DEREnumerated
    • + *
    • 'utf8str' - DERUTF8String
    • + *
    • 'numstr' - DERNumericString
    • + *
    • 'prnstr' - DERPrintableString
    • + *
    • 'telstr' - DERTeletexString
    • + *
    • 'ia5str' - DERIA5String
    • + *
    • 'utctime' - DERUTCTime
    • + *
    • 'gentime' - DERGeneralizedTime
    • + *
    • 'seq' - DERSequence
    • + *
    • 'set' - DERSet
    • + *
    • 'tag' - DERTaggedObject
    • + *
    + * @example + * newObject({'prnstr': 'aaa'}); + * newObject({'seq': [{'int': 3}, {'prnstr': 'aaa'}]}) + * // ASN.1 Tagged Object + * newObject({'tag': {'tag': 'a1', + * 'explicit': true, + * 'obj': {'seq': [{'int': 3}, {'prnstr': 'aaa'}]}}}); + * // more simple representation of ASN.1 Tagged Object + * newObject({'tag': ['a1', + * true, + * {'seq': [ + * {'int': 3}, + * {'prnstr': 'aaa'}]} + * ]}); + */ + this.newObject = function(param) { + var _KJUR = KJUR, + _KJUR_asn1 = _KJUR.asn1, + _DERBoolean = _KJUR_asn1.DERBoolean, + _DERInteger = _KJUR_asn1.DERInteger, + _DERBitString = _KJUR_asn1.DERBitString, + _DEROctetString = _KJUR_asn1.DEROctetString, + _DERNull = _KJUR_asn1.DERNull, + _DERObjectIdentifier = _KJUR_asn1.DERObjectIdentifier, + _DEREnumerated = _KJUR_asn1.DEREnumerated, + _DERUTF8String = _KJUR_asn1.DERUTF8String, + _DERNumericString = _KJUR_asn1.DERNumericString, + _DERPrintableString = _KJUR_asn1.DERPrintableString, + _DERTeletexString = _KJUR_asn1.DERTeletexString, + _DERIA5String = _KJUR_asn1.DERIA5String, + _DERUTCTime = _KJUR_asn1.DERUTCTime, + _DERGeneralizedTime = _KJUR_asn1.DERGeneralizedTime, + _DERSequence = _KJUR_asn1.DERSequence, + _DERSet = _KJUR_asn1.DERSet, + _DERTaggedObject = _KJUR_asn1.DERTaggedObject, + _newObject = _KJUR_asn1.ASN1Util.newObject; + + var keys = Object.keys(param); + if (keys.length != 1) + throw "key of param shall be only one."; + var key = keys[0]; + + if (":bool:int:bitstr:octstr:null:oid:enum:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + key + ":") == -1) + throw "undefined key: " + key; + + if (key == "bool") return new _DERBoolean(param[key]); + if (key == "int") return new _DERInteger(param[key]); + if (key == "bitstr") return new _DERBitString(param[key]); + if (key == "octstr") return new _DEROctetString(param[key]); + if (key == "null") return new _DERNull(param[key]); + if (key == "oid") return new _DERObjectIdentifier(param[key]); + if (key == "enum") return new _DEREnumerated(param[key]); + if (key == "utf8str") return new _DERUTF8String(param[key]); + if (key == "numstr") return new _DERNumericString(param[key]); + if (key == "prnstr") return new _DERPrintableString(param[key]); + if (key == "telstr") return new _DERTeletexString(param[key]); + if (key == "ia5str") return new _DERIA5String(param[key]); + if (key == "utctime") return new _DERUTCTime(param[key]); + if (key == "gentime") return new _DERGeneralizedTime(param[key]); + + if (key == "seq") { + var paramList = param[key]; + var a = []; + for (var i = 0; i < paramList.length; i++) { + var asn1Obj = _newObject(paramList[i]); + a.push(asn1Obj); + } + return new _DERSequence({'array': a}); + } + + if (key == "set") { + var paramList = param[key]; + var a = []; + for (var i = 0; i < paramList.length; i++) { + var asn1Obj = _newObject(paramList[i]); + a.push(asn1Obj); + } + return new _DERSet({'array': a}); + } + + if (key == "tag") { + var tagParam = param[key]; + if (Object.prototype.toString.call(tagParam) === '[object Array]' && + tagParam.length == 3) { + var obj = _newObject(tagParam[2]); + return new _DERTaggedObject({tag: tagParam[0], + explicit: tagParam[1], + obj: obj}); + } else { + var newParam = {}; + if (tagParam.explicit !== undefined) + newParam.explicit = tagParam.explicit; + if (tagParam.tag !== undefined) + newParam.tag = tagParam.tag; + if (tagParam.obj === undefined) + throw "obj shall be specified for 'tag'."; + newParam.obj = _newObject(tagParam.obj); + return new _DERTaggedObject(newParam); + } + } + }; + + /** + * get encoded hexadecimal string of ASN1Object specifed by JSON parameters + * @name jsonToASN1HEX + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {Array} param JSON parameter to generate ASN1Object + * @return hexadecimal string of ASN1Object + * @since asn1 1.0.4 + * @description + * As for ASN.1 object representation of JSON object, + * please see {@link newObject}. + * @example + * jsonToASN1HEX({'prnstr': 'aaa'}); + */ + this.jsonToASN1HEX = function(param) { + var asn1Obj = this.newObject(param); + return asn1Obj.getEncodedHex(); + }; +}; + +/** + * get dot noted oid number string from hexadecimal value of OID + * @name oidHexToInt + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} hex hexadecimal value of object identifier + * @return {String} dot noted string of object identifier + * @since jsrsasign 4.8.3 asn1 1.0.7 + * @description + * This static method converts from hexadecimal string representation of + * ASN.1 value of object identifier to oid number string. + * @example + * KJUR.asn1.ASN1Util.oidHexToInt('550406') → "2.5.4.6" + */ +KJUR.asn1.ASN1Util.oidHexToInt = function(hex) { + var s = ""; + var i01 = parseInt(hex.substr(0, 2), 16); + var i0 = Math.floor(i01 / 40); + var i1 = i01 % 40; + var s = i0 + "." + i1; + + var binbuf = ""; + for (var i = 2; i < hex.length; i += 2) { + var value = parseInt(hex.substr(i, 2), 16); + var bin = ("00000000" + value.toString(2)).slice(- 8); + binbuf = binbuf + bin.substr(1, 7); + if (bin.substr(0, 1) == "0") { + var bi = new BigInteger(binbuf, 2); + s = s + "." + bi.toString(10); + binbuf = ""; + } + }; + + return s; +}; + +/** + * get hexadecimal value of object identifier from dot noted oid value + * @name oidIntToHex + * @memberOf KJUR.asn1.ASN1Util + * @function + * @param {String} oidString dot noted string of object identifier + * @return {String} hexadecimal value of object identifier + * @since jsrsasign 4.8.3 asn1 1.0.7 + * @description + * This static method converts from object identifier value string. + * to hexadecimal string representation of it. + * @example + * KJUR.asn1.ASN1Util.oidIntToHex("2.5.4.6") → "550406" + */ +KJUR.asn1.ASN1Util.oidIntToHex = function(oidString) { + var itox = function(i) { + var h = i.toString(16); + if (h.length == 1) h = '0' + h; + return h; + }; + + var roidtox = function(roid) { + var h = ''; + var bi = new BigInteger(roid, 10); + var b = bi.toString(2); + var padLen = 7 - b.length % 7; + if (padLen == 7) padLen = 0; + var bPad = ''; + for (var i = 0; i < padLen; i++) bPad += '0'; + b = bPad + b; + for (var i = 0; i < b.length - 1; i += 7) { + var b8 = b.substr(i, 7); + if (i != b.length - 7) b8 = '1' + b8; + h += itox(parseInt(b8, 2)); + } + return h; + }; + + if (! oidString.match(/^[0-9.]+$/)) { + throw "malformed oid string: " + oidString; + } + var h = ''; + var a = oidString.split('.'); + var i0 = parseInt(a[0]) * 40 + parseInt(a[1]); + h += itox(i0); + a.splice(0, 2); + for (var i = 0; i < a.length; i++) { + h += roidtox(a[i]); + } + return h; +}; + + +// ******************************************************************** +// Abstract ASN.1 Classes +// ******************************************************************** + +// ******************************************************************** + +/** + * base class for ASN.1 DER encoder object + * @name KJUR.asn1.ASN1Object + * @class base class for ASN.1 DER encoder object + * @property {Boolean} isModified flag whether internal data was changed + * @property {String} hTLV hexadecimal string of ASN.1 TLV + * @property {String} hT hexadecimal string of ASN.1 TLV tag(T) + * @property {String} hL hexadecimal string of ASN.1 TLV length(L) + * @property {String} hV hexadecimal string of ASN.1 TLV value(V) + * @description + */ +KJUR.asn1.ASN1Object = function() { + var isModified = true; + var hTLV = null; + var hT = '00'; + var hL = '00'; + var hV = ''; + + /** + * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V) + * @name getLengthHexFromValue + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV length(L) + */ + this.getLengthHexFromValue = function() { + if (typeof this.hV == "undefined" || this.hV == null) { + throw "this.hV is null or undefined."; + } + if (this.hV.length % 2 == 1) { + throw "value hex must be even length: n=" + hV.length + ",v=" + this.hV; + } + var n = this.hV.length / 2; + var hN = n.toString(16); + if (hN.length % 2 == 1) { + hN = "0" + hN; + } + if (n < 128) { + return hN; + } else { + var hNlen = hN.length / 2; + if (hNlen > 15) { + throw "ASN.1 length too long to represent by 8x: n = " + n.toString(16); + } + var head = 128 + hNlen; + return head.toString(16) + hN; + } + }; + + /** + * get hexadecimal string of ASN.1 TLV bytes + * @name getEncodedHex + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV + */ + this.getEncodedHex = function() { + if (this.hTLV == null || this.isModified) { + this.hV = this.getFreshValueHex(); + this.hL = this.getLengthHexFromValue(); + this.hTLV = this.hT + this.hL + this.hV; + this.isModified = false; + //alert("first time: " + this.hTLV); + } + return this.hTLV; + }; + + /** + * get hexadecimal string of ASN.1 TLV value(V) bytes + * @name getValueHex + * @memberOf KJUR.asn1.ASN1Object# + * @function + * @return {String} hexadecimal string of ASN.1 TLV value(V) bytes + */ + this.getValueHex = function() { + this.getEncodedHex(); + return this.hV; + } + + this.getFreshValueHex = function() { + return ''; + }; +}; + +// == BEGIN DERAbstractString ================================================ +/** + * base class for ASN.1 DER string classes + * @name KJUR.asn1.DERAbstractString + * @class base class for ASN.1 DER string classes + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @property {String} s internal string of value + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • str - specify initial ASN.1 value(V) by a string
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERAbstractString = function(params) { + KJUR.asn1.DERAbstractString.superclass.constructor.call(this); + var s = null; + var hV = null; + + /** + * get string value of this string object + * @name getString + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @return {String} string value of this string object + */ + this.getString = function() { + return this.s; + }; + + /** + * set value by a string + * @name setString + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @param {String} newS value by a string to set + */ + this.setString = function(newS) { + this.hTLV = null; + this.isModified = true; + this.s = newS; + this.hV = stohex(this.s); + }; + + /** + * set value by a hexadecimal string + * @name setStringHex + * @memberOf KJUR.asn1.DERAbstractString# + * @function + * @param {String} newHexString value by a hexadecimal string to set + */ + this.setStringHex = function(newHexString) { + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params == "string") { + this.setString(params); + } else if (typeof params['str'] != "undefined") { + this.setString(params['str']); + } else if (typeof params['hex'] != "undefined") { + this.setStringHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractString, KJUR.asn1.ASN1Object); +// == END DERAbstractString ================================================ + +// == BEGIN DERAbstractTime ================================================== +/** + * base class for ASN.1 DER Generalized/UTCTime class + * @name KJUR.asn1.DERAbstractTime + * @class base class for ASN.1 DER Generalized/UTCTime class + * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERAbstractTime = function(params) { + KJUR.asn1.DERAbstractTime.superclass.constructor.call(this); + var s = null; + var date = null; + + // --- PRIVATE METHODS -------------------- + this.localDateToUTC = function(d) { + utc = d.getTime() + (d.getTimezoneOffset() * 60000); + var utcDate = new Date(utc); + return utcDate; + }; + + /* + * format date string by Data object + * @name formatDate + * @memberOf KJUR.asn1.AbstractTime; + * @param {Date} dateObject + * @param {string} type 'utc' or 'gen' + * @param {boolean} withMillis flag for with millisections or not + * @description + * 'withMillis' flag is supported from asn1 1.0.6. + */ + this.formatDate = function(dateObject, type, withMillis) { + var pad = this.zeroPadding; + var d = this.localDateToUTC(dateObject); + var year = String(d.getFullYear()); + if (type == 'utc') year = year.substr(2, 2); + var month = pad(String(d.getMonth() + 1), 2); + var day = pad(String(d.getDate()), 2); + var hour = pad(String(d.getHours()), 2); + var min = pad(String(d.getMinutes()), 2); + var sec = pad(String(d.getSeconds()), 2); + var s = year + month + day + hour + min + sec; + if (withMillis === true) { + var millis = d.getMilliseconds(); + if (millis != 0) { + var sMillis = pad(String(millis), 3); + sMillis = sMillis.replace(/[0]+$/, ""); + s = s + "." + sMillis; + } + } + return s + "Z"; + }; + + this.zeroPadding = function(s, len) { + if (s.length >= len) return s; + return new Array(len - s.length + 1).join('0') + s; + }; + + // --- PUBLIC METHODS -------------------- + /** + * get string value of this string object + * @name getString + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @return {String} string value of this time object + */ + this.getString = function() { + return this.s; + }; + + /** + * set value by a string + * @name setString + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @param {String} newS value by a string to set such like "130430235959Z" + */ + this.setString = function(newS) { + this.hTLV = null; + this.isModified = true; + this.s = newS; + this.hV = stohex(newS); + }; + + /** + * set value by a Date object + * @name setByDateValue + * @memberOf KJUR.asn1.DERAbstractTime# + * @function + * @param {Integer} year year of date (ex. 2013) + * @param {Integer} month month of date between 1 and 12 (ex. 12) + * @param {Integer} day day of month + * @param {Integer} hour hours of date + * @param {Integer} min minutes of date + * @param {Integer} sec seconds of date + */ + this.setByDateValue = function(year, month, day, hour, min, sec) { + var dateObject = new Date(Date.UTC(year, month - 1, day, hour, min, sec, 0)); + this.setByDate(dateObject); + }; + + this.getFreshValueHex = function() { + return this.hV; + }; +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractTime, KJUR.asn1.ASN1Object); +// == END DERAbstractTime ================================================== + +// == BEGIN DERAbstractStructured ============================================ +/** + * base class for ASN.1 DER structured class + * @name KJUR.asn1.DERAbstractStructured + * @class base class for ASN.1 DER structured class + * @property {Array} asn1Array internal array of ASN1Object + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERAbstractStructured = function(params) { + KJUR.asn1.DERAbstractString.superclass.constructor.call(this); + var asn1Array = null; + + /** + * set value by array of ASN1Object + * @name setByASN1ObjectArray + * @memberOf KJUR.asn1.DERAbstractStructured# + * @function + * @param {array} asn1ObjectArray array of ASN1Object to set + */ + this.setByASN1ObjectArray = function(asn1ObjectArray) { + this.hTLV = null; + this.isModified = true; + this.asn1Array = asn1ObjectArray; + }; + + /** + * append an ASN1Object to internal array + * @name appendASN1Object + * @memberOf KJUR.asn1.DERAbstractStructured# + * @function + * @param {ASN1Object} asn1Object to add + */ + this.appendASN1Object = function(asn1Object) { + this.hTLV = null; + this.isModified = true; + this.asn1Array.push(asn1Object); + }; + + this.asn1Array = new Array(); + if (typeof params != "undefined") { + if (typeof params['array'] != "undefined") { + this.asn1Array = params['array']; + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERAbstractStructured, KJUR.asn1.ASN1Object); + + +// ******************************************************************** +// ASN.1 Object Classes +// ******************************************************************** + +// ******************************************************************** +/** + * class for ASN.1 DER Boolean + * @name KJUR.asn1.DERBoolean + * @class class for ASN.1 DER Boolean + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERBoolean = function() { + KJUR.asn1.DERBoolean.superclass.constructor.call(this); + this.hT = "01"; + this.hTLV = "0101ff"; +}; +YAHOO.lang.extend(KJUR.asn1.DERBoolean, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER Integer + * @name KJUR.asn1.DERInteger + * @class class for ASN.1 DER Integer + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • int - specify initial ASN.1 value(V) by integer value
    • + *
    • bigint - specify initial ASN.1 value(V) by BigInteger object
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERInteger = function(params) { + KJUR.asn1.DERInteger.superclass.constructor.call(this); + this.hT = "02"; + + /** + * set value by Tom Wu's BigInteger object + * @name setByBigInteger + * @memberOf KJUR.asn1.DERInteger# + * @function + * @param {BigInteger} bigIntegerValue to set + */ + this.setByBigInteger = function(bigIntegerValue) { + this.hTLV = null; + this.isModified = true; + this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue); + }; + + /** + * set value by integer value + * @name setByInteger + * @memberOf KJUR.asn1.DERInteger + * @function + * @param {Integer} integer value to set + */ + this.setByInteger = function(intValue) { + var bi = new BigInteger(String(intValue), 10); + this.setByBigInteger(bi); + }; + + /** + * set value by integer value + * @name setValueHex + * @memberOf KJUR.asn1.DERInteger# + * @function + * @param {String} hexadecimal string of integer value + * @description + *
    + * NOTE: Value shall be represented by minimum octet length of + * two's complement representation. + * @example + * new KJUR.asn1.DERInteger(123); + * new KJUR.asn1.DERInteger({'int': 123}); + * new KJUR.asn1.DERInteger({'hex': '1fad'}); + */ + this.setValueHex = function(newHexString) { + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['bigint'] != "undefined") { + this.setByBigInteger(params['bigint']); + } else if (typeof params['int'] != "undefined") { + this.setByInteger(params['int']); + } else if (typeof params == "number") { + this.setByInteger(params); + } else if (typeof params['hex'] != "undefined") { + this.setValueHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERInteger, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER encoded BitString primitive + * @name KJUR.asn1.DERBitString + * @class class for ASN.1 DER encoded BitString primitive + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • bin - specify binary string (ex. '10111')
    • + *
    • array - specify array of boolean (ex. [true,false,true,true])
    • + *
    • hex - specify hexadecimal string of ASN.1 value(V) including unused bits
    • + *
    • obj - specify {@link KJUR.asn1.ASN1Util.newObject} + * argument for "BitString encapsulates" structure.
    • + *
    + * NOTE1: 'params' can be omitted.
    + * NOTE2: 'obj' parameter have been supported since + * asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25).
    + * @example + * // default constructor + * o = new KJUR.asn1.DERBitString(); + * // initialize with binary string + * o = new KJUR.asn1.DERBitString({bin: "1011"}); + * // initialize with boolean array + * o = new KJUR.asn1.DERBitString({array: [true,false,true,true]}); + * // initialize with hexadecimal string (04 is unused bits) + * o = new KJUR.asn1.DEROctetString({hex: "04bac0"}); + * // initialize with ASN1Util.newObject argument for encapsulated + * o = new KJUR.asn1.DERBitString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}}); + * // above generates a ASN.1 data like this: + * // BIT STRING, encapsulates { + * // SEQUENCE { + * // INTEGER 3 + * // PrintableString 'aaa' + * // } + * // } + */ +KJUR.asn1.DERBitString = function(params) { + if (params !== undefined && typeof params.obj !== "undefined") { + var o = KJUR.asn1.ASN1Util.newObject(params.obj); + params.hex = "00" + o.getEncodedHex(); + } + KJUR.asn1.DERBitString.superclass.constructor.call(this); + this.hT = "03"; + + /** + * set ASN.1 value(V) by a hexadecimal string including unused bits + * @name setHexValueIncludingUnusedBits + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {String} newHexStringIncludingUnusedBits + */ + this.setHexValueIncludingUnusedBits = function(newHexStringIncludingUnusedBits) { + this.hTLV = null; + this.isModified = true; + this.hV = newHexStringIncludingUnusedBits; + }; + + /** + * set ASN.1 value(V) by unused bit and hexadecimal string of value + * @name setUnusedBitsAndHexValue + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {Integer} unusedBits + * @param {String} hValue + */ + this.setUnusedBitsAndHexValue = function(unusedBits, hValue) { + if (unusedBits < 0 || 7 < unusedBits) { + throw "unused bits shall be from 0 to 7: u = " + unusedBits; + } + var hUnusedBits = "0" + unusedBits; + this.hTLV = null; + this.isModified = true; + this.hV = hUnusedBits + hValue; + }; + + /** + * set ASN.1 DER BitString by binary string
    + * @name setByBinaryString + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {String} binaryString binary value string (i.e. '10111') + * @description + * Its unused bits will be calculated automatically by length of + * 'binaryValue'.
    + * NOTE: Trailing zeros '0' will be ignored. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.setByBooleanArray("01011"); + */ + this.setByBinaryString = function(binaryString) { + binaryString = binaryString.replace(/0+$/, ''); + var unusedBits = 8 - binaryString.length % 8; + if (unusedBits == 8) unusedBits = 0; + for (var i = 0; i <= unusedBits; i++) { + binaryString += '0'; + } + var h = ''; + for (var i = 0; i < binaryString.length - 1; i += 8) { + var b = binaryString.substr(i, 8); + var x = parseInt(b, 2).toString(16); + if (x.length == 1) x = '0' + x; + h += x; + } + this.hTLV = null; + this.isModified = true; + this.hV = '0' + unusedBits + h; + }; + + /** + * set ASN.1 TLV value(V) by an array of boolean
    + * @name setByBooleanArray + * @memberOf KJUR.asn1.DERBitString# + * @function + * @param {array} booleanArray array of boolean (ex. [true, false, true]) + * @description + * NOTE: Trailing falses will be ignored in the ASN.1 DER Object. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.setByBooleanArray([false, true, false, true, true]); + */ + this.setByBooleanArray = function(booleanArray) { + var s = ''; + for (var i = 0; i < booleanArray.length; i++) { + if (booleanArray[i] == true) { + s += '1'; + } else { + s += '0'; + } + } + this.setByBinaryString(s); + }; + + /** + * generate an array of falses with specified length
    + * @name newFalseArray + * @memberOf KJUR.asn1.DERBitString + * @function + * @param {Integer} nLength length of array to generate + * @return {array} array of boolean falses + * @description + * This static method may be useful to initialize boolean array. + * @example + * o = new KJUR.asn1.DERBitString(); + * o.newFalseArray(3) → [false, false, false] + */ + this.newFalseArray = function(nLength) { + var a = new Array(nLength); + for (var i = 0; i < nLength; i++) { + a[i] = false; + } + return a; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params == "string" && params.toLowerCase().match(/^[0-9a-f]+$/)) { + this.setHexValueIncludingUnusedBits(params); + } else if (typeof params['hex'] != "undefined") { + this.setHexValueIncludingUnusedBits(params['hex']); + } else if (typeof params['bin'] != "undefined") { + this.setByBinaryString(params['bin']); + } else if (typeof params['array'] != "undefined") { + this.setByBooleanArray(params['array']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERBitString, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER OctetString
    + * @name KJUR.asn1.DEROctetString + * @class class for ASN.1 DER OctetString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * This class provides ASN.1 OctetString simple type.
    + * Supported "params" attributes are: + *
      + *
    • str - to set a string as a value
    • + *
    • hex - to set a hexadecimal string as a value
    • + *
    • obj - to set a encapsulated ASN.1 value by JSON object + * which is defined in {@link KJUR.asn1.ASN1Util.newObject}
    • + *
    + * NOTE: A parameter 'obj' have been supported + * for "OCTET STRING, encapsulates" structure. + * since asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25). + * @see KJUR.asn1.DERAbstractString - superclass + * @example + * // default constructor + * o = new KJUR.asn1.DEROctetString(); + * // initialize with string + * o = new KJUR.asn1.DEROctetString({str: "aaa"}); + * // initialize with hexadecimal string + * o = new KJUR.asn1.DEROctetString({hex: "616161"}); + * // initialize with ASN1Util.newObject argument + * o = new KJUR.asn1.DEROctetString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}}); + * // above generates a ASN.1 data like this: + * // OCTET STRING, encapsulates { + * // SEQUENCE { + * // INTEGER 3 + * // PrintableString 'aaa' + * // } + * // } + */ +KJUR.asn1.DEROctetString = function(params) { + if (params !== undefined && typeof params.obj !== "undefined") { + var o = KJUR.asn1.ASN1Util.newObject(params.obj); + params.hex = o.getEncodedHex(); + } + KJUR.asn1.DEROctetString.superclass.constructor.call(this, params); + this.hT = "04"; +}; +YAHOO.lang.extend(KJUR.asn1.DEROctetString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER Null + * @name KJUR.asn1.DERNull + * @class class for ASN.1 DER Null + * @extends KJUR.asn1.ASN1Object + * @description + * @see KJUR.asn1.ASN1Object - superclass + */ +KJUR.asn1.DERNull = function() { + KJUR.asn1.DERNull.superclass.constructor.call(this); + this.hT = "05"; + this.hTLV = "0500"; +}; +YAHOO.lang.extend(KJUR.asn1.DERNull, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER ObjectIdentifier + * @name KJUR.asn1.DERObjectIdentifier + * @class class for ASN.1 DER ObjectIdentifier + * @param {Array} params associative array of parameters (ex. {'oid': '2.5.4.5'}) + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • oid - specify initial ASN.1 value(V) by a oid string (ex. 2.5.4.13)
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERObjectIdentifier = function(params) { + var itox = function(i) { + var h = i.toString(16); + if (h.length == 1) h = '0' + h; + return h; + }; + var roidtox = function(roid) { + var h = ''; + var bi = new BigInteger(roid, 10); + var b = bi.toString(2); + var padLen = 7 - b.length % 7; + if (padLen == 7) padLen = 0; + var bPad = ''; + for (var i = 0; i < padLen; i++) bPad += '0'; + b = bPad + b; + for (var i = 0; i < b.length - 1; i += 7) { + var b8 = b.substr(i, 7); + if (i != b.length - 7) b8 = '1' + b8; + h += itox(parseInt(b8, 2)); + } + return h; + } + + KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this); + this.hT = "06"; + + /** + * set value by a hexadecimal string + * @name setValueHex + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} newHexString hexadecimal value of OID bytes + */ + this.setValueHex = function(newHexString) { + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = newHexString; + }; + + /** + * set value by a OID string
    + * @name setValueOidString + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} oidString OID string (ex. 2.5.4.13) + * @example + * o = new KJUR.asn1.DERObjectIdentifier(); + * o.setValueOidString("2.5.4.13"); + */ + this.setValueOidString = function(oidString) { + if (! oidString.match(/^[0-9.]+$/)) { + throw "malformed oid string: " + oidString; + } + var h = ''; + var a = oidString.split('.'); + var i0 = parseInt(a[0]) * 40 + parseInt(a[1]); + h += itox(i0); + a.splice(0, 2); + for (var i = 0; i < a.length; i++) { + h += roidtox(a[i]); + } + this.hTLV = null; + this.isModified = true; + this.s = null; + this.hV = h; + }; + + /** + * set value by a OID name + * @name setValueName + * @memberOf KJUR.asn1.DERObjectIdentifier# + * @function + * @param {String} oidName OID name (ex. 'serverAuth') + * @since 1.0.1 + * @description + * OID name shall be defined in 'KJUR.asn1.x509.OID.name2oidList'. + * Otherwise raise error. + * @example + * o = new KJUR.asn1.DERObjectIdentifier(); + * o.setValueName("serverAuth"); + */ + this.setValueName = function(oidName) { + var oid = KJUR.asn1.x509.OID.name2oid(oidName); + if (oid !== '') { + this.setValueOidString(oid); + } else { + throw "DERObjectIdentifier oidName undefined: " + oidName; + } + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (params !== undefined) { + if (typeof params === "string") { + if (params.match(/^[0-2].[0-9.]+$/)) { + this.setValueOidString(params); + } else { + this.setValueName(params); + } + } else if (params.oid !== undefined) { + this.setValueOidString(params.oid); + } else if (params.hex !== undefined) { + this.setValueHex(params.hex); + } else if (params.name !== undefined) { + this.setValueName(params.name); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER Enumerated + * @name KJUR.asn1.DEREnumerated + * @class class for ASN.1 DER Enumerated + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • int - specify initial ASN.1 value(V) by integer value
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    + * NOTE: 'params' can be omitted. + * @example + * new KJUR.asn1.DEREnumerated(123); + * new KJUR.asn1.DEREnumerated({int: 123}); + * new KJUR.asn1.DEREnumerated({hex: '1fad'}); + */ +KJUR.asn1.DEREnumerated = function(params) { + KJUR.asn1.DEREnumerated.superclass.constructor.call(this); + this.hT = "0a"; + + /** + * set value by Tom Wu's BigInteger object + * @name setByBigInteger + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {BigInteger} bigIntegerValue to set + */ + this.setByBigInteger = function(bigIntegerValue) { + this.hTLV = null; + this.isModified = true; + this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue); + }; + + /** + * set value by integer value + * @name setByInteger + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {Integer} integer value to set + */ + this.setByInteger = function(intValue) { + var bi = new BigInteger(String(intValue), 10); + this.setByBigInteger(bi); + }; + + /** + * set value by integer value + * @name setValueHex + * @memberOf KJUR.asn1.DEREnumerated# + * @function + * @param {String} hexadecimal string of integer value + * @description + *
    + * NOTE: Value shall be represented by minimum octet length of + * two's complement representation. + */ + this.setValueHex = function(newHexString) { + this.hV = newHexString; + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['int'] != "undefined") { + this.setByInteger(params['int']); + } else if (typeof params == "number") { + this.setByInteger(params); + } else if (typeof params['hex'] != "undefined") { + this.setValueHex(params['hex']); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DEREnumerated, KJUR.asn1.ASN1Object); + +// ******************************************************************** +/** + * class for ASN.1 DER UTF8String + * @name KJUR.asn1.DERUTF8String + * @class class for ASN.1 DER UTF8String + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERUTF8String = function(params) { + KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params); + this.hT = "0c"; +}; +YAHOO.lang.extend(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER NumericString + * @name KJUR.asn1.DERNumericString + * @class class for ASN.1 DER NumericString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERNumericString = function(params) { + KJUR.asn1.DERNumericString.superclass.constructor.call(this, params); + this.hT = "12"; +}; +YAHOO.lang.extend(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER PrintableString + * @name KJUR.asn1.DERPrintableString + * @class class for ASN.1 DER PrintableString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERPrintableString = function(params) { + KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params); + this.hT = "13"; +}; +YAHOO.lang.extend(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER TeletexString + * @name KJUR.asn1.DERTeletexString + * @class class for ASN.1 DER TeletexString + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERTeletexString = function(params) { + KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params); + this.hT = "14"; +}; +YAHOO.lang.extend(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER IA5String + * @name KJUR.asn1.DERIA5String + * @class class for ASN.1 DER IA5String + * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) + * @extends KJUR.asn1.DERAbstractString + * @description + * @see KJUR.asn1.DERAbstractString - superclass + */ +KJUR.asn1.DERIA5String = function(params) { + KJUR.asn1.DERIA5String.superclass.constructor.call(this, params); + this.hT = "16"; +}; +YAHOO.lang.extend(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString); + +// ******************************************************************** +/** + * class for ASN.1 DER UTCTime + * @name KJUR.asn1.DERUTCTime + * @class class for ASN.1 DER UTCTime + * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) + * @extends KJUR.asn1.DERAbstractTime + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • str - specify initial ASN.1 value(V) by a string (ex.'130430235959Z')
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    • date - specify Date object.
    • + *
    + * NOTE: 'params' can be omitted. + *

    EXAMPLES

    + * @example + * d1 = new KJUR.asn1.DERUTCTime(); + * d1.setString('130430125959Z'); + * + * d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'}); + * d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))}); + * d4 = new KJUR.asn1.DERUTCTime('130430125959Z'); + */ +KJUR.asn1.DERUTCTime = function(params) { + KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params); + this.hT = "17"; + + /** + * set value by a Date object
    + * @name setByDate + * @memberOf KJUR.asn1.DERUTCTime# + * @function + * @param {Date} dateObject Date object to set ASN.1 value(V) + * @example + * o = new KJUR.asn1.DERUTCTime(); + * o.setByDate(new Date("2016/12/31")); + */ + this.setByDate = function(dateObject) { + this.hTLV = null; + this.isModified = true; + this.date = dateObject; + this.s = this.formatDate(this.date, 'utc'); + this.hV = stohex(this.s); + }; + + this.getFreshValueHex = function() { + if (typeof this.date == "undefined" && typeof this.s == "undefined") { + this.date = new Date(); + this.s = this.formatDate(this.date, 'utc'); + this.hV = stohex(this.s); + } + return this.hV; + }; + + if (params !== undefined) { + if (params.str !== undefined) { + this.setString(params.str); + } else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) { + this.setString(params); + } else if (params.hex !== undefined) { + this.setStringHex(params.hex); + } else if (params.date !== undefined) { + this.setByDate(params.date); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime); + +// ******************************************************************** +/** + * class for ASN.1 DER GeneralizedTime + * @name KJUR.asn1.DERGeneralizedTime + * @class class for ASN.1 DER GeneralizedTime + * @param {Array} params associative array of parameters (ex. {'str': '20130430235959Z'}) + * @property {Boolean} withMillis flag to show milliseconds or not + * @extends KJUR.asn1.DERAbstractTime + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • str - specify initial ASN.1 value(V) by a string (ex.'20130430235959Z')
    • + *
    • hex - specify initial ASN.1 value(V) by a hexadecimal string
    • + *
    • date - specify Date object.
    • + *
    • millis - specify flag to show milliseconds (from 1.0.6)
    • + *
    + * NOTE1: 'params' can be omitted. + * NOTE2: 'withMillis' property is supported from asn1 1.0.6. + */ +KJUR.asn1.DERGeneralizedTime = function(params) { + KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params); + this.hT = "18"; + this.withMillis = false; + + /** + * set value by a Date object + * @name setByDate + * @memberOf KJUR.asn1.DERGeneralizedTime# + * @function + * @param {Date} dateObject Date object to set ASN.1 value(V) + * @example + * When you specify UTC time, use 'Date.UTC' method like this:
    + * o1 = new DERUTCTime(); + * o1.setByDate(date); + * + * date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59 + */ + this.setByDate = function(dateObject) { + this.hTLV = null; + this.isModified = true; + this.date = dateObject; + this.s = this.formatDate(this.date, 'gen', this.withMillis); + this.hV = stohex(this.s); + }; + + this.getFreshValueHex = function() { + if (this.date === undefined && this.s === undefined) { + this.date = new Date(); + this.s = this.formatDate(this.date, 'gen', this.withMillis); + this.hV = stohex(this.s); + } + return this.hV; + }; + + if (params !== undefined) { + if (params.str !== undefined) { + this.setString(params.str); + } else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) { + this.setString(params); + } else if (params.hex !== undefined) { + this.setStringHex(params.hex); + } else if (params.date !== undefined) { + this.setByDate(params.date); + } + if (params.millis === true) { + this.withMillis = true; + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime); + +// ******************************************************************** +/** + * class for ASN.1 DER Sequence + * @name KJUR.asn1.DERSequence + * @class class for ASN.1 DER Sequence + * @extends KJUR.asn1.DERAbstractStructured + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • array - specify array of ASN1Object to set elements of content
    • + *
    + * NOTE: 'params' can be omitted. + */ +KJUR.asn1.DERSequence = function(params) { + KJUR.asn1.DERSequence.superclass.constructor.call(this, params); + this.hT = "30"; + this.getFreshValueHex = function() { + var h = ''; + for (var i = 0; i < this.asn1Array.length; i++) { + var asn1Obj = this.asn1Array[i]; + h += asn1Obj.getEncodedHex(); + } + this.hV = h; + return this.hV; + }; +}; +YAHOO.lang.extend(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured); + +// ******************************************************************** +/** + * class for ASN.1 DER Set + * @name KJUR.asn1.DERSet + * @class class for ASN.1 DER Set + * @extends KJUR.asn1.DERAbstractStructured + * @description + *
    + * As for argument 'params' for constructor, you can specify one of + * following properties: + *
      + *
    • array - specify array of ASN1Object to set elements of content
    • + *
    • sortflag - flag for sort (default: true). ASN.1 BER is not sorted in 'SET OF'.
    • + *
    + * NOTE1: 'params' can be omitted.
    + * NOTE2: sortflag is supported since 1.0.5. + */ +KJUR.asn1.DERSet = function(params) { + KJUR.asn1.DERSet.superclass.constructor.call(this, params); + this.hT = "31"; + this.sortFlag = true; // item shall be sorted only in ASN.1 DER + this.getFreshValueHex = function() { + var a = new Array(); + for (var i = 0; i < this.asn1Array.length; i++) { + var asn1Obj = this.asn1Array[i]; + a.push(asn1Obj.getEncodedHex()); + } + if (this.sortFlag == true) a.sort(); + this.hV = a.join(''); + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params.sortflag != "undefined" && + params.sortflag == false) + this.sortFlag = false; + } +}; +YAHOO.lang.extend(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured); + +// ******************************************************************** +/** + * class for ASN.1 DER TaggedObject + * @name KJUR.asn1.DERTaggedObject + * @class class for ASN.1 DER TaggedObject + * @extends KJUR.asn1.ASN1Object + * @description + *
    + * Parameter 'tagNoNex' is ASN.1 tag(T) value for this object. + * For example, if you find '[1]' tag in a ASN.1 dump, + * 'tagNoHex' will be 'a1'. + *
    + * As for optional argument 'params' for constructor, you can specify *ANY* of + * following properties: + *
      + *
    • explicit - specify true if this is explicit tag otherwise false + * (default is 'true').
    • + *
    • tag - specify tag (default is 'a0' which means [0])
    • + *
    • obj - specify ASN1Object which is tagged
    • + *
    + * @example + * d1 = new KJUR.asn1.DERUTF8String({'str':'a'}); + * d2 = new KJUR.asn1.DERTaggedObject({'obj': d1}); + * hex = d2.getEncodedHex(); + */ +KJUR.asn1.DERTaggedObject = function(params) { + KJUR.asn1.DERTaggedObject.superclass.constructor.call(this); + this.hT = "a0"; + this.hV = ''; + this.isExplicit = true; + this.asn1Object = null; + + /** + * set value by an ASN1Object + * @name setString + * @memberOf KJUR.asn1.DERTaggedObject# + * @function + * @param {Boolean} isExplicitFlag flag for explicit/implicit tag + * @param {Integer} tagNoHex hexadecimal string of ASN.1 tag + * @param {ASN1Object} asn1Object ASN.1 to encapsulate + */ + this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) { + this.hT = tagNoHex; + this.isExplicit = isExplicitFlag; + this.asn1Object = asn1Object; + if (this.isExplicit) { + this.hV = this.asn1Object.getEncodedHex(); + this.hTLV = null; + this.isModified = true; + } else { + this.hV = null; + this.hTLV = asn1Object.getEncodedHex(); + this.hTLV = this.hTLV.replace(/^../, tagNoHex); + this.isModified = false; + } + }; + + this.getFreshValueHex = function() { + return this.hV; + }; + + if (typeof params != "undefined") { + if (typeof params['tag'] != "undefined") { + this.hT = params['tag']; + } + if (typeof params['explicit'] != "undefined") { + this.isExplicit = params['explicit']; + } + if (typeof params['obj'] != "undefined") { + this.asn1Object = params['obj']; + this.setASN1Object(this.isExplicit, this.hT, this.asn1Object); + } + } +}; +YAHOO.lang.extend(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object); \ No newline at end of file diff --git a/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/yahoo.js b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/yahoo.js new file mode 100644 index 0000000..fca3b26 --- /dev/null +++ b/uni_modules/x-crypto-s/utssdk/web/src/lib/jsrsasign/yahoo.js @@ -0,0 +1,72 @@ +/*! +Copyright (c) 2011, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.9.0 +*/ +export var YAHOO = {}; +YAHOO.lang = { + /** + * Utility to set up the prototype, constructor and superclass properties to + * support an inheritance strategy that can chain constructors and methods. + * Static members will not be inherited. + * + * @method extend + * @static + * @param {Function} subc the object to modify + * @param {Function} superc the object to inherit + * @param {Object} overrides additional properties/methods to add to the + * subclass prototype. These will override the + * matching items obtained from the superclass + * if present. + */ + extend: function(subc, superc, overrides) { + if (! superc || ! subc) { + throw new Error("YAHOO.lang.extend failed, please check that " + + "all dependencies are included."); + } + + var F = function() {}; + F.prototype = superc.prototype; + subc.prototype = new F(); + subc.prototype.constructor = subc; + subc.superclass = superc.prototype; + + if (superc.prototype.constructor == Object.prototype.constructor) { + superc.prototype.constructor = superc; + } + + if (overrides) { + var i; + for (i in overrides) { + subc.prototype[i] = overrides[i]; + } + + /* + * IE will not enumerate native functions in a derived object even if the + * function was overridden. This is a workaround for specific functions + * we care about on the Object prototype. + * @property _IEEnumFix + * @param {Function} r the object to receive the augmentation + * @param {Function} s the object that supplies the properties to augment + * @static + * @private + */ + var _IEEnumFix = function() {}, + ADD = ["toString", "valueOf"]; + try { + if (/MSIE/.test(navigator.userAgent)) { + _IEEnumFix = function(r, s) { + for (i = 0; i < ADD.length; i = i + 1) { + var fname = ADD[i], f = s[fname]; + if (typeof f === 'function' && f != Object.prototype[fname]) { + r[fname] = f; + } + } + }; + } + } catch (ex) {}; + _IEEnumFix(subc.prototype, overrides); + } + } +}; \ No newline at end of file diff --git a/uni_modules/x-design/changelog.md b/uni_modules/x-design/changelog.md new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-design/components/x-design/x-design.uvue b/uni_modules/x-design/components/x-design/x-design.uvue new file mode 100644 index 0000000..216da74 --- /dev/null +++ b/uni_modules/x-design/components/x-design/x-design.uvue @@ -0,0 +1,9 @@ + + + diff --git a/uni_modules/x-design/components/xd-blur/xd-blur.uvue b/uni_modules/x-design/components/xd-blur/xd-blur.uvue new file mode 100644 index 0000000..de18797 --- /dev/null +++ b/uni_modules/x-design/components/xd-blur/xd-blur.uvue @@ -0,0 +1,109 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/x-design/components/xd-modal-page/xd-modal-page.uvue b/uni_modules/x-design/components/xd-modal-page/xd-modal-page.uvue new file mode 100644 index 0000000..48bd802 --- /dev/null +++ b/uni_modules/x-design/components/xd-modal-page/xd-modal-page.uvue @@ -0,0 +1,53 @@ + + + diff --git a/uni_modules/x-design/components/xd-picker-view/xd-picker-view.uvue b/uni_modules/x-design/components/xd-picker-view/xd-picker-view.uvue new file mode 100644 index 0000000..131d716 --- /dev/null +++ b/uni_modules/x-design/components/xd-picker-view/xd-picker-view.uvue @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/x-design/package.json b/uni_modules/x-design/package.json new file mode 100644 index 0000000..722ab5c --- /dev/null +++ b/uni_modules/x-design/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-design", + "displayName": "x-design", + "version": "1.0.0", + "description": "x-design", + "keywords": [ + "x-design" +], + "repository": "", + "engines": { + "HBuilderX": "^4.31" + }, + "dcloudext": { + "type": "uts-vue-component", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-design/readme.md b/uni_modules/x-design/readme.md new file mode 100644 index 0000000..736a9e5 --- /dev/null +++ b/uni_modules/x-design/readme.md @@ -0,0 +1,46 @@ +# x-design +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +这是标准组件库依赖系列 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 使用 + +与正常的uvue组件一样使用,但不同的是,这些全是原生标准组件,需要打包或者mac系统配置环境使用,不能在普通win环境使用. +如果在win下使用,请先在页面调用 ,再打基座使用.如果是mac配置好环境可以直接使用. + +**xd-blur有三个属性** +blur:0-100模糊度 +bgColor:模糊的叠加颜色 +into:模糊对象,可选值parent:模糊它的父级(即背景),self:模糊自身内容(标签内的所有内容被模糊) +当模糊背景的时候需要设置为fiexd在根节点的直接子直接,这样可以模糊动态背景内容,当模糊自身内容时,请把内容放到标签内. + +### 模糊组件xdBlur +模糊背景: +它的背景会被局部模糊到xd-blur自身(俗称的磨砂背景效果),作为背景模糊时,插槽会失效,因此你要把它当作一个背景图定位到你的内容下方。 +```vue + + + +``` +模糊自己的内容: +它的内容会被全部模糊化(俗称的图片模糊,内容模糊) +```vue + + + 主色 + 错误 + 警告 + 危险 + 成功 + 次要 + + +``` diff --git a/uni_modules/x-design/utssdk/app-android/config.json b/uni_modules/x-design/utssdk/app-android/config.json new file mode 100644 index 0000000..156d2b0 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-android/config.json @@ -0,0 +1,7 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "jp.wasabeef:blurry:4.0.1", + "com.github.Dimezis:BlurView:version-2.0.6" + ] +} diff --git a/uni_modules/x-design/utssdk/app-android/index.uts b/uni_modules/x-design/utssdk/app-android/index.uts new file mode 100644 index 0000000..4cc4cb3 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-android/index.uts @@ -0,0 +1,134 @@ +// import UniversalBlurHelper from 'uts.sdk.modules.utsXdBlur.UniversalBlurHelper'; +import Color from 'android.graphics.Color'; +import View from 'android.view.View'; + +import Blurry from 'jp.wasabeef.blurry.Blurry' +import ViewGroup from "android.view.ViewGroup"; +import Bitmap from "android.graphics.Bitmap"; +import ImageView from 'android.widget.ImageView'; +import Canvas from 'android.graphics.Canvas'; + +import BitmapDrawable from "android.graphics.drawable.BitmapDrawable"; +import { hexToRgb } from '../libs/color.uts' +import { ManiWinFloat } from './mainWinFloa.uts' + +export class xModalPage { + contentView : View | null = null; + rootWin : ManiWinFloat = new ManiWinFloat(); + constructor() { + + } + setView(ele : UniElement | null) { + if (ele == null) return; + let userView = ele.getAndroidView() as View | null + + + if (userView == null) return; + + this.contentView = userView; + this.rootWin.setContent(userView) + } + show() { + this.rootWin.show() + + } + hide() { + + } + destroy() { + + } +} + + + +export class xdBlur { + $element : UniNativeViewElement; + targetView : View | null = null; + // bgView:bgBlurView = new bgBlurView(UTSAndroid.getAppContext()!) + constructor(element : UniNativeViewElement) { + //接收传递过来的UniNativeViewElement + this.$element = element; + this.bindView(); + } + bindView() { + //通过UniElement.getAndroidActivity()获取android平台activity 用于创建view的上下文 + this.targetView = new View(this.$element.getAndroidActivity()!); //构建原生view + // this.targetView = new bgBlurView(this.$element.getAndroidActivity()!); //构建原生view + + // this.targetView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)) + + // //限制原生Button 文案描述不自动大写 + // this.button?.setAllCaps(false) + // //监听原生Button点击事件 + // this.button?.setOnClickListener(_ => { + // const detail = {} + // //构建自定义UniNativeViewEvent返回对象 + // const event = new UniNativeViewEvent("customClick", detail) + // //触发原生Button的点击事件 + // this.$element.dispatchEvent(event) + // }) + //UniNativeViewEvent 绑定 安卓原生view + this.$element.bindAndroidView(this.targetView!); + } + + + setFilterBg(blur : number, bgcolor : string, ele : UniElement | null = null) { + // let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + // this.targetView?.refreshBG(decorView) + + let colorrgba = hexToRgb(bgcolor) + let r = (colorrgba?.r ?? 255).toInt() + let g = (colorrgba?.g ?? 255).toInt() + let b = (colorrgba?.b ?? 255).toInt() + let a = ((colorrgba?.a ?? 1) * 255).toInt() + let br = (blur / 100 * 25).toFloat() + let view = this.targetView!; + view.setBackgroundColor(Color.argb(a, r, g, b)) + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + let context = UTSAndroid.getAppContext()!; + + let bitmap : Bitmap = Blurry.with(context) + .radius(br.toInt()) // 模糊度 + .sampling(8) // 采样 + .color(Color.argb(a, r, g, b)) + .capture(decorView) // 捕获背景View + .get() + let location = new IntArray(2); + view.getLocationInWindow(location); + let top = (location[1]).toInt() + let left = location[0] + let okbitm = Bitmap.createBitmap(bitmap, left, top, view.getWidth(), view.getHeight()); + view.setBackground(new BitmapDrawable(view.getResources(), okbitm)); + } + + public static setFilterSelfBg(ele : UniElement, bg : UniElement, blur : number, bgcolor : string) { + let colorrgba = hexToRgb(bgcolor) + let r = (colorrgba?.r ?? 255).toInt() + let g = (colorrgba?.g ?? 255).toInt() + let b = (colorrgba?.b ?? 255).toInt() + let a = ((colorrgba?.a ?? 1) * 255).toInt() + let br = (blur / 100 * 25).toFloat() + let view = ele.getAndroidView()! as View + let viewbg = bg.getAndroidView()! as View + let context = UTSAndroid.getAppContext()!; + + let bitmapbg = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888) + let canvas = new Canvas(bitmapbg) + view.draw(canvas) + + let imgview = new ImageView(context) + Blurry.with(context) + .radius(br.toInt()) + .sampling(8) + .color(Color.argb(a, r, g, b)) + .from(bitmapbg) + .into(imgview) + + viewbg.setBackground(imgview.getDrawable()); + } + + + +} + diff --git a/uni_modules/x-design/utssdk/app-android/mainWinFloa.uts b/uni_modules/x-design/utssdk/app-android/mainWinFloa.uts new file mode 100644 index 0000000..607fac3 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-android/mainWinFloa.uts @@ -0,0 +1,82 @@ +import LinearLayout from 'android.widget.LinearLayout'; +import Context from 'android.content.Context' +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import Color from 'android.graphics.Color'; +import Gravity from 'android.view.Gravity'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable'; +import TextView from 'android.widget.TextView'; +import Typeface from 'android.graphics.Typeface'; +import TextUtils from 'android.text.TextUtils'; +import Uri from 'android.net.Uri'; +import ObjectAnimator from 'android.animation.ObjectAnimator'; +import ValueAnimator from 'android.animation.ValueAnimator'; +import TimeInterpolator from 'android.animation.TimeInterpolator'; +import MotionEvent from 'android.view.MotionEvent'; +import { hexToRgb } from "../libs/color.uts" +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; +import ScrollView from 'android.widget.ScrollView'; +import AccelerateDecelerateInterpolator from 'android.view.animation.AccelerateDecelerateInterpolator'; +// #ifdef UNI-APP-X +import getCurrentPages from 'io.dcloud.uniapp.framework.getCurrentPages'; +import onReady from 'io.dcloud.uniapp.framework.onReady'; +import onUnload from 'io.dcloud.uniapp.framework.onUnload'; +import onShow from 'io.dcloud.uniapp.framework.onShow'; +import Visibility from 'android.transition.Visibility'; +// #endif + + +export class ManiWinFloat { + contentView:View|null = null; + parentView:LinearLayout|null = null; + contentWrap:ScrollView|null = null; + constructor(){ + this._createRootView(); + } + getContext():Context{ + const context = UTSAndroid.getAppContext()! as Context + return context; + } + getWinRoot():ViewGroup{ + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + return decorView; + } + setContent(view:View){ + this.contentView = view; + this.contentWrap?.addView(view) + console.log(view) + } + show(){ + this.parentView?.setVisibility(View.VISIBLE) + } + hide(){} + destroy(){ + + } + + _createRootView(){ + // 内容容器 + let container = new LinearLayout(this.getContext()); + + let containerLayrPrams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + container.setLayoutParams(containerLayrPrams) + container.setBackgroundColor(Color.GREEN) + container.setOrientation(LinearLayout.VERTICAL) + // container.setGravity(Gravity.CENTER) + container.setVisibility(View.GONE) + container.setAlpha((0.3).toFloat()) + + // 滚动容器 + let scroll = new ScrollView(this.getContext()) + scroll.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) + this.contentWrap = scroll; + container.addView(scroll) + this.parentView = container; + this.getWinRoot().addView(this.parentView) + + } +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/app-harmony/builder.ets b/uni_modules/x-design/utssdk/app-harmony/builder.ets new file mode 100644 index 0000000..cccd3d4 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-harmony/builder.ets @@ -0,0 +1,14 @@ +@Builder +export function buildXdBlurView(params: ESObject) { + Column(){}.width('100%').height('100%') + .backgroundColor('rgba(255,0,0,0.3') + .backdropBlur(params.blur,{grayscale:[50,50]}) +} + + +@Builder +export function buildXdParentBlurView(params: ESObject) { + Column(){}.width('100%').height('100%') + .backgroundColor('rgba(255,0,0,0.3') + .backdropBlur(params.blur,{grayscale:[50,50]}) +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/app-harmony/index.uts b/uni_modules/x-design/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..c129a25 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-harmony/index.uts @@ -0,0 +1,38 @@ +import { BuilderNode, ComponentContent } from "@kit.ArkUI" +import { image } from '@kit.ImageKit'; +import * from '@ohos.multimedia.image'; +import {buildXdBlurView,buildXdParentBlurView} from "./builder.ets" +// 定义 buildButton 的参数类型 +interface NativeXdblurOptions { + blur:number +} +export class xdBlur { + $element : UniNativeViewElement; + targetView : BuilderNode<[NativeXdblurOptions]> | null = null; + // 初始化 buildButton 默认参数 + private params : NativeXdblurOptions = { + blur: 30, + } + constructor(element : UniNativeViewElement) { + // 绑定 wrapBuilder 函数 + this.targetView = element.bindHarmonyWrappedBuilder(wrapBuilder<[NativeXdblurOptions]>(buildXdBlurView), this.params) + this.$element = element + // 绑定当前实例为自定义的controller,方便其他地方通过 element 获取使用 + this.$element.bindHarmonyController(this) + // this.targetView. + } + setFilterBg(blur : number, bgcolor : string,ele:UniElement|null = null) { + this.params.blur = blur; + this.targetView?.update(this.params) + } + setFilterSelfBg(ele : UniElement,bg:UniElement, blur : number, bgcolor : string) { + // this.params.blur = blur; + // const parent = this.targetView?.getFrameNode()?.getParent(); + // const uiContext = UTSHarmony.getCurrentWindow()!.getUIContext(); + // let component = new ComponentContent(uiContext, wrapBuilder<[NativeXdblurOptions]>(buildXdParentBlurView), this.params) + // parent?.addComponentContent(component) + // const px = uiContext.getComponentSnapshot().getSyncWithUniqueId(parent?.getUniqueId()!) + // let pos = image.PositionArea + // ele.getDrawableContext()?.fill(px.readPixelsSync()) + } +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-design/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-design/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-design/utssdk/app-ios/XdBlur.swift b/uni_modules/x-design/utssdk/app-ios/XdBlur.swift new file mode 100644 index 0000000..d6bf008 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-ios/XdBlur.swift @@ -0,0 +1,117 @@ +import UIKit +class XdBlur { + /// 为视图添加背景模糊效果 + /// - Parameters: + /// - view: 需要添加模糊效果的目标视图 + /// - style: 模糊样式(Light, Dark, ExtraLight) + /// - intensity: 模糊强度,范围 0-1 + /// - backgroundColor: 可选的背景颜色叠加 + static func applyBlur( + to view: UIView, + style: UIBlurEffect.Style = .light, + intensity: CGFloat = 0.8, + backgroundColor: UIColor? = nil + ) { + // 移除之前可能存在的模糊效果 + view.subviews + .filter { $0 is UIVisualEffectView } + .forEach { $0.removeFromSuperview() } + + // 创建模糊效果 + let blurEffect = UIBlurEffect(style: style) + let blurView = UIVisualEffectView(effect: blurEffect) + + // 调整模糊强度 + if #available(iOS 13.0, *) { + let vibrancyView = UIVisualEffectView(effect: + UIVibrancyEffect(blurEffect: blurEffect, style: .fill) + ) + blurView.contentView.addSubview(vibrancyView) + } + + // 设置frame与目标视图一致 + blurView.frame = view.bounds + blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + // 设置透明度控制模糊强度 + blurView.alpha = intensity + + // 如果需要叠加背景色 + if let backgroundColor = backgroundColor { + let colorView = UIView(frame: blurView.bounds) + colorView.backgroundColor = backgroundColor + colorView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + blurView.contentView.addSubview(colorView) + } + + // 插入到视图底部 + view.insertSubview(blurView, at: 0) + } + + /// 移除背景模糊效果 + /// - Parameter view: 需要移除模糊效果的视图 + static func removeBlur(from view: UIView) { + view.subviews + .filter { $0 is UIVisualEffectView } + .forEach { $0.removeFromSuperview() } + } + + /// 为视图添加自定义高斯模糊效果 + /// - Parameters: + /// - view: 目标视图 + /// - radius: 模糊半径 + /// - tintColor: 颜色叠加 + static func applyCustomBlur( + to view: UIView, + radius: CGFloat = 10, + tintColor: UIColor? = nil + ) { + // 创建模糊效果 + let blurEffect = UIBlurEffect(style: .light) + let blurView = UIVisualEffectView(effect: blurEffect) + + // 应用额外的模糊 + let vibrancyView = UIVisualEffectView(effect: + UIVibrancyEffect(blurEffect: blurEffect) + ) + + blurView.frame = view.bounds + blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + // 添加自定义颜色叠加 + if let tintColor = tintColor { + let colorView = UIView(frame: blurView.bounds) + colorView.backgroundColor = tintColor + colorView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + blurView.contentView.addSubview(colorView) + } + + view.insertSubview(blurView, at: 0) + } + + static func applyBlurSelf(ele: UIView ,bg:UIView, blur: CGFloat, backgroundColor: UIColor = .clear) { + // Create snapshot of element + UIGraphicsBeginImageContextWithOptions(ele.bounds.size, false, 0) + ele.layer.render(in: UIGraphicsGetCurrentContext()!) + let snapshot = UIGraphicsGetImageFromCurrentImageContext()! + UIGraphicsEndImageContext() + + // Create blur effect + let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) + effectView.frame = bg.bounds + + // Create color overlay + let colorView = UIView(frame: bg.bounds) + colorView.backgroundColor = backgroundColor + colorView.alpha = blur + + // Add views to background + bg.addSubview(effectView) + bg.addSubview(colorView) + + // Set snapshot as background + let imageView = UIImageView(image: snapshot) + imageView.frame = bg.bounds + bg.insertSubview(imageView, at: 0) + } +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/app-ios/config.json b/uni_modules/x-design/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-design/utssdk/app-ios/index.uts b/uni_modules/x-design/utssdk/app-ios/index.uts new file mode 100644 index 0000000..f821844 --- /dev/null +++ b/uni_modules/x-design/utssdk/app-ios/index.uts @@ -0,0 +1,103 @@ +import { UIViewController, UIView, UIWindow, UIScreen, UIColor, UIBlurEffect } from 'UIKit'; +import { CGRect, CGFloat, CGPoint, CGAffineTransform, CGSize } from 'CoreFoundation'; +import { CABasicAnimation, CAMediaTimingFillMode, CATransform3DIsIdentity, CATransform3DIdentity, CATransform3DMakeTranslation, CATransform3DRotate, CATransform3DScale } from 'QuartzCore'; +import { getRootView } from "./libs/util.uts" +import { Color } from 'SwiftUI'; +import { hexToRgb } from '../libs/color.uts' + + + +export class xModalPage { + contentView : UIView | null = null; + rootWin : UIWindow; + constructor() { + let winsize = UIScreen.main.bounds as CGRect; + let mainwidth = new CGRect(x = 0, y = 180, width = 300, height = 200) + // 创建一个新的 UIWindow 实例 + let newWindow = new UIWindow(frame = mainwidth) + // newWindow.frame = mainwidth + this.rootWin = newWindow; + } + setView(ele : UniElement | null) { + if (ele == null) return; + let userView = ele!.getIOSView() as UIView | null + if (userView == null) return; + this.contentView = userView!; + class ContentWin extends UIViewController { + userView : UIView | null = null; + setAddView(userViewBox : UIView | null) { + this.userView = userViewBox; + } + override viewDidLoad() { + super.viewDidLoad(); + let root = super.view as UIView; + root.backgroundColor = UIColor.black + if (this.userView != null) { + let cview = this.userView! as UIView; + cview.frame = UIScreen.main.bounds + root.addSubview(cview) + } + } + + + } + if (this.contentView == null) return; + DispatchQueue.main.async(execute = () : void => { + // 创建一个新的 UIViewController 实例作为模态视图控制器 + let secondViewController = new ContentWin() + secondViewController.setAddView(this.contentView) + // 将模态视图控制器添加到新窗口中 + this.rootWin.rootViewController = secondViewController as UIViewController + + }) + } + show() { + let pageconroll = this.rootWin.rootViewController; + if (this.contentView == null || pageconroll == null) return; + DispatchQueue.main.async(execute = () : void => { + this.rootWin.makeKeyAndVisible() + let parent = UTSiOS.getCurrentViewController() as UIViewController; + parent.present(pageconroll!, animated = true, completion = nil) + }) + + } + hide() { + DispatchQueue.main.async(execute = () : void => { + this.rootWin.rootViewController?.dismiss(animated = true, completion = nil) + }) + } + destroy() { + + } +} + +export class xdBlur { + $element : UniNativeViewElement; + targetView : UIView | null = null; + constructor(element : UniNativeViewElement) { + //接收传递过来的UniNativeViewElement + this.$element = element; + this.targetView = new UIView() + this.$element.bindIOSView(this.targetView!); + } + + setFilterBg(blur : number, bgcolor : string,ele:UniElement|null = null) { + let colorrgba = hexToRgb(bgcolor) + let br = (blur / 100).toFloat() + let view = this.targetView! + XdBlur.applyBlur( + to = view, + style = UIBlurEffect.Style.light, + intensity = new CGFloat(br), + backgroundColor = UTSiOS.colorWithString(bgcolor) + ) + } + public static setFilterSelfBg(ele : UniElement,bg:UniElement, blur : number, bgcolor : string) { + let colorrgba = hexToRgb(bgcolor) + let br = (blur / 100).toFloat() + let view = ele.getIOSView()! as UIView + let viewbg = bg.getIOSView()! as UIView + + XdBlur.applyBlurSelf(ele=view,bg = viewbg, blur = new CGFloat(br), backgroundColor = UTSiOS.colorWithString(bgcolor)) + } +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/app-ios/libs/util.uts b/uni_modules/x-design/utssdk/app-ios/libs/util.uts new file mode 100644 index 0000000..8f76f8b --- /dev/null +++ b/uni_modules/x-design/utssdk/app-ios/libs/util.uts @@ -0,0 +1,10 @@ +import { UIViewController, UIView } from 'UIKit'; +export function getRootView() : UIView { + let parent = UTSiOS.getCurrentViewController() as UIViewController; + let windUiview = parent.view as UIView + return windUiview; +} +export function getRoot() : UIViewController { + let parent = UTSiOS.getCurrentViewController() as UIViewController; + return parent; +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/libs/color.uts b/uni_modules/x-design/utssdk/libs/color.uts new file mode 100644 index 0000000..e4e51a9 --- /dev/null +++ b/uni_modules/x-design/utssdk/libs/color.uts @@ -0,0 +1,65 @@ +type RGBA = { r : number, g : number, b : number, a : number } +export function hexToRgb(sColors : string) : RGBA | null { + if (sColors == "") { + return { r: 0, g: 0, b: 0, a: 0 } as RGBA + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + + let p : number[] = arr.map((val : string) : number => parseInt(val)); + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + arr.push('1') + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: parseFloat(arr[3]) + } as RGBA + } else { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + + return null; +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/mp-weixin/index.uts b/uni_modules/x-design/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..fe21ac7 --- /dev/null +++ b/uni_modules/x-design/utssdk/mp-weixin/index.uts @@ -0,0 +1,50 @@ +import { hexToRgb } from '../libs/color.uts' + + + +export class xModalPage { + contentView : HTMLDivElement | null = null; + rootWin : HTMLDivElement | null = null; + constructor() { + + } + setView(ele : HTMLDivElement | null) { + + } + show() { + + + } + hide() { + + } + destroy() { + + } +} + +export class xdBlur { + constructor(element : UniNativeViewElement) { + + } + setFilterBg( blur : number, bgcolor : string,ele : HTMLDivElement|null=null) { + let colorrgba = hexToRgb(bgcolor) + let r = (colorrgba?.r??255) + let g = (colorrgba?.g??255) + let b = (colorrgba?.b??255) + let a = (colorrgba?.a??1) + let br = blur + ele?.style.setProperty('background-color',`rgba(${r},${g},${b},${a})`) + ele?.style.setProperty('backdrop-filter',`blur(${Math.min(br,10)}px)`) + } + public static setFilterSelfBg(ele : HTMLDivElement,bg:HTMLDivElement, blur : number, bgcolor : string) { + let colorrgba = hexToRgb(bgcolor) + let r = (colorrgba?.r??255) + let g = (colorrgba?.g??255) + let b = (colorrgba?.b??255) + let a = (colorrgba?.a??1) + let br = blur + bg.style.setProperty('background-color',`rgba(${r},${g},${b},${a})`) + bg.style.setProperty('backdrop-filter',`blur(${Math.min(br,10)}px)`) + } +} \ No newline at end of file diff --git a/uni_modules/x-design/utssdk/web/index.uts b/uni_modules/x-design/utssdk/web/index.uts new file mode 100644 index 0000000..0897c7f --- /dev/null +++ b/uni_modules/x-design/utssdk/web/index.uts @@ -0,0 +1,51 @@ +import { hexToRgb } from '../libs/color.uts' + + + +export class xModalPage { + contentView : HTMLDivElement | null = null; + rootWin : HTMLDivElement | null = null; + constructor() { + + } + setView(ele : HTMLDivElement | null) { + + } + show() { + + + } + hide() { + + } + destroy() { + + } +} + +export class xdBlur { + constructor(element : UniNativeViewElement) { + + } + setFilterBg( blur : number, bgcolor : string,ele : HTMLDivElement|null=null) { + + let colorrgba = hexToRgb(bgcolor) + let r = (colorrgba?.r??255) + let g = (colorrgba?.g??255) + let b = (colorrgba?.b??255) + let a = (colorrgba?.a??1) + let br = blur + ele?.style.setProperty('background-color',`rgba(${r},${g},${b},${a})`) + ele?.style.setProperty('backdrop-filter',`blur(${Math.min(br,10)}px)`) + } + public static setFilterSelfBg(ele : HTMLDivElement,bg:HTMLDivElement, blur : number, bgcolor : string) { + let colorrgba = hexToRgb(bgcolor) + let r = (colorrgba?.r??255) + let g = (colorrgba?.g??255) + let b = (colorrgba?.b??255) + let a = (colorrgba?.a??1) + let br = blur + bg.style.setProperty('background-color',`rgba(${r},${g},${b},${a})`) + bg.style.setProperty('backdrop-filter',`blur(${Math.min(br,10)}px)`) + } +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/changelog.md b/uni_modules/x-facedetection/changelog.md new file mode 100644 index 0000000..b5a2369 --- /dev/null +++ b/uni_modules/x-facedetection/changelog.md @@ -0,0 +1,2 @@ +## 1.0.1(2025-07-27) +* 兼容鸿蒙原生,IOS \ No newline at end of file diff --git a/uni_modules/x-facedetection/package.json b/uni_modules/x-facedetection/package.json new file mode 100644 index 0000000..1328ddf --- /dev/null +++ b/uni_modules/x-facedetection/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-facedetection", + "displayName": "x-facedetection", + "version": "1.0.0", + "description": "x-facedetection", + "keywords": [ + "x-facedetection" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/readme.md b/uni_modules/x-facedetection/readme.md new file mode 100644 index 0000000..579a666 --- /dev/null +++ b/uni_modules/x-facedetection/readme.md @@ -0,0 +1,234 @@ +# x-facedetection + +## 特性说明 + +1. 检测提供的图片是否有人脸信息 +2. 从相册中选取检测人脸信息 +3. 通过相机实时捕捉人脸信息(并通过姿势姿态检测当前活体) +4. ios端后续提供,仅支持图片人脸信息检测 + +## 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | - | 支持 | x | x | + +## 安装方式 + +通过HBuilderX导入插件,或在插件市场下载后导入项目。 + +## API接口说明 + +### 检测图片中的人脸 + +```ts +// 通过相册选择图片检测人脸,仅支持安卓,ios,鸿蒙 +checkFaceByImage(config: XFACE_CHECK_OPTS) + +// 通过提供的图片路径检测人脸,仅支持安卓,ios,鸿蒙 +checkFaceByImageFromFilePath(config: XFACE_CHECK_OPTS) +``` + +### 通过相机进行人脸活体检测 + +```ts +// 检查相机权限,仅安卓 +checkCamraPermissions(call: (istrue: boolean) => void) + +// 打开相机进行人脸活体检测,仅安卓 +checkFaceByCamra(config: XFACE_CHECK_OPTS) +``` + +## 参数类型说明 + +### XFACE_CHECK_OPTS + +```ts +type XFACE_CHECK_OPTS = { + // 如果是通过图片检测需要提供图片路径 + url?: string, + // 如果是通过图片buffer解析需要提供(暂无法使用) + buffer?: ArrayBuffer, + // 如果是通过相机动态绑定嵌入式页面时,需要提供页面view的id + viewId?: string, + /** + * 活体检测指令,通过相机视频检测 + * 如果提供指令数组时,会根据完整指令顺序检测直到验证通过. + * 如果视频检测时,指令为空数组则只检测整个五官是不是在画面中,一旦检测到人脸立即验证通过. + */ + instruction?: XFACE_INS[] + // 验证结束并通过时返回 + success?: (data: XFACE_EVENT_CHECK_SUCCESS) => void, + /** + * 在视频活体检测时,返回每一帧的检测详细检测过程的信息,此事件是持续触发,直到结束。 + * 在图片检测的时候,只返回一次。 + */ + enter?: (data: XFACE_EVENT_SUCCESS[], maps: string) => void, + /** + * 开始检测,正在开始检测的指令。类似:向左转一次,向右转一次,点点头,张张嘴等执行时触发, + * 方便用户自定自己的提示语或者语音播报 + * 'start',现在开始, + * 'ins_start_指令名称':某个指令开始,如:ins_start_left,ins_start_right + * 'ins_end_指令名称':某个指令结束,如:ins_end_left,ins_end_right + * 'end'结束所有指令 + */ + insTipsEvent?: (data: string) => void, + fail?: (error: string) => void, +} +``` + +### 活体检测指令类型 + +```ts +/** + * 活体检测指令,可以通过指令控制检测动作 + * left: 向左转一次 + * right: 向右转一次 + * downUp: 上下点头 + * eyeOplenClose: 眨眼 + * monthOpenClose: 张张嘴 + */ +type XFACE_INS = "left" | "right" | "downUp" | "eyeOplenClose" | "monthOpenClose" +``` + +### 检测结果类型 + +```ts +type XFACE_EVENT_SUCCESS = { + // 右眼眨眼睛的闭合数据 + rightEye: XFACE_TEST_EYE_TYPE, + // 左眼眨眼睛的闭合数据 + leftEye: XFACE_TEST_EYE_TYPE, + // 是否在微笑 + isSmile: boolean, + // 脸向左,向右,中间 + faceRightLeft: XFACE_FACE_Direction, + // 点头的方向 + faceUpDown: XFACE_FACE_Direction, + imgWidth: number, + imgHeight: number, + // 嘴巴是不是张开 + isMouthOpened: boolean, + // 整个脑袋是否在画面中 + allHeadBody: boolean, + // 人脸ID,用于追踪同一个人脸 + faceId: number | null +} + +type XFACE_EVENT_CHECK_SUCCESS = { + /** + * 验证结束保存的视频地址,方便上传保存到后台储存备份,抽查验证。 + * 仅在活体检测时返回,图片检测时为空字符串。 + */ + videoPath: string + /** + * 在活体检测过程中,会按照指令顺序进行截图,保存验证时人脸对应的动画图片。 + * 多少个指令就有多少张图片。最后一张为全脸捕捉画面。 + * 图片检测时,返回检测的图片路径。 + */ + images: string[], + /** + * 验证是否通过 + */ + isPass: boolean +} +``` + +## 使用示例 + +### 图片人脸检测 + +仅安卓,鸿蒙 Next,ios 支持 + +```ts +import { checkFaceByImage, checkFaceByImageFromFilePath } from '@/uni_modules/x-facedetection' + +// 从相册选择图片检测人脸 +checkFaceByImage({ + success: (res) => { + console.log('检测成功', res.isPass) + console.log('图片路径', res.images) + }, + fail: (err) => { + console.error('检测失败', err) + }, + enter: (data, maps) => { + console.log('人脸信息', data) + } +}) + +// 通过图片路径检测人脸 +checkFaceByImageFromFilePath({ + url: '图片路径', + success: (res) => { + console.log('检测成功', res.isPass) + console.log('图片路径', res.images) + }, + fail: (err) => { + console.error('检测失败', err) + }, + enter: (data, maps) => { + console.log('人脸信息', data) + } +}) +``` + +### 相机活体检测 + +仅安卓 + +```ts +import { checkCamraPermissions, checkFaceByCamra } from '@/uni_modules/x-facedetection/utssdk/app-android/index.uts' + +// 检查相机权限 +checkCamraPermissions((hasPermission) => { + if (hasPermission) { + // 有权限,开始活体检测 + startFaceDetection() + } else { + console.error('没有相机权限') + } +}) + +// 开始活体检测 +function startFaceDetection() { + checkFaceByCamra({ + viewId: 'camera-container', // 相机预览容器的ID + instruction: ['left', 'right', 'eyeOplenClose', 'monthOpenClose'], // 活体检测指令序列 + insTipsEvent: (event) => { + // 处理指令提示事件 + if (event === 'start') { + console.log('开始检测') + } else if (event.startsWith('ins_start_')) { + const action = event.replace('ins_start_', '') + console.log(`开始执行动作: ${action}`) + } else if (event.startsWith('ins_end_')) { + const action = event.replace('ins_end_', '') + console.log(`完成动作: ${action}`) + } else if (event === 'end') { + console.log('检测完成') + } + }, + success: (res) => { + console.log('活体检测成功', res.isPass) + console.log('视频路径', res.videoPath) + console.log('检测过程图片', res.images) + }, + fail: (err) => { + console.error('活体检测失败', err) + }, + enter: (data, maps) => { + // 实时人脸检测数据 + console.log('实时人脸数据', data) + } + }) +} +``` + +## 注意事项 + +1. 活体检测需要用户保持面部在摄像头范围内,并按照指令完成相应动作 +2. 检测过程中如果用户移出屏幕或光线变化太大,可能会导致检测失败 +3. 为获得最佳效果,建议在光线充足的环境下使用 +4. iOS和Android实现可能存在细微差异,请根据实际测试结果调整应用逻辑 +5. 鸿蒙人脸检测效率由原生支持。 diff --git a/uni_modules/x-facedetection/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-facedetection/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..cdc5f22 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/uni_modules/x-facedetection/utssdk/app-android/assets/downUp.mp3 b/uni_modules/x-facedetection/utssdk/app-android/assets/downUp.mp3 new file mode 100644 index 0000000..51c1db8 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-android/assets/downUp.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-android/assets/eyeOplenClose.mp3 b/uni_modules/x-facedetection/utssdk/app-android/assets/eyeOplenClose.mp3 new file mode 100644 index 0000000..dd3be55 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-android/assets/eyeOplenClose.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-android/assets/goold.mp3 b/uni_modules/x-facedetection/utssdk/app-android/assets/goold.mp3 new file mode 100644 index 0000000..e9b75a6 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-android/assets/goold.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-android/assets/left.mp3 b/uni_modules/x-facedetection/utssdk/app-android/assets/left.mp3 new file mode 100644 index 0000000..79d6ae6 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-android/assets/left.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-android/assets/monthOpenClose.mp3 b/uni_modules/x-facedetection/utssdk/app-android/assets/monthOpenClose.mp3 new file mode 100644 index 0000000..4091c89 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-android/assets/monthOpenClose.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-android/assets/right.mp3 b/uni_modules/x-facedetection/utssdk/app-android/assets/right.mp3 new file mode 100644 index 0000000..e933f1d Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-android/assets/right.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-android/audio.uts b/uni_modules/x-facedetection/utssdk/app-android/audio.uts new file mode 100644 index 0000000..a8c6ce4 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-android/audio.uts @@ -0,0 +1,51 @@ +import MediaPlayer from "android.media.MediaPlayer" +import File from 'java.io.File'; +import FileOutputStream from 'java.io.FileOutputStream'; +export class xAudio { + audio:MediaPlayer; + constructor(){ + this.audio = new MediaPlayer(); + } + play(src:string){ + + + this.audio.stop(); + this.audio.release() + this.audio = new MediaPlayer(); + let assetManager = UTSAndroid.getAppContext()!.getAssets(); + // 加载free.mp3 资源 + const listAssets = assetManager.list(""); + let filename = src+".mp3"; + let isExites = listAssets?.contains(filename)??false + + if(!isExites) return; + let afd = assetManager.openFd(filename); + try { + // 使用android 自带的媒体组件进行播放 + let mediaPlayer = this.audio; + mediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength()); + mediaPlayer.prepare(); + mediaPlayer.start(); + class audioCompleted implements MediaPlayer.OnCompletionListener{ + override onCompletion(m:MediaPlayer|null){ + // if(m!=null){ + // m.release() + // } + } + } + mediaPlayer.setOnCompletionListener(new audioCompleted()) + } catch (e: Exception) { + console.log("AudioPlayer", "Error setting data source: ",e) + + } finally { + // 确保关闭文件描述符 + afd.close() + } + } + stop(){ + // this.audio.stop(); + } + destory(){ + // this.audio.release() + } +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/utssdk/app-android/camera.uts b/uni_modules/x-facedetection/utssdk/app-android/camera.uts new file mode 100644 index 0000000..c4813f5 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-android/camera.uts @@ -0,0 +1,548 @@ +import ListView from 'android.widget.ListView'; +import FrameLayout from 'android.widget.FrameLayout'; +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' +import Camera2CameraControl from 'androidx.camera.camera2.interop.Camera2CameraControl' +import Camera2CameraInfo from 'androidx.camera.camera2.interop.Camera2CameraInfo' + + + + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' +import Range from 'android.util.Range'; + +import InputImage from "com.google.mlkit.vision.common.InputImage" + +import Executor from 'java.util.concurrent.Executor' +import Looper from 'android.os.Looper' +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; + +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import OnImageAvailableListener from 'android.media.ImageReader.OnImageAvailableListener' + + +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import ViewGroup from 'android.view.ViewGroup'; + + +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +// import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner" +// import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions" +// import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning" +// import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions" +// import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback" +// import Barcode from "com.google.mlkit.vision.barcode.common.Barcode" +// import InputImage from "com.google.mlkit.vision.common.InputImage" + +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" + +// x +import ProcessCameraProvider from "androidx.camera.lifecycle.ProcessCameraProvider" +import PreviewView from "androidx.camera.view.PreviewView" +import CameraController from "androidx.camera.view.CameraController" +import CameraSelector from "androidx.camera.core.CameraSelector" +import Preview from 'androidx.camera.core.Preview' +import Camera from 'androidx.camera.core.Camera' +import LifecycleObserver from "androidx.lifecycle.LifecycleObserver" +import LifecycleOwner from "androidx.lifecycle.LifecycleOwner" +import OnLifecycleEvent from "androidx.lifecycle.OnLifecycleEvent" +import ImageAnalysis from 'androidx.camera.core.ImageAnalysis' +import ImageProxy from 'androidx.camera.core.ImageProxy' +import ImageCapture from 'androidx.camera.core.ImageCapture'; +import AspectRatio from 'androidx.camera.core.AspectRatio'; +import CameraInfo from 'androidx.camera.core.CameraInfo'; +import CameraControl from 'androidx.camera.core.CameraControl' + +import NonNull from 'androidx.annotation.NonNull' +import ExecutorService from 'java.util.concurrent.ExecutorService' +import Executors from 'java.util.concurrent.Executors' +// import TargetResolution from 'androidx.camera.core.ImageAnalysis.TargetResolution' +import {decodeImage} from "./index.uts" + + +type buffoptsPlanesType = { + data : ByteBuffer, + getRowStride : number, + getPixelStride : number, +} +type buffoptsType = { + width : number, + height : number, + format : number, + rect : Rect, + planes : buffoptsPlanesType[], +} + +import { AUTH_CALL_BACK_TYPE, CAMERA_PHOTO_SIZE,XCHECKFACE_ENTER_CALL,XFACE_EVENT_SUCCESS } from "../interface.uts" + +import ContextCompat from 'androidx.core.content.ContextCompat'; +import FileOutputStream from 'java.io.FileOutputStream'; +import PreviewConfig from 'androidx.camera.core.impl.PreviewConfig'; +import VideoSource from 'android.media.MediaRecorder.VideoSource'; +import VideoCapture from 'androidx.camera.video.VideoCapture'; +import OutputFileOptions from 'androidx.camera.core.ImageCapture.OutputFileOptions'; +import Recorder from 'androidx.camera.video.Recorder'; +import Quality from 'androidx.camera.video.Quality'; +import QualitySelector from 'androidx.camera.video.QualitySelector'; +import OutputFileResults from 'androidx.camera.core.ImageCapture.OutputFileResults'; +import FileDescriptor from 'java.io.FileDescriptor'; +import FileOutputOptions from 'androidx.camera.video.FileOutputOptions'; + +import VideoRecordEvent from 'androidx.camera.video.VideoRecordEvent'; +import Consumer from 'androidx.core.util.Consumer'; +import Recording from 'androidx.camera.video.Recording'; +import ResolutionCorrector from 'androidx.camera.camera2.internal.compat.workaround.ResolutionCorrector'; +import AspectRatioStrategy from 'androidx.camera.core.resolutionselector.AspectRatioStrategy'; +import ResolutionSelector from 'androidx.camera.core.resolutionselector.ResolutionSelector'; + +type cameraListNameType = { id : string, device : CameraCharacteristics } +type TAKE_CALL_BACK = (path : string) => void; +let callFuntake = (path : string) => { } +let callVideoFun = (path : string) => { } +let callVideoFaceFun= (img : XFACE_EVENT_SUCCESS[],imgBit:Bitmap|null) => { } +let checking = true +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} +export class xCamera { + parentView : FrameLayout; + + + + + viewBox_width = 0 + viewBox_height = 0 + + imgPointsBycanmarea = [] as RelativeLayout[] + + + /** 手动震动服务 */ + vibrator = null as null | Vibrator + context : Context; + // 相机旋转的角度。 + cameraRate = new Map([ + [Surface.ROTATION_0, 0], + [Surface.ROTATION_90, 0], + [Surface.ROTATION_180, 0], + [Surface.ROTATION_270, 0] + ]) + // 相机服务 + cameraService : CameraManager + // 相机列表,name,id + cameraListName = new Map(); + // + cameraPreviewSize = { width: 800, height: 800 } as CAMERA_PHOTO_SIZE + // 当前预览的什么是设备 + cameraDevice : CameraDevice | null = null + cameraDeviceCaptureSession : CameraCaptureSession | null = null + sufaceHolderView : Surface | null = null + + // 相机区域视图 + cameraView : PreviewView | null = null; + cameraProvider : ProcessCameraProvider | null = null + camera : Camera | null = null; + cameraPreview : Preview | null = null; + videoCapture : VideoCapture | null = null; + // Recording + recoderVideoObj:Recording|null = null; + + // 是否拍照中 + isDecoderQring = false + // 当前相机是否正在预览中。 + isOpeningCameraing = false; + + callFunEvent : TAKE_CALL_BACK = (str : string) => { } + //摄像头朝向,默认是向后置摄像头. + CamerDeviceDir = CameraSelector.LENS_FACING_FRONT + //摄像头的是否开 + flashMode = false + // 拍照模式,还是录像模式. + takeModelType = 'video'; //photo,video + + private PHOTO_TYPE = "image/jpeg" + private RATIO_4_3_VALUE = 4.0 / 3.0 + private RATIO_16_9_VALUE = 16.0 / 9.0 + constructor(GroupView : FrameLayout) { + this.context = UTSAndroid.getAppContext()! as Context; + this.parentView = GroupView; + this.cameraService = this.context.getSystemService(Context.CAMERA_SERVICE) as CameraManager + this.vibrator = this.context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + this._createCameraView() + } + + /** 创建相机预览区域 */ + private _createCameraView() { + + let sv = new PreviewView(UTSAndroid.getAppContext()!) + sv.scaleType = PreviewView.ScaleType.FILL_CENTER + + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + + this.parentView.addView(this.cameraView!) + } + + openCamera() { + let _this = this; + if (this.isOpeningCameraing) { + this.closeCamera() + } + _this._openCamera(); + } + startRecoderVideo(call : (path : string) => void) { + callVideoFun = call; + let _this = this; + + if(_this.recoderVideoObj?.isClosed()==false){ + _this.recoderVideoObj?.resume() + }else{ + if (this.isOpeningCameraing||this.recoderVideoObj!=null) { + this.stopRecoderVideo() + this.closeCamera() + } + _this.takeModelType = 'video' + _this._openCamera(); + } + } + pauseRecoderVideo(){ + let _this = this; + _this.recoderVideoObj?.pause() + } + stopRecoderVideo() { + let _this = this; + _this.takeModelType = 'photo' + _this.recoderVideoObj?.stop() + _this.recoderVideoObj?.close() + _this.recoderVideoObj = null; + _this.videoCapture = null; + // closeCamera(); + } + + + setCallEvent(call : TAKE_CALL_BACK) { + this.callFunEvent = call; + } + setCheckFaceEnter(call:XCHECKFACE_ENTER_CALL){ + callVideoFaceFun = call + } + getCamraRotation() : Number { + return 0 + } + + closeCamera() { + let t = this; + class IntentRunable2 extends Runnable { + override run() { + t.cameraProvider?.unbindAll() + t.cameraPreview?.setSurfaceProvider(null) + t.isOpeningCameraing = false; + } + } + // 确保在主线程中关闭相机 + new Handler(Looper.getMainLooper()).post(new IntentRunable2()); + } + + private aspectRatio(width : Int, height : Int) : Int { + let previewRatio = Math.max(width, height).toDouble() / Math.min(width, height) + if (Math.abs(previewRatio - this.RATIO_4_3_VALUE) <= Math.abs(previewRatio - this.RATIO_16_9_VALUE)) { + return AspectRatio.RATIO_4_3 + } + return AspectRatio.RATIO_16_9 + } + + private imageToBitmap(image: Image): Bitmap { + // Assuming the image format is YUV_420_888 and converting it to Bitmap + let buffer = image.planes[0].buffer + let bytes = ByteArray(buffer.capacity()) + buffer.get(bytes) + let yuvImage = YuvImage(bytes, ImageFormat.NV21, image.width, image.height, null) + let out = ByteArrayOutputStream() + yuvImage.compressToJpeg(Rect(0, 0, image.width, image.height), 100, out) + let byteArray = out.toByteArray() + return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size) + } + + private increaseBrightness(camera: Camera) { + // 调整曝光补偿以提高亮度 + let cameraControl = camera.cameraControl + let cameraInfo = camera.cameraInfo + + let exposureState = cameraInfo.exposureState + let range = exposureState.exposureCompensationRange + let maxExposure = range.upper + + if (maxExposure > 0) { + cameraControl.setExposureCompensationIndex(maxExposure) + console.log("曝光补偿值已设置为最大值: $",maxExposure) + } else { + console.log("相机不支持曝光补偿。") + } + + + } + + private setISO(camera: Camera) { + + } + + private setWhiteBalance(camera: Camera) { + + + + } + + private _openCamera() { + let _this = this; + let cameraProviderFuture = ProcessCameraProvider.getInstance(this.context) + + class IntentRunable extends Runnable { + override run() { + let cameraProvider : ProcessCameraProvider = cameraProviderFuture.get() + let previewView = _this.cameraView! as PreviewView + + let cameraSelector : CameraSelector = new CameraSelector.Builder() + .requireLensFacing(_this.CamerDeviceDir) + .build(); + + // 预览比例 + let screenAspectRatio = _this.aspectRatio((300).toInt(), (300).toInt()) + let preview : Preview = new Preview.Builder() + .setTargetAspectRatio(screenAspectRatio) + .build(); + preview.setSurfaceProvider(previewView.getSurfaceProvider()) + // 创建ImageCapture用例,并设置闪光灯模式 + + let imageCapture : ImageCapture = new ImageCapture.Builder() + .setTargetAspectRatio(screenAspectRatio) + .build(); + + + let imageAnalysis = new ImageAnalysis.Builder() + .setTargetResolution(new Size(300, 300)) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + class MyImageAnalyzer implements ImageAnalysis.Analyzer { + constructor() { + super() + } + override analyze(image : ImageProxy) { + // image + if (_this.isDecoderQring) { + _this.savePhotoTocache(image) + + } else { + const imgInput = image.getImage() + if(imgInput!=null){ + + let img = InputImage.fromMediaImage(imgInput,image.getImageInfo().getRotationDegrees()) + decodeImage((evt:XFACE_EVENT_SUCCESS[])=>{ + UTSAndroid.getDispatcher("main").async(function(_){ + let imgbitmap = image.toBitmap() + callVideoFaceFun(evt,imgbitmap) + image.close() + },null) + },()=>{},img) + }else{ + image.close() + } + + } + + } + override getDefaultTargetResolution() : Size { + return new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt()); + } + + } + let cameraExecutor = Executors.newSingleThreadExecutor(); + imageAnalysis.setAnalyzer(cameraExecutor, new MyImageAnalyzer()); + + let recorder = Recorder.Builder() + .setQualitySelector(QualitySelector.from(Quality.LOWEST)) // 选择录制质量,HD、FHD等 + .build() + _this.videoCapture = VideoCapture.withOutput(recorder) + + + let camera : Camera = cameraProvider.bindToLifecycle(UTSAndroid.getUniActivity()! as LifecycleOwner, + cameraSelector, + imageCapture, + imageAnalysis, + preview, + videoCapture! + ); + + + if (_this.takeModelType == 'video') { + // 录制视频 + let filepath = _this.context.getExternalCacheDir()?.getPath() ?? "" + let videoFile = new File(filepath, 'tmui4xCamreaVideo' + getUid(1, 12) + '.mp4') + let outputOptions = FileOutputOptions.Builder(videoFile).build() + class DirectExecutor implements Executor { + override execute(r:Runnable ) { + r.run(); + console.error('录制错误') + callVideoFun('') + } + } + // Consumer + class reocdereventClass implements Consumer { + override accept(event: VideoRecordEvent) { + if(event instanceof VideoRecordEvent.Start){ + console.log("开始录制") + }else if(event instanceof VideoRecordEvent.Finalize){ + console.log("结束录制",videoFile.absolutePath) + callVideoFun(videoFile.absolutePath) + } + } + } + // ContextCompat.getMainExecutor(_this.context) + _this.recoderVideoObj = _this.videoCapture!.getOutput() + .prepareRecording(_this.context,outputOptions) + .start(ContextCompat.getMainExecutor(_this.context),new reocdereventClass() as Consumer) + + + } + + + let cameraControl = camera.getCameraControl() + let cameraInfo : CameraInfo = camera.getCameraInfo() + + + _this.increaseBrightness(camera) + + // 闪光灯. + cameraControl.enableTorch(_this.flashMode) + _this.camera = camera + _this.cameraPreview = preview + + _this.cameraProvider = cameraProvider + _this.isDecoderQring = false + _this.isOpeningCameraing = true + + } + } + + try{ + cameraProviderFuture.addListener(new IntentRunable(), ContextCompat.getMainExecutor(this.context)) + }catch(e){ + console.error('开启错误.') + } + } + + takPhoto(call : (path : string) => void) { + callFuntake = call; + this.isDecoderQring = true; + } + //front,前置,back后置 + setCameraDir(type : string) { + this.CamerDeviceDir = type == 'back' ? CameraSelector.LENS_FACING_BACK : CameraSelector.LENS_FACING_FRONT + } + setFlash(type : boolean) { + this.flashMode = type; + } + + + savePhotoTocache(image : ImageProxy) { + let context = UTSAndroid.getAppContext()! + let filepath = context.getExternalCacheDir()?.getPath() ?? "" + let img : Bitmap | null = image.toBitmap() + let file = new File(filepath, 'tmui4xCamrea' + getUid(1, 12) + '.jpg'); + let fos = new FileOutputStream(file) + let conunt = (img?.getByteCount() ?? 0) / 1024 / 1024 + + let saved = img!.compress(Bitmap.CompressFormat.JPEG, conunt > 1 ? 64 : 100, fos); + let t = this; + class IntentRunable2 extends Runnable { + override run() { + if (saved) { + callFuntake(file.getPath()) + t.isDecoderQring = false + } + // ,拍照暂不关闭相机让用户手动关闭. + // t.closeCamera() + } + } + image.close() + new Handler(Looper.getMainLooper()).post(new IntentRunable2()); + } + + savePhotoBitmapTocache(img : Bitmap) { + let context = UTSAndroid.getAppContext()! + let filepath = context.getExternalCacheDir()?.getPath() ?? "" + let file = new File(filepath, 'tmui4xCamrea' + getUid(1, 12) + '.jpg'); + let fos = new FileOutputStream(file) + let conunt = img.getByteCount() / 1024 / 1024 + img!.compress(Bitmap.CompressFormat.JPEG, conunt > 1 ? 64 : 100, fos); + return file.getPath(); + } + + +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/utssdk/app-android/config.json b/uni_modules/x-facedetection/utssdk/app-android/config.json new file mode 100644 index 0000000..3a85e0f --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-android/config.json @@ -0,0 +1,12 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "com.google.mlkit:face-detection:16.1.7", + "androidx.camera:camera-core:1.3.4", + "androidx.camera:camera-camera2:1.3.4", + "androidx.camera:camera-lifecycle:1.3.4", + "androidx.camera:camera-video:1.3.4", + "androidx.camera:camera-view:1.3.4", + "androidx.camera:camera-extensions:1.3.4" + ] +} diff --git a/uni_modules/x-facedetection/utssdk/app-android/index.uts b/uni_modules/x-facedetection/utssdk/app-android/index.uts new file mode 100644 index 0000000..824c145 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-android/index.uts @@ -0,0 +1,561 @@ +import Intent from 'android.content.Intent'; +import Context from 'android.content.Context' +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import Bitmap from "android.graphics.Bitmap" +import FrameLayout from 'android.widget.FrameLayout'; +import FaceDetection from "com.google.mlkit.vision.face.FaceDetection" +import FaceDetectorOptions from "com.google.mlkit.vision.face.FaceDetectorOptions" +import FaceLandmark from "com.google.mlkit.vision.face.FaceLandmark" +import FaceContour from "com.google.mlkit.vision.face.FaceContour" +import Face from "com.google.mlkit.vision.face.Face" + +import InputImage from "com.google.mlkit.vision.common.InputImage" + +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" +import ByteBuffer from 'java.nio.ByteBuffer' +import ImageFormat from 'android.graphics.ImageFormat' +import Kotlin from 'kotlin.jvm.internal.Intrinsics.Kotlin'; +import Image from 'android.media.Image'; +import LinearLayout from 'android.widget.LinearLayout'; +import ViewGroup from 'android.view.ViewGroup'; + +import { XFACE_CHECK_OPTS, XFACE_EVENT_SUCCESS, XFACE_TEST_EYE_TYPE, XFACE_FACE_Direction, XFACE_EVENT_CHECK_SUCCESS } from "../interface.uts" +import { XFACE_CHECK_OPTS_REAL, getDefaultConfig } from "../libs/config.uts" +import BitmapFactory from 'android.graphics.BitmapFactory'; +import View from 'android.view.View'; +import { xCamera } from "./camera.uts" +import { xAudio } from "./audio.uts" + +let camera : xCamera | null = null; +const audio = new xAudio(); +const checkFaceResult = (image : InputImage, faces : MutableList, callBack : (result : XFACE_EVENT_SUCCESS[]) => void) => { + const cfaces = [] as XFACE_EVENT_SUCCESS[] + // @ts-ignore + for (item in faces) { + // @ts-ignore + const face = item as Face; + let rightEye = { openNum: 0, isOpen: false } as XFACE_TEST_EYE_TYPE; + let leftEye = { openNum: 0, isOpen: false } as XFACE_TEST_EYE_TYPE; + // 眼睛 + let rightEyeMark = face.getLandmark(FaceLandmark.RIGHT_EYE) + let leftEyeMark = face.getLandmark(FaceLandmark.RIGHT_EYE) + // 鼻子 + let noseMark = face.getLandmark(FaceLandmark.NOSE_BASE) + // 耳朵 + let rightEarMark = face.getLandmark(FaceLandmark.RIGHT_EAR) + let leftEarMark = face.getLandmark(FaceLandmark.LEFT_EAR) + + + let rightEyeNum = face.getRightEyeOpenProbability() + let leftEyeNum = face.getLeftEyeOpenProbability() + let isSmile = face.getSmilingProbability() + + let faceId = face.getTrackingId() + + if (rightEyeNum != null) { + rightEye.openNum = rightEyeNum + 0; + rightEye.isOpen = rightEyeNum > 0.7 + } + if (leftEyeNum != null) { + leftEye.openNum = leftEyeNum + 0; + leftEye.isOpen = leftEyeNum > 0.7 + } + + // 检测当前左,右,下,上 + let faceRightLeft : XFACE_FACE_Direction = "center" + let faceUpDown : XFACE_FACE_Direction = "center" + + + let eulerX = face.getHeadEulerAngleX(); // 获取头部左右旋转角度 + let eulerY = face.getHeadEulerAngleY(); // 获取头部上下俯仰角度 + let eulerZ = face.getHeadEulerAngleZ(); // 获取头部上下俯仰角度 + + // 嘴巴 + let leftMouth = face.getLandmark(FaceLandmark.MOUTH_LEFT) + let rightMouth = face.getLandmark(FaceLandmark.MOUTH_RIGHT) + let bottomMouth = face.getLandmark(FaceLandmark.MOUTH_BOTTOM) + + let isMouthOpened = false + let ANGLE_THRESHOLD = 30; // 容差值 + let ANGLE_HEAD_THRESHOLD = 0; // 容差值 + let ANGLE_EYE_THRESHOLD = 6; // 眨眼的容差. + + let allHeadBody = false; + + if (Math.abs(eulerY) > ANGLE_THRESHOLD) { // 确保头部没有明显上下俯仰 + faceRightLeft = eulerY > 0 ? 'left' : 'right'; + } + + if (Math.abs(eulerX) >= ANGLE_HEAD_THRESHOLD) { // 确保头部没有明显上下俯仰 + faceUpDown = eulerY > 0 ? 'down' : 'up'; + } + + if (leftMouth != null && rightMouth != null && bottomMouth != null) { + // @ts-ignore + let mouthWidth = rightMouth.position.x - leftMouth.position.x + // @ts-ignore + let mouthHeight = bottomMouth.position.y - ((leftMouth.position.y + rightMouth.position.y) / 2) + + if (mouthHeight / mouthWidth > 0.4 && faceRightLeft == 'center') { + isMouthOpened = true; + } else { + isMouthOpened = false; + } + } + + if( + leftMouth != null && + rightMouth != null && + bottomMouth != null && + noseMark !=null&& + rightEarMark !=null&& + leftEarMark !=null&& + rightEyeMark !=null&& + leftEyeMark !=null + ){ + allHeadBody = true; + } + + cfaces.push({ + imgWidth: image.getWidth(), + imgHeight: image.getHeight(), + isSmile: isSmile == null ? false : (isSmile >= 0.8), + rightEye, + leftEye, + faceRightLeft, + faceUpDown, + isMouthOpened, + allHeadBody, + faceId:faceId!=null?(faceId+0):null + }) + + } + + callBack(cfaces) +} + + + +export function decodeImage(success : (evt : XFACE_EVENT_SUCCESS[]) => void, fail : () => void, image : InputImage) { + // @ts-ignore + const highAccuracyOpts = new FaceDetectorOptions.Builder() + .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST) + .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) + .setContourMode(FaceDetectorOptions.CONTOUR_MODE_NONE) + .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) + .enableTracking() + .build() + const detector = FaceDetection.getClient(highAccuracyOpts) + + + detector.process(image) + .addOnSuccessListener((faces : MutableList) => { + + UTSAndroid.getDispatcher("main").async(function(_){ + checkFaceResult(image, faces, (result : XFACE_EVENT_SUCCESS[]) => { + success(result) + }) + },null) + + }) + .addOnFailureListener(e => { + console.error(e) + fail() + }) +} + +/** + * 通过相册选择检测当前图片是否有人脸. + */ +export function checkFaceByImage(config : XFACE_CHECK_OPTS | null = null) { + const cfg = getDefaultConfig(config) + // @ts-ignore + const highAccuracyOpts = new FaceDetectorOptions.Builder() + .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE) + .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) + .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) + .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) + .build() + + // @ts-ignore + uni.chooseImage({ + count: 1, + // @ts-ignore + success(evt : ChooseImageSuccess) { + if (evt.tempFilePaths.length == 0) return; + const imgs = evt.tempFilePaths[0] as string; + const decodedPath = UTSAndroid.convert2AbsFullPath(imgs) + const file = new File(decodedPath) + const image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + // const image = InputImage.fromBitmap(BitmapFactory.decodeFile(decodedPath)!, 0) + const detector = FaceDetection.getClient(highAccuracyOpts) + detector.process(image) + .addOnSuccessListener((faces : MutableList) => { + if (faces.size == 0) { + cfg.success({ + isPass: false, + images: [decodedPath] as string[], + videoPath: "" + }) + return; + } + checkFaceResult(image, faces, (result : XFACE_EVENT_SUCCESS[]) => { + + cfg.enter(result,JSON.stringify(result)) + cfg.success({ + isPass: true, + images: [decodedPath] as string[], + videoPath: "" + }) + + }) + }) + .addOnFailureListener(e => { + console.error(e) + cfg.fail("解析错误") + }) + }, + fail() { + console.error("未选择图片") + cfg.fail("未选择图片") + } + }) +} +/** + * 提供外部图片地址检测当前图片是否存在人脸 + */ +export function checkFaceByImageFromFilePath(config : XFACE_CHECK_OPTS) { + const cfg = getDefaultConfig(config) + if (cfg.url == '') { + cfg.fail("url图片地址没提供正确.") + return; + } + const decodedPath = UTSAndroid.convert2AbsFullPath(cfg.url) + const file = new File(decodedPath) + const image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + // const image = InputImage.fromBitmap(BitmapFactory.decodeFile(decodedPath)!, 0) + // @ts-ignore + const highAccuracyOpts = new FaceDetectorOptions.Builder() + .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE) + .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) + .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) + .build() + const detector = FaceDetection.getClient(highAccuracyOpts) + detector.process(image) + .addOnSuccessListener((faces : MutableList) => { + if (faces.size == 0) { + cfg.enter([] as XFACE_EVENT_SUCCESS[],JSON.stringify([] as XFACE_EVENT_SUCCESS[] )) + cfg.fail("未检测到人脸") + return; + } + checkFaceResult(image, faces, (result : XFACE_EVENT_SUCCESS[]) => { + + cfg.enter(result,JSON.stringify(result)) + cfg.success({ + isPass: true, + images: [decodedPath] as string[], + videoPath: "" + }) + }) + }) + .addOnFailureListener(e => { + console.error(e) + cfg.fail("解析错误") + }) +} + +/** + * 检查相机权限 + */ +export function checkCamraPermissions(call : (istrue : boolean) => void) { + let permissionCheck = ["android.permission.CAMERA"] + + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + call(true) + } else { + console.log("当前不具备指定权限") + // 请求拍照权限 + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (allRight : boolean, _ : string[]) { + call(true) + }, function (_ : boolean, _ : string[]) { + //用户拒绝了部分权限 + call(false) + }) + } +} +let tid = 0 +//当前等待检测的指令 +let nowInsIndex = 0; +//是否允许开始动作检测 +//allow,next,‘wait' +let isCheckNext = 'wait' +//指令执行中start,checking,dercoding,end +let actioning = '' + +/** + * 打开视频进行人脸活体检测 + */ +@UTSJS.keepAlive +export function checkFaceByCamra(config : XFACE_CHECK_OPTS) { + + if (camera != null) { + camera!.closeCamera() + clearTimeout(tid) + } + actioning = '' + isCheckNext = 'wait' + nowInsIndex = 0 + + const cfg = getDefaultConfig(config) + if (cfg.viewId == '') { + cfg.fail("没有提供正在的view的id绑定.") + return; + } + if (cfg.instruction.length == 0) { + console.warn("未提供指令,将仅进行人脸验证.") + // cfg.fail("没有提供活体检测指令") + // return; + } + // @ts-ignore + let ele = uni.getElementById(cfg.viewId) as UniElement | null; + if (ele == null) { + cfg.fail("绑定的容器view找不到") + return; + } + let parentView = ele.getAndroidView() as ViewGroup; + let viewWidth = parentView.getWidth() + let viewHeight = parentView.getHeight() + let grop = new FrameLayout(UTSAndroid!.getAppContext()!) + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + grop.setLayoutParams(layaout) + parentView.addView(grop) + + let isPassCheck = false + let checkImgs = [] as string[] + let lastFaceAllBody = "" + let faceId = null as null|number; + if (viewWidth == 0 || viewHeight == 0) { + cfg.fail("绑定的容器view宽高不能为0") + return; + } + + camera = new xCamera(grop) + camera?.setCameraDir('front') + camera?.setFlash(false) + + camera?.startRecoderVideo((videoPath : string) => { + console.log(videoPath) + UTSAndroid.getDispatcher("main").async(function (_) { + if(lastFaceAllBody!=''){ + checkImgs.push(lastFaceAllBody) + } + cfg.success({ + videoPath, + images:checkImgs, + isPass:isPassCheck + } as XFACE_EVENT_CHECK_SUCCESS) + }) + }) + + function closeCamera() { + camera?.stopRecoderVideo() + camera?.closeCamera() + parentView.removeAllViews() + } + + tid = setTimeout(() => { + cfg.insTipsEvent("start") + actioning = 'start' + isCheckNext = 'allow' + }, 2000) + + let headDonwUp = 0 + UTSAndroid.getDispatcher("main").async(function (_) { + camera?.setCheckFaceEnter((result:XFACE_EVENT_SUCCESS[],imgBit:any|null) => { + + // 无指令时的正脸检测 + if(cfg.instruction.length==0){ + if(result.length>0){ + let item = result[0] + if(item.allHeadBody){ + nowInsIndex = -1; + if(imgBit!=null&&camera!=null&&imgBit instanceof Bitmap){ + checkImgs.push(camera!.savePhotoBitmapTocache((imgBit! as Bitmap))) + } + isPassCheck = true; + closeCamera() + } + } + return; + } + + if (nowInsIndex == -1 || actioning == '') { + return; + } + if (nowInsIndex > cfg.instruction.length - 1) { + nowInsIndex = -1; + cfg.insTipsEvent("end") + isPassCheck = true; + closeCamera() + return; + } + let item = null as null|XFACE_EVENT_SUCCESS + if(result.length>0){ + item = result[0] + } + let dir = cfg.instruction[nowInsIndex] + if (actioning == 'start') { + actioning = '' + audio.play(dir) + setTimeout(function () { + cfg.insTipsEvent("ins_start_" + dir) + isCheckNext = 'allow' + actioning = 'checking' + }, 1500); + return; + } + + + // 保存一次正脸 + if(lastFaceAllBody==""){ + if(result.length>0){ + let item = result[0] + if(item.allHeadBody){ + lastFaceAllBody = camera!.savePhotoBitmapTocache(imgBit! as Bitmap) + faceId = item.faceId + console.log(faceId,'+++') + } + } + return; + } + + // 进行人脸检测 + if(item!=null&&actioning == 'checking'&&isCheckNext == 'allow'){ + let rts = result! + if(faceId!=item.faceId||item.faceId==null||faceId==null){ + console.log(item.faceId,'---') + isPassCheck = false; + console.log("检脸追踪id变化,检测失败") + nowInsIndex = -1; + cfg.insTipsEvent("end") + closeCamera() + return; + } + // 向左转 + if (dir == 'left' && item.faceRightLeft == 'left') { + // 立即更改状态,防止重复处理 + actioning = 'dercoding' + cfg.insTipsEvent("ins_end_" + dir) + cfg.enter(result,JSON.stringify(rts)) + isCheckNext = 'wait'; + audio.play('goold') + if(imgBit!=null&&camera!=null){ + checkImgs.push(camera!.savePhotoBitmapTocache(imgBit! as Bitmap)) + } + tid = setTimeout(function () { + isCheckNext = 'next'; + }, 1000); + } else if (dir == 'right' && item.faceRightLeft == 'right') { + // 立即更改状态,防止重复处理 + actioning = 'dercoding' + cfg.insTipsEvent("ins_end_" + dir) + cfg.enter(result,JSON.stringify(rts)) + isCheckNext = 'wait'; + audio.play('goold') + if(imgBit!=null&&camera!=null){ + checkImgs.push(camera!.savePhotoBitmapTocache(imgBit! as Bitmap)) + } + tid = setTimeout(function () { + isCheckNext = 'next'; + }, 1000); + + } else if(dir == 'downUp'&&(item.faceUpDown=='up'||item.faceUpDown=='down')){ + if(item.faceUpDown=='up'&&headDonwUp==0){ + headDonwUp = 1; + + }else if(item.faceUpDown=='down'&&headDonwUp==1){ + headDonwUp = 2; + + // 立即更改状态,防止重复处理 + actioning = 'dercoding' + cfg.insTipsEvent("ins_end_" + dir) + cfg.enter(result,JSON.stringify(rts)) + audio.play('goold') + isCheckNext = 'wait'; + if(imgBit!=null&&camera!=null){ + checkImgs.push(camera!.savePhotoBitmapTocache(imgBit! as Bitmap)) + } + tid = setTimeout(function () { + isCheckNext = 'next'; + headDonwUp = 0 + }, 1000); + + } + }else if(dir == 'monthOpenClose'){ + if(item.isMouthOpened==true&&headDonwUp==0){ + headDonwUp = 1; + + }else if(item.isMouthOpened == false&&headDonwUp==1){ + headDonwUp = 2; + // 立即更改状态,防止重复处理 + actioning = 'dercoding' + cfg.insTipsEvent("ins_end_" + dir) + cfg.enter(result,JSON.stringify(rts)) + audio.play('goold') + isCheckNext = 'wait'; + if(imgBit!=null&&camera!=null){ + checkImgs.push(camera!.savePhotoBitmapTocache(imgBit! as Bitmap)) + } + tid = setTimeout(function () { + isCheckNext = 'next'; + headDonwUp = 0 + }, 1000); + + } + }else if(dir == 'eyeOplenClose'){ + if((item.leftEye.isOpen&&item.rightEye.isOpen)&&headDonwUp==0){ + headDonwUp = 1; + }else if((!item.leftEye.isOpen&&!item.rightEye.isOpen)&&headDonwUp==1){ + headDonwUp = 2; + }else if((item.leftEye.isOpen&&item.rightEye.isOpen)&&headDonwUp==2){ + headDonwUp = 3; + // 立即更改状态,防止重复处理 + actioning = 'dercoding' + cfg.insTipsEvent("ins_end_" + dir) + cfg.enter(result,JSON.stringify(rts)) + audio.play('goold') + isCheckNext = 'wait'; + if(imgBit!=null&&camera!=null){ + checkImgs.push(camera!.savePhotoBitmapTocache(imgBit! as Bitmap)) + } + tid = setTimeout(function () { + isCheckNext = 'next'; + headDonwUp = 0 + }, 1000); + + } + } + + + } + if (isCheckNext == 'next'){ + isCheckNext = 'allow'; + actioning = 'start' + nowInsIndex += 1; + } + + }) + + }) + + + + + + + +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/utssdk/app-harmony/config.json b/uni_modules/x-facedetection/utssdk/app-harmony/config.json new file mode 100644 index 0000000..39e7ffc --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_facedetection": "./lib/x_facedetection.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/utssdk/app-harmony/index.uts b/uni_modules/x-facedetection/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..ed3fc45 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-harmony/index.uts @@ -0,0 +1,44 @@ +import { x_facedetection_imgcheck } from "x_facedetection" + +import { XFACE_CHECK_OPTS, XFACE_EVENT_SUCCESS, XFACE_TEST_EYE_TYPE, XFACE_FACE_Direction, XFACE_EVENT_CHECK_SUCCESS } from "../interface.uts" +import { XFACE_CHECK_OPTS_REAL, getDefaultConfig } from "../libs/config.uts" + + +export function checkFaceByImage(config : XFACE_CHECK_OPTS | null = null) { + const cfg = getDefaultConfig(config) + // @ts-ignore + uni.chooseImage({ + count: 1, + // @ts-ignore + success(evt : ChooseImageSuccess) { + if (evt.tempFilePaths.length == 0) return; + const imgs = evt.tempFilePaths[0] as string; + x_facedetection_imgcheck(imgs, (ispass : boolean) => { + cfg.success({ + isPass: ispass, + images: [] as string[], + videoPath: "" + }) + }) + }, + fail() { + cfg.fail("解析错误") + } + }) +} + + +/** + * 提供外部图片地址检测当前图片是否存在人脸 + */ +export function checkFaceByImageFromFilePath(config : XFACE_CHECK_OPTS) { + const cfg = getDefaultConfig(config) + const imgs = cfg.url; + x_facedetection_imgcheck(imgs, (ispass : boolean) => { + cfg.success({ + isPass: ispass, + images: [] as string[], + videoPath: "" + }) + }) +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/utssdk/app-harmony/lib/x_facedetection.har b/uni_modules/x-facedetection/utssdk/app-harmony/lib/x_facedetection.har new file mode 100644 index 0000000..5e69c32 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-harmony/lib/x_facedetection.har differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-facedetection/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLjoy_200.emd b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLjoy_200.emd new file mode 100644 index 0000000..0363a4c Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLjoy_200.emd differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLlefteyeclosed_200.emd b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLlefteyeclosed_200.emd new file mode 100644 index 0000000..0ac3e17 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLlefteyeclosed_200.emd differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLrighteyeclosed_200.emd b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLrighteyeclosed_200.emd new file mode 100644 index 0000000..8db84a0 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/BCLrighteyeclosed_200.emd differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/Info.plist b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/Info.plist new file mode 100644 index 0000000..beec997 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/Info.plist differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/LMprec_600.emd b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/LMprec_600.emd new file mode 100644 index 0000000..0d7702f Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/LMprec_600.emd differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/MFT_fssd_accgray.pb b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/MFT_fssd_accgray.pb new file mode 100644 index 0000000..b773b72 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/MFT_fssd_accgray.pb differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/MFT_fssd_fastgray.pb b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/MFT_fssd_fastgray.pb new file mode 100644 index 0000000..d3e7098 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/MFT_fssd_fastgray.pb differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/blazeface.tfl b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/blazeface.tfl new file mode 100644 index 0000000..e5258b1 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/blazeface.tfl differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/contours.tfl b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/contours.tfl new file mode 100644 index 0000000..50b40b1 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/contours.tfl differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_gray_v1.tflite b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_gray_v1.tflite new file mode 100644 index 0000000..403aa41 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_gray_v1.tflite differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_v1.tflite b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_v1.tflite new file mode 100644 index 0000000..e947aab Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_v1.tflite differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_gray_v1.tflite b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_gray_v1.tflite new file mode 100644 index 0000000..9f37e30 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_gray_v1.tflite differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_v1.tflite b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_v1.tflite new file mode 100644 index 0000000..da07f12 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_v1.tflite differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/_CodeSignature/CodeResources b/uni_modules/x-facedetection/utssdk/app-ios/Resources/_CodeSignature/CodeResources new file mode 100644 index 0000000..bad0c72 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-ios/Resources/_CodeSignature/CodeResources @@ -0,0 +1,355 @@ + + + + + files + + GoogleMVFaceDetectorResources.bundle/BCLjoy_200.emd + + 96Uw5p4tLIiDbN11Du0p0c5xqE8= + + GoogleMVFaceDetectorResources.bundle/BCLlefteyeclosed_200.emd + + KBTvwnLXsoe2PIlGUwZzMUOp5k8= + + GoogleMVFaceDetectorResources.bundle/BCLrighteyeclosed_200.emd + + fW6O7h6Je5DNmNrbOeCGmAixyLI= + + GoogleMVFaceDetectorResources.bundle/Info.plist + + sS7uhwBl1ZXssfZceNWmGpZYct0= + + GoogleMVFaceDetectorResources.bundle/LMprec_600.emd + + trY9XrpS4DxHzs3eHljZHIJNHrI= + + GoogleMVFaceDetectorResources.bundle/MFT_fssd_accgray.pb + + tq7fRawRQ359i/c0FEVvpQ6Oee0= + + GoogleMVFaceDetectorResources.bundle/MFT_fssd_fastgray.pb + + DP+qJf0czliL6znGLVx90ASNzCY= + + GoogleMVFaceDetectorResources.bundle/blazeface.tfl + + oseYQ/EQxo7JsNpdNgo4YVLh7a4= + + GoogleMVFaceDetectorResources.bundle/contours.tfl + + PaAh9+zFw3Is4fLMn5iQsLG5M34= + + GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_gray_v1.tflite + + VCp0NyrYJWQnYbGaxVv0Vzy0IeA= + + GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_v1.tflite + + AHaxev+fV4YGoIDboAUFlxfISmY= + + GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_gray_v1.tflite + + Rd53RFFpKHZNvbiDaE2p4XxjbY0= + + GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_v1.tflite + + RxtbTN3LjpFChp3tmniX3KD+dsE= + + Headers/unimoduleXFacedetection-Swift.h + + BgxJ1I5k5MMBQ6xo5tZUy5d60tQ= + + Headers/unimoduleXFacedetection.h + + FH2SRnQAHIO8AbDZPa5/Bz/CcdA= + + Info.plist + + PAgX/P+2Nr5qTH+62odWUCKos8k= + + Modules/module.modulemap + + Zs/pbohrSFVhBYtMd56wG2K8w+s= + + Modules/unimoduleXFacedetection.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + aS63R8pVNYw0JVr4ejn70VPlNUc= + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.abi.json + + VR3vMqk9fyleB4pmV+rgX1OX9F4= + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + y73yJ903XXHaZ0v6wemdBjTKYF0= + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + qliuAzBQoC+dStdbKgiR0WqcTV0= + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + y73yJ903XXHaZ0v6wemdBjTKYF0= + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + eXYli4ct9KFQLJTu7d0hBYsH/xw= + + config.json + + CzGjQQN8WuE+yTnq013U9m0usAM= + + + files2 + + GoogleMVFaceDetectorResources.bundle/BCLjoy_200.emd + + hash2 + + 8A8lZEpijnOMFV9JPQcq8UPyU8v5nwi/SCnL5dT0NRw= + + + GoogleMVFaceDetectorResources.bundle/BCLlefteyeclosed_200.emd + + hash2 + + 0xIT5PJf+LIXgeeG/YnO3lkX75s/vlC99V1IOvE27e0= + + + GoogleMVFaceDetectorResources.bundle/BCLrighteyeclosed_200.emd + + hash2 + + Y8oL2DjlGXdImtrbgKC+AWxaoLe2kPvDiaBkWqzP5P8= + + + GoogleMVFaceDetectorResources.bundle/Info.plist + + hash2 + + kLtzThegQhDjMdMnp21m/n5y4M/GWaJBT3DF395jFL0= + + + GoogleMVFaceDetectorResources.bundle/LMprec_600.emd + + hash2 + + DtXIUoL5QNFKVyOmwK8F+cKr1Okww8TwvloHI203QRE= + + + GoogleMVFaceDetectorResources.bundle/MFT_fssd_accgray.pb + + hash2 + + 8K2wTXshtNmImTKmLw7/En7tsn0vhTQqkBRBU8oLgbE= + + + GoogleMVFaceDetectorResources.bundle/MFT_fssd_fastgray.pb + + hash2 + + CUNCXfGzUODFinvmaL4flC6sM4wZjhpPFoWco+Eif0U= + + + GoogleMVFaceDetectorResources.bundle/blazeface.tfl + + hash2 + + TyXMFC6WtfIbMjbSFmwuZikgaB8dI5QtJRDpjIr27Nw= + + + GoogleMVFaceDetectorResources.bundle/contours.tfl + + hash2 + + hBYLwMSnSVF+Yvk8ssaKuP9J3lcfcOttFgJUypoHicA= + + + GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_gray_v1.tflite + + hash2 + + ekzwnGrkp1gUTUK/NbmiapWYfjxYQdDcORCVaYKZ2as= + + + GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_v1.tflite + + hash2 + + OvuTDu3I0dQENEgCgdO16M7EwwTlLTT9/IqVCDQLtxk= + + + GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_gray_v1.tflite + + hash2 + + IVEbvtJxoKkri5ORjg+I9u+70RWjbRVV8GHO4TH2qzw= + + + GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_v1.tflite + + hash2 + + 2pAlL0mzu5QuX4gBgKFFYfZpKW5/s+3s3quqi2u3gio= + + + Headers/unimoduleXFacedetection-Swift.h + + hash2 + + rTildwV5zLFcxijbFWhzuO4YvO9LA74X/7lz8WuQqJU= + + + Headers/unimoduleXFacedetection.h + + hash2 + + XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY= + + + Modules/module.modulemap + + hash2 + + mktK2hAXHkebM3pE/qIOCLCiT0PsQ+hRCZ1j7Cbvxf4= + + + Modules/unimoduleXFacedetection.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + hash2 + + J9NnQTKtAGGpoVeYKyZw5c4MV06RKpL8Al+SnPwYZdA= + + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.abi.json + + hash2 + + q82Bl78THFBZ+ZocAvtg3vOuP28SaJ8euEkpbaHmZRA= + + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + hash2 + + M+3tx0iPWvL/1tT7IYkaDX1waVEMZ0IyQGmfsPV4JNQ= + + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + hash2 + + WjiHhAVADf0QcXgeRlnwqWksqonEUfqUD8RRV4E3hd8= + + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + hash2 + + M+3tx0iPWvL/1tT7IYkaDX1waVEMZ0IyQGmfsPV4JNQ= + + + Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + hash2 + + Yulvj7VnfZMMHAC7X3icMFcyuJ7FzZNFowozFX8vwpQ= + + + config.json + + hash2 + + u75O7GUa7m6ue3dUjfs+U7kF97YboIw8B2A8pKZTLAo= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/downUp.mp3 b/uni_modules/x-facedetection/utssdk/app-ios/Resources/downUp.mp3 new file mode 100644 index 0000000..51c1db8 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/downUp.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/eyeOplenClose.mp3 b/uni_modules/x-facedetection/utssdk/app-ios/Resources/eyeOplenClose.mp3 new file mode 100644 index 0000000..dd3be55 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/eyeOplenClose.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/goold.mp3 b/uni_modules/x-facedetection/utssdk/app-ios/Resources/goold.mp3 new file mode 100644 index 0000000..e9b75a6 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/goold.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/left.mp3 b/uni_modules/x-facedetection/utssdk/app-ios/Resources/left.mp3 new file mode 100644 index 0000000..79d6ae6 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/left.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/monthOpenClose.mp3 b/uni_modules/x-facedetection/utssdk/app-ios/Resources/monthOpenClose.mp3 new file mode 100644 index 0000000..4091c89 Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/monthOpenClose.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/Resources/right.mp3 b/uni_modules/x-facedetection/utssdk/app-ios/Resources/right.mp3 new file mode 100644 index 0000000..e933f1d Binary files /dev/null and b/uni_modules/x-facedetection/utssdk/app-ios/Resources/right.mp3 differ diff --git a/uni_modules/x-facedetection/utssdk/app-ios/config.json b/uni_modules/x-facedetection/utssdk/app-ios/config.json new file mode 100644 index 0000000..fe0fec8 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-ios/config.json @@ -0,0 +1,10 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "GoogleMLKit/FaceDetection", + "version": "5.0.0" + } + ] +} + diff --git a/uni_modules/x-facedetection/utssdk/app-ios/index.uts b/uni_modules/x-facedetection/utssdk/app-ios/index.uts new file mode 100644 index 0000000..1589c4f --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-ios/index.uts @@ -0,0 +1,225 @@ +import { AVCaptureSession, AVCaptureDevice, AVMediaType, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureDeviceInput, AVCaptureInput, AVCaptureVideoDataOutput, AVCaptureConnection, AVCaptureVideoPreviewLayer, AVLayerVideoGravity, AVCaptureVideoOrientation } from 'AVFoundation'; +import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos'; +import { CMSampleBuffer, CMSampleBufferGetFormatDescription, CMFormatDescription, CMVideoFormatDescriptionGetDimensions } from 'CoreMedia'; +import { DispatchQueue } from "Dispatch" +import { UIView, UIImage, UIApplication, UIImageView, UILabel, UIViewController, UIFontDescriptor, UIFont, NSTextAlignment, UITapGestureRecognizer, UIImagePickerController, UIImagePickerControllerDelegate, UINavigationControllerDelegate } from 'UIKit'; +import { CGRect, CGFloat, CGPoint } from 'CoreFoundation'; +import { Face, FaceContour, FaceDetector, FaceDetectorOptions,FaceContourType,FaceLandmarkType, FaceLandmark,FaceDetectorPerformanceMode,FaceDetectorClassificationMode,FaceDetectorLandmarkMode } from "MLKitFaceDetection" +import { VisionImage } from "MLKit" + +import { NotificationCenter, NSNotification, Notification } from 'Foundation'; +import { Selector } from 'ObjectiveC'; +import { Alignment } from 'ARKit'; +import { CABasicAnimation } from 'QuartzCore'; +import { Int,Float } from 'Swift'; + +import { XFACE_CHECK_OPTS, XFACE_EVENT_SUCCESS, XFACE_TEST_EYE_TYPE, XFACE_FACE_Direction, XFACE_EVENT_CHECK_SUCCESS } from "../interface.uts" +import { XFACE_CHECK_OPTS_REAL, getDefaultConfig } from "../libs/config.uts" + + +const checkFaceResult = (orimg:UIImage, faces : Array, callBack : (result : XFACE_EVENT_SUCCESS[]) => void) => { + const cfaces = [] as XFACE_EVENT_SUCCESS[] + // @ts-ignore + for (item in faces) { + // @ts-ignore + const face = item as Face; + let rightEye = { openNum: 0, isOpen: false } as XFACE_TEST_EYE_TYPE; + let leftEye = { openNum: 0, isOpen: false } as XFACE_TEST_EYE_TYPE; + // 眼睛 + let rightEyeMark = face.landmark(ofType = FaceLandmarkType.rightEye) + let leftEyeMark = face.landmark(ofType = FaceLandmarkType.leftEye) + + // 鼻子 + let noseMark = face.landmark(ofType = FaceLandmarkType.noseBase) + // 耳朵 + let rightEarMark = face.landmark(ofType = FaceLandmarkType.rightEar) + let leftEarMark = face.landmark(ofType = FaceLandmarkType.leftEar) + + let rightEyeNum = face.rightEyeOpenProbability + let leftEyeNum = face.leftEyeOpenProbability + let isSmile = face.smilingProbability + + let faceId = face.trackingID + + + if (rightEyeNum != null) { + rightEye.openNum = new Number(rightEyeNum) + 0; + rightEye.isOpen = new Number(rightEyeNum) > 0.7 + } + if (leftEyeNum != null) { + leftEye.openNum = new Number(leftEyeNum)+ 0; + leftEye.isOpen = new Number(leftEyeNum) > 0.7 + } + + // 检测当前左,右,下,上 + let faceRightLeft : XFACE_FACE_Direction = "center" + let faceUpDown : XFACE_FACE_Direction = "center" + + + let eulerX = face.headEulerAngleX; // 获取头部左右旋转角度 + let eulerY = face.headEulerAngleY; // 获取头部上下俯仰角度 + let eulerZ = face.headEulerAngleZ; // 获取头部上下俯仰角度 + + // 嘴巴 + let leftMouth = face.landmark(ofType = FaceLandmarkType.mouthLeft) + let rightMouth = face.landmark(ofType = FaceLandmarkType.mouthRight) + let bottomMouth = face.landmark(ofType = FaceLandmarkType.mouthBottom) + + let isMouthOpened = false + let ANGLE_THRESHOLD = 30; // 容差值 + let ANGLE_HEAD_THRESHOLD = 0; // 容差值 + let ANGLE_EYE_THRESHOLD = 6; // 眨眼的容差. + + let allHeadBody = false; + + if (Math.abs(Number(eulerY)) > ANGLE_THRESHOLD) { // 确保头部没有明显上下俯仰 + faceRightLeft = eulerY > 0 ? 'left' : 'right'; + } + + if (Math.abs(Number(eulerX)) >= ANGLE_HEAD_THRESHOLD) { // 确保头部没有明显上下俯仰 + faceUpDown = eulerY > 0 ? 'down' : 'up'; + } + + if (leftMouth != null && rightMouth != null && bottomMouth != null) { + let mouthWidth = rightMouth!.position.x - leftMouth!.position.x + let mouthHeight = bottomMouth!.position.y - ((leftMouth!.position.y + rightMouth!.position.y) / 2) + + if (mouthHeight / mouthWidth > 0.4 && faceRightLeft == 'center') { + isMouthOpened = true; + } else { + isMouthOpened = false; + } + } + + + + if( + leftMouth != null && + rightMouth != null && + bottomMouth != null && + noseMark !=null&& + rightEarMark !=null&& + leftEarMark !=null&& + rightEyeMark !=null&& + leftEyeMark !=null + ){ + allHeadBody = true; + } + cfaces.push({ + imgWidth: orimg.size.width, + imgHeight: orimg.size.height, + isSmile: isSmile == null ? false : (isSmile >= 0.8), + rightEye, + leftEye, + faceRightLeft, + faceUpDown, + isMouthOpened, + allHeadBody, + faceId:faceId!=null?(faceId+0):null + }) + + + + } + + callBack(cfaces) +} + +export function checkFaceByImage(config : XFACE_CHECK_OPTS | null = null){ + const cfg = getDefaultConfig(config) + let options_s = FaceDetectorOptions() + options_s.performanceMode = FaceDetectorPerformanceMode.accurate + options_s.landmarkMode = FaceDetectorLandmarkMode.all + options_s.classificationMode = FaceDetectorClassificationMode.all + // @ts-ignore + uni.chooseImage({ + count: 1, + // @ts-ignore + success(evt : ChooseImageSuccess) { + if (evt.tempFilePaths.length == 0) return; + const imgs = evt.tempFilePaths[0] as string; + const decodedPath = UTSiOS.convert2AbsFullPath(imgs) + let img = new UIImage(contentsOfFile = decodedPath); + let image = new VisionImage(image = img!); + let faceDetector = FaceDetector.faceDetector(options = options_s) + faceDetector.process(image as VisionImage,completion = (faces:Array|null,error:any|null)=>{ + + if(error != null||faces==null||(faces?.length??0)==0){ + cfg.success({ + images:[], + videoPath:"", + isPass:false + }) + return; + } + const _faces = faces!; + + checkFaceResult(img!, _faces, (result : XFACE_EVENT_SUCCESS[]) => { + + DispatchQueue.main.async(execute = () : void => { + + cfg.enter(result,JSON.stringify(result)!) + cfg.success({ + isPass: true, + images: [decodedPath] as string[], + videoPath: "" + }) + }) + + }) + // for(item in faces!){ + // const face = item as Face + // let leftEye = face.landmark(ofType = FaceLandmarkType.leftEye) + // if(leftEye!=null){ + // let leftEyePosition = leftEye!.position + // console.log(leftEyePosition.x,'----',img!.size.width) + // } + // } + }) + }, + fail() { + cfg.fail("解析错误") + } + }) +} + +/** + * 提供外部图片地址检测当前图片是否存在人脸 + */ +export function checkFaceByImageFromFilePath(config : XFACE_CHECK_OPTS) { + const cfg = getDefaultConfig(config) + const imgs = cfg.url; + const decodedPath = UTSiOS.convert2AbsFullPath(imgs!) + let img = new UIImage(contentsOfFile = decodedPath); + let image = new VisionImage(image = img!); + let options_s = FaceDetectorOptions() + options_s.performanceMode = FaceDetectorPerformanceMode.accurate + options_s.landmarkMode = FaceDetectorLandmarkMode.all + options_s.classificationMode = FaceDetectorClassificationMode.all + + let faceDetector = FaceDetector.faceDetector(options = options_s) + faceDetector.process(image as VisionImage,completion = (faces:Array|null,error:any|null)=>{ + if(error != null||faces==null||(faces?.length??0)==0){ + cfg.success({ + images:[], + videoPath:"", + isPass:false + }) + return; + } + const _faces = faces!; + checkFaceResult(img!, _faces, (result : XFACE_EVENT_SUCCESS[]) => { + DispatchQueue.main.async(execute = () : void => { + cfg.enter(result,JSON.stringify(result)!) + cfg.success({ + isPass: true, + images: [decodedPath] as string[], + videoPath: "" + }) + }) + + }) + + }) +} + diff --git a/uni_modules/x-facedetection/utssdk/app-ios/info.plist b/uni_modules/x-facedetection/utssdk/app-ios/info.plist new file mode 100644 index 0000000..3d2be4d --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/app-ios/info.plist @@ -0,0 +1,10 @@ + + + + + NSCameraUsageDescription + 我们需要您的相机权限来拍照或录像。 + NSPhotoLibraryUsageDescription + 需要使用你的相册进行选择视频及图片 + + \ No newline at end of file diff --git a/uni_modules/x-facedetection/utssdk/interface.uts b/uni_modules/x-facedetection/utssdk/interface.uts new file mode 100644 index 0000000..ca46342 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/interface.uts @@ -0,0 +1,99 @@ + +export type XFACE_CHECK_OPTS = { + //如果是通过图片检测需要提供 + url ?: string, + //如果是通过图片buffer解析需要提供(暂无法使用) + buffer ?: ArrayBuffer, + //ViewId,如果是通过相机动态绑定嵌入式页面时,需要提供页面view的id + viewId ?: string, + /** + * 活体检测指令,通过相机视频检测 + * 如果提供指令数组时,会根据完整指令顺序检测直到验证通过. + * 如果视频检测时,指令为空数组则只检测整个五官是不是在画面中,一旦检测到人脸立即验证通过. + */ + instruction ?: XFACE_INS[] + //验证结束并通过时返回 + success ?: (data : XFACE_EVENT_CHECK_SUCCESS) => void, + /** + * 在视频活体检测时,返回每一帧的检测详细检测过程的信息,此事件是持续触发,直到结束,会一直触发每帧的图片检测结果。 + * 在图片检测的时候,只返回一次。 + */ + enter ?: (data : XFACE_EVENT_SUCCESS[],maps:string) => void, + /** + * 开始检测,正在开始检测的指令。类似:向左转一次,向右转一次,点点头,张张嘴等执行时触发, + * 方便用户自定自己的提示语或者语音播报 + * 'start',现在开始, + * 'ins_start_指令名称':某个指令开始,如:ins_start_left,ins_start_right,通过这个解析哪个指令开始执行 + * 'ins_end_指令名称':某个指令结束,如:ins_end_left,ins_end_right,通过这个解析哪个指令结束执行 + * 'end'结束所有指令 + * 之后会触发success,enter事件 + */ + insTipsEvent ?: (data : string) => void, + fail ?: (error : string) => void, +} +export type XFACE_TEST_EYE_TYPE = { + //眼睛张开的概率值 + openNum : number, + isOpen : boolean +} +export type XFACE_FACE_Direction = "left" | "right" | "center" | "down" | "up" + +/** + * 活体检测指令,可以通过指令控制检测动作 + * left:向左转一次 + * right:向右转一次 + * downUp:上下点头 + * eyeOplenClose:眨眼 + * monthOpenClose:张张嘴. + */ +export type XFACE_INS = "left" | "right" | "downUp" | "eyeOplenClose" | "monthOpenClose" +// >0.8就算打开了眼或者张开了嘴. +export type XFACE_EVENT_SUCCESS = { + // 右眼眨眼睛的闭合数据 + rightEye : XFACE_TEST_EYE_TYPE, + // 左眼眨眼睛的闭合数据 + leftEye : XFACE_TEST_EYE_TYPE, + // 是否在微信 + isSmile : boolean, + //脸向左,向在,中间 + faceRightLeft : XFACE_FACE_Direction, + //点头的方向 + faceUpDown : XFACE_FACE_Direction, + imgWidth : number, + imgHeight : number, + // 嘴巴是不是张开 + isMouthOpened : boolean, + // 整个脑袋是否在画面中. + allHeadBody : boolean, + /** + * 检测过程中如果被检测人移动移出屏幕或者光线变化太大或者明显改变人造型等都会被改变此值,并认为并非是同一个从而 + * 让检测认证失败,因此被检测人一定要从头到尾保持端正并始终不离开视频画面. + * 人脸Id + */ + faceId:number|null +} +export type XFACE_EVENT_CHECK_SUCCESS = { + /** + * 此结果是在活体检测结果会返回,如果是通过图片人脸检测,则此值为空值. + * 验证结束保存的视频地址,方便上传保存到后台储存备份,抽查验证。 + */ + videoPath : string + /** + * 此结果是在活体检测结果会返回,如果是通过图片人脸检测,则此值为空数组 + * 在活体检测过程中,会按照你给定人的指令顺序进行截图,保存验证时人脸对应的动画图片.多少个指令就有多少张图片.最后 + * 一张为全脸捕捉画面. + */ + images : string[], + /** + * 验证是否通过 + */ + isPass : boolean +} + +export type AUTH_CALL_BACK_TYPE = (auth : boolean) => void; +export type XCHECKFACE_ENTER_CALL = (image : XFACE_EVENT_SUCCESS[], bitMap : any | null) => void; + +export type CAMERA_PHOTO_SIZE = { + width : number, + height : number +} \ No newline at end of file diff --git a/uni_modules/x-facedetection/utssdk/libs/config.uts b/uni_modules/x-facedetection/utssdk/libs/config.uts new file mode 100644 index 0000000..e6fde25 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/libs/config.uts @@ -0,0 +1,36 @@ +import { XFACE_CHECK_OPTS,XFACE_EVENT_SUCCESS,XFACE_EVENT_CHECK_SUCCESS,XFACE_INS } from "../interface.uts" +export type XFACE_CHECK_OPTS_REAL = { + url : string, + buffer : ArrayBuffer, + viewId :string, + // 活体检测指令,在通过相机视频检测的时候为必填 + instruction:XFACE_INS[], + insTipsEvent:(data:string)=>void, + success : (data : XFACE_EVENT_CHECK_SUCCESS) => void, + enter : (data : XFACE_EVENT_SUCCESS[],maps:string) => void, + fail : (error : string) => void, +} +export function getDefaultConfig(config : XFACE_CHECK_OPTS|null = null) : XFACE_CHECK_OPTS_REAL{ + let cfg = { + url: "", + buffer: new ArrayBuffer(0), + viewId:"", + instruction:[] as XFACE_INS[], + insTipsEvent:(data:string)=> {}, + success: (data : XFACE_EVENT_CHECK_SUCCESS) => { }, + enter : (data : XFACE_EVENT_SUCCESS[],maps:string) => { }, + fail: (error : string) => { }, + } as XFACE_CHECK_OPTS_REAL + if(config==null) return cfg; + cfg.url = config?.url ?? cfg.url; + cfg.buffer = config?.buffer ?? cfg.buffer; + cfg.success = config?.success ?? cfg.success; + cfg.enter = config?.enter ?? cfg.enter; + cfg.fail = config?.fail ?? cfg.fail; + cfg.viewId = config?.viewId ?? cfg.viewId; + cfg.instruction = config?.instruction ?? cfg.instruction; + cfg.insTipsEvent = config?.insTipsEvent ?? cfg.insTipsEvent; + + return cfg; + +} diff --git a/uni_modules/x-facedetection/utssdk/mp-weixin/index.uts b/uni_modules/x-facedetection/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..f72ba41 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/mp-weixin/index.uts @@ -0,0 +1,3 @@ +export function checkFaceByImage(){} +export function checkFaceByImageFromFilePath(){} + diff --git a/uni_modules/x-facedetection/utssdk/unierror.uts b/uni_modules/x-facedetection/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-facedetection/utssdk/web/index.uts b/uni_modules/x-facedetection/utssdk/web/index.uts new file mode 100644 index 0000000..e03c430 --- /dev/null +++ b/uni_modules/x-facedetection/utssdk/web/index.uts @@ -0,0 +1,2 @@ +export function checkFaceByImage(){} +export function checkFaceByImageFromFilePath(){} diff --git a/uni_modules/x-file-s/1.jpg b/uni_modules/x-file-s/1.jpg new file mode 100644 index 0000000..0dd7456 Binary files /dev/null and b/uni_modules/x-file-s/1.jpg differ diff --git a/uni_modules/x-file-s/2.png b/uni_modules/x-file-s/2.png new file mode 100644 index 0000000..6599db4 Binary files /dev/null and b/uni_modules/x-file-s/2.png differ diff --git a/uni_modules/x-file-s/3.png b/uni_modules/x-file-s/3.png new file mode 100644 index 0000000..46abb3d Binary files /dev/null and b/uni_modules/x-file-s/3.png differ diff --git a/uni_modules/x-file-s/changelog.md b/uni_modules/x-file-s/changelog.md new file mode 100644 index 0000000..f4fd750 --- /dev/null +++ b/uni_modules/x-file-s/changelog.md @@ -0,0 +1,16 @@ +## 1.0.8(2025-08-17) +* 兼容支持鸿蒙 Next +## 1.0.4(2025-01-12) +* 支持微信小程序 +## 1.0.3(2024-09-12) +* 安卓更新了相关bug,另外使用方法改变以了有些方法类型变以了,更新时请注意比对demo方法. +## 1.0.2(2024-08-14) +* 新增属性超过指定文件大小,会被标注,并且三端会返回文件大小。 +## 1.0.1(2024-05-24) +* 本次适配了IOS 11+(含),现在你可以在ios,安卓,web下选择文件上传了哦。 +* 请认真看说明文档使用,使用复杂了点,由于安卓,ios隐私等限制没办法抹平使用差异,请看仔细使用。如果不会用,请使用我tmui4.0x中的x-upload-file来进行文件上传。 +## 1.0.0(2024-04-13) +* 原生文件选择器,支持安卓(不需要权限,也不需要打基座,标准基座即可) +* web原生支持 +* ios待适配 +* tmui4.0种子用户,可免费赠送源码,无需购买 diff --git a/uni_modules/x-file-s/package.json b/uni_modules/x-file-s/package.json new file mode 100644 index 0000000..ec2b4d5 --- /dev/null +++ b/uni_modules/x-file-s/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-file-s", + "displayName": "tm-ui-4.0 安卓 IOS WEB 鸿蒙 文件选择器 通用无权限使用", + "version": "1.0.8", + "description": "安卓端不需要权限,web端,ios三端规格统一,抹平差异。", + "keywords": [ + "安卓,web文件选择器,ios,鸿蒙" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "99.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-file-s/readme.md b/uni_modules/x-file-s/readme.md new file mode 100644 index 0000000..9434915 --- /dev/null +++ b/uni_modules/x-file-s/readme.md @@ -0,0 +1,187 @@ +# x-file-s +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +**如果需要查看效果请[下载TMUI4.0组件库应用demo](https://ext.dcloud.net.cn/plugin?id=16369),导航到原生插件栏目体验。** + +### 功能特色 + +** 本插件是API接口插件非组件,插件截图是我的TMUI4.0 x-upload-file基于此api接口封装的ui组件 ** + +- 支持安卓,无权限操作 +- 支持web选择文件上传 +- 支持多选,单选 +- 支持微信 + +### 功能说明 + +**请仔细看下面的使用方法,ios和web,安卓有区别注意条件编译进上传上传** + +与官方 新 出的文件选择最大不同的是: +1. 选择的文件不会有真实的文件,还要在上传时再执行内部 copy,因此理论上你选择 100 个文件上传,都是单个循环上传,不会造成崩溃 +除非你单个文件就非常大。(官方的是限制数量 100,默认选择后就给你一起复制到缓存了,而我是按需复制缓存文件。) +2. 后缀不一样,可以任意标签的 miniType 格式如 application/msword等。 + +- 安卓端无需权限,返回系统的文件列表,但不包含真实文件地址。如果需要操作上传读取等,需要配置copyFileToPath方法,生成一个你自己的文件缓存目录。把文件复制到此位置。 +- 如果不要用了,要自己通过官方uni.getFileSystemManager来管理和清空缓存文件夹。不然应用随意使用的推移会增大。 +- web端直接选择上传没有上述问题 +- ios已支持从系统文件 管理器选择任意文件上传,它同安卓一样会在选择的时候copy一份文件到应用专属缓存文件中(不用担心变大,会自动清除),选择的文件只能当即临时上传 +时间长了会自动删除。返回的文件路径需要自行uni.env.CACHE_PATH + "/" + item.realFilePath组合路径进行上传 + +- 如果你不会使用,建议使用我的tmui4.0组件中的x-upload-file,它是基于此api接口封装的上传组件,啥都帮你配置好了,你只要提供个服务器的上传地址。 + + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件。种子用户可免于购买。 + +非种子用户: + +普通授权:99元 +源码授权:199元 + +### 使用 +如果你需要32位系统和模拟器x86上运行,需要自行配置打包cpu 支持类型,配置abis +需要自定义基座运行,且安卓4.4+(含4.4)以上支持 + +```ts +// 导入 +import {xFileSystem,fileListType} from "@/uni_modules/x-file-s" + +/** + * 新建文件管理对象, + * typeFilter:string|null 文件过滤器例:"*/*",或者所有图片 "image/*" + * tempmultiple:boolean|null 是否多选,默认是 + * maxSize:number|null 限制的文件大小,不是禁止用户选中,是返回的列表会标stauts=4,表示超过了大小。 + */ +this.xfile = new xFileSystem(null,null) + +// 打开文件夹选择文件 +this.xfile!.openDocument((list:any)=>{ + // 安卓是 list:fileListType[]是选中的文件列表,但这个文件列表是虚拟的,并非真实的文件地址。 + // web端list:fileListType[] 可以通过item.file访问文件对象即File + // ios端是string + + let list = [] as fileListType[]; + // #ifdef APP-IOS + let templist = JSON.parseArray(listtest) + for(let i=0;i{ + // #ifdef WEB + return Promise.resolve("") + // #endif + //默认创建一个临时的 tmui4temp 目录 + let baseNamePath = dir==null?'tmui4temp':dir + baseNamePath = uni.env.CACHE_PATH + "/" + baseNamePath + const fileManager = uni.getFileSystemManager() + return new Promise((res,rej)=>{ + fileManager.readdir({ + dirPath:baseNamePath, + success(result:ReadDirSuccessResult){ + if(result==null){ + fileManager.mkdir({ + dirPath:baseNamePath, + recursive:true, + success(result:FileManagerSuccessResult){ + res(baseNamePath) + }, + fail(er:UniError){ + console.log('创建目录失败',er) + rej("") + } + } as MkDirOptions) + }else{ + // 这个是目录路径 + res(baseNamePath) + } + }, + fail(ere:UniError){ + fileManager.mkdir({ + dirPath:baseNamePath, + recursive:true, + success(result:FileManagerSuccessResult){ + res(baseNamePath) + }, + fail(er:UniError){ + console.log('创建目录失败',er) + rej("") + } + } as MkDirOptions) + } + } as ReadDirOptions) + }) +} + +//调用上述方法,确保临时目录存在后通过Promise回调来复制文件路径 +// web,安卓如下执行读取真实路径给uploadfile来上传 +this.fileIsOnlyInSys('tmui4temp') +.then((basedir:string)=>{ + _this.xfile!.copyFileToPath(item.id,basedir) + .then((oreal:fileListType|null)=>{ + // oreal 这个对象包含了真实的上传地址 + // 在这里面你可以读取,上传文件了。 + }) +}) +// ios端不需要执行上面的步骤。 +// 直接就是前面的项目fileListType中的 uni.env.CACHE_PATH + "/" + item.realFilePath 组合路径进行上传 + + + +``` + +## 类型参考 + +```ts +// api内部类型。 +type xFileSNameTYpe = { + name:string, + type:string, + uri:Uri, + id:string, + realFilePath:string, + cacheFilePath:string, + size:number, + status:number +} +// 你外部使用的文件对象类型 +export type xFileSListType = { + name:string, + type:string, + id:string, + /** web平台文件对象 */ + file?:any, + /** 个人用户自定数据 */ + request?:any, + /** 安卓机/ios机下面的真实sd路径 */ + realFilePath:string, + /** uniapp应用协议文件路径,可用uni.getFileSystemManager进行删除或者查询到 */ + cacheFilePath:string, + /** 文件大小 */ + size?:number + /** + * 0等待,1失败,2成功,3上传中,4超过大小。 + */ + status?:0|1|2|3|4 +} + + +``` \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/app-android/config.json b/uni_modules/x-file-s/utssdk/app-android/config.json new file mode 100644 index 0000000..7ed4299 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "19" +} \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/app-android/index.uts b/uni_modules/x-file-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..0eda512 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/app-android/index.uts @@ -0,0 +1,432 @@ +import MediaStore from "android.provider.MediaStore" +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import Uri from "android.net.Uri" +import Context from 'android.content.Context' +import ContentResolver from 'android.content.ContentResolver' +import InputStream from 'java.io.InputStream' +import FileOutputStream from 'java.io.FileOutputStream' +import File from 'java.io.File' + +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import MimeTypeMap from 'android.webkit.MimeTypeMap' +import OpenableColumns from 'android.provider.OpenableColumns' +import Build from 'android.os.Build' +import ParcelFileDescriptor from 'android.os.ParcelFileDescriptor' + +import { xFileSListType,fileListType } from "../interface.uts" + +type xFileSNameTYpe = { + name : string, + type : string, + uri : Uri, + id : string, + realFilePath : string, + cacheFilePath : string, + fileSize : number, + status : number +} +type callReadBackFun = (byte : ByteArray) => void + +type resumtype = (requestCode : Int, resultCode : Int, data : any) => void + +const mimeTypes = new Map([ + // 图片类型 + ["jpg", "image/*"], + ["jpeg", "image/*"], + ["png", "image/*"], + ["gif", "image/*"], + ["bmp", "image/*"], + ["webp", "image/*"], + ["tiff", "image/*"], + ["svg", "image/*"], + ["ico", "image/*"], + + // 视频类型 + ["mp4", "video/*"], + ["webm", "video/*"], + ["ogv", "video/*"], + ["mov", "video/*"], + ["avi", "video/*"], + ["wmv", "video/*"], + + // 音频类型 + ["mp3", "audio/*"], + ["wav", "audio/*"], + ["ogg", "audio/*"], + ["flac", "audio/*"], + ["aac", "audio/*"], + + // 文档类型 + ["pdf", "application/*"], + ["doc", "application/*"], + ["docx", "application/*"], + ["xls", "application/*"], + ["xlsx", "application/*"], + ["ppt", "application/*"], + ["pptx", "application/*"], + ["odt", "application/*"], + ["ods", "application/*"], + + // 文本类型 + ["txt", "text/plain"], + ["html", "text/html"], + ["css", "text/css"], + ["js", "text/javascript"], + ["xml", "text/xml"], + + // 其他类型 + ["zip", "application/*"], + ["rar", "application/*"], + ["7z", "application/*"], + ["json", "application/*"] +]); + + + +function getMimeTypeFromUri(uri : Uri, max : number) : xFileSNameTYpe { + let context = UTSAndroid.getAppContext() as Context + let contentResolver = context.getContentResolver() as ContentResolver; + let mime = MimeTypeMap.getSingleton() as MimeTypeMap; + let gz = mime.getExtensionFromMimeType(contentResolver.getType(uri)) as string | null; + let str = uri.getEncodedPath() + let par = contentResolver.openFileDescriptor(uri, "r") as ParcelFileDescriptor + let filesize = par.getStatSize() + if (gz == null) { + gz = str!.substring(str!.lastIndexOf(".") + 1) + } + let name = str!.substring(0, str!.lastIndexOf("/")) + name = str!.substring(0, str!.lastIndexOf(".")) + ///安卓10,api 29+需要遵循隐私策略获取名称。 + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + let cursor = contentResolver.query(uri, null, null, null, null) + if (cursor != null && cursor.moveToFirst()) { + let nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); + if (nameIndex != -1) { + name = cursor.getString(nameIndex); + } + cursor.close(); + } + // 确保关闭游标 + if (cursor != null && !cursor.isClosed()) { + cursor.close(); + } + } + + return { + name, + type: gz!, + uri: uri, + id: Math.floor(Math.random() * 1 * Math.floor(Math.random() * Date.now())).toString().substring(0, 10), + realFilePath: "", + cacheFilePath: "", + fileSize: filesize, + status: filesize > max ? 4 : 0 + + } as xFileSNameTYpe; +} + +function readFileToInputStrem(uri : Uri) : ByteArray { + //读写块的大小。 + let sizeBlock = 1024 + let context = UTSAndroid.getAppContext() as Context + let cover = context.getContentResolver() as ContentResolver + let inputStream = cover.openInputStream(uri) + let byteArrayOutputStream = new ByteArrayOutputStream(); + // 文件的字节数组 + let buffer = new ByteArray(sizeBlock.toInt()); + let n = inputStream!.read(buffer) + while (-1 != n) { + byteArrayOutputStream.write(buffer, 0, n); + n = inputStream!.read(buffer) + } + + return buffer; +} + +let filelistAll = [] as xFileSNameTYpe[] +function isInfilelist(file : xFileSNameTYpe) : boolean { + return filelistAll.some((el) : boolean => { + return el.name == file.name && el.type == file.type + }) +} +let callFun = (list : fileListType[]) => { } +let nowXFileSystem = null as null|xFileSystem; +const activityResult = (requestCode : Int, resultCode : Int, data ?: Intent)=>{ + + let jgCode = 1; + console.log(1) + if (data != null && requestCode == jgCode.toInt()) { + let fdata = data! as Intent + let flistdata = fdata.getClipData(); + let flistdataOnly = data?.data + //多选 + if (flistdata != null) { + let count = flistdata.getItemCount(); + + for (let i = 0; i < count; i++) { + let item = flistdata.getItemAt(i.toInt()) + let uri = item.getUri() + + + let itemfile = getMimeTypeFromUri(uri, nowXFileSystem!.maxFileSize) + if (!isInfilelist(itemfile)) { + + filelistAll.push(itemfile) + } + + } + //单选 + } else if (flistdataOnly != null) { + let itemfile = getMimeTypeFromUri(flistdataOnly!, nowXFileSystem!.maxFileSize) + if (!isInfilelist(itemfile)) { + filelistAll.push(itemfile) + } + } + let listfile = filelistAll.map((el) : fileListType => { + return { + name: el.name, + type: el.type, + id: el.id, + uri: '', + realFilePath: el.realFilePath, + cacheFilePath: el.cacheFilePath, + status: el.fileSize > nowXFileSystem!.maxFileSize ? 4 : 0, + size: el.fileSize + } as fileListType + }); + + callFun(listfile) + + } +} + +/** + * 由于安卓隐私的问题。实际得到的所有文件 其实 都不是真实地址。因此你想要得到真实的地址,你就得复制到你的应用沙盒中。 + */ +export class xFileSystem { + mimeTypeFilter : string[] = [] as string[] + filelist = [] as xFileSNameTYpe[] + multiple : boolean = true; + + maxFileSize = 30 * 1024 * 1024; + + constructor(typeFilter : string[] | null, tempmultiple : boolean | null, maxSize : number | null) { + if (typeFilter != null) { + + let filter : string[] = [] as string[]; + let tms = typeFilter! as string[] + for (let i = 0; i < tms.length; i++) { + if (mimeTypes.get(tms[i]) != null) { + filter.push(mimeTypes.get(tms[i])!) + } + } + if (filter.length == 0) { + filter.push("*/*") + } + + this.mimeTypeFilter = filter + + } + if (tempmultiple != null) { + this.multiple = tempmultiple! + } + if (maxSize != null) { + this.maxFileSize = maxSize! + } + nowXFileSystem = this; + UTSAndroid.onAppActivityResult(activityResult); + } + + + + destory() { + UTSAndroid.offAppActivityResult(activityResult) + // filelistAll = [] as xFileSNameTYpe[] + } + openDocument(call : (list : fileListType[]) => void) { + + let intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + intent.setAction(Intent.ACTION_OPEN_DOCUMENT); + } else { + intent.setAction(Intent.ACTION_GET_CONTENT); + } + + // intent.addCategory(Intent.CATEGORY_OPENABLE); + if (this.mimeTypeFilter.length == 0) { + intent.type = "*/*" + } else { + let key = this.mimeTypeFilter[this.mimeTypeFilter.length - 1] + let ftype = key; + if (ftype != null) { + intent.setType(ftype!); + } else { + intent.setType("*/*"); + } + // console.log(this.mimeTypeFilter) + // intent.putExtra(Intent.EXTRA_MIME_TYPES, []); + + } + + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, this.multiple) + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + let _this = this; + callFun = call; + + UTSAndroid.getUniActivity()!.startActivityForResult(intent, 1); + } + + /** + * 删除一个文件条目 + * @param {string} id - 文件id + * @returns {fileListType[]} 最新的文件列表 + */ + remove(id : string) : fileListType[] { + + let index = -1; + for (let i = 0; i < filelistAll.length; i++) { + let item = filelistAll[i] + if (item.id == id) { + filelistAll.splice(i, 1) + break; + } + } + + return filelistAll.map((el) : fileListType => { + + return { + name: el.name, + type: el.type, + id: el.id, + uri: '', + realFilePath: el.realFilePath, + cacheFilePath: el.cacheFilePath, + size: el.fileSize, + status: el.status + } as fileListType + }); + } + /** + * 返回一个空文件列表数组 + */ + clear() : fileListType[] { + filelistAll = [] as xFileSNameTYpe[]; + this.filelist = [] as xFileSNameTYpe[]; + return [] as fileListType[] + } + /** + * 读取文件 + * @description 提供这个函数是因为如果是大文件上传,你可能需要分块上传。由于安卓隐私问题,大文件超过16mb复制回用户区可能会卡或者其它意外事项。 + * @param {string} id - 文件id + * @param {number} size - 读写块的大小,每次读取的大小 + * @param {Function} callBack - 读取文件时的回调。 + */ + readFile(item : xFileSListType, size : number | null = null, callBack : null | callReadBackFun = null) : ByteArray { + let index = -1; + for (let i = 0; i < filelistAll.length; i++) { + let item2 = filelistAll[i] + if (item.id == item2.id) { + index = i; + break; + } + } + + if (index == -1) { + console.error("文件id不存在") + return new ByteArray((0).toInt()) + } + let file = filelistAll[index] + // 1024 + + let sizeBlock = size == null ? 1024 : size!; + let context = UTSAndroid.getAppContext() as Context + let cover = context.getContentResolver() as ContentResolver + let inputStream = cover.openInputStream(file.uri) + let byteArrayOutputStream = new ByteArrayOutputStream(); + // 文件的字节数组 + let buffer = new ByteArray(sizeBlock.toInt()); + let n = inputStream!.read(buffer) + + while (-1 != n) { + byteArrayOutputStream.write(buffer, 0, n); + if (callBack != null) { + let tempbuffer = new ByteArray(sizeBlock.toInt()); + byteArrayOutputStream.write(tempbuffer, 0, n); + callBack(tempbuffer)! + } + n = inputStream!.read(buffer) + } + let ar = byteArrayOutputStream.toByteArray() + try { + byteArrayOutputStream.flush() + } catch (e) { + byteArrayOutputStream.close() + } + return ar + } + /** + * 获取文件地址 + * @description 主要是用来你外部上传用,但记住这个内部会放到临时目录中,因此你的地址也是临时在用户中。 + * @returns {Promise} 返回文件地址 + */ + copyFileToPath(item : xFileSListType, path : string) : Promise { + // let index = -1; + // for(let i=0;i { + try { + let outputStream = new FileOutputStream(realfilepath) + outputStream.write(fileData); + outputStream.flush(); + uni.hideLoading() + file.realFilePath = realfilepath + file.cacheFilePath = filepath + res({ + name: file.name, + type: file.type, + id: file.id, + realFilePath: file.realFilePath, + cacheFilePath: file.cacheFilePath, + status: file.status, + size: file.size, + uri: file.uri + } as xFileSListType) + } catch (e) { + console.error(e) + uni.hideLoading() + uni.showToast({ title: "异常", icon: 'none' }) + rej("异常") + + } + + }) + + } + +} \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/app-harmony/config.json b/uni_modules/x-file-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..0eab5f0 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_file_s": "./lib/x_file_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/app-harmony/index.uts b/uni_modules/x-file-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..9fc6595 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/app-harmony/index.uts @@ -0,0 +1,92 @@ +import { x_xFileSNameTYpe, x_xFileSystem } from "x_file_s" +import { fileListType, xFileSListType } from "../interface" + +let HxFilesSytem : x_xFileSystem | null = null; +export class xFileSystem { + mimeTypeFilter : string[] = [] + filelist = [] as fileListType[] + multiple : boolean = true; + maxFileSize = 30 * 1024 * 1024; + constructor(typeFilter : string[] | null, tempmultiple : boolean | null, maxSize : number | null) { + if (typeFilter != null) { + let tms = typeFilter! as string[]; + this.mimeTypeFilter = tms; + } + if (tempmultiple != null) { + let tm = tempmultiple as boolean; + this.multiple = tm + } + if (maxSize != null) { + this.maxFileSize = maxSize! + } + + if (HxFilesSytem == null) { + HxFilesSytem = new x_xFileSystem(UTSHarmony.getCurrentWindow()!.getUIContext(), this.mimeTypeFilter, this.multiple, this.maxFileSize) + } else { + HxFilesSytem!.clear(); + } + } + destory() { + HxFilesSytem = null; + this.filelist = [] as fileListType[] + } + openDocument(callfun : (list : fileListType[]) => void) { + if (HxFilesSytem != null) { + HxFilesSytem!.openDocument((templist : x_xFileSNameTYpe[]) => { + let listfile = templist.map((el) : fileListType => { + return { + name: el.name, + type: el.type, + id: el.id, + uri: el.uri, + realFilePath: el.realFilePath, + cacheFilePath: el.cacheFilePath, + status: el.status, + size: el.fileSize + } as fileListType + }); + this.filelist = listfile + callfun(listfile) + }) + } + } + + /** + * 删除一个文件条目 + * @param {string} id - 文件id + * @returns {fileListType[]} 最新的文件列表 + */ + remove(id : string) : fileListType[] { + + const templist = HxFilesSytem!.remove(id) + + let listfile = templist.map((el) : fileListType => { + return { + name: el.name, + type: el.type, + id: el.id, + uri: el.uri, + realFilePath: el.realFilePath, + cacheFilePath: el.cacheFilePath, + status: el.status, + size: el.fileSize + } as fileListType + }); + this.filelist = listfile + + return listfile + } + + /** + * 返回一个空文件列表数组 + */ + clear() : fileListType[] { + this.filelist = [] as fileListType[]; + HxFilesSytem!.clear(); + return [] as fileListType[] + } + + copyFileToPath(item : xFileSListType, path : string) : Promise { + return Promise.resolve(item); + } +} \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/app-harmony/lib/x_file_s.har b/uni_modules/x-file-s/utssdk/app-harmony/lib/x_file_s.har new file mode 100644 index 0000000..82c434f Binary files /dev/null and b/uni_modules/x-file-s/utssdk/app-harmony/lib/x_file_s.har differ diff --git a/uni_modules/x-file-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-file-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-file-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-file-s/utssdk/app-ios/config.json b/uni_modules/x-file-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..dfb9a96 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "11" +} \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/app-ios/index.uts b/uni_modules/x-file-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..4f72279 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/app-ios/index.uts @@ -0,0 +1,197 @@ +import { xFileSListType,fileListType } from "../interface" +import { UIDocumentPickerViewController, UIDocumentPickerMode, UIDocumentPickerDelegate, UIViewController } from "UIKit" +import { URL, URLResourceKey, URLResourceValues, Data, FileManager } from "Foundation" +import { UTType } from "UniformTypeIdentifiers" +import Swift from "Swift" + +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} +let filelistAll = [] as fileListType[] +export class xFileSystem { + + mimeTypeFilter : string[] = [] + + filelist = [] as fileListType[] + multiple : boolean = true; + actionSeleCtedFiles : ActionsClass | null = null + maxFileSize = 30 * 1024 * 1024; + constructor(typeFilter : string[] | null, tempmultiple : boolean | null, maxSize : number | null) { + if (typeFilter != null) { + let tms = typeFilter! as string[]; + this.mimeTypeFilter = tms; + + } + if (tempmultiple != null) { + let tm = tempmultiple as boolean; + this.multiple = tm + } + if (maxSize != null) { + this.maxFileSize = maxSize! + } + } + destory(){ + + } + openDocument(callfun : (list : any) => void) { + let _this = this;; + DispatchQueue.main.async(execute = () : void => { + _this.actionSeleCtedFiles = new ActionsClass((files : URL[]) => { + let keysToFetch = new Swift.Set(); + keysToFetch.insert(URLResourceKey.totalFileAllocatedSizeKey) + // 获得当前用户的缓存目录路径主目录。 + let userDir = FileManager.default.urls(for = FileManager.SearchPathDirectory.cachesDirectory, in = FileManager.SearchPathDomainMask.userDomainMask).first! + + for (let item in files) { + let ditem = item; + + try { + let ds = UTSiOS.try(ditem.resourceValues(forKeys = keysToFetch), "?") + + if (ds != null) { + let fSize = ds?.totalFileAllocatedSize ?? 0 + let fName = ditem.lastPathComponent; + let fPath = ditem.absoluteString; + let fType = fName.substring((fName.lastIndexOf('.') + 1).toInt()) + let realFilePath = '' + let cacheFilePath = fPath + let status = 0 + let ifleid = getUid(1, 8); + let tempath = UTSiOS.getDataPath() as string + + let destinationFileName = ifleid + "." + fType + let destinationURL = userDir.appendingPathComponent(destinationFileName) + + let real = UTSiOS.try(FileManager.default.copyItem(at = ditem, to = destinationURL), "?"); + let itemobj = { + name: fName, + type: fType, + id: ifleid, + uri:"", + realFilePath: destinationFileName, + cacheFilePath: destinationFileName, + size: fSize, + status: fSize > _this.maxFileSize ? 4 : 0 + + } as fileListType; + + if(!_this.isInfilelist(itemobj)){ + + _this.filelist.push(itemobj) + filelistAll.push(itemobj) + } + + } + } catch (e) { + //TODO handle the exception + + } + } + + let list = [] as string[] + for (file in _this.filelist) { + list.push(JSON.stringify(file)!) + } + callfun(JSON.stringify(list)) + _this.filelist = [] as fileListType[] + + }) + try { + if (UTSiOS.available("iOS 14.0, *")) { + let filter : UTType[] = [] as UTType[]; + for (let i = 0; i < _this.mimeTypeFilter.length; i++) { + let contentType = new UTType(filenameExtension = _this.mimeTypeFilter[i]) + if (contentType != null) { + filter.push(new UTType(filenameExtension = _this.mimeTypeFilter[i])!) + } + } + if(filter.length==0){ + filter.push(UTType.item) + } + + let documentPickerController = new UIDocumentPickerViewController(forOpeningContentTypes = filter,asCopy = true) + documentPickerController.delegate = _this.actionSeleCtedFiles + documentPickerController.allowsMultipleSelection = _this.multiple // 是否允许选择多个文件 + UTSiOS.getCurrentViewController().present(documentPickerController, animated = true, completion = null) + } else { + let documentPickerController = new UIDocumentPickerViewController(documentTypes = ['public.data'], in = UIDocumentPickerMode.import) + documentPickerController.delegate = _this.actionSeleCtedFiles + documentPickerController.allowsMultipleSelection = _this.multiple // 是否允许选择多个文件 + UTSiOS.getCurrentViewController().present(documentPickerController, animated = true, completion = null) + } + + + } catch (e) { + console.error(e) + } + }) + + } + //读取文件 + copyFileToPath(item : xFileSListType, basedir : string) : string { + // let filepath = '' + // for (file in this.filelist) { + // if (file.id == id) { + // filepath = file.cacheFilePath + // break; + // } + // } + return item.cacheFilePath; + } + isInfilelist(file:fileListType):boolean{ + return filelistAll.some((el):boolean=>{ + return el.name==file.name&&el.type==file.type + }) + } + /** + * 返回一个空文件列表数组 + */ + clear():fileListType[]{ + filelistAll = [] as fileListType[]; + this.filelist = [] as fileListType[]; + return [] as fileListType[] + } + // ios不作删除自行管理缓存文件。 + remove(id : string) : fileListType[] { + let index = -1; + for(let i=0;i{ + return { + name:el.name, + type:el.type, + id:el.id, + uri:'', + realFilePath:el.realFilePath, + cacheFilePath:el.cacheFilePath, + size:el.size, + status:el.status + } as fileListType + }); + } +} + +@MainActor +class ActionsClass implements UIDocumentPickerDelegate { + callSuccessFiles = (files : URL[]) => { } + constructor(call : (files : URL[]) => void) { + super() + this.callSuccessFiles = call; + } + documentPicker(controller : UIDocumentPickerViewController, @argumentLabel("didPickDocumentsAt") urls : URL[]) { + + this.callSuccessFiles(urls) + } + documentPickerWasCancelled(controller : UIDocumentPickerViewController) { + console.log("User cancelled the document picker") + } +} \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/interface.uts b/uni_modules/x-file-s/utssdk/interface.uts new file mode 100644 index 0000000..dba6610 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/interface.uts @@ -0,0 +1,28 @@ +export type xFileSListType = { + name:string, + type:string, + id:string, + uri:string, + /** web平台文件对象 */ + file?:any, + /** 个人用户自定数据 */ + request?:any, + /** 安卓机/ios机下面的真实sd路径 */ + realFilePath:string, + /** uniapp应用协议文件路径,可用uni.getFileSystemManager进行删除或者查询到 */ + cacheFilePath:string, + /** 文件大小 */ + size?:number + /** + * 0等待,1失败,2成功,3上传中,4超过大小。 + */ + status?:0|1|2|3|4 +} + +// #ifndef MP +export type fileListType = xFileSListType +// #endif + +// #ifdef MP +export type fileListType = any +// #endif diff --git a/uni_modules/x-file-s/utssdk/mp-weixin/index.uts b/uni_modules/x-file-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..cce7fe5 --- /dev/null +++ b/uni_modules/x-file-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,123 @@ + +export { xFileSListType } from "../interface" +export type fileListType = any; + +type xFileSNameTYpe = { + name:string, + type:string, + uri:string, + id:string, + file:any, + size:number, + status:number +} +// type callReadBackFun = (byte:ByteArray)=>void + + + +/** + * 由于安卓隐私的问题。实际得到的所有文件 其实 都不是真实地址。因此你想要得到真实的地址,你就得复制到你的应用沙盒中。 + */ +export class xFileSystem { + mimeTypeFilter = [] as string[]; + filelist = [] as xFileSNameTYpe[] + inputDom:null|HTMLInputElement = null; + multiple:boolean = true; + maxFileSize:number = 30*1024*1024 + constructor(typeFilter:string|null,tempmultiple:boolean|null,maxSize:number|null){ + if(typeFilter!=null){ + + let filter : string[] = [] as string[]; + let tms = typeFilter! as string[] + for (let i = 0; i < tms.length; i++) { + filter.push("."+tms[i]) + } + if(filter.length==0){ + filter.push("*/*") + } + + this.mimeTypeFilter = filter + } + if(tempmultiple!=null){ + this.multiple = tempmultiple! + } + if(maxSize!=null){ + this.maxFileSize = maxSize! + } + } + isInfilelist(file:xFileSNameTYpe):boolean{ + return this.filelist.some((el):boolean=>{ + return el.name==file.name&&el.type==file.type + }) + } + destory(){ + + } + openDocument(call:(list:xFileSListType[])=>void){ + + let _this = this; + let filetype = this.mimeTypeFilter[0].split('/')[0] + if(filetype=='*'){ + filetype = 'all' + } + + wx.chooseMessageFile({ + count:100, + type:filetype, + success(result) { + let filelist = result.tempFiles + for(let i=0;i_this.maxFileSize?4:0, + } as xFileSNameTYpe + if(!_this.isInfilelist(fileitem)){ + _this.filelist.push(fileitem) + } + } + call(_this.filelist.map((el)=>{ + return { + name:el.name, + type:el.type, + id:el.id, + request:null, + realFilePath:el.file.path, + cacheFilePath:el.file.path, + size:el.size, + status:el.status + } + })) + }, + fail(er) { + console.error(er) + } + }) + } + /** + * 删除一个文件条目 + * @param {string} id - 文件id + * @returns {fileListType[]} 最新的文件列表 + */ + remove(id:string):xFileSListType[]{ + + return this.filelist.filter(el=>el.id!=id) + + } + /** + * 返回一个空文件列表数组 + */ + clear():xFileSListType[]{ + this.filelist = [] as xFileSNameTYpe[]; + return [] as xFileSListType[] + } + copyFileToPath(item:xFileSListType,path:string):Promise{ + return Promise.resolve(item) + } + +} \ No newline at end of file diff --git a/uni_modules/x-file-s/utssdk/unierror.uts b/uni_modules/x-file-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-file-s/utssdk/web/index.uts b/uni_modules/x-file-s/utssdk/web/index.uts new file mode 100644 index 0000000..7ec97de --- /dev/null +++ b/uni_modules/x-file-s/utssdk/web/index.uts @@ -0,0 +1,130 @@ + + +export { xFileSListType } from "../interface" + +export type fileListType = xFileSListType; + + +type xFileSNameTYpe = { + name:string, + type:string, + uri:string, + id:string, + file:any, + size:number, + status:number +} +// type callReadBackFun = (byte:ByteArray)=>void + + + +/** + * 由于安卓隐私的问题。实际得到的所有文件 其实 都不是真实地址。因此你想要得到真实的地址,你就得复制到你的应用沙盒中。 + */ +export class xFileSystem { + mimeTypeFilter = [] as string[]; + filelist = [] as xFileSNameTYpe[] + inputDom:null|HTMLInputElement = null; + multiple:boolean = true; + maxFileSize:number = 30*1024*1024 + constructor(typeFilter:string|null,tempmultiple:boolean|null,maxSize:number|null){ + if(typeFilter!=null){ + + let filter : string[] = [] as string[]; + let tms = typeFilter! as string[] + for (let i = 0; i < tms.length; i++) { + filter.push("."+tms[i]) + } + if(filter.length==0){ + filter.push("*/*") + } + + this.mimeTypeFilter = filter + } + if(tempmultiple!=null){ + this.multiple = tempmultiple! + } + if(maxSize!=null){ + this.maxFileSize = maxSize! + } + } + isInfilelist(file:xFileSNameTYpe):boolean{ + return this.filelist.some((el):boolean=>{ + return el.name==file.name&&el.type==file.type + }) + } + destory(){ + + } + openDocument(call:(list:fileListType[])=>void){ + if(this.inputDom!=null){ + this.inputDom!.remove() + } + let _this = this; + let inputdom = document.createElement("input") + inputdom.type = 'file'; + inputdom.accept = this.mimeTypeFilter.join(", "); + inputdom.style.setProperty('position','absolute') + inputdom.style.setProperty('left','-200%') + inputdom.style.setProperty('top','-200%') + inputdom.style.setProperty('opacity','0') + if(this.multiple){ + inputdom.multiple = "multiple" + } + inputdom.onchange = function(evt){ + let filelist = inputdom.files||[] as File[]; + for(let i=0;i_this.maxFileSize?4:0 + } as xFileSNameTYpe + if(!_this.isInfilelist(fileitem)){ + _this.filelist.push(fileitem) + } + + } + + call(_this.filelist.map((el)=>{ + return { + name:el.name, + type:el.type, + file:el.file, + id:el.id, + request:null, + realFilePath:"", + cacheFilePath:"", + size:el.size, + status:el.size>_this.maxFileSize?4:0 + } + })) + } + inputdom.click() + } + /** + * 删除一个文件条目 + * @param {string} id - 文件id + * @returns {fileListType[]} 最新的文件列表 + */ + remove(id:string):fileListType[]{ + return [] as fileListType[] + } + /** + * 返回一个空文件列表数组 + */ + clear():fileListType[]{ + this.filelist = [] as xFileSNameTYpe[]; + return [] as fileListType[] + } + copyFileToPath(item:fileListType,path:string):Promise{ + return Promise.resolve(item) + } + + +} \ No newline at end of file diff --git a/uni_modules/x-keyboardheightchange-s/changelog.md b/uni_modules/x-keyboardheightchange-s/changelog.md new file mode 100644 index 0000000..5bd4964 --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/changelog.md @@ -0,0 +1,12 @@ +## 1.0.0(2024-06-07) + +### 新增 +- 实现键盘高度实时监听核心功能 +- 添加安全区域高度自动计算逻辑 + +### 优化 +- 重构readme文档结构,增加使用示例章节 +- 完善TS类型声明文件 + +### 兼容 +- 支持Android/iOS双平台键盘监听 \ No newline at end of file diff --git a/uni_modules/x-keyboardheightchange-s/package.json b/uni_modules/x-keyboardheightchange-s/package.json new file mode 100644 index 0000000..a52c5ee --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-keyboardheightchange-s", + "displayName": "x-keyboardheightchange-s", + "version": "1.0.0", + "description": "x-keyboardheightchange-s", + "keywords": [ + "x-keyboardheightchange-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-keyboardheightchange-s/readme.md b/uni_modules/x-keyboardheightchange-s/readme.md new file mode 100644 index 0000000..e32afa9 --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/readme.md @@ -0,0 +1,71 @@ +# x-keyboardheightchange-s + +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +### 介绍 + +`x-keyboardheightchange-s` 是一个用于监听键盘高度变化的UTS插件,可以实时获取键盘弹出和收起时的高度变化,方便开发者处理键盘遮挡UI的问题。该插件会自动处理安全区域高度,返回实际可用的键盘高度值。 + +### 兼容性 + +| IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | +| 支持 | 支持 | x | x | + +### API 说明 + +#### keyboardHeightChange(callback) + +监听键盘高度变化,返回一个取消监听的函数。 + +**参数说明:** + +| 参数名 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| callback | Function | 是 | 键盘高度变化的回调函数,参数为键盘高度(单位px) | + +**返回值:** + +| 类型 | 说明 | +| --- | --- | +| Function | 取消监听的函数,调用此函数可以注销键盘高度监听 | + +### 使用示例 + +```typescript +// 引入模块 +import { keyboardHeightChange } from '@/uni_modules/x-keyboardheightchange-s/utssdk'; + +// 注册键盘高度监听 +const cancelKeyboardListener = keyboardHeightChange((height: number) => { + console.log('当前键盘高度:', height); + + // 键盘弹出 + if (height > 0) { + // 处理键盘弹出逻辑 + } + // 键盘收起 + else { + // 处理键盘收起逻辑 + } +}); + +// 在组件销毁时注销监听 +onUnload(() => { + // 调用返回的函数取消监听 + cancelKeyboardListener(); +}); +``` + +### 注意事项 + +1. 该插件已自动处理安全区域高度,返回的高度值已减去底部安全区域高度 +2. iOS平台使用系统通知监听键盘高度变化 +3. Android平台通过原生方法监听键盘高度变化 +4. 只有当键盘高度发生变化时才会触发回调 +5. 键盘收起时,回调函数的参数为0 +6. 请务必在组件销毁时调用返回的取消函数,避免内存泄漏 + + diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/app-android/config.json b/uni_modules/x-keyboardheightchange-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/app-android/index.uts b/uni_modules/x-keyboardheightchange-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..ca93210 --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/utssdk/app-android/index.uts @@ -0,0 +1,15 @@ + +import keyboardHeightChangeByKt from 'uts.sdk.modules.utsXKeyboardheightchangeS.keyboardHeightChangeByKt'; + + +// 监听键盘高度变化 +@UTSJS.keepAlive +export const keyboardHeightChange = (callback : (h : number) => void):()=>void => { + const cancelFun = keyboardHeightChangeByKt(UTSAndroid.getUniActivity()!,(keyboardHeight:Int)=>{ + callback(UTSAndroid.devicePX2px(keyboardHeight)) + }); + const cancel = ()=>{ + cancelFun() + }; + return cancel; +} diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/app-android/keyboardHeightChange.kt b/uni_modules/x-keyboardheightchange-s/utssdk/app-android/keyboardHeightChange.kt new file mode 100644 index 0000000..8c723b8 --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/utssdk/app-android/keyboardHeightChange.kt @@ -0,0 +1,88 @@ +package uts.sdk.modules.utsXKeyboardheightchangeS +import android.app.Activity +import android.graphics.Rect +import android.os.Build +import android.view.View +import android.view.ViewTreeObserver +import android.view.WindowInsets + +typealias cacelCallBack = () -> Unit + +fun keyboardHeightChangeByKt(activity: Activity, callback: (height: Int) -> Unit): cacelCallBack { + val rootView = activity.window.decorView.rootView + val rect = Rect() + var lastHeight = 0 + + val listener = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // Android 11及以上使用WindowInsets API + View.OnApplyWindowInsetsListener { _, insets -> + val imeHeight = insets.getInsets(WindowInsets.Type.ime()).bottom + val navigationBarHeight = insets.getInsets(WindowInsets.Type.navigationBars()).bottom + val keyboardHeight = if (imeHeight > 0) imeHeight - navigationBarHeight else 0 + + if (keyboardHeight != lastHeight) { + lastHeight = keyboardHeight + callback(keyboardHeight) + } + insets + } + } else { + // Android 5.0 - Android 10使用传统方法 + ViewTreeObserver.OnGlobalLayoutListener { + rootView.getWindowVisibleDisplayFrame(rect) + val screenHeight = rootView.height + val keyboardHeight = screenHeight - rect.bottom + + // 考虑导航栏高度 + val navigationBarHeight = getNavigationBarHeight(activity) + + val actualKeyboardHeight = if (keyboardHeight > navigationBarHeight) { + keyboardHeight - navigationBarHeight + } else 0 + + if (actualKeyboardHeight != lastHeight) { + lastHeight = actualKeyboardHeight + callback(actualKeyboardHeight) + } + } + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + rootView.setOnApplyWindowInsetsListener(listener as View.OnApplyWindowInsetsListener) + } else { + rootView.viewTreeObserver.addOnGlobalLayoutListener(listener as ViewTreeObserver.OnGlobalLayoutListener) + } + + return { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + rootView.setOnApplyWindowInsetsListener(null) + } else { + rootView.viewTreeObserver.removeOnGlobalLayoutListener(listener as ViewTreeObserver.OnGlobalLayoutListener) + } + } +} + +// 添加原生方法检测导航栏高度 +private fun getNavigationBarHeight(activity: Activity): Int { + val resources = activity.resources + val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") + return if (resourceId > 0 && hasNavigationBar(activity)) { + resources.getDimensionPixelSize(resourceId) + } else 0 +} + +// 检测设备是否有导航栏 +private fun hasNavigationBar(activity: Activity): Boolean { + val windowManager = activity.windowManager + val d = windowManager.defaultDisplay + + val realDisplayMetrics = android.util.DisplayMetrics() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + d.getRealMetrics(realDisplayMetrics) + } + + val displayMetrics = android.util.DisplayMetrics() + d.getMetrics(displayMetrics) + + return realDisplayMetrics.heightPixels > displayMetrics.heightPixels +} \ No newline at end of file diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/app-ios/config.json b/uni_modules/x-keyboardheightchange-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/app-ios/index.uts b/uni_modules/x-keyboardheightchange-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..0c1b91f --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/utssdk/app-ios/index.uts @@ -0,0 +1,53 @@ +import { NotificationCenter, OperationQueue, Notification } from "Foundation"; +import { UIResponder } from "UIKit"; +import { CGRect } from "CoreFoundation"; + +// 监听键盘高度变化 +@UTSJS.keepAlive +export function keyboardHeightChange(callback : (h : number) => void):()=>void { + let lastHeight = 0 + const showObserver = NotificationCenter.default.addObserver( + forName = UIResponder.keyboardWillShowNotification, + object= null, + queue= OperationQueue.main, + using = (notification:Notification)=>{ + if(notification==null) return; + let keyboardFrame = notification.userInfo?.get(UIResponder.keyboardFrameEndUserInfoKey) as CGRect|null + if(keyboardFrame==null) return; + const keyGrect = keyboardFrame! as CGRect; + let keyboardheight = keyGrect.height + + // 计算实际键盘高度(减去安全区域) + let actualKeyboardHeight = Math.max(0, Number(keyboardheight) - uni.getWindowInfo().safeAreaInsets.bottom) + // 只有当高度变化时才回调 + if(actualKeyboardHeight != lastHeight) { + lastHeight = actualKeyboardHeight + DispatchQueue.main.async(execute = () : void => { + callback(actualKeyboardHeight) + }) + } + + + } + ) + + const hideObserver = NotificationCenter.default.addObserver( + forName = UIResponder.keyboardWillHideNotification, + object= null, + queue= OperationQueue.main, + using = (_:Foundation.Notification)=>{ + if(lastHeight != 0) { + lastHeight = 0 + DispatchQueue.main.async(execute = () : void => { + callback(0) + }) + } + } + ) + const cancel = ()=>{ + NotificationCenter.default.removeObserver(showObserver) + NotificationCenter.default.removeObserver(hideObserver) + }; + return cancel + +} \ No newline at end of file diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/interface.uts b/uni_modules/x-keyboardheightchange-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/mp-weixin/index.uts b/uni_modules/x-keyboardheightchange-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..d245ef3 --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,10 @@ +type cacelCall = () => void; +export const keyboardHeightChange = (callback : (h : number) => void) : cacelCall => { + const fun = (result) => { + callback(result.height) + } + wx.onKeyboardHeightChange(fun) + return () => { + wx.offKeyboardHeightChange(fun) + } +} \ No newline at end of file diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/unierror.uts b/uni_modules/x-keyboardheightchange-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-keyboardheightchange-s/utssdk/web/index.uts b/uni_modules/x-keyboardheightchange-s/utssdk/web/index.uts new file mode 100644 index 0000000..9672a8f --- /dev/null +++ b/uni_modules/x-keyboardheightchange-s/utssdk/web/index.uts @@ -0,0 +1,9 @@ +type cacelCall = () => void; +export const keyboardHeightChange = (callback : (h : number) => void) : cacelCall => { + + + + return () => { + + } +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/changelog.md b/uni_modules/x-loading-s/changelog.md new file mode 100644 index 0000000..77b7a0e --- /dev/null +++ b/uni_modules/x-loading-s/changelog.md @@ -0,0 +1,12 @@ +## 1.0.6(2025-08-17) +* 兼容原生鸿蒙 +## 1.0.3(2025-04-13) +* 安卓端修改了布局结构现会覆盖官方的dialog-page了并且会自动隐藏状态栏,并可以覆盖底部安全区域 +## 1.0.2(2025-02-23) +* 安卓添加了显示背景遮罩动画,及关闭遮罩动画 +* ios添加了显示背景遮罩动画,及关闭遮罩动画 +* 上述添加后,不管是显示和关闭都更加的自然 +## 1.0.1(2024-09-06) +* 更新支持Uniapp +## 1.0.0(2024-08-06) +安卓,ios,web可用。 diff --git a/uni_modules/x-loading-s/loading.png b/uni_modules/x-loading-s/loading.png new file mode 100644 index 0000000..544641c Binary files /dev/null and b/uni_modules/x-loading-s/loading.png differ diff --git a/uni_modules/x-loading-s/package.json b/uni_modules/x-loading-s/package.json new file mode 100644 index 0000000..b103817 --- /dev/null +++ b/uni_modules/x-loading-s/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-loading-s", + "displayName": "全屏加载,可覆盖系统界面任意位置调用", + "version": "1.0.6", + "description": "平替官方uni.showLoading", + "keywords": [ + "uts,tmui,uappx,原生插件" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "1.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/readme.md b/uni_modules/x-loading-s/readme.md new file mode 100644 index 0000000..4fbcadb --- /dev/null +++ b/uni_modules/x-loading-s/readme.md @@ -0,0 +1,77 @@ +# x-loading-s + +### 特性说明 + +主要是用来代替uni.showLoading的,相比优化有: + +1. 高自动适应,因此可以添加超长的title文字。 +2. 图标可以任意更新,大小,颜色等 +3. 可以添加title标题,允许改变字号,颜色 +4. 支持渐隐动画效果,包括遮罩层渐入和内容缩放 +5. 遮罩层会阻止点击穿透,保护底层内容 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 开发文档 + +**浏览器端需要你把目录中的```remixicon.ttf```复制到static目录下** + +调用: +```ts +import { showLoading, hideXloading, XLOADINGS_TYPE } from "@/uni_modules/x-loading-s" +// 显示,字段参数全是可选的 +showLoading({} as XLOADINGS_TYPE) +// 或者,null使用默认值 +showLoading(null) +// 隐藏 +hideXloading() + +``` + +参数配置: + +下面的图标iconCode,同组件库x-icon是相同的字体图标,请打开图标网站:[查看](https://remixicon.com/) +找到直接想要的图标后 复制 unicode ,不是名称。比如:我们只要取ED29 +下面的参数图标iconCode就是ED29 **iconCode:'ED29'** + +**XLOADINGS_TYPE** +```ts +// 所有参数都是可选的 +export type XLOADINGS_TYPE = { + // 图标颜色,默认:#2979ff + iconColor?:string, + // 内容背景色,默认:#fff + contentBgColor?:string, + // 遮罩层背景色,默认:rgba(0,0,0,0.3) + maskBgColor?:string, + // 图标大小,默认:42 + iconSize?:number, + // 图标编码,默认:ED29 + iconCode?:string, + // 提示文字 + title?:string, + // 文字大小,默认:28 + titleSize?:number, + // 文字颜色,默认:#333 + titleColor?:string, + // 约定的宽,最小高值100,宽100,默认:220 + size?:number, +} +``` + +### 显示和隐藏时机 + +- 组件会在页面ready后显示 +- 页面卸载时会自动隐藏 +- 可以通过hideXloading()手动隐藏 + +### 动画效果 + +- 显示时有300ms的渐入动画 +- 遮罩层透明度从0到1渐变 +- 内容区域有缩放和透明度渐变效果 +- 加载图标有持续旋转动画 \ No newline at end of file diff --git a/uni_modules/x-loading-s/remixicon.ttf b/uni_modules/x-loading-s/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-loading-s/remixicon.ttf differ diff --git a/uni_modules/x-loading-s/utssdk/app-android/assets/remixicon.ttf b/uni_modules/x-loading-s/utssdk/app-android/assets/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-loading-s/utssdk/app-android/assets/remixicon.ttf differ diff --git a/uni_modules/x-loading-s/utssdk/app-android/config.json b/uni_modules/x-loading-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/app-android/index.uts b/uni_modules/x-loading-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..7a89e9d --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-android/index.uts @@ -0,0 +1,276 @@ +import LinearLayout from 'android.widget.LinearLayout'; +import Context from 'android.content.Context' +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import { XLOADINGS_TYPE, XLOADINGS_TYPE_PRIVATE } from "../interface.uts" +import Color from 'android.graphics.Color'; +import Gravity from 'android.view.Gravity'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable'; +import TextView from 'android.widget.TextView'; +import Typeface from 'android.graphics.Typeface'; +import TextUtils from 'android.text.TextUtils'; +import Uri from 'android.net.Uri'; +import ObjectAnimator from 'android.animation.ObjectAnimator'; +import ValueAnimator from 'android.animation.ValueAnimator'; +import TimeInterpolator from 'android.animation.TimeInterpolator'; +import MotionEvent from 'android.view.MotionEvent'; +import { hexToRgb } from "../libs/color.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; +import AccelerateDecelerateInterpolator from 'android.view.animation.AccelerateDecelerateInterpolator'; +// #ifdef UNI-APP-X +import getCurrentPages from 'io.dcloud.uniapp.framework.getCurrentPages'; +import onReady from 'io.dcloud.uniapp.framework.onReady'; +import onUnload from 'io.dcloud.uniapp.framework.onUnload'; +import onShow from 'io.dcloud.uniapp.framework.onShow'; +// #endif + +import AttributeSet from 'android.util.AttributeSet'; +import R from 'android.R'; +import Bundle from "android.os.Bundle"; +import Dialog from "android.app.Dialog"; +import WindowManager from "android.view.WindowManager"; +import Window from "android.view.Window"; +import ColorDrawable from "android.graphics.drawable.ColorDrawable"; +let rotationAnimator:ObjectAnimator|null = null; +let maskDomId = 5894 +function px2dp(n : number) : number { + + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + + return mets.density * n +} +function setSpin(textView : TextView) { + try { + textView.clearAnimation(); + } catch (e) { + //TODO handle the exception + } + let rotationStart = 0 + let rotation = 360 + let rotationSFD = 0.5 + if(rotationAnimator!=null){ + rotationAnimator!.cancel() + } + rotationAnimator = ObjectAnimator.ofFloat(textView, "rotation", rotationStart.toFloat(), rotation.toFloat()); + if(rotationAnimator==null) return; + rotationAnimator!.setDuration(1000); + class LinearInterpolator implements TimeInterpolator { + override getInterpolation(input : Float) : Float { + return input; + } + } + rotationAnimator!.setInterpolator(new LinearInterpolator()); + rotationAnimator!.setRepeatCount(ValueAnimator.INFINITE); + rotationAnimator!.start(); +} +let dialogModal : FullScreenDialogFragment | null = null; +class FullScreenDialogFragment extends Dialog { + private mContext : Context; + private opts : XLOADINGS_TYPE|null = null; + private maskeDom:RelativeLayout|null = null; + constructor(context : Context, optsOwer : XLOADINGS_TYPE|null) { + super(context,R.style.Theme_Translucent_NoTitleBar_Fullscreen); + this.mContext = context; + this.opts = optsOwer + } + override onCreate(savedInstanceState ?: Bundle) { + super.onCreate(savedInstanceState) + this.requestWindowFeature(Window.FEATURE_NO_TITLE) + // 禁止按键返回及侧滑返回. + this.setCancelable(false) + this.maskeDom = _createToastView(this.getContext(),this.window!.decorView! as ViewGroup,this.opts) + // 设置窗口属性 + let window = this.getWindow(); + if (window != null) { + // 首先设置全屏标志 + window.setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN + ); + + // 设置布局参数为全屏 + window.setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT + ); + + // 设置背景透明 + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + + window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + window.setGravity(Gravity.CENTER); + + // 完整的沉浸式设置 + let decorView = window.getDecorView(); + let option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + decorView.setSystemUiVisibility(option); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + window.setStatusBarColor(Color.TRANSPARENT) + window.setNavigationBarColor(Color.TRANSPARENT) + window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) + } + + } + override dismiss(){ + super.dismiss() + this.maskeDom = null; + dialogModal = null; + } + +} + + +export function hideXloading() { + UTSAndroid.getDispatcher("main").async(function (_) { + dialogModal?.dismiss() + dialogModal = null; + rotationAnimator?.cancel() + rotationAnimator = null; + }) +} + +function _createToastView(context : Context, decorView : ViewGroup, opts : XLOADINGS_TYPE|null):RelativeLayout{ + + let realopts = opts == null ? ({} as XLOADINGS_TYPE) : (opts!) + let config = configCover(realopts) + let rmbgColor = hexToRgb(config.maskBgColor); + let textColor = hexToRgb(config.iconColor); + let wrapColor = hexToRgb(config.contentBgColor); + let titleColorRgb = hexToRgb(config.titleColor); + + let mbgColor = rmbgColor == null ? Color.parseColor(config.maskBgColor) : Color.argb((rmbgColor!.a * 255).toInt(), rmbgColor!.r.toInt(), rmbgColor!.g.toInt(), rmbgColor!.b.toInt()) + let fontColor = textColor == null ? Color.parseColor(config.iconColor) : Color.argb((textColor!.a * 255).toInt(), textColor!.r.toInt(), textColor!.g.toInt(), textColor!.b.toInt()) + let contentColor = rmbgColor == null ? Color.parseColor(config.contentBgColor) : Color.argb((wrapColor!.a * 255).toInt(), wrapColor!.r.toInt(), wrapColor!.g.toInt(), wrapColor!.b.toInt()) + let titleColor = titleColorRgb == null ? Color.parseColor(config.titleColor) : Color.argb((titleColorRgb!.a * 255).toInt(), titleColorRgb!.r.toInt(), titleColorRgb!.g.toInt(), titleColorRgb!.b.toInt()) + + let maskerDom = new RelativeLayout(context) + + class MaskerDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + // 阻止事件向下传递。 + return true; + } + } + maskerDom.setAlpha((0).toFloat()) + maskerDom.setOnTouchListener(new MaskerDomClickListsner()) + + let maskerDomLayrPrams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + maskerDom.setLayoutParams(maskerDomLayrPrams) + maskerDom.setBackgroundColor(mbgColor) + + + maskerDom.setGravity(Gravity.CENTER) + maskerDom.setId((maskDomId).toInt()) + let contentWrapDiv = new LinearLayout(context); + // 设置圆角背景 + let bg = new GradientDrawable() + bg.setColor(contentColor) + bg.setCornerRadius((px2dp(16)).toFloat()) + contentWrapDiv.setBackground(bg) + // contentWrapDiv.setBackgroundColor(Color.parseColor(config.contentBgColor)) + let wpx = px2dp(config.size).toInt(); + let contentLays = new LinearLayout.LayoutParams(wpx,ViewGroup.LayoutParams.WRAP_CONTENT); + + contentWrapDiv.setLayoutParams(contentLays) + contentWrapDiv.setMinimumHeight(wpx) + let wpadingx = px2dp(16).toInt(); + contentWrapDiv.setPadding(wpadingx, wpadingx, wpadingx, wpadingx) + contentWrapDiv.setGravity(Gravity.CENTER) + contentWrapDiv.setOrientation(LinearLayout.VERTICAL) + + // 创建图标。 + let iconDiv = new TextView(context) + // iconDiv.setLineHeight(1) + iconDiv.setTextColor(fontColor) + let assetManager = context!.getAssets(); + let typeface = Typeface.createFromAsset(assetManager, "remixicon.ttf") + iconDiv.setTypeface(typeface) + iconDiv.setGravity(Gravity.CENTER) + iconDiv.setTextSize(config.iconSize.toFloat()) + if (!TextUtils.isEmpty(config.iconCode)) { + let codePoint = Integer.parseInt(config.iconCode, 16); + let charArray = Character.toChars(codePoint); + let text = new String(charArray); + iconDiv.setText(text); + } + setSpin(iconDiv) + + + + + contentWrapDiv.addView(iconDiv) + + if (config.title != "") { + // 添加一个title + let titleDiv = new TextView(context) + titleDiv.setText(config.title) + titleDiv.setTextSize((config.titleSize).toFloat()) + titleDiv.setTextColor(titleColor) + titleDiv.setGravity(Gravity.CENTER) + contentWrapDiv.addView(titleDiv) + } + + maskerDom.addView(contentWrapDiv) + + decorView.addView(maskerDom!) + + try { + let s0 = (0).toFloat() + let s1 = (1).toFloat() + contentWrapDiv.setAlpha(s0) + contentWrapDiv.setScaleX(s0) + contentWrapDiv.setScaleY(s0) + + // 遮罩渐变 + const maskAni = maskerDom.animate() as ViewPropertyAnimator; + maskAni.alpha(s1) + .setDuration(300) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + + let ani = contentWrapDiv.animate() as ViewPropertyAnimator; + ani.alpha(s1) + .scaleX(s1) + .scaleY(s1) + .setDuration(300) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + } catch (e) { + //TODO handle the exception + } + + return maskerDom; +} +function _showLoading_(opts : XLOADINGS_TYPE | null) { + dialogModal = new FullScreenDialogFragment(UTSAndroid.getUniActivity()!,opts) + UTSAndroid.getDispatcher("main").async(function (_) { + dialogModal?.show() + }) +} + +export function showLoading(opts : XLOADINGS_TYPE | null) { + dialogModal?.dismiss() + const pages = getCurrentPages(); + if (pages.length > 0) { + const page = pages[pages.length - 1].vm! + const instance = page.$ + if (page.$isReady) { + _showLoading_(opts) + } else { + hideXloading() + } + onUnload(() => { + hideXloading() + }, instance) + }else{ + _showLoading_(opts) + } +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/app-harmony/config.json b/uni_modules/x-loading-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..e4ee153 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_loading_s": "./lib/x_loading_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/app-harmony/index.uts b/uni_modules/x-loading-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..9650c9d --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-harmony/index.uts @@ -0,0 +1,14 @@ +import { XLOADINGS_TYPE, XLOADINGS_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { hexToRgb } from "../libs/color.uts" +import { xshowLoadings,xhidesloadings } from "x_loading_s"; + + + +export const hideXloading = () => { + xhidesloadings(UTSHarmony.getCurrentWindow()!.getUIContext()) +} +export function showLoading(opts : XLOADINGS_TYPE|null) { + let config = configCover(opts==null ? ({} as XLOADINGS_TYPE) : (opts!)) + xshowLoadings(UTSHarmony.getCurrentWindow()!.getUIContext(),config) +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/app-harmony/lib/x_loading_s.har b/uni_modules/x-loading-s/utssdk/app-harmony/lib/x_loading_s.har new file mode 100644 index 0000000..6ce99be Binary files /dev/null and b/uni_modules/x-loading-s/utssdk/app-harmony/lib/x_loading_s.har differ diff --git a/uni_modules/x-loading-s/utssdk/app-ios/Info.plist b/uni_modules/x-loading-s/utssdk/app-ios/Info.plist new file mode 100644 index 0000000..1dd21fc --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-ios/Info.plist @@ -0,0 +1,10 @@ + + + + + UIAppFonts + + remixicon.ttf + + + \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-loading-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-loading-s/utssdk/app-ios/Resources/remixiconModal.ttf b/uni_modules/x-loading-s/utssdk/app-ios/Resources/remixiconModal.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-loading-s/utssdk/app-ios/Resources/remixiconModal.ttf differ diff --git a/uni_modules/x-loading-s/utssdk/app-ios/config.json b/uni_modules/x-loading-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-loading-s/utssdk/app-ios/index.uts b/uni_modules/x-loading-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..dbb7ef8 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/app-ios/index.uts @@ -0,0 +1,143 @@ +import { XLOADINGS_TYPE, XLOADINGS_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { UIView, UIViewController, NSLayoutConstraint, UITextView, UIFont, UILabel, NSTextAlignment, NSLineBreakMode } from 'UIKit'; +import { CGRect, CGPoint, CGFloat, CGSize, CFDictionary } from 'CoreFoundation'; +import { CGSizeMake } from 'CoreGraphics'; +import { Alignment } from 'SwiftUI'; +import { UInt32, KeyPath } from 'Swift'; +import { NSString } from 'Foundation'; +import { CABasicAnimation, CAMediaTimingFunction, CAMediaTimingFunctionName } from 'QuartzCore'; + +let maskerDom : null | UIView = null; + + +export function showLoading(opts : XLOADINGS_TYPE | null) { + DispatchQueue.main.async(execute = () : void => { + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + } + let parent = UTSiOS.getCurrentViewController() as UIViewController; + let parentView = parent.view as UIView + + let realopts = opts == null ? ({} as XLOADINGS_TYPE) : (opts!) + let config = configCover(realopts) + + maskerDom = new UIView() + + if (maskerDom == null) return; + let cg = parentView.frame as CGRect + maskerDom!.frame = cg + maskerDom!.backgroundColor = UTSiOS.colorWithString(config.maskBgColor) + + let contetDiv = new UIView(); + contetDiv.layer.cornerRadius = 16 + contetDiv.layer.masksToBounds = true; + contetDiv.backgroundColor = UTSiOS.colorWithString(config.contentBgColor) + + // contetDiv.frame = new CGRect(x = 0, y = 0, width = 100, height = 100) + // contetDiv.center = new CGPoint(x = (cg.size.width) / 2, y = (cg.size.height) / 2) + + let textView = new UILabel() + textView.frame = new CGRect(x = 0, y = 0, width = config.iconSize.toInt(), height = config.iconSize.toInt()) + textView.font = new UIFont(name = "remixicon", size = new CGFloat(config.iconSize)) + + let codePoint = new UInt32(config.iconCode, radix = 16) + let stricon = new NSString(format = "%C", codePoint!) + + textView.text = new String(stricon); + textView.textColor = UTSiOS.colorWithString(config.iconColor) + textView.textAlignment = NSTextAlignment.center + + + + // 添加动画图标旋转 + let spinAni = new CABasicAnimation(keyPath = "transform.rotation") + spinAni.fromValue = 0 + spinAni.toValue = 2 * CGFloat.pi + spinAni.duration = 1.1 + spinAni.repeatCount = HUGE + textView.layer.add(spinAni, forKey = "rotationAnimation") + // 添加内容缩放动画 + let scaleAni = new CABasicAnimation(keyPath = "transform.scale") + scaleAni.fromValue = 0 + scaleAni.toValue = 1 + scaleAni.duration = 0.3 + scaleAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + contetDiv.layer.add(scaleAni, forKey = "scaleAnimation") + + let opacityAni = new CABasicAnimation(keyPath = "opacity") + opacityAni.fromValue = 0 + opacityAni.toValue = 1 + opacityAni.duration = 0.3 + opacityAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + + maskerDom!.layer.add(opacityAni, forKey = "opacityAnimation") + + + + if (config.title != "") { + textView.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(textView) + + NSLayoutConstraint.activate([ + // 顶部约束 + textView.topAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.topAnchor, constant = 16), + // textView.bottomAnchor.constraint(equalTo= contetDiv.safeAreaLayoutGuide.bottomAnchor,constant=-16), + // 左侧约束 + textView.leadingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.leadingAnchor, constant = 16), + // 右侧约束 + textView.trailingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.trailingAnchor, constant = -16) + ]) + } else { + textView.center = new CGPoint(x = 50, y = 50) + contetDiv.addSubview(textView) + } + + + // 设置标题 + if (config.title != "") { + let titleView = new UILabel() + titleView.text = new String(config.title); + titleView.textAlignment = NSTextAlignment.center + titleView.lineBreakMode = NSLineBreakMode.byWordWrapping + titleView.numberOfLines = 0 + titleView.font = UIFont.systemFont(ofSize = new CGFloat(config.titleSize)) + titleView.textColor = UTSiOS.colorWithString(config.titleColor) + titleView.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(titleView) + NSLayoutConstraint.activate([ + // 顶部约束 + titleView.topAnchor.constraint(equalTo = textView.safeAreaLayoutGuide.bottomAnchor, constant = 1), + titleView.bottomAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.bottomAnchor, constant = -16), + // 左侧约束 + titleView.leadingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.leadingAnchor, constant = 16), + // 右侧约束 + titleView.trailingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.trailingAnchor, constant = -16) + ]) + + } + + contetDiv.translatesAutoresizingMaskIntoConstraints = false + maskerDom!.addSubview(contetDiv) + NSLayoutConstraint.activate([ + // 中心约束 + contetDiv.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + contetDiv.centerYAnchor.constraint(equalTo = maskerDom!.centerYAnchor), + // 宽约束100 + contetDiv.widthAnchor.constraint(equalToConstant = config.size.toDouble()), + // 高为至少100 + contetDiv.heightAnchor.constraint(greaterThanOrEqualToConstant = config.size.toDouble()) + ]) + + parentView.addSubview(maskerDom!) + + }) +} + +export function hideXloading() { + DispatchQueue.main.async(execute = () : void => { + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + } + }) +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/interface.uts b/uni_modules/x-loading-s/utssdk/interface.uts new file mode 100644 index 0000000..77f5a47 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/interface.uts @@ -0,0 +1,22 @@ +export type XLOADINGS_TYPE = { + iconColor?:string, + contentBgColor?:string, + maskBgColor?:string, + iconSize?:number, + iconCode?:string, + title?:string, + titleSize?:number, + titleColor?:string, + size?:number +} +export type XLOADINGS_TYPE_PRIVATE = { + iconColor:string, + contentBgColor:string, + maskBgColor:string, + iconSize:number, + iconCode:string, + title:string, + titleSize:number, + titleColor:string, + size:number +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/libs/color.uts b/uni_modules/x-loading-s/utssdk/libs/color.uts new file mode 100644 index 0000000..f27f07e --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/libs/color.uts @@ -0,0 +1,58 @@ +type RGBA = { r : number, g : number, b : number, a : number } +export function hexToRgb(sColors : string) : RGBA | null { + if (sColors == "") { + return null + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + let p : number[] = arr.map((val : string) : number => parseInt(val)); + + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + p.add(1) + + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: arr.length==3?p[3]:parseFloat(arr[3]) + } as RGBA + } + + return null; +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/libs/config.uts b/uni_modules/x-loading-s/utssdk/libs/config.uts new file mode 100644 index 0000000..fcf3305 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/libs/config.uts @@ -0,0 +1,33 @@ +import { XLOADINGS_TYPE, XLOADINGS_TYPE_PRIVATE } from "../interface.uts" +export const defaultConfig = { + iconColor:'rgb(5,121,255)', + contentBgColor:'rgba(255,255,255,1)', + maskBgColor:'rgba(0,0,0,0.6)', + iconSize:36, + iconCode:'EEC4', + title:'', + titleSize:12, + titleColor:'#a0a1a7', + size:100 +} as XLOADINGS_TYPE_PRIVATE + +export function configCover(opts : XLOADINGS_TYPE) : XLOADINGS_TYPE_PRIVATE { + let iconColor = opts.iconColor != null ? (opts.iconColor!) : defaultConfig.iconColor; + let contentBgColor = opts.contentBgColor != null ? (opts.contentBgColor!) : defaultConfig.contentBgColor; + let maskBgColor = opts.maskBgColor != null ? (opts.maskBgColor!) : defaultConfig.maskBgColor; + let iconSize = opts.iconSize != null ? (opts.iconSize!) : defaultConfig.iconSize; + let iconCode = opts.iconCode != null ? (opts.iconCode!) : defaultConfig.iconCode; + let title = opts.title != null ? (opts.title!) : defaultConfig.title; + let titleSize = opts.titleSize != null ? (opts.titleSize!) : defaultConfig.titleSize; + let titleColor = opts.titleColor != null ? (opts.titleColor!) : defaultConfig.titleColor; + let size = opts.size != null ? (opts.size!) : defaultConfig.size; + + return { + iconColor, + contentBgColor, + maskBgColor, + iconSize, + iconCode,title,titleSize,titleColor,size + } as XLOADINGS_TYPE_PRIVATE +} + diff --git a/uni_modules/x-loading-s/utssdk/mp-weixin/index.uts b/uni_modules/x-loading-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..e797073 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,13 @@ +import {defaultConfig,configCover} from "../libs/config.uts" +export {XLOADINGS_TYPE,XLOADINGS_TYPE_PRIVATE} from "../interface.uts" +export const showLoading = (opts : XLOADINGS_TYPE|null) => { + let realopts = opts==null?({} as XLOADINGS_TYPE):(opts!) + let config = configCover(realopts) + wx.showLoading({ + title:opts?.title??"...", + mask:true + }) +} +export const hideXloading = ()=>{ + wx.hideLoading() +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/web/index.uts b/uni_modules/x-loading-s/utssdk/web/index.uts new file mode 100644 index 0000000..4cb61f2 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/web/index.uts @@ -0,0 +1,112 @@ +export {XLOADINGS_TYPE,XLOADINGS_TYPE_PRIVATE} from "../interface.uts" +import {defaultConfig,configCover} from "../libs/config.uts" +import { LoadFontFace } from "./loadFont.uts" +let maskerDom : null | HTMLDivElement = null; + + + +// @ts-ignore +export const showLoading = (opts : XLOADINGS_TYPE|null) => { + LoadFontFace() + if (maskerDom != null) { + maskerDom.remove() + } + // @ts-ignore + let realopts = opts==null?({} as XLOADINGS_TYPE):(opts!) + let config = configCover(realopts) + + maskerDom = document.createElement("div") + if (maskerDom == null) return; + maskerDom.style.setProperty("background-color", config.maskBgColor) + maskerDom.style.setProperty("position", "fixed") + maskerDom.style.setProperty("left", "0px") + maskerDom.style.setProperty("top", "0px") + maskerDom.style.setProperty("width", "100%") + maskerDom.style.setProperty("height", "100%") + maskerDom.style.display = "flex" + maskerDom.style.flexDirection = "row" + maskerDom.style.justifyContent = "center" + maskerDom.style.alignItems = "center" + maskerDom.style.zIndex = "10000" + + let contentWrapDiv = document.createElement("div") + contentWrapDiv.style.padding = "16px" + contentWrapDiv.style.width = config.size+"px" + // contentWrapDiv.style.height = "100px" + contentWrapDiv.style.minHeight = config.size+"px" + contentWrapDiv.style.backgroundColor = config.contentBgColor + contentWrapDiv.style.borderRadius = "16px" + contentWrapDiv.style.boxSizing = "border-box" + contentWrapDiv.style.display = "flex" + contentWrapDiv.style.flexDirection = "column" + contentWrapDiv.style.justifyContent = "center" + contentWrapDiv.style.alignItems = "center" + contentWrapDiv.style.transition = 'all 0.3s' + contentWrapDiv.style.scale = '0' + let textDiv = document.createElement("span") + + textDiv.innerText = String.fromCharCode(parseInt(config.iconCode, 16)); + textDiv.style.fontFamily = "remixicon" + textDiv.style.fontSize = config.iconSize+"px" + textDiv.style.color = config.iconColor + textDiv.className = 'xShowLoadingAnimation' + + + var anistr = ` + .xShowLoadingAnimation{ + animation-name: xShowLoadingAnimation; + animation-duration: 1.2s; + animation-timing-function: linear; + animation-iteration-count: infinite; + } + + @keyframes xShowLoadingAnimation { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } + } + ` + var styleDIv = document.getElementById('xUiLoadWeingIcon'); + if (!styleDIv) { + let style = document.createElement("style"); + style.id = 'xUiLoadWeingIcon' + document.head.appendChild(style) + styleDIv = style; + } + let sheet = styleDIv.sheet; + if (sheet.cssRules.length == 0) { + styleDIv.append(anistr) + } + + contentWrapDiv.appendChild(textDiv) + + if(config.title!=''){ + let titleDiv = document.createElement("span") + titleDiv.innerText = config.title; + titleDiv.style.fontSize=config.titleSize+"px" + titleDiv.style.color= config.titleColor + contentWrapDiv.appendChild(titleDiv) + titleDiv.style.textAlign = "center" + } + + maskerDom!.appendChild(contentWrapDiv) + window.document.body.appendChild(maskerDom!) + + try{ + setTimeout(function() { + contentWrapDiv.style.scale = '1' + }, 10); + }catch(e){ + //TODO handle the exception + } +} + +export const hideXloading = ()=>{ + if(maskerDom!=null){ + maskerDom.remove() + } +} \ No newline at end of file diff --git a/uni_modules/x-loading-s/utssdk/web/loadFont.uts b/uni_modules/x-loading-s/utssdk/web/loadFont.uts new file mode 100644 index 0000000..18e18b7 --- /dev/null +++ b/uni_modules/x-loading-s/utssdk/web/loadFont.uts @@ -0,0 +1,13 @@ +export function LoadFontFace(){ + // 定义字体 + // @ts-ignore + const font = new FontFace("remixicon", "url(/static/tmui4xLibs/static/remixicon.ttf)", { + style: "italic", + weight: "800", + stretch: "condensed", + }); + + // 把字体添加到 document.fonts(FontFaceSet)中 + document.fonts.add(font); + font.load(); +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-48-00-776_uni.UNIB73859A.jpg b/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-48-00-776_uni.UNIB73859A.jpg new file mode 100644 index 0000000..f4bdd0b Binary files /dev/null and b/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-48-00-776_uni.UNIB73859A.jpg differ diff --git a/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-51-20-547_uni.UNIB73859A.jpg b/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-51-20-547_uni.UNIB73859A.jpg new file mode 100644 index 0000000..057867d Binary files /dev/null and b/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-51-20-547_uni.UNIB73859A.jpg differ diff --git a/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-55-55-076_uni.UNIB73859A.jpg b/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-55-55-076_uni.UNIB73859A.jpg new file mode 100644 index 0000000..cb345f9 Binary files /dev/null and b/uni_modules/x-mlkit-scannig-s/Screenshot_2024-01-23-23-55-55-076_uni.UNIB73859A.jpg differ diff --git a/uni_modules/x-mlkit-scannig-s/changelog.md b/uni_modules/x-mlkit-scannig-s/changelog.md new file mode 100644 index 0000000..349094e --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/changelog.md @@ -0,0 +1,41 @@ +## 1.1.2(2025-08-17) +* 针对微信的浏览器内核设定相关属性,以防止全屏脱离文档。 +## 1.1.1(2025-02-13) +* web,和微信相册识别已经改版本,能识别大多数码,效率有所提升。因为采用像素解析识别码,因此web,微信它是可以通用的,并且不依赖微信官方本身,所以 +* 你现在在微信端也能独立的识别远程或者静态图片码,而不需要调用uni.scan官方自带的接口。同样微信和web图片识别都是只能单码识别 +## 1.0.9(2024-11-18) +* 界面上添加了闪光灯控制,用于打开和关闭手电筒 +## 1.0.8(2024-09-12) +* 优化和修改了核心识别,调整了安卓识别页面兼容华为部分机型. +## 1.0.7(2024-08-31) +* openCameraApi接口调用增加了第二个onlyCamre是否仅使用相机识别,不通过相册识别. +## 1.0.6(2024-08-11) +* 升级安卓扫码为全屏扫码,码识别速度提升,并支持5.0安卓以上. +* 升级ios支持全屏识别,改善识别速率. +* ios,安卓,web增加显示动画缩放动画小到大. +* 安卓,ios填写相册识别并让小绿点精准率提到为100%,实时的小绿点位置在多点时可能会有偏差. +## 1.0.5(2024-07-30) +升级支持ios扫码功能,ios最低为ios12+ +升级支持H5(手机端)/WEB(带摄像头的win电脑及mac电脑) +## 1.0.4(2024-01-27) +1. 预览区域调整缩小一点, +2. 捕捉的图像再次放小一点。 +3. 扫描速率调整到500ms +如果你是有特定机器上有问题,请自己通过修改uts源码调整上面的这些参数,将影响识别速度,精准度,捕捉位置优化等可以自己通过源码调整。 +## 1.0.3(2024-01-26) +修改焦距为持续视频对焦模式,并拉近焦距(相当于视野变小了,之前是宽视野可以同时识别出10几个码,但现实中没必要这样,因此根据其它的应用参考,应该拉近点焦距)。 +对焦点识别的位置进行了优化比对,识别时位置更准,但不能保证非常准确。比如手机识别慢100ms左右,你手抖了下,可能位置是前100ms的位置 +会造成识别的位置和预览图可能有点区别。但经过持续的测试,红米note11 pro ,2年前的手机,基本很少出现对焦识别失准的情况。 +我把识别速度调整为1秒识别一次,对低端机可能更好。如果想识别非常的迅速可以调低这个值,比如100ms,基本一对准就识别了,精准度非常高。 +识别的震动改为了80ms,之前是200ms,感觉过长。 +识别成功后增加了黑色遮罩。 +另外识别程序放在了子线程中执行了,防止偶尔的卡钝。 + +**特别提醒,网友测试如果你是开发模式部分手机可能会比较卡,原因不明,但打包后的程序是非常流畅无比的** +## 1.0.2(2024-01-25) +1. 增加了识别成功后,短震动提示 +2. 识别多点后,给提示点增加了动画缩放指示提醒用户点按识别点。 +## 1.0.1(2024-01-24) +增加返回按钮事件 +## 1.0.0(2024-01-24) +首次发布 diff --git a/uni_modules/x-mlkit-scannig-s/package.json b/uni_modules/x-mlkit-scannig-s/package.json new file mode 100644 index 0000000..b5cbabc --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/package.json @@ -0,0 +1,86 @@ +{ + "id": "x-mlkit-scannig-s", + "displayName": "tmui4.0 UTS原生二维码扫一扫 机器学习", + "version": "1.0.7", + "description": "机器学习识别码库,它是tmui4.0附属插件,可实时识别多码,速度快,效率不错,精准度也不错", + "keywords": [ + "扫码", + "机器学习", + "二维码", + "扫一扫" +], + "repository": "", + "engines": { + "HBuilderX": "^3.99" + }, + "dcloudext": { + "type": "component-uts", + "sale": { + "regular": { + "price": "99.00" + }, + "sourcecode": { + "price": "199.00" + } + }, + "contact": { + "qq": "369986563" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "n", + "vue3": "y" + }, + "App": { + "app-android": { + "minVersion": "21" + }, + "app-ios": "n" + }, + "H5-mobile": { + "Safari": "n", + "Android Browser": "n", + "微信浏览器(Android)": "n", + "QQ浏览器(Android)": "n" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "n", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/readme.md b/uni_modules/x-mlkit-scannig-s/readme.md new file mode 100644 index 0000000..c6fb801 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/readme.md @@ -0,0 +1,45 @@ +# x-mlkit-scannig-u +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +### 功能特色 + +1. ios,安卓是Ai模型识别速度非常快,大概ios:50-100ms,安卓:200-350ms +2. web/h5带摄像头,实时识别时,效率比较低,识别精度不高,要多对几次 +3. web/微信图片识别时,精度中上。(不依赖微信官方,也不依赖Uniapp官方纯像素插件识别),不要图片了好多码,识别不准,如果码是黑色,多码能识别一个 +如果多码是非黑色,可能识别不出来 +4. 嵌入式页面识别,方便自己布局和装饰扫码界面。 +5. 微信,web只能是单码识别,多码一起识别不精准 + +**嵌入式相机识别在微信端:微信官方的本身这个组件就有很多问题,如果遇到没有扫码结果,请自行向微信官方提问,不需要问我,我的xs max就没有任何响应,但安卓有** +**最主要的更新是兼容了微信,并支持微信自定图片识别,这样可以不用打开微信自带的界面再选择图片识别,给了大家商用非常好的便利** +**web,微信图片识别时,请注意图片的干净,尽量不要多码放一起,一图一码,识别精准度还是好的** + + +### 兼容性 + +| IOS | Andriod | WEB | 小程序 | +| --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件。种子用户可免于购买。 + +非种子用户: + +普通授权:99元 +源码授权:199元 + +### 使用 + +需要自定义基座运行,且安卓5.0+(含5.0)以上支持 + +```ts +import {openCameraApi,closeCamera} from "@/uni_modules/x-mlkit-scannig-s" +const apiOpen = ()=>{ + openCameraApi((str:string)=>{ + console.log(str) + },false) +} +``` \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..917c5fb --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/camera copy.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/camera copy.uts new file mode 100644 index 0000000..c6ca821 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/camera copy.uts @@ -0,0 +1,951 @@ +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' + + +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import ViewGroup from 'android.view.ViewGroup' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; +import R from 'io.dcloud.uni_modules.xMlkitScannigS.R'; +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import Bundle from 'android.os.Bundle' +import Handler from 'android.os.Handler' +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import { decoderUriPathToQr, decoderBuffToQr, decoderUriPathToQrByUri } from "./index.uts" +import xView from "./libview/view.uts" +import Gravity from 'android.view.Gravity'; + +// x +import ProcessCameraProvider from "androidx.camera.lifecycle.ProcessCameraProvider" +import PreviewView from "androidx.camera.view.PreviewView" +import CameraController from "androidx.camera.view.CameraController" +import CameraSelector from "androidx.camera.core.CameraSelector" +import Preview from 'androidx.camera.core.Preview' +import Camera from 'androidx.camera.core.Camera' +import LifecycleObserver from "androidx.lifecycle.LifecycleObserver" +import LifecycleOwner from "androidx.lifecycle.LifecycleOwner" +import OnLifecycleEvent from "androidx.lifecycle.OnLifecycleEvent" +import ImageAnalysis from 'androidx.camera.core.ImageAnalysis' +import ImageProxy from 'androidx.camera.core.ImageProxy' +import NonNull from 'androidx.annotation.NonNull' +import ExecutorService from 'java.util.concurrent.ExecutorService' +import Executors from 'java.util.concurrent.Executors' +import ContextCompat from 'androidx.core.content.ContextCompat'; +import LifecycleRegistry from "androidx.lifecycle.LifecycleRegistry" +import Lifecycle from "androidx.lifecycle.Lifecycle" +import FrameLayout from 'android.widget.FrameLayout'; +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; + +import { SCANNING_OPTIONS, CAMERA_PHOTO_SIZE, CALL_RESULT_FUN, Call_BACK, Call_BACK_TYPE, SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND } from "../interface.uts" +type buffoptsPlanesType = { + data : ByteBuffer, + getRowStride : number, + getPixelStride : number, +} +type buffoptsType = { + width : number, + height : number, + format : number, + rect : Rect, + planes : buffoptsPlanesType[], +} +type ConverXy = { + x : number, + y : number, + minx : number, + maxx : number, + miny : number, + maxy : number, +} +type contaiaSize = { + width : number, + height : number +} +type contaiaCalseSize = { + scale : number, + offsetX : number, + offsetY : number +} +type contaiPointXy = { + x : number, + y : number +} +let parentView : RelativeLayout | null = null; + +let maskDomId = 8586 + + +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} + + +export class xCamera { + /** 手动震动服务 */ + vibrator = null as null | Vibrator + context : Context; + // 识别点的区域 + resultView : RelativeLayout | null = null; + // 存放小绿点的数组 + imgPointsBycanmarea = [] as RelativeLayout[] + //相机容器 + camreaLayouView:RelativeLayout|null = null; + // 图片容器层. + imageLayouView:RelativeLayout|null = null; + + viewBox_width = 0 + viewBox_height = 0 + + imageView = null as null | ImageView + imageUrl = null as null | Uri + isSelectedImging = false; + + // 相机区域视图 + cameraView : PreviewView | null = null; + cameraProvider : ProcessCameraProvider | null = null + camera : Camera | null = null; + cameraPreview : Preview | null = null; + + + // 当前是否在解析码制中。 + isDecoderQring = false + // 当前相机是否正在预览中。 + isOpeningCameraing = false; + + callFunEvent : CALL_RESULT_FUN = (str : string) => { } + onlyCamera:boolean = false; + // 临时存放的识别成功的结果,防止重复扫码。 + tempresultList = [] as string[]; + activityresult = (requestCode : Int, resultCode : Int, data ?: Intent)=>{ + let t = this; + if (resultCode == Activity.RESULT_OK && data != null && data?.data != null) { + let selectedImageUri = data.data! + this.camreaLayouView!.setVisibility(View.GONE) + this.imageUrl = selectedImageUri + this.isSelectedImging = false + decoderUriPathToQrByUri(this.imageUrl!,(res:SCANNING_PHOTO_RESULT)=>{ + t.isOpeningCameraing = false + t.clearImageView(); + t.imageView!.setImageURI(t.imageUrl!); + let matrix = t.getCorrectionMatrixByimgUri(t.imageView!, t.cameraView!,90) + let ruslt = res as SCANNING_PHOTO_RESULT; + if(ruslt.text.length>0){ + t.setVibatar() + } + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + + let result = t.calcPoint(t.imageView!, t.cameraView!,item.centerX,item.centerY,0) + + // let ponit = floatArrayOf(item.centerX.toFloat(), item.centerY.toFloat()) + // matrix.mapPoints(ponit) + // item.centerX = ponit[0] + // item.centerY = ponit[1] + item.centerX = result.x + item.centerY = result.y + } + t.setImageViewRusletBox(ruslt) + if (ruslt.text.length == 1) { + t.callFunEvent(ruslt.text[0]) + t.close() + } + + }) + + } else { + this.isSelectedImging = false + + } + } + constructor() { + this.context = UTSAndroid.getAppContext()! as Context + this.vibrator = this.context!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + } + clearImageView() { + this.clearImagePonit(); + if (!this.isOpeningCameraing) { + this.imageView!.setImageDrawable(null) + } + + } + setVibatar() { + if (this.vibrator == null) return + // 检查设备是否支持震动 + if (this.vibrator!.hasVibrator()) { + // 触发短暂的震动,持续时间为200毫秒 + this.vibrator!.vibrate(80); + } + } + openCamera(call:CALL_RESULT_FUN,onlyCameras:boolean) { + this.onlyCamera = onlyCameras; + let t = this; + this.callFunEvent = call + if (parentView == null) { + this.createView(); + t._openCamera() + } else { + this._openCamera() + } + } + + close() { + UTSAndroid.offAppActivityResult(this.activityresult) + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + this.closeCamera(); + this.clearImagePonit(); + if (parentView != null) { + decorView.removeView(parentView) + } + parentView = null; + + } + private _openCamera() { + let _this = this; + this.closeCamera(); + this.clearImagePonit(); + let cameraProviderFuture = ProcessCameraProvider.getInstance(this.context) + this.camreaLayouView!.setVisibility(View.VISIBLE) + class IntentRunable extends Runnable { + override run() { + let cameraProvider : ProcessCameraProvider = cameraProviderFuture.get() + let previewView = _this.cameraView! as PreviewView + let cameraSelector : CameraSelector = new CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + let preview : Preview = new Preview.Builder().build(); + + preview.setSurfaceProvider(previewView.getSurfaceProvider()) + + let imageAnalysis = new ImageAnalysis.Builder() + .setTargetResolution(new Size(800, 800)) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + class MyImageAnalyzer implements ImageAnalysis.Analyzer { + constructor() { + super() + } + override analyze(image : ImageProxy) { + _this.qrDecoder(image) + + } + override getDefaultTargetResolution() : Size { + return new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt()); + } + + } + let cameraExecutor = Executors.newSingleThreadExecutor(); + imageAnalysis.setAnalyzer(cameraExecutor, new MyImageAnalyzer()); + let camera : Camera = cameraProvider.bindToLifecycle( + UTSAndroid.getUniActivity()! as LifecycleOwner, cameraSelector, preview, imageAnalysis); + + _this.camera = camera + _this.cameraPreview = preview + + _this.cameraProvider = cameraProvider + _this.isDecoderQring = false + _this.isOpeningCameraing = true + + + } + } + + cameraProviderFuture.addListener(new IntentRunable(), ContextCompat.getMainExecutor(this.context)) + } + closeCamera() { + this.cameraProvider?.unbindAll() + this.cameraPreview?.setSurfaceProvider(null) + this.isOpeningCameraing = false; + + } + clearImagePonit(){ + for (let i = 0; i < this.imgPointsBycanmarea.length; i++) { + this.resultView?.removeView(this.imgPointsBycanmarea[i]) + } + } + private createView() { + let t = this; + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + // 创建父容器。 + parentView = new RelativeLayout(this.context); + parentView!.setId((maskDomId).toInt()) + // parentView!.setOrientation(LinearLayout.VERTICAL) + parentView!.setBackgroundColor(Color.BLACK) + + + + parentView!.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )) + + class MaskerDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + //阻止事件向下穿透。 + override onTouch(view : View, event : MotionEvent) : Boolean { + return true; + } + } + parentView!.setOnTouchListener(new MaskerDomClickListsner()) + + let continaer = new LinearLayout(this.context); + continaer.setOrientation(LinearLayout.VERTICAL) + continaer.setBackgroundColor(Color.TRANSPARENT) + let continaerLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + continaer.setLayoutParams(continaerLayparams) + + + // 创建一个中间容器 + let boxWrapParent = new LinearLayout(this.context); + boxWrapParent.setOrientation(LinearLayout.VERTICAL) + + let boxLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + boxLayparams.weight = (1).toFloat(); + boxLayparams.height = 0; + boxWrapParent.setLayoutParams(boxLayparams) + // 创建一个定位容器 + let boxWrap = new RelativeLayout(this.context); + boxWrap.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )) + + boxWrapParent.addView(boxWrap) + + //监听尺寸变化。 + + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.viewBox_width = right - left; + t.viewBox_height = bottom - top; + + } + } + boxWrap.addOnLayoutChangeListener(new previewChangeRectadd()) + + let rongqitop = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + rongqitop.topMargin = 0 + rongqitop.leftMargin = 0 + // 创建容器内小绿点容器。 + this.resultView = new RelativeLayout(this.context); + this.resultView!.setLayoutParams(rongqitop) + + // 图片容器 + let imgPview = new RelativeLayout(this.context); + let rongqitop2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + rongqitop2.topMargin = 0 + rongqitop2.leftMargin = 0 + imgPview.setLayoutParams(rongqitop2) + + // 创建一张图片 + this.imageView = new ImageView(this.context); + this.imageView!.setScaleType(ImageView.ScaleType.CENTER_INSIDE) + this.imageView!.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) + imgPview.addView(this.imageView!) + this.imageView!.setImageDrawable(null) + // 相机容器。 + let cview = new RelativeLayout(this.context); + let rongqitop3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + + // rongqitop3.width = 1000 + // rongqitop3.height = 1000 + cview.setLayoutParams(rongqitop3) + // 相机预览层。 + let sv = new PreviewView(this.context) + // https://developer.android.google.cn/reference/androidx/camera/view/PreviewView.ScaleType?hl=en + sv.setScaleType(PreviewView.ScaleType.FILL_CENTER) + + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + cview.addView(this.cameraView!) + + + // this.imageView!.setVisibility(View.INVISIBLE) + //相机容器 + this.camreaLayouView = cview; + // 图片容器层. + this.imageLayouView= imgPview; + boxWrap.addView(imgPview) + boxWrap.addView(cview) + boxWrap.addView(this.resultView!) + + + + + // 创建底 + let footerWrap = new LinearLayout(this.context); + footerWrap.setOrientation(LinearLayout.HORIZONTAL) + + let footerWrapLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + + footerWrapLayparams.height = px2dp(100).toInt(); + footerWrap.setLayoutParams(footerWrapLayparams) + + // 创建选择相册 + let photoView = new LinearLayout(this.context); + photoView.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )) + let xiangcheText = new TextView(this.context); + xiangcheText.setTextColor(Color.WHITE) + xiangcheText.setPadding(32, 52, 0, 0) + xiangcheText.setTextSize((16).toFloat()) + xiangcheText.setGravity(Gravity.LEFT) + xiangcheText.setText(!this.onlyCamera?"相册选择":" ") + xiangcheText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class XiangcheClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + UTSAndroid.offAppActivityResult(t.activityresult) + if(event.getAction()==MotionEvent.ACTION_UP){ + t.closeCamera() + t.isSelectedImging = true; + let intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + UTSAndroid.onAppActivityResult(t.activityresult); + UTSAndroid.getUniActivity()!.startActivityForResult(intent, 1) + } + + + return true; + } + } + if(!this.onlyCamera){ + xiangcheText.setOnTouchListener(new XiangcheClickListsner()) + } + photoView.addView(xiangcheText) + + // 中间占位 + let cneterView = new LinearLayout(this.context); + let cneterViewParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + cneterViewParams.weight = (1).toFloat(); + cneterView.setLayoutParams(cneterViewParams) + + + // 扫一扫view + let scanView = new LinearLayout(this.context); + scanView.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )) + scanView.setGravity(Gravity.RIGHT) + + let shaoyishaoText = new TextView(this.context); + shaoyishaoText.setTextColor(Color.WHITE) + shaoyishaoText.setPadding(0, 52, 32, 0) + shaoyishaoText.setTextSize((16).toFloat()) + shaoyishaoText.setGravity(Gravity.RIGHT) + shaoyishaoText.setText("扫一扫") + shaoyishaoText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class ShaoyishaoTextClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + if(event.getAction()==MotionEvent.ACTION_UP){ + t._openCamera() + } + + return true; + } + } + shaoyishaoText.setOnTouchListener(new ShaoyishaoTextClickListsner()) + scanView.addView(shaoyishaoText) + + + + footerWrap.addView(photoView) + footerWrap.addView(cneterView) + footerWrap.addView(scanView) + + // 创建一个顶部 + let titleView = new RelativeLayout(this.context); + // titleView!.setOrientation(LinearLayout.HORIZONTAL) + // titleView!.setBackgroundColor(Color.RED) + let tplays = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + tplays.topMargin = px2dp(60).toInt() + tplays.leftMargin = px2dp(16).toInt() + titleView!.setLayoutParams(tplays) + // 创建一个返回按钮 + let backBtn = new TextView(this.context); + backBtn.setTextColor(Color.WHITE) + backBtn.setTextSize((16).toFloat()) + backBtn.setGravity(Gravity.BOTTOM) + backBtn.setText("返回") + + backBtn.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class BackDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + t.close(); + return true; + } + } + backBtn.setOnTouchListener(new BackDomClickListsner()) + titleView!.addView(backBtn) + + + + continaer.addView(boxWrapParent) + continaer.addView(footerWrap) + + parentView!.addView(continaer) + parentView!.addView(titleView) + decorView.addView(parentView!) + + // 增加动画 + try { + let s0 = (0).toFloat() + let s1 = (1).toFloat() + parentView!.setAlpha(s0) + parentView!.setScaleX(s0) + parentView!.setScaleY(s0) + + + let ani = parentView!.animate() as ViewPropertyAnimator; + ani.alpha(s1) + .scaleX(s1) + .scaleY(s1) + .setDuration(250) + .start() + + } catch (e) { + //TODO handle the exception + } + } + // 设置图片上的小圆的识别位置。 + setImageViewRusletBox(jieguo : SCANNING_PHOTO_RESULT) { + let t = this; + let btnwidth = 100; + let btnwidth2 = 50; + + for (let i = 0; i < jieguo.bounds.length; i++) { + let item = jieguo.bounds[i]; + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + let x = item.centerX + let y = item.centerY + + layoutParams.topMargin = (y - btnwidth2).toInt() // 设置顶部边距 + layoutParams.leftMargin = (x - btnwidth2).toInt() // 设置左边距 + let relativeLayout = new RelativeLayout(t.context) + relativeLayout.layoutParams = layoutParams + + const rtxt = jieguo.text[i] + let v = new xView(t.context) + v.setSize(btnwidth, btnwidth) + .setRadius(100) + .setBackgroundColor('#21d429') + .setBorder(12, "#ffffff", false) + .setClick((event : MotionEvent) => { + try { + // t.callFunEvent([rtxt], 'click') + t.callFunEvent(rtxt) + t.close() + } catch (e) { + //TODO handle the exception + } + }) + let ov = v.getView(); + + + // 创建缩放动画 + let scaleAnimation = new ScaleAnimation(1.0.toFloat(), 0.7.toFloat(), 1.0.toFloat(), 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat()); + scaleAnimation.setDuration(600); // 设置动画持续时间 + scaleAnimation.setRepeatMode(Animation.REVERSE); // 设置重复模式为反向 + scaleAnimation.setRepeatCount(Animation.INFINITE); // 设置重复次数为无限 + // 启动动画 + ov.startAnimation(scaleAnimation); + relativeLayout.addView(ov) + this.imgPointsBycanmarea.push(relativeLayout) + this.resultView!.addView(relativeLayout) + } + + + } + + + YUV42088ToNV21Copy(a:ByteBuffer,b:ByteBuffer,c:ByteBuffer,widths:number,heights:number,yr:number,ur:number,vr:number) : ByteArray { + // 获取图像的宽度、高度以及各平面的行间距 + let width = widths + let height = heights; + // 获取各平面的数据与信息 + + let yBuffer = a; + let uBuffer = b; + let vBuffer = c; + + yBuffer.rewind(); + uBuffer.rewind(); + vBuffer.rewind(); + + let yRowStride = yr; + let uvRowStride = ur; + let uvPixelStride = vr; // U 和 V 的像素间距通常是一样的 + + // 创建一个足够大的NV21输出数组 + let nv21Data = new ByteArray((width * height * 3 / 2).toInt()); + + // 指针用于遍历输出数组 + let yIndex = 0; + let uvIndex = width * height; + let bytesPerPixel = 1 + try { + // 遍历Y平面 + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + nv21Data[(yIndex++).toInt()] = yBuffer.get(); + } + // 跳过未使用的行数据(如果有) + let rowRemainder = yRowStride - width * bytesPerPixel; + + if (rowRemainder > 0) { + yBuffer.position((yBuffer.position() + rowRemainder).toInt()); + } else { + yBuffer.position((yBuffer.position() + width * bytesPerPixel).toInt()); // 防止由于计算错误导致的负数 + } + + } + } catch (e) { + //TODO handle the exception + } + // // 处理UV平面 + try { + for (let row = 0; row < height / 2; row++) { + for (let col = 0; col < width / 2; col++) { + // 先读取U分量 + nv21Data[(uvIndex++).toInt()] = uBuffer.get(); + // 如果UV像素不是交错存储,则跳过一个位置 + if (uvPixelStride == 2) { + uBuffer.position((uBuffer.position() + 1).toInt()); + } + + // 再读取V分量 + nv21Data[(uvIndex++).toInt()] = vBuffer.get(); + // 如果UV像素是交错存储,这里也需要相应调整位置 + if (uvPixelStride == 2) { + vBuffer.position((vBuffer.position() + 1).toInt()); + } + } + // 跳过未使用的行数据(如果有) + let uvRowSkip = uvRowStride - (width / 2) * uvPixelStride; + if (uvRowSkip > 0) { + uBuffer.position((uBuffer.position() + uvRowSkip).toInt()); + vBuffer.position((vBuffer.position() + uvRowSkip).toInt()); + } + } + } catch (e) { + //TODO handle the exception + } + return nv21Data; + } + + copyImagePlan(plane:Plane):ByteBuffer{ + // 创建一个新的ByteBuffer来存储复制的数据 + let copiedBuffer = ByteBuffer.allocateDirect(plane.getBuffer().capacity()); + copiedBuffer.order(ByteOrder.nativeOrder()); // 确保字节顺序与原Buffer一致 + + // 将原始Plane的ByteBuffer内容复制到新的ByteBuffer中 + plane.getBuffer().rewind(); // 移动缓冲区指针到开始位置(可选,如果已经知道在开始处则无需此步) + copiedBuffer.put(plane.getBuffer()); + + // 复制完成后,可以移动新ByteBuffer的指针回到起始位置以便读取 + copiedBuffer.rewind(); + + return copiedBuffer + } + getCorrectionMatrixByimgUri(imgView : ImageView, previewView : PreviewView,rotationDegrees:number) : Matrix { + + let matrix = new Matrix() + let imgWidt = imgView.drawable!.intrinsicWidth as number + let imgHeight = imgView.drawable!.intrinsicHeight as number + let d0 = (0).toFloat() + let source = floatArrayOf( + d0, + d0, + imgWidt.toFloat(), + d0, + imgWidt.toFloat(), + imgHeight.toFloat(), + d0, + imgHeight.toFloat() + ) + + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf( + d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat() + ) + + + let vertexSize = 2 + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + getCorrectionMatrix(imageProxy : ImageProxy, previewView : PreviewView) : Matrix { + let cropRect = imageProxy.cropRect + let rotationDegrees = imageProxy.imageInfo.rotationDegrees + let matrix = new Matrix() + + // A float array of the source vertices (crop rect) in clockwise order. + + let source = floatArrayOf( + cropRect.left.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.bottom.toFloat(), + cropRect.left.toFloat(), + cropRect.bottom.toFloat() + ) + let d0 = (0).toFloat() + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf( + d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat() + ) + + + let vertexSize = 2 + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + + + calcPoint(imgView : ImageView, previewView : PreviewView, image_point_x : number, image_point_y : number,degration:number) : ConverXy { + + const image_w = imgView.drawable!.intrinsicWidth as number + const image_h = imgView.drawable!.intrinsicHeight as number + const c_w = previewView.width; + const c_h = previewView.height; + + function scaleAndCenterContent( + container : contaiaSize, + content : contaiaSize + ) : contaiaCalseSize { + // 计算缩放比例 + const scaleWidth = container.width / content.width; + const scaleHeight = container.height / content.height; + const scale = Math.min(scaleWidth, scaleHeight); + + // 计算居中偏移量 + const offsetX = (container.width - content.width * scale) / 2; + const offsetY = (container.height - content.height * scale) / 2; + + return { scale, offsetX, offsetY } as contaiaCalseSize; + } + function mapContentCoordinatesToContainer( + contentX : number, + contentY : number, + calcsize : contaiaCalseSize + ) : contaiPointXy { + // 映射内容层坐标到容器层坐标 + const containerX = contentX * calcsize.scale + calcsize.offsetX; + const containerY = contentY * calcsize.scale + calcsize.offsetY; + + return { x: containerX, y: containerY } as contaiPointXy; + } + + let rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_h, height: image_w } as contaiaSize + ) + if(degration==0){ + rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_w, height: image_h } as contaiaSize + ) + } + + let result = mapContentCoordinatesToContainer(image_point_y, image_point_x, rc) + if(degration==0){ + result = mapContentCoordinatesToContainer(image_point_x,image_point_y,rc) + } + let nexyxcov = { + x: c_w - result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + if(degration==0){ + nexyxcov = { + x: result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + } + return nexyxcov + + } + + qrDecoder(img : ImageProxy) { + let t = this; + let image = img.getImage(); + if (!this.isDecoderQring&&image!=null&&t.isOpeningCameraing) { + this.isDecoderQring = true; + let width = image.getWidth(); + let height = image.getHeight(); + + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + + let a = this.copyImagePlan(planes[0]); + let b = this.copyImagePlan(planes[1]); + let c = this.copyImagePlan(planes[2]); + let yr = planes[0].getRowStride() + let ur = planes[1].getRowStride() + let vr = planes[1].getPixelStride() + + let starttime = new Date().getTime() + + let av = this.YUV42088ToNV21Copy(a,b,c,width,height,yr,ur,vr) + let rotationDegrees = img.imageInfo.rotationDegrees + + decoderBuffToQr(av, width, height, 0) + .then((res) => { + if (res != null ) { + let matrix = t.getCorrectionMatrix(img, t.cameraView!) + if (res.text.length > 0) { + let ruslt = res as SCANNING_PHOTO_RESULT; + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + let ponit = floatArrayOf(item.centerX.toFloat(), item.centerY.toFloat()) + // let xy = t.covertXy(img, t.cameraView!,item.centerX,item.centerY); + matrix.mapPoints(ponit) + item.centerX = ponit[0] + item.centerY = ponit[1] + // item.centerX = xy[0] + // item.centerY = xy[1] + // console.log(item.centerX ,item.centerY) + + } + if(ruslt.text.length>0){ + t.setVibatar() + } + t.setImageViewRusletBox(ruslt) + t.closeCamera() + if (ruslt.text.length == 1) { + t.callFunEvent(ruslt.text[0]) + t.close() + } + }else{ + t.isDecoderQring = false + } + } + // image.close(); + }) + .catch(() => { + t.isDecoderQring = false + }) + } + img.close(); + } + + + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/camera.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/camera.uts new file mode 100644 index 0000000..c6ca821 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/camera.uts @@ -0,0 +1,951 @@ +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' + + +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import ViewGroup from 'android.view.ViewGroup' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; +import R from 'io.dcloud.uni_modules.xMlkitScannigS.R'; +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import Bundle from 'android.os.Bundle' +import Handler from 'android.os.Handler' +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import { decoderUriPathToQr, decoderBuffToQr, decoderUriPathToQrByUri } from "./index.uts" +import xView from "./libview/view.uts" +import Gravity from 'android.view.Gravity'; + +// x +import ProcessCameraProvider from "androidx.camera.lifecycle.ProcessCameraProvider" +import PreviewView from "androidx.camera.view.PreviewView" +import CameraController from "androidx.camera.view.CameraController" +import CameraSelector from "androidx.camera.core.CameraSelector" +import Preview from 'androidx.camera.core.Preview' +import Camera from 'androidx.camera.core.Camera' +import LifecycleObserver from "androidx.lifecycle.LifecycleObserver" +import LifecycleOwner from "androidx.lifecycle.LifecycleOwner" +import OnLifecycleEvent from "androidx.lifecycle.OnLifecycleEvent" +import ImageAnalysis from 'androidx.camera.core.ImageAnalysis' +import ImageProxy from 'androidx.camera.core.ImageProxy' +import NonNull from 'androidx.annotation.NonNull' +import ExecutorService from 'java.util.concurrent.ExecutorService' +import Executors from 'java.util.concurrent.Executors' +import ContextCompat from 'androidx.core.content.ContextCompat'; +import LifecycleRegistry from "androidx.lifecycle.LifecycleRegistry" +import Lifecycle from "androidx.lifecycle.Lifecycle" +import FrameLayout from 'android.widget.FrameLayout'; +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; + +import { SCANNING_OPTIONS, CAMERA_PHOTO_SIZE, CALL_RESULT_FUN, Call_BACK, Call_BACK_TYPE, SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND } from "../interface.uts" +type buffoptsPlanesType = { + data : ByteBuffer, + getRowStride : number, + getPixelStride : number, +} +type buffoptsType = { + width : number, + height : number, + format : number, + rect : Rect, + planes : buffoptsPlanesType[], +} +type ConverXy = { + x : number, + y : number, + minx : number, + maxx : number, + miny : number, + maxy : number, +} +type contaiaSize = { + width : number, + height : number +} +type contaiaCalseSize = { + scale : number, + offsetX : number, + offsetY : number +} +type contaiPointXy = { + x : number, + y : number +} +let parentView : RelativeLayout | null = null; + +let maskDomId = 8586 + + +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} + + +export class xCamera { + /** 手动震动服务 */ + vibrator = null as null | Vibrator + context : Context; + // 识别点的区域 + resultView : RelativeLayout | null = null; + // 存放小绿点的数组 + imgPointsBycanmarea = [] as RelativeLayout[] + //相机容器 + camreaLayouView:RelativeLayout|null = null; + // 图片容器层. + imageLayouView:RelativeLayout|null = null; + + viewBox_width = 0 + viewBox_height = 0 + + imageView = null as null | ImageView + imageUrl = null as null | Uri + isSelectedImging = false; + + // 相机区域视图 + cameraView : PreviewView | null = null; + cameraProvider : ProcessCameraProvider | null = null + camera : Camera | null = null; + cameraPreview : Preview | null = null; + + + // 当前是否在解析码制中。 + isDecoderQring = false + // 当前相机是否正在预览中。 + isOpeningCameraing = false; + + callFunEvent : CALL_RESULT_FUN = (str : string) => { } + onlyCamera:boolean = false; + // 临时存放的识别成功的结果,防止重复扫码。 + tempresultList = [] as string[]; + activityresult = (requestCode : Int, resultCode : Int, data ?: Intent)=>{ + let t = this; + if (resultCode == Activity.RESULT_OK && data != null && data?.data != null) { + let selectedImageUri = data.data! + this.camreaLayouView!.setVisibility(View.GONE) + this.imageUrl = selectedImageUri + this.isSelectedImging = false + decoderUriPathToQrByUri(this.imageUrl!,(res:SCANNING_PHOTO_RESULT)=>{ + t.isOpeningCameraing = false + t.clearImageView(); + t.imageView!.setImageURI(t.imageUrl!); + let matrix = t.getCorrectionMatrixByimgUri(t.imageView!, t.cameraView!,90) + let ruslt = res as SCANNING_PHOTO_RESULT; + if(ruslt.text.length>0){ + t.setVibatar() + } + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + + let result = t.calcPoint(t.imageView!, t.cameraView!,item.centerX,item.centerY,0) + + // let ponit = floatArrayOf(item.centerX.toFloat(), item.centerY.toFloat()) + // matrix.mapPoints(ponit) + // item.centerX = ponit[0] + // item.centerY = ponit[1] + item.centerX = result.x + item.centerY = result.y + } + t.setImageViewRusletBox(ruslt) + if (ruslt.text.length == 1) { + t.callFunEvent(ruslt.text[0]) + t.close() + } + + }) + + } else { + this.isSelectedImging = false + + } + } + constructor() { + this.context = UTSAndroid.getAppContext()! as Context + this.vibrator = this.context!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + } + clearImageView() { + this.clearImagePonit(); + if (!this.isOpeningCameraing) { + this.imageView!.setImageDrawable(null) + } + + } + setVibatar() { + if (this.vibrator == null) return + // 检查设备是否支持震动 + if (this.vibrator!.hasVibrator()) { + // 触发短暂的震动,持续时间为200毫秒 + this.vibrator!.vibrate(80); + } + } + openCamera(call:CALL_RESULT_FUN,onlyCameras:boolean) { + this.onlyCamera = onlyCameras; + let t = this; + this.callFunEvent = call + if (parentView == null) { + this.createView(); + t._openCamera() + } else { + this._openCamera() + } + } + + close() { + UTSAndroid.offAppActivityResult(this.activityresult) + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + this.closeCamera(); + this.clearImagePonit(); + if (parentView != null) { + decorView.removeView(parentView) + } + parentView = null; + + } + private _openCamera() { + let _this = this; + this.closeCamera(); + this.clearImagePonit(); + let cameraProviderFuture = ProcessCameraProvider.getInstance(this.context) + this.camreaLayouView!.setVisibility(View.VISIBLE) + class IntentRunable extends Runnable { + override run() { + let cameraProvider : ProcessCameraProvider = cameraProviderFuture.get() + let previewView = _this.cameraView! as PreviewView + let cameraSelector : CameraSelector = new CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + let preview : Preview = new Preview.Builder().build(); + + preview.setSurfaceProvider(previewView.getSurfaceProvider()) + + let imageAnalysis = new ImageAnalysis.Builder() + .setTargetResolution(new Size(800, 800)) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + class MyImageAnalyzer implements ImageAnalysis.Analyzer { + constructor() { + super() + } + override analyze(image : ImageProxy) { + _this.qrDecoder(image) + + } + override getDefaultTargetResolution() : Size { + return new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt()); + } + + } + let cameraExecutor = Executors.newSingleThreadExecutor(); + imageAnalysis.setAnalyzer(cameraExecutor, new MyImageAnalyzer()); + let camera : Camera = cameraProvider.bindToLifecycle( + UTSAndroid.getUniActivity()! as LifecycleOwner, cameraSelector, preview, imageAnalysis); + + _this.camera = camera + _this.cameraPreview = preview + + _this.cameraProvider = cameraProvider + _this.isDecoderQring = false + _this.isOpeningCameraing = true + + + } + } + + cameraProviderFuture.addListener(new IntentRunable(), ContextCompat.getMainExecutor(this.context)) + } + closeCamera() { + this.cameraProvider?.unbindAll() + this.cameraPreview?.setSurfaceProvider(null) + this.isOpeningCameraing = false; + + } + clearImagePonit(){ + for (let i = 0; i < this.imgPointsBycanmarea.length; i++) { + this.resultView?.removeView(this.imgPointsBycanmarea[i]) + } + } + private createView() { + let t = this; + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + // 创建父容器。 + parentView = new RelativeLayout(this.context); + parentView!.setId((maskDomId).toInt()) + // parentView!.setOrientation(LinearLayout.VERTICAL) + parentView!.setBackgroundColor(Color.BLACK) + + + + parentView!.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )) + + class MaskerDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + //阻止事件向下穿透。 + override onTouch(view : View, event : MotionEvent) : Boolean { + return true; + } + } + parentView!.setOnTouchListener(new MaskerDomClickListsner()) + + let continaer = new LinearLayout(this.context); + continaer.setOrientation(LinearLayout.VERTICAL) + continaer.setBackgroundColor(Color.TRANSPARENT) + let continaerLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + continaer.setLayoutParams(continaerLayparams) + + + // 创建一个中间容器 + let boxWrapParent = new LinearLayout(this.context); + boxWrapParent.setOrientation(LinearLayout.VERTICAL) + + let boxLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + boxLayparams.weight = (1).toFloat(); + boxLayparams.height = 0; + boxWrapParent.setLayoutParams(boxLayparams) + // 创建一个定位容器 + let boxWrap = new RelativeLayout(this.context); + boxWrap.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )) + + boxWrapParent.addView(boxWrap) + + //监听尺寸变化。 + + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.viewBox_width = right - left; + t.viewBox_height = bottom - top; + + } + } + boxWrap.addOnLayoutChangeListener(new previewChangeRectadd()) + + let rongqitop = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + rongqitop.topMargin = 0 + rongqitop.leftMargin = 0 + // 创建容器内小绿点容器。 + this.resultView = new RelativeLayout(this.context); + this.resultView!.setLayoutParams(rongqitop) + + // 图片容器 + let imgPview = new RelativeLayout(this.context); + let rongqitop2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + rongqitop2.topMargin = 0 + rongqitop2.leftMargin = 0 + imgPview.setLayoutParams(rongqitop2) + + // 创建一张图片 + this.imageView = new ImageView(this.context); + this.imageView!.setScaleType(ImageView.ScaleType.CENTER_INSIDE) + this.imageView!.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) + imgPview.addView(this.imageView!) + this.imageView!.setImageDrawable(null) + // 相机容器。 + let cview = new RelativeLayout(this.context); + let rongqitop3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + + // rongqitop3.width = 1000 + // rongqitop3.height = 1000 + cview.setLayoutParams(rongqitop3) + // 相机预览层。 + let sv = new PreviewView(this.context) + // https://developer.android.google.cn/reference/androidx/camera/view/PreviewView.ScaleType?hl=en + sv.setScaleType(PreviewView.ScaleType.FILL_CENTER) + + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + cview.addView(this.cameraView!) + + + // this.imageView!.setVisibility(View.INVISIBLE) + //相机容器 + this.camreaLayouView = cview; + // 图片容器层. + this.imageLayouView= imgPview; + boxWrap.addView(imgPview) + boxWrap.addView(cview) + boxWrap.addView(this.resultView!) + + + + + // 创建底 + let footerWrap = new LinearLayout(this.context); + footerWrap.setOrientation(LinearLayout.HORIZONTAL) + + let footerWrapLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + + footerWrapLayparams.height = px2dp(100).toInt(); + footerWrap.setLayoutParams(footerWrapLayparams) + + // 创建选择相册 + let photoView = new LinearLayout(this.context); + photoView.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )) + let xiangcheText = new TextView(this.context); + xiangcheText.setTextColor(Color.WHITE) + xiangcheText.setPadding(32, 52, 0, 0) + xiangcheText.setTextSize((16).toFloat()) + xiangcheText.setGravity(Gravity.LEFT) + xiangcheText.setText(!this.onlyCamera?"相册选择":" ") + xiangcheText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class XiangcheClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + UTSAndroid.offAppActivityResult(t.activityresult) + if(event.getAction()==MotionEvent.ACTION_UP){ + t.closeCamera() + t.isSelectedImging = true; + let intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + UTSAndroid.onAppActivityResult(t.activityresult); + UTSAndroid.getUniActivity()!.startActivityForResult(intent, 1) + } + + + return true; + } + } + if(!this.onlyCamera){ + xiangcheText.setOnTouchListener(new XiangcheClickListsner()) + } + photoView.addView(xiangcheText) + + // 中间占位 + let cneterView = new LinearLayout(this.context); + let cneterViewParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + cneterViewParams.weight = (1).toFloat(); + cneterView.setLayoutParams(cneterViewParams) + + + // 扫一扫view + let scanView = new LinearLayout(this.context); + scanView.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )) + scanView.setGravity(Gravity.RIGHT) + + let shaoyishaoText = new TextView(this.context); + shaoyishaoText.setTextColor(Color.WHITE) + shaoyishaoText.setPadding(0, 52, 32, 0) + shaoyishaoText.setTextSize((16).toFloat()) + shaoyishaoText.setGravity(Gravity.RIGHT) + shaoyishaoText.setText("扫一扫") + shaoyishaoText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class ShaoyishaoTextClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + if(event.getAction()==MotionEvent.ACTION_UP){ + t._openCamera() + } + + return true; + } + } + shaoyishaoText.setOnTouchListener(new ShaoyishaoTextClickListsner()) + scanView.addView(shaoyishaoText) + + + + footerWrap.addView(photoView) + footerWrap.addView(cneterView) + footerWrap.addView(scanView) + + // 创建一个顶部 + let titleView = new RelativeLayout(this.context); + // titleView!.setOrientation(LinearLayout.HORIZONTAL) + // titleView!.setBackgroundColor(Color.RED) + let tplays = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + tplays.topMargin = px2dp(60).toInt() + tplays.leftMargin = px2dp(16).toInt() + titleView!.setLayoutParams(tplays) + // 创建一个返回按钮 + let backBtn = new TextView(this.context); + backBtn.setTextColor(Color.WHITE) + backBtn.setTextSize((16).toFloat()) + backBtn.setGravity(Gravity.BOTTOM) + backBtn.setText("返回") + + backBtn.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class BackDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + t.close(); + return true; + } + } + backBtn.setOnTouchListener(new BackDomClickListsner()) + titleView!.addView(backBtn) + + + + continaer.addView(boxWrapParent) + continaer.addView(footerWrap) + + parentView!.addView(continaer) + parentView!.addView(titleView) + decorView.addView(parentView!) + + // 增加动画 + try { + let s0 = (0).toFloat() + let s1 = (1).toFloat() + parentView!.setAlpha(s0) + parentView!.setScaleX(s0) + parentView!.setScaleY(s0) + + + let ani = parentView!.animate() as ViewPropertyAnimator; + ani.alpha(s1) + .scaleX(s1) + .scaleY(s1) + .setDuration(250) + .start() + + } catch (e) { + //TODO handle the exception + } + } + // 设置图片上的小圆的识别位置。 + setImageViewRusletBox(jieguo : SCANNING_PHOTO_RESULT) { + let t = this; + let btnwidth = 100; + let btnwidth2 = 50; + + for (let i = 0; i < jieguo.bounds.length; i++) { + let item = jieguo.bounds[i]; + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + let x = item.centerX + let y = item.centerY + + layoutParams.topMargin = (y - btnwidth2).toInt() // 设置顶部边距 + layoutParams.leftMargin = (x - btnwidth2).toInt() // 设置左边距 + let relativeLayout = new RelativeLayout(t.context) + relativeLayout.layoutParams = layoutParams + + const rtxt = jieguo.text[i] + let v = new xView(t.context) + v.setSize(btnwidth, btnwidth) + .setRadius(100) + .setBackgroundColor('#21d429') + .setBorder(12, "#ffffff", false) + .setClick((event : MotionEvent) => { + try { + // t.callFunEvent([rtxt], 'click') + t.callFunEvent(rtxt) + t.close() + } catch (e) { + //TODO handle the exception + } + }) + let ov = v.getView(); + + + // 创建缩放动画 + let scaleAnimation = new ScaleAnimation(1.0.toFloat(), 0.7.toFloat(), 1.0.toFloat(), 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat()); + scaleAnimation.setDuration(600); // 设置动画持续时间 + scaleAnimation.setRepeatMode(Animation.REVERSE); // 设置重复模式为反向 + scaleAnimation.setRepeatCount(Animation.INFINITE); // 设置重复次数为无限 + // 启动动画 + ov.startAnimation(scaleAnimation); + relativeLayout.addView(ov) + this.imgPointsBycanmarea.push(relativeLayout) + this.resultView!.addView(relativeLayout) + } + + + } + + + YUV42088ToNV21Copy(a:ByteBuffer,b:ByteBuffer,c:ByteBuffer,widths:number,heights:number,yr:number,ur:number,vr:number) : ByteArray { + // 获取图像的宽度、高度以及各平面的行间距 + let width = widths + let height = heights; + // 获取各平面的数据与信息 + + let yBuffer = a; + let uBuffer = b; + let vBuffer = c; + + yBuffer.rewind(); + uBuffer.rewind(); + vBuffer.rewind(); + + let yRowStride = yr; + let uvRowStride = ur; + let uvPixelStride = vr; // U 和 V 的像素间距通常是一样的 + + // 创建一个足够大的NV21输出数组 + let nv21Data = new ByteArray((width * height * 3 / 2).toInt()); + + // 指针用于遍历输出数组 + let yIndex = 0; + let uvIndex = width * height; + let bytesPerPixel = 1 + try { + // 遍历Y平面 + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + nv21Data[(yIndex++).toInt()] = yBuffer.get(); + } + // 跳过未使用的行数据(如果有) + let rowRemainder = yRowStride - width * bytesPerPixel; + + if (rowRemainder > 0) { + yBuffer.position((yBuffer.position() + rowRemainder).toInt()); + } else { + yBuffer.position((yBuffer.position() + width * bytesPerPixel).toInt()); // 防止由于计算错误导致的负数 + } + + } + } catch (e) { + //TODO handle the exception + } + // // 处理UV平面 + try { + for (let row = 0; row < height / 2; row++) { + for (let col = 0; col < width / 2; col++) { + // 先读取U分量 + nv21Data[(uvIndex++).toInt()] = uBuffer.get(); + // 如果UV像素不是交错存储,则跳过一个位置 + if (uvPixelStride == 2) { + uBuffer.position((uBuffer.position() + 1).toInt()); + } + + // 再读取V分量 + nv21Data[(uvIndex++).toInt()] = vBuffer.get(); + // 如果UV像素是交错存储,这里也需要相应调整位置 + if (uvPixelStride == 2) { + vBuffer.position((vBuffer.position() + 1).toInt()); + } + } + // 跳过未使用的行数据(如果有) + let uvRowSkip = uvRowStride - (width / 2) * uvPixelStride; + if (uvRowSkip > 0) { + uBuffer.position((uBuffer.position() + uvRowSkip).toInt()); + vBuffer.position((vBuffer.position() + uvRowSkip).toInt()); + } + } + } catch (e) { + //TODO handle the exception + } + return nv21Data; + } + + copyImagePlan(plane:Plane):ByteBuffer{ + // 创建一个新的ByteBuffer来存储复制的数据 + let copiedBuffer = ByteBuffer.allocateDirect(plane.getBuffer().capacity()); + copiedBuffer.order(ByteOrder.nativeOrder()); // 确保字节顺序与原Buffer一致 + + // 将原始Plane的ByteBuffer内容复制到新的ByteBuffer中 + plane.getBuffer().rewind(); // 移动缓冲区指针到开始位置(可选,如果已经知道在开始处则无需此步) + copiedBuffer.put(plane.getBuffer()); + + // 复制完成后,可以移动新ByteBuffer的指针回到起始位置以便读取 + copiedBuffer.rewind(); + + return copiedBuffer + } + getCorrectionMatrixByimgUri(imgView : ImageView, previewView : PreviewView,rotationDegrees:number) : Matrix { + + let matrix = new Matrix() + let imgWidt = imgView.drawable!.intrinsicWidth as number + let imgHeight = imgView.drawable!.intrinsicHeight as number + let d0 = (0).toFloat() + let source = floatArrayOf( + d0, + d0, + imgWidt.toFloat(), + d0, + imgWidt.toFloat(), + imgHeight.toFloat(), + d0, + imgHeight.toFloat() + ) + + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf( + d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat() + ) + + + let vertexSize = 2 + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + getCorrectionMatrix(imageProxy : ImageProxy, previewView : PreviewView) : Matrix { + let cropRect = imageProxy.cropRect + let rotationDegrees = imageProxy.imageInfo.rotationDegrees + let matrix = new Matrix() + + // A float array of the source vertices (crop rect) in clockwise order. + + let source = floatArrayOf( + cropRect.left.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.bottom.toFloat(), + cropRect.left.toFloat(), + cropRect.bottom.toFloat() + ) + let d0 = (0).toFloat() + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf( + d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat() + ) + + + let vertexSize = 2 + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + + + calcPoint(imgView : ImageView, previewView : PreviewView, image_point_x : number, image_point_y : number,degration:number) : ConverXy { + + const image_w = imgView.drawable!.intrinsicWidth as number + const image_h = imgView.drawable!.intrinsicHeight as number + const c_w = previewView.width; + const c_h = previewView.height; + + function scaleAndCenterContent( + container : contaiaSize, + content : contaiaSize + ) : contaiaCalseSize { + // 计算缩放比例 + const scaleWidth = container.width / content.width; + const scaleHeight = container.height / content.height; + const scale = Math.min(scaleWidth, scaleHeight); + + // 计算居中偏移量 + const offsetX = (container.width - content.width * scale) / 2; + const offsetY = (container.height - content.height * scale) / 2; + + return { scale, offsetX, offsetY } as contaiaCalseSize; + } + function mapContentCoordinatesToContainer( + contentX : number, + contentY : number, + calcsize : contaiaCalseSize + ) : contaiPointXy { + // 映射内容层坐标到容器层坐标 + const containerX = contentX * calcsize.scale + calcsize.offsetX; + const containerY = contentY * calcsize.scale + calcsize.offsetY; + + return { x: containerX, y: containerY } as contaiPointXy; + } + + let rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_h, height: image_w } as contaiaSize + ) + if(degration==0){ + rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_w, height: image_h } as contaiaSize + ) + } + + let result = mapContentCoordinatesToContainer(image_point_y, image_point_x, rc) + if(degration==0){ + result = mapContentCoordinatesToContainer(image_point_x,image_point_y,rc) + } + let nexyxcov = { + x: c_w - result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + if(degration==0){ + nexyxcov = { + x: result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + } + return nexyxcov + + } + + qrDecoder(img : ImageProxy) { + let t = this; + let image = img.getImage(); + if (!this.isDecoderQring&&image!=null&&t.isOpeningCameraing) { + this.isDecoderQring = true; + let width = image.getWidth(); + let height = image.getHeight(); + + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + + let a = this.copyImagePlan(planes[0]); + let b = this.copyImagePlan(planes[1]); + let c = this.copyImagePlan(planes[2]); + let yr = planes[0].getRowStride() + let ur = planes[1].getRowStride() + let vr = planes[1].getPixelStride() + + let starttime = new Date().getTime() + + let av = this.YUV42088ToNV21Copy(a,b,c,width,height,yr,ur,vr) + let rotationDegrees = img.imageInfo.rotationDegrees + + decoderBuffToQr(av, width, height, 0) + .then((res) => { + if (res != null ) { + let matrix = t.getCorrectionMatrix(img, t.cameraView!) + if (res.text.length > 0) { + let ruslt = res as SCANNING_PHOTO_RESULT; + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + let ponit = floatArrayOf(item.centerX.toFloat(), item.centerY.toFloat()) + // let xy = t.covertXy(img, t.cameraView!,item.centerX,item.centerY); + matrix.mapPoints(ponit) + item.centerX = ponit[0] + item.centerY = ponit[1] + // item.centerX = xy[0] + // item.centerY = xy[1] + // console.log(item.centerX ,item.centerY) + + } + if(ruslt.text.length>0){ + t.setVibatar() + } + t.setImageViewRusletBox(ruslt) + t.closeCamera() + if (ruslt.text.length == 1) { + t.callFunEvent(ruslt.text[0]) + t.close() + } + }else{ + t.isDecoderQring = false + } + } + // image.close(); + }) + .catch(() => { + t.isDecoderQring = false + }) + } + img.close(); + } + + + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx copy 1.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx copy 1.uts new file mode 100644 index 0000000..557efe0 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx copy 1.uts @@ -0,0 +1,936 @@ +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' + + +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import ViewGroup from 'android.view.ViewGroup' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; +import R from 'io.dcloud.uni_modules.xMlkitScannigS.R'; +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import Bundle from 'android.os.Bundle' +import Handler from 'android.os.Handler' +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import { decoderUriPathToQr, decoderBuffToQr,decoderUriPathToQrByUri } from "./index.uts" +import { SCANNING_PHOTO_RESULT } from "../interface.uts" +import xView from "./libview/view.uts" +import Gravity from 'android.view.Gravity'; + +// x +import ProcessCameraProvider from "androidx.camera.lifecycle.ProcessCameraProvider" +import PreviewView from "androidx.camera.view.PreviewView" +import CameraController from "androidx.camera.view.CameraController" +import CameraSelector from "androidx.camera.core.CameraSelector" +import Preview from 'androidx.camera.core.Preview' +import Camera from 'androidx.camera.core.Camera' +import LifecycleObserver from "androidx.lifecycle.LifecycleObserver" +import LifecycleOwner from "androidx.lifecycle.LifecycleOwner" +import OnLifecycleEvent from "androidx.lifecycle.OnLifecycleEvent" +import ImageAnalysis from 'androidx.camera.core.ImageAnalysis' +import ImageProxy from 'androidx.camera.core.ImageProxy' +import NonNull from 'androidx.annotation.NonNull' +import ExecutorService from 'java.util.concurrent.ExecutorService' +import Executors from 'java.util.concurrent.Executors' +import ContextCompat from 'androidx.core.content.ContextCompat'; +import LifecycleRegistry from "androidx.lifecycle.LifecycleRegistry" +import Lifecycle from "androidx.lifecycle.Lifecycle" + + +type Dimension = number[]; +let textStr = null as null | string +function findClosestRatio(dimensions : Dimension[], targetWidth : number, targetHeight : number) : Dimension | null { + let minDiff = Integer.MAX_VALUE; + let closestPair : Dimension | null = null; + + for (let i = 0; i < dimensions.length; i++) { + const width = dimensions[i][0]! + const height = dimensions[i][1]! + const currentRatio = width / height; + const targetRatio = targetWidth / targetHeight; + + // const diff = Math.abs(currentRatio - targetRatio); + const diff = Math.abs(width - targetWidth) + Math.abs(height - targetHeight); + if (diff < minDiff) { + minDiff = diff.toInt(); + closestPair = [width, height]; + } + } + + return closestPair; +} + + + +class DemoActivity extends Activity implements LifecycleOwner { + scanSpeed = 500 //识别速度单位ms + scanPrevwSize = 800 //预期识别的像素大小,这是预期,会根据这个值找到相机支持的相近的相机尺寸。 + lifecycleRegistry:LifecycleRegistry|null = null + context : Context; + camera_service : CameraManager; + cameraPermissioPass = false; + camerManIds = null as string | null + cameraDevice = null as null | CameraDevice + preview = null as null | LinearLayout; + captureSession = null as null | CameraCaptureSession + + // 相机区域视图 + cameraView : PreviewView | null = null; + cameraProvider : ProcessCameraProvider | null = null + camera : Camera | null = null; + cameraPreview : Preview | null = null; + + + + previewWidth = 0 as Int; + previewHeight = 0 as Int; + prviewTop = 0 + prviewLeft = 0 + okScal = [0, 0] as Dimension + imageHandler = null as null | Handler; + + isDecodreIng = false + + scanBoxView = null as null | View + scanBoxViewDrawble = null as null | GradientDrawable + //选择相册按钮 + xiangCeBtn = null as TextView | null + paiZhaoBtn = null as TextView | null + shaoyishaoBtn = null as TextView | null + + //相册的标识点容器 + xiangjiBox = null as RelativeLayout | null + + //相册图片预览父viewout + imageYuranBox = null as RelativeLayout | null + imageYuranBox_width = 0 as Int; + imageYuranBox_height = 0 as Int; + imageView = null as null | ImageView + imageUrl = null as null | Uri + isSelectedImging = false; + + // 结果集的标注点。 + imgPoints = [] as RelativeLayout[] + imgPointsBycanmarea = [] as RelativeLayout[] + + ORIENTATIONS = new Map() + // 当前是否正在扫码中 + isScannig = true + + tid = 0; + + vibrator = null as null|Vibrator + + constructor() { + super(); + this.context = UTSAndroid.getAppContext() as Context; + this.camera_service = this.context!.getSystemService(Context.CAMERA_SERVICE) as CameraManager + this.ORIENTATIONS.set(Surface.ROTATION_0, 0) + this.ORIENTATIONS.set(Surface.ROTATION_90, 90) + this.ORIENTATIONS.set(Surface.ROTATION_180, 180) + this.ORIENTATIONS.set(Surface.ROTATION_270, 270) + + // 在你的Activity或者Fragment中 + this.vibrator = this.context!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + + + } + + + override onCreate(savedInstanceState ?: Bundle) : void { + super.onCreate(savedInstanceState) + this.lifecycleRegistry = new LifecycleRegistry(this); + this.lifecycleRegistry!.markState(Lifecycle.State.CREATED); + + this.hideTitleBar() + this.setContentView(R.layout.demo_activity); + + this.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + + this.preview = this.findViewById(R.id.surface_camera_box); + this.preview!.removeView(this.findViewById(R.id.surface_camera)) + + this.xiangCeBtn = this.findViewById(R.id.footer_asml); + this.paiZhaoBtn = this.findViewById(R.id.footer_camre); + this.shaoyishaoBtn = this.findViewById(R.id.footer_scanning); + //相机的图片预览 + this.imageYuranBox = this.findViewById(R.id.scan_box); + //相机的遮罩标记点的容器 + + + this.xiangjiBox = this.findViewById(R.id.camre_center_preview) + + let t = this; + + + this.steBtnLisents() + + + // 创建图片预览的组件。 + this.imageView = new ImageView(this.context); + this.imageView!.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) + this.imageYuranBox!.addView(this.imageView) + + + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + + this._createCameraView() + + + //监听尺寸变化。 + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.imageYuranBox_width = right - left; + t.imageYuranBox_height = bottom - top; + v.removeOnLayoutChangeListener(this); + } + } + this.imageYuranBox!.addOnLayoutChangeListener(new previewChangeRectadd()) + + + // this.scanBoxView = this.findViewById(R.id.scan_view_canvas); + // this.scanBoxViewDrawble = new GradientDrawable(); + // this.scanBoxView.setOnDragListener + // this.customStyleSacnBox(); + + } + + /** 创建相机预览区域 */ + private _createCameraView() { + + let sv = new PreviewView(this.context) + sv.scaleType = PreviewView.ScaleType.FILL_CENTER + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + + this.preview!.addView(this.cameraView!) + } + + steBtnLisents() { + let t = this; + class xiangCheCallClick extends View.OnClickListener { + override onClick(v ?: View) : void { + t.closeCamra() + t.isSelectedImging = true; + + let intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + t.startActivityForResult(intent, 1) + } + } + // 相同选择时。 + this.xiangCeBtn!.setOnClickListener(new xiangCheCallClick()) + + + class shaoyishaoBtnCallClick extends View.OnClickListener { + override onClick(v ?: View) : void { + t.isSelectedImging = false; + t.clearImageView() + t.openCamra(); + } + } + //实时扫一扫时 + this.shaoyishaoBtn!.setOnClickListener(new shaoyishaoBtnCallClick()) + + let backBtn = this.findViewById(R.id.header_back); + + class backCallClick extends View.OnClickListener { + override onClick(v ?: View) : void { + t.finish() + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } + } + //实时扫一扫时 + backBtn!.setOnClickListener(new backCallClick()) + + } + // 设置扫码框的样式。 + customStyleSacnBox() { + if (this.scanBoxView == null) return; + // this.scanBoxViewDrawble!.setShape(GradientDrawable.RECTANGLE) + // this.scanBoxViewDrawble!.setStroke((4).toInt(),Color.GREEN) + // this.scanBoxViewDrawble!.mutate() + // this.scanBoxView!.setBackground(this!.scanBoxViewDrawble) + } + //震动手机 + vibatarLong(){ + if(this.vibrator == null) return + // 检查设备是否支持震动 + if (this.vibrator!.hasVibrator()) { + // 触发短暂的震动,持续时间为200毫秒 + this.vibrator!.vibrate(80); + } + } + + // 在需要隐藏标题栏的地方调用 + hideTitleBar() : void { + requestWindowFeature(Window.FEATURE_NO_TITLE); + this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + // 在需要显示标题栏的地方调用 + showTitleBar() : void { + this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + /** + * 检查相机权限 + */ + isCheckPermissions() : Promise { + let permissionCheck = ["android.permission.CAMERA"] + // 请求拍照权限 + return new Promise(res => { + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + console.log("当前已具备指定权限") + this.cameraPermissioPass = true + res(true) + } else { + console.log("当前不具备指定权限") + // 请求拍照权限 + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (allRight : boolean, _ : string[]) { + this.cameraPermissioPass = allRight + res(true) + }, function (_ : boolean, _ : string[]) { + //用户拒绝了部分权限 + this.cameraPermissioPass = false + res(false) + }) + } + }) + } + + + + // 设置相机对焦模式 + // setCamraFoucsAuto(){ + // let cameraManager = this.getSystemService(Context.CAMERA_SERVICE) as CameraManager + // let characteristics = cameraManager.getCameraCharacteristics(this.camerManIds!) + // // console.log(CaptureRequest.CONTROL_AF_MODE) + // captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_VIDEO); + // } + // 获取当前相机的旋转角度。 + getCamraRotation() : Int { + + return 0 + } + + YUV42088ToNV21(image : Image) : ByteArray { + // 获取图像的宽度、高度以及各平面的行间距 + let width = image.getWidth(); + let height = image.getHeight(); + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + let yBuffer = planes[0].getBuffer().duplicate(); + let uBuffer = planes[1].getBuffer().duplicate(); + let vBuffer = planes[2].getBuffer().duplicate(); + + yBuffer.rewind(); + uBuffer.rewind(); + vBuffer.rewind(); + + + let yRowStride = planes[0].getRowStride(); + let uvRowStride = planes[1].getRowStride(); + let uvPixelStride = planes[1].getPixelStride(); // U 和 V 的像素间距通常是一样的 + + // 创建一个足够大的NV21输出数组 + let nv21Data = new ByteArray(width * height * 3 / 2); + + // 指针用于遍历输出数组 + let yIndex = 0; + let uvIndex = width * height; + let bytesPerPixel = 1 + try { + // 遍历Y平面 + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + nv21Data[(yIndex++).toInt()] = yBuffer.get(); + } + // 跳过未使用的行数据(如果有) + let rowRemainder = yRowStride - width * bytesPerPixel; + + if (rowRemainder > 0) { + yBuffer.position((yBuffer.position() + rowRemainder).toInt()); + } else { + yBuffer.position((yBuffer.position() + width * bytesPerPixel).toInt()); // 防止由于计算错误导致的负数 + } + + } + } catch (e) { + //TODO handle the exception + } + // // 处理UV平面 + try { + for (let row = 0; row < height / 2; row++) { + for (let col = 0; col < width / 2; col++) { + // 先读取U分量 + nv21Data[uvIndex++] = uBuffer.get(); + // 如果UV像素不是交错存储,则跳过一个位置 + if (uvPixelStride == 2) { + uBuffer.position(uBuffer.position() + 1); + } + + // 再读取V分量 + nv21Data[uvIndex++] = vBuffer.get(); + // 如果UV像素是交错存储,这里也需要相应调整位置 + if (uvPixelStride == 2) { + vBuffer.position(vBuffer.position() + 1); + } + } + // 跳过未使用的行数据(如果有) + let uvRowSkip = uvRowStride - (width / 2) * uvPixelStride; + if (uvRowSkip > 0) { + uBuffer.position(uBuffer.position() + uvRowSkip); + vBuffer.position(vBuffer.position() + uvRowSkip); + } + } + } catch (e) { + //TODO handle the exception + } + return nv21Data; + } + + YUV42088ToNV21Copy(a:ByteBuffer,b:ByteBuffer,c:ByteBuffer,widths:number,heights:number,yr:number,ur:number,vr:number) : ByteArray { + // 获取图像的宽度、高度以及各平面的行间距 + let width = widths + let height = heights; + // 获取各平面的数据与信息 + + let yBuffer = a; + let uBuffer = b; + let vBuffer = c; + + yBuffer.rewind(); + uBuffer.rewind(); + vBuffer.rewind(); + + let yRowStride = yr; + let uvRowStride = ur; + let uvPixelStride = vr; // U 和 V 的像素间距通常是一样的 + + // 创建一个足够大的NV21输出数组 + let nv21Data = new ByteArray((width * height * 3 / 2).toInt()); + + // 指针用于遍历输出数组 + let yIndex = 0; + let uvIndex = width * height; + let bytesPerPixel = 1 + try { + // 遍历Y平面 + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + nv21Data[(yIndex++).toInt()] = yBuffer.get(); + } + // 跳过未使用的行数据(如果有) + let rowRemainder = yRowStride - width * bytesPerPixel; + + if (rowRemainder > 0) { + yBuffer.position((yBuffer.position() + rowRemainder).toInt()); + } else { + yBuffer.position((yBuffer.position() + width * bytesPerPixel).toInt()); // 防止由于计算错误导致的负数 + } + + } + } catch (e) { + //TODO handle the exception + } + // // 处理UV平面 + try { + for (let row = 0; row < height / 2; row++) { + for (let col = 0; col < width / 2; col++) { + // 先读取U分量 + nv21Data[(uvIndex++).toInt()] = uBuffer.get(); + // 如果UV像素不是交错存储,则跳过一个位置 + if (uvPixelStride == 2) { + uBuffer.position((uBuffer.position() + 1).toInt()); + } + + // 再读取V分量 + nv21Data[(uvIndex++).toInt()] = vBuffer.get(); + // 如果UV像素是交错存储,这里也需要相应调整位置 + if (uvPixelStride == 2) { + vBuffer.position((vBuffer.position() + 1).toInt()); + } + } + // 跳过未使用的行数据(如果有) + let uvRowSkip = uvRowStride - (width / 2) * uvPixelStride; + if (uvRowSkip > 0) { + uBuffer.position((uBuffer.position() + uvRowSkip).toInt()); + vBuffer.position((vBuffer.position() + uvRowSkip).toInt()); + } + } + } catch (e) { + //TODO handle the exception + } + return nv21Data; + } + + copyImagePlan(plane:Plane):ByteBuffer{ + // 创建一个新的ByteBuffer来存储复制的数据 + let copiedBuffer = ByteBuffer.allocateDirect(plane.getBuffer().capacity()); + copiedBuffer.order(ByteOrder.nativeOrder()); // 确保字节顺序与原Buffer一致 + + // 将原始Plane的ByteBuffer内容复制到新的ByteBuffer中 + plane.getBuffer().rewind(); // 移动缓冲区指针到开始位置(可选,如果已经知道在开始处则无需此步) + copiedBuffer.put(plane.getBuffer()); + + // 复制完成后,可以移动新ByteBuffer的指针回到起始位置以便读取 + copiedBuffer.rewind(); + + return copiedBuffer + } + getCorrectionMatrix(imageProxy : ImageProxy, previewView : PreviewView) : Matrix { + let cropRect = imageProxy.cropRect + let rotationDegrees = imageProxy.imageInfo.rotationDegrees + let matrix = new Matrix() + + // A float array of the source vertices (crop rect) in clockwise order. + new FloatArray(8) + let source = floatArrayOf(cropRect.left.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.bottom.toFloat(), + cropRect.left.toFloat(), + cropRect.bottom.toFloat()) + + let d0 = (0).toFloat() + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf(d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat()) + + // The destination vertexes need to be shifted based on rotation degrees. The + // rotation degree represents the clockwise rotation needed to correct the image. + + // Each vertex is represented by 2 float numbers in the vertices array. + let vertexSize = 2 + // The destination needs to be shifted 1 vertex for every 90° rotation. + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + + qrDecoder(img : ImageProxy) { + let t = this; + let image = img.getImage(); + if (!this.isDecodreIng&&image!=null) { + this.isDecodreIng = true; + let width = image.getWidth(); + let height = image.getHeight(); + + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + + let a = this.copyImagePlan(planes[0]); + let b = this.copyImagePlan(planes[1]); + let c = this.copyImagePlan(planes[2]); + let yr = planes[0].getRowStride() + let ur = planes[1].getRowStride() + let vr = planes[1].getPixelStride() + + let starttime = new Date().getTime() + + let av = this.YUV42088ToNV21Copy(a,b,c,width,height,yr,ur,vr) + decoderBuffToQr(av, width, height, this.getCamraRotation()) + .then((res) => { + if (res != null&&t.isScannig ) { + let matrix = t.getCorrectionMatrix(img, t.cameraView!) + if (res.text.length > 0) { + t.vibatarLong() + + + + let ruslt = res as SCANNING_PHOTO_RESULT; + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + let ponit = floatArrayOf(item.centerX.toFloat(), item.centerY.toFloat()) + + matrix.mapPoints(ponit) + + item.centerX = ponit[0] + item.centerY = ponit[1] + + } + + t.setImageViewRusletBox(t.previewWidth, t.previewWidth, width, height, ruslt) + uni.setStorageSync('xMlkitScannigUResult_time_start', 'end:'+(new Date().getTime() - starttime).toString()+'ms') + t.closeCamra() + + + if (ruslt.text.length == 1) { + uni.setStorageSync('xMlkitScannigUResult', ruslt.text[0]) + t.finish(); + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } + + } + } + // image.close(); + }) + .catch(() => { + // this.imageUrl = null + }) + setTimeout(function () { + this.isDecodreIng = false + }, this.scanSpeed); + + } + img.close(); + } + closeCamra() { + + + + this.cameraProvider?.unbindAll() + this.cameraPreview?.setSurfaceProvider(null) + + + + this.clearImageView() + + } + + openCamra() { + let t = this; + if (this.captureSession != null) { + return; + } + + if (t.previewWidth == 0) { + //监听尺寸变化。 + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.previewWidth = right - left; + t.previewHeight = bottom - top; + t.prviewTop = top + t.prviewLeft = left + v.removeOnLayoutChangeListener(this); + t.isCheckPermissions() + .then(() => { + let layoutParams = t.preview!.getLayoutParams() as ViewGroup.LayoutParams + layoutParams.height = t.previewWidth + t.preview!.layoutParams = layoutParams; + + + + let layoutParamsbx = t.xiangjiBox!.getLayoutParams() as ViewGroup.LayoutParams + layoutParamsbx.height = t.previewWidth + t.xiangjiBox!.layoutParams = layoutParamsbx; + + + t.closeCamra(); + t.openCamrae(); + }) + } + } + + this.preview!.addOnLayoutChangeListener(new previewChangeRectadd()) + } else { + t.isScannig = true + t.closeCamra(); + t.openCamrae(); + } + } + + // 设置图片上的小圆的识别位置。 + setImageViewRusletBox(width : number, height : number, realWidth : number, realHeight : number, jieguo : SCANNING_PHOTO_RESULT) { + let t = this; + let wRatio = width / realWidth; + let hRatio = height / realHeight; + let btnwidth = 100; + let btnwidth2 = 50; + + this.imageYuranBox!.setBackgroundColor(Color.argb(0,0,0,0)) + this.xiangjiBox!.setBackgroundColor(Color.argb(0,0,0,0)) + for (let i = 0; i < jieguo.bounds.length; i++) { + let item = jieguo.bounds[i]; + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + + if (this.isScannig) { + layoutParams.topMargin = (item.centerY- btnwidth2).toInt() // 设置顶部边距 + layoutParams.leftMargin = (item.centerX- btnwidth2).toInt() // 设置左边距 + } else { + layoutParams.topMargin = (hRatio * item.centerY-btnwidth2).toInt() // 设置顶部边距 + layoutParams.leftMargin = (wRatio * item.centerX-btnwidth2).toInt() // 设置左边距 + } + let relativeLayout = new RelativeLayout(t.context) + relativeLayout.layoutParams = layoutParams + + const rtxt = jieguo.text[i] + + + let v = new xView(t.context) + v.setSize(btnwidth , btnwidth) + .setRadius(100) + .setBackgroundColor('#21d429') + .setBorder(12, "#ffffff", false) + .setClick((event : MotionEvent) => { + try { + uni.setStorageSync('xMlkitScannigUResult', rtxt) + t.finish() + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } catch (e) { + //TODO handle the exception + } + }) + let ov = v.getView(); + + + // 创建缩放动画 + let scaleAnimation = new ScaleAnimation(1.0.toFloat(), 0.7.toFloat(), 1.0.toFloat(), 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat()); + scaleAnimation.setDuration(600); // 设置动画持续时间 + scaleAnimation.setRepeatMode(Animation.REVERSE); // 设置重复模式为反向 + scaleAnimation.setRepeatCount(Animation.INFINITE); // 设置重复次数为无限 + // 启动动画 + ov.startAnimation(scaleAnimation); + + + relativeLayout.addView(v.getView()) + if (this.isScannig) { + this.xiangjiBox!.addView(relativeLayout) + this.imgPointsBycanmarea.push(relativeLayout) + this.xiangjiBox!.setBackgroundColor(Color.argb(100,0,0,0)) + + + } else { + this.imageYuranBox!.addView(relativeLayout) + this.imgPoints.push(relativeLayout) + this.imageYuranBox!.setBackgroundColor(Color.argb(100,0,0,0)) + } + + } + + + } + + clearImageView() { + for (let i = 0; i < this.imgPointsBycanmarea.length; i++) { + this.xiangjiBox!.removeView(this.imgPointsBycanmarea[i]) + } + for (let i = 0; i < this.imgPoints.length; i++) { + this.imageYuranBox!.removeView(this.imgPoints[i]) + } + if (!this.isScannig) { + this.imageView!.setImageDrawable(null) + } + + } + override onActivityResult(requestCode : Int, resultCode : Int, data ?: Intent) { + super.onActivityResult(requestCode, resultCode, data) + let t = this; + if (resultCode == Activity.RESULT_OK && data != null && data?.data != null) { + let selectedImageUri = data.data! + this.imageUrl = selectedImageUri + this.isSelectedImging = false + decoderUriPathToQrByUri(this.imageUrl!,(res:SCANNING_PHOTO_RESULT)=>{ + t.isScannig = false + t.clearImageView(); + t.imageView!.setImageURI(t.imageUrl!); + let reaLwidth = t.imageView!.drawable?.intrinsicWidth; + let reaLheight = t.imageView!.drawable?.intrinsicHeight; + + if (reaLwidth != null && reaLheight != null) { + t.vibatarLong() + t.setImageViewRusletBox(t.imageView!.width, t.imageView!.height, reaLwidth!, reaLheight!, res!) + if (res.text.length == 1) { + uni.setStorageSync('xMlkitScannigUResult', res.text[0]) + t.finish() + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } + } + + }) + + } else { + this.isSelectedImging = false + + } + } + + override onStart() { + super.onStart(); + lifecycleRegistry!.markState(Lifecycle.State.STARTED); + } + + override onDestroy() : void { + super.onDestroy(); + this.closeCamra() + this.showTitleBar(); + } + + override onStop() { + lifecycleRegistry!.markState(Lifecycle.State.CREATED); + super.onStop(); + } + + + override onPause() : void { + super.onPause(); + lifecycleRegistry!.markState(Lifecycle.State.CREATED); + console.log("暂停扫码") + this.closeCamra() + } + + override onResume() : void { + super.onResume(); + lifecycleRegistry!.markState(Lifecycle.State.RESUMED); + let t = this; + if (this.captureSession != null || t.imageUrl != null || t.isSelectedImging) { + return; + } + console.log("恢复扫码") + this.closeCamra() + this.openCamra(); + + } + override getLifecycle(): Lifecycle { + return this.lifecycleRegistry! + } + openCamrae() { + let _this = this; + + let cameraProviderFuture = ProcessCameraProvider.getInstance(this.context) + + class IntentRunable extends Runnable { + override run() { + let cameraProvider : ProcessCameraProvider = cameraProviderFuture.get() + let previewView = _this.cameraView! as PreviewView + let cameraSelector : CameraSelector = new CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + let preview : Preview = new Preview.Builder().build(); + + preview.setSurfaceProvider(previewView.getSurfaceProvider()) + + let imageAnalysis = new ImageAnalysis.Builder() + // .setTargetResolution(new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt())) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + class MyImageAnalyzer implements ImageAnalysis.Analyzer { + constructor() { + super() + } + override analyze(image : ImageProxy) { + _this.qrDecoder(image) + } + override getDefaultTargetResolution() : Size { + return new Size(_this.previewWidth.toInt(), _this.previewHeight.toInt()); + } + + } + let cameraExecutor = Executors.newSingleThreadExecutor(); + imageAnalysis.setAnalyzer(cameraExecutor, new MyImageAnalyzer()); + let camera : Camera = cameraProvider.bindToLifecycle( + _this as LifecycleOwner, cameraSelector, preview, imageAnalysis); + + _this.camera = camera + _this.cameraPreview = preview + + _this.cameraProvider = cameraProvider + _this.isDecodreIng = false + _this.isScannig = true + + + } + } + + cameraProviderFuture.addListener(new IntentRunable(), ContextCompat.getMainExecutor(this.context)) + } +} + + +@Suppress("DEPRECATION") +class IntentRunable extends Runnable { + override run() { + let intent = new Intent(UTSAndroid.getUniActivity(), DemoActivity().javaClass); + UTSAndroid.getUniActivity()!.startActivityForResult(intent,1); + } +} + +@Suppress("DEPRECATION") +export function gotoDemoActivity() : boolean { + // 跳转到一个新的界面 + UTSAndroid.getUniActivity()!.runOnUiThread(new IntentRunable()) + return true; + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx copy.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx copy.uts new file mode 100644 index 0000000..aa98cf3 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx copy.uts @@ -0,0 +1,979 @@ +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' + + +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import ViewGroup from 'android.view.ViewGroup' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; +import R from 'io.dcloud.uni_modules.xMlkitScannigS.R'; +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import Bundle from 'android.os.Bundle' +import Handler from 'android.os.Handler' +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import { decoderUriPathToQr, decoderBuffToQr,decoderUriPathToQrByUri } from "./index.uts" +import { SCANNING_PHOTO_RESULT } from "../interface.uts" +import xView from "./libview/view.uts" + +type Dimension = number[]; +let textStr = null as null | string +function findClosestRatio(dimensions : Dimension[], targetWidth : number, targetHeight : number) : Dimension | null { + let minDiff = Integer.MAX_VALUE; + let closestPair : Dimension | null = null; + + for (let i = 0; i < dimensions.length; i++) { + const width = dimensions[i][0]! + const height = dimensions[i][1]! + const currentRatio = width / height; + const targetRatio = targetWidth / targetHeight; + + // const diff = Math.abs(currentRatio - targetRatio); + const diff = Math.abs(width - targetWidth) + Math.abs(height - targetHeight); + if (diff < minDiff) { + minDiff = diff.toInt(); + closestPair = [width, height]; + } + } + + return closestPair; +} + + + +class DemoActivity extends Activity { + scanSpeed = 500 //识别速度单位ms + scanPrevwSize = 800 //预期识别的像素大小,这是预期,会根据这个值找到相机支持的相近的相机尺寸。 + + context : Context; + camera_service : CameraManager; + cameraPermissioPass = false; + camerManIds = null as string | null + cameraDevice = null as null | CameraDevice + preview = null as null | SurfaceView; + captureSession = null as null | CameraCaptureSession + + previewWidth = 0 as Int; + previewHeight = 0 as Int; + prviewTop = 0 + prviewLeft = 0 + okScal = [0, 0] as Dimension + imageHandler = null as null | Handler; + + isDecodreIng = false + + scanBoxView = null as null | View + scanBoxViewDrawble = null as null | GradientDrawable + //选择相册按钮 + xiangCeBtn = null as TextView | null + paiZhaoBtn = null as TextView | null + shaoyishaoBtn = null as TextView | null + + //相册的标识点容器 + xiangjiBox = null as RelativeLayout | null + + //相册图片预览父viewout + imageYuranBox = null as RelativeLayout | null + imageYuranBox_width = 0 as Int; + imageYuranBox_height = 0 as Int; + imageView = null as null | ImageView + imageUrl = null as null | Uri + isSelectedImging = false; + + // 结果集的标注点。 + imgPoints = [] as RelativeLayout[] + imgPointsBycanmarea = [] as RelativeLayout[] + + ORIENTATIONS = new Map() + // 当前是否正在扫码中 + isScannig = true + + tid = 0; + + vibrator = null as null|Vibrator + + constructor() { + super(); + this.context = UTSAndroid.getAppContext() as Context; + this.camera_service = this.context!.getSystemService(Context.CAMERA_SERVICE) as CameraManager + this.ORIENTATIONS.set(Surface.ROTATION_0, 0) + this.ORIENTATIONS.set(Surface.ROTATION_90, 90) + this.ORIENTATIONS.set(Surface.ROTATION_180, 180) + this.ORIENTATIONS.set(Surface.ROTATION_270, 270) + + // 在你的Activity或者Fragment中 + this.vibrator = this.context!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + + + } + + + override onCreate(savedInstanceState ?: Bundle) : void { + super.onCreate(savedInstanceState) + this.hideTitleBar() + this.setContentView(R.layout.demo_activity); + + this.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + + this.preview = this.findViewById(R.id.surface_camera); + this.xiangCeBtn = this.findViewById(R.id.footer_asml); + this.paiZhaoBtn = this.findViewById(R.id.footer_camre); + this.shaoyishaoBtn = this.findViewById(R.id.footer_scanning); + //相机的图片预览 + this.imageYuranBox = this.findViewById(R.id.scan_box); + //相机的遮罩标记点的容器 + this.xiangjiBox = this.findViewById(R.id.camre_center_preview); + + let t = this; + + this.steBtnLisents() + + + // 创建图片预览的组件。 + this.imageView = new ImageView(this.context); + this.imageView!.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) + this.imageYuranBox!.addView(this.imageView) + + + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + + + + //监听尺寸变化。 + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.imageYuranBox_width = right - left; + t.imageYuranBox_height = bottom - top; + v.removeOnLayoutChangeListener(this); + } + } + this.imageYuranBox!.addOnLayoutChangeListener(new previewChangeRectadd()) + + + // this.scanBoxView = this.findViewById(R.id.scan_view_canvas); + // this.scanBoxViewDrawble = new GradientDrawable(); + // this.scanBoxView.setOnDragListener + // this.customStyleSacnBox(); + + } + steBtnLisents() { + let t = this; + class xiangCheCallClick extends View.OnClickListener { + override onClick(v ?: View) : void { + t.closeCamra() + t.isSelectedImging = true; + let intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + t.startActivityForResult(intent, 1) + } + } + // 相同选择时。 + this.xiangCeBtn!.setOnClickListener(new xiangCheCallClick()) + + + class shaoyishaoBtnCallClick extends View.OnClickListener { + override onClick(v ?: View) : void { + t.isSelectedImging = false; + t.clearImageView() + t.openCamra(); + } + } + //实时扫一扫时 + this.shaoyishaoBtn!.setOnClickListener(new shaoyishaoBtnCallClick()) + + let backBtn = this.findViewById(R.id.header_back); + + class backCallClick extends View.OnClickListener { + override onClick(v ?: View) : void { + t.finish() + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } + } + //实时扫一扫时 + backBtn!.setOnClickListener(new backCallClick()) + + } + // 设置扫码框的样式。 + customStyleSacnBox() { + if (this.scanBoxView == null) return; + // this.scanBoxViewDrawble!.setShape(GradientDrawable.RECTANGLE) + // this.scanBoxViewDrawble!.setStroke((4).toInt(),Color.GREEN) + // this.scanBoxViewDrawble!.mutate() + // this.scanBoxView!.setBackground(this!.scanBoxViewDrawble) + } + //震动手机 + vibatarLong(){ + if(this.vibrator == null) return + // 检查设备是否支持震动 + if (this.vibrator!.hasVibrator()) { + // 触发短暂的震动,持续时间为200毫秒 + this.vibrator!.vibrate(80); + } + } + + override onDestroy() : void { + super.onDestroy(); + if (this.captureSession != null) { + this.captureSession!.close(); + this.cameraDevice?.close() + this.captureSession = null; + this.cameraDevice = null; + console.log("关闭相机"); + + } + this.showTitleBar(); + } + + // 在需要隐藏标题栏的地方调用 + hideTitleBar() : void { + requestWindowFeature(Window.FEATURE_NO_TITLE); + this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + // 在需要显示标题栏的地方调用 + showTitleBar() : void { + this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + /** + * 检查相机权限 + */ + isCheckPermissions() : Promise { + let permissionCheck = ["android.permission.CAMERA"] + // 请求拍照权限 + return new Promise(res => { + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + console.log("当前已具备指定权限") + this.cameraPermissioPass = true + res(true) + } else { + console.log("当前不具备指定权限") + // 请求拍照权限 + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (allRight : boolean, _ : string[]) { + this.cameraPermissioPass = allRight + res(true) + }, function (_ : boolean, _ : string[]) { + //用户拒绝了部分权限 + this.cameraPermissioPass = false + res(false) + }) + } + }) + } + getCameraById() { + // const cameraIds = this.camera_service.cameraIdList + let caIds = null as null | string; + + for (id in this.camera_service.getCameraIdList()) { + let ps = this.camera_service.getCameraCharacteristics(id); + let facing = ps.get(CameraCharacteristics.LENS_FACING); + // 后置摄像头 + if (facing == CameraCharacteristics.LENS_FACING_BACK) { + caIds = id; + let rulest = null as Dimension | null + // 获取尺寸 + let maps = ps.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) + if (maps != null) { + let testSize = maps!.getOutputSizes(ImageFormat.JPEG) + let psdd = [] as Array + for (sz in testSize) { + let w = sz.getWidth() + let h = sz.getHeight() + psdd.push([w, h] as Dimension) + } + // console.log(psdd) + // 这里使用一个800*800视野区域图片大概64万像素的图片进行识别,这样可以提高性能减少手机识别的负担。 + let pd = findClosestRatio(psdd, this.scanPrevwSize, this.scanPrevwSize) + // 如果想要高清识别或者加缩小焦距(就景深远,视野大,就开启下面的) + // let pd = findClosestRatio(psdd, this.previewWidth, this.previewHeight) + if (pd != null) { + this.okScal = pd as Dimension; + } + } + + break; + } + + } + + this.camerManIds = caIds + // characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + + // console.log(this.camera_service.cameraIdList) + // this.camerListIds = this.camera_service.getCameraIdList(); + // for(let i=0;i cameraOutputHeight * previewWidth) { + // 裁剪高度为相机输出高度,根据宽高比计算裁剪宽度 + cropHeight = cameraOutputHeight + cropWidth = (cropHeight * targetAspectRatio) + cropWidth = Math.min(cropWidth, cameraOutputWidth) + } else { + // 裁剪宽度为相机输出宽度,根据宽高比计算裁剪高度 + cropWidth = cameraOutputWidth + cropHeight = (cropWidth / targetAspectRatio) + cropHeight = Math.min(cropHeight, cameraOutputHeight) + } + + // 计算居中对齐的裁剪区域 + let centerX = (cameraOutputWidth - cropWidth) / 2 + let centerY = (cameraOutputHeight - cropHeight) / 2 + + return Rect( + centerX.toInt(), // 左边界 + centerY.toInt(), // 上边界 + (centerX + cropWidth).toInt(), // 右边界 + (centerY + cropHeight).toInt() // 下边界 + ) + } + + + createCameraPreviewSession() { + if (this.preview == null) return; + let holder = this.preview!.getHolder() + let suface = holder!.getSurface(); + if (this.cameraDevice == null) return; + let t = this; + let previewRequestBuilder = this.cameraDevice!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) + previewRequestBuilder?.addTarget(suface) + let totalWidth = this.okScal[0].toInt() + let totalHeight = this.okScal[1].toInt() + + console.log(totalWidth,totalHeight) + previewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, totalWidth*3, totalHeight*3)); + // previewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, this.calculateCropRegion(totalWidth, totalHeight, this.previewWidth, this.previewWidth)); + // 再添加一个image来预览 + let minh = Math.min(this.previewWidth, this.previewHeight) + let reader = ImageReader.newInstance(minh.toInt(), minh.toInt(), ImageFormat.YUV_420_888, 1) + previewRequestBuilder?.addTarget(reader.getSurface()) + let outsufaces = [suface, reader.getSurface()] as Surface[] + + + class sessionCallback extends CameraCaptureSession.StateCallback { + + constructor() { + + } + override onConfigured(session : CameraCaptureSession) { + t.captureSession = session + try { + t.captureSession?.setRepeatingRequest(previewRequestBuilder.build(), null, null) + } catch (e) { + console.log("Failed to start camera preview session.", e) + } + } + override onConfigureFailed(session : CameraCaptureSession) { + + } + override onClosed(session : CameraCaptureSession) { + + } + override onSurfacePrepared(session : CameraCaptureSession, testSuface : Surface) { + + } + + } + + + class imageReaderCallback extends ImageReader.OnImageAvailableListener { + private currentImage = null as Image | null; + override onImageAvailable(irader : ImageReader) { + if (this.currentImage != null) { + this.currentImage!.close(); // 先关闭上一帧的Image + } + let curimage = irader.acquireNextImage(); + + @Suppress("DEPRECATION") + class IntentRunable extends Runnable{ + override run(){ + if(!t.isScannig ) return; + t.qrDecoder(curimage!) + } + } + // curimage.close() + // 跳转到一个新的界面 + // UTSAndroid.getUniActivity()!.runOnUiThread(new IntentRunable()) + + this.currentImage = curimage + if (this.currentImage != null) { + new Thread(new IntentRunable()).start() + + } + + } + } + + reader.setOnImageAvailableListener(new imageReaderCallback(), null) + this.cameraDevice!.createCaptureSession(outsufaces, new sessionCallback(), null) + + // previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_VIDEO); + previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); + previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); + + + + } + // 设置相机对焦模式 + // setCamraFoucsAuto(){ + // let cameraManager = this.getSystemService(Context.CAMERA_SERVICE) as CameraManager + // let characteristics = cameraManager.getCameraCharacteristics(this.camerManIds!) + // // console.log(CaptureRequest.CONTROL_AF_MODE) + // captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_VIDEO); + // } + // 获取当前相机的旋转角度。 + getCamraRotation() : Int { + let cameraId = this.camerManIds!; + let isFrontFacing = false; + let deviceRotation = this.windowManager.defaultDisplay.rotation + let rotationCompensation = ORIENTATIONS.get(deviceRotation) as number + + // Get the device's sensor orientation. + let cameraManager = this.getSystemService(Context.CAMERA_SERVICE) as CameraManager + let sensorOrientation = cameraManager + .getCameraCharacteristics(cameraId) + .get(CameraCharacteristics.SENSOR_ORIENTATION)!! as number + + if (isFrontFacing) { + rotationCompensation = ((sensorOrientation + rotationCompensation) % 360).toInt() + } else { // back-facing + rotationCompensation = ((sensorOrientation - rotationCompensation + 360) % 360).toInt() + } + return rotationCompensation + } + + YUV42088ToNV21(image : Image) : ByteArray { + // 获取图像的宽度、高度以及各平面的行间距 + let width = image.getWidth(); + let height = image.getHeight(); + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + let yBuffer = planes[0].getBuffer().duplicate(); + let uBuffer = planes[1].getBuffer().duplicate(); + let vBuffer = planes[2].getBuffer().duplicate(); + + yBuffer.rewind(); + uBuffer.rewind(); + vBuffer.rewind(); + + + let yRowStride = planes[0].getRowStride(); + let uvRowStride = planes[1].getRowStride(); + let uvPixelStride = planes[1].getPixelStride(); // U 和 V 的像素间距通常是一样的 + + // 创建一个足够大的NV21输出数组 + let nv21Data = new ByteArray(width * height * 3 / 2); + + // 指针用于遍历输出数组 + let yIndex = 0; + let uvIndex = width * height; + let bytesPerPixel = 1 + try { + // 遍历Y平面 + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + nv21Data[(yIndex++).toInt()] = yBuffer.get(); + } + // 跳过未使用的行数据(如果有) + let rowRemainder = yRowStride - width * bytesPerPixel; + + if (rowRemainder > 0) { + yBuffer.position((yBuffer.position() + rowRemainder).toInt()); + } else { + yBuffer.position((yBuffer.position() + width * bytesPerPixel).toInt()); // 防止由于计算错误导致的负数 + } + + } + } catch (e) { + //TODO handle the exception + } + // // 处理UV平面 + try { + for (let row = 0; row < height / 2; row++) { + for (let col = 0; col < width / 2; col++) { + // 先读取U分量 + nv21Data[uvIndex++] = uBuffer.get(); + // 如果UV像素不是交错存储,则跳过一个位置 + if (uvPixelStride == 2) { + uBuffer.position(uBuffer.position() + 1); + } + + // 再读取V分量 + nv21Data[uvIndex++] = vBuffer.get(); + // 如果UV像素是交错存储,这里也需要相应调整位置 + if (uvPixelStride == 2) { + vBuffer.position(vBuffer.position() + 1); + } + } + // 跳过未使用的行数据(如果有) + let uvRowSkip = uvRowStride - (width / 2) * uvPixelStride; + if (uvRowSkip > 0) { + uBuffer.position(uBuffer.position() + uvRowSkip); + vBuffer.position(vBuffer.position() + uvRowSkip); + } + } + } catch (e) { + //TODO handle the exception + } + return nv21Data; + } + + YUV42088ToNV21Copy(a:ByteBuffer,b:ByteBuffer,c:ByteBuffer,widths:number,heights:number,yr:number,ur:number,vr:number) : ByteArray { + // 获取图像的宽度、高度以及各平面的行间距 + let width = widths + let height = heights; + // 获取各平面的数据与信息 + + let yBuffer = a; + let uBuffer = b; + let vBuffer = c; + + yBuffer.rewind(); + uBuffer.rewind(); + vBuffer.rewind(); + + let yRowStride = yr; + let uvRowStride = ur; + let uvPixelStride = vr; // U 和 V 的像素间距通常是一样的 + + // 创建一个足够大的NV21输出数组 + let nv21Data = new ByteArray((width * height * 3 / 2).toInt()); + + // 指针用于遍历输出数组 + let yIndex = 0; + let uvIndex = width * height; + let bytesPerPixel = 1 + try { + // 遍历Y平面 + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + nv21Data[(yIndex++).toInt()] = yBuffer.get(); + } + // 跳过未使用的行数据(如果有) + let rowRemainder = yRowStride - width * bytesPerPixel; + + if (rowRemainder > 0) { + yBuffer.position((yBuffer.position() + rowRemainder).toInt()); + } else { + yBuffer.position((yBuffer.position() + width * bytesPerPixel).toInt()); // 防止由于计算错误导致的负数 + } + + } + } catch (e) { + //TODO handle the exception + } + // // 处理UV平面 + try { + for (let row = 0; row < height / 2; row++) { + for (let col = 0; col < width / 2; col++) { + // 先读取U分量 + nv21Data[(uvIndex++).toInt()] = uBuffer.get(); + // 如果UV像素不是交错存储,则跳过一个位置 + if (uvPixelStride == 2) { + uBuffer.position((uBuffer.position() + 1).toInt()); + } + + // 再读取V分量 + nv21Data[(uvIndex++).toInt()] = vBuffer.get(); + // 如果UV像素是交错存储,这里也需要相应调整位置 + if (uvPixelStride == 2) { + vBuffer.position((vBuffer.position() + 1).toInt()); + } + } + // 跳过未使用的行数据(如果有) + let uvRowSkip = uvRowStride - (width / 2) * uvPixelStride; + if (uvRowSkip > 0) { + uBuffer.position((uBuffer.position() + uvRowSkip).toInt()); + vBuffer.position((vBuffer.position() + uvRowSkip).toInt()); + } + } + } catch (e) { + //TODO handle the exception + } + return nv21Data; + } + + copyImagePlan(plane:Plane):ByteBuffer{ + // 创建一个新的ByteBuffer来存储复制的数据 + let copiedBuffer = ByteBuffer.allocateDirect(plane.getBuffer().capacity()); + copiedBuffer.order(ByteOrder.nativeOrder()); // 确保字节顺序与原Buffer一致 + + // 将原始Plane的ByteBuffer内容复制到新的ByteBuffer中 + plane.getBuffer().rewind(); // 移动缓冲区指针到开始位置(可选,如果已经知道在开始处则无需此步) + copiedBuffer.put(plane.getBuffer()); + + // 复制完成后,可以移动新ByteBuffer的指针回到起始位置以便读取 + copiedBuffer.rewind(); + + return copiedBuffer + } + qrDecoder(image : Image) { + let t = this; + if (!this.isDecodreIng) { + this.isDecodreIng = true; + let width = image.getWidth(); + let height = image.getHeight(); + + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + + let a = this.copyImagePlan(planes[0]); + let b = this.copyImagePlan(planes[1]); + let c = this.copyImagePlan(planes[2]); + let yr = planes[0].getRowStride() + let ur = planes[1].getRowStride() + let vr = planes[1].getPixelStride() + + let starttime = new Date().getTime() + + let av = this.YUV42088ToNV21Copy(a,b,c,width,height,yr,ur,vr) + decoderBuffToQr(av, width, height, this.getCamraRotation()) + .then((res) => { + if (res != null&&t.isScannig ) { + if (res.text.length > 0) { + t.vibatarLong() + t.clearImageView(); + t.setImageViewRusletBox(t.previewWidth, t.previewWidth, width, height, res as SCANNING_PHOTO_RESULT) + uni.setStorageSync('xMlkitScannigUResult_time_start', 'end:'+(new Date().getTime() - starttime).toString()+'ms') + t.closeCamra() + if (res.text.length == 1) { + uni.setStorageSync('xMlkitScannigUResult', res.text[0]) + t.finish(); + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } + + } + } + // image.close(); + }) + .catch(() => { + // this.imageUrl = null + }) + setTimeout(function () { + this.isDecodreIng = false + }, this.scanSpeed); + image.close(); + } + + } + closeCamra() { + this.isScannig = false + if (this.captureSession != null) { + this.captureSession!.close(); + this.captureSession = null; + this.cameraDevice?.close() + this.cameraDevice = null; + console.log("手动关闭相机"); + } + } + + openCamra() { + let t = this; + if (this.captureSession != null) { + return; + } + if (t.previewWidth == 0) { + //监听尺寸变化。 + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.previewWidth = right - left; + t.previewHeight = bottom - top; + t.prviewTop = top + t.prviewLeft = left + v.removeOnLayoutChangeListener(this); + t.isCheckPermissions() + .then(() => { + let layoutParams = t.preview!.getLayoutParams() as ViewGroup.LayoutParams + layoutParams.height = t.previewWidth + t.preview!.layoutParams = layoutParams; + + + + let layoutParamsbx = t.xiangjiBox!.getLayoutParams() as ViewGroup.LayoutParams + layoutParamsbx.height = t.previewWidth + t.xiangjiBox!.layoutParams = layoutParamsbx; + + + t.isScannig = true + t.clearImageView() + t.getCameraById(); + t.openCamrae(); + }) + } + } + + this.preview!.addOnLayoutChangeListener(new previewChangeRectadd()) + } else { + t.isScannig = true + t.clearImageView() + t.getCameraById(); + t.openCamrae(); + } + } + + // 设置图片上的小圆的识别位置。 + setImageViewRusletBox(width : number, height : number, realWidth : number, realHeight : number, jieguo : SCANNING_PHOTO_RESULT) { + let t = this; + let wRatio = width / realWidth; + let hRatio = height / realHeight; + this.imageYuranBox!.setBackgroundColor(Color.argb(0,0,0,0)) + this.xiangjiBox!.setBackgroundColor(Color.argb(0,0,0,0)) + for (let i = 0; i < jieguo.bounds.length; i++) { + let item = jieguo.bounds[i]; + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + if (this.isScannig) { + layoutParams.topMargin = (hRatio * (item.centerY-60)).toInt() // 设置顶部边距 + layoutParams.leftMargin = (wRatio * (item.centerX-60)).toInt() // 设置左边距 + } else { + layoutParams.topMargin = (hRatio * item.centerY-60).toInt() // 设置顶部边距 + layoutParams.leftMargin = (wRatio * item.centerX-60).toInt() // 设置左边距 + } + let relativeLayout = new RelativeLayout(t.context) + relativeLayout.layoutParams = layoutParams + + const rtxt = jieguo.text[i] + + let v = new xView(t.context) + v.setSize(120, 120) + .setRadius(100) + .setBackgroundColor('#21d429') + .setBorder(12, "#ffffff", false) + .setClick((event : MotionEvent) => { + try { + uni.setStorageSync('xMlkitScannigUResult', rtxt) + t.finish() + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } catch (e) { + //TODO handle the exception + } + }) + let ov = v.getView(); + + + // 创建缩放动画 + let scaleAnimation = new ScaleAnimation(1.0.toFloat(), 0.7.toFloat(), 1.0.toFloat(), 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat()); + scaleAnimation.setDuration(600); // 设置动画持续时间 + scaleAnimation.setRepeatMode(Animation.REVERSE); // 设置重复模式为反向 + scaleAnimation.setRepeatCount(Animation.INFINITE); // 设置重复次数为无限 + // 启动动画 + ov.startAnimation(scaleAnimation); + + + relativeLayout.addView(v.getView()) + if (this.isScannig) { + this.xiangjiBox!.addView(relativeLayout) + this.imgPointsBycanmarea.push(relativeLayout) + this.xiangjiBox!.setBackgroundColor(Color.argb(100,0,0,0)) + } else { + this.imageYuranBox!.addView(relativeLayout) + this.imgPoints.push(relativeLayout) + this.imageYuranBox!.setBackgroundColor(Color.argb(100,0,0,0)) + } + + } + + + } + + clearImageView() { + for (let i = 0; i < this.imgPointsBycanmarea.length; i++) { + this.xiangjiBox!.removeView(this.imgPointsBycanmarea[i]) + } + for (let i = 0; i < this.imgPoints.length; i++) { + this.imageYuranBox!.removeView(this.imgPoints[i]) + } + if (!this.isScannig) { + this.imageView!.setImageDrawable(null) + } + + } + override onActivityResult(requestCode : Int, resultCode : Int, data ?: Intent) { + super.onActivityResult(requestCode, resultCode, data) + let t = this; + if (resultCode == Activity.RESULT_OK && data != null && data?.data != null) { + let selectedImageUri = data.data! + this.imageUrl = selectedImageUri + this.isSelectedImging = false + decoderUriPathToQrByUri(this.imageUrl!,(res:SCANNING_PHOTO_RESULT)=>{ + t.isScannig = false + t.clearImageView(); + t.imageView!.setImageURI(t.imageUrl!); + let reaLwidth = t.imageView!.drawable?.intrinsicWidth; + let reaLheight = t.imageView!.drawable?.intrinsicHeight; + + if (reaLwidth != null && reaLheight != null) { + t.vibatarLong() + t.setImageViewRusletBox(t.imageView!.width, t.imageView!.height, reaLwidth!, reaLheight!, res!) + if (res.text.length == 1) { + uni.setStorageSync('xMlkitScannigUResult', res.text[0]) + t.finish() + t.overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); + } + } + + }) + + } else { + this.isSelectedImging = false + + } + } + + override onPause() : void { + super.onPause(); + console.log("暂停扫码") + + this.isScannig = false + if (this.captureSession != null) { + this.captureSession!.close(); + this.captureSession = null; + this.cameraDevice?.close() + this.cameraDevice = null; + console.log("关闭相机"); + } + + // 停止图像处理线程 + if (this.imageHandler != null) { + this.imageHandler!.getLooper()!.quitSafely(); + } + } + + override onResume() : void { + super.onResume(); + + let t = this; + if (this.captureSession != null || t.imageUrl != null || t.isSelectedImging) { + return; + } + console.log("恢复扫码") + + + this.openCamra(); + + + } + + openCamrae() { + if (this.camerManIds == null) return; + // let t = this; + class CamerCallTstasBack implements StateCallback { + + constructor() { + + } + override onOpened(camera : CameraDevice) : void { + console.log('打开成功') + cameraDevice = camera + createCameraPreviewSession() + + } + override onDisconnected(camera : CameraDevice) : void { + console.log('连接失败') + cameraDevice?.close() + cameraDevice = null + } + override onError(camera : CameraDevice, error : Int) : void { + console.log('出错') + cameraDevice?.close() + cameraDevice = null + } + override onClosed(camera : CameraDevice) : void { + console.log('关闭') + cameraDevice?.close() + cameraDevice = null + } + + } + this.camera_service.openCamera(this!.camerManIds as string, new CamerCallTstasBack(), null); + } +} + + +@Suppress("DEPRECATION") +class IntentRunable extends Runnable { + override run() { + let intent = new Intent(UTSAndroid.getUniActivity(), DemoActivity().javaClass); + UTSAndroid.getUniActivity()!.startActivityForResult(intent,1); + } +} + +@Suppress("DEPRECATION") +export function gotoDemoActivity() : boolean { + // 跳转到一个新的界面 + UTSAndroid.getUniActivity()!.runOnUiThread(new IntentRunable()) + return true; + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx.uts new file mode 100644 index 0000000..9bfe45d --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/cameraByx.uts @@ -0,0 +1,1054 @@ +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' + + +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import ViewGroup from 'android.view.ViewGroup' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; +import R from 'io.dcloud.uni_modules.xMlkitScannigS.R'; +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import Bundle from 'android.os.Bundle' +import Handler from 'android.os.Handler' +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import { decoderUriPathToQr, decoderBuffToQr,decoderUriPathToQrByUri } from "./index.uts" +import xView from "./libview/view.uts" +import Gravity from 'android.view.Gravity'; + +// x +import ProcessCameraProvider from "androidx.camera.lifecycle.ProcessCameraProvider" +import PreviewView from "androidx.camera.view.PreviewView" +import CameraController from "androidx.camera.view.CameraController" +import CameraSelector from "androidx.camera.core.CameraSelector" +import Preview from 'androidx.camera.core.Preview' +import Camera from 'androidx.camera.core.Camera' +import LifecycleObserver from "androidx.lifecycle.LifecycleObserver" +import LifecycleOwner from "androidx.lifecycle.LifecycleOwner" +import OnLifecycleEvent from "androidx.lifecycle.OnLifecycleEvent" +import ImageAnalysis from 'androidx.camera.core.ImageAnalysis' +import ImageProxy from 'androidx.camera.core.ImageProxy' +import NonNull from 'androidx.annotation.NonNull' +import ExecutorService from 'java.util.concurrent.ExecutorService' +import Executors from 'java.util.concurrent.Executors' +import ContextCompat from 'androidx.core.content.ContextCompat'; +import LifecycleRegistry from "androidx.lifecycle.LifecycleRegistry" +import Lifecycle from "androidx.lifecycle.Lifecycle" + +import { SCANNING_OPTIONS, CAMERA_PHOTO_SIZE, CALL_RESULT_FUN, Call_BACK, Call_BACK_TYPE, SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND } from "../interface.uts" +type buffoptsPlanesType = { + data : ByteBuffer, + getRowStride : number, + getPixelStride : number, +} +type buffoptsType = { + width : number, + height : number, + format : number, + rect : Rect, + planes : buffoptsPlanesType[], +} +type ConverXy = { + x : number, + y : number, + minx : number, + maxx : number, + miny : number, + maxy : number, +} +type contaiaSize = { + width : number, + height : number +} +type contaiaCalseSize = { + scale : number, + offsetX : number, + offsetY : number +} +type contaiPointXy = { + x : number, + y : number +} +let parentView : RelativeLayout | null = null; + +let maskDomId = 8586 +let onlyCamera = false; +let callFunEvent:CALL_RESULT_FUN = (str:string)=>{} + +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} + + +class DemoActivity extends Activity implements LifecycleOwner { + lifecycleRegistry:LifecycleRegistry|null = null + /** 手动震动服务 */ + vibrator = null as null | Vibrator + context : Context; + // 识别点的区域 + resultView : RelativeLayout | null = null; + // 存放小绿点的数组 + imgPointsBycanmarea = [] as RelativeLayout[] + //相机容器 + camreaLayouView:RelativeLayout|null = null; + // 图片容器层. + imageLayouView:RelativeLayout|null = null; + + viewBox_width = 0 + viewBox_height = 0 + + imageView = null as null | ImageView + imageUrl = null as null | Uri + isSelectedImging = false; + + // 相机区域视图 + cameraView : PreviewView | null = null; + cameraProvider : ProcessCameraProvider | null = null + camera : Camera | null = null; + cameraPreview : Preview | null = null; + flashMode = false; + + + // 当前是否在解析码制中。 + isDecoderQring = false + // 当前相机是否正在预览中。 + isOpeningCameraing = false; + + // callFunEvent : CALL_RESULT_FUN = (str : string) => { } + // onlyCamera:boolean = false; + // 临时存放的识别成功的结果,防止重复扫码。 + tempresultList = [] as string[]; + + constructor() { + super(); + this.context = UTSAndroid.getAppContext() as Context; + // this.camera_service = this.context!.getSystemService(Context.CAMERA_SERVICE) as CameraManager + // 在你的Activity或者Fragment中 + this.vibrator = this.context!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + this.lifecycleRegistry = new LifecycleRegistry(this); + this.lifecycleRegistry!.markState(Lifecycle.State.CREATED); + + } + + private createView() { + let t = this; + // let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + // 创建父容器。 + parentView = new RelativeLayout(this.context); + // parentView!.setId((maskDomId).toInt()) + // parentView!.setOrientation(LinearLayout.VERTICAL) + parentView!.setBackgroundColor(Color.BLACK) + + + + parentView!.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )) + + class MaskerDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + //阻止事件向下穿透。 + override onTouch(view : View, event : MotionEvent) : Boolean { + return true; + } + } + parentView!.setOnTouchListener(new MaskerDomClickListsner()) + + let continaer = new LinearLayout(this.context); + continaer.setOrientation(LinearLayout.VERTICAL) + continaer.setBackgroundColor(Color.TRANSPARENT) + let continaerLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + continaer.setLayoutParams(continaerLayparams) + + + // 创建一个中间容器 + let boxWrapParent = new LinearLayout(this.context); + boxWrapParent.setOrientation(LinearLayout.VERTICAL) + + let boxLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + boxLayparams.weight = (1).toFloat(); + boxLayparams.height = 0; + boxWrapParent.setLayoutParams(boxLayparams) + // 创建一个定位容器 + let boxWrap = new RelativeLayout(this.context); + boxWrap.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )) + + boxWrapParent.addView(boxWrap) + + //监听尺寸变化。 + + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.viewBox_width = right - left; + t.viewBox_height = bottom - top; + + } + } + boxWrap.addOnLayoutChangeListener(new previewChangeRectadd()) + + let rongqitop = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + rongqitop.topMargin = 0 + rongqitop.leftMargin = 0 + // 创建容器内小绿点容器。 + this.resultView = new RelativeLayout(this.context); + this.resultView!.setLayoutParams(rongqitop) + + // 图片容器 + let imgPview = new RelativeLayout(this.context); + let rongqitop2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + rongqitop2.topMargin = 0 + rongqitop2.leftMargin = 0 + imgPview.setLayoutParams(rongqitop2) + + // 创建一张图片 + this.imageView = new ImageView(this.context); + this.imageView!.setScaleType(ImageView.ScaleType.CENTER_INSIDE) + this.imageView!.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) + imgPview.addView(this.imageView!) + this.imageView!.setImageDrawable(null) + // 相机容器。 + let cview = new RelativeLayout(this.context); + let rongqitop3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + + // rongqitop3.width = 1000 + // rongqitop3.height = 1000 + cview.setLayoutParams(rongqitop3) + // 相机预览层。 + let sv = new PreviewView(this.context) + // https://developer.android.google.cn/reference/androidx/camera/view/PreviewView.ScaleType?hl=en + sv.setScaleType(PreviewView.ScaleType.FILL_CENTER) + + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + cview.addView(this.cameraView!) + + + // this.imageView!.setVisibility(View.INVISIBLE) + //相机容器 + this.camreaLayouView = cview; + // 图片容器层. + this.imageLayouView= imgPview; + boxWrap.addView(imgPview) + boxWrap.addView(cview) + boxWrap.addView(this.resultView!) + + + + + // 创建底 + let footerWrap = new LinearLayout(this.context); + footerWrap.setOrientation(LinearLayout.HORIZONTAL) + + let footerWrapLayparams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + + footerWrapLayparams.height = px2dp(100).toInt(); + footerWrap.setLayoutParams(footerWrapLayparams) + + // 创建选择相册 + let photoView = new LinearLayout(this.context); + photoView.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )) + let xiangcheText = new TextView(this.context); + xiangcheText.setTextColor(Color.WHITE) + xiangcheText.setPadding(32, 52, 0, 0) + xiangcheText.setTextSize((16).toFloat()) + xiangcheText.setGravity(Gravity.LEFT) + xiangcheText.setText(!onlyCamera?"相册选择":" ") + xiangcheText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class XiangcheClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + + if(event.getAction()==MotionEvent.ACTION_UP){ + t.closeCamera() + t.isSelectedImging = true; + let intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + t.startActivityForResult(intent,1) + } + + + return true; + } + } + if(!onlyCamera){ + xiangcheText.setOnTouchListener(new XiangcheClickListsner()) + } + photoView.addView(xiangcheText) + + //添加开和关灯光的按钮. + let falshText = new TextView(this.context); + falshText.setTextColor(Color.WHITE) + falshText.setPadding(32, 52, 0, 0) + falshText.setTextSize((16).toFloat()) + falshText.setGravity(Gravity.CENTER) + falshText.setText(this.flashMode?"关灯":"开灯") + falshText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class FalshTextClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + + if(event.getAction()==MotionEvent.ACTION_UP){ + t.flashMode = !t.flashMode; + falshText.setText(t.flashMode?"关灯":"开灯") + t.setFlashModel(t.flashMode) + } + + return true; + } + } + falshText.setOnTouchListener(new FalshTextClickListsner()) + + let cneterView = new LinearLayout(this.context); + let cneterViewParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + cneterViewParams.weight = (1).toFloat(); + cneterView.setGravity(Gravity.CENTER) + cneterView.setLayoutParams(cneterViewParams) + cneterView.addView(falshText) + + // 扫一扫view + let scanView = new LinearLayout(this.context); + scanView.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )) + scanView.setGravity(Gravity.RIGHT) + + let shaoyishaoText = new TextView(this.context); + shaoyishaoText.setTextColor(Color.WHITE) + shaoyishaoText.setPadding(0, 52, 32, 0) + shaoyishaoText.setTextSize((16).toFloat()) + shaoyishaoText.setGravity(Gravity.RIGHT) + shaoyishaoText.setText("扫一扫") + shaoyishaoText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class ShaoyishaoTextClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + if(event.getAction()==MotionEvent.ACTION_UP){ + t._openCamera() + } + + return true; + } + } + shaoyishaoText.setOnTouchListener(new ShaoyishaoTextClickListsner()) + scanView.addView(shaoyishaoText) + + + + footerWrap.addView(photoView) + footerWrap.addView(cneterView) + footerWrap.addView(scanView) + + // 创建一个顶部 + let titleView = new RelativeLayout(this.context); + // titleView!.setOrientation(LinearLayout.HORIZONTAL) + // titleView!.setBackgroundColor(Color.RED) + let tplays = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + tplays.topMargin = px2dp(60).toInt() + tplays.leftMargin = px2dp(16).toInt() + titleView!.setLayoutParams(tplays) + // 创建一个返回按钮 + let backBtn = new TextView(this.context); + backBtn.setTextColor(Color.WHITE) + backBtn.setTextSize((16).toFloat()) + backBtn.setGravity(Gravity.BOTTOM) + backBtn.setText("返回") + + backBtn.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + class BackDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + t.close(); + return true; + } + } + backBtn.setOnTouchListener(new BackDomClickListsner()) + titleView!.addView(backBtn) + + + + continaer.addView(boxWrapParent) + continaer.addView(footerWrap) + + parentView!.addView(continaer) + parentView!.addView(titleView) + // decorView.addView(parentView!) + this.setContentView(parentView) + + } + override onCreate(savedInstanceState ?: Bundle) : void { + super.onCreate(savedInstanceState) + this.lifecycleRegistry = new LifecycleRegistry(this); + this.lifecycleRegistry!.markState(Lifecycle.State.CREATED); + this.hideTitleBar() + // this.openCamera(); + } + + clearImageView() { + this.clearImagePonit(); + if (!this.isOpeningCameraing) { + this.imageView!.setImageDrawable(null) + } + + } + openCamera() { + let t = this; + if (parentView == null) { + this.createView(); + t._openCamera() + } else { + this._openCamera() + } + } + + close() { + this.closeCamera(); + this.clearImagePonit(); + parentView = null; + this.finish() + } + closeCamera() { + try{ + this.setFlashModel(false); + this.cameraProvider?.unbindAll() + this.cameraPreview?.setSurfaceProvider(null) + this.isOpeningCameraing = false; + + }catch(e){ + //TODO handle the exception + } + } + private _openCamera() { + let _this = this; + let lifecycleOwner = this; + this.closeCamera(); + this.clearImagePonit(); + let cameraProviderFuture = ProcessCameraProvider.getInstance(this.context) + this.camreaLayouView!.setVisibility(View.VISIBLE) + class IntentRunable extends Runnable { + override run() { + let cameraProvider : ProcessCameraProvider = cameraProviderFuture.get() + let previewView = _this.cameraView! as PreviewView + let cameraSelector : CameraSelector = CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + let preview : Preview = new Preview.Builder().build(); + + preview.setSurfaceProvider(previewView.getSurfaceProvider()) + + let imageAnalysis = new ImageAnalysis.Builder() + .setTargetResolution(new Size(800, 800)) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + class MyImageAnalyzer implements ImageAnalysis.Analyzer { + constructor() { + super() + } + override analyze(image : ImageProxy) { + _this.qrDecoder(image) + + } + override getDefaultTargetResolution() : Size { + return new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt()); + } + + } + let cameraExecutor = Executors.newSingleThreadExecutor(); + imageAnalysis.setAnalyzer(cameraExecutor, new MyImageAnalyzer()); + + let camera : Camera = cameraProvider.bindToLifecycle( + lifecycleOwner, cameraSelector, preview, imageAnalysis); + + _this.camera = camera + _this.cameraPreview = preview + + _this.cameraProvider = cameraProvider + _this.isDecoderQring = false + _this.isOpeningCameraing = true + + + } + } + + cameraProviderFuture.addListener(new IntentRunable(), ContextCompat.getMainExecutor(this.context)) + } + + clearImagePonit(){ + for (let i = 0; i < this.imgPointsBycanmarea.length; i++) { + this.resultView?.removeView(this.imgPointsBycanmarea[i]) + } + } + + // 设置图片上的小圆的识别位置。 + setImageViewRusletBox(jieguo : SCANNING_PHOTO_RESULT) { + let t = this; + let btnwidth = 100; + let btnwidth2 = 50; + + for (let i = 0; i < jieguo.bounds.length; i++) { + let item = jieguo.bounds[i]; + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + let x = item.centerX + let y = item.centerY + + layoutParams.topMargin = (y - btnwidth2).toInt() // 设置顶部边距 + layoutParams.leftMargin = (x - btnwidth2).toInt() // 设置左边距 + let relativeLayout = new RelativeLayout(t.context) + relativeLayout.layoutParams = layoutParams + + const rtxt = jieguo.text[i] + let v = new xView(t.context) + v.setSize(btnwidth, btnwidth) + .setRadius(100) + .setBackgroundColor('#21d429') + .setBorder(12, "#ffffff", false) + .setClick((event : MotionEvent) => { + try { + // t.callFunEvent([rtxt], 'click') + callFunEvent(rtxt) + t.close() + } catch (e) { + //TODO handle the exception + } + }) + let ov = v.getView(); + + + // 创建缩放动画 + let scaleAnimation = new ScaleAnimation(1.0.toFloat(), 0.7.toFloat(), 1.0.toFloat(), 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat()); + scaleAnimation.setDuration(600); // 设置动画持续时间 + scaleAnimation.setRepeatMode(Animation.REVERSE); // 设置重复模式为反向 + scaleAnimation.setRepeatCount(Animation.INFINITE); // 设置重复次数为无限 + // 启动动画 + ov.startAnimation(scaleAnimation); + relativeLayout.addView(ov) + this.imgPointsBycanmarea.push(relativeLayout) + this.resultView!.addView(relativeLayout) + } + + + } + + + YUV42088ToNV21Copy(a:ByteBuffer,b:ByteBuffer,c:ByteBuffer,widths:number,heights:number,yr:number,ur:number,vr:number) : ByteArray { + // 获取图像的宽度、高度以及各平面的行间距 + let width = widths + let height = heights; + // 获取各平面的数据与信息 + + let yBuffer = a; + let uBuffer = b; + let vBuffer = c; + + yBuffer.rewind(); + uBuffer.rewind(); + vBuffer.rewind(); + + let yRowStride = yr; + let uvRowStride = ur; + let uvPixelStride = vr; // U 和 V 的像素间距通常是一样的 + + // 创建一个足够大的NV21输出数组 + let nv21Data = new ByteArray((width * height * 3 / 2).toInt()); + + // 指针用于遍历输出数组 + let yIndex = 0; + let uvIndex = width * height; + let bytesPerPixel = 1 + try { + // 遍历Y平面 + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + nv21Data[(yIndex++).toInt()] = yBuffer.get(); + } + // 跳过未使用的行数据(如果有) + let rowRemainder = yRowStride - width * bytesPerPixel; + + if (rowRemainder > 0) { + yBuffer.position((yBuffer.position() + rowRemainder).toInt()); + } else { + yBuffer.position((yBuffer.position() + width * bytesPerPixel).toInt()); // 防止由于计算错误导致的负数 + } + + } + } catch (e) { + //TODO handle the exception + } + // // 处理UV平面 + try { + for (let row = 0; row < height / 2; row++) { + for (let col = 0; col < width / 2; col++) { + // 先读取U分量 + nv21Data[(uvIndex++).toInt()] = uBuffer.get(); + // 如果UV像素不是交错存储,则跳过一个位置 + if (uvPixelStride == 2) { + uBuffer.position((uBuffer.position() + 1).toInt()); + } + + // 再读取V分量 + nv21Data[(uvIndex++).toInt()] = vBuffer.get(); + // 如果UV像素是交错存储,这里也需要相应调整位置 + if (uvPixelStride == 2) { + vBuffer.position((vBuffer.position() + 1).toInt()); + } + } + // 跳过未使用的行数据(如果有) + let uvRowSkip = uvRowStride - (width / 2) * uvPixelStride; + if (uvRowSkip > 0) { + uBuffer.position((uBuffer.position() + uvRowSkip).toInt()); + vBuffer.position((vBuffer.position() + uvRowSkip).toInt()); + } + } + } catch (e) { + //TODO handle the exception + } + return nv21Data; + } + + copyImagePlan(plane:Plane):ByteBuffer{ + // 创建一个新的ByteBuffer来存储复制的数据 + let copiedBuffer = ByteBuffer.allocateDirect(plane.getBuffer().capacity()); + copiedBuffer.order(ByteOrder.nativeOrder()); // 确保字节顺序与原Buffer一致 + + // 将原始Plane的ByteBuffer内容复制到新的ByteBuffer中 + plane.getBuffer().rewind(); // 移动缓冲区指针到开始位置(可选,如果已经知道在开始处则无需此步) + copiedBuffer.put(plane.getBuffer()); + + // 复制完成后,可以移动新ByteBuffer的指针回到起始位置以便读取 + copiedBuffer.rewind(); + + return copiedBuffer + } + getCorrectionMatrixByimgUri(imgView : ImageView, previewView : PreviewView,rotationDegrees:number) : Matrix { + + let matrix = new Matrix() + let imgWidt = imgView.drawable!.intrinsicWidth as number + let imgHeight = imgView.drawable!.intrinsicHeight as number + let d0 = (0).toFloat() + let source = floatArrayOf( + d0, + d0, + imgWidt.toFloat(), + d0, + imgWidt.toFloat(), + imgHeight.toFloat(), + d0, + imgHeight.toFloat() + ) + + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf( + d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat() + ) + + + let vertexSize = 2 + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + getCorrectionMatrix(imageProxy : ImageProxy, previewView : PreviewView) : Matrix { + let cropRect = imageProxy.cropRect + let rotationDegrees = imageProxy.imageInfo.rotationDegrees + let matrix = new Matrix() + + // A float array of the source vertices (crop rect) in clockwise order. + + let source = floatArrayOf( + cropRect.left.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.bottom.toFloat(), + cropRect.left.toFloat(), + cropRect.bottom.toFloat() + ) + let d0 = (0).toFloat() + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf( + d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat() + ) + + + let vertexSize = 2 + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + + + calcPoint(imgView : ImageView, previewView : PreviewView, image_point_x : number, image_point_y : number,degration:number) : ConverXy { + + const image_w = imgView.drawable!.intrinsicWidth as number + const image_h = imgView.drawable!.intrinsicHeight as number + const c_w = previewView.width; + const c_h = previewView.height; + + function scaleAndCenterContent( + container : contaiaSize, + content : contaiaSize + ) : contaiaCalseSize { + // 计算缩放比例 + const scaleWidth = container.width / content.width; + const scaleHeight = container.height / content.height; + const scale = Math.min(scaleWidth, scaleHeight); + + // 计算居中偏移量 + const offsetX = (container.width - content.width * scale) / 2; + const offsetY = (container.height - content.height * scale) / 2; + + return { scale, offsetX, offsetY } as contaiaCalseSize; + } + function mapContentCoordinatesToContainer( + contentX : number, + contentY : number, + calcsize : contaiaCalseSize + ) : contaiPointXy { + // 映射内容层坐标到容器层坐标 + const containerX = contentX * calcsize.scale + calcsize.offsetX; + const containerY = contentY * calcsize.scale + calcsize.offsetY; + + return { x: containerX, y: containerY } as contaiPointXy; + } + + let rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_h, height: image_w } as contaiaSize + ) + if(degration==0){ + rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_w, height: image_h } as contaiaSize + ) + } + + let result = mapContentCoordinatesToContainer(image_point_y, image_point_x, rc) + if(degration==0){ + result = mapContentCoordinatesToContainer(image_point_x,image_point_y,rc) + } + let nexyxcov = { + x: c_w - result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + if(degration==0){ + nexyxcov = { + x: result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + } + return nexyxcov + + } + + qrDecoder(img : ImageProxy) { + let t = this; + let image = img.getImage(); + if (!this.isDecoderQring&&image!=null&&t.isOpeningCameraing) { + this.isDecoderQring = true; + let width = image.getWidth(); + let height = image.getHeight(); + + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + + let a = this.copyImagePlan(planes[0]); + let b = this.copyImagePlan(planes[1]); + let c = this.copyImagePlan(planes[2]); + let yr = planes[0].getRowStride() + let ur = planes[1].getRowStride() + let vr = planes[1].getPixelStride() + + let starttime = new Date().getTime() + + let av = this.YUV42088ToNV21Copy(a,b,c,width,height,yr,ur,vr) + let rotationDegrees = img.imageInfo.rotationDegrees + + decoderBuffToQr(av, width, height, 0) + .then((res) => { + if (res != null ) { + let matrix = t.getCorrectionMatrix(img, t.cameraView!) + if (res.text.length > 0) { + let ruslt = res as SCANNING_PHOTO_RESULT; + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + let ponit = floatArrayOf(item.centerX.toFloat(), item.centerY.toFloat()) + // let xy = t.covertXy(img, t.cameraView!,item.centerX,item.centerY); + matrix.mapPoints(ponit) + item.centerX = ponit[0] + item.centerY = ponit[1] + // item.centerX = xy[0] + // item.centerY = xy[1] + // console.log(item.centerX ,item.centerY) + + } + if(ruslt.text.length>0){ + t.setVibatar() + } + t.setImageViewRusletBox(ruslt) + t.closeCamera() + if (ruslt.text.length == 1) { + callFunEvent(ruslt.text[0]) + t.close() + } + }else{ + t.isDecoderQring = false + } + } + // image.close(); + }) + .catch(() => { + t.isDecoderQring = false + }) + } + img.close(); + } + //设置手机的闪光灯 + setFlashModel(flash:boolean){ + if(this.camera!=null&&this.isOpeningCameraing){ + this.flashMode = flash; + let cameraControl = this.camera!.cameraControl! + cameraControl.enableTorch(flash) + } + } + //震动手机 + setVibatar(){ + if(this.vibrator == null) return + // 检查设备是否支持震动 + if (this.vibrator!.hasVibrator()) { + // 触发短暂的震动,持续时间为200毫秒 + this.vibrator!.vibrate(80); + } + } + + // 在需要隐藏标题栏的地方调用 + hideTitleBar() : void { + requestWindowFeature(Window.FEATURE_NO_TITLE); + this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + // 在需要显示标题栏的地方调用 + showTitleBar() : void { + this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + override onActivityResult(requestCode : Int, resultCode : Int, data ?: Intent) { + super.onActivityResult(requestCode, resultCode, data) + let t = this; + if (resultCode == Activity.RESULT_OK && data != null && data?.data != null) { + let selectedImageUri = data.data! + this.camreaLayouView!.setVisibility(View.GONE) + this.imageUrl = selectedImageUri + this.isSelectedImging = false + decoderUriPathToQrByUri(this.imageUrl!,(res:SCANNING_PHOTO_RESULT)=>{ + t.isOpeningCameraing = false + t.clearImageView(); + t.imageView!.setImageURI(t.imageUrl!); + let matrix = t.getCorrectionMatrixByimgUri(t.imageView!, t.cameraView!,90) + let ruslt = res as SCANNING_PHOTO_RESULT; + if(ruslt.text.length>0){ + t.setVibatar() + } + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + + let result = t.calcPoint(t.imageView!, t.cameraView!,item.centerX,item.centerY,0) + + item.centerX = result.x + item.centerY = result.y + } + t.setImageViewRusletBox(ruslt) + if (ruslt.text.length == 1) { + callFunEvent(ruslt.text[0]) + t.close() + } + + }) + + } else { + this.isSelectedImging = false + + } + } + + override onStart() { + super.onStart(); + lifecycleRegistry!.markState(Lifecycle.State.STARTED); + } + + override onDestroy() : void { + super.onDestroy(); + this.close() + this.showTitleBar(); + console.log('扫码被注销.') + } + + override onStop() { + lifecycleRegistry!.markState(Lifecycle.State.CREATED); + super.onStop(); + } + + + override onPause() : void { + super.onPause(); + lifecycleRegistry!.markState(Lifecycle.State.CREATED); + console.log("暂停扫码") + this.closeCamera() + + } + + override onResume() : void { + super.onResume(); + lifecycleRegistry!.markState(Lifecycle.State.RESUMED); + let t = this; + console.log("恢复扫码1",t.isSelectedImging) + if (t.imageUrl != null || t.isSelectedImging) { + return; + } + console.log("恢复扫码2") + this.closeCamera() + this.openCamera() + + } + override getLifecycle(): Lifecycle { + return this.lifecycleRegistry! + } + +} + + +@Suppress("DEPRECATION") +class IntentRunable extends Runnable { + override run() { + let intent = new Intent(UTSAndroid.getUniActivity(), DemoActivity().javaClass); + UTSAndroid.getUniActivity()!.startActivityForResult(intent,1); + } +} + +@Suppress("DEPRECATION") +export function gotoDemoActivity(call:CALL_RESULT_FUN,onlyCamera:boolean) : boolean { + callFunEvent = call; + onlyCamera = onlyCamera + // 跳转到一个新的界面 + UTSAndroid.getUniActivity()!.runOnUiThread(new IntentRunable()) + return true; + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/config.json b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/config.json new file mode 100644 index 0000000..360f986 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/config.json @@ -0,0 +1,13 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "com.google.mlkit:barcode-scanning:17.2.0", + "androidx.camera:camera-core:1.3.4", + "androidx.camera:camera-camera2:1.3.4", + "androidx.camera:camera-lifecycle:1.3.4", + "androidx.camera:camera-video:1.3.4", + "androidx.camera:camera-view:1.3.4", + "androidx.camera:camera-extensions:1.3.4" + ] +} + diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/index.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..1d8fed6 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/index.uts @@ -0,0 +1,382 @@ +/** + * 引用 Android 系统库,示例如下: + * import { Context } from "android.content.Context"; + * [可选实现,按需引入] + */ + +/* 引入 interface.uts 文件中定义的变量 */ +import { SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND, SCANNING_PHOTO_RESULT_POS } from '../interface.uts'; + +/* 引入 unierror.uts 文件中定义的变量 */ +import Intent from 'android.content.Intent'; +import Context from 'android.content.Context' +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import Bitmap from "android.graphics.Bitmap" +import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner" +import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions" +import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning" +import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions" +import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback" +import Barcode from "com.google.mlkit.vision.barcode.common.Barcode" +import InputImage from "com.google.mlkit.vision.common.InputImage" + +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" +import ByteBuffer from 'java.nio.ByteBuffer' +import ImageFormat from 'android.graphics.ImageFormat' + +import {xCamera} from "./camera.uts" +import {CALL_RESULT_FUN} from "../interface.uts" + +import {gotoDemoActivity} from "./cameraByx.uts" + +const camera = new xCamera() + +/** +* 从相册中选取图片进行解码 +* @public chooseImageDecodeQr +*/ +export function chooseImage() : Promise { + return new Promise((res) => { + uni.chooseImage({ + count: 1, + sourceType:['album'], + albumMode:"system", + success(evt : ChooseImageSuccess) { + console.log('**') + if (evt.tempFilePaths.length > 0) { + console.log(evt, "----") + const imgs = evt.tempFilePaths[0] as string; + try { + const decodedPath = Uri.decode(imgs).substring(7) + const file = File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + let scanner = BarcodeScanning.getClient(); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + res({ + url: imgs, + position: listpos, + bounds: bounedlist, + text: rulstText, + imgWidth:image.getWidth(), + imgHeight:image.getHeight() + } as SCANNING_PHOTO_RESULT) + }) + + } catch (e : IOException) { + res(null) + } + } + }, + fail() { + res(null) + } + }) + }) +} + +/** +* 给定图片路径解析图片。 +* @public decoderUriPathToQr +*/ +export function decoderUriPathToQr(filePath : string,callback:(rs:SCANNING_PHOTO_RESULT)=>void) { + try{ + let uri = UTSAndroid.getFileProviderUri(new File(filePath))! + + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, uri); + let scanner = BarcodeScanning.getClient(); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + callback({ + url: "", + position: listpos, + bounds: bounedlist, + text: rulstText, + imgWidth:image.getWidth(), + imgHeight:image.getHeight() + } as SCANNING_PHOTO_RESULT) + }) + }catch(e){ + console.error(e) + } +} + + +/** +* 给定图片路径Uri解析图片。 +* @public decoderUriPathToQr +*/ +export function decoderUriPathToQrByUri(filePath : Uri,callback:(rs:SCANNING_PHOTO_RESULT)=>void) { + try{ + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, filePath); + let options = BarcodeScannerOptions.Builder() + .setBarcodeFormats( + Barcode.FORMAT_QR_CODE, + Barcode.FORMAT_EAN_13, + Barcode.FORMAT_CODE_128, + Barcode.FORMAT_CODABAR + ) + .build() + let scanner = BarcodeScanning.getClient(options); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + callback({ + url: "", + position: listpos, + bounds: bounedlist, + text: rulstText, + imgWidth:image.getWidth(), + imgHeight:image.getHeight() + } as SCANNING_PHOTO_RESULT) + }) + }catch(e){ + console.error(e) + } +} + +/** +* 给定ImageBuffer +* @public decoderBuffToQr +*/ +export function decoderBuffToQr(bitmap : ByteArray, width : Number, height : Number, ration : Number) : Promise { + return new Promise((res) => { + let options = BarcodeScannerOptions.Builder() + .setBarcodeFormats( + Barcode.FORMAT_QR_CODE, + Barcode.FORMAT_EAN_13, + Barcode.FORMAT_CODE_128, + Barcode.FORMAT_CODABAR + ) + .build() + + let image = InputImage.fromByteArray(bitmap, width.toInt(), height.toInt(), ration.toInt(), InputImage.IMAGE_FORMAT_NV21) + // 如果只扫qr开启这行,速度快一点。 + let scanner = BarcodeScanning.getClient(options); + // let scanner = BarcodeScanning.getClient(); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + res({ + url: "", + position: listpos, + bounds: bounedlist, + text: rulstText, + imgWidth:image.getWidth(), + imgHeight:image.getHeight() + } as SCANNING_PHOTO_RESULT) + }) + .addOnFailureListener((e) => { + + res(null) + }) + }) +} + + +/** + * 提供一个网络图片地址进行解码 + * @public urlPathDecoderQr + */ +export function urlPathDecoderQr(url : String,callback:(rs:SCANNING_PHOTO_RESULT)=>void) { + uni.downloadFile({ + url, + success(res) { + const contentResolver = UTSAndroid.getAppContext()!.contentResolver + let decodedPath = res.tempFilePath + if (res.tempFilePath.indexOf('file://') > -1) { + decodedPath = Uri.decode(res.tempFilePath).substring(7) + } + decoderUriPathToQr(decodedPath,callback) + }, + fail() { + console.error('下载图片错误') + } + }) +} + +/** + * 检查相机权限 + */ +export function checkPermissions() : Promise { + let permissionCheck = ["android.permission.CAMERA"] + let _this = this; + // 请求拍照权限 + return new Promise((res) => { + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + // _this.cameraPermissioPass = true + res(true) + } else { + console.log("当前不具备指定权限") + // 请求拍照权限 + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (allRight : boolean, _ : string[]) { + // _this.cameraPermissioPass = allRight + res(true) + }, function (_ : boolean, _ : string[]) { + //用户拒绝了部分权限 + res(false) + }) + } + }) +} + + +let callCustomFun = null as null|CALL_RESULT_FUN + +const xMlkitScanningActivityResult = (requestCode : Int, resultCode : Int, data ?: Intent)=>{ + let _this = this; + let jgCode = 1; + let datastr = uni.getStorageSync('xMlkitScannigUResult'); + + if(requestCode==jgCode.toInt()&&datastr!=null&&callCustomFun!=null){ + let str = "" + let call = callCustomFun!; + if(typeof datastr == 'bigint'||typeof datastr == 'number' || typeof datastr == 'int'){ + call(datastr.toString()) + }else{ + str = datastr as string; + call(str) + } + uni.removeStorageSync('xMlkitScannigUResult') + } +} + + + +export function openCameraApi(call:CALL_RESULT_FUN,onlyCamera:boolean){ + + + // UTSAndroid.offAppActivityResult(xMlkitScanningActivityResult) + // callCustomFun = call + let isPrivacyAgreeCamrea = uni.getStorageSync('isPrivacyAgreeCamreaByTmui') + if(isPrivacyAgreeCamrea!='on'){ + uni.showModal({ + title:"提醒", + content:"将授权你的设备相机使用权限进行拍摄识别功能,是否允许?", + success(isPermisseions){ + if(isPermisseions.confirm){ + checkPermissions() + .then((res:boolean)=>{ + gotoDemoActivity(call,onlyCamera) + uni.setStorageSync('isPrivacyAgreeCamreaByTmui','on') + + }) + .catch(()=>{ + uni.setStorageSync('isPrivacyAgreeCamreaByTmui','off') + }) + } + }, + fail(){ + uni.showToast({title:"未授权相机使用权",icon:"none"}) + } + }) + }else{ + // camera.openCamera(call,onlyCamera) + gotoDemoActivity(call,onlyCamera) + } + + + +} + +export function closeCamera(){ + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/libview/view.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/libview/view.uts new file mode 100644 index 0000000..eaffcd2 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/libview/view.uts @@ -0,0 +1,468 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +// import CardView from 'androidx.cardview.widget.CardView'; +import { ref, } from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import ColorStateList from 'android.content.res.ColorStateList'; +import attr from 'android.R.attr' +import {hexToRgb,getDefaultColor} from "./xCoreColorUtil.uts" + + +/** + * 随机一个uid + * @param rdix 随机因子 + * @param length 取的长度 + * @param isAddStr 是否限制随机结果中的长度,不允许输出长度 + * @returns String + */ +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifndef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length); + // #endif + + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} + +class MyClickListener implements View.OnClickListener { + callbackFun:()=>void; + constructor(cal?:()=>void){ + this.callbackFun = cal as ()=>void; + } + override onClick(v?:View):void { + if(typeof this.callbackFun !='underfinde'){ + this.callbackFun(); + } + } +} +class MyTouchListener implements View.OnTouchListener { + //down,up,move,cancel,longClick + callbackFun:(types:string,event : MotionEvent,detail:UTSJSONObject)=>void; + dubleTime = 0; + tid = 56; + _x = 0; + _y = 0; + // 判断方向的差值 + swipe_mindiff = 40 + // 滑动时,一定时间内只能触发一次事件。不能连续触发。 + tid_siper = 100; + swipeDirection = "" + constructor(call:(types:string,event : MotionEvent,detail?:UTSJSONObject)=>void) { + this.callbackFun = call; + } + override onTouch(view : View, event : MotionEvent) : Boolean { + + if(event.action == MotionEvent.ACTION_DOWN ){ + this._x = event.getX(); + this._y = event.getY(); + this.swipeDirection = "" + this.callbackFun('down',event,{}); + let difftime = new Date().getTime() - this.dubleTime; + if(difftime >0 && difftime<=300){ + this.callbackFun('doubleClick',event ,{}); + } + this.dubleTime = new Date().getTime(); + clearTimeout(this.tid) + tid = setTimeout(function() { + this.callbackFun('longPress',event,{}); + }, 800); + } + if(event.action == MotionEvent.ACTION_UP ){ + clearTimeout(this.tid) + this.callbackFun('up',event,{}); + if(new Date().getTime() - this.dubleTime > 50){ + this.callbackFun('click',event,{}); + } + } + if(event.action == MotionEvent.ACTION_CANCEL || event.action== MotionEvent.ACTION_OUTSIDE ){ + this.callbackFun('cancel',event,{}); + clearTimeout(this.tid) + + } + + if(event.action == MotionEvent.ACTION_MOVE ){ + let x = event.getX(); + let y = event.getY(); + let deltaX = Math.abs(x - this._x); + let deltaY = Math.abs(y - this._y); + if(deltaX > deltaY && deltaX > this.swipe_mindiff){ + this.swipeDirection = (this._x > x) ? "left" : "right"; + }else if(deltaY > deltaX && deltaY > this.swipe_mindiff){ + this.swipeDirection = (this._y < y) ? "down" : "up"; + } + if(this.swipeDirection !=""){ + this.callbackFun('swiper',event,{x,y,diffX:deltaX,diffY:deltaY,direction:this.swipeDirection}); + } + // this._x = x; + // this._y = y; + this.callbackFun('move',event,{}); + clearTimeout(this.tid) + } + + + return true; + } +} + +class xView { + public view : any; + public tagId:string = 'x_view_id_'+getUid(); + public bgView:GradientDrawable + private _onclickFun= (_event : MotionEvent):void=>{}; + private _onTouchStart= (_event : MotionEvent):void=>{}; + private _onTouchEnd= (_event : MotionEvent):void=>{}; + private _onTouchCancel= (_event : MotionEvent):void=>{}; + private _onTouchMove= (_event : MotionEvent):void=>{}; + private _onTouchLongPress= (_event : MotionEvent):void=>{}; + private _onTouchDubleClick= (_event : MotionEvent):void=>{}; + private _onTouchSwiper= (_event : MotionEvent,detail?:UTSJSONObject):void=>{}; + // 设置禁用,不会触发上面的事件。 + private _disabled = false; + constructor(context : Context) { + let view = new View(context); + + view.setTag(this.tagId) + let layoutParams_crd = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + view.setLayoutParams(layoutParams_crd); + this.bgView = new GradientDrawable(); + + // let statuesInts= [[attr.state_enabled].toKotlinList().toIntArray(),[attr.state_pressed].toKotlinList().toIntArray(),[-attr.state_enabled].toKotlinList().toIntArray()] + // let statuesColors= [Color.WHITE,Color.RED,Color.RED] + // let states = new ColorStateList(statuesInts.toKotlinList().toTypedArray(),statuesColors.toKotlinList().toIntArray()) + + this.bgView.setShape(GradientDrawable.RECTANGLE) + this.bgView.setColor(Color.WHITE) + this.bgView.mutate() + view.setBackground(this.bgView) + + this.view = view; + + // view.setOnClickListener(new MyClickListener(():void=>{ + // this._onclickFun() + // })); + view.setOnTouchListener(new MyTouchListener((types:string,event : MotionEvent,detail?:UTSJSONObject):void=>{ + + if(this._disabled == false){ + if(types=='down'){ + this._onTouchStart(event) + } + if(types=='up'){ + this._onTouchEnd(event); + } + if(types=='click'){ + this._onclickFun(event); + } + if(types=='move'){ + this._onTouchMove(event) + } + if(types=='cancel'){ + this._onTouchCancel(event) + } + if(types=='longPress'){ + this._onTouchLongPress(event) + } + if(types=='doubleClick'){ + this._onTouchDubleClick(event) + } + if(types=='swiper'){ + this._onTouchSwiper(event,detail) + } + } + })); + + + } + getView():View{ + return this.view as View; + } + setDisabled(dis:boolean) : xView{ + this._disabled = dis; + return this; + } + + /** + * 触发距离是大于50时触发并判断方向 + * x,y当前坐标,diffX滑动时距离开始时按下的横向x距离,diffY表示竖向。Direction为方向:left,right,up,dowon + *detail: + *{x,y,diffX,diffY,direction} + */ + setSwiper(fun?:(event: MotionEvent,detail?:UTSJSONObject)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchSwiper = fun; + } + return this; + } + setDoubleClick(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchDubleClick = fun; + } + return this; + } + setClick(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onclickFun = fun; + } + return this; + } + setTouchStart(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchStart = fun; + } + return this; + } + setTouchMove(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchMove = fun; + } + return this; + } + setTouchEnd(fun?:(event: MotionEvent)=>void) : xView{ + + if(typeof fun !== 'undefined'){ + this._onTouchEnd = fun; + } + return this; + } + setTouchCancel(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchCancel = fun; + } + return this; + } + setTouchLongPress(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchLongPress = fun; + } + return this; + } + + + setBackgroundColor(colorStr : string) : xView { + this.bgView.mutate() + if(colorStr == 'transparent'){ + this.bgView.setColor(Color.TRANSPARENT) + }else{ + this.bgView.setColor(Color.parseColor(getDefaultColor(colorStr))) + } + + return this; + } + + setBorder(w?:number,colorStr?:string,dashed?:boolean) : xView { + this.bgView.mutate() + + let tw:number = 1; + let tcolor = 'transparent'; + let tdashed = false; + if(typeof tw !== 'undefined'){ + tw = w as number; + } + if(typeof tw !== 'undefined'){ + tcolor = colorStr as string; + } + + if(typeof dashed !== 'undefined'){ + tdashed = dashed as boolean; + } + + let colorNum = Color.TRANSPARENT; + if(tcolor != 'transparent'){ + colorNum = Color.parseColor(getDefaultColor(tcolor)); + } + if(dashed == true){ + let dashedWidth = 8 + let dashedGap = 5 + this.bgView.setStroke(tw.toInt(),colorNum,dashedWidth.toFloat(),dashedGap.toFloat()) + }else{ + this.bgView.setStroke(tw.toInt(),colorNum) + } + + + return this; + } + setMargin(n:any):xView{ + let view = this.view as View; + let selfPrams = view.getLayoutParams() + let params = new LinearLayout.LayoutParams( + selfPrams.width, + selfPrams.height + ) + + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = (rds).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = (rd[0]).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + let rds = 0; + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[0]).toInt(),(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = (rd).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + } + + view.setLayoutParams(params); + return this; + } + + setPadding(n:any):xView{ + let view = this.view as View; + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = (rds).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = (rd[0]).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[0]).toInt(),(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = (rd).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + } + + return this; + } + setRadius(radius:any) : xView{ + let x =0 + let y =0 + this.bgView.mutate() + if(Array.isArray(radius)){ + let rd = radius as number[]; + if(rd.length==0){ + let rdfs = 0; + this.bgView.setCornerRadius((rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==1){ + let rdfs = rd[0]; + this.bgView.setCornerRadius((rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==2){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + x.toFloat(),x.toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==3){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + (rd[2]).toFloat(),(rd[2]).toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==4){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + (rd[2]).toFloat(),(rd[2]).toFloat(), + (rd[3]).toFloat(),(rd[3]).toFloat(), + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + } + }else{ + + let rd = radius as number; + + this.bgView.setCornerRadius((rd).toFloat()); + } + + + return this; + } + /** 设置当前宽和高为父级的相对宽和高 + *w,h有效值为:auto|100% + */ + setSizeBy(w:string="100%",h:string = "auto"){ + let view = this.view as View; + let ww = ViewGroup.LayoutParams.MATCH_PARENT; + let hh = ViewGroup.LayoutParams.MATCH_PARENT; + if(w=="auto"){ + ww = ViewGroup.LayoutParams.WRAP_CONTENT + } + if(h=="auto"){ + hh = ViewGroup.LayoutParams.WRAP_CONTENT + } + + let layoutParams_crd = new LinearLayout.LayoutParams(ww,hh) + view.setLayoutParams(layoutParams_crd); + } + setSize(width : number, height : number) : xView { + let view = this.view as View; + let layoutParams_crd = new LinearLayout.LayoutParams( + (width).toInt(), + (height).toInt() + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + setWidth(width : number) : xView { + let view = this.view as View; + let lpar = view.getLayoutParams(); + let layoutParams_crd = new LinearLayout.LayoutParams( + (width).toInt(), + (lpar.height).toInt(), + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + setHeight(height : number) : xView { + let view = this.view as View; + let lpar = view.getLayoutParams(); + let layoutParams_crd = new LinearLayout.LayoutParams( + (lpar.width).toInt(), + (height).toInt(), + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + + + +} + +export default xView; \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/libview/xCoreColorUtil.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/libview/xCoreColorUtil.uts new file mode 100644 index 0000000..d92083c --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/libview/xCoreColorUtil.uts @@ -0,0 +1,676 @@ + +/** + * 数字转16进制 + */ +function toHex(numbers : number) : string { + let i = 0 as number + if (numbers === i) { + return '00'; + } + let hex = ''; + const hexChars = '0123456789abcdef'; + while (numbers > 0) { + const remainder = numbers % 16; + hex = hexChars[remainder] + hex; + numbers = Math.floor(numbers / 16); + } + return hex; +} + +/** + * 颜色值列表 + */ + +export const colors = new Map([ + ['primary', '#0579FF'], + ['success', '#09CC54'], + ['danger', '#FE6D1B'], + ['warn', '#F0A22C'], + ['error', '#E2001B'], + ['info', '#F2F2F2'], + + ['kleinblue', '#002FA7'], // 克莱因蓝 + ['chinesered', '#FF0000'], // 中国红 + ['internationalorange', '#FF4F00'], // 国际橙 + ['egyptianvlue', '#1034A6'], // 埃及艳蓝 + ['parisviolet', '#6C3082'], // 巴黎紫 + ['moroccanblue', '#1256A7'], // 摩洛哥蓝 + ['brazilgreen', '#009B3A'], // 巴西绿 + ['britishracinggreen', '#004225'], // 英国赛车绿 + ['indianyellow', '#E3A857'], // 印度黄 + ['australiangold', '#FFDF00'], // 澳大利亚金 + ['venetianred', '#C80815'], // 威尼斯红 + ['majorelleblue', '#6050DC'], // 马若雷蓝 + ['tuscanred', '#7C3030'], // 托斯卡红 + ['naplesyellow', '#FADA5E'], // 那不勒斯黄 + ['capumortuum', '#592720'], // 死者之首 + ['mayablue', '#73C2FB'], // 玛雅蓝 + ['persianrose', '#FE28A2'], // 波斯玫瑰 + ['tyrianpurple', '#66023C'], // 泰尔紫 + ['saharasand', '#F1E788'], // 撒哈拉沙 + ['burmeseruby', '#B00A0A'], // 缅甸红宝石 + + ['transparent', 'rgba(0,0,0,0)'], + ['aliceblue', '#F0F8FF'], + ['antiquewhite', '#FAEBD7'], + ['aqua', '#00FFFF'], + ['aquamarine', '#7FFFD4'], + ['azure', '#F0FFFF'], + ['beige', '#F5F5DC'], + ['bisque', '#FFE4C4'], + ['black', '#000000'], + ['blanchedalmond', '#FFEBCD'], + ['blue', '#0000FF'], + ['blueviolet', '#8A2BE2'], + ['brown', '#A52A2A'], + ['burlywood', '#DEB887'], + ['cadetblue', '#5F9EA0'], + ['chartreuse', '#7FFF00'], + ['chocolate', '#D2691E'], + ['coral', '#FF7F50'], + ['cornflowerblue', '#6495ED'], + ['cornsilk', '#FFF8DC'], + ['crimson', '#DC143C'], + ['cyan', '#00FFFF'], + ['darkblue', '#00008B'], + ['darkcyan', '#008B8B'], + ['darkgoldenrod', '#B8860B'], + ['darkgray', '#A9A9A9'], + ['darkgreen', '#006400'], + ['darkkhaki', '#BDB76B'], + ['darkmagenta', '#8B008B'], + ['darkolivegreen', '#556B2F'], + ['darkorange', '#FF8C00'], + ['darkorchid', '#9932CC'], + ['darkred', '#8B0000'], + ['darksalmon', '#E9967A'], + ['darkseagreen', '#8FBC8F'], + ['darkslateblue', '#483D8B'], + ['darkslategray', '#2F4F4F'], + ['darkturquoise', '#00CED1'], + ['darkviolet', '#9400D3'], + ['deeppink', '#FF1493'], + ['deepskyblue', '#00BFFF'], + ['dimgray', '#696969'], + ['dodgerblue', '#1E90FF'], + ['firebrick', '#B22222'], + ['floralwhite', '#FFFAF0'], + ['forestgreen', '#228B22'], + ['fuchsia', '#FF00FF'], + ['gainsboro', '#DCDCDC'], + ['ghostwhite', '#F8F8FF'], + ['gold', '#FFD700'], + ['goldenrod', '#DAA520'], + ['gray', '#808080'], + ['green', '#008000'], + ['greenyellow', '#ADFF2F'], + ['honeydew', '#F0FFF0'], + ['hotpink', '#FF69B4'], + ['indianred', '#CD5C5C'], + ['indigo', '#4B0082'], + ['ivory', '#FFFFF0'], + ['khaki', '#F0E68C'], + ['lavender', '#E6E6FA'], + ['lavenderblush', '#FFF0F5'], + ['lawngreen', '#7CFC00'], + ['lemonchiffon', '#FFFACD'], + ['lightblue', '#ADD8E6'], + ['lightcoral', '#F08080'], + ['lightcyan', '#E0FFFF'], + ['lightgoldenrodyellow', '#FAFAD2'], + ['lightgray', '#D3D3D3'], + ['lightgreen', '#90EE90'], + ['lightpink', '#FFB6C1'], + ['lightsalmon', '#FFA07A'], + ['lightseagreen', '#20B2AA'], + ['lightskyblue', '#87CEFA'], + ['lightslategray', '#778899'], + ['lightsteelblue', '#B0C4DE'], + ['lightyellow', '#FFFFE0'], + ['lime', '#00FF00'], + ['limegreen', '#32CD32'], + ['linen', '#FAF0E6'], + ['magenta', '#FF00FF'], + ['maroon', '#800000'], + ['mediumaquamarine', '#66CDAA'], + ['mediumblue', '#0000CD'], + ['mediumorchid', '#BA55D3'], + ['mediumpurple', '#9370DB'], + ['mediumseagreen', '#3CB371'], + ['mediumslateblue', '#7B68EE'], + ['mediumspringgreen', '#00FA9A'], + ['mediumturquoise', '#48D1CC'], + ['mediumvioletred', '#C71585'], + ['midnightblue', '#191970'], + ['mintcream', '#F5FFFA'], + ['mistyrose', '#FFE4E1'], + ['moccasin', '#FFE4B5'], + ['navajowhite', '#FFDEAD'], + ['navy', '#000080'], + ['oldlace', '#FDF5E6'], + ['olive', '#808000'], + ['olivedrab', '#6B8E23'], + ['orange', '#FFA500'], + ['orangered', '#FF4500'], + ['orchid', '#DA70D6'], + ['palegoldenrod', '#EEE8AA'], + ['palegreen', '#98FB98'], + ['paleturquoise', '#AFEEEE'], + ['palevioletred', '#DB7093'], + ['papayawhip', '#FFEFD5'], + ['peachpuff', '#FFDAB9'], + ['peru', '#CD853F'], + ['pink', '#FFC0CB'], + ['plum', '#DDA0DD'], + ['powderblue', '#B0E0E6'], + ['purple', '#800080'], + ['rebeccapurple', '#663399'], + ['red', '#FF0000'], + ['rosybrown', '#BC8F8F'], + ['royalblue', '#4169E1'], + ['saddlebrown', '#8B4513'], + ['salmon', '#FA8072'], + ['sandybrown', '#F4A460'], + ['seagreen', '#2E8B57'], + ['seashell', '#FFF5EE'], + ['sienna', '#A0522D'], + ['silver', '#C0C0C0'], + ['skyblue', '#87CEEB'], + ['slateblue', '#6A5ACD'], + ['slategray', '#708090'], + ['snow', '#FFFAFA'], + ['springgreen', '#00FF7F'], + ['steelblue', '#4682B4'], + ['tan', '#D2B48C'], + ['teal', '#008080'], + ['thistle', '#D8BFD8'], + ['tomato', '#FF6347'], + ['turquoise', '#40E0D0'], + ['violet', '#EE82EE'], + ['wheat', '#F5DEB3'], + ['white', '#FFFFFF'], + ['whitesmoke', '#F5F5F5'], + ['yellow', '#FFFF00'], + ['yellowgreen', '#9ACD32'] + +]) + +export function isValidColor(color : string) : boolean { + // return chroma.valid(color); + const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + const rgbRegex = /^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/; + const rgbaRegex = /^rgba\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*((1(\.0{1,2})?)|(0(\.\d{1,2})?))\)$/; + const hslRegex = /^hsl\((\d{1,3}), (\d{1,3})%, (\d{1,3})%\)$/; + const hslaRegex = /^hsla\(\s*((\d{1,2}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)\s*,\s*((\d{1,2}|\d{0,1}\d{1}\d{1}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)%\s*,\s*((\d{1,2}|\d{0,1}\d{1}\d{1}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)%\s*,\s*((1|0(\.\d{1,2})?|(\.\d{1,2})))\)$/i; + + + if (color == '') { + return false; // 颜色值为空 + } else if (color === 'inherit' || color === 'transparent') { + return false; // 特殊颜色值 + } else if (color === 'currentColor') { + return false; // currentColor 不是有效的颜色值 + } else if (hexRegex.test(color) || rgbRegex.test(color) || rgbaRegex.test(color) || hslRegex.test(color) || hslaRegex.test(color)) { + return true; // 符合颜色值的格式 + } + return false; +} +/** + * 获取默认的颜色值 + * @param [string] 颜色名称或者16进制颜色值 + */ +export function getDefaultColor(sColor : string) : string { + if(sColor=="") return "" + let sc = sColor.toLocaleLowerCase().trim().replace(" ",""); + + if (isValidColor(sc)) { + // 如果符合所有颜色值,进行转换为16进制。css方便统一解析。 + return sc; + } + // 检测是否是颜色名称。 + let sco = colors.get(sc); + if (typeof sco == 'string') return sco as string; + return colors.get("primary")!; +} + +/** + * 16进制转rgb + */ +export function hexToRgb(sColors : string) : RGBA { + if (sColors == "") { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + let p : number[] = arr.map((val : string) : number => parseInt(val)); + + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + p.add(1) + + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: arr.length==3?p[3]:parseFloat(arr[3]) + } as RGBA + } + + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA; +} +/** + * rgb转hsl + */ +export function rgbToHsl(rgb : UTSJSONObject) : UTSJSONObject { + let r = rgb.getNumber("r") + r = r as number / 255 + let g = rgb.getNumber("g") + g = g as number / 255 + let b = rgb.getNumber("b") + b = b as number / 255 + let a = rgb.getNumber("a") + + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + let h=60 * (4 + (r - g) / (max - min)); + let s=(max - min) / (2 - max - min); + let l= (max + min) / 2; + + if (max === r) { + h = (60 * (g - b)) / (max - min); + } else if (max === g) { + h = 60 * (2 + (b - r) / (max - min)); + } + + if (h < 0) { + h += 360; + } + + + if (max === min) { + s = 0; + } else if (l < 0.5) { + s = (max - min) / (max + min); + } + + return { h: h, s: s * 100, l: l * 100, a: a }; +} + +/** + * hsl转rgb + */ +export function hslToRgb(hsl : UTSJSONObject) : UTSJSONObject { + let h = hsl.getNumber("h")! + let s = hsl.getNumber("s")! + let l = hsl.getNumber("l")! + let a = hsl.getNumber("a")! + + h = h / 360; + s = s / 100; + l = l / 100; + let r = l; + let g = l; + let b = l; + + function hue2rgb(pxx : number, q : number, txs : number) : number { + let t = txs; + let p = pxx; + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + + + if (s > 0) { + let q = l * (1 + s); + if (l >= 0.5) { + q = l + s - l * s; + } + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + + } + + r = Math.round(r * 255); + g = Math.round(g * 255); + b = Math.round(b * 255); + return { r, g, b, a }; +} + +/** + * rgb转16进制 + */ +export function rgbToHex(rgb : UTSJSONObject) : string { + let r = rgb.getNumber("r")! + let g = rgb.getNumber("g")! + let b = rgb.getNumber("b")! + let a = rgb.getNumber("a")! + return "#" + toHex(r) + toHex(g) + toHex(b) + toHex(a*255) +} +export function hslaToCss(hsl : UTSJSONObject) : string { + + let rgb = hslToRgb(hsl) + + return rgbToHex(rgb) +} + +export function hslaToRgbCss(hsl : UTSJSONObject) : string { + + let rgb = hslToRgb(hsl) + let r = rgb.getNumber("r")! + let g = rgb.getNumber("g")! + let b = rgb.getNumber("b")! + let a = rgb.getNumber("a")! + return `rgba(${r},${g},${b},${a})` +} + +// 根据 HSLA 颜色计算亮度 +export function getLuminance(color : UTSJSONObject, type = "rgba") : number { + + + let colordefault : UTSJSONObject = type == 'rgba' ? color : hslToRgb(color); + const r= colordefault.getNumber("r")! + const g= colordefault.getNumber("g")! + const b= colordefault.getNumber("b")! + const rs = r / 255 + const gs = g / 255 + const bs = b / 255 + const rl = Math.pow(rs <= 0.03928 ? rs / 12.92 : ((rs + 0.055) / 1.055), 2.4); + const gl = Math.pow(gs <= 0.03928 ? gs / 12.92 : ((gs + 0.055) / 1.055), 2.4); + const bl = Math.pow(bs <= 0.03928 ? bs / 12.92 : ((bs + 0.055) / 1.055), 2.4); + + return 0.2126 * rl + 0.7152 * gl + 0.0722 * bl; +} + +/** + * 对颜色加深 + */ +export function colorAddDeepen(sColor : string) : string { + + let rgb = hexToRgb(getDefaultColor(sColor)); + + let hsl = rgbToHsl(rgb); + + let l = hsl.getNumber("l")! - 5; + l = Math.max(0, Math.min(l, 100)) + + return hslaToRgbCss({ h: hsl.getNumber("h"), s: hsl.getNumber("s"), l, a: hsl.getNumber("a")! }) +} +/** + * 对颜色提亮 + */ +export function colorAddBrighten(sColor : string) : string { + let rgb = hexToRgb(getDefaultColor(sColor)); + let hsl = rgbToHsl(rgb); + let l = hsl.getNumber("l")! + 10; + l = Math.max(0, Math.min(l, 100)) + return rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s:hsl.getNumber("s"), l, a: hsl.getNumber("a")! })) +} + + + + +/** + * 获取浅色系主题,根据颜色值计算。返回正常值和hover值。 + */ +export function colorGetThint(sColor : string) { + let rgb = hexToRgb(getDefaultColor(sColor)); + let hsl = rgbToHsl(rgb); + let s = hsl.getNumber("s")!; + // let l = hsl.getNumber("l"); + if (Math.ceil(s) > 0) { + s = 45 + } + return { + default: rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s, l: 93, a: hsl.getNumber("a")! })), + hover: rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s, l: 85, a: hsl.getNumber("a")! })) + } +} +/** + * 获取正常主题,根据颜色值计算。返回正常值和hover值。 + */ +export function colorGetHover(sColor : string) { + + return { + default: sColor, + hover: colorAddDeepen(sColor) + } +} + + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getDefaultColorObj(color : string, hoverColor : string) : UTSJSONObject { + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + let shadow = hslaToRgbCss({ h: hsla.getNumber("h")!, s: (hsla.getNumber("s")!)== 0 ? 0 : 60, l: 40, a: 0.4 }); + let shadowHOver = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: (hoverHsla.getNumber("s")!)== 0 ? 0 : 60, l: 40, a: 0.4 }); + if((hsla.getNumber("h")!)==0&&(hsla.getNumber("s")!)==0){ + shadow = "transparent" + } + if((hoverHsla.getNumber("h")!)==0&&(hoverHsla.getNumber("s")!)==0){ + shadowHOver = "transparent" + } + let o = { + default: { + background: hslaToRgbCss(hsla), + borderColor: hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: Math.min(Math.max(0, hsla.getNumber("l")! - 5), hsla.getNumber("l")!) }), + fontColor: getLuminance(hsla, 'hsla') < 0.46 && hsla.getNumber("a")! > 0.1 ? '#ffffff' : '#000000', + shadow: shadow + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: Math.min(Math.max(0, hoverHsla.getNumber("l")! - 10), hoverHsla.getNumber("l")!) }), + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: Math.max(Math.max(0, hoverHsla.getNumber("l")! - 10), hoverHsla.getNumber("l")!) }), + fontColor: getLuminance(hoverHsla, 'hsla') < 0.46 && hoverHsla.getNumber("a")! > 0.1 ? '#ffffff' : '#000000', + shadow: shadowHOver + } + } as UTSJSONObject + + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getTextColorObj(color : string, hoverColor : string) : UTSJSONObject { + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let o = { + default: { + background: "transparent", + borderColor: "transparent", + fontColor: getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 95 }), + borderColor:"transparent", + fontColor: getLuminance(hoverHsla, 'hsla') < 0.3 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getThinColorObj(color : string, hoverColor : string,isCoverDark?:boolean) : UTSJSONObject { + let dark = isCoverDark==null?false:isCoverDark + // #ifdef WEB + dark = isCoverDark==undefined?false:dark + // #endif + + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let fontcolor = getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l:30 }) + let bordercolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark==true?21:92 }) + let bgcolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark==true?20:95 }) + if(dark){ + let p = hsla; + p.set('l',90) + fontcolor = hslaToRgbCss(p) + p.set('l',20) + p.set('s',p.getNumber('s')!==0?0:20) + bgcolor = hslaToRgbCss(p) + p.set('l',22) + bordercolor = hslaToRgbCss(p) + } + let o = { + default: { + background: bgcolor, + borderColor:bordercolor, + fontColor: fontcolor, + shadow: "transparent", + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark==true?18:88 }), + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a:0, l: dark==true?18:80 }), + fontColor: getLuminance(hoverHsla, 'hsla') < 0.3 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getOutlineColorObj(color : string, hoverColor : string) : UTSJSONObject { + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let o = { + default: { + background: 'transparent', + borderColor:hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: 1, l: 75 }), + fontColor: getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + }, + + active: { + background: 'transparent', + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a:1, l: 70 }), + fontColor: getLuminance(hoverHsla, 'hsla') < 0.3 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 设置颜色的亮度值。29 + * isCoverDark:是根据亮度值,是否要设置n的值,如果n超过了 + * 指定的30就不操作。 + */ +export function setTextColorLightByDark(color:string):string{ + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let l = hsla.getNumber('l')! + let s = hsla.getNumber('s')! + if(l<30){ + if(s>0){ + hsla.set('l',50) + }else{ + hsla.set('l',100) + } + + } + + return hslaToRgbCss(hsla) +} +/** + * 变动的颜色是否需要变深。如果不需要返回原始颜色 + * 如果果需要自动加深。 + */ +export function setBgColorLightByDark(color:string):string{ + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let l = hsla.getNumber('l')! + let s = hsla.getNumber('s')! + if(s==0&&l>50){ + hsla.set('l',100-l) + } + if(s>0){ + if(l>50){ + hsla.set('l',100-l) + } + } + return hslaToRgbCss(hsla) +} + +export function isBlackAndWhite(color:string):boolean{ + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let s = hsla.getNumber('s')! + return s==0 +} + + + diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/anim/enter_anim.xml b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/anim/enter_anim.xml new file mode 100644 index 0000000..8d4ecfa --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/anim/enter_anim.xml @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/anim/exit_anim.xml b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/anim/exit_anim.xml new file mode 100644 index 0000000..0f46c62 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/anim/exit_anim.xml @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/layout/demo_activity.xml b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/layout/demo_activity.xml new file mode 100644 index 0000000..2768384 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-android/res/layout/demo_activity.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-harmony/index.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..f76fe07 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-harmony/index.uts @@ -0,0 +1,7 @@ +import {CALL_RESULT_FUN} from "../interface.uts" +export function openCameraApi(callback : CALL_RESULT_FUN, onlyCameras : boolean) { + +} +export function closeCamera() { + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources new file mode 100644 index 0000000..0bfa43f --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources @@ -0,0 +1,212 @@ + + + + + files + + Headers/unimoduleXMlkitScannigS-Swift.h + + HFgFRh52QVFRripRAm++m8vPUac= + + Headers/unimoduleXMlkitScannigS.h + + FH2SRnQAHIO8AbDZPa5/Bz/CcdA= + + Info.plist + + G4k0SeG744Lkgqw1b+k6ksST6dA= + + Modules/module.modulemap + + NFo72bjg30tp1kal2iM5fGM3zq8= + + Modules/unimoduleXMlkitScannigS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + pOY7RAEwyRn2iytrDpxN4AHPkRk= + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.abi.json + + K/bnDRDf5y9AgNJoEBNi0VTphF4= + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + mVavA9fh+FYY94dQ5NaeIyOJVuA= + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + QEufnDNcE56gLXZxvRbTRO6726k= + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + mVavA9fh+FYY94dQ5NaeIyOJVuA= + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + TikwGU5EgjS4+ZdpC0krx1khEDA= + + config.json + + 88FIH2zCpVE0VhuGIIM7Imjpgcc= + + + files2 + + Headers/unimoduleXMlkitScannigS-Swift.h + + hash2 + + E4Dgwf5RamV3mYHjKR7FONZ/4+4DSHTMNJiHRDFDXDg= + + + Headers/unimoduleXMlkitScannigS.h + + hash2 + + XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY= + + + Modules/module.modulemap + + hash2 + + fUhLEoFeXfVrTN631TcXpE6uFd0Axl0ViKW+dgm9asA= + + + Modules/unimoduleXMlkitScannigS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + hash2 + + KPKUL9/AgF4vrs7f0PSiUYH7vvw6J/2C/Kr/vuy3xQc= + + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.abi.json + + hash2 + + Y9riNBbHfsbD+9QW/87fL8r+aXQhImNKSiL6J9cFX3Q= + + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + hash2 + + 1pT7hTGOzumJGeoX2uCvP8YdB2INlF8T9zDlXWZcDz4= + + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + hash2 + + JSEDYvJXFaJ8lmZPib1fHYRGfbS+OjRe6rsh0MJGPKM= + + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + hash2 + + 1pT7hTGOzumJGeoX2uCvP8YdB2INlF8T9zDlXWZcDz4= + + + Modules/unimoduleXMlkitScannigS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + hash2 + + TfRDPS+zHSBY/geHv1Gqp4N3jBAqPIrencgsGg5vDzI= + + + config.json + + hash2 + + w41XwHPkqBxEtGJ4WF63+7VPz1ej3515wAWG/Aou0XY= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/config.json b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..e78da0b --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/config.json @@ -0,0 +1,9 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "GoogleMLKit/BarcodeScanning", + "version": "5.0.0" + } + ] +} diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/index.uts b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..ffe0469 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/index.uts @@ -0,0 +1,743 @@ +import { AVCaptureSession, AVCaptureDevice, AVMediaType, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureDeviceInput, AVCaptureInput, AVCaptureVideoDataOutput, AVCaptureConnection, AVCaptureVideoPreviewLayer, AVLayerVideoGravity, AVCaptureVideoOrientation } from 'AVFoundation'; +import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos'; +import { CMSampleBuffer, CMSampleBufferGetFormatDescription, CMFormatDescription, CMVideoFormatDescriptionGetDimensions } from 'CoreMedia'; +import { DispatchQueue } from "Dispatch" +import { UIView, UIImage, UIApplication, UIImageView, UILabel, UIViewController, UIFontDescriptor, UIFont, NSTextAlignment, UITapGestureRecognizer, UIImagePickerController, UIImagePickerControllerDelegate, UINavigationControllerDelegate } from 'UIKit'; +import { CGRect, CGFloat, CGPoint } from 'CoreFoundation'; +import { Barcode, BarcodeScannerOptions, BarcodeFormat, BarcodeScanner, CMVideoDimensions } from "MLKitBarcodeScanning" +import { VisionImage } from "MLKit" +import { SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND, CALL_RESULT_FUN, AUTH_CALL_BACK_TYPE } from '../interface.uts'; + +import { NotificationCenter, NSNotification, Notification } from 'Foundation'; +import { Selector } from 'ObjectiveC'; +import { Alignment } from 'ARKit'; +import { CABasicAnimation } from 'QuartzCore'; + +type ConverXy = { + x : number, + y : number, + minx : number, + maxx : number, + miny : number, + maxy : number, +} +type contaiaSize = { + width : number, + height : number +} +type contaiaCalseSize = { + scale : number, + offsetX : number, + offsetY : number +} +type contaiPointXy = { + x : number, + y : number +} +// 资料参考: +// https://github.com/JimmyPun610/BarcodeScanner.Mobile/blob/master/BarcodeScanner.Mobile.Maui/Platforms/iOS/CaptureVideoDelegate.cs +// 识别结果 +let scanResult = [] as Swift.Array +let captureSession : null | AVCaptureSession = null; + +let captureDeviceAllGlobal : null | AVCaptureDevice = null; +let FlashButton:null|UILabel = null; +let flashModel = false; +// 视频宽 +let videoWidth = 0 +// 视频高 +let videoHeight = 0 +// 图像捕捉事件代理。 +let captureOutDelegate : CaptureOutSessionBuffer | null = null; +let pointsEvents = [] as PointClickEvent[] +let isCamreaing = false; + +let pointView = [] as UIView[] + +let onlyCamera : boolean = false; + +let barcodeOptions = BarcodeScannerOptions(formats = BarcodeFormat.all) +let parentView : UIView | null = null +let camreaViewLayer : UIView | null = null +let pointsLayerView : UIView | null = null +let imageUiView : UIImageView | null = null +let cameraView : AVCaptureVideoPreviewLayer | null = null + +let backevents : BackEvents | null = null; +let photosevents : PhotoSelectedEvents | null = null; +let scanevents : ScanEvents | null = null; +let flashBtnevents:FlashBtnEvents|null = null; +let rsultCallBack : CALL_RESULT_FUN = (str : string) => { } +let delegate : null | useImagePickerDelegate = null; +let openAnimation = true; +/** 加上这个标签可以持续响应事件,回调执行时必要的标签. */ +@MainActor +class useImagePickerDelegate implements UIImagePickerControllerDelegate, UINavigationControllerDelegate { + call : (image : any | null) => void; + constructor(call : (image : any | null) => void) { + this.call = call; + } + imagePickerController(controller : UIImagePickerController, @argumentLabel("didFinishPickingMediaWithInfo") info : Map) { + let image = info.get(UIImagePickerController.InfoKey.originalImage) + this.call(image) + controller.dismiss(animated = true, completion = null) + } + imagePickerControllerDidCancel(controller : UIImagePickerController) { + this.call(null) + controller.dismiss(animated = true, completion = null) + } +} + + +class PointClickEvent { + private callback : (txt : string) => void + private text : string; + constructor(callback : (txt : string) => void, atext : string) { + this.callback = callback; + this.text = atext; + super.init() + } + + @objc onclick() { + + this.callback(this.text) + } +} + +class BackEvents { + private callback : () => void + constructor(callback : () => void) { + this.callback = callback + super.init() + } + @objc onclick() { + + this.callback() + } +} +class PhotoSelectedEvents { + private callback : () => void + constructor(callback : () => void) { + this.callback = callback + super.init() + } + @objc onclick() { + + this.callback() + } +} +class ScanEvents { + private callback : () => void + constructor(callback : () => void) { + this.callback = callback + super.init() + } + @objc onclick() { + + this.callback() + } +} + +class FlashBtnEvents { + private callback : () => void + constructor(callback : () => void) { + this.callback = callback + super.init() + } + @objc onclick() { + this.callback() + } +} + +class CaptureOutSessionBuffer implements AVCaptureVideoDataOutputSampleBufferDelegate { + callback : (str : SCANNING_PHOTO_RESULT) => void = (str : SCANNING_PHOTO_RESULT) => { } + constructor(dv : (str : SCANNING_PHOTO_RESULT) => void) { + this.callback = dv; + super() + } + captureOutput(output : AVCaptureOutput, @argumentLabel("didOutput") sampleBuffer : CMSampleBuffer, @argumentLabel("from") connection : AVCaptureConnection) { + if (!isCamreaing) return; + // console.log('图片捕捉正确') + + let image = new VisionImage(buffer = sampleBuffer) + // 这里会直接影响到测量的起始点。下面是镜像,测量是图片左上为起始,但设备是竖向,因此计算时的x,y坐标其实是相对屏幕向右转下,x,y是反向的,因为是镜像 + // 所以计算位置时,x,y是反的,宽和高也是相反的。 + image.orientation = UIImage.Orientation.right + let barcodeOptions = BarcodeScannerOptions(formats = BarcodeFormat.all) + // options=barcodeOptions + let barcodeScanner = new BarcodeScanner.barcodeScanner(options = barcodeOptions) + + barcodeScanner.process(image, completion = (features : Swift.Array | null, error) => { + + if (features == null || error != null) { + return; + } + if (features!.length == 0 || scanResult.length > 0) { + return; + } + + // 暂停识别。 + captureSession!.stopRunning() + + scanResult = features! + let descVideo : CMFormatDescription | null = CMSampleBufferGetFormatDescription(sampleBuffer); + if (descVideo != null) { + let dimesionsize : CMVideoDimensions = CMVideoFormatDescriptionGetDimensions(descVideo!) + videoWidth = Number(dimesionsize.width) + videoHeight = Number(dimesionsize.height) + } + + + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + + for (let i = 0; i < features!.length; i++) { + let barcode = features![i] + // 位置信息 + let bounds = barcode.frame + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + let iminfo = { + width: Number(bounds.width), + height: Number(bounds.height), + centerX: Number(bounds.midX), + centerY: Number(bounds.midY) + } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners!) { + // pos是pointValue类型并返回CGPoint,其中有x,y + let ponit = pos.cgPointValue + posinfo.push([Number(ponit.x), Number(ponit.y)] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue == null ? '' : (rawValue!)) + + } + let res = { + url: '', + position: listpos, + bounds: bounedlist, + text: rulstText, + imgWidth:0, + imgHeight:0 + } as SCANNING_PHOTO_RESULT + + this.callback(res) + }) + + } +} +// 检查权限 +export function isCheckPermissions(callFun : null | AUTH_CALL_BACK_TYPE) { + let realcall : AUTH_CALL_BACK_TYPE = (_ : boolean) => { }; + if (callFun != null) { + let cllfunFun = callFun!; + realcall = cllfunFun + } + if (!onlyCamera) { + PHPhotoLibrary.requestAuthorization((isok : PHAuthorizationStatus) => { + // 拒绝了相册选取权限。 + if (isok != PHAuthorizationStatus.authorized) { + realcall(false) + return; + } + AVCaptureDevice.requestAccess(for = AVMediaType.video, completionHandler = (isok2 : boolean) => { + if (!isok2) { + realcall(false) + return; + } + realcall(true) + }) + }) + } else { + AVCaptureDevice.requestAccess(for = AVMediaType.video, completionHandler = (isok2 : boolean) => { + if (!isok2) { + realcall(false) + return; + } + realcall(true) + }) + } + +} + + + + +function xCamreaInit() { + let t = this; + let sys = uni.getSystemInfoSync(); + if (parentView != null) { + parentView!.removeFromSuperview() + } + parentView = new UIView(); + let scaleAni = new CABasicAnimation(keyPath = "transform.scale") + scaleAni.fromValue = 0 + scaleAni.toValue = 1 + scaleAni.duration = 0.25 + + + parentView!.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = (sys.screenHeight).toInt()) + parentView!.backgroundColor = UTSiOS.colorWithString("#000000") + + let parent = UTSiOS.getCurrentViewController() as UIViewController; + let windUiview = parent.view as UIView + windUiview.addSubview(parentView!) + + + + let safeTop = sys.statusBarHeight + 50 + let safeHeight = sys.screenHeight - 100 - sys.statusBarHeight - 50 + + // 绘制界面 + + // 创建一张图片预览层。 + imageUiView = new UIImageView(); + imageUiView!.frame = new CGRect(x = 0, y = safeTop.toInt(), width = (sys.windowWidth).toInt(), height = (safeHeight).toInt()) + imageUiView!.isHidden = true; + + parentView!.addSubview(imageUiView!); + + // 创建小绿点层. + pointsLayerView = new UIView() + pointsLayerView!.frame = new CGRect(x = 0, y = safeTop.toInt(), width = (sys.windowWidth).toInt(), height = (safeHeight).toInt()) + + // 创建视频预览层。 + camreaViewLayer = new UIView() + camreaViewLayer!.frame = new CGRect(x = 0, y = safeTop.toInt(), width = (sys.windowWidth).toInt(), height = (safeHeight).toInt()) + parentView!.addSubview(camreaViewLayer!); + + cameraView = new AVCaptureVideoPreviewLayer(session = captureSession!) + // 设置预览层绑定 + // 下面的缩放会居中显示,因此左顶点可能在左上方 + cameraView!.videoGravity = AVLayerVideoGravity.resizeAspectFill + cameraView!.connection!.videoOrientation = AVCaptureVideoOrientation.portrait + cameraView!.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = (safeHeight).toInt()) + + DispatchQueue.main.async(execute = () : void => { + // 绑定渲染层。 + camreaViewLayer!.layer.addSublayer(cameraView!) + captureSession!.startRunning() + + + // 创建一个上遮盖板。 + // let toplayer = new UIView() + // toplayer.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = 100) + // toplayer.backgroundColor = UTSiOS.colorWithString("rgba(255,0,0,0)") + // parentView!.addSubview(toplayer); + + // 创建一个下遮盖板。 + let bottomlayer = new UIView() + bottomlayer.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = 100) + bottomlayer.backgroundColor = UTSiOS.colorWithString("#000000") + parentView!.addSubview(bottomlayer); + + // 创建一个返回按钮文本。 + let backButton = new UILabel() + backButton.frame = new CGRect(x = 16, y = 58, width = (sys.windowWidth - 16).toInt(), height = 32) + backButton.text = String("返回") + backButton.font = UIFont.systemFont(ofSize = new CGFloat(16)) + backButton.textColor = UTSiOS.colorWithString("#FFFFFF") + + parentView!.addSubview(backButton); + + // 创建一个相册选取按钮 + let photoBtn = new UILabel() + photoBtn.frame = new CGRect(x = 16, y = (sys.screenHeight - 88).toInt(), width = 80, height = 32) + photoBtn.text = String(onlyCamera ? "" : "相册选取") + + photoBtn.font = UIFont.systemFont(ofSize = new CGFloat(16)) + photoBtn.textColor = UTSiOS.colorWithString("#FFFFFF") + parentView!.addSubview(photoBtn); + + // 创建个闪光灯打开和关闭的文本层. + let flashBtn = new UILabel() + flashBtn.frame = new CGRect(x = ((sys.windowWidth - 80)/2).toInt(), y = (sys.screenHeight - 88).toInt(), width = 80, height = 32) + flashBtn.text = String("开灯") + flashBtn.font = UIFont.systemFont(ofSize = new CGFloat(16)) + flashBtn.textAlignment = NSTextAlignment.center + flashBtn.textColor = UTSiOS.colorWithString("#FFFFFF") + parentView!.addSubview(flashBtn); + FlashButton = flashBtn; + + + // 创建一个继续扫一扫的按钮 + let scanBtn = new UILabel() + scanBtn.frame = new CGRect(x = (sys.windowWidth - 96).toInt(), y = (sys.screenHeight - 88).toInt(), width = 80, height = 32) + + scanBtn.text = String("扫一扫") + scanBtn.font = UIFont.systemFont(ofSize = new CGFloat(16)) + scanBtn.textAlignment = NSTextAlignment.right + scanBtn.textColor = UTSiOS.colorWithString("#FFFFFF") + parentView!.addSubview(scanBtn); + + + // 最高层级. + parentView!.addSubview(pointsLayerView!); + + + // 添加事件。 + // 返回,关闭弹层。 + backevents = new BackEvents(() => { + closeScan(); + quitView(); + }) + // 点击了相册选取。 + function setToXiangChe() { + if (onlyCamera) { + return; + } + let pic = new UIImagePickerController() + DispatchQueue.main.async(execute = () : void => { + delegate = new useImagePickerDelegate((image : any | null) => { + if (image != null) { + let realimageds = image! as UIImage; + closeScan(); + imageUiView!.image = realimageds + imageUiView!.contentMode = UIView.ContentMode.scaleAspectFit + camreaViewLayer!.isHidden = true; + imageUiView!.isHidden = false; + + // 图片识别码. + let visionImage = new VisionImage(image = realimageds) + visionImage.orientation = realimageds.imageOrientation + + let barcodeOptions = BarcodeScannerOptions(formats = BarcodeFormat.all) + let barcodeScanner = new BarcodeScanner.barcodeScanner(options = barcodeOptions) + barcodeScanner.process(visionImage, completion = (features : Swift.Array | null, error) => { + + if (features == null || error != null) { + return; + } + if (features!.length == 0) { + return; + } + + scanResult = features! + + videoWidth = Number(realimageds.size.width); + videoHeight = Number(realimageds.size.height); + + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + + for (let i = 0; i < features!.length; i++) { + let barcode = features![i] + // 位置信息 + let bounds = barcode.frame + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + let iminfo = { + width: Number(bounds.width), + height: Number(bounds.height), + centerX: Number(bounds.midX), + centerY: Number(bounds.midY) + } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners!) { + // pos是pointValue类型并返回CGPoint,其中有x,y + let ponit = pos.cgPointValue + posinfo.push([Number(ponit.x), Number(ponit.y)] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue == null ? '' : (rawValue!)) + + } + let result = { + url: '', + position: listpos, + bounds: bounedlist, + text: rulstText, + imgWidth:0, + imgHeight:0 + } as SCANNING_PHOTO_RESULT + let deg = 0; + if (realimageds.imageOrientation == UIImage.Orientation.right) { + deg = 90 + } else if (realimageds.imageOrientation == UIImage.Orientation.up) { + deg = 0 + } else if (realimageds.imageOrientation == UIImage.Orientation.left) { + deg = 270 + } else if (realimageds.imageOrientation == UIImage.Orientation.down) { + deg = 180 + } + + console.log(deg) + createPointView(result, deg) + uni.setStorageSync("xMlKITScaning", JSON.stringify(result.text)) + // t.$emit("scan") + if (result.text.length == 1) { + rsultCallBack(result.text[0]) + closeScan() + quitView() + } + + }) + } + }); + pic.sourceType = UIImagePickerController.SourceType.photoLibrary + pic.mediaTypes = ["public.image"] + pic.delegate = delegate! + UTSiOS.getCurrentViewController().present(pic, animated = true, completion = nil) + }) + + + } + photosevents = new PhotoSelectedEvents(() => { + + setToXiangChe(); + }) + scanevents = new ScanEvents(() => { + // 继续扫一扫 + openAnimation = false + startCamera(); + }) + flashBtnevents = new FlashBtnEvents(() => { + // 开头灯光 + flashModel = !flashModel + setFlashModel(flashModel) + flashBtn.text = flashModel?"关灯":String("开灯") + }) + + + // 返回的事件。 + backButton.isUserInteractionEnabled = true + let backevents_rz = new UITapGestureRecognizer() + backevents_rz.addTarget(backevents, action = new Selector("onclick")) + backButton.addGestureRecognizer(backevents_rz) + // 相册 按钮事件。。 + let photosevents_rz = new UITapGestureRecognizer() + photosevents_rz.addTarget(photosevents, action = new Selector("onclick")) + photoBtn.addGestureRecognizer(photosevents_rz) + photoBtn.isUserInteractionEnabled = true + // 扫一扫 按钮事件。。 + scanBtn.isUserInteractionEnabled = true + let scanevents_rz = new UITapGestureRecognizer() + scanevents_rz.addTarget(scanevents, action = new Selector("onclick")) + scanBtn.addGestureRecognizer(scanevents_rz) + //打开灯光事件.setFlashModel + flashBtn.isUserInteractionEnabled = true + let flashBtnevents_rz = new UITapGestureRecognizer() + flashBtnevents_rz.addTarget(flashBtnevents, action = new Selector("onclick")) + flashBtn.addGestureRecognizer(flashBtnevents_rz) + + + if (openAnimation) { + // 增加显示动画. + parentView!.layer.add(scaleAni, forKey = "scaleAnimation") + } + // ios识别太快了,图像还没定焦就识别出来了,稍微延迟下,不要太快了。与安卓对齐 下。 + setTimeout(function () { + isCamreaing = true; + }, 300); + }) + +} + +function calcPoint(c_w : number, c_h : number, image_w : number, image_h : number, image_point_x : number, image_point_y : number, degration : number) : ConverXy { + function scaleAndCenterContent( + container : contaiaSize, + content : contaiaSize + ) : contaiaCalseSize { + // 计算缩放比例 + const scaleWidth = container.width / content.width; + const scaleHeight = container.height / content.height; + const scale = Math.min(scaleWidth, scaleHeight); + + // 计算居中偏移量 + const offsetX = (container.width - content.width * scale) / 2; + const offsetY = (container.height - content.height * scale) / 2; + + return { scale, offsetX, offsetY } as contaiaCalseSize; + } + function mapContentCoordinatesToContainer( + contentX : number, + contentY : number, + calcsize : contaiaCalseSize + ) : contaiPointXy { + // 映射内容层坐标到容器层坐标 + const containerX = contentX * calcsize.scale + calcsize.offsetX; + const containerY = contentY * calcsize.scale + calcsize.offsetY; + + return { x: containerX, y: containerY } as contaiPointXy; + } + + let rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_h, height: image_w } as contaiaSize + ) + if (degration == 0) { + rc = scaleAndCenterContent( + { width: c_w, height: c_h } as contaiaSize, + { width: image_w, height: image_h } as contaiaSize + ) + } + + let result = mapContentCoordinatesToContainer(image_point_y, image_point_x, rc) + if (degration == 0) { + result = mapContentCoordinatesToContainer(image_point_x, image_point_y, rc) + } + let nexyxcov = { + x: c_w - result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + if (degration == 0) { + nexyxcov = { + x: result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0 + } as ConverXy + } + return nexyxcov + +} + +function createPointView(result : SCANNING_PHOTO_RESULT, degration : number) { + + let realCgSize = camreaViewLayer!.frame as CGRect; + let realWidth = Number(realCgSize.width); + let realHeight = Number(realCgSize.height); + clearPointView(); + + let pointSize = 30 + DispatchQueue.main.async(execute = () : void => { + + for (let i = 0; i < result.bounds.length; i++) { + let text = result.text[i] + let bounds = result.bounds[i] + let pos = result.position[i]; + + let resutxy = calcPoint(realWidth, realHeight, videoWidth, videoHeight, bounds.centerX, bounds.centerY, degration) + + let x = resutxy.x - 15 + let y = resutxy.y - 15 + let rect = new CGRect(x = x.toInt(), y = y.toInt(), width = pointSize.toInt(), height = pointSize.toInt()) + let pointViewSelf = new UIView(); + pointViewSelf.layer.frame = rect; + pointViewSelf.backgroundColor = UTSiOS.colorWithString('#21d429'); + pointViewSelf.layer.borderWidth = 2 + pointViewSelf.layer.borderColor = UTSiOS.colorWithString('#FFFFFF').cgColor; + pointViewSelf.layer.cornerRadius = new CGFloat(pointSize / 2); + + let onlick = new PointClickEvent((atext : string) => { + rsultCallBack(atext) + closeScan() + quitView() + }, text); + pointsEvents.push(onlick) + let tapGestureCancel = new UITapGestureRecognizer() + tapGestureCancel.addTarget(onlick, action = new Selector("onclick")) + pointViewSelf.addGestureRecognizer(tapGestureCancel) + + + pointsLayerView!.addSubview(pointViewSelf) + pointView.push(pointViewSelf) + + } + }) +} + +/** 手动开启和关闭闪光灯 */ +function setFlashModel(flash : boolean) { + if (captureDeviceAllGlobal != null) { + let islock = UTSiOS.try(captureDeviceAllGlobal!.lockForConfiguration(), "?") + if (islock != null) { + captureDeviceAllGlobal!.torchMode = flash ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off + captureDeviceAllGlobal!.unlockForConfiguration() + } + } +} +function clearPointView() { + DispatchQueue.main.async(execute = () : void => { + for (let i = 0; i < pointView.length; i++) { + let item = pointView[i]; + item.removeFromSuperview(); + } + pointView = [] as UIView[] + }) +} +function closeScan() { + // 移除点。 + clearPointView() + if (captureSession != null) { + captureSession!.stopRunning() + + for (input in captureSession!.inputs) { + captureSession!.removeInput(input) + } + + for (output in captureSession!.outputs) { + captureSession!.removeOutput(output) + } + captureSession = null; + } + scanResult = [] as Swift.Array + pointsEvents = [] as PointClickEvent[] + + captureDeviceAllGlobal = nil; + FlashButton = nil; + +} +function startCamera() { + isCamreaing = false; + closeScan(); + captureSession = new AVCaptureSession(); + let captureDevice = AVCaptureDevice.default(for = AVMediaType.video) + let captureOut = new AVCaptureVideoDataOutput(); + captureSession!.sessionPreset = AVCaptureSession.Preset.photo + captureOutDelegate = new CaptureOutSessionBuffer((result : SCANNING_PHOTO_RESULT) => { + + createPointView(result, 90) + + uni.setStorageSync("xMlKITScaning", JSON.stringify(result.text)) + // t.$emit("scan") + if (result.text.length == 1) { + rsultCallBack(result.text[0]) + + setTimeout(function () { + closeScan() + quitView() + }, 150); + } + }) + + // 新建设备的输入设备 + let inputDevice = UTSiOS.try(new AVCaptureDeviceInput(device = captureDevice!), "?") + if (inputDevice != null) { + // 添加输入到会话中。 + captureSession!.addInput(inputDevice!) + } + + captureOut.alwaysDiscardsLateVideoFrames = true; + // 设置输出会话 + captureOut.setSampleBufferDelegate(captureOutDelegate!, queue = DispatchQueue.global()) + if (captureSession!.canAddOutput(captureOut)) { + captureSession!.addOutput(captureOut) + // console.log("绑定输出层正确!") + } + + + xCamreaInit(); + captureDeviceAllGlobal = captureDevice +} +function quitView() { + if (parentView != null) { + parentView!.removeFromSuperview() + } +} + +export function openCameraApi(callback : CALL_RESULT_FUN, onlyCameras : boolean) { + rsultCallBack = callback + openAnimation = true; + onlyCamera = onlyCameras + startCamera(); +} +export function closeCamera() { + closeScan(); + quitView(); +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/info.plist b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/info.plist new file mode 100644 index 0000000..3d2be4d --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/info.plist @@ -0,0 +1,10 @@ + + + + + NSCameraUsageDescription + 我们需要您的相机权限来拍照或录像。 + NSPhotoLibraryUsageDescription + 需要使用你的相册进行选择视频及图片 + + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/interface.uts b/uni_modules/x-mlkit-scannig-s/utssdk/interface.uts new file mode 100644 index 0000000..762c4c8 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/interface.uts @@ -0,0 +1,71 @@ +export type SCANNING_PHOTO_RESULT_BOUND = { + width:number, + height:number, + centerX:number, + centerY:number +} + +export type SCANNING_PHOTO_RESULT = { + url:string,//图片地址 + position:number[][][], + bounds:SCANNING_PHOTO_RESULT_BOUND[], + text:string[], + imgWidth:number, + imgHeight:number +} + + + +export type CAMERA_PHOTO_SIZE = { + width:number, + height:number +} +export type CALL_RESULT_FUN= (str:string) => void; + +export type Call_BACK = (str:string,type : string) => void; +export type Call_BACK_TYPE ='auto' | 'click' +export type AUTH_CALL_BACK_TYPE = (auth:boolean)=>void; +export type BARCODEFORMAT = 'AZTEC' + | 'CODABAR' + | 'CODE_39' + | 'CODE_93' + | 'CODE_128' + | 'DATA_MATRIX' + | 'EAN_8' + | 'EAN_13' + | 'ITF' + | 'MAXICODE' + | 'PDF_417' + | 'QR_CODE' + | 'RSS_14' + | 'RSS_EXPANDED' + | 'UPC_A' + | 'UPC_E' + | 'UPC_EAN_EXTENSION'; + +export type SCANNING_OPTIONS = { + width:number, + height:number, + //前置还是后置摄像头 + cameraDevice:'FRONT'|'BACK', + /** 放大倍数1-10效果要看你的设备,并一定有用。越小视频越宽,越大视野越小。 */ + zoom?:number, + // 是否连续扫码识别,相对的间隔如果是自动的话根据设备性能一般是50-300ms之间 + // 默认为false即单次识别就停止需要手动继续识别 + continuousScan?:boolean, + //识别成功后是否震动设备 + vibatar?:boolean, + //单位毫秒,扫描识别间隔/及抓拍间隔 + scanSpeedduration?:450, + //是否打开识别码的功能,暂不支持设置,默认就是识别功能,等我完善 + scanningQrCode?:boolean, + //扫码成功后是否保存图片,暂未实现,等我完善 + isSavePhoto?:boolean, + /** + * 开识别条码的类型 + * 如果需要指定识别类型的条码时有用。比如快递单上有多个码制 + * 如果指定为条码,就可以避免识别二维码了。 + * ,暂不支持设置,等我完善 + */ + qrCodeType?:BARCODEFORMAT|null +} diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/mp-weixin/index.uts b/uni_modules/x-mlkit-scannig-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..8feb80f --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,20 @@ +import { SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND, Call_BACK, AUTH_CALL_BACK_TYPE } from '../interface.uts'; +var qre; +var resultQr = "" +// https://www.npmjs.com/package/qr-scanner/v/1.4.2?activeTab=readme +export function closeCamera() { + +} +export function openCameraApi(callback : Call_BACK,onlyCameras:boolean) { + wx.scanCode({ + onlyFromCamera:onlyCameras, + success(res){ + if(res?.result){ + callback(res?.result??"","auto") + } + }, + fail(er){ + console.error(er) + } + }) +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/web/index.uts b/uni_modules/x-mlkit-scannig-s/utssdk/web/index.uts new file mode 100644 index 0000000..c26244a --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/web/index.uts @@ -0,0 +1,241 @@ +export { SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND, Call_BACK, AUTH_CALL_BACK_TYPE } from '../interface.uts'; +import Zxing from "./zxing.js" +var qre; +var resultQr = "" +var cid +// https://www.npmjs.com/package/qr-scanner/v/1.4.2?activeTab=readme +export function closeCamera() { + let parentView = document.getElementById("xScannigDiv") + if (parentView) { + parentView.remove() + } + if (qre) { + qre.getTracks().forEach(function (track) { + track.stop(); + }); + } + resultQr = "" + +} +// @ts-ignore +export function openCameraApi(callback : Call_BACK,onlyCameras:boolean) { + qre = null; + resultQr = "" + let onleyCamrae = onlyCameras + scanning() + + function scanning() { + closeCamera(); + let parenView : HTMLElement = document.createElement("div") + parenView.id = 'xScannigDiv'; + parenView.style.position = "fixed" + parenView.style.left = "0px" + parenView.style.top = "0px" + parenView.style.width = "100%" + parenView.style.height = "100%" + parenView.style.zIndex = "888" + parenView.style.backgroundColor = "#000" + parenView.style.display = "flex" + parenView.style.flexDirection = "column" + parenView.style.transitionDuration = '0.25s' + parenView.style.transitionProperty = 'transform' + parenView.style.transitionTimingFunction = 'linear' + parenView.style.transform = 'scale(0)' + + let backText = document.createElement("div") + backText.innerText = "返回" + backText.style.fontSize = "16px" + backText.style.height = "50px" + backText.style.lineHeight = "50px" + backText.style.padding = "0px 20px" + backText.style.color = "white" + backText.onclick = function () { + closeCamera() + } + + let video : HTMLVideoElement = document.createElement("video") + video.style.flex = "1" + video.style.backgroundColor = '#111' + video.style.width = '100%' + video.style.objectFit = 'cover' + + video.playsInline = true; + video.muted = true; + video.autoplay = true; + video.controls = false; + // 针对微信的x5内核 + video.setAttribute('playsinline',true) + video.setAttribute('webkit-playsinline',true) + video.setAttribute('x5-playsinline',true) + video.setAttribute('x5-video-player-type','h5') + video.setAttribute('x5-video-player-fullscreen','false') + + + let bottomView = document.createElement("div") + bottomView.style.height = "100px" + bottomView.style.display = "flex" + bottomView.style.flexDirection = "row" + bottomView.style.justifyContent = "space-between" + + let photo = document.createElement("div") + photo.innerText = onleyCamrae?"":"相册选取" + photo.style.fontSize = "16px" + photo.style.height = "50px" + photo.style.lineHeight = "50px" + photo.style.padding = "0px 20px" + photo.style.color = "white" + let scan = document.createElement("div") + scan.innerText = "扫一扫" + scan.style.fontSize = "16px" + scan.style.height = "50px" + scan.style.lineHeight = "50px" + scan.style.padding = "0px 20px" + scan.style.color = "white" + photo.onclick = function () { + if(onleyCamrae) return; + uni.chooseImage({ + sourceType:["album"], + success(res) { + if (res.tempFilePaths.length > 0) { + + let img = new Image() + img.src = res.tempFilePaths[0]; + img.onload = function () { + closeCamera(); + var newWidth = 600; + // @ts-ignore + var newHeight = newWidth*img.width / img.height; + var canvas = document.createElement('canvas'); + canvas.width = 600; + canvas.height = 600; + var ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, newWidth, newHeight) + ctx.drawImage(img, 0, 0, newWidth, newHeight) + var imageData = ctx.getImageData(0, 0, 600, 600); + let code = new Zxing(imageData.data,600,600,{inversionAttempts:true}) + if(code&&code?.data){ + callback(code.data) + resultQr = "" + } + } + + + + + } + + } + }) + } + + bottomView.appendChild(photo) + bottomView.appendChild(scan) + + parenView.appendChild(backText) + parenView.appendChild(video) + parenView.appendChild(bottomView) + document.body.appendChild(parenView) + + + + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d')!; + var constraints = { + audio: false, + video: { + width: 800, + height: 800, + facingMode:"environment" + } + }; + navigator.mediaDevices.getUserMedia(constraints) + .then(stream => { + video.srcObject = stream; + qre = stream + video.play(); + var newWidth = 800; + var newHeight = newWidth*video.offsetWidth / video.offsetHeight; + + canvas.width = newWidth + canvas.height = newHeight + function readFrame() { + ctx.clearRect(0,0,newWidth,newWidth) + ctx.drawImage(video, 0, 0, newWidth, newHeight); + const frameData = ctx.getImageData(0, 0, newWidth, newWidth); + + let code = Zxing(frameData.data,newWidth,newWidth,{inversionAttempts:true}) + if(code&&code?.data&&resultQr==''){ + resultQr = code.data + callback(code.data) + cancelAnimationFrame(cid) + closeCamera() + } + + cid = requestAnimationFrame(readFrame); + } + // 开始读取帧 + readFrame(); + }) + .catch(error => { + console.error('Error accessing media devices:', error); + }); + + + + + // navigator.mediaDevices.getUserMedia({ video: true }) + // .then(stream => { + // video.srcObject = stream; + // t.qre = stream + // video.play(); + + // // 设置 canvas 用于读取视频帧 + // const canvas = document.createElement('canvas'); + // canvas.style.width = video.offsetWidth + 'px' + // canvas.style.height = video.offsetHeight + 'px' + // canvas.width = video.offsetWidth + // canvas.height = video.offsetHeight + // const ctx = canvas.getContext('2d'); + // function readFrame() { + // ctx.drawImage(video, 0, 0, canvas.width, canvas.height); + // const frameData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + // let p = new Zxing() + // let qrd = new p() + // qrd.callback = function (err, value) { + // if (resultQr == '' && value?.result) { + // resultQr = value.result + // t.$emit("scan", [value.result]) + // cancelAnimationFrame(t.cid) + // } + // } + // qrd.decode(frameData); + // t.cid = requestAnimationFrame(readFrame); + // } + // // 开始读取帧 + // readFrame(); + // }) + // .catch(error => { + // console.error('Error accessing media devices:', error); + // }); + + + + // qre = new QrScanner( + // video, + // function (result) { + // console.log(result) + // qre.stop() + // video.pause(); + // resultQr = result; + // callback(result) + // closeCamera(); + // qre = null; + // } + // ); + // qre.start() + setTimeout(function() { + parenView.style.transform = 'scale(1)' + }, 50); + } +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-s/utssdk/web/zxing.js b/uni_modules/x-mlkit-scannig-s/utssdk/web/zxing.js new file mode 100644 index 0000000..c97dc1e --- /dev/null +++ b/uni_modules/x-mlkit-scannig-s/utssdk/web/zxing.js @@ -0,0 +1,2909 @@ +class BitMatrix { + constructor(data, width) { + this.width = width; + this.height = data.length / width; + this.data = data; + } + static createEmpty(width, height) { + return new BitMatrix(new Uint8ClampedArray(width * height), width); + } + get(x, y) { + if (x < 0 || x >= this.width || y < 0 || y >= this.height) { + return false; + } + return !!this.data[y * this.width + x]; + } + set(x, y, v) { + this.data[y * this.width + x] = v ? 1 : 0; + } + setRegion(left, top, width, height, v) { + for (let y = top; y < top + height; y++) { + for (let x = left; x < left + width; x++) { + this.set(x, y, !!v); + } + } + } +} + +const REGION_SIZE = 8; +const MIN_DYNAMIC_RANGE = 24; +function numBetween(value, min, max) { + return value < min ? min : value > max ? max : value; +} +// Like BitMatrix but accepts arbitry Uint8 values +class Matrix { + constructor(width, height, buffer) { + this.width = width; + const bufferSize = width * height; + if (buffer && buffer.length !== bufferSize) { + throw new Error("Wrong buffer size"); + } + this.data = buffer || new Uint8ClampedArray(bufferSize); + } + get(x, y) { + return this.data[y * this.width + x]; + } + set(x, y, value) { + this.data[y * this.width + x] = value; + } +} +function binarize(data, width, height, returnInverted, greyscaleWeights, canOverwriteImage) { + const pixelCount = width * height; + if (data.length !== pixelCount * 4) { + throw new Error("Malformed data passed to binarizer."); + } + // assign the greyscale and binary image within the rgba buffer as the rgba image will not be needed after conversion + let bufferOffset = 0; + // Convert image to greyscale + let greyscaleBuffer; + if (canOverwriteImage) { + greyscaleBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + bufferOffset += pixelCount; + } + const greyscalePixels = new Matrix(width, height, greyscaleBuffer); + if (greyscaleWeights.useIntegerApproximation) { + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const pixelPosition = (y * width + x) * 4; + const r = data[pixelPosition]; + const g = data[pixelPosition + 1]; + const b = data[pixelPosition + 2]; + greyscalePixels.set(x, y, + // tslint:disable-next-line no-bitwise + (greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b + 128) >> 8); + } + } + } + else { + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const pixelPosition = (y * width + x) * 4; + const r = data[pixelPosition]; + const g = data[pixelPosition + 1]; + const b = data[pixelPosition + 2]; + greyscalePixels.set(x, y, greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b); + } + } + } + const horizontalRegionCount = Math.ceil(width / REGION_SIZE); + const verticalRegionCount = Math.ceil(height / REGION_SIZE); + const blackPointsCount = horizontalRegionCount * verticalRegionCount; + let blackPointsBuffer; + if (canOverwriteImage) { + blackPointsBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, blackPointsCount); + bufferOffset += blackPointsCount; + } + const blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount, blackPointsBuffer); + for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + let min = Infinity; + let max = 0; + for (let y = 0; y < REGION_SIZE; y++) { + for (let x = 0; x < REGION_SIZE; x++) { + const pixelLumosity = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y); + min = Math.min(min, pixelLumosity); + max = Math.max(max, pixelLumosity); + } + } + // We could also compute the real average of all pixels but following the assumption that the qr code consists + // of bright and dark pixels and essentially not much in between, by (min + max)/2 we make the cut really between + // those two classes. If using the average over all pixel in a block of mostly bright pixels and few dark pixels, + // the avg would tend to the bright side and darker bright pixels could be interpreted as dark. + let average = (min + max) / 2; + // Small bias towards black by moving the threshold up. We do this, as in the finder patterns white holes tend + // to appear which makes them undetectable. + const blackBias = 1.11; + average = Math.min(255, average * blackBias); + if (max - min <= MIN_DYNAMIC_RANGE) { + // If variation within the block is low, assume this is a block with only light or only + // dark pixels. In that case we do not want to use the average, as it would divide this + // low contrast area into black and white pixels, essentially creating data out of noise. + // + // Default the blackpoint for these blocks to be half the min - effectively white them out + average = min / 2; + if (verticalRegion > 0 && hortizontalRegion > 0) { + // Correct the "white background" assumption for blocks that have neighbors by comparing + // the pixels in this block to the previously calculated black points. This is based on + // the fact that dark barcode symbology is always surrounded by some amount of light + // background for which reasonable black point estimates were made. The bp estimated at + // the boundaries is used for the interior. + // The (min < bp) is arbitrary but works better than other heuristics that were tried. + const averageNeighborBlackPoint = (blackPoints.get(hortizontalRegion, verticalRegion - 1) + + (2 * blackPoints.get(hortizontalRegion - 1, verticalRegion)) + + blackPoints.get(hortizontalRegion - 1, verticalRegion - 1)) / 4; + if (min < averageNeighborBlackPoint) { + average = averageNeighborBlackPoint; // no need to apply black bias as already applied to neighbors + } + } + } + blackPoints.set(hortizontalRegion, verticalRegion, average); + } + } + let binarized; + if (canOverwriteImage) { + const binarizedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + bufferOffset += pixelCount; + binarized = new BitMatrix(binarizedBuffer, width); + } + else { + binarized = BitMatrix.createEmpty(width, height); + } + let inverted = null; + if (returnInverted) { + if (canOverwriteImage) { + const invertedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + inverted = new BitMatrix(invertedBuffer, width); + } + else { + inverted = BitMatrix.createEmpty(width, height); + } + } + for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + const left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3); + const top = numBetween(verticalRegion, 2, verticalRegionCount - 3); + let sum = 0; + for (let xRegion = -2; xRegion <= 2; xRegion++) { + for (let yRegion = -2; yRegion <= 2; yRegion++) { + sum += blackPoints.get(left + xRegion, top + yRegion); + } + } + const threshold = sum / 25; + for (let xRegion = 0; xRegion < REGION_SIZE; xRegion++) { + for (let yRegion = 0; yRegion < REGION_SIZE; yRegion++) { + const x = hortizontalRegion * REGION_SIZE + xRegion; + const y = verticalRegion * REGION_SIZE + yRegion; + const lum = greyscalePixels.get(x, y); + binarized.set(x, y, lum <= threshold); + if (returnInverted) { + inverted.set(x, y, !(lum <= threshold)); + } + } + } + } + } + if (returnInverted) { + return { binarized, inverted }; + } + return { binarized }; +} + +// tslint:disable:no-bitwise +class BitStream { + constructor(bytes) { + this.byteOffset = 0; + this.bitOffset = 0; + this.bytes = bytes; + } + readBits(numBits) { + if (numBits < 1 || numBits > 32 || numBits > this.available()) { + throw new Error("Cannot read " + numBits.toString() + " bits"); + } + let result = 0; + // First, read remainder from current byte + if (this.bitOffset > 0) { + const bitsLeft = 8 - this.bitOffset; + const toRead = numBits < bitsLeft ? numBits : bitsLeft; + const bitsToNotRead = bitsLeft - toRead; + const mask = (0xFF >> (8 - toRead)) << bitsToNotRead; + result = (this.bytes[this.byteOffset] & mask) >> bitsToNotRead; + numBits -= toRead; + this.bitOffset += toRead; + if (this.bitOffset === 8) { + this.bitOffset = 0; + this.byteOffset++; + } + } + // Next read whole bytes + if (numBits > 0) { + while (numBits >= 8) { + result = (result << 8) | (this.bytes[this.byteOffset] & 0xFF); + this.byteOffset++; + numBits -= 8; + } + // Finally read a partial byte + if (numBits > 0) { + const bitsToNotRead = 8 - numBits; + const mask = (0xFF >> bitsToNotRead) << bitsToNotRead; + result = (result << numBits) | ((this.bytes[this.byteOffset] & mask) >> bitsToNotRead); + this.bitOffset += numBits; + } + } + return result; + } + available() { + return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset; + } +} + +// tslint:disable:no-bitwise +var Mode; +(function (Mode) { + Mode["Numeric"] = "numeric"; + Mode["Alphanumeric"] = "alphanumeric"; + Mode["Byte"] = "byte"; + Mode["Kanji"] = "kanji"; + Mode["ECI"] = "eci"; + Mode["StructuredAppend"] = "structuredappend"; +})(Mode || (Mode = {})); +var ModeByte; +(function (ModeByte) { + ModeByte[ModeByte["Terminator"] = 0] = "Terminator"; + ModeByte[ModeByte["Numeric"] = 1] = "Numeric"; + ModeByte[ModeByte["Alphanumeric"] = 2] = "Alphanumeric"; + ModeByte[ModeByte["Byte"] = 4] = "Byte"; + ModeByte[ModeByte["Kanji"] = 8] = "Kanji"; + ModeByte[ModeByte["ECI"] = 7] = "ECI"; + ModeByte[ModeByte["StructuredAppend"] = 3] = "StructuredAppend"; + // FNC1FirstPosition = 0x5, + // FNC1SecondPosition = 0x9, +})(ModeByte || (ModeByte = {})); +function decodeNumeric(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [10, 12, 14][size]; + let length = stream.readBits(characterCountSize); + // Read digits in groups of 3 + while (length >= 3) { + const num = stream.readBits(10); + if (num >= 1000) { + throw new Error("Invalid numeric value above 999"); + } + const a = Math.floor(num / 100); + const b = Math.floor(num / 10) % 10; + const c = num % 10; + bytes.push(48 + a, 48 + b, 48 + c); + text += a.toString() + b.toString() + c.toString(); + length -= 3; + } + // If the number of digits aren't a multiple of 3, the remaining digits are special cased. + if (length === 2) { + const num = stream.readBits(7); + if (num >= 100) { + throw new Error("Invalid numeric value above 99"); + } + const a = Math.floor(num / 10); + const b = num % 10; + bytes.push(48 + a, 48 + b); + text += a.toString() + b.toString(); + } + else if (length === 1) { + const num = stream.readBits(4); + if (num >= 10) { + throw new Error("Invalid numeric value above 9"); + } + bytes.push(48 + num); + text += num.toString(); + } + return { bytes, text }; +} +const AlphanumericCharacterCodes = [ + "0", "1", "2", "3", "4", "5", "6", "7", "8", + "9", "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", "Q", + "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + " ", "$", "%", "*", "+", "-", ".", "/", ":", +]; +function decodeAlphanumeric(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [9, 11, 13][size]; + let length = stream.readBits(characterCountSize); + while (length >= 2) { + const v = stream.readBits(11); + const a = Math.floor(v / 45); + const b = v % 45; + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0), AlphanumericCharacterCodes[b].charCodeAt(0)); + text += AlphanumericCharacterCodes[a] + AlphanumericCharacterCodes[b]; + length -= 2; + } + if (length === 1) { + const a = stream.readBits(6); + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0)); + text += AlphanumericCharacterCodes[a]; + } + return { bytes, text }; +} +function decodeByte(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [8, 16, 16][size]; + const length = stream.readBits(characterCountSize); + for (let i = 0; i < length; i++) { + const b = stream.readBits(8); + bytes.push(b); + } + try { + text += decodeURIComponent(bytes.map(b => `%${("0" + b.toString(16)).substr(-2)}`).join("")); + } + catch (_a) { + // failed to decode + } + return { bytes, text }; +} +function decodeKanji(stream, size) { + const bytes = []; + const characterCountSize = [8, 10, 12][size]; + const length = stream.readBits(characterCountSize); + for (let i = 0; i < length; i++) { + const k = stream.readBits(13); + let c = (Math.floor(k / 0xC0) << 8) | (k % 0xC0); + if (c < 0x1F00) { + c += 0x8140; + } + else { + c += 0xC140; + } + bytes.push(c >> 8, c & 0xFF); + } + const text = new TextDecoder("shift-jis").decode(Uint8Array.from(bytes)); + return { bytes, text }; +} +function decode$2(data, version) { + const stream = new BitStream(data); + // There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2). + const size = version <= 9 ? 0 : version <= 26 ? 1 : 2; + const result = { + text: "", + bytes: [], + chunks: [], + version, + }; + while (stream.available() >= 4) { + const mode = stream.readBits(4); + if (mode === ModeByte.Terminator) { + return result; + } + else if (mode === ModeByte.ECI) { + if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(7), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(14), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(21), + }); + } + else { + // ECI data seems corrupted + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: -1, + }); + } + } + else if (mode === ModeByte.Numeric) { + const numericResult = decodeNumeric(stream, size); + result.text += numericResult.text; + result.bytes.push(...numericResult.bytes); + result.chunks.push({ + type: Mode.Numeric, + text: numericResult.text, + }); + } + else if (mode === ModeByte.Alphanumeric) { + const alphanumericResult = decodeAlphanumeric(stream, size); + result.text += alphanumericResult.text; + result.bytes.push(...alphanumericResult.bytes); + result.chunks.push({ + type: Mode.Alphanumeric, + text: alphanumericResult.text, + }); + } + else if (mode === ModeByte.Byte) { + const byteResult = decodeByte(stream, size); + result.text += byteResult.text; + result.bytes.push(...byteResult.bytes); + result.chunks.push({ + type: Mode.Byte, + bytes: byteResult.bytes, + text: byteResult.text, + }); + } + else if (mode === ModeByte.Kanji) { + const kanjiResult = decodeKanji(stream, size); + result.text += kanjiResult.text; + result.bytes.push(...kanjiResult.bytes); + result.chunks.push({ + type: Mode.Kanji, + bytes: kanjiResult.bytes, + text: kanjiResult.text, + }); + } + else if (mode === ModeByte.StructuredAppend) { + result.chunks.push({ + type: Mode.StructuredAppend, + currentSequence: stream.readBits(4), + totalSequence: stream.readBits(4), + parity: stream.readBits(8), + }); + } + } + // If there is no data left, or the remaining bits are all 0, then that counts as a termination marker + if (stream.available() === 0 || stream.readBits(stream.available()) === 0) { + return result; + } +} + +class GenericGFPoly { + constructor(field, coefficients) { + if (coefficients.length === 0) { + throw new Error("No coefficients."); + } + this.field = field; + const coefficientsLength = coefficients.length; + if (coefficientsLength > 1 && coefficients[0] === 0) { + // Leading term must be non-zero for anything except the constant polynomial "0" + let firstNonZero = 1; + while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) { + firstNonZero++; + } + if (firstNonZero === coefficientsLength) { + this.coefficients = field.zero.coefficients; + } + else { + this.coefficients = new Uint8ClampedArray(coefficientsLength - firstNonZero); + for (let i = 0; i < this.coefficients.length; i++) { + this.coefficients[i] = coefficients[firstNonZero + i]; + } + } + } + else { + this.coefficients = coefficients; + } + } + degree() { + return this.coefficients.length - 1; + } + isZero() { + return this.coefficients[0] === 0; + } + getCoefficient(degree) { + return this.coefficients[this.coefficients.length - 1 - degree]; + } + addOrSubtract(other) { + if (this.isZero()) { + return other; + } + if (other.isZero()) { + return this; + } + let smallerCoefficients = this.coefficients; + let largerCoefficients = other.coefficients; + if (smallerCoefficients.length > largerCoefficients.length) { + [smallerCoefficients, largerCoefficients] = [largerCoefficients, smallerCoefficients]; + } + const sumDiff = new Uint8ClampedArray(largerCoefficients.length); + const lengthDiff = largerCoefficients.length - smallerCoefficients.length; + for (let i = 0; i < lengthDiff; i++) { + sumDiff[i] = largerCoefficients[i]; + } + for (let i = lengthDiff; i < largerCoefficients.length; i++) { + sumDiff[i] = addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); + } + return new GenericGFPoly(this.field, sumDiff); + } + multiply(scalar) { + if (scalar === 0) { + return this.field.zero; + } + if (scalar === 1) { + return this; + } + const size = this.coefficients.length; + const product = new Uint8ClampedArray(size); + for (let i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], scalar); + } + return new GenericGFPoly(this.field, product); + } + multiplyPoly(other) { + if (this.isZero() || other.isZero()) { + return this.field.zero; + } + const aCoefficients = this.coefficients; + const aLength = aCoefficients.length; + const bCoefficients = other.coefficients; + const bLength = bCoefficients.length; + const product = new Uint8ClampedArray(aLength + bLength - 1); + for (let i = 0; i < aLength; i++) { + const aCoeff = aCoefficients[i]; + for (let j = 0; j < bLength; j++) { + product[i + j] = addOrSubtractGF(product[i + j], this.field.multiply(aCoeff, bCoefficients[j])); + } + } + return new GenericGFPoly(this.field, product); + } + multiplyByMonomial(degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid degree less than 0"); + } + if (coefficient === 0) { + return this.field.zero; + } + const size = this.coefficients.length; + const product = new Uint8ClampedArray(size + degree); + for (let i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], coefficient); + } + return new GenericGFPoly(this.field, product); + } + evaluateAt(a) { + let result = 0; + if (a === 0) { + // Just return the x^0 coefficient + return this.getCoefficient(0); + } + const size = this.coefficients.length; + if (a === 1) { + // Just the sum of the coefficients + this.coefficients.forEach((coefficient) => { + result = addOrSubtractGF(result, coefficient); + }); + return result; + } + result = this.coefficients[0]; + for (let i = 1; i < size; i++) { + result = addOrSubtractGF(this.field.multiply(a, result), this.coefficients[i]); + } + return result; + } +} + +function addOrSubtractGF(a, b) { + return a ^ b; // tslint:disable-line:no-bitwise +} +class GenericGF { + constructor(primitive, size, genBase) { + this.primitive = primitive; + this.size = size; + this.generatorBase = genBase; + this.expTable = new Array(this.size); + this.logTable = new Array(this.size); + let x = 1; + for (let i = 0; i < this.size; i++) { + this.expTable[i] = x; + x = x * 2; + if (x >= this.size) { + x = (x ^ this.primitive) & (this.size - 1); // tslint:disable-line:no-bitwise + } + } + for (let i = 0; i < this.size - 1; i++) { + this.logTable[this.expTable[i]] = i; + } + this.zero = new GenericGFPoly(this, Uint8ClampedArray.from([0])); + this.one = new GenericGFPoly(this, Uint8ClampedArray.from([1])); + } + multiply(a, b) { + if (a === 0 || b === 0) { + return 0; + } + return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)]; + } + inverse(a) { + if (a === 0) { + throw new Error("Can't invert 0"); + } + return this.expTable[this.size - this.logTable[a] - 1]; + } + buildMonomial(degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid monomial degree less than 0"); + } + if (coefficient === 0) { + return this.zero; + } + const coefficients = new Uint8ClampedArray(degree + 1); + coefficients[0] = coefficient; + return new GenericGFPoly(this, coefficients); + } + log(a) { + if (a === 0) { + throw new Error("Can't take log(0)"); + } + return this.logTable[a]; + } + exp(a) { + return this.expTable[a]; + } +} + +function runEuclideanAlgorithm(field, a, b, R) { + // Assume a's degree is >= b's + if (a.degree() < b.degree()) { + [a, b] = [b, a]; + } + let rLast = a; + let r = b; + let tLast = field.zero; + let t = field.one; + // Run Euclidean algorithm until r's degree is less than R/2 + while (r.degree() >= R / 2) { + const rLastLast = rLast; + const tLastLast = tLast; + rLast = r; + tLast = t; + // Divide rLastLast by rLast, with quotient in q and remainder in r + if (rLast.isZero()) { + // Euclidean algorithm already terminated? + return null; + } + r = rLastLast; + let q = field.zero; + const denominatorLeadingTerm = rLast.getCoefficient(rLast.degree()); + const dltInverse = field.inverse(denominatorLeadingTerm); + while (r.degree() >= rLast.degree() && !r.isZero()) { + const degreeDiff = r.degree() - rLast.degree(); + const scale = field.multiply(r.getCoefficient(r.degree()), dltInverse); + q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); + r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); + } + t = q.multiplyPoly(tLast).addOrSubtract(tLastLast); + if (r.degree() >= rLast.degree()) { + return null; + } + } + const sigmaTildeAtZero = t.getCoefficient(0); + if (sigmaTildeAtZero === 0) { + return null; + } + const inverse = field.inverse(sigmaTildeAtZero); + return [t.multiply(inverse), r.multiply(inverse)]; +} +function findErrorLocations(field, errorLocator) { + // This is a direct application of Chien's search + const numErrors = errorLocator.degree(); + if (numErrors === 1) { + return [errorLocator.getCoefficient(1)]; + } + const result = new Array(numErrors); + let errorCount = 0; + for (let i = 1; i < field.size && errorCount < numErrors; i++) { + if (errorLocator.evaluateAt(i) === 0) { + result[errorCount] = field.inverse(i); + errorCount++; + } + } + if (errorCount !== numErrors) { + return null; + } + return result; +} +function findErrorMagnitudes(field, errorEvaluator, errorLocations) { + // This is directly applying Forney's Formula + const s = errorLocations.length; + const result = new Array(s); + for (let i = 0; i < s; i++) { + const xiInverse = field.inverse(errorLocations[i]); + let denominator = 1; + for (let j = 0; j < s; j++) { + if (i !== j) { + denominator = field.multiply(denominator, addOrSubtractGF(1, field.multiply(errorLocations[j], xiInverse))); + } + } + result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator)); + if (field.generatorBase !== 0) { + result[i] = field.multiply(result[i], xiInverse); + } + } + return result; +} +function decode$1(bytes, twoS) { + const outputBytes = new Uint8ClampedArray(bytes.length); + outputBytes.set(bytes); + const field = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 + const poly = new GenericGFPoly(field, outputBytes); + const syndromeCoefficients = new Uint8ClampedArray(twoS); + let error = false; + for (let s = 0; s < twoS; s++) { + const evaluation = poly.evaluateAt(field.exp(s + field.generatorBase)); + syndromeCoefficients[syndromeCoefficients.length - 1 - s] = evaluation; + if (evaluation !== 0) { + error = true; + } + } + if (!error) { + return outputBytes; + } + const syndrome = new GenericGFPoly(field, syndromeCoefficients); + const sigmaOmega = runEuclideanAlgorithm(field, field.buildMonomial(twoS, 1), syndrome, twoS); + if (sigmaOmega === null) { + return null; + } + const errorLocations = findErrorLocations(field, sigmaOmega[0]); + if (errorLocations == null) { + return null; + } + const errorMagnitudes = findErrorMagnitudes(field, sigmaOmega[1], errorLocations); + for (let i = 0; i < errorLocations.length; i++) { + const position = outputBytes.length - 1 - field.log(errorLocations[i]); + if (position < 0) { + return null; + } + outputBytes[position] = addOrSubtractGF(outputBytes[position], errorMagnitudes[i]); + } + return outputBytes; +} + +const VERSIONS = [ + { + infoBits: null, + versionNumber: 1, + alignmentPatternCenters: [], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 7, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + { + ecCodewordsPerBlock: 13, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 13 }], + }, + { + ecCodewordsPerBlock: 17, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 2, + alignmentPatternCenters: [6, 18], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 34 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 28 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 22 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 3, + alignmentPatternCenters: [6, 22], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 15, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 55 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 44 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 17 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 4, + alignmentPatternCenters: [6, 26], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 80 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 32 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 24 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 5, + alignmentPatternCenters: [6, 30], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 108 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 43 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 11 }, + { numBlocks: 2, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: null, + versionNumber: 6, + alignmentPatternCenters: [6, 34], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 68 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 27 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 15 }], + }, + ], + }, + { + infoBits: 0x07C94, + versionNumber: 7, + alignmentPatternCenters: [6, 22, 38], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 78 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 31 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + { numBlocks: 1, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x085BC, + versionNumber: 8, + alignmentPatternCenters: [6, 24, 42], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 97 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 38 }, + { numBlocks: 2, dataCodewordsPerBlock: 39 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 18 }, + { numBlocks: 2, dataCodewordsPerBlock: 19 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 14 }, + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x09A99, + versionNumber: 9, + alignmentPatternCenters: [6, 26, 46], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 116 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0A4D3, + versionNumber: 10, + alignmentPatternCenters: [6, 28, 50], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 68 }, + { numBlocks: 2, dataCodewordsPerBlock: 69 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 43 }, + { numBlocks: 1, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x0BBF6, + versionNumber: 11, + alignmentPatternCenters: [6, 30, 54], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 81 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 50 }, + { numBlocks: 4, dataCodewordsPerBlock: 51 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + { numBlocks: 4, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 12 }, + { numBlocks: 8, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0C762, + versionNumber: 12, + alignmentPatternCenters: [6, 32, 58], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 92 }, + { numBlocks: 2, dataCodewordsPerBlock: 93 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 20 }, + { numBlocks: 6, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x0D847, + versionNumber: 13, + alignmentPatternCenters: [6, 34, 62], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 107 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 37 }, + { numBlocks: 1, dataCodewordsPerBlock: 38 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 20 }, + { numBlocks: 4, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 11 }, + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: 0x0E60D, + versionNumber: 14, + alignmentPatternCenters: [6, 26, 46, 66], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 40 }, + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 16 }, + { numBlocks: 5, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 5, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0F928, + versionNumber: 15, + alignmentPatternCenters: [6, 26, 48, 70], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 87 }, + { numBlocks: 1, dataCodewordsPerBlock: 88 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + { numBlocks: 5, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 7, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x10B78, + versionNumber: 16, + alignmentPatternCenters: [6, 26, 50, 74], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 98 }, + { numBlocks: 1, dataCodewordsPerBlock: 99 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1145D, + versionNumber: 17, + alignmentPatternCenters: [6, 30, 54, 78], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 1, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 22 }, + { numBlocks: 15, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 17, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x12A17, + versionNumber: 18, + alignmentPatternCenters: [6, 30, 56, 82], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 120 }, + { numBlocks: 1, dataCodewordsPerBlock: 121 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 43 }, + { numBlocks: 4, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x13532, + versionNumber: 19, + alignmentPatternCenters: [6, 30, 58, 86], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 113 }, + { numBlocks: 4, dataCodewordsPerBlock: 114 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 44 }, + { numBlocks: 11, dataCodewordsPerBlock: 45 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 21 }, + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 13 }, + { numBlocks: 16, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x149A6, + versionNumber: 20, + alignmentPatternCenters: [6, 34, 62, 90], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 41 }, + { numBlocks: 13, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 5, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 15 }, + { numBlocks: 10, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x15683, + versionNumber: 21, + alignmentPatternCenters: [6, 28, 50, 72, 94], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 116 }, + { numBlocks: 4, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 42 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 16 }, + { numBlocks: 6, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x168C9, + versionNumber: 22, + alignmentPatternCenters: [6, 26, 50, 74, 98], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 111 }, + { numBlocks: 7, dataCodewordsPerBlock: 112 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 46 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 34, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: 0x177EC, + versionNumber: 23, + alignmentPatternCenters: [6, 30, 54, 74, 102], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 121 }, + { numBlocks: 5, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + { numBlocks: 14, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 16, dataCodewordsPerBlock: 15 }, + { numBlocks: 14, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x18EC4, + versionNumber: 24, + alignmentPatternCenters: [6, 28, 54, 80, 106], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 45 }, + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 30, dataCodewordsPerBlock: 16 }, + { numBlocks: 2, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x191E1, + versionNumber: 25, + alignmentPatternCenters: [6, 32, 58, 84, 110], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 106 }, + { numBlocks: 4, dataCodewordsPerBlock: 107 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 47 }, + { numBlocks: 13, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1AFAB, + versionNumber: 26, + alignmentPatternCenters: [6, 30, 58, 86, 114], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 114 }, + { numBlocks: 2, dataCodewordsPerBlock: 115 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 46 }, + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 28, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 33, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x1B08E, + versionNumber: 27, + alignmentPatternCenters: [6, 34, 62, 90, 118], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 23 }, + { numBlocks: 26, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1CC1A, + versionNumber: 28, + alignmentPatternCenters: [6, 26, 50, 74, 98, 122], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 117 }, + { numBlocks: 10, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 45 }, + { numBlocks: 23, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 24 }, + { numBlocks: 31, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 31, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1D33F, + versionNumber: 29, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 116 }, + { numBlocks: 7, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 21, dataCodewordsPerBlock: 45 }, + { numBlocks: 7, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + { numBlocks: 37, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 26, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1ED75, + versionNumber: 30, + alignmentPatternCenters: [6, 26, 52, 78, 104, 130], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 115 }, + { numBlocks: 10, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 47 }, + { numBlocks: 10, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 25, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 25, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1F250, + versionNumber: 31, + alignmentPatternCenters: [6, 30, 56, 82, 108, 134], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 3, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 46 }, + { numBlocks: 29, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 24 }, + { numBlocks: 1, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x209D5, + versionNumber: 32, + alignmentPatternCenters: [6, 34, 60, 86, 112, 138], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 115 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 24 }, + { numBlocks: 35, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 35, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x216F0, + versionNumber: 33, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 21, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 24 }, + { numBlocks: 19, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x228BA, + versionNumber: 34, + alignmentPatternCenters: [6, 34, 62, 90, 118, 146], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 6, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 44, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 59, dataCodewordsPerBlock: 16 }, + { numBlocks: 1, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x2379F, + versionNumber: 35, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126, 150], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 121 }, + { numBlocks: 7, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 47 }, + { numBlocks: 26, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 39, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 41, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x24B0B, + versionNumber: 36, + alignmentPatternCenters: [6, 24, 50, 76, 102, 128, 154], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 121 }, + { numBlocks: 14, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 47 }, + { numBlocks: 34, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 46, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 64, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x2542E, + versionNumber: 37, + alignmentPatternCenters: [6, 28, 54, 80, 106, 132, 158], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 46 }, + { numBlocks: 14, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 49, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 24, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x26A64, + versionNumber: 38, + alignmentPatternCenters: [6, 32, 58, 84, 110, 136, 162], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 122 }, + { numBlocks: 18, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 46 }, + { numBlocks: 32, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 48, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 15 }, + { numBlocks: 32, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x27541, + versionNumber: 39, + alignmentPatternCenters: [6, 26, 54, 82, 110, 138, 166], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 40, dataCodewordsPerBlock: 47 }, + { numBlocks: 7, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 43, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 15 }, + { numBlocks: 67, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x28C69, + versionNumber: 40, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142, 170], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 118 }, + { numBlocks: 6, dataCodewordsPerBlock: 119 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 18, dataCodewordsPerBlock: 47 }, + { numBlocks: 31, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 34, dataCodewordsPerBlock: 24 }, + { numBlocks: 34, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 15 }, + { numBlocks: 61, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, +]; + +// tslint:disable:no-bitwise +function numBitsDiffering(x, y) { + let z = x ^ y; + let bitCount = 0; + while (z) { + bitCount++; + z &= z - 1; + } + return bitCount; +} +function pushBit(bit, byte) { + return (byte << 1) | bit; +} +// tslint:enable:no-bitwise +const FORMAT_INFO_TABLE = [ + { bits: 0x5412, formatInfo: { errorCorrectionLevel: 1, dataMask: 0 } }, + { bits: 0x5125, formatInfo: { errorCorrectionLevel: 1, dataMask: 1 } }, + { bits: 0x5E7C, formatInfo: { errorCorrectionLevel: 1, dataMask: 2 } }, + { bits: 0x5B4B, formatInfo: { errorCorrectionLevel: 1, dataMask: 3 } }, + { bits: 0x45F9, formatInfo: { errorCorrectionLevel: 1, dataMask: 4 } }, + { bits: 0x40CE, formatInfo: { errorCorrectionLevel: 1, dataMask: 5 } }, + { bits: 0x4F97, formatInfo: { errorCorrectionLevel: 1, dataMask: 6 } }, + { bits: 0x4AA0, formatInfo: { errorCorrectionLevel: 1, dataMask: 7 } }, + { bits: 0x77C4, formatInfo: { errorCorrectionLevel: 0, dataMask: 0 } }, + { bits: 0x72F3, formatInfo: { errorCorrectionLevel: 0, dataMask: 1 } }, + { bits: 0x7DAA, formatInfo: { errorCorrectionLevel: 0, dataMask: 2 } }, + { bits: 0x789D, formatInfo: { errorCorrectionLevel: 0, dataMask: 3 } }, + { bits: 0x662F, formatInfo: { errorCorrectionLevel: 0, dataMask: 4 } }, + { bits: 0x6318, formatInfo: { errorCorrectionLevel: 0, dataMask: 5 } }, + { bits: 0x6C41, formatInfo: { errorCorrectionLevel: 0, dataMask: 6 } }, + { bits: 0x6976, formatInfo: { errorCorrectionLevel: 0, dataMask: 7 } }, + { bits: 0x1689, formatInfo: { errorCorrectionLevel: 3, dataMask: 0 } }, + { bits: 0x13BE, formatInfo: { errorCorrectionLevel: 3, dataMask: 1 } }, + { bits: 0x1CE7, formatInfo: { errorCorrectionLevel: 3, dataMask: 2 } }, + { bits: 0x19D0, formatInfo: { errorCorrectionLevel: 3, dataMask: 3 } }, + { bits: 0x0762, formatInfo: { errorCorrectionLevel: 3, dataMask: 4 } }, + { bits: 0x0255, formatInfo: { errorCorrectionLevel: 3, dataMask: 5 } }, + { bits: 0x0D0C, formatInfo: { errorCorrectionLevel: 3, dataMask: 6 } }, + { bits: 0x083B, formatInfo: { errorCorrectionLevel: 3, dataMask: 7 } }, + { bits: 0x355F, formatInfo: { errorCorrectionLevel: 2, dataMask: 0 } }, + { bits: 0x3068, formatInfo: { errorCorrectionLevel: 2, dataMask: 1 } }, + { bits: 0x3F31, formatInfo: { errorCorrectionLevel: 2, dataMask: 2 } }, + { bits: 0x3A06, formatInfo: { errorCorrectionLevel: 2, dataMask: 3 } }, + { bits: 0x24B4, formatInfo: { errorCorrectionLevel: 2, dataMask: 4 } }, + { bits: 0x2183, formatInfo: { errorCorrectionLevel: 2, dataMask: 5 } }, + { bits: 0x2EDA, formatInfo: { errorCorrectionLevel: 2, dataMask: 6 } }, + { bits: 0x2BED, formatInfo: { errorCorrectionLevel: 2, dataMask: 7 } }, +]; +const DATA_MASKS = [ + (p) => ((p.y + p.x) % 2) === 0, + (p) => (p.y % 2) === 0, + (p) => p.x % 3 === 0, + (p) => (p.y + p.x) % 3 === 0, + (p) => (Math.floor(p.y / 2) + Math.floor(p.x / 3)) % 2 === 0, + (p) => ((p.x * p.y) % 2) + ((p.x * p.y) % 3) === 0, + (p) => ((((p.y * p.x) % 2) + (p.y * p.x) % 3) % 2) === 0, + (p) => ((((p.y + p.x) % 2) + (p.y * p.x) % 3) % 2) === 0, +]; +function buildFunctionPatternMask(version) { + const dimension = 17 + 4 * version.versionNumber; + const matrix = BitMatrix.createEmpty(dimension, dimension); + matrix.setRegion(0, 0, 9, 9, true); // Top left finder pattern + separator + format + matrix.setRegion(dimension - 8, 0, 8, 9, true); // Top right finder pattern + separator + format + matrix.setRegion(0, dimension - 8, 9, 8, true); // Bottom left finder pattern + separator + format + // Alignment patterns + for (const x of version.alignmentPatternCenters) { + for (const y of version.alignmentPatternCenters) { + if (!(x === 6 && y === 6 || x === 6 && y === dimension - 7 || x === dimension - 7 && y === 6)) { + matrix.setRegion(x - 2, y - 2, 5, 5, true); + } + } + } + matrix.setRegion(6, 9, 1, dimension - 17, true); // Vertical timing pattern + matrix.setRegion(9, 6, dimension - 17, 1, true); // Horizontal timing pattern + if (version.versionNumber > 6) { + matrix.setRegion(dimension - 11, 0, 3, 6, true); // Version info, top right + matrix.setRegion(0, dimension - 11, 6, 3, true); // Version info, bottom left + } + return matrix; +} +function readCodewords(matrix, version, formatInfo) { + const dataMask = DATA_MASKS[formatInfo.dataMask]; + const dimension = matrix.height; + const functionPatternMask = buildFunctionPatternMask(version); + const codewords = []; + let currentByte = 0; + let bitsRead = 0; + // Read columns in pairs, from right to left + let readingUp = true; + for (let columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) { + if (columnIndex === 6) { // Skip whole column with vertical alignment pattern; + columnIndex--; + } + for (let i = 0; i < dimension; i++) { + const y = readingUp ? dimension - 1 - i : i; + for (let columnOffset = 0; columnOffset < 2; columnOffset++) { + const x = columnIndex - columnOffset; + if (!functionPatternMask.get(x, y)) { + bitsRead++; + let bit = matrix.get(x, y); + if (dataMask({ y, x })) { + bit = !bit; + } + currentByte = pushBit(bit, currentByte); + if (bitsRead === 8) { // Whole bytes + codewords.push(currentByte); + bitsRead = 0; + currentByte = 0; + } + } + } + } + readingUp = !readingUp; + } + return codewords; +} +function readVersion(matrix) { + const dimension = matrix.height; + const provisionalVersion = Math.floor((dimension - 17) / 4); + if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code + return VERSIONS[provisionalVersion - 1]; + } + let topRightVersionBits = 0; + for (let y = 5; y >= 0; y--) { + for (let x = dimension - 9; x >= dimension - 11; x--) { + topRightVersionBits = pushBit(matrix.get(x, y), topRightVersionBits); + } + } + let bottomLeftVersionBits = 0; + for (let x = 5; x >= 0; x--) { + for (let y = dimension - 9; y >= dimension - 11; y--) { + bottomLeftVersionBits = pushBit(matrix.get(x, y), bottomLeftVersionBits); + } + } + let bestDifference = Infinity; + let bestVersion; + for (const version of VERSIONS) { + if (version.infoBits === topRightVersionBits || version.infoBits === bottomLeftVersionBits) { + return version; + } + let difference = numBitsDiffering(topRightVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + difference = numBitsDiffering(bottomLeftVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + } + // We can tolerate up to 3 bits of error since no two version info codewords will + // differ in less than 8 bits. + if (bestDifference <= 3) { + return bestVersion; + } +} +function readFormatInformation(matrix) { + let topLeftFormatInfoBits = 0; + for (let x = 0; x <= 8; x++) { + if (x !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits); + } + } + for (let y = 7; y >= 0; y--) { + if (y !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits); + } + } + const dimension = matrix.height; + let topRightBottomRightFormatInfoBits = 0; + for (let y = dimension - 1; y >= dimension - 7; y--) { // bottom left + topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits); + } + for (let x = dimension - 8; x < dimension; x++) { // top right + topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits); + } + let bestDifference = Infinity; + let bestFormatInfo = null; + for (const { bits, formatInfo } of FORMAT_INFO_TABLE) { + if (bits === topLeftFormatInfoBits || bits === topRightBottomRightFormatInfoBits) { + return formatInfo; + } + let difference = numBitsDiffering(topLeftFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option + difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + } + } + // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match + if (bestDifference <= 3) { + return bestFormatInfo; + } + return null; +} +function getDataBlocks(codewords, version, ecLevel) { + const ecInfo = version.errorCorrectionLevels[ecLevel]; + const dataBlocks = []; + let totalCodewords = 0; + ecInfo.ecBlocks.forEach(block => { + for (let i = 0; i < block.numBlocks; i++) { + dataBlocks.push({ numDataCodewords: block.dataCodewordsPerBlock, codewords: [] }); + totalCodewords += block.dataCodewordsPerBlock + ecInfo.ecCodewordsPerBlock; + } + }); + // In some cases the QR code will be malformed enough that we pull off more or less than we should. + // If we pull off less there's nothing we can do. + // If we pull off more we can safely truncate + if (codewords.length < totalCodewords) { + return null; + } + codewords = codewords.slice(0, totalCodewords); + const shortBlockSize = ecInfo.ecBlocks[0].dataCodewordsPerBlock; + // Pull codewords to fill the blocks up to the minimum size + for (let i = 0; i < shortBlockSize; i++) { + for (const dataBlock of dataBlocks) { + dataBlock.codewords.push(codewords.shift()); + } + } + // If there are any large blocks, pull codewords to fill the last element of those + if (ecInfo.ecBlocks.length > 1) { + const smallBlockCount = ecInfo.ecBlocks[0].numBlocks; + const largeBlockCount = ecInfo.ecBlocks[1].numBlocks; + for (let i = 0; i < largeBlockCount; i++) { + dataBlocks[smallBlockCount + i].codewords.push(codewords.shift()); + } + } + // Add the rest of the codewords to the blocks. These are the error correction codewords. + while (codewords.length > 0) { + for (const dataBlock of dataBlocks) { + dataBlock.codewords.push(codewords.shift()); + } + } + return dataBlocks; +} +function decodeMatrix(matrix) { + const version = readVersion(matrix); + if (!version) { + return null; + } + const formatInfo = readFormatInformation(matrix); + if (!formatInfo) { + return null; + } + const codewords = readCodewords(matrix, version, formatInfo); + const dataBlocks = getDataBlocks(codewords, version, formatInfo.errorCorrectionLevel); + if (!dataBlocks) { + return null; + } + // Count total number of data bytes + const totalBytes = dataBlocks.reduce((a, b) => a + b.numDataCodewords, 0); + const resultBytes = new Uint8ClampedArray(totalBytes); + let resultIndex = 0; + for (const dataBlock of dataBlocks) { + const correctedBytes = decode$1(dataBlock.codewords, dataBlock.codewords.length - dataBlock.numDataCodewords); + if (!correctedBytes) { + return null; + } + for (let i = 0; i < dataBlock.numDataCodewords; i++) { + resultBytes[resultIndex++] = correctedBytes[i]; + } + } + try { + return decode$2(resultBytes, version.versionNumber); + } + catch (_a) { + return null; + } +} +function decode(matrix) { + if (matrix == null) { + return null; + } + const result = decodeMatrix(matrix); + if (result) { + return result; + } + // Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line. + for (let x = 0; x < matrix.width; x++) { + for (let y = x + 1; y < matrix.height; y++) { + if (matrix.get(x, y) !== matrix.get(y, x)) { + matrix.set(x, y, !matrix.get(x, y)); + matrix.set(y, x, !matrix.get(y, x)); + } + } + } + return decodeMatrix(matrix); +} + +function squareToQuadrilateral(p1, p2, p3, p4) { + const dx3 = p1.x - p2.x + p3.x - p4.x; + const dy3 = p1.y - p2.y + p3.y - p4.y; + if (dx3 === 0 && dy3 === 0) { // Affine + return { + a11: p2.x - p1.x, + a12: p2.y - p1.y, + a13: 0, + a21: p3.x - p2.x, + a22: p3.y - p2.y, + a23: 0, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } + else { + const dx1 = p2.x - p3.x; + const dx2 = p4.x - p3.x; + const dy1 = p2.y - p3.y; + const dy2 = p4.y - p3.y; + const denominator = dx1 * dy2 - dx2 * dy1; + const a13 = (dx3 * dy2 - dx2 * dy3) / denominator; + const a23 = (dx1 * dy3 - dx3 * dy1) / denominator; + return { + a11: p2.x - p1.x + a13 * p2.x, + a12: p2.y - p1.y + a13 * p2.y, + a13, + a21: p4.x - p1.x + a23 * p4.x, + a22: p4.y - p1.y + a23 * p4.y, + a23, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } +} +function quadrilateralToSquare(p1, p2, p3, p4) { + // Here, the adjoint serves as the inverse: + const sToQ = squareToQuadrilateral(p1, p2, p3, p4); + return { + a11: sToQ.a22 * sToQ.a33 - sToQ.a23 * sToQ.a32, + a12: sToQ.a13 * sToQ.a32 - sToQ.a12 * sToQ.a33, + a13: sToQ.a12 * sToQ.a23 - sToQ.a13 * sToQ.a22, + a21: sToQ.a23 * sToQ.a31 - sToQ.a21 * sToQ.a33, + a22: sToQ.a11 * sToQ.a33 - sToQ.a13 * sToQ.a31, + a23: sToQ.a13 * sToQ.a21 - sToQ.a11 * sToQ.a23, + a31: sToQ.a21 * sToQ.a32 - sToQ.a22 * sToQ.a31, + a32: sToQ.a12 * sToQ.a31 - sToQ.a11 * sToQ.a32, + a33: sToQ.a11 * sToQ.a22 - sToQ.a12 * sToQ.a21, + }; +} +function times(a, b) { + return { + a11: a.a11 * b.a11 + a.a21 * b.a12 + a.a31 * b.a13, + a12: a.a12 * b.a11 + a.a22 * b.a12 + a.a32 * b.a13, + a13: a.a13 * b.a11 + a.a23 * b.a12 + a.a33 * b.a13, + a21: a.a11 * b.a21 + a.a21 * b.a22 + a.a31 * b.a23, + a22: a.a12 * b.a21 + a.a22 * b.a22 + a.a32 * b.a23, + a23: a.a13 * b.a21 + a.a23 * b.a22 + a.a33 * b.a23, + a31: a.a11 * b.a31 + a.a21 * b.a32 + a.a31 * b.a33, + a32: a.a12 * b.a31 + a.a22 * b.a32 + a.a32 * b.a33, + a33: a.a13 * b.a31 + a.a23 * b.a32 + a.a33 * b.a33, + }; +} +function extract(image, location) { + const qToS = quadrilateralToSquare({ x: 3.5, y: 3.5 }, { x: location.dimension - 3.5, y: 3.5 }, { x: location.dimension - 6.5, y: location.dimension - 6.5 }, { x: 3.5, y: location.dimension - 3.5 }); + const sToQ = squareToQuadrilateral(location.topLeft, location.topRight, location.alignmentPattern, location.bottomLeft); + const transform = times(sToQ, qToS); + const matrix = BitMatrix.createEmpty(location.dimension, location.dimension); + const mappingFunction = (x, y) => { + const denominator = transform.a13 * x + transform.a23 * y + transform.a33; + return { + x: (transform.a11 * x + transform.a21 * y + transform.a31) / denominator, + y: (transform.a12 * x + transform.a22 * y + transform.a32) / denominator, + }; + }; + for (let y = 0; y < location.dimension; y++) { + for (let x = 0; x < location.dimension; x++) { + const xValue = x + 0.5; + const yValue = y + 0.5; + const sourcePixel = mappingFunction(xValue, yValue); + matrix.set(x, y, image.get(Math.floor(sourcePixel.x), Math.floor(sourcePixel.y))); + } + } + return { + matrix, + mappingFunction, + }; +} + +const MAX_FINDERPATTERNS_TO_SEARCH = 5; +const MIN_QUAD_RATIO = 0.5; +const MAX_QUAD_RATIO = 1.5; +const distance = (a, b) => Math.sqrt(Math.pow((b.x - a.x), 2) + Math.pow((b.y - a.y), 2)); +function sum(values) { + return values.reduce((a, b) => a + b); +} +// Takes three finder patterns and organizes them into topLeft, topRight, etc +function reorderFinderPatterns(pattern1, pattern2, pattern3) { + // Find distances between pattern centers + const oneTwoDistance = distance(pattern1, pattern2); + const twoThreeDistance = distance(pattern2, pattern3); + const oneThreeDistance = distance(pattern1, pattern3); + let bottomLeft; + let topLeft; + let topRight; + // Assume one closest to other two is B; A and C will just be guesses at first + if (twoThreeDistance >= oneTwoDistance && twoThreeDistance >= oneThreeDistance) { + [bottomLeft, topLeft, topRight] = [pattern2, pattern1, pattern3]; + } + else if (oneThreeDistance >= twoThreeDistance && oneThreeDistance >= oneTwoDistance) { + [bottomLeft, topLeft, topRight] = [pattern1, pattern2, pattern3]; + } + else { + [bottomLeft, topLeft, topRight] = [pattern1, pattern3, pattern2]; + } + // Use cross product to figure out whether bottomLeft (A) and topRight (C) are correct or flipped in relation to topLeft (B) + // This asks whether BC x BA has a positive z component, which is the arrangement we want. If it's negative, then + // we've got it flipped around and should swap topRight and bottomLeft. + if (((topRight.x - topLeft.x) * (bottomLeft.y - topLeft.y)) - ((topRight.y - topLeft.y) * (bottomLeft.x - topLeft.x)) < 0) { + [bottomLeft, topRight] = [topRight, bottomLeft]; + } + return { bottomLeft, topLeft, topRight }; +} +// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns +function computeDimension(topLeft, topRight, bottomLeft, matrix) { + const moduleSize = (sum(countBlackWhiteRun(topLeft, bottomLeft, matrix, 5)) / 7 + // Divide by 7 since the ratio is 1:1:3:1:1 + sum(countBlackWhiteRun(topLeft, topRight, matrix, 5)) / 7 + + sum(countBlackWhiteRun(bottomLeft, topLeft, matrix, 5)) / 7 + + sum(countBlackWhiteRun(topRight, topLeft, matrix, 5)) / 7) / 4; + if (moduleSize < 1) { + throw new Error("Invalid module size"); + } + const topDimension = Math.round(distance(topLeft, topRight) / moduleSize); + const sideDimension = Math.round(distance(topLeft, bottomLeft) / moduleSize); + let dimension = Math.floor((topDimension + sideDimension) / 2) + 7; + switch (dimension % 4) { + case 0: + dimension++; + break; + case 2: + dimension--; + break; + } + return { dimension, moduleSize }; +} +// Takes an origin point and an end point and counts the sizes of the black white run from the origin towards the end point. +// Returns an array of elements, representing the pixel size of the black white run. +// Uses a variant of http://en.wikipedia.org/wiki/Bresenham's_line_algorithm +function countBlackWhiteRunTowardsPoint(origin, end, matrix, length) { + const switchPoints = [{ x: Math.floor(origin.x), y: Math.floor(origin.y) }]; + const steep = Math.abs(end.y - origin.y) > Math.abs(end.x - origin.x); + let fromX; + let fromY; + let toX; + let toY; + if (steep) { + fromX = Math.floor(origin.y); + fromY = Math.floor(origin.x); + toX = Math.floor(end.y); + toY = Math.floor(end.x); + } + else { + fromX = Math.floor(origin.x); + fromY = Math.floor(origin.y); + toX = Math.floor(end.x); + toY = Math.floor(end.y); + } + const dx = Math.abs(toX - fromX); + const dy = Math.abs(toY - fromY); + let error = Math.floor(-dx / 2); + const xStep = fromX < toX ? 1 : -1; + const yStep = fromY < toY ? 1 : -1; + let currentPixel = true; + // Loop up until x == toX, but not beyond + for (let x = fromX, y = fromY; x !== toX + xStep; x += xStep) { + // Does current pixel mean we have moved white to black or vice versa? + // Scanning black in state 0,2 and white in state 1, so if we find the wrong + // color, advance to next state or end if we are in state 2 already + const realX = steep ? y : x; + const realY = steep ? x : y; + if (matrix.get(realX, realY) !== currentPixel) { + currentPixel = !currentPixel; + switchPoints.push({ x: realX, y: realY }); + if (switchPoints.length === length + 1) { + break; + } + } + error += dy; + if (error > 0) { + if (y === toY) { + break; + } + y += yStep; + error -= dx; + } + } + const distances = []; + for (let i = 0; i < length; i++) { + if (switchPoints[i] && switchPoints[i + 1]) { + distances.push(distance(switchPoints[i], switchPoints[i + 1])); + } + else { + distances.push(0); + } + } + return distances; +} +// Takes an origin point and an end point and counts the sizes of the black white run in the origin point +// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes +// of the black white run. Takes a length which represents the number of switches from black to white to look for. +function countBlackWhiteRun(origin, end, matrix, length) { + const rise = end.y - origin.y; + const run = end.x - origin.x; + const towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2)); + const awayFromEnd = countBlackWhiteRunTowardsPoint(origin, { x: origin.x - run, y: origin.y - rise }, matrix, Math.ceil(length / 2)); + const middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel + return awayFromEnd.concat(middleValue).concat(...towardsEnd); +} +// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the "error" - +// that is the amount the run diverges from the expected ratio +function scoreBlackWhiteRun(sequence, ratios) { + const averageSize = sum(sequence) / sum(ratios); + let error = 0; + ratios.forEach((ratio, i) => { + error += Math.pow((sequence[i] - ratio * averageSize), 2); + }); + return { averageSize, error }; +} +// Takes an X,Y point and an array of sizes and scores the point against those ratios. +// For example for a finder pattern takes the ratio list of 1:1:3:1:1 and checks horizontal, vertical and diagonal ratios +// against that. +function scorePattern(point, ratios, matrix) { + try { + const horizontalRun = countBlackWhiteRun(point, { x: -1, y: point.y }, matrix, ratios.length); + const verticalRun = countBlackWhiteRun(point, { x: point.x, y: -1 }, matrix, ratios.length); + const topLeftPoint = { + x: Math.max(0, point.x - point.y) - 1, + y: Math.max(0, point.y - point.x) - 1, + }; + const topLeftBottomRightRun = countBlackWhiteRun(point, topLeftPoint, matrix, ratios.length); + const bottomLeftPoint = { + x: Math.min(matrix.width, point.x + point.y) + 1, + y: Math.min(matrix.height, point.y + point.x) + 1, + }; + const bottomLeftTopRightRun = countBlackWhiteRun(point, bottomLeftPoint, matrix, ratios.length); + const horzError = scoreBlackWhiteRun(horizontalRun, ratios); + const vertError = scoreBlackWhiteRun(verticalRun, ratios); + const diagDownError = scoreBlackWhiteRun(topLeftBottomRightRun, ratios); + const diagUpError = scoreBlackWhiteRun(bottomLeftTopRightRun, ratios); + const ratioError = Math.sqrt(horzError.error * horzError.error + + vertError.error * vertError.error + + diagDownError.error * diagDownError.error + + diagUpError.error * diagUpError.error); + const avgSize = (horzError.averageSize + vertError.averageSize + diagDownError.averageSize + diagUpError.averageSize) / 4; + const sizeError = (Math.pow((horzError.averageSize - avgSize), 2) + + Math.pow((vertError.averageSize - avgSize), 2) + + Math.pow((diagDownError.averageSize - avgSize), 2) + + Math.pow((diagUpError.averageSize - avgSize), 2)) / avgSize; + return ratioError + sizeError; + } + catch (_a) { + return Infinity; + } +} +function recenterLocation(matrix, p) { + let leftX = Math.round(p.x); + while (matrix.get(leftX, Math.round(p.y))) { + leftX--; + } + let rightX = Math.round(p.x); + while (matrix.get(rightX, Math.round(p.y))) { + rightX++; + } + const x = (leftX + rightX) / 2; + let topY = Math.round(p.y); + while (matrix.get(Math.round(x), topY)) { + topY--; + } + let bottomY = Math.round(p.y); + while (matrix.get(Math.round(x), bottomY)) { + bottomY++; + } + const y = (topY + bottomY) / 2; + return { x, y }; +} +function locate(matrix) { + const finderPatternQuads = []; + let activeFinderPatternQuads = []; + const alignmentPatternQuads = []; + let activeAlignmentPatternQuads = []; + for (let y = 0; y <= matrix.height; y++) { + let length = 0; + let lastBit = false; + let scans = [0, 0, 0, 0, 0]; + for (let x = -1; x <= matrix.width; x++) { + const v = matrix.get(x, y); + if (v === lastBit) { + length++; + } + else { + scans = [scans[1], scans[2], scans[3], scans[4], length]; + length = 1; + lastBit = v; + // Do the last 5 color changes ~ match the expected ratio for a finder pattern? 1:1:3:1:1 of b:w:b:w:b + const averageFinderPatternBlocksize = sum(scans) / 7; + const validFinderPattern = Math.abs(scans[0] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[1] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[2] - 3 * averageFinderPatternBlocksize) < 3 * averageFinderPatternBlocksize && + Math.abs(scans[3] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[4] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + !v; // And make sure the current pixel is white since finder patterns are bordered in white + // Do the last 3 color changes ~ match the expected ratio for an alignment pattern? 1:1:1 of w:b:w + const averageAlignmentPatternBlocksize = sum(scans.slice(-3)) / 3; + const validAlignmentPattern = Math.abs(scans[2] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[3] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[4] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + v; // Is the current pixel black since alignment patterns are bordered in black + if (validFinderPattern) { + // Compute the start and end x values of the large center black square + const endX = x - scans[3] - scans[4]; + const startX = endX - scans[2]; + const line = { startX, endX, y }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + const matchingQuads = activeFinderPatternQuads.filter(q => (startX >= q.bottom.startX && startX <= q.bottom.endX) || + (endX >= q.bottom.startX && startX <= q.bottom.endX) || + (startX <= q.bottom.startX && endX >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO))); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeFinderPatternQuads.push({ top: line, bottom: line }); + } + } + if (validAlignmentPattern) { + // Compute the start and end x values of the center black square + const endX = x - scans[4]; + const startX = endX - scans[3]; + const line = { startX, y, endX }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + const matchingQuads = activeAlignmentPatternQuads.filter(q => (startX >= q.bottom.startX && startX <= q.bottom.endX) || + (endX >= q.bottom.startX && startX <= q.bottom.endX) || + (startX <= q.bottom.startX && endX >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO))); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeAlignmentPatternQuads.push({ top: line, bottom: line }); + } + } + } + } + finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y !== y && q.bottom.y - q.top.y >= 2)); + activeFinderPatternQuads = activeFinderPatternQuads.filter(q => q.bottom.y === y); + alignmentPatternQuads.push(...activeAlignmentPatternQuads.filter(q => q.bottom.y !== y)); + activeAlignmentPatternQuads = activeAlignmentPatternQuads.filter(q => q.bottom.y === y); + } + finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y - q.top.y >= 2)); + alignmentPatternQuads.push(...activeAlignmentPatternQuads); + // Refactored from cozmo/jsQR to (hopefully) circumvent an issue in Safari 13+ on both Mac and iOS (also including + // iOS Chrome and other Safari iOS derivatives). Safari was very occasionally and apparently not deterministically + // throwing a "RangeError: Array size is not a small enough positive integer." exception seemingly within the second + // .map of the original code (here the second for-loop). This second .map contained a nested .map call over the same + // array instance which was the chained result from previous calls to .map, .filter and .sort which potentially caused + // this bug in Safari? + // Also see https://github.com/cozmo/jsQR/issues/157 and https://bugs.webkit.org/show_bug.cgi?id=211619#c3 + const scoredFinderPatternPositions = []; + for (const quad of finderPatternQuads) { + if (quad.bottom.y - quad.top.y < 2) { + // All quads must be at least 2px tall since the center square is larger than a block + continue; + } + // calculate quad center + const x = (quad.top.startX + quad.top.endX + quad.bottom.startX + quad.bottom.endX) / 4; + const y = (quad.top.y + quad.bottom.y + 1) / 2; + if (!matrix.get(Math.round(x), Math.round(y))) { + continue; + } + const lengths = [quad.top.endX - quad.top.startX, quad.bottom.endX - quad.bottom.startX, quad.bottom.y - quad.top.y + 1]; + const size = sum(lengths) / lengths.length; + // Initial scoring of finder pattern quads by looking at their ratios, not taking into account position + const score = scorePattern({ x: Math.round(x), y: Math.round(y) }, [1, 1, 3, 1, 1], matrix); + scoredFinderPatternPositions.push({ score, x, y, size }); + } + if (scoredFinderPatternPositions.length < 3) { + // A QR code has 3 finder patterns, therefore we need at least 3 candidates. + return null; + } + scoredFinderPatternPositions.sort((a, b) => a.score - b.score); + // Now take the top finder pattern options and try to find 2 other options with a similar size. + const finderPatternGroups = []; + for (let i = 0; i < Math.min(scoredFinderPatternPositions.length, MAX_FINDERPATTERNS_TO_SEARCH); ++i) { + const point = scoredFinderPatternPositions[i]; + const otherPoints = []; + for (const otherPoint of scoredFinderPatternPositions) { + if (otherPoint === point) { + continue; + } + otherPoints.push(Object.assign(Object.assign({}, otherPoint), { score: otherPoint.score + (Math.pow((otherPoint.size - point.size), 2)) / point.size })); + } + otherPoints.sort((a, b) => a.score - b.score); + finderPatternGroups.push({ + points: [point, otherPoints[0], otherPoints[1]], + score: point.score + otherPoints[0].score + otherPoints[1].score, // total combined score of the three points in the group + }); + } + finderPatternGroups.sort((a, b) => a.score - b.score); + const bestFinderPatternGroup = finderPatternGroups[0]; + const { topRight, topLeft, bottomLeft } = reorderFinderPatterns(...bestFinderPatternGroup.points); + const alignment = findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft); + const result = []; + if (alignment) { + result.push({ + alignmentPattern: { x: alignment.alignmentPattern.x, y: alignment.alignmentPattern.y }, + bottomLeft: { x: bottomLeft.x, y: bottomLeft.y }, + dimension: alignment.dimension, + topLeft: { x: topLeft.x, y: topLeft.y }, + topRight: { x: topRight.x, y: topRight.y }, + }); + } + // We normally use the center of the quads as the location of the tracking points, which is optimal for most cases and will account + // for a skew in the image. However, In some cases, a slight skew might not be real and instead be caused by image compression + // errors and/or low resolution. For those cases, we'd be better off centering the point exactly in the middle of the black area. We + // compute and return the location data for the naively centered points as it is little additional work and allows for multiple + // attempts at decoding harder images. + const midTopRight = recenterLocation(matrix, topRight); + const midTopLeft = recenterLocation(matrix, topLeft); + const midBottomLeft = recenterLocation(matrix, bottomLeft); + const centeredAlignment = findAlignmentPattern(matrix, alignmentPatternQuads, midTopRight, midTopLeft, midBottomLeft); + if (centeredAlignment) { + result.push({ + alignmentPattern: { x: centeredAlignment.alignmentPattern.x, y: centeredAlignment.alignmentPattern.y }, + bottomLeft: { x: midBottomLeft.x, y: midBottomLeft.y }, + topLeft: { x: midTopLeft.x, y: midTopLeft.y }, + topRight: { x: midTopRight.x, y: midTopRight.y }, + dimension: centeredAlignment.dimension, + }); + } + if (result.length === 0) { + return null; + } + return result; +} +function findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft) { + // Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code. + // We'll use these to help find the alignment pattern but also later when we do the extraction. + let dimension; + let moduleSize; + try { + ({ dimension, moduleSize } = computeDimension(topLeft, topRight, bottomLeft, matrix)); + } + catch (e) { + return null; + } + // Now find the alignment pattern + const bottomRightFinderPattern = { + x: topRight.x - topLeft.x + bottomLeft.x, + y: topRight.y - topLeft.y + bottomLeft.y, + }; + const modulesBetweenFinderPatterns = ((distance(topLeft, bottomLeft) + distance(topLeft, topRight)) / 2 / moduleSize); + const correctionToTopLeft = 1 - (3 / modulesBetweenFinderPatterns); + const expectedAlignmentPattern = { + x: topLeft.x + correctionToTopLeft * (bottomRightFinderPattern.x - topLeft.x), + y: topLeft.y + correctionToTopLeft * (bottomRightFinderPattern.y - topLeft.y), + }; + const alignmentPatterns = alignmentPatternQuads + .map(q => { + const x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4; + const y = (q.top.y + q.bottom.y + 1) / 2; + if (!matrix.get(Math.floor(x), Math.floor(y))) { + return; + } + const sizeScore = scorePattern({ x: Math.floor(x), y: Math.floor(y) }, [1, 1, 1], matrix); + const score = sizeScore + distance({ x, y }, expectedAlignmentPattern); + return { x, y, score }; + }) + .filter(v => !!v) + .sort((a, b) => a.score - b.score); + // If there are less than 15 modules between finder patterns it's a version 1 QR code and as such has no alignmemnt pattern + // so we can only use our best guess. + const alignmentPattern = modulesBetweenFinderPatterns >= 15 && alignmentPatterns.length ? alignmentPatterns[0] : expectedAlignmentPattern; + return { alignmentPattern, dimension }; +} + +function scan(matrix) { + const locations = locate(matrix); + if (!locations) { + return null; + } + for (const location of locations) { + const extracted = extract(matrix, location); + const decoded = decode(extracted.matrix); + if (decoded) { + return { + binaryData: decoded.bytes, + data: decoded.text, + chunks: decoded.chunks, + version: decoded.version, + location: { + topRightCorner: extracted.mappingFunction(location.dimension, 0), + topLeftCorner: extracted.mappingFunction(0, 0), + bottomRightCorner: extracted.mappingFunction(location.dimension, location.dimension), + bottomLeftCorner: extracted.mappingFunction(0, location.dimension), + topRightFinderPattern: location.topRight, + topLeftFinderPattern: location.topLeft, + bottomLeftFinderPattern: location.bottomLeft, + bottomRightAlignmentPattern: location.alignmentPattern, + }, + matrix: extracted.matrix, + }; + } + } + return null; +} +const defaultOptions = { + inversionAttempts: "attemptBoth", + greyScaleWeights: { + red: 0.2126, + green: 0.7152, + blue: 0.0722, + useIntegerApproximation: false, + }, + canOverwriteImage: true, +}; +function mergeObject(target, src) { + Object.keys(src).forEach(opt => { + target[opt] = src[opt]; + }); +} +function jsQR(data, width, height, providedOptions = {}) { + const options = Object.create(null); + mergeObject(options, defaultOptions); + mergeObject(options, providedOptions); + const tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst"; + const shouldInvert = options.inversionAttempts === "attemptBoth" || tryInvertedFirst; + const { binarized, inverted } = binarize(data, width, height, shouldInvert, options.greyScaleWeights, options.canOverwriteImage); + let result = scan(tryInvertedFirst ? inverted : binarized); + if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) { + result = scan(tryInvertedFirst ? binarized : inverted); + } + return result; +} +jsQR.default = jsQR; + +export { jsQR as default }; \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/changelog.md b/uni_modules/x-mlkit-scannig-u/changelog.md new file mode 100644 index 0000000..a599154 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/changelog.md @@ -0,0 +1,41 @@ +## 1.1.2(2025-08-17) +* 针对微信的浏览器内核设定相关属性,以防止全屏脱离文档。 +## 1.1.1(2025-02-13) +* web,和微信相册识别已经改版本,能识别大多数码,效率有所提升。因为采用像素解析识别码,因此web,微信它是可以通用的,并且不依赖微信官方本身,所以 +* 你现在在微信端也能独立的识别远程或者静态图片码,而不需要调用uni.scan官方自带的接口。同样微信和web图片识别都是只能单码识别 +## 1.1.0(2024-12-18) +* 新增属性flash默认是否开启闪光灯.后续如果需要动态打开 和 关闭闪光请使用ref方法:setFlashModel(boolean) +## 1.0.9(2024-09-12) +* 优化和修改了核心识别,调整了安卓识别页面兼容华为部分机型. +## 1.0.8(2024-08-31) +* 新增ref函数chooseImage,相册选取识别 +## 1.0.7(2024-08-11) +* 优化改善识别速率,提高安卓兼容低版本性。优化ios。 +* 现在安卓和ios允许任意尺寸嵌入页面识别了。 +## 1.0.6(2024-07-30) +升级支持ios扫码功能,ios最低为ios12+ +升级支持H5(手机端)/WEB(带摄像头的win电脑及mac电脑) +## 1.0.5(2024-05-4) +* 升级后,原先的api跳转界面已经没有了,因为改成嵌入页面扫码,布局更为方便,可以自行任意装饰和布局。 +## 1.0.4(2024-01-27) +1. 预览区域调整缩小一点, +2. 捕捉的图像再次放小一点。 +3. 扫描速率调整到500ms +如果你是有特定机器上有问题,请自己通过修改uts源码调整上面的这些参数,将影响识别速度,精准度,捕捉位置优化等可以自己通过源码调整。 +## 1.0.3(2024-01-26) +修改焦距为持续视频对焦模式,并拉近焦距(相当于视野变小了,之前是宽视野可以同时识别出10几个码,但现实中没必要这样,因此根据其它的应用参考,应该拉近点焦距)。 +对焦点识别的位置进行了优化比对,识别时位置更准,但不能保证非常准确。比如手机识别慢100ms左右,你手抖了下,可能位置是前100ms的位置 +会造成识别的位置和预览图可能有点区别。但经过持续的测试,红米note11 pro ,2年前的手机,基本很少出现对焦识别失准的情况。 +我把识别速度调整为1秒识别一次,对低端机可能更好。如果想识别非常的迅速可以调低这个值,比如100ms,基本一对准就识别了,精准度非常高。 +识别的震动改为了80ms,之前是200ms,感觉过长。 +识别成功后增加了黑色遮罩。 +另外识别程序放在了子线程中执行了,防止偶尔的卡钝。 + +**特别提醒,网友测试如果你是开发模式部分手机可能会比较卡,原因不明,但打包后的程序是非常流畅无比的** +## 1.0.2(2024-01-25) +1. 增加了识别成功后,短震动提示 +2. 识别多点后,给提示点增加了动画缩放指示提醒用户点按识别点。 +## 1.0.1(2024-01-24) +增加返回按钮事件 +## 1.0.0(2024-01-24) +首次发布 diff --git a/uni_modules/x-mlkit-scannig-u/package.json b/uni_modules/x-mlkit-scannig-u/package.json new file mode 100644 index 0000000..e85b320 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/package.json @@ -0,0 +1,90 @@ +{ + "id": "x-mlkit-scannig-u", + "displayName": "tmui4.0 UTS原生二维码扫一扫 机器学习", + "version": "1.1.0", + "description": "机器学习识别码库,它是tmui4.0附属插件,可实时识别多码,速度快,效率不错,精准度也不错", + "keywords": [ + "扫码", + "机器学习", + "二维码", + "扫一扫" +], + "repository": "", + "engines": { + "HBuilderX": "^3.99" + }, + "dcloudext": { + "type": "component-uts", + "sale": { + "regular": { + "price": "99.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "369986563" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "n" + }, + "client": { + "Vue": { + "vue2": "n", + "vue3": "y" + }, + "App": { + "app-android": { + "minVersion": "29" + }, + "app-ios": { + "minVersion": "12" + }, + "app-harmony": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "n", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/readme.md b/uni_modules/x-mlkit-scannig-u/readme.md new file mode 100644 index 0000000..d3e6331 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/readme.md @@ -0,0 +1,98 @@ +# x-mlkit-scannig-u +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +### 功能特色 + +1. ios,安卓是Ai模型识别速度非常快,大概ios:50-100ms,安卓:200-350ms +2. web/h5带摄像头,实时识别时,效率比较低,识别精度不高,要多对几次 +3. web/微信图片识别时,精度中上。(不依赖微信官方,也不依赖Uniapp官方纯像素插件识别),不要图片了好多码,识别不准,如果码是黑色,多码能识别一个 +如果多码是非黑色,可能识别不出来 +4. 嵌入式页面识别,方便自己布局和装饰扫码界面。 +5. 微信,web只能是单码识别,多码一起识别不精准 + +**嵌入式相机识别在微信端:微信官方的本身这个组件就有很多问题,如果遇到没有扫码结果,请自行向微信官方提问,不需要问我,我的xs max就没有任何响应,但安卓有** +**最主要的更新是兼容了微信,并支持微信自定图片识别,这样可以不用打开微信自带的界面再选择图片识别,给了大家商用非常好的便利** +**web,微信图片识别时,请注意图片的干净,尽量不要多码放一起,一图一码,识别精准度还是好的** + +### 兼容性 + +| IOS | Andriod | WEB | 小程序 | +| --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | + +### 使用 + +如果是安卓请务必打自定义基座,如果ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。 + +```ts + +// 添加组件 + + + + +export default { + data() { + return { + result:[] as string[], + apiStr:"" + }; + }, + methods: { + saningEvent(str:string[]){ + // #ifdef APP-ANDROID||WEB||MP + + this.result = str as string[]; + // #endif + // #ifdef APP-IOS + + let resultstr = uni.getStorageSync("xMlKITScaning") + if(resultstr!=null){ + let result = JSON.parseArray(resultstr as string) + this.result = result + } + + // #endif + }, + onclickQr(str:string){ + // #ifdef APP-ANDROID||WEB||MP + uni.showModal({ + title:"提醒", + content:str, + showCancel:false + }) + // #endif + // #ifdef APP-IOS + let resultstr = uni.getStorageSync("xMlKITScaningClick") + uni.showModal({ + title:"提醒", + content:resultstr, + showCancel:false + }) + // #endif + }, + openCamera(){ + let el = (this.$refs['XscanU'] as XMlkitScannigUElement) + el.openCamera() + }, + //通过相册选取图片识别. + choose(){ + let el = (this.$refs['XscanU'] as XMlkitScannigUElement) + el.chooseImage() + }, + closeCamera(){ + let el = (this.$refs['XscanU'] as XMlkitScannigUElement) + el.closeCamera() + } + }, + +} + +``` \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..8ab1244 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/camera - 副本 (2).uts b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/camera - 副本 (2).uts new file mode 100644 index 0000000..b0fdd23 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/camera - 副本 (2).uts @@ -0,0 +1,821 @@ +import ListView from 'android.widget.ListView'; +import FrameLayout from 'android.widget.FrameLayout'; +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' +import Range from 'android.util.Range'; + +import Executor from 'java.util.concurrent.Executor' +import Looper from 'android.os.Looper' +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; + +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import OnImageAvailableListener from 'android.media.ImageReader.OnImageAvailableListener' + + +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import ViewGroup from 'android.view.ViewGroup'; + + +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner" +import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions" +import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning" +import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions" +import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback" +import Barcode from "com.google.mlkit.vision.barcode.common.Barcode" +import InputImage from "com.google.mlkit.vision.common.InputImage" +import xView from "./libview/view.uts" +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" +type buffoptsPlanesType = { + data : ByteBuffer, + getRowStride : number, + getPixelStride : number, +} +type buffoptsType = { + width : number, + height : number, + format : number, + rect : Rect, + planes : buffoptsPlanesType[], +} + +import { SCANNING_OPTIONS, CAMERA_PHOTO_SIZE, CallFunType, SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND } from "../interface.uts" +import { decoderUriPathToQr, decoderBuffToQr } from "./index.uts" + +type cameraListNameType = { id : string, device : CameraCharacteristics } + +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} + +export class xCamera { + parentView : FrameLayout; + // 相机区域视图 + cameraView : SurfaceView | null = null; + // 识别点的区域 + resultView : RelativeLayout | null = null; + + + viewBox_width = 0 + viewBox_height = 0 + + imgPointsBycanmarea = [] as RelativeLayout[] + + options = { + width: 800, + height: 800, + cameraDevice: 'BACK', + scanSpeedduration: 450, + scanningQrCode: true, + isSavePhoto: false, + qrCodeType: null, + vibatar: true, + zoom: 3, + continuousScan: false + } as SCANNING_OPTIONS + + /** 手动震动服务 */ + vibrator = null as null | Vibrator + context : Context; + // 相机旋转的角度。 + cameraRate = new Map([ + [Surface.ROTATION_0, 0], + [Surface.ROTATION_90, 0], + [Surface.ROTATION_180, 0], + [Surface.ROTATION_270, 0] + ]) + // 相机服务 + cameraService : CameraManager + // 相机列表,name,id + cameraListName = new Map(); + // + cameraPreviewSize = { width: 800, height: 800 } as CAMERA_PHOTO_SIZE + // 当前预览的什么是设备 + cameraDevice : CameraDevice | null = null + cameraDeviceCaptureSession : CameraCaptureSession | null = null + sufaceHolderView : Surface | null = null + // 当前是否在解析码制中。 + isDecoderQring = false + // 当前相机是否正在预览中。 + isOpeningCameraing = false; + + callFunEvent : CallFunType = (str : string[], type : 'auto' | 'click') => { } + + // 临时存放的识别成功的结果,防止重复扫码。 + tempresultList = [] as string[]; + + isAppPause = false + + constructor(GroupView : FrameLayout, options : SCANNING_OPTIONS | null = null) { + this.context = UTSAndroid.getAppContext()! as Context; + this.parentView = GroupView; + if (options != null) { + this.options = { + width: options.width, + height: options.height, + cameraDevice: options.cameraDevice, + scanSpeedduration: options.scanSpeedduration == null ? this.options.scanSpeedduration : options.scanSpeedduration, + scanningQrCode: options.scanningQrCode == null ? this.options.scanningQrCode : options.scanningQrCode, + isSavePhoto: options.isSavePhoto == null ? this.options.isSavePhoto : options.isSavePhoto, + qrCodeType: options.qrCodeType == null ? this.options.qrCodeType : options.qrCodeType, + vibatar: options.vibatar == null ? this.options.vibatar : options.vibatar, + zoom: options.zoom == null ? this.options.zoom : options.zoom, + continuousScan: options.continuousScan == null ? this.options.continuousScan : options.continuousScan + } as SCANNING_OPTIONS; + } + this.cameraService = this.context!.getSystemService(Context.CAMERA_SERVICE) as CameraManager + this.vibrator = this.context!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + this._createCameraView() + this._creatCameraResultView() + } + //震动手机 + setVibatar() { + if (this.vibrator == null) return + // 检查设备是否支持震动 + if (this.vibrator!.hasVibrator()) { + // 触发短暂的震动,持续时间为200毫秒 + this.vibrator!.vibrate(80); + } + } + /** 创建相机预览区域 */ + private _createCameraView() { + let sv = new SurfaceView(this.context) + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + + this.parentView.addView(this.cameraView!) + } + // 创建一个动画层容器 + private _creatCameraResultView() { + let t = this; + let resultView = new RelativeLayout(this.context) + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + resultView.setLayoutParams(layaout) + // resultView.setBackgroundColor(Color.argb(30,255,0,0)) + this.resultView = resultView; + this.parentView.addView(this.resultView!) + + //监听尺寸变化。 + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.viewBox_width = right - left; + t.viewBox_height = bottom - top; + + + // t.parentView!.removeOnLayoutChangeListener(this); + } + } + this.parentView!.addOnLayoutChangeListener(new previewChangeRectadd()) + + + } + openCamera() : Promise { + let _this = this; + if (this.isOpeningCameraing) { + this.closeCamera() + } + return new Promise((res, rej) => { + _this.checkPermissions() + .then((res : boolean) => { + if (!res) { + uni.showToast({ title: "未授权相机使用权", icon: "none" }) + return; + } + try { + _this.getCamreaListName() + _this.getCamreaDeviceSizeList() + _this.setCamreaSize() + _this._openCamera(); + _this.setCamreaFocalLength(1) + _this.addListenApp() + } catch (e) { + //TODO handle the exception + } + res(true) + }) + .catch(() => { + uni.showToast({ title: "未授权相机使用权", icon: "none" }) + rej(false) + }) + }) + + } + + addListenApp() { + let t = this; + let listener : (() => void) | null = null; + listener = () => { + t.isAppPause = true; + // console.log(UTSAndroid.getDispatcher()) + if (t.isOpeningCameraing) { + t.pauseCamera() + } + if (listener != null) { + UTSAndroid.offAppActivityPause(listener!); + } + } + UTSAndroid.onAppActivityPause(listener); + + let listener2 : (() => void) | null = null; + listener2 = () => { + t.isAppPause = false + if (t.isOpeningCameraing) { + t.openCamera() + } + if (listener2 != null) { + UTSAndroid.offAppActivityResume(listener2!); + } + + } + UTSAndroid.onAppActivityResume(listener2); + + } + pauseCamera() { + this.sufaceHolderView?.release() + this.cameraDeviceCaptureSession?.close() + this.cameraDevice?.close() + this.cameraDevice = null; + this.cameraDeviceCaptureSession = null; + this.sufaceHolderView = null; + } + closeCamera() { + this.sufaceHolderView?.release() + this.cameraDeviceCaptureSession?.close() + this.cameraDevice?.close() + this.cameraDevice = null; + this.cameraDeviceCaptureSession = null; + this.isOpeningCameraing = false; + this.sufaceHolderView = null; + for (let i = 0; i < this.imgPointsBycanmarea.length; i++) { + this.resultView?.removeView(this.imgPointsBycanmarea[i]) + } + + + } + private _openCamera() { + let _this = this; + if (this.cameraListName.size == 0) return; + let camreaNow = this.cameraListName.get(this.options.cameraDevice); + if (camreaNow == null) return; + class CamerCallTstasBack implements StateCallback { + constructor() { + + } + override onOpened(camera : CameraDevice) : void { + console.log('打开成功') + _this.cameraDevice = camera + _this.createCameraPreviewSession() + + } + override onDisconnected(camera : CameraDevice) : void { + console.log('连接失败') + _this.cameraDevice?.close() + _this.cameraDevice = null + } + override onError(camera : CameraDevice, error : Int) : void { + console.log('出错') + _this.cameraDevice?.close() + _this.cameraDevice = null + } + override onClosed(camera : CameraDevice) : void { + console.log('关闭') + _this.cameraDevice?.close() + _this.cameraDevice = null + } + + } + this.cameraService.openCamera(camreaNow.id! as string, new CamerCallTstasBack(), null); + } + + /** + * 检查相机权限 + */ + checkPermissions() : Promise { + let permissionCheck = ["android.permission.CAMERA"] + let _this = this; + // 请求拍照权限 + return new Promise(res => { + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + // _this.cameraPermissioPass = true + res(true) + } else { + console.log("当前不具备指定权限") + // 请求拍照权限 + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (allRight : boolean, _ : string[]) { + // _this.cameraPermissioPass = allRight + res(true) + }, function (_ : boolean, _ : string[]) { + //用户拒绝了部分权限 + // _this.cameraPermissioPass = false + res(false) + }) + } + }) + } + + /** + * 获取相机设备列表 + */ + getCamreaListName(deviceName : 'FRONT' | 'BACK' | null = null) { + // 前置还是后置。 + let deviceLens = CameraCharacteristics.LENS_FACING_BACK; + let dname = this.options.cameraDevice + if (deviceName != null) { + dname = deviceName! + } + if (dname == 'FRONT') { + deviceLens = CameraCharacteristics.LENS_FACING_FRONT; + } + if (dname == 'BACK') { + deviceLens = CameraCharacteristics.LENS_FACING_BACK; + } + this.cameraListName.clear() + + + for (caIds in this.cameraService.getCameraIdList()) { + let ps = this.cameraService.getCameraCharacteristics(caIds as string); + let facing = ps.get(CameraCharacteristics.LENS_FACING); + if (facing == CameraCharacteristics.LENS_FACING_FRONT) { + this.cameraListName.set('FRONT', { id: caIds as string, device: ps } as cameraListNameType) + } + if (facing == CameraCharacteristics.LENS_FACING_BACK) { + this.cameraListName.set('BACK', { id: caIds as string, device: ps } as cameraListNameType) + } + } + + this.setCamreaSize(); + } + /** + * 获取相机设备尺寸列表 + * 调用此函数的前提是要先获取设备列表,要先调用getCamreaListName函数 + */ + getCamreaDeviceSizeList() : CAMERA_PHOTO_SIZE[] { + let sizelist = [] as CAMERA_PHOTO_SIZE[] + if (this.cameraListName.size == 0) { + console.error("请先调用getCamreaListName获取设备列表") + return sizelist; + } + let camrea = this.cameraListName.get(this.options.cameraDevice) as cameraListNameType; + if (camrea != null) { + let maps = camrea!.device!.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) as StreamConfigurationMap + if (maps != null) { + + let testSize = maps!.getOutputSizes(ImageFormat.JPEG) + for (sz in testSize) { + let w = sz.getWidth() + let h = sz.getHeight() + sizelist.push({ width: w, height: h } as CAMERA_PHOTO_SIZE) + } + + } + } + return sizelist; + } + /** + * 设置相机焦距 + * 0-1之间。 + * 暂未实现。 + */ + setCamreaFocalLength(focal : number) { + + if (this.cameraListName.size == 0) { + console.error("请先调用getCamreaListName获取设备列表") + return + } + let camrea = this.cameraListName.get(this.options.cameraDevice) as cameraListNameType; + + if (camrea != null) { + let zoomMax = camrea!.device!.get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE) + let nowZoom = camrea!.device!.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE) + + } + } + /** + * 设置相机前置还是后置,设置后需要重新打开相机。 + * BACK 后置 + * FRONT 前置 + */ + setCamreaDevice(name : 'FRONT' | 'BACK') { + this.options.cameraDevice = name; + } + /** + * 设置相机摄像尺寸,通过options中的width,height来匹配设置 + * 返回的不一定是真实的options中的宽高,只是与其相近的值。 + * 以设置后要重新打开。相机生效。 + * 返回相机生效的尺寸 + */ + setCamreaSize(width : number | null = null, height : number | null = null) : CAMERA_PHOTO_SIZE { + // 宽高列表 + const dimensions = this.getCamreaDeviceSizeList() + // 目标宽高 + const targetWidth = width != null ? width! : this.options.width; + const targetHeight = height != null ? height! : this.options.height; + const targetRatio = targetWidth / targetHeight; + // 找到最接近目标比例的宽高值 + const closestDimension = dimensions.reduce((prev : CAMERA_PHOTO_SIZE, curr : CAMERA_PHOTO_SIZE) : CAMERA_PHOTO_SIZE => { + const currRatio = curr.width / curr.height; + const prevRatio = prev.width / prev.height; + const currDiffRatio = Math.abs(currRatio - targetRatio); + const prevDiffRatio = Math.abs(prevRatio - targetRatio); + + // 计算宽高值与目标值的差的平方和 + const currDiffValue = Math.pow(curr.width - targetWidth, 2) + Math.pow(curr.height - targetHeight, 2); + const prevDiffValue = Math.pow(prev.width - targetWidth, 2) + Math.pow(prev.height - targetHeight, 2); + + // 给比例差和值差赋予不同的权重,这里假设两者权重相同 + const currTotalDiff = currDiffRatio + currDiffValue; + const prevTotalDiff = prevDiffRatio + prevDiffValue; + + return currTotalDiff < prevTotalDiff ? curr : prev; + }, dimensions[0]); + this.cameraPreviewSize = closestDimension + + return closestDimension; + } + + // 获取当前相机的旋转角度。 + getCamraRotation() : Number { + let sensorOrientation = 0 + let tempra = 0 + if (this.cameraListName.size == 0) return sensorOrientation; + let camreaNow = this.cameraListName.get(this.options.cameraDevice); + if (camreaNow == null) return sensorOrientation; + + let windowManager = UTSAndroid.getUniActivity()!.getWindowManager() as WindowManager + + let deviceRotation = windowManager!.getDefaultDisplay().getRotation() + let rotationCompensation = this.cameraRate.get(deviceRotation) as number + + tempra = camreaNow.device.get(CameraCharacteristics.SENSOR_ORIENTATION)!! as number + + if (this.options.cameraDevice == 'FRONT') { + tempra = ((tempra + rotationCompensation) % 360) + } else { + tempra = ((tempra - rotationCompensation + 360) % 360) + } + return tempra + } + + // 设置识别成功的回调函数 + setCallEvent(call : CallFunType) { + this.callFunEvent = call; + } + + // 创建视频预览流。 + private createCameraPreviewSession() { + if (this.cameraView == null) return; + + // 设置预览区域 + let previewAspectRatio = this.cameraPreviewSize.width / this.cameraPreviewSize.height; + let layoutWidth = this.viewBox_width + let layoutHeight = this.viewBox_height + let layoutAspectRatio = layoutWidth / layoutHeight; + + + let holder = this.cameraView!.getHolder() + let suface = holder!.getSurface(); + this.sufaceHolderView = suface + + if (this.cameraDevice == null) return; + let t = this; + let previewRequestBuilder = this.cameraDevice!.createCaptureRequest(CameraDevice.PREVIEW) + previewRequestBuilder?.addTarget(suface) + + let totalWidth = this.cameraPreviewSize.width + let totalHeight = this.cameraPreviewSize.height + + + // 再添加一个image来预览 + let minh = Math.min(this.options.width, this.options.height) + let reader = ImageReader.newInstance(minh.toInt(), minh.toInt(), ImageFormat.YUV_420_888, 1) + previewRequestBuilder?.addTarget(reader.getSurface()) + let outsufaces = [suface, reader.getSurface()] as Surface[] + + + class sessionCallback extends CameraCaptureSession.StateCallback { + constructor() { } + override onConfigured(session : CameraCaptureSession) { + t.cameraDeviceCaptureSession = session + t.isOpeningCameraing = true; + try { + t.cameraDeviceCaptureSession?.setRepeatingRequest(previewRequestBuilder.build(), null, null) + } catch (e) { + console.log("Failed to start camera preview session.", e) + } + } + override onConfigureFailed(session : CameraCaptureSession) { + + } + override onClosed(session : CameraCaptureSession) { + t.closeCamera() + } + override onSurfacePrepared(session : CameraCaptureSession, testSuface : Surface) { + + } + + } + + reader.setOnImageAvailableListener(this.createCameraImageRenderLisen() as OnImageAvailableListener, null) + this.cameraDevice!.createCaptureSession(outsufaces, new sessionCallback(), null) + + + } + + private createCameraImageRenderLisen() : any { + let t = this; + class imageReaderCallback extends ImageReader.OnImageAvailableListener { + private currentImage = null as Image | null; + override onImageAvailable(irader : ImageReader) { + if (this.currentImage != null) { + this.currentImage!.close(); // 先关闭上一帧的Image + } + let curimage = irader.acquireNextImage(); + + @Suppress("DEPRECATION") + class IntentRunable extends Runnable { + override run() { + if (t.isDecoderQring || !t.isOpeningCameraing || t.isAppPause) return; + try { + t.qrDecoder(curimage!) + } catch (e) { + t.closeCamera() + console.error('应用异常:', e) + } + } + } + this.currentImage = curimage + if (this.currentImage != null) { + new Thread(new IntentRunable()).start() + } + + } + } + + return new imageReaderCallback() + } + + // 设置图片上的小圆的识别位置。 + setImageViewRusletBox(width : number, height : number, realWidth : number, realHeight : number, jieguo : SCANNING_PHOTO_RESULT) { + let t = this; + let wRatio = t.viewBox_width / realWidth; + let hRatio = t.viewBox_height / realHeight; + let btnwidth = 120; + let zoom = 10 - this.options.zoom! + + for (let i = 0; i < jieguo.bounds.length; i++) { + let item = jieguo.bounds[i]; + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + + let x = wRatio * item.centerX + let y = hRatio * item.centerY + + layoutParams.topMargin = (y - 60).toInt() // 设置顶部边距 + layoutParams.leftMargin = (x - 60).toInt() // 设置左边距 + let relativeLayout = new RelativeLayout(t.context) + relativeLayout.layoutParams = layoutParams + + const rtxt = jieguo.text[i] + let v = new xView(t.context) + v.setSize(120, 120) + .setRadius(100) + .setBackgroundColor('#21d429') + .setBorder(12, "#ffffff", false) + .setClick((event : MotionEvent) => { + try { + t.callFunEvent([rtxt], 'click') + } catch (e) { + //TODO handle the exception + } + }) + let ov = v.getView(); + + + // 创建缩放动画 + let scaleAnimation = new ScaleAnimation(1.0.toFloat(), 0.7.toFloat(), 1.0.toFloat(), 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat()); + scaleAnimation.setDuration(600); // 设置动画持续时间 + scaleAnimation.setRepeatMode(Animation.REVERSE); // 设置重复模式为反向 + scaleAnimation.setRepeatCount(Animation.INFINITE); // 设置重复次数为无限 + // 启动动画 + ov.startAnimation(scaleAnimation); + + relativeLayout.addView(ov) + + this.imgPointsBycanmarea.push(relativeLayout) + this.resultView!.addView(relativeLayout) + } + + + } + private YUV_420_888toNV21(opts : buffoptsType) : ByteArray { + + let crop = opts.rect; + let format = opts.format; + let width = crop.width(); + let height = crop.height(); + let planes = opts.planes!; + let data = new ByteArray((width * height * ImageFormat.getBitsPerPixel(format.toInt()) / 8).toInt()); + let rowData = new ByteArray((planes[0].getRowStride).toInt()); + let channelOffset = 0; + let outputStride = 1; + for (let i = 0; i < planes.length; i++) { + switch (i) { + case 0: + channelOffset = 0; + outputStride = 1; + break; + case 1: + channelOffset = width * height; + outputStride = 1; + break; + case 2: + channelOffset = width * height * 1.25; + outputStride = 1; + break; + } + let buffer = planes[i.toInt()].data!; + let rowStride = planes[i.toInt()].getRowStride; + let pixelStride = planes[i.toInt()].getPixelStride; + + let shift = (i == 0) ? 0 : 1; + let w = width >> shift; + let h = height >> shift; + buffer.position((rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift)).toInt()); + for (let row = 0; row < h; row++) { + let length = 0; + if (pixelStride == 1 && outputStride == 1) { + length = w; + buffer.get(data, channelOffset.toInt(), length.toInt()); + channelOffset += length; + } else { + length = (w - 1) * pixelStride + 1; + buffer.get(rowData, 0, length.toInt()); + for (let col = 0; col < w; col++) { + data[channelOffset.toInt()] = rowData[(col * pixelStride).toInt()]; + channelOffset += outputStride; + } + } + if (row < h - 1) { + buffer.position((buffer.position() + rowStride - length).toInt()); + } + } + } + return data; + } + + private qrDecoder(image : Image) { + let t = this; + if (!this.isDecoderQring && !this.isAppPause) { + this.isDecoderQring = true; + + let width = image.getWidth(); + let height = image.getHeight(); + let frameSize = width * height; + let qFrameSize = frameSize / 4; + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + + let yBufferCopy = [] as ByteArray[] + let yrurvrNumber = [] as number[] + + let yr = planes[0] + let ur = planes[1] + let vr = planes[2] + let oraingMax = yr.getBuffer().limit() + + for (let i = 0; i < 3; i++) { + let buffer = planes[i.toInt()].getBuffer(); + yBufferCopy.push(new ByteArray(buffer.remaining().toInt())) + buffer.get(yBufferCopy[i.toInt()]); + } + let y = ByteBuffer.wrap(yBufferCopy[0]!) + let u = ByteBuffer.wrap(yBufferCopy[1]!) + let v = ByteBuffer.wrap(yBufferCopy[2]!) + + let opts = { + width, + height, + format: image.getFormat(), + rect: image.getCropRect(), + planes: [ + { + data: y, + getRowStride: yr.getRowStride(), + getPixelStride: yr.getPixelStride(), + }, + { + data: u, + getRowStride: ur.getRowStride(), + getPixelStride: ur.getPixelStride(), + }, + { + data: v, + getRowStride: vr.getRowStride(), + getPixelStride: vr.getPixelStride(), + } + ] as buffoptsPlanesType[] + } as buffoptsType + + decoderBuffToQr(this.YUV_420_888toNV21(opts), width, height, this.getCamraRotation()) + .then((res) => { + + if (res != null && t.isOpeningCameraing && !t.isAppPause) { + let texts = res.text as string[] + if (texts.length > 0) { + // texts.some((el:string):boolean=>t.tempresultList.includes(el)) + + if (t.options.vibatar == true) { + t.setVibatar() + } + if (t.options.continuousScan == false) { + t.closeCamera() + } + t.callFunEvent(texts, 'auto') + t.setImageViewRusletBox(t.options.width, t.options.height, width, height, res as SCANNING_PHOTO_RESULT) + } + t.isDecoderQring = false + } else { + t.isDecoderQring = false + } + // image.close(); + }) + .catch(() => { + // this.imageUrl = null + }) + // setTimeout(function () { + // t.isDecoderQring = false + // }, t.options!.scanSpeedduration!); + // image.close(); + } + image.close(); + } + + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/camera.uts b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/camera.uts new file mode 100644 index 0000000..d4d215e --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/camera.uts @@ -0,0 +1,648 @@ +import ListView from 'android.widget.ListView'; +import FrameLayout from 'android.widget.FrameLayout'; +import CameraManager from 'android.hardware.camera2.CameraManager' +import CameraDevice from 'android.hardware.camera2.CameraDevice' +import StateCallback from 'android.hardware.camera2.CameraDevice.StateCallback' +import CameraCaptureSession from 'android.hardware.camera2.CameraCaptureSession' + +import CaptureRequest from 'android.hardware.camera2.CaptureRequest' +import TotalCaptureResult from 'android.hardware.camera2.TotalCaptureResult' +import StreamConfigurationMap from 'android.hardware.camera2.params.StreamConfigurationMap' +import MeteringRectangle from 'android.hardware.camera2.params.MeteringRectangle' +import OutputConfiguration from 'android.hardware.camera2.params.OutputConfiguration' +import SessionConfiguration from 'android.hardware.camera2.params.SessionConfiguration' +import CameraCharacteristics from 'android.hardware.camera2.CameraCharacteristics' +import CameraMetadata from 'android.hardware.camera2.CameraMetadata' +import Range from 'android.util.Range'; + +import Executor from 'java.util.concurrent.Executor' +import Looper from 'android.os.Looper' +import ImageFormat from 'android.graphics.ImageFormat' +import Size from 'android.util.Size' +import SurfaceTexture from 'android.graphics.SurfaceTexture' +import Handler from 'android.os.Handler' +import Surface from 'android.view.Surface' +import Image from 'android.media.Image' +import LinearLayout from 'android.widget.LinearLayout'; +import Intent from 'android.content.Intent'; +import Integer from 'java.lang.Integer'; +import ByteOrder from 'java.nio.ByteOrder'; + +import SurfaceHolder from 'android.view.SurfaceHolder' +import SurfaceView from 'android.view.SurfaceView' +import TextureView from 'android.view.TextureView' +import View from 'android.view.View' +import Context from 'android.content.Context' +import Manifest from "android.Manifest"; +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import System from 'java.lang.System' +import Activity from 'android.app.Activity'; +import Bundle from 'android.os.Bundle'; +import Intent from 'android.content.Intent'; +import IntentFilter from 'android.content.IntentFilter'; + +import Rect from 'android.graphics.Rect'; +import Matrix from 'android.graphics.Matrix' +import ImageReader from 'android.media.ImageReader' +import OnImageAvailableListener from 'android.media.ImageReader.OnImageAvailableListener' + + +import ByteBuffer from 'java.nio.ByteBuffer' +import MediaStore from 'android.provider.MediaStore' +import Plane from 'android.media.Image.Plane' +import Bitmap from "android.graphics.Bitmap" +import BitmapFactory from "android.graphics.BitmapFactory" +import Vibrator from "android.os.Vibrator" +import Animation from "android.view.animation.Animation" +import ScaleAnimation from "android.view.animation.ScaleAnimation" +import AnimationUtils from "android.view.animation.AnimationUtils" + + +import Color from "android.graphics.Color" +import Window from "android.view.Window" +import WindowManager from "android.view.WindowManager" +import TextView from "android.widget.TextView" +import RelativeLayout from "android.widget.RelativeLayout" +import ImageView from "android.widget.ImageView" +import HandlerThread from 'android.os.HandlerThread' +import YuvImage from 'android.graphics.YuvImage' +import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream' +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import ViewGroup from 'android.view.ViewGroup'; + + +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner" +import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions" +import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning" +import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions" +import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback" +import Barcode from "com.google.mlkit.vision.barcode.common.Barcode" +import InputImage from "com.google.mlkit.vision.common.InputImage" +import xView from "./libview/view.uts" +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" + +// x +import ProcessCameraProvider from "androidx.camera.lifecycle.ProcessCameraProvider" +import PreviewView from "androidx.camera.view.PreviewView" +import CameraController from "androidx.camera.view.CameraController" +import CameraSelector from "androidx.camera.core.CameraSelector" +import Preview from 'androidx.camera.core.Preview' +import Camera from 'androidx.camera.core.Camera' +import LifecycleObserver from "androidx.lifecycle.LifecycleObserver" +import LifecycleOwner from "androidx.lifecycle.LifecycleOwner" +import OnLifecycleEvent from "androidx.lifecycle.OnLifecycleEvent" +import ImageAnalysis from 'androidx.camera.core.ImageAnalysis' +import ImageProxy from 'androidx.camera.core.ImageProxy' +import NonNull from 'androidx.annotation.NonNull' +import ExecutorService from 'java.util.concurrent.ExecutorService' +import Executors from 'java.util.concurrent.Executors' +// import TargetResolution from 'androidx.camera.core.ImageAnalysis.TargetResolution' + +type buffoptsPlanesType = { + data : ByteBuffer, + getRowStride : number, + getPixelStride : number, +} +type buffoptsType = { + width : number, + height : number, + format : number, + rect : Rect, + planes : buffoptsPlanesType[], +} + +import { SCANNING_OPTIONS, CAMERA_PHOTO_SIZE, CallFunType, SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND } from "../interface.uts" +import { decoderUriPathToQr, decoderBuffToQr } from "./index.uts" +import ContextCompat from 'androidx.core.content.ContextCompat'; + +type cameraListNameType = { id : string, device : CameraCharacteristics } + +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} + +export class xCamera { + parentView : FrameLayout; + + // 识别点的区域 + resultView : RelativeLayout | null = null; + + + viewBox_width = 0 + viewBox_height = 0 + + imgPointsBycanmarea = [] as RelativeLayout[] + + options = { + width: 800, + height: 800, + cameraDevice: 'BACK', + scanSpeedduration: 450, + scanningQrCode: true, + isSavePhoto: false, + qrCodeType: null, + vibatar: true, + zoom: 3, + continuousScan: false + } as SCANNING_OPTIONS + + /** 手动震动服务 */ + vibrator = null as null | Vibrator + context : Context; + // 相机旋转的角度。 + cameraRate = new Map([ + [Surface.ROTATION_0, 0], + [Surface.ROTATION_90, 0], + [Surface.ROTATION_180, 0], + [Surface.ROTATION_270, 0] + ]) + // 相机服务 + cameraService : CameraManager + // 相机列表,name,id + cameraListName = new Map(); + // + cameraPreviewSize = { width: 800, height: 800 } as CAMERA_PHOTO_SIZE + // 当前预览的什么是设备 + cameraDevice : CameraDevice | null = null + cameraDeviceCaptureSession : CameraCaptureSession | null = null + sufaceHolderView : Surface | null = null + + // 相机区域视图 + cameraView : PreviewView | null = null; + cameraProvider : ProcessCameraProvider | null = null + camera : Camera | null = null; + cameraPreview : Preview | null = null; + + + // 当前是否在解析码制中。 + isDecoderQring = false + // 当前相机是否正在预览中。 + isOpeningCameraing = false; + + callFunEvent : CallFunType = (str : string[], type : 'auto' | 'click') => { } + + // 临时存放的识别成功的结果,防止重复扫码。 + tempresultList = [] as string[]; + + isAppPause = false + + flashMode = false; + + constructor(GroupView : FrameLayout, options : SCANNING_OPTIONS | null = null) { + this.context = UTSAndroid.getAppContext()! as Context; + this.parentView = GroupView; + if (options != null) { + this.options = { + width: options.width, + height: options.height, + cameraDevice: options.cameraDevice, + scanSpeedduration: options.scanSpeedduration == null ? this.options.scanSpeedduration : options.scanSpeedduration, + scanningQrCode: options.scanningQrCode == null ? this.options.scanningQrCode : options.scanningQrCode, + isSavePhoto: options.isSavePhoto == null ? this.options.isSavePhoto : options.isSavePhoto, + qrCodeType: options.qrCodeType == null ? this.options.qrCodeType : options.qrCodeType, + vibatar: options.vibatar == null ? this.options.vibatar : options.vibatar, + zoom: options.zoom == null ? this.options.zoom : options.zoom, + continuousScan: options.continuousScan == null ? this.options.continuousScan : options.continuousScan + } as SCANNING_OPTIONS; + this.flashMode = options.flashMode + } + this.cameraService = this.context!.getSystemService(Context.CAMERA_SERVICE) as CameraManager + this.vibrator = this.context!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + this._createCameraView() + this._creatCameraResultView() + } + //震动手机 + setVibatar() { + if (this.vibrator == null) return + // 检查设备是否支持震动 + if (this.vibrator!.hasVibrator()) { + // 触发短暂的震动,持续时间为200毫秒 + this.vibrator!.vibrate(80); + } + } + /** 创建相机预览区域 */ + private _createCameraView() { + + let sv = new PreviewView(UTSAndroid.getAppContext()!) + sv.scaleType = PreviewView.ScaleType.FILL_CENTER + // 让相机的高和宽与组件对齐。 + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + sv.setLayoutParams(layaout) + this.cameraView = sv; + + this.parentView.addView(this.cameraView!) + } + // 创建一个动画层容器 + private _creatCameraResultView() { + let t = this; + let resultView = new RelativeLayout(this.context) + let layaout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + resultView.setLayoutParams(layaout) + // resultView.setBackgroundColor(Color.argb(30,255,0,0)) + this.resultView = resultView; + this.parentView.addView(this.resultView!) + + //监听尺寸变化。 + class previewChangeRectadd extends View.OnLayoutChangeListener { + override onLayoutChange(v : View, left : Int, top : Int, right : Int, bottom : Int, + oldLeft : Int, oldTop : Int, oldRight : Int, oldBottom : Int + ) { + t.viewBox_width = right - left; + t.viewBox_height = bottom - top; + } + } + this.parentView!.addOnLayoutChangeListener(new previewChangeRectadd()) + + + } + openCamera() : Promise { + let _this = this; + if (this.isOpeningCameraing) { + this.closeCamera() + } + + return new Promise((res, rej) => { + _this.checkPermissions() + .then((res : boolean) => { + if (!res) { + uni.showToast({ title: "未授权相机使用权", icon: "none" }) + return; + } + try { + _this._openCamera(); + + } catch (e) { + console.log(e) + //TODO handle the exception + } + res(true) + }) + .catch(() => { + uni.showToast({ title: "未授权相机使用权", icon: "none" }) + rej(false) + }) + }) + + } + // 设置识别成功的回调函数 + setCallEvent(call : CallFunType) { + this.callFunEvent = call; + } + getCamraRotation() : Number { + return 0 + } + setFlashModel(flash:boolean){ + + if(this.camera!=null&&this.isOpeningCameraing){ + let cameraControl = this.camera!.cameraControl! + cameraControl.enableTorch(flash) + } + } + + closeCamera() { + this.setFlashModel(false); + this.cameraProvider?.unbindAll() + this.cameraPreview?.setSurfaceProvider(null) + this.isOpeningCameraing = false; + + for (let i = 0; i < this.imgPointsBycanmarea.length; i++) { + this.resultView?.removeView(this.imgPointsBycanmarea[i]) + } + + + } + private _openCamera() { + let _this = this; + let cameraProviderFuture = ProcessCameraProvider.getInstance(this.context) + + class IntentRunable extends Runnable { + override run() { + let cameraProvider : ProcessCameraProvider = cameraProviderFuture.get() + let previewView = _this.cameraView! as PreviewView + let cameraSelector : CameraSelector = new CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + let preview : Preview = new Preview.Builder().build(); + + preview.setSurfaceProvider(previewView.getSurfaceProvider()) + + let imageAnalysis = new ImageAnalysis.Builder() + // .setTargetResolution(new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt())) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + class MyImageAnalyzer implements ImageAnalysis.Analyzer { + constructor() { + super() + } + override analyze(image : ImageProxy) { + _this.qrDecoder(image) + } + override getDefaultTargetResolution() : Size { + return new Size(_this.viewBox_width.toInt(), _this.viewBox_height.toInt()); + } + + } + let cameraExecutor = Executors.newSingleThreadExecutor(); + imageAnalysis.setAnalyzer(cameraExecutor, new MyImageAnalyzer()); + let camera : Camera = cameraProvider.bindToLifecycle( + UTSAndroid.getUniActivity()! as LifecycleOwner, cameraSelector, preview, imageAnalysis); + _this.camera = camera + _this.cameraPreview = preview + + _this.cameraProvider = cameraProvider + _this.isDecoderQring = false + _this.isOpeningCameraing = true + _this.setFlashModel(_this.flashMode) + + } + } + + cameraProviderFuture.addListener(new IntentRunable(), ContextCompat.getMainExecutor(this.context)) + } + + /** + * 检查相机权限 + */ + checkPermissions() : Promise { + let permissionCheck = ["android.permission.CAMERA"] + let _this = this; + // 请求拍照权限 + return new Promise(res => { + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, permissionCheck)) { + // _this.cameraPermissioPass = true + res(true) + } else { + console.log("当前不具备指定权限") + // 请求拍照权限 + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionCheck, function (allRight : boolean, _ : string[]) { + // _this.cameraPermissioPass = allRight + res(true) + }, function (_ : boolean, _ : string[]) { + //用户拒绝了部分权限 + // _this.cameraPermissioPass = false + res(false) + }) + } + }) + } + + + // 设置图片上的小圆的识别位置。 + setImageViewRusletBox(width : number, height : number, realWidth : number, realHeight : number, jieguo : SCANNING_PHOTO_RESULT) { + let t = this; + let btnwidth = 100; + let btnwidth2 = 50; + + for (let i = 0; i < jieguo.bounds.length; i++) { + let item = jieguo.bounds[i]; + let layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + + let x = item.centerX + let y = item.centerY + + layoutParams.topMargin = (y - btnwidth2).toInt() // 设置顶部边距 + layoutParams.leftMargin = (x - btnwidth2).toInt() // 设置左边距 + let relativeLayout = new RelativeLayout(t.context) + relativeLayout.layoutParams = layoutParams + + const rtxt = jieguo.text[i] + let v = new xView(t.context) + v.setSize(btnwidth, btnwidth) + .setRadius(100) + .setBackgroundColor('#21d429') + .setBorder(12, "#ffffff", false) + .setClick((event : MotionEvent) => { + try { + t.callFunEvent([rtxt], 'click') + } catch (e) { + //TODO handle the exception + } + }) + let ov = v.getView(); + + + // 创建缩放动画 + let scaleAnimation = new ScaleAnimation(1.0.toFloat(), 0.7.toFloat(), 1.0.toFloat(), 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat(), Animation.RELATIVE_TO_SELF, 0.7.toFloat()); + scaleAnimation.setDuration(600); // 设置动画持续时间 + scaleAnimation.setRepeatMode(Animation.REVERSE); // 设置重复模式为反向 + scaleAnimation.setRepeatCount(Animation.INFINITE); // 设置重复次数为无限 + // 启动动画 + ov.startAnimation(scaleAnimation); + relativeLayout.addView(ov) + this.imgPointsBycanmarea.push(relativeLayout) + this.resultView!.addView(relativeLayout) + } + + + } + private YUV_420_888toNV21(opts : buffoptsType) : ByteArray { + + let crop = opts.rect; + let format = opts.format; + let width = crop.width(); + let height = crop.height(); + let planes = opts.planes!; + let data = new ByteArray((width * height * ImageFormat.getBitsPerPixel(format.toInt()) / 8).toInt()); + let rowData = new ByteArray((planes[0].getRowStride).toInt()); + let channelOffset = 0; + let outputStride = 1; + for (let i = 0; i < planes.length; i++) { + switch (i) { + case 0: + channelOffset = 0; + outputStride = 1; + break; + case 1: + channelOffset = width * height; + outputStride = 1; + break; + case 2: + channelOffset = width * height * 1.25; + outputStride = 1; + break; + } + let buffer = planes[i.toInt()].data!; + let rowStride = planes[i.toInt()].getRowStride; + let pixelStride = planes[i.toInt()].getPixelStride; + + let shift = (i == 0) ? 0 : 1; + let w = width >> shift; + let h = height >> shift; + buffer.position((rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift)).toInt()); + for (let row = 0; row < h; row++) { + let length = 0; + if (pixelStride == 1 && outputStride == 1) { + length = w; + buffer.get(data, channelOffset.toInt(), length.toInt()); + channelOffset += length; + } else { + length = (w - 1) * pixelStride + 1; + buffer.get(rowData, 0, length.toInt()); + for (let col = 0; col < w; col++) { + data[channelOffset.toInt()] = rowData[(col * pixelStride).toInt()]; + channelOffset += outputStride; + } + } + if (row < h - 1) { + buffer.position((buffer.position() + rowStride - length).toInt()); + } + } + } + return data; + } + + getCorrectionMatrix(imageProxy : ImageProxy, previewView : PreviewView) : Matrix { + let cropRect = imageProxy.cropRect + let rotationDegrees = imageProxy.imageInfo.rotationDegrees + let matrix = new Matrix() + + // A float array of the source vertices (crop rect) in clockwise order. + + let source = floatArrayOf(cropRect.left.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.top.toFloat(), + cropRect.right.toFloat(), + cropRect.bottom.toFloat(), + cropRect.left.toFloat(), + cropRect.bottom.toFloat()) + + let d0 = (0).toFloat() + // A float array of the destination vertices in clockwise order. + let destination = floatArrayOf(d0, + d0, + previewView.width.toFloat(), + d0, + previewView.width.toFloat(), + previewView.height.toFloat(), + d0, + previewView.height.toFloat()) + + // The destination vertexes need to be shifted based on rotation degrees. The + // rotation degree represents the clockwise rotation needed to correct the image. + + // Each vertex is represented by 2 float numbers in the vertices array. + let vertexSize = 2 + // The destination needs to be shifted 1 vertex for every 90° rotation. + let shiftOffset = rotationDegrees / 90 * vertexSize; + let tempArray = destination.clone() + for (toIndex in source.indices) { + let fromIndex = (toIndex + shiftOffset) % source.size + destination[toIndex] = tempArray[fromIndex.toInt()] + } + let success = matrix.setPolyToPoly(source, 0, destination, 0, 4) + + return matrix + } + private qrDecoder(img : ImageProxy) { + let t = this; + let image = img.getImage(); + + if (!this.isDecoderQring && image != null) { + this.isDecoderQring = true; + + let width = image.getWidth(); + let height = image.getHeight(); + let frameSize = width * height; + let qFrameSize = frameSize / 4; + // 获取各平面的数据与信息 + let planes = image.getPlanes(); + + let yBufferCopy = [] as ByteArray[] + let yrurvrNumber = [] as number[] + + let yr = planes[0] + let ur = planes[1] + let vr = planes[2] + let oraingMax = yr.getBuffer().limit() + + for (let i = 0; i < 3; i++) { + let buffer = planes[i.toInt()].getBuffer(); + yBufferCopy.push(new ByteArray(buffer.remaining().toInt())) + buffer.get(yBufferCopy[i.toInt()]); + } + let y = ByteBuffer.wrap(yBufferCopy[0]!) + let u = ByteBuffer.wrap(yBufferCopy[1]!) + let v = ByteBuffer.wrap(yBufferCopy[2]!) + + let opts = { + width, + height, + format: image.getFormat(), + rect: image.getCropRect(), + planes: [ + { + data: y, + getRowStride: yr.getRowStride(), + getPixelStride: yr.getPixelStride(), + }, + { + data: u, + getRowStride: ur.getRowStride(), + getPixelStride: ur.getPixelStride(), + }, + { + data: v, + getRowStride: vr.getRowStride(), + getPixelStride: vr.getPixelStride(), + } + ] as buffoptsPlanesType[] + } as buffoptsType + + decoderBuffToQr(this.YUV_420_888toNV21(opts), width, height,0) + .then((res) => { + + if (res != null && t.isOpeningCameraing) { + let matrix = t.getCorrectionMatrix(img, this.cameraView!) + let texts = res.text as string[] + if (texts.length > 0) { + // texts.some((el:string):boolean=>t.tempresultList.includes(el)) + + if (t.options.vibatar == true) { + t.setVibatar() + } + if (t.options.continuousScan == false) { + t.closeCamera() + } + let ruslt = res as SCANNING_PHOTO_RESULT; + for (let i = 0; i < ruslt.bounds.length; i++) { + let item = ruslt.bounds[i] + let ponit = floatArrayOf(item.centerX.toFloat(), item.centerY.toFloat()) + + matrix.mapPoints(ponit) + + item.centerX = ponit[0] + item.centerY = ponit[1] + + } + t.callFunEvent(texts, 'auto') + t.setImageViewRusletBox(t.options.width, t.options.height, width, height, ruslt) + } + t.isDecoderQring = false + } else { + t.isDecoderQring = false + } + // image.close(); + }) + .catch(() => { + // this.imageUrl = null + }) + // setTimeout(function () { + // t.isDecoderQring = false + // }, t.options!.scanSpeedduration!); + // image.close(); + } + img.close(); + } + + +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/config.json b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/config.json new file mode 100644 index 0000000..a4aafb8 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/config.json @@ -0,0 +1,12 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "com.google.mlkit:barcode-scanning:17.2.0", + "androidx.camera:camera-core:1.3.4", + "androidx.camera:camera-camera2:1.3.4", + "androidx.camera:camera-lifecycle:1.3.4", + "androidx.camera:camera-video:1.3.4", + "androidx.camera:camera-view:1.3.4", + "androidx.camera:camera-extensions:1.3.4" + ] +} diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/index.uts b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/index.uts new file mode 100644 index 0000000..549d0d7 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/index.uts @@ -0,0 +1,262 @@ +/** + * 引用 Android 系统库,示例如下: + * import { Context } from "android.content.Context"; + * [可选实现,按需引入] + */ + +/* 引入 interface.uts 文件中定义的变量 */ +import { SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND, SCANNING_PHOTO_RESULT_POS } from '../interface.uts'; + +/* 引入 unierror.uts 文件中定义的变量 */ + +import Context from 'android.content.Context' +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import Bitmap from "android.graphics.Bitmap" +import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner" +import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions" +import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning" +import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions" +import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback" +import Barcode from "com.google.mlkit.vision.barcode.common.Barcode" +import InputImage from "com.google.mlkit.vision.common.InputImage" + +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" +import ByteBuffer from 'java.nio.ByteBuffer' +import ImageFormat from 'android.graphics.ImageFormat' + +/** +* 从相册中选取图片进行解码 +* @public chooseImageDecodeQr +*/ +export function chooseImage() : Promise { + return new Promise((res) => { + uni.chooseImage({ + count: 1, + success(evt : ChooseImageSuccess) { + console.log('**') + if (evt.tempFilePaths.length > 0) { + console.log(evt, "----") + const imgs = evt.tempFilePaths[0] as string; + try { + const decodedPath = Uri.decode(imgs).substring(7) + const file = File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + let scanner = BarcodeScanning.getClient(); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + res({ + url: imgs, + position: listpos, + bounds: bounedlist, + text: rulstText + } as SCANNING_PHOTO_RESULT) + }) + + } catch (e : IOException) { + res(null) + } + } + }, + fail() { + res(null) + } + }) + }) +} + +/** +* 给定图片路径Uri解析图片。 +* @public decoderUriPathToQr +*/ +export function decoderUriPathToQr(filePath : Uri) : Promise { + return new Promise((res) => { + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, filePath); + let scanner = BarcodeScanning.getClient(); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + res({ + url: "", + position: listpos, + bounds: bounedlist, + text: rulstText + } as SCANNING_PHOTO_RESULT) + }) + }) +} + +/** +* 给定ImageBuffer +* @public decoderBuffToQr +*/ +export function decoderBuffToQr(bitmap : ByteArray, width : Number, height : Number, ration : Number) : Promise { + return new Promise((res) => { + let options = BarcodeScannerOptions.Builder() + .setBarcodeFormats( + Barcode.FORMAT_QR_CODE, + Barcode.FORMAT_EAN_13, + Barcode.FORMAT_CODE_128, + Barcode.FORMAT_CODABAR + ) + .build() + let image = InputImage.fromByteArray(bitmap, width.toInt(), height.toInt(), ration.toInt(), InputImage.IMAGE_FORMAT_NV21) + // 如果只扫qr开启这行,速度快一点。 + let scanner = BarcodeScanning.getClient(options); + // let scanner = BarcodeScanning.getClient(); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + res({ + url: "", + position: listpos, + bounds: bounedlist, + text: rulstText + } as SCANNING_PHOTO_RESULT) + }) + .addOnFailureListener((e) => { + + res(null) + }) + }) +} + + +/** + * 提供一个网络图片地址进行解码 + * @public urlPathDecoderQr + */ +export function urlPathDecoderQr(url : String) : Promise { + return new Promise((res) => { + uni.downloadFile({ + url, + success(res) { + + const contentResolver = UTSAndroid.getAppContext()!.contentResolver + let decodedPath = res.tempFilePath + if (res.tempFilePath.indexOf('file://') > -1) { + decodedPath = Uri.decode(res.tempFilePath).substring(7) + } + + try { + const file = File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + let scanner = BarcodeScanning.getClient(); + scanner.process(image) + .addOnSuccessListener((barcodes) => { + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + for (barcode in barcodes) { + // 位置信息 + let bounds = barcode.boundingBox + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + // 码的格式 + let valueType = barcode.valueType + + if (rawValue != null && bounds != null && corners != null) { + let iminfo = { width: bounds!.width(), height: bounds!.height(), centerX: bounds!.centerX(), centerY: bounds!.centerY() } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners) { + posinfo.push([pos!.x as number, pos!.y as number] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue) + } + } + res({ + url: url, + position: listpos, + bounds: bounedlist, + text: rulstText + } as SCANNING_PHOTO_RESULT) + }) + + } catch (e : IOException) { + res(null) + } + + }, + fail() { + res(null) + } + }) + }) +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/index.vue b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/index.vue new file mode 100644 index 0000000..6fcf1f5 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/index.vue @@ -0,0 +1,280 @@ + + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/libview/view.uts b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/libview/view.uts new file mode 100644 index 0000000..eaffcd2 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/libview/view.uts @@ -0,0 +1,468 @@ +import Context from 'android.content.Context' +import LinearLayout from 'android.widget.LinearLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import TextView from 'android.widget.TextView'; +import ImageView from 'android.widget.ImageView'; +import Gravity from 'android.view.Gravity'; +import Color from 'android.graphics.Color'; +import Activity from 'android.app.Activity'; +// import CardView from 'androidx.cardview.widget.CardView'; +import { ref, } from "vue" +import TextUtils from 'android.text.TextUtils'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable' +import MotionEvent from 'android.view.MotionEvent'; +import ColorStateList from 'android.content.res.ColorStateList'; +import attr from 'android.R.attr' +import {hexToRgb,getDefaultColor} from "./xCoreColorUtil.uts" + + +/** + * 随机一个uid + * @param rdix 随机因子 + * @param length 取的长度 + * @param isAddStr 是否限制随机结果中的长度,不允许输出长度 + * @returns String + */ +function getUid(rdix = 1, length = 12) : string { + let ix = ""; + // #ifndef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length); + // #endif + + // #ifdef APP + ix = Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString().substring(0, length as Int); + // #endif + return ix; +} + +class MyClickListener implements View.OnClickListener { + callbackFun:()=>void; + constructor(cal?:()=>void){ + this.callbackFun = cal as ()=>void; + } + override onClick(v?:View):void { + if(typeof this.callbackFun !='underfinde'){ + this.callbackFun(); + } + } +} +class MyTouchListener implements View.OnTouchListener { + //down,up,move,cancel,longClick + callbackFun:(types:string,event : MotionEvent,detail:UTSJSONObject)=>void; + dubleTime = 0; + tid = 56; + _x = 0; + _y = 0; + // 判断方向的差值 + swipe_mindiff = 40 + // 滑动时,一定时间内只能触发一次事件。不能连续触发。 + tid_siper = 100; + swipeDirection = "" + constructor(call:(types:string,event : MotionEvent,detail?:UTSJSONObject)=>void) { + this.callbackFun = call; + } + override onTouch(view : View, event : MotionEvent) : Boolean { + + if(event.action == MotionEvent.ACTION_DOWN ){ + this._x = event.getX(); + this._y = event.getY(); + this.swipeDirection = "" + this.callbackFun('down',event,{}); + let difftime = new Date().getTime() - this.dubleTime; + if(difftime >0 && difftime<=300){ + this.callbackFun('doubleClick',event ,{}); + } + this.dubleTime = new Date().getTime(); + clearTimeout(this.tid) + tid = setTimeout(function() { + this.callbackFun('longPress',event,{}); + }, 800); + } + if(event.action == MotionEvent.ACTION_UP ){ + clearTimeout(this.tid) + this.callbackFun('up',event,{}); + if(new Date().getTime() - this.dubleTime > 50){ + this.callbackFun('click',event,{}); + } + } + if(event.action == MotionEvent.ACTION_CANCEL || event.action== MotionEvent.ACTION_OUTSIDE ){ + this.callbackFun('cancel',event,{}); + clearTimeout(this.tid) + + } + + if(event.action == MotionEvent.ACTION_MOVE ){ + let x = event.getX(); + let y = event.getY(); + let deltaX = Math.abs(x - this._x); + let deltaY = Math.abs(y - this._y); + if(deltaX > deltaY && deltaX > this.swipe_mindiff){ + this.swipeDirection = (this._x > x) ? "left" : "right"; + }else if(deltaY > deltaX && deltaY > this.swipe_mindiff){ + this.swipeDirection = (this._y < y) ? "down" : "up"; + } + if(this.swipeDirection !=""){ + this.callbackFun('swiper',event,{x,y,diffX:deltaX,diffY:deltaY,direction:this.swipeDirection}); + } + // this._x = x; + // this._y = y; + this.callbackFun('move',event,{}); + clearTimeout(this.tid) + } + + + return true; + } +} + +class xView { + public view : any; + public tagId:string = 'x_view_id_'+getUid(); + public bgView:GradientDrawable + private _onclickFun= (_event : MotionEvent):void=>{}; + private _onTouchStart= (_event : MotionEvent):void=>{}; + private _onTouchEnd= (_event : MotionEvent):void=>{}; + private _onTouchCancel= (_event : MotionEvent):void=>{}; + private _onTouchMove= (_event : MotionEvent):void=>{}; + private _onTouchLongPress= (_event : MotionEvent):void=>{}; + private _onTouchDubleClick= (_event : MotionEvent):void=>{}; + private _onTouchSwiper= (_event : MotionEvent,detail?:UTSJSONObject):void=>{}; + // 设置禁用,不会触发上面的事件。 + private _disabled = false; + constructor(context : Context) { + let view = new View(context); + + view.setTag(this.tagId) + let layoutParams_crd = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + view.setLayoutParams(layoutParams_crd); + this.bgView = new GradientDrawable(); + + // let statuesInts= [[attr.state_enabled].toKotlinList().toIntArray(),[attr.state_pressed].toKotlinList().toIntArray(),[-attr.state_enabled].toKotlinList().toIntArray()] + // let statuesColors= [Color.WHITE,Color.RED,Color.RED] + // let states = new ColorStateList(statuesInts.toKotlinList().toTypedArray(),statuesColors.toKotlinList().toIntArray()) + + this.bgView.setShape(GradientDrawable.RECTANGLE) + this.bgView.setColor(Color.WHITE) + this.bgView.mutate() + view.setBackground(this.bgView) + + this.view = view; + + // view.setOnClickListener(new MyClickListener(():void=>{ + // this._onclickFun() + // })); + view.setOnTouchListener(new MyTouchListener((types:string,event : MotionEvent,detail?:UTSJSONObject):void=>{ + + if(this._disabled == false){ + if(types=='down'){ + this._onTouchStart(event) + } + if(types=='up'){ + this._onTouchEnd(event); + } + if(types=='click'){ + this._onclickFun(event); + } + if(types=='move'){ + this._onTouchMove(event) + } + if(types=='cancel'){ + this._onTouchCancel(event) + } + if(types=='longPress'){ + this._onTouchLongPress(event) + } + if(types=='doubleClick'){ + this._onTouchDubleClick(event) + } + if(types=='swiper'){ + this._onTouchSwiper(event,detail) + } + } + })); + + + } + getView():View{ + return this.view as View; + } + setDisabled(dis:boolean) : xView{ + this._disabled = dis; + return this; + } + + /** + * 触发距离是大于50时触发并判断方向 + * x,y当前坐标,diffX滑动时距离开始时按下的横向x距离,diffY表示竖向。Direction为方向:left,right,up,dowon + *detail: + *{x,y,diffX,diffY,direction} + */ + setSwiper(fun?:(event: MotionEvent,detail?:UTSJSONObject)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchSwiper = fun; + } + return this; + } + setDoubleClick(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchDubleClick = fun; + } + return this; + } + setClick(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onclickFun = fun; + } + return this; + } + setTouchStart(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchStart = fun; + } + return this; + } + setTouchMove(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchMove = fun; + } + return this; + } + setTouchEnd(fun?:(event: MotionEvent)=>void) : xView{ + + if(typeof fun !== 'undefined'){ + this._onTouchEnd = fun; + } + return this; + } + setTouchCancel(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchCancel = fun; + } + return this; + } + setTouchLongPress(fun?:(event: MotionEvent)=>void) : xView{ + if(typeof fun !== 'undefined'){ + this._onTouchLongPress = fun; + } + return this; + } + + + setBackgroundColor(colorStr : string) : xView { + this.bgView.mutate() + if(colorStr == 'transparent'){ + this.bgView.setColor(Color.TRANSPARENT) + }else{ + this.bgView.setColor(Color.parseColor(getDefaultColor(colorStr))) + } + + return this; + } + + setBorder(w?:number,colorStr?:string,dashed?:boolean) : xView { + this.bgView.mutate() + + let tw:number = 1; + let tcolor = 'transparent'; + let tdashed = false; + if(typeof tw !== 'undefined'){ + tw = w as number; + } + if(typeof tw !== 'undefined'){ + tcolor = colorStr as string; + } + + if(typeof dashed !== 'undefined'){ + tdashed = dashed as boolean; + } + + let colorNum = Color.TRANSPARENT; + if(tcolor != 'transparent'){ + colorNum = Color.parseColor(getDefaultColor(tcolor)); + } + if(dashed == true){ + let dashedWidth = 8 + let dashedGap = 5 + this.bgView.setStroke(tw.toInt(),colorNum,dashedWidth.toFloat(),dashedGap.toFloat()) + }else{ + this.bgView.setStroke(tw.toInt(),colorNum) + } + + + return this; + } + setMargin(n:any):xView{ + let view = this.view as View; + let selfPrams = view.getLayoutParams() + let params = new LinearLayout.LayoutParams( + selfPrams.width, + selfPrams.height + ) + + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = (rds).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = (rd[0]).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + let rds = 0; + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[0]).toInt(),(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + params.setMargins((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = (rd).toInt(); + params.setMargins(rdf,rdf,rdf,rdf) + } + + view.setLayoutParams(params); + return this; + } + + setPadding(n:any):xView{ + let view = this.view as View; + if(Array.isArray(n)){ + let rd = n as number[]; + if(rd.length==0){ + let rds = 0; + let rdf = (rds).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==1){ + let rdf = (rd[0]).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + }else if(rd.length==2){ + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[0]).toInt(),(rd[1]).toInt()) + }else if(rd.length==3){ + let rds = 0; + let rdf = rds.toInt(); + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),rdf) + }else if(rd.length==4){ + view.setPadding((rd[0]).toInt(),(rd[1]).toInt(),(rd[2]).toInt(),(rd[3]).toInt()) + } + }else{ + + let rd = n as number; + let rdf = (rd).toInt(); + view.setPadding(rdf,rdf,rdf,rdf) + } + + return this; + } + setRadius(radius:any) : xView{ + let x =0 + let y =0 + this.bgView.mutate() + if(Array.isArray(radius)){ + let rd = radius as number[]; + if(rd.length==0){ + let rdfs = 0; + this.bgView.setCornerRadius((rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==1){ + let rdfs = rd[0]; + this.bgView.setCornerRadius((rdfs).toFloat()); + // view.setBackground(this.bgView) + }else if(rd.length==2){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + x.toFloat(),x.toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==3){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + (rd[2]).toFloat(),(rd[2]).toFloat(), + x.toFloat(),x.toFloat() + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + }else if(rd.length==4){ + let tl = [ + (rd[0]).toFloat(),(rd[0]).toFloat(), + (rd[1]).toFloat(),(rd[1]).toFloat(), + (rd[2]).toFloat(),(rd[2]).toFloat(), + (rd[3]).toFloat(),(rd[3]).toFloat(), + ] + let tlint = tl.toKotlinList().toFloatArray() + this.bgView.setCornerRadii(tlint); + } + }else{ + + let rd = radius as number; + + this.bgView.setCornerRadius((rd).toFloat()); + } + + + return this; + } + /** 设置当前宽和高为父级的相对宽和高 + *w,h有效值为:auto|100% + */ + setSizeBy(w:string="100%",h:string = "auto"){ + let view = this.view as View; + let ww = ViewGroup.LayoutParams.MATCH_PARENT; + let hh = ViewGroup.LayoutParams.MATCH_PARENT; + if(w=="auto"){ + ww = ViewGroup.LayoutParams.WRAP_CONTENT + } + if(h=="auto"){ + hh = ViewGroup.LayoutParams.WRAP_CONTENT + } + + let layoutParams_crd = new LinearLayout.LayoutParams(ww,hh) + view.setLayoutParams(layoutParams_crd); + } + setSize(width : number, height : number) : xView { + let view = this.view as View; + let layoutParams_crd = new LinearLayout.LayoutParams( + (width).toInt(), + (height).toInt() + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + setWidth(width : number) : xView { + let view = this.view as View; + let lpar = view.getLayoutParams(); + let layoutParams_crd = new LinearLayout.LayoutParams( + (width).toInt(), + (lpar.height).toInt(), + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + setHeight(height : number) : xView { + let view = this.view as View; + let lpar = view.getLayoutParams(); + let layoutParams_crd = new LinearLayout.LayoutParams( + (lpar.width).toInt(), + (height).toInt(), + ) + view.setLayoutParams(layoutParams_crd); + return this; + } + + + +} + +export default xView; \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-android/libview/xCoreColorUtil.uts b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/libview/xCoreColorUtil.uts new file mode 100644 index 0000000..5475d85 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-android/libview/xCoreColorUtil.uts @@ -0,0 +1,669 @@ + +/** + * 数字转16进制 + */ +function toHex(numbers : number) : string { + let i = 0 as number + if (numbers === i) { + return '00'; + } + let hex = ''; + const hexChars = '0123456789abcdef'; + while (numbers > 0) { + const remainder = numbers % 16; + hex = hexChars[remainder] + hex; + numbers = Math.floor(numbers / 16); + } + return hex; +} + +/** + * 颜色值列表 + */ + +export const colors = new Map([ + ['primary', '#0579FF'], + ['success', '#09CC54'], + ['danger', '#FE6D1B'], + ['warn', '#F0A22C'], + ['error', '#E2001B'], + ['info', '#F2F2F2'], + + ['kleinblue', '#002FA7'], // 克莱因蓝 + ['chinesered', '#FF0000'], // 中国红 + ['internationalorange', '#FF4F00'], // 国际橙 + ['egyptianvlue', '#1034A6'], // 埃及艳蓝 + ['parisviolet', '#6C3082'], // 巴黎紫 + ['moroccanblue', '#1256A7'], // 摩洛哥蓝 + ['brazilgreen', '#009B3A'], // 巴西绿 + ['britishracinggreen', '#004225'], // 英国赛车绿 + ['indianyellow', '#E3A857'], // 印度黄 + ['australiangold', '#FFDF00'], // 澳大利亚金 + ['venetianred', '#C80815'], // 威尼斯红 + ['majorelleblue', '#6050DC'], // 马若雷蓝 + ['tuscanred', '#7C3030'], // 托斯卡红 + ['naplesyellow', '#FADA5E'], // 那不勒斯黄 + ['capumortuum', '#592720'], // 死者之首 + ['mayablue', '#73C2FB'], // 玛雅蓝 + ['persianrose', '#FE28A2'], // 波斯玫瑰 + ['tyrianpurple', '#66023C'], // 泰尔紫 + ['saharasand', '#F1E788'], // 撒哈拉沙 + ['burmeseruby', '#B00A0A'], // 缅甸红宝石 + + ['transparent', 'rgba(0,0,0,0)'], + ['aliceblue', '#F0F8FF'], + ['antiquewhite', '#FAEBD7'], + ['aqua', '#00FFFF'], + ['aquamarine', '#7FFFD4'], + ['azure', '#F0FFFF'], + ['beige', '#F5F5DC'], + ['bisque', '#FFE4C4'], + ['black', '#000000'], + ['blanchedalmond', '#FFEBCD'], + ['blue', '#0000FF'], + ['blueviolet', '#8A2BE2'], + ['brown', '#A52A2A'], + ['burlywood', '#DEB887'], + ['cadetblue', '#5F9EA0'], + ['chartreuse', '#7FFF00'], + ['chocolate', '#D2691E'], + ['coral', '#FF7F50'], + ['cornflowerblue', '#6495ED'], + ['cornsilk', '#FFF8DC'], + ['crimson', '#DC143C'], + ['cyan', '#00FFFF'], + ['darkblue', '#00008B'], + ['darkcyan', '#008B8B'], + ['darkgoldenrod', '#B8860B'], + ['darkgray', '#A9A9A9'], + ['darkgreen', '#006400'], + ['darkkhaki', '#BDB76B'], + ['darkmagenta', '#8B008B'], + ['darkolivegreen', '#556B2F'], + ['darkorange', '#FF8C00'], + ['darkorchid', '#9932CC'], + ['darkred', '#8B0000'], + ['darksalmon', '#E9967A'], + ['darkseagreen', '#8FBC8F'], + ['darkslateblue', '#483D8B'], + ['darkslategray', '#2F4F4F'], + ['darkturquoise', '#00CED1'], + ['darkviolet', '#9400D3'], + ['deeppink', '#FF1493'], + ['deepskyblue', '#00BFFF'], + ['dimgray', '#696969'], + ['dodgerblue', '#1E90FF'], + ['firebrick', '#B22222'], + ['floralwhite', '#FFFAF0'], + ['forestgreen', '#228B22'], + ['fuchsia', '#FF00FF'], + ['gainsboro', '#DCDCDC'], + ['ghostwhite', '#F8F8FF'], + ['gold', '#FFD700'], + ['goldenrod', '#DAA520'], + ['gray', '#808080'], + ['green', '#008000'], + ['greenyellow', '#ADFF2F'], + ['honeydew', '#F0FFF0'], + ['hotpink', '#FF69B4'], + ['indianred', '#CD5C5C'], + ['indigo', '#4B0082'], + ['ivory', '#FFFFF0'], + ['khaki', '#F0E68C'], + ['lavender', '#E6E6FA'], + ['lavenderblush', '#FFF0F5'], + ['lawngreen', '#7CFC00'], + ['lemonchiffon', '#FFFACD'], + ['lightblue', '#ADD8E6'], + ['lightcoral', '#F08080'], + ['lightcyan', '#E0FFFF'], + ['lightgoldenrodyellow', '#FAFAD2'], + ['lightgray', '#D3D3D3'], + ['lightgreen', '#90EE90'], + ['lightpink', '#FFB6C1'], + ['lightsalmon', '#FFA07A'], + ['lightseagreen', '#20B2AA'], + ['lightskyblue', '#87CEFA'], + ['lightslategray', '#778899'], + ['lightsteelblue', '#B0C4DE'], + ['lightyellow', '#FFFFE0'], + ['lime', '#00FF00'], + ['limegreen', '#32CD32'], + ['linen', '#FAF0E6'], + ['magenta', '#FF00FF'], + ['maroon', '#800000'], + ['mediumaquamarine', '#66CDAA'], + ['mediumblue', '#0000CD'], + ['mediumorchid', '#BA55D3'], + ['mediumpurple', '#9370DB'], + ['mediumseagreen', '#3CB371'], + ['mediumslateblue', '#7B68EE'], + ['mediumspringgreen', '#00FA9A'], + ['mediumturquoise', '#48D1CC'], + ['mediumvioletred', '#C71585'], + ['midnightblue', '#191970'], + ['mintcream', '#F5FFFA'], + ['mistyrose', '#FFE4E1'], + ['moccasin', '#FFE4B5'], + ['navajowhite', '#FFDEAD'], + ['navy', '#000080'], + ['oldlace', '#FDF5E6'], + ['olive', '#808000'], + ['olivedrab', '#6B8E23'], + ['orange', '#FFA500'], + ['orangered', '#FF4500'], + ['orchid', '#DA70D6'], + ['palegoldenrod', '#EEE8AA'], + ['palegreen', '#98FB98'], + ['paleturquoise', '#AFEEEE'], + ['palevioletred', '#DB7093'], + ['papayawhip', '#FFEFD5'], + ['peachpuff', '#FFDAB9'], + ['peru', '#CD853F'], + ['pink', '#FFC0CB'], + ['plum', '#DDA0DD'], + ['powderblue', '#B0E0E6'], + ['purple', '#800080'], + ['rebeccapurple', '#663399'], + ['red', '#FF0000'], + ['rosybrown', '#BC8F8F'], + ['royalblue', '#4169E1'], + ['saddlebrown', '#8B4513'], + ['salmon', '#FA8072'], + ['sandybrown', '#F4A460'], + ['seagreen', '#2E8B57'], + ['seashell', '#FFF5EE'], + ['sienna', '#A0522D'], + ['silver', '#C0C0C0'], + ['skyblue', '#87CEEB'], + ['slateblue', '#6A5ACD'], + ['slategray', '#708090'], + ['snow', '#FFFAFA'], + ['springgreen', '#00FF7F'], + ['steelblue', '#4682B4'], + ['tan', '#D2B48C'], + ['teal', '#008080'], + ['thistle', '#D8BFD8'], + ['tomato', '#FF6347'], + ['turquoise', '#40E0D0'], + ['violet', '#EE82EE'], + ['wheat', '#F5DEB3'], + ['white', '#FFFFFF'], + ['whitesmoke', '#F5F5F5'], + ['yellow', '#FFFF00'], + ['yellowgreen', '#9ACD32'] + +]) + +export function isValidColor(color : string) : boolean { + // return chroma.valid(color); + const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + const rgbRegex = /^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/; + const rgbaRegex = /^rgba\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*((1(\.0{1,2})?)|(0(\.\d{1,2})?))\)$/; + const hslRegex = /^hsl\((\d{1,3}), (\d{1,3})%, (\d{1,3})%\)$/; + const hslaRegex = /^hsla\(\s*((\d{1,2}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)\s*,\s*((\d{1,2}|\d{0,1}\d{1}\d{1}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)%\s*,\s*((\d{1,2}|\d{0,1}\d{1}\d{1}|[1-2]\d{2}|3[0-5]\d)(\.\d+)?|\d+(\.\d+)?)%\s*,\s*((1|0(\.\d{1,2})?|(\.\d{1,2})))\)$/i; + + + if (color == '') { + return false; // 颜色值为空 + } else if (color === 'inherit' || color === 'transparent') { + return false; // 特殊颜色值 + } else if (color === 'currentColor') { + return false; // currentColor 不是有效的颜色值 + } else if (hexRegex.test(color) || rgbRegex.test(color) || rgbaRegex.test(color) || hslRegex.test(color) || hslaRegex.test(color)) { + return true; // 符合颜色值的格式 + } + return false; +} +/** + * 获取默认的颜色值 + * @param [string] 颜色名称或者16进制颜色值 + */ +export function getDefaultColor(sColor : string) : string { + if(sColor=="") return "" + let sc = sColor.toLocaleLowerCase().trim().replace(" ",""); + + if (isValidColor(sc)) { + // 如果符合所有颜色值,进行转换为16进制。css方便统一解析。 + return sc; + } + // 检测是否是颜色名称。 + let sco = colors.get(sc); + if (typeof sco == 'string') return sco as string; + return colors.get("primary")!; +} + +/** + * 16进制转rgb + */ +export function hexToRgb(sColors : string) : UTSJSONObject { + if (sColors == "") { + return { r: 0, g: 0, b: 0, a: 0 } + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if(sColor.length==9){ + sColorChange.push(parseInt(sColor.substring(7, 9), 16)/255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length==4?sColorChange[3]:1 + } + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + let p : number[] = arr.map((val : string) : number => parseInt(val)); + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } + } + if (p.length == 3) { + p.push(1) + } + return { + r: p[0], + g: p[1], + b: p[2], + a: p[3] + } + } else { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } + } +} +/** + * rgb转hsl + */ +export function rgbToHsl(rgb : UTSJSONObject) : UTSJSONObject { + let r = rgb.getNumber("r") + r = r as number / 255 + let g = rgb.getNumber("g") + g = g as number / 255 + let b = rgb.getNumber("b") + b = b as number / 255 + let a = rgb.getNumber("a") + + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + let h=60 * (4 + (r - g) / (max - min)); + let s=(max - min) / (2 - max - min); + let l= (max + min) / 2; + + if (max === r) { + h = (60 * (g - b)) / (max - min); + } else if (max === g) { + h = 60 * (2 + (b - r) / (max - min)); + } + + if (h < 0) { + h += 360; + } + + + if (max === min) { + s = 0; + } else if (l < 0.5) { + s = (max - min) / (max + min); + } + + return { h: h, s: s * 100, l: l * 100, a: a }; +} + +/** + * hsl转rgb + */ +export function hslToRgb(hsl : UTSJSONObject) : UTSJSONObject { + let h = hsl.getNumber("h")! + let s = hsl.getNumber("s")! + let l = hsl.getNumber("l")! + let a = hsl.getNumber("a")! + + h = h / 360; + s = s / 100; + l = l / 100; + let r = l; + let g = l; + let b = l; + + function hue2rgb(pxx : number, q : number, txs : number) : number { + let t = txs; + let p = pxx; + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + + + if (s > 0) { + let q = l * (1 + s); + if (l >= 0.5) { + q = l + s - l * s; + } + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + + } + + r = Math.round(r * 255); + g = Math.round(g * 255); + b = Math.round(b * 255); + return { r, g, b, a }; +} + +/** + * rgb转16进制 + */ +export function rgbToHex(rgb : UTSJSONObject) : string { + let r = rgb.getNumber("r")! + let g = rgb.getNumber("g")! + let b = rgb.getNumber("b")! + let a = rgb.getNumber("a")! + return "#" + toHex(r) + toHex(g) + toHex(b) + toHex(a*255) +} +export function hslaToCss(hsl : UTSJSONObject) : string { + + let rgb = hslToRgb(hsl) + + return rgbToHex(rgb) +} + +export function hslaToRgbCss(hsl : UTSJSONObject) : string { + + let rgb = hslToRgb(hsl) + let r = rgb.getNumber("r")! + let g = rgb.getNumber("g")! + let b = rgb.getNumber("b")! + let a = rgb.getNumber("a")! + return `rgba(${r},${g},${b},${a})` +} + +// 根据 HSLA 颜色计算亮度 +export function getLuminance(color : UTSJSONObject, type = "rgba") : number { + + + let colordefault : UTSJSONObject = type == 'rgba' ? color : hslToRgb(color); + const r= colordefault.getNumber("r")! + const g= colordefault.getNumber("g")! + const b= colordefault.getNumber("b")! + const rs = r / 255 + const gs = g / 255 + const bs = b / 255 + const rl = Math.pow(rs <= 0.03928 ? rs / 12.92 : ((rs + 0.055) / 1.055), 2.4); + const gl = Math.pow(gs <= 0.03928 ? gs / 12.92 : ((gs + 0.055) / 1.055), 2.4); + const bl = Math.pow(bs <= 0.03928 ? bs / 12.92 : ((bs + 0.055) / 1.055), 2.4); + + return 0.2126 * rl + 0.7152 * gl + 0.0722 * bl; +} + +/** + * 对颜色加深 + */ +export function colorAddDeepen(sColor : string) : string { + + let rgb = hexToRgb(getDefaultColor(sColor)); + + let hsl = rgbToHsl(rgb); + + let l = hsl.getNumber("l")! - 5; + l = Math.max(0, Math.min(l, 100)) + + return hslaToRgbCss({ h: hsl.getNumber("h"), s: hsl.getNumber("s"), l, a: hsl.getNumber("a")! }) +} +/** + * 对颜色提亮 + */ +export function colorAddBrighten(sColor : string) : string { + let rgb = hexToRgb(getDefaultColor(sColor)); + let hsl = rgbToHsl(rgb); + let l = hsl.getNumber("l")! + 10; + l = Math.max(0, Math.min(l, 100)) + return rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s:hsl.getNumber("s"), l, a: hsl.getNumber("a")! })) +} + + + + +/** + * 获取浅色系主题,根据颜色值计算。返回正常值和hover值。 + */ +export function colorGetThint(sColor : string) { + let rgb = hexToRgb(getDefaultColor(sColor)); + let hsl = rgbToHsl(rgb); + let s = hsl.getNumber("s")!; + // let l = hsl.getNumber("l"); + if (Math.ceil(s) > 0) { + s = 45 + } + return { + default: rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s, l: 93, a: hsl.getNumber("a")! })), + hover: rgbToHex(hslToRgb({ h: hsl.getNumber("h"), s, l: 85, a: hsl.getNumber("a")! })) + } +} +/** + * 获取正常主题,根据颜色值计算。返回正常值和hover值。 + */ +export function colorGetHover(sColor : string) { + + return { + default: sColor, + hover: colorAddDeepen(sColor) + } +} + + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getDefaultColorObj(color : string, hoverColor : string) : UTSJSONObject { + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + let shadow = hslaToRgbCss({ h: hsla.getNumber("h")!, s: (hsla.getNumber("s")!)== 0 ? 0 : 60, l: 40, a: 0.4 }); + let shadowHOver = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: (hoverHsla.getNumber("s")!)== 0 ? 0 : 60, l: 40, a: 0.4 }); + if((hsla.getNumber("h")!)==0&&(hsla.getNumber("s")!)==0){ + shadow = "transparent" + } + if((hoverHsla.getNumber("h")!)==0&&(hoverHsla.getNumber("s")!)==0){ + shadowHOver = "transparent" + } + let o = { + default: { + background: hslaToRgbCss(hsla), + borderColor: hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: Math.min(Math.max(0, hsla.getNumber("l")! - 5), hsla.getNumber("l")!) }), + fontColor: getLuminance(hsla, 'hsla') < 0.46 && hsla.getNumber("a")! > 0.1 ? '#ffffff' : '#000000', + shadow: shadow + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: Math.min(Math.max(0, hoverHsla.getNumber("l")! - 10), hoverHsla.getNumber("l")!) }), + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: Math.max(Math.max(0, hoverHsla.getNumber("l")! - 10), hoverHsla.getNumber("l")!) }), + fontColor: getLuminance(hoverHsla, 'hsla') < 0.46 && hoverHsla.getNumber("a")! > 0.1 ? '#ffffff' : '#000000', + shadow: shadowHOver + } + } as UTSJSONObject + + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getTextColorObj(color : string, hoverColor : string) : UTSJSONObject { + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let o = { + default: { + background: "transparent", + borderColor: "transparent", + fontColor: getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 95 }), + borderColor:"transparent", + fontColor: getLuminance(hoverHsla, 'hsla') < 0.3 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getThinColorObj(color : string, hoverColor : string,isCoverDark?:boolean) : UTSJSONObject { + let dark = isCoverDark==null?false:isCoverDark + // #ifdef WEB + dark = isCoverDark==undefined?false:dark + // #endif + + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let fontcolor = getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l:30 }) + let bordercolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark==true?21:92 }) + let bgcolor = hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark==true?20:95 }) + if(dark){ + let p = hsla; + p.set('l',90) + fontcolor = hslaToRgbCss(p) + p.set('l',20) + p.set('s',p.getNumber('s')!==0?0:20) + bgcolor = hslaToRgbCss(p) + p.set('l',22) + bordercolor = hslaToRgbCss(p) + } + let o = { + default: { + background: bgcolor, + borderColor:bordercolor, + fontColor: fontcolor, + shadow: "transparent", + }, + active: { + background: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: dark==true?18:88 }), + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a:0, l: dark==true?18:80 }), + fontColor: getLuminance(hoverHsla, 'hsla') < 0.3 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 处理相主题色。 + * @param color 需要处理的颜色值 + * @param hoverColor 对应按下去的颜色默认与color相等。 + * @returns UTSJSONObject + */ +export function getOutlineColorObj(color : string, hoverColor : string) : UTSJSONObject { + let hsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(color))); + let hoverHsla : UTSJSONObject = rgbToHsl(hexToRgb(getDefaultColor(hoverColor))); + // tmxColor.hslaToCss({ ...hsla}) : tmxColor.hslaToCss({ ...hsla,l:30}) + let o = { + default: { + background: 'transparent', + borderColor:hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: 1, l: 75 }), + fontColor: getLuminance(hsla, 'hsla') < 0.3 && hsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hsla) : hslaToRgbCss({ h: hsla.getNumber("h")!, s: hsla.getNumber("s")!, a: hsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + }, + + active: { + background: 'transparent', + borderColor: hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a:1, l: 70 }), + fontColor: getLuminance(hoverHsla, 'hsla') < 0.3 && hoverHsla.getNumber("a")! > 0.1 ? hslaToRgbCss(hoverHsla) : hslaToRgbCss({ h: hoverHsla.getNumber("h")!, s: hoverHsla.getNumber("s")!, a: hoverHsla.getNumber("a")!, l: 30 }), + shadow: "transparent", + } + } as UTSJSONObject + return o; +} + +/** + * 设置颜色的亮度值。29 + * isCoverDark:是根据亮度值,是否要设置n的值,如果n超过了 + * 指定的30就不操作。 + */ +export function setTextColorLightByDark(color:string):string{ + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let l = hsla.getNumber('l')! + let s = hsla.getNumber('s')! + if(l<30){ + if(s>0){ + hsla.set('l',50) + }else{ + hsla.set('l',100) + } + + } + + return hslaToRgbCss(hsla) +} +/** + * 变动的颜色是否需要变深。如果不需要返回原始颜色 + * 如果果需要自动加深。 + */ +export function setBgColorLightByDark(color:string):string{ + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let l = hsla.getNumber('l')! + let s = hsla.getNumber('s')! + if(s==0&&l>50){ + hsla.set('l',100-l) + } + if(s>0){ + if(l>50){ + hsla.set('l',100-l) + } + } + return hslaToRgbCss(hsla) +} + +export function isBlackAndWhite(color:string):boolean{ + let realColor = getDefaultColor(color); + let hsla = rgbToHsl(hexToRgb(realColor)) + let s = hsla.getNumber('s')! + return s==0 +} + + + diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/Resources/_CodeSignature/CodeResources b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/Resources/_CodeSignature/CodeResources new file mode 100644 index 0000000..44fdac3 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/Resources/_CodeSignature/CodeResources @@ -0,0 +1,212 @@ + + + + + files + + Headers/unimoduleXMlkitScannigU-Swift.h + + rrVnYx9RgfpqdbbblROMvU/4Unk= + + Headers/unimoduleXMlkitScannigU.h + + FH2SRnQAHIO8AbDZPa5/Bz/CcdA= + + Info.plist + + oggkQO8+5ChK5UkvRJRHpMoSBFI= + + Modules/module.modulemap + + wKuVddM+8I2G/8RcOmW6s0wX31M= + + Modules/unimoduleXMlkitScannigU.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + jtqbS2Trq3D8rtb92vby7+bs5o4= + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.abi.json + + aL7ncI5o4KD4BuCR7PRaOaVMe74= + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + 3tANMXD9JTgGV6RX7TRRcoYtUFA= + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + V0pmF7rnAzF9xczsp8QRRW6oedw= + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + 3tANMXD9JTgGV6RX7TRRcoYtUFA= + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + HD1yZ99Moza0WmezwtWRpMx5Pnw= + + config.json + + YDYijrWiF8Rxzv8lihbkxXuOk7s= + + + files2 + + Headers/unimoduleXMlkitScannigU-Swift.h + + hash2 + + 5EiTAikkGs6OTkMJQl4yJG93zGnE9T3Xrx0k9gPJx9k= + + + Headers/unimoduleXMlkitScannigU.h + + hash2 + + XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY= + + + Modules/module.modulemap + + hash2 + + +9eWeZGAx3sZSdYnYgkJicwkn6jTvvAsdR2TYB6RkJ8= + + + Modules/unimoduleXMlkitScannigU.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + hash2 + + wP6hT6p1lWe3E3s+SUNjJQZ9E5PH6uILYCL8RbV/eT4= + + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.abi.json + + hash2 + + qs8Ju2FnIp4JwyRbr3eZBTHjXnx1Zf+UZdZuRy+9kBs= + + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + hash2 + + HauXAU+7IlSB5MF/vIm1VHVr3OWKqepeLQgIUrC6wQ4= + + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + hash2 + + MzXLl4ShiG1kAyuafALgeqtRIcp7ZWXecbXf1V6UnSM= + + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + hash2 + + HauXAU+7IlSB5MF/vIm1VHVr3OWKqepeLQgIUrC6wQ4= + + + Modules/unimoduleXMlkitScannigU.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + hash2 + + 4noLKKIKPbb2FMi/RHd6gtbVz/if6JDHpgyY8vWcJEw= + + + config.json + + hash2 + + NoNtCzvQ0iOAfyiuCHYdlYR2DRmlZB9Toiooz3wQ0lQ= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/camera.uts b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/camera.uts new file mode 100644 index 0000000..c33aab6 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/camera.uts @@ -0,0 +1,297 @@ +import { AVCaptureSession, AVCaptureDevice, AVMediaType, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureDeviceInput, AVCaptureInput, AVCaptureVideoDataOutput, AVCaptureConnection, AVCaptureVideoPreviewLayer, AVLayerVideoGravity, AVCaptureVideoOrientation } from 'AVFoundation'; +import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos'; +import { CMSampleBuffer, CMSampleBufferGetFormatDescription, CMFormatDescription, CMVideoFormatDescriptionGetDimensions } from 'CoreMedia'; +import { DispatchQueue } from "Dispatch" +import { UIView, UIImage , UIApplication } from 'UIKit'; +import { CGRect, CGFloat } from 'CoreFoundation'; +import { Barcode, BarcodeScannerOptions, BarcodeFormat, BarcodeScanner, CMVideoDimensions } from "MLKitBarcodeScanning" +import { VisionImage } from "MLKit" +import { SCANNING_PHOTO_RESULT, CALL_BACK_TYPE_PRIVATE, SCANNING_PHOTO_RESULT_BOUND, SCANNING_PHOTO_RESULT_POS ,AUTH_CALL_BACK_TYPE} from '../interface.uts'; +import { NotificationCenter , NSNotification , Notification } from 'Foundation'; +import { Selector } from 'ObjectiveC'; +// 识别结果 +let scanResult = [] as Swift.Array +// 视频宽 +let videoWidth = 0 +// 视频高 +let videoHeight = 0 +// let camera:xCamera|null = null; +let barcodeOptions = BarcodeScannerOptions(formats = BarcodeFormat.all) +class CaptureOutSessionBuffer implements AVCaptureVideoDataOutputSampleBufferDelegate { + onwerCamera:xCamera + constructor(dv:xCamera) { + this.onwerCamera = dv; + super() + } + captureOutput(output : AVCaptureOutput, @argumentLabel("didOutput") sampleBuffer : CMSampleBuffer, @argumentLabel("from") connection : AVCaptureConnection) { + let t = this; + DispatchQueue.main.async(execute=():void => { + + // console.log('图片捕捉正确') + let image = new VisionImage(buffer = sampleBuffer) + // 这里会直接影响到测量的起始点。下面是镜像,测量是图片左上为起始,但设备是竖向,因此计算时的x,y坐标其实是相对屏幕向右转下,x,y是反向的,因为是镜像 + // 所以计算位置时,x,y是反的,宽和高也是相反的。 + image.orientation = UIImage.Orientation.upMirrored + + // options=barcodeOptions + let barcodeScanner = new BarcodeScanner.barcodeScanner(options = barcodeOptions) + console.log(image) + barcodeScanner.process(image, completion = (features : Swift.Array | null, error) => { + if (features == null || error != null) { + return; + } + if (features!.length == 0 || scanResult.length>0) { + return; + } + scanResult = features! + let descVideo : CMFormatDescription | null = CMSampleBufferGetFormatDescription(sampleBuffer); + if (descVideo != null) { + let dimesionsize : CMVideoDimensions = CMVideoFormatDescriptionGetDimensions(descVideo!) + t.onwerCamera.videoBox_width= Number(dimesionsize.width) + t.onwerCamera.videoBox_height = Number(dimesionsize.height) + } + this.onwerCamera.pause() + + let listpos = [] as number[][][] + let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[] + let rulstText = [] as string[] + + for (let i = 0; i < features!.length; i++) { + let barcode = features![i] + // 位置信息 + let bounds = barcode.frame + // 坐标 + let corners = barcode.cornerPoints + // 解析的内容 + let rawValue = barcode.rawValue + let iminfo = { + width: Number(bounds.width), + height: Number(bounds.height), + centerX: Number(bounds.midX), + centerY: Number(bounds.midY) + } as SCANNING_PHOTO_RESULT_BOUND + let posinfo = [] as number[][] + for (pos in corners!) { + // pos是pointValue类型并返回CGPoint,其中有x,y + let ponit = pos.cgPointValue + posinfo.push([Number(ponit.x), Number(ponit.y)] as number[]) + } + listpos.push(posinfo) + bounedlist.push(iminfo) + rulstText.push(rawValue == null ? '' : (rawValue!)) + + } + let res = { + url: '', + position: listpos, + bounds: bounedlist, + text: rulstText + } as SCANNING_PHOTO_RESULT + + t.onwerCamera.createPointView(res) + }) + }) + + + + } +} + +// 检查权限 +export function isCheckPermissions(callFun : null | AUTH_CALL_BACK_TYPE){ + let realcall : AUTH_CALL_BACK_TYPE = (_ : boolean) => { }; + if (callFun != null) { + let cllfunFun = callFun!; + realcall = cllfunFun + } + // 相册选取权限 + PHPhotoLibrary.requestAuthorization((isok : PHAuthorizationStatus) => { + // 拒绝了相册选取权限。 + if (isok != PHAuthorizationStatus.authorized) { + realcall(false) + return; + } + // 录像权限 + AVCaptureDevice.requestAccess(for = AVMediaType.video, completionHandler = (isok2 : boolean) => { + if (!isok2) { + realcall(false) + return; + } + }) + + }) + + +} + +export class xCamera { + // 父容器 + parentView : UIView|null = null; + // 相机区域视图 + cameraView : AVCaptureVideoPreviewLayer|null = null; + // 视频宽 + videoBox_width = 0 + // 视频高。 + videoBox_height = 0 + pointView = [] as UIView[] + // 默认的相机 + captureDevice:AVCaptureDevice|null = null + // 捕获会话 + captureSession:AVCaptureSession|null = null + // 输入相机设备 + inputDevice : AVCaptureDeviceInput | null = null; + // 输出会话 + captureOut = new AVCaptureVideoDataOutput(); + // 图像捕捉事件代理。 + captureOutDelegate : CaptureOutSessionBuffer|null = null ; + constructor(){ + super(); + } + + newCamraViewLayer(){ + // 设置预览层绑定 + // 下面的缩放会居中显示,因此左顶点可能在左上方 + this.cameraView!.videoGravity = AVLayerVideoGravity.resizeAspectFill + this.cameraView!.connection!.videoOrientation = AVCaptureVideoOrientation.portrait + this.cameraView!.frame = this.parentView!.layer.bounds; + // 绑定渲染层。 + this.parentView!.layer.addSublayer(this.cameraView!) + } + clearPointView(){ + for (let i = 0; i < this.pointView.length; i++) { + let item = this.pointView[i]; + item.removeFromSuperview(); + } + this.pointView = [] as UIView[] + } + // 创建点。 + createPointView (result : SCANNING_PHOTO_RESULT){ + if (this.cameraView == null || this.parentView == null) return; + let realCgSize = this.cameraView!.frame as CGRect; + let realWidth = Number(realCgSize.width); + let realHeight = Number(realCgSize.height); + this.clearPointView(); + // 计算视频和容器的宽高比 + let videoAspectRatio = this.videoBox_width / this.videoBox_height + let containerAspectRatio = realWidth / realHeight + let ratio_real_width = 0 + let ratio_real_height = 0 + if (videoAspectRatio > containerAspectRatio) { + ratio_real_width = realWidth + // 视频的宽高比大于预览层的宽高比,宽为预览宽,但高会大于预览高从而被裁剪。 + ratio_real_height = realHeight * videoAspectRatio + } else { + ratio_real_width = realWidth / videoAspectRatio + ratio_real_height = realHeight + } + + let pointSize = 30 + for (let i = 0; i < result.bounds.length; i++) { + let text = result.text[i] + let bounds = result.bounds[i] + let pos = result.position[i]; + let centerx = (pos[2][0] - pos[0][0]) / 2 + pos[0][0] + let centery = (pos[2][1] - pos[0][1]) / 2 + pos[0][1] + let diffTop = (realHeight - ratio_real_height) / 2 + let diffLeft = (realWidth - ratio_real_width) / 2 + let x = (ratio_real_width - ratio_real_width * (bounds.centerY / this.videoBox_height) - diffLeft - 15).toInt() + + let y = (ratio_real_height * (bounds.centerX / this.videoBox_width) + diffTop - 15).toInt() + // console.log(bounds.centerX,bounds.centerY,x,y,videoWidth,videoHeight,realWidth,realHeight,ratio_real_width,ratio_real_height) + + let rect = new CGRect(x = x, y = y, width = pointSize.toInt(), height = pointSize.toInt()) + let pointViewSelf = new UIView(); + pointViewSelf.layer.frame = rect; + pointViewSelf.backgroundColor = UTSiOS.colorWithString('#21d429'); + pointViewSelf.layer.borderWidth = 2 + pointViewSelf.layer.borderColor = UTSiOS.colorWithString('#FFFFFF').cgColor; + pointViewSelf.layer.cornerRadius = new CGFloat(pointSize / 2); + pointViewSelf.isUserInteractionEnabled = true; + // let onlick = new PointClickEvent((atext:string) => { + // console.log("ok....",result.text) + // component!.__$$emit('clickQr',new Map([["result",atext]])) + // },text); + // pointClickEvent.push(onlick) + // let tapGestureCancel = new UITapGestureRecognizer() + // tapGestureCancel.addTarget(pointClickEvent[pointClickEvent.length-1], action = new Selector("onclick")) + // pointViewSelf.addGestureRecognizer(tapGestureCancel) + + this.parentView!.addSubview(pointViewSelf) + + this.pointView.push(pointViewSelf) + + } + } + setView(view:UIView){ + this.parentView = view; + } + oninit(){ + this.captureDevice = AVCaptureDevice.default(for = AVMediaType.video) + this.captureSession = new AVCaptureSession(); + this.captureSession!.sessionPreset = AVCaptureSession.Preset.low + + this.captureOutDelegate = new CaptureOutSessionBuffer(this) + + // 注册相机启动时的通知事件。 + NotificationCenter.default.addObserver(this,selector = Selector("camreaOpeingStatus"),name=NSNotification.Name("didStartRunningNotification"),object = null) + // 新建设备的输入设备 + this.inputDevice = UTSiOS.try(new AVCaptureDeviceInput(device = this.captureDevice!), "?") + if(this.inputDevice!=null){ + // 添加输入到会话中。 + this.captureSession!.addInput(this.inputDevice!) + } + + this.captureOut.alwaysDiscardsLateVideoFrames = true; + // 设置输出会话 + this.captureOut.setSampleBufferDelegate(this.captureOutDelegate!, queue = DispatchQueue.global()) + if (this.captureSession!.canAddOutput(this.captureOut)) { + this.captureSession!.addOutput(this.captureOut) + console.log("绑定输出层正确!") + } + let t = this; + DispatchQueue.main.async(execute=():void => { + t.cameraView = new AVCaptureVideoPreviewLayer(session = t.captureSession!) + // 设置预览层绑定 + // 下面的缩放会居中显示,因此左顶点可能在左上方 + t.cameraView!.videoGravity = AVLayerVideoGravity.resizeAspectFill + t.cameraView!.connection!.videoOrientation = AVCaptureVideoOrientation.portrait + t.cameraView!.frame = t.parentView!.layer.bounds; + // 绑定渲染层。 + t.parentView!.layer.addSublayer(t.cameraView!) + }) + + + } + @objc static camreaOpeingStatus(notification:Notification){ + + console.log(notification,'启动了。') + } + open(){ + this.clearPointView() + this.pause(); + this.captureSession!.startRunning() + this.oninit(); + } + stop(){ + // 暂停预览。 + this.pause() + // 移除通知。 + NotificationCenter.default.removeObserver(this, name=NSNotification.Name("didStartRunningNotification"),object = null) + // 移除视频预览层。 + this.cameraView!.removeFromSuperlayer() + // 移除点。 + this.clearPointView() + if(this.inputDevice!=null){ + this.captureSession!.removeInput(this.inputDevice!) + } + this.captureSession!.removeOutput(this.captureOut) + + } + pause(){ + if(this.captureSession!.isRunning){ + this.captureSession!.stopRunning() + + } + this.cameraView!.removeFromSuperlayer() + } +} \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/config.json b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/config.json new file mode 100644 index 0000000..e78da0b --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/config.json @@ -0,0 +1,9 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "GoogleMLKit/BarcodeScanning", + "version": "5.0.0" + } + ] +} diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/index.vue b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/index.vue new file mode 100644 index 0000000..9cad4dc --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/index.vue @@ -0,0 +1,537 @@ + + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/info.plist b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/info.plist new file mode 100644 index 0000000..6087c70 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/app-ios/info.plist @@ -0,0 +1,8 @@ + + + + + NSCameraUsageDescription + 我们需要您的相机权限来拍照或录像。 + + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/interface.uts b/uni_modules/x-mlkit-scannig-u/utssdk/interface.uts new file mode 100644 index 0000000..4731e05 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/interface.uts @@ -0,0 +1,69 @@ +export type SCANNING_PHOTO_RESULT_BOUND = { + width:number, + height:number, + centerX:number, + centerY:number +} + +export type SCANNING_PHOTO_RESULT = { + url:string,//图片地址 + position:number[][][], + bounds:SCANNING_PHOTO_RESULT_BOUND[], + text:string[] +} + + + +export type CAMERA_PHOTO_SIZE = { + width:number, + height:number +} +export type CallFunType = (str:string[],type:'auto'|'click') => void; +export type CALL_BACK_TYPE_PRIVATE = (str:string[])=>void +export type AUTH_CALL_BACK_TYPE = (auth:boolean)=>void + +export type BARCODEFORMAT = 'AZTEC' + | 'CODABAR' + | 'CODE_39' + | 'CODE_93' + | 'CODE_128' + | 'DATA_MATRIX' + | 'EAN_8' + | 'EAN_13' + | 'ITF' + | 'MAXICODE' + | 'PDF_417' + | 'QR_CODE' + | 'RSS_14' + | 'RSS_EXPANDED' + | 'UPC_A' + | 'UPC_E' + | 'UPC_EAN_EXTENSION'; + +export type SCANNING_OPTIONS = { + width:number, + height:number, + //前置还是后置摄像头 + cameraDevice:'FRONT'|'BACK', + /** 放大倍数1-10效果要看你的设备,并一定有用。越小视频越宽,越大视野越小。 */ + zoom?:number, + // 是否连续扫码识别,相对的间隔如果是自动的话根据设备性能一般是50-300ms之间 + // 默认为false即单次识别就停止需要手动继续识别 + continuousScan?:boolean, + //识别成功后是否震动设备 + vibatar?:boolean, + //单位毫秒,扫描识别间隔/及抓拍间隔 + scanSpeedduration?:450, + //是否打开识别码的功能,暂不支持设置,默认就是识别功能,等我完善 + scanningQrCode?:boolean, + //扫码成功后是否保存图片,暂未实现,等我完善 + isSavePhoto?:boolean, + /** + * 开识别条码的类型 + * 如果需要指定识别类型的条码时有用。比如快递单上有多个码制 + * 如果指定为条码,就可以避免识别二维码了。 + * ,暂不支持设置,等我完善 + */ + qrCodeType?:BARCODEFORMAT|null, + flashMode:boolean +} diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/mp-weixin/index.vue b/uni_modules/x-mlkit-scannig-u/utssdk/mp-weixin/index.vue new file mode 100644 index 0000000..3d31f73 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/mp-weixin/index.vue @@ -0,0 +1,124 @@ + + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/mp-weixin/zxing.js b/uni_modules/x-mlkit-scannig-u/utssdk/mp-weixin/zxing.js new file mode 100644 index 0000000..c97dc1e --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/mp-weixin/zxing.js @@ -0,0 +1,2909 @@ +class BitMatrix { + constructor(data, width) { + this.width = width; + this.height = data.length / width; + this.data = data; + } + static createEmpty(width, height) { + return new BitMatrix(new Uint8ClampedArray(width * height), width); + } + get(x, y) { + if (x < 0 || x >= this.width || y < 0 || y >= this.height) { + return false; + } + return !!this.data[y * this.width + x]; + } + set(x, y, v) { + this.data[y * this.width + x] = v ? 1 : 0; + } + setRegion(left, top, width, height, v) { + for (let y = top; y < top + height; y++) { + for (let x = left; x < left + width; x++) { + this.set(x, y, !!v); + } + } + } +} + +const REGION_SIZE = 8; +const MIN_DYNAMIC_RANGE = 24; +function numBetween(value, min, max) { + return value < min ? min : value > max ? max : value; +} +// Like BitMatrix but accepts arbitry Uint8 values +class Matrix { + constructor(width, height, buffer) { + this.width = width; + const bufferSize = width * height; + if (buffer && buffer.length !== bufferSize) { + throw new Error("Wrong buffer size"); + } + this.data = buffer || new Uint8ClampedArray(bufferSize); + } + get(x, y) { + return this.data[y * this.width + x]; + } + set(x, y, value) { + this.data[y * this.width + x] = value; + } +} +function binarize(data, width, height, returnInverted, greyscaleWeights, canOverwriteImage) { + const pixelCount = width * height; + if (data.length !== pixelCount * 4) { + throw new Error("Malformed data passed to binarizer."); + } + // assign the greyscale and binary image within the rgba buffer as the rgba image will not be needed after conversion + let bufferOffset = 0; + // Convert image to greyscale + let greyscaleBuffer; + if (canOverwriteImage) { + greyscaleBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + bufferOffset += pixelCount; + } + const greyscalePixels = new Matrix(width, height, greyscaleBuffer); + if (greyscaleWeights.useIntegerApproximation) { + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const pixelPosition = (y * width + x) * 4; + const r = data[pixelPosition]; + const g = data[pixelPosition + 1]; + const b = data[pixelPosition + 2]; + greyscalePixels.set(x, y, + // tslint:disable-next-line no-bitwise + (greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b + 128) >> 8); + } + } + } + else { + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const pixelPosition = (y * width + x) * 4; + const r = data[pixelPosition]; + const g = data[pixelPosition + 1]; + const b = data[pixelPosition + 2]; + greyscalePixels.set(x, y, greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b); + } + } + } + const horizontalRegionCount = Math.ceil(width / REGION_SIZE); + const verticalRegionCount = Math.ceil(height / REGION_SIZE); + const blackPointsCount = horizontalRegionCount * verticalRegionCount; + let blackPointsBuffer; + if (canOverwriteImage) { + blackPointsBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, blackPointsCount); + bufferOffset += blackPointsCount; + } + const blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount, blackPointsBuffer); + for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + let min = Infinity; + let max = 0; + for (let y = 0; y < REGION_SIZE; y++) { + for (let x = 0; x < REGION_SIZE; x++) { + const pixelLumosity = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y); + min = Math.min(min, pixelLumosity); + max = Math.max(max, pixelLumosity); + } + } + // We could also compute the real average of all pixels but following the assumption that the qr code consists + // of bright and dark pixels and essentially not much in between, by (min + max)/2 we make the cut really between + // those two classes. If using the average over all pixel in a block of mostly bright pixels and few dark pixels, + // the avg would tend to the bright side and darker bright pixels could be interpreted as dark. + let average = (min + max) / 2; + // Small bias towards black by moving the threshold up. We do this, as in the finder patterns white holes tend + // to appear which makes them undetectable. + const blackBias = 1.11; + average = Math.min(255, average * blackBias); + if (max - min <= MIN_DYNAMIC_RANGE) { + // If variation within the block is low, assume this is a block with only light or only + // dark pixels. In that case we do not want to use the average, as it would divide this + // low contrast area into black and white pixels, essentially creating data out of noise. + // + // Default the blackpoint for these blocks to be half the min - effectively white them out + average = min / 2; + if (verticalRegion > 0 && hortizontalRegion > 0) { + // Correct the "white background" assumption for blocks that have neighbors by comparing + // the pixels in this block to the previously calculated black points. This is based on + // the fact that dark barcode symbology is always surrounded by some amount of light + // background for which reasonable black point estimates were made. The bp estimated at + // the boundaries is used for the interior. + // The (min < bp) is arbitrary but works better than other heuristics that were tried. + const averageNeighborBlackPoint = (blackPoints.get(hortizontalRegion, verticalRegion - 1) + + (2 * blackPoints.get(hortizontalRegion - 1, verticalRegion)) + + blackPoints.get(hortizontalRegion - 1, verticalRegion - 1)) / 4; + if (min < averageNeighborBlackPoint) { + average = averageNeighborBlackPoint; // no need to apply black bias as already applied to neighbors + } + } + } + blackPoints.set(hortizontalRegion, verticalRegion, average); + } + } + let binarized; + if (canOverwriteImage) { + const binarizedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + bufferOffset += pixelCount; + binarized = new BitMatrix(binarizedBuffer, width); + } + else { + binarized = BitMatrix.createEmpty(width, height); + } + let inverted = null; + if (returnInverted) { + if (canOverwriteImage) { + const invertedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + inverted = new BitMatrix(invertedBuffer, width); + } + else { + inverted = BitMatrix.createEmpty(width, height); + } + } + for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + const left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3); + const top = numBetween(verticalRegion, 2, verticalRegionCount - 3); + let sum = 0; + for (let xRegion = -2; xRegion <= 2; xRegion++) { + for (let yRegion = -2; yRegion <= 2; yRegion++) { + sum += blackPoints.get(left + xRegion, top + yRegion); + } + } + const threshold = sum / 25; + for (let xRegion = 0; xRegion < REGION_SIZE; xRegion++) { + for (let yRegion = 0; yRegion < REGION_SIZE; yRegion++) { + const x = hortizontalRegion * REGION_SIZE + xRegion; + const y = verticalRegion * REGION_SIZE + yRegion; + const lum = greyscalePixels.get(x, y); + binarized.set(x, y, lum <= threshold); + if (returnInverted) { + inverted.set(x, y, !(lum <= threshold)); + } + } + } + } + } + if (returnInverted) { + return { binarized, inverted }; + } + return { binarized }; +} + +// tslint:disable:no-bitwise +class BitStream { + constructor(bytes) { + this.byteOffset = 0; + this.bitOffset = 0; + this.bytes = bytes; + } + readBits(numBits) { + if (numBits < 1 || numBits > 32 || numBits > this.available()) { + throw new Error("Cannot read " + numBits.toString() + " bits"); + } + let result = 0; + // First, read remainder from current byte + if (this.bitOffset > 0) { + const bitsLeft = 8 - this.bitOffset; + const toRead = numBits < bitsLeft ? numBits : bitsLeft; + const bitsToNotRead = bitsLeft - toRead; + const mask = (0xFF >> (8 - toRead)) << bitsToNotRead; + result = (this.bytes[this.byteOffset] & mask) >> bitsToNotRead; + numBits -= toRead; + this.bitOffset += toRead; + if (this.bitOffset === 8) { + this.bitOffset = 0; + this.byteOffset++; + } + } + // Next read whole bytes + if (numBits > 0) { + while (numBits >= 8) { + result = (result << 8) | (this.bytes[this.byteOffset] & 0xFF); + this.byteOffset++; + numBits -= 8; + } + // Finally read a partial byte + if (numBits > 0) { + const bitsToNotRead = 8 - numBits; + const mask = (0xFF >> bitsToNotRead) << bitsToNotRead; + result = (result << numBits) | ((this.bytes[this.byteOffset] & mask) >> bitsToNotRead); + this.bitOffset += numBits; + } + } + return result; + } + available() { + return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset; + } +} + +// tslint:disable:no-bitwise +var Mode; +(function (Mode) { + Mode["Numeric"] = "numeric"; + Mode["Alphanumeric"] = "alphanumeric"; + Mode["Byte"] = "byte"; + Mode["Kanji"] = "kanji"; + Mode["ECI"] = "eci"; + Mode["StructuredAppend"] = "structuredappend"; +})(Mode || (Mode = {})); +var ModeByte; +(function (ModeByte) { + ModeByte[ModeByte["Terminator"] = 0] = "Terminator"; + ModeByte[ModeByte["Numeric"] = 1] = "Numeric"; + ModeByte[ModeByte["Alphanumeric"] = 2] = "Alphanumeric"; + ModeByte[ModeByte["Byte"] = 4] = "Byte"; + ModeByte[ModeByte["Kanji"] = 8] = "Kanji"; + ModeByte[ModeByte["ECI"] = 7] = "ECI"; + ModeByte[ModeByte["StructuredAppend"] = 3] = "StructuredAppend"; + // FNC1FirstPosition = 0x5, + // FNC1SecondPosition = 0x9, +})(ModeByte || (ModeByte = {})); +function decodeNumeric(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [10, 12, 14][size]; + let length = stream.readBits(characterCountSize); + // Read digits in groups of 3 + while (length >= 3) { + const num = stream.readBits(10); + if (num >= 1000) { + throw new Error("Invalid numeric value above 999"); + } + const a = Math.floor(num / 100); + const b = Math.floor(num / 10) % 10; + const c = num % 10; + bytes.push(48 + a, 48 + b, 48 + c); + text += a.toString() + b.toString() + c.toString(); + length -= 3; + } + // If the number of digits aren't a multiple of 3, the remaining digits are special cased. + if (length === 2) { + const num = stream.readBits(7); + if (num >= 100) { + throw new Error("Invalid numeric value above 99"); + } + const a = Math.floor(num / 10); + const b = num % 10; + bytes.push(48 + a, 48 + b); + text += a.toString() + b.toString(); + } + else if (length === 1) { + const num = stream.readBits(4); + if (num >= 10) { + throw new Error("Invalid numeric value above 9"); + } + bytes.push(48 + num); + text += num.toString(); + } + return { bytes, text }; +} +const AlphanumericCharacterCodes = [ + "0", "1", "2", "3", "4", "5", "6", "7", "8", + "9", "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", "Q", + "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + " ", "$", "%", "*", "+", "-", ".", "/", ":", +]; +function decodeAlphanumeric(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [9, 11, 13][size]; + let length = stream.readBits(characterCountSize); + while (length >= 2) { + const v = stream.readBits(11); + const a = Math.floor(v / 45); + const b = v % 45; + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0), AlphanumericCharacterCodes[b].charCodeAt(0)); + text += AlphanumericCharacterCodes[a] + AlphanumericCharacterCodes[b]; + length -= 2; + } + if (length === 1) { + const a = stream.readBits(6); + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0)); + text += AlphanumericCharacterCodes[a]; + } + return { bytes, text }; +} +function decodeByte(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [8, 16, 16][size]; + const length = stream.readBits(characterCountSize); + for (let i = 0; i < length; i++) { + const b = stream.readBits(8); + bytes.push(b); + } + try { + text += decodeURIComponent(bytes.map(b => `%${("0" + b.toString(16)).substr(-2)}`).join("")); + } + catch (_a) { + // failed to decode + } + return { bytes, text }; +} +function decodeKanji(stream, size) { + const bytes = []; + const characterCountSize = [8, 10, 12][size]; + const length = stream.readBits(characterCountSize); + for (let i = 0; i < length; i++) { + const k = stream.readBits(13); + let c = (Math.floor(k / 0xC0) << 8) | (k % 0xC0); + if (c < 0x1F00) { + c += 0x8140; + } + else { + c += 0xC140; + } + bytes.push(c >> 8, c & 0xFF); + } + const text = new TextDecoder("shift-jis").decode(Uint8Array.from(bytes)); + return { bytes, text }; +} +function decode$2(data, version) { + const stream = new BitStream(data); + // There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2). + const size = version <= 9 ? 0 : version <= 26 ? 1 : 2; + const result = { + text: "", + bytes: [], + chunks: [], + version, + }; + while (stream.available() >= 4) { + const mode = stream.readBits(4); + if (mode === ModeByte.Terminator) { + return result; + } + else if (mode === ModeByte.ECI) { + if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(7), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(14), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(21), + }); + } + else { + // ECI data seems corrupted + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: -1, + }); + } + } + else if (mode === ModeByte.Numeric) { + const numericResult = decodeNumeric(stream, size); + result.text += numericResult.text; + result.bytes.push(...numericResult.bytes); + result.chunks.push({ + type: Mode.Numeric, + text: numericResult.text, + }); + } + else if (mode === ModeByte.Alphanumeric) { + const alphanumericResult = decodeAlphanumeric(stream, size); + result.text += alphanumericResult.text; + result.bytes.push(...alphanumericResult.bytes); + result.chunks.push({ + type: Mode.Alphanumeric, + text: alphanumericResult.text, + }); + } + else if (mode === ModeByte.Byte) { + const byteResult = decodeByte(stream, size); + result.text += byteResult.text; + result.bytes.push(...byteResult.bytes); + result.chunks.push({ + type: Mode.Byte, + bytes: byteResult.bytes, + text: byteResult.text, + }); + } + else if (mode === ModeByte.Kanji) { + const kanjiResult = decodeKanji(stream, size); + result.text += kanjiResult.text; + result.bytes.push(...kanjiResult.bytes); + result.chunks.push({ + type: Mode.Kanji, + bytes: kanjiResult.bytes, + text: kanjiResult.text, + }); + } + else if (mode === ModeByte.StructuredAppend) { + result.chunks.push({ + type: Mode.StructuredAppend, + currentSequence: stream.readBits(4), + totalSequence: stream.readBits(4), + parity: stream.readBits(8), + }); + } + } + // If there is no data left, or the remaining bits are all 0, then that counts as a termination marker + if (stream.available() === 0 || stream.readBits(stream.available()) === 0) { + return result; + } +} + +class GenericGFPoly { + constructor(field, coefficients) { + if (coefficients.length === 0) { + throw new Error("No coefficients."); + } + this.field = field; + const coefficientsLength = coefficients.length; + if (coefficientsLength > 1 && coefficients[0] === 0) { + // Leading term must be non-zero for anything except the constant polynomial "0" + let firstNonZero = 1; + while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) { + firstNonZero++; + } + if (firstNonZero === coefficientsLength) { + this.coefficients = field.zero.coefficients; + } + else { + this.coefficients = new Uint8ClampedArray(coefficientsLength - firstNonZero); + for (let i = 0; i < this.coefficients.length; i++) { + this.coefficients[i] = coefficients[firstNonZero + i]; + } + } + } + else { + this.coefficients = coefficients; + } + } + degree() { + return this.coefficients.length - 1; + } + isZero() { + return this.coefficients[0] === 0; + } + getCoefficient(degree) { + return this.coefficients[this.coefficients.length - 1 - degree]; + } + addOrSubtract(other) { + if (this.isZero()) { + return other; + } + if (other.isZero()) { + return this; + } + let smallerCoefficients = this.coefficients; + let largerCoefficients = other.coefficients; + if (smallerCoefficients.length > largerCoefficients.length) { + [smallerCoefficients, largerCoefficients] = [largerCoefficients, smallerCoefficients]; + } + const sumDiff = new Uint8ClampedArray(largerCoefficients.length); + const lengthDiff = largerCoefficients.length - smallerCoefficients.length; + for (let i = 0; i < lengthDiff; i++) { + sumDiff[i] = largerCoefficients[i]; + } + for (let i = lengthDiff; i < largerCoefficients.length; i++) { + sumDiff[i] = addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); + } + return new GenericGFPoly(this.field, sumDiff); + } + multiply(scalar) { + if (scalar === 0) { + return this.field.zero; + } + if (scalar === 1) { + return this; + } + const size = this.coefficients.length; + const product = new Uint8ClampedArray(size); + for (let i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], scalar); + } + return new GenericGFPoly(this.field, product); + } + multiplyPoly(other) { + if (this.isZero() || other.isZero()) { + return this.field.zero; + } + const aCoefficients = this.coefficients; + const aLength = aCoefficients.length; + const bCoefficients = other.coefficients; + const bLength = bCoefficients.length; + const product = new Uint8ClampedArray(aLength + bLength - 1); + for (let i = 0; i < aLength; i++) { + const aCoeff = aCoefficients[i]; + for (let j = 0; j < bLength; j++) { + product[i + j] = addOrSubtractGF(product[i + j], this.field.multiply(aCoeff, bCoefficients[j])); + } + } + return new GenericGFPoly(this.field, product); + } + multiplyByMonomial(degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid degree less than 0"); + } + if (coefficient === 0) { + return this.field.zero; + } + const size = this.coefficients.length; + const product = new Uint8ClampedArray(size + degree); + for (let i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], coefficient); + } + return new GenericGFPoly(this.field, product); + } + evaluateAt(a) { + let result = 0; + if (a === 0) { + // Just return the x^0 coefficient + return this.getCoefficient(0); + } + const size = this.coefficients.length; + if (a === 1) { + // Just the sum of the coefficients + this.coefficients.forEach((coefficient) => { + result = addOrSubtractGF(result, coefficient); + }); + return result; + } + result = this.coefficients[0]; + for (let i = 1; i < size; i++) { + result = addOrSubtractGF(this.field.multiply(a, result), this.coefficients[i]); + } + return result; + } +} + +function addOrSubtractGF(a, b) { + return a ^ b; // tslint:disable-line:no-bitwise +} +class GenericGF { + constructor(primitive, size, genBase) { + this.primitive = primitive; + this.size = size; + this.generatorBase = genBase; + this.expTable = new Array(this.size); + this.logTable = new Array(this.size); + let x = 1; + for (let i = 0; i < this.size; i++) { + this.expTable[i] = x; + x = x * 2; + if (x >= this.size) { + x = (x ^ this.primitive) & (this.size - 1); // tslint:disable-line:no-bitwise + } + } + for (let i = 0; i < this.size - 1; i++) { + this.logTable[this.expTable[i]] = i; + } + this.zero = new GenericGFPoly(this, Uint8ClampedArray.from([0])); + this.one = new GenericGFPoly(this, Uint8ClampedArray.from([1])); + } + multiply(a, b) { + if (a === 0 || b === 0) { + return 0; + } + return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)]; + } + inverse(a) { + if (a === 0) { + throw new Error("Can't invert 0"); + } + return this.expTable[this.size - this.logTable[a] - 1]; + } + buildMonomial(degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid monomial degree less than 0"); + } + if (coefficient === 0) { + return this.zero; + } + const coefficients = new Uint8ClampedArray(degree + 1); + coefficients[0] = coefficient; + return new GenericGFPoly(this, coefficients); + } + log(a) { + if (a === 0) { + throw new Error("Can't take log(0)"); + } + return this.logTable[a]; + } + exp(a) { + return this.expTable[a]; + } +} + +function runEuclideanAlgorithm(field, a, b, R) { + // Assume a's degree is >= b's + if (a.degree() < b.degree()) { + [a, b] = [b, a]; + } + let rLast = a; + let r = b; + let tLast = field.zero; + let t = field.one; + // Run Euclidean algorithm until r's degree is less than R/2 + while (r.degree() >= R / 2) { + const rLastLast = rLast; + const tLastLast = tLast; + rLast = r; + tLast = t; + // Divide rLastLast by rLast, with quotient in q and remainder in r + if (rLast.isZero()) { + // Euclidean algorithm already terminated? + return null; + } + r = rLastLast; + let q = field.zero; + const denominatorLeadingTerm = rLast.getCoefficient(rLast.degree()); + const dltInverse = field.inverse(denominatorLeadingTerm); + while (r.degree() >= rLast.degree() && !r.isZero()) { + const degreeDiff = r.degree() - rLast.degree(); + const scale = field.multiply(r.getCoefficient(r.degree()), dltInverse); + q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); + r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); + } + t = q.multiplyPoly(tLast).addOrSubtract(tLastLast); + if (r.degree() >= rLast.degree()) { + return null; + } + } + const sigmaTildeAtZero = t.getCoefficient(0); + if (sigmaTildeAtZero === 0) { + return null; + } + const inverse = field.inverse(sigmaTildeAtZero); + return [t.multiply(inverse), r.multiply(inverse)]; +} +function findErrorLocations(field, errorLocator) { + // This is a direct application of Chien's search + const numErrors = errorLocator.degree(); + if (numErrors === 1) { + return [errorLocator.getCoefficient(1)]; + } + const result = new Array(numErrors); + let errorCount = 0; + for (let i = 1; i < field.size && errorCount < numErrors; i++) { + if (errorLocator.evaluateAt(i) === 0) { + result[errorCount] = field.inverse(i); + errorCount++; + } + } + if (errorCount !== numErrors) { + return null; + } + return result; +} +function findErrorMagnitudes(field, errorEvaluator, errorLocations) { + // This is directly applying Forney's Formula + const s = errorLocations.length; + const result = new Array(s); + for (let i = 0; i < s; i++) { + const xiInverse = field.inverse(errorLocations[i]); + let denominator = 1; + for (let j = 0; j < s; j++) { + if (i !== j) { + denominator = field.multiply(denominator, addOrSubtractGF(1, field.multiply(errorLocations[j], xiInverse))); + } + } + result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator)); + if (field.generatorBase !== 0) { + result[i] = field.multiply(result[i], xiInverse); + } + } + return result; +} +function decode$1(bytes, twoS) { + const outputBytes = new Uint8ClampedArray(bytes.length); + outputBytes.set(bytes); + const field = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 + const poly = new GenericGFPoly(field, outputBytes); + const syndromeCoefficients = new Uint8ClampedArray(twoS); + let error = false; + for (let s = 0; s < twoS; s++) { + const evaluation = poly.evaluateAt(field.exp(s + field.generatorBase)); + syndromeCoefficients[syndromeCoefficients.length - 1 - s] = evaluation; + if (evaluation !== 0) { + error = true; + } + } + if (!error) { + return outputBytes; + } + const syndrome = new GenericGFPoly(field, syndromeCoefficients); + const sigmaOmega = runEuclideanAlgorithm(field, field.buildMonomial(twoS, 1), syndrome, twoS); + if (sigmaOmega === null) { + return null; + } + const errorLocations = findErrorLocations(field, sigmaOmega[0]); + if (errorLocations == null) { + return null; + } + const errorMagnitudes = findErrorMagnitudes(field, sigmaOmega[1], errorLocations); + for (let i = 0; i < errorLocations.length; i++) { + const position = outputBytes.length - 1 - field.log(errorLocations[i]); + if (position < 0) { + return null; + } + outputBytes[position] = addOrSubtractGF(outputBytes[position], errorMagnitudes[i]); + } + return outputBytes; +} + +const VERSIONS = [ + { + infoBits: null, + versionNumber: 1, + alignmentPatternCenters: [], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 7, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + { + ecCodewordsPerBlock: 13, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 13 }], + }, + { + ecCodewordsPerBlock: 17, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 2, + alignmentPatternCenters: [6, 18], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 34 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 28 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 22 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 3, + alignmentPatternCenters: [6, 22], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 15, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 55 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 44 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 17 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 4, + alignmentPatternCenters: [6, 26], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 80 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 32 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 24 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 5, + alignmentPatternCenters: [6, 30], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 108 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 43 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 11 }, + { numBlocks: 2, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: null, + versionNumber: 6, + alignmentPatternCenters: [6, 34], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 68 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 27 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 15 }], + }, + ], + }, + { + infoBits: 0x07C94, + versionNumber: 7, + alignmentPatternCenters: [6, 22, 38], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 78 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 31 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + { numBlocks: 1, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x085BC, + versionNumber: 8, + alignmentPatternCenters: [6, 24, 42], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 97 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 38 }, + { numBlocks: 2, dataCodewordsPerBlock: 39 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 18 }, + { numBlocks: 2, dataCodewordsPerBlock: 19 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 14 }, + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x09A99, + versionNumber: 9, + alignmentPatternCenters: [6, 26, 46], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 116 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0A4D3, + versionNumber: 10, + alignmentPatternCenters: [6, 28, 50], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 68 }, + { numBlocks: 2, dataCodewordsPerBlock: 69 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 43 }, + { numBlocks: 1, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x0BBF6, + versionNumber: 11, + alignmentPatternCenters: [6, 30, 54], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 81 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 50 }, + { numBlocks: 4, dataCodewordsPerBlock: 51 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + { numBlocks: 4, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 12 }, + { numBlocks: 8, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0C762, + versionNumber: 12, + alignmentPatternCenters: [6, 32, 58], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 92 }, + { numBlocks: 2, dataCodewordsPerBlock: 93 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 20 }, + { numBlocks: 6, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x0D847, + versionNumber: 13, + alignmentPatternCenters: [6, 34, 62], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 107 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 37 }, + { numBlocks: 1, dataCodewordsPerBlock: 38 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 20 }, + { numBlocks: 4, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 11 }, + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: 0x0E60D, + versionNumber: 14, + alignmentPatternCenters: [6, 26, 46, 66], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 40 }, + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 16 }, + { numBlocks: 5, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 5, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0F928, + versionNumber: 15, + alignmentPatternCenters: [6, 26, 48, 70], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 87 }, + { numBlocks: 1, dataCodewordsPerBlock: 88 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + { numBlocks: 5, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 7, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x10B78, + versionNumber: 16, + alignmentPatternCenters: [6, 26, 50, 74], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 98 }, + { numBlocks: 1, dataCodewordsPerBlock: 99 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1145D, + versionNumber: 17, + alignmentPatternCenters: [6, 30, 54, 78], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 1, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 22 }, + { numBlocks: 15, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 17, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x12A17, + versionNumber: 18, + alignmentPatternCenters: [6, 30, 56, 82], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 120 }, + { numBlocks: 1, dataCodewordsPerBlock: 121 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 43 }, + { numBlocks: 4, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x13532, + versionNumber: 19, + alignmentPatternCenters: [6, 30, 58, 86], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 113 }, + { numBlocks: 4, dataCodewordsPerBlock: 114 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 44 }, + { numBlocks: 11, dataCodewordsPerBlock: 45 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 21 }, + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 13 }, + { numBlocks: 16, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x149A6, + versionNumber: 20, + alignmentPatternCenters: [6, 34, 62, 90], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 41 }, + { numBlocks: 13, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 5, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 15 }, + { numBlocks: 10, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x15683, + versionNumber: 21, + alignmentPatternCenters: [6, 28, 50, 72, 94], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 116 }, + { numBlocks: 4, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 42 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 16 }, + { numBlocks: 6, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x168C9, + versionNumber: 22, + alignmentPatternCenters: [6, 26, 50, 74, 98], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 111 }, + { numBlocks: 7, dataCodewordsPerBlock: 112 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 46 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 34, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: 0x177EC, + versionNumber: 23, + alignmentPatternCenters: [6, 30, 54, 74, 102], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 121 }, + { numBlocks: 5, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + { numBlocks: 14, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 16, dataCodewordsPerBlock: 15 }, + { numBlocks: 14, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x18EC4, + versionNumber: 24, + alignmentPatternCenters: [6, 28, 54, 80, 106], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 45 }, + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 30, dataCodewordsPerBlock: 16 }, + { numBlocks: 2, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x191E1, + versionNumber: 25, + alignmentPatternCenters: [6, 32, 58, 84, 110], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 106 }, + { numBlocks: 4, dataCodewordsPerBlock: 107 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 47 }, + { numBlocks: 13, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1AFAB, + versionNumber: 26, + alignmentPatternCenters: [6, 30, 58, 86, 114], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 114 }, + { numBlocks: 2, dataCodewordsPerBlock: 115 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 46 }, + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 28, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 33, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x1B08E, + versionNumber: 27, + alignmentPatternCenters: [6, 34, 62, 90, 118], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 23 }, + { numBlocks: 26, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1CC1A, + versionNumber: 28, + alignmentPatternCenters: [6, 26, 50, 74, 98, 122], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 117 }, + { numBlocks: 10, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 45 }, + { numBlocks: 23, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 24 }, + { numBlocks: 31, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 31, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1D33F, + versionNumber: 29, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 116 }, + { numBlocks: 7, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 21, dataCodewordsPerBlock: 45 }, + { numBlocks: 7, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + { numBlocks: 37, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 26, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1ED75, + versionNumber: 30, + alignmentPatternCenters: [6, 26, 52, 78, 104, 130], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 115 }, + { numBlocks: 10, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 47 }, + { numBlocks: 10, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 25, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 25, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1F250, + versionNumber: 31, + alignmentPatternCenters: [6, 30, 56, 82, 108, 134], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 3, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 46 }, + { numBlocks: 29, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 24 }, + { numBlocks: 1, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x209D5, + versionNumber: 32, + alignmentPatternCenters: [6, 34, 60, 86, 112, 138], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 115 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 24 }, + { numBlocks: 35, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 35, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x216F0, + versionNumber: 33, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 21, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 24 }, + { numBlocks: 19, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x228BA, + versionNumber: 34, + alignmentPatternCenters: [6, 34, 62, 90, 118, 146], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 6, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 44, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 59, dataCodewordsPerBlock: 16 }, + { numBlocks: 1, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x2379F, + versionNumber: 35, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126, 150], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 121 }, + { numBlocks: 7, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 47 }, + { numBlocks: 26, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 39, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 41, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x24B0B, + versionNumber: 36, + alignmentPatternCenters: [6, 24, 50, 76, 102, 128, 154], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 121 }, + { numBlocks: 14, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 47 }, + { numBlocks: 34, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 46, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 64, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x2542E, + versionNumber: 37, + alignmentPatternCenters: [6, 28, 54, 80, 106, 132, 158], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 46 }, + { numBlocks: 14, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 49, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 24, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x26A64, + versionNumber: 38, + alignmentPatternCenters: [6, 32, 58, 84, 110, 136, 162], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 122 }, + { numBlocks: 18, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 46 }, + { numBlocks: 32, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 48, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 15 }, + { numBlocks: 32, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x27541, + versionNumber: 39, + alignmentPatternCenters: [6, 26, 54, 82, 110, 138, 166], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 40, dataCodewordsPerBlock: 47 }, + { numBlocks: 7, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 43, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 15 }, + { numBlocks: 67, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x28C69, + versionNumber: 40, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142, 170], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 118 }, + { numBlocks: 6, dataCodewordsPerBlock: 119 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 18, dataCodewordsPerBlock: 47 }, + { numBlocks: 31, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 34, dataCodewordsPerBlock: 24 }, + { numBlocks: 34, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 15 }, + { numBlocks: 61, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, +]; + +// tslint:disable:no-bitwise +function numBitsDiffering(x, y) { + let z = x ^ y; + let bitCount = 0; + while (z) { + bitCount++; + z &= z - 1; + } + return bitCount; +} +function pushBit(bit, byte) { + return (byte << 1) | bit; +} +// tslint:enable:no-bitwise +const FORMAT_INFO_TABLE = [ + { bits: 0x5412, formatInfo: { errorCorrectionLevel: 1, dataMask: 0 } }, + { bits: 0x5125, formatInfo: { errorCorrectionLevel: 1, dataMask: 1 } }, + { bits: 0x5E7C, formatInfo: { errorCorrectionLevel: 1, dataMask: 2 } }, + { bits: 0x5B4B, formatInfo: { errorCorrectionLevel: 1, dataMask: 3 } }, + { bits: 0x45F9, formatInfo: { errorCorrectionLevel: 1, dataMask: 4 } }, + { bits: 0x40CE, formatInfo: { errorCorrectionLevel: 1, dataMask: 5 } }, + { bits: 0x4F97, formatInfo: { errorCorrectionLevel: 1, dataMask: 6 } }, + { bits: 0x4AA0, formatInfo: { errorCorrectionLevel: 1, dataMask: 7 } }, + { bits: 0x77C4, formatInfo: { errorCorrectionLevel: 0, dataMask: 0 } }, + { bits: 0x72F3, formatInfo: { errorCorrectionLevel: 0, dataMask: 1 } }, + { bits: 0x7DAA, formatInfo: { errorCorrectionLevel: 0, dataMask: 2 } }, + { bits: 0x789D, formatInfo: { errorCorrectionLevel: 0, dataMask: 3 } }, + { bits: 0x662F, formatInfo: { errorCorrectionLevel: 0, dataMask: 4 } }, + { bits: 0x6318, formatInfo: { errorCorrectionLevel: 0, dataMask: 5 } }, + { bits: 0x6C41, formatInfo: { errorCorrectionLevel: 0, dataMask: 6 } }, + { bits: 0x6976, formatInfo: { errorCorrectionLevel: 0, dataMask: 7 } }, + { bits: 0x1689, formatInfo: { errorCorrectionLevel: 3, dataMask: 0 } }, + { bits: 0x13BE, formatInfo: { errorCorrectionLevel: 3, dataMask: 1 } }, + { bits: 0x1CE7, formatInfo: { errorCorrectionLevel: 3, dataMask: 2 } }, + { bits: 0x19D0, formatInfo: { errorCorrectionLevel: 3, dataMask: 3 } }, + { bits: 0x0762, formatInfo: { errorCorrectionLevel: 3, dataMask: 4 } }, + { bits: 0x0255, formatInfo: { errorCorrectionLevel: 3, dataMask: 5 } }, + { bits: 0x0D0C, formatInfo: { errorCorrectionLevel: 3, dataMask: 6 } }, + { bits: 0x083B, formatInfo: { errorCorrectionLevel: 3, dataMask: 7 } }, + { bits: 0x355F, formatInfo: { errorCorrectionLevel: 2, dataMask: 0 } }, + { bits: 0x3068, formatInfo: { errorCorrectionLevel: 2, dataMask: 1 } }, + { bits: 0x3F31, formatInfo: { errorCorrectionLevel: 2, dataMask: 2 } }, + { bits: 0x3A06, formatInfo: { errorCorrectionLevel: 2, dataMask: 3 } }, + { bits: 0x24B4, formatInfo: { errorCorrectionLevel: 2, dataMask: 4 } }, + { bits: 0x2183, formatInfo: { errorCorrectionLevel: 2, dataMask: 5 } }, + { bits: 0x2EDA, formatInfo: { errorCorrectionLevel: 2, dataMask: 6 } }, + { bits: 0x2BED, formatInfo: { errorCorrectionLevel: 2, dataMask: 7 } }, +]; +const DATA_MASKS = [ + (p) => ((p.y + p.x) % 2) === 0, + (p) => (p.y % 2) === 0, + (p) => p.x % 3 === 0, + (p) => (p.y + p.x) % 3 === 0, + (p) => (Math.floor(p.y / 2) + Math.floor(p.x / 3)) % 2 === 0, + (p) => ((p.x * p.y) % 2) + ((p.x * p.y) % 3) === 0, + (p) => ((((p.y * p.x) % 2) + (p.y * p.x) % 3) % 2) === 0, + (p) => ((((p.y + p.x) % 2) + (p.y * p.x) % 3) % 2) === 0, +]; +function buildFunctionPatternMask(version) { + const dimension = 17 + 4 * version.versionNumber; + const matrix = BitMatrix.createEmpty(dimension, dimension); + matrix.setRegion(0, 0, 9, 9, true); // Top left finder pattern + separator + format + matrix.setRegion(dimension - 8, 0, 8, 9, true); // Top right finder pattern + separator + format + matrix.setRegion(0, dimension - 8, 9, 8, true); // Bottom left finder pattern + separator + format + // Alignment patterns + for (const x of version.alignmentPatternCenters) { + for (const y of version.alignmentPatternCenters) { + if (!(x === 6 && y === 6 || x === 6 && y === dimension - 7 || x === dimension - 7 && y === 6)) { + matrix.setRegion(x - 2, y - 2, 5, 5, true); + } + } + } + matrix.setRegion(6, 9, 1, dimension - 17, true); // Vertical timing pattern + matrix.setRegion(9, 6, dimension - 17, 1, true); // Horizontal timing pattern + if (version.versionNumber > 6) { + matrix.setRegion(dimension - 11, 0, 3, 6, true); // Version info, top right + matrix.setRegion(0, dimension - 11, 6, 3, true); // Version info, bottom left + } + return matrix; +} +function readCodewords(matrix, version, formatInfo) { + const dataMask = DATA_MASKS[formatInfo.dataMask]; + const dimension = matrix.height; + const functionPatternMask = buildFunctionPatternMask(version); + const codewords = []; + let currentByte = 0; + let bitsRead = 0; + // Read columns in pairs, from right to left + let readingUp = true; + for (let columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) { + if (columnIndex === 6) { // Skip whole column with vertical alignment pattern; + columnIndex--; + } + for (let i = 0; i < dimension; i++) { + const y = readingUp ? dimension - 1 - i : i; + for (let columnOffset = 0; columnOffset < 2; columnOffset++) { + const x = columnIndex - columnOffset; + if (!functionPatternMask.get(x, y)) { + bitsRead++; + let bit = matrix.get(x, y); + if (dataMask({ y, x })) { + bit = !bit; + } + currentByte = pushBit(bit, currentByte); + if (bitsRead === 8) { // Whole bytes + codewords.push(currentByte); + bitsRead = 0; + currentByte = 0; + } + } + } + } + readingUp = !readingUp; + } + return codewords; +} +function readVersion(matrix) { + const dimension = matrix.height; + const provisionalVersion = Math.floor((dimension - 17) / 4); + if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code + return VERSIONS[provisionalVersion - 1]; + } + let topRightVersionBits = 0; + for (let y = 5; y >= 0; y--) { + for (let x = dimension - 9; x >= dimension - 11; x--) { + topRightVersionBits = pushBit(matrix.get(x, y), topRightVersionBits); + } + } + let bottomLeftVersionBits = 0; + for (let x = 5; x >= 0; x--) { + for (let y = dimension - 9; y >= dimension - 11; y--) { + bottomLeftVersionBits = pushBit(matrix.get(x, y), bottomLeftVersionBits); + } + } + let bestDifference = Infinity; + let bestVersion; + for (const version of VERSIONS) { + if (version.infoBits === topRightVersionBits || version.infoBits === bottomLeftVersionBits) { + return version; + } + let difference = numBitsDiffering(topRightVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + difference = numBitsDiffering(bottomLeftVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + } + // We can tolerate up to 3 bits of error since no two version info codewords will + // differ in less than 8 bits. + if (bestDifference <= 3) { + return bestVersion; + } +} +function readFormatInformation(matrix) { + let topLeftFormatInfoBits = 0; + for (let x = 0; x <= 8; x++) { + if (x !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits); + } + } + for (let y = 7; y >= 0; y--) { + if (y !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits); + } + } + const dimension = matrix.height; + let topRightBottomRightFormatInfoBits = 0; + for (let y = dimension - 1; y >= dimension - 7; y--) { // bottom left + topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits); + } + for (let x = dimension - 8; x < dimension; x++) { // top right + topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits); + } + let bestDifference = Infinity; + let bestFormatInfo = null; + for (const { bits, formatInfo } of FORMAT_INFO_TABLE) { + if (bits === topLeftFormatInfoBits || bits === topRightBottomRightFormatInfoBits) { + return formatInfo; + } + let difference = numBitsDiffering(topLeftFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option + difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + } + } + // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match + if (bestDifference <= 3) { + return bestFormatInfo; + } + return null; +} +function getDataBlocks(codewords, version, ecLevel) { + const ecInfo = version.errorCorrectionLevels[ecLevel]; + const dataBlocks = []; + let totalCodewords = 0; + ecInfo.ecBlocks.forEach(block => { + for (let i = 0; i < block.numBlocks; i++) { + dataBlocks.push({ numDataCodewords: block.dataCodewordsPerBlock, codewords: [] }); + totalCodewords += block.dataCodewordsPerBlock + ecInfo.ecCodewordsPerBlock; + } + }); + // In some cases the QR code will be malformed enough that we pull off more or less than we should. + // If we pull off less there's nothing we can do. + // If we pull off more we can safely truncate + if (codewords.length < totalCodewords) { + return null; + } + codewords = codewords.slice(0, totalCodewords); + const shortBlockSize = ecInfo.ecBlocks[0].dataCodewordsPerBlock; + // Pull codewords to fill the blocks up to the minimum size + for (let i = 0; i < shortBlockSize; i++) { + for (const dataBlock of dataBlocks) { + dataBlock.codewords.push(codewords.shift()); + } + } + // If there are any large blocks, pull codewords to fill the last element of those + if (ecInfo.ecBlocks.length > 1) { + const smallBlockCount = ecInfo.ecBlocks[0].numBlocks; + const largeBlockCount = ecInfo.ecBlocks[1].numBlocks; + for (let i = 0; i < largeBlockCount; i++) { + dataBlocks[smallBlockCount + i].codewords.push(codewords.shift()); + } + } + // Add the rest of the codewords to the blocks. These are the error correction codewords. + while (codewords.length > 0) { + for (const dataBlock of dataBlocks) { + dataBlock.codewords.push(codewords.shift()); + } + } + return dataBlocks; +} +function decodeMatrix(matrix) { + const version = readVersion(matrix); + if (!version) { + return null; + } + const formatInfo = readFormatInformation(matrix); + if (!formatInfo) { + return null; + } + const codewords = readCodewords(matrix, version, formatInfo); + const dataBlocks = getDataBlocks(codewords, version, formatInfo.errorCorrectionLevel); + if (!dataBlocks) { + return null; + } + // Count total number of data bytes + const totalBytes = dataBlocks.reduce((a, b) => a + b.numDataCodewords, 0); + const resultBytes = new Uint8ClampedArray(totalBytes); + let resultIndex = 0; + for (const dataBlock of dataBlocks) { + const correctedBytes = decode$1(dataBlock.codewords, dataBlock.codewords.length - dataBlock.numDataCodewords); + if (!correctedBytes) { + return null; + } + for (let i = 0; i < dataBlock.numDataCodewords; i++) { + resultBytes[resultIndex++] = correctedBytes[i]; + } + } + try { + return decode$2(resultBytes, version.versionNumber); + } + catch (_a) { + return null; + } +} +function decode(matrix) { + if (matrix == null) { + return null; + } + const result = decodeMatrix(matrix); + if (result) { + return result; + } + // Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line. + for (let x = 0; x < matrix.width; x++) { + for (let y = x + 1; y < matrix.height; y++) { + if (matrix.get(x, y) !== matrix.get(y, x)) { + matrix.set(x, y, !matrix.get(x, y)); + matrix.set(y, x, !matrix.get(y, x)); + } + } + } + return decodeMatrix(matrix); +} + +function squareToQuadrilateral(p1, p2, p3, p4) { + const dx3 = p1.x - p2.x + p3.x - p4.x; + const dy3 = p1.y - p2.y + p3.y - p4.y; + if (dx3 === 0 && dy3 === 0) { // Affine + return { + a11: p2.x - p1.x, + a12: p2.y - p1.y, + a13: 0, + a21: p3.x - p2.x, + a22: p3.y - p2.y, + a23: 0, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } + else { + const dx1 = p2.x - p3.x; + const dx2 = p4.x - p3.x; + const dy1 = p2.y - p3.y; + const dy2 = p4.y - p3.y; + const denominator = dx1 * dy2 - dx2 * dy1; + const a13 = (dx3 * dy2 - dx2 * dy3) / denominator; + const a23 = (dx1 * dy3 - dx3 * dy1) / denominator; + return { + a11: p2.x - p1.x + a13 * p2.x, + a12: p2.y - p1.y + a13 * p2.y, + a13, + a21: p4.x - p1.x + a23 * p4.x, + a22: p4.y - p1.y + a23 * p4.y, + a23, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } +} +function quadrilateralToSquare(p1, p2, p3, p4) { + // Here, the adjoint serves as the inverse: + const sToQ = squareToQuadrilateral(p1, p2, p3, p4); + return { + a11: sToQ.a22 * sToQ.a33 - sToQ.a23 * sToQ.a32, + a12: sToQ.a13 * sToQ.a32 - sToQ.a12 * sToQ.a33, + a13: sToQ.a12 * sToQ.a23 - sToQ.a13 * sToQ.a22, + a21: sToQ.a23 * sToQ.a31 - sToQ.a21 * sToQ.a33, + a22: sToQ.a11 * sToQ.a33 - sToQ.a13 * sToQ.a31, + a23: sToQ.a13 * sToQ.a21 - sToQ.a11 * sToQ.a23, + a31: sToQ.a21 * sToQ.a32 - sToQ.a22 * sToQ.a31, + a32: sToQ.a12 * sToQ.a31 - sToQ.a11 * sToQ.a32, + a33: sToQ.a11 * sToQ.a22 - sToQ.a12 * sToQ.a21, + }; +} +function times(a, b) { + return { + a11: a.a11 * b.a11 + a.a21 * b.a12 + a.a31 * b.a13, + a12: a.a12 * b.a11 + a.a22 * b.a12 + a.a32 * b.a13, + a13: a.a13 * b.a11 + a.a23 * b.a12 + a.a33 * b.a13, + a21: a.a11 * b.a21 + a.a21 * b.a22 + a.a31 * b.a23, + a22: a.a12 * b.a21 + a.a22 * b.a22 + a.a32 * b.a23, + a23: a.a13 * b.a21 + a.a23 * b.a22 + a.a33 * b.a23, + a31: a.a11 * b.a31 + a.a21 * b.a32 + a.a31 * b.a33, + a32: a.a12 * b.a31 + a.a22 * b.a32 + a.a32 * b.a33, + a33: a.a13 * b.a31 + a.a23 * b.a32 + a.a33 * b.a33, + }; +} +function extract(image, location) { + const qToS = quadrilateralToSquare({ x: 3.5, y: 3.5 }, { x: location.dimension - 3.5, y: 3.5 }, { x: location.dimension - 6.5, y: location.dimension - 6.5 }, { x: 3.5, y: location.dimension - 3.5 }); + const sToQ = squareToQuadrilateral(location.topLeft, location.topRight, location.alignmentPattern, location.bottomLeft); + const transform = times(sToQ, qToS); + const matrix = BitMatrix.createEmpty(location.dimension, location.dimension); + const mappingFunction = (x, y) => { + const denominator = transform.a13 * x + transform.a23 * y + transform.a33; + return { + x: (transform.a11 * x + transform.a21 * y + transform.a31) / denominator, + y: (transform.a12 * x + transform.a22 * y + transform.a32) / denominator, + }; + }; + for (let y = 0; y < location.dimension; y++) { + for (let x = 0; x < location.dimension; x++) { + const xValue = x + 0.5; + const yValue = y + 0.5; + const sourcePixel = mappingFunction(xValue, yValue); + matrix.set(x, y, image.get(Math.floor(sourcePixel.x), Math.floor(sourcePixel.y))); + } + } + return { + matrix, + mappingFunction, + }; +} + +const MAX_FINDERPATTERNS_TO_SEARCH = 5; +const MIN_QUAD_RATIO = 0.5; +const MAX_QUAD_RATIO = 1.5; +const distance = (a, b) => Math.sqrt(Math.pow((b.x - a.x), 2) + Math.pow((b.y - a.y), 2)); +function sum(values) { + return values.reduce((a, b) => a + b); +} +// Takes three finder patterns and organizes them into topLeft, topRight, etc +function reorderFinderPatterns(pattern1, pattern2, pattern3) { + // Find distances between pattern centers + const oneTwoDistance = distance(pattern1, pattern2); + const twoThreeDistance = distance(pattern2, pattern3); + const oneThreeDistance = distance(pattern1, pattern3); + let bottomLeft; + let topLeft; + let topRight; + // Assume one closest to other two is B; A and C will just be guesses at first + if (twoThreeDistance >= oneTwoDistance && twoThreeDistance >= oneThreeDistance) { + [bottomLeft, topLeft, topRight] = [pattern2, pattern1, pattern3]; + } + else if (oneThreeDistance >= twoThreeDistance && oneThreeDistance >= oneTwoDistance) { + [bottomLeft, topLeft, topRight] = [pattern1, pattern2, pattern3]; + } + else { + [bottomLeft, topLeft, topRight] = [pattern1, pattern3, pattern2]; + } + // Use cross product to figure out whether bottomLeft (A) and topRight (C) are correct or flipped in relation to topLeft (B) + // This asks whether BC x BA has a positive z component, which is the arrangement we want. If it's negative, then + // we've got it flipped around and should swap topRight and bottomLeft. + if (((topRight.x - topLeft.x) * (bottomLeft.y - topLeft.y)) - ((topRight.y - topLeft.y) * (bottomLeft.x - topLeft.x)) < 0) { + [bottomLeft, topRight] = [topRight, bottomLeft]; + } + return { bottomLeft, topLeft, topRight }; +} +// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns +function computeDimension(topLeft, topRight, bottomLeft, matrix) { + const moduleSize = (sum(countBlackWhiteRun(topLeft, bottomLeft, matrix, 5)) / 7 + // Divide by 7 since the ratio is 1:1:3:1:1 + sum(countBlackWhiteRun(topLeft, topRight, matrix, 5)) / 7 + + sum(countBlackWhiteRun(bottomLeft, topLeft, matrix, 5)) / 7 + + sum(countBlackWhiteRun(topRight, topLeft, matrix, 5)) / 7) / 4; + if (moduleSize < 1) { + throw new Error("Invalid module size"); + } + const topDimension = Math.round(distance(topLeft, topRight) / moduleSize); + const sideDimension = Math.round(distance(topLeft, bottomLeft) / moduleSize); + let dimension = Math.floor((topDimension + sideDimension) / 2) + 7; + switch (dimension % 4) { + case 0: + dimension++; + break; + case 2: + dimension--; + break; + } + return { dimension, moduleSize }; +} +// Takes an origin point and an end point and counts the sizes of the black white run from the origin towards the end point. +// Returns an array of elements, representing the pixel size of the black white run. +// Uses a variant of http://en.wikipedia.org/wiki/Bresenham's_line_algorithm +function countBlackWhiteRunTowardsPoint(origin, end, matrix, length) { + const switchPoints = [{ x: Math.floor(origin.x), y: Math.floor(origin.y) }]; + const steep = Math.abs(end.y - origin.y) > Math.abs(end.x - origin.x); + let fromX; + let fromY; + let toX; + let toY; + if (steep) { + fromX = Math.floor(origin.y); + fromY = Math.floor(origin.x); + toX = Math.floor(end.y); + toY = Math.floor(end.x); + } + else { + fromX = Math.floor(origin.x); + fromY = Math.floor(origin.y); + toX = Math.floor(end.x); + toY = Math.floor(end.y); + } + const dx = Math.abs(toX - fromX); + const dy = Math.abs(toY - fromY); + let error = Math.floor(-dx / 2); + const xStep = fromX < toX ? 1 : -1; + const yStep = fromY < toY ? 1 : -1; + let currentPixel = true; + // Loop up until x == toX, but not beyond + for (let x = fromX, y = fromY; x !== toX + xStep; x += xStep) { + // Does current pixel mean we have moved white to black or vice versa? + // Scanning black in state 0,2 and white in state 1, so if we find the wrong + // color, advance to next state or end if we are in state 2 already + const realX = steep ? y : x; + const realY = steep ? x : y; + if (matrix.get(realX, realY) !== currentPixel) { + currentPixel = !currentPixel; + switchPoints.push({ x: realX, y: realY }); + if (switchPoints.length === length + 1) { + break; + } + } + error += dy; + if (error > 0) { + if (y === toY) { + break; + } + y += yStep; + error -= dx; + } + } + const distances = []; + for (let i = 0; i < length; i++) { + if (switchPoints[i] && switchPoints[i + 1]) { + distances.push(distance(switchPoints[i], switchPoints[i + 1])); + } + else { + distances.push(0); + } + } + return distances; +} +// Takes an origin point and an end point and counts the sizes of the black white run in the origin point +// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes +// of the black white run. Takes a length which represents the number of switches from black to white to look for. +function countBlackWhiteRun(origin, end, matrix, length) { + const rise = end.y - origin.y; + const run = end.x - origin.x; + const towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2)); + const awayFromEnd = countBlackWhiteRunTowardsPoint(origin, { x: origin.x - run, y: origin.y - rise }, matrix, Math.ceil(length / 2)); + const middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel + return awayFromEnd.concat(middleValue).concat(...towardsEnd); +} +// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the "error" - +// that is the amount the run diverges from the expected ratio +function scoreBlackWhiteRun(sequence, ratios) { + const averageSize = sum(sequence) / sum(ratios); + let error = 0; + ratios.forEach((ratio, i) => { + error += Math.pow((sequence[i] - ratio * averageSize), 2); + }); + return { averageSize, error }; +} +// Takes an X,Y point and an array of sizes and scores the point against those ratios. +// For example for a finder pattern takes the ratio list of 1:1:3:1:1 and checks horizontal, vertical and diagonal ratios +// against that. +function scorePattern(point, ratios, matrix) { + try { + const horizontalRun = countBlackWhiteRun(point, { x: -1, y: point.y }, matrix, ratios.length); + const verticalRun = countBlackWhiteRun(point, { x: point.x, y: -1 }, matrix, ratios.length); + const topLeftPoint = { + x: Math.max(0, point.x - point.y) - 1, + y: Math.max(0, point.y - point.x) - 1, + }; + const topLeftBottomRightRun = countBlackWhiteRun(point, topLeftPoint, matrix, ratios.length); + const bottomLeftPoint = { + x: Math.min(matrix.width, point.x + point.y) + 1, + y: Math.min(matrix.height, point.y + point.x) + 1, + }; + const bottomLeftTopRightRun = countBlackWhiteRun(point, bottomLeftPoint, matrix, ratios.length); + const horzError = scoreBlackWhiteRun(horizontalRun, ratios); + const vertError = scoreBlackWhiteRun(verticalRun, ratios); + const diagDownError = scoreBlackWhiteRun(topLeftBottomRightRun, ratios); + const diagUpError = scoreBlackWhiteRun(bottomLeftTopRightRun, ratios); + const ratioError = Math.sqrt(horzError.error * horzError.error + + vertError.error * vertError.error + + diagDownError.error * diagDownError.error + + diagUpError.error * diagUpError.error); + const avgSize = (horzError.averageSize + vertError.averageSize + diagDownError.averageSize + diagUpError.averageSize) / 4; + const sizeError = (Math.pow((horzError.averageSize - avgSize), 2) + + Math.pow((vertError.averageSize - avgSize), 2) + + Math.pow((diagDownError.averageSize - avgSize), 2) + + Math.pow((diagUpError.averageSize - avgSize), 2)) / avgSize; + return ratioError + sizeError; + } + catch (_a) { + return Infinity; + } +} +function recenterLocation(matrix, p) { + let leftX = Math.round(p.x); + while (matrix.get(leftX, Math.round(p.y))) { + leftX--; + } + let rightX = Math.round(p.x); + while (matrix.get(rightX, Math.round(p.y))) { + rightX++; + } + const x = (leftX + rightX) / 2; + let topY = Math.round(p.y); + while (matrix.get(Math.round(x), topY)) { + topY--; + } + let bottomY = Math.round(p.y); + while (matrix.get(Math.round(x), bottomY)) { + bottomY++; + } + const y = (topY + bottomY) / 2; + return { x, y }; +} +function locate(matrix) { + const finderPatternQuads = []; + let activeFinderPatternQuads = []; + const alignmentPatternQuads = []; + let activeAlignmentPatternQuads = []; + for (let y = 0; y <= matrix.height; y++) { + let length = 0; + let lastBit = false; + let scans = [0, 0, 0, 0, 0]; + for (let x = -1; x <= matrix.width; x++) { + const v = matrix.get(x, y); + if (v === lastBit) { + length++; + } + else { + scans = [scans[1], scans[2], scans[3], scans[4], length]; + length = 1; + lastBit = v; + // Do the last 5 color changes ~ match the expected ratio for a finder pattern? 1:1:3:1:1 of b:w:b:w:b + const averageFinderPatternBlocksize = sum(scans) / 7; + const validFinderPattern = Math.abs(scans[0] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[1] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[2] - 3 * averageFinderPatternBlocksize) < 3 * averageFinderPatternBlocksize && + Math.abs(scans[3] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[4] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + !v; // And make sure the current pixel is white since finder patterns are bordered in white + // Do the last 3 color changes ~ match the expected ratio for an alignment pattern? 1:1:1 of w:b:w + const averageAlignmentPatternBlocksize = sum(scans.slice(-3)) / 3; + const validAlignmentPattern = Math.abs(scans[2] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[3] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[4] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + v; // Is the current pixel black since alignment patterns are bordered in black + if (validFinderPattern) { + // Compute the start and end x values of the large center black square + const endX = x - scans[3] - scans[4]; + const startX = endX - scans[2]; + const line = { startX, endX, y }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + const matchingQuads = activeFinderPatternQuads.filter(q => (startX >= q.bottom.startX && startX <= q.bottom.endX) || + (endX >= q.bottom.startX && startX <= q.bottom.endX) || + (startX <= q.bottom.startX && endX >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO))); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeFinderPatternQuads.push({ top: line, bottom: line }); + } + } + if (validAlignmentPattern) { + // Compute the start and end x values of the center black square + const endX = x - scans[4]; + const startX = endX - scans[3]; + const line = { startX, y, endX }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + const matchingQuads = activeAlignmentPatternQuads.filter(q => (startX >= q.bottom.startX && startX <= q.bottom.endX) || + (endX >= q.bottom.startX && startX <= q.bottom.endX) || + (startX <= q.bottom.startX && endX >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO))); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeAlignmentPatternQuads.push({ top: line, bottom: line }); + } + } + } + } + finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y !== y && q.bottom.y - q.top.y >= 2)); + activeFinderPatternQuads = activeFinderPatternQuads.filter(q => q.bottom.y === y); + alignmentPatternQuads.push(...activeAlignmentPatternQuads.filter(q => q.bottom.y !== y)); + activeAlignmentPatternQuads = activeAlignmentPatternQuads.filter(q => q.bottom.y === y); + } + finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y - q.top.y >= 2)); + alignmentPatternQuads.push(...activeAlignmentPatternQuads); + // Refactored from cozmo/jsQR to (hopefully) circumvent an issue in Safari 13+ on both Mac and iOS (also including + // iOS Chrome and other Safari iOS derivatives). Safari was very occasionally and apparently not deterministically + // throwing a "RangeError: Array size is not a small enough positive integer." exception seemingly within the second + // .map of the original code (here the second for-loop). This second .map contained a nested .map call over the same + // array instance which was the chained result from previous calls to .map, .filter and .sort which potentially caused + // this bug in Safari? + // Also see https://github.com/cozmo/jsQR/issues/157 and https://bugs.webkit.org/show_bug.cgi?id=211619#c3 + const scoredFinderPatternPositions = []; + for (const quad of finderPatternQuads) { + if (quad.bottom.y - quad.top.y < 2) { + // All quads must be at least 2px tall since the center square is larger than a block + continue; + } + // calculate quad center + const x = (quad.top.startX + quad.top.endX + quad.bottom.startX + quad.bottom.endX) / 4; + const y = (quad.top.y + quad.bottom.y + 1) / 2; + if (!matrix.get(Math.round(x), Math.round(y))) { + continue; + } + const lengths = [quad.top.endX - quad.top.startX, quad.bottom.endX - quad.bottom.startX, quad.bottom.y - quad.top.y + 1]; + const size = sum(lengths) / lengths.length; + // Initial scoring of finder pattern quads by looking at their ratios, not taking into account position + const score = scorePattern({ x: Math.round(x), y: Math.round(y) }, [1, 1, 3, 1, 1], matrix); + scoredFinderPatternPositions.push({ score, x, y, size }); + } + if (scoredFinderPatternPositions.length < 3) { + // A QR code has 3 finder patterns, therefore we need at least 3 candidates. + return null; + } + scoredFinderPatternPositions.sort((a, b) => a.score - b.score); + // Now take the top finder pattern options and try to find 2 other options with a similar size. + const finderPatternGroups = []; + for (let i = 0; i < Math.min(scoredFinderPatternPositions.length, MAX_FINDERPATTERNS_TO_SEARCH); ++i) { + const point = scoredFinderPatternPositions[i]; + const otherPoints = []; + for (const otherPoint of scoredFinderPatternPositions) { + if (otherPoint === point) { + continue; + } + otherPoints.push(Object.assign(Object.assign({}, otherPoint), { score: otherPoint.score + (Math.pow((otherPoint.size - point.size), 2)) / point.size })); + } + otherPoints.sort((a, b) => a.score - b.score); + finderPatternGroups.push({ + points: [point, otherPoints[0], otherPoints[1]], + score: point.score + otherPoints[0].score + otherPoints[1].score, // total combined score of the three points in the group + }); + } + finderPatternGroups.sort((a, b) => a.score - b.score); + const bestFinderPatternGroup = finderPatternGroups[0]; + const { topRight, topLeft, bottomLeft } = reorderFinderPatterns(...bestFinderPatternGroup.points); + const alignment = findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft); + const result = []; + if (alignment) { + result.push({ + alignmentPattern: { x: alignment.alignmentPattern.x, y: alignment.alignmentPattern.y }, + bottomLeft: { x: bottomLeft.x, y: bottomLeft.y }, + dimension: alignment.dimension, + topLeft: { x: topLeft.x, y: topLeft.y }, + topRight: { x: topRight.x, y: topRight.y }, + }); + } + // We normally use the center of the quads as the location of the tracking points, which is optimal for most cases and will account + // for a skew in the image. However, In some cases, a slight skew might not be real and instead be caused by image compression + // errors and/or low resolution. For those cases, we'd be better off centering the point exactly in the middle of the black area. We + // compute and return the location data for the naively centered points as it is little additional work and allows for multiple + // attempts at decoding harder images. + const midTopRight = recenterLocation(matrix, topRight); + const midTopLeft = recenterLocation(matrix, topLeft); + const midBottomLeft = recenterLocation(matrix, bottomLeft); + const centeredAlignment = findAlignmentPattern(matrix, alignmentPatternQuads, midTopRight, midTopLeft, midBottomLeft); + if (centeredAlignment) { + result.push({ + alignmentPattern: { x: centeredAlignment.alignmentPattern.x, y: centeredAlignment.alignmentPattern.y }, + bottomLeft: { x: midBottomLeft.x, y: midBottomLeft.y }, + topLeft: { x: midTopLeft.x, y: midTopLeft.y }, + topRight: { x: midTopRight.x, y: midTopRight.y }, + dimension: centeredAlignment.dimension, + }); + } + if (result.length === 0) { + return null; + } + return result; +} +function findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft) { + // Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code. + // We'll use these to help find the alignment pattern but also later when we do the extraction. + let dimension; + let moduleSize; + try { + ({ dimension, moduleSize } = computeDimension(topLeft, topRight, bottomLeft, matrix)); + } + catch (e) { + return null; + } + // Now find the alignment pattern + const bottomRightFinderPattern = { + x: topRight.x - topLeft.x + bottomLeft.x, + y: topRight.y - topLeft.y + bottomLeft.y, + }; + const modulesBetweenFinderPatterns = ((distance(topLeft, bottomLeft) + distance(topLeft, topRight)) / 2 / moduleSize); + const correctionToTopLeft = 1 - (3 / modulesBetweenFinderPatterns); + const expectedAlignmentPattern = { + x: topLeft.x + correctionToTopLeft * (bottomRightFinderPattern.x - topLeft.x), + y: topLeft.y + correctionToTopLeft * (bottomRightFinderPattern.y - topLeft.y), + }; + const alignmentPatterns = alignmentPatternQuads + .map(q => { + const x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4; + const y = (q.top.y + q.bottom.y + 1) / 2; + if (!matrix.get(Math.floor(x), Math.floor(y))) { + return; + } + const sizeScore = scorePattern({ x: Math.floor(x), y: Math.floor(y) }, [1, 1, 1], matrix); + const score = sizeScore + distance({ x, y }, expectedAlignmentPattern); + return { x, y, score }; + }) + .filter(v => !!v) + .sort((a, b) => a.score - b.score); + // If there are less than 15 modules between finder patterns it's a version 1 QR code and as such has no alignmemnt pattern + // so we can only use our best guess. + const alignmentPattern = modulesBetweenFinderPatterns >= 15 && alignmentPatterns.length ? alignmentPatterns[0] : expectedAlignmentPattern; + return { alignmentPattern, dimension }; +} + +function scan(matrix) { + const locations = locate(matrix); + if (!locations) { + return null; + } + for (const location of locations) { + const extracted = extract(matrix, location); + const decoded = decode(extracted.matrix); + if (decoded) { + return { + binaryData: decoded.bytes, + data: decoded.text, + chunks: decoded.chunks, + version: decoded.version, + location: { + topRightCorner: extracted.mappingFunction(location.dimension, 0), + topLeftCorner: extracted.mappingFunction(0, 0), + bottomRightCorner: extracted.mappingFunction(location.dimension, location.dimension), + bottomLeftCorner: extracted.mappingFunction(0, location.dimension), + topRightFinderPattern: location.topRight, + topLeftFinderPattern: location.topLeft, + bottomLeftFinderPattern: location.bottomLeft, + bottomRightAlignmentPattern: location.alignmentPattern, + }, + matrix: extracted.matrix, + }; + } + } + return null; +} +const defaultOptions = { + inversionAttempts: "attemptBoth", + greyScaleWeights: { + red: 0.2126, + green: 0.7152, + blue: 0.0722, + useIntegerApproximation: false, + }, + canOverwriteImage: true, +}; +function mergeObject(target, src) { + Object.keys(src).forEach(opt => { + target[opt] = src[opt]; + }); +} +function jsQR(data, width, height, providedOptions = {}) { + const options = Object.create(null); + mergeObject(options, defaultOptions); + mergeObject(options, providedOptions); + const tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst"; + const shouldInvert = options.inversionAttempts === "attemptBoth" || tryInvertedFirst; + const { binarized, inverted } = binarize(data, width, height, shouldInvert, options.greyScaleWeights, options.canOverwriteImage); + let result = scan(tryInvertedFirst ? inverted : binarized); + if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) { + result = scan(tryInvertedFirst ? binarized : inverted); + } + return result; +} +jsQR.default = jsQR; + +export { jsQR as default }; \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/web/index.vue b/uni_modules/x-mlkit-scannig-u/utssdk/web/index.vue new file mode 100644 index 0000000..05183b0 --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/web/index.vue @@ -0,0 +1,157 @@ + + \ No newline at end of file diff --git a/uni_modules/x-mlkit-scannig-u/utssdk/web/zxing.js b/uni_modules/x-mlkit-scannig-u/utssdk/web/zxing.js new file mode 100644 index 0000000..c97dc1e --- /dev/null +++ b/uni_modules/x-mlkit-scannig-u/utssdk/web/zxing.js @@ -0,0 +1,2909 @@ +class BitMatrix { + constructor(data, width) { + this.width = width; + this.height = data.length / width; + this.data = data; + } + static createEmpty(width, height) { + return new BitMatrix(new Uint8ClampedArray(width * height), width); + } + get(x, y) { + if (x < 0 || x >= this.width || y < 0 || y >= this.height) { + return false; + } + return !!this.data[y * this.width + x]; + } + set(x, y, v) { + this.data[y * this.width + x] = v ? 1 : 0; + } + setRegion(left, top, width, height, v) { + for (let y = top; y < top + height; y++) { + for (let x = left; x < left + width; x++) { + this.set(x, y, !!v); + } + } + } +} + +const REGION_SIZE = 8; +const MIN_DYNAMIC_RANGE = 24; +function numBetween(value, min, max) { + return value < min ? min : value > max ? max : value; +} +// Like BitMatrix but accepts arbitry Uint8 values +class Matrix { + constructor(width, height, buffer) { + this.width = width; + const bufferSize = width * height; + if (buffer && buffer.length !== bufferSize) { + throw new Error("Wrong buffer size"); + } + this.data = buffer || new Uint8ClampedArray(bufferSize); + } + get(x, y) { + return this.data[y * this.width + x]; + } + set(x, y, value) { + this.data[y * this.width + x] = value; + } +} +function binarize(data, width, height, returnInverted, greyscaleWeights, canOverwriteImage) { + const pixelCount = width * height; + if (data.length !== pixelCount * 4) { + throw new Error("Malformed data passed to binarizer."); + } + // assign the greyscale and binary image within the rgba buffer as the rgba image will not be needed after conversion + let bufferOffset = 0; + // Convert image to greyscale + let greyscaleBuffer; + if (canOverwriteImage) { + greyscaleBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + bufferOffset += pixelCount; + } + const greyscalePixels = new Matrix(width, height, greyscaleBuffer); + if (greyscaleWeights.useIntegerApproximation) { + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const pixelPosition = (y * width + x) * 4; + const r = data[pixelPosition]; + const g = data[pixelPosition + 1]; + const b = data[pixelPosition + 2]; + greyscalePixels.set(x, y, + // tslint:disable-next-line no-bitwise + (greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b + 128) >> 8); + } + } + } + else { + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const pixelPosition = (y * width + x) * 4; + const r = data[pixelPosition]; + const g = data[pixelPosition + 1]; + const b = data[pixelPosition + 2]; + greyscalePixels.set(x, y, greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b); + } + } + } + const horizontalRegionCount = Math.ceil(width / REGION_SIZE); + const verticalRegionCount = Math.ceil(height / REGION_SIZE); + const blackPointsCount = horizontalRegionCount * verticalRegionCount; + let blackPointsBuffer; + if (canOverwriteImage) { + blackPointsBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, blackPointsCount); + bufferOffset += blackPointsCount; + } + const blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount, blackPointsBuffer); + for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + let min = Infinity; + let max = 0; + for (let y = 0; y < REGION_SIZE; y++) { + for (let x = 0; x < REGION_SIZE; x++) { + const pixelLumosity = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y); + min = Math.min(min, pixelLumosity); + max = Math.max(max, pixelLumosity); + } + } + // We could also compute the real average of all pixels but following the assumption that the qr code consists + // of bright and dark pixels and essentially not much in between, by (min + max)/2 we make the cut really between + // those two classes. If using the average over all pixel in a block of mostly bright pixels and few dark pixels, + // the avg would tend to the bright side and darker bright pixels could be interpreted as dark. + let average = (min + max) / 2; + // Small bias towards black by moving the threshold up. We do this, as in the finder patterns white holes tend + // to appear which makes them undetectable. + const blackBias = 1.11; + average = Math.min(255, average * blackBias); + if (max - min <= MIN_DYNAMIC_RANGE) { + // If variation within the block is low, assume this is a block with only light or only + // dark pixels. In that case we do not want to use the average, as it would divide this + // low contrast area into black and white pixels, essentially creating data out of noise. + // + // Default the blackpoint for these blocks to be half the min - effectively white them out + average = min / 2; + if (verticalRegion > 0 && hortizontalRegion > 0) { + // Correct the "white background" assumption for blocks that have neighbors by comparing + // the pixels in this block to the previously calculated black points. This is based on + // the fact that dark barcode symbology is always surrounded by some amount of light + // background for which reasonable black point estimates were made. The bp estimated at + // the boundaries is used for the interior. + // The (min < bp) is arbitrary but works better than other heuristics that were tried. + const averageNeighborBlackPoint = (blackPoints.get(hortizontalRegion, verticalRegion - 1) + + (2 * blackPoints.get(hortizontalRegion - 1, verticalRegion)) + + blackPoints.get(hortizontalRegion - 1, verticalRegion - 1)) / 4; + if (min < averageNeighborBlackPoint) { + average = averageNeighborBlackPoint; // no need to apply black bias as already applied to neighbors + } + } + } + blackPoints.set(hortizontalRegion, verticalRegion, average); + } + } + let binarized; + if (canOverwriteImage) { + const binarizedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + bufferOffset += pixelCount; + binarized = new BitMatrix(binarizedBuffer, width); + } + else { + binarized = BitMatrix.createEmpty(width, height); + } + let inverted = null; + if (returnInverted) { + if (canOverwriteImage) { + const invertedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount); + inverted = new BitMatrix(invertedBuffer, width); + } + else { + inverted = BitMatrix.createEmpty(width, height); + } + } + for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + const left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3); + const top = numBetween(verticalRegion, 2, verticalRegionCount - 3); + let sum = 0; + for (let xRegion = -2; xRegion <= 2; xRegion++) { + for (let yRegion = -2; yRegion <= 2; yRegion++) { + sum += blackPoints.get(left + xRegion, top + yRegion); + } + } + const threshold = sum / 25; + for (let xRegion = 0; xRegion < REGION_SIZE; xRegion++) { + for (let yRegion = 0; yRegion < REGION_SIZE; yRegion++) { + const x = hortizontalRegion * REGION_SIZE + xRegion; + const y = verticalRegion * REGION_SIZE + yRegion; + const lum = greyscalePixels.get(x, y); + binarized.set(x, y, lum <= threshold); + if (returnInverted) { + inverted.set(x, y, !(lum <= threshold)); + } + } + } + } + } + if (returnInverted) { + return { binarized, inverted }; + } + return { binarized }; +} + +// tslint:disable:no-bitwise +class BitStream { + constructor(bytes) { + this.byteOffset = 0; + this.bitOffset = 0; + this.bytes = bytes; + } + readBits(numBits) { + if (numBits < 1 || numBits > 32 || numBits > this.available()) { + throw new Error("Cannot read " + numBits.toString() + " bits"); + } + let result = 0; + // First, read remainder from current byte + if (this.bitOffset > 0) { + const bitsLeft = 8 - this.bitOffset; + const toRead = numBits < bitsLeft ? numBits : bitsLeft; + const bitsToNotRead = bitsLeft - toRead; + const mask = (0xFF >> (8 - toRead)) << bitsToNotRead; + result = (this.bytes[this.byteOffset] & mask) >> bitsToNotRead; + numBits -= toRead; + this.bitOffset += toRead; + if (this.bitOffset === 8) { + this.bitOffset = 0; + this.byteOffset++; + } + } + // Next read whole bytes + if (numBits > 0) { + while (numBits >= 8) { + result = (result << 8) | (this.bytes[this.byteOffset] & 0xFF); + this.byteOffset++; + numBits -= 8; + } + // Finally read a partial byte + if (numBits > 0) { + const bitsToNotRead = 8 - numBits; + const mask = (0xFF >> bitsToNotRead) << bitsToNotRead; + result = (result << numBits) | ((this.bytes[this.byteOffset] & mask) >> bitsToNotRead); + this.bitOffset += numBits; + } + } + return result; + } + available() { + return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset; + } +} + +// tslint:disable:no-bitwise +var Mode; +(function (Mode) { + Mode["Numeric"] = "numeric"; + Mode["Alphanumeric"] = "alphanumeric"; + Mode["Byte"] = "byte"; + Mode["Kanji"] = "kanji"; + Mode["ECI"] = "eci"; + Mode["StructuredAppend"] = "structuredappend"; +})(Mode || (Mode = {})); +var ModeByte; +(function (ModeByte) { + ModeByte[ModeByte["Terminator"] = 0] = "Terminator"; + ModeByte[ModeByte["Numeric"] = 1] = "Numeric"; + ModeByte[ModeByte["Alphanumeric"] = 2] = "Alphanumeric"; + ModeByte[ModeByte["Byte"] = 4] = "Byte"; + ModeByte[ModeByte["Kanji"] = 8] = "Kanji"; + ModeByte[ModeByte["ECI"] = 7] = "ECI"; + ModeByte[ModeByte["StructuredAppend"] = 3] = "StructuredAppend"; + // FNC1FirstPosition = 0x5, + // FNC1SecondPosition = 0x9, +})(ModeByte || (ModeByte = {})); +function decodeNumeric(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [10, 12, 14][size]; + let length = stream.readBits(characterCountSize); + // Read digits in groups of 3 + while (length >= 3) { + const num = stream.readBits(10); + if (num >= 1000) { + throw new Error("Invalid numeric value above 999"); + } + const a = Math.floor(num / 100); + const b = Math.floor(num / 10) % 10; + const c = num % 10; + bytes.push(48 + a, 48 + b, 48 + c); + text += a.toString() + b.toString() + c.toString(); + length -= 3; + } + // If the number of digits aren't a multiple of 3, the remaining digits are special cased. + if (length === 2) { + const num = stream.readBits(7); + if (num >= 100) { + throw new Error("Invalid numeric value above 99"); + } + const a = Math.floor(num / 10); + const b = num % 10; + bytes.push(48 + a, 48 + b); + text += a.toString() + b.toString(); + } + else if (length === 1) { + const num = stream.readBits(4); + if (num >= 10) { + throw new Error("Invalid numeric value above 9"); + } + bytes.push(48 + num); + text += num.toString(); + } + return { bytes, text }; +} +const AlphanumericCharacterCodes = [ + "0", "1", "2", "3", "4", "5", "6", "7", "8", + "9", "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", "Q", + "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + " ", "$", "%", "*", "+", "-", ".", "/", ":", +]; +function decodeAlphanumeric(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [9, 11, 13][size]; + let length = stream.readBits(characterCountSize); + while (length >= 2) { + const v = stream.readBits(11); + const a = Math.floor(v / 45); + const b = v % 45; + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0), AlphanumericCharacterCodes[b].charCodeAt(0)); + text += AlphanumericCharacterCodes[a] + AlphanumericCharacterCodes[b]; + length -= 2; + } + if (length === 1) { + const a = stream.readBits(6); + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0)); + text += AlphanumericCharacterCodes[a]; + } + return { bytes, text }; +} +function decodeByte(stream, size) { + const bytes = []; + let text = ""; + const characterCountSize = [8, 16, 16][size]; + const length = stream.readBits(characterCountSize); + for (let i = 0; i < length; i++) { + const b = stream.readBits(8); + bytes.push(b); + } + try { + text += decodeURIComponent(bytes.map(b => `%${("0" + b.toString(16)).substr(-2)}`).join("")); + } + catch (_a) { + // failed to decode + } + return { bytes, text }; +} +function decodeKanji(stream, size) { + const bytes = []; + const characterCountSize = [8, 10, 12][size]; + const length = stream.readBits(characterCountSize); + for (let i = 0; i < length; i++) { + const k = stream.readBits(13); + let c = (Math.floor(k / 0xC0) << 8) | (k % 0xC0); + if (c < 0x1F00) { + c += 0x8140; + } + else { + c += 0xC140; + } + bytes.push(c >> 8, c & 0xFF); + } + const text = new TextDecoder("shift-jis").decode(Uint8Array.from(bytes)); + return { bytes, text }; +} +function decode$2(data, version) { + const stream = new BitStream(data); + // There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2). + const size = version <= 9 ? 0 : version <= 26 ? 1 : 2; + const result = { + text: "", + bytes: [], + chunks: [], + version, + }; + while (stream.available() >= 4) { + const mode = stream.readBits(4); + if (mode === ModeByte.Terminator) { + return result; + } + else if (mode === ModeByte.ECI) { + if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(7), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(14), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(21), + }); + } + else { + // ECI data seems corrupted + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: -1, + }); + } + } + else if (mode === ModeByte.Numeric) { + const numericResult = decodeNumeric(stream, size); + result.text += numericResult.text; + result.bytes.push(...numericResult.bytes); + result.chunks.push({ + type: Mode.Numeric, + text: numericResult.text, + }); + } + else if (mode === ModeByte.Alphanumeric) { + const alphanumericResult = decodeAlphanumeric(stream, size); + result.text += alphanumericResult.text; + result.bytes.push(...alphanumericResult.bytes); + result.chunks.push({ + type: Mode.Alphanumeric, + text: alphanumericResult.text, + }); + } + else if (mode === ModeByte.Byte) { + const byteResult = decodeByte(stream, size); + result.text += byteResult.text; + result.bytes.push(...byteResult.bytes); + result.chunks.push({ + type: Mode.Byte, + bytes: byteResult.bytes, + text: byteResult.text, + }); + } + else if (mode === ModeByte.Kanji) { + const kanjiResult = decodeKanji(stream, size); + result.text += kanjiResult.text; + result.bytes.push(...kanjiResult.bytes); + result.chunks.push({ + type: Mode.Kanji, + bytes: kanjiResult.bytes, + text: kanjiResult.text, + }); + } + else if (mode === ModeByte.StructuredAppend) { + result.chunks.push({ + type: Mode.StructuredAppend, + currentSequence: stream.readBits(4), + totalSequence: stream.readBits(4), + parity: stream.readBits(8), + }); + } + } + // If there is no data left, or the remaining bits are all 0, then that counts as a termination marker + if (stream.available() === 0 || stream.readBits(stream.available()) === 0) { + return result; + } +} + +class GenericGFPoly { + constructor(field, coefficients) { + if (coefficients.length === 0) { + throw new Error("No coefficients."); + } + this.field = field; + const coefficientsLength = coefficients.length; + if (coefficientsLength > 1 && coefficients[0] === 0) { + // Leading term must be non-zero for anything except the constant polynomial "0" + let firstNonZero = 1; + while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) { + firstNonZero++; + } + if (firstNonZero === coefficientsLength) { + this.coefficients = field.zero.coefficients; + } + else { + this.coefficients = new Uint8ClampedArray(coefficientsLength - firstNonZero); + for (let i = 0; i < this.coefficients.length; i++) { + this.coefficients[i] = coefficients[firstNonZero + i]; + } + } + } + else { + this.coefficients = coefficients; + } + } + degree() { + return this.coefficients.length - 1; + } + isZero() { + return this.coefficients[0] === 0; + } + getCoefficient(degree) { + return this.coefficients[this.coefficients.length - 1 - degree]; + } + addOrSubtract(other) { + if (this.isZero()) { + return other; + } + if (other.isZero()) { + return this; + } + let smallerCoefficients = this.coefficients; + let largerCoefficients = other.coefficients; + if (smallerCoefficients.length > largerCoefficients.length) { + [smallerCoefficients, largerCoefficients] = [largerCoefficients, smallerCoefficients]; + } + const sumDiff = new Uint8ClampedArray(largerCoefficients.length); + const lengthDiff = largerCoefficients.length - smallerCoefficients.length; + for (let i = 0; i < lengthDiff; i++) { + sumDiff[i] = largerCoefficients[i]; + } + for (let i = lengthDiff; i < largerCoefficients.length; i++) { + sumDiff[i] = addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); + } + return new GenericGFPoly(this.field, sumDiff); + } + multiply(scalar) { + if (scalar === 0) { + return this.field.zero; + } + if (scalar === 1) { + return this; + } + const size = this.coefficients.length; + const product = new Uint8ClampedArray(size); + for (let i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], scalar); + } + return new GenericGFPoly(this.field, product); + } + multiplyPoly(other) { + if (this.isZero() || other.isZero()) { + return this.field.zero; + } + const aCoefficients = this.coefficients; + const aLength = aCoefficients.length; + const bCoefficients = other.coefficients; + const bLength = bCoefficients.length; + const product = new Uint8ClampedArray(aLength + bLength - 1); + for (let i = 0; i < aLength; i++) { + const aCoeff = aCoefficients[i]; + for (let j = 0; j < bLength; j++) { + product[i + j] = addOrSubtractGF(product[i + j], this.field.multiply(aCoeff, bCoefficients[j])); + } + } + return new GenericGFPoly(this.field, product); + } + multiplyByMonomial(degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid degree less than 0"); + } + if (coefficient === 0) { + return this.field.zero; + } + const size = this.coefficients.length; + const product = new Uint8ClampedArray(size + degree); + for (let i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], coefficient); + } + return new GenericGFPoly(this.field, product); + } + evaluateAt(a) { + let result = 0; + if (a === 0) { + // Just return the x^0 coefficient + return this.getCoefficient(0); + } + const size = this.coefficients.length; + if (a === 1) { + // Just the sum of the coefficients + this.coefficients.forEach((coefficient) => { + result = addOrSubtractGF(result, coefficient); + }); + return result; + } + result = this.coefficients[0]; + for (let i = 1; i < size; i++) { + result = addOrSubtractGF(this.field.multiply(a, result), this.coefficients[i]); + } + return result; + } +} + +function addOrSubtractGF(a, b) { + return a ^ b; // tslint:disable-line:no-bitwise +} +class GenericGF { + constructor(primitive, size, genBase) { + this.primitive = primitive; + this.size = size; + this.generatorBase = genBase; + this.expTable = new Array(this.size); + this.logTable = new Array(this.size); + let x = 1; + for (let i = 0; i < this.size; i++) { + this.expTable[i] = x; + x = x * 2; + if (x >= this.size) { + x = (x ^ this.primitive) & (this.size - 1); // tslint:disable-line:no-bitwise + } + } + for (let i = 0; i < this.size - 1; i++) { + this.logTable[this.expTable[i]] = i; + } + this.zero = new GenericGFPoly(this, Uint8ClampedArray.from([0])); + this.one = new GenericGFPoly(this, Uint8ClampedArray.from([1])); + } + multiply(a, b) { + if (a === 0 || b === 0) { + return 0; + } + return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)]; + } + inverse(a) { + if (a === 0) { + throw new Error("Can't invert 0"); + } + return this.expTable[this.size - this.logTable[a] - 1]; + } + buildMonomial(degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid monomial degree less than 0"); + } + if (coefficient === 0) { + return this.zero; + } + const coefficients = new Uint8ClampedArray(degree + 1); + coefficients[0] = coefficient; + return new GenericGFPoly(this, coefficients); + } + log(a) { + if (a === 0) { + throw new Error("Can't take log(0)"); + } + return this.logTable[a]; + } + exp(a) { + return this.expTable[a]; + } +} + +function runEuclideanAlgorithm(field, a, b, R) { + // Assume a's degree is >= b's + if (a.degree() < b.degree()) { + [a, b] = [b, a]; + } + let rLast = a; + let r = b; + let tLast = field.zero; + let t = field.one; + // Run Euclidean algorithm until r's degree is less than R/2 + while (r.degree() >= R / 2) { + const rLastLast = rLast; + const tLastLast = tLast; + rLast = r; + tLast = t; + // Divide rLastLast by rLast, with quotient in q and remainder in r + if (rLast.isZero()) { + // Euclidean algorithm already terminated? + return null; + } + r = rLastLast; + let q = field.zero; + const denominatorLeadingTerm = rLast.getCoefficient(rLast.degree()); + const dltInverse = field.inverse(denominatorLeadingTerm); + while (r.degree() >= rLast.degree() && !r.isZero()) { + const degreeDiff = r.degree() - rLast.degree(); + const scale = field.multiply(r.getCoefficient(r.degree()), dltInverse); + q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); + r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); + } + t = q.multiplyPoly(tLast).addOrSubtract(tLastLast); + if (r.degree() >= rLast.degree()) { + return null; + } + } + const sigmaTildeAtZero = t.getCoefficient(0); + if (sigmaTildeAtZero === 0) { + return null; + } + const inverse = field.inverse(sigmaTildeAtZero); + return [t.multiply(inverse), r.multiply(inverse)]; +} +function findErrorLocations(field, errorLocator) { + // This is a direct application of Chien's search + const numErrors = errorLocator.degree(); + if (numErrors === 1) { + return [errorLocator.getCoefficient(1)]; + } + const result = new Array(numErrors); + let errorCount = 0; + for (let i = 1; i < field.size && errorCount < numErrors; i++) { + if (errorLocator.evaluateAt(i) === 0) { + result[errorCount] = field.inverse(i); + errorCount++; + } + } + if (errorCount !== numErrors) { + return null; + } + return result; +} +function findErrorMagnitudes(field, errorEvaluator, errorLocations) { + // This is directly applying Forney's Formula + const s = errorLocations.length; + const result = new Array(s); + for (let i = 0; i < s; i++) { + const xiInverse = field.inverse(errorLocations[i]); + let denominator = 1; + for (let j = 0; j < s; j++) { + if (i !== j) { + denominator = field.multiply(denominator, addOrSubtractGF(1, field.multiply(errorLocations[j], xiInverse))); + } + } + result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator)); + if (field.generatorBase !== 0) { + result[i] = field.multiply(result[i], xiInverse); + } + } + return result; +} +function decode$1(bytes, twoS) { + const outputBytes = new Uint8ClampedArray(bytes.length); + outputBytes.set(bytes); + const field = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 + const poly = new GenericGFPoly(field, outputBytes); + const syndromeCoefficients = new Uint8ClampedArray(twoS); + let error = false; + for (let s = 0; s < twoS; s++) { + const evaluation = poly.evaluateAt(field.exp(s + field.generatorBase)); + syndromeCoefficients[syndromeCoefficients.length - 1 - s] = evaluation; + if (evaluation !== 0) { + error = true; + } + } + if (!error) { + return outputBytes; + } + const syndrome = new GenericGFPoly(field, syndromeCoefficients); + const sigmaOmega = runEuclideanAlgorithm(field, field.buildMonomial(twoS, 1), syndrome, twoS); + if (sigmaOmega === null) { + return null; + } + const errorLocations = findErrorLocations(field, sigmaOmega[0]); + if (errorLocations == null) { + return null; + } + const errorMagnitudes = findErrorMagnitudes(field, sigmaOmega[1], errorLocations); + for (let i = 0; i < errorLocations.length; i++) { + const position = outputBytes.length - 1 - field.log(errorLocations[i]); + if (position < 0) { + return null; + } + outputBytes[position] = addOrSubtractGF(outputBytes[position], errorMagnitudes[i]); + } + return outputBytes; +} + +const VERSIONS = [ + { + infoBits: null, + versionNumber: 1, + alignmentPatternCenters: [], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 7, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + { + ecCodewordsPerBlock: 13, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 13 }], + }, + { + ecCodewordsPerBlock: 17, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 2, + alignmentPatternCenters: [6, 18], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 34 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 28 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 22 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 3, + alignmentPatternCenters: [6, 22], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 15, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 55 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 44 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 17 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 4, + alignmentPatternCenters: [6, 26], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 80 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 32 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 24 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 5, + alignmentPatternCenters: [6, 30], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 108 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 43 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 11 }, + { numBlocks: 2, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: null, + versionNumber: 6, + alignmentPatternCenters: [6, 34], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 68 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 27 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 15 }], + }, + ], + }, + { + infoBits: 0x07C94, + versionNumber: 7, + alignmentPatternCenters: [6, 22, 38], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 78 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 31 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + { numBlocks: 1, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x085BC, + versionNumber: 8, + alignmentPatternCenters: [6, 24, 42], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 97 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 38 }, + { numBlocks: 2, dataCodewordsPerBlock: 39 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 18 }, + { numBlocks: 2, dataCodewordsPerBlock: 19 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 14 }, + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x09A99, + versionNumber: 9, + alignmentPatternCenters: [6, 26, 46], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 116 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0A4D3, + versionNumber: 10, + alignmentPatternCenters: [6, 28, 50], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 68 }, + { numBlocks: 2, dataCodewordsPerBlock: 69 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 43 }, + { numBlocks: 1, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x0BBF6, + versionNumber: 11, + alignmentPatternCenters: [6, 30, 54], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 81 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 50 }, + { numBlocks: 4, dataCodewordsPerBlock: 51 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + { numBlocks: 4, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 12 }, + { numBlocks: 8, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0C762, + versionNumber: 12, + alignmentPatternCenters: [6, 32, 58], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 92 }, + { numBlocks: 2, dataCodewordsPerBlock: 93 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 20 }, + { numBlocks: 6, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x0D847, + versionNumber: 13, + alignmentPatternCenters: [6, 34, 62], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 107 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 37 }, + { numBlocks: 1, dataCodewordsPerBlock: 38 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 20 }, + { numBlocks: 4, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 11 }, + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: 0x0E60D, + versionNumber: 14, + alignmentPatternCenters: [6, 26, 46, 66], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 40 }, + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 16 }, + { numBlocks: 5, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 5, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0F928, + versionNumber: 15, + alignmentPatternCenters: [6, 26, 48, 70], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 87 }, + { numBlocks: 1, dataCodewordsPerBlock: 88 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + { numBlocks: 5, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 7, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x10B78, + versionNumber: 16, + alignmentPatternCenters: [6, 26, 50, 74], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 98 }, + { numBlocks: 1, dataCodewordsPerBlock: 99 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1145D, + versionNumber: 17, + alignmentPatternCenters: [6, 30, 54, 78], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 1, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 22 }, + { numBlocks: 15, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 17, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x12A17, + versionNumber: 18, + alignmentPatternCenters: [6, 30, 56, 82], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 120 }, + { numBlocks: 1, dataCodewordsPerBlock: 121 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 43 }, + { numBlocks: 4, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x13532, + versionNumber: 19, + alignmentPatternCenters: [6, 30, 58, 86], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 113 }, + { numBlocks: 4, dataCodewordsPerBlock: 114 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 44 }, + { numBlocks: 11, dataCodewordsPerBlock: 45 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 21 }, + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 13 }, + { numBlocks: 16, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x149A6, + versionNumber: 20, + alignmentPatternCenters: [6, 34, 62, 90], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 41 }, + { numBlocks: 13, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 5, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 15 }, + { numBlocks: 10, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x15683, + versionNumber: 21, + alignmentPatternCenters: [6, 28, 50, 72, 94], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 116 }, + { numBlocks: 4, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 42 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 16 }, + { numBlocks: 6, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x168C9, + versionNumber: 22, + alignmentPatternCenters: [6, 26, 50, 74, 98], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 111 }, + { numBlocks: 7, dataCodewordsPerBlock: 112 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 46 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 34, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: 0x177EC, + versionNumber: 23, + alignmentPatternCenters: [6, 30, 54, 74, 102], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 121 }, + { numBlocks: 5, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + { numBlocks: 14, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 16, dataCodewordsPerBlock: 15 }, + { numBlocks: 14, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x18EC4, + versionNumber: 24, + alignmentPatternCenters: [6, 28, 54, 80, 106], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 45 }, + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 30, dataCodewordsPerBlock: 16 }, + { numBlocks: 2, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x191E1, + versionNumber: 25, + alignmentPatternCenters: [6, 32, 58, 84, 110], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 106 }, + { numBlocks: 4, dataCodewordsPerBlock: 107 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 47 }, + { numBlocks: 13, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1AFAB, + versionNumber: 26, + alignmentPatternCenters: [6, 30, 58, 86, 114], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 114 }, + { numBlocks: 2, dataCodewordsPerBlock: 115 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 46 }, + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 28, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 33, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x1B08E, + versionNumber: 27, + alignmentPatternCenters: [6, 34, 62, 90, 118], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 23 }, + { numBlocks: 26, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1CC1A, + versionNumber: 28, + alignmentPatternCenters: [6, 26, 50, 74, 98, 122], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 117 }, + { numBlocks: 10, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 45 }, + { numBlocks: 23, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 24 }, + { numBlocks: 31, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 31, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1D33F, + versionNumber: 29, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 116 }, + { numBlocks: 7, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 21, dataCodewordsPerBlock: 45 }, + { numBlocks: 7, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + { numBlocks: 37, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 26, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1ED75, + versionNumber: 30, + alignmentPatternCenters: [6, 26, 52, 78, 104, 130], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 115 }, + { numBlocks: 10, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 47 }, + { numBlocks: 10, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 25, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 25, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1F250, + versionNumber: 31, + alignmentPatternCenters: [6, 30, 56, 82, 108, 134], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 3, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 46 }, + { numBlocks: 29, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 24 }, + { numBlocks: 1, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x209D5, + versionNumber: 32, + alignmentPatternCenters: [6, 34, 60, 86, 112, 138], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 115 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 24 }, + { numBlocks: 35, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 35, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x216F0, + versionNumber: 33, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 21, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 24 }, + { numBlocks: 19, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x228BA, + versionNumber: 34, + alignmentPatternCenters: [6, 34, 62, 90, 118, 146], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 6, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 44, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 59, dataCodewordsPerBlock: 16 }, + { numBlocks: 1, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x2379F, + versionNumber: 35, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126, 150], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 121 }, + { numBlocks: 7, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 47 }, + { numBlocks: 26, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 39, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 41, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x24B0B, + versionNumber: 36, + alignmentPatternCenters: [6, 24, 50, 76, 102, 128, 154], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 121 }, + { numBlocks: 14, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 47 }, + { numBlocks: 34, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 46, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 64, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x2542E, + versionNumber: 37, + alignmentPatternCenters: [6, 28, 54, 80, 106, 132, 158], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 46 }, + { numBlocks: 14, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 49, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 24, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x26A64, + versionNumber: 38, + alignmentPatternCenters: [6, 32, 58, 84, 110, 136, 162], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 122 }, + { numBlocks: 18, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 46 }, + { numBlocks: 32, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 48, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 15 }, + { numBlocks: 32, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x27541, + versionNumber: 39, + alignmentPatternCenters: [6, 26, 54, 82, 110, 138, 166], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 40, dataCodewordsPerBlock: 47 }, + { numBlocks: 7, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 43, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 15 }, + { numBlocks: 67, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x28C69, + versionNumber: 40, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142, 170], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 118 }, + { numBlocks: 6, dataCodewordsPerBlock: 119 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 18, dataCodewordsPerBlock: 47 }, + { numBlocks: 31, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 34, dataCodewordsPerBlock: 24 }, + { numBlocks: 34, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 15 }, + { numBlocks: 61, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, +]; + +// tslint:disable:no-bitwise +function numBitsDiffering(x, y) { + let z = x ^ y; + let bitCount = 0; + while (z) { + bitCount++; + z &= z - 1; + } + return bitCount; +} +function pushBit(bit, byte) { + return (byte << 1) | bit; +} +// tslint:enable:no-bitwise +const FORMAT_INFO_TABLE = [ + { bits: 0x5412, formatInfo: { errorCorrectionLevel: 1, dataMask: 0 } }, + { bits: 0x5125, formatInfo: { errorCorrectionLevel: 1, dataMask: 1 } }, + { bits: 0x5E7C, formatInfo: { errorCorrectionLevel: 1, dataMask: 2 } }, + { bits: 0x5B4B, formatInfo: { errorCorrectionLevel: 1, dataMask: 3 } }, + { bits: 0x45F9, formatInfo: { errorCorrectionLevel: 1, dataMask: 4 } }, + { bits: 0x40CE, formatInfo: { errorCorrectionLevel: 1, dataMask: 5 } }, + { bits: 0x4F97, formatInfo: { errorCorrectionLevel: 1, dataMask: 6 } }, + { bits: 0x4AA0, formatInfo: { errorCorrectionLevel: 1, dataMask: 7 } }, + { bits: 0x77C4, formatInfo: { errorCorrectionLevel: 0, dataMask: 0 } }, + { bits: 0x72F3, formatInfo: { errorCorrectionLevel: 0, dataMask: 1 } }, + { bits: 0x7DAA, formatInfo: { errorCorrectionLevel: 0, dataMask: 2 } }, + { bits: 0x789D, formatInfo: { errorCorrectionLevel: 0, dataMask: 3 } }, + { bits: 0x662F, formatInfo: { errorCorrectionLevel: 0, dataMask: 4 } }, + { bits: 0x6318, formatInfo: { errorCorrectionLevel: 0, dataMask: 5 } }, + { bits: 0x6C41, formatInfo: { errorCorrectionLevel: 0, dataMask: 6 } }, + { bits: 0x6976, formatInfo: { errorCorrectionLevel: 0, dataMask: 7 } }, + { bits: 0x1689, formatInfo: { errorCorrectionLevel: 3, dataMask: 0 } }, + { bits: 0x13BE, formatInfo: { errorCorrectionLevel: 3, dataMask: 1 } }, + { bits: 0x1CE7, formatInfo: { errorCorrectionLevel: 3, dataMask: 2 } }, + { bits: 0x19D0, formatInfo: { errorCorrectionLevel: 3, dataMask: 3 } }, + { bits: 0x0762, formatInfo: { errorCorrectionLevel: 3, dataMask: 4 } }, + { bits: 0x0255, formatInfo: { errorCorrectionLevel: 3, dataMask: 5 } }, + { bits: 0x0D0C, formatInfo: { errorCorrectionLevel: 3, dataMask: 6 } }, + { bits: 0x083B, formatInfo: { errorCorrectionLevel: 3, dataMask: 7 } }, + { bits: 0x355F, formatInfo: { errorCorrectionLevel: 2, dataMask: 0 } }, + { bits: 0x3068, formatInfo: { errorCorrectionLevel: 2, dataMask: 1 } }, + { bits: 0x3F31, formatInfo: { errorCorrectionLevel: 2, dataMask: 2 } }, + { bits: 0x3A06, formatInfo: { errorCorrectionLevel: 2, dataMask: 3 } }, + { bits: 0x24B4, formatInfo: { errorCorrectionLevel: 2, dataMask: 4 } }, + { bits: 0x2183, formatInfo: { errorCorrectionLevel: 2, dataMask: 5 } }, + { bits: 0x2EDA, formatInfo: { errorCorrectionLevel: 2, dataMask: 6 } }, + { bits: 0x2BED, formatInfo: { errorCorrectionLevel: 2, dataMask: 7 } }, +]; +const DATA_MASKS = [ + (p) => ((p.y + p.x) % 2) === 0, + (p) => (p.y % 2) === 0, + (p) => p.x % 3 === 0, + (p) => (p.y + p.x) % 3 === 0, + (p) => (Math.floor(p.y / 2) + Math.floor(p.x / 3)) % 2 === 0, + (p) => ((p.x * p.y) % 2) + ((p.x * p.y) % 3) === 0, + (p) => ((((p.y * p.x) % 2) + (p.y * p.x) % 3) % 2) === 0, + (p) => ((((p.y + p.x) % 2) + (p.y * p.x) % 3) % 2) === 0, +]; +function buildFunctionPatternMask(version) { + const dimension = 17 + 4 * version.versionNumber; + const matrix = BitMatrix.createEmpty(dimension, dimension); + matrix.setRegion(0, 0, 9, 9, true); // Top left finder pattern + separator + format + matrix.setRegion(dimension - 8, 0, 8, 9, true); // Top right finder pattern + separator + format + matrix.setRegion(0, dimension - 8, 9, 8, true); // Bottom left finder pattern + separator + format + // Alignment patterns + for (const x of version.alignmentPatternCenters) { + for (const y of version.alignmentPatternCenters) { + if (!(x === 6 && y === 6 || x === 6 && y === dimension - 7 || x === dimension - 7 && y === 6)) { + matrix.setRegion(x - 2, y - 2, 5, 5, true); + } + } + } + matrix.setRegion(6, 9, 1, dimension - 17, true); // Vertical timing pattern + matrix.setRegion(9, 6, dimension - 17, 1, true); // Horizontal timing pattern + if (version.versionNumber > 6) { + matrix.setRegion(dimension - 11, 0, 3, 6, true); // Version info, top right + matrix.setRegion(0, dimension - 11, 6, 3, true); // Version info, bottom left + } + return matrix; +} +function readCodewords(matrix, version, formatInfo) { + const dataMask = DATA_MASKS[formatInfo.dataMask]; + const dimension = matrix.height; + const functionPatternMask = buildFunctionPatternMask(version); + const codewords = []; + let currentByte = 0; + let bitsRead = 0; + // Read columns in pairs, from right to left + let readingUp = true; + for (let columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) { + if (columnIndex === 6) { // Skip whole column with vertical alignment pattern; + columnIndex--; + } + for (let i = 0; i < dimension; i++) { + const y = readingUp ? dimension - 1 - i : i; + for (let columnOffset = 0; columnOffset < 2; columnOffset++) { + const x = columnIndex - columnOffset; + if (!functionPatternMask.get(x, y)) { + bitsRead++; + let bit = matrix.get(x, y); + if (dataMask({ y, x })) { + bit = !bit; + } + currentByte = pushBit(bit, currentByte); + if (bitsRead === 8) { // Whole bytes + codewords.push(currentByte); + bitsRead = 0; + currentByte = 0; + } + } + } + } + readingUp = !readingUp; + } + return codewords; +} +function readVersion(matrix) { + const dimension = matrix.height; + const provisionalVersion = Math.floor((dimension - 17) / 4); + if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code + return VERSIONS[provisionalVersion - 1]; + } + let topRightVersionBits = 0; + for (let y = 5; y >= 0; y--) { + for (let x = dimension - 9; x >= dimension - 11; x--) { + topRightVersionBits = pushBit(matrix.get(x, y), topRightVersionBits); + } + } + let bottomLeftVersionBits = 0; + for (let x = 5; x >= 0; x--) { + for (let y = dimension - 9; y >= dimension - 11; y--) { + bottomLeftVersionBits = pushBit(matrix.get(x, y), bottomLeftVersionBits); + } + } + let bestDifference = Infinity; + let bestVersion; + for (const version of VERSIONS) { + if (version.infoBits === topRightVersionBits || version.infoBits === bottomLeftVersionBits) { + return version; + } + let difference = numBitsDiffering(topRightVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + difference = numBitsDiffering(bottomLeftVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + } + // We can tolerate up to 3 bits of error since no two version info codewords will + // differ in less than 8 bits. + if (bestDifference <= 3) { + return bestVersion; + } +} +function readFormatInformation(matrix) { + let topLeftFormatInfoBits = 0; + for (let x = 0; x <= 8; x++) { + if (x !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits); + } + } + for (let y = 7; y >= 0; y--) { + if (y !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits); + } + } + const dimension = matrix.height; + let topRightBottomRightFormatInfoBits = 0; + for (let y = dimension - 1; y >= dimension - 7; y--) { // bottom left + topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits); + } + for (let x = dimension - 8; x < dimension; x++) { // top right + topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits); + } + let bestDifference = Infinity; + let bestFormatInfo = null; + for (const { bits, formatInfo } of FORMAT_INFO_TABLE) { + if (bits === topLeftFormatInfoBits || bits === topRightBottomRightFormatInfoBits) { + return formatInfo; + } + let difference = numBitsDiffering(topLeftFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option + difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + } + } + // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match + if (bestDifference <= 3) { + return bestFormatInfo; + } + return null; +} +function getDataBlocks(codewords, version, ecLevel) { + const ecInfo = version.errorCorrectionLevels[ecLevel]; + const dataBlocks = []; + let totalCodewords = 0; + ecInfo.ecBlocks.forEach(block => { + for (let i = 0; i < block.numBlocks; i++) { + dataBlocks.push({ numDataCodewords: block.dataCodewordsPerBlock, codewords: [] }); + totalCodewords += block.dataCodewordsPerBlock + ecInfo.ecCodewordsPerBlock; + } + }); + // In some cases the QR code will be malformed enough that we pull off more or less than we should. + // If we pull off less there's nothing we can do. + // If we pull off more we can safely truncate + if (codewords.length < totalCodewords) { + return null; + } + codewords = codewords.slice(0, totalCodewords); + const shortBlockSize = ecInfo.ecBlocks[0].dataCodewordsPerBlock; + // Pull codewords to fill the blocks up to the minimum size + for (let i = 0; i < shortBlockSize; i++) { + for (const dataBlock of dataBlocks) { + dataBlock.codewords.push(codewords.shift()); + } + } + // If there are any large blocks, pull codewords to fill the last element of those + if (ecInfo.ecBlocks.length > 1) { + const smallBlockCount = ecInfo.ecBlocks[0].numBlocks; + const largeBlockCount = ecInfo.ecBlocks[1].numBlocks; + for (let i = 0; i < largeBlockCount; i++) { + dataBlocks[smallBlockCount + i].codewords.push(codewords.shift()); + } + } + // Add the rest of the codewords to the blocks. These are the error correction codewords. + while (codewords.length > 0) { + for (const dataBlock of dataBlocks) { + dataBlock.codewords.push(codewords.shift()); + } + } + return dataBlocks; +} +function decodeMatrix(matrix) { + const version = readVersion(matrix); + if (!version) { + return null; + } + const formatInfo = readFormatInformation(matrix); + if (!formatInfo) { + return null; + } + const codewords = readCodewords(matrix, version, formatInfo); + const dataBlocks = getDataBlocks(codewords, version, formatInfo.errorCorrectionLevel); + if (!dataBlocks) { + return null; + } + // Count total number of data bytes + const totalBytes = dataBlocks.reduce((a, b) => a + b.numDataCodewords, 0); + const resultBytes = new Uint8ClampedArray(totalBytes); + let resultIndex = 0; + for (const dataBlock of dataBlocks) { + const correctedBytes = decode$1(dataBlock.codewords, dataBlock.codewords.length - dataBlock.numDataCodewords); + if (!correctedBytes) { + return null; + } + for (let i = 0; i < dataBlock.numDataCodewords; i++) { + resultBytes[resultIndex++] = correctedBytes[i]; + } + } + try { + return decode$2(resultBytes, version.versionNumber); + } + catch (_a) { + return null; + } +} +function decode(matrix) { + if (matrix == null) { + return null; + } + const result = decodeMatrix(matrix); + if (result) { + return result; + } + // Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line. + for (let x = 0; x < matrix.width; x++) { + for (let y = x + 1; y < matrix.height; y++) { + if (matrix.get(x, y) !== matrix.get(y, x)) { + matrix.set(x, y, !matrix.get(x, y)); + matrix.set(y, x, !matrix.get(y, x)); + } + } + } + return decodeMatrix(matrix); +} + +function squareToQuadrilateral(p1, p2, p3, p4) { + const dx3 = p1.x - p2.x + p3.x - p4.x; + const dy3 = p1.y - p2.y + p3.y - p4.y; + if (dx3 === 0 && dy3 === 0) { // Affine + return { + a11: p2.x - p1.x, + a12: p2.y - p1.y, + a13: 0, + a21: p3.x - p2.x, + a22: p3.y - p2.y, + a23: 0, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } + else { + const dx1 = p2.x - p3.x; + const dx2 = p4.x - p3.x; + const dy1 = p2.y - p3.y; + const dy2 = p4.y - p3.y; + const denominator = dx1 * dy2 - dx2 * dy1; + const a13 = (dx3 * dy2 - dx2 * dy3) / denominator; + const a23 = (dx1 * dy3 - dx3 * dy1) / denominator; + return { + a11: p2.x - p1.x + a13 * p2.x, + a12: p2.y - p1.y + a13 * p2.y, + a13, + a21: p4.x - p1.x + a23 * p4.x, + a22: p4.y - p1.y + a23 * p4.y, + a23, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } +} +function quadrilateralToSquare(p1, p2, p3, p4) { + // Here, the adjoint serves as the inverse: + const sToQ = squareToQuadrilateral(p1, p2, p3, p4); + return { + a11: sToQ.a22 * sToQ.a33 - sToQ.a23 * sToQ.a32, + a12: sToQ.a13 * sToQ.a32 - sToQ.a12 * sToQ.a33, + a13: sToQ.a12 * sToQ.a23 - sToQ.a13 * sToQ.a22, + a21: sToQ.a23 * sToQ.a31 - sToQ.a21 * sToQ.a33, + a22: sToQ.a11 * sToQ.a33 - sToQ.a13 * sToQ.a31, + a23: sToQ.a13 * sToQ.a21 - sToQ.a11 * sToQ.a23, + a31: sToQ.a21 * sToQ.a32 - sToQ.a22 * sToQ.a31, + a32: sToQ.a12 * sToQ.a31 - sToQ.a11 * sToQ.a32, + a33: sToQ.a11 * sToQ.a22 - sToQ.a12 * sToQ.a21, + }; +} +function times(a, b) { + return { + a11: a.a11 * b.a11 + a.a21 * b.a12 + a.a31 * b.a13, + a12: a.a12 * b.a11 + a.a22 * b.a12 + a.a32 * b.a13, + a13: a.a13 * b.a11 + a.a23 * b.a12 + a.a33 * b.a13, + a21: a.a11 * b.a21 + a.a21 * b.a22 + a.a31 * b.a23, + a22: a.a12 * b.a21 + a.a22 * b.a22 + a.a32 * b.a23, + a23: a.a13 * b.a21 + a.a23 * b.a22 + a.a33 * b.a23, + a31: a.a11 * b.a31 + a.a21 * b.a32 + a.a31 * b.a33, + a32: a.a12 * b.a31 + a.a22 * b.a32 + a.a32 * b.a33, + a33: a.a13 * b.a31 + a.a23 * b.a32 + a.a33 * b.a33, + }; +} +function extract(image, location) { + const qToS = quadrilateralToSquare({ x: 3.5, y: 3.5 }, { x: location.dimension - 3.5, y: 3.5 }, { x: location.dimension - 6.5, y: location.dimension - 6.5 }, { x: 3.5, y: location.dimension - 3.5 }); + const sToQ = squareToQuadrilateral(location.topLeft, location.topRight, location.alignmentPattern, location.bottomLeft); + const transform = times(sToQ, qToS); + const matrix = BitMatrix.createEmpty(location.dimension, location.dimension); + const mappingFunction = (x, y) => { + const denominator = transform.a13 * x + transform.a23 * y + transform.a33; + return { + x: (transform.a11 * x + transform.a21 * y + transform.a31) / denominator, + y: (transform.a12 * x + transform.a22 * y + transform.a32) / denominator, + }; + }; + for (let y = 0; y < location.dimension; y++) { + for (let x = 0; x < location.dimension; x++) { + const xValue = x + 0.5; + const yValue = y + 0.5; + const sourcePixel = mappingFunction(xValue, yValue); + matrix.set(x, y, image.get(Math.floor(sourcePixel.x), Math.floor(sourcePixel.y))); + } + } + return { + matrix, + mappingFunction, + }; +} + +const MAX_FINDERPATTERNS_TO_SEARCH = 5; +const MIN_QUAD_RATIO = 0.5; +const MAX_QUAD_RATIO = 1.5; +const distance = (a, b) => Math.sqrt(Math.pow((b.x - a.x), 2) + Math.pow((b.y - a.y), 2)); +function sum(values) { + return values.reduce((a, b) => a + b); +} +// Takes three finder patterns and organizes them into topLeft, topRight, etc +function reorderFinderPatterns(pattern1, pattern2, pattern3) { + // Find distances between pattern centers + const oneTwoDistance = distance(pattern1, pattern2); + const twoThreeDistance = distance(pattern2, pattern3); + const oneThreeDistance = distance(pattern1, pattern3); + let bottomLeft; + let topLeft; + let topRight; + // Assume one closest to other two is B; A and C will just be guesses at first + if (twoThreeDistance >= oneTwoDistance && twoThreeDistance >= oneThreeDistance) { + [bottomLeft, topLeft, topRight] = [pattern2, pattern1, pattern3]; + } + else if (oneThreeDistance >= twoThreeDistance && oneThreeDistance >= oneTwoDistance) { + [bottomLeft, topLeft, topRight] = [pattern1, pattern2, pattern3]; + } + else { + [bottomLeft, topLeft, topRight] = [pattern1, pattern3, pattern2]; + } + // Use cross product to figure out whether bottomLeft (A) and topRight (C) are correct or flipped in relation to topLeft (B) + // This asks whether BC x BA has a positive z component, which is the arrangement we want. If it's negative, then + // we've got it flipped around and should swap topRight and bottomLeft. + if (((topRight.x - topLeft.x) * (bottomLeft.y - topLeft.y)) - ((topRight.y - topLeft.y) * (bottomLeft.x - topLeft.x)) < 0) { + [bottomLeft, topRight] = [topRight, bottomLeft]; + } + return { bottomLeft, topLeft, topRight }; +} +// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns +function computeDimension(topLeft, topRight, bottomLeft, matrix) { + const moduleSize = (sum(countBlackWhiteRun(topLeft, bottomLeft, matrix, 5)) / 7 + // Divide by 7 since the ratio is 1:1:3:1:1 + sum(countBlackWhiteRun(topLeft, topRight, matrix, 5)) / 7 + + sum(countBlackWhiteRun(bottomLeft, topLeft, matrix, 5)) / 7 + + sum(countBlackWhiteRun(topRight, topLeft, matrix, 5)) / 7) / 4; + if (moduleSize < 1) { + throw new Error("Invalid module size"); + } + const topDimension = Math.round(distance(topLeft, topRight) / moduleSize); + const sideDimension = Math.round(distance(topLeft, bottomLeft) / moduleSize); + let dimension = Math.floor((topDimension + sideDimension) / 2) + 7; + switch (dimension % 4) { + case 0: + dimension++; + break; + case 2: + dimension--; + break; + } + return { dimension, moduleSize }; +} +// Takes an origin point and an end point and counts the sizes of the black white run from the origin towards the end point. +// Returns an array of elements, representing the pixel size of the black white run. +// Uses a variant of http://en.wikipedia.org/wiki/Bresenham's_line_algorithm +function countBlackWhiteRunTowardsPoint(origin, end, matrix, length) { + const switchPoints = [{ x: Math.floor(origin.x), y: Math.floor(origin.y) }]; + const steep = Math.abs(end.y - origin.y) > Math.abs(end.x - origin.x); + let fromX; + let fromY; + let toX; + let toY; + if (steep) { + fromX = Math.floor(origin.y); + fromY = Math.floor(origin.x); + toX = Math.floor(end.y); + toY = Math.floor(end.x); + } + else { + fromX = Math.floor(origin.x); + fromY = Math.floor(origin.y); + toX = Math.floor(end.x); + toY = Math.floor(end.y); + } + const dx = Math.abs(toX - fromX); + const dy = Math.abs(toY - fromY); + let error = Math.floor(-dx / 2); + const xStep = fromX < toX ? 1 : -1; + const yStep = fromY < toY ? 1 : -1; + let currentPixel = true; + // Loop up until x == toX, but not beyond + for (let x = fromX, y = fromY; x !== toX + xStep; x += xStep) { + // Does current pixel mean we have moved white to black or vice versa? + // Scanning black in state 0,2 and white in state 1, so if we find the wrong + // color, advance to next state or end if we are in state 2 already + const realX = steep ? y : x; + const realY = steep ? x : y; + if (matrix.get(realX, realY) !== currentPixel) { + currentPixel = !currentPixel; + switchPoints.push({ x: realX, y: realY }); + if (switchPoints.length === length + 1) { + break; + } + } + error += dy; + if (error > 0) { + if (y === toY) { + break; + } + y += yStep; + error -= dx; + } + } + const distances = []; + for (let i = 0; i < length; i++) { + if (switchPoints[i] && switchPoints[i + 1]) { + distances.push(distance(switchPoints[i], switchPoints[i + 1])); + } + else { + distances.push(0); + } + } + return distances; +} +// Takes an origin point and an end point and counts the sizes of the black white run in the origin point +// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes +// of the black white run. Takes a length which represents the number of switches from black to white to look for. +function countBlackWhiteRun(origin, end, matrix, length) { + const rise = end.y - origin.y; + const run = end.x - origin.x; + const towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2)); + const awayFromEnd = countBlackWhiteRunTowardsPoint(origin, { x: origin.x - run, y: origin.y - rise }, matrix, Math.ceil(length / 2)); + const middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel + return awayFromEnd.concat(middleValue).concat(...towardsEnd); +} +// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the "error" - +// that is the amount the run diverges from the expected ratio +function scoreBlackWhiteRun(sequence, ratios) { + const averageSize = sum(sequence) / sum(ratios); + let error = 0; + ratios.forEach((ratio, i) => { + error += Math.pow((sequence[i] - ratio * averageSize), 2); + }); + return { averageSize, error }; +} +// Takes an X,Y point and an array of sizes and scores the point against those ratios. +// For example for a finder pattern takes the ratio list of 1:1:3:1:1 and checks horizontal, vertical and diagonal ratios +// against that. +function scorePattern(point, ratios, matrix) { + try { + const horizontalRun = countBlackWhiteRun(point, { x: -1, y: point.y }, matrix, ratios.length); + const verticalRun = countBlackWhiteRun(point, { x: point.x, y: -1 }, matrix, ratios.length); + const topLeftPoint = { + x: Math.max(0, point.x - point.y) - 1, + y: Math.max(0, point.y - point.x) - 1, + }; + const topLeftBottomRightRun = countBlackWhiteRun(point, topLeftPoint, matrix, ratios.length); + const bottomLeftPoint = { + x: Math.min(matrix.width, point.x + point.y) + 1, + y: Math.min(matrix.height, point.y + point.x) + 1, + }; + const bottomLeftTopRightRun = countBlackWhiteRun(point, bottomLeftPoint, matrix, ratios.length); + const horzError = scoreBlackWhiteRun(horizontalRun, ratios); + const vertError = scoreBlackWhiteRun(verticalRun, ratios); + const diagDownError = scoreBlackWhiteRun(topLeftBottomRightRun, ratios); + const diagUpError = scoreBlackWhiteRun(bottomLeftTopRightRun, ratios); + const ratioError = Math.sqrt(horzError.error * horzError.error + + vertError.error * vertError.error + + diagDownError.error * diagDownError.error + + diagUpError.error * diagUpError.error); + const avgSize = (horzError.averageSize + vertError.averageSize + diagDownError.averageSize + diagUpError.averageSize) / 4; + const sizeError = (Math.pow((horzError.averageSize - avgSize), 2) + + Math.pow((vertError.averageSize - avgSize), 2) + + Math.pow((diagDownError.averageSize - avgSize), 2) + + Math.pow((diagUpError.averageSize - avgSize), 2)) / avgSize; + return ratioError + sizeError; + } + catch (_a) { + return Infinity; + } +} +function recenterLocation(matrix, p) { + let leftX = Math.round(p.x); + while (matrix.get(leftX, Math.round(p.y))) { + leftX--; + } + let rightX = Math.round(p.x); + while (matrix.get(rightX, Math.round(p.y))) { + rightX++; + } + const x = (leftX + rightX) / 2; + let topY = Math.round(p.y); + while (matrix.get(Math.round(x), topY)) { + topY--; + } + let bottomY = Math.round(p.y); + while (matrix.get(Math.round(x), bottomY)) { + bottomY++; + } + const y = (topY + bottomY) / 2; + return { x, y }; +} +function locate(matrix) { + const finderPatternQuads = []; + let activeFinderPatternQuads = []; + const alignmentPatternQuads = []; + let activeAlignmentPatternQuads = []; + for (let y = 0; y <= matrix.height; y++) { + let length = 0; + let lastBit = false; + let scans = [0, 0, 0, 0, 0]; + for (let x = -1; x <= matrix.width; x++) { + const v = matrix.get(x, y); + if (v === lastBit) { + length++; + } + else { + scans = [scans[1], scans[2], scans[3], scans[4], length]; + length = 1; + lastBit = v; + // Do the last 5 color changes ~ match the expected ratio for a finder pattern? 1:1:3:1:1 of b:w:b:w:b + const averageFinderPatternBlocksize = sum(scans) / 7; + const validFinderPattern = Math.abs(scans[0] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[1] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[2] - 3 * averageFinderPatternBlocksize) < 3 * averageFinderPatternBlocksize && + Math.abs(scans[3] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[4] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + !v; // And make sure the current pixel is white since finder patterns are bordered in white + // Do the last 3 color changes ~ match the expected ratio for an alignment pattern? 1:1:1 of w:b:w + const averageAlignmentPatternBlocksize = sum(scans.slice(-3)) / 3; + const validAlignmentPattern = Math.abs(scans[2] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[3] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[4] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + v; // Is the current pixel black since alignment patterns are bordered in black + if (validFinderPattern) { + // Compute the start and end x values of the large center black square + const endX = x - scans[3] - scans[4]; + const startX = endX - scans[2]; + const line = { startX, endX, y }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + const matchingQuads = activeFinderPatternQuads.filter(q => (startX >= q.bottom.startX && startX <= q.bottom.endX) || + (endX >= q.bottom.startX && startX <= q.bottom.endX) || + (startX <= q.bottom.startX && endX >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO))); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeFinderPatternQuads.push({ top: line, bottom: line }); + } + } + if (validAlignmentPattern) { + // Compute the start and end x values of the center black square + const endX = x - scans[4]; + const startX = endX - scans[3]; + const line = { startX, y, endX }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + const matchingQuads = activeAlignmentPatternQuads.filter(q => (startX >= q.bottom.startX && startX <= q.bottom.endX) || + (endX >= q.bottom.startX && startX <= q.bottom.endX) || + (startX <= q.bottom.startX && endX >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO))); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeAlignmentPatternQuads.push({ top: line, bottom: line }); + } + } + } + } + finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y !== y && q.bottom.y - q.top.y >= 2)); + activeFinderPatternQuads = activeFinderPatternQuads.filter(q => q.bottom.y === y); + alignmentPatternQuads.push(...activeAlignmentPatternQuads.filter(q => q.bottom.y !== y)); + activeAlignmentPatternQuads = activeAlignmentPatternQuads.filter(q => q.bottom.y === y); + } + finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y - q.top.y >= 2)); + alignmentPatternQuads.push(...activeAlignmentPatternQuads); + // Refactored from cozmo/jsQR to (hopefully) circumvent an issue in Safari 13+ on both Mac and iOS (also including + // iOS Chrome and other Safari iOS derivatives). Safari was very occasionally and apparently not deterministically + // throwing a "RangeError: Array size is not a small enough positive integer." exception seemingly within the second + // .map of the original code (here the second for-loop). This second .map contained a nested .map call over the same + // array instance which was the chained result from previous calls to .map, .filter and .sort which potentially caused + // this bug in Safari? + // Also see https://github.com/cozmo/jsQR/issues/157 and https://bugs.webkit.org/show_bug.cgi?id=211619#c3 + const scoredFinderPatternPositions = []; + for (const quad of finderPatternQuads) { + if (quad.bottom.y - quad.top.y < 2) { + // All quads must be at least 2px tall since the center square is larger than a block + continue; + } + // calculate quad center + const x = (quad.top.startX + quad.top.endX + quad.bottom.startX + quad.bottom.endX) / 4; + const y = (quad.top.y + quad.bottom.y + 1) / 2; + if (!matrix.get(Math.round(x), Math.round(y))) { + continue; + } + const lengths = [quad.top.endX - quad.top.startX, quad.bottom.endX - quad.bottom.startX, quad.bottom.y - quad.top.y + 1]; + const size = sum(lengths) / lengths.length; + // Initial scoring of finder pattern quads by looking at their ratios, not taking into account position + const score = scorePattern({ x: Math.round(x), y: Math.round(y) }, [1, 1, 3, 1, 1], matrix); + scoredFinderPatternPositions.push({ score, x, y, size }); + } + if (scoredFinderPatternPositions.length < 3) { + // A QR code has 3 finder patterns, therefore we need at least 3 candidates. + return null; + } + scoredFinderPatternPositions.sort((a, b) => a.score - b.score); + // Now take the top finder pattern options and try to find 2 other options with a similar size. + const finderPatternGroups = []; + for (let i = 0; i < Math.min(scoredFinderPatternPositions.length, MAX_FINDERPATTERNS_TO_SEARCH); ++i) { + const point = scoredFinderPatternPositions[i]; + const otherPoints = []; + for (const otherPoint of scoredFinderPatternPositions) { + if (otherPoint === point) { + continue; + } + otherPoints.push(Object.assign(Object.assign({}, otherPoint), { score: otherPoint.score + (Math.pow((otherPoint.size - point.size), 2)) / point.size })); + } + otherPoints.sort((a, b) => a.score - b.score); + finderPatternGroups.push({ + points: [point, otherPoints[0], otherPoints[1]], + score: point.score + otherPoints[0].score + otherPoints[1].score, // total combined score of the three points in the group + }); + } + finderPatternGroups.sort((a, b) => a.score - b.score); + const bestFinderPatternGroup = finderPatternGroups[0]; + const { topRight, topLeft, bottomLeft } = reorderFinderPatterns(...bestFinderPatternGroup.points); + const alignment = findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft); + const result = []; + if (alignment) { + result.push({ + alignmentPattern: { x: alignment.alignmentPattern.x, y: alignment.alignmentPattern.y }, + bottomLeft: { x: bottomLeft.x, y: bottomLeft.y }, + dimension: alignment.dimension, + topLeft: { x: topLeft.x, y: topLeft.y }, + topRight: { x: topRight.x, y: topRight.y }, + }); + } + // We normally use the center of the quads as the location of the tracking points, which is optimal for most cases and will account + // for a skew in the image. However, In some cases, a slight skew might not be real and instead be caused by image compression + // errors and/or low resolution. For those cases, we'd be better off centering the point exactly in the middle of the black area. We + // compute and return the location data for the naively centered points as it is little additional work and allows for multiple + // attempts at decoding harder images. + const midTopRight = recenterLocation(matrix, topRight); + const midTopLeft = recenterLocation(matrix, topLeft); + const midBottomLeft = recenterLocation(matrix, bottomLeft); + const centeredAlignment = findAlignmentPattern(matrix, alignmentPatternQuads, midTopRight, midTopLeft, midBottomLeft); + if (centeredAlignment) { + result.push({ + alignmentPattern: { x: centeredAlignment.alignmentPattern.x, y: centeredAlignment.alignmentPattern.y }, + bottomLeft: { x: midBottomLeft.x, y: midBottomLeft.y }, + topLeft: { x: midTopLeft.x, y: midTopLeft.y }, + topRight: { x: midTopRight.x, y: midTopRight.y }, + dimension: centeredAlignment.dimension, + }); + } + if (result.length === 0) { + return null; + } + return result; +} +function findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft) { + // Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code. + // We'll use these to help find the alignment pattern but also later when we do the extraction. + let dimension; + let moduleSize; + try { + ({ dimension, moduleSize } = computeDimension(topLeft, topRight, bottomLeft, matrix)); + } + catch (e) { + return null; + } + // Now find the alignment pattern + const bottomRightFinderPattern = { + x: topRight.x - topLeft.x + bottomLeft.x, + y: topRight.y - topLeft.y + bottomLeft.y, + }; + const modulesBetweenFinderPatterns = ((distance(topLeft, bottomLeft) + distance(topLeft, topRight)) / 2 / moduleSize); + const correctionToTopLeft = 1 - (3 / modulesBetweenFinderPatterns); + const expectedAlignmentPattern = { + x: topLeft.x + correctionToTopLeft * (bottomRightFinderPattern.x - topLeft.x), + y: topLeft.y + correctionToTopLeft * (bottomRightFinderPattern.y - topLeft.y), + }; + const alignmentPatterns = alignmentPatternQuads + .map(q => { + const x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4; + const y = (q.top.y + q.bottom.y + 1) / 2; + if (!matrix.get(Math.floor(x), Math.floor(y))) { + return; + } + const sizeScore = scorePattern({ x: Math.floor(x), y: Math.floor(y) }, [1, 1, 1], matrix); + const score = sizeScore + distance({ x, y }, expectedAlignmentPattern); + return { x, y, score }; + }) + .filter(v => !!v) + .sort((a, b) => a.score - b.score); + // If there are less than 15 modules between finder patterns it's a version 1 QR code and as such has no alignmemnt pattern + // so we can only use our best guess. + const alignmentPattern = modulesBetweenFinderPatterns >= 15 && alignmentPatterns.length ? alignmentPatterns[0] : expectedAlignmentPattern; + return { alignmentPattern, dimension }; +} + +function scan(matrix) { + const locations = locate(matrix); + if (!locations) { + return null; + } + for (const location of locations) { + const extracted = extract(matrix, location); + const decoded = decode(extracted.matrix); + if (decoded) { + return { + binaryData: decoded.bytes, + data: decoded.text, + chunks: decoded.chunks, + version: decoded.version, + location: { + topRightCorner: extracted.mappingFunction(location.dimension, 0), + topLeftCorner: extracted.mappingFunction(0, 0), + bottomRightCorner: extracted.mappingFunction(location.dimension, location.dimension), + bottomLeftCorner: extracted.mappingFunction(0, location.dimension), + topRightFinderPattern: location.topRight, + topLeftFinderPattern: location.topLeft, + bottomLeftFinderPattern: location.bottomLeft, + bottomRightAlignmentPattern: location.alignmentPattern, + }, + matrix: extracted.matrix, + }; + } + } + return null; +} +const defaultOptions = { + inversionAttempts: "attemptBoth", + greyScaleWeights: { + red: 0.2126, + green: 0.7152, + blue: 0.0722, + useIntegerApproximation: false, + }, + canOverwriteImage: true, +}; +function mergeObject(target, src) { + Object.keys(src).forEach(opt => { + target[opt] = src[opt]; + }); +} +function jsQR(data, width, height, providedOptions = {}) { + const options = Object.create(null); + mergeObject(options, defaultOptions); + mergeObject(options, providedOptions); + const tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst"; + const shouldInvert = options.inversionAttempts === "attemptBoth" || tryInvertedFirst; + const { binarized, inverted } = binarize(data, width, height, shouldInvert, options.greyScaleWeights, options.canOverwriteImage); + let result = scan(tryInvertedFirst ? inverted : binarized); + if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) { + result = scan(tryInvertedFirst ? binarized : inverted); + } + return result; +} +jsQR.default = jsQR; + +export { jsQR as default }; \ No newline at end of file diff --git a/uni_modules/x-modal-s/changelog.md b/uni_modules/x-modal-s/changelog.md new file mode 100644 index 0000000..65862b8 --- /dev/null +++ b/uni_modules/x-modal-s/changelog.md @@ -0,0 +1,16 @@ +## 1.0.6(2025-08-17) +* 更新支持鸿蒙原生 Next,采用自己编译的 Har 包来支持 +## 1.0.5(2025-04-30) +* ios,安卓,web内容现在可以渲染html内容,不要太复杂.安卓和web会拦截a标签,ios目前拦截不了会直接跳转外链. +## 1.0.4(2025-04-13) +* 安卓端弹层修改布局,现在可以覆盖官方的Dialog-page页面了,并且可以接受安卓的返回键及侧滑关闭弹层了.并且会自动隐藏状态栏,并可以覆盖底部安全区域 +## 1.0.3(2025-02-23) +* 安卓添加了显示背景遮罩动画,及关闭遮罩动画 +* ios添加了显示背景遮罩动画,及关闭遮罩动画 +* 上述添加后,不管是显示和关闭都更加的自然 +## 1.0.2(2025-02-13) +* 兼容微信 +## 1.0.1(2024-08-15) +* 新增contentAlign,可以让内容顶左对齐,还是让内容左右上下居中对齐 . +## 1.0.0(2024-08-06) +安卓,ios,web可用。 diff --git a/uni_modules/x-modal-s/modal.png b/uni_modules/x-modal-s/modal.png new file mode 100644 index 0000000..0ea0a73 Binary files /dev/null and b/uni_modules/x-modal-s/modal.png differ diff --git a/uni_modules/x-modal-s/package.json b/uni_modules/x-modal-s/package.json new file mode 100644 index 0000000..c8e687e --- /dev/null +++ b/uni_modules/x-modal-s/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-modal-s", + "displayName": "TM-UI 4.0x全屏对话框,可覆盖任意界面任意位置调用", + "version": "1.0.6", + "description": "主要是用来代替uni.showModal", + "keywords": [ + "uts,原生插件,tmui" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "1.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/readme.md b/uni_modules/x-modal-s/readme.md new file mode 100644 index 0000000..0e59e49 --- /dev/null +++ b/uni_modules/x-modal-s/readme.md @@ -0,0 +1,171 @@ +# x-modal-s + +### 特性说明 + +主要是用来代替uni.showModal的,相比优化有: +1. 高自动适应,因此可以添加超长的title文字。 +2. 图标可以任意更新,大小,颜色等 +3. 可以添加title标题,允许改变字号,颜色 及背景 +4. 精致美观,可以定制界面达到与品牌相符的设计 +5. 可以重复打开,或者连续打开不用担心前一个是否关闭,我内部会检测关闭上一个对话框。 + +**微信内使用官方的弹层,大多属性无效,只有同官方的属性会生效** + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 开发文档 + +**浏览器端需要你把目录中的```remixicon.ttf```复制到static目录下** + +调用: +```ts +import { showModal,X_MODAL_TYPE} from "@/uni_modules/x-modal-s" +// 显示 +showModal({ + title: "提醒框", + content: "这是一条测试消息对话框,默认是按钮分离哦。", + confirmText: "确定", + cancelText: "取消", + // 按钮分离模式 + isSplitBtn: true, + // 点击遮罩是否关闭 + clickMaskClose: true, + // 确认按钮回调 + confirm: () => { + console.log("点击确认") + }, + // 取消按钮回调 + cancel: () => { + console.log("点击取消") + }, + // 关闭回调 + close: () => { + console.log("对话框关闭") + } +} as X_MODAL_TYPE) +``` + +### 参数配置 + +下面的图标iconCode,同组件库x-icon是相同的字体图标,请打开图标网站:[查看](https://remixicon.com/) +找到直接想要的图标后 复制 unicode ,不是名称。比如:我们只要取ED29 +下面的参数图标iconCode就是ED29 **iconCode:'ED29'** + +**X_MODAL_TYPE参数说明** +```ts +export type X_MODAL_TYPE = { + // 标题文字 + title?: string, + // 内容文字 + content?: string, + // 内容对齐方式:'center'(上下左右居中) 或 'left'(顶左对齐) + contentAlign?: string, + // 取消按钮文字 + cancelText?: string, + // 取消按钮背景色 + cancelBgColor?: string, + // 取消按钮文字颜色 + cancelColor?: string, + // 确认按钮文字 + confirmText?: string, + // 确认按钮背景色 + confirmBgColor?: string, + // 确认按钮文字颜色 + confirmColor?: string, + // 圆角大小 + radius?: number, + // 确认按钮图标(Remix图标unicode) + confirmIcon?: string, + // 取消按钮图标(Remix图标unicode) + cancelIcon?: string, + // 标题文字颜色 + titleColor?: string, + // 内容文字颜色 + contentColor?: string, + // 按钮是否分离显示 + isSplitBtn?: boolean, + // 对话框内容背景色 + contentBgColor?: string, + // 遮罩背景色 + maskBgColor?: string, + // ios不支持,会直接打开对应的链接。只有安卓,鸿蒙,web支持。 + clickLink?:(href:string)=>void, + // 确认按钮回调 + confirm?: () => void, + // 取消按钮回调 + cancel?: () => void, + // 关闭回调 + close?: () => void, + // 背景模糊效果(仅web端生效) + isBlurMask?: boolean, + // 对话框高度 + height?: number, + // 对话框宽度 + width?: number, + // 是否允许点击遮罩关闭 + clickMaskClose?: boolean, + // 是否显示取消按钮 + showCancel?: boolean +} +``` + +### 平台差异说明 + +1. Web端 +- 支持背景模糊效果(isBlurMask) +- 需将remixicon.ttf字体文件复制到static目录 + +2. 微信小程序 +- 使用官方原生showModal组件 +- 仅支持基础属性(title,content,confirmText,cancelText等) +- 不支持自定义样式 + +3. Android/iOS +- 完整支持所有特性 +- 支持自定义按钮图标 +- 支持按钮分离模式 +- 支持遮罩点击关闭 + +### 使用示例 + +1. 基础用法 +```ts +showModal({ + title: "提示", + content: "这是一个基础对话框" +} as X_MODAL_TYPE) +``` + +2. 自定义按钮 +```ts +showModal({ + title: "自定义按钮", + content: "自定义按钮文字和颜色", + confirmText: "知道了", + confirmColor: "#2979ff", + showCancel: false +} as X_MODAL_TYPE) +``` + +3. 带图标按钮 +```ts +showModal({ + title: "带图标", + content: "使用Remix图标库", + confirmIcon: "ED29", + cancelIcon: "EAD8" +} as X_MODAL_TYPE) +``` + +4. 居中内容 +```ts +showModal({ + title: "居中内容", + content: "内容上下左右居中对齐", + contentAlign: "center" +} as X_MODAL_TYPE) +``` \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/app-android/assets/remixicon.ttf b/uni_modules/x-modal-s/utssdk/app-android/assets/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-modal-s/utssdk/app-android/assets/remixicon.ttf differ diff --git a/uni_modules/x-modal-s/utssdk/app-android/config.json b/uni_modules/x-modal-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/app-android/index.uts b/uni_modules/x-modal-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..bec52d8 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-android/index.uts @@ -0,0 +1,566 @@ +import LinearLayout from 'android.widget.LinearLayout'; +import Context from 'android.content.Context' +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import { X_MODAL_TYPE, X_MODAL_TYPE_PRIVATE, RGBA } from "../interface.uts" +import Color from 'android.graphics.Color'; +import Gravity from 'android.view.Gravity'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable'; +import TextView from 'android.widget.TextView'; +import Typeface from 'android.graphics.Typeface'; +import TextUtils from 'android.text.TextUtils'; +import Uri from 'android.net.Uri'; +import Html from 'android.text.Html'; + +import ObjectAnimator from 'android.animation.ObjectAnimator'; +import ValueAnimator from 'android.animation.ValueAnimator'; +import TimeInterpolator from 'android.animation.TimeInterpolator'; +import MotionEvent from 'android.view.MotionEvent'; +import { hexToRgb } from "../libs/color.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; +import ScrollView from 'android.widget.ScrollView'; +import AccelerateDecelerateInterpolator from 'android.view.animation.AccelerateDecelerateInterpolator'; +// #ifdef UNI-APP-X +import getCurrentPages from 'io.dcloud.uniapp.framework.getCurrentPages'; +import onReady from 'io.dcloud.uniapp.framework.onReady'; +import onUnload from 'io.dcloud.uniapp.framework.onUnload'; +import onShow from 'io.dcloud.uniapp.framework.onShow'; +// #endif +import R from 'android.R'; +import Bundle from "android.os.Bundle"; +import Dialog from "android.app.Dialog"; +import WindowManager from "android.view.WindowManager"; +import Window from "android.view.Window"; +import ColorDrawable from "android.graphics.drawable.ColorDrawable"; +import LinkMovementMethod from 'android.text.method.LinkMovementMethod'; +import SpannableString from "android.text.SpannableString"; +import Spannable from "android.text.Spannable"; +import URLSpan from 'android.text.style.URLSpan'; +import ClickableSpan from 'android.text.style.ClickableSpan'; +import TextPaint from 'android.text.TextPaint' +import WindowInsetsController from "android.view.WindowInsetsController"; +import WindowInsets from "android.view.WindowInsets"; +import Build from 'android.os.Build'; +import LayerDrawable from "android.graphics.drawable.LayerDrawable"; + + + + +let masker : null | RelativeLayout = null; +let contentDom : null | LinearLayout = null; +let maskDomId = 586 +let tid = 0 +let isClsoing = false +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} +function setSpin(textView : TextView) { + try { + textView.clearAnimation(); + } catch (e) { + //TODO handle the exception + } + let rotationStart = 0 + let rotation = 360 + let rotationSFD = 0.5 + let rotationAnimator = ObjectAnimator.ofFloat(textView, "rotation", rotationStart.toFloat(), rotation.toFloat()); + rotationAnimator.setDuration(1000); + class LinearInterpolator implements TimeInterpolator { + override getInterpolation(input : Float) : Float { + return input; + } + } + + rotationAnimator.setInterpolator(new LinearInterpolator()); + + rotationAnimator.setRepeatCount(ValueAnimator.INFINITE); + rotationAnimator.start(); +} +let dialogModal : FullScreenDialogFragment | null = null; + +class FullScreenDialogFragment extends Dialog { + private mContext : Context; + private opts : X_MODAL_TYPE + constructor(context : Context, optsOwer : X_MODAL_TYPE) { + super(context, R.style.Theme_Translucent_NoTitleBar_Fullscreen); + this.mContext = context; + this.opts = optsOwer + } + override onCreate(savedInstanceState ?: Bundle) { + super.onCreate(savedInstanceState) + this.requestWindowFeature(Window.FEATURE_NO_TITLE) + + // 设置窗口属性 + let window = this.getWindow(); + if (window != null) { + // 首先设置全屏标志 + window.setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN + ); + + // 设置布局参数为全屏 + window.setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT + ); + + // 设置背景透明 + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + + window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + window.setGravity(Gravity.CENTER); + + // 完整的沉浸式设置 + let decorView = window.getDecorView(); + let option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + decorView.setSystemUiVisibility(option); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + window.setStatusBarColor(Color.TRANSPARENT) + window.setNavigationBarColor(Color.TRANSPARENT) + window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) + } + _createModalView(this.getContext(), this.window!.decorView! as ViewGroup, this.opts) + + } + override dismiss() { + super.dismiss() + contentDom = null; + isClsoing = false; + dialogModal = null; + } + +} + + +export function close(call : () => void, isClose : boolean) { + UTSAndroid.getDispatcher("main").async(function (_) { + if (!isClose) return; + let mk = masker + if (mk != null) { + clearTimeout(tid) + try { + let s0 = (0).toFloat() + let s1 = (0).toFloat() + let maskAni = mk.animate() as ViewPropertyAnimator; + maskAni.alpha(s1) + .setDuration(300) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + if (contentDom != null) { + let ani = contentDom!.animate() as ViewPropertyAnimator; + ani.alpha(s0) + .scaleX(s1) + .scaleY(s1) + .setDuration(300) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + + tid = setTimeout(function () { + isClsoing = false + dialogModal?.dismiss() + + mk = null; + contentDom = null; + masker = null; + dialogModal = null; + + }, 300); + } else { + isClsoing = false; + dialogModal?.dismiss() + mk = null; + contentDom = null; + masker = null; + dialogModal = null; + } + + } catch (e) { + //TODO handle the exception + } + call() + } + }, null) + + +} +function rgbToColorNumber(rgba : RGBA) : Int { + return Color.argb((rgba.a * 255).toInt(), rgba!.r.toInt(), rgba!.g.toInt(), rgba!.b.toInt()) +} + +function _clickLinksRender(contextText : TextView, config : X_MODAL_TYPE_PRIVATE) { + let spanned = Html.fromHtml(config.content) + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ + spanned = Html.fromHtml(config.content, Html.FROM_HTML_MODE_LEGACY) + } + const spannableString = new SpannableString(spanned); + + function addLinksClick() { + + // 获取所有的 URLSpan(对应 标签) + const urlSpans = spanned.getSpans(0, spanned.length, UTSAndroid.getJavaClass(URLSpan)); + + // 遍历每个 URLSpan 并用自定义的 ClickableSpan 替换 + for (item in urlSpans) { + const urlSpan = item as URLSpan + const start = spanned.getSpanStart(urlSpan); + const end = spanned.getSpanEnd(urlSpan); + + // 创建自定义的 ClickableSpan + class clickableSpan extends ClickableSpan { + constructor() { + super() + } + override onClick(wv : View) { + // 当链接被点击时触发 + const url : string = urlSpan.getURL(); + config.clickLink(url) + console.log(url) + } + override updateDrawState(ds : TextPaint) { + super.updateDrawState(ds); + ds.setColor(rgbToColorNumber(hexToRgb(config.linkFontColor)!)); // 设置链接颜色 + ds.setUnderlineText(true); // 设置下划线 + } + }; + + // 替换 URLSpan 为自定义的 ClickableSpan + spannableString.setSpan(new clickableSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + // 移除原始的 URLSpan + spannableString.removeSpan(urlSpan); + } + } + addLinksClick() + contextText.setText(spannableString); + contextText.setMovementMethod(new LinkMovementMethod()); +} + +function _createModalView(context : Context, decorView : ViewGroup, opts : X_MODAL_TYPE) { + + // + let config = configCover(opts) + let titleHeight = 60; + let footerHeight = 74 + let contentHeight = config.height; + let width = config.width; + let height = config.height + + if (isClsoing) return; + let maskBgColorRgb = rgbToColorNumber(hexToRgb(config.maskBgColor)!); + let cancelColorRgb = rgbToColorNumber(hexToRgb(config.cancelColor)!); + let cancelBgColorRgb = rgbToColorNumber(hexToRgb(config.cancelBgColor)!); + let confirmBgColorRgb = rgbToColorNumber(hexToRgb(config.confirmBgColor)!); + let confirmColorRgb = rgbToColorNumber(hexToRgb(config.confirmColor)!); + let contentBgColorRgb = rgbToColorNumber(hexToRgb(config.contentBgColor)!); + let contentColorColorRgb = rgbToColorNumber(hexToRgb(config.contentColor)!); + let titleColorColorRgb = rgbToColorNumber(hexToRgb(config.titleColor)!); + let maskerDom = new RelativeLayout(context) + let maskerDomLayrPrams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + maskerDom.setLayoutParams(maskerDomLayrPrams) + maskerDom.setBackgroundColor(maskBgColorRgb) + maskerDom.setGravity(Gravity.CENTER) + maskerDom.setId((maskDomId).toInt()) + maskerDom.setAlpha((0).toFloat()) + + // 内容容器 + let container = new LinearLayout(context); + contentDom = container + container.setOrientation(LinearLayout.VERTICAL) + container.setGravity(Gravity.CENTER) + + // 设置圆角背景 + let bg = new GradientDrawable() + bg.setColor(contentBgColorRgb) + bg.setCornerRadius((px2dp(16)).toFloat()) + container.setClipToOutline(true) + container.setBackground(bg) + let wpx = px2dp(config.width).toInt(); + container.setLayoutParams(new LinearLayout.LayoutParams(wpx, ViewGroup.LayoutParams.WRAP_CONTENT)) + let defaultNumScale = (0).toFloat() + container.setAlpha(defaultNumScale) + container.setScaleX(defaultNumScale) + container.setScaleY(defaultNumScale) + let titleDiv = new TextView(context) + let titleDivheight = px2dp(titleHeight).toInt(); + titleDiv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, titleDivheight)) + titleDiv.setGravity(Gravity.CENTER) + titleDiv.setTextSize((18.0).toFloat()) + titleDiv.setTextColor(titleColorColorRgb) + titleDiv.setText(config.title) + + // 内容 + let content = new ScrollView(context) + let contentDivheight = px2dp(contentHeight).toInt(); + content.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, contentDivheight)) + + let contextText = new TextView(context); + if (config.contentAlign == 'center') { + contextText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) + contextText.setGravity(Gravity.CENTER) + contextText.setMinHeight(contentDivheight) + } else { + contextText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + } + contextText.setTextSize((15.0).toFloat()) + contextText.setTextColor(contentColorColorRgb) + + + _clickLinksRender(contextText, config) + + let contentPadding = px2dp(16).toInt() + contextText.setPadding(contentPadding, 0, contentPadding, contentPadding) + + // 边线 + const lineColor = rgbToColorNumber(hexToRgb(config.lineColor=='transparent'?'rgba(255,255,255,0)':config.lineColor)!) + let borderBottomView = new View(context); + borderBottomView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1)) + borderBottomView.setBackgroundColor(lineColor) + + // 竖向边线 + let borderRightView = new View(context); + borderRightView.setLayoutParams(new LinearLayout.LayoutParams(1,ViewGroup.LayoutParams.MATCH_PARENT)) + borderRightView.setBackgroundColor(lineColor) + + // 底部容器 + let footerDiv = new LinearLayout(context) + footerDiv.setOrientation(LinearLayout.HORIZONTAL) + footerDiv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + + let footerDivPadding = px2dp(16).toInt() + + if (config.isSplitBtn) { + footerDiv.setPadding(footerDivPadding, 0, contentPadding, footerDivPadding) + } else { + footerDiv.setPadding(0, 0, 0, 0) + } + + // 取消按钮 + let btnheight = px2dp(50).toInt() + let cancelBtnBG = new GradientDrawable() + cancelBtnBG.setColor(cancelBgColorRgb) + if (config.isSplitBtn) { + cancelBtnBG.setCornerRadius((px2dp(50)).toFloat()) + } + let confirmBtnBG = new GradientDrawable() + confirmBtnBG.setColor(confirmBgColorRgb) + if (config.isSplitBtn) { + confirmBtnBG.setCornerRadius((px2dp(50)).toFloat()) + } + + let cancelDiv = new TextView(context); + cancelDiv.setLayoutParams(new LinearLayout.LayoutParams(0, btnheight, (1).toFloat())); + cancelDiv.setTextSize((16.0).toFloat()); + cancelDiv.setTextColor(cancelColorRgb); + cancelDiv.setGravity(Gravity.CENTER); + + + + cancelDiv.setBackground(cancelBtnBG); + if (config.showCancel) { + if (config.cancelIcon != '') { + let assetManager = context!.getAssets(); + let typeface = Typeface.createFromAsset(assetManager, "remixicon.ttf") + cancelDiv.setTypeface(typeface) + if (!TextUtils.isEmpty(config.cancelIcon)) { + let codePoint = Integer.parseInt(config.cancelIcon, 16); + let charArray = Character.toChars(codePoint); + let text = new String(charArray); + let str = config.cancelText != "" ? (" " + config.cancelText) : config.cancelText + cancelDiv.setText(text + str); + } + } else { + cancelDiv.setText(config.cancelText); + } + + + } + + + + let confirmDiv = new TextView(context); + confirmDiv.setLayoutParams(new LinearLayout.LayoutParams(0, btnheight, (1).toFloat())); + confirmDiv.setTextSize((16.0).toFloat()); + confirmDiv.setTextColor(confirmColorRgb); + confirmDiv.setGravity(Gravity.CENTER); + confirmDiv.setBackground(confirmBtnBG); + + if (config.confirmIcon != '') { + let assetManager = context!.getAssets(); + let typeface = Typeface.createFromAsset(assetManager, "remixicon.ttf") + confirmDiv.setTypeface(typeface) + if (!TextUtils.isEmpty(config.confirmIcon)) { + let codePoint = Integer.parseInt(config.confirmIcon, 16); + let charArray = Character.toChars(codePoint); + let text = new String(charArray); + let str = config.confirmText != "" ? (" " + config.confirmText) : config.confirmText + confirmDiv.setText(text + str); + } + } else { + confirmDiv.setText(config.confirmText); + } + + let confirmDivPadding = px2dp(16).toInt() + let spaceDiv = new TextView(context); + spaceDiv.setLayoutParams(new LinearLayout.LayoutParams(confirmDivPadding, btnheight)); + + + + // 添加遮罩事件. + class MaskerDomClickListsner extends View.OnTouchListener { + firstX = 0 + firstY = 0 + type = "" + constructor(type : string) { + super(); + this.type = type + } + override onTouch(view : View, event : MotionEvent) : Boolean { + + + let action = event.getAction() + let t = this; + if (action == MotionEvent.ACTION_DOWN) { + this.firstX = event.getX() + this.firstY = event.getY() + } + if (action == MotionEvent.ACTION_UP) { + + + // 检查是否是点击动作 + if (event.getDownTime() - event.getEventTime() < 300) { + // event.getX() == this.firstX && event.getY() == this.firstY + // 下面是兼容三星S21-23机型 + if (Math.abs(event.getX() - this.firstX) < 10 && Math.abs(event.getY() - this.firstY) < 10 && !isClsoing) { + isClsoing = true; + + close(() => { + + if (t.type == 'cancel') { + config.cancel() + config.close() + } + if (t.type == 'confirm') { + config.confirm() + config.close() + } + if (t.type == 'mask') { + config.close() + + } + }, (t.type == 'mask' && config.clickMaskClose) || t.type != 'mask') + } + } + } + return true; + } + } + maskerDom.setOnTouchListener(new MaskerDomClickListsner('mask')) + + // 内容容器事件 + class containerDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + return true; + } + } + container.setOnTouchListener(new containerDomClickListsner()) + // 取消事件 + cancelDiv.setOnTouchListener(new MaskerDomClickListsner('cancel')) + // 确认按钮事件 + confirmDiv.setOnTouchListener(new MaskerDomClickListsner('confirm')) + + + if (config.showCancel) { + footerDiv.addView(cancelDiv) + if (!config.isSplitBtn) { + footerDiv.addView(borderRightView) + } + } + + if (config.isSplitBtn && config.showCancel) { + footerDiv.addView(spaceDiv) + } + + + + + footerDiv.addView(confirmDiv) + + + content.addView(contextText) + + container.addView(titleDiv) + container.addView(content) + + + if (!config.isSplitBtn) { + container.addView(borderBottomView) + } + + container.addView(footerDiv) + maskerDom.addView(container) + decorView.addView(maskerDom!) + + try { + let s0 = (0).toFloat() + let s1 = (1).toFloat() + container.setAlpha(s0) + container.setScaleX(s0) + container.setScaleY(s0) + + // 遮罩渐变 + const maskAni = maskerDom.animate() as ViewPropertyAnimator; + maskAni.alpha(s1) + .setDuration(350) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + let ani = container.animate() as ViewPropertyAnimator; + ani.alpha(s1) + .scaleX(s1) + .scaleY(s1) + .setDuration(350) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + + } catch (e) { + console.error(e) + //TODO handle the exception + } + + masker = maskerDom + +} + +function _showModal_(opts : X_MODAL_TYPE) { + dialogModal = new FullScreenDialogFragment(UTSAndroid.getUniActivity()!, opts) + UTSAndroid.getDispatcher("main").async(function (_) { + dialogModal?.show() + + }, null) +} +export function showModal(opts : X_MODAL_TYPE) { + dialogModal?.dismiss() + const pages = getCurrentPages(); + if (pages.length > 0) { + const page = pages[pages.length - 1].vm! + const instance = page.$ + if (page.$isReady) { + _showModal_(opts) + } + onUnload(() => { + close(() => { }, true) + }, instance) + } else { + _showModal_(opts) + } +} + diff --git a/uni_modules/x-modal-s/utssdk/app-harmony/config.json b/uni_modules/x-modal-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..5ee020c --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_modal_s": "./lib/x_modal_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/app-harmony/index.uts b/uni_modules/x-modal-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..b2009b1 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-harmony/index.uts @@ -0,0 +1,14 @@ +import { X_MODAL_TYPE, X_MODAL_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { hexToRgb } from "../libs/color.uts" +import {xcloseModal,xshowModal} from "x_modal_s" + + +export const close = (call : () => void, isClose : boolean) => { + if (!isClose) return; + xcloseModal(UTSHarmony.getCurrentWindow()!.getUIContext()) +} +export function showModal(opts : X_MODAL_TYPE) { + let config = configCover(opts) + xshowModal(UTSHarmony.getCurrentWindow()!.getUIContext(),config) +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/app-harmony/lib/x_modal_s.har b/uni_modules/x-modal-s/utssdk/app-harmony/lib/x_modal_s.har new file mode 100644 index 0000000..8f3f160 Binary files /dev/null and b/uni_modules/x-modal-s/utssdk/app-harmony/lib/x_modal_s.har differ diff --git a/uni_modules/x-modal-s/utssdk/app-ios/Info.plist b/uni_modules/x-modal-s/utssdk/app-ios/Info.plist new file mode 100644 index 0000000..1dd21fc --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-ios/Info.plist @@ -0,0 +1,10 @@ + + + + + UIAppFonts + + remixicon.ttf + + + \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-modal-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-modal-s/utssdk/app-ios/Resources/remixicon.ttf b/uni_modules/x-modal-s/utssdk/app-ios/Resources/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-modal-s/utssdk/app-ios/Resources/remixicon.ttf differ diff --git a/uni_modules/x-modal-s/utssdk/app-ios/config.json b/uni_modules/x-modal-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-modal-s/utssdk/app-ios/index.uts b/uni_modules/x-modal-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..8809d97 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/app-ios/index.uts @@ -0,0 +1,501 @@ +import { X_MODAL_TYPE, X_MODAL_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { UIView, UIViewController, NSLayoutConstraint, UIScrollView, NSLineBreakMode, UIFont, UILabel, UITapGestureRecognizer, UITextView, UITextItemInteraction, UITextViewDelegate, UIScrollViewDelegate, UITextItem, UIAction, UIEvent, UIUserInterfaceStyle, UIDataDetectorTypes, UIColor } from 'UIKit'; +import { CGRect, CGPoint, CGFloat, CGAffineTransform } from 'CoreFoundation'; +import { Alignment , Color } from 'SwiftUI'; +import { UInt32, KeyPath } from 'Swift'; +import { NSString, Data, NSAttributedString, URL, AttributedString } from 'Foundation'; +import { CABasicAnimation, CAAnimationDelegate, CAMediaTimingFillMode, CAAnimation, CAMediaTimingFunction, CAMediaTimingFunctionName, CALayer } from 'QuartzCore'; +import { Selector, NSObject, NSObjectProtocol } from "ObjectiveC"; +import { String } from "Swift"; +type callTYPE = (str:string)=>void +let maskerDom : null | UIView = null; +let tid = 0 +class AllModalObjectLisen { + private callback : () => void + constructor(callback : () => void) { + this.callback = callback; + super.init() + } + + @objc cancelClick() { + // console.log("取消被点击") + this.callback() + } + @objc confirmClick() { + // console.log("确认被点击") + this.callback() + } + @objc maskClick() { + // console.log("遮罩被点击") + this.callback() + } + @objc containerClick() { + // console.log("内容区域点击了") + + } +} +class AnimaionStop implements CAAnimationDelegate { + + animationDidStop(_ : CAAnimation, @argumentLabel("finished") flag : boolean) { + console.log("动画关闭2", flag) + closeModal() + } +} + +class contentTextDeleage18 implements UITextViewDelegate { + private callback :callTYPE + constructor(callback : callTYPE) { + this.callback = callback; + super.init() + } + textView(tv : UITextView, url : URL, characterRange : NSRange, interaction : UITextItemInteraction) : boolean { + // this.optsRealConfig.clickLink(url.absoluteString) + console.log('点击') + return false; + } +} + +// new AllModalObjectLisen() +let cancellListen : AllModalObjectLisen | null = null; +let confirmlListen : AllModalObjectLisen | null = null; +let masklListen : AllModalObjectLisen | null = null; +let containerlListen : AllModalObjectLisen | null = null; +let closeinganimationListen : AnimaionStop | null = null; + +let linkDelegage : UITextViewDelegate | null = null; +function closeModal() { + DispatchQueue.main.async(execute = () : void => { + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + maskerDom = null; + masklListen = null; + cancellListen = null; + confirmlListen = null; + containerlListen = null; + } + }) +} +export const close = (call : () => void, isClose : boolean) => { + if (!isClose) return; + closeModal() + call() +} +export function showModal(opts : X_MODAL_TYPE) { + DispatchQueue.main.async(execute = () : void => { + if (maskerDom != null) { + clearTimeout(tid) + maskerDom!.removeFromSuperview() + } + let parent = UTSiOS.getCurrentViewController() as UIViewController; + let parentView = parent.view as UIView + + let config = configCover(opts) + let titleHeight = 50; + let footerHeight = 74 + let contentHeight = config.height - titleHeight; + let width = config.width; + let height = config.height + titleHeight + + maskerDom = new UIView() + + if (maskerDom == null) return; + let cg = parentView.frame as CGRect + maskerDom!.frame = cg + maskerDom!.backgroundColor = UTSiOS.colorWithString(config.maskBgColor) + + // 内容区域外框。 + let container = new UIView(); + container.layer.cornerRadius = 16 + container.layer.masksToBounds = true; + container.backgroundColor = UTSiOS.colorWithString(config.contentBgColor) + // 内容区域外框 + let scaleAni = new CABasicAnimation(keyPath = "transform.scale") + scaleAni.fromValue = 0 + scaleAni.toValue = 1 + scaleAni.duration = 0.3 + scaleAni.autoreverses = true + scaleAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + let opacityAni = new CABasicAnimation(keyPath = "opacity") + opacityAni.fromValue = 0 + opacityAni.toValue = 1 + opacityAni.duration = 0.3 + + opacityAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + container.layer.add(scaleAni, forKey = "scaleAnimation") + // UIView.animate(withDuration = 0.3, animations = ()=>{ + // container.transform = new CGAffineTransform(scaleX= 1.5, y= 1.5) + // }) + container.layer.add(opacityAni, forKey = "opacityAnimation") + maskerDom!.layer.add(opacityAni, forKey = "opacityAnimation") + + + + + container.translatesAutoresizingMaskIntoConstraints = false + maskerDom!.addSubview(container) + NSLayoutConstraint.activate([ + // 中心约束 + container.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + container.centerYAnchor.constraint(equalTo = maskerDom!.centerYAnchor), + // 宽约束100 + container.widthAnchor.constraint(equalToConstant = new CGFloat(width!)), + // 高为至少100 + container.heightAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(height)) + ]) + // 添加标题 + let titleDiv = new UILabel(); + titleDiv.textColor = UTSiOS.colorWithString(config.titleColor) + titleDiv.text = new String(config.title) + titleDiv.font = UIFont.systemFont(ofSize = new CGFloat(18)) + titleDiv.frame = new CGRect(x = 0, y = 0, width = (width!).toInt(), height = titleHeight.toInt()) + titleDiv.textAlignment = NSTextAlignment.center + container.addSubview(titleDiv) + // 添加scroll + let content = new UIScrollView(); + content.frame = new CGRect(x = 0, y = titleHeight.toInt(), width = (width!).toInt(), height = config.height!.toInt()) + content.isScrollEnabled = true; + content.bounces = true + container.addSubview(content) + let contextText = new UITextView(); + contextText.isEditable = false; + contextText.isSelectable = true; + // contextText.isUserInteractionEnabled = true; + // contextText.delaysContentTouches = true; + // contextText.dataDetectorTypes = [UIDataDetectorTypes.link,UIDataDetectorTypes.phoneNumber] + + + if (UTSiOS.available("iOS 13.0, *")) { + contextText.overrideUserInterfaceStyle = UIUserInterfaceStyle.light + } + // config.content + const htmlContentData : Data = new String(config.content).data(using = String.Encoding.utf8)! + const opts = new Map([ + [NSAttributedString.DocumentReadingOptionKey.documentType, NSAttributedString.DocumentType.html], + [NSAttributedString.DocumentReadingOptionKey.characterEncoding, String.Encoding.utf8.rawValue] + ]) + let attributedString = UTSiOS.try(new NSAttributedString(data = htmlContentData, options = opts, documentAttributes = null), "?") + let mutableAttrStr = NSMutableAttributedString(attributedString = attributedString!) + mutableAttrStr.addAttribute(NSAttributedString.Key.foregroundColor, value=config.contentColor, range= NSRange(location= 0, length= attributedString!.length)) + contextText.attributedText = mutableAttrStr + contextText.textColor = UTSiOS.colorWithString(config.contentColor) + contextText.backgroundColor = UTSiOS.colorWithString(config.contentBgColor) + + linkDelegage = new contentTextDeleage18(config.clickLink as callTYPE) as UITextViewDelegate + contextText.delegate = linkDelegage! + // contextText.text = new String(config.content) + contextText.font = UIFont.systemFont(ofSize = new CGFloat(15)) + // contextText.lineBreakMode = NSLineBreakMode.byWordWrapping + // contextText.backgroundColor = UTSiOS.colorWithString("red") + // contextText.numberOfLines = 0 + // 根据内容调整UILabel的大小 + contextText.sizeToFit() + contextText.translatesAutoresizingMaskIntoConstraints = false + content.addSubview(contextText) + + + + + if (config.contentAlign == 'center') { + contextText.textAlignment = NSTextAlignment.center + NSLayoutConstraint.activate([ + // 顶部约束 + contextText.topAnchor.constraint(equalTo = content.topAnchor, constant = 0), + contextText.bottomAnchor.constraint(equalTo = content.bottomAnchor, constant = 0), + // contextText.widthAnchor.constraint(equalToConstant = new CGFloat((width!-32))), + // 左侧约束 + contextText.leadingAnchor.constraint(equalTo = content.leadingAnchor, constant = 16), + // 右侧约束 + contextText.trailingAnchor.constraint(equalTo = content.safeAreaLayoutGuide.trailingAnchor, constant = -16), + contextText.centerXAnchor.constraint(equalTo = content.centerXAnchor), + contextText.centerYAnchor.constraint(equalTo = content.centerYAnchor), + ]) + } else { + NSLayoutConstraint.activate([ + // 顶部约束 + contextText.topAnchor.constraint(equalTo = content.topAnchor, constant = 0), + contextText.bottomAnchor.constraint(equalTo = content.bottomAnchor, constant = 0), + // contextText.widthAnchor.constraint(equalToConstant = new CGFloat((width!-32))), + // 左侧约束 + contextText.leadingAnchor.constraint(equalTo = content.leadingAnchor, constant = 16), + // 右侧约束 + contextText.trailingAnchor.constraint(equalTo = content.safeAreaLayoutGuide.trailingAnchor, constant = -16) + ]) + } + + if (!config.isSplitBtn&&config.lineColor!=''&&config.lineColor!='transparent'){ + // 添加边线顶。 + let footerDivTopBorder = new UIView() + footerDivTopBorder.translatesAutoresizingMaskIntoConstraints = false + footerDivTopBorder.backgroundColor = UTSiOS.colorWithString(config.lineColor) + container.addSubview(footerDivTopBorder) + NSLayoutConstraint.activate([ + footerDivTopBorder.heightAnchor.constraint(equalToConstant = 0.5), + footerDivTopBorder.widthAnchor.constraint(equalTo = container.safeAreaLayoutGuide.widthAnchor), + // 顶部约束 + footerDivTopBorder.topAnchor.constraint(equalTo = content.bottomAnchor, constant = 15), + ]) + } + + + // 底部容器 + let footerDiv = new UIView() + footerDiv.translatesAutoresizingMaskIntoConstraints = false + // footerDiv.backgroundColor = UTSiOS.colorWithString("#333333") + + container.addSubview(footerDiv) + if (config.isSplitBtn) { + NSLayoutConstraint.activate([ + footerDiv.heightAnchor.constraint(equalToConstant = 50), + // footerDiv.widthAnchor.constraint(equalTo = container.safeAreaLayoutGuide.widthAnchor), + // 顶部约束 + footerDiv.topAnchor.constraint(equalTo = content.bottomAnchor, constant = 16), + footerDiv.bottomAnchor.constraint(equalTo = container.bottomAnchor, constant = -16), + // 左侧约束 + footerDiv.leadingAnchor.constraint(equalTo = container.leadingAnchor, constant = 16), + // 右侧约束 + footerDiv.trailingAnchor.constraint(equalTo = container.trailingAnchor, constant = -16) + ]) + } else { + + + NSLayoutConstraint.activate([ + footerDiv.heightAnchor.constraint(equalToConstant = 50), + // 顶部约束 + footerDiv.topAnchor.constraint(equalTo = content.bottomAnchor, constant = 16), + footerDiv.bottomAnchor.constraint(equalTo = container.bottomAnchor, constant = 0), + // 左侧约束 + footerDiv.leadingAnchor.constraint(equalTo = container.leadingAnchor, constant = 0), + // 右侧约束 + footerDiv.trailingAnchor.constraint(equalTo = container.trailingAnchor, constant = 0) + ]) + } + + + + // 添加取消按钮。 + let cancelDiv = new UILabel(); + cancelDiv.font = new UIFont(name = "remixicon", size = new CGFloat(15)) + let cancelIcontext = "" + if (config.cancelIcon != '') { + let codePoint = new UInt32(config.cancelIcon, radix = 16) + let stricon = new NSString(format = "%C", codePoint!) + cancelIcontext = new String(stricon); + } + + cancelDiv.textColor = UTSiOS.colorWithString(config.cancelColor) + cancelDiv.text = new String(cancelIcontext != '' ? (cancelIcontext + ' ' + config.cancelText) : config.cancelText) + // cancelDiv.font = UIFont.systemFont(ofSize = new CGFloat(15)) + cancelDiv.textAlignment = NSTextAlignment.center + cancelDiv.backgroundColor = UTSiOS.colorWithString(config.cancelBgColor) + + + + if (config.isSplitBtn) { + cancelDiv.layer.cornerRadius = 25 + cancelDiv.layer.masksToBounds = true; + } + // 添加确认按钮。 + let confirmDiv = new UILabel(); + confirmDiv.font = new UIFont(name = "remixicon", size = new CGFloat(15)) + let confirmIcontext = "" + if (config.confirmIcon != '') { + let codePoint = new UInt32(config.confirmIcon, radix = 16) + let stricon = new NSString(format = "%C", codePoint!) + confirmIcontext = new String(stricon); + } + confirmDiv.textColor = UTSiOS.colorWithString(config.confirmColor) + confirmDiv.text = new String(confirmIcontext != '' ? (confirmIcontext + ' ' + config.confirmText) : config.confirmText) + + confirmDiv.textAlignment = NSTextAlignment.center + confirmDiv.backgroundColor = UTSiOS.colorWithString(config.confirmBgColor) + if (config.isSplitBtn) { + confirmDiv.layer.cornerRadius = 25 + confirmDiv.layer.masksToBounds = true; + } + cancelDiv.translatesAutoresizingMaskIntoConstraints = false + confirmDiv.translatesAutoresizingMaskIntoConstraints = false + + + + if (config.isSplitBtn) { + if (config.showCancel) { + footerDiv.addSubview(cancelDiv) + footerDiv.addSubview(confirmDiv) + NSLayoutConstraint.activate([ + // 顶部约束 + cancelDiv.topAnchor.constraint(equalTo = footerDiv.topAnchor, constant = 0), + cancelDiv.bottomAnchor.constraint(equalTo = footerDiv.bottomAnchor, constant = 0), + // 左侧约束 + cancelDiv.leadingAnchor.constraint(equalTo = content.safeAreaLayoutGuide.leadingAnchor, constant = 16), + cancelDiv.trailingAnchor.constraint(equalTo = confirmDiv.safeAreaLayoutGuide.trailingAnchor, constant = 8), + cancelDiv.widthAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.widthAnchor, multiplier = 0.5), + + // 顶部约束 + confirmDiv.topAnchor.constraint(equalTo = footerDiv.topAnchor, constant = 0), + confirmDiv.bottomAnchor.constraint(equalTo = footerDiv.bottomAnchor, constant = 0), + // 左侧约束 + confirmDiv.leadingAnchor.constraint(equalTo = cancelDiv.safeAreaLayoutGuide.trailingAnchor, constant = 8), + confirmDiv.trailingAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.trailingAnchor, constant = 0), + // confirmDiv.widthAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.widthAnchor,multiplier=0.5), + // confirmDiv.heightAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.heightAnchor) + ]) + } else { + footerDiv.addSubview(confirmDiv) + NSLayoutConstraint.activate([ + // 顶部约束 + confirmDiv.topAnchor.constraint(equalTo = footerDiv.topAnchor, constant = 0), + confirmDiv.bottomAnchor.constraint(equalTo = footerDiv.bottomAnchor, constant = 0), + // 左侧约束 + confirmDiv.leadingAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.leadingAnchor, constant = 0), + confirmDiv.trailingAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.trailingAnchor, constant = 0), + ]) + } + + } else { + if (config.showCancel) { + footerDiv.addSubview(cancelDiv) + footerDiv.addSubview(confirmDiv) + NSLayoutConstraint.activate([ + // 顶部约束 + cancelDiv.topAnchor.constraint(equalTo = footerDiv.topAnchor, constant = 0), + cancelDiv.bottomAnchor.constraint(equalTo = footerDiv.bottomAnchor, constant = 0), + // 左侧约束 + cancelDiv.leadingAnchor.constraint(equalTo = content.safeAreaLayoutGuide.leadingAnchor, constant = 0), + cancelDiv.trailingAnchor.constraint(equalTo = confirmDiv.safeAreaLayoutGuide.trailingAnchor, constant = 0), + cancelDiv.widthAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.widthAnchor, multiplier = 0.5), + + // 顶部约束 + confirmDiv.topAnchor.constraint(equalTo = footerDiv.topAnchor, constant = 0), + confirmDiv.bottomAnchor.constraint(equalTo = footerDiv.bottomAnchor, constant = 0), + // 左侧约束 + confirmDiv.leadingAnchor.constraint(equalTo = cancelDiv.safeAreaLayoutGuide.trailingAnchor, constant = 0), + confirmDiv.trailingAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.trailingAnchor, constant = 0), + // confirmDiv.widthAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.widthAnchor,multiplier=0.5), + // confirmDiv.heightAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.heightAnchor) + ]) + } else { + footerDiv.addSubview(confirmDiv) + NSLayoutConstraint.activate([ + // 顶部约束 + confirmDiv.topAnchor.constraint(equalTo = footerDiv.topAnchor, constant = 0), + confirmDiv.bottomAnchor.constraint(equalTo = footerDiv.bottomAnchor, constant = 0), + // 左侧约束 + confirmDiv.leadingAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.leadingAnchor, constant = 0), + confirmDiv.trailingAnchor.constraint(equalTo = footerDiv.safeAreaLayoutGuide.trailingAnchor, constant = 0), + ]) + } + + // 添加按钮的右边线。 + if (!config.isSplitBtn&&config.lineColor!=''&&config.lineColor!='transparent'&&config.showCancel){ + // 添加边线顶。 + let cancelRightBorder = new UIView() + cancelRightBorder.translatesAutoresizingMaskIntoConstraints = false + cancelRightBorder.backgroundColor = UTSiOS.colorWithString(config.lineColor) + footerDiv.addSubview(cancelRightBorder) + NSLayoutConstraint.activate([ + cancelRightBorder.heightAnchor.constraint(equalTo = cancelDiv.heightAnchor), + cancelRightBorder.widthAnchor.constraint(equalToConstant = 0.5), + // 顶部约束 + cancelDiv.topAnchor.constraint(equalTo = content.bottomAnchor, constant = 16), + cancelRightBorder.leadingAnchor.constraint(equalTo = confirmDiv.safeAreaLayoutGuide.leadingAnchor, constant = 1), + ]) + } + } + + cancelDiv.isUserInteractionEnabled = true; + confirmDiv.isUserInteractionEnabled = true; + container.isUserInteractionEnabled = true; + maskerDom!.isUserInteractionEnabled = true; + + function closeanimation() { + if (maskerDom == null) return; + let scaleAni = new CABasicAnimation(keyPath = "transform.scale") + scaleAni.fromValue = 1 + scaleAni.toValue = 0 + scaleAni.duration = 0.3 + scaleAni.fillMode = CAMediaTimingFillMode.forwards + scaleAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + scaleAni.isRemovedOnCompletion = false + let opactiyAni = new CABasicAnimation(keyPath = "opacity") + opactiyAni.fromValue = 1 + opactiyAni.toValue = 0 + opactiyAni.duration = 0.3 + opactiyAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut); + opactiyAni.isRemovedOnCompletion = false + opacityAni.fillMode = CAMediaTimingFillMode.forwards + container.layer.add(scaleAni, forKey = "scaleAnimation") + container.layer.add(opactiyAni, forKey = "opacityAnimation") + + + let opactiyAniBymsk = new CABasicAnimation(keyPath = "opacity") + opactiyAniBymsk.fromValue = 1 + opactiyAniBymsk.toValue = 0 + opactiyAniBymsk.duration = 0.3 + opactiyAniBymsk.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut); + opactiyAniBymsk.isRemovedOnCompletion = false + opactiyAniBymsk.fillMode = CAMediaTimingFillMode.forwards + maskerDom!.layer.add(opactiyAniBymsk, forKey = "opacityAnimation") + + class AniDelete implements NSObject, CAAnimationDelegate { + animationDidStop(_ : CAAnimation, @argumentLabel("finished") flag : boolean) { + console.log("动画关闭2", flag) + closeModal() + } + } + + scaleAni.delegate = new AniDelete() + // closeinganimationListen = new AnimaionStop() + + tid = setTimeout(function () { + container.layer.opacity = 0 + closeModal() + }, 280); + } + + + + function callbackFun(type : string) { + if (type == 'container') return; + + if (type == 'cancel') { + config.cancel() + config.close() + closeanimation() + } + if (type == 'confirm') { + config.confirm() + config.close() + closeanimation() + } + if (type == 'mask' && config.clickMaskClose) { + config.close() + closeanimation() + } + } + + cancellListen = new AllModalObjectLisen(() => { callbackFun('cancel') }); + confirmlListen = new AllModalObjectLisen(() => { callbackFun('confirm') }); + masklListen = new AllModalObjectLisen(() => { callbackFun('mask') }); + containerlListen = new AllModalObjectLisen(() => { callbackFun('container') }); + + + let tapGestureCancel = new UITapGestureRecognizer() + tapGestureCancel.addTarget(cancellListen, action = new Selector("cancelClick")) + let tapGestureConfirm = new UITapGestureRecognizer() + tapGestureConfirm.addTarget(confirmlListen, action = new Selector("confirmClick")) + let tapGestureMask = new UITapGestureRecognizer() + tapGestureMask.addTarget(masklListen, action = new Selector("maskClick")) + let tapGestureContainer = new UITapGestureRecognizer() + tapGestureContainer.addTarget(containerlListen, action = new Selector("containerClick")) + + + cancelDiv.addGestureRecognizer(tapGestureCancel) + confirmDiv.addGestureRecognizer(tapGestureConfirm) + maskerDom!.addGestureRecognizer(tapGestureMask) + container.addGestureRecognizer(tapGestureContainer) + + + parentView.addSubview(maskerDom!) + }) +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/interface.uts b/uni_modules/x-modal-s/utssdk/interface.uts new file mode 100644 index 0000000..2d2de1c --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/interface.uts @@ -0,0 +1,91 @@ +export type RGBA = { r : number, g : number, b : number, a : number } + +export type X_MODAL_TYPE = { + title?:string, + content?:string, + /** + * 内容居中方式: + * left:就是正常的顶左对齐. + * center:就是左右上下居中. + */ + contentAlign?:string, + cancelText?:string, + cancelBgColor?:string, + cancelColor?:string, + confirmText?:string, + confirmBgColor?:string, + confirmColor?:string, + linkFontColor?:string, + radius?:number, + confirmIcon?:string, + cancelIcon?:string, + titleColor?:string, + contentColor?:string, + /** + * 按钮是否分离 + * @default true + */ + isSplitBtn?:boolean, + /** + * 当isSplitBtn为false时,如果按钮都为白时需要添加上边线和按钮中间分割线时可以启用分割线颜色 + * 默认为透明。 + */ + lineColor?:string, + // 框体内容背景 + contentBgColor?:string, + // 遮罩背景 + maskBgColor?:string, + confirm?:()=>void, + cancel?:()=>void, + close?:()=>void, + clickLink?:(href:string)=>void, + /** + * 背景模糊,目前仅web生效 + * @default true + */ + isBlurMask?:boolean, + height?:number, + width?:number, + /** + * 是否允许点击遮罩关闭 + * @default true + */ + clickMaskClose?:boolean, + /** + * 是否显示取消按钮 + * @default true + */ + showCancel?:boolean +} +export type X_MODAL_TYPE_PRIVATE = { + title:string, + content:string, + contentAlign:string, + cancelText:string, + cancelBgColor:string, + cancelColor:string, + titleColor:string, + contentColor:string, + confirmText:string, + confirmBgColor:string, + confirmColor:string, + linkFontColor:string, + lineColor:string, + radius:number, + confirmIcon:string, + cancelIcon:string, + isSplitBtn:boolean, + // 框体内容背景 + contentBgColor:string, + // 遮罩背景 + maskBgColor:string, + confirm:()=>void, + cancel:()=>void, + close:()=>void, + clickLink:(href:string)=>void, + isBlurMask:boolean, + height:number, + width:number, + clickMaskClose:boolean, + showCancel:boolean +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/libs/color.uts b/uni_modules/x-modal-s/utssdk/libs/color.uts new file mode 100644 index 0000000..0579d0b --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/libs/color.uts @@ -0,0 +1,59 @@ + +import {RGBA} from "../interface.uts" +export function hexToRgb(sColors : string) : RGBA | null { + if (sColors == "") { + return null + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + let p : number[] = arr.map((val : string) : number => parseInt(val)); + + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + p.add(1) + + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: arr.length==3?p[3]:parseFloat(arr[3]) + } as RGBA + } + + return null; +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/libs/config.uts b/uni_modules/x-modal-s/utssdk/libs/config.uts new file mode 100644 index 0000000..44f3516 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/libs/config.uts @@ -0,0 +1,109 @@ +import {X_MODAL_TYPE,X_MODAL_TYPE_PRIVATE} from "../interface.uts" +export const defaultConfig = { + title:"提醒", + content:"", + contentAlign:'center', + cancelText:"取消", + cancelColor:"#333", + cancelBgColor:"#f5f5f5", + confirmText:"确认", + confirmBgColor:"#0579FF", + confirmColor:"#FFF", + titleColor:'#000000', + contentColor:"#333333", + lineColor:"transparent", + linkFontColor:"rgb(5, 121, 255)", + radius:16, + confirmIcon:"", + cancelIcon:"", + isSplitBtn:true, + contentBgColor:"#fff", + maskBgColor:"rgba(0,0,0,0.6)", + confirm:()=>{}, + cancel:()=>{}, + close:()=>{}, + clickLink:(href:string)=>{}, + isBlurMask:true, + height:80, + width:320, + clickMaskClose:true, + showCancel:true +} as X_MODAL_TYPE_PRIVATE + + +export const configCover = (opts : X_MODAL_TYPE) : X_MODAL_TYPE_PRIVATE => { + let title = opts.title==null?defaultConfig.title:(opts.title!); + let content = opts.content==null?defaultConfig.content:(opts.content!); + let cancelText = opts.cancelText==null?defaultConfig.cancelText:(opts.cancelText!); + let cancelBgColor = opts.cancelBgColor==null?defaultConfig.cancelBgColor:(opts.cancelBgColor!); + let cancelColor = opts.cancelColor==null?defaultConfig.cancelColor:(opts.cancelColor!); + let confirmText = opts.confirmText==null?defaultConfig.confirmText:(opts.confirmText!); + let confirmBgColor = opts.confirmBgColor==null?defaultConfig.confirmBgColor:(opts.confirmBgColor!); + let confirmColor = opts.confirmColor==null?defaultConfig.confirmColor:(opts.confirmColor!); + let radius = opts.radius==null?defaultConfig.radius:(opts.radius!); + let confirmIcon = opts.confirmIcon==null?defaultConfig.confirmIcon:(opts.confirmIcon!); + let cancelIcon = opts.cancelIcon==null?defaultConfig.cancelIcon:(opts.cancelIcon!); + let contentBgColor = opts.contentBgColor==null?defaultConfig.contentBgColor:(opts.contentBgColor!); + let maskBgColor = opts.maskBgColor==null?defaultConfig.maskBgColor:(opts.maskBgColor!); + let confirm = opts.confirm==null?defaultConfig.confirm:(opts.confirm!); + let cancel = opts.cancel==null?defaultConfig.cancel:(opts.cancel!); + let close = opts.close==null?defaultConfig.close:(opts.close!); + let height = opts.height==null?defaultConfig.height:(opts.height!); + let width = opts.width==null?defaultConfig.width:(opts.width!); + let titleColor = opts.titleColor==null?defaultConfig.titleColor:(opts.titleColor!); + let contentColor = opts.contentColor==null?defaultConfig.contentColor:(opts.contentColor!); + let contentAlign = opts.contentAlign==null?defaultConfig.contentAlign:(opts.contentAlign!); + let clickLink = opts.clickLink==null?defaultConfig.clickLink:(opts.clickLink!); + let linkFontColor = opts.linkFontColor==null?defaultConfig.linkFontColor:(opts.linkFontColor!); + let lineColor = opts.lineColor==null?defaultConfig.lineColor:(opts.lineColor!); + + + // #ifdef APP-ANDROID || APP-HARMONY + + let clickMaskClose = opts.clickMaskClose==null?defaultConfig.clickMaskClose:(opts.clickMaskClose!); + let showCancel = opts.showCancel==null?defaultConfig.showCancel:(opts.showCancel!); + let isBlurMask = opts.isBlurMask==null?defaultConfig.isBlurMask:(opts.isBlurMask!); + let isSplitBtn = opts.isSplitBtn==null?defaultConfig.isSplitBtn:(opts.isSplitBtn!); + // #endif + + // #ifdef WEB || APP-IOS || MP + + let clickMaskClose = opts.clickMaskClose==null?defaultConfig.clickMaskClose:(opts.clickMaskClose); + let showCancel = opts.showCancel==null?defaultConfig.showCancel:(opts.showCancel); + let isBlurMask = opts.isBlurMask==null?defaultConfig.isBlurMask:(opts.isBlurMask); + let isSplitBtn = opts.isSplitBtn==null?defaultConfig.isSplitBtn:(opts.isSplitBtn); + // #endif + + return { + title, + content, + cancelText, + cancelBgColor, + cancelColor, + confirmText, + confirmBgColor, + confirmColor, + linkFontColor, + lineColor, + radius, + confirmIcon, + cancelIcon, + isSplitBtn, + // 框体内容背景 + contentBgColor, + // 遮罩背景 + maskBgColor, + confirm, + cancel, + close, + clickLink, + isBlurMask, + height, + width, + clickMaskClose, + showCancel, + titleColor, + contentColor, + contentAlign + } as X_MODAL_TYPE_PRIVATE +} \ No newline at end of file diff --git a/uni_modules/x-modal-s/utssdk/mp-weixin/index.uts b/uni_modules/x-modal-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..b305b44 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,25 @@ +export {X_MODAL_TYPE,X_MODAL_TYPE_PRIVATE} from "../interface.uts" +import {configCover} from "../libs/config.uts" +export const close = (call : () => void, isClose : boolean)=>{ + if (!isClose) return; + call() + console.error("微信无法关闭showModal") +} + +export const showModal = (opts : any)=>{ + let config = configCover(opts) + uni.showModal({ + title:config.title, + content:config.content, + confirmText:config.confirmText, + cancelText:config.cancelText, + success(e){ + if(e.confirm){ + config.confirm() + }else{ + config.cancel() + } + }, + + }) +} diff --git a/uni_modules/x-modal-s/utssdk/web/index.uts b/uni_modules/x-modal-s/utssdk/web/index.uts new file mode 100644 index 0000000..ad0797d --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/web/index.uts @@ -0,0 +1,220 @@ +export {X_MODAL_TYPE,X_MODAL_TYPE_PRIVATE} from "../interface.uts" +import {defaultConfig,configCover} from "../libs/config.uts" +import { LoadFontFace } from "./loadFont.uts" +let maskerDom : null | HTMLDivElement = null; +let tid = 0 + + +export const close = (call : () => void, isClose : boolean)=>{ + if (!isClose) return; + if (maskerDom != null) { + clearTimeout(tid) + maskerDom.remove() + } + call() +} +// @ts-ignore +export const showModal = (opts : X_MODAL_TYPE) => { + LoadFontFace() + if (maskerDom != null) { + clearTimeout(tid) + maskerDom.remove() + } + let config = configCover(opts) + let titleHeight = 60; + let footerHeight = 74 + let contentHeight = config.height; + let width = config.width; + let height = config.height + + maskerDom = document.createElement("div") + if (maskerDom == null) return; + + maskerDom.style.setProperty("background-color", config.maskBgColor) + maskerDom.style.setProperty("position", "fixed") + maskerDom.style.setProperty("left", "0px") + maskerDom.style.setProperty("top", "0px") + maskerDom.style.setProperty("width", "100%") + maskerDom.style.setProperty("height", "100%") + maskerDom.style.display = "flex" + maskerDom.style.flexDirection = "row" + maskerDom.style.justifyContent = "center" + maskerDom.style.alignItems = "center" + maskerDom.style.zIndex = "301" + // 内容层 + let container = document.createElement("div") + // container.style.padding = "30px" + container.style.width = width+"px" + // container.style.height = height+"px" + container.style.backgroundColor = config.contentBgColor + container.style.borderRadius = config.radius+"px" + container.style.boxSizing = "border-box" + container.style.display = "flex" + container.style.overflow = "hidden" + container.style.flexDirection = "column" + container.style.transition = 'all 0.3s cubic-bezier(.42,.38,.15,.93)' + container.style.scale = "0" + container.style.opacity = "0" + + // 标题 + let titleDiv = document.createElement("div"); + titleDiv.style.textAlign = "center"; + titleDiv.style.height = titleHeight + "px"; + + titleDiv.style.display = "flex" + titleDiv.style.flexDirection = "row" + titleDiv.style.alignItems = "center" + titleDiv.style.justifyContent = "center" + titleDiv.style.fontSize = "18px" + titleDiv.style.fontWeight = "bold" + titleDiv.style.color = config.titleColor + titleDiv.innerText = config.title + + // 内容 + let content = document.createElement("div"); + content.style.height = contentHeight + "px"; + content.style.display = "flex" + content.style.fontSize = "16px" + content.style.color = config.contentColor + content.innerHTML = config.content + content.style.overflowY = 'auto'; + content.style.boxSizing = "border-box" + content.style.padding = "0 16px" + if(config.contentAlign=='center'){ + content.style.flexDirection = 'column' + content.style.justifyContent = 'center' + content.style.alignItems = 'center' + content.style.textAlign = 'center' + } + + content.addEventListener('click',(e:PointerEvent)=>{ + e.preventDefault() + e.stopPropagation() + // @ts-ignore + if(e.target?.href){ + // @ts-ignore + let href = e.target?.href??"" + if(href){ + config.clickLink(href) + } + } + + }) + // 底部容器 + let footerDiv = document.createElement("div"); + footerDiv.style.display = "flex" + footerDiv.style.flexDirection = "row" + footerDiv.style.justifyContent = "center" + footerDiv.style.alignItems = "center" + + // 取消按钮 + let cancelDiv = document.createElement("div"); + cancelDiv.style.flex = "1" + cancelDiv.style.height = "55px" + cancelDiv.style.backgroundColor = config.cancelBgColor + cancelDiv.style.color = config.cancelColor + cancelDiv.style.fontSize = "16px" + cancelDiv.style.display = "flex" + cancelDiv.style.flexDirection = "row" + cancelDiv.style.justifyContent = "center" + cancelDiv.style.alignItems = "center" + cancelDiv.style.fontFamily = "remixicon" + + if(config.cancelIcon!=""){ + let iconstr = String.fromCharCode(parseInt(config.cancelIcon, 16)); + let str = config.cancelText==""?iconstr:(iconstr+" "+config.cancelText) + cancelDiv.innerHTML = str + }else{ + cancelDiv.innerText = config.cancelText + } + + + let confirmDiv = document.createElement("div"); + confirmDiv.style.flex = "1" + confirmDiv.style.height = "55px" + confirmDiv.style.backgroundColor = config.confirmBgColor + confirmDiv.style.color = config.confirmColor + confirmDiv.style.fontSize = "16px" + confirmDiv.style.display = "flex" + confirmDiv.style.flexDirection = "row" + confirmDiv.style.justifyContent = "center" + confirmDiv.style.alignItems = "center" + confirmDiv.style.fontFamily = "remixicon" + if(config.confirmIcon!=""){ + let iconstr = String.fromCharCode(parseInt(config.confirmIcon, 16)); + let str = config.confirmText==""?iconstr:(iconstr+" "+config.confirmText) + confirmDiv.innerHTML = str + }else{ + confirmDiv.innerText = config.confirmText + } + + + + if(config.isSplitBtn){ + footerDiv.style.padding = "16px" + cancelDiv.style.marginRight = "16px" + confirmDiv.style.borderRadius = "55px" + cancelDiv.style.borderRadius = "55px" + }else{ + content.style.paddingBottom = "16px" + } + if(!config.isSplitBtn&&config.showCancel){ + footerDiv.style.borderTop = `0.5px solid ${config.lineColor}` + cancelDiv.style.borderRight = `0.5px solid ${config.lineColor}` + } + if(config.isBlurMask){ + maskerDom.style.backdropFilter = "blur(6px)" + } + + function close(){ + try{ + container.style.scale = "0" + container.style.opacity = "0" + tid = setTimeout(function() { + maskerDom?.remove() + }, 200); + }catch(e){ + //TODO handle the exception + } + } + + cancelDiv.addEventListener("click",function(){ + close() + config.close() + config.cancel() + }) + confirmDiv.addEventListener("click",function(){ + close() + config.close() + config.confirm() + }) + container.addEventListener("click",function(evt:PointerEvent){ + evt.preventDefault() + evt.stopPropagation() + + }) + maskerDom.addEventListener("click",function(){ + if(config.clickMaskClose){ + close() + config.close() + } + }) + if(config.showCancel){ + footerDiv.appendChild(cancelDiv) + } + footerDiv.appendChild(confirmDiv) + container.appendChild(titleDiv) + container.appendChild(content) + container.appendChild(footerDiv) + maskerDom!.appendChild(container) + window.document.body.appendChild(maskerDom!) + + try{ + setTimeout(function() { + container.style.scale = "1" + container.style.opacity = "1" + }, 10); + }catch(e){ + //TODO handle the exception + } +} diff --git a/uni_modules/x-modal-s/utssdk/web/loadFont.uts b/uni_modules/x-modal-s/utssdk/web/loadFont.uts new file mode 100644 index 0000000..18e18b7 --- /dev/null +++ b/uni_modules/x-modal-s/utssdk/web/loadFont.uts @@ -0,0 +1,13 @@ +export function LoadFontFace(){ + // 定义字体 + // @ts-ignore + const font = new FontFace("remixicon", "url(/static/tmui4xLibs/static/remixicon.ttf)", { + style: "italic", + weight: "800", + stretch: "condensed", + }); + + // 把字体添加到 document.fonts(FontFaceSet)中 + document.fonts.add(font); + font.load(); +} \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/changelog.md b/uni_modules/x-mqtt-s/changelog.md new file mode 100644 index 0000000..6415ce0 --- /dev/null +++ b/uni_modules/x-mqtt-s/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2025-08-17) +* 兼容 原生鸿蒙 Next +## 1.0.2(2025-02-13) +* 兼容微信 +## 1.0.1(2024-09-13) +* ios补充取消订阅的方法。 +## 1.0.0(2024-09-05) +首次发布 diff --git a/uni_modules/x-mqtt-s/package.json b/uni_modules/x-mqtt-s/package.json new file mode 100644 index 0000000..48bf883 --- /dev/null +++ b/uni_modules/x-mqtt-s/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-mqtt-s", + "displayName": "MQTT tmui4.0消息推送插件", + "version": "1.0.3", + "description": "mqtt,tmui,webstocket,anriod,ios三端兼容的消息订阅和推送", + "keywords": [ + "ios,mqtt,anriod" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "39.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "网格权限" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/readme.md b/uni_modules/x-mqtt-s/readme.md new file mode 100644 index 0000000..3e62184 --- /dev/null +++ b/uni_modules/x-mqtt-s/readme.md @@ -0,0 +1,130 @@ +# x-mqtt-s +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +用于mqtt连接,推送,订阅消息的插件。 + +安卓:适于用tcp,ssl,ws,wssl等几乎所有协议 +ios:仅适配了webstock mqtt,ws协议 +web:适配webstock mqtt,ws,wss协议 +微信端:wss协议,且服务器不能为mqtt服务需要是ws服务,因此可能需要你在服务器将Mqtt转换为ws + +### 微信使用说明 +微信不支持websocket连接以Mqtt为服务的服务器,你需要在服务器上转换 + + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 类型参考 + +```vue + + + + + + +``` diff --git a/uni_modules/x-mqtt-s/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-mqtt-s/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..e704781 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-android/config.json b/uni_modules/x-mqtt-s/utssdk/app-android/config.json new file mode 100644 index 0000000..eed8b20 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-android/config.json @@ -0,0 +1,6 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "com.github.hannesa2:paho.mqtt.android:4.2.4" + ] +} diff --git a/uni_modules/x-mqtt-s/utssdk/app-android/index.uts b/uni_modules/x-mqtt-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..37f59fe --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-android/index.uts @@ -0,0 +1,237 @@ +import MqttMessage from "org.eclipse.paho.client.mqttv3.MqttMessage"; +import MqttException from "org.eclipse.paho.client.mqttv3.MqttException"; +import MqttConnectOptions from "org.eclipse.paho.client.mqttv3.MqttConnectOptions"; +import MqttCallbackExtended from "org.eclipse.paho.client.mqttv3.MqttCallbackExtended"; +import IMqttToken from "org.eclipse.paho.client.mqttv3.IMqttToken"; +import IMqttMessageListener from "org.eclipse.paho.client.mqttv3.IMqttMessageListener"; +import IMqttDeliveryToken from "org.eclipse.paho.client.mqttv3.IMqttDeliveryToken"; +import IMqttActionListener from "org.eclipse.paho.client.mqttv3.IMqttActionListener"; +import DisconnectedBufferOptions from "org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions"; +import MqttAndroidClient from "info.mqtt.android.service.MqttAndroidClient"; +import QoS from "info.mqtt.android.service.QoS"; +import MqttCallback from "org.eclipse.paho.client.mqttv3.MqttCallback"; +import Kotlin from 'kotlin.jvm.internal.Intrinsics.Kotlin'; +import Context from 'android.content.Context'; +import Intent from 'android.content.Intent'; +import MqttService from 'org.eclipse.paho.android.service.MqttService'; +import Service from 'android.app.Service'; +import IBinder from 'android.os.IBinder'; +import Build from 'android.os.Build'; +import { + CONNECT_STATUS, MQTT_EVENT_TYPE, MQTT_EVENT_CALL, MQTT_EVENT_PUBLISH, MQTT_SUBSCRIBE, MQTT_EVENTS_CALL, + MQTT_PUBLISH_TOPIC, MQTT_CONNECT_OPTS +} from "../interface.uts" + + +// + +// mqtt测试服务器 +// https://console.hivemq.cloud/ +// https://github.com/hannesa2/paho.mqtt.android/blob/master/extendedSample/src/main/java/info/mqtt/android/extsample/MainActivity.kt + + +// let context = UTSAndroid.getAppContext()! as Context +// let serviceIntent = new Intent(UTSAndroid.getUniActivity()!, UTSAndroid.getJavaClass(MqttService)); +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +// context.startForegroundService(serviceIntent); // 对于 Android Oreo 及以上版本 +// } else { +// context.startService(serviceIntent); // 对于 Android Oreo 以下版本 +// } + + + +export class xMqtt { + mqtt : MqttAndroidClient | null = null; + mqttConnectOptions : MqttConnectOptions | null = null; + connectStatus : CONNECT_STATUS = 'wait' + events = new Map(); + constructor() { } + /** + * @param ulr {string} 连接地址 + * @param clientIdStr {string} 客户端id + * @param username {string|null} 用户名称,如果不需要,设置为null即可 + * @param password {string|null} 登录密码,如果不需要,设置为null即可 + */ + create(opts : MQTT_CONNECT_OPTS) : xMqtt { + + let serverUri = opts.protocol + opts.server + ":" + opts.port.toString() + opts.path + let clientId = opts.clientId + this.mqttConnectOptions = new MqttConnectOptions() as MqttConnectOptions; + if (this.mqttConnectOptions == null) return this; + // 失败时,是否自动连接服务器。 + this.mqttConnectOptions!.isAutomaticReconnect = opts.reconnect + + // 连接时是否清除会话 + this.mqttConnectOptions!.isCleanSession = false + //超时 + this.mqttConnectOptions!.connectionTimeout = (opts.timeout * 100).toInt() + //活跃间隔 + this.mqttConnectOptions!.setKeepAliveInterval(opts.keepAliveInterval.toInt()) + // 帐号名称 + if (opts.userName != '') { + this.mqttConnectOptions!.setUserName(opts.userName!) + } + // 帐号密码 + if (opts.passWord != null) { + this.mqttConnectOptions!.setPassword(opts.passWord!.toCharArray()) + } + + this.mqtt = new MqttAndroidClient(UTSAndroid.getAppContext()!, serverUri, clientId); + this.connectStatus = 'wait' + return this; + } + /** + * @param type {MQTT_EVENT_TYPE} 事件名称 + * @param call {MQTT_EVENT_CALL} 事件回调 + */ + @UTSJS.keepAlive + addEventListener(type : MQTT_EVENT_TYPE, call : MQTT_EVENT_CALL) : string { + let id = Date.now().toString() + (Math.random() * 100).toString() + this.events.set(id, + { + type, + value: call + } as MQTT_EVENTS_CALL + ) + + return id; + } + /** + * @param id {string} addEventListener返回的事件id + */ + removeEventListener(id : string) : xMqtt { + this.events.delete(id) + return this; + } + private buildCallEvents(type : MQTT_EVENT_TYPE, toppic : string | null, str : string) { + this.events.forEach((value : MQTT_EVENTS_CALL, key : string) => { + if (value.type == type) { + value.value(type, toppic, str) + } + }) + } + /** + * 连接mqtt服务器 + */ + connect() : xMqtt { + let t = this; + if (this.mqtt == null) return this; + try { + class mqttCallBack implements MqttCallback { + // 连接丢失 + override connectionLost(cause : kotlin.Throwable | null) { + // console.log('Mqtt:Connection lost') + t.connectStatus = 'dissconnect' + t.buildCallEvents('dissconnect', null, '连接断开') + } + // 首次连接时收到的消息 + override messageArrived(topic : string, message : MqttMessage) { + // console.log('Mqtt:', new String(message.getPayload())) + } + // 发布的消息是否已到达 + override deliveryComplete(token : IMqttDeliveryToken) { + // console.log('Message delivered') + } + } + class connectListen implements IMqttActionListener { + // 连接成功 + override onSuccess(asyncActionToken : IMqttToken) { + // console.log('Connected to MQTT broker',asyncActionToken) + t.connectStatus = 'open' + t.buildCallEvents('open', null, '连接成功') + } + // 连接失败 + override onFailure(asyncActionToken : IMqttToken, exception : kotlin.Throwable) { + // console.log('Connected to MQTT Failed', exception) + t.connectStatus = 'error' + t.buildCallEvents('error', null, '连接失败') + } + } + this.connectStatus = 'opening' + this.mqtt!.setCallback(new mqttCallBack()); + this.mqtt!.connect(this.mqttConnectOptions!, null, new connectListen()); + } catch (e : kotlin.Throwable) { + //TODO handle the exception + } + + return this; + + } + /** + * 推送消息 + * @param call {MQTT_EVENT_PUBLISH} + */ + publish(msg : MQTT_PUBLISH_TOPIC, call : MQTT_EVENT_PUBLISH) : xMqtt { + if (this.mqtt == null) return this; + let topic = msg.topic + let message = msg.message + let mqttMessage = new MqttMessage(message.toByteArray()); + // 设置消息服务质量等级0,1,2 + mqttMessage.setQos(msg.qos.toInt()); + // 设置消息是否需要被服务器持久化 + mqttMessage.setRetained(msg.retained); + + class messageListen implements IMqttActionListener { + override onSuccess(asyncActionToken : IMqttToken) { + console.log(topic, '发布成功') + call(true) + } + override onFailure(asyncActionToken : IMqttToken, exception : kotlin.Throwable) { + console.log(topic, '发布失败', exception) + call(false) + } + } + this.mqtt!.publish(topic, mqttMessage, null, new messageListen()); + return this; + } + /** + * 订阅 + * @param data {MQTT_SUBSCRIBE[]} 订阅的消息数组 + */ + subscribe(data : MQTT_SUBSCRIBE[]) : xMqtt { + let t = this; + if (this.mqtt == null) return this; + let msglisten = [] as IMqttMessageListener[]; + let tops = [] as string[] + let qos = new IntArray(data.length.toInt()) + for (let i = 0; i < data.length; i++) { + class messageListen implements IMqttMessageListener { + override messageArrived(topic : string, message : MqttMessage) { + // 处理消息 + let data = message.getPayload(); + + t.buildCallEvents('message', topic, String(data)) + } + } + msglisten.push(new messageListen()) + tops.push(data[i].topic) + qos.set(i.toInt(), data[i].qos.toInt()) + } + + let token : IMqttToken = this.mqtt!.subscribe(tops.toTypedArray(), qos, msglisten.toTypedArray()) + if (token.isComplete()) { + console.log("订阅成功") + } + return this; + + } + /** + * 取消订阅 + * @param topics {string[]} 主题数组 + */ + unsubscribe(topics : string[]) : xMqtt { + let t = this; + if (this.mqtt == null || topics.length == 0) return this; + this.mqtt!.unsubscribe(topics.toTypedArray()) + return this; + } + /** + * 断开连接 + */ + disconnect() : xMqtt { + if (this.mqtt == null) return this; + this.mqtt!.disconnect() + return this; + } + +} \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-harmony/config.json b/uni_modules/x-mqtt-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..4222884 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_mqtt_s": "./lib/x_mqtt_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-harmony/index.uts b/uni_modules/x-mqtt-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..bb9617f --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-harmony/index.uts @@ -0,0 +1,97 @@ +import { + CONNECT_STATUS, MQTT_EVENT_TYPE, MQTT_EVENT_CALL, MQTT_EVENT_PUBLISH, MQTT_SUBSCRIBE, MQTT_EVENTS_CALL, + MQTT_PUBLISH_TOPIC, MQTT_CONNECT_OPTS +} from "../interface.uts" +import { x_xMqtt } from "x_mqtt_s" + +export class xMqtt { + mqtt : x_xMqtt | null = null; + mqttConnectOptions : MQTT_CONNECT_OPTS | null = null; + connectStatus : CONNECT_STATUS = 'wait' + events = new Map(); + constructor() { } + /** + * @param ulr {string} 连接地址 + * @param clientIdStr {string} 客户端id + * @param username {string|null} 用户名称,如果不需要,设置为null即可 + * @param password {string|null} 登录密码,如果不需要,设置为null即可 + */ + create(opts : MQTT_CONNECT_OPTS) : xMqtt { + this.mqttConnectOptions = opts; + this.mqtt = new x_xMqtt(UTSHarmony.getCurrentWindow()!.getUIContext(), this.mqttConnectOptions!) + this.mqtt!.setCallBack((type: string, topic: string | null, str: string)=>{ + console.log('88888',str) + this.buildCallEvents(type as MQTT_EVENT_TYPE,topic,str) + }) + return this; + } + /** + * @param type {MQTT_EVENT_TYPE} 事件名称 + * @param call {MQTT_EVENT_CALL} 事件回调 + */ + addEventListener(type:MQTT_EVENT_TYPE,call:MQTT_EVENT_CALL):string{ + let id = Date.now().toString()+(Math.random()*100).toString() + this.events.set(id, + { + type, + value:call + } as MQTT_EVENTS_CALL + ) + + return id; + } + /** + * @param id {string} addEventListener返回的事件id + */ + removeEventListener(id:string):xMqtt{ + this.events.delete(id) + return this; + } + private buildCallEvents(type:MQTT_EVENT_TYPE,toppic:string|null,str:string){ + this.events.forEach((value:MQTT_EVENTS_CALL,key:string)=>{ + if(value.type == type){ + value.value(type,toppic,str) + } + }) + } + + connect():xMqtt{ + this.mqtt!.connect(); + return this; + } + + /** + * 订阅 + * @param data {MQTT_SUBSCRIBE[]} 订阅的消息数组 + */ + subscribe(data:MQTT_SUBSCRIBE[]):xMqtt{ + this.mqtt!.subscribe(data) + return this; + } + + /** + * 推送消息 + * @param message {MQTT_EVENT_PUBLISH} + * @param call ()=>void 推送消息成功时的回调【web端永为真】 + */ + publish(message:MQTT_PUBLISH_TOPIC,call:MQTT_EVENT_PUBLISH):xMqtt{ + this.mqtt!.publish(message,call) + return this; + } + /** + * 取消订阅 + * @param topics {string[]} 主题数组 + */ + unsubscribe(topics:string[]):xMqtt{ + this.mqtt!.unsubscribe(topics) + return this; + } + /** + * 断开连接 + */ + disconnect():xMqtt{ + if(this.mqtt == null) return this; + this.mqtt!.disconnect() + return this; + } +} \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-harmony/lib/x_mqtt_s.har b/uni_modules/x-mqtt-s/utssdk/app-harmony/lib/x_mqtt_s.har new file mode 100644 index 0000000..c62c99d Binary files /dev/null and b/uni_modules/x-mqtt-s/utssdk/app-harmony/lib/x_mqtt_s.har differ diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-mqtt-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources b/uni_modules/x-mqtt-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources new file mode 100644 index 0000000..8cbebf4 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/Resources/_CodeSignature/CodeResources @@ -0,0 +1,212 @@ + + + + + files + + Headers/unimoduleXMqttS-Swift.h + + us3c7FdOtvvpxAdVgLk4pWNuwOA= + + Headers/unimoduleXMqttS.h + + FH2SRnQAHIO8AbDZPa5/Bz/CcdA= + + Info.plist + + UQNJ7jyX3QAsqknIpAm6FCxq3WA= + + Modules/module.modulemap + + GNmBhr+kPC7jCw5hmJ/XWlcQ90o= + + Modules/unimoduleXMqttS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + 5PJpCvFI3hp5mYermg/rG/zQlIk= + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.abi.json + + j8wYwGynekAGd/D50u+hNETt9Uw= + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + DlWqI5eYTqgv8qwdIj208giOfrE= + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + 1K+l3rq/J9hvut58H8vgiWTjR/I= + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + DlWqI5eYTqgv8qwdIj208giOfrE= + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + nUELKkTPB2lwDB0G0YefuZFhBZ8= + + config.json + + 86zzbbpH14xDJT7XFihyGwNWXhM= + + + files2 + + Headers/unimoduleXMqttS-Swift.h + + hash2 + + Md5kS0WFiaXtbeTSKO/8du82DglwsOS5TY+BDmh79tI= + + + Headers/unimoduleXMqttS.h + + hash2 + + XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY= + + + Modules/module.modulemap + + hash2 + + SM0R5ohUl4WWA6FqKV7y4wdGy+fRoO/nHbdNP7N7xdo= + + + Modules/unimoduleXMqttS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo + + hash2 + + BVFOw0ORUqXAggKQ8xJIR5bEa9t+1V0HfJITJkZG1yQ= + + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.abi.json + + hash2 + + NKt0ctJcSMY3hJt34jWIJU6abzw2KGbtnpNeGTT2cOE= + + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface + + hash2 + + yjSDkB3gJt5oO5/gvlxhx+RCJpV1ImEsfQ02JY3k8gA= + + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc + + hash2 + + 6rl/O8hn+LP0gdZdxwkODD88w3vBOthyKojL1GlpeH0= + + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface + + hash2 + + yjSDkB3gJt5oO5/gvlxhx+RCJpV1ImEsfQ02JY3k8gA= + + + Modules/unimoduleXMqttS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule + + hash2 + + trB/R39AmC8X7aLYvod7ARDXu7T+ztP6Fm8XVQfjcD0= + + + config.json + + hash2 + + UHsnIaXxl3l3rh1rB45DjCJk/E1Wnk5h+/9qtjl7vfQ= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/Resources/ca.crt b/uni_modules/x-mqtt-s/utssdk/app-ios/Resources/ca.crt new file mode 100644 index 0000000..8f3aea9 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/Resources/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/back b/uni_modules/x-mqtt-s/utssdk/app-ios/back new file mode 100644 index 0000000..b7dbd02 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/back @@ -0,0 +1,285 @@ +import { + CONNECT_STATUS, MQTT_EVENT_TYPE, MQTT_EVENT_CALL, MQTT_EVENT_PUBLISH, MQTT_SUBSCRIBE, MQTT_EVENTS_CALL, + MQTT_PUBLISH_TOPIC, MQTT_CONNECT_OPTS +} from "../interface.uts" +import { + CocoaMQTT, CocoaMQTTWebSocket, CocoaMQTT5Delegate, CocoaMQTT5, MqttConnectProperties, + CocoaMQTTDISCONNECTReasonCode, + CocoaMQTTAUTHReasonCode, + MqttDecodeUnsubAck, + MqttDecodeSubAck, + CocoaMQTT5Message, + MqttDecodePublish, + MqttDecodePubAck, + MqttDecodePubRec, + MqttDecodeConnAck, + CocoaMQTTCONNACKReasonCode, + CocoaMQTTConnState, + CocoaMQTTQoS, MqttPublishProperties, CocoaMQTTError, CocoaMQTTMessage + +} from "CocoaMQTT" + +// https://github.com/anatoliykant/SwiftMQTT +import { UInt16 } from 'Swift'; +import { Bundle, CFArray, SecPKCS12Import } from 'Foundation'; +import { kCFStreamSSLCertificates } from 'CFNetwork'; +import { NSObject } from 'ObjectiveC'; + + +// https://github.com/emqx/CocoaMQTT +// https://cocoapods.org/pods/CocoaMQTT +// 文档:https://www.emqx.com/en/blog/ios-mqtt5-client + + +class MQTTDELETED implements CocoaMQTT5Delegate { + // 授权状态 + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didReceiveAuthReasonCode") reasonCode : CocoaMQTTAUTHReasonCode) { + console.log(4) + } + // 连接丢失状态 + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didReceiveDisconnectReasonCode") reasonCode : CocoaMQTTDISCONNECTReasonCode) { + console.log(3) + } + // 取消订阅 MqttDecodeUnsubAck + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didUnsubscribeTopics") topics : string[], unsubAckData : any) { + console.log(2) + } + // 订阅 MqttDecodeSubAck + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didSubscribeTopics") success : NSDictionary, failed : string[], subAckData : any) { + console.log(1) + } + // 收到消息 MqttDecodePublish + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didReceiveMessage") message : CocoaMQTT5Message, id : number, publishData : any) { + console.log(8) + } + // 重复发送消息 MqttDecodePubRec + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didPublishRec") id : number, pubRecData : any) { + console.log(8) + } + // 推送消息异常 MqttDecodePubAck + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didPublishAck") id : number, pubAckData : any) { + console.log(8) + } + // 推送消息 + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didPublishMessage") message : CocoaMQTT5Message, id : number) { + console.log(8) + } + + // 推送消息 MqttDecodeConnAck + mqtt5(mqtt5 : CocoaMQTT5, @argumentLabel("didConnectAck") ack : CocoaMQTTCONNACKReasonCode, connAckData : any) { + console.log(8) + } + + + + +} +let xmqtt : CocoaMQTT | null = null +const connectDeleted : MQTTDELETED | null = null; +export class xMqtt { + mqtt : CocoaMQTT | null = null; + mqttConnectOptions : MqttConnectProperties | null = null; + connectStatus : CONNECT_STATUS = 'wait' + events = new Map(); + constructor() { } + + + /** + * @param type {MQTT_EVENT_TYPE} 事件名称 + * @param call {MQTT_EVENT_CALL} 事件回调 + */ + @UTSJS.keepAlive + addEventListener(type : MQTT_EVENT_TYPE, call : MQTT_EVENT_CALL) : string { + let id = Date.now().toString() + (Math.random() * 100).toString() + this.events.set(id, + { + type, + value: call + } as MQTT_EVENTS_CALL + ) + + return id; + } + /** + * @param id {string} addEventListener返回的事件id + */ + removeEventListener(id : string) : xMqtt { + this.events.delete(id) + return this; + } + + private buildCallEvents(type : MQTT_EVENT_TYPE, toppic : string | null, str : string) { + this.events.forEach((value : MQTT_EVENTS_CALL, key : string) => { + if (value.type == type) { + value.value(type, toppic, str) + } + }) + } + create(opts : MQTT_CONNECT_OPTS) : xMqtt { + let t = this; + + let clientID = opts.clientId! + let websocket = CocoaMQTTWebSocket(uri = opts.path) + let mqtt5 = new CocoaMQTT(clientID = clientID, host = opts.server, port = opts.port!.toUInt16(), socket = websocket) + mqtt5.willMessage = new CocoaMQTTMessage(topic = "/will", string = "dieout") + + // let connectProperties = MqttConnectProperties() + // connectProperties.topicAliasMaximum = 0 + // connectProperties.sessionExpiryInterval = 0 + // connectProperties.receiveMaximum = 100 + // connectProperties.maximumPacketSize = 5000 + // mqtt5.connectProperties = connectProperties + mqtt5.username = opts.userName + mqtt5.password = opts.passWord + mqtt5.keepAlive = opts.keepAliveInterval.toUInt16() + mqtt5.enableSSL = opts.useSSL + mqtt5.autoReconnect = opts.reconnect + mqtt5.allowUntrustCACertificate = true + let sslCart = opts.certName==null?"":(opts.certName) + let isP12 = false; + // let sslSettings = new Map() + if (sslCart != "" && opts.useSSL) { + isP12 = sslCart.lastIndexOf(".p12") > -1; + if (isP12) { + let passwordSsl = opts.certPassword == null ? "" : (opts.certPassword) + if (passwordSsl != "") { + let crtpath = Bundle.main.path(forResource = String(sslCart.substring(0, sslCart.lastIndexOf("."))), ofType = "p12") + let temsslSettings = getClientCertFromP12File(resourcePath = crtpath == null ? "" : (crtpath!), certPassword = String(passwordSsl)) + if (temsslSettings != null) { + mqtt5.sslSettings = temsslSettings! + } else { + console.error("提供的P12证书有误或者文件不存在.") + } + } else { + console.error("提供了p12证书,但未提供证书密码.") + } + } else { + let crtpath = Bundle.main.path(forResource = String(sslCart.substring(0, sslCart.lastIndexOf("."))), ofType = "crt") + + // ca文件. + let temsslSettings = getClientCertFromCrtFile(resourcePath = crtpath == null ? "" : (crtpath!)) + if (temsslSettings != null) { + // console.log(temsslSettings) + mqtt5.sslSettings = temsslSettings! + } else { + console.error("提供的Ca证书有误或者文件不存在.") + } + + } + + } + + mqtt5.cleanSession = true + // mqtt5.delegate = new MQTTDELETED() + mqtt5.didDisconnect = (client : CocoaMQTT, errorcode ?: any) => { + let code = errorcode as CocoaMQTTError | null + + if (errorcode instanceof CocoaMQTTError) { + t.connectStatus = 'error' + t.buildCallEvents('error', null, '连接错误') + + } else { + t.connectStatus = 'error' + t.buildCallEvents('error', null, '地址错误,或者没有网络。') + } + + } + + mqtt5.didConnectAck = (client : CocoaMQTT, cack ?: any) => { + t.connectStatus = 'open' + t.buildCallEvents('open', null, '已连接') + + + console.log('success') + } + mqtt5.didChangeState = (client : CocoaMQTT, state : CocoaMQTTConnState) => { + if (state == CocoaMQTTConnState.connecting) { + console.log('连接中') + } + if (state == CocoaMQTTConnState.connected) { + console.log('连接成功') + } + if (state == CocoaMQTTConnState.disconnected) { + console.log('连接失败') + t.connectStatus = 'dissconnect' + t.buildCallEvents('dissconnect', null, '已断开连接') + } + } + + mqtt5.didReceiveMessage = (client : CocoaMQTT, message : CocoaMQTTMessage, id : UInt16) => { + let topic = message.topic + let msg = message.string + t.connectStatus = 'message' + t.buildCallEvents('message', topic, msg == null ? '' : (msg!)) + } + + + + this.mqtt = mqtt5; + + return this; + } + + connect() : xMqtt { + if (this.mqtt == null) return this; + this.mqtt!.connect() + return this; + } + /** + * 推送消息 + * @param call {MQTT_EVENT_PUBLISH} + */ + publish(msg : MQTT_PUBLISH_TOPIC, call : MQTT_EVENT_PUBLISH) : xMqtt { + if (this.mqtt == null) return this; + let topic = msg.topic + let message = msg.message + let qos : CocoaMQTTQoS = CocoaMQTTQoS.qos0 + if (msg.qos == 1) { + qos = CocoaMQTTQoS.qos1 + } else if (msg.qos == 2) { + qos = CocoaMQTTQoS.qos2 + } + this.mqtt!.publish(new CocoaMQTTMessage(topic = topic!, string = message!, qos = qos, retained = msg.retained)) + call(true) + return this; + } + /** + * 订阅 + * @param data {MQTT_SUBSCRIBE[]} 订阅的消息数组 + */ + subscribe(data : MQTT_SUBSCRIBE[]) : xMqtt { + let t = this; + if (this.mqtt == null) return this; + for (let i = 0; i < data.length; i++) { + let qos : CocoaMQTTQoS = CocoaMQTTQoS.qos0 + if (data[i].qos == 1) { + qos = CocoaMQTTQoS.qos1 + } else if (data[i].qos == 2) { + qos = CocoaMQTTQoS.qos2 + } + this.mqtt!.subscribe(data[i].topic, qos = qos) + } + return this; + } + + /** + * 取消订阅 + * @param topics {string[]} 主题数组 + */ + unsubscribe(topics : string[]) : xMqtt { + if (this.mqtt == null) return this; + for (let i = 0; i < topics.length; i++) { + this.mqtt!.unsubscribe(topics[i]) + } + return this; + } + /** + * 断开连接 + */ + disconnect() : xMqtt { + if (this.mqtt == null) return this; + this.mqtt!.disconnect() + return this; + } + +} \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/config.json b/uni_modules/x-mqtt-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..78f66da --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/config.json @@ -0,0 +1,9 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "CocoaMQTT/WebSockets", + "version": "2.1.6" + } + ] +} diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/index.uts b/uni_modules/x-mqtt-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..97bae2a --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/index.uts @@ -0,0 +1,132 @@ +import { + CONNECT_STATUS, MQTT_EVENT_TYPE, MQTT_EVENT_CALL, MQTT_EVENT_PUBLISH, MQTT_SUBSCRIBE, MQTT_EVENTS_CALL, + MQTT_PUBLISH_TOPIC, MQTT_CONNECT_OPTS +} from "../interface.uts" +import { + CocoaMQTT, CocoaMQTTWebSocket, CocoaMQTT5Delegate, CocoaMQTT5, MqttConnectProperties, + CocoaMQTTDISCONNECTReasonCode, + CocoaMQTTAUTHReasonCode, + MqttDecodeUnsubAck, + MqttDecodeSubAck, + CocoaMQTT5Message, + MqttDecodePublish, + MqttDecodePubAck, + MqttDecodePubRec, + MqttDecodeConnAck, + CocoaMQTTCONNACKReasonCode, + CocoaMQTTConnState, + CocoaMQTTQoS, MqttPublishProperties, CocoaMQTTError, CocoaMQTTMessage + +} from "CocoaMQTT" + +// https://github.com/anatoliykant/SwiftMQTT +import { UInt16 } from 'Swift'; +import { Bundle, CFArray, NSDictionary, SecPKCS12Import } from 'Foundation'; +import { kCFStreamSSLCertificates } from 'CFNetwork'; +import { NSObject } from 'ObjectiveC'; + + +// https://github.com/emqx/CocoaMQTT +// https://cocoapods.org/pods/CocoaMQTT +// 文档:https://www.emqx.com/en/blog/ios-mqtt5-client + + + +export class xMqtt { + mqtt:XMqttHelp = new XMqttHelp(); + mqttConnectOptions : MqttConnectProperties | null = null; + connectStatus : CONNECT_STATUS = 'wait' + constructor() { } + /** + * @param type {MQTT_EVENT_TYPE} 事件名称 + * @param call {MQTT_EVENT_CALL} 事件回调 + */ + @UTSJS.keepAlive + addEventListener(type : MQTT_EVENT_TYPE, call : MQTT_EVENT_CALL) : string { + @escaping + return this.mqtt.addEventListener( + type, + callback = call); + } + /** + * @param id {string} addEventListener返回的事件id + */ + removeEventListener(id : string) : xMqtt { + this.mqtt.removeEventListener(id) + return this; + } + + private buildCallEvents() { + @escaping + this.mqtt.setCallBack(()=>{ + this.connectStatus = this.mqtt.getStatus(); + console.log(this.connectStatus) + }) + } + create(opts : MQTT_CONNECT_OPTS) : xMqtt { + let optsjson = JSON.parseObject(JSON.stringify(opts)!)!; + const realJson = {...optsjson,allowUntrustCACertificate:opts.allowUntrustCACertificate==true,protocol:opts.useSSL?'wss':'ws'} + this.mqtt.create(realJson.toMap() as NSDictionary) + this.buildCallEvents() + return this; + } + connect() : xMqtt { + // if (this.mqtt.getStatus()!='dissconnect'&&this.mqtt.getStatus()!='error') return this; + this.mqtt.connect() + return this; + } + /** + * 推送消息 + * @param call {MQTT_EVENT_PUBLISH} + */ + publish(msg : MQTT_PUBLISH_TOPIC, call : MQTT_EVENT_PUBLISH) : xMqtt { + // if (this.mqtt.getStatus() != 'open' && this.mqtt.getStatus() != 'message') return this; + @escaping + this.mqtt.publish( + msg.topic, + message = msg.message, + qos = msg.qos.toInt(), + retained=msg.retained, + completion = (ok:boolean)=>{ + console.log('ok',ok) + call(ok) + } + ) + return this; + } + /** + * 订阅 + * @param data {MQTT_SUBSCRIBE[]} 订阅的消息数组 + */ + subscribe(data : MQTT_SUBSCRIBE[]) : xMqtt { + // if (this.mqtt.getStatus() != 'open' && this.mqtt.getStatus() != 'message') return this; + let d:NSDictionary[] = []; + data.forEach(el=>{ + let p = JSON.parseObject(JSON.stringify(el)!)!.toMap(); + let qos = p.get('qos')! as number + p.set('qos',qos.toInt()) + d.push(p as NSDictionary) + }) + this.mqtt.subscribe(d) + return this; + } + + /** + * 取消订阅 + * @param topics {string[]} 主题数组 + */ + unsubscribe(topics : string[]) : xMqtt { + // if (this.mqtt.getStatus() != 'open' && this.mqtt.getStatus() != 'message') return this; + this.mqtt.unsubscribe(topics) + + return this; + } + /** + * 断开连接 + */ + disconnect() : xMqtt { + this.mqtt.disconnect(); + return this; + } + +} \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/info.plist b/uni_modules/x-mqtt-s/utssdk/app-ios/info.plist new file mode 100644 index 0000000..e1e0610 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/info.plist @@ -0,0 +1,12 @@ + + + + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + + + \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/xMqttCerHelp.swift b/uni_modules/x-mqtt-s/utssdk/app-ios/xMqttCerHelp.swift new file mode 100644 index 0000000..d68cae7 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/xMqttCerHelp.swift @@ -0,0 +1,122 @@ +import Foundation +import Security +// UTS内置对象的引用 +import DCloudUTSFoundation +func getClientCertFromP12File(resourcePath: String, certPassword: String) -> [String: NSObject]? { + do { + // 读取证书文件数据 + let p12Data = try Data(contentsOf: URL(fileURLWithPath: resourcePath)) + + // 创建密钥字典用于读取p12文件 + let key = kSecImportExportPassphrase as String + let options : NSDictionary = [key: certPassword] + + var items : CFArray? + let securityError = SecPKCS12Import(p12Data as NSData, options, &items) + + guard securityError == errSecSuccess else { + if securityError == errSecAuthFailed { + console.log("ERROR: SecPKCS12Import returned errSecAuthFailed. Incorrect password?") + } else { + console.log("Failed to open the certificate file", resourcePath) + } + return nil + } + + guard let theArray = items, CFArrayGetCount(theArray) > 0 else { + return nil + } + + let dictionary = (theArray as NSArray).object(at: 0) + guard let identity = (dictionary as AnyObject).value(forKey: kSecImportItemIdentity as String) as? NSObject else { + return nil + } + + return [ + "useCertificateChainValidation": NSNumber(value: true), + "useSSLCertificateVerification": NSNumber(value: true), + "clientCertificate": identity + ] + } catch { + console.log("读取证书文件失败", resourcePath) + return nil + } +} + +// 将PEM格式的证书转换为DER格式 +func convertPEMToDER(pemString: String) -> Data? { + // 移除所有空格和换行符 + var cleanedString = pemString.trimmingCharacters(in: .whitespacesAndNewlines) + + // 检查是否包含PEM证书的头尾标记 + let beginCertPattern = "-----BEGIN CERTIFICATE-----" + let endCertPattern = "-----END CERTIFICATE-----" + + // 如果没有找到标准的PEM头尾标记,记录日志并尝试直接解码 + if !cleanedString.contains(beginCertPattern) || !cleanedString.contains(endCertPattern) { + console.log("警告: PEM证书格式不标准,缺少标准头尾标记") + // 尝试直接解码,假设整个字符串都是Base64编码 + let noWhitespace = cleanedString.replacingOccurrences(of: "\\s", with: "", options: .regularExpression) + return Data(base64Encoded: noWhitespace) + } + + // 提取BEGIN和END标记之间的内容 + guard let startRange = cleanedString.range(of: beginCertPattern), + let endRange = cleanedString.range(of: endCertPattern) else { + console.log("无法定位PEM证书的头尾标记位置") + return nil + } + + // 获取BEGIN标记之后的内容 + let afterBeginIndex = cleanedString.index(after: startRange.upperBound) + // 获取END标记之前的内容 + let beforeEndIndex = endRange.lowerBound + + // 提取Base64编码部分 + let base64Content = String(cleanedString[afterBeginIndex.. [String: NSObject]? { + + do { + // 读取证书文件数据 + let pemData = try Data(contentsOf: URL(fileURLWithPath: resourcePath)) + // 将证书数据转换为字符串 + guard let pemString = String(data: pemData, encoding: .utf8) else { + console.log("将证书数据转换为字符串失败") + return nil + } + // 将PEM格式转换为DER格式 + guard let derData = convertPEMToDER(pemString: pemString) else { + console.log("转换PEM到DER格式失败") + return nil + } + // 创建SecCertificate对象 + guard let certificate = SecCertificateCreateWithData(nil, derData as CFData) else { + console.log("创建SecCertificate对象失败") + return nil + } + + return [ + "useCertificateChainValidation": NSNumber(value: true), + "useSSLCertificateVerification": NSNumber(value: true), + "kCFStreamSSLCertificates": [certificate] as NSArray + ] + } catch { + console.log("读取证书文件失败",resourcePath) + return nil + } + +} + diff --git a/uni_modules/x-mqtt-s/utssdk/app-ios/xMqttHelp.swift b/uni_modules/x-mqtt-s/utssdk/app-ios/xMqttHelp.swift new file mode 100644 index 0000000..73d6b30 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/app-ios/xMqttHelp.swift @@ -0,0 +1,294 @@ +import Foundation +import CocoaMQTT +import DCloudUTSFoundation + +// 证书加载工具预计由同目录的 xMqttCerHelp.swift 提供 +// getClientCertFromP12File(resourcePath: String, certPassword: String) -> [String: Any]? +// getClientCertFromCrtFile(resourcePath: String) -> [String: Any]? + +@objc public class XMqttHelp: NSObject { + + @objc public enum ConnectStatus: Int { + case wait + case opening + case open + case error + case dissconnect + case message + } + + public typealias EventType = String // 'open' | 'error' | 'dissconnect' | 'message' + public typealias MQTTEventCallback = @convention(block) (_ type: EventType, _ topic: String?, _ payload: String) -> Void + public typealias VoidCallback = @convention(block) () -> Void + + private var mqtt: CocoaMQTT? + @objc public private(set) var connectStatus: ConnectStatus = .wait + private var anyStateCallback: VoidCallback? + + private struct EventItem { + let type: EventType + let callback: MQTTEventCallback + } + private var events = [String: EventItem]() + private var pendingSubs = [(topic: String, qos: CocoaMQTTQoS)]() + + @objc public override init() { + super.init() + } + + // opts keys 对齐 index.uts: protocol, server, port, path, clientId, userName, passWord, keepAliveInterval, reconnect, useSSL, certName, certPassword + @objc public func create(_ opts: NSDictionary) -> XMqttHelp { + let proto = ((opts["protocol"] as? String) ?? "wss").lowercased() // ws | wss + let server = (opts["server"] as? String) ?? "" + let port = (opts["port"] as? NSNumber)?.uint16Value ?? 0 + let path = (opts["path"] as? String) ?? "/mqtt" + let clientId = (opts["clientId"] as? String) ?? ("iOS-" + UUID().uuidString) + let userName = opts["userName"] as? String + let passWord = opts["passWord"] as? String + let keepAlive = (opts["keepAliveInterval"] as? NSNumber)?.uint16Value ?? 60 + let reconnect = (opts["reconnect"] as? NSNumber)?.boolValue ?? true + var useSSL = (opts["useSSL"] as? NSNumber)?.boolValue ?? (proto == "wss") + let certName = opts["certName"] as? String + let certPassword = opts["certPassword"] as? String + let allowUntrust = (opts["allowUntrustCACertificate"] as? NSNumber)?.boolValue ?? false + var headers = opts["headers"] as? [String: String] ?? [:] + let subProtocols = opts["protocols"] as? [String] ?? ["mqtt"] + let connectTimeoutMs = (opts["connectTimeoutMs"] as? NSNumber)?.intValue ?? 30000 + + let websocket = CocoaMQTTWebSocket(uri: path) + // if !subProtocols.isEmpty { + // // 通过请求头携带子协议,等效于 Sec-WebSocket-Protocol + // headers["sec-websocket-protocol"] = subProtocols.joined(separator: ", ") + // } + // 常见要求:补 Host 与 Origin + headers["Host"] = server + if headers["Origin"] == nil { + headers["Origin"] = "https://\(server)" + } + // 标准版本 + headers["Sec-WebSocket-Version"] = "13" + headers["sec-websocket-protocol"] = "mqtt" + headers["upgrade"] = "websocket" + headers["connection"] = "Upgrade" + websocket.headers = headers + // 显式打开 wss(CocoaMQTT 2.1.x 部分版本需要) + // 存在则赋值,不存在编译器会报错;若报错我再回退此行 + #if compiler(>=5.0) + // 尝试兼容的属性名 + // @available: 部分版本属性名为 enableSSL 或 isSecure + // 这里使用可选链避免编译期错误不可行,因此直接尝试常见属性名 + // 如果你的 CocoaMQTT 版本不支持,将移除此行由 mqtt.enableSSL 控制 + #endif + let mqtt = CocoaMQTT(clientID: clientId, host: server, port: port, socket: websocket) + mqtt.username = userName + mqtt.password = passWord + mqtt.keepAlive = keepAlive + mqtt.enableSSL = useSSL + mqtt.autoReconnect = reconnect + mqtt.cleanSession = true + mqtt.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout") + + console.log("[XMqttHelp] connect url => \(proto)://\(server):\(port)\(path), ssl=\(useSSL), headers=\(headers)") + + // 证书策略(可选) + if useSSL, let name = certName, !name.isEmpty { + if name.lowercased().hasSuffix(".p12") { + if let pwd = certPassword, !pwd.isEmpty { + let base = (name as NSString).deletingPathExtension + if let path = Bundle.main.path(forResource: base, ofType: "p12"), + let settings = getClientCertFromP12File(resourcePath: path, certPassword: pwd) { + mqtt.sslSettings = settings + } else { + console.log("[XMqttHelp] p12 证书无效或找不到: \(name)") + } + } else { + console.log("[XMqttHelp] p12 证书未提供密码") + } + } else if name.lowercased().hasSuffix(".crt") { + let base = (name as NSString).deletingPathExtension + if let path = Bundle.main.path(forResource: base, ofType: "crt"), + let settings = getClientCertFromCrtFile(resourcePath: path) { + mqtt.sslSettings = settings + } else { + console.log("[XMqttHelp] crt 证书无效或找不到: \(name)") + } + } + } + + // 自签证书信任(调试可开,生产建议禁用或使用证书绑定) + mqtt.allowUntrustCACertificate = allowUntrust + + // 指定 SNI 主机名,避免非标准端口下的握手失败 + if useSSL { + var ssl = mqtt.sslSettings ?? [:] + ssl[kCFStreamSSLPeerName as String] = server as NSString + mqtt.sslSettings = ssl + } + + // 事件回调 + weak var weakSelf = self + mqtt.didDisconnect = { [weak weakSelf] _, error in + guard let self = weakSelf else { return } + self.connectStatus = .error + self.notifyStateChange() + self.buildCallEvents(type: "error", topic: nil, payload: (error as? CocoaMQTTError) != nil ? "连接错误" : "地址错误,或者没有网络。") + } + mqtt.didConnectAck = { [weak weakSelf] _, _ in + guard let self = weakSelf else { return } + self.connectStatus = .open + self.notifyStateChange() + self.buildCallEvents(type: "open", topic: nil, payload: "已连接") + // 补发未完成的订阅 + if !self.pendingSubs.isEmpty { + for item in self.pendingSubs { + self.mqtt?.subscribe(item.topic, qos: item.qos) + console.log("[XMqttHelp] re-subscribe => \(item.topic) qos=\(item.qos.rawValue)") + } + self.pendingSubs.removeAll() + } + } + mqtt.didChangeState = { [weak weakSelf] _, state in + guard let self = weakSelf else { return } + switch state { + case .connecting: + console.log("[XMqttHelp] 连接中") + case .connected: + console.log("[XMqttHelp] 连接成功") + case .disconnected: + self.connectStatus = .dissconnect + self.notifyStateChange() + self.buildCallEvents(type: "dissconnect", topic: nil, payload: "已断开连接") + default: + break + } + } + mqtt.didReceiveMessage = { [weak weakSelf] _, message, _ in + guard let self = weakSelf else { return } + self.connectStatus = .message + self.notifyStateChange() + let payload = message.string ?? (String(data: Data(message.payload), encoding: .utf8) ?? "") + self.buildCallEvents(type: "message", topic: message.topic, payload: payload) + } + + self.mqtt = mqtt + self.connectStatus = .wait + self.notifyStateChange() + + // 连接超时保护 + if connectTimeoutMs > 0 { + let deadline = DispatchTime.now() + .milliseconds(connectTimeoutMs) + DispatchQueue.main.asyncAfter(deadline: deadline) { [weak self] in + guard let self = self else { return } + if self.connectStatus == .opening { + console.log("[XMqttHelp] 连接超时: \(connectTimeoutMs)ms") + _ = self.disconnect() + self.connectStatus = .error + self.notifyStateChange() + self.buildCallEvents(type: "error", topic: nil, payload: "连接超时") + } + } + } + return self + } + + @objc public func connect() -> XMqttHelp { + guard let mqtt = self.mqtt else { return self } + self.connectStatus = .opening + self.notifyStateChange() + mqtt.connect() + return self + } + + @objc public func publish(_ topic: String, message: String, qos: Int, retained: Bool, completion: @escaping @convention(block) (_ ok: Bool) -> Void) -> XMqttHelp { + guard let mqtt = self.mqtt else { completion(false); return self } + let q: CocoaMQTTQoS = (qos == 2) ? .qos2 : ((qos == 1) ? .qos1 : .qos0) + let msg = CocoaMQTTMessage(topic: topic, string: message, qos: q, retained: retained) + mqtt.publish(msg) + completion(true) + return self + } + + @objc public func subscribe(_ topics: [NSDictionary]) -> XMqttHelp { + guard let mqtt = self.mqtt else { return self } + for item in topics { + guard let topic = item["topic"] as? String else { continue } + let qosVal = (item["qos"] as? NSNumber)?.intValue ?? 0 + let q: CocoaMQTTQoS = (qosVal == 2) ? .qos2 : ((qosVal == 1) ? .qos1 : .qos0) + console.log(self.connectStatus == .open,"opeing status") + if self.connectStatus == .open { + mqtt.subscribe(topic, qos: q) + console.log("[XMqttHelp] subscribe => \(topic) qos=\(q.rawValue)") + } else { + self.pendingSubs.append((topic, q)) + console.log("[XMqttHelp] cache subscribe (not open) => \(topic) qos=\(q.rawValue)") + } + } + return self + } + + @objc public func unsubscribe(_ topics: [String]) -> XMqttHelp { + guard let mqtt = self.mqtt else { return self } + for t in topics { mqtt.unsubscribe(t) } + return self + } + + @objc public func disconnect() -> XMqttHelp { + guard let mqtt = self.mqtt else { return self } + mqtt.disconnect() + return self + } + + // 注册任意状态变化的回调(无参数) + @objc public func setCallBack(_ cb: @escaping VoidCallback) { + self.anyStateCallback = cb + } + + + // 规范命名,提供同等功能(可选使用) + @objc public func getStatus() -> String { + return self.statusString(self.connectStatus) + } + + // 事件系统:与 index.uts 的 addEventListener/removeEventListener 对齐 + @objc @discardableResult + public func addEventListener(_ type: EventType, callback: @escaping MQTTEventCallback) -> String { + let id = String(format: "%.0f-%d", Date().timeIntervalSince1970 * 1000, Int.random(in: 0...9999)) + events[id] = EventItem(type: type, callback: callback) + return id + } + + @objc @discardableResult + public func removeEventListener(_ id: String) -> XMqttHelp { + events.removeValue(forKey: id) + return self + } + + private func buildCallEvents(type: EventType, topic: String?, payload: String) { + for (_, item) in events where item.type == type { + item.callback(type, topic, payload) + } + } + + private func notifyStateChange() { + anyStateCallback?() + } + + private func statusString(_ status: ConnectStatus) -> String { + switch status { + case .wait: + return "wait" + case .opening: + return "opening" + case .open: + return "open" + case .error: + return "error" + case .dissconnect: + return "dissconnect" + case .message: + return "message" + } + } +} + + diff --git a/uni_modules/x-mqtt-s/utssdk/interface.uts b/uni_modules/x-mqtt-s/utssdk/interface.uts new file mode 100644 index 0000000..f5f732f --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/interface.uts @@ -0,0 +1,50 @@ +export type CONNECT_STATUS = "opening" | "open" | "dissconnect" | "error" | "wait"; +export type MQTT_EVENT_TYPE = "open" | "dissconnect" | "error" | "message"; +export type MQTT_EVENT_CALL = (type : MQTT_EVENT_TYPE, topic : string | null, str : string) => void; +export type MQTT_EVENT_PUBLISH = (isSuccess : boolean) => void; +export type MQTT_SUBSCRIBE = { topic : string, qos : number }; +export type MQTT_PUBLISH_TOPIC = { + // 订阅的主题 + topic:string, + message:string, + // 优先级0,1,2 依此表示至少接收到的消息级别1至少要收到1次 + qos:number, + // 消息是否持久化,就是指推送的消息是否保留在服务器上,供未来订阅者订阅时收到此前发送的消息。 + retained:boolean +}; +export type MQTT_CONNECT_OPTS = { + // web端不会起作用,由软件根据useSSL来判断是ws,wss,app需要指定是ws://,wss://,ssl://等 + protocol : string, + // 连接的路径,如果没有就空值,有就填写比如:'/mqtt' + path : string, + // 客户端id + clientId : string, + // 服务器地址 + server : string, + // 服务器端口 + port : number, + // 用户名,没有为空 + userName : string, + // 用户密码,没有为空 + passWord : string, + // 是否使用加密连接,web端true时为wss,否则为ws协议 + useSSL : boolean, + // 保持消息跳动的间隔 + keepAliveInterval : number, + // 连接超时时间 + timeout : number, + // 是否自动重连 + reconnect : boolean, + // ios用,是否启用公共加密连接 + allowUntrustCACertificate?:boolean, + // ios专用的p12证书密码,如果是ca证书则不需要 + certPassword ?: string, + // ios下你放置在插件目录Resources内的证书名称,含后缀 如:ca.crt,ca.p12 + certName ?: string +}; + + +export type MQTT_EVENTS_CALL = { + type : MQTT_EVENT_TYPE, + value : MQTT_EVENT_CALL +}; \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/mp-weixin/index.uts b/uni_modules/x-mqtt-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..763b768 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,158 @@ +export { CONNECT_STATUS,MQTT_EVENT_TYPE,MQTT_EVENT_CALL,MQTT_EVENT_PUBLISH,MQTT_SUBSCRIBE,MQTT_EVENTS_CALL,MQTT_PUBLISH_TOPIC,MQTT_CONNECT_OPTS } from "../interface.uts" +import Paho from './mqtt.js' +// var client = new Paho.MQTT.Client(location.hostname, Number(location.port), "clientId"); +// mqtt测试服务器 +// https://console.hivemq.cloud/ +// https://github.com/eclipse/paho.mqtt.javascript +// https://eclipse.dev/paho/files/jsdoc/Paho.MQTT.Client.html + +type MqttConnectOptions = { + userName?:string, + password?:string, + useSSL?:boolean, + keepAliveInterval?:number, + timeout?:number, + reconnect?:boolean, + onSuccess?:any, + onFailure?:any +} + + +export class xMqtt { + mqtt : MqttAndroidClient | null = null; + mqttConnectOptions : MqttConnectOptions | null = null; + connectStatus:CONNECT_STATUS = 'wait' + events = new Map(); + constructor(){ + + } + /** + * @param ulr {string} 连接地址 + * @param clientIdStr {string} 客户端id + * @param username {string|null} 用户名称,如果不需要,设置为null即可 + * @param password {string|null} 登录密码,如果不需要,设置为null即可 + */ + async create(opts:MQTT_CONNECT_OPTS):xMqtt { + let t = this; + this.mqttConnectOptions = {} as MqttConnectOptions; + this.mqttConnectOptions.userName = opts.userName; + this.mqttConnectOptions.password = opts.passWord; + this.mqttConnectOptions.useSSL = opts.useSSL; + this.mqttConnectOptions.keepAliveInterval = opts.keepAliveInterval; + this.mqttConnectOptions.timeout = opts.timeout; + + this.mqttConnectOptions.reconnect = opts.reconnect; + this.mqtt = new Paho.Client( `${opts.protocol}${opts.server}:${opts.port}${opts.path}`, opts.clientId); + this.mqttConnectOptions.onSuccess = ()=>{ + t.buildCallEvents('open',null,'连接成功') + }; + this.mqttConnectOptions.onFailure = ()=>{ + t.buildCallEvents('error',null,'连接失败') + }; + + this.mqtt.onConnectionLost = ()=>{ + t.buildCallEvents('dissconnect',null,'连接断开') + }; + this.mqtt.onMessageArrived = (evt)=>{ + + t.buildCallEvents('message',evt.topic,evt.payloadString) + }; + this.connectStatus = 'wait' + this.mqtt.connect(this.mqttConnectOptions) + + return this; + } + + /** + * @param type {MQTT_EVENT_TYPE} 事件名称 + * @param call {MQTT_EVENT_CALL} 事件回调 + */ + addEventListener(type:MQTT_EVENT_TYPE,call:MQTT_EVENT_CALL):string{ + let id = Date.now().toString()+(Math.random()*100).toString() + this.events.set(id, + { + type, + value:call + } as MQTT_EVENTS_CALL + ) + + return id; + } + /** + * @param id {string} addEventListener返回的事件id + */ + removeEventListener(id:string):xMqtt{ + this.events.delete(ids[i]) + return this; + } + private buildCallEvents(type:MQTT_EVENT_TYPE,toppic:string|null,str:string){ + this.events.forEach((value:MQTT_EVENTS_CALL,key:string)=>{ + if(value.type == type){ + value.value(type,toppic,str) + } + }) + } + connect():xMqtt{ + + this.mqtt?.connect(this.mqttConnectOptions); + return this; + } + /** + * 订阅 + * @param data {MQTT_SUBSCRIBE[]} 订阅的消息数组 + */ + subscribe(data:MQTT_SUBSCRIBE[]):xMqtt{ + let t = this; + if(this.mqtt == null) return this; + for(let i=0;ivoid 推送消息成功时的回调【web端永为真】 + */ + publish(message:MQTT_PUBLISH_TOPIC,call:MQTT_EVENT_PUBLISH):xMqtt{ + if(this.mqtt == null) return this; + this.mqtt!.publish(message.topic,message.message,message.qos,true); + call(true) + return this; + } + /** + * 取消订阅 + * @param topics {string[]} 主题数组 + */ + unsubscribe(topics:string[]):xMqtt{ + let t = this; + if(this.mqtt == null||topics.length==0) return this; + for(let i=0;i>8;b[d++]=a%256;return d}function u(a,b,d,k){k=r(b,d,k);D(a,d,k);return k+b}function p(a){for(var b=0,d=0;d=k&&(d++,b++),b+=3):127=e){var f=a.charCodeAt(++k);if(isNaN(f))throw Error(h(g.MALFORMED_UNICODE,[e,f]));e=(e-55296<<10)+(f-56320)+65536}127>=e?b[d++]=e:(2047>=e?b[d++]=e>>6&31|192:(65535>=e?b[d++]=e>>12&15|224:(b[d++]=e>>18&7|240,b[d++]=e>>12&63|128),b[d++]=e>>6&63|128),b[d++]=e&63|128)}return b}function E(a,b,d){for(var k="",e,f=b;fe)){var n=a[f++]-128;if(0>n)throw Error(h(g.MALFORMED_UTF,[e.toString(16),n.toString(16), +""]));if(224>e)e=64*(e-192)+n;else{var c=a[f++]-128;if(0>c)throw Error(h(g.MALFORMED_UTF,[e.toString(16),n.toString(16),c.toString(16)]));if(240>e)e=4096*(e-224)+64*n+c;else{var l=a[f++]-128;if(0>l)throw Error(h(g.MALFORMED_UTF,[e.toString(16),n.toString(16),c.toString(16),l.toString(16)]));if(248>e)e=262144*(e-240)+4096*n+64*c+l;else throw Error(h(g.MALFORMED_UTF,[e.toString(16),n.toString(16),c.toString(16),l.toString(16)]));}}}65535>10)),e=56320+(e& +1023));k+=String.fromCharCode(e)}return k}var y=function(a,b){for(var d in a)if(a.hasOwnProperty(d))if(b.hasOwnProperty(d)){if(typeof a[d]!==b[d])throw Error(h(g.INVALID_TYPE,[typeof a[d],d]));}else{d="Unknown property, "+d+". Valid properties are:";for(var k in b)b.hasOwnProperty(k)&&(d=d+" "+k);throw Error(d);}},s=function(a,b){return function(){return a.apply(b,arguments)}},g={OK:{code:0,text:"AMQJSC0000I OK."},CONNECT_TIMEOUT:{code:1,text:"AMQJSC0001E Connect timed out."},SUBSCRIBE_TIMEOUT:{code:2, +text:"AMQJS0002E Subscribe timed out."},UNSUBSCRIBE_TIMEOUT:{code:3,text:"AMQJS0003E Unsubscribe timed out."},PING_TIMEOUT:{code:4,text:"AMQJS0004E Ping timed out."},INTERNAL_ERROR:{code:5,text:"AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}"},CONNACK_RETURNCODE:{code:6,text:"AMQJS0006E Bad Connack return code:{0} {1}."},SOCKET_ERROR:{code:7,text:"AMQJS0007E Socket error:{0}."},SOCKET_CLOSE:{code:8,text:"AMQJS0008I Socket closed."},MALFORMED_UTF:{code:9,text:"AMQJS0009E Malformed UTF data:{0} {1} {2}."}, +UNSUPPORTED:{code:10,text:"AMQJS0010E {0} is not supported by this browser."},INVALID_STATE:{code:11,text:"AMQJS0011E Invalid state {0}."},INVALID_TYPE:{code:12,text:"AMQJS0012E Invalid type {0} for {1}."},INVALID_ARGUMENT:{code:13,text:"AMQJS0013E Invalid argument {0} for {1}."},UNSUPPORTED_OPERATION:{code:14,text:"AMQJS0014E Unsupported operation."},INVALID_STORED_DATA:{code:15,text:"AMQJS0015E Invalid data in local storage key\x3d{0} value\x3d{1}."},INVALID_MQTT_MESSAGE_TYPE:{code:16,text:"AMQJS0016E Invalid MQTT message type {0}."}, +MALFORMED_UNICODE:{code:17,text:"AMQJS0017E Malformed Unicode string:{0} {1}."},BUFFER_FULL:{code:18,text:"AMQJS0018E Message buffer is full, maximum buffer size: {0}."}},H={0:"Connection Accepted",1:"Connection Refused: unacceptable protocol version",2:"Connection Refused: identifier rejected",3:"Connection Refused: server unavailable",4:"Connection Refused: bad user name or password",5:"Connection Refused: not authorized"},h=function(a,b){var d=a.text;if(b)for(var k,e,f=0;f>7;0h);c=f.length+1;b=new ArrayBuffer(b+c);h=new Uint8Array(b);h[0]=a;h.set(f,1);if(3==this.type)c=u(this.payloadMessage.destinationName,k,h,c);else if(1==this.type){switch(this.mqttVersion){case 3:h.set(A,c);c+=A.length; +break;case 4:h.set(B,c),c+=B.length}a=0;this.cleanSession&&(a=2);void 0!==this.willMessage&&(a=a|4|this.willMessage.qos<<3,this.willMessage.retained&&(a|=32));void 0!==this.userName&&(a|=128);void 0!==this.password&&(a|=64);h[c++]=a;c=r(this.keepAliveInterval,h,c)}void 0!==this.messageIdentifier&&(c=r(this.messageIdentifier,h,c));switch(this.type){case 1:c=u(this.clientId,p(this.clientId),h,c);void 0!==this.willMessage&&(c=u(this.willMessage.destinationName,p(this.willMessage.destinationName),h,c), +c=r(e.byteLength,h,c),h.set(e,c),c+=e.byteLength);void 0!==this.userName&&(c=u(this.userName,p(this.userName),h,c));void 0!==this.password&&u(this.password,p(this.password),h,c);break;case 3:h.set(g,c);break;case 8:for(f=0;f +this.disconnectedBufferSize)throw Error(h(g.BUFFER_FULL,[this.disconnectedBufferSize]));0=e[f]?c+"0"+e[f].toString(16):c+e[f].toString(16);d.payloadMessage.payloadHex=c;d.payloadMessage.qos=b.payloadMessage.qos;d.payloadMessage.destinationName=b.payloadMessage.destinationName;b.payloadMessage.duplicate&&(d.payloadMessage.duplicate=!0);b.payloadMessage.retained&&(d.payloadMessage.retained= +!0);0===a.indexOf("Sent:")&&(void 0===b.sequence&&(b.sequence=++this._sequence),d.sequence=b.sequence);break;default:throw Error(h(g.INVALID_STORED_DATA,[key,d]));}try{m.setStorageSync(a+this._localKey+b.messageIdentifier,JSON.stringify(d))}catch(n){}};c.prototype.restore=function(a){var b=m.getStorageSync(a),d=JSON.parse(b),c=new q(d.type,d);switch(d.type){case 3:for(var b=d.payloadMessage.payloadHex,e=new ArrayBuffer(b.length/2),e=new Uint8Array(e),f=0;2<=b.length;){var n=parseInt(b.substring(0, +2),16),b=b.substring(2,b.length);e[f++]=n}b=new v(e);b.qos=d.payloadMessage.qos;b.destinationName=d.payloadMessage.destinationName;d.payloadMessage.duplicate&&(b.duplicate=!0);d.payloadMessage.retained&&(b.retained=!0);c.payloadMessage=b;break;default:throw Error(h(g.INVALID_STORED_DATA,[a,b]));}0===a.indexOf("Sent:"+this._localKey)?(c.payloadMessage.duplicate=!0,this._sentMessages[c.messageIdentifier]=c):0===a.indexOf("Received:"+this._localKey)&&(this._receivedMessages[c.messageIdentifier]=c)}; +c.prototype._process_queue=function(){for(var a=null,b=this._msg_queue.reverse();a=b.pop();)this._socket_send(a),this._notify_msg_sent[a]&&(this._notify_msg_sent[a](),delete this._notify_msg_sent[a])};c.prototype._requires_ack=function(a){var b=Object.keys(this._sentMessages).length;if(b>this.maxMessageIdentifier)throw Error("Too many messages:"+b);for(;void 0!==this._sentMessages[this._message_identifier];)this._message_identifier++;a.messageIdentifier=this._message_identifier;this._sentMessages[a.messageIdentifier]= +a;3===a.type&&this.store("Sent:",a);this._message_identifier===this.maxMessageIdentifier&&(this._message_identifier=1)};c.prototype._on_socket_open=function(a){a=new q(1,this.connectOptions);a.clientId=this.clientId;this._socket_send(a)};c.prototype._on_socket_message=function(a){this._trace("Client._on_socket_message",a.data);a=this._deframeMessages(a.data);for(var b=0;b>4,t=m&15,f=f+1,w=void 0,C=0,p=1;do{if(f==e.length){c=[null,n];break a}w=e[f++];C+=(w&127)*p;p*=128}while(0!==(w&128));w=f+C;if(w>e.length)c=[null,n];else{var x=new q(l);switch(l){case 2:e[f++]&1&&(x.sessionPresent=!0);x.returnCode=e[f++];break;case 3:var n=t>>1&3,r=256*e[f]+e[f+1],f=f+2,u=E(e,f,r), +f=f+r;0this._reconnectInterval&&(this._reconnectInterval*=2),this.connectOptions.uris?(this.hostIndex=0,this._doConnect(this.connectOptions.uris[0])):this._doConnect(this.uri))};c.prototype._disconnected=function(a,b){this._trace("Client._disconnected",a,b);if(void 0!==a&&this._reconnecting)this._reconnectTimeout=new z(this,this._reconnectInterval, +this._reconnect);else if(this.sendPinger.cancel(),this.receivePinger.cancel(),this._connectTimeout&&(this._connectTimeout.cancel(),this._connectTimeout=null),this._msg_queue=[],this._buffered_msg_queue=[],this._notify_msg_sent={},this.connectOptions.uris&&this.hostIndexb)throw Error(h(g.INVALID_TYPE,[typeof b,"port"]));if("string"!==typeof d)throw Error(h(g.INVALID_TYPE,[typeof d,"path"]));e="ws://"+(-1!==a.indexOf(":")&&"["!==a.slice(0,1)&&"]"!==a.slice(-1)?"["+a+"]":a)+":"+b+d}for(var n=f=0;n=m&&n++;f++}if("string"!==typeof k||65535a.mqttVersion)throw Error(h(g.INVALID_ARGUMENT,[a.mqttVersion,"connectOptions.mqttVersion"]));void 0===a.mqttVersion?(a.mqttVersionExplicit=!1,a.mqttVersion=4):a.mqttVersionExplicit=!0;if(void 0!==a.password&&void 0===a.userName)throw Error(h(g.INVALID_ARGUMENT,[a.password,"connectOptions.password"]));if(a.willMessage){if(!(a.willMessage instanceof +v))throw Error(h(g.INVALID_TYPE,[a.willMessage,"connectOptions.willMessage"]));a.willMessage.stringPayload=null;if("undefined"===typeof a.willMessage.destinationName)throw Error(h(g.INVALID_TYPE,[typeof a.willMessage.destinationName,"connectOptions.willMessage.destinationName"]));}"undefined"===typeof a.cleanSession&&(a.cleanSession=!0);if(a.hosts){if(!(a.hosts instanceof Array))throw Error(h(g.INVALID_ARGUMENT,[a.hosts,"connectOptions.hosts"]));if(1>a.hosts.length)throw Error(h(g.INVALID_ARGUMENT, +[a.hosts,"connectOptions.hosts"]));for(var b=!1,c=0;ca.ports[c])throw Error(h(g.INVALID_TYPE,[typeof a.ports[c],"connectOptions.ports["+c+"]"]));var b=a.hosts[c],f=a.ports[c];e="ws://"+(-1!==b.indexOf(":")?"["+b+"]":b)+":"+f+d;a.uris.push(e)}}}l.connect(a)}; +this.subscribe=function(a,b){if("string"!==typeof a)throw Error("Invalid argument:"+a);b=b||{};y(b,{qos:"number",invocationContext:"object",onSuccess:"function",onFailure:"function",timeout:"number"});if(b.timeout&&!b.onFailure)throw Error("subscribeOptions.timeout specified with no onFailure callback.");if("undefined"!==typeof b.qos&&0!==b.qos&&1!==b.qos&&2!==b.qos)throw Error(h(g.INVALID_ARGUMENT,[b.qos,"subscribeOptions.qos"]));l.subscribe(a,b)};this.unsubscribe=function(a,b){if("string"!==typeof a)throw Error("Invalid argument:"+ +a);b=b||{};y(b,{invocationContext:"object",onSuccess:"function",onFailure:"function",timeout:"number"});if(b.timeout&&!b.onFailure)throw Error("unsubscribeOptions.timeout specified with no onFailure callback.");l.unsubscribe(a,b)};this.send=function(a,b,c,d){var e;if(0===arguments.length)throw Error("Invalid argument.length");if(1==arguments.length){if(!(a instanceof v)&&"string"!==typeof a)throw Error("Invalid argument:"+typeof a);e=a;if("undefined"===typeof e.destinationName)throw Error(h(g.INVALID_ARGUMENT, +[e.destinationName,"Message.destinationName"]));}else e=new v(b),e.destinationName=a,3<=arguments.length&&(e.qos=c),4<=arguments.length&&(e.retained=d);l.send(e)};this.publish=function(a,b,c,d){console.log("Publising message to: ",a);var e;if(0===arguments.length)throw Error("Invalid argument.length");if(1==arguments.length){if(!(a instanceof v)&&"string"!==typeof a)throw Error("Invalid argument:"+typeof a);e=a;if("undefined"===typeof e.destinationName)throw Error(h(g.INVALID_ARGUMENT,[e.destinationName, +"Message.destinationName"]));}else e=new v(b),e.destinationName=a,3<=arguments.length&&(e.qos=c),4<=arguments.length&&(e.retained=d);l.send(e)};this.disconnect=function(){l.disconnect()};this.getTraceLog=function(){return l.getTraceLog()};this.startTrace=function(){l.startTrace()};this.stopTrace=function(){l.stopTrace()};this.isConnected=function(){return l.connected}};G.prototype={get host(){return this._getHost()},set host(a){this._setHost(a)},get port(){return this._getPort()},set port(a){this._setPort(a)}, +get path(){return this._getPath()},set path(a){this._setPath(a)},get clientId(){return this._getClientId()},set clientId(a){this._setClientId(a)},get onConnected(){return this._getOnConnected()},set onConnected(a){this._setOnConnected(a)},get disconnectedPublishing(){return this._getDisconnectedPublishing()},set disconnectedPublishing(a){this._setDisconnectedPublishing(a)},get disconnectedBufferSize(){return this._getDisconnectedBufferSize()},set disconnectedBufferSize(a){this._setDisconnectedBufferSize(a)}, +get onConnectionLost(){return this._getOnConnectionLost()},set onConnectionLost(a){this._setOnConnectionLost(a)},get onMessageDelivered(){return this._getOnMessageDelivered()},set onMessageDelivered(a){this._setOnMessageDelivered(a)},get onMessageArrived(){return this._getOnMessageArrived()},set onMessageArrived(a){this._setOnMessageArrived(a)},get trace(){return this._getTrace()},set trace(a){this._setTrace(a)}};var v=function(a){var b;if("string"===typeof a||a instanceof ArrayBuffer||a instanceof +Int8Array||a instanceof Uint8Array||a instanceof Int16Array||a instanceof Uint16Array||a instanceof Int32Array||a instanceof Uint32Array||a instanceof Float32Array||a instanceof Float64Array)b=a;else throw h(g.INVALID_ARGUMENT,[a,"newPayload"]);this._getPayloadString=function(){return"string"===typeof b?b:E(b,0,b.length)};this._getPayloadBytes=function(){if("string"===typeof b){var a=new ArrayBuffer(p(b)),a=new Uint8Array(a);D(b,a,0);return a}return b};var c;this._getDestinationName=function(){return c}; +this._setDestinationName=function(a){if("string"===typeof a)c=a;else throw Error(h(g.INVALID_ARGUMENT,[a,"newDestinationName"]));};var k=0;this._getQos=function(){return k};this._setQos=function(a){if(0===a||1===a||2===a)k=a;else throw Error("Invalid argument:"+a);};var e=!1;this._getRetained=function(){return e};this._setRetained=function(a){if("boolean"===typeof a)e=a;else throw Error(h(g.INVALID_ARGUMENT,[a,"newRetained"]));};var f=!1;this._getDuplicate=function(){return f};this._setDuplicate= +function(a){f=a}};v.prototype={get payloadString(){return this._getPayloadString()},get payloadBytes(){return this._getPayloadBytes()},get destinationName(){return this._getDestinationName()},set destinationName(a){this._setDestinationName(a)},get topic(){return this._getDestinationName()},set topic(a){this._setDestinationName(a)},get qos(){return this._getQos()},set qos(a){this._setQos(a)},get retained(){return this._getRetained()},set retained(a){this._setRetained(a)},get duplicate(){return this._getDuplicate()}, +set duplicate(a){this._setDuplicate(a)}};return{Client:G,Message:v}}(wx)}); +// ESM only export +const __PahoMQTT = (typeof global !== 'undefined' && global.Paho && global.Paho.MQTT) ? global.Paho.MQTT : null; +export default __PahoMQTT; \ No newline at end of file diff --git a/uni_modules/x-mqtt-s/utssdk/unierror.uts b/uni_modules/x-mqtt-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-mqtt-s/utssdk/web/index.uts b/uni_modules/x-mqtt-s/utssdk/web/index.uts new file mode 100644 index 0000000..0d9ebf7 --- /dev/null +++ b/uni_modules/x-mqtt-s/utssdk/web/index.uts @@ -0,0 +1,156 @@ +export { CONNECT_STATUS,MQTT_EVENT_TYPE,MQTT_EVENT_CALL,MQTT_EVENT_PUBLISH,MQTT_SUBSCRIBE,MQTT_EVENTS_CALL,MQTT_PUBLISH_TOPIC,MQTT_CONNECT_OPTS } from "../interface.uts" +import PahoMqtt from "./paho-mqtt.min.js" +// var client = new Paho.MQTT.Client(location.hostname, Number(location.port), "clientId"); +// mqtt测试服务器 +// https://console.hivemq.cloud/ +// https://github.com/eclipse/paho.mqtt.javascript +// https://eclipse.dev/paho/files/jsdoc/Paho.MQTT.Client.html + +type MqttConnectOptions = { + userName?:string, + password?:string, + useSSL?:boolean, + keepAliveInterval?:number, + timeout?:number, + reconnect?:boolean, + onSuccess?:any, + onFailure?:any +} +const Paho = PahoMqtt() +export class xMqtt { + mqtt : MqttAndroidClient | null = null; + mqttConnectOptions : MqttConnectOptions | null = null; + connectStatus:CONNECT_STATUS = 'wait' + events = new Map(); + constructor(){ + + } + /** + * @param ulr {string} 连接地址 + * @param clientIdStr {string} 客户端id + * @param username {string|null} 用户名称,如果不需要,设置为null即可 + * @param password {string|null} 登录密码,如果不需要,设置为null即可 + */ + create(opts:MQTT_CONNECT_OPTS):xMqtt { + + let t = this; + this.mqtt = new Paho.Client(opts.server,opts.port,opts.path, opts.clientId); + this.mqttConnectOptions = {} as MqttConnectOptions; + this.mqttConnectOptions.userName = opts.userName; + this.mqttConnectOptions.password = opts.passWord; + this.mqttConnectOptions.useSSL = opts.useSSL; + this.mqttConnectOptions.keepAliveInterval = opts.keepAliveInterval; + this.mqttConnectOptions.timeout = opts.timeout; + this.mqttConnectOptions.onSuccess = ()=>{ + console.log('****') + t.buildCallEvents('open',null,'连接成功') + }; + this.mqttConnectOptions.onFailure = ()=>{ + t.buildCallEvents('error',null,'连接失败') + }; + this.mqttConnectOptions.reconnect = opts.reconnect; + this.mqtt.onConnectionLost = ()=>{ + t.buildCallEvents('dissconnect',null,'连接断开') + }; + this.mqtt.onMessageArrived = (evt)=>{ + + t.buildCallEvents('message',evt.topic,evt.payloadString) + }; + this.connectStatus = 'wait' + + return this; + } + + /** + * @param type {MQTT_EVENT_TYPE} 事件名称 + * @param call {MQTT_EVENT_CALL} 事件回调 + */ + addEventListener(type:MQTT_EVENT_TYPE,call:MQTT_EVENT_CALL):string{ + let id = Date.now().toString()+(Math.random()*100).toString() + this.events.set(id, + { + type, + value:call + } as MQTT_EVENTS_CALL + ) + + return id; + } + /** + * @param id {string} addEventListener返回的事件id + */ + removeEventListener(id:string):xMqtt{ + this.events.delete(id) + return this; + } + private buildCallEvents(type:MQTT_EVENT_TYPE,toppic:string|null,str:string){ + this.events.forEach((value:MQTT_EVENTS_CALL,key:string)=>{ + if(value.type == type){ + value.value(type,toppic,str) + } + }) + } + connect():xMqtt{ + + this.mqtt?.connect(this.mqttConnectOptions); + return this; + } + /** + * 订阅 + * @param data {MQTT_SUBSCRIBE[]} 订阅的消息数组 + */ + subscribe(data:MQTT_SUBSCRIBE[]):xMqtt{ + let t = this; + if(this.mqtt == null) return this; + for(let i=0;ivoid 推送消息成功时的回调【web端永为真】 + */ + publish(message:MQTT_PUBLISH_TOPIC,call:MQTT_EVENT_PUBLISH):xMqtt{ + if(this.mqtt == null) return this; + this.mqtt!.publish(message.topic,message.message,message.qos,true); + call(true) + return this; + } + /** + * 取消订阅 + * @param topics {string[]} 主题数组 + */ + unsubscribe(topics:string[]):xMqtt{ + let t = this; + if(this.mqtt == null||topics.length==0) return this; + for(let i=0;i + * This programming interface lets a JavaScript client application use the MQTT V3.1 or + * V3.1.1 protocol to connect to an MQTT-supporting messaging server. + * + * The function supported includes: + *
      + *
    1. Connecting to and disconnecting from a server. The server is identified by its host name and port number. + *
    2. Specifying options that relate to the communications link with the server, + * for example the frequency of keep-alive heartbeats, and whether SSL/TLS is required. + *
    3. Subscribing to and receiving messages from MQTT Topics. + *
    4. Publishing messages to MQTT Topics. + *
    + *

    + * The API consists of two main objects: + *

    + *
    {@link Paho.Client}
    + *
    This contains methods that provide the functionality of the API, + * including provision of callbacks that notify the application when a message + * arrives from or is delivered to the messaging server, + * or when the status of its connection to the messaging server changes.
    + *
    {@link Paho.Message}
    + *
    This encapsulates the payload of the message along with various attributes + * associated with its delivery, in particular the destination to which it has + * been (or is about to be) sent.
    + *
    + *

    + * The programming interface validates parameters passed to it, and will throw + * an Error containing an error message intended for developer use, if it detects + * an error with any parameter. + *

    + * Example: + * + *

    +var client = new Paho.MQTT.Client(location.hostname, Number(location.port), "clientId");
    +client.onConnectionLost = onConnectionLost;
    +client.onMessageArrived = onMessageArrived;
    +client.connect({onSuccess:onConnect});
    +
    +function onConnect() {
    +  // Once a connection has been made, make a subscription and send a message.
    +  console.log("onConnect");
    +  client.subscribe("/World");
    +  var message = new Paho.MQTT.Message("Hello");
    +  message.destinationName = "/World";
    +  client.send(message);
    +};
    +function onConnectionLost(responseObject) {
    +  if (responseObject.errorCode !== 0)
    +	console.log("onConnectionLost:"+responseObject.errorMessage);
    +};
    +function onMessageArrived(message) {
    +  console.log("onMessageArrived:"+message.payloadString);
    +  client.disconnect();
    +};
    + * 
    + * @namespace Paho + */ + + +export default function() { + const global = window; + // Private variables below, these are only visible inside the function closure + // which is used to define the module. + var version = "@VERSION@-@BUILDLEVEL@"; + + /** + * @private + */ + var localStorage = (function() { + var data = {}; + return { + setItem: function(key, item) { + data[key] = item; + }, + getItem: function(key) { + return data[key]; + }, + removeItem: function(key) { + delete data[key]; + }, + }; + })(); + + /** + * Unique message type identifiers, with associated + * associated integer values. + * @private + */ + var MESSAGE_TYPE = { + CONNECT: 1, + CONNACK: 2, + PUBLISH: 3, + PUBACK: 4, + PUBREC: 5, + PUBREL: 6, + PUBCOMP: 7, + SUBSCRIBE: 8, + SUBACK: 9, + UNSUBSCRIBE: 10, + UNSUBACK: 11, + PINGREQ: 12, + PINGRESP: 13, + DISCONNECT: 14 + }; + + // Collection of utility methods used to simplify module code + // and promote the DRY pattern. + + /** + * Validate an object's parameter names to ensure they + * match a list of expected variables name for this option + * type. Used to ensure option object passed into the API don't + * contain erroneous parameters. + * @param {Object} obj - User options object + * @param {Object} keys - valid keys and types that may exist in obj. + * @throws {Error} Invalid option parameter found. + * @private + */ + var validate = function(obj, keys) { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if (keys.hasOwnProperty(key)) { + if (typeof obj[key] !== keys[key]) + throw new Error(format(ERROR.INVALID_TYPE, [typeof obj[key], key])); + } else { + var errorStr = "Unknown property, " + key + ". Valid properties are:"; + for (var validKey in keys) + if (keys.hasOwnProperty(validKey)) + errorStr = errorStr + " " + validKey; + throw new Error(errorStr); + } + } + } + }; + + /** + * Return a new function which runs the user function bound + * to a fixed scope. + * @param {function} User function + * @param {object} Function scope + * @return {function} User function bound to another scope + * @private + */ + var scope = function(f, scope) { + return function() { + return f.apply(scope, arguments); + }; + }; + + /** + * Unique message type identifiers, with associated + * associated integer values. + * @private + */ + var ERROR = { + OK: { + code: 0, + text: "AMQJSC0000I OK." + }, + CONNECT_TIMEOUT: { + code: 1, + text: "AMQJSC0001E Connect timed out." + }, + SUBSCRIBE_TIMEOUT: { + code: 2, + text: "AMQJS0002E Subscribe timed out." + }, + UNSUBSCRIBE_TIMEOUT: { + code: 3, + text: "AMQJS0003E Unsubscribe timed out." + }, + PING_TIMEOUT: { + code: 4, + text: "AMQJS0004E Ping timed out." + }, + INTERNAL_ERROR: { + code: 5, + text: "AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}" + }, + CONNACK_RETURNCODE: { + code: 6, + text: "AMQJS0006E Bad Connack return code:{0} {1}." + }, + SOCKET_ERROR: { + code: 7, + text: "AMQJS0007E Socket error:{0}." + }, + SOCKET_CLOSE: { + code: 8, + text: "AMQJS0008I Socket closed." + }, + MALFORMED_UTF: { + code: 9, + text: "AMQJS0009E Malformed UTF data:{0} {1} {2}." + }, + UNSUPPORTED: { + code: 10, + text: "AMQJS0010E {0} is not supported by this browser." + }, + INVALID_STATE: { + code: 11, + text: "AMQJS0011E Invalid state {0}." + }, + INVALID_TYPE: { + code: 12, + text: "AMQJS0012E Invalid type {0} for {1}." + }, + INVALID_ARGUMENT: { + code: 13, + text: "AMQJS0013E Invalid argument {0} for {1}." + }, + UNSUPPORTED_OPERATION: { + code: 14, + text: "AMQJS0014E Unsupported operation." + }, + INVALID_STORED_DATA: { + code: 15, + text: "AMQJS0015E Invalid data in local storage key={0} value={1}." + }, + INVALID_MQTT_MESSAGE_TYPE: { + code: 16, + text: "AMQJS0016E Invalid MQTT message type {0}." + }, + MALFORMED_UNICODE: { + code: 17, + text: "AMQJS0017E Malformed Unicode string:{0} {1}." + }, + BUFFER_FULL: { + code: 18, + text: "AMQJS0018E Message buffer is full, maximum buffer size: {0}." + }, + }; + + /** CONNACK RC Meaning. */ + var CONNACK_RC = { + 0: "Connection Accepted", + 1: "Connection Refused: unacceptable protocol version", + 2: "Connection Refused: identifier rejected", + 3: "Connection Refused: server unavailable", + 4: "Connection Refused: bad user name or password", + 5: "Connection Refused: not authorized" + }; + + /** + * Format an error message text. + * @private + * @param {error} ERROR value above. + * @param {substitutions} [array] substituted into the text. + * @return the text with the substitutions made. + */ + var format = function(error, substitutions) { + var text = error.text; + if (substitutions) { + var field, start; + for (var i = 0; i < substitutions.length; i++) { + field = "{" + i + "}"; + start = text.indexOf(field); + if (start > 0) { + var part1 = text.substring(0, start); + var part2 = text.substring(start + field.length); + text = part1 + substitutions[i] + part2; + } + } + } + return text; + }; + + //MQTT protocol and version 6 M Q I s d p 3 + var MqttProtoIdentifierv3 = [0x00, 0x06, 0x4d, 0x51, 0x49, 0x73, 0x64, 0x70, 0x03]; + //MQTT proto/version for 311 4 M Q T T 4 + var MqttProtoIdentifierv4 = [0x00, 0x04, 0x4d, 0x51, 0x54, 0x54, 0x04]; + + /** + * Construct an MQTT wire protocol message. + * @param type MQTT packet type. + * @param options optional wire message attributes. + * + * Optional properties + * + * messageIdentifier: message ID in the range [0..65535] + * payloadMessage: Application Message - PUBLISH only + * connectStrings: array of 0 or more Strings to be put into the CONNECT payload + * topics: array of strings (SUBSCRIBE, UNSUBSCRIBE) + * requestQoS: array of QoS values [0..2] + * + * "Flag" properties + * cleanSession: true if present / false if absent (CONNECT) + * willMessage: true if present / false if absent (CONNECT) + * isRetained: true if present / false if absent (CONNECT) + * userName: true if present / false if absent (CONNECT) + * password: true if present / false if absent (CONNECT) + * keepAliveInterval: integer [0..65535] (CONNECT) + * + * @private + * @ignore + */ + var WireMessage = function(type, options) { + this.type = type; + for (var name in options) { + if (options.hasOwnProperty(name)) { + this[name] = options[name]; + } + } + }; + + WireMessage.prototype.encode = function() { + // Compute the first byte of the fixed header + var first = ((this.type & 0x0f) << 4); + + /* + * Now calculate the length of the variable header + payload by adding up the lengths + * of all the component parts + */ + + var remLength = 0; + var topicStrLength = []; + var destinationNameLength = 0; + var willMessagePayloadBytes; + + // if the message contains a messageIdentifier then we need two bytes for that + if (this.messageIdentifier !== undefined) + remLength += 2; + + switch (this.type) { + // If this a Connect then we need to include 12 bytes for its header + case MESSAGE_TYPE.CONNECT: + switch (this.mqttVersion) { + case 3: + remLength += MqttProtoIdentifierv3.length + 3; + break; + case 4: + remLength += MqttProtoIdentifierv4.length + 3; + break; + } + + remLength += UTF8Length(this.clientId) + 2; + if (this.willMessage !== undefined) { + remLength += UTF8Length(this.willMessage.destinationName) + 2; + // Will message is always a string, sent as UTF-8 characters with a preceding length. + willMessagePayloadBytes = this.willMessage.payloadBytes; + if (!(willMessagePayloadBytes instanceof Uint8Array)) + willMessagePayloadBytes = new Uint8Array(payloadBytes); + remLength += willMessagePayloadBytes.byteLength + 2; + } + if (this.userName !== undefined) + remLength += UTF8Length(this.userName) + 2; + if (this.password !== undefined) + remLength += UTF8Length(this.password) + 2; + break; + + // Subscribe, Unsubscribe can both contain topic strings + case MESSAGE_TYPE.SUBSCRIBE: + first |= 0x02; // Qos = 1; + for (var i = 0; i < this.topics.length; i++) { + topicStrLength[i] = UTF8Length(this.topics[i]); + remLength += topicStrLength[i] + 2; + } + remLength += this.requestedQos.length; // 1 byte for each topic's Qos + // QoS on Subscribe only + break; + + case MESSAGE_TYPE.UNSUBSCRIBE: + first |= 0x02; // Qos = 1; + for (var i = 0; i < this.topics.length; i++) { + topicStrLength[i] = UTF8Length(this.topics[i]); + remLength += topicStrLength[i] + 2; + } + break; + + case MESSAGE_TYPE.PUBREL: + first |= 0x02; // Qos = 1; + break; + + case MESSAGE_TYPE.PUBLISH: + if (this.payloadMessage.duplicate) first |= 0x08; + first = first |= (this.payloadMessage.qos << 1); + if (this.payloadMessage.retained) first |= 0x01; + destinationNameLength = UTF8Length(this.payloadMessage.destinationName); + remLength += destinationNameLength + 2; + var payloadBytes = this.payloadMessage.payloadBytes; + remLength += payloadBytes.byteLength; + if (payloadBytes instanceof ArrayBuffer) + payloadBytes = new Uint8Array(payloadBytes); + else if (!(payloadBytes instanceof Uint8Array)) + payloadBytes = new Uint8Array(payloadBytes.buffer); + break; + + case MESSAGE_TYPE.DISCONNECT: + break; + + default: + break; + } + + // Now we can allocate a buffer for the message + + var mbi = encodeMBI(remLength); // Convert the length to MQTT MBI format + var pos = mbi.length + 1; // Offset of start of variable header + var buffer = new ArrayBuffer(remLength + pos); + var byteStream = new Uint8Array(buffer); // view it as a sequence of bytes + + //Write the fixed header into the buffer + byteStream[0] = first; + byteStream.set(mbi, 1); + + // If this is a PUBLISH then the variable header starts with a topic + if (this.type == MESSAGE_TYPE.PUBLISH) + pos = writeString(this.payloadMessage.destinationName, destinationNameLength, byteStream, pos); + // If this is a CONNECT then the variable header contains the protocol name/version, flags and keepalive time + + else if (this.type == MESSAGE_TYPE.CONNECT) { + switch (this.mqttVersion) { + case 3: + byteStream.set(MqttProtoIdentifierv3, pos); + pos += MqttProtoIdentifierv3.length; + break; + case 4: + byteStream.set(MqttProtoIdentifierv4, pos); + pos += MqttProtoIdentifierv4.length; + break; + } + var connectFlags = 0; + if (this.cleanSession) + connectFlags = 0x02; + if (this.willMessage !== undefined) { + connectFlags |= 0x04; + connectFlags |= (this.willMessage.qos << 3); + if (this.willMessage.retained) { + connectFlags |= 0x20; + } + } + if (this.userName !== undefined) + connectFlags |= 0x80; + if (this.password !== undefined) + connectFlags |= 0x40; + byteStream[pos++] = connectFlags; + pos = writeUint16(this.keepAliveInterval, byteStream, pos); + } + + // Output the messageIdentifier - if there is one + if (this.messageIdentifier !== undefined) + pos = writeUint16(this.messageIdentifier, byteStream, pos); + + switch (this.type) { + case MESSAGE_TYPE.CONNECT: + pos = writeString(this.clientId, UTF8Length(this.clientId), byteStream, pos); + if (this.willMessage !== undefined) { + pos = writeString(this.willMessage.destinationName, UTF8Length(this.willMessage + .destinationName), byteStream, pos); + pos = writeUint16(willMessagePayloadBytes.byteLength, byteStream, pos); + byteStream.set(willMessagePayloadBytes, pos); + pos += willMessagePayloadBytes.byteLength; + + } + if (this.userName !== undefined) + pos = writeString(this.userName, UTF8Length(this.userName), byteStream, pos); + if (this.password !== undefined) + pos = writeString(this.password, UTF8Length(this.password), byteStream, pos); + break; + + case MESSAGE_TYPE.PUBLISH: + // PUBLISH has a text or binary payload, if text do not add a 2 byte length field, just the UTF characters. + byteStream.set(payloadBytes, pos); + + break; + + // case MESSAGE_TYPE.PUBREC: + // case MESSAGE_TYPE.PUBREL: + // case MESSAGE_TYPE.PUBCOMP: + // break; + + case MESSAGE_TYPE.SUBSCRIBE: + // SUBSCRIBE has a list of topic strings and request QoS + for (var i = 0; i < this.topics.length; i++) { + pos = writeString(this.topics[i], topicStrLength[i], byteStream, pos); + byteStream[pos++] = this.requestedQos[i]; + } + break; + + case MESSAGE_TYPE.UNSUBSCRIBE: + // UNSUBSCRIBE has a list of topic strings + for (var i = 0; i < this.topics.length; i++) + pos = writeString(this.topics[i], topicStrLength[i], byteStream, pos); + break; + + default: + // Do nothing. + } + + return buffer; + }; + + function decodeMessage(input, pos) { + var startingPos = pos; + var first = input[pos]; + var type = first >> 4; + var messageInfo = first &= 0x0f; + pos += 1; + + + // Decode the remaining length (MBI format) + + var digit; + var remLength = 0; + var multiplier = 1; + do { + if (pos == input.length) { + return [null, startingPos]; + } + digit = input[pos++]; + remLength += ((digit & 0x7F) * multiplier); + multiplier *= 128; + } while ((digit & 0x80) !== 0); + + var endPos = pos + remLength; + if (endPos > input.length) { + return [null, startingPos]; + } + + var wireMessage = new WireMessage(type); + switch (type) { + case MESSAGE_TYPE.CONNACK: + var connectAcknowledgeFlags = input[pos++]; + if (connectAcknowledgeFlags & 0x01) + wireMessage.sessionPresent = true; + wireMessage.returnCode = input[pos++]; + break; + + case MESSAGE_TYPE.PUBLISH: + var qos = (messageInfo >> 1) & 0x03; + + var len = readUint16(input, pos); + pos += 2; + var topicName = parseUTF8(input, pos, len); + pos += len; + // If QoS 1 or 2 there will be a messageIdentifier + if (qos > 0) { + wireMessage.messageIdentifier = readUint16(input, pos); + pos += 2; + } + + var message = new Message(input.subarray(pos, endPos)); + if ((messageInfo & 0x01) == 0x01) + message.retained = true; + if ((messageInfo & 0x08) == 0x08) + message.duplicate = true; + message.qos = qos; + message.destinationName = topicName; + wireMessage.payloadMessage = message; + break; + + case MESSAGE_TYPE.PUBACK: + case MESSAGE_TYPE.PUBREC: + case MESSAGE_TYPE.PUBREL: + case MESSAGE_TYPE.PUBCOMP: + case MESSAGE_TYPE.UNSUBACK: + wireMessage.messageIdentifier = readUint16(input, pos); + break; + + case MESSAGE_TYPE.SUBACK: + wireMessage.messageIdentifier = readUint16(input, pos); + pos += 2; + wireMessage.returnCode = input.subarray(pos, endPos); + break; + + default: + break; + } + + return [wireMessage, endPos]; + } + + function writeUint16(input, buffer, offset) { + buffer[offset++] = input >> 8; //MSB + buffer[offset++] = input % 256; //LSB + return offset; + } + + function writeString(input, utf8Length, buffer, offset) { + offset = writeUint16(utf8Length, buffer, offset); + stringToUTF8(input, buffer, offset); + return offset + utf8Length; + } + + function readUint16(buffer, offset) { + return 256 * buffer[offset] + buffer[offset + 1]; + } + + /** + * Encodes an MQTT Multi-Byte Integer + * @private + */ + function encodeMBI(number) { + var output = new Array(1); + var numBytes = 0; + + do { + var digit = number % 128; + number = number >> 7; + if (number > 0) { + digit |= 0x80; + } + output[numBytes++] = digit; + } while ((number > 0) && (numBytes < 4)); + + return output; + } + + /** + * Takes a String and calculates its length in bytes when encoded in UTF8. + * @private + */ + function UTF8Length(input) { + var output = 0; + for (var i = 0; i < input.length; i++) { + var charCode = input.charCodeAt(i); + if (charCode > 0x7FF) { + // Surrogate pair means its a 4 byte character + if (0xD800 <= charCode && charCode <= 0xDBFF) { + i++; + output++; + } + output += 3; + } else if (charCode > 0x7F) + output += 2; + else + output++; + } + return output; + } + + /** + * Takes a String and writes it into an array as UTF8 encoded bytes. + * @private + */ + function stringToUTF8(input, output, start) { + var pos = start; + for (var i = 0; i < input.length; i++) { + var charCode = input.charCodeAt(i); + + // Check for a surrogate pair. + if (0xD800 <= charCode && charCode <= 0xDBFF) { + var lowCharCode = input.charCodeAt(++i); + if (isNaN(lowCharCode)) { + throw new Error(format(ERROR.MALFORMED_UNICODE, [charCode, lowCharCode])); + } + charCode = ((charCode - 0xD800) << 10) + (lowCharCode - 0xDC00) + 0x10000; + + } + + if (charCode <= 0x7F) { + output[pos++] = charCode; + } else if (charCode <= 0x7FF) { + output[pos++] = charCode >> 6 & 0x1F | 0xC0; + output[pos++] = charCode & 0x3F | 0x80; + } else if (charCode <= 0xFFFF) { + output[pos++] = charCode >> 12 & 0x0F | 0xE0; + output[pos++] = charCode >> 6 & 0x3F | 0x80; + output[pos++] = charCode & 0x3F | 0x80; + } else { + output[pos++] = charCode >> 18 & 0x07 | 0xF0; + output[pos++] = charCode >> 12 & 0x3F | 0x80; + output[pos++] = charCode >> 6 & 0x3F | 0x80; + output[pos++] = charCode & 0x3F | 0x80; + } + } + return output; + } + + function parseUTF8(input, offset, length) { + var output = ""; + var utf16; + var pos = offset; + + while (pos < offset + length) { + var byte1 = input[pos++]; + if (byte1 < 128) + utf16 = byte1; + else { + var byte2 = input[pos++] - 128; + if (byte2 < 0) + throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), ""])); + if (byte1 < 0xE0) // 2 byte character + utf16 = 64 * (byte1 - 0xC0) + byte2; + else { + var byte3 = input[pos++] - 128; + if (byte3 < 0) + throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), + byte3.toString(16) + ])); + if (byte1 < 0xF0) // 3 byte character + utf16 = 4096 * (byte1 - 0xE0) + 64 * byte2 + byte3; + else { + var byte4 = input[pos++] - 128; + if (byte4 < 0) + throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), + byte3.toString(16), byte4.toString(16) + ])); + if (byte1 < 0xF8) // 4 byte character + utf16 = 262144 * (byte1 - 0xF0) + 4096 * byte2 + 64 * byte3 + byte4; + else // longer encodings are not supported + throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), + byte3.toString(16), byte4.toString(16) + ])); + } + } + } + + if (utf16 > 0xFFFF) // 4 byte character - express as a surrogate pair + { + utf16 -= 0x10000; + output += String.fromCharCode(0xD800 + (utf16 >> 10)); // lead character + utf16 = 0xDC00 + (utf16 & 0x3FF); // trail character + } + output += String.fromCharCode(utf16); + } + return output; + } + + /** + * Repeat keepalive requests, monitor responses. + * @ignore + */ + var Pinger = function(client, keepAliveInterval) { + this._client = client; + this._keepAliveInterval = keepAliveInterval * 1000; + this.isReset = false; + + var pingReq = new WireMessage(MESSAGE_TYPE.PINGREQ).encode(); + + var doTimeout = function(pinger) { + return function() { + return doPing.apply(pinger); + }; + }; + + /** @ignore */ + var doPing = function() { + if (!this.isReset) { + this._client._trace("Pinger.doPing", "Timed out"); + this._client._disconnected(ERROR.PING_TIMEOUT.code, format(ERROR.PING_TIMEOUT)); + } else { + this.isReset = false; + this._client._trace("Pinger.doPing", "send PINGREQ"); + this._client.socket.send(pingReq); + this.timeout = setTimeout(doTimeout(this), this._keepAliveInterval); + } + }; + + this.reset = function() { + this.isReset = true; + clearTimeout(this.timeout); + if (this._keepAliveInterval > 0) + this.timeout = setTimeout(doTimeout(this), this._keepAliveInterval); + }; + + this.cancel = function() { + clearTimeout(this.timeout); + }; + }; + + /** + * Monitor request completion. + * @ignore + */ + var Timeout = function(client, timeoutSeconds, action, args) { + if (!timeoutSeconds) + timeoutSeconds = 30; + + var doTimeout = function(action, client, args) { + return function() { + return action.apply(client, args); + }; + }; + this.timeout = setTimeout(doTimeout(action, client, args), timeoutSeconds * 1000); + + this.cancel = function() { + clearTimeout(this.timeout); + }; + }; + + /** + * Internal implementation of the Websockets MQTT V3.1 client. + * + * @name Paho.ClientImpl @constructor + * @param {String} host the DNS nameof the webSocket host. + * @param {Number} port the port number for that host. + * @param {String} clientId the MQ client identifier. + */ + var ClientImpl = function(uri, host, port, path, clientId) { + // Check dependencies are satisfied in this browser. + if (!("WebSocket" in global && global.WebSocket !== null)) { + throw new Error(format(ERROR.UNSUPPORTED, ["WebSocket"])); + } + if (!("ArrayBuffer" in global && global.ArrayBuffer !== null)) { + throw new Error(format(ERROR.UNSUPPORTED, ["ArrayBuffer"])); + } + this._trace("Paho.Client", uri, host, port, path, clientId); + + this.host = host; + this.port = port; + this.path = path; + this.uri = uri; + this.clientId = clientId; + this._wsuri = null; + + // Local storagekeys are qualified with the following string. + // The conditional inclusion of path in the key is for backward + // compatibility to when the path was not configurable and assumed to + // be /mqtt + this._localKey = host + ":" + port + (path != "/mqtt" ? ":" + path : "") + ":" + clientId + ":"; + + // Create private instance-only message queue + // Internal queue of messages to be sent, in sending order. + this._msg_queue = []; + this._buffered_msg_queue = []; + + // Messages we have sent and are expecting a response for, indexed by their respective message ids. + this._sentMessages = {}; + + // Messages we have received and acknowleged and are expecting a confirm message for + // indexed by their respective message ids. + this._receivedMessages = {}; + + // Internal list of callbacks to be executed when messages + // have been successfully sent over web socket, e.g. disconnect + // when it doesn't have to wait for ACK, just message is dispatched. + this._notify_msg_sent = {}; + + // Unique identifier for SEND messages, incrementing + // counter as messages are sent. + this._message_identifier = 1; + + // Used to determine the transmission sequence of stored sent messages. + this._sequence = 0; + + + // Load the local state, if any, from the saved version, only restore state relevant to this client. + for (var key in localStorage) + if (key.indexOf("Sent:" + this._localKey) === 0 || key.indexOf("Received:" + this._localKey) === + 0) + this.restore(key); + }; + + // Messaging Client public instance members. + ClientImpl.prototype.host = null; + ClientImpl.prototype.port = null; + ClientImpl.prototype.path = null; + ClientImpl.prototype.uri = null; + ClientImpl.prototype.clientId = null; + + // Messaging Client private instance members. + ClientImpl.prototype.socket = null; + /* true once we have received an acknowledgement to a CONNECT packet. */ + ClientImpl.prototype.connected = false; + /* The largest message identifier allowed, may not be larger than 2**16 but + * if set smaller reduces the maximum number of outbound messages allowed. + */ + ClientImpl.prototype.maxMessageIdentifier = 65536; + ClientImpl.prototype.connectOptions = null; + ClientImpl.prototype.hostIndex = null; + ClientImpl.prototype.onConnected = null; + ClientImpl.prototype.onConnectionLost = null; + ClientImpl.prototype.onMessageDelivered = null; + ClientImpl.prototype.onMessageArrived = null; + ClientImpl.prototype.traceFunction = null; + ClientImpl.prototype._msg_queue = null; + ClientImpl.prototype._buffered_msg_queue = null; + ClientImpl.prototype._connectTimeout = null; + /* The sendPinger monitors how long we allow before we send data to prove to the server that we are alive. */ + ClientImpl.prototype.sendPinger = null; + /* The receivePinger monitors how long we allow before we require evidence that the server is alive. */ + ClientImpl.prototype.receivePinger = null; + ClientImpl.prototype._reconnectInterval = 1; // Reconnect Delay, starts at 1 second + ClientImpl.prototype._reconnecting = false; + ClientImpl.prototype._reconnectTimeout = null; + ClientImpl.prototype.disconnectedPublishing = false; + ClientImpl.prototype.disconnectedBufferSize = 5000; + + ClientImpl.prototype.receiveBuffer = null; + + ClientImpl.prototype._traceBuffer = null; + ClientImpl.prototype._MAX_TRACE_ENTRIES = 100; + + ClientImpl.prototype.connect = function(connectOptions) { + var connectOptionsMasked = this._traceMask(connectOptions, "password"); + this._trace("Client.connect", connectOptionsMasked, this.socket, this.connected); + + if (this.connected) + throw new Error(format(ERROR.INVALID_STATE, ["already connected"])); + if (this.socket) + throw new Error(format(ERROR.INVALID_STATE, ["already connected"])); + + if (this._reconnecting) { + // connect() function is called while reconnect is in progress. + // Terminate the auto reconnect process to use new connect options. + this._reconnectTimeout.cancel(); + this._reconnectTimeout = null; + this._reconnecting = false; + } + + this.connectOptions = connectOptions; + this._reconnectInterval = 1; + this._reconnecting = false; + if (connectOptions.uris) { + this.hostIndex = 0; + this._doConnect(connectOptions.uris[0]); + } else { + this._doConnect(this.uri); + } + + }; + + ClientImpl.prototype.subscribe = function(filter, subscribeOptions) { + this._trace("Client.subscribe", filter, subscribeOptions); + + if (!this.connected) + throw new Error(format(ERROR.INVALID_STATE, ["not connected"])); + + var wireMessage = new WireMessage(MESSAGE_TYPE.SUBSCRIBE); + wireMessage.topics = filter.constructor === Array ? filter : [filter]; + if (subscribeOptions.qos === undefined) + subscribeOptions.qos = 0; + wireMessage.requestedQos = []; + for (var i = 0; i < wireMessage.topics.length; i++) + wireMessage.requestedQos[i] = subscribeOptions.qos; + + if (subscribeOptions.onSuccess) { + wireMessage.onSuccess = function(grantedQos) { + subscribeOptions.onSuccess({ + invocationContext: subscribeOptions.invocationContext, + grantedQos: grantedQos + }); + }; + } + + if (subscribeOptions.onFailure) { + wireMessage.onFailure = function(errorCode) { + subscribeOptions.onFailure({ + invocationContext: subscribeOptions.invocationContext, + errorCode: errorCode, + errorMessage: format(errorCode) + }); + }; + } + + if (subscribeOptions.timeout) { + wireMessage.timeOut = new Timeout(this, subscribeOptions.timeout, subscribeOptions.onFailure, + [{ + invocationContext: subscribeOptions.invocationContext, + errorCode: ERROR.SUBSCRIBE_TIMEOUT.code, + errorMessage: format(ERROR.SUBSCRIBE_TIMEOUT) + }]); + } + + // All subscriptions return a SUBACK. + this._requires_ack(wireMessage); + this._schedule_message(wireMessage); + }; + + /** @ignore */ + ClientImpl.prototype.unsubscribe = function(filter, unsubscribeOptions) { + this._trace("Client.unsubscribe", filter, unsubscribeOptions); + + if (!this.connected) + throw new Error(format(ERROR.INVALID_STATE, ["not connected"])); + + var wireMessage = new WireMessage(MESSAGE_TYPE.UNSUBSCRIBE); + wireMessage.topics = filter.constructor === Array ? filter : [filter]; + + if (unsubscribeOptions.onSuccess) { + wireMessage.callback = function() { + unsubscribeOptions.onSuccess({ + invocationContext: unsubscribeOptions.invocationContext + }); + }; + } + if (unsubscribeOptions.timeout) { + wireMessage.timeOut = new Timeout(this, unsubscribeOptions.timeout, unsubscribeOptions + .onFailure, + [{ + invocationContext: unsubscribeOptions.invocationContext, + errorCode: ERROR.UNSUBSCRIBE_TIMEOUT.code, + errorMessage: format(ERROR.UNSUBSCRIBE_TIMEOUT) + }]); + } + + // All unsubscribes return a SUBACK. + this._requires_ack(wireMessage); + this._schedule_message(wireMessage); + }; + + ClientImpl.prototype.send = function(message) { + this._trace("Client.send", message); + + var wireMessage = new WireMessage(MESSAGE_TYPE.PUBLISH); + wireMessage.payloadMessage = message; + + if (this.connected) { + // Mark qos 1 & 2 message as "ACK required" + // For qos 0 message, invoke onMessageDelivered callback if there is one. + // Then schedule the message. + if (message.qos > 0) { + this._requires_ack(wireMessage); + } else if (this.onMessageDelivered) { + this._notify_msg_sent[wireMessage] = this.onMessageDelivered(wireMessage.payloadMessage); + } + this._schedule_message(wireMessage); + } else { + // Currently disconnected, will not schedule this message + // Check if reconnecting is in progress and disconnected publish is enabled. + if (this._reconnecting && this.disconnectedPublishing) { + // Check the limit which include the "required ACK" messages + var messageCount = Object.keys(this._sentMessages).length + this._buffered_msg_queue.length; + if (messageCount > this.disconnectedBufferSize) { + throw new Error(format(ERROR.BUFFER_FULL, [this.disconnectedBufferSize])); + } else { + if (message.qos > 0) { + // Mark this message as "ACK required" + this._requires_ack(wireMessage); + } else { + wireMessage.sequence = ++this._sequence; + // Add messages in fifo order to array, by adding to start + this._buffered_msg_queue.unshift(wireMessage); + } + } + } else { + throw new Error(format(ERROR.INVALID_STATE, ["not connected"])); + } + } + }; + + ClientImpl.prototype.disconnect = function() { + this._trace("Client.disconnect"); + + if (this._reconnecting) { + // disconnect() function is called while reconnect is in progress. + // Terminate the auto reconnect process. + this._reconnectTimeout.cancel(); + this._reconnectTimeout = null; + this._reconnecting = false; + } + + if (!this.socket) + throw new Error(format(ERROR.INVALID_STATE, ["not connecting or connected"])); + + var wireMessage = new WireMessage(MESSAGE_TYPE.DISCONNECT); + + // Run the disconnected call back as soon as the message has been sent, + // in case of a failure later on in the disconnect processing. + // as a consequence, the _disconected call back may be run several times. + this._notify_msg_sent[wireMessage] = scope(this._disconnected, this); + + this._schedule_message(wireMessage); + }; + + ClientImpl.prototype.getTraceLog = function() { + if (this._traceBuffer !== null) { + this._trace("Client.getTraceLog", new Date()); + this._trace("Client.getTraceLog in flight messages", this._sentMessages.length); + for (var key in this._sentMessages) + this._trace("_sentMessages ", key, this._sentMessages[key]); + for (var key in this._receivedMessages) + this._trace("_receivedMessages ", key, this._receivedMessages[key]); + + return this._traceBuffer; + } + }; + + ClientImpl.prototype.startTrace = function() { + if (this._traceBuffer === null) { + this._traceBuffer = []; + } + this._trace("Client.startTrace", new Date(), version); + }; + + ClientImpl.prototype.stopTrace = function() { + delete this._traceBuffer; + }; + + ClientImpl.prototype._doConnect = function(wsurl) { + // When the socket is open, this client will send the CONNECT WireMessage using the saved parameters. + if (this.connectOptions.useSSL) { + var uriParts = wsurl.split(":"); + uriParts[0] = "wss"; + wsurl = uriParts.join(":"); + } + this._wsuri = wsurl; + this.connected = false; + + + + if (this.connectOptions.mqttVersion < 4) { + this.socket = new WebSocket(wsurl, ["mqttv3.1"]); + } else { + this.socket = new WebSocket(wsurl, ["mqtt"]); + } + this.socket.binaryType = "arraybuffer"; + this.socket.onopen = scope(this._on_socket_open, this); + this.socket.onmessage = scope(this._on_socket_message, this); + this.socket.onerror = scope(this._on_socket_error, this); + this.socket.onclose = scope(this._on_socket_close, this); + + this.sendPinger = new Pinger(this, this.connectOptions.keepAliveInterval); + this.receivePinger = new Pinger(this, this.connectOptions.keepAliveInterval); + if (this._connectTimeout) { + this._connectTimeout.cancel(); + this._connectTimeout = null; + } + this._connectTimeout = new Timeout(this, this.connectOptions.timeout, this._disconnected, [ERROR + .CONNECT_TIMEOUT.code, format(ERROR.CONNECT_TIMEOUT) + ]); + }; + + + // Schedule a new message to be sent over the WebSockets + // connection. CONNECT messages cause WebSocket connection + // to be started. All other messages are queued internally + // until this has happened. When WS connection starts, process + // all outstanding messages. + ClientImpl.prototype._schedule_message = function(message) { + // Add messages in fifo order to array, by adding to start + this._msg_queue.unshift(message); + // Process outstanding messages in the queue if we have an open socket, and have received CONNACK. + if (this.connected) { + this._process_queue(); + } + }; + + ClientImpl.prototype.store = function(prefix, wireMessage) { + var storedMessage = { + type: wireMessage.type, + messageIdentifier: wireMessage.messageIdentifier, + version: 1 + }; + + switch (wireMessage.type) { + case MESSAGE_TYPE.PUBLISH: + if (wireMessage.pubRecReceived) + storedMessage.pubRecReceived = true; + + // Convert the payload to a hex string. + storedMessage.payloadMessage = {}; + var hex = ""; + var messageBytes = wireMessage.payloadMessage.payloadBytes; + for (var i = 0; i < messageBytes.length; i++) { + if (messageBytes[i] <= 0xF) + hex = hex + "0" + messageBytes[i].toString(16); + else + hex = hex + messageBytes[i].toString(16); + } + storedMessage.payloadMessage.payloadHex = hex; + + storedMessage.payloadMessage.qos = wireMessage.payloadMessage.qos; + storedMessage.payloadMessage.destinationName = wireMessage.payloadMessage.destinationName; + if (wireMessage.payloadMessage.duplicate) + storedMessage.payloadMessage.duplicate = true; + if (wireMessage.payloadMessage.retained) + storedMessage.payloadMessage.retained = true; + + // Add a sequence number to sent messages. + if (prefix.indexOf("Sent:") === 0) { + if (wireMessage.sequence === undefined) + wireMessage.sequence = ++this._sequence; + storedMessage.sequence = wireMessage.sequence; + } + break; + + default: + throw Error(format(ERROR.INVALID_STORED_DATA, [prefix + this._localKey + wireMessage + .messageIdentifier, storedMessage + ])); + } + localStorage.setItem(prefix + this._localKey + wireMessage.messageIdentifier, JSON.stringify( + storedMessage)); + }; + + ClientImpl.prototype.restore = function(key) { + var value = localStorage.getItem(key); + var storedMessage = JSON.parse(value); + + var wireMessage = new WireMessage(storedMessage.type, storedMessage); + + switch (storedMessage.type) { + case MESSAGE_TYPE.PUBLISH: + // Replace the payload message with a Message object. + var hex = storedMessage.payloadMessage.payloadHex; + var buffer = new ArrayBuffer((hex.length) / 2); + var byteStream = new Uint8Array(buffer); + var i = 0; + while (hex.length >= 2) { + var x = parseInt(hex.substring(0, 2), 16); + hex = hex.substring(2, hex.length); + byteStream[i++] = x; + } + var payloadMessage = new Message(byteStream); + + payloadMessage.qos = storedMessage.payloadMessage.qos; + payloadMessage.destinationName = storedMessage.payloadMessage.destinationName; + if (storedMessage.payloadMessage.duplicate) + payloadMessage.duplicate = true; + if (storedMessage.payloadMessage.retained) + payloadMessage.retained = true; + wireMessage.payloadMessage = payloadMessage; + + break; + + default: + throw Error(format(ERROR.INVALID_STORED_DATA, [key, value])); + } + + if (key.indexOf("Sent:" + this._localKey) === 0) { + wireMessage.payloadMessage.duplicate = true; + this._sentMessages[wireMessage.messageIdentifier] = wireMessage; + } else if (key.indexOf("Received:" + this._localKey) === 0) { + this._receivedMessages[wireMessage.messageIdentifier] = wireMessage; + } + }; + + ClientImpl.prototype._process_queue = function() { + var message = null; + + // Send all queued messages down socket connection + while ((message = this._msg_queue.pop())) { + this._socket_send(message); + // Notify listeners that message was successfully sent + if (this._notify_msg_sent[message]) { + this._notify_msg_sent[message](); + delete this._notify_msg_sent[message]; + } + } + }; + + /** + * Expect an ACK response for this message. Add message to the set of in progress + * messages and set an unused identifier in this message. + * @ignore + */ + ClientImpl.prototype._requires_ack = function(wireMessage) { + var messageCount = Object.keys(this._sentMessages).length; + if (messageCount > this.maxMessageIdentifier) + throw Error("Too many messages:" + messageCount); + + while (this._sentMessages[this._message_identifier] !== undefined) { + this._message_identifier++; + } + wireMessage.messageIdentifier = this._message_identifier; + this._sentMessages[wireMessage.messageIdentifier] = wireMessage; + if (wireMessage.type === MESSAGE_TYPE.PUBLISH) { + this.store("Sent:", wireMessage); + } + if (this._message_identifier === this.maxMessageIdentifier) { + this._message_identifier = 1; + } + }; + + /** + * Called when the underlying websocket has been opened. + * @ignore + */ + ClientImpl.prototype._on_socket_open = function() { + // Create the CONNECT message object. + var wireMessage = new WireMessage(MESSAGE_TYPE.CONNECT, this.connectOptions); + wireMessage.clientId = this.clientId; + this._socket_send(wireMessage); + }; + + /** + * Called when the underlying websocket has received a complete packet. + * @ignore + */ + ClientImpl.prototype._on_socket_message = function(event) { + this._trace("Client._on_socket_message", event.data); + var messages = this._deframeMessages(event.data); + for (var i = 0; i < messages.length; i += 1) { + this._handleMessage(messages[i]); + } + }; + + ClientImpl.prototype._deframeMessages = function(data) { + var byteArray = new Uint8Array(data); + var messages = []; + if (this.receiveBuffer) { + var newData = new Uint8Array(this.receiveBuffer.length + byteArray.length); + newData.set(this.receiveBuffer); + newData.set(byteArray, this.receiveBuffer.length); + byteArray = newData; + delete this.receiveBuffer; + } + try { + var offset = 0; + while (offset < byteArray.length) { + var result = decodeMessage(byteArray, offset); + var wireMessage = result[0]; + offset = result[1]; + if (wireMessage !== null) { + messages.push(wireMessage); + } else { + break; + } + } + if (offset < byteArray.length) { + this.receiveBuffer = byteArray.subarray(offset); + } + } catch (error) { + var errorStack = ((error.hasOwnProperty("stack") == "undefined") ? error.stack.toString() : + "No Error Stack Available"); + this._disconnected(ERROR.INTERNAL_ERROR.code, format(ERROR.INTERNAL_ERROR, [error.message, + errorStack + ])); + return; + } + return messages; + }; + + ClientImpl.prototype._handleMessage = function(wireMessage) { + + this._trace("Client._handleMessage", wireMessage); + + try { + switch (wireMessage.type) { + case MESSAGE_TYPE.CONNACK: + this._connectTimeout.cancel(); + if (this._reconnectTimeout) + this._reconnectTimeout.cancel(); + + // If we have started using clean session then clear up the local state. + if (this.connectOptions.cleanSession) { + for (var key in this._sentMessages) { + var sentMessage = this._sentMessages[key]; + localStorage.removeItem("Sent:" + this._localKey + sentMessage + .messageIdentifier); + } + this._sentMessages = {}; + + for (var key in this._receivedMessages) { + var receivedMessage = this._receivedMessages[key]; + localStorage.removeItem("Received:" + this._localKey + receivedMessage + .messageIdentifier); + } + this._receivedMessages = {}; + } + // Client connected and ready for business. + if (wireMessage.returnCode === 0) { + + this.connected = true; + // Jump to the end of the list of uris and stop looking for a good host. + + if (this.connectOptions.uris) + this.hostIndex = this.connectOptions.uris.length; + + } else { + this._disconnected(ERROR.CONNACK_RETURNCODE.code, format(ERROR.CONNACK_RETURNCODE, [ + wireMessage.returnCode, CONNACK_RC[wireMessage.returnCode] + ])); + break; + } + + // Resend messages. + var sequencedMessages = []; + for (var msgId in this._sentMessages) { + if (this._sentMessages.hasOwnProperty(msgId)) + sequencedMessages.push(this._sentMessages[msgId]); + } + + // Also schedule qos 0 buffered messages if any + if (this._buffered_msg_queue.length > 0) { + var msg = null; + while ((msg = this._buffered_msg_queue.pop())) { + sequencedMessages.push(msg); + if (this.onMessageDelivered) + this._notify_msg_sent[msg] = this.onMessageDelivered(msg.payloadMessage); + } + } + + // Sort sentMessages into the original sent order. + var sequencedMessages = sequencedMessages.sort(function(a, b) { + return a.sequence - b.sequence; + }); + for (var i = 0, len = sequencedMessages.length; i < len; i++) { + var sentMessage = sequencedMessages[i]; + if (sentMessage.type == MESSAGE_TYPE.PUBLISH && sentMessage.pubRecReceived) { + var pubRelMessage = new WireMessage(MESSAGE_TYPE.PUBREL, { + messageIdentifier: sentMessage.messageIdentifier + }); + this._schedule_message(pubRelMessage); + } else { + this._schedule_message(sentMessage); + } + } + + // Execute the connectOptions.onSuccess callback if there is one. + // Will also now return if this connection was the result of an automatic + // reconnect and which URI was successfully connected to. + if (this.connectOptions.onSuccess) { + this.connectOptions.onSuccess({ + invocationContext: this.connectOptions.invocationContext + }); + } + + var reconnected = false; + if (this._reconnecting) { + reconnected = true; + this._reconnectInterval = 1; + this._reconnecting = false; + } + + // Execute the onConnected callback if there is one. + this._connected(reconnected, this._wsuri); + + // Process all queued messages now that the connection is established. + this._process_queue(); + break; + + case MESSAGE_TYPE.PUBLISH: + this._receivePublish(wireMessage); + break; + + case MESSAGE_TYPE.PUBACK: + var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; + // If this is a re flow of a PUBACK after we have restarted receivedMessage will not exist. + if (sentMessage) { + delete this._sentMessages[wireMessage.messageIdentifier]; + localStorage.removeItem("Sent:" + this._localKey + wireMessage.messageIdentifier); + if (this.onMessageDelivered) + this.onMessageDelivered(sentMessage.payloadMessage); + } + break; + + case MESSAGE_TYPE.PUBREC: + var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; + // If this is a re flow of a PUBREC after we have restarted receivedMessage will not exist. + if (sentMessage) { + sentMessage.pubRecReceived = true; + var pubRelMessage = new WireMessage(MESSAGE_TYPE.PUBREL, { + messageIdentifier: wireMessage.messageIdentifier + }); + this.store("Sent:", sentMessage); + this._schedule_message(pubRelMessage); + } + break; + + case MESSAGE_TYPE.PUBREL: + var receivedMessage = this._receivedMessages[wireMessage.messageIdentifier]; + localStorage.removeItem("Received:" + this._localKey + wireMessage.messageIdentifier); + // If this is a re flow of a PUBREL after we have restarted receivedMessage will not exist. + if (receivedMessage) { + this._receiveMessage(receivedMessage); + delete this._receivedMessages[wireMessage.messageIdentifier]; + } + // Always flow PubComp, we may have previously flowed PubComp but the server lost it and restarted. + var pubCompMessage = new WireMessage(MESSAGE_TYPE.PUBCOMP, { + messageIdentifier: wireMessage.messageIdentifier + }); + this._schedule_message(pubCompMessage); + + + break; + + case MESSAGE_TYPE.PUBCOMP: + var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; + delete this._sentMessages[wireMessage.messageIdentifier]; + localStorage.removeItem("Sent:" + this._localKey + wireMessage.messageIdentifier); + if (this.onMessageDelivered) + this.onMessageDelivered(sentMessage.payloadMessage); + break; + + case MESSAGE_TYPE.SUBACK: + var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; + if (sentMessage) { + if (sentMessage.timeOut) + sentMessage.timeOut.cancel(); + // This will need to be fixed when we add multiple topic support + if (wireMessage.returnCode[0] === 0x80) { + if (sentMessage.onFailure) { + sentMessage.onFailure(wireMessage.returnCode); + } + } else if (sentMessage.onSuccess) { + sentMessage.onSuccess(wireMessage.returnCode); + } + delete this._sentMessages[wireMessage.messageIdentifier]; + } + break; + + case MESSAGE_TYPE.UNSUBACK: + var sentMessage = this._sentMessages[wireMessage.messageIdentifier]; + if (sentMessage) { + if (sentMessage.timeOut) + sentMessage.timeOut.cancel(); + if (sentMessage.callback) { + sentMessage.callback(); + } + delete this._sentMessages[wireMessage.messageIdentifier]; + } + + break; + + case MESSAGE_TYPE.PINGRESP: + /* The sendPinger or receivePinger may have sent a ping, the receivePinger has already been reset. */ + this.sendPinger.reset(); + break; + + case MESSAGE_TYPE.DISCONNECT: + // Clients do not expect to receive disconnect packets. + this._disconnected(ERROR.INVALID_MQTT_MESSAGE_TYPE.code, format(ERROR + .INVALID_MQTT_MESSAGE_TYPE, [wireMessage.type])); + break; + + default: + this._disconnected(ERROR.INVALID_MQTT_MESSAGE_TYPE.code, format(ERROR + .INVALID_MQTT_MESSAGE_TYPE, [wireMessage.type])); + } + } catch (error) { + var errorStack = ((error.hasOwnProperty("stack") == "undefined") ? error.stack.toString() : + "No Error Stack Available"); + this._disconnected(ERROR.INTERNAL_ERROR.code, format(ERROR.INTERNAL_ERROR, [error.message, + errorStack + ])); + return; + } + }; + + /** @ignore */ + ClientImpl.prototype._on_socket_error = function(error) { + if (!this._reconnecting) { + this._disconnected(ERROR.SOCKET_ERROR.code, format(ERROR.SOCKET_ERROR, [error.data])); + } + }; + + /** @ignore */ + ClientImpl.prototype._on_socket_close = function() { + if (!this._reconnecting) { + this._disconnected(ERROR.SOCKET_CLOSE.code, format(ERROR.SOCKET_CLOSE)); + } + }; + + /** @ignore */ + ClientImpl.prototype._socket_send = function(wireMessage) { + + if (wireMessage.type == 1) { + var wireMessageMasked = this._traceMask(wireMessage, "password"); + this._trace("Client._socket_send", wireMessageMasked); + } else this._trace("Client._socket_send", wireMessage); + + this.socket.send(wireMessage.encode()); + /* We have proved to the server we are alive. */ + this.sendPinger.reset(); + }; + + /** @ignore */ + ClientImpl.prototype._receivePublish = function(wireMessage) { + switch (wireMessage.payloadMessage.qos) { + case "undefined": + case 0: + this._receiveMessage(wireMessage); + break; + + case 1: + var pubAckMessage = new WireMessage(MESSAGE_TYPE.PUBACK, { + messageIdentifier: wireMessage.messageIdentifier + }); + this._schedule_message(pubAckMessage); + this._receiveMessage(wireMessage); + break; + + case 2: + this._receivedMessages[wireMessage.messageIdentifier] = wireMessage; + this.store("Received:", wireMessage); + var pubRecMessage = new WireMessage(MESSAGE_TYPE.PUBREC, { + messageIdentifier: wireMessage.messageIdentifier + }); + this._schedule_message(pubRecMessage); + + break; + + default: + throw Error("Invaild qos=" + wireMessage.payloadMessage.qos); + } + }; + + /** @ignore */ + ClientImpl.prototype._receiveMessage = function(wireMessage) { + if (this.onMessageArrived) { + this.onMessageArrived(wireMessage.payloadMessage); + } + }; + + /** + * Client has connected. + * @param {reconnect} [boolean] indicate if this was a result of reconnect operation. + * @param {uri} [string] fully qualified WebSocket URI of the server. + */ + ClientImpl.prototype._connected = function(reconnect, uri) { + // Execute the onConnected callback if there is one. + if (this.onConnected) + this.onConnected(reconnect, uri); + }; + + /** + * Attempts to reconnect the client to the server. + * For each reconnect attempt, will double the reconnect interval + * up to 128 seconds. + */ + ClientImpl.prototype._reconnect = function() { + this._trace("Client._reconnect"); + if (!this.connected) { + this._reconnecting = true; + this.sendPinger.cancel(); + this.receivePinger.cancel(); + if (this._reconnectInterval < 128) + this._reconnectInterval = this._reconnectInterval * 2; + if (this.connectOptions.uris) { + this.hostIndex = 0; + this._doConnect(this.connectOptions.uris[0]); + } else { + this._doConnect(this.uri); + } + } + }; + + /** + * Client has disconnected either at its own request or because the server + * or network disconnected it. Remove all non-durable state. + * @param {errorCode} [number] the error number. + * @param {errorText} [string] the error text. + * @ignore + */ + ClientImpl.prototype._disconnected = function(errorCode, errorText) { + this._trace("Client._disconnected", errorCode, errorText); + + if (errorCode !== undefined && this._reconnecting) { + //Continue automatic reconnect process + this._reconnectTimeout = new Timeout(this, this._reconnectInterval, this._reconnect); + return; + } + + this.sendPinger.cancel(); + this.receivePinger.cancel(); + if (this._connectTimeout) { + this._connectTimeout.cancel(); + this._connectTimeout = null; + } + + // Clear message buffers. + this._msg_queue = []; + this._buffered_msg_queue = []; + this._notify_msg_sent = {}; + + if (this.socket) { + // Cancel all socket callbacks so that they cannot be driven again by this socket. + this.socket.onopen = null; + this.socket.onmessage = null; + this.socket.onerror = null; + this.socket.onclose = null; + if (this.socket.readyState === 1) + this.socket.close(); + delete this.socket; + } + + if (this.connectOptions.uris && this.hostIndex < this.connectOptions.uris.length - 1) { + // Try the next host. + this.hostIndex++; + this._doConnect(this.connectOptions.uris[this.hostIndex]); + } else { + + if (errorCode === undefined) { + errorCode = ERROR.OK.code; + errorText = format(ERROR.OK); + } + + // Run any application callbacks last as they may attempt to reconnect and hence create a new socket. + if (this.connected) { + this.connected = false; + // Execute the connectionLostCallback if there is one, and we were connected. + if (this.onConnectionLost) { + this.onConnectionLost({ + errorCode: errorCode, + errorMessage: errorText, + reconnect: this.connectOptions.reconnect, + uri: this._wsuri + }); + } + if (errorCode !== ERROR.OK.code && this.connectOptions.reconnect) { + // Start automatic reconnect process for the very first time since last successful connect. + this._reconnectInterval = 1; + this._reconnect(); + return; + } + } else { + // Otherwise we never had a connection, so indicate that the connect has failed. + if (this.connectOptions.mqttVersion === 4 && this.connectOptions.mqttVersionExplicit === + false) { + this._trace("Failed to connect V4, dropping back to V3"); + this.connectOptions.mqttVersion = 3; + if (this.connectOptions.uris) { + this.hostIndex = 0; + this._doConnect(this.connectOptions.uris[0]); + } else { + this._doConnect(this.uri); + } + } else if (this.connectOptions.onFailure) { + this.connectOptions.onFailure({ + invocationContext: this.connectOptions.invocationContext, + errorCode: errorCode, + errorMessage: errorText + }); + } + } + } + }; + + /** @ignore */ + ClientImpl.prototype._trace = function() { + // Pass trace message back to client's callback function + if (this.traceFunction) { + var args = Array.prototype.slice.call(arguments); + for (var i in args) { + if (typeof args[i] !== "undefined") + args.splice(i, 1, JSON.stringify(args[i])); + } + var record = args.join(""); + this.traceFunction({ + severity: "Debug", + message: record + }); + } + + //buffer style trace + if (this._traceBuffer !== null) { + for (var i = 0, max = arguments.length; i < max; i++) { + if (this._traceBuffer.length == this._MAX_TRACE_ENTRIES) { + this._traceBuffer.shift(); + } + if (i === 0) this._traceBuffer.push(arguments[i]); + else if (typeof arguments[i] === "undefined") this._traceBuffer.push(arguments[i]); + else this._traceBuffer.push(" " + JSON.stringify(arguments[i])); + } + } + }; + + /** @ignore */ + ClientImpl.prototype._traceMask = function(traceObject, masked) { + var traceObjectMasked = {}; + for (var attr in traceObject) { + if (traceObject.hasOwnProperty(attr)) { + if (attr == masked) + traceObjectMasked[attr] = "******"; + else + traceObjectMasked[attr] = traceObject[attr]; + } + } + return traceObjectMasked; + }; + + // ------------------------------------------------------------------------ + // Public Programming interface. + // ------------------------------------------------------------------------ + + /** + * The JavaScript application communicates to the server using a {@link Paho.Client} object. + *

    + * Most applications will create just one Client object and then call its connect() method, + * however applications can create more than one Client object if they wish. + * In this case the combination of host, port and clientId attributes must be different for each Client object. + *

    + * The send, subscribe and unsubscribe methods are implemented as asynchronous JavaScript methods + * (even though the underlying protocol exchange might be synchronous in nature). + * This means they signal their completion by calling back to the application, + * via Success or Failure callback functions provided by the application on the method in question. + * Such callbacks are called at most once per method invocation and do not persist beyond the lifetime + * of the script that made the invocation. + *

    + * In contrast there are some callback functions, most notably onMessageArrived, + * that are defined on the {@link Paho.Client} object. + * These may get called multiple times, and aren't directly related to specific method invocations made by the client. + * + * @name Paho.Client + * + * @constructor + * + * @param {string} host - the address of the messaging server, as a fully qualified WebSocket URI, as a DNS name or dotted decimal IP address. + * @param {number} port - the port number to connect to - only required if host is not a URI + * @param {string} path - the path on the host to connect to - only used if host is not a URI. Default: '/mqtt'. + * @param {string} clientId - the Messaging client identifier, between 1 and 23 characters in length. + * + * @property {string} host - read only the server's DNS hostname or dotted decimal IP address. + * @property {number} port - read only the server's port. + * @property {string} path - read only the server's path. + * @property {string} clientId - read only used when connecting to the server. + * @property {function} onConnectionLost - called when a connection has been lost. + * after a connect() method has succeeded. + * Establish the call back used when a connection has been lost. The connection may be + * lost because the client initiates a disconnect or because the server or network + * cause the client to be disconnected. The disconnect call back may be called without + * the connectionComplete call back being invoked if, for example the client fails to + * connect. + * A single response object parameter is passed to the onConnectionLost callback containing the following fields: + *

      + *
    1. errorCode + *
    2. errorMessage + *
    + * @property {function} onMessageDelivered - called when a message has been delivered. + * All processing that this Client will ever do has been completed. So, for example, + * in the case of a Qos=2 message sent by this client, the PubComp flow has been received from the server + * and the message has been removed from persistent storage before this callback is invoked. + * Parameters passed to the onMessageDelivered callback are: + *
      + *
    1. {@link Paho.Message} that was delivered. + *
    + * @property {function} onMessageArrived - called when a message has arrived in this Paho.client. + * Parameters passed to the onMessageArrived callback are: + *
      + *
    1. {@link Paho.Message} that has arrived. + *
    + * @property {function} onConnected - called when a connection is successfully made to the server. + * after a connect() method. + * Parameters passed to the onConnected callback are: + *
      + *
    1. reconnect (boolean) - If true, the connection was the result of a reconnect.
    2. + *
    3. URI (string) - The URI used to connect to the server.
    4. + *
    + * @property {boolean} disconnectedPublishing - if set, will enable disconnected publishing in + * in the event that the connection to the server is lost. + * @property {number} disconnectedBufferSize - Used to set the maximum number of messages that the disconnected + * buffer will hold before rejecting new messages. Default size: 5000 messages + * @property {function} trace - called whenever trace is called. TODO + */ + var Client = function(host, port, path, clientId) { + + var uri; + + if (typeof host !== "string") + throw new Error(format(ERROR.INVALID_TYPE, [typeof host, "host"])); + + if (arguments.length == 2) { + // host: must be full ws:// uri + // port: clientId + clientId = port; + uri = host; + var match = uri.match(/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/); + if (match) { + host = match[4] || match[2]; + port = parseInt(match[7]); + path = match[8]; + } else { + throw new Error(format(ERROR.INVALID_ARGUMENT, [host, "host"])); + } + } else { + if (arguments.length == 3) { + clientId = path; + path = "/mqtt"; + } + if (typeof port !== "number" || port < 0) + throw new Error(format(ERROR.INVALID_TYPE, [typeof port, "port"])); + if (typeof path !== "string") + throw new Error(format(ERROR.INVALID_TYPE, [typeof path, "path"])); + + var ipv6AddSBracket = (host.indexOf(":") !== -1 && host.slice(0, 1) !== "[" && host.slice(- + 1) !== "]"); + uri = "ws://" + (ipv6AddSBracket ? "[" + host + "]" : host) + ":" + port + path; + } + + var clientIdLength = 0; + for (var i = 0; i < clientId.length; i++) { + var charCode = clientId.charCodeAt(i); + if (0xD800 <= charCode && charCode <= 0xDBFF) { + i++; // Surrogate pair. + } + clientIdLength++; + } + if (typeof clientId !== "string" || clientIdLength > 65535) + throw new Error(format(ERROR.INVALID_ARGUMENT, [clientId, "clientId"])); + + var client = new ClientImpl(uri, host, port, path, clientId); + + //Public Properties + Object.defineProperties(this, { + "host": { + get: function() { + return host; + }, + set: function() { + throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); + } + }, + "port": { + get: function() { + return port; + }, + set: function() { + throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); + } + }, + "path": { + get: function() { + return path; + }, + set: function() { + throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); + } + }, + "uri": { + get: function() { + return uri; + }, + set: function() { + throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); + } + }, + "clientId": { + get: function() { + return client.clientId; + }, + set: function() { + throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); + } + }, + "onConnected": { + get: function() { + return client.onConnected; + }, + set: function(newOnConnected) { + if (typeof newOnConnected === "function") + client.onConnected = newOnConnected; + else + throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnConnected, + "onConnected" + ])); + } + }, + "disconnectedPublishing": { + get: function() { + return client.disconnectedPublishing; + }, + set: function(newDisconnectedPublishing) { + client.disconnectedPublishing = newDisconnectedPublishing; + } + }, + "disconnectedBufferSize": { + get: function() { + return client.disconnectedBufferSize; + }, + set: function(newDisconnectedBufferSize) { + client.disconnectedBufferSize = newDisconnectedBufferSize; + } + }, + "onConnectionLost": { + get: function() { + return client.onConnectionLost; + }, + set: function(newOnConnectionLost) { + if (typeof newOnConnectionLost === "function") + client.onConnectionLost = newOnConnectionLost; + else + throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnConnectionLost, + "onConnectionLost" + ])); + } + }, + "onMessageDelivered": { + get: function() { + return client.onMessageDelivered; + }, + set: function(newOnMessageDelivered) { + if (typeof newOnMessageDelivered === "function") + client.onMessageDelivered = newOnMessageDelivered; + else + throw new Error(format(ERROR.INVALID_TYPE, [ + typeof newOnMessageDelivered, "onMessageDelivered" + ])); + } + }, + "onMessageArrived": { + get: function() { + return client.onMessageArrived; + }, + set: function(newOnMessageArrived) { + if (typeof newOnMessageArrived === "function") + client.onMessageArrived = newOnMessageArrived; + else + throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnMessageArrived, + "onMessageArrived" + ])); + } + }, + "trace": { + get: function() { + return client.traceFunction; + }, + set: function(trace) { + if (typeof trace === "function") { + client.traceFunction = trace; + } else { + throw new Error(format(ERROR.INVALID_TYPE, [typeof trace, "onTrace"])); + } + } + }, + }); + + /** + * Connect this Messaging client to its server. + * + * @name Paho.Client#connect + * @function + * @param {object} connectOptions - Attributes used with the connection. + * @param {number} connectOptions.timeout - If the connect has not succeeded within this + * number of seconds, it is deemed to have failed. + * The default is 30 seconds. + * @param {string} connectOptions.userName - Authentication username for this connection. + * @param {string} connectOptions.password - Authentication password for this connection. + * @param {Paho.Message} connectOptions.willMessage - sent by the server when the client + * disconnects abnormally. + * @param {number} connectOptions.keepAliveInterval - the server disconnects this client if + * there is no activity for this number of seconds. + * The default value of 60 seconds is assumed if not set. + * @param {boolean} connectOptions.cleanSession - if true(default) the client and server + * persistent state is deleted on successful connect. + * @param {boolean} connectOptions.useSSL - if present and true, use an SSL Websocket connection. + * @param {object} connectOptions.invocationContext - passed to the onSuccess callback or onFailure callback. + * @param {function} connectOptions.onSuccess - called when the connect acknowledgement + * has been received from the server. + * A single response object parameter is passed to the onSuccess callback containing the following fields: + *
      + *
    1. invocationContext as passed in to the onSuccess method in the connectOptions. + *
    + * @param {function} connectOptions.onFailure - called when the connect request has failed or timed out. + * A single response object parameter is passed to the onFailure callback containing the following fields: + *
      + *
    1. invocationContext as passed in to the onFailure method in the connectOptions. + *
    2. errorCode a number indicating the nature of the error. + *
    3. errorMessage text describing the error. + *
    + * @param {array} connectOptions.hosts - If present this contains either a set of hostnames or fully qualified + * WebSocket URIs (ws://iot.eclipse.org:80/ws), that are tried in order in place + * of the host and port paramater on the construtor. The hosts are tried one at at time in order until + * one of then succeeds. + * @param {array} connectOptions.ports - If present the set of ports matching the hosts. If hosts contains URIs, this property + * is not used. + * @param {boolean} connectOptions.reconnect - Sets whether the client will automatically attempt to reconnect + * to the server if the connection is lost. + *
      + *
    • If set to false, the client will not attempt to automatically reconnect to the server in the event that the + * connection is lost.
    • + *
    • If set to true, in the event that the connection is lost, the client will attempt to reconnect to the server. + * It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay + * will double until it is at 2 minutes at which point the delay will stay at 2 minutes.
    • + *
    + * @param {number} connectOptions.mqttVersion - The version of MQTT to use to connect to the MQTT Broker. + *
      + *
    • 3 - MQTT V3.1
    • + *
    • 4 - MQTT V3.1.1
    • + *
    + * @param {boolean} connectOptions.mqttVersionExplicit - If set to true, will force the connection to use the + * selected MQTT Version or will fail to connect. + * @param {array} connectOptions.uris - If present, should contain a list of fully qualified WebSocket uris + * (e.g. ws://iot.eclipse.org:80/ws), that are tried in order in place of the host and port parameter of the construtor. + * The uris are tried one at a time in order until one of them succeeds. Do not use this in conjunction with hosts as + * the hosts array will be converted to uris and will overwrite this property. + * @throws {InvalidState} If the client is not in disconnected state. The client must have received connectionLost + * or disconnected before calling connect for a second or subsequent time. + */ + this.connect = function(connectOptions) { + connectOptions = connectOptions || {}; + validate(connectOptions, { + timeout: "number", + userName: "string", + password: "string", + willMessage: "object", + keepAliveInterval: "number", + cleanSession: "boolean", + useSSL: "boolean", + invocationContext: "object", + onSuccess: "function", + onFailure: "function", + hosts: "object", + ports: "object", + reconnect: "boolean", + mqttVersion: "number", + mqttVersionExplicit: "boolean", + uris: "object" + }); + + // If no keep alive interval is set, assume 60 seconds. + if (connectOptions.keepAliveInterval === undefined) + connectOptions.keepAliveInterval = 60; + + if (connectOptions.mqttVersion > 4 || connectOptions.mqttVersion < 3) { + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.mqttVersion, + "connectOptions.mqttVersion" + ])); + } + + if (connectOptions.mqttVersion === undefined) { + connectOptions.mqttVersionExplicit = false; + connectOptions.mqttVersion = 4; + } else { + connectOptions.mqttVersionExplicit = true; + } + + //Check that if password is set, so is username + if (connectOptions.password !== undefined && connectOptions.userName === undefined) + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.password, + "connectOptions.password" + ])); + + if (connectOptions.willMessage) { + if (!(connectOptions.willMessage instanceof Message)) + throw new Error(format(ERROR.INVALID_TYPE, [connectOptions.willMessage, + "connectOptions.willMessage" + ])); + // The will message must have a payload that can be represented as a string. + // Cause the willMessage to throw an exception if this is not the case. + connectOptions.willMessage.stringPayload = null; + + if (typeof connectOptions.willMessage.destinationName === "undefined") + throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.willMessage + .destinationName, "connectOptions.willMessage.destinationName" + ])); + } + if (typeof connectOptions.cleanSession === "undefined") + connectOptions.cleanSession = true; + if (connectOptions.hosts) { + + if (!(connectOptions.hosts instanceof Array)) + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts, + "connectOptions.hosts" + ])); + if (connectOptions.hosts.length < 1) + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts, + "connectOptions.hosts" + ])); + + var usingURIs = false; + for (var i = 0; i < connectOptions.hosts.length; i++) { + if (typeof connectOptions.hosts[i] !== "string") + throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.hosts[i], + "connectOptions.hosts[" + i + "]" + ])); + if (/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/.test(connectOptions.hosts[ + i])) { + if (i === 0) { + usingURIs = true; + } else if (!usingURIs) { + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts[i], + "connectOptions.hosts[" + i + "]" + ])); + } + } else if (usingURIs) { + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts[i], + "connectOptions.hosts[" + i + "]" + ])); + } + } + + if (!usingURIs) { + if (!connectOptions.ports) + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, + "connectOptions.ports" + ])); + if (!(connectOptions.ports instanceof Array)) + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, + "connectOptions.ports" + ])); + if (connectOptions.hosts.length !== connectOptions.ports.length) + throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, + "connectOptions.ports" + ])); + + connectOptions.uris = []; + + for (var i = 0; i < connectOptions.hosts.length; i++) { + if (typeof connectOptions.ports[i] !== "number" || connectOptions.ports[i] < 0) + throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.ports[i], + "connectOptions.ports[" + i + "]" + ])); + var host = connectOptions.hosts[i]; + var port = connectOptions.ports[i]; + + var ipv6 = (host.indexOf(":") !== -1); + uri = "ws://" + (ipv6 ? "[" + host + "]" : host) + ":" + port + path; + connectOptions.uris.push(uri); + } + } else { + connectOptions.uris = connectOptions.hosts; + } + } + + client.connect(connectOptions); + }; + + /** + * Subscribe for messages, request receipt of a copy of messages sent to the destinations described by the filter. + * + * @name Paho.Client#subscribe + * @function + * @param {string} filter describing the destinations to receive messages from. + *
    + * @param {object} subscribeOptions - used to control the subscription + * + * @param {number} subscribeOptions.qos - the maximum qos of any publications sent + * as a result of making this subscription. + * @param {object} subscribeOptions.invocationContext - passed to the onSuccess callback + * or onFailure callback. + * @param {function} subscribeOptions.onSuccess - called when the subscribe acknowledgement + * has been received from the server. + * A single response object parameter is passed to the onSuccess callback containing the following fields: + *
      + *
    1. invocationContext if set in the subscribeOptions. + *
    + * @param {function} subscribeOptions.onFailure - called when the subscribe request has failed or timed out. + * A single response object parameter is passed to the onFailure callback containing the following fields: + *
      + *
    1. invocationContext - if set in the subscribeOptions. + *
    2. errorCode - a number indicating the nature of the error. + *
    3. errorMessage - text describing the error. + *
    + * @param {number} subscribeOptions.timeout - which, if present, determines the number of + * seconds after which the onFailure calback is called. + * The presence of a timeout does not prevent the onSuccess + * callback from being called when the subscribe completes. + * @throws {InvalidState} if the client is not in connected state. + */ + this.subscribe = function(filter, subscribeOptions) { + if (typeof filter !== "string" && filter.constructor !== Array) + throw new Error("Invalid argument:" + filter); + subscribeOptions = subscribeOptions || {}; + validate(subscribeOptions, { + qos: "number", + invocationContext: "object", + onSuccess: "function", + onFailure: "function", + timeout: "number" + }); + if (subscribeOptions.timeout && !subscribeOptions.onFailure) + throw new Error("subscribeOptions.timeout specified with no onFailure callback."); + if (typeof subscribeOptions.qos !== "undefined" && !(subscribeOptions.qos === 0 || + subscribeOptions.qos === 1 || subscribeOptions.qos === 2)) + throw new Error(format(ERROR.INVALID_ARGUMENT, [subscribeOptions.qos, + "subscribeOptions.qos" + ])); + client.subscribe(filter, subscribeOptions); + }; + + /** + * Unsubscribe for messages, stop receiving messages sent to destinations described by the filter. + * + * @name Paho.Client#unsubscribe + * @function + * @param {string} filter - describing the destinations to receive messages from. + * @param {object} unsubscribeOptions - used to control the subscription + * @param {object} unsubscribeOptions.invocationContext - passed to the onSuccess callback + or onFailure callback. + * @param {function} unsubscribeOptions.onSuccess - called when the unsubscribe acknowledgement has been received from the server. + * A single response object parameter is passed to the + * onSuccess callback containing the following fields: + *
      + *
    1. invocationContext - if set in the unsubscribeOptions. + *
    + * @param {function} unsubscribeOptions.onFailure called when the unsubscribe request has failed or timed out. + * A single response object parameter is passed to the onFailure callback containing the following fields: + *
      + *
    1. invocationContext - if set in the unsubscribeOptions. + *
    2. errorCode - a number indicating the nature of the error. + *
    3. errorMessage - text describing the error. + *
    + * @param {number} unsubscribeOptions.timeout - which, if present, determines the number of seconds + * after which the onFailure callback is called. The presence of + * a timeout does not prevent the onSuccess callback from being + * called when the unsubscribe completes + * @throws {InvalidState} if the client is not in connected state. + */ + this.unsubscribe = function(filter, unsubscribeOptions) { + if (typeof filter !== "string" && filter.constructor !== Array) + throw new Error("Invalid argument:" + filter); + unsubscribeOptions = unsubscribeOptions || {}; + validate(unsubscribeOptions, { + invocationContext: "object", + onSuccess: "function", + onFailure: "function", + timeout: "number" + }); + if (unsubscribeOptions.timeout && !unsubscribeOptions.onFailure) + throw new Error("unsubscribeOptions.timeout specified with no onFailure callback."); + client.unsubscribe(filter, unsubscribeOptions); + }; + + /** + * Send a message to the consumers of the destination in the Message. + * + * @name Paho.Client#send + * @function + * @param {string|Paho.Message} topic - mandatory The name of the destination to which the message is to be sent. + * - If it is the only parameter, used as Paho.Message object. + * @param {String|ArrayBuffer} payload - The message data to be sent. + * @param {number} qos The Quality of Service used to deliver the message. + *
    + *
    0 Best effort (default). + *
    1 At least once. + *
    2 Exactly once. + *
    + * @param {Boolean} retained If true, the message is to be retained by the server and delivered + * to both current and future subscriptions. + * If false the server only delivers the message to current subscribers, this is the default for new Messages. + * A received message has the retained boolean set to true if the message was published + * with the retained boolean set to true + * and the subscrption was made after the message has been published. + * @throws {InvalidState} if the client is not connected. + */ + this.send = function(topic, payload, qos, retained) { + var message; + + if (arguments.length === 0) { + throw new Error("Invalid argument." + "length"); + + } else if (arguments.length == 1) { + + if (!(topic instanceof Message) && (typeof topic !== "string")) + throw new Error("Invalid argument:" + typeof topic); + + message = topic; + if (typeof message.destinationName === "undefined") + throw new Error(format(ERROR.INVALID_ARGUMENT, [message.destinationName, + "Message.destinationName" + ])); + client.send(message); + + } else { + //parameter checking in Message object + message = new Message(payload); + message.destinationName = topic; + if (arguments.length >= 3) + message.qos = qos; + if (arguments.length >= 4) + message.retained = retained; + client.send(message); + } + }; + + /** + * Publish a message to the consumers of the destination in the Message. + * Synonym for Paho.Mqtt.Client#send + * + * @name Paho.Client#publish + * @function + * @param {string|Paho.Message} topic - mandatory The name of the topic to which the message is to be published. + * - If it is the only parameter, used as Paho.Message object. + * @param {String|ArrayBuffer} payload - The message data to be published. + * @param {number} qos The Quality of Service used to deliver the message. + *
    + *
    0 Best effort (default). + *
    1 At least once. + *
    2 Exactly once. + *
    + * @param {Boolean} retained If true, the message is to be retained by the server and delivered + * to both current and future subscriptions. + * If false the server only delivers the message to current subscribers, this is the default for new Messages. + * A received message has the retained boolean set to true if the message was published + * with the retained boolean set to true + * and the subscrption was made after the message has been published. + * @throws {InvalidState} if the client is not connected. + */ + this.publish = function(topic, payload, qos, retained) { + var message; + + if (arguments.length === 0) { + throw new Error("Invalid argument." + "length"); + + } else if (arguments.length == 1) { + + if (!(topic instanceof Message) && (typeof topic !== "string")) + throw new Error("Invalid argument:" + typeof topic); + + message = topic; + if (typeof message.destinationName === "undefined") + throw new Error(format(ERROR.INVALID_ARGUMENT, [message.destinationName, + "Message.destinationName" + ])); + client.send(message); + + } else { + //parameter checking in Message object + message = new Message(payload); + message.destinationName = topic; + if (arguments.length >= 3) + message.qos = qos; + if (arguments.length >= 4) + message.retained = retained; + client.send(message); + } + }; + + /** + * Normal disconnect of this Messaging client from its server. + * + * @name Paho.Client#disconnect + * @function + * @throws {InvalidState} if the client is already disconnected. + */ + this.disconnect = function() { + client.disconnect(); + }; + + /** + * Get the contents of the trace log. + * + * @name Paho.Client#getTraceLog + * @function + * @return {Object[]} tracebuffer containing the time ordered trace records. + */ + this.getTraceLog = function() { + return client.getTraceLog(); + }; + + /** + * Start tracing. + * + * @name Paho.Client#startTrace + * @function + */ + this.startTrace = function() { + client.startTrace(); + }; + + /** + * Stop tracing. + * + * @name Paho.Client#stopTrace + * @function + */ + this.stopTrace = function() { + client.stopTrace(); + }; + + this.isConnected = function() { + return client.connected; + }; + }; + + /** + * An application message, sent or received. + *

    + * All attributes may be null, which implies the default values. + * + * @name Paho.Message + * @constructor + * @param {String|ArrayBuffer} payload The message data to be sent. + *

    + * @property {string} payloadString read only The payload as a string if the payload consists of valid UTF-8 characters. + * @property {ArrayBuffer} payloadBytes read only The payload as an ArrayBuffer. + *

    + * @property {string} destinationName mandatory The name of the destination to which the message is to be sent + * (for messages about to be sent) or the name of the destination from which the message has been received. + * (for messages received by the onMessage function). + *

    + * @property {number} qos The Quality of Service used to deliver the message. + *

    + *
    0 Best effort (default). + *
    1 At least once. + *
    2 Exactly once. + *
    + *

    + * @property {Boolean} retained If true, the message is to be retained by the server and delivered + * to both current and future subscriptions. + * If false the server only delivers the message to current subscribers, this is the default for new Messages. + * A received message has the retained boolean set to true if the message was published + * with the retained boolean set to true + * and the subscrption was made after the message has been published. + *

    + * @property {Boolean} duplicate read only If true, this message might be a duplicate of one which has already been received. + * This is only set on messages received from the server. + * + */ + var Message = function(newPayload) { + var payload; + if (typeof newPayload === "string" || + newPayload instanceof ArrayBuffer || + (ArrayBuffer.isView(newPayload) && !(newPayload instanceof DataView)) + ) { + payload = newPayload; + } else { + throw (format(ERROR.INVALID_ARGUMENT, [newPayload, "newPayload"])); + } + + var destinationName; + var qos = 0; + var retained = false; + var duplicate = false; + + Object.defineProperties(this, { + "payloadString": { + enumerable: true, + get: function() { + if (typeof payload === "string") + return payload; + else + return parseUTF8(payload, 0, payload.length); + } + }, + "payloadBytes": { + enumerable: true, + get: function() { + if (typeof payload === "string") { + var buffer = new ArrayBuffer(UTF8Length(payload)); + var byteStream = new Uint8Array(buffer); + stringToUTF8(payload, byteStream, 0); + + return byteStream; + } else { + return payload; + } + } + }, + "destinationName": { + enumerable: true, + get: function() { + return destinationName; + }, + set: function(newDestinationName) { + if (typeof newDestinationName === "string") + destinationName = newDestinationName; + else + throw new Error(format(ERROR.INVALID_ARGUMENT, [newDestinationName, + "newDestinationName" + ])); + } + }, + "qos": { + enumerable: true, + get: function() { + return qos; + }, + set: function(newQos) { + if (newQos === 0 || newQos === 1 || newQos === 2) + qos = newQos; + else + throw new Error("Invalid argument:" + newQos); + } + }, + "retained": { + enumerable: true, + get: function() { + return retained; + }, + set: function(newRetained) { + if (typeof newRetained === "boolean") + retained = newRetained; + else + throw new Error(format(ERROR.INVALID_ARGUMENT, [newRetained, + "newRetained" + ])); + } + }, + "topic": { + enumerable: true, + get: function() { + return destinationName; + }, + set: function(newTopic) { + destinationName = newTopic; + } + }, + "duplicate": { + enumerable: true, + get: function() { + return duplicate; + }, + set: function(newDuplicate) { + duplicate = newDuplicate; + } + } + }); + }; + + // Module contents. + return { + Client: Client, + Message: Message + }; + // eslint-disable-next-line no-nested-ternary +} \ No newline at end of file diff --git a/uni_modules/x-network-change/changelog.md b/uni_modules/x-network-change/changelog.md new file mode 100644 index 0000000..189f258 --- /dev/null +++ b/uni_modules/x-network-change/changelog.md @@ -0,0 +1,6 @@ +## 1.0.2(2025-07-25) +* 兼容原生鸿蒙 +## 1.0.1(2025-06-10) +添加isNetworkAvailable和getNetworkType +## 1.0.0(2024-08-15) +监视当前网络变化,安卓,ios,web可用。 diff --git a/uni_modules/x-network-change/package.json b/uni_modules/x-network-change/package.json new file mode 100644 index 0000000..ec89b5a --- /dev/null +++ b/uni_modules/x-network-change/package.json @@ -0,0 +1,82 @@ +{ + "id": "x-network-change", + "displayName": "x-network-change", + "version": "1.0.0", + "description": "x-network-change", + "keywords": [ + "x-network-change" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-network-change/readme.md b/uni_modules/x-network-change/readme.md new file mode 100644 index 0000000..744d591 --- /dev/null +++ b/uni_modules/x-network-change/readme.md @@ -0,0 +1,65 @@ +# x-network-change + +### 特性说明 + +用来监测网络状态变化,支持Android和iOS平台。插件会实时监听设备的网络连接状态,当网络状态发生变化时(如连接、断开等)会触发回调函数。 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### API说明 + +#### xNetChange(callback) +监听网络状态变化 + +**参数说明:** +- callback: `(connecting: boolean) => void` + - connecting: 布尔值,true表示网络已连接,false表示网络已断开 + +#### xUnNetChange() +取消网络状态监听 + +#### isNetworkAvailable() +当前是否有网络,返回 `Promise` + +#### getNetworkType() +当前网络状态类型返回,部分浏览器支持返回具体类型 `Promise ` +`export type xNetworkType = "WiFi"|"Mobile"|"WiredNetwork"|"Other"|null` + +**注意事项:** +- 不使用时,记得要取消监视,避免内存泄漏 +- 建议在页面卸载时(onUnload)调用xUnNetChange取消监听 + +### 使用示例 + +```ts +import { xNetChange, xUnNetChange,isNetworkAvailable,getNetworkType } from "@/uni_modules/x-network-change" + +// 开始监听网络状态 +xNetChange((netcon: boolean) => { + if (netcon) { + console.log("网络已连接") + // 执行网络连接后的业务逻辑 + } else { + console.log("网络已断开") + // 执行网络断开后的业务逻辑 + } +}) + +// 在页面卸载时取消监听 +onUnload(() => { + xUnNetChange() +}) + +isNetworkAvailable().then((isNetConecting:boolean)=>{ + console.log("当前网络状态:",isNetConecting) +}) +getNetworkType().then((netType)=>{ + console.log("当前网络类型:",netType) +}) + + +``` diff --git a/uni_modules/x-network-change/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-network-change/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..c74cafd --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/uni_modules/x-network-change/utssdk/app-android/config.json b/uni_modules/x-network-change/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-network-change/utssdk/app-android/index.uts b/uni_modules/x-network-change/utssdk/app-android/index.uts new file mode 100644 index 0000000..a95f661 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-android/index.uts @@ -0,0 +1,133 @@ +import Build from 'android.os.Build'; +import Context from 'android.content.Context'; +import ConnectivityManager from 'android.net.ConnectivityManager'; +import NetworkCallback from 'android.net.ConnectivityManager.NetworkCallback'; +import Network from 'android.net.Network'; +import NetworkCapabilities from 'android.net.NetworkCapabilities'; +import NetworkRequest from 'android.net.NetworkRequest'; +import NetworkInfo from "android.net.NetworkInfo"; +import {xNetworkType} from "../interface" + + +let netmarnger : ConnectivityManager | null = null; +let networkCallback : ConnectivityManager.NetworkCallback | null = null; +const context = UTSAndroid.getAppContext()!; + +//当前是否有网络。 +export function isNetworkAvailable() : Promise { + let connectivityManager : ConnectivityManager | null = context!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | null; + if (connectivityManager == null) { + return Promise.resolve(false); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + // Android 6.0及以上版本 + let network : Network | null = connectivityManager!.getActiveNetwork(); + if (network == null) { + return Promise.resolve(false); + } + + let capabilities : NetworkCapabilities | null = connectivityManager.getNetworkCapabilities(network!); + return Promise.resolve(capabilities != null && + capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && + capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)); + } else { + // Android 6.0以下版本 + let networkInfo : NetworkInfo | null = connectivityManager.getActiveNetworkInfo(); + return Promise.resolve(networkInfo != null && networkInfo.isConnected()); + } +} + + +/** + * 获取网络类型 + * @returns {Promise} "WiFi","Mobile","WiredNetwork",null网络 + */ +export function getNetworkType() : Promise { + let connectivityManager : ConnectivityManager | null = context!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | null; + if (connectivityManager == null) { + return Promise.resolve(null); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + let network : Network | null = connectivityManager!.getActiveNetwork(); + if (network == null) { + return Promise.resolve(null); + } + + let capabilities : NetworkCapabilities | null = connectivityManager.getNetworkCapabilities(network!); + if (capabilities == null) { + return Promise.resolve(null); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + return Promise.resolve("WiFi"); + } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return Promise.resolve("Mobile"); + } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + return Promise.resolve("WiredNetwork"); + } + } else { + let networkInfo : NetworkInfo | null = connectivityManager.getActiveNetworkInfo(); + if (networkInfo != null && networkInfo.isConnected()) { + let type = networkInfo.getType(); + if (type == ConnectivityManager.TYPE_WIFI) { + return Promise.resolve("WiFi"); + } else if (type == ConnectivityManager.TYPE_MOBILE) { + return Promise.resolve("Mobile"); + } else { + return Promise.resolve("WiredNetwork"); + } + } + } + + return Promise.resolve(null); +} + +@UTSJS.keepAlive +function changeByBig(call : (conecting : boolean) => void) { + netmarnger = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + class xnetworkCallback extends ConnectivityManager.NetworkCallback() { + override onAvailable(network : Network) { + super.onAvailable(network) + console.log("网络可用") + call(true) + } + override onLost(network : Network) { + super.onLost(network) + console.log("网络断开") + call(false) + } + override onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) { + super.onCapabilitiesChanged(network, networkCapabilities) + } + } + networkCallback = new xnetworkCallback() as NetworkCallback + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + netmarnger!.registerDefaultNetworkCallback(networkCallback!) + } else { + //安卓5-8 + let builder = NetworkRequest.Builder() + let networkRequest = builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build() + netmarnger!.registerNetworkCallback(networkRequest, networkCallback!) + } +} +//监听网络变化 +export function xNetChange(call : (conecting : boolean) => void) { + changeByBig(call); +} +//取消监听 +export function xUnNetChange() { + if (networkCallback != null && netmarnger != null) { + // @ts-ignore + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + netmarnger!.unregisterNetworkCallback(networkCallback!) + } else { + // @ts-ignore + let builder = NetworkRequest.Builder() + let networkRequest = builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build() + // @ts-ignore + netmarnger!.unregisterNetworkCallback(networkCallback!) + } + } + +} \ No newline at end of file diff --git a/uni_modules/x-network-change/utssdk/app-harmony/index.uts b/uni_modules/x-network-change/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..6680765 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-harmony/index.uts @@ -0,0 +1,272 @@ +import network, { NetworkResponse } from '@system.network'; +import { connection } from '@kit.NetworkKit'; +import { xNetworkType } from "../interface" +import radio from '@ohos.telephony.radio' +import { Emitter, onNativePageReady } from '@dcloudio/uni-runtime'; +import { BusinessError } from "@kit.BasicServicesKit"; + +export type OnNetworkStatusChangeCallbackResult = { + /** + * 当前是否有网络连接 + * @type boolean + */ + isConnected : boolean, + /** + * 网络类型 + */ + networkType : string +}; +export type OnNetworkStatusChangeCallback = (result : OnNetworkStatusChangeCallbackResult) => void; +export type OnNetworkStatusChange = (callback : OnNetworkStatusChangeCallback) => void; +export type OffNetworkStatusChange = (callback : (result : any) => void) => void; + + +interface IUniGetNetworkTypeEventEmitter { + on : (eventName : string, callback : Function) => void + once : (eventName : string, callback : Function) => void + off : (eventName : string, callback ?: Function) => void + emit : (eventName : string, ...args : (Object | undefined | null)[]) => void +} +const UniGetNetworkTypeEventEmitter = new Emitter() as IUniGetNetworkTypeEventEmitter +function networkGetType() { + return new Promise((resolve, reject) => { + try { + radio.getPrimarySlotId() + .then((slotId : number) => radio.getSignalInformationSync(slotId)) + .then((signalInformation : Array) => { + const data = signalInformation[0] + if (data && data.signalType) { + resolve(signalType(data.signalType)) + } else { + resolve(NetworkinfoType.NONE) + } + }) + } catch (error) { + reject(error as BusinessError) + } + }) +} + +enum NetworkinfoType { + // 网络连接状态未知 + UNKNOW = 0, + // 未连接网络 + NONE = 1, + // 有线网络 + ETHERNET = 2, + // 无线WIFI网络 + WIFI = 3, + + "2G" = 4, + "3G" = 5, + "4G" = 6, + "5G" = 7, +} + + +function signalType(resultObj : radio.NetworkType) : number { + switch (resultObj) { + case radio.NetworkType.NETWORK_TYPE_GSM: + case radio.NetworkType.NETWORK_TYPE_CDMA: + return NetworkinfoType['2G'] + case radio.NetworkType.NETWORK_TYPE_WCDMA: + case radio.NetworkType.NETWORK_TYPE_TDSCDMA: + return NetworkinfoType['3G'] + case radio.NetworkType.NETWORK_TYPE_LTE: + return NetworkinfoType['4G'] + case radio.NetworkType.NETWORK_TYPE_NR: + return NetworkinfoType['5G'] + case radio.NetworkType.NETWORK_TYPE_UNKNOWN: + return NetworkinfoType.UNKNOW + default: + return NetworkinfoType.NONE + } +} + +// 构造单例对象 +class GlobalContext { + public netList : connection.NetHandle[] = []; + public netHandle : connection.NetHandle | null = null; + private constructor() { } + private static instance : GlobalContext; + + public static getContext() : GlobalContext { + if (!GlobalContext.instance) { + GlobalContext.instance = new GlobalContext(); + } + return GlobalContext.instance; + } +} + + +//当前是否有网络。 +export function isNetworkAvailable() : Promise { + return new Promise((resolve) => { + try { + radio.getPrimarySlotId() + .then((slotId : number) => radio.getSignalInformationSync(slotId)) + .then((signalInformation : Array) => { + const data = signalInformation[0] + if (data && data.signalType) { + resolve(signalType(data.signalType) != NetworkinfoType.NONE) + } else { + resolve(false) + } + }) + } catch (error) { + resolve(false) + } + }) +} + +export function getNetworkType() : Promise { + return new Promise((resolve, reject) => { + try { + // 调用getDefaultNet方法,获取默认的数据网络(NetHandle) + connection.getDefaultNet().then((data : connection.NetHandle) => { + if (data) { + GlobalContext.getContext().netHandle = data; + // 获取netHandle对应网络的能力信息。能力信息包含了网络类型、网络具体能力等网络信息 + connection.getNetCapabilities(GlobalContext.getContext().netHandle!).then((data : connection.NetCapabilities) => { + // 获取网络类型(bearerTypes) + const bearerTypes : Set = new Set(data.bearerTypes); + const bearerTypesNum = Array.from(bearerTypes.values()); + for (const item of bearerTypesNum) { + if (item == connection.NetBearType.BEARER_CELLULAR) { + // 蜂窝网 + networkGetType().then(() => { + resolve('Mobile') + }).catch(reject) + } else if (item == connection.NetBearType.BEARER_WIFI) { + // Wi-Fi网络 + resolve('WiFi') + } else if (item == connection.NetBearType.BEARER_ETHERNET) { + // 以太网网络 + resolve('WiredNetwork') + } else { + resolve('Other') + } + } + }).catch((err : BusinessError) => { + reject(err) + }) + } + }) + } catch (error) { + reject(null) + } + + }) +} + +function invokeOnNetworkStatusChange(networkType : string) { + // UniGetNetworkTypeEventEmitter.emit( + // 'networkStatusChange', + // { + // isConnected: networkType !== NetworkinfoType[1], + // networkType: networkType.toLocaleLowerCase(), + // } as OnNetworkStatusChangeCallbackResult + // ) + + UniGetNetworkTypeEventEmitter.emit('networkStatusChange',networkType !== NetworkinfoType[1]) +} + +function getCurrentType() { + return new Promise((resolve, reject) => { + // 调用getDefaultNet方法,获取默认的数据网络(NetHandle) + connection.getDefaultNet().then((data : connection.NetHandle) => { + if (data) { + GlobalContext.getContext().netHandle = data; + // 获取netHandle对应网络的能力信息。能力信息包含了网络类型、网络具体能力等网络信息 + connection.getNetCapabilities(GlobalContext.getContext().netHandle!).then((data : connection.NetCapabilities) => { + // 获取网络类型(bearerTypes) + const bearerTypes : Set = new Set(data.bearerTypes); + const bearerTypesNum = Array.from(bearerTypes.values()); + for (const item of bearerTypesNum) { + if (item == connection.NetBearType.BEARER_CELLULAR) { + // 蜂窝网 + networkGetType().then(resolve).catch(reject) + } else if (item == connection.NetBearType.BEARER_WIFI) { + // Wi-Fi网络 + resolve(NetworkinfoType.WIFI) + } else if (item == connection.NetBearType.BEARER_ETHERNET) { + // 以太网网络 + resolve(NetworkinfoType.ETHERNET) + } else { + resolve(NetworkinfoType.UNKNOW) + } + } + }).catch((err : BusinessError) => { + reject(err) + }) + } + }) + }) +} + + + +class Network { + static netConnection : connection.NetConnection | null = null + + constructor() { + Network.netConnection = connection.createNetConnection() + } + + static ohoSubscribe() { + if (!Network.netConnection) { + Network.netConnection = connection.createNetConnection() + } + + if (Network.netConnection) { + + Network.netConnection.register((err : BusinessError) => { }) + Network.netConnection.on('netCapabilitiesChange', (capability : connection.NetCapabilityInfo) => { + const NetBearType = capability?.netCap?.bearerTypes[0] + let networkType = '' + switch (NetBearType) { + case connection.NetBearType.BEARER_CELLULAR: + getCurrentType().then((type : number) => { + invokeOnNetworkStatusChange(NetworkinfoType[type]) + }).catch(() => { + invokeOnNetworkStatusChange(NetworkinfoType[1]) + }) + return + case connection.NetBearType.BEARER_WIFI: + networkType = NetworkinfoType[3] + break + case connection.NetBearType.BEARER_ETHERNET: + networkType = NetworkinfoType[2] + break + /* case connection.NetBearType.BEARER_VPN: + networkType = 'vpn' + break */ + default: + networkType = NetworkinfoType[1] + } + invokeOnNetworkStatusChange(networkType) + + }) + Network.netConnection.on('netLost', (netLost : connection.NetHandle) => { + invokeOnNetworkStatusChange(NetworkinfoType[1]) + }) + } + } +} + +new Network() + +type CallType = (conecting : boolean) => void; +let call : CallType = (conecting : boolean) => { } +export const xNetChange = (callback : CallType) => { + call = callback; + UniGetNetworkTypeEventEmitter.on('networkStatusChange', call) +} +//取消监听 +export function xUnNetChange() { + UniGetNetworkTypeEventEmitter.off('networkStatusChange', call) +} + +onNativePageReady().then(() => { + Network.ohoSubscribe() +}) \ No newline at end of file diff --git a/uni_modules/x-network-change/utssdk/app-harmony/module.json5 b/uni_modules/x-network-change/utssdk/app-harmony/module.json5 new file mode 100644 index 0000000..89bd1b8 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-harmony/module.json5 @@ -0,0 +1,20 @@ +{ + "module": { + "name": "uni_modules__x_network_change", + "type": "har", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ], + "requestPermissions": [ + { + "name": "ohos.permission.INTERNET", + "usedScene": { + "when": "inuse" + } + }, + {"name": "ohos.permission.GET_NETWORK_INFO"} + ] + } +} diff --git a/uni_modules/x-network-change/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-network-change/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-network-change/utssdk/app-ios/config.json b/uni_modules/x-network-change/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-network-change/utssdk/app-ios/index.uts b/uni_modules/x-network-change/utssdk/app-ios/index.uts new file mode 100644 index 0000000..5dffe09 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/app-ios/index.uts @@ -0,0 +1,72 @@ +import { NWPathMonitor, NWPath, NWInterface } from 'Network'; +import { DispatchQueue } from "Dispatch" +import { xNetworkType } from "../interface" +let network = new NWPathMonitor() + +@UTSJS.keepAlive +export function xNetChange(call : (conecting : boolean) => void) { + network.pathUpdateHandler = (nwpath : NWPath) => { + if (nwpath.status == NWPath.Status.satisfied) { + DispatchQueue.main.async(execute = () : void => { + call(true) + }) + } else { + DispatchQueue.main.async(execute = () : void => { + call(false) + }) + } + } + network.start(queue = DispatchQueue.global()) +} +export function xUnNetChange() { + let network = new NWPathMonitor() + network.cancel() +} + +//当前是否有网络。 +export function isNetworkAvailable() : Promise { + return new Promise((res) => { + let network2 = new NWPathMonitor() + network2.pathUpdateHandler = (nwpath : NWPath) => { + if (nwpath.status == NWPath.Status.satisfied) { + DispatchQueue.main.async(execute = () : void => { + res(true) + }) + } else { + DispatchQueue.main.async(execute = () : void => { + res(false) + }) + } + network2.cancel() + } + network2.start(queue = DispatchQueue.global()) + }) +} + +export function getNetworkType() : Promise { + return new Promise((res) => { + let network2 = new NWPathMonitor() + network2.pathUpdateHandler = (nwpath : NWPath) => { + if (nwpath.status == NWPath.Status.satisfied) { + DispatchQueue.main.async(execute = () : void => { + if (nwpath.usesInterfaceType(NWInterface.InterfaceType.wifi)) { + res('WiFi') + } else if (nwpath.usesInterfaceType(NWInterface.InterfaceType.cellular)) { + res('Mobile') + } else if (nwpath.usesInterfaceType(NWInterface.InterfaceType.wiredEthernet)) { + res('WiredNetwork') + } else { + res('Other') + } + + }) + } else { + DispatchQueue.main.async(execute = () : void => { + res(null) + }) + } + network2.cancel() + } + network2.start(queue = DispatchQueue.global()) + }) +} \ No newline at end of file diff --git a/uni_modules/x-network-change/utssdk/interface.uts b/uni_modules/x-network-change/utssdk/interface.uts new file mode 100644 index 0000000..4d2ae20 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/interface.uts @@ -0,0 +1 @@ +export type xNetworkType = "WiFi"|"Mobile"|"WiredNetwork"|"Other"|null \ No newline at end of file diff --git a/uni_modules/x-network-change/utssdk/mp-weixin/index.uts b/uni_modules/x-network-change/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..5ab18c4 --- /dev/null +++ b/uni_modules/x-network-change/utssdk/mp-weixin/index.uts @@ -0,0 +1,55 @@ +import { xNetworkType } from "../interface" +let netSuccess : any | null = null; +let netFail : any | null = null; +let callfun = (conecting : boolean) => { } +const statChangeCall = (res : any) => { + console.log(res) + callfun(res?.isConnected ?? false) +} +export function xNetChange(call : (conecting : boolean) => void) { + callfun = call + wx.onNetworkStatusChange(statChangeCall) +} +export function xUnNetChange() { + wx.offNetworkStatusChange(statChangeCall) +} +//当前是否有网络。 +export function isNetworkAvailable() : Promise { + return new Promise((res) => { + wx.getNetworkType({ + success(res) { + const networkType = res.networkType + if (networkType === 'none') { + res(false) + } else { + res(true) + } + }, + fail(err) { + res(false) + } + }) + }) +} +//获取当前网络状态。 +export function getNetworkType() : Promise { + return new Promise((res) => { + wx.getNetworkType({ + success(res) { + const networkType = res.networkType + if (networkType === 'none') { + res(null) + } else if (networkType == 'wifi') { + res('WiFi') + } else if (['2g', '3g', '4g', '5g'].includes(networkType){ + res('Mobile') + } else { + res('Other') + } + }, + fail(err) { + res(null) + } + }) + }) +} \ No newline at end of file diff --git a/uni_modules/x-network-change/utssdk/unierror.uts b/uni_modules/x-network-change/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-network-change/utssdk/web/index.uts b/uni_modules/x-network-change/utssdk/web/index.uts new file mode 100644 index 0000000..4d3c93a --- /dev/null +++ b/uni_modules/x-network-change/utssdk/web/index.uts @@ -0,0 +1,50 @@ +import { xNetworkType } from "../interface" +let netSuccess : any = null; +let netFail : any = null; +export function xNetChange(call : (conecting : boolean) => void) { + netSuccess = () => { + call(true) + } + netFail = () => { + call(false) + } + window.addEventListener('online', netSuccess) + window.addEventListener('offline', netFail) +} +export function xUnNetChange() { + if (netSuccess) { + window.removeEventListener('online', netSuccess!) + } + if (netFail) { + window.removeEventListener('offline', netFail!) + } +} + +//当前是否有网络。 +export function isNetworkAvailable() : Promise { + return Promise.resolve(window.navigator.onLine); +} + +export function getNetworkType() : Promise { + if ('connection' in navigator) { + const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; + if (!window.navigator.onLine) { + return Promise.resolve(null); + } + if (connection?.type != undefined) { + if (connection.type == 'cellular') { + return Promise.resolve("Mobile"); + } else if (['wifi', 'wimax', 'ethernet'].includes(connection.type)) { + return Promise.resolve("Wifi"); + } else { + return Promise.resolve("Other"); + } + } else { + return Promise.resolve("Mobile"); + } + + } else { + console.log('浏览器不支持Network Information API'); + return Promise.resolve(null); + } +} \ No newline at end of file diff --git a/uni_modules/x-ocr-s/1.jpg b/uni_modules/x-ocr-s/1.jpg new file mode 100644 index 0000000..b6bb9bb Binary files /dev/null and b/uni_modules/x-ocr-s/1.jpg differ diff --git a/uni_modules/x-ocr-s/2.jpg b/uni_modules/x-ocr-s/2.jpg new file mode 100644 index 0000000..77a0eac Binary files /dev/null and b/uni_modules/x-ocr-s/2.jpg differ diff --git a/uni_modules/x-ocr-s/3.jpg b/uni_modules/x-ocr-s/3.jpg new file mode 100644 index 0000000..c68c851 Binary files /dev/null and b/uni_modules/x-ocr-s/3.jpg differ diff --git a/uni_modules/x-ocr-s/changelog.md b/uni_modules/x-ocr-s/changelog.md new file mode 100644 index 0000000..0659a7c --- /dev/null +++ b/uni_modules/x-ocr-s/changelog.md @@ -0,0 +1,20 @@ +## 1.0.8(2025-08-17) +* 兼容鸿蒙原生 +## 1.0.7(2025-02-14) +* 增加对web的支持,web使用时需要网络加载模型数据 +## 1.0.6(2024-12-18) +* ios,安卓添加本地路径识别函数localFilePathImageBuilder,可自己循环批量处理. +## 1.0.5(2024-11-01) +* 修复ios可能的兼容问题 +## 1.0.4(2024-10-31) +* ios没对齐安卓,失败不会返回回调. +## 1.0.3(2024-10-27) +升级了调用方式,使得安卓,ios用同样的方式调用,不再区别,统一使用callback,并且在回调中携带回了坐标,以便让大家通过坐标计算识别比例或者绘制位置 +.并且文本块统一为行返回(之前是文本块返回,但在源始数据中还是块和坐标) +## 1.0.2(2024-09-24) +* 各个函数追回了个参数language:string|null,可以是zh,ja,两种语言中文和日文识别。 +## 1.0.1(2024-05-04) +* 更新支持IOS端,需要IOS12.0(含)+ +## 1.0.0(2024-04-10) +* ocr文本识别,ai模型识别,离线识别。 +* tmui4.0种子用户,可免费赠送源码,无需购买 diff --git a/uni_modules/x-ocr-s/package.json b/uni_modules/x-ocr-s/package.json new file mode 100644 index 0000000..9616b1c --- /dev/null +++ b/uni_modules/x-ocr-s/package.json @@ -0,0 +1,97 @@ +{ + "id": "x-ocr-s", + "displayName": "Ocr文本识别ai模型离线本机识别无需服务端 支持ios,andriod,鸿蒙Next安卓", + "version": "1.0.8", + "description": "支持中文,日语,韩语,英语识别,支持本地,远程图片,相机相机选取识别文本", + "keywords": [ + "ocr,文本识别,tmui4.0,uts" +], + "repository": "", + "engines": { + "HBuilderX": "^3.99", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "99.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "369986563" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "本地相机/相册选取权限,需要征得同意。" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "x" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-ocr-s/readme.md b/uni_modules/x-ocr-s/readme.md new file mode 100644 index 0000000..49439f8 --- /dev/null +++ b/uni_modules/x-ocr-s/readme.md @@ -0,0 +1,156 @@ +# x-ocr-s +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +**如果需要查看效果请[下载TMUI4.0组件库应用demo](https://ext.dcloud.net.cn/plugin?id=16369),导航到原生插件栏目体验。** + +**本插件会让你的安卓应用增加大约8.7mb体积** +**本插件会让你的IOS应用增加大约38mb(估算)体积** +**web端需要网络加载模型文件,因为web无法离线,也不是调用api就是本地模型加载一次后,就不需要网络了** + +### UniApp 适配的版本 +[oc离线识别uniapp版本](https://ext.dcloud.net.cn/plugin?name=tm-ocr) + +### 功能 + +支持以下特殊的ocr文本识别。**离线识别,不需要联网** + +注意:鸿蒙使用本插件时第二参数语言类型不会起作用,它会自适应识别语言。 + +- 支持中文 +- 支持英文 +- 支持韩文 +- 支持日文 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | x | + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件。种子用户可免于购买。 + +非种子用户: + +普通授权:99元 +源码授权:299元 + +### 使用 + +如果是安卓请务必打自定义基座,如果ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。 + +安卓: + +如果你需要32位系统和模拟器x86上运行,需要自行配置打包cpu 支持类型,配置abis +需要自定义基座运行,且安卓5.0+(含5.0)以上支持 + +Ios: +同样按照官方文档配置所需CPU类型,默认是arm64 + +WEB: +请复制插件目录中的static目录到低的根目录static目录中即可。 + +### API说明 + +插件提供了三个主要的API函数用于OCR文本识别: + +#### 1. chooseImageBuilder +从相册或相机选择图片进行文字识别 + +```ts + +chooseImageBuilder( + callback: (str: string[], source: string[]) => void, + langs: string|null +) +``` + +参数说明: +- callback:识别结果回调函数 + - str: 识别出的文本数组 + - source: 包含文本位置信息的数组,每个元素为JSON字符串,格式为:`{boundingBox:[left,top,width,height], text:string}` +- langs:识别语言,可选值: + - 'zh':中文识别 + - 'ja':日文识别 + - null:默认中文zh + +#### 2. downloadUrlImageBuilder +下载网络图片进行文字识别 + +```ts + +downloadUrlImageBuilder( + url: string, + callback: (str: string[], source: string[]) => void, + langs: string|null +) +``` + +参数说明: +- url:网络图片地址 +- callback:识别结果回调函数,参数同chooseImageBuilder +- langs:识别语言,可选值同chooseImageBuilder + +#### 3. localFilePathImageBuilder +识别本地图片文件 + +```ts + +localFilePathImageBuilder( + pathfile: string, + callback: (str: string[], source: string[]) => void, + langs: string|null +) +``` + +参数说明: +- pathfile:本地图片文件路径 +- callback:识别结果回调函数,参数同chooseImageBuilder +- langs:识别语言,可选值同chooseImageBuilder + +### 使用示例 + +```ts + +import {chooseImageBuilder,downloadUrlImageBuilder,localFilePathImageBuilder} from "@/uni_modules/x-ocr-s" + +// 从相册/相机选择图片识别 +chooseImageBuilder((txt:string[], sour:string[])=>{ + // txt为识别出的文本数组 + // sour为包含位置信息的JSON字符串数组,需要JSON.parse转换 + sour.forEach(item => { + const info = JSON.parse(item) + console.log('文本:', info.text) + console.log('位置:', info.boundingBox) + }) +}, 'zh') + +// 识别网络图片 +downloadUrlImageBuilder( + 'https://example.com/test.jpg', + (txt:string[], sour:string[])=>{ + console.log('识别文本:', txt) + console.log('详细信息:', sour) + }, + 'ja' // 日文识别 +) + +// 识别本地图片 +localFilePathImageBuilder( + '/static/test.png', + (txt:string[], sour:string[])=>{ + console.log('识别文本:', txt) + console.log('详细信息:', sour) + }, + 'zh' // 中文识别 +) +``` + +### 注意事项 + +1. 识别置信度默认设置为0.50,只返回置信度大于等于0.50的识别结果 +2. 回调函数中的source参数需要通过JSON.parse解析才能获取位置信息 +3. 建议图片清晰度较高,避免模糊、反光等影响识别效果 +4. Web端首次使用需要下载模型文件,请确保网络环境良好 diff --git a/uni_modules/x-ocr-s/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-ocr-s/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..739f105 --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/uni_modules/x-ocr-s/utssdk/app-android/config.json b/uni_modules/x-ocr-s/utssdk/app-android/config.json new file mode 100644 index 0000000..32e76ff --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-android/config.json @@ -0,0 +1,11 @@ +{ + "minSdkVersion": "20", + "dependencies":[ + "com.google.mlkit:text-recognition:16.0.0", + "com.google.mlkit:text-recognition-chinese:16.0.0", + "com.google.mlkit:text-recognition-devanagari:16.0.0", + "com.google.mlkit:text-recognition-japanese:16.0.0", + "com.google.mlkit:text-recognition-korean:16.0.0" + ], + "abis": ["armeabi-v7a", "arm64-v8a"] +} \ No newline at end of file diff --git a/uni_modules/x-ocr-s/utssdk/app-android/index copy.uts b/uni_modules/x-ocr-s/utssdk/app-android/index copy.uts new file mode 100644 index 0000000..83501a7 --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-android/index copy.uts @@ -0,0 +1,260 @@ +import Text from "com.google.mlkit.vision.text.Text" +import TextRecognition from "com.google.mlkit.vision.text.TextRecognition" +import TextRecognizer from "com.google.mlkit.vision.text.TextRecognizer" +import TextRecognizerOptionsInterface from "com.google.mlkit.vision.text.TextRecognizerOptionsInterface" +import ChineseTextRecognizerOptions from "com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions" +import JapaneseTextRecognizerOptions from "com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions" + +import Context from 'android.content.Context' +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import Bitmap from "android.graphics.Bitmap" +import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner" +import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions" +import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning" +import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions" +import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback" +import Barcode from "com.google.mlkit.vision.barcode.common.Barcode" +import InputImage from "com.google.mlkit.vision.common.InputImage" +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" +import ByteBuffer from 'java.nio.ByteBuffer' +import ImageFormat from 'android.graphics.ImageFormat' + +import Vibrator from "android.os.Vibrator" + + +import ContentValues from "android.content.ContentValues" +import ContentUris from "android.content.ContentUris" +import JSONObject from "org.json.JSONObject" +import TimeZone from "java.util.TimeZone" +import Cursor from "android.database.Cursor" +import MediaStore from "android.provider.MediaStore" +import SimpleDateFormat from "java.text.SimpleDateFormat" +import Locale from "java.util.Locale" +import MediaScannerConnection from "android.media.MediaScannerConnection" + + +type callType = (list:any)=> void; + +/** + * 震动 + * @param {number} duriation 震动时间单位ms + */ +export function vibrator(duriation : number) : boolean { + try { + const context = UTSAndroid.getAppContext() as Context + let vb = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + if (vb!.hasVibrator()) { + vb!.vibrate(duriation.toLong()); + } else { + return false + } + } catch (e) { + console.error(e) + + } + return false +} + + +/** +* 从相册/相机中选取图片进行识别 +*/ +export function chooseImageBuilder(language:string|null) : Promise { + // 置信度 + let zxd = 0.50 + let local = language == null?'zh':language! + return new Promise((res, rej) => { + uni.chooseImage({ + count: 1, + success(evt : ChooseImageSuccess) { + uni.showLoading({ title: '...', mask: true }) + if (evt.tempFilePaths.length > 0) { + const imgs = evt.tempFilePaths[0] as string; + try { + const decodedPath = Uri.decode(imgs).substring(7) + const file = File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + let opts = new ChineseTextRecognizerOptions().Builder() + // if(local == 'ja'){ + // opts = new JapaneseTextRecognizerOptions().Builder() + // } + const recognizer = TextRecognition.getClient(opts.build()) as TextRecognizer; + recognizer.process(image!) + .addOnSuccessListener((TextList) => { + let str = [] as string[] + for (block in TextList.textBlocks) { + for (line in block.lines) { + // let lineText = line.text + // let lineCornerPoints = line.cornerPoints + // let lineFrame = line.boundingBox + for (element in line.elements) { + if (element.getConfidence() >= zxd) { + let elementText = element.text as string; + // let elementCornerPoints = element.cornerPoints + // let elementFrame = element.boundingBox + str.push(elementText as string) + } + } + } + } + uni.hideLoading() + vibrator(100) + res(str as string[]) + }) + .addOnFailureListener((e) => { + uni.hideLoading() + rej(["识别失败"] as string[]) + }) + + + } catch (e : IOException) { + uni.hideLoading() + rej(["图片选取失败"] as string[]) + } + } + }, + fail() { + rej(["图片选择失败"] as string[]) + } + }) + }) +} + +/** + * 提供一个远程图片地址进行识别 + */ +export function downloadUrlImageBuilder(url : string,language:string|null) : Promise { + // 置信度 + let zxd = 0.50 + let local = language == null?'zh':language! + uni.showLoading({ title: '...', mask: true }) + return new Promise((res, rej) => { + uni.downloadFile({ + url, + success(evt) { + const contentResolver = UTSAndroid.getAppContext()!.contentResolver + let decodedPath = evt.tempFilePath + if (evt.tempFilePath.indexOf('file://') > -1) { + decodedPath = Uri.decode(evt.tempFilePath).substring(7) + } + + try { + const file = File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + console.log(typeof ChineseTextRecognizerOptions) + let opts = new ChineseTextRecognizerOptions().Builder() + // if(local == 'ja'){ + // opts = new JapaneseTextRecognizerOptions().Builder() + // } + + const recognizer = TextRecognition.getClient(opts.build()) as TextRecognizer; + if (image != null) { + const result = recognizer.process(image!) + .addOnSuccessListener((TextList) => { + let str = [] as string[] + for (block in TextList.textBlocks) { + for (line in block.lines) { + // let lineText = line.text + // let lineCornerPoints = line.cornerPoints + // let lineFrame = line.boundingBox + for (element in line.elements) { + if (element.getConfidence() >= zxd) { + let elementText = element.text as string; + // let elementCornerPoints = element.cornerPoints + // let elementFrame = element.boundingBox + str.push(elementText as string) + } + } + } + } + uni.hideLoading() + vibrator(100) + res(str as string[]) + }) + .addOnFailureListener((e) => { + uni.hideLoading() + rej(["识别失败"] as string[]) + }) + } else { + uni.hideLoading() + rej(["图片下载失败"]) + } + } catch (e : IOException) { + uni.hideLoading() + rej(["图片下载失败"]) + } + + }, + fail() { + uni.hideLoading() + rej(["图片下载失败"]) + } + }) + }) +} + +/** +* 给定图片路径进行识别 +*/ +export function localFilePathImageBuilder(pathfile : string,language:string|null) : Promise { + // 置信度 + let zxd = 0.50 + let local = language == null?'zh':language! + uni.showLoading({ title: '...', mask: true }) + return new Promise((res, rej) => { + try { + let decodedPath = pathfile + if (pathfile.indexOf('file://') > -1) { + decodedPath = Uri.decode(pathfile).substring(7) + } + const file = File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + let opts = new ChineseTextRecognizerOptions().Builder() + // if(local == 'ja'){ + // opts = new JapaneseTextRecognizerOptions().Builder() + // } + const recognizer = TextRecognition.getClient(opts.build()) as TextRecognizer; + if (image != null) { + const result = recognizer.process(image!) + .addOnSuccessListener((TextList) => { + let str = [] as string[] + for (block in TextList.textBlocks) { + for (line in block.lines) { + // let lineText = line.text + // let lineCornerPoints = line.cornerPoints + // let lineFrame = line.boundingBox + for (element in line.elements) { + if (element.getConfidence() >= zxd) { + let elementText = element.text as string; + // let elementCornerPoints = element.cornerPoints + // let elementFrame = element.boundingBox + str.push(elementText as string) + } + } + } + } + uni.hideLoading() + vibrator(100) + res(str as string[]) + }) + .addOnFailureListener((e) => { + uni.hideLoading() + rej(["识别失败"] as string[]) + }) + } else { + uni.hideLoading() + rej(["图片地址解析失败"]) + } + } catch (e : IOException) { + uni.hideLoading() + rej(["图片地址解析失败"]) + } + + + }) +} + diff --git a/uni_modules/x-ocr-s/utssdk/app-android/index.uts b/uni_modules/x-ocr-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..9286ff6 --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-android/index.uts @@ -0,0 +1,258 @@ +import Text from "com.google.mlkit.vision.text.Text" +import TextRecognition from "com.google.mlkit.vision.text.TextRecognition" +import TextRecognizer from "com.google.mlkit.vision.text.TextRecognizer" +import TextRecognizerOptionsInterface from "com.google.mlkit.vision.text.TextRecognizerOptionsInterface" +import ChineseTextRecognizerOptions from "com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions" +import JapaneseTextRecognizerOptions from "com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions" + +import Context from 'android.content.Context' +import IOException from 'java.io.IOException' +import InputStream from 'java.io.InputStream' +import Uri from 'android.net.Uri'; +import File from 'java.io.File' +import Bitmap from "android.graphics.Bitmap" +import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner" +import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions" +import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning" +import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions" +import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback" +import Barcode from "com.google.mlkit.vision.barcode.common.Barcode" +import InputImage from "com.google.mlkit.vision.common.InputImage" +import Task from "com.google.android.gms.tasks.Task" +import List from "java.util.List" +import ByteBuffer from 'java.nio.ByteBuffer' +import ImageFormat from 'android.graphics.ImageFormat' + +import Vibrator from "android.os.Vibrator" + + +import ContentValues from "android.content.ContentValues" +import ContentUris from "android.content.ContentUris" +import JSONObject from "org.json.JSONObject" +import TimeZone from "java.util.TimeZone" +import Cursor from "android.database.Cursor" +import MediaStore from "android.provider.MediaStore" +import SimpleDateFormat from "java.text.SimpleDateFormat" +import Locale from "java.util.Locale" +import MediaScannerConnection from "android.media.MediaScannerConnection" +import Rect from 'android.graphics.Rect'; + + +type callType = (list:any)=> void; + +/** + * 震动 + * @param {number} duriation 震动时间单位ms + */ +export function vibrator(duriation : number) : boolean { + try { + const context = UTSAndroid.getAppContext() as Context + let vb = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + if (vb!.hasVibrator()) { + vb!.vibrate(duriation.toLong()); + } else { + return false + } + } catch (e) { + console.error(e) + + } + return false +} + + +/** +* 从相册/相机中选取图片进行识别 +* @param callback {(string[],any[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料 +* @param language {string} 需要识别的语言 zh中文,ja日文 +*/ +export function chooseImageBuilder(callback:(str:string[],source:string[])=>void,langs:string|null){ + // 置信度 + let zxd = 0.50 + + uni.chooseImage({ + count: 1, + success(evt : ChooseImageSuccess) { + uni.showLoading({ title: '...', mask: true }) + if (evt.tempFilePaths.length > 0) { + const imgs = evt.tempFilePaths[0] as string; + try { + const decodedPath = UTSAndroid.convert2AbsFullPath(imgs) + const file = new File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + + let recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build()) as TextRecognizer; + if(langs=='ja'){ + recognizer = TextRecognition.getClient(new JapaneseTextRecognizerOptions.Builder().build()) as TextRecognizer; + } + recognizer.process(image!) + .addOnSuccessListener((TextList) => { + let str = [] as string[] + let sour = [] as string[] + for (block in TextList.textBlocks) { + for (line in block.lines) { + // let lineText = line.text + // let lineCornerPoints = line.cornerPoints + // let lineFrame = line.getBoundingBox + let texts = '' + for (element in line.elements) { + if (element.getConfidence() >= zxd) { + let elementText = element.text as string; + + let elementFrame = element.getBoundingBox() + let rect = elementFrame as Rect + sour.push(JSON.stringify({boundingBox:[rect.left,rect.top,rect.width(),rect.height()],text:elementText} as UTSJSONObject)) + texts+=elementText + + } + } + if(texts!=''){ + str.push(texts) + } + } + } + uni.hideLoading() + vibrator(100) + callback(str as string[],sour as string[]) + }) + .addOnFailureListener((e) => { + + callback([] as string[],[] as string[]) + }) + + + } catch (e : IOException) { + callback([] as string[],[] as string[]) + } + } + }, + fail() { + callback([] as string[],[] as string[]) + } + }) +} + +/** +* 从相册/相机中选取图片进行识别 +* @param url {string} 图片地址. +* @param callback {(string[],any[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料 +* @param language {string} 需要识别的语言 zh中文,ja日文 +*/ +export function downloadUrlImageBuilder(url : string,callback:(str:string[],source:string[])=>void,langs:string|null) { + // 置信度 + let zxd = 0.50 + uni.downloadFile({ + url, + success(evt) { + const contentResolver = UTSAndroid.getAppContext()!.contentResolver + let decodedPath = UTSAndroid.convert2AbsFullPath(evt.tempFilePath) + + try { + const file = new File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + let recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build()) as TextRecognizer; + if(langs=='ja'){ + recognizer = TextRecognition.getClient(new JapaneseTextRecognizerOptions.Builder().build()) as TextRecognizer; + } + if (image != null) { + const result = recognizer.process(image!) + .addOnSuccessListener((TextList) => { + let str = [] as string[] + let sour = [] as string[] + for (block in TextList.textBlocks) { + for (line in block.lines) { + let texts = '' + for (element in line.elements) { + if (element.getConfidence() >= zxd) { + let elementText = element.text as string; + + let elementFrame = element.getBoundingBox() + let rect = elementFrame as Rect + sour.push(JSON.stringify({boundingBox:[rect.left,rect.top,rect.width(),rect.height()],text:elementText} as UTSJSONObject)) + texts+=elementText + + } + } + if(texts!=''){ + str.push(texts) + } + } + } + uni.hideLoading() + vibrator(100) + callback(str as string[],sour) + }) + .addOnFailureListener((e) => { + callback([] as string[],[] as string[]) + }) + } else { + callback([] as string[],[] as string[]) + } + } catch (e : IOException) { + callback([] as string[],[] as string[]) + } + + }, + fail() { + callback([] as string[],[] as string[]) + } + }) +} + + +/** +* 从相册/相机中选取图片进行识别 +* @param pathfile {string} 图片地址. +* @param callback {(string[],any[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料 +* @param language {string} 需要识别的语言 zh中文,ja日文 +*/ +export function localFilePathImageBuilder(pathfile : string,callback:(str:string[],source:string[])=>void,langs:string|null){ + // 置信度 + let zxd = 0.50 + try { + let decodedPath = UTSAndroid.convert2AbsFullPath(pathfile) + + const file = new File(decodedPath) + let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file)); + let recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build()) as TextRecognizer; + if(langs=='ja'){ + recognizer = TextRecognition.getClient(new JapaneseTextRecognizerOptions.Builder().build()) as TextRecognizer; + } + + if (image != null) { + const result = recognizer.process(image!) + .addOnSuccessListener((TextList) => { + let str = [] as string[] + let sour = [] as string[] + for (block in TextList.textBlocks) { + for (line in block.lines) { + let texts = '' + for (element in line.elements) { + if (element.getConfidence() >= zxd) { + let elementText = element.text as string; + + let elementFrame = element.getBoundingBox() + let rect = elementFrame as Rect + sour.push(JSON.stringify({boundingBox:[rect.left,rect.top,rect.width(),rect.height()],text:elementText} as UTSJSONObject)) + texts+=elementText + + } + } + if(texts!=''){ + str.push(texts) + } + } + } + callback(str as string[],sour) + }) + .addOnFailureListener((e) => { + callback([] as string[],[] as string[]) + }) + } else { + callback([] as string[],[] as string[]) + } + } catch (e : IOException) { + callback([] as string[],[] as string[]) + } +} + diff --git a/uni_modules/x-ocr-s/utssdk/app-harmony/config.json b/uni_modules/x-ocr-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..4e6675a --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_ocr_s": "./lib/x_ocr_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-ocr-s/utssdk/app-harmony/index.uts b/uni_modules/x-ocr-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..3a00b5d --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-harmony/index.uts @@ -0,0 +1,36 @@ +import { x_ocrDecode } from "x_ocr_s" + +export function chooseImageBuilder(callback : (str : string[], source : string[]) => void, langs : string | null) { + uni.chooseImage({ + count: 1, + success(evt : ChooseImageSuccess) { + uni.showLoading({ title: '', mask: true }) + if (evt.tempFilePaths.length > 0) { + const imgs = UTSHarmony.convert2AbsFullPath(evt.tempFilePaths[0] as string); + x_ocrDecode(imgs, (arg1 : string[], arg2 : string[]) => { + callback(arg1, arg2) + uni.hideLoading() + }) + } + }, + fail() { + callback([] as string[], [] as string[]) + } + }) +} + +export function downloadUrlImageBuilder(url : string,callback:(str:string[],source:string[])=>void,langs:string|null) { + uni.downloadFile({ + url, + success(evt) { + x_ocrDecode(UTSHarmony.convert2AbsFullPath(evt.tempFilePath), callback) + }, + fail() { + callback([] as string[],[] as string[]) + } + }) +} + +export function localFilePathImageBuilder(pathfile : string,callback:(str:string[],source:string[])=>void,langs:string|null){ + x_ocrDecode(UTSHarmony.convert2AbsFullPath(pathfile), callback) +} \ No newline at end of file diff --git a/uni_modules/x-ocr-s/utssdk/app-harmony/lib/x_ocr_s.har b/uni_modules/x-ocr-s/utssdk/app-harmony/lib/x_ocr_s.har new file mode 100644 index 0000000..174930a Binary files /dev/null and b/uni_modules/x-ocr-s/utssdk/app-harmony/lib/x_ocr_s.har differ diff --git a/uni_modules/x-ocr-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-ocr-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-ocr-s/utssdk/app-ios/config.json b/uni_modules/x-ocr-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..ccf40b3 --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-ios/config.json @@ -0,0 +1,17 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "GoogleMLKit/TextRecognition", + "version": "3.2.0" + }, + { + "name": "GoogleMLKit/TextRecognitionChinese", + "version": "3.2.0" + }, + { + "name": "GoogleMLKit/TextRecognitionJapanese", + "version": "3.2.0" + } + ] +} diff --git a/uni_modules/x-ocr-s/utssdk/app-ios/index.uts b/uni_modules/x-ocr-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..7a06a7e --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-ios/index.uts @@ -0,0 +1,222 @@ +import {ChineseTextRecognizerOptions,JapaneseTextRecognizerOptions,TextRecognizer,VisionImage,TextBlock,Text} from "MLKit" +import * as UIKit from "UIKit" +import { UIAlertController , UIAlertAction , UITextField,UIImage } from "UIKit" +import { UTSiOS } from "DCloudUTSFoundation" +import {String} from "Swift" +import { PHPhotoLibrary } from "Photos" +import { CGPoint , CGRect } from 'CoreFoundation'; + + +/** +* 从相册/相机中选取图片进行识别 +* @param callback {(string[],string[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料 +* @param language {string} 需要识别的语言 zh中文,ja日文 +*/ +export function chooseImageBuilder(callback:(str:string[],source:string[])=>void,langs:string|null){ + // 置信度 + let zxd = 0.50 + let local = 'zh' + if(langs=='ja'){ + local = 'ja' + } + uni.chooseImage({ + count: 1, + success:(evt : ChooseImageSuccess)=> { + uni.showLoading({title:'...',mask:true}) + let chineseOptions = new ChineseTextRecognizerOptions() + + let chineseTextRecognizer = TextRecognizer.textRecognizer(options=chineseOptions) + if(local == 'ja'){ + chineseTextRecognizer = TextRecognizer.textRecognizer(options=new JapaneseTextRecognizerOptions()) + } + if (evt.tempFilePaths.length > 0) { + let imgs = evt.tempFilePaths[0] as string; + try { + let realImgPath = UTSiOS.convert2AbsFullPath(imgs) + + let img = new UIImage(contentsOfFile = realImgPath); + if(img!=null){ + let image = new VisionImage(image = img!); + chineseTextRecognizer.process(image as VisionImage,completion=(TextList,error)=>{ + if(error!=null||TextList==null){ + uni.hideLoading() + uni.showToast({title:"失败",icon:'none'}) + return; + } + let str = [] as string[] + let sour = [] as string[] + for(block in TextList!.blocks){ + let lines = block.lines + if(lines!=null){ + for(line in lines) { + let elements = line.elements + + if(elements!=null){ + let texts = '' + for(element in elements) { + let elementText = element.text; + let rect = element.frame as CGRect + let elementFrame = [rect.origin.x,rect.origin.y,rect.size.width,rect.size.height] as number[] + sour.push(JSON.stringify({boundingBox:elementFrame,text:elementText})!) + texts+=elementText + } + if(texts!=''){ + str.push(texts) + } + } + + } + } + + } + uni.hideLoading() + callback(str as string[],sour) + }) + + } + + } catch (e) { + console.warn("图片选择失败") + uni.hideLoading() + callback([] as string[],[] as string[]) + + } + } + }, + fail() { + console.warn("图片选择失败") + uni.showToast({title:"图片选择失败",icon:'none'}) + callback([] as string[],[] as string[]) + } + }) + +} +/** +* 从相册/相机中选取图片进行识别 +* @param url {string} 图片地址. +* @param callback {(string[],string[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料 +* @param language {string} 需要识别的语言 zh中文,ja日文 +*/ +export function downloadUrlImageBuilder(url : string,callback:(str:string[],source:string[])=>void,langs:string|null){ + uni.showLoading({title:'...',mask:true}) + let local = langs == null?'zh':(langs! as string) + uni.downloadFile({ + url, + success:(evt)=> { + let chineseOptions = new ChineseTextRecognizerOptions() + let chineseTextRecognizer = TextRecognizer.textRecognizer(options=chineseOptions) + + if(local == 'ja'){ + chineseTextRecognizer = TextRecognizer.textRecognizer(options=new JapaneseTextRecognizerOptions()) + } + let imgs = evt.tempFilePath as string; + + try { + let realImgPath = UTSiOS.convert2AbsFullPath(imgs) + let img = new UIImage(contentsOfFile = realImgPath); + + if(img!=null){ + let image = new VisionImage(image = img!); + chineseTextRecognizer.process(image as VisionImage,completion=(TextList,error)=>{ + if(error!=null||TextList==null){ + uni.hideLoading() + uni.showToast({title:"失败",icon:'none'}) + return; + } + let str = [] as string[] + let sour = [] as string[] + for(block in TextList!.blocks){ + let lines = block.lines + if(lines!=null){ + for(line in lines) { + let elements = line.elements + if(elements!=null){ + let texts = '' + for(element in elements) { + let elementText = element.text; + let rect = element.frame as CGRect + let elementFrame = [rect.origin.x,rect.origin.y,rect.size.width,rect.size.height] as number[] + sour.push(JSON.stringify({boundingBox:elementFrame,text:elementText})!) + + texts+=elementText + } + if(texts!=''){ + str.push(texts) + } + } + + } + } + + } + uni.hideLoading() + callback(str as string[],sour) + }) + + } + + } catch (e) { + console.warn("下载失败") + uni.hideLoading() + uni.showToast({title:"下载失败",icon:'none'}) + callback([] as string[],[] as string[]) + } + + }, + fail() { + uni.hideLoading() + uni.showToast({title:"下载失败",icon:'none'}) + callback([] as string[],[] as string[]) + } + }) +} +export function localFilePathImageBuilder(pathfile : string,callback:(str:string[],source:string[])=>void,langs:string|null){ + let local = langs == null?'zh':(langs! as string) + let chineseOptions = new ChineseTextRecognizerOptions() + let chineseTextRecognizer = TextRecognizer.textRecognizer(options=chineseOptions) + + if(local == 'ja'){ + chineseTextRecognizer = TextRecognizer.textRecognizer(options=new JapaneseTextRecognizerOptions()) + } + let realImgPath = UTSiOS.convert2AbsFullPath(pathfile) + let img = new UIImage(contentsOfFile = realImgPath); + + if(img!=null){ + let image = new VisionImage(image = img!); + chineseTextRecognizer.process(image as VisionImage,completion=(TextList,error)=>{ + if(error!=null||TextList==null){ + callback([] as string[],[] as string[]) + return; + } + let str = [] as string[] + let sour = [] as string[] + for(block in TextList!.blocks){ + let lines = block.lines + if(lines!=null){ + for(line in lines) { + let elements = line.elements + if(elements!=null){ + let texts = '' + for(element in elements) { + let elementText = element.text; + let rect = element.frame as CGRect + let elementFrame = [rect.origin.x,rect.origin.y,rect.size.width,rect.size.height] as number[] + sour.push(JSON.stringify({boundingBox:elementFrame,text:elementText})!) + + texts+=elementText + } + if(texts!=''){ + str.push(texts) + } + } + + } + } + + } + callback(str as string[],sour) + }) + + } + +} diff --git a/uni_modules/x-ocr-s/utssdk/app-ios/info.plist b/uni_modules/x-ocr-s/utssdk/app-ios/info.plist new file mode 100644 index 0000000..d4574d6 --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/app-ios/info.plist @@ -0,0 +1,8 @@ + + + + + NSPhotoLibraryUsageDescription + 读取您的相册图片,用来识别图片中的文字功能,如果拒绝将无法使用相关识别功能. + + \ No newline at end of file diff --git a/uni_modules/x-ocr-s/utssdk/interface.uts b/uni_modules/x-ocr-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-ocr-s/utssdk/unierror.uts b/uni_modules/x-ocr-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-ocr-s/utssdk/web/index.uts b/uni_modules/x-ocr-s/utssdk/web/index.uts new file mode 100644 index 0000000..ff3d536 --- /dev/null +++ b/uni_modules/x-ocr-s/utssdk/web/index.uts @@ -0,0 +1,103 @@ +async function loadScript(url) { + return new Promise(res=>{ + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = url; + + // 当脚本加载完成后,执行回调 + script.onload = function() { + res() + }; + + // 处理旧版浏览器的onreadystatechange事件 + script.onreadystatechange = function() { + if (this.readyState === 'loaded' || this.readyState === 'complete') { + script.onload(); + } + }; + + // 将脚本添加到head中,开始加载 + document.head.appendChild(script); + }) +} + +async function loadScripts(scripts) { + await (async function loadNextScript(i) { + if (i < scripts.length) { + await loadScript(scripts[i]); + await loadNextScript(i + 1) + } + })(0); + +} +let ocr = window?.paddlejs?.ocr??null; +let jsFiles = [ + '/static/tmui4xLibs/lib/ocrLib.js' +]; +const decoderText =async (imgpath:string,callback)=>{ + if(!window?.paddlejs){ + await loadScripts(jsFiles) + ocr = paddlejs.ocr + await ocr.init() + } + let img = new Image() + img.src = imgpath + img.onload = async function(){ + const canvas = document.createElement('canvas') + canvas.width = 800; + canvas.height = 800 + const res = await ocr.recognize(img, { canvas }); + let texts = res.text + let bounds = [] + for(let i=0;i void, langs : string | null) { + + uni.chooseImage({ + count: 1, + success:async (evt : ChooseImageSuccess)=> { + uni.showLoading({title:'...',mask:true}) + if (evt.tempFilePaths.length > 0) { + let imgpath = evt.tempFilePaths[0] as string; + try { + await decoderText(imgpath,callback) + } catch (error) { + console.error(error) + callback([] as string[],[] as string[]) + } + } + uni.hideLoading() + }, + fail() { + console.warn("图片选择失败") + callback([] as string[],[] as string[]) + } + }) + + +} +export async function downloadUrlImageBuilder(url : string, callback : (str : string[], source : string[]) => void, langs : string | null) { + uni.showLoading({title:'...',mask:true}) + try { + await decoderText(url,callback) + } catch (error) { + console.error(error) + callback([] as string[],[] as string[]) + } + uni.hideLoading() +} +export async function localFilePathImageBuilder(pathfile : string, callback : (str : string[], source : string[]) => void, langs : string | null) { + downloadUrlImageBuilder(pathfile,callback) +} \ No newline at end of file diff --git a/uni_modules/x-openweb/changelog.md b/uni_modules/x-openweb/changelog.md new file mode 100644 index 0000000..68f535c --- /dev/null +++ b/uni_modules/x-openweb/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2025-07-25) +* 兼容原生鸿蒙 +## 1.0.2(2025-03-15) +* 兼容ios16+ +## 1.0.1(2025-02-10) +* 兼容微信 +## 1.0.0(2024-08-24) +首次发布 diff --git a/uni_modules/x-openweb/package.json b/uni_modules/x-openweb/package.json new file mode 100644 index 0000000..933948c --- /dev/null +++ b/uni_modules/x-openweb/package.json @@ -0,0 +1,97 @@ +{ + "id": "x-openweb", + "displayName": "x-openweb", + "version": "1.0.1", + "description": "x-openweb", + "keywords": [ + "x-openweb" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "^3.1.0", + "uni-app-x": "^3.1.0" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "", + "darkmode": "-", + "i18n": "-", + "widescreen": "-" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "-", + "aliyun": "-", + "alipay": "-" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-openweb/readme.md b/uni_modules/x-openweb/readme.md new file mode 100644 index 0000000..f84c8d5 --- /dev/null +++ b/uni_modules/x-openweb/readme.md @@ -0,0 +1,27 @@ +# x-openweb +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +应用app打开外链或者h5打开链接使用. +微信使用的是webview,因为你的小程序需要企业帐号权限,个人小程序无法使用。 + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 使用 + +如果是安卓请务必打自定义基座,如果ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。 + +```ts + +import {openWeb} from "@/uni_modules/x-openweb" +openWeb(url) + +``` \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/app-android/config.json b/uni_modules/x-openweb/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-openweb/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/app-android/index.uts b/uni_modules/x-openweb/utssdk/app-android/index.uts new file mode 100644 index 0000000..4dc49ab --- /dev/null +++ b/uni_modules/x-openweb/utssdk/app-android/index.uts @@ -0,0 +1,8 @@ +import Intent from 'android.content.Intent'; +import Uri from 'android.net.Uri'; +import Activity from 'android.app.Activity'; +export function openWeb(url : string) { + let intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)) + let ac = UTSAndroid.getUniActivity() as Activity + ac.startActivity(intent) +} \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/app-harmony/config.json b/uni_modules/x-openweb/utssdk/app-harmony/config.json new file mode 100644 index 0000000..6df5a0e --- /dev/null +++ b/uni_modules/x-openweb/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_library_s": "./lib/x_library_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/app-harmony/index.uts b/uni_modules/x-openweb/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..b8ecc7f --- /dev/null +++ b/uni_modules/x-openweb/utssdk/app-harmony/index.uts @@ -0,0 +1,10 @@ +import { x_openweb } from "x_library_s"; +import { BusinessError } from "@kit.BasicServicesKit"; + +export function openWeb(url : string) { + const context = UTSHarmony.getCurrentWindow()!.getUIContext(); + x_openweb(context,url) + .catch((error:boolean)=>{ + console.error("TMUI","打开失败") + }) +} \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/app-harmony/lib/x_library_s.har b/uni_modules/x-openweb/utssdk/app-harmony/lib/x_library_s.har new file mode 100644 index 0000000..2562540 Binary files /dev/null and b/uni_modules/x-openweb/utssdk/app-harmony/lib/x_library_s.har differ diff --git a/uni_modules/x-openweb/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-openweb/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-openweb/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-openweb/utssdk/app-ios/config.json b/uni_modules/x-openweb/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-openweb/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-openweb/utssdk/app-ios/index.uts b/uni_modules/x-openweb/utssdk/app-ios/index.uts new file mode 100644 index 0000000..a24a2f7 --- /dev/null +++ b/uni_modules/x-openweb/utssdk/app-ios/index.uts @@ -0,0 +1,16 @@ +import { URL } from 'Foundation'; +import { UIApplication } from 'UIKit'; +export function openWeb(url : string) { + let href = new URL(string = url) + + + if (UTSiOS.available("iOS 16.0, *")) { + if (UIApplication.shared.canOpenURL(href!)) { + UIApplication.shared.open(href!, options= new Map(), completionHandler= nil) + } + }else{ + if (UIApplication.shared.canOpenURL(href!)) { + UIApplication.shared.openURL(href!) + } + } +} \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/interface.uts b/uni_modules/x-openweb/utssdk/interface.uts new file mode 100644 index 0000000..6200866 --- /dev/null +++ b/uni_modules/x-openweb/utssdk/interface.uts @@ -0,0 +1,45 @@ +/** + * interface.uts + * uts插件接口定义文件,按规范定义接口文件可以在HBuilderX中更好的做到语法提示 + */ + +/** + * myApi 异步函数的参数,在type里定义函数需要的参数以及api成功、失败的相关回调函数。 + */ +export type MyApiOptions = { + paramA : boolean + success ?: (res : MyApiResult) => void + fail ?: (res : MyApiFail) => void + complete ?: (res : any) => void +} + +/** + * 函数返回结果 + * 可以是void, 基本数据类型,自定义type, 或者其他类型。 + * [可选实现] + */ +export type MyApiResult = { + fieldA : number, + fieldB : boolean, + fieldC : string +} + +/** + * 错误码 + * 根据uni错误码规范要求,建议错误码以90开头,以下是错误码示例: + * - 9010001 错误信息1 + * - 9010002 错误信息2 + */ +export type MyApiErrorCode = 9010001 | 9010002; +/** + * myApi 的错误回调参数 + */ +export interface MyApiFail extends IUniError { + errCode : MyApiErrorCode +}; + +/* 异步函数定义 */ +export type MyApi = (options : MyApiOptions) => void + +/* 同步函数定义 */ +export type MyApiSync = (paramA : boolean) => MyApiResult \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/mp-weixin/index.uts b/uni_modules/x-openweb/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..0860ce8 --- /dev/null +++ b/uni_modules/x-openweb/utssdk/mp-weixin/index.uts @@ -0,0 +1,4 @@ + +export function openWeb(url : string) { + wx.openUrl ({ url:url, complete: console.log } ) +} \ No newline at end of file diff --git a/uni_modules/x-openweb/utssdk/unierror.uts b/uni_modules/x-openweb/utssdk/unierror.uts new file mode 100644 index 0000000..ee086ef --- /dev/null +++ b/uni_modules/x-openweb/utssdk/unierror.uts @@ -0,0 +1,39 @@ +/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */ +import { MyApiErrorCode, MyApiFail } from "./interface.uts" +/** + * 错误主题 + * 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。 + * [可选实现] + */ +export const UniErrorSubject = 'uts-api'; + + +/** + * 错误信息 + * @UniError + * [可选实现] + */ +export const MyAPIErrors : Map = new Map([ + /** + * 错误码及对应的错误信息 + */ + [9010001, 'custom error mseeage1'], + [9010002, 'custom error mseeage2'], +]); + + +/** + * 错误对象实现 + */ +export class MyApiFailImpl extends UniError implements MyApiFail { + + /** + * 错误对象构造函数 + */ + constructor(errCode : MyApiErrorCode) { + super(); + this.errSubject = UniErrorSubject; + this.errCode = errCode; + this.errMsg = MyAPIErrors.get(errCode) ?? ""; + } +} diff --git a/uni_modules/x-openweb/utssdk/web/index.uts b/uni_modules/x-openweb/utssdk/web/index.uts new file mode 100644 index 0000000..121b3d1 --- /dev/null +++ b/uni_modules/x-openweb/utssdk/web/index.uts @@ -0,0 +1,4 @@ + +export function openWeb(url : string) { + location.href = url; +} \ No newline at end of file diff --git a/uni_modules/x-runnable-s/changelog.md b/uni_modules/x-runnable-s/changelog.md new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-runnable-s/package.json b/uni_modules/x-runnable-s/package.json new file mode 100644 index 0000000..d1992ee --- /dev/null +++ b/uni_modules/x-runnable-s/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-runnable-s", + "displayName": "x-runnable-s", + "version": "1.0.0", + "description": "x-runnable-s", + "keywords": [ + "x-runnable-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-runnable-s/readme.md b/uni_modules/x-runnable-s/readme.md new file mode 100644 index 0000000..0d56a2f --- /dev/null +++ b/uni_modules/x-runnable-s/readme.md @@ -0,0 +1,8 @@ +# x-runnable-s +### 开发文档 +[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html) +[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html) +[UTS uni-app兼容模式组件](https://uniapp.dcloud.net.cn/plugin/uts-component.html) +[UTS 标准模式组件](https://doc.dcloud.net.cn/uni-app-x/plugin/uts-vue-component.html) +[Hello UTS](https://gitcode.net/dcloud/hello-uts) + diff --git a/uni_modules/x-runnable-s/utssdk/app-android/config.json b/uni_modules/x-runnable-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-runnable-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-runnable-s/utssdk/app-android/index.uts b/uni_modules/x-runnable-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..550959e --- /dev/null +++ b/uni_modules/x-runnable-s/utssdk/app-android/index.uts @@ -0,0 +1,23 @@ + +export function runWorker(callback : () => any | null, resultCallback : (msg : any | null) => void) { + class IntentRunable extends Runnable { + dataResult:any|null; + constructor(data:any|null){ + super() + this.dataResult = data; + } + override run() { + resultCallback(this.dataResult) + } + } + + UTSAndroid.getDispatcher("io").async(function(_){ + let data:any|null = callback(); + UTSAndroid.getUniActivity()!.runOnUiThread(new IntentRunable(data)) + },null) +} + + + + + diff --git a/uni_modules/x-runnable-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-runnable-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-runnable-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-runnable-s/utssdk/app-ios/config.json b/uni_modules/x-runnable-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-runnable-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-runnable-s/utssdk/app-ios/index.uts b/uni_modules/x-runnable-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..6112982 --- /dev/null +++ b/uni_modules/x-runnable-s/utssdk/app-ios/index.uts @@ -0,0 +1,71 @@ + +import { DispatchQoS, DispatchConcurrentQueue, Operation, OperationQueue, Thread,DispatchTime } from "Foundation" +// Operation +class newThreadClassBytmui extends Operation { + task : () => any | null + result : any | null + init(@escaping callback : () => any | null) { + this.task = callback + super.init() + } + + override main() { + this.result = this.task() + } +} +/** ios不支持直接传递函数进行多任务直接返回结果 */ +export function runWorker(callback : () => any | null, resultCallback : (msg : any | null) => void) { + resultCallback(callback) + // DispatchQueue.global().asyncAfter(deadline = DispatchTime.now(),execute = ()=>{ + // callback() + // }) + + // let callcalc = ():Promise =>{ + // return new Promise((res)=>{ + // setTimeout(function() { + // res(callback()) + // }, 1500); + // }) + // }; + // Thread.detachNewThread(()=>{ + // callcalc().then((result:any|null)=>{ + // console.log(result,'---') + // DispatchQueue.main.async(execute = () : void => { + // console.log(result,'***') + // resultCallback(result) + // }) + // }) + + // }) + + // let thred = new Thread(block = () => { + // let data : any | null = callback(); + // console.log(data) + // // DispatchQueue.main.async(execute = () : void => { + // // console.log(data) + // // }) + // }) + // thred.isMainThread = true; + // thred.start() + // OperationQueue + // let workerQueue = new OperationQueue() + // workerQueue.maxConcurrentOperationCount = 30 + // let worker = new newThreadClassBytmui(callback = callback) + // worker.completionBlock = ()=>{ + + // DispatchQueue.main.async(execute = () : void => { + // console.log(worker.result) + // }) + // } + // workerQueue.addOperation(worker) + // 在后台线程执行 + // DispatchQueue(label = "xtm.omg.td2", qos = DispatchQoS.background, attributes = DispatchQueue.Attributes.concurrent) + // .async(execute = () : void => { + // let data : any | null = callback(); + // resultCallback(data) + // // DispatchQueue.main.async(execute = () : void => { + + // // }) + // }) + +} \ No newline at end of file diff --git a/uni_modules/x-runnable-s/utssdk/interface.uts b/uni_modules/x-runnable-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-runnable-s/utssdk/unierror.uts b/uni_modules/x-runnable-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-runnable-s/utssdk/web/index.uts b/uni_modules/x-runnable-s/utssdk/web/index.uts new file mode 100644 index 0000000..ed56046 --- /dev/null +++ b/uni_modules/x-runnable-s/utssdk/web/index.uts @@ -0,0 +1,44 @@ +// 将函数转换为 Worker +function createWorker(workerFunction) { + // 将函数转换为字符串 + const workerCode = ` + const result = (${workerFunction.toString()})(); + self.postMessage(result); + `; + + // 创建 Blob + const blob = new Blob([workerCode], { type: 'application/javascript' }); + + // 创建 URL + const workerUrl = URL.createObjectURL(blob); + + // 创建 Worker + const worker = new Worker(workerUrl); + + // 清理 URL + worker.addEventListener('message', () => { + URL.revokeObjectURL(workerUrl); + }); + + return worker; +} + + + +export function runWorker(callback : () => any | null, resultCallback : (msg : any | null) => void) { + // 创建 Worker + const worker = createWorker(callback); + + // 接收结果 + worker.onmessage = (event) => { + resultCallback(event.data) + // 删除旧的worder + worker.postMessage('remove') + }; + + // 错误处理 + worker.onerror = (error) => { + console.error('Worker error:', error); + }; + +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/changelog.md b/uni_modules/x-runstart-logo/changelog.md new file mode 100644 index 0000000..b0346d6 --- /dev/null +++ b/uni_modules/x-runstart-logo/changelog.md @@ -0,0 +1,6 @@ +## 1.0.2(2025-08-17) +* 兼容原生鸿蒙 +## 1.0.1(2024-09-13) +* ios端将弹层注入到了app根节点.这样不管跳转到哪个页面弹层始终在最前面. +## 1.0.0(2024-08-06) +启动界面展示,可以配合我的另一个插件xmodals来达到隐私协议的展现。 diff --git a/uni_modules/x-runstart-logo/package.json b/uni_modules/x-runstart-logo/package.json new file mode 100644 index 0000000..278981b --- /dev/null +++ b/uni_modules/x-runstart-logo/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-runstart-logo", + "displayName": "TM-UI 4.0全屏启动界面展示,可在appvue中启动覆盖界面以达到启动Logo展示的定制", + "version": "1.0.2", + "description": "可以定制自己的启动展示界面在启动时展示可以覆盖启动后的界面", + "keywords": [ + "tmui,uts,原生插件" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "1.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "x" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/readme.md b/uni_modules/x-runstart-logo/readme.md new file mode 100644 index 0000000..d5ba42f --- /dev/null +++ b/uni_modules/x-runstart-logo/readme.md @@ -0,0 +1,105 @@ +# x-runstart-logo +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +设置应用启动时的界面,暂不能设置背景图,只可设置logo图放到static目录即可. + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | x | + +### 使用 + +如果是uniapp应用需要自定基座,uniappx不需要定义基座,但win开发ios时需要 +如果是mac开发uniappx不需要基座 + +**使用时请在app.vue中onLaunch内直接执行方法显示,建议配合xmodals使用.** + +### 注意 +经过测试,在ios端,注入后,可以覆盖任意页面,就是你页面跳转不同页面也没关系,始终会覆盖所有页面. + +但在安卓端因为版本不同需要不同的权限,还可能导致应用无法审核上架到googleplay中,因此我不打算采用特殊方法实现所有页面(显示时,你又跳转了页面) +因此安卓要实现ios那样的功能我的建议是如下: + +安卓可以自己使用一个mins混淆到onLoad中这样初始运行时不管跳转到哪个页面都显示这个弹层并覆盖页面.当你确实要关闭时当前弹层.并写入本地值. +然后在onShow中读取此值判断已弹出的层(就是页面被打开过的层,没执行过当然不需要关闭了) + +下面是一个示例. + +```ts +import { XRUN_START_LOGO_OPTS, showRunLogo, hideRunLogo } from "@/uni_modules/x-runstart-logo" +import { showModal, X_MODAL_TYPE } from "@/uni_modules/x-modal-s" + +let tonyixie = uni.getStorageSync('xTmui4.0Xieyi') +let imgsrc = 'logo.png' + +showRunLogo({ + bgColor: '#006deb', + logo: imgsrc, + width: 60, + height: 60, + logoPadding: 20, + round: 14, + logoBgColor: '#ffffff', + rightText: 'tmui4.0x / 2024 by tmzdy', + fontSize: 11, + fontColor: '#ffffff' +} as XRUN_START_LOGO_OPTS) + +if (tonyixie != 'true') { + showModal({ + title: "隐私政策", content: "我同意《TMUIX4.0使用协议》我确认我使用的是正版tmuix4.0组件及附带插件软件,并承担相应法律风险,同意请点我同意,不同意请点不同意终止访问.", + cancelText: '不同意', + confirmText: "我同意", + clickMaskClose:false, + confirm() { + uni.setStorageSync('xTmui4.0Xieyi', 'true') + setTimeout(function () { + hideRunLogo() + }, 1000); + }, + cancel() { + + // #ifdef APP-ANDROID + uni.exit() + // #endif + + } + } as X_MODAL_TYPE) +} else { + hideRunLogo() +} + +``` +**类型参考** + +```ts +export type XRUN_START_LOGO_OPTS = { + /** 启动界面背景色,不能使用颜色名称 */ + bgColor:string, + /** logo图片,放到static目录,也可以是网络图片地址 */ + logo:string, + /** logo宽 */ + width:number, + /** logo高 */ + height:number, + /** logo容器圆角 */ + round:number, + /** logo容器背景,不能使用颜色名称 */ + logoBgColor:string, + /** logo下方文字 */ + rightText:string, + /** 文字字号 */ + fontSize:number, + /** 文字颜色,不能使用颜色名称 */ + fontColor:string, + /** logo容器的padding */ + logoPadding:number +} +``` \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/sample.jpg b/uni_modules/x-runstart-logo/sample.jpg new file mode 100644 index 0000000..0a25874 Binary files /dev/null and b/uni_modules/x-runstart-logo/sample.jpg differ diff --git a/uni_modules/x-runstart-logo/utssdk/app-android/assets/logo.png b/uni_modules/x-runstart-logo/utssdk/app-android/assets/logo.png new file mode 100644 index 0000000..dd6f116 Binary files /dev/null and b/uni_modules/x-runstart-logo/utssdk/app-android/assets/logo.png differ diff --git a/uni_modules/x-runstart-logo/utssdk/app-android/config.json b/uni_modules/x-runstart-logo/utssdk/app-android/config.json new file mode 100644 index 0000000..d08ff53 --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/app-android/config.json @@ -0,0 +1,6 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "com.facebook.fresco:drawee:3.1.3" + ] +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/utssdk/app-android/index.uts b/uni_modules/x-runstart-logo/utssdk/app-android/index.uts new file mode 100644 index 0000000..2751e78 --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/app-android/index.uts @@ -0,0 +1,158 @@ +import LinearLayout from 'android.widget.LinearLayout'; +import Context from 'android.content.Context' +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import { XRUN_START_LOGO_OPTS, RGBA } from "../interface.uts" +import Color from 'android.graphics.Color'; +import Gravity from 'android.view.Gravity'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable'; +import TextView from 'android.widget.TextView'; +import Typeface from 'android.graphics.Typeface'; +import TextUtils from 'android.text.TextUtils'; +import Uri from 'android.net.Uri'; +import ObjectAnimator from 'android.animation.ObjectAnimator'; +import ValueAnimator from 'android.animation.ValueAnimator'; +import TimeInterpolator from 'android.animation.TimeInterpolator'; +import MotionEvent from 'android.view.MotionEvent'; +import { hexToRgb } from "../libs/color.uts" +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; +import ScrollView from 'android.widget.ScrollView'; +import FrameLayout from 'android.widget.FrameLayout'; + +import Fresco from 'com.facebook.fresco.Fresco'; +// import DraweeController from 'com.facebook.drawee.interfaces.DraweeController'; +import SimpleDraweeView from 'com.facebook.drawee.view.SimpleDraweeView'; +import File from 'java.io.File'; +import WindowManager from 'android.view.WindowManager'; +import WindowManagerWrapper from 'com.dcloud.android.widget.toast.SafeToastContext.WindowManagerWrapper'; +import Build from 'android.os.Build'; +import BitmapFactory from "android.graphics.BitmapFactory"; +import Bitmap from 'android.graphics.Bitmap'; +import ImageView from 'android.widget.ImageView'; +// import ImageRequest from 'com.facebook.imagepipeline.request.ImageRequest'; +// import ImageRequestBuilder from 'com.facebook.imagepipeline.request.ImageRequestBuilder'; + + +let maskerDom : null | RelativeLayout = null; +let maskDomId = 686 +let tid = 0 +let isClsoing = false +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} + +export function hideRunLogo() { + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + let mk = decorView.findViewById((maskDomId).toInt()) + if (mk != null) { + decorView.removeView(mk) + } +} +function rgbToColorNumber(rgba : RGBA) : Int { + return Color.argb((rgba.a * 255).toInt(), rgba!.r.toInt(), rgba!.g.toInt(), rgba!.b.toInt()) +} + +export function showRunLogo(opts : XRUN_START_LOGO_OPTS) { + + const context = UTSAndroid.getAppContext()! as Context + + let win = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager; + + + + + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + let config : XRUN_START_LOGO_OPTS = opts! + + try { + let mk = decorView.findViewById((maskDomId).toInt()) + if (mk != null) { + decorView.removeView(mk!) + } + + } catch (e) { + //TODO handle the exception + } + if (isClsoing) return; + let bgColor = rgbToColorNumber(hexToRgb(config.bgColor)!); + let logoBgcolor = rgbToColorNumber(hexToRgb(config.logoBgColor)!); + let fontColor = rgbToColorNumber(hexToRgb(config.fontColor)!); + + let maskerDom = new RelativeLayout(context) + let maskerDomLayrPrams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + maskerDom.setLayoutParams(maskerDomLayrPrams) + maskerDom.setBackgroundColor(bgColor) + maskerDom.setId((maskDomId).toInt()) + + //创建一个容器用来在底部显示. + + let container = new LinearLayout(context); + container.setOrientation(LinearLayout.VERTICAL) + container.setGravity(Gravity.CENTER) + let containerLayrPrams = new RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + containerLayrPrams.addRule(RelativeLayout.CENTER_HORIZONTAL) + containerLayrPrams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM) + let containerPadding = px2dp(80).toInt(); + container.setPadding(0, 0, 0, containerPadding) + container.setLayoutParams(containerLayrPrams) + + // 创建一个logo容器 + let logoBox = new LinearLayout(context) + logoBox.setBottom(px2dp(16).toInt()) + let wpxlogoBox_w = px2dp(config.width + config.logoPadding).toInt(); + let wpxlogoBox_h = px2dp(config.height + config.logoPadding).toInt(); + logoBox.setGravity(Gravity.CENTER) + + // 设置圆角背景 + let bg = new GradientDrawable() + bg.setColor(logoBgcolor) + bg.setCornerRadius((px2dp(config.round)).toFloat()) + logoBox.setClipToOutline(true) + logoBox.setBackground(bg) + logoBox.setLayoutParams(new LinearLayout.LayoutParams(wpxlogoBox_w, wpxlogoBox_h)) + + function loadImageFromAssets(fname : string) : Bitmap|null{ + let bitmap : Bitmap | null = null + try { + let assetManager = UTSAndroid.getAppContext()!.getAssets() + let inputStream = assetManager.open(fname) + bitmap = BitmapFactory.decodeStream(inputStream) + } catch (e) { + + } + + return bitmap + } + + // 创建图片显示logo; + let img = new ImageView(context) + img.setImageBitmap(loadImageFromAssets(config.logo)) + img.setLayoutParams(new FrameLayout.LayoutParams(px2dp(config.width).toInt(), px2dp(config.height).toInt())) + logoBox.addView(img) + + //底部的版权. + let titleDiv = new TextView(context) + // let titleDivheight = px2dp(titleHeight).toInt(); + titleDiv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + titleDiv.setGravity(Gravity.CENTER) + titleDiv.setTextSize((config.fontSize).toFloat()) + titleDiv.setTextColor(fontColor) + titleDiv.setText(config.rightText) + let titleDivPadding = px2dp(8).toInt(); + titleDiv.setPadding(0, titleDivPadding, 0, 0) + + container.addView(logoBox) + container.addView(titleDiv) + maskerDom.addView(container) + decorView.addView(maskerDom!) + +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/utssdk/app-harmony/Resources/base/media/logo.png b/uni_modules/x-runstart-logo/utssdk/app-harmony/Resources/base/media/logo.png new file mode 100644 index 0000000..dd6f116 Binary files /dev/null and b/uni_modules/x-runstart-logo/utssdk/app-harmony/Resources/base/media/logo.png differ diff --git a/uni_modules/x-runstart-logo/utssdk/app-harmony/config.json b/uni_modules/x-runstart-logo/utssdk/app-harmony/config.json new file mode 100644 index 0000000..7a41bfa --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_runstart_logo": "./lib/x_runstart_logo.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/utssdk/app-harmony/index.uts b/uni_modules/x-runstart-logo/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..4e7f130 --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/app-harmony/index.uts @@ -0,0 +1,10 @@ +import { XRUN_START_LOGO_OPTS} from "../interface.uts" +import { x_showRunLogo,x_hideRunLogo } from "x_runstart_logo"; + +export function hideRunLogo() { + x_hideRunLogo(UTSHarmony.getCurrentWindow()!.getUIContext()) +} + +export function showRunLogo(opts : XRUN_START_LOGO_OPTS) { + x_showRunLogo(UTSHarmony.getCurrentWindow()!.getUIContext(),opts) +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/utssdk/app-harmony/lib/x_runstart_logo.har b/uni_modules/x-runstart-logo/utssdk/app-harmony/lib/x_runstart_logo.har new file mode 100644 index 0000000..5e7c782 Binary files /dev/null and b/uni_modules/x-runstart-logo/utssdk/app-harmony/lib/x_runstart_logo.har differ diff --git a/uni_modules/x-runstart-logo/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-runstart-logo/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-runstart-logo/utssdk/app-ios/Resources/logo.png b/uni_modules/x-runstart-logo/utssdk/app-ios/Resources/logo.png new file mode 100644 index 0000000..dd6f116 Binary files /dev/null and b/uni_modules/x-runstart-logo/utssdk/app-ios/Resources/logo.png differ diff --git a/uni_modules/x-runstart-logo/utssdk/app-ios/config.json b/uni_modules/x-runstart-logo/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-runstart-logo/utssdk/app-ios/index.uts b/uni_modules/x-runstart-logo/utssdk/app-ios/index.uts new file mode 100644 index 0000000..69d5243 --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/app-ios/index.uts @@ -0,0 +1,86 @@ +import { XRUN_START_LOGO_OPTS, RGBA } from "../interface.uts" +import { UIView, UIViewController, NSLayoutConstraint, UIScrollView, NSLineBreakMode,UIWindow, UIFont, UILabel, UITapGestureRecognizer, UIImageView, UIImage } from 'UIKit'; +import { CGRect, CGPoint, CGFloat } from 'CoreFoundation'; +import { Alignment } from 'SwiftUI'; +import { UInt32, KeyPath } from 'Swift'; +import { NSString, URL, URLSession } from 'Foundation'; +import { CABasicAnimation, CAAnimationDelegate, CAAnimation } from 'QuartzCore'; +import { Selector } from "ObjectiveC"; + +let maskerDom : null | UIView = null; +let tid = 0 + +export function hideRunLogo() { + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + } +} + +export function showRunLogo(opts : XRUN_START_LOGO_OPTS) { + let nowwindow = UTSiOS.getKeyWindow() as UIWindow + let rootUIview = nowwindow.rootViewController as UIViewController|null + + if (maskerDom != null) { + clearTimeout(tid) + maskerDom!.removeFromSuperview() + } + let parent = UTSiOS.getCurrentViewController() as UIViewController; + if(rootUIview!=null){ + parent = rootUIview!; + } + let parentView = parent.view as UIView + + let config : XRUN_START_LOGO_OPTS = opts + + maskerDom = new UIView() + + if (maskerDom == null) return; + let cg = parentView.frame as CGRect + maskerDom!.frame = cg + maskerDom!.backgroundColor = UTSiOS.colorWithString(config.bgColor) + + // 添加标题 + let titleDiv = new UILabel(); + titleDiv.textColor = UTSiOS.colorWithString(config.fontColor) + titleDiv.text = new String(config.rightText) + titleDiv.font = UIFont.systemFont(ofSize = new CGFloat(config.fontSize)) + titleDiv.textAlignment = NSTextAlignment.center + maskerDom!.addSubview(titleDiv) + titleDiv.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + // 顶部约束 + // titleDiv.topAnchor.constraint(equalTo = content.topAnchor, constant = 0), + titleDiv.bottomAnchor.constraint(equalTo = maskerDom!.bottomAnchor, constant = -80), + // contextText.widthAnchor.constraint(equalToConstant = new CGFloat((width!-32))), + // 左侧约束 + titleDiv.leadingAnchor.constraint(equalTo = maskerDom!.leadingAnchor, constant = 16), + // 右侧约束 + titleDiv.trailingAnchor.constraint(equalTo = maskerDom!.safeAreaLayoutGuide.trailingAnchor, constant = -16) + ]) + + // 内容外框。 + let container = new UIView(); + container.layer.cornerRadius = new CGFloat(config.round) + container.layer.masksToBounds = true; + container.backgroundColor = UTSiOS.colorWithString(config.logoBgColor) + container.translatesAutoresizingMaskIntoConstraints = false + // container.frame = new CGRect(x = 0, y = 0, width = (config.width+config.logoPadding).toInt(), height = (config.height+config.round).toInt()) + maskerDom!.addSubview(container) + NSLayoutConstraint.activate([ + container.bottomAnchor.constraint(equalTo = titleDiv.topAnchor, constant = -12), + container.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + container.widthAnchor.constraint(equalToConstant = new CGFloat(config.width + config.logoPadding)), + container.heightAnchor.constraint(equalToConstant = new CGFloat(config.height + config.logoPadding)) + ]) + + // 图片. + let img = new UIImageView() + + let imgTop = (config.logoPadding/2).toInt() + img.frame = new CGRect(x = imgTop, y = imgTop, width = (config.width).toInt(), height = (config.height).toInt()) + img.image = new UIImage(named = config.logo) + + container.addSubview(img) + parentView.addSubview(maskerDom!) +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/utssdk/interface.uts b/uni_modules/x-runstart-logo/utssdk/interface.uts new file mode 100644 index 0000000..3cdaa7a --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/interface.uts @@ -0,0 +1,23 @@ +export type RGBA = { r : number, g : number, b : number, a : number } +export type XRUN_START_LOGO_OPTS = { + /** 启动界面背景色,不能使用颜色名称 */ + bgColor:string, + /** logo图片名称 */ + logo:string, + /** logo宽 */ + width:number, + /** logo高 */ + height:number, + /** logo容器圆角 */ + round:number, + /** logo容器背景,不能使用颜色名称 */ + logoBgColor:string, + /** logo下方文字 */ + rightText:string, + /** 文字字号 */ + fontSize:number, + /** 文字颜色,不能使用颜色名称 */ + fontColor:string, + /** logo容器的padding */ + logoPadding:number +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/utssdk/libs/color.uts b/uni_modules/x-runstart-logo/utssdk/libs/color.uts new file mode 100644 index 0000000..331c088 --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/libs/color.uts @@ -0,0 +1,58 @@ +import { RGBA } from "../interface"; +export function hexToRgb(sColors : string) : RGBA | null { + if (sColors == "") { + return null + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + let p : number[] = arr.map((val : string) : number => parseInt(val)); + + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + p.add(1) + + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: arr.length==3?p[3]:parseFloat(arr[3]) + } as RGBA + } + + return null; +} \ No newline at end of file diff --git a/uni_modules/x-runstart-logo/utssdk/unierror.uts b/uni_modules/x-runstart-logo/utssdk/unierror.uts new file mode 100644 index 0000000..ee086ef --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/unierror.uts @@ -0,0 +1,39 @@ +/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */ +import { MyApiErrorCode, MyApiFail } from "./interface.uts" +/** + * 错误主题 + * 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。 + * [可选实现] + */ +export const UniErrorSubject = 'uts-api'; + + +/** + * 错误信息 + * @UniError + * [可选实现] + */ +export const MyAPIErrors : Map = new Map([ + /** + * 错误码及对应的错误信息 + */ + [9010001, 'custom error mseeage1'], + [9010002, 'custom error mseeage2'], +]); + + +/** + * 错误对象实现 + */ +export class MyApiFailImpl extends UniError implements MyApiFail { + + /** + * 错误对象构造函数 + */ + constructor(errCode : MyApiErrorCode) { + super(); + this.errSubject = UniErrorSubject; + this.errCode = errCode; + this.errMsg = MyAPIErrors.get(errCode) ?? ""; + } +} diff --git a/uni_modules/x-runstart-logo/utssdk/web/index.uts b/uni_modules/x-runstart-logo/utssdk/web/index.uts new file mode 100644 index 0000000..a17c85e --- /dev/null +++ b/uni_modules/x-runstart-logo/utssdk/web/index.uts @@ -0,0 +1,61 @@ +export {XRUN_START_LOGO_OPTS} from "../interface" +import {hexToRgb} from "../libs/color" +let xRunStartBoxDiv:null|HTMLElement = null; +// @ts-ignore +export function showRunLogo(opts:XRUN_START_LOGO_OPTS){ + let appwidth = '100vw'; + let appheight = '100vh'; + let _bgcolor = hexToRgb(opts.bgColor); + let bgColor = _bgcolor?`rgba(${_bgcolor.r},${_bgcolor.g},${_bgcolor.b},${_bgcolor.a})`:'#f7f7f7' + let _LogoBgColor = hexToRgb(opts.logoBgColor); + let LogoBgColor = _LogoBgColor?`rgba(${_LogoBgColor.r},${_LogoBgColor.g},${_LogoBgColor.b},${_LogoBgColor.a})`:'#ffffff' + let _fontColor = hexToRgb(opts.fontColor); + let fontColor = _fontColor?`rgba(${_fontColor.r},${_fontColor.g},${_fontColor.b},${_fontColor.a})`:'#888888' + + let box = document.createElement("div") + box.style.position = 'fixed' + box.style.left = '0px' + box.style.top = '0px' + box.style.zIndex = '300' + box.style.width = appwidth + box.style.height = appheight + box.style.background = bgColor + box.style.display = 'flex' + box.style.flexDirection = 'column' + box.style.justifyContent = 'flex-end' + box.style.alignItems = 'center' + + let rightText = document.createElement('span') + rightText.style.fontSize = opts.fontSize+'px' + rightText.style.color = fontColor + rightText.style.marginBottom = '80px' + rightText.style.marginTop = '12px' + rightText.innerText = opts.rightText + + let logoBox = document.createElement('div') + logoBox.style.width = opts.width+'px' + logoBox.style.height = opts.height+'px' + logoBox.style.background = LogoBgColor + logoBox.style.borderRadius = opts.round+'px' + logoBox.style.padding = opts.logoPadding+'px' + + let logo = document.createElement("img") + logo.src = "/static/tmui4xLibs/static/"+opts.logo + logo.style.width = opts.width+'px' + logo.style.height = opts.height+'px' + logo.style.borderRadius = opts.round+'px' + + logoBox.append(logo) + box.append(logoBox) + box.append(rightText) + document.body.append(box) + + xRunStartBoxDiv = box; +} + + +export function hideRunLogo() { + if(xRunStartBoxDiv){ + document.body.removeChild(xRunStartBoxDiv) + } +} \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/changelog.md b/uni_modules/x-screenshot-s/changelog.md new file mode 100644 index 0000000..0bda090 --- /dev/null +++ b/uni_modules/x-screenshot-s/changelog.md @@ -0,0 +1,4 @@ +## 1.0.1(2025-07-27) +* 兼容鸿蒙 +## 1.0.0(2024-12-18) +* 对屏幕截图保存(不需要权限),对指定截图进行保存,安卓,ios支持,web不支持. diff --git a/uni_modules/x-screenshot-s/package.json b/uni_modules/x-screenshot-s/package.json new file mode 100644 index 0000000..75f40d1 --- /dev/null +++ b/uni_modules/x-screenshot-s/package.json @@ -0,0 +1,87 @@ +{ + "id": "x-screenshot-s", + "displayName": "应用页截图 页面局部截图 保存页面图片", + "version": "1.0.0", + "description": "可以对应用页面进行保存,或者对指定节点截图保存图片", + "keywords": [ + "tmui,截图,页面图片" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "10.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "y" + }, + "client": { + "Vue": { + "vue2": "n", + "vue3": "y" + }, + "App": { + "app-android": { + "minVersion": "21" + }, + "app-ios": { + "minVersion": "10" + }, + "app-harmony": "n" + }, + "H5-mobile": { + "Safari": "n", + "Android Browser": "n", + "微信浏览器(Android)": "n", + "QQ浏览器(Android)": "n" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "n", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/readme.md b/uni_modules/x-screenshot-s/readme.md new file mode 100644 index 0000000..a975a4b --- /dev/null +++ b/uni_modules/x-screenshot-s/readme.md @@ -0,0 +1,101 @@ +# x-screenshot-s +### 开发文档 + +1. 可以对窗口进行静默截图 +2. 可以对某一个view节点进行截图 + +### 应用场景 + +1. 对产品端,给用户反馈保存时,可以对当前反馈的页面进行截图反馈,比如界面异常上传等 +2. 对局部节点截图保存可以进行对局部的分享保存,比如页面的排版海报 +3. 对整个页面分享保存 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | x | x | + +### 注意事项 + +使用前一定要打基座才可用,一定要在页面上先引用,再去打基座。 +如果你mac开发。ios可以不用打基座,能直接使用(但前提是你要配置好原生开发环境,否则一样要打包) +如果你是开始安卓,不管是mac,win电脑都要打包基座才能使用。 + +### API说明 + +#### getRootShotImage +```ts +function getRootShotImage(callback: (str: string) => void): void +``` + + +**参数说明:** +- callback:截图完成后的回调函数 + - str:截图保存后的文件路径,如果截图失败则返回空字符串 + +#### getElementShotImage +```ts +function getElementShotImage(ele: UniElement|null, callback: (str: string) => void): void +``` + +**鸿蒙不支持此方法,原因在于官方的 sdk 无法获取鸿蒙节点的原生 View 实例信息** + +**参数说明:** +- ele:要截图的目标元素,UniElement类型 +- callback:截图完成后的回调函数 + - str:截图保存后的文件路径,如果截图失败则返回空字符串 + + +### 示例代码 + +```vue + + + +``` + +### 常见问题 + +1. 截图黑屏或无内容 + - 确保已正确打包基座 + - 检查目标View是否已完成渲染 + - Android端确保View的宽高不为0 + +2. 截图文件路径无效 + - 检查应用是否有存储权限 + - 确保缓存目录可写入 + +3. 性能注意事项 + - 大尺寸View截图可能占用较多内存 + - 建议在截图后及时释放不需要的图片资源 \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/utssdk/app-android/config.json b/uni_modules/x-screenshot-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/utssdk/app-android/index.uts b/uni_modules/x-screenshot-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..e6e775a --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/app-android/index.uts @@ -0,0 +1,59 @@ +import ViewGroup from 'android.view.ViewGroup'; +import Bitmap from 'android.graphics.Bitmap'; +import View from 'android.view.View'; +import FileOutputStream from 'java.io.FileOutputStream'; +import File from 'java.io.File'; +import Canvas from 'android.graphics.Canvas'; +function savePhotoTocache(img : Bitmap) : string { + let context = UTSAndroid.getAppContext()! + let filepath = context.getExternalCacheDir()?.getPath() ?? "" + let fileid = Math.random().toString(16).substring(2, 11); + let file = new File(filepath, fileid + '.jpg'); + let fos = new FileOutputStream(file) + img.compress(Bitmap.CompressFormat.JPEG, 100, fos); + return file.getPath() +} +function getScreenImage() { + let decorView : ViewGroup = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + let rootview : View = decorView.getRootView() + // rootview.setDrawingCacheEnabled(true) + // let bitmap = Bitmap.createBitmap(rootview.getDrawingCache()) + // rootview.setDrawingCacheEnabled(false) + + let bitmap = Bitmap.createBitmap(rootview.width, rootview.height, Bitmap.Config.ARGB_8888) + let canvas = new Canvas(bitmap) + rootview.draw(canvas) + + + return savePhotoTocache(bitmap); +} +/** + * 获取窗口截图 + */ +export function getRootShotImage(callback : (str : string) => void) { + callback(getScreenImage()) +} +/** + * 获取指定元素截图 + */ +export function getElementShotImage(ele:UniElement|null, callback : (str : string) => void) { + if(ele == null) { + callback("") + return; + } + let view = ele.getAndroidView() as View|null; + if(view == null) { + callback("") + return; + } + let rootview = view as View; + // rootview.setDrawingCacheEnabled(true) + // let bitmap = Bitmap.createBitmap(rootview.getDrawingCache()) + // rootview.setDrawingCacheEnabled(false) + let bitmap = Bitmap.createBitmap(rootview.width, rootview.height, Bitmap.Config.ARGB_8888) + let canvas = new Canvas(bitmap) + rootview.draw(canvas) + + let imgpath:string = savePhotoTocache(bitmap); + callback(imgpath) +} \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/utssdk/app-harmony/config.json b/uni_modules/x-screenshot-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..d524f55 --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_screenshot_s": "./lib/x_screenshot_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/utssdk/app-harmony/index.uts b/uni_modules/x-screenshot-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..596828e --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/app-harmony/index.uts @@ -0,0 +1,64 @@ +import { x_getElementShotImage,x_getRootShotImage } from "x_screenshot_s"; +/** + * 获取窗口截图 + */ +export function getRootShotImage(callback : (str : string) => void) { + x_getRootShotImage(UTSHarmony.getCurrentWindow()!.getUIContext(),callback) +} + +/** + * 获取指定元素截图 + */ +export function getElementShotImage(ele:UniElement|null, callback : (str : string) => void) { + x_getElementShotImage(UTSHarmony.getCurrentWindow()!.getUIContext(),ele?.getAttribute("id"),callback) +} + +/** + * 递归查询 + */ +function iterateElement(homeElement : UniElement) : UniNativeViewElement | null { + if ("NATIVE-VIEW" == homeElement.nodeName) { + return homeElement as UniNativeViewElement + } + for (const perChildEle of homeElement.children) { + let findEle = iterateElement(perChildEle) + if (findEle != null) { + return findEle + } + } + + return null +} + +function getPageRootView(id : string, ins : ComponentPublicInstance | null = null) : FrameNode | null { + if (ins == null) { + const pages = getCurrentPages() + if (pages.length > 0) { + const page = pages[pages.length - 1] + const rootViewElement = page.getElementById(id) + if (rootViewElement != null) { + /** + * 找到了root节点,递归检索目标 native-view + */ + const nativeViewElement = iterateElement(rootViewElement) + + if (nativeViewElement != null) { + return nativeViewElement.getHarmonyFrameNode() + } + } + } + } else { + /** + * 尝试迭代遍历 + */ + if (ins.$el != null) { + const nativeViewElement = iterateElement(ins.$el as UniElement) + if (nativeViewElement != null) { + + return nativeViewElement.getHarmonyFrameNode() + } + } + } + + return null +} \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/utssdk/app-harmony/lib/x_screenshot_s.har b/uni_modules/x-screenshot-s/utssdk/app-harmony/lib/x_screenshot_s.har new file mode 100644 index 0000000..272fc8d Binary files /dev/null and b/uni_modules/x-screenshot-s/utssdk/app-harmony/lib/x_screenshot_s.har differ diff --git a/uni_modules/x-screenshot-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-screenshot-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-screenshot-s/utssdk/app-ios/config.json b/uni_modules/x-screenshot-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..4de44cd --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "10" +} diff --git a/uni_modules/x-screenshot-s/utssdk/app-ios/index.uts b/uni_modules/x-screenshot-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..5c4a8c5 --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/app-ios/index.uts @@ -0,0 +1,58 @@ +import { UIButton, UIControl, UIImage, UIView, UIImageView, UIImageWriteToSavedPhotosAlbum, UIGraphicsImageRenderer } from "UIKit"; +import { URL, FileManager, NSAttributedString } from 'Foundation'; +function savePhotoTocache(image : UIImage) : string { + let fileid = Math.random().toString(16).substring(2, 11); + let userDir = FileManager.default.urls(for = FileManager.SearchPathDirectory.cachesDirectory, in = FileManager.SearchPathDomainMask.userDomainMask).first! + let filename = fileid + '.jpg'; + let destinationURL = userDir.appendingPathComponent(filename) + let imageData = image.jpegData(compressionQuality = 1); + let real = UTSiOS.try(imageData!.write(to = destinationURL), "?"); + if (real == null) return "" + return destinationURL.path +} +function getScreenImage(callback : (str : string) => void) { + if (UTSiOS.available("iOS 10.0, *")) { + let parent = UTSiOS.getCurrentViewController() as UIViewController; + let rootView = parent.view as UIView + let renderer = new UIGraphicsImageRenderer(size = rootView.bounds.size); + renderer.image(actions = (context : UIGraphicsImageRendererContext) => { + rootView.drawHierarchy(in = rootView.bounds, afterScreenUpdates = true) + let image = context.currentImage + callback(savePhotoTocache(image)) + }) + } + +} +/** + * 获取窗口截图 + */ +export function getRootShotImage(callback : (str : string) => void) { + getScreenImage((str : string) => { + callback(str) + }) +} +/** + * 获取指定元素截图 + */ +export function getElementShotImage(ele:UniElement|null, callback : (str : string) => void) { + if (ele == null) { + callback("") + return; + } + let view = ele!.getIOSView() as UIView | null; + if (view == null) { + callback("") + return; + } + let rootView = view! as UIView; + if (UTSiOS.available("iOS 10.0, *")) { + let renderer = new UIGraphicsImageRenderer(size = rootView.bounds.size); + renderer.image(actions = (context : UIGraphicsImageRendererContext) => { + rootView.drawHierarchy(in = rootView.bounds, afterScreenUpdates = true) + let image = context.currentImage + callback(savePhotoTocache(image)) + // UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) + }) + } + +} \ No newline at end of file diff --git a/uni_modules/x-screenshot-s/utssdk/interface.uts b/uni_modules/x-screenshot-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-screenshot-s/utssdk/unierror.uts b/uni_modules/x-screenshot-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-screenshot-s/utssdk/web/index.uts b/uni_modules/x-screenshot-s/utssdk/web/index.uts new file mode 100644 index 0000000..b2ec5b0 --- /dev/null +++ b/uni_modules/x-screenshot-s/utssdk/web/index.uts @@ -0,0 +1,12 @@ +/** + * 获取窗口截图 + */ +export function getRootShotImage(callback : (str : string) => void) { + callback("") +} +/** + * 获取指定元素截图 + */ +export function getElementShotImage(ele:UniElement|null, callback : (str : string) => void) { + callback("") +} \ No newline at end of file diff --git a/uni_modules/x-share-s/changelog.md b/uni_modules/x-share-s/changelog.md new file mode 100644 index 0000000..56475db --- /dev/null +++ b/uni_modules/x-share-s/changelog.md @@ -0,0 +1,17 @@ +## 1.0.8(2025-08-17) +* 兼容原生鸿蒙 +## 1.0.6(2024-09-22) +* 修改可能的文件无法读取的问题,有的用户把文件存在到非缓存目录.可能导致文件无法读取. +## 1.0.5(2024-08-24) +* 经过测试可以在uniapp上分享啦。也能在ios上分享,可以分享文本和链接到微信中,具体操作请购买后联系我。 +## 1.0.4(2024-08-06) +* 安卓端改了下判断逻辑 +## 1.0.3(2024-08-05) +* 解决uniapp项目无法在安卓上分享本地图片资源问题 +## 1.0.2(2024-07-30) +IOS支持分享文件,视频,音频,图片到微信。 +## 1.0.1(2024-07-11) +修改支持本地路径文件,兼容uniapp项目。 +## 1.0.0(2024-06-01) +分享内容到其它应用 +安卓,ios支持。 diff --git a/uni_modules/x-share-s/package.json b/uni_modules/x-share-s/package.json new file mode 100644 index 0000000..eca7c80 --- /dev/null +++ b/uni_modules/x-share-s/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-share-s", + "displayName": "安卓,ios,鸿蒙文件视频文本任意文件分享到其它应用", + "version": "1.0.8", + "description": "可以让你的内容分享到其它应用中,安卓和ios支持", + "keywords": [ + "ios,安卓,文件分享" +], + "repository": "", + "engines": { + "HBuilderX": "^4.15", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "68.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "读写文件权限" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "x", + "chrome": "x" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-share-s/readme.md b/uni_modules/x-share-s/readme.md new file mode 100644 index 0000000..f36ac38 --- /dev/null +++ b/uni_modules/x-share-s/readme.md @@ -0,0 +1,76 @@ +# x-share-s +### 开发文档 + +通过接口简单使用可分享你的任意内容到其它app + +前提: + +- 需要打包时指定分享路径,请看下面的技术说明 +- 安卓端请联系下载AndroidManifest.xml文件至你项目中,联系我技术支持,否则无法分享。 +- vip用户请直接在demo中复制 `AndroidManifest.xml`到你根目录后,自己按照插件内的图文教程介绍配置好名称即可。 + +### tmui4.0Vip用户不需要购买已经集成在组件库中 +[tmui4.0](https://ext.dcloud.net.cn/plugin?id=16369) + +### 功能说明 + +- 安卓端可以分享任意文件,文本,视频,图片,音乐至其它app +- IOS端,支持分享任意文件到其它APP,可以分享图片,视频,音频到微信qq等等 +- 文本分享到微信 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | x | x | + +### 方法说明 + +差异说明: + +- 安卓端title就是分享内容时所要展示的分享标题,但在ios端就是你的分享内容,ios端没有标题一说,系统不支持,安卓端如果同时提供了标题和content,最终分享的是content文本 +- minType,如果为text/plain时,title是标题(安卓可用),content为分享的文本内容 +- minType为其它时比如图片等格式 title是标题(安卓可用),content无用,path就是文件地址(文档,图片,视频等等任意文件) + +```ts +/** + * title:分享的标题 + * minType:分享的内容格式 + * 文本:text/plain + * 图片:image/* + * 音频: audio/* + * 视频: video/* + * 任意文件: *\/* + * +*/ +xShare(title : string, minType : string, content ?: string, path ?: string) + +``` + +### 使用示例 + +如果是安卓请务必打自定义基座 +如果是ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。 + +```vue +// 你的uts代码 + + + \ No newline at end of file diff --git a/uni_modules/x-svg-u/package.json b/uni_modules/x-svg-u/package.json new file mode 100644 index 0000000..6deec4f --- /dev/null +++ b/uni_modules/x-svg-u/package.json @@ -0,0 +1,97 @@ +{ + "id": "x-svg-u", + "displayName": "x-svg-u", + "version": "1.0.0", + "description": "x-svg-u", + "keywords": [ + "x-svg-u" + ], + "repository": "", + "engines": { + "HBuilderX": "^4.31", + "uni-app": "^3.1.0", + "uni-app-x": "^3.1.0" + }, + "dcloudext": { + "type": "uts-vue-component", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "", + "darkmode": "-", + "i18n": "-", + "widescreen": "-" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "-", + "aliyun": "-", + "alipay": "-" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-svg-u/readme.md b/uni_modules/x-svg-u/readme.md new file mode 100644 index 0000000..ee1653e --- /dev/null +++ b/uni_modules/x-svg-u/readme.md @@ -0,0 +1,19 @@ +# x-svg-u + +### 开发文档 + +从 1.0.1 开始此组件变更为标准原生组件,使用时,不需要导入组件,可以直接在页面上使用组件,更方便了。 + +```vue + +``` + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 注意事项 + +使用前一定要打基座才可用,一定要在页面上先引用,再去打基座。 diff --git a/uni_modules/x-svg-u/utssdk/app-android/config.json b/uni_modules/x-svg-u/utssdk/app-android/config.json new file mode 100644 index 0000000..7b75ed1 --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/app-android/config.json @@ -0,0 +1,6 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "com.caverock:androidsvg:1.4" + ] +} diff --git a/uni_modules/x-svg-u/utssdk/app-android/index.uts b/uni_modules/x-svg-u/utssdk/app-android/index.uts new file mode 100644 index 0000000..2ea4bba --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/app-android/index.uts @@ -0,0 +1,38 @@ +import View from "android.view.View"; +import InputStream from "java.io.InputStream"; +import Context from "com.alibaba.fastjson.parser.deserializer.ASMDeserializerFactory.Context"; +import FileInputStream from "java.io.FileInputStream"; +import File from "java.io.File"; +import PictureDrawable from "android.graphics.drawable.PictureDrawable"; +import SVG from "com.caverock.androidsvg.SVG" +import ImageView from 'android.widget.ImageView'; + +export class xSvgU { + $element : UniNativeViewElement; + targetView : ImageView | null = null; + constructor(element : UniNativeViewElement) { + //接收传递过来的UniNativeViewElement + this.$element = element; + this.bindView(); + } + bindView() { + this.targetView = new ImageView(this.$element.getAndroidActivity()!); //构建原生view + this.$element.bindAndroidView(this.targetView!); + } + setImage(newval:string){ + let furl = UTSAndroid.convert2AbsFullPath(newval) + let inputStream:InputStream|null = null; + if(furl.indexOf('android_asset')==-1){ + inputStream = new FileInputStream(new File(furl)) + }else{ + inputStream = UTSAndroid.getUniActivity()!.getAssets().open(furl.replace("/android_asset/", "")); + } + if(inputStream ==null) return + let svg = SVG.getFromInputStream(inputStream!); + let pictureDrawable = new PictureDrawable(svg.renderToPicture()); + this.targetView?.setImageDrawable(pictureDrawable); + + + } + +} diff --git a/uni_modules/x-svg-u/utssdk/app-harmony/index.uts b/uni_modules/x-svg-u/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..ca34d9c --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/app-harmony/index.uts @@ -0,0 +1 @@ +export class xSvgU {} \ No newline at end of file diff --git a/uni_modules/x-svg-u/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-svg-u/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-svg-u/utssdk/app-ios/config.json b/uni_modules/x-svg-u/utssdk/app-ios/config.json new file mode 100644 index 0000000..c0ced16 --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/app-ios/config.json @@ -0,0 +1,7 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [{ + "name": "SVGKit", + "version": "3.0.0" + }] +} \ No newline at end of file diff --git a/uni_modules/x-svg-u/utssdk/app-ios/index.uts b/uni_modules/x-svg-u/utssdk/app-ios/index.uts new file mode 100644 index 0000000..0686bf8 --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/app-ios/index.uts @@ -0,0 +1,40 @@ + import { + UIButton, + UIControl, + UIImageView, + UIImage + } from "UIKit" + import { SVGKImage } from "SVGKit" assert { type: "implementationOnly" }; + import { UTSComponent } from "DCloudUTSFoundation" + import { Data } from 'Assignables'; + import { CALayer } from 'QuartzCore'; + import { CGRect, CGSize } from 'CoreFoundation'; + + + +export class xSvgU { + $element : UniNativeViewElement; + targetView : UIImageView | null = null; + constructor(element : UniNativeViewElement) { + this.$element = element; + this.targetView = new UIImageView() + this.$element.bindIOSView(this.targetView!); + } + + setImage(newval : string) { + if (newval != '') { + let url = UTSiOS.getResourcePath(newval) + // let width = (16).toInt(); + // let height = (16).toInt(); + // this.targetView!.frame = new CGRect(x = 0, y = 0, width = width, height = height); + const size:CGRect = this.targetView!.frame; + let svgURL = new URL(fileURLWithPath = url) + let svgData = UTSiOS.try(new Data(contentsOf = svgURL),"?") + if(svgData==null) return; + let svgImage = new SVGKImage(data = svgData!) + svgImage!.size = new CGSize(width= size.width, height= size.height) + this.targetView!.image = svgImage?.uiImage + } + } + +} diff --git a/uni_modules/x-svg-u/utssdk/interface.uts b/uni_modules/x-svg-u/utssdk/interface.uts new file mode 100644 index 0000000..83c2cb7 --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/interface.uts @@ -0,0 +1,6 @@ +export type xSvgPropsType = { + src:string, + width:number, + height:number, + color:string +} \ No newline at end of file diff --git a/uni_modules/x-svg-u/utssdk/mp-weixin/index.uts b/uni_modules/x-svg-u/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..ca34d9c --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/mp-weixin/index.uts @@ -0,0 +1 @@ +export class xSvgU {} \ No newline at end of file diff --git a/uni_modules/x-svg-u/utssdk/web/index.uts b/uni_modules/x-svg-u/utssdk/web/index.uts new file mode 100644 index 0000000..ca34d9c --- /dev/null +++ b/uni_modules/x-svg-u/utssdk/web/index.uts @@ -0,0 +1 @@ +export class xSvgU {} \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/changelog.md b/uni_modules/x-texttovoice-s/changelog.md new file mode 100644 index 0000000..c70f920 --- /dev/null +++ b/uni_modules/x-texttovoice-s/changelog.md @@ -0,0 +1,2 @@ +## 1.0.0(2025-09-21) +支持Android,iOS,Harmony,web/h5文本语音播报功能。 \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/package.json b/uni_modules/x-texttovoice-s/package.json new file mode 100644 index 0000000..1a8cdf1 --- /dev/null +++ b/uni_modules/x-texttovoice-s/package.json @@ -0,0 +1,97 @@ +{ + "id": "x-texttovoice-s", + "displayName": "x-texttovoice-s", + "version": "1.0.0", + "description": "x-texttovoice-s", + "keywords": [ + "x-texttovoice-s" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "^3.1.0", + "uni-app-x": "^3.1.0" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "", + "darkmode": "-", + "i18n": "-", + "widescreen": "-" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "-", + "aliyun": "-", + "alipay": "-" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/readme.md b/uni_modules/x-texttovoice-s/readme.md new file mode 100644 index 0000000..b38699e --- /dev/null +++ b/uni_modules/x-texttovoice-s/readme.md @@ -0,0 +1,90 @@ +# x-texttovoice-s + +### 开发文档 + +将文字转为语音播报。 + +### 兼容性 + +**注意:Harmony需要使用模拟器6.0+(api 20+)才支持在模拟器上使用本插件,低于此版本需要真机调试。** + +| iOS | Harmony | 小程序 | Andriod | WEB | +| --- | --- | --- | --- | --- | +| 12+ | 12+ | x | 5.0+ | 全部 | + +### 方法说明 + +使用 +```ts + +import { XTtsSpeek, xTtsImplIns } from '@/uni_modules/x-texttovoice-s'; +const word = ref("我是待播放的语音文本。") +const onclick = () => { + XTtsSpeek({ + fail(res) { + console.error(res) + }, + onDone() { + console.log('播放完毕') + }, + onStop() { + console.log('stop') + }, + success(res) { + // 初始成功后,调用播放功能。 + xTtsImplIns.play(word.value) + } + }) +} + +``` + +### XTtsSpeek(opts:XuiTextToVoiceOpts) +引擎初始方法 +```ts + +export type XuiTextToVoiceResult = { + +} + +export interface XuiTextToVoiceFail extends IUniError { + errCode : number +}; + +export type XuiTextToVoiceOpts = { + onStart ?:() => void + onStop ?:() => void + onError ?:(res : XuiTextToVoiceFail) => void + /** 播放完成 */ + onDone ?:() => void + /** 函数执行初始化成功,然后就可以播放,停止等操作了。 */ + success ?: (res : XTTSImpl) => void + /** 函数初始化失败 */ + fail ?: (res : XuiTextToVoiceFail) => void + /** 不管初始失败还是成功都执行。 */ + complete ?: (res : XuiTextToVoiceResult|null) => void +} + + + + + +``` + +### xTtsImplIns +语音播放静态类方法。 + +#### isPlaying(): boolean; 获取当前状态 +#### play(c:string); 播播文本语音 +#### stop(); 停止播报 + +```ts +import { XTtsSpeek, xTtsImplIns } from '@/uni_modules/x-texttovoice-s'; +// xTtsImplIns就是实例 XTTSImpl,含有以下方法。 +export interface XTTSImpl { + isPlaying(): boolean; + play(c:string):void + stop():void +} + +``` \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-texttovoice-s/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..45251e0 --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/uni_modules/x-texttovoice-s/utssdk/app-android/config.json b/uni_modules/x-texttovoice-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/utssdk/app-android/index.uts b/uni_modules/x-texttovoice-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..07d674d --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/app-android/index.uts @@ -0,0 +1,108 @@ +import TextToSpeech from "android.speech.tts.TextToSpeech" +import OnInitListener from "android.speech.tts.TextToSpeech.OnInitListener" +import OnUtteranceCompletedListener from "android.speech.tts.TextToSpeech.OnUtteranceCompletedListener" +import UtteranceProgressListener from "android.speech.tts.UtteranceProgressListener" +import Locale from "java.util.Locale" +import { XuiTextToVoiceOpts, XuiTextToVoiceResult, XTTSImpl } from "../interface.uts" +import { XuiTextToVoiceFailImpl } from "../unierror.uts" +import Bundle from "android.os.Bundle"; +let tts : TextToSpeech | null = null + +/** + * 检查权限 + */ +export function checkPermissions(call : (isAuth : boolean) => void) { + let cehckPerMissionsArs = [] as string[] + if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, cehckPerMissionsArs)) { + call(true) + } else { + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, cehckPerMissionsArs, function (_A : boolean, _B : string[]) { + call(true) + }, function (_B : boolean, _A : string[]) { + call(false) + }) + } +} + +class TtsObj implements XTTSImpl { + config : XuiTextToVoiceOpts; + constructor(opts : XuiTextToVoiceOpts) { + this.config = opts; + } + isPlaying() : boolean { + let isplay = tts?.isSpeaking; + return isplay == null ? false : isplay + } + play(c : string) { + const params = Bundle() + tts?.speak(c, TextToSpeech.QUEUE_FLUSH, params, Math.random().toString(16).substring(4)) + } + stop() { + tts?.stop() + tts?.shutdown() + this.config.onStop?.() + } +} +let TtsObjIml:TtsObj|null = null; +export class xTtsImplIns { + public static play(c:string){ + TtsObjIml?.play(c) + } + public static isPlaying() : boolean { + return TtsObjIml?.isPlaying()??false + } + public static stop(){ + TtsObjIml?.stop() + } +} + +export function XTtsSpeek(opts : XuiTextToVoiceOpts) { + function initTTS() { + class Listen extends OnInitListener { + override onInit(status : Int) { + if (status != TextToSpeech.SUCCESS) { + tts = null + console.error("TMUI Error:", status) + opts.fail?.(new XuiTextToVoiceFailImpl(1001)); + opts.complete?.(null) + return; + } + let ttsObj = tts!; + const result = ttsObj.setLanguage(Locale.CHINESE) + if (result == TextToSpeech.LANG_MISSING_DATA) { + tts = null + opts.fail?.(new XuiTextToVoiceFailImpl(1002)); + opts.complete?.(null) + return; + } + TtsObjIml = new TtsObj(opts) + opts.success?.(TtsObjIml!) + opts.complete?.(null) + } + } + class ProgressListen extends UtteranceProgressListener { + constructor() { + super() + } + public override onError(param : string | null) { + opts.onError?.(new XuiTextToVoiceFailImpl(1004)); + } + public override onStart(param : string | null) { + opts.onStart?.(); + } + + public override onDone(param : string | null) { + opts.onDone?.(); + } + } + tts = new TextToSpeech(UTSAndroid.getAppContext()!, new Listen()) + tts!.setOnUtteranceProgressListener(new ProgressListen()) + } + + if (tts != null) { + tts?.stop() + tts?.shutdown() + tts = null; + } + initTTS() +} \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/utssdk/app-harmony/index.uts b/uni_modules/x-texttovoice-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..1d29f89 --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/app-harmony/index.uts @@ -0,0 +1,94 @@ +import { XuiTextToVoiceOpts, XuiTextToVoiceResult, XTTSImpl } from "../interface.uts" +import { XuiTextToVoiceFailImpl } from "../unierror.uts" +import { textToSpeech } from '@kit.CoreSpeechKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +let tts : textToSpeech.TextToSpeechEngine | null = null; +class TtsObj implements XTTSImpl { + config : XuiTextToVoiceOpts; + constructor(opts : XuiTextToVoiceOpts) { + this.config = opts; + } + isPlaying() : boolean { + return tts?.isBusy() ?? false + } + play(c : string) { + // 设置播报相关参数 + let extraParam:Record = { + "queueMode": 0, "speed": 0.9, "pitch": 1, "languageContext": 'zh-CN', + "audioType": "pcm", "soundChannel": 3, "playType": 1 + }; + let speakParams : textToSpeech.SpeakParams = { + requestId: Math.random().toString(16).substring(4), + extraParams: extraParam + }; + tts?.speak(c, speakParams); + } + + stop() { + tts?.stop() + tts?.shutdown() + } +} + +let TtsObjIml : TtsObj | null = null; +export class xTtsImplIns { + public static play(c : string) { + TtsObjIml?.play(c) + } + public static isPlaying() : boolean { + return TtsObjIml?.isPlaying() ?? false + } + public static stop() { + TtsObjIml?.stop() + } +} +export function XTtsSpeek(opts : XuiTextToVoiceOpts) { + tts = null; + let extraParam:Record = { "style": 'interaction-broadcast', "locate": 'CN', "name": 'EngineName' }; + let initParamsInfo : textToSpeech.CreateEngineParams = { + language: 'zh-CN', + person: 0, + online: 1, + extraParams: extraParam + }; + let speakListener : textToSpeech.SpeakListener = { + // 开始播报回调 + onStart(requestId : string, response : textToSpeech.StartResponse) { + opts.onStart?.() + }, + // 合成完成及播报完成回调 + onComplete(requestId : string, response : textToSpeech.CompleteResponse) { + opts.onDone?.() + }, + // 停止播报回调 + onStop(requestId : string, response : textToSpeech.StopResponse) { + opts.onStop?.() + }, + // 返回音频流 + onData(requestId : string, audio : ArrayBuffer, response : textToSpeech.SynthesisResponse) { + }, + // 错误回调 + onError(requestId : string, errorCode : number, errorMessage : string) { + console.error(`onError, requestId: ${requestId} errorCode: ${errorCode} errorMessage: ${errorMessage}`); + opts.onError?.(new XuiTextToVoiceFailImpl(1004)) + } + }; + // 调用createEngine方法 + textToSpeech.createEngine(initParamsInfo, (err : BusinessError, textToSpeechEngine : textToSpeech.TextToSpeechEngine) => { + if (!err) { + console.info('Succeeded in creating engine'); + // 接收创建引擎的实例 + tts = textToSpeechEngine; + tts!.setListener(speakListener); + TtsObjIml = new TtsObj(opts) + opts.success?.(TtsObjIml!) + opts.complete?.(null) + } else { + console.error(`Failed to create engine. Code: ${err.code}, message: ${err.message}.`); + opts.fail?.(new XuiTextToVoiceFailImpl(1001)) + opts.complete?.(null) + } + }); + + +} \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/utssdk/app-ios/config.json b/uni_modules/x-texttovoice-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..7ff7cb0 --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/app-ios/config.json @@ -0,0 +1,4 @@ +{ + "deploymentTarget": "12", + "abis": ["armeabi-v7a", "arm64-v8a"] +} diff --git a/uni_modules/x-texttovoice-s/utssdk/app-ios/index.uts b/uni_modules/x-texttovoice-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..0f55f75 --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/app-ios/index.uts @@ -0,0 +1,83 @@ +import { XuiTextToVoiceOpts, XuiTextToVoiceResult, XTTSImpl } from "../interface.uts" +import { XuiTextToVoiceFailImpl } from "../unierror.uts" +import { AVSpeechBoundary, AVSpeechSynthesisVoice, AVSpeechSynthesizer, AVSpeechSynthesizerDelegate, AVSpeechUtterance } from "AVFAudio"; +import { NSObject } from "ObjectiveC"; +import {AVPlayerLayer} from "AVFoundation" +let tts:AVSpeechSynthesizer|null = null + +class TtsObj implements XTTSImpl { + config : XuiTextToVoiceOpts; + constructor(opts : XuiTextToVoiceOpts) { + this.config = opts; + } + isPlaying() : boolean { + return tts!.isSpeaking; + } + play(c : string) { + + console.log(c) + let utterance = new AVSpeechUtterance(string = c) + utterance.voice = new AVSpeechSynthesisVoice(language = "zh-CN") + tts!.speak(utterance) + } + + stop() { + tts!.stopSpeaking(at = AVSpeechBoundary.immediate) + this.config.onStop?.() + } +} +// 委托类 +class TTSDelegate implements AVSpeechSynthesizerDelegate{ + private config: XuiTextToVoiceOpts + constructor(opts : XuiTextToVoiceOpts) { + this.config = opts + } + speechSynthesizer(synthesizer: AVSpeechSynthesizer, @argumentLabel("didStart") utterance: AVSpeechUtterance) { + this.config.onStart?.() + } + + speechSynthesizer(synthesizer: AVSpeechSynthesizer, @argumentLabel("didFinish") utterance: AVSpeechUtterance) { + this.config.onDone?.() + } + + speechSynthesizer(synthesizer: AVSpeechSynthesizer, @argumentLabel("didCancel") utterance: AVSpeechUtterance) { + this.config.onDone?.() + } + + speechSynthesizer(synthesizer: AVSpeechSynthesizer, @argumentLabel("didPause") utterance: AVSpeechUtterance) { + this.config.onStop?.() + } + +} +let TtsObjIml:TtsObj|null = null; +let ttsDelegate:TTSDelegate|null = null; +export class xTtsImplIns { + public static play(c:string){ + TtsObjIml?.play(c) + } + public static isPlaying() : boolean { + return TtsObjIml?.isPlaying()??false + } + public static stop(){ + TtsObjIml?.stop() + } +} +export function XTtsSpeek(opts : XuiTextToVoiceOpts) { + tts = null; + DispatchQueue.main.async(execute=():void => { + try { + tts = new AVSpeechSynthesizer() + TtsObjIml = new TtsObj(opts) + ttsDelegate = new TTSDelegate(opts) + tts!.delegate = ttsDelegate! + opts.success?.(TtsObjIml!) + opts.complete?.(null) + } catch (error) { + console.error("TMUI Error:",error) + opts.fail?.(new XuiTextToVoiceFailImpl(1001)) + opts.complete?.(null) + } + }) + + +} \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/utssdk/interface.uts b/uni_modules/x-texttovoice-s/utssdk/interface.uts new file mode 100644 index 0000000..d124c1b --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/interface.uts @@ -0,0 +1,30 @@ + +export type XuiTextToVoiceResult = { + +} + +export interface XuiTextToVoiceFail extends IUniError { + errCode : number +}; + +export type XuiTextToVoiceOpts = { + onStart ?:() => void + onStop ?:() => void + onError ?:(res : XuiTextToVoiceFail) => void + /** 播放完成 */ + onDone ?:() => void + /** 函数执行初始化成功,然后就可以播放,停止等操作了。 */ + success ?: (res : XTTSImpl) => void + /** 函数初始化失败 */ + fail ?: (res : XuiTextToVoiceFail) => void + /** 不管初始失败还是成功都执行。 */ + complete ?: (res : XuiTextToVoiceResult|null) => void +} + +export interface XTTSImpl { + isPlaying(): boolean; + play(c:string):void + stop():void +} + + diff --git a/uni_modules/x-texttovoice-s/utssdk/unierror.uts b/uni_modules/x-texttovoice-s/utssdk/unierror.uts new file mode 100644 index 0000000..1aea338 --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/unierror.uts @@ -0,0 +1,22 @@ +/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */ +import { XuiTextToVoiceFail } from "./interface.uts" + +export const XuiErrors : Map = new Map([ + [1000, '没有相关权限'], + [1001, '初始化失败'], + [1002, '设置的语文包在系统中缺失'], + [1003, '初始化中或者还在报播中'], + [1004, '播放中出现错误'], +]); + +export class XuiTextToVoiceFailImpl extends UniError implements XuiTextToVoiceFail { + /** + * 错误对象构造函数 + */ + constructor(errCode : number) { + super(); + this.errSubject = "x-chinesetopinyin-s"; + this.errCode = errCode; + this.errMsg = XuiErrors.get(errCode) ?? ""; + } +} \ No newline at end of file diff --git a/uni_modules/x-texttovoice-s/utssdk/web/index.uts b/uni_modules/x-texttovoice-s/utssdk/web/index.uts new file mode 100644 index 0000000..91c6292 --- /dev/null +++ b/uni_modules/x-texttovoice-s/utssdk/web/index.uts @@ -0,0 +1,58 @@ +import { XuiTextToVoiceOpts, XuiTextToVoiceResult, XTTSImpl } from "../interface.uts" +import { XuiTextToVoiceFailImpl } from "../unierror.uts" +let tts:SpeechSynthesisUtterance|null = null; +class TtsObj implements XTTSImpl { + config : XuiTextToVoiceOpts; + constructor(opts : XuiTextToVoiceOpts) { + this.config = opts; + } + isPlaying() : boolean { + return speechSynthesis.speaking; + } + play(c : string) { + tts!.text = c; + tts!.pitch = 0.5 + speechSynthesis.speak(tts!); + } + + stop() { + speechSynthesis.pause() + this.config.onStop?.() + } +} + +let TtsObjIml:TtsObj|null = null; +export class xTtsImplIns { + public static play(c:string){ + TtsObjIml?.play(c) + } + public static isPlaying() : boolean { + return TtsObjIml?.isPlaying()??false + } + public static stop(){ + TtsObjIml?.stop() + } +} +export function XTtsSpeek(opts : XuiTextToVoiceOpts) { + tts = null; + // 检查浏览器支持 + if ('speechSynthesis' in window) { + tts = new SpeechSynthesisUtterance(); + tts!.onend = ()=>{ + opts.onDone?.() + } + tts!.onerror = ()=>{ + opts.onError?.(new XuiTextToVoiceFailImpl(1004)) + } + tts!.onstart = ()=>{ + opts.onStart?.() + } + TtsObjIml = new TtsObj(opts) + opts.success?.(TtsObjIml!) + opts.complete?.(null) + } else { + console.error("TMUI Error:",'浏览器不支持语音合成') + opts.fail?.(new XuiTextToVoiceFailImpl(1001)) + opts.complete?.(null) + } +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/changelog.md b/uni_modules/x-tips-s/changelog.md new file mode 100644 index 0000000..655b646 --- /dev/null +++ b/uni_modules/x-tips-s/changelog.md @@ -0,0 +1,7 @@ +## 1.0.2(2025-07-25) +* 更新支持鸿蒙原生 Next,采用自己编译的 Har 包来支持 +## 1.0.1(2025-02-23) +* 更新了动画,并修复了,如果路径页面,上个页面不会自动关闭的问题. +* ios端添加了显示动画,显示更自然 +## 1.0.0(2024-08-06) +安卓,ios,web可用。 diff --git a/uni_modules/x-tips-s/package.json b/uni_modules/x-tips-s/package.json new file mode 100644 index 0000000..3f1cad8 --- /dev/null +++ b/uni_modules/x-tips-s/package.json @@ -0,0 +1,82 @@ +{ + "id": "x-tips-s", + "displayName": "TM-UI 4.0x消息提示可任意位置调用覆盖任意界面", + "version": "1.0.0", + "description": "主要是用来在顶部或者底部进行一些全局的消息提示", + "keywords": [ + "uts,uniappx,tmui,原生" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "1.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "y" + }, + "client": { + "Vue": { + "vue2": "n", + "vue3": "y" + }, + "App": { + "app-android": "y", + "app-ios": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "u", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/readme.md b/uni_modules/x-tips-s/readme.md new file mode 100644 index 0000000..9f6bd2d --- /dev/null +++ b/uni_modules/x-tips-s/readme.md @@ -0,0 +1,75 @@ +# x-tips-s + +### 特性说明 +主要是用来一段在顶部或者底部的一段文字提示,而且不受干扰,自行消失,也不影响用户操作. + +. 可以重复打开,或者连续打开不用担心前一个是否关闭,我内部会检测关闭上一个提示。 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 开发文档 + +**浏览器端需要你把目录中的```remixicon.ttf```复制到static目录下** + + +调用: +```ts +import { showTips,hideTips,XTIPS_TYPE } from "@/uni_modules/x-tips-s" +// 打开提示 +showTips({title:"提示消息"} as XTIPS_TYPE) +// 手动隐藏 +hideTips() +``` + +参数配置: + +下面的图标iconCode,同组件库x-icon是相同的字体图标,请打开图标网站:[查看](https://remixicon.com/) +找到直接想要的图标后 复制 unicode ,不是名称。比如:我们只要取ED29 +下面的参数图标iconCode就是ED29 **iconCode:'ED29'** + +**XTIPS_TYPE** + +```ts +// 所有参数都是可选的, 但标题是必选。 +export type XTIPS_TYPE = { + iconColor?:string, + contentBgColor?:string, + maskBgColor?:string, + iconSize?:number, + /** + * 正常应该填写图标的16进制符号如:EEC4 + * 本组件允许几个状态名称使用默认图标,为空是info图标。 + * warn,error,success,info + */ + iconCode?:string, + /** + * 标题为空不显示。 + */ + title:string, + titleSize?:number, + titleColor?:string, + /** + * 几秒后消失,0 表示永不消失 + */ + duration?:number, + close?:()=>void, + /** 宽 */ + size?:number, + /** + * 允许穿透 + * @default false + */ + maskDisableClik?:boolean, + position?:'top'|'bottom', + /** + * 偏移量 + * @default 50 + */ + offset?:number +} + +``` \ No newline at end of file diff --git a/uni_modules/x-tips-s/remixicon.ttf b/uni_modules/x-tips-s/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-tips-s/remixicon.ttf differ diff --git a/uni_modules/x-tips-s/toast.png b/uni_modules/x-tips-s/toast.png new file mode 100644 index 0000000..e312a71 Binary files /dev/null and b/uni_modules/x-tips-s/toast.png differ diff --git a/uni_modules/x-tips-s/utssdk/app-android/assets/remixicon.ttf b/uni_modules/x-tips-s/utssdk/app-android/assets/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-tips-s/utssdk/app-android/assets/remixicon.ttf differ diff --git a/uni_modules/x-tips-s/utssdk/app-android/config.json b/uni_modules/x-tips-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/app-android/index.uts b/uni_modules/x-tips-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..f3d89f5 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-android/index.uts @@ -0,0 +1,220 @@ +import LinearLayout from 'android.widget.LinearLayout'; +import Context from 'android.content.Context' +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import { XTIPS_TYPE, XTIPS_TYPE_PRIVATE } from "../interface.uts" +import Color from 'android.graphics.Color'; +import Gravity from 'android.view.Gravity'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable'; +import TextView from 'android.widget.TextView'; +import Typeface from 'android.graphics.Typeface'; +import TextUtils from 'android.text.TextUtils'; +import Uri from 'android.net.Uri'; +import ObjectAnimator from 'android.animation.ObjectAnimator'; +import ValueAnimator from 'android.animation.ValueAnimator'; +import TimeInterpolator from 'android.animation.TimeInterpolator'; +import MotionEvent from 'android.view.MotionEvent'; +import { hexToRgb } from "../libs/color.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; +import LayoutParams from 'android.widget.RelativeLayout.LayoutParams'; +// #ifdef UNI-APP-X +import getCurrentPages from 'io.dcloud.uniapp.framework.getCurrentPages'; +import onReady from 'io.dcloud.uniapp.framework.onReady'; +import onUnload from 'io.dcloud.uniapp.framework.onUnload'; +import onShow from 'io.dcloud.uniapp.framework.onShow'; +import AccelerateDecelerateInterpolator from 'android.view.animation.AccelerateDecelerateInterpolator'; +// #endif + + +let tid : number | null = 0 +let maskDomId = 388 +let currentOpts:XTIPS_TYPE | null = null; +function px2dp(n : number) : number { + + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + + return mets.density * n +} + +export function hideTips() { + UTSAndroid.getDispatcher("main").async(function (_) { + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + let mk = decorView.findViewById((maskDomId).toInt()) + if (mk != null) { + decorView.removeView(mk) + } + if (tid != null) { + clearTimeout(tid!) + } + currentOpts?.close?.() + }) +} +function __hideTips__(decorView : ViewGroup) { + UTSAndroid.getDispatcher("main").async(function (_) { + let mk = decorView.findViewById((maskDomId).toInt()) + if (mk != null) { + decorView.removeView(mk) + } + if (tid != null) { + clearTimeout(tid!) + } + currentOpts?.close?.() + }) +} +function _showTips_(opts : XTIPS_TYPE | null) { + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + UTSAndroid.getDispatcher("main").async(function (_) { + try { + let mk = decorView.findViewById((maskDomId).toInt()) + if (mk != null) { + decorView.removeView(mk) + } + if (tid != null) { + clearTimeout(tid!) + } + + } catch (e) { + //TODO handle the exception + } + let realopts = opts == null ? ({ title: '' } as XTIPS_TYPE) : (opts!) + let config = configCover(realopts) + let rmbgColor = hexToRgb(config.maskBgColor); + let textColor = hexToRgb(config.iconColor); + let wrapColor = hexToRgb(config.contentBgColor); + let titleColorRgb = hexToRgb(config.titleColor); + + let mbgColor = rmbgColor == null ? Color.parseColor(config.maskBgColor) : Color.argb((rmbgColor!.a * 255).toInt(), rmbgColor!.r.toInt(), rmbgColor!.g.toInt(), rmbgColor!.b.toInt()) + let fontColor = textColor == null ? Color.parseColor(config.iconColor) : Color.argb((textColor!.a * 255).toInt(), textColor!.r.toInt(), textColor!.g.toInt(), textColor!.b.toInt()) + let contentColor = rmbgColor == null ? Color.parseColor(config.contentBgColor) : Color.argb((wrapColor!.a * 255).toInt(), wrapColor!.r.toInt(), wrapColor!.g.toInt(), wrapColor!.b.toInt()) + let titleColor = titleColorRgb == null ? Color.parseColor(config.titleColor) : Color.argb((titleColorRgb!.a * 255).toInt(), titleColorRgb!.r.toInt(), titleColorRgb!.g.toInt(), titleColorRgb!.b.toInt()) + + const context = UTSAndroid.getAppContext()! as Context + let maskerDom = new RelativeLayout(context) + + class MaskerDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + + return false + } + } + + maskerDom.setOnTouchListener(new MaskerDomClickListsner()) + + let maskerDomLayrPrams : LayoutParams = new RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + if (config.position == 'top') { + maskerDomLayrPrams.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE) + maskerDom.setPadding(px2dp(16).toInt(), px2dp(config.offset).toInt(), px2dp(16).toInt(), 0) + maskerDom.setGravity(Gravity.CENTER_HORIZONTAL) + } else if (config.position == 'bottom') { + maskerDomLayrPrams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE) + maskerDom.setPadding(px2dp(16).toInt(), 0, px2dp(16).toInt(), px2dp(config.offset).toInt()) + maskerDom.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL) + } + maskerDom.setLayoutParams(maskerDomLayrPrams) + maskerDom.setBackgroundColor(mbgColor) + maskerDom.setId((maskDomId).toInt()) + + let contentWrapDiv = new LinearLayout(context); + // 设置圆角背景 + let bg = new GradientDrawable() + bg.setColor(contentColor) + bg.setCornerRadius((px2dp(16)).toFloat()) + contentWrapDiv.setBackground(bg) + // contentWrapDiv.setBackgroundColor(Color.parseColor(config.contentBgColor)) + let wpx = px2dp(config.size + 16).toInt(); + let minHeight = px2dp(Math.max(config.titleSize, config.iconSize) + 16).toInt(); + contentWrapDiv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + contentWrapDiv.setMinimumHeight(minHeight) + contentWrapDiv.setMinimumWidth(wpx) + let wpadingx = px2dp(8).toInt(); + contentWrapDiv.setPadding(wpadingx, wpadingx, wpadingx, wpadingx) + + contentWrapDiv.setGravity(Gravity.CENTER) + contentWrapDiv.setOrientation(LinearLayout.HORIZONTAL) + // 创建图标。 + let iconDiv = new TextView(context) + // iconDiv.setLineHeight(1) + iconDiv.setTextColor(fontColor) + let assetManager = context!.getAssets(); + let typeface = Typeface.createFromAsset(assetManager, "remixicon.ttf") + iconDiv.setTypeface(typeface) + iconDiv.setGravity(Gravity.CENTER) + iconDiv.setTextSize(config.iconSize.toFloat()) + if (!TextUtils.isEmpty(config.iconCode) && config.iconCode != '') { + let codePoint = Integer.parseInt(config.iconCode, 16); + let charArray = Character.toChars(codePoint); + let text = new String(charArray); + iconDiv.setText(text); + contentWrapDiv.addView(iconDiv) + } + + + if (config.title != "") { + // 添加一个title + let titleDiv = new TextView(context) + titleDiv.setText(config.title) + titleDiv.setTextSize((config.titleSize).toFloat()) + titleDiv.setTextColor(titleColor) + titleDiv.setGravity(Gravity.CENTER) + titleDiv.setPadding(px2dp(10).toInt(), 0, 0, 0) + contentWrapDiv.addView(titleDiv) + } + + maskerDom.addView(contentWrapDiv) + + decorView.addView(maskerDom!) + + try { + let s0 = (0).toFloat() + let s1 = (1).toFloat() + contentWrapDiv.setAlpha(s0) + contentWrapDiv.setScaleX(s0) + contentWrapDiv.setScaleY(s0) + let ani = contentWrapDiv.animate() as ViewPropertyAnimator; + ani.alpha(s1) + .scaleX(s1) + .scaleY(s1) + .setDuration(300) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + } catch (e) { + //TODO handle the exception + } + + if (config.duration == 0) return; + tid = setTimeout(function () { + tid = null; + __hideTips__(decorView) + }, (config.duration + 300).toInt()); + + }) +} + +export function showTips(opts : XTIPS_TYPE | null) { + const pages = getCurrentPages(); + if (pages.length > 0) { + const page = pages[pages.length - 1].vm! + const instance = page.$ + if (page.$isReady) { + currentOpts = opts; + _showTips_(opts) + } else { + hideTips() + } + onUnload(() => { + hideTips() + }, instance) + }else{ + currentOpts = opts; + _showTips_(opts) + } +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/app-harmony/config.json b/uni_modules/x-tips-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..a5be609 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_tips_s": "./lib/x_tips_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/app-harmony/index.uts b/uni_modules/x-tips-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..2c9fd0d --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-harmony/index.uts @@ -0,0 +1,14 @@ +import { XTIPS_TYPE, XTIPS_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { hexToRgb } from "../libs/color.uts" +import { xshowtips,xhideTips } from "x_tips_s"; + + + +export const hideTips = () => { + xhideTips(UTSHarmony.getCurrentWindow()!.getUIContext()) +} +export function showTips(opts : XTIPS_TYPE|null) { + let config = configCover(opts==null ? ({} as XTIPS_TYPE) : (opts!)) + xshowtips(UTSHarmony.getCurrentWindow()!.getUIContext(),config) +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/app-harmony/lib/x_tips_s.har b/uni_modules/x-tips-s/utssdk/app-harmony/lib/x_tips_s.har new file mode 100644 index 0000000..3fde81c Binary files /dev/null and b/uni_modules/x-tips-s/utssdk/app-harmony/lib/x_tips_s.har differ diff --git a/uni_modules/x-tips-s/utssdk/app-ios/Info.plist b/uni_modules/x-tips-s/utssdk/app-ios/Info.plist new file mode 100644 index 0000000..1dd21fc --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-ios/Info.plist @@ -0,0 +1,10 @@ + + + + + UIAppFonts + + remixicon.ttf + + + \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-tips-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-tips-s/utssdk/app-ios/Resources/remixicon.ttf b/uni_modules/x-tips-s/utssdk/app-ios/Resources/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-tips-s/utssdk/app-ios/Resources/remixicon.ttf differ diff --git a/uni_modules/x-tips-s/utssdk/app-ios/config.json b/uni_modules/x-tips-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-tips-s/utssdk/app-ios/index.uts b/uni_modules/x-tips-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..8497919 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/app-ios/index.uts @@ -0,0 +1,214 @@ +import { XTIPS_TYPE, XTIPS_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { UIView,UIEdgeInsets, UIViewController, NSLayoutConstraint,UILayoutPriority, UITextView, UIFont, UILabel, NSTextAlignment, NSLineBreakMode , Distribution, UIColor } from 'UIKit'; +import { CGRect, CGPoint, CGFloat, CGSize, CFDictionary } from 'CoreFoundation'; +import { CGSizeMake } from 'CoreGraphics'; +import { Alignment } from 'SwiftUI'; +import { UInt32, KeyPath } from 'Swift'; +import { NSString } from 'Foundation'; +import { CABasicAnimation , CAMediaTiming , CAMediaTimingFunction , CAMediaTimingFunctionName } from 'QuartzCore'; + +let maskerDom : null | UIView = null; +let tid : number | null = 0 +let currentOpts:XTIPS_TYPE | null = null; +export function hideTips() { + DispatchQueue.main.async(execute = () : void => { + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + } + if (tid != null) { + clearTimeout(tid!) + } + currentOpts?.close?.() + }) +} + +export function showTips(opts : XTIPS_TYPE | null) { + DispatchQueue.main.async(execute = () : void => { + currentOpts = opts; + if (tid != null) { + clearTimeout(tid!) + tid = null; + } + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + } + let parent = UTSiOS.getCurrentViewController() as UIViewController; + let parentView = parent.view as UIView + + let realopts = opts == null ? ({} as XTIPS_TYPE) : (opts!) + let config = configCover(realopts) + + maskerDom = new UIView() + + // 允许遮罩穿透. + maskerDom!.isUserInteractionEnabled = !config.maskDisableClik; + + + if (maskerDom == null) return; + let cg = parentView.frame as CGRect + maskerDom!.frame = cg + maskerDom!.backgroundColor = UTSiOS.colorWithString(config.maskBgColor) + maskerDom!.layoutMargins = new UIEdgeInsets(top=0,left=16,bottom=0,right=16) + + let contetDiv = new UIView(); + contetDiv.layer.cornerRadius = 16 + contetDiv.layer.masksToBounds = true; + contetDiv.backgroundColor = UTSiOS.colorWithString(config.contentBgColor) + + // 添加投影 + + contetDiv.layer.shadowColor = UIColor.black.cgColor + contetDiv.layer.shadowOpacity = 0.5 + contetDiv.layer.shadowOffset = new CGSize(width= 10, height= 10) + contetDiv.layer.shadowRadius = 20 + + + + let textView = new UILabel() + textView.frame = new CGRect(x = 0, y = 0, width = config.iconSize.toInt(), height = config.iconSize.toInt()) + textView.font = new UIFont(name = "remixicon", size = new CGFloat(config.iconSize)) + textView.textColor = UTSiOS.colorWithString(config.iconColor) + textView.textAlignment = NSTextAlignment.center + + if (config.iconCode != "") { + let codePoint = new UInt32(config.iconCode, radix = 16) + let stricon = new NSString(format = "%C", codePoint!) + textView.text = new String(stricon); + // 添加动画图标旋转 + let spinAni = new CABasicAnimation(keyPath = "transform.scale") + spinAni.fromValue = 0.4 + spinAni.toValue = 1 + spinAni.duration = 0.5 + textView.layer.add(spinAni, forKey = "scaleAnimation") + } + + + + // 添加内容缩放动画 + let scaleAni = new CABasicAnimation(keyPath = "transform.scale") + scaleAni.fromValue = 0 + scaleAni.toValue = 1 + scaleAni.duration = 0.3 + scaleAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + + let scaleOpacity = new CABasicAnimation(keyPath = "opacity") + scaleOpacity.fromValue = 0 + scaleOpacity.toValue = 1 + scaleOpacity.duration = 0.3 + scaleOpacity.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + + contetDiv.layer.add(scaleAni, forKey = "scaleAnimation") + contetDiv.layer.add(scaleAni, forKey = "opacityAnimation") + + // 两个都不空 + if (config.title != "" && config.iconCode != "") { + + textView.translatesAutoresizingMaskIntoConstraints = false + + let titleView = new UILabel() + titleView.text = new String(config.title); + titleView.textAlignment = NSTextAlignment.center + titleView.lineBreakMode = NSLineBreakMode.byWordWrapping + titleView.numberOfLines = 0 + titleView.font = UIFont.systemFont(ofSize = new CGFloat(config.titleSize)) + titleView.textColor = UTSiOS.colorWithString(config.titleColor) + titleView.translatesAutoresizingMaskIntoConstraints = false + + + let contetDivWrap = new UIStackView(arrangedSubviews = [textView,titleView]) + contetDivWrap.axis = NSLayoutConstraint.Axis.horizontal + contetDivWrap.distribution = UIStackView.Distribution.fill + contetDivWrap.alignment = UIStackView.Alignment.center + contetDivWrap.spacing = 5 + + + contetDivWrap.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(contetDivWrap) + + + NSLayoutConstraint.activate([ + // 中心约束 + // contetDivWrap.centerXAnchor.constraint(equalTo = contetDiv.centerXAnchor), + contetDivWrap.centerYAnchor.constraint(equalTo = contetDiv.centerYAnchor), + // 左侧约束 + contetDivWrap.leadingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.leadingAnchor, constant = 16), + // 右侧约束 + contetDivWrap.trailingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.trailingAnchor, constant = -16), + contetDivWrap.topAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.topAnchor, constant = 16), + contetDivWrap.widthAnchor.constraint(lessThanOrEqualToConstant = cg.width-32), + // contetDivWrap.bottomAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.bottomAnchor, constant = -16), + ]) + + + // 图标空,标题不空 + } else if (config.iconCode == "" && config.title != "") { + let titleView = new UILabel() + titleView.text = new String(config.title); + titleView.textAlignment = NSTextAlignment.center + titleView.lineBreakMode = NSLineBreakMode.byWordWrapping + titleView.numberOfLines = 0 + titleView.font = UIFont.systemFont(ofSize = new CGFloat(config.titleSize)) + titleView.textColor = UTSiOS.colorWithString(config.titleColor) + titleView.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(titleView) + NSLayoutConstraint.activate([ + // 顶部约束 + titleView.topAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.topAnchor, constant = 16), + titleView.bottomAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.bottomAnchor, constant = -16), + // 左侧约束 + titleView.leadingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.leadingAnchor, constant = 16), + // 右侧约束 + titleView.trailingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.trailingAnchor, constant = -16) + ]) + // 图标不空,文字空。 + } else { + textView.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(textView) + NSLayoutConstraint.activate([ + // 中心约束 + textView.centerXAnchor.constraint(equalTo = contetDiv.centerXAnchor), + textView.centerYAnchor.constraint(equalTo = contetDiv.centerYAnchor), + + ]) + } + + + + + contetDiv.translatesAutoresizingMaskIntoConstraints = false + maskerDom!.addSubview(contetDiv) + + if(config.position == 'top'){ + NSLayoutConstraint.activate([ + // 中心约束 + contetDiv.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + contetDiv.topAnchor.constraint(equalTo = maskerDom!.safeAreaLayoutGuide.topAnchor, constant = new CGFloat(config.offset!)), + // 宽约束100 + contetDiv.widthAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(config.size!)), + contetDiv.widthAnchor.constraint(lessThanOrEqualToConstant = cg.width-32), + + ]) + }else if(config.position == 'bottom'){ + NSLayoutConstraint.activate([ + // 中心约束 + contetDiv.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + contetDiv.bottomAnchor.constraint(equalTo = maskerDom!.safeAreaLayoutGuide.bottomAnchor, constant = new CGFloat((config.offset!) * -1)), + // 宽约束100 + contetDiv.widthAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(config.size!)), + contetDiv.widthAnchor.constraint(lessThanOrEqualToConstant = cg.width-32), + + ]) + } + + + parentView.addSubview(maskerDom!) + + if (config.duration == 0) return; + tid = setTimeout(function () { + tid = null; + hideTips() + }, (config.duration + 300).toInt()); + + }) +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/interface.uts b/uni_modules/x-tips-s/utssdk/interface.uts new file mode 100644 index 0000000..4dd5810 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/interface.uts @@ -0,0 +1,54 @@ +export type XTIPS_TYPE = { + iconColor?:string, + contentBgColor?:string, + maskBgColor?:string, + iconSize?:number, + /** + * 正常应该填写图标的16进制符号如:EEC4 + * 本组件允许几个状态名称使用默认图标,为空是info图标。 + * warn,error,success,info + */ + iconCode?:string, + /** + * 标题为空不显示。 + */ + title:string, + titleSize?:number, + titleColor?:string, + /** + * 几秒后消失,0 表示永不消失 + * @default 2000 + */ + duration?:number, + close?:()=>void, + /** 宽 */ + size?:number, + /** + * 禁用遮罩穿透点击事件 + * @default false + */ + maskDisableClik?:boolean, + position?:'top'|'bottom', + /** + * 偏移量 + * @default 50 + */ + offset?:number +} +export type XTIPS_TYPE_PRIVATE = { + iconColor:string, + contentBgColor:string, + maskBgColor:string, + iconSize:number, + iconCode:string, + title:string, + titleSize:number, + titleColor:string, + duration:number, + close:()=>void, + size:number, + maskDisableClik:boolean, + position:'top'|'bottom', + //偏移量 + offset:number +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/libs/color.uts b/uni_modules/x-tips-s/utssdk/libs/color.uts new file mode 100644 index 0000000..f27f07e --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/libs/color.uts @@ -0,0 +1,58 @@ +type RGBA = { r : number, g : number, b : number, a : number } +export function hexToRgb(sColors : string) : RGBA | null { + if (sColors == "") { + return null + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + let p : number[] = arr.map((val : string) : number => parseInt(val)); + + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + p.add(1) + + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: arr.length==3?p[3]:parseFloat(arr[3]) + } as RGBA + } + + return null; +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/libs/config.uts b/uni_modules/x-tips-s/utssdk/libs/config.uts new file mode 100644 index 0000000..23f17ef --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/libs/config.uts @@ -0,0 +1,65 @@ +import { XTIPS_TYPE, XTIPS_TYPE_PRIVATE } from "../interface.uts" +export const defaultConfig = { + iconColor: 'rgb(5,121,255)', + contentBgColor: 'rgba(255,255,255,1)', + maskBgColor: 'rgba(0,0,0,0)', + iconSize: 20, + iconCode: 'F449', + title: '', + titleSize: 16, + titleColor: 'rgb(5,121,255)', + duration: 2000, + size: 130, + close: () => { }, + + maskDisableClik: false, + position:'top', + offset:50 + +} as XTIPS_TYPE_PRIVATE + +export const defaultStatusIcon = new Map([ + ['warn', 'ECA1'], + ['error', 'EB97'], + ['success', 'EB79'], + ['info', 'F449'], +]) + +export function configCover(opts : XTIPS_TYPE) : XTIPS_TYPE_PRIVATE { + let iconColor = opts.iconColor != null ? (opts.iconColor!) : defaultConfig.iconColor; + let contentBgColor = opts.contentBgColor != null ? (opts.contentBgColor!) : defaultConfig.contentBgColor; + let maskBgColor = opts.maskBgColor != null ? (opts.maskBgColor!) : defaultConfig.maskBgColor; + let iconSize = opts.iconSize != null ? (opts.iconSize!) : defaultConfig.iconSize; + let iconCode : string = opts.iconCode != null ? (opts.iconCode!) : defaultConfig.iconCode; + if (defaultStatusIcon.has(iconCode)) { + iconCode = defaultStatusIcon.get(iconCode)! + } + let title = opts.title != null ? (opts.title!) : defaultConfig.title; + let titleSize = opts.titleSize != null ? (opts.titleSize!) : defaultConfig.titleSize; + let titleColor = opts.titleColor != null ? (opts.titleColor!) : defaultConfig.titleColor; + let duration = opts.duration != null ? (opts.duration!) : defaultConfig.duration; + let close = opts.close != null ? (opts.close!) : defaultConfig.close; + let size = opts.size != null ? (opts.size!) : defaultConfig.size; + let position = opts.position != null ? (opts.position!) : defaultConfig.position; + let offset = opts.offset != null ? (opts.offset!) : defaultConfig.offset; + let maskDisableClik = false; + + // #ifdef APP-ANDROID || APP-HARMONY + maskDisableClik = opts.maskDisableClik == null ? defaultConfig.maskDisableClik : (opts.maskDisableClik!); + // #endif + // #ifdef WEB + maskDisableClik = opts.maskDisableClik == null ? (defaultConfig.maskDisableClik) : (opts.maskDisableClik); + // #endif + + // #ifdef APP-IOS + maskDisableClik = opts.maskDisableClik == null ? (!defaultConfig.maskDisableClik) : (!opts.maskDisableClik); + // #endif + + return { + iconColor, + contentBgColor, + maskBgColor, + iconSize, + iconCode, title, titleSize, titleColor, duration, close, size, maskDisableClik,position,offset + } as XTIPS_TYPE_PRIVATE +} \ No newline at end of file diff --git a/uni_modules/x-tips-s/utssdk/web/index.uts b/uni_modules/x-tips-s/utssdk/web/index.uts new file mode 100644 index 0000000..1126e00 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/web/index.uts @@ -0,0 +1,150 @@ +export { XTIPS_TYPE, XTIPS_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { LoadFontFace } from "./loadFont.uts" +let maskerDom : null | HTMLDivElement = null; +let tid:number|null = 0 +let currentOpts:XTIPS_TYPE | null = null; +export const hideTips = () => { + if (maskerDom != null) { + maskerDom.remove() + } + if(tid!=null){ + clearTimeout(tid!) + } + currentOpts?.close?.() +} +// @ts-ignore +export const showTips = (opts : XTIPS_TYPE | null) => { + LoadFontFace() + currentOpts = opts; + if(tid!=null){ + clearTimeout(tid!) + tid=null; + } + if (maskerDom != null) { + maskerDom.remove() + } + // @ts-ignore + let realopts = opts == null ? ({} as XTIPS_TYPE) : (opts!) + let config = configCover(realopts) + + maskerDom = document.createElement("div") + if (maskerDom == null) return; + maskerDom.style.setProperty("background-color", config.maskBgColor) + maskerDom.style.setProperty("position", "fixed") + maskerDom.style.setProperty("left", "0px") + maskerDom.style.setProperty("top", "0px") + maskerDom.style.setProperty("width", "100%") + maskerDom.style.setProperty("height", "100%") + maskerDom.style.display = "flex" + maskerDom.style.flexDirection = "row" + maskerDom.style.justifyContent = "center" + maskerDom.style.alignItems = config.position=='top'?'flex-start': "flex-end" + maskerDom.style.zIndex = "10000" + maskerDom.style.pointerEvents = config.maskDisableClik?'auto':"none" + + let contentWrapDiv = document.createElement("div") + contentWrapDiv.style.padding = "8px 16px" + contentWrapDiv.style.minWidth = config.size+"px" + contentWrapDiv.style.maxWidth = "414px" + if(config.position=='top'){ + contentWrapDiv.style.marginTop = config.offset+'px' + }else if(config.position=='bottom'){ + contentWrapDiv.style.marginBottom = config.offset+'px' + } + + // contentWrapDiv.style.height = "100px" + if((config.iconCode!=''&&config.title!='')||(config.iconCode!=''&&config.title=='')){ + contentWrapDiv.style.minHeight = (Math.max(config.iconSize,config.titleSize))+"px" + } + contentWrapDiv.style.backgroundColor = config.contentBgColor + contentWrapDiv.style.borderRadius = "8px" + contentWrapDiv.style.boxSizing = "border-box" + contentWrapDiv.style.display = "flex" + contentWrapDiv.style.flexDirection = "row" + contentWrapDiv.style.justifyContent = "center" + contentWrapDiv.style.alignItems = "center" + contentWrapDiv.style.lineHeight = "1" + contentWrapDiv.className = 'xShowToasScaleAnimation' + let textDiv = document.createElement("span") + if(config.iconCode!=''){ + textDiv.innerText = String.fromCharCode(parseInt(config.iconCode, 16)); + textDiv.style.fontFamily = "remixicon" + textDiv.style.fontSize = config.iconSize + "px" + textDiv.style.color = config.iconColor + textDiv.className = 'xShowToasAnimation' + } + + + var anistr = ` + .xShowToasAnimation{ + animation-name: xUiToastIconAni; + animation-duration: 1s; + animation-timing-function: cubic-bezier(.42,.38,.15,.93); + } + .xShowToasScaleAnimation{ + animation-name: xUiToastIconAniScale; + animation-duration: 0.3s; + animation-timing-function: cubic-bezier(.42,.38,.15,.93); + } + @keyframes xUiToastIconAni { + 0% { + transform: scale(0); + } + + 50% { + transform: scale(1.2); + } + 100% { + transform: scale(1); + } + } + @keyframes xUiToastIconAniScale { + 0% { + transform: scale(0); + opacity:0; + } + + 100% { + transform: scale(1); + opacity:1; + } + } + ` + var styleDIv = document.getElementById('xUiToastIcon'); + if (!styleDIv) { + let style = document.createElement("style"); + style.id = 'xUiLoadWeingIcon' + document.head.appendChild(style) + styleDIv = style; + } + let sheet = styleDIv.sheet; + if (sheet.cssRules.length == 0) { + styleDIv.append(anistr) + } + + contentWrapDiv.appendChild(textDiv) + + + if (config.title != '') { + let titleDiv = document.createElement("span") + titleDiv.innerText = config.title; + titleDiv.style.paddingLeft = '10px' + titleDiv.style.fontSize = config.titleSize + "px" + titleDiv.style.color = config.titleColor + contentWrapDiv.appendChild(titleDiv) + titleDiv.style.textAlign = "center" + titleDiv.style.wordBreak = "break-all" + + } + + maskerDom!.appendChild(contentWrapDiv) + window.document.body.appendChild(maskerDom!) + + if(config.duration==0) return; + tid = setTimeout(function() { + tid = null; + hideTips() + }, (config.duration)); +} + diff --git a/uni_modules/x-tips-s/utssdk/web/loadFont.uts b/uni_modules/x-tips-s/utssdk/web/loadFont.uts new file mode 100644 index 0000000..18e18b7 --- /dev/null +++ b/uni_modules/x-tips-s/utssdk/web/loadFont.uts @@ -0,0 +1,13 @@ +export function LoadFontFace(){ + // 定义字体 + // @ts-ignore + const font = new FontFace("remixicon", "url(/static/tmui4xLibs/static/remixicon.ttf)", { + style: "italic", + weight: "800", + stretch: "condensed", + }); + + // 把字体添加到 document.fonts(FontFaceSet)中 + document.fonts.add(font); + font.load(); +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/changelog.md b/uni_modules/x-toast-s/changelog.md new file mode 100644 index 0000000..203d392 --- /dev/null +++ b/uni_modules/x-toast-s/changelog.md @@ -0,0 +1,17 @@ +## 1.0.6(2025-08-17) +* 兼容原生鸿蒙 +## 1.0.5(2025-04-13) +* xToast在安卓,ios,web布局已更新为宽自动,并设定最大宽(之前宽是固定),方便在平板手机内容超多时自动断行及限定最大宽 +* 在安卓端并且会自动隐藏状态栏,并可以覆盖底部安全区域,还可以覆盖住官方的diaglo-page,做到真正的全覆盖 +* 补上close事件 +## 1.0.4(2025-02-23) +* 安卓端重新设定了动画参数,让打开显示的更自然.同时关闭逻辑改成了:当页面卸载或者超时跳转页面时,不会自动关闭上页的问题. +* ios端添加了显示动画,显示更自然 +## 1.0.3(2025-02-13) +* 兼容微信 +## 1.0.2(2024-09-12) +* 增加了maskDisableClik事件穿透,false表示允许穿透默认是true禁止事件穿透遮罩. +## 1.0.1(2024-09-06) +* 更新支持Uniapp +## 1.0.0(2024-08-06) +安卓,ios,web可用。 diff --git a/uni_modules/x-toast-s/package.json b/uni_modules/x-toast-s/package.json new file mode 100644 index 0000000..8124016 --- /dev/null +++ b/uni_modules/x-toast-s/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-toast-s", + "displayName": "TM-UI 4.0x全屏消息提醒覆盖任意界面", + "version": "1.0.6", + "description": "主要是用来代替uni.showToast", + "keywords": [ + "uts,uniappx,tmui,原生" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "1.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/readme.md b/uni_modules/x-toast-s/readme.md new file mode 100644 index 0000000..1f370e5 --- /dev/null +++ b/uni_modules/x-toast-s/readme.md @@ -0,0 +1,74 @@ +# x-toast-s + +### 特性说明 + +主要是用来代替uni.showToast的,相比优化有: + +1. 高自动适应,因此可以添加超长的title文字。 +2. 图标可以任意更新,大小,颜色等 +3. 可以添加title标题,允许改变字号,颜色 及背景 +4. 精致美观,可以定制界面达到与品牌相符的设计 +5. 可以重复打开,或者连续打开不用担心前一个是否关闭,我内部会检测关闭上一个提示。 + +**微信内使用官方的弹层,大多属性无效,只有同官方的属性会生效** + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 开发文档 + +**浏览器端需要你把目录中的```remixicon.ttf```复制到static目录下** + +调用: +```ts +import { showToast,XTOAST_TYPE } from "@/uni_modules/x-toast-s" +// 打开提示 +showToast({title:"提示消息"} as XTOAST_TYPE) +// 手动隐藏 +hideToast() +``` + +参数配置: + +下面的图标iconCode,同组件库x-icon是相同的字体图标,请打开图标网站:[查看](https://remixicon.com/) +找到直接想要的图标后 复制 unicode ,不是名称。比如:我们只要取ED29 +下面的参数图标iconCode就是ED29 **iconCode:'ED29'** + +**XLOADINGS_TYPE** +```ts +// 所有参数都是可选的, 但标题是必选。 +export type XTOAST_TYPE = { + iconColor?:string, + contentBgColor?:string, + maskBgColor?:string, + iconSize?:number, + /** + * 正常应该填写图标的16进制符号如:EEC4 + * 本组件允许几个状态名称使用默认图标,为空是info图标。 + * warn,error,success,info + */ + iconCode?:string, + /** + * 标题为空不显示。 + */ + title:string, + titleSize?:number, + titleColor?:string, + /** + * 几秒后消失,0 表示永不消失 + */ + duration?:number, + close?:()=>void, + /** 宽 */ + size?:number, + /** + * 禁用遮罩穿透点击事件 + * @default true + */ + maskDisableClik?:boolean +} + +``` \ No newline at end of file diff --git a/uni_modules/x-toast-s/remixicon.ttf b/uni_modules/x-toast-s/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-toast-s/remixicon.ttf differ diff --git a/uni_modules/x-toast-s/toast.png b/uni_modules/x-toast-s/toast.png new file mode 100644 index 0000000..e312a71 Binary files /dev/null and b/uni_modules/x-toast-s/toast.png differ diff --git a/uni_modules/x-toast-s/utssdk/app-android/assets/remixicon.ttf b/uni_modules/x-toast-s/utssdk/app-android/assets/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-toast-s/utssdk/app-android/assets/remixicon.ttf differ diff --git a/uni_modules/x-toast-s/utssdk/app-android/config.json b/uni_modules/x-toast-s/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/app-android/index.uts b/uni_modules/x-toast-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..f71b6af --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-android/index.uts @@ -0,0 +1,319 @@ +import LinearLayout from 'android.widget.LinearLayout'; +import Context from 'android.content.Context' +import RelativeLayout from 'android.widget.RelativeLayout'; +import ViewGroup from 'android.view.ViewGroup'; +import View from 'android.view.View'; +import { XTOAST_TYPE, XTOAST_TYPE_PRIVATE } from "../interface.uts" +import Color from 'android.graphics.Color'; +import Gravity from 'android.view.Gravity'; +import GradientDrawable from 'android.graphics.drawable.GradientDrawable'; +import TextView from 'android.widget.TextView'; +import Typeface from 'android.graphics.Typeface'; +import TextUtils from 'android.text.TextUtils'; +import Uri from 'android.net.Uri'; +import ObjectAnimator from 'android.animation.ObjectAnimator'; +import ValueAnimator from 'android.animation.ValueAnimator'; +import TimeInterpolator from 'android.animation.TimeInterpolator'; +import MotionEvent from 'android.view.MotionEvent'; +import { hexToRgb } from "../libs/color.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import ViewPropertyAnimator from 'android.view.ViewPropertyAnimator'; +import AccelerateDecelerateInterpolator from 'android.view.animation.AccelerateDecelerateInterpolator'; +// #ifdef UNI-APP-X +import getCurrentPages from 'io.dcloud.uniapp.framework.getCurrentPages'; +import onReady from 'io.dcloud.uniapp.framework.onReady'; +import onUnload from 'io.dcloud.uniapp.framework.onUnload'; +import onShow from 'io.dcloud.uniapp.framework.onShow'; +import MeasureSpec from 'android.view.View.MeasureSpec'; +// #endif +import AttributeSet from 'android.util.AttributeSet'; +import R from 'android.R'; +import Bundle from "android.os.Bundle"; +import Dialog from "android.app.Dialog"; +import WindowManager from "android.view.WindowManager"; +import Window from "android.view.Window"; +import ColorDrawable from "android.graphics.drawable.ColorDrawable"; + + +let tid : number | null = 0 +let maskDomId = 588 + +class MaxWidthLinearLayout extends LinearLayout { + private mMaxWidth = 300; + + constructor(context:Context) { + super(context); + } + + setMaximumWidth(maxWidth:Int) { + this.mMaxWidth = maxWidth; + this.requestLayout(); + } + + override onMeasure(widthMeasureSpec:Int , heightMeasureSpec:Int ) { + let widthSize = MeasureSpec.getSize(widthMeasureSpec); + + if (this.mMaxWidth > 0 && this.mMaxWidth < widthSize) { + let widthMode = MeasureSpec.getMode(widthMeasureSpec); + widthMeasureSpec = MeasureSpec.makeMeasureSpec(this.mMaxWidth.toInt(), widthMode); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } +} + + +let dialogModal : FullScreenDialogFragment | null = null; +class FullScreenDialogFragment extends Dialog { + private mContext : Context; + private opts : XTOAST_TYPE|null = null; + private maskeDom:RelativeLayout|null = null; + constructor(context : Context, optsOwer : XTOAST_TYPE|null) { + super(context,R.style.Theme_Translucent_NoTitleBar_Fullscreen); + this.mContext = context; + this.opts = optsOwer + } + override onCreate(savedInstanceState ?: Bundle) { + super.onCreate(savedInstanceState) + this.requestWindowFeature(Window.FEATURE_NO_TITLE) + // 禁止按键返回及侧滑返回. + this.setCancelable(false) + this.maskeDom = _createToastView(this.getContext(),this.window!.decorView! as ViewGroup,this.opts) + // 设置窗口属性 + let window = this.getWindow(); + if (window != null) { + // 首先设置全屏标志 + window.setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN + ); + + // 设置布局参数为全屏 + window.setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT + ); + + // 设置背景透明 + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + + window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + window.setGravity(Gravity.CENTER); + + // 完整的沉浸式设置 + let decorView = window.getDecorView(); + let option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + decorView.setSystemUiVisibility(option); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + window.setStatusBarColor(Color.TRANSPARENT) + window.setNavigationBarColor(Color.TRANSPARENT) + window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) + } + + } + override dismiss(){ + super.dismiss() + this.maskeDom = null; + if(this.opts!=null){ + let closeEvent = this.opts?.close??null + if(closeEvent!=null){ + closeEvent() + } + } + + dialogModal = null + } + +} + + +function px2dp(n : number) : number { + const mets = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics() + return mets.density * n +} + +export function hideToast() { + UTSAndroid.getDispatcher("main").async(function (_) { + dialogModal?.dismiss() + if (tid != null) { + clearTimeout(tid!) + } + }) +} +function __hideToast__(mainDialog:FullScreenDialogFragment | null) { + UTSAndroid.getDispatcher("main").async(function (_) { + mainDialog?.dismiss() + if (tid != null) { + clearTimeout(tid!) + } + }) +} +function _createToastView(context : Context, decorView : ViewGroup, opts : XTOAST_TYPE|null):RelativeLayout{ + + let realopts = opts == null ? ({ title: '' } as XTOAST_TYPE) : (opts!) + let config = configCover(realopts) + let rmbgColor = hexToRgb(config.maskBgColor); + let textColor = hexToRgb(config.iconColor); + let wrapColor = hexToRgb(config.contentBgColor); + let titleColorRgb = hexToRgb(config.titleColor); + + let mbgColor = rmbgColor == null ? Color.parseColor(config.maskBgColor) : Color.argb((rmbgColor!.a * 255).toInt(), rmbgColor!.r.toInt(), rmbgColor!.g.toInt(), rmbgColor!.b.toInt()) + let fontColor = textColor == null ? Color.parseColor(config.iconColor) : Color.argb((textColor!.a * 255).toInt(), textColor!.r.toInt(), textColor!.g.toInt(), textColor!.b.toInt()) + let contentColor = rmbgColor == null ? Color.parseColor(config.contentBgColor) : Color.argb((wrapColor!.a * 255).toInt(), wrapColor!.r.toInt(), wrapColor!.g.toInt(), wrapColor!.b.toInt()) + let titleColor = titleColorRgb == null ? Color.parseColor(config.titleColor) : Color.argb((titleColorRgb!.a * 255).toInt(), titleColorRgb!.r.toInt(), titleColorRgb!.g.toInt(), titleColorRgb!.b.toInt()) + + + let maskerDom = new RelativeLayout(context) + + class MaskerDomClickListsner extends View.OnTouchListener { + constructor() { + super(); + } + override onTouch(view : View, event : MotionEvent) : Boolean { + // 阻止事件向下传递。 + return config.maskDisableClik; + } + } + + maskerDom.setOnTouchListener(new MaskerDomClickListsner()) + + let maskerDomLayrPrams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + maskerDom.setLayoutParams(maskerDomLayrPrams) + maskerDom.setBackgroundColor(mbgColor) + + + maskerDom.setGravity(Gravity.CENTER) + maskerDom.setId((maskDomId).toInt()) + + + let contentWrapDiv = new MaxWidthLinearLayout(context); + // 设置圆角背景 + let bg = new GradientDrawable() + bg.setColor(contentColor) + bg.setCornerRadius((px2dp(16)).toFloat()) + contentWrapDiv.setBackground(bg) + // contentWrapDiv.setBackgroundColor(Color.parseColor(config.contentBgColor)) + let wpx = px2dp(config.size).toInt(); + let contentWrapDivParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + // contentWrapDivParams.width = px2dp(500).toInt();; + const maxwidthbody = UTSAndroid.getAppContext()!.resources!.getDisplayMetrics().widthPixels + contentWrapDiv.setMaximumWidth((Math.min((maxwidthbody-px2dp(80)),px2dp(320))).toInt()) + contentWrapDiv.setMinimumHeight(wpx) + contentWrapDiv.setMinimumWidth(wpx) + contentWrapDiv.setLayoutParams(contentWrapDivParams) + + + if ((config.iconCode != '' && config.title != '') || (config.iconCode != '' && config.title == '')) { + contentWrapDiv.setMinimumHeight(wpx) + } else { + wpx = px2dp(32 + config.titleSize).toInt(); + contentWrapDiv.setMinimumHeight(wpx) + } + let wpadingx = px2dp(16).toInt(); + contentWrapDiv.setPadding(wpadingx, wpadingx, wpadingx, wpadingx) + contentWrapDiv.setGravity(Gravity.CENTER) + contentWrapDiv.setOrientation(LinearLayout.VERTICAL) + // 创建图标。 + let iconDiv = new TextView(context) + // iconDiv.setLineHeight(1) + iconDiv.setTextColor(fontColor) + let assetManager = context!.getAssets(); + let typeface = Typeface.createFromAsset(assetManager, "remixicon.ttf") + iconDiv.setTypeface(typeface) + iconDiv.setGravity(Gravity.CENTER) + iconDiv.setTextSize(config.iconSize.toFloat()) + if (!TextUtils.isEmpty(config.iconCode) && config.iconCode != '') { + let codePoint = Integer.parseInt(config.iconCode, 16); + let charArray = Character.toChars(codePoint); + let text = new String(charArray); + iconDiv.setText(text); + contentWrapDiv.addView(iconDiv) + } + + if (config.title != "") { + // 添加一个title + let titleDiv = new TextView(context) + titleDiv.setText(config.title) + titleDiv.setTextSize((config.titleSize).toFloat()) + titleDiv.setTextColor(titleColor) + titleDiv.setGravity(Gravity.CENTER) + contentWrapDiv.addView(titleDiv) + } + maskerDom.setAlpha((0).toFloat()) + maskerDom.addView(contentWrapDiv) + decorView.addView(maskerDom!) + try { + let s0 = (0).toFloat() + let s1 = (1).toFloat() + contentWrapDiv.setAlpha(s0) + contentWrapDiv.setScaleX(s0) + contentWrapDiv.setScaleY(s0) + + // 遮罩渐变 + const maskAni = maskerDom.animate() as ViewPropertyAnimator; + maskAni.alpha(s1) + .setDuration(300) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + + let ani = contentWrapDiv.animate() as ViewPropertyAnimator; + ani.alpha(s1) + .scaleX(s1) + .scaleY(s1) + .setDuration(300) + .setInterpolator(AccelerateDecelerateInterpolator()) + .start() + } catch (e) { + //TODO handle the exception + } + + if (config.duration == 0) return maskerDom + tid = setTimeout(function () { + tid = null; + __hideToast__(dialogModal) + }, (config.duration + 300).toInt()); + + return maskerDom + +} +function _showToast_(opts : XTOAST_TYPE | null) { + if (tid != null) { + clearTimeout(tid!) + } + dialogModal = new FullScreenDialogFragment(UTSAndroid.getUniActivity()!,opts) + UTSAndroid.getDispatcher("main").async(function (_) { + dialogModal?.show() + }) +} + +export function showToast(opts : XTOAST_TYPE | null) { + // hideToast() + dialogModal?.dismiss() + const pages = getCurrentPages(); + if (pages.length > 0) { + const page = pages[pages.length - 1].vm! + const instance = page.$ + + if (page.$isReady) { + + _showToast_(opts) + // onShow(()=>{ + // console.log('on show page') + // },instance) + // onReady(() => { + // console.log('on ready page') + // }, instance) + } else { + hideToast() + } + onUnload(() => { + hideToast() + }, instance) + }else{ + _showToast_(opts) + } +} + + diff --git a/uni_modules/x-toast-s/utssdk/app-harmony/config.json b/uni_modules/x-toast-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..9b0068f --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_toast_s": "./lib/x_toast_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/app-harmony/index.uts b/uni_modules/x-toast-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..eebb38c --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-harmony/index.uts @@ -0,0 +1,14 @@ +import { XTOAST_TYPE, XTIPS_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { hexToRgb } from "../libs/color.uts" +import { xshowtoasts,xhidetoasts } from "x_toast_s"; + + + +export const hideToast = () => { + xhidetoasts(UTSHarmony.getCurrentWindow()!.getUIContext()) +} +export function showToast(opts : XTOAST_TYPE|null) { + let config = configCover(opts==null ? ({} as XTOAST_TYPE) : (opts!)) + xshowtoasts(UTSHarmony.getCurrentWindow()!.getUIContext(),config) +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/app-harmony/lib/x_toast_s.har b/uni_modules/x-toast-s/utssdk/app-harmony/lib/x_toast_s.har new file mode 100644 index 0000000..d02db1d Binary files /dev/null and b/uni_modules/x-toast-s/utssdk/app-harmony/lib/x_toast_s.har differ diff --git a/uni_modules/x-toast-s/utssdk/app-ios/Info.plist b/uni_modules/x-toast-s/utssdk/app-ios/Info.plist new file mode 100644 index 0000000..1dd21fc --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-ios/Info.plist @@ -0,0 +1,10 @@ + + + + + UIAppFonts + + remixicon.ttf + + + \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-toast-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-toast-s/utssdk/app-ios/Resources/remixicon.ttf b/uni_modules/x-toast-s/utssdk/app-ios/Resources/remixicon.ttf new file mode 100644 index 0000000..22ce6de Binary files /dev/null and b/uni_modules/x-toast-s/utssdk/app-ios/Resources/remixicon.ttf differ diff --git a/uni_modules/x-toast-s/utssdk/app-ios/config.json b/uni_modules/x-toast-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-toast-s/utssdk/app-ios/index.uts b/uni_modules/x-toast-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..218aab7 --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/app-ios/index.uts @@ -0,0 +1,243 @@ +import { XTOAST_TYPE, XTOAST_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { UIView, UIViewController, NSLayoutConstraint,UILayoutPriority, UITextView, UIFont, UILabel, NSTextAlignment, NSLineBreakMode , Distribution } from 'UIKit'; +import { CGRect, CGPoint, CGFloat, CGSize, CFDictionary } from 'CoreFoundation'; +import { CGSizeMake } from 'CoreGraphics'; +import { Alignment } from 'SwiftUI'; +import { UInt32, KeyPath } from 'Swift'; +import { NSString } from 'Foundation'; +import { CABasicAnimation, CAMediaTimingFunction, CAMediaTimingFunctionName } from 'QuartzCore'; +import { LessThanOrEqualToComparator } from 'AppIntents'; + +let maskerDom : null | UIView = null; +let tid : number | null = 0 +let globalOpts: XTOAST_TYPE | null = null; +export function hideToast() { + DispatchQueue.main.async(execute = () : void => { + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + } + if (tid != null) { + clearTimeout(tid!) + } + if(globalOpts!=null){ + let closeEvent = globalOpts?.close??null; + if(closeEvent!=null){ + closeEvent!() + } + } + }) +} + +export function showToast(opts : XTOAST_TYPE | null) { + globalOpts = opts; + DispatchQueue.main.async(execute = () : void => { + + if (tid != null) { + clearTimeout(tid!) + tid = null; + } + if (maskerDom != null) { + maskerDom!.removeFromSuperview() + } + let parent = UTSiOS.getCurrentViewController() as UIViewController; + let parentView = parent.view as UIView + + let realopts = opts == null ? ({} as XTOAST_TYPE) : (opts!) + let config = configCover(realopts) + + maskerDom = new UIView() + + // 允许遮罩穿透. + maskerDom!.isUserInteractionEnabled = !config.maskDisableClik; + + + if (maskerDom == null) return; + let cg = parentView.frame as CGRect + maskerDom!.frame = cg + maskerDom!.backgroundColor = UTSiOS.colorWithString(config.maskBgColor) + + let contetDiv = new UIView(); + contetDiv.layer.cornerRadius = 16 + contetDiv.layer.masksToBounds = true; + contetDiv.backgroundColor = UTSiOS.colorWithString(config.contentBgColor) + + + + let textView = new UILabel() + textView.frame = new CGRect(x = 0, y = 0, width = config.iconSize.toInt(), height = config.iconSize.toInt()) + textView.font = new UIFont(name = "remixicon", size = new CGFloat(config.iconSize)) + textView.textColor = UTSiOS.colorWithString(config.iconColor) + textView.textAlignment = NSTextAlignment.center + + if (config.iconCode != "") { + let codePoint = new UInt32(config.iconCode, radix = 16) + let stricon = new NSString(format = "%C", codePoint!) + textView.text = new String(stricon); + // 添加动画图标旋转 + let spinAni = new CABasicAnimation(keyPath = "transform.scale") + spinAni.fromValue = 0.4 + spinAni.toValue = 1 + spinAni.duration = 0.5 + textView.layer.add(spinAni, forKey = "scaleAnimation") + + // setTimeout(function () { + // spinAni.fromValue = 1.2 + // spinAni.toValue = 1 + // spinAni.duration = 0.5 + + // textView.layer.add(spinAni, forKey = "scaleAnimation") + // }, 200); + + } + + + + + + + // 添加内容缩放动画 + let scaleAni = new CABasicAnimation(keyPath = "transform.scale") + scaleAni.fromValue = 0 + scaleAni.toValue = 1 + scaleAni.duration = 0.3 + scaleAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + contetDiv.layer.add(scaleAni, forKey = "scaleAnimation") + + let opacityAni = new CABasicAnimation(keyPath = "opacity") + opacityAni.fromValue = 0 + opacityAni.toValue = 1 + opacityAni.duration = 0.3 + opacityAni.timingFunction = new CAMediaTimingFunction(name = CAMediaTimingFunctionName.easeInEaseOut) + maskerDom!.layer.add(opacityAni, forKey = "opacityAnimation") + + + + + // 两个都不空 + if (config.title != "" && config.iconCode != "") { + + textView.translatesAutoresizingMaskIntoConstraints = false + + let titleView = new UILabel() + titleView.text = new String(config.title); + titleView.textAlignment = NSTextAlignment.center + titleView.lineBreakMode = NSLineBreakMode.byWordWrapping + titleView.numberOfLines = 0 + titleView.font = UIFont.systemFont(ofSize = new CGFloat(config.titleSize)) + titleView.textColor = UTSiOS.colorWithString(config.titleColor) + titleView.translatesAutoresizingMaskIntoConstraints = false + + + let contetDivWrap = new UIStackView(arrangedSubviews = [textView,titleView]) + contetDivWrap.axis = NSLayoutConstraint.Axis.vertical + contetDivWrap.distribution = UIStackView.Distribution.fill + contetDivWrap.alignment = UIStackView.Alignment.center + contetDivWrap.spacing = 5 + + contetDivWrap.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(contetDivWrap) + + + NSLayoutConstraint.activate([ + // 中心约束 + // contetDivWrap.centerXAnchor.constraint(equalTo = contetDiv.centerXAnchor), + contetDivWrap.centerYAnchor.constraint(equalTo = contetDiv.centerYAnchor), + // 左侧约束 + contetDivWrap.leadingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.leadingAnchor, constant = 16), + // 右侧约束 + contetDivWrap.trailingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.trailingAnchor, constant = -16), + contetDivWrap.topAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.topAnchor, constant = 16), + // contetDivWrap.bottomAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.bottomAnchor, constant = -16), + ]) + + + // 图标空,标题不空 + } else if (config.iconCode == "" && config.title != "") { + let titleView = new UILabel() + titleView.text = new String(config.title); + titleView.textAlignment = NSTextAlignment.center + titleView.lineBreakMode = NSLineBreakMode.byWordWrapping + titleView.numberOfLines = 0 + titleView.font = UIFont.systemFont(ofSize = new CGFloat(config.titleSize)) + titleView.textColor = UTSiOS.colorWithString(config.titleColor) + titleView.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(titleView) + NSLayoutConstraint.activate([ + // 顶部约束 + titleView.topAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.topAnchor, constant = 16), + titleView.bottomAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.bottomAnchor, constant = -16), + // 左侧约束 + titleView.leadingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.leadingAnchor, constant = 16), + // 右侧约束 + titleView.trailingAnchor.constraint(equalTo = contetDiv.safeAreaLayoutGuide.trailingAnchor, constant = -16) + ]) + // 图标不空,文字空。 + } else { + textView.translatesAutoresizingMaskIntoConstraints = false + contetDiv.addSubview(textView) + NSLayoutConstraint.activate([ + // 中心约束 + textView.centerXAnchor.constraint(equalTo = contetDiv.centerXAnchor), + textView.centerYAnchor.constraint(equalTo = contetDiv.centerYAnchor), + + ]) + } + + + + + + contetDiv.translatesAutoresizingMaskIntoConstraints = false + maskerDom!.addSubview(contetDiv) + if ((config.title != '' && config.iconCode != '')) { + + NSLayoutConstraint.activate([ + // 中心约束 + contetDiv.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + contetDiv.centerYAnchor.constraint(equalTo = maskerDom!.centerYAnchor), + // 宽大100 + contetDiv.widthAnchor.constraint(lessThanOrEqualToConstant = new CGFloat(Math.min(Number(cg.size.width)-80,320))), + // 最小100 + contetDiv.widthAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(config.size!)), + // 高为至少100 + contetDiv.heightAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(config.size!)) + ]) + }else if ((config.title == '' && config.iconCode != '')) { + NSLayoutConstraint.activate([ + // 中心约束 + contetDiv.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + contetDiv.centerYAnchor.constraint(equalTo = maskerDom!.centerYAnchor), + // 宽大100 + contetDiv.widthAnchor.constraint(lessThanOrEqualToConstant = new CGFloat(Math.min(Number(cg.size.width)-80,320))), + // 最小100 + contetDiv.widthAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(config.size!)), + // 高为至少100 + contetDiv.heightAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(config.size!)) + ]) + } else { + NSLayoutConstraint.activate([ + // 中心约束 + contetDiv.centerXAnchor.constraint(equalTo = maskerDom!.centerXAnchor), + contetDiv.centerYAnchor.constraint(equalTo = maskerDom!.centerYAnchor), + // 宽大100 + contetDiv.widthAnchor.constraint(lessThanOrEqualToConstant = new CGFloat(Math.min(Number(cg.size.width)-80,320))), + // 最小100 + contetDiv.widthAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(config.size!)), + // 高为至少100 + contetDiv.heightAnchor.constraint(greaterThanOrEqualToConstant = new CGFloat(32 + config.titleSize)) + ]) + } + + + + parentView.addSubview(maskerDom!) + + if (config.duration == 0) return; + tid = setTimeout(function () { + tid = null; + hideToast() + }, (config.duration + 200).toInt()); + + }) +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/interface.uts b/uni_modules/x-toast-s/utssdk/interface.uts new file mode 100644 index 0000000..7e04446 --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/interface.uts @@ -0,0 +1,44 @@ +export type XTOAST_TYPE = { + iconColor?:string, + contentBgColor?:string, + maskBgColor?:string, + iconSize?:number, + /** + * 正常应该填写图标的16进制符号如:EEC4 + * 本组件允许几个状态名称使用默认图标,为空是info图标。 + * warn,error,success,info + */ + iconCode?:string, + /** + * 标题为空不显示。 + */ + title:string, + titleSize?:number, + titleColor?:string, + /** + * 几秒后消失,0 表示永不消失 + */ + duration?:number, + close?:()=>void, + /** 宽 */ + size?:number, + /** + * 禁用遮罩穿透点击事件 + * @default true + */ + maskDisableClik?:boolean +} +export type XTOAST_TYPE_PRIVATE = { + iconColor:string, + contentBgColor:string, + maskBgColor:string, + iconSize:number, + iconCode:string, + title:string, + titleSize:number, + titleColor:string, + duration:number, + close:()=>void, + size:number, + maskDisableClik:boolean +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/libs/color.uts b/uni_modules/x-toast-s/utssdk/libs/color.uts new file mode 100644 index 0000000..f27f07e --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/libs/color.uts @@ -0,0 +1,58 @@ +type RGBA = { r : number, g : number, b : number, a : number } +export function hexToRgb(sColors : string) : RGBA | null { + if (sColors == "") { + return null + } + let reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/; + let sColor : string = sColors.toLowerCase(); + + if (sColor != '' && reg.test(sColor)) { + if (sColor.length == 4) { + let sColorNew = "#"; + for (let i = 1; i < 4; i += 1) { + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1)); + } + sColor = sColorNew; + } + + //处理六位的颜色值 + let sColorChange : number[] = []; + sColorChange.push(parseInt(sColor.substring(1, 3), 16)); + sColorChange.push(parseInt(sColor.substring(3, 5), 16)); + sColorChange.push(parseInt(sColor.substring(5, 7), 16)); + if (sColor.length == 9) { + sColorChange.push(parseInt(sColor.substring(7, 9), 16) / 255); + } + return { + r: sColorChange[0], + g: sColorChange[1], + b: sColorChange[2], + a: sColorChange.length == 4 ? sColorChange[3] : 1 + } as RGBA + } else if (/^(rgb|RGB|rgba|RGBA)/.test(sColor)) { + let arr : string[] = sColor.replace(/(?:\(|\)|rgba|rgb|RGB|RGBA)*/g, "").split(",") + let p : number[] = arr.map((val : string) : number => parseInt(val)); + + if (p.length < 3) { + return { + r: 0, + g: 0, + b: 0, + a: 1 + } as RGBA + } + if (p.length == 3) { + p.add(1) + + } + + return { + r: p[0], + g: p[1], + b: p[2], + a: arr.length==3?p[3]:parseFloat(arr[3]) + } as RGBA + } + + return null; +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/libs/config.uts b/uni_modules/x-toast-s/utssdk/libs/config.uts new file mode 100644 index 0000000..c1ce77d --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/libs/config.uts @@ -0,0 +1,62 @@ +import { XTOAST_TYPE, XTOAST_TYPE_PRIVATE } from "../interface.uts" +export const defaultConfig = { + iconColor:'rgb(5,121,255)', + contentBgColor:'rgba(255,255,255,1)', + maskBgColor:'rgba(0,0,0,0.6)', + iconSize:52, + iconCode:'F449', + title:'', + titleSize:14, + titleColor:'rgb(5,121,255)', + duration:2000, + size:130, + close:()=>{}, + + maskDisableClik:true + +} as XTOAST_TYPE_PRIVATE + +export const defaultStatusIcon = new Map([ + ['warn','ECA1'], + ['error','EB97'], + ['success','EB79'], + ['info','F449'], +]) + +export function configCover(opts : XTOAST_TYPE) : XTOAST_TYPE_PRIVATE { + let iconColor = opts.iconColor != null ? (opts.iconColor!) : defaultConfig.iconColor; + let contentBgColor = opts.contentBgColor != null ? (opts.contentBgColor!) : defaultConfig.contentBgColor; + let maskBgColor = opts.maskBgColor != null ? (opts.maskBgColor!) : defaultConfig.maskBgColor; + let iconSize = opts.iconSize != null ? (opts.iconSize!) : defaultConfig.iconSize; + let iconCode:string = opts.iconCode != null ? (opts.iconCode!) : defaultConfig.iconCode; + if(defaultStatusIcon.has(iconCode)){ + iconCode = defaultStatusIcon.get(iconCode)! + } + let title = opts.title != null ? (opts.title!) : defaultConfig.title; + let titleSize = opts.titleSize != null ? (opts.titleSize!) : defaultConfig.titleSize; + let titleColor = opts.titleColor != null ? (opts.titleColor!) : defaultConfig.titleColor; + let duration = opts.duration != null ? (opts.duration!) : defaultConfig.duration; + let close = opts.close != null ? (opts.close!) : defaultConfig.close; + let size = opts.size != null ? (opts.size!) : defaultConfig.size; + let maskDisableClik = true; + + // #ifdef APP-ANDROID + maskDisableClik = opts.maskDisableClik==null?defaultConfig.maskDisableClik:(opts.maskDisableClik!); + // #endif + // #ifdef WEB||MP + maskDisableClik = opts.maskDisableClik==null?(defaultConfig.maskDisableClik):(opts.maskDisableClik); + // #endif + + // #ifdef APP-IOS + maskDisableClik = opts.maskDisableClik==null?(!defaultConfig.maskDisableClik):(!opts.maskDisableClik); + // #endif + + return { + iconColor, + contentBgColor, + maskBgColor, + iconSize, + iconCode,title,titleSize,titleColor,duration,close,size,maskDisableClik + } as XTOAST_TYPE_PRIVATE +} + diff --git a/uni_modules/x-toast-s/utssdk/mp-weixin/index.uts b/uni_modules/x-toast-s/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..b579cf1 --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/mp-weixin/index.uts @@ -0,0 +1,33 @@ +import { configCover } from "../libs/config.uts" +export { XTOAST_TYPE, XTOAST_TYPE_PRIVATE } from "../interface.uts" +let globalOpts:any | null = null; +export const hideToast = () => { + uni.hideToast() + globalOpts?.close(); +} + +export const showToast = (opts : any) => { + hideToast() + const config = configCover(opts) + globalOpts = config; + let title = config.title || config.content; + if(title){ + wx.showToast({ + title: config.title || config.content, + icon: config.iconCode || 'none', + duration: config.duration, + success(){ + globalOpts?.close(); + } + }) + }else{ + wx.showToast({ + icon: config.iconCode || 'success', + duration: config.duration, + success(){ + globalOpts?.close(); + } + }) + } + +} \ No newline at end of file diff --git a/uni_modules/x-toast-s/utssdk/web/index.uts b/uni_modules/x-toast-s/utssdk/web/index.uts new file mode 100644 index 0000000..e5b9a1b --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/web/index.uts @@ -0,0 +1,144 @@ +export { XTOAST_TYPE, XTOAST_TYPE_PRIVATE } from "../interface.uts" +import { defaultConfig, configCover } from "../libs/config.uts" +import { LoadFontFace } from "./loadFont.uts" +let maskerDom : null | HTMLDivElement = null; +let tid:number|null = 0 +let globalOpts:XTOAST_TYPE | null = null; + +export const hideToast = () => { + if (maskerDom != null) { + maskerDom.remove() + } + if(tid!=null){ + clearTimeout(tid!) + } + globalOpts?.close?.() +} + +export const showToast = (opts : XTOAST_TYPE | null) => { + hideToast() + globalOpts = opts; + LoadFontFace() + if(tid!=null){ + clearTimeout(tid!) + tid=null; + } + if (maskerDom != null) { + maskerDom.remove() + } + let realopts = opts == null ? ({} as XTOAST_TYPE) : (opts!) + let config = configCover(realopts) + + maskerDom = document.createElement("div") + if (maskerDom == null) return; + maskerDom.style.setProperty("background-color", config.maskBgColor) + maskerDom.style.setProperty("position", "fixed") + maskerDom.style.setProperty("left", "0px") + maskerDom.style.setProperty("top", "0px") + maskerDom.style.setProperty("width", "100%") + maskerDom.style.setProperty("height", "100%") + maskerDom.style.display = "flex" + maskerDom.style.flexDirection = "row" + maskerDom.style.justifyContent = "center" + maskerDom.style.alignItems = "center" + maskerDom.style.zIndex = "10000" + maskerDom.style.pointerEvents = config.maskDisableClik?'auto':"none" + + let contentWrapDiv = document.createElement("div") + contentWrapDiv.style.padding = "16px" + contentWrapDiv.style.minWidth = config.size+"px" + let maxwidth = window.innerWidth; + contentWrapDiv.style.maxWidth = Math.min((maxwidth-40),320)+'px' + // contentWrapDiv.style.height = "100px" + if((config.iconCode!=''&&config.title!='')||(config.iconCode!=''&&config.title=='')){ + contentWrapDiv.style.minHeight = config.size+"px" + } + contentWrapDiv.style.backgroundColor = config.contentBgColor + contentWrapDiv.style.borderRadius = "16px" + contentWrapDiv.style.boxSizing = "border-box" + contentWrapDiv.style.display = "flex" + contentWrapDiv.style.flexDirection = "column" + contentWrapDiv.style.justifyContent = "center" + contentWrapDiv.style.alignItems = "center" + contentWrapDiv.className = 'xShowToasScaleAnimation' + let textDiv = document.createElement("span") + if(config.iconCode!=''){ + textDiv.innerText = String.fromCharCode(parseInt(config.iconCode, 16)); + textDiv.style.fontFamily = "remixicon" + textDiv.style.fontSize = config.iconSize + "px" + textDiv.style.color = config.iconColor + textDiv.className = 'xShowToasAnimation' + } + + + var anistr = ` + .xShowToasAnimation{ + animation-name: xUiToastIconAni; + animation-duration: 1s; + animation-timing-function: cubic-bezier(.42,.38,.15,.93); + } + .xShowToasScaleAnimation{ + animation-name: xUiToastIconAniScale; + animation-duration: 0.3s; + animation-timing-function: cubic-bezier(.42,.38,.15,.93); + } + @keyframes xUiToastIconAni { + 0% { + transform: scale(0); + } + + 50% { + transform: scale(1.2); + } + 100% { + transform: scale(1); + } + } + @keyframes xUiToastIconAniScale { + 0% { + transform: scale(0); + opacity:0; + } + + 100% { + transform: scale(1); + opacity:1; + } + } + ` + var styleDIv = document.getElementById('xUiToastIcon'); + if (!styleDIv) { + let style = document.createElement("style"); + style.id = 'xUiLoadWeingIcon' + document.head.appendChild(style) + styleDIv = style; + } + let sheet = styleDIv.sheet; + if (sheet.cssRules.length == 0) { + styleDIv.append(anistr) + } + + contentWrapDiv.appendChild(textDiv) + + + if (config.title != '') { + let titleDiv = document.createElement("span") + titleDiv.innerText = config.title; + titleDiv.style.fontSize = config.titleSize + "px" + titleDiv.style.color = config.titleColor + contentWrapDiv.appendChild(titleDiv) + titleDiv.style.textAlign = "center" + titleDiv.style.wordBreak = "break-all" + + } + + maskerDom!.appendChild(contentWrapDiv) + window.document.body.appendChild(maskerDom!) + + if(config.duration==0) return; + tid = setTimeout(function() { + tid = null; + hideToast() + }, (config.duration)); +} + diff --git a/uni_modules/x-toast-s/utssdk/web/loadFont.uts b/uni_modules/x-toast-s/utssdk/web/loadFont.uts new file mode 100644 index 0000000..18e18b7 --- /dev/null +++ b/uni_modules/x-toast-s/utssdk/web/loadFont.uts @@ -0,0 +1,13 @@ +export function LoadFontFace(){ + // 定义字体 + // @ts-ignore + const font = new FontFace("remixicon", "url(/static/tmui4xLibs/static/remixicon.ttf)", { + style: "italic", + weight: "800", + stretch: "condensed", + }); + + // 把字体添加到 document.fonts(FontFaceSet)中 + document.fonts.add(font); + font.load(); +} \ No newline at end of file diff --git a/uni_modules/x-translate-s/changelog.md b/uni_modules/x-translate-s/changelog.md new file mode 100644 index 0000000..d6ec301 --- /dev/null +++ b/uni_modules/x-translate-s/changelog.md @@ -0,0 +1,3 @@ +## 1.0.0(2024-12-18) +* 翻译,翻译前需要主动下载模型到本地(目前不支持离线模型或者说自己部署服务器模型,我还未破解出来),目前仅在有网的时候自行下载模型 +,下载后,断网可以离线使用,前提是要先下载模型. diff --git a/uni_modules/x-translate-s/package.json b/uni_modules/x-translate-s/package.json new file mode 100644 index 0000000..396e166 --- /dev/null +++ b/uni_modules/x-translate-s/package.json @@ -0,0 +1,83 @@ +{ + "id": "x-translate-s", + "displayName": "翻译插件各国语言翻译", + "version": "1.0.0", + "description": "通过谷歌大模型翻译,可以翻译多达56种语言文件", + "keywords": [ + "翻译,uts,tmui,插件" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "50.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "y" + }, + "client": { + "Vue": { + "vue2": "n", + "vue3": "y" + }, + "App": { + "app-android": "y", + "app-ios": "y", + "app-harmony": "n" + }, + "H5-mobile": { + "Safari": "n", + "Android Browser": "n", + "微信浏览器(Android)": "n", + "QQ浏览器(Android)": "n" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "n", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-translate-s/readme.md b/uni_modules/x-translate-s/readme.md new file mode 100644 index 0000000..30e53d9 --- /dev/null +++ b/uni_modules/x-translate-s/readme.md @@ -0,0 +1,52 @@ +# x-translate-s +### 开发文档 + +1. 目前使用前需要预下载离线模型文件才可以翻译 +2. 下载好后,断网也能离线翻译 +3. 如果想直接预置模型或者把模型文件部署到自己服务器上,我目前仅突破了ios端,安卓端目前我还没突破限制需要在线下载好才能离线翻译 +4. 翻译仅可轻量使用,不要用专业场景,因为翻译模型是把英文作为中介,再翻译到其它语种,这给翻译带来了不确定性和精确性,仅作为参考翻译使用. + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| x | 支持 | 支持 | x | x | + +### 使用 + +如果是安卓请务必打自定义基座,如果ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。 + + +```ts + + + + + +import { translate,checkTranslateModeDonload,downloadTranslateMode } from "@/uni_modules/x-translate-s" + + // 翻译 +const fanyi = () => { + translate(fanyitext.value,'zh','ja',(str:string)=>{ + console.log('success:',str) + }) +} +//检查模型下载情况 +const checkmode = ()=>{ + // let rootdir = uni.env.SANDBOX_PATH + 'Library/Application Support/com.google.mlkit.nl.translate' + checkTranslateModeDonload(['ja'] as string[],(result:boolean)=>{ + uni.showToast({ + title:result?"已经下载了模型":'没有下载' + }) + }) + +} + +// 下载语言 +const donloadGoogleMode = ()=>{ + downloadTranslateMode('zh','ja',(ok:boolean)=>{ + console.log('downloadn:',ok?'Ok':'Fail') + }) +} + +``` diff --git a/uni_modules/x-translate-s/utssdk/app-android/XTranslateUtil.kt b/uni_modules/x-translate-s/utssdk/app-android/XTranslateUtil.kt new file mode 100644 index 0000000..66538d2 --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-android/XTranslateUtil.kt @@ -0,0 +1,25 @@ +package uts.sdk.modules.utsXTranslateUtil +import io.dcloud.uts.console + +import com.google.mlkit.common.model.RemoteModelManager +import com.google.mlkit.nl.translate.TranslateRemoteModel +import com.google.mlkit.nl.translate.TranslateLanguage + + +object NativeCode { + fun getDownloadedModels(callback:(ArrayList)->Unit){ + val modelManager = RemoteModelManager.getInstance() + modelManager.getDownloadedModels(TranslateRemoteModel::class.java) + .addOnSuccessListener { models -> + val stringList = ArrayList() + for (item in models) { + stringList.add(item.getLanguage()) + } + callback(stringList) + } + .addOnFailureListener { + val stringList = ArrayList() + callback(stringList) + } + } +} \ No newline at end of file diff --git a/uni_modules/x-translate-s/utssdk/app-android/config.json b/uni_modules/x-translate-s/utssdk/app-android/config.json new file mode 100644 index 0000000..f8ae190 --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-android/config.json @@ -0,0 +1,6 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "com.google.mlkit:translate:17.0.3" + ] +} diff --git a/uni_modules/x-translate-s/utssdk/app-android/index.uts b/uni_modules/x-translate-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..1bf34b0 --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-android/index.uts @@ -0,0 +1,105 @@ +import RemoteModelManager from "com.google.mlkit.common.model.RemoteModelManager" +import DownloadConditions from "com.google.mlkit.common.model.DownloadConditions" +import LocalModel from "com.google.mlkit.common.model.LocalModel" +import TranslateRemoteModel from "com.google.mlkit.nl.translate.TranslateRemoteModel" +import TranslateLanguage from "com.google.mlkit.nl.translate.TranslateLanguage" +import TranslatorOptions from "com.google.mlkit.nl.translate.TranslatorOptions" +import Translation from "com.google.mlkit.nl.translate.Translation" +import NativeCode from "uts.sdk.modules.utsXTranslateUtil.NativeCode" +import Kotlin from 'kotlin.jvm.internal.Intrinsics.Kotlin'; +import Context from 'android.content.Context'; +function getTranslatorOpts(lang : string, target : string) : TranslatorOptions { + let langopts = new Map([ + ['zh', TranslateLanguage.CHINESE],//中文 + ['en', TranslateLanguage.ENGLISH],//英语 + ['ja', TranslateLanguage.JAPANESE],//日本 + ['de', TranslateLanguage.GERMAN],//德国 + ['fr', TranslateLanguage.FRENCH],//法国 + ['ko', TranslateLanguage.KOREAN],//韩国 + ['ru', TranslateLanguage.RUSSIAN],//俄罗斯 + ['it', TranslateLanguage.ITALIAN],//意大利 + ['th', TranslateLanguage.THAI],//泰国 + ['vi', TranslateLanguage.VIETNAMESE],//越南语 + ['id', TranslateLanguage.INDONESIAN],//印度尼西亚 + ]) + let sou = langopts.get(lang)! + let targ = langopts.get(target)! + let options = TranslatorOptions.Builder() + .setSourceLanguage(sou) + .setTargetLanguage(targ) + .build() + + return options; + +} +export function checkTranslateModeDonload(lang : string[], callback : (inlang : boolean) => void) { + NativeCode.getDownloadedModels((str : ArrayList) => { + console.log(str) + let len = str.size + if (len == 0) { + callback(false) + return + } + let isin = lang.some((el : string) : boolean => str.contains(el)); + callback(isin) + }) + + let context = UTSAndroid.getAppContext() as Context; + let libdir = context.getCacheDir().getAbsolutePath() + '/no_backup' + console.log(libdir) +} +export function downloadTranslateMode(lang : string, target : string, call : (ok : boolean) => void) { + let options = getTranslatorOpts(lang, target) + let englishGermanTranslator = Translation.getClient(options) + // let modelManager = RemoteModelManager.getInstance() + // let germanModel = TranslateRemoteModel.Builder(TranslateLanguage.CHINESE).build() + // let conditions = DownloadConditions.Builder() + // .requireWifi() + // .build() + // modelManager.download(germanModel, conditions) + // .addOnSuccessListener((error) => { + // console.log('true', error) + // call(true) + // englishGermanTranslator.translate("我是谁") + // .addOnSuccessListener(translatedText=>{ + // console.log(translatedText) + // }) + // .addOnFailureListener(exception=>{ + + // }) + + // }) + // .addOnFailureListener((exception) => { + // console.log('false') + // call(false) + // }) + + // /data/user/0/uni.UNIA478431/cache + var conditions = DownloadConditions.Builder() + // .requireWifi() + .build() + // LocalModel.Builder().setAssetManifestFilePath(UTSAndroid.convert2AbsFullPath(modelpath)) + englishGermanTranslator.downloadModelIfNeeded(conditions) + .addOnSuccessListener((error) => { + console.log('true', error) + call(true) + }) + .addOnFailureListener((exception) => { + console.log('false') + call(false) + }) + +} + +export function translate(text : string, lang : string, target : string, callback : (str : string) => void) { + let options = getTranslatorOpts(lang, target) + let englishGermanTranslator = Translation.getClient(options) + englishGermanTranslator.translate(text) + .addOnSuccessListener((translatedText) => { + callback(translatedText) + }) + .addOnFailureListener((exception) => { + console.log('error', exception) + callback('') + }) +} \ No newline at end of file diff --git a/uni_modules/x-translate-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-translate-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/Info.plist b/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/Info.plist new file mode 100644 index 0000000..42b450c Binary files /dev/null and b/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/Info.plist differ diff --git a/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/generated_rapid_response_client_defaults.json b/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/generated_rapid_response_client_defaults.json new file mode 100644 index 0000000..2be54ed --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/generated_rapid_response_client_defaults.json @@ -0,0 +1,350 @@ +{ + "nl_translate_rapid_response_nmt_af_en": "", + "nl_translate_rapid_response_pbmt_af_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_af_en": "", + "nl_translate_rapid_response_nmt_en_af": "", + "nl_translate_rapid_response_pbmt_en_af": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_af": "", + "nl_translate_rapid_response_nmt_ar_en": "", + "nl_translate_rapid_response_pbmt_ar_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ar_en": "", + "nl_translate_rapid_response_nmt_en_ar": "", + "nl_translate_rapid_response_pbmt_en_ar": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ar": "", + "nl_translate_rapid_response_nmt_be_en": "", + "nl_translate_rapid_response_pbmt_be_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_be_en": "", + "nl_translate_rapid_response_nmt_en_be": "", + "nl_translate_rapid_response_pbmt_en_be": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_be": "", + "nl_translate_rapid_response_nmt_bg_en": "", + "nl_translate_rapid_response_pbmt_bg_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_bg_en": "", + "nl_translate_rapid_response_nmt_en_bg": "", + "nl_translate_rapid_response_pbmt_en_bg": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_bg": "", + "nl_translate_rapid_response_nmt_bn_en": "", + "nl_translate_rapid_response_pbmt_bn_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_bn_en": "", + "nl_translate_rapid_response_nmt_en_bn": "", + "nl_translate_rapid_response_pbmt_en_bn": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_bn": "", + "nl_translate_rapid_response_nmt_ca_en": "", + "nl_translate_rapid_response_pbmt_ca_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ca_en": "", + "nl_translate_rapid_response_nmt_en_ca": "", + "nl_translate_rapid_response_pbmt_en_ca": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ca": "", + "nl_translate_rapid_response_nmt_cs_en": "", + "nl_translate_rapid_response_pbmt_cs_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_cs_en": "", + "nl_translate_rapid_response_nmt_en_cs": "", + "nl_translate_rapid_response_pbmt_en_cs": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_cs": "", + "nl_translate_rapid_response_nmt_cy_en": "", + "nl_translate_rapid_response_pbmt_cy_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_cy_en": "", + "nl_translate_rapid_response_nmt_en_cy": "", + "nl_translate_rapid_response_pbmt_en_cy": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_cy": "", + "nl_translate_rapid_response_nmt_da_en": "", + "nl_translate_rapid_response_pbmt_da_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_da_en": "", + "nl_translate_rapid_response_nmt_en_da": "", + "nl_translate_rapid_response_pbmt_en_da": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_da": "", + "nl_translate_rapid_response_nmt_de_en": "", + "nl_translate_rapid_response_pbmt_de_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_de_en": "", + "nl_translate_rapid_response_nmt_en_de": "", + "nl_translate_rapid_response_pbmt_en_de": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_de": "", + "nl_translate_rapid_response_nmt_el_en": "", + "nl_translate_rapid_response_pbmt_el_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_el_en": "", + "nl_translate_rapid_response_nmt_en_el": "", + "nl_translate_rapid_response_pbmt_en_el": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_el": "", + "nl_translate_rapid_response_nmt_eo_en": "", + "nl_translate_rapid_response_pbmt_eo_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_eo_en": "", + "nl_translate_rapid_response_nmt_en_eo": "", + "nl_translate_rapid_response_pbmt_en_eo": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_eo": "", + "nl_translate_rapid_response_nmt_es_en": "", + "nl_translate_rapid_response_pbmt_es_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_es_en": "", + "nl_translate_rapid_response_nmt_en_es": "", + "nl_translate_rapid_response_pbmt_en_es": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_es": "", + "nl_translate_rapid_response_nmt_et_en": "", + "nl_translate_rapid_response_pbmt_et_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_et_en": "", + "nl_translate_rapid_response_nmt_en_et": "", + "nl_translate_rapid_response_pbmt_en_et": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_et": "", + "nl_translate_rapid_response_nmt_fa_en": "", + "nl_translate_rapid_response_pbmt_fa_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_fa_en": "", + "nl_translate_rapid_response_nmt_en_fa": "", + "nl_translate_rapid_response_pbmt_en_fa": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_fa": "", + "nl_translate_rapid_response_nmt_fi_en": "", + "nl_translate_rapid_response_pbmt_fi_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_fi_en": "", + "nl_translate_rapid_response_nmt_en_fi": "", + "nl_translate_rapid_response_pbmt_en_fi": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_fi": "", + "nl_translate_rapid_response_nmt_fr_en": "", + "nl_translate_rapid_response_pbmt_fr_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_fr_en": "", + "nl_translate_rapid_response_nmt_en_fr": "", + "nl_translate_rapid_response_pbmt_en_fr": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_fr": "", + "nl_translate_rapid_response_nmt_ga_en": "", + "nl_translate_rapid_response_pbmt_ga_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ga_en": "", + "nl_translate_rapid_response_nmt_en_ga": "", + "nl_translate_rapid_response_pbmt_en_ga": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ga": "", + "nl_translate_rapid_response_nmt_gl_en": "", + "nl_translate_rapid_response_pbmt_gl_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_gl_en": "", + "nl_translate_rapid_response_nmt_en_gl": "", + "nl_translate_rapid_response_pbmt_en_gl": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_gl": "", + "nl_translate_rapid_response_nmt_gu_en": "", + "nl_translate_rapid_response_pbmt_gu_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_gu_en": "", + "nl_translate_rapid_response_nmt_en_gu": "", + "nl_translate_rapid_response_pbmt_en_gu": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_gu": "", + "nl_translate_rapid_response_nmt_iw_en": "", + "nl_translate_rapid_response_pbmt_iw_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_iw_en": "", + "nl_translate_rapid_response_nmt_en_iw": "", + "nl_translate_rapid_response_pbmt_en_iw": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_iw": "", + "nl_translate_rapid_response_nmt_hi_en": "", + "nl_translate_rapid_response_pbmt_hi_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_hi_en": "", + "nl_translate_rapid_response_nmt_en_hi": "", + "nl_translate_rapid_response_pbmt_en_hi": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_hi": "", + "nl_translate_rapid_response_nmt_hr_en": "", + "nl_translate_rapid_response_pbmt_hr_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_hr_en": "", + "nl_translate_rapid_response_nmt_en_hr": "", + "nl_translate_rapid_response_pbmt_en_hr": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_hr": "", + "nl_translate_rapid_response_nmt_ht_en": "", + "nl_translate_rapid_response_pbmt_ht_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ht_en": "", + "nl_translate_rapid_response_nmt_en_ht": "", + "nl_translate_rapid_response_pbmt_en_ht": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ht": "", + "nl_translate_rapid_response_nmt_hu_en": "", + "nl_translate_rapid_response_pbmt_hu_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_hu_en": "", + "nl_translate_rapid_response_nmt_en_hu": "", + "nl_translate_rapid_response_pbmt_en_hu": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_hu": "", + "nl_translate_rapid_response_nmt_id_en": "", + "nl_translate_rapid_response_pbmt_id_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_id_en": "", + "nl_translate_rapid_response_nmt_en_id": "", + "nl_translate_rapid_response_pbmt_en_id": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_id": "", + "nl_translate_rapid_response_nmt_is_en": "", + "nl_translate_rapid_response_pbmt_is_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_is_en": "", + "nl_translate_rapid_response_nmt_en_is": "", + "nl_translate_rapid_response_pbmt_en_is": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_is": "", + "nl_translate_rapid_response_nmt_it_en": "", + "nl_translate_rapid_response_pbmt_it_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_it_en": "", + "nl_translate_rapid_response_nmt_en_it": "", + "nl_translate_rapid_response_pbmt_en_it": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_it": "", + "nl_translate_rapid_response_nmt_ja_en": "", + "nl_translate_rapid_response_pbmt_ja_en": "", + "nl_translate_rapid_response_stt_ja_en": "", + "nl_translate_rapid_response_nmt_en_ja": "", + "nl_translate_rapid_response_pbmt_en_ja": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ja": "", + "nl_translate_rapid_response_nmt_ka_en": "", + "nl_translate_rapid_response_pbmt_ka_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ka_en": "", + "nl_translate_rapid_response_nmt_en_ka": "", + "nl_translate_rapid_response_pbmt_en_ka": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ka": "", + "nl_translate_rapid_response_nmt_kn_en": "", + "nl_translate_rapid_response_pbmt_kn_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_kn_en": "", + "nl_translate_rapid_response_nmt_en_kn": "", + "nl_translate_rapid_response_pbmt_en_kn": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_kn": "", + "nl_translate_rapid_response_nmt_ko_en": "", + "nl_translate_rapid_response_pbmt_ko_en": "", + "nl_translate_rapid_response_stt_ko_en": "", + "nl_translate_rapid_response_nmt_en_ko": "", + "nl_translate_rapid_response_pbmt_en_ko": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ko": "", + "nl_translate_rapid_response_nmt_lt_en": "", + "nl_translate_rapid_response_pbmt_lt_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_lt_en": "", + "nl_translate_rapid_response_nmt_en_lt": "", + "nl_translate_rapid_response_pbmt_en_lt": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_lt": "", + "nl_translate_rapid_response_nmt_lv_en": "", + "nl_translate_rapid_response_pbmt_lv_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_lv_en": "", + "nl_translate_rapid_response_nmt_en_lv": "", + "nl_translate_rapid_response_pbmt_en_lv": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_lv": "", + "nl_translate_rapid_response_nmt_mk_en": "", + "nl_translate_rapid_response_pbmt_mk_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_mk_en": "", + "nl_translate_rapid_response_nmt_en_mk": "", + "nl_translate_rapid_response_pbmt_en_mk": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_mk": "", + "nl_translate_rapid_response_nmt_mr_en": "", + "nl_translate_rapid_response_pbmt_mr_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_mr_en": "", + "nl_translate_rapid_response_nmt_en_mr": "", + "nl_translate_rapid_response_pbmt_en_mr": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_mr": "", + "nl_translate_rapid_response_nmt_ms_en": "", + "nl_translate_rapid_response_pbmt_ms_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ms_en": "", + "nl_translate_rapid_response_nmt_en_ms": "", + "nl_translate_rapid_response_pbmt_en_ms": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ms": "", + "nl_translate_rapid_response_nmt_mt_en": "", + "nl_translate_rapid_response_pbmt_mt_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_mt_en": "", + "nl_translate_rapid_response_nmt_en_mt": "", + "nl_translate_rapid_response_pbmt_en_mt": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_mt": "", + "nl_translate_rapid_response_nmt_nl_en": "", + "nl_translate_rapid_response_pbmt_nl_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_nl_en": "", + "nl_translate_rapid_response_nmt_en_nl": "", + "nl_translate_rapid_response_pbmt_en_nl": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_nl": "", + "nl_translate_rapid_response_nmt_no_en": "", + "nl_translate_rapid_response_pbmt_no_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_no_en": "", + "nl_translate_rapid_response_nmt_en_no": "", + "nl_translate_rapid_response_pbmt_en_no": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_no": "", + "nl_translate_rapid_response_nmt_pl_en": "", + "nl_translate_rapid_response_pbmt_pl_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_pl_en": "", + "nl_translate_rapid_response_nmt_en_pl": "", + "nl_translate_rapid_response_pbmt_en_pl": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_pl": "", + "nl_translate_rapid_response_nmt_pt_en": "", + "nl_translate_rapid_response_pbmt_pt_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_pt_en": "", + "nl_translate_rapid_response_nmt_en_pt": "", + "nl_translate_rapid_response_pbmt_en_pt": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_pt": "", + "nl_translate_rapid_response_nmt_ro_en": "", + "nl_translate_rapid_response_pbmt_ro_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ro_en": "", + "nl_translate_rapid_response_nmt_en_ro": "", + "nl_translate_rapid_response_pbmt_en_ro": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ro": "", + "nl_translate_rapid_response_nmt_ru_en": "", + "nl_translate_rapid_response_pbmt_ru_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ru_en": "", + "nl_translate_rapid_response_nmt_en_ru": "", + "nl_translate_rapid_response_pbmt_en_ru": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ru": "", + "nl_translate_rapid_response_nmt_sk_en": "", + "nl_translate_rapid_response_pbmt_sk_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_sk_en": "", + "nl_translate_rapid_response_nmt_en_sk": "", + "nl_translate_rapid_response_pbmt_en_sk": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_sk": "", + "nl_translate_rapid_response_nmt_sl_en": "", + "nl_translate_rapid_response_pbmt_sl_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_sl_en": "", + "nl_translate_rapid_response_nmt_en_sl": "", + "nl_translate_rapid_response_pbmt_en_sl": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_sl": "", + "nl_translate_rapid_response_nmt_sq_en": "", + "nl_translate_rapid_response_pbmt_sq_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_sq_en": "", + "nl_translate_rapid_response_nmt_en_sq": "", + "nl_translate_rapid_response_pbmt_en_sq": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_sq": "", + "nl_translate_rapid_response_nmt_sv_en": "", + "nl_translate_rapid_response_pbmt_sv_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_sv_en": "", + "nl_translate_rapid_response_nmt_en_sv": "", + "nl_translate_rapid_response_pbmt_en_sv": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_sv": "", + "nl_translate_rapid_response_nmt_sw_en": "", + "nl_translate_rapid_response_pbmt_sw_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_sw_en": "", + "nl_translate_rapid_response_nmt_en_sw": "", + "nl_translate_rapid_response_pbmt_en_sw": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_sw": "", + "nl_translate_rapid_response_nmt_ta_en": "", + "nl_translate_rapid_response_pbmt_ta_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ta_en": "", + "nl_translate_rapid_response_nmt_en_ta": "", + "nl_translate_rapid_response_pbmt_en_ta": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ta": "", + "nl_translate_rapid_response_nmt_te_en": "", + "nl_translate_rapid_response_pbmt_te_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_te_en": "", + "nl_translate_rapid_response_nmt_en_te": "", + "nl_translate_rapid_response_pbmt_en_te": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_te": "", + "nl_translate_rapid_response_nmt_th_en": "", + "nl_translate_rapid_response_pbmt_th_en": "", + "nl_translate_rapid_response_stt_th_en": "", + "nl_translate_rapid_response_nmt_en_th": "", + "nl_translate_rapid_response_pbmt_en_th": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_th": "", + "nl_translate_rapid_response_nmt_tl_en": "", + "nl_translate_rapid_response_pbmt_tl_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_tl_en": "", + "nl_translate_rapid_response_nmt_en_tl": "", + "nl_translate_rapid_response_pbmt_en_tl": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_tl": "", + "nl_translate_rapid_response_nmt_tr_en": "Ch0KBXNpa21hEgRmdWNrGglzcXVlZXppbmclzczMPQogCgVzaWttYRIHZnVja2luZxoJc3F1ZWV6aW5nJc3MzD0\u003d", + "nl_translate_rapid_response_pbmt_tr_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_tr_en": "", + "nl_translate_rapid_response_nmt_en_tr": "", + "nl_translate_rapid_response_pbmt_en_tr": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_tr": "", + "nl_translate_rapid_response_nmt_uk_en": "", + "nl_translate_rapid_response_pbmt_uk_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_uk_en": "", + "nl_translate_rapid_response_nmt_en_uk": "", + "nl_translate_rapid_response_pbmt_en_uk": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_uk": "", + "nl_translate_rapid_response_nmt_ur_en": "", + "nl_translate_rapid_response_pbmt_ur_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_ur_en": "", + "nl_translate_rapid_response_nmt_en_ur": "", + "nl_translate_rapid_response_pbmt_en_ur": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_ur": "", + "nl_translate_rapid_response_nmt_vi_en": "", + "nl_translate_rapid_response_pbmt_vi_en": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_vi_en": "", + "nl_translate_rapid_response_nmt_en_vi": "", + "nl_translate_rapid_response_pbmt_en_vi": "CgIQAQ\u003d\u003d", + "nl_translate_rapid_response_stt_en_vi": "", + "nl_translate_rapid_response_nmt_zh_en": "", + "nl_translate_rapid_response_pbmt_zh_en": "", + "nl_translate_rapid_response_stt_zh_en": "", + "nl_translate_rapid_response_nmt_en_zh": "", + "nl_translate_rapid_response_pbmt_en_zh": "CgIQAQoICgYKBHBhcms\u003d", + "nl_translate_rapid_response_stt_en_zh": "" +} \ No newline at end of file diff --git a/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/profiles_r29.json b/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/profiles_r29.json new file mode 100644 index 0000000..9f58f3b --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-ios/Resources/MLKitTranslate_resource.bundle/profiles_r29.json @@ -0,0 +1 @@ +{"PKG_HIGH":{"af_en":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":34646224,"HASH":"0727292b4610a59bb598a9b6d99421baedb03d2b2702f020add5fea52de20033","RV":29,"SZ":44169505},"ar_en":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34953174,"HASH":"2d2685a5c4419a86d22533d1f06d4a18e068ac4ac2307e7b7e782c8b83ffdc28","RV":29,"SZ":44815755},"be_en":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":31722008,"HASH":"2499e87d4887690558954d57d7b5ab71e20d0b992b617e9299aa53142ce2b4b3","RV":29,"SZ":39497409},"bg_en":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":33617293,"HASH":"188ac2b77d7fa7219a1b66e52f3792924dab8063d447303d13fd086e085063ab","RV":29,"SZ":42692592},"bn_en":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":36345388,"HASH":"ce01d6ba3bca424549ca8af7ebd7d30ac50c76fd23530e27953679a6ec4e1faf","RV":29,"SZ":47980615},"ca_en":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34586112,"HASH":"116159addffea58457e97301313c14432a039fe883814628a97e48715a9cc961","RV":29,"SZ":43405294},"cs_en":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":32977989,"HASH":"630c96659997750d01541c1e08879b4f4ba01f1be7f9f8420b85126bd831a5b3","RV":29,"SZ":41511590},"cy_en":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33014146,"HASH":"b8c6c58e7aa253cb39afaae8f600e17504b0f0e3cfca4258eef889adcc781bd4","RV":29,"SZ":40925298},"da_en":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":35198211,"HASH":"c344f3f29fbea1a04a76d56b71da2b955c5bb6735162b04819051721b79a05f1","RV":29,"SZ":44717709},"de_en":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":36154421,"HASH":"2c35205bb4579850c09f1afd7b43e7c7ab9a5ece26e80233c7eb77d22ad91a92","RV":29,"SZ":46564399},"el_en":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":34040778,"HASH":"36b5db60d5e9a3c29203f36967c1127d51216c69f0064f995dfd5c621a73971c","RV":29,"SZ":43409415},"en_eo":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":32964696,"HASH":"1d4a068ab1d6e898496c2c5b07688775a6b029974fde666d5702af0792930828","RV":29,"SZ":41859343},"en_es":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":36128744,"HASH":"2aa7581e7e6fa36cf4e7aa2a55a70d8aab8f3c02c9e896ee9a7cd90552f710de","RV":29,"SZ":45311607},"en_et":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":32353113,"HASH":"2bfa68787f13bca1de9bc1753ad9587fb3b48b2aa38f696bcffe9d918644f04c","RV":29,"SZ":41339540},"en_fa":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":32405428,"HASH":"39603ed8f06fe81f0e21b26181145e163594df96cfbb375d9e6209472a46485c","RV":29,"SZ":39928876},"en_fi":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":33907543,"HASH":"ef297fda387746fa50c6420bd8a7ac4fda7292008d3da5c8d75c4bc02f9c72df","RV":29,"SZ":43376951},"en_fr":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":36104323,"HASH":"cd0765a2f5bf7222fd417f8f6b82c3c905adfcd912b2dc6cd1dd434090c035c7","RV":29,"SZ":45219919},"en_ga":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33439809,"HASH":"165ad0d3bd370fa78a731c3c1d45a6bc32a7169251f912834936d60a02022b01","RV":29,"SZ":41751669},"en_gl":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33896760,"HASH":"26a4a92c2e0f1fae992f075d309f6a49d71ebde4ddd21dbe1a53f78978699a69","RV":29,"SZ":43283920},"en_gu":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":35167225,"HASH":"71cbfacfbd4f24109745c6bc31a35d1cc203f01338b290b76862cc507fdd4b1b","RV":29,"SZ":45622671},"en_hi":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":35653801,"HASH":"0e48c20b9a7d1fb961a124589048f29b15bb010252f5707e690fbfd9b9fc3351","RV":29,"SZ":47231727},"en_hr":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":32967456,"HASH":"3ade06d96b0f06005c22b678a4d1b179f14f63ec298001da7acb1763fec61938","RV":29,"SZ":42376096},"en_ht":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":35565479,"HASH":"5476e038eac5f26e932aed520b04962b5549049c6a10d71c249616ccca72a2eb","RV":29,"SZ":45080786},"en_hu":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34009425,"HASH":"e99ae87f09e365a500fe7eb6b0f28054b9646ef2ca56ed8762ea4a329fb241a0","RV":29,"SZ":43411646},"en_id":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":38612958,"HASH":"5847ed76833667499a24e72541fbf3d426368d1485231f2c35ae5ae1b1e2b724","RV":29,"SZ":48373476},"en_is":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33250462,"HASH":"381e8ac9b25a169c7fa8fbd691cb02c015e90d38a333294b8d9b7f3340549b1f","RV":29,"SZ":42313693},"en_it":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34799539,"HASH":"9b0f6d7e3e888da144d21bc03d608015b8af6c908fa0549f4b6df5cf62de8bdc","RV":29,"SZ":43756004},"en_iw":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33610735,"HASH":"f5d8f7cae2d087041108e1fdea2c935eef62edafad76a3dbeac89f5cd2a87a3b","RV":29,"SZ":41087515},"en_ja":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":48033822,"HASH":"f9a05620aa07a142f2181cbc3bc045c821fbfecdaed697841be1b83b90bda131","RV":29,"SZ":63391975},"en_ka":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":31255269,"HASH":"53ad0707034eb16835906c96ca305f28783cd1b2a9ceedf4e44b4d7c21ad7082","RV":29,"SZ":40132904},"en_kn":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":34159231,"HASH":"6964a275364505b2978201b989466dc671d3ea78c31776ae8fb84fc485b96657","RV":29,"SZ":45769526},"en_ko":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":41381751,"HASH":"3665f086d01d15fd04938b4513493827c7d6f0ff096bdec3086b359a643a3f0a","RV":29,"SZ":52651545},"en_lt":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":32932408,"HASH":"471dd916c3fb692da8f99636082d6aa012e544e09fcac6ea4c3b8aebe94e40ad","RV":29,"SZ":41944336},"en_lv":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":32336537,"HASH":"310b28a0f75e7349c0e3a52b1f5b48de946ebb4354c4c78abd8cf8ec9bebb4c9","RV":29,"SZ":40713266},"en_mk":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":32671316,"HASH":"22f01316abdeba4794022c94611c18d55ea70cfdd8f22f2e696f263c09a73cc6","RV":29,"SZ":40910306},"en_mr":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":34694995,"HASH":"a51d2c108fdb940f1146075d5c865bbe581edc445913563f1587c6f8ec0c0a70","RV":29,"SZ":44844025},"en_ms":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":35454412,"HASH":"ab4165b69a4e935df16caf268b19c11dd88efc8721c2e4a0f090a0e098e8364e","RV":29,"SZ":44812042},"en_mt":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":34485110,"HASH":"0a8e84f2f54f39408b636bd64ff823da6ae82c57081cbf1b5a38abaf94f10397","RV":29,"SZ":43705367},"en_nl":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":35597265,"HASH":"33b2461c562edf977247978a05b7eb26646d8ab9b4c963f349779ae51582c7b4","RV":29,"SZ":45742163},"en_no":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":36192486,"HASH":"5a02edff20183cdc9667ecb60bb75ebea689a68895284af9cd4751cf7432161e","RV":29,"SZ":46297766},"en_pl":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34055132,"HASH":"0c4a612d50441e71f0cc8290382257e6393616608e9f0975b1fc93942a8e660e","RV":29,"SZ":42792686},"en_pt":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":37652526,"HASH":"f9b144406cf39f388a2c92b80aad8975a104216693fa0f1ddc19010cd232f4d0","RV":29,"SZ":48014671},"en_ro":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34004336,"HASH":"123d7d77a276c902e4a62347d8347e428e49a60d01755595e7453ac93f313a65","RV":29,"SZ":42533126},"en_ru":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":33018676,"HASH":"505ea55e47b5e2e53597895e40d44ffaeca8596a81e03611ce499995b8c72621","RV":29,"SZ":42194898},"en_sk":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34280742,"HASH":"024f6761b35df83634a0629f5f8c85a2a193e858a6616bab8de1ea445b63338c","RV":29,"SZ":43498195},"en_sl":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":32490322,"HASH":"9caa424fad34395d38bc1a64be91e0c038fcc87002f2f1abcd69c9b0fc61f04a","RV":29,"SZ":40657761},"en_sq":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33662485,"HASH":"49b7e66628f2897233f2e07a274eb1622f14aa33c6415534e611510db9218583","RV":29,"SZ":42872236},"en_sv":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":36040790,"HASH":"6c51aa6ce3b4ddd3215fad3ed89b19124e7af60ab0f4b076e550eeafca5a3a35","RV":29,"SZ":45759197},"en_sw":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33298576,"HASH":"ea90bac99fe4e92918da2a7854860b5fb10ebbd8fa9d8c5d0cce11b0c418d297","RV":29,"SZ":42075109},"en_ta":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":33101138,"HASH":"ed42192ae4a6f867f993d6ff666a1f2e2f7118d20cd14918697cdc1accc226ad","RV":29,"SZ":45000394},"en_te":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":34679360,"HASH":"48f5380e83cf6b2ad6abfc2d52fc2df10b2a33d1a094a22cafa10348beb6e7a1","RV":29,"SZ":45808004},"en_th":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":35159460,"HASH":"a40f37b262b8c44961efcebb748b74d6fa4e6920703b5fb96909e9b11f0fe1a4","RV":29,"SZ":46423111},"en_tl":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":34647510,"HASH":"c1f213997cbab1a2d2f5b6a64e71c0187088f63ef7958e8c02a9aa065252220d","RV":29,"SZ":45188760},"en_tr":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":35150909,"HASH":"48cd7ed4fcc391e98da6b6d283eaf145f2315d643fdc954fbfbf2ee02bd16f88","RV":29,"SZ":45206025},"en_uk":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":32255617,"HASH":"55ff89b4a3e9c4e14228eeb18119e9f7581154acf4aa5970d360b2b93b0ab99d","RV":29,"SZ":40529034},"en_ur":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":41735869,"HASH":"030134c695a07a2f33348df1114ca7af253024bd4bdcf1c057e702628ab13785","RV":29,"SZ":52942410},"en_vi":{"CAPS":{"L1":["NMT","TRANSLIT","L2"],"L2":["NMT","TRANSLIT","L1"]},"DL_SZ":35515032,"HASH":"fdfbcad433462f900daf5d06839b1ea70079aa8562290feb94b1095ec15cf8a3","RV":29,"SZ":45692325},"en_zh":{"CAPS":{"L1":["NMT","OCR","TRANSLIT","L2"],"L2":["NMT","OCR","TRANSLIT","L1"]},"DL_SZ":35347571,"HASH":"ab077c810b001d16667877d9fcda565a206718128a5163428ab5b6ace08936c4","RV":29,"SZ":45148168}},"PKG_LOW":{"ar_de":{"CAPS":{"L1":["TRANSLIT"],"L2":["OCR","TRANSLIT"]},"DL_SZ":1484625,"HASH":"fb126f9d433092d083dd317f7677c6be6fa7cc792cc6e8a3d12e1acd9c44ca90","RV":11,"SZ":3215517},"ar_en":{"CAPS":{"L1":["TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1528301,"HASH":"92a49afc6568d3ba038a2a2089aff4f1d8a5f95a389bbeba8c2ed370fa8ea1c8","RV":11,"SZ":2710079},"bg_en":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1556551,"HASH":"ae0b5c2a90afd09793fb91154f1fdc6596a8be8f66e7fb94a22adb950098bb29","RV":11,"SZ":3018782},"ca_en":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1610353,"HASH":"a886f7fca8b8ffd5261d4857b0176dfb690e2b59b318124a9a1253a8ee99e673","RV":11,"SZ":2992228},"cs_en":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1688512,"HASH":"6c1684524ef9cce8d2cd29f77e830422ec313c0134af8d5c6a4afdf1069fc9b9","RV":11,"SZ":3305115},"da_en":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1553439,"HASH":"875a1ef5c8da9f358b09f5b1fb9ebd2467a144a5575961d1a97cb3db45f219f8","RV":11,"SZ":2988982},"de_en":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":2217693,"HASH":"be8375ae1458201505779b5919ff3191d190eb08f8101a84a72234d634ba12ea","RV":11,"SZ":4492044},"en_es":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1201533,"HASH":"9b5c73d52f4c5a0ac0ce39218ea7b87a65f6cdffdf767c1ac59c2a36a33748c4","RV":11,"SZ":2478386},"en_fi":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1794682,"HASH":"2a0807ff73f08469db07639742f94682a8e3bfce43a4e3dc055cc922fdebe85f","RV":11,"SZ":3540718},"en_fr":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1286311,"HASH":"6b4d47ca8e1a35c01709028169605cbe26ce3df3fb582e1b137423a9343327af","RV":11,"SZ":2526607},"en_hi":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["TRANSLIT","L1"]},"DL_SZ":1654253,"HASH":"3f3f8c8594935f8b2a048d9c71bb481f7f51607126a6c9d43eb7546a4115793e","RV":11,"SZ":3758591},"en_hr":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1698222,"HASH":"d6cc5f9716df9d180d597bc80c49d57ec7d530eade184c5679d3ac66abacbfb1","RV":11,"SZ":3220274},"en_hu":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1846339,"HASH":"8e30a0fd700e92abbfbf99d16f27a0f53410b355a59f50742436d53b0050f539","RV":11,"SZ":3676770},"en_id":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1532660,"HASH":"6d649c11ac76341f4a3356cdad42c487575d44e5f0a5fd027094c5fb0d1fa014","RV":11,"SZ":2718038},"en_it":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1282858,"HASH":"fa1f8bb7b89fad6593f23fefab71a656f3d5e4134ded463e6bad61d35025611b","RV":11,"SZ":2659222},"en_lt":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1903256,"HASH":"a095ec65d97786a7f15f8b5432eadc9efaef139241f6612f72a6987f4a4361b2","RV":11,"SZ":3603666},"en_nl":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1909862,"HASH":"65e7206b2fbf0d0e25e3ecea75670e762467943a1bcbd8e19a57e5e8131ba6e5","RV":11,"SZ":3734096},"en_no":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1836572,"HASH":"547039c28ded866a5a5e49f3a4eba4df5c3ca362e9b230567204bdd9926daf9f","RV":11,"SZ":3443462},"en_pl":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1904098,"HASH":"6144d3a5ab1aa7cf8566cb2d2a02d3aabaf8af76acd386ba5b0929412ec1186d","RV":11,"SZ":3677928},"en_pt":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1430816,"HASH":"47d25c6fc2faa3f1931eb58fdfde7ff13e1c4bd93b6613ae92e0aa57effbd969","RV":13,"SZ":2981993},"en_ro":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1656179,"HASH":"46359c9813699fba02c258be72fbb4a54598448f53e80c93f9add2f9b51f9763","RV":11,"SZ":3161362},"en_ru":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1991638,"HASH":"64e692609b78aed2fe629d3649efea468577527245057aa09c51bb0b109cf497","RV":11,"SZ":4406782},"en_sk":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1858401,"HASH":"8ebbda44a612aa528df7b5ee77d07ee9a3b8a47b29c6137c3c6488c927abcc0b","RV":11,"SZ":3501699},"en_sv":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":2102840,"HASH":"8064f225f76b1e76987d126c2342cc6bb98c29a6e5974d59013374baebb4c118","RV":11,"SZ":3990144},"en_th":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["TRANSLIT","L1"]},"DL_SZ":2336722,"HASH":"69cd5a42fd91e38d26ee0d34161fc01701ed6a2c6f25f9f4aa0c811fd1235c60","RV":11,"SZ":5163407},"en_tl":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1866226,"HASH":"63635af37ab532dffa9cef622b94b0bbb7d64b3a712ac2cd29ae38540409fb15","RV":11,"SZ":3581394},"en_tr":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":2007468,"HASH":"97468f51d7df67e11d1dc95456e19b30cfc192afa8f70c2eb8b532e1b7f28118","RV":11,"SZ":3783806},"en_uk":{"CAPS":{"L1":["OCR","TRANSLIT","L2"],"L2":["OCR","TRANSLIT","L1"]},"DL_SZ":1682513,"HASH":"c22bc18db2e742ae19ae3731a5cc05c64aec99cfb6ebc9e8e18f955fa009b6aa","RV":11,"SZ":3211150}},"V":5,"VARIANTS":{"PKG_HIGH":"25","PKG_LOW":"02"}} \ No newline at end of file diff --git a/uni_modules/x-translate-s/utssdk/app-ios/config.json b/uni_modules/x-translate-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..11975c2 --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-ios/config.json @@ -0,0 +1,9 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "GoogleMLKit/Translate", + "version": "3.2.0" + } + ] +} diff --git a/uni_modules/x-translate-s/utssdk/app-ios/index.uts b/uni_modules/x-translate-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..4d20f45 --- /dev/null +++ b/uni_modules/x-translate-s/utssdk/app-ios/index.uts @@ -0,0 +1,68 @@ +import { TranslateLanguage, TranslatorOptions, Translator,ModelManager,ModelDownloadConditions} from "MLKitTranslate" +function getTranslatorOpts(lang : string, target : string):TranslatorOptions{ + let langopts = new Map([ + ['zh',TranslateLanguage.chinese],//中文 + ['en',TranslateLanguage.english],//英语 + ['ja',TranslateLanguage.japanese],//日本 + ['de',TranslateLanguage.german],//德国 + ['fr',TranslateLanguage.french],//法国 + ['ko',TranslateLanguage.korean],//韩国 + ['ru',TranslateLanguage.russian],//俄罗斯 + ['it',TranslateLanguage.italian],//意大利 + ['th',TranslateLanguage.thai],//泰国 + ['vi',TranslateLanguage.vietnamese],//越南语 + ['id',TranslateLanguage.indonesian],//印度尼西亚 + ]) + let sou = langopts.get(lang)! as TranslateLanguage + let targ = langopts.get(target)! as TranslateLanguage + let options = TranslatorOptions(sourceLanguage = sou, targetLanguage = targ) + + return options; +} +export function checkTranslateModeDonload(lang:string[],callback:(inlang:boolean)=>void){ + let localModels = ModelManager.modelManager().downloadedTranslateModels + let langlist = [] as string[] + for(item in localModels){ + let str = item.debugDescription.split(":") as string[]; + let lg = str[str.length-1].trim() + langlist.push(lg) + } + if(langlist.length==0){ + console.log('langauge:',langlist) + callback(false) + } + let isin = lang.some((el:string):boolean=>langlist.includes(el)); + + callback(isin) +} +export function downloadTranslateMode(lang : string, target : string ,call:(ok:boolean)=>void) { + let options = getTranslatorOpts(lang,target) + let modoptions = ModelDownloadConditions( + allowsCellularAccess = false, + allowsBackgroundDownloading = true + ) + let trator = Translator.translator(options= options) + trator.downloadModelIfNeeded(with= modoptions,completion=(error)=>{ + console.log("tips:",error) + if(error!=null){ + console.log("error:",error) + call(false) + return; + } + call(true) + }) + ModelManager.modelManager().downloadedTranslateModels + call(true) +} +export function translate(text : string, lang : string, target : string,callback:(str:string)=>void) { + let options = getTranslatorOpts(lang,target) + let zhtoen = Translator.translator(options = options) + zhtoen.translate(text, completion = (translatedText, error) => { + if (error != null) { + console.log("error:", error) + callback("") + return; + } + callback(translatedText!) + }) +} \ No newline at end of file diff --git a/uni_modules/x-translate-s/utssdk/interface.uts b/uni_modules/x-translate-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-translate-s/utssdk/unierror.uts b/uni_modules/x-translate-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-vibrate-s/changelog.md b/uni_modules/x-vibrate-s/changelog.md new file mode 100644 index 0000000..059230d --- /dev/null +++ b/uni_modules/x-vibrate-s/changelog.md @@ -0,0 +1,11 @@ +## 1.0.3(2025-07-25) +* 兼容原生鸿蒙 +## 1.0.2(2025-04-13) +* IOS端现在支持指定震动频率. +## 1.0.1(2025-02-10) +* 兼容微信 +## 1.0.1(2025-07-25) +* 兼容原生鸿蒙 +## 1.0.0(2024-06-01) +使用手机震动 +安卓,ios支持。 diff --git a/uni_modules/x-vibrate-s/package.json b/uni_modules/x-vibrate-s/package.json new file mode 100644 index 0000000..7f0ecb2 --- /dev/null +++ b/uni_modules/x-vibrate-s/package.json @@ -0,0 +1,82 @@ +{ + "id": "x-vibrate-s", + "displayName": "x-vibrate-s", + "version": "1.0.1", + "description": "x-vibrate-s", + "keywords": [ + "x-vibrate-s" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-vibrate-s/readme.md b/uni_modules/x-vibrate-s/readme.md new file mode 100644 index 0000000..2a6efbf --- /dev/null +++ b/uni_modules/x-vibrate-s/readme.md @@ -0,0 +1,31 @@ +# x-vibrate-s + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +### 开发文档 + +鸿蒙使用了:ohos.permission.VIBRATE 权限 + +调用: +```ts +import { vibrator } from "@/uni_modules/x-vibrate-s" +// 使用,ios13+支持指定频率震动,ios12及以下不支持. +vibrator(50) + +``` + +参数配置: + + +```uts +/** + * 震动 + * @param {number} duriation 震动时间单位ms,ios(12及以下)无效 + */ +vibrator(duriation : number):boolean + +``` diff --git a/uni_modules/x-vibrate-s/utssdk/app-android/AndroidManifest.xml b/uni_modules/x-vibrate-s/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..a4146c9 --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/uni_modules/x-vibrate-s/utssdk/app-android/config.json b/uni_modules/x-vibrate-s/utssdk/app-android/config.json new file mode 100644 index 0000000..7ed4299 --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "19" +} \ No newline at end of file diff --git a/uni_modules/x-vibrate-s/utssdk/app-android/index.uts b/uni_modules/x-vibrate-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..699f45f --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-android/index.uts @@ -0,0 +1,21 @@ +import Vibrator from "android.os.Vibrator" +import Context from 'android.content.Context' + +/** + * 震动 + * @param {number} duriation 震动时间单位ms + */ +export function vibrator(duriation : number):boolean { + try { + const context = UTSAndroid.getAppContext() as Context + let vb = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator; + if (vb!.hasVibrator()) { + vb!.vibrate(duriation.toLong()); + } else { + return false + } + } catch (e) { + console.error(e) + } + return false +} \ No newline at end of file diff --git a/uni_modules/x-vibrate-s/utssdk/app-harmony/config.json b/uni_modules/x-vibrate-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..6df5a0e --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_library_s": "./lib/x_library_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-vibrate-s/utssdk/app-harmony/index.uts b/uni_modules/x-vibrate-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..0579d1e --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-harmony/index.uts @@ -0,0 +1,17 @@ +import { x_vibrator } from "x_library_s"; +import { BusinessError } from "@kit.BasicServicesKit"; + +/** + * 震动 + * @param {number} duriation 震动时间单位ms + */ +export function vibrator(duriation : number) : boolean { + try { + x_vibrator(duriation) + } catch (err) { + let e : BusinessError = err as BusinessError; + console.error(e.message); + return false; + } + return true; +} \ No newline at end of file diff --git a/uni_modules/x-vibrate-s/utssdk/app-harmony/lib/x_library_s.har b/uni_modules/x-vibrate-s/utssdk/app-harmony/lib/x_library_s.har new file mode 100644 index 0000000..96fa816 Binary files /dev/null and b/uni_modules/x-vibrate-s/utssdk/app-harmony/lib/x_library_s.har differ diff --git a/uni_modules/x-vibrate-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-vibrate-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-vibrate-s/utssdk/app-ios/config.json b/uni_modules/x-vibrate-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..721b81e --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "9" +} \ No newline at end of file diff --git a/uni_modules/x-vibrate-s/utssdk/app-ios/index.uts b/uni_modules/x-vibrate-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..0d619d6 --- /dev/null +++ b/uni_modules/x-vibrate-s/utssdk/app-ios/index.uts @@ -0,0 +1,26 @@ +import * as AudioToolbox from 'AudioToolbox'; +import * as UIKit from 'UIKit'; +import { Thread } from 'Foundation'; + + +/** + * 震动 + * @param {number} duriation 震动时间单位ms,ios 13.+有用。 + */ +export function vibrator(duriation : number):boolean { + if (UTSiOS.available("iOS 13.0, *")) { + let generator = new UIKit.UIImpactFeedbackGenerator(style = UIKit.UIImpactFeedbackGenerator.FeedbackStyle.medium) + generator.prepare(); + let start = new Date().getTime(); + let end = start + duriation + while(start globalI18nInstans + // @ts-ignore + app.mixin({ + data() { + return { + /** + * 模板vue内及选项式this.i18n可调用使用 + */ + i18n: globalI18nInstans as Tmui4xI18n + } + }, + onLaunch(){ + } + }) + } +}) +export const $i18n = () : Tmui4xI18n => createI18n() +export const mergeI18nOpts = (args : I18nOptions|null) : I18nOptionsReally => i18n.mergeI18nOpts(args) + diff --git a/uni_modules/x-vuei18n-s/instans/example.uts b/uni_modules/x-vuei18n-s/instans/example.uts new file mode 100644 index 0000000..435621f --- /dev/null +++ b/uni_modules/x-vuei18n-s/instans/example.uts @@ -0,0 +1,244 @@ +/** + * Vue I18n UTS 使用示例 + * 展示如何在UniApp-X中使用移植的vue-i18n库 + */ +import { createI18n} from '@/uni_modules/x-vuei18n-s' +import { Tmui4xI18n,NumberFormat,DateTimeFormat} from '@/uni_modules/x-vuei18n-s/interface.uts' +// 示例:创建简单的i18n实例 +export function createExampleI18n():Tmui4xI18n{ + // 准备消息数据 + const messages: UTSJSONObject = {} + + // 中文消息 + const zhMessages: UTSJSONObject = { + 'hello': '你好', + 'welcome': '欢迎使用UniApp-X', + 'user': { + 'name': '用户名', + 'age': '年龄', + 'profile': '个人资料' + }, + 'items': { + 'apple': '苹果 | 苹果们', + 'apple2': '苹果 | 苹果们 | 复杂嵌套{count}', + 'book': '书 | 书们' + }, + 'greeting': '你好,{name}!', + 'greetingList': '你好,{0}!', + 'itemCount': '你有 {count} 个项目' + } + + // 英文消息 + const enMessages: UTSJSONObject = { + 'hello': 'Hello', + 'welcome': 'Welcome to UniApp-X', + 'user': { + 'name': 'Username', + 'age': 'Age', + 'profile': 'Profile' + }, + 'items': { + 'apple': 'apple | apples', + 'apple2': 'apple | apples | apples{count}', + 'book': 'book | books' + }, + 'greeting': 'Hello, {name}!', + 'greetingList': 'Hello, {0}!', + 'itemCount': 'You have {count} items' + } + + messages.set('zh-Hans', zhMessages) + messages.set('en', enMessages) + + // 创建i18n实例 + const i18n = createI18n({locale:'zh-Hans',messages}) + + return i18n +} + +// 示例:基本翻译功能 +export function basicTranslationExample() { + const i18n = createExampleI18n() + + console.log('=== 基本翻译示例 ===') + + // 简单翻译 + console.log(i18n.t('hello')) // 输出: 你好 + console.log(i18n.t('welcome')) // 输出: 欢迎使用UniApp-X + + // 嵌套路径翻译 + console.log(i18n.t('user.name')) // 输出: 用户名 + console.log(i18n.t('user.profile')) // 输出: 个人资料 + + // 切换语言 + i18n.setLocale('en') + console.log(i18n.t('hello')) // 输出: Hello + console.log(i18n.t('user.name')) // 输出: Username + + + // 切换回中文 + i18n.setLocale('zh-Hans') +} + +// 示例:参数插值 +export function interpolationExample() { + const i18n = createExampleI18n() + + console.log('=== 参数插值示例 ===') + + // 命名参数 + const namedParams: UTSJSONObject = { 'name': '张三' } + console.log(i18n.t('greeting', namedParams),'----') // 输出: 你好,张三! + + // 列表参数 + const listParams = ['李四'] + console.log(i18n.t('greetingList', listParams)) // 输出: 你好,李四! + + // 数字参数 + const countParams: UTSJSONObject = { 'count': 5 } + console.log(i18n.t('itemCount', countParams)) // 输出: 你有 5 个项目 +} + +// 示例:复数处理 +export function pluralExample() { + const i18n = createExampleI18n() + + console.log('=== 复数处理示例 ===') + + // 单数 + console.log(i18n.t('items.apple', 0)) // 输出: 苹果 + + // 复数 + console.log(i18n.t('items.apple', 1)) // 输出: 苹果们 + console.log(i18n.t('items.apple2', 2,{count:8})) // 输出: 复杂嵌套8 + + + // 切换到英文测试复数 + i18n.setLocale('en') + console.log(i18n.t('items.apple', 0)) // 输出: apple + console.log(i18n.t('items.apple', 1)) // 输出: apples + console.log(i18n.t('items.apple2', 2,{count:8})) // 输出: apples8 + i18n.setLocale('zh-Hans') +} + +// 示例:数字格式化 +export function numberFormatExample() { + const i18n = createExampleI18n() + + console.log('=== 数字格式化示例 中文 ===') + + // 基本数字格式化 + console.log(i18n.n(1234)) // 输出: 1,234.56 + console.log(i18n.n(1234567.89)) // 输出: 1,234,567.89 + + // 货币格式化 + const currencyOptions:NumberFormat = { + style: 'currency', + currency: 'CNY', + useGrouping:true + } + console.log(i18n.n(1234.56,null, currencyOptions)) // 输出: ¥1,234.56 + + // 百分比格式化 + const percentOptions:NumberFormat = { + style: 'percent' + } + console.log(i18n.n(0.1234,null, percentOptions)) // 输出: 12.34% + + + console.log('=== 货币式化示例 英文 ===') + // 货币格式化 + const currencyOptionsEn:NumberFormat = { + style: 'currency', + currency: 'USD', + useGrouping:true + } + console.log(i18n.n(1234.56,null, currencyOptionsEn)) + + +} + +// 示例:日期时间格式化 +export function dateTimeFormatExample() { + const i18n = createExampleI18n() + + console.log('=== 日期时间格式化示例 ===') + + const now = new Date() + + // 基本日期格式化 + console.log(i18n.d(now)) // 输出: 2024年01月01日 12:00:00 + + // 自定义格式 + const dateOptions:DateTimeFormat = { + year: 'numeric', + month: 'long', + day: 'numeric', + dateSeparator:'', + local:'en' + } + console.log(i18n.d(now,null, dateOptions)) // 输出: 2024年一月1日 + + // 时间格式 + const timeOptions:DateTimeFormat = { + year: '', + month: '', + day: '', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + } + console.log(i18n.d(now,null, timeOptions)) // 输出: 12:00:00 +} + +// 示例:检查翻译键是否存在 +export function translationExistsExample() { + const i18n = createExampleI18n() + + console.log('=== 翻译键存在检查示例 ===') + + console.log(i18n.te('hello')) // 输出: true + console.log(i18n.te('user.name')) // 输出: true + console.log(i18n.te('nonexistent.key')) // 输出: false + + // 检查特定语言的键 + console.log(i18n.te('hello', 'en')) // 输出: true + console.log(i18n.te('hello', 'fr-FR')) // 输出: false +} + +// 示例:动态添加翻译 +export function dynamicTranslationExample() { + const i18n = createExampleI18n() + + console.log('=== 动态翻译示例 ===') + + // 添加新的翻译 + const newMessages: UTSJSONObject = { + 'goodbye': '再见', + 'settings': { + 'language': '语言设置', + 'theme': '主题设置' + } + } + + i18n.mergeLocaleMessage('zh-Hans', newMessages) + console.log(i18n.t('goodbye')) // 输出: 再见 + console.log(i18n.t('settings.language')) // 输出: 语言设置 + + console.log('可用语言:', i18n.availableLocales()) // 输出: ['zh-CN', 'en-US'] +} + +// 运行所有示例 +export function runAllExamples() { + console.log('Vue I18n UTS 库示例开始运行...') + // createExampleI18n() + basicTranslationExample() + interpolationExample() + pluralExample() + numberFormatExample() + dateTimeFormatExample() + translationExistsExample() + dynamicTranslationExample() + + console.log('Vue I18n UTS 库示例运行完成!') +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/instans/i18n.uts b/uni_modules/x-vuei18n-s/instans/i18n.uts new file mode 100644 index 0000000..73fa1c6 --- /dev/null +++ b/uni_modules/x-vuei18n-s/instans/i18n.uts @@ -0,0 +1,1862 @@ +import { BasePluralRule, Tmui4xI18nTml, DateTimeFormatReal, I18nOptions, I18nOptionsReally, NumberFormat, NumberFormatOpts, StringOrNull, NumberOrNull, StringOrNumber, StringOrNumberOrNull, DateOrNumberOrString, UTSJSONObjectOrNull, UTSJSONObjectOrArray, AnyOrNull, GetAnyType, I18nOptionsOrNull, NumberFormatOrNull, DateTimeFormatOrNull, GetAnyTypeOrNull } from "../interface"; + +/** + * uniapp-x多语言插件 + * @author tmui4x + * @copyright https://tmui.design + * @date 2025/7/8 + */ + +// 日期时间名称格式类型 +type DateTimeNames = { + long : string[], + short : string[], + narrow : string[] +} +type BestTimeTYpe = { unit : string, value : number } +type timeUnitsTYpe = {unit:string,ms:number,threshold:number} +export function mergeI18nOpts(args : I18nOptions|null = null) : I18nOptionsReally { + let localLang = uni.getStorageSync("language") + // 提供默认配置 + const currentLan = localLang!=null&&localLang!=''&& typeof localLang == 'string'?(localLang! as string):"zh-Hans" + const defaultOptions : I18nOptionsReally = { + locale: currentLan, + fallbackLocale: "en", + messages: {}, + datetimeFormats: new Map(), + numberFormats: new Map(), + modifiers: new Map(), + pluralRules: new Map(), + missing: null, + missingWarn: true, + fallbackWarn: true, + fallbackRoot: true, + fallbackFormat: false, + unresolving: true, + postTranslation: null, + warnHtmlMessage: true, + escapeParameter: true, + inheritLocale: true, + warnHandler: (v, e) => { + console.warn(`[tmui4x]:${v}`, e == null ? '' : e!); + }, + pluralRule: (choice : number, choicesLength : number, orgRule ?: BasePluralRule) : number => { + // 默认英语复数规则实现 + // 参考 Vue I18n 标准实现:https://vue-i18n.intlify.dev/guide/essentials/pluralization + // 如果提供了原始规则函数,优先使用 + if (orgRule != null) { + return orgRule(choice, choicesLength); + } + + // 确保索引在有效范围内 + if (choicesLength <= 1) { + return 0; + } + return choice; + // 标准英语复数规则 + // 当只有2个选项时: 0=复数形式, 1=单数形式 + // 当有3个或更多选项时: 0=零, 1=单数, 2=复数 + // if (choicesLength == 2) { + // // 二元模式: [复数, 单数] + // return choice == 1 ? 1 : 0; + // } else { + // // 多元模式: [零, 单数, 复数, ...] + // if (choice == 0) { + // return 0; // 零 + // } else if (choice == 1) { + // return 1; // 单数 + // } else { + // return Math.min(2, choicesLength - 1); // 复数或最后一个选项 + // } + // } + }, + globalInjection: true, + allowComposition: true, + legacy: true + }; + + // 如果没有传入参数,返回默认配置 + if (args == null) { + return defaultOptions; + } + + // 合并用户配置和默认配置 + return { + locale: args.locale ?? defaultOptions.locale, + fallbackLocale: args.fallbackLocale ?? defaultOptions.fallbackLocale, + messages: args.messages ?? defaultOptions.messages, + datetimeFormats: args.datetimeFormats ?? defaultOptions.datetimeFormats, + numberFormats: args.numberFormats ?? defaultOptions.numberFormats, + modifiers: args.modifiers ?? defaultOptions.modifiers, + pluralRules: args.pluralRules ?? defaultOptions.pluralRules, + missing: args.missing ?? defaultOptions.missing, + missingWarn: args.missingWarn ?? defaultOptions.missingWarn, + fallbackWarn: args.fallbackWarn ?? defaultOptions.fallbackWarn, + fallbackRoot: args.fallbackRoot ?? defaultOptions.fallbackRoot, + fallbackFormat: args.fallbackFormat ?? defaultOptions.fallbackFormat, + unresolving: args.unresolving ?? defaultOptions.unresolving, + postTranslation: args.postTranslation ?? defaultOptions.postTranslation, + warnHtmlMessage: args.warnHtmlMessage ?? defaultOptions.warnHtmlMessage, + escapeParameter: args.escapeParameter ?? defaultOptions.escapeParameter, + inheritLocale: args.inheritLocale ?? defaultOptions.inheritLocale, + warnHandler: args.warnHandler ?? defaultOptions.warnHandler, + pluralRule: args.pluralRule ?? defaultOptions.pluralRule, + globalInjection: args.globalInjection ?? defaultOptions.globalInjection, + allowComposition: args.allowComposition ?? defaultOptions.allowComposition, + legacy: args.legacy ?? defaultOptions.legacy + } as I18nOptionsReally; + + +} +export class Tmui4xI18n implements Tmui4xI18nTml { + ops : I18nOptionsReally + constructor(args : I18nOptions|null) { + this.ops = mergeI18nOpts(args) + } + // 语言 + setLocale(local : string) { + uni.setStorageSync('language',local) + this.ops.locale = local + } + //设置语言 + getLocale() : string { + return this.ops.locale + } + getFallbackLocale() : string { + return this.ops.fallbackLocale + } + + setFallbackLocale(local : string) { + this.ops.fallbackLocale = local + } + setOptions(args : I18nOptions|null){ + this.ops = mergeI18nOpts(args) + } + /** + * 翻译方法 - 参考 Vue I18n 实现(UTS类型安全优化版本) + * @param key 翻译键 + * @param args 可选参数:数字(用于复数)、对象(用于插值)、字符串(locale)等同原vueI18n使用方式 + * @param opts 可选的第二个参数当args为复数数字,key中函数 | 时,此opts起效且必须为utsjsonobject格式等同原vueI18n使用方式 + * @returns 翻译后的字符串 + */ + t(key : string, ...argsopts : Array) : string { + + let repeatCount : NumberOrNull = null; + let values : UTSJSONObjectOrArray = {}; + let locale : string = this.ops.locale; + if (argsopts.length > 0) { + // 严格的类型检查和参数解析 + let args : AnyOrNull = argsopts[0] + let opts : AnyOrNull = null; + if (argsopts.length > 1) { + opts = argsopts[1] + } + + if (args != null && opts == null) { + if (typeof args == 'number') { + // args 是数字类型 + const numArgs : number = args; + values = { count: numArgs, n: numArgs }; + repeatCount = numArgs + } else if (typeof args == 'string') { + // args 是字符串类型(locale) + const strArgs : string = args; + locale = strArgs; + + } else if (args instanceof UTSJSONObject) { + const objArgs : UTSJSONObject = args; + values = objArgs; + + } else if (Array.isArray(args)) { + const arrArgs : Array = args; + values = arrArgs; + } + } else if (typeof args == 'number' && opts instanceof UTSJSONObject) { + const objOpts : UTSJSONObject = opts; + values = objOpts; + const numArgs : number = args; + repeatCount = numArgs + } + } + + + // 类型安全的消息获取 + let message : StringOrNull = this.getMessage(key, locale); + + // 如果没有找到消息,尝试回退语言 + if (message == null && locale != this.ops.fallbackLocale) { + message = this.getMessage(key, this.ops.fallbackLocale); + if (this.ops.fallbackWarn && message != null) { + this.ops.warnHandler(`Fall back to translate the key '${key}' with '${this.ops.fallbackLocale}' locale.`, null); + } + } + + // 如果仍然没有找到消息 + if (message == null) { + this.ops.warnHandler(`Not found '${key}' key in '${locale}' locale messages.`, null); + return key; // 返回键名作为默认值 + } + + // 类型安全的复数处理 + if (repeatCount != null && typeof message == 'string' && message.includes('|')) { + const safeCount : number = repeatCount; + message = this.handlePlural(message, safeCount, locale); + } + + // 类型安全的插值处理 + if (typeof message == 'string') { + message = this.interpolate(message, values); + } + + // 类型安全的后处理 + if (this.ops.postTranslation != null && typeof message == 'string') { + const processedMessage : string = this.ops.postTranslation(message, key); + message = processedMessage; + } + + // 确保返回字符串类型 + return typeof message == 'string' ? message : key; + } + + /** + * 数字格式化方法 - 参考 Vue I18n 实现 + * @param val 要格式化的数字 + * @param name 格式化名称模板,如果不存在以opts为准,如果opts也没有则取默认值。 + * @param opts 格式化选项 + * @returns 格式化后的字符串 + */ + n(val : number, formatName ?: string, opts ?: NumberFormat) : string { + let currentLocale = (opts?.local ?? this.ops.locale)!; + let formatOptions : NumberFormatOpts = { + style: 'decimal', + currency: 'CNY', + local: currentLocale, + currencyDisplay: 'symbol', + useGrouping: false, + minimumIntegerDigits: 1, + minimumFractionDigits: 0, + maximumFractionDigits: 3, + minimumSignificantDigits: null, + maximumSignificantDigits: null, + }; + if (opts != null) { + formatOptions = { + style: opts?.style ?? formatOptions.style, + currency: opts?.currency ?? formatOptions.currency, + local: opts?.local ?? formatOptions.local, + currencyDisplay: opts?.currencyDisplay ?? formatOptions.currencyDisplay, + useGrouping: opts?.useGrouping ?? formatOptions.useGrouping, + minimumIntegerDigits: opts?.minimumIntegerDigits ?? formatOptions.minimumIntegerDigits, + minimumFractionDigits: opts?.minimumFractionDigits ?? formatOptions.minimumFractionDigits, + maximumFractionDigits: opts?.maximumFractionDigits ?? formatOptions.maximumFractionDigits, + minimumSignificantDigits: opts?.minimumSignificantDigits ?? formatOptions.minimumSignificantDigits, + maximumSignificantDigits: opts?.maximumSignificantDigits ?? formatOptions.maximumSignificantDigits + }; + } + + // 处理参数 + if (typeof formatName == 'string') { + // 如果是字符串,从预定义格式中获取 + const formatNameReal = formatName!; + if (this.ops.numberFormats.has(currentLocale)) { + const localeFormats = this.ops.numberFormats.get(currentLocale)!; + if (localeFormats.has(formatNameReal)) { + const formatOptions_templ = localeFormats.get(formatNameReal)!; + formatOptions = { + style: formatOptions_templ?.style ?? formatOptions.style, + currency: formatOptions_templ?.currency ?? formatOptions.currency, + local: formatOptions_templ?.local ?? formatOptions.local, + currencyDisplay: formatOptions_templ?.currencyDisplay ?? formatOptions.currencyDisplay, + useGrouping: formatOptions_templ?.useGrouping ?? formatOptions.useGrouping, + minimumIntegerDigits: formatOptions_templ?.minimumIntegerDigits ?? formatOptions.minimumIntegerDigits, + minimumFractionDigits: formatOptions_templ?.minimumFractionDigits ?? formatOptions.minimumFractionDigits, + maximumFractionDigits: formatOptions_templ?.maximumFractionDigits ?? formatOptions.maximumFractionDigits, + minimumSignificantDigits: formatOptions_templ?.minimumSignificantDigits ?? formatOptions.minimumSignificantDigits, + maximumSignificantDigits: formatOptions_templ?.maximumSignificantDigits ?? formatOptions.maximumSignificantDigits + }; + } else { + this.ops.warnHandler(`Number format '${formatNameReal}' not found for locale '${currentLocale}'`, null); + } + } else { + this.ops.warnHandler(`Number formats not found for locale '${currentLocale}'`, null); + } + } + + currentLocale = formatOptions.local + // 执行数字格式化 + return this.formatNumber(val, formatOptions, currentLocale); + } + + /** + * 日期时间格式化方法 - 参考 Vue I18n 实现 + * @param val 要格式化的日期时间值(Date对象、时间戳数字或日期字符串) + * @param formatName 格式化名称模板,如果不存在以opts为准,如果opts也没有则取默认值 + * @param opts 格式化选项 + * @returns 格式化后的字符串 + */ + d(val : DateOrNumberOrString, formatName ?: StringOrNull, opts ?: DateTimeFormatOrNull) : string { + let currentLocale = (opts?.local ?? this.ops.locale)!; + let formatOptions : DateTimeFormatReal = { + localeMatcher: 'best fit', + local: currentLocale, + calendar: 'gregory', + numberingSystem: 'latn', + dateSeparator: "", + timeZone: 'UTC', + hour12: false, + hourCycle: 'h23', + formatMatcher: 'best fit', + weekday: '', + era: '', + year: 'numeric', + month: 'numeric', + day: 'numeric', + dayPeriod: '', + hour: '', + minute: '', + second: '', + fractionalSecondDigits: 0, + timeZoneName: '', + dateStyle: '', + timeStyle: '' + }; + + if (opts != null) { + formatOptions = { + localeMatcher: opts?.localeMatcher ?? formatOptions.localeMatcher, + local: opts?.local ?? formatOptions.local, + dateSeparator: opts?.dateSeparator ?? formatOptions.dateSeparator, + calendar: opts?.calendar ?? formatOptions.calendar, + numberingSystem: opts?.numberingSystem ?? formatOptions.numberingSystem, + timeZone: opts?.timeZone ?? formatOptions.timeZone, + hour12: opts?.hour12 ?? formatOptions.hour12, + hourCycle: opts?.hourCycle ?? formatOptions.hourCycle, + formatMatcher: opts?.formatMatcher ?? formatOptions.formatMatcher, + weekday: opts?.weekday ?? formatOptions.weekday, + era: opts?.era ?? formatOptions.era, + year: opts?.year ?? formatOptions.year, + month: opts?.month ?? formatOptions.month, + day: opts?.day ?? formatOptions.day, + dayPeriod: opts?.dayPeriod ?? formatOptions.dayPeriod, + hour: opts?.hour ?? formatOptions.hour, + minute: opts?.minute ?? formatOptions.minute, + second: opts?.second ?? formatOptions.second, + fractionalSecondDigits: opts?.fractionalSecondDigits ?? formatOptions.fractionalSecondDigits, + timeZoneName: opts?.timeZoneName ?? formatOptions.timeZoneName, + dateStyle: opts?.dateStyle ?? formatOptions.dateStyle, + timeStyle: opts?.timeStyle ?? formatOptions.timeStyle + }; + } + + // 处理参数 + if (typeof formatName == 'string') { + // 如果是字符串,从预定义格式中获取 + const formatNameReal = formatName!; + if (this.ops.datetimeFormats.has(currentLocale)) { + const localeFormats = this.ops.datetimeFormats.get(currentLocale)!; + if (localeFormats.has(formatNameReal)) { + const formatOptions_templ = localeFormats.get(formatNameReal)!; + formatOptions = { + localeMatcher: formatOptions_templ?.localeMatcher ?? formatOptions.localeMatcher, + local: formatOptions_templ?.local ?? formatOptions.local, + calendar: formatOptions_templ?.calendar ?? formatOptions.calendar, + numberingSystem: formatOptions_templ?.numberingSystem ?? formatOptions.numberingSystem, + timeZone: formatOptions_templ?.timeZone ?? formatOptions.timeZone, + hour12: formatOptions_templ?.hour12 ?? formatOptions.hour12, + hourCycle: formatOptions_templ?.hourCycle ?? formatOptions.hourCycle, + formatMatcher: formatOptions_templ?.formatMatcher ?? formatOptions.formatMatcher, + dateSeparator: formatOptions_templ?.dateSeparator ?? formatOptions.dateSeparator, + weekday: formatOptions_templ?.weekday ?? formatOptions.weekday, + era: formatOptions_templ?.era ?? formatOptions.era, + year: formatOptions_templ?.year ?? formatOptions.year, + month: formatOptions_templ?.month ?? formatOptions.month, + day: formatOptions_templ?.day ?? formatOptions.day, + dayPeriod: formatOptions_templ?.dayPeriod ?? formatOptions.dayPeriod, + hour: formatOptions_templ?.hour ?? formatOptions.hour, + minute: formatOptions_templ?.minute ?? formatOptions.minute, + second: formatOptions_templ?.second ?? formatOptions.second, + fractionalSecondDigits: formatOptions_templ?.fractionalSecondDigits ?? formatOptions.fractionalSecondDigits, + timeZoneName: formatOptions_templ?.timeZoneName ?? formatOptions.timeZoneName, + dateStyle: formatOptions_templ?.dateStyle ?? formatOptions.dateStyle, + timeStyle: formatOptions_templ?.timeStyle ?? formatOptions.timeStyle + }; + } else { + this.ops.warnHandler(`DateTime format '${formatNameReal}' not found for locale '${currentLocale}'`, null); + } + } else { + this.ops.warnHandler(`DateTime formats not found for locale '${currentLocale}'`, null); + } + } + currentLocale = formatOptions.local + + // 执行日期时间格式化 + return this.formatDateTime(val, formatOptions, currentLocale); + } + /** + * 动态添加语言的新字段 + * @param {string} local 语言 + * @param {UTSJSONObject} newMessage 键值及字段。 + */ + mergeLocaleMessage(local : string, newMessage : UTSJSONObject) { + let nowmessage = this.ops.messages.getJSON(local); + if (nowmessage != null) { + nowmessage = { ...nowmessage, ...newMessage } + this.ops.messages.set(local, nowmessage) + } else { + this.ops.messages.set(local, newMessage) + } + } + /** + * 检测翻译键是否存在 - 参考 Vue I18n 的 te 方法实现 + * @param {string} key 翻译键,支持嵌套路径如 'user.name' + * @param {string} locale 可选的语言代码,不提供则使用当前语言 + * @returns {boolean} 存在返回true,不存在返回false + */ + te(key : string, locale ?: string | null) : boolean { + // 确定要检查的语言 + const targetLocale = (locale != null ? locale : this.ops.locale); + + // 检查语言包是否存在 + const messages = this.ops.messages; + if (messages[targetLocale] == null) { + return false; + } + + // 获取指定语言的消息 + const localeMessages = messages[targetLocale] as UTSJSONObjectOrNull; + if (localeMessages == null) { + return false; + } + + // 检查翻译键是否存在 + const message = this.getNestedValue(localeMessages, key); + return message != null; + } + /** + * 相对时间 + * @param {string,number,Date} timeValue 时间差(毫秒) + * @param {string} unit 首选单位,它会自动进阶更高的维度,比如提供秒,超过60秒以分为单位进阶。 + * @param {string} locale 可选语言,不提供以默认创建的设置为准。 + * @returns {string} 格式化后的时间字符串 + */ + rt(timeValues ?: number | Date | string | null, units ?: string | null, locale ?: string | null) : string { + const targetLocale = (locale != null ? locale : this.ops.locale) + const timeValue = (timeValues != null ? new Date() : timeValues!) + const unit = (units != null ? 'minute' : units!) + + + try { + // 获取目标时间的时间戳 + let targetTimestamp = 0; + if (typeof timeValue == 'number') { + targetTimestamp = timeValue; + } else if (timeValue instanceof Date) { + targetTimestamp = timeValue.getTime(); + } else if (typeof timeValue == 'string') { + targetTimestamp = new Date(timeValue.replace(/-/g,'/')).getTime(); + } + + // 获取当前时间戳 + const currentTimestamp = new Date().getTime(); + + // 计算时间差(毫秒) + const timeDiff = targetTimestamp - currentTimestamp; + + // 验证单位参数 + const validUnits = ['year', 'years', 'quarter', 'quarters', 'month', 'months', 'week', 'weeks', 'day', 'days', 'hour', 'hours', 'minute', 'minutes', 'second', 'seconds']; + let normalizedUnit = unit.toLowerCase(); + + // 标准化单位名称(移除复数形式) + if (normalizedUnit.endsWith('s') && normalizedUnit != 'seconds') { + normalizedUnit = normalizedUnit.slice(0, -1); + } + + // 处理特殊单位名称 + switch (normalizedUnit) { + case 'yr': + case 'y': + normalizedUnit = 'year'; + break; + case 'mo': + case 'm': + normalizedUnit = 'month'; + break; + case 'w': + normalizedUnit = 'week'; + break; + case 'd': + normalizedUnit = 'day'; + break; + case 'h': + normalizedUnit = 'hour'; + break; + case 'min': + normalizedUnit = 'minute'; + break; + case 's': + case 'sec': + normalizedUnit = 'second'; + break; + case 'q': + normalizedUnit = 'quarter'; + break; + } + + // 验证单位是否有效 + if (!validUnits.includes(normalizedUnit) && !validUnits.includes(normalizedUnit + 's')) { + this.ops.warnHandler(`Invalid unit '${unit}' for relative time formatting. Valid units are: ${validUnits.join(', ')}`, null); + return `${timeValue} ${unit}`; // 返回原始格式作为回退 + } + + // 智能选择最合适的时间单位和数值 + const bestTime = this.getBestTimeUnit(timeDiff, normalizedUnit); + + // 使用自定义实现,确保跨平台兼容性 + return this.formatRelativeTimeFallback(bestTime.value, bestTime.unit, targetLocale); + + } catch (e) { + this.ops.warnHandler(`Relative time formatting failed for value ${timeValue} ${unit}`, e as Error); + return `${timeValue} ${unit}`; // 返回原始格式作为回退 + } + } + + /** + * 获取可用语言列表 + * @returns {string[]} + */ + availableLocales() : string[] { + return UTSJSONObject.keys(this.ops.messages) + } + /** + * 智能选择最合适的时间单位和数值 + * @param timeDiff 时间差(毫秒) + * @param preferredUnit 首选单位 + * @returns 包含最佳单位和数值的对象 + */ + private getBestTimeUnit(timeDiff : number, preferredUnit : string) : BestTimeTYpe { + const absTimeDiff = Math.abs(timeDiff); + + // 定义时间单位的毫秒值和优先级 + const timeUnits:timeUnitsTYpe[] = [ + { unit: 'second', ms: 1000, threshold: 60 }, + { unit: 'minute', ms: 1000 * 60, threshold: 60 }, + { unit: 'hour', ms: 1000 * 60 * 60, threshold: 24 }, + { unit: 'day', ms: 1000 * 60 * 60 * 24, threshold: 7 }, + { unit: 'week', ms: 1000 * 60 * 60 * 24 * 7, threshold: 4.33 }, + { unit: 'month', ms: 1000 * 60 * 60 * 24 * 30.44, threshold: 3 }, + { unit: 'quarter', ms: 1000 * 60 * 60 * 24 * 30.44 * 3, threshold: 4 }, + { unit: 'year', ms: 1000 * 60 * 60 * 24 * 365.25, threshold: Infinity } + ]; + + // 找到首选单位的索引 + let startIndex = timeUnits.findIndex(tu => tu.unit === preferredUnit); + if (startIndex === -1) startIndex = 0; // 如果找不到,从秒开始 + + // 从首选单位开始,向上查找最合适的单位 + for (let i = startIndex; i < timeUnits.length; i++) { + const currentUnit = timeUnits[i]; + const value = Math.round(timeDiff / currentUnit.ms); + const absValue = Math.abs(value); + + // 如果当前单位的值在合理范围内,或者已经是最大单位 + if (absValue < currentUnit.threshold || i === timeUnits.length - 1) { + return { unit: currentUnit.unit, value: value } as BestTimeTYpe; + } + } + + // 回退到首选单位 + const fallbackUnit = timeUnits[startIndex]; + return { + unit: fallbackUnit.unit, + value: Math.round(timeDiff / fallbackUnit.ms) + } as BestTimeTYpe; + } + + /** + * 相对时间格式化的回退实现 + * @param value 数值 + * @param unit 单位 + * @param locale 语言代码 + * @returns 格式化后的相对时间字符串 + */ + private formatRelativeTimeFallback(value : number, unit : string, locale : string) : string { + const absValue = Math.abs(value); + const isPast = value < 0; + const isFuture = value > 0; + const isNow = value == 0; + + // 获取语言代码 + const langCode = locale.split('-')[0].toLowerCase(); + + // 处理特殊情况(今天、昨天、明天等) + if (unit == 'day') { + if (isNow) { + return langCode == 'zh' ? '今天' : langCode == 'ja' ? '今日' : langCode == 'ko' ? '오늘' : 'today'; + } else if (value == -1) { + return langCode == 'zh' ? '昨天' : langCode == 'ja' ? '昨日' : langCode == 'ko' ? '어제' : 'yesterday'; + } else if (value == 1) { + return langCode == 'zh' ? '明天' : langCode == 'ja' ? '明日' : langCode == 'ko' ? '내일' : 'tomorrow'; + } + } + + // 获取单位的本地化名称 + const unitName = this.getLocalizedUnitName(unit, absValue, langCode); + + // 构建相对时间字符串 + if (langCode == 'zh') { + if (isPast) { + return `${absValue}${unitName}前`; + } else if (isFuture) { + return `${absValue}${unitName}后`; + } else { + return `现在`; + } + } else if (langCode == 'ja') { + if (isPast) { + return `${absValue}${unitName}前`; + } else if (isFuture) { + return `${absValue}${unitName}後`; + } else { + return `今`; + } + } else if (langCode == 'ko') { + if (isPast) { + return `${absValue}${unitName} 전`; + } else if (isFuture) { + return `${absValue}${unitName} 후`; + } else { + return `지금`; + } + } else { + // 英语和其他语言 + if (isPast) { + return `${absValue} ${unitName} ago`; + } else if (isFuture) { + return `in ${absValue} ${unitName}`; + } else { + return `now`; + } + } + } + + /** + * 获取本地化的单位名称 + * @param unit 单位 + * @param value 数值(用于确定单复数) + * @param langCode 语言代码 + * @returns 本地化的单位名称 + */ + private getLocalizedUnitName(unit : string, value : number, langCode : string) : string { + const isPlural = value != 1; + + switch (langCode) { + case 'zh': + switch (unit) { + case 'year': return '年'; + case 'quarter': return '季度'; + case 'month': return '个月'; + case 'week': return '周'; + case 'day': return '天'; + case 'hour': return '小时'; + case 'minute': return '分钟'; + case 'second': return '秒'; + default: return unit; + } + case 'ja': + switch (unit) { + case 'year': return '年'; + case 'quarter': return '四半期'; + case 'month': return 'ヶ月'; + case 'week': return '週間'; + case 'day': return '日'; + case 'hour': return '時間'; + case 'minute': return '分'; + case 'second': return '秒'; + default: return unit; + } + case 'ko': + switch (unit) { + case 'year': return '년'; + case 'quarter': return '분기'; + case 'month': return '개월'; + case 'week': return '주'; + case 'day': return '일'; + case 'hour': return '시간'; + case 'minute': return '분'; + case 'second': return '초'; + default: return unit; + } + default: + // 英语和其他语言 + switch (unit) { + case 'year': return isPlural ? 'years' : 'year'; + case 'quarter': return isPlural ? 'quarters' : 'quarter'; + case 'month': return isPlural ? 'months' : 'month'; + case 'week': return isPlural ? 'weeks' : 'week'; + case 'day': return isPlural ? 'days' : 'day'; + case 'hour': return isPlural ? 'hours' : 'hour'; + case 'minute': return isPlural ? 'minutes' : 'minute'; + case 'second': return isPlural ? 'seconds' : 'second'; + default: return unit; + } + } + } + + /** + * 内部日期时间格式化实现 + * @param value 日期时间值 + * @param options 格式化选项 + * @param locale 语言代码 + * @returns 格式化后的字符串 + */ + private formatDateTime(value : DateOrNumberOrString, options : DateTimeFormatReal, locale : string) : string { + try { + // 转换输入值为Date对象 + let dateObj : Date = new Date(); + if (value instanceof Date) { + dateObj = value; + } else if (typeof value == 'number') { + dateObj = new Date(value); + } else if (typeof value == 'string') { + dateObj = new Date(value.replace(/-/g,'/')); + } + + // 检查日期是否有效 + if (isNaN(dateObj.getTime())) { + this.ops.warnHandler(`Invalid date: ${value}`, null); + return value.toString(); + } + + // 处理预定义样式 + if (options.dateStyle != '' || options.timeStyle != '') { + return this.formatWithPredefinedStyle(dateObj, options, locale); + } + + // 自定义格式化 + return this.formatWithCustomOptions(dateObj, options, locale); + + } catch (e) { + this.ops.warnHandler(`DateTime formatting failed for value ${value}`, e as Error); + return value.toString(); + } + } + + /** + * 使用预定义样式格式化日期时间 + * @param date Date对象 + * @param options 格式化选项 + * @param locale 语言代码 + * @returns 格式化后的字符串 + */ + private formatWithPredefinedStyle(date : Date, options : DateTimeFormatReal, locale : string) : string { + let result = ''; + + // 处理日期样式 + if (options.dateStyle != '') { + switch (options.dateStyle) { + case 'full': + result += this.getFullDateFormat(date, locale); + break; + case 'long': + result += this.getLongDateFormat(date, locale); + break; + case 'medium': + result += this.getMediumDateFormat(date, locale); + break; + case 'short': + result += this.getShortDateFormat(date, locale); + break; + default: + result += this.getMediumDateFormat(date, locale); + break; + } + } + + // 处理时间样式 + if (options.timeStyle != '') { + if (result != '') result += ' '; + switch (options.timeStyle) { + case 'full': + result += this.getFullTimeFormat(date, options, locale); + break; + case 'long': + result += this.getLongTimeFormat(date, options, locale); + break; + case 'medium': + result += this.getMediumTimeFormat(date, options, locale); + break; + case 'short': + result += this.getShortTimeFormat(date, options, locale); + break; + default: + result += this.getMediumTimeFormat(date, options, locale); + break; + } + } + + return result; + } + + /** + * 使用自定义选项格式化日期时间 + * @param date Date对象 + * @param options 格式化选项 + * @param locale 语言代码 + * @returns 格式化后的字符串 + */ + private formatWithCustomOptions(date : Date, options : DateTimeFormatReal, locale : string) : string { + const dateParts : string[] = []; + const timeParts : string[] = []; + + // 根据语言环境确定日期组件的排列顺序 + const langCode = locale.split('-')[0].toLowerCase(); + const isUSFormat = langCode == 'en' && (locale.toLowerCase().includes('us') || locale.toLowerCase() == 'en'); + + // 处理非日期组件(星期和纪元) + if (options.weekday != '') { + dateParts.push(this.formatWeekday(date, options.weekday, locale)); + } + + if (options.era != '') { + dateParts.push(this.formatEra(date, options.era, locale)); + } + + // 根据语言环境按正确顺序添加日期组件 + if (isUSFormat) { + // 美式英语:月/日/年 + if (options.month != '') { + dateParts.push(this.formatMonth(date, options.month, locale, options.numberingSystem, options.dateSeparator)); + } + if (options.day != '') { + dateParts.push(this.formatDay(date, options.day, locale, options.numberingSystem, options.dateSeparator)); + } + if (options.year != '') { + dateParts.push(this.formatYear(date, options.year, locale, options.numberingSystem, options.dateSeparator)); + } + } else { + // 其他语言(包括中文、英式英语等):年/月/日 或 日/月/年 + if (langCode == 'zh' || langCode == 'ja' || langCode == 'ko') { + // 东亚语言:年/月/日 + if (options.year != '') { + dateParts.push(this.formatYear(date, options.year, locale, options.numberingSystem, options.dateSeparator)); + } + if (options.month != '') { + dateParts.push(this.formatMonth(date, options.month, locale, options.numberingSystem, options.dateSeparator)); + } + if (options.day != '') { + dateParts.push(this.formatDay(date, options.day, locale, options.numberingSystem, options.dateSeparator)); + } + } else { + // 欧洲语言(英式英语、德语、法语等):日/月/年 + if (options.day != '') { + dateParts.push(this.formatDay(date, options.day, locale, options.numberingSystem, options.dateSeparator)); + } + if (options.month != '') { + dateParts.push(this.formatMonth(date, options.month, locale, options.numberingSystem, options.dateSeparator)); + } + if (options.year != '') { + dateParts.push(this.formatYear(date, options.year, locale, options.numberingSystem, options.dateSeparator)); + } + } + } + + // 处理时间组件 + if (options.hour != '') { + timeParts.push(this.formatHour(date, options.hour, options.hour12, options.hourCycle, options.numberingSystem)); + } + + if (options.minute != '') { + timeParts.push(this.formatMinute(date, options.minute, options.numberingSystem)); + } + + if (options.second != '') { + timeParts.push(this.formatSecond(date, options.second, options.fractionalSecondDigits, options.numberingSystem)); + } + + // 组合时间部分(用冒号连接) + let timeStr = ''; + if (timeParts.length > 0) { + timeStr = timeParts.join(':'); + + // 添加 AM/PM + if (options.dayPeriod != '' && options.hour12) { + timeStr += ` ${this.formatDayPeriod(date, options.dayPeriod, locale)}`; + } + + // 添加时区 + if (options.timeZoneName != '') { + timeStr += ` ${this.formatTimeZone(date, options.timeZoneName, options.timeZone)}`; + } + } + + // 组合日期和时间 + const result : string[] = []; + if (dateParts.length > 0) { + result.push(this.combineDateTimeParts(dateParts, locale, options.dateSeparator)); + } + if (timeStr != '') { + result.push(timeStr); + } + + return result.join(' '); + } + + /** + * 内部数字格式化实现 + * @param value 数字值 + * @param options 格式化选项 + * @param locale 语言代码 + * @returns 格式化后的字符串 + */ + private formatNumber(value : number, options : NumberFormatOpts, locale : string) : string { + try { + // 基础格式化逻辑 + let result = value.toString(); + + // 处理有效数字位数(优先级高于小数位数) + if (options.minimumSignificantDigits != null || options.maximumSignificantDigits != null) { + result = this.formatWithSignificantDigits(value, options); + } else { + // 处理小数位数 + if (options.minimumFractionDigits != null || options.maximumFractionDigits != null) { + const minDigits = options.minimumFractionDigits == null ? 0 : options.minimumFractionDigits!; + const maxDigits = options.maximumFractionDigits == null ? 3 : options.maximumFractionDigits!; + result = value.toFixed(Math.max(minDigits, Math.min(maxDigits, 10))); + + // 移除尾随零(如果maxDigits允许) + if (maxDigits > minDigits) { + result = parseFloat(result).toString(); + // 确保最小小数位数 + if (minDigits > 0) { + const parts = result.split('.'); + if (parts.length == 1) { + result += '.' + '0'.repeat(minDigits); + } else { + const decimalPart = parts[1]; + if (decimalPart.length < minDigits) { + result += '0'.repeat(minDigits - decimalPart.length); + } + } + } + } + } + + // 处理最小整数位数 + if (options.minimumIntegerDigits != null && options.minimumIntegerDigits > 1) { + result = this.formatWithMinimumIntegerDigits(result, options.minimumIntegerDigits); + } + } + + // 处理千分位分隔符 + if (options.useGrouping == true) { + result = this.addThousandsSeparator(result, locale); + } + + // 处理样式 + if (options.style != null) { + switch (options.style) { + case 'currency': + result = this.formatCurrency(result, options, locale); + break; + case 'percent': + result = this.formatPercent(result, value); + break; + case 'decimal': + default: + // 已经是十进制格式 + break; + } + } + + return result; + } catch (e) { + this.ops.warnHandler(`Number formatting failed for value ${value}`, e as Error); + return value.toString(); + } + } + + /** + * 使用有效数字位数格式化数字 + * @param value 数字值 + * @param options 格式化选项 + * @returns 格式化后的字符串 + */ + private formatWithSignificantDigits(value : number, options : NumberFormatOpts) : string { + const minSigDigits = options.minimumSignificantDigits ?? 1; + const maxSigDigits = options.maximumSignificantDigits ?? 21; + + // 确保有效数字位数在合理范围内 + const actualMinSigDigits = Math.max(1, Math.min(minSigDigits, 21)); + const actualMaxSigDigits = Math.max(actualMinSigDigits, Math.min(maxSigDigits, 21)); + + // 使用toPrecision方法格式化有效数字 + let result = value.toPrecision(actualMaxSigDigits); + + // 移除科学计数法表示(如果不是很大或很小的数) + if (!result.includes('e') && !result.includes('E')) { + // 移除尾随零,但保持最小有效数字位数 + const num = parseFloat(result); + result = num.toPrecision(actualMinSigDigits); + + // 如果结果不包含科学计数法,转换为普通数字格式 + if (!result.includes('e') && !result.includes('E')) { + result = parseFloat(result).toString(); + } + } + + return result; + } + + /** + * 使用最小整数位数格式化数字 + * @param numStr 数字字符串 + * @param minIntegerDigits 最小整数位数 + * @returns 格式化后的字符串 + */ + private formatWithMinimumIntegerDigits(numStr : string, minIntegerDigits : number) : string { + const parts = numStr.split('.'); + const integerPart = parts[0]; + const decimalPart = parts.length > 1 ? parts[1] : ''; + + // 在整数部分前面补零 + const paddedInteger = integerPart.padStart(minIntegerDigits, '0'); + + return decimalPart == '' ? `${paddedInteger}.${decimalPart}` : paddedInteger; + } + + // ==================== 日期时间格式化辅助方法 ==================== + + /** + * 获取完整日期格式 + */ + private getFullDateFormat(date : Date, locale : string) : string { + const langCode = locale.split('-')[0].toLowerCase(); + const isUSFormat = langCode == 'en' && (locale.toLowerCase().includes('us') || locale.toLowerCase() == 'en'); + + if (langCode == 'zh') { + return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日 ${this.formatWeekday(date, 'long', locale)}`; + } else if (langCode == 'ja') { + return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日 ${this.formatWeekday(date, 'long', locale)}`; + } else if (langCode == 'ko') { + return `${date.getFullYear()}년 ${date.getMonth() + 1}월 ${date.getDate()}일 ${this.formatWeekday(date, 'long', locale)}`; + } else if (isUSFormat) { + // 美式英语:dddd, MMMM d, yyyy + return `${this.formatWeekday(date, 'long', locale)}, ${this.formatMonth(date, 'long', locale)} ${date.getDate()}, ${date.getFullYear()}`; + } else { + // 欧洲语言:dddd, d MMMM yyyy + return `${this.formatWeekday(date, 'long', locale)}, ${date.getDate()} ${this.formatMonth(date, 'long', locale)} ${date.getFullYear()}`; + } + } + + /** + * 获取长日期格式 + */ + private getLongDateFormat(date : Date, locale : string) : string { + const langCode = locale.split('-')[0].toLowerCase(); + const isUSFormat = langCode == 'en' && (locale.toLowerCase().includes('us') || locale.toLowerCase() == 'en'); + + if (langCode == 'zh') { + return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`; + } else if (langCode == 'ja') { + return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`; + } else if (langCode == 'ko') { + return `${date.getFullYear()}년 ${date.getMonth() + 1}월 ${date.getDate()}일`; + } else if (isUSFormat) { + // 美式英语:MMMM d, yyyy + return `${this.formatMonth(date, 'long', locale)} ${date.getDate()}, ${date.getFullYear()}`; + } else { + // 欧洲语言:d MMMM yyyy + return `${date.getDate()} ${this.formatMonth(date, 'long', locale)} ${date.getFullYear()}`; + } + } + + /** + * 获取中等日期格式 + */ + private getMediumDateFormat(date : Date, locale : string) : string { + const langCode = locale.split('-')[0].toLowerCase(); + const isUSFormat = langCode == 'en' && (locale.toLowerCase().includes('us') || locale.toLowerCase() == 'en'); + + if (langCode == 'zh' || langCode == 'ja' || langCode == 'ko') { + // 东亚语言:YYYY-MM-dd + return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`; + } else if (isUSFormat) { + // 美式英语:MMM d, yyyy + return `${this.formatMonth(date, 'short', locale)} ${date.getDate()}, ${date.getFullYear()}`; + } else { + // 欧洲语言:d MMM yyyy + return `${date.getDate()} ${this.formatMonth(date, 'short', locale)} ${date.getFullYear()}`; + } + } + + /** + * 获取短日期格式 + */ + private getShortDateFormat(date : Date, locale : string) : string { + const langCode = locale.split('-')[0].toLowerCase(); + const isUSFormat = langCode == 'en' && (locale.toLowerCase().includes('us') || locale.toLowerCase() == 'en'); + const year = date.getFullYear().toString().slice(-2); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const day = date.getDate().toString().padStart(2, '0'); + + if (isUSFormat) { + // 美式英语:MM/dd/yy + return `${month}/${day}/${year}`; + } else if (langCode == 'zh' || langCode == 'ja' || langCode == 'ko') { + // 东亚语言:yy/MM/dd + return `${year}/${month}/${day}`; + } else { + // 欧洲语言(英式英语、德语、法语等):dd/MM/yy + return `${day}/${month}/${year}`; + } + } + + /** + * 获取完整时间格式 + */ + private getFullTimeFormat(date : Date, options : DateTimeFormatReal, locale : string) : string { + const timeStr = this.getMediumTimeFormat(date, options, locale); + const timeZone = this.formatTimeZone(date, 'long', options.timeZone); + return `${timeStr} ${timeZone}`; + } + + /** + * 获取长时间格式 + */ + private getLongTimeFormat(date : Date, options : DateTimeFormatReal, locale : string) : string { + const timeStr = this.getMediumTimeFormat(date, options, locale); + const timeZone = this.formatTimeZone(date, 'short', options.timeZone); + return `${timeStr} ${timeZone}`; + } + + /** + * 获取中等时间格式 + */ + private getMediumTimeFormat(date : Date, options : DateTimeFormatReal, locale : string) : string { + const hour = this.formatHour(date, 'numeric', options.hour12, options.hourCycle); + const minute = this.formatMinute(date, '2-digit'); + const second = this.formatSecond(date, '2-digit', 0); + const dayPeriod = options.hour12 ? ` ${this.formatDayPeriod(date, 'short', locale)}` : ''; + return `${hour}:${minute}:${second}${dayPeriod}`; + } + + /** + * 获取短时间格式 + */ + private getShortTimeFormat(date : Date, options : DateTimeFormatReal, locale : string) : string { + const hour = this.formatHour(date, 'numeric', options.hour12, options.hourCycle); + const minute = this.formatMinute(date, '2-digit'); + const dayPeriod = options.hour12 ? ` ${this.formatDayPeriod(date, 'short', locale)}` : ''; + return `${hour}:${minute}${dayPeriod}`; + } + + /** + * 格式化星期 + */ + private formatWeekday(date : Date, style : string, locale : string) : string { + const weekdays = this.getWeekdayNames(locale); + const dayIndex = date.getDay(); + + switch (style) { + case 'long': + return weekdays.long[dayIndex]; + case 'short': + return weekdays.short[dayIndex]; + case 'narrow': + return weekdays.narrow[dayIndex]; + default: + return weekdays.long[dayIndex]; + } + } + + /** + * 格式化纪元 + */ + private formatEra(date : Date, style : string, locale : string) : string { + const year = date.getFullYear(); + const langCode = locale.split('-')[0].toLowerCase(); + + if (langCode == 'zh') { + return year > 0 ? '公元' : '公元前'; + } else { + switch (style) { + case 'long': + return year > 0 ? 'Anno Domini' : 'Before Christ'; + case 'short': + case 'narrow': + default: + return year > 0 ? 'AD' : 'BC'; + } + } + } + + /** + * 数字系统转换 + * @param number 数字字符串 + * @param numberingSystem 数字系统 + * @returns 转换后的数字字符串 + */ + private convertNumberingSystem(number : string, numberingSystem : string) : string { + if (numberingSystem == 'latn' || numberingSystem == '') { + return number; // 拉丁数字(默认) + } + + // 数字系统映射表 + const numberingSystems = new Map(); + numberingSystems.set('arab', ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩']); // 阿拉伯-印度数字 + numberingSystems.set('arabext', ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']); // 扩展阿拉伯-印度数字 + numberingSystems.set('deva', ['०', '१', '२', '३', '४', '५', '६', '७', '८', '९']); // 天城文数字 + numberingSystems.set('fullwide', ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']); // 全角数字 + numberingSystems.set('hanidec', ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九']); // 汉字数字 + numberingSystems.set('thai', ['๐', '๑', '๒', '๓', '๔', '๕', '๖', '๗', '๘', '๙']); // 泰文数字 + + const digits = numberingSystems.get(numberingSystem); + if (digits == null) { + return number; // 不支持的数字系统,返回原数字 + } + + // 转换每个数字字符 + let result = ''; + for (let i = 0; i < number.length; i++) { + const char = number.charAt(i); + if (char >= '0' && char <= '9') { + const digitIndex = parseInt(char); + result += digits[digitIndex]; + } else { + result += char; // 非数字字符保持不变 + } + } + + return result; + } + + /** + * 格式化年份 + */ + private formatYear(date : Date, style : string, locale : string = '', numberingSystem : string = 'latn', dateSeparator : string = '') : string { + const year = date.getFullYear(); + const langCode = locale.split('-')[0].toLowerCase(); + + let yearStr = ''; + switch (style) { + case 'numeric': + yearStr = this.convertNumberingSystem(year.toString(), numberingSystem); + // 如果提供了分隔符,返回纯数字;否则中文环境下添加"年"字 + return (dateSeparator != '' || langCode != 'zh') ? yearStr : `${yearStr}年`; + case '2-digit': + const shortYear = year.toString().slice(-2).padStart(2, '0'); + yearStr = this.convertNumberingSystem(shortYear, numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? yearStr : `${yearStr}年`; + default: + yearStr = this.convertNumberingSystem(year.toString(), numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? yearStr : `${yearStr}年`; + } + } + + /** + * 格式化月份 + */ + private formatMonth(date : Date, style : string, locale : string, numberingSystem : string = 'latn', dateSeparator : string = '') : string { + const month = date.getMonth(); + const monthNames = this.getMonthNames(locale); + const langCode = locale.split('-')[0].toLowerCase(); + + switch (style) { + case 'numeric': + // 如果提供了分隔符,返回纯数字;否则中文环境下添加"月"字 + const monthStr = this.convertNumberingSystem((month + 1).toString(), numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? monthStr : `${monthStr}月`; + case '2-digit': + const paddedMonth = (month + 1).toString().padStart(2, '0'); + const paddedMonthStr = this.convertNumberingSystem(paddedMonth, numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? paddedMonthStr : `${paddedMonthStr}月`; + case 'long': + return monthNames.long[month]; + case 'short': + return monthNames.short[month]; + case 'narrow': + return monthNames.narrow[month]; + default: + const defaultMonthStr = this.convertNumberingSystem((month + 1).toString(), numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? defaultMonthStr : `${defaultMonthStr}月`; + } + } + + /** + * 格式化日期 + */ + private formatDay(date : Date, style : string, locale : string = '', numberingSystem : string = 'latn', dateSeparator : string = '') : string { + const day = date.getDate(); + const langCode = locale.split('-')[0].toLowerCase(); + + switch (style) { + case 'numeric': + // 如果提供了分隔符,返回纯数字;否则中文环境下添加"日"字 + const dayStr = this.convertNumberingSystem(day.toString(), numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? dayStr : `${dayStr}日`; + case '2-digit': + const paddedDay = day.toString().padStart(2, '0'); + const paddedDayStr = this.convertNumberingSystem(paddedDay, numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? paddedDayStr : `${paddedDayStr}日`; + default: + const defaultDayStr = this.convertNumberingSystem(day.toString(), numberingSystem); + return (dateSeparator != '' || langCode != 'zh') ? defaultDayStr : `${defaultDayStr}日`; + } + } + + /** + * 格式化小时 + */ + private formatHour(date : Date, style : string, hour12 : boolean, hourCycle : string, numberingSystem : string = 'latn') : string { + let hour = date.getHours(); + + if (hour12) { + if (hourCycle == 'h11') { + hour = hour % 12; + } else { // h12 + hour = hour % 12; + if (hour == 0) hour = 12; + } + } else { + if (hourCycle == 'h11') { + hour = hour % 12; + } else if (hourCycle == 'h24') { + if (hour == 0) hour = 24; + } + // h23 保持原样 + } + + switch (style) { + case 'numeric': + return this.convertNumberingSystem(hour.toString(), numberingSystem); + case '2-digit': + return this.convertNumberingSystem(hour.toString().padStart(2, '0'), numberingSystem); + default: + return this.convertNumberingSystem(hour.toString(), numberingSystem); + } + } + + /** + * 格式化分钟 + */ + private formatMinute(date : Date, style : string, numberingSystem : string = 'latn') : string { + const minute = date.getMinutes(); + switch (style) { + case 'numeric': + return this.convertNumberingSystem(minute.toString(), numberingSystem); + case '2-digit': + return this.convertNumberingSystem(minute.toString().padStart(2, '0'), numberingSystem); + default: + return this.convertNumberingSystem(minute.toString(), numberingSystem); + } + } + + /** + * 格式化秒 + */ + private formatSecond(date : Date, style : string, fractionalDigits : number, numberingSystem : string = 'latn') : string { + const second = date.getSeconds(); + const millisecond = date.getMilliseconds(); + + let result = ''; + switch (style) { + case 'numeric': + result = this.convertNumberingSystem(second.toString(), numberingSystem); + break; + case '2-digit': + result = this.convertNumberingSystem(second.toString().padStart(2, '0'), numberingSystem); + break; + default: + result = this.convertNumberingSystem(second.toString(), numberingSystem); + break; + } + + // 添加小数秒 + if (fractionalDigits > 0) { + const fractional = millisecond.toString().padStart(3, '0').slice(0, fractionalDigits); + const convertedFractional = this.convertNumberingSystem(fractional, numberingSystem); + result += `.${convertedFractional}`; + } + + return result; + } + + /** + * 格式化时段(AM/PM) + */ + private formatDayPeriod(date : Date, style : string, locale : string) : string { + const hour = date.getHours(); + const isAM = hour < 12; + const langCode = locale.split('-')[0].toLowerCase(); + + if (langCode == 'zh') { + switch (style) { + case 'long': + return isAM ? '上午' : '下午'; + case 'short': + case 'narrow': + default: + return isAM ? '上午' : '下午'; + } + } else { + switch (style) { + case 'long': + return isAM ? 'AM' : 'PM'; + case 'short': + case 'narrow': + default: + return isAM ? 'AM' : 'PM'; + } + } + } + + /** + * 格式化时区 + */ + private formatTimeZone(date : Date, style : string, timeZone : string) : string { + // 简化实现,实际应用中可能需要更复杂的时区处理 + switch (style) { + case 'long': + return timeZone == 'UTC' ? 'Coordinated Universal Time' : timeZone; + case 'short': + default: + return timeZone == 'UTC' ? 'UTC' : timeZone; + } + } + + /** + * 组合日期时间各部分 + */ + private combineDateTimeParts(parts : string[], locale : string, dateSeparator : string = '') : string { + const langCode = locale.split('-')[0].toLowerCase(); + + // 如果设置了自定义分隔符,使用自定义分隔符连接 + if (dateSeparator != '') { + return parts.join(dateSeparator); + } + + if (langCode == 'zh') { + // 中文习惯:直接连接(年份和日期已包含单位字符) + return parts.join(''); + } else { + // 英文习惯:用空格分隔 + return parts.join(' '); + } + } + + /** + * 获取星期名称 + */ + private getWeekdayNames(locale : string) : DateTimeNames { + const langCode = locale.split('-')[0].toLowerCase(); + + if (langCode == 'zh') { + return { + long: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], + short: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], + narrow: ['日', '一', '二', '三', '四', '五', '六'] + }; + } else { + return { + long: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + short: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + narrow: ['S', 'M', 'T', 'W', 'T', 'F', 'S'] + }; + } + } + + /** + * 获取月份名称 + */ + private getMonthNames(locale : string) : DateTimeNames { + const langCode = locale.split('-')[0].toLowerCase(); + + if (langCode == 'zh') { + return { + long: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + short: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + narrow: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] + }; + } else { + return { + long: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + short: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'] + }; + } + } + + /** + * 添加千分位分隔符 + * @param numStr 数字字符串 + * @param locale 语言代码 + * @returns 带千分位分隔符的字符串 + */ + private addThousandsSeparator(numStr : string, locale : string) : string { + const parts = numStr.split('.'); + const integerPart = parts[0]; + const decimalPart = parts.length > 1 ? parts[1] : ''; + + // 根据语言选择分隔符 + const separator = this.getThousandsSeparator(locale); + + // 添加千分位分隔符 + const formattedInteger = integerPart.replace(/(\d)(?=(\d{3})+(?!\d))/g, `$1${separator}`); + + return decimalPart == '' ? `${formattedInteger}.${decimalPart}` : formattedInteger; + } + + /** + * 千分位分隔符映射配置 + */ + private static readonly THOUSANDS_SEPARATOR_MAP = new Map([ + // 使用逗号的语言 + ['en', ','], // 英语 + ['zh', ','], // 中文 + ['zh-Hant', ','], // 中文 + ['zh', ','], // 中文 + ['ja', ','], // 日语 + ['ko', ','], // 韩语 + ['pt', ','], // 葡萄牙语 + ['th', ','], // 泰语 + ['vi', ','], // 越南语 + ['id', ','], // 印尼语 + ['ms', ','], // 马来语 + ['tl', ','], // 菲律宾语 + ['he', ','], // 希伯来语 + ['ar', ','], // 阿拉伯语 + // 使用空格的语言 + ['de', ' '], // 德语 + ['fr', ' '], // 法语 + ['ru', ' '], // 俄语 + ['sv', ' '], // 瑞典语 + ['no', ' '], // 挪威语 + ['da', ' '], // 丹麦语 + ['fi', ' '], // 芬兰语 + ['cs', ' '], // 捷克语 + ['sk', ' '], // 斯洛伐克语 + ['pl', ' '], // 波兰语 + // 使用点号的语言 + ['es', '.'], // 西班牙语 + ['it', '.'], // 意大利语 + ['nl', '.'], // 荷兰语 + ['tr', '.'], // 土耳其语 + // 使用撇号的语言 + ['ch', "'"], // 瑞士德语 + ]); + + /** + * 获取千分位分隔符 + * @param locale 语言代码 + * @returns 分隔符字符 + */ + private getThousandsSeparator(locale : string) : string { + // 提取语言代码前缀(如 'en-US' -> 'en') + const langCode = locale.split('-')[0].toLowerCase(); + + // 从映射中获取分隔符 + const separator = Tmui4xI18n.THOUSANDS_SEPARATOR_MAP.get(langCode); + + // 如果找到对应的分隔符则返回,否则返回默认的逗号 + return separator ?? ','; + } + + /** + * 格式化货币 + * @param numStr 数字字符串 + * @param options 格式化选项 + * @param locale 语言代码 + * @returns 格式化后的货币字符串 + */ + private formatCurrency(numStr : string, options : NumberFormatOpts, locale : string) : string { + const currency = options.currency ?? 'USD'; + const currencyDisplay = options.currencyDisplay ?? 'symbol'; + + let currencySymbol = currency; + if (currencyDisplay == 'symbol') { + // 全球主要经济体货币符号映射 + switch (currency.toUpperCase()) { + // 美洲 + case 'USD': + currencySymbol = '$'; + break; + case 'CAD': + currencySymbol = 'C$'; + break; + case 'BRL': + currencySymbol = 'R$'; + break; + case 'MXN': + currencySymbol = '$'; + break; + // 欧洲 + case 'EUR': + currencySymbol = '€'; + break; + case 'GBP': + currencySymbol = '£'; + break; + case 'CHF': + currencySymbol = 'CHF'; + break; + case 'RUB': + currencySymbol = '₽'; + break; + // 亚太地区 + case 'JPY': + currencySymbol = '¥'; + break; + case 'CNY': + case 'RMB': + currencySymbol = '¥'; + break; + case 'KRW': + currencySymbol = '₩'; + break; + case 'INR': + currencySymbol = '₹'; + break; + case 'AUD': + currencySymbol = 'A$'; + break; + case 'SGD': + currencySymbol = 'S$'; + break; + case 'HKD': + currencySymbol = 'HK$'; + break; + case 'TWD': + currencySymbol = 'NT$'; + break; + case 'THB': + currencySymbol = '฿'; + break; + case 'MYR': + currencySymbol = 'RM'; + break; + case 'VND': + currencySymbol = '₫'; + break; + case 'IDR': + currencySymbol = 'Rp'; + break; + case 'PHP': + currencySymbol = '₱'; + break; + // 中东地区 + case 'SAR': + currencySymbol = '﷼'; + break; + case 'AED': + currencySymbol = 'د.إ'; + break; + case 'ILS': + currencySymbol = '₪'; + break; + case 'TRY': + currencySymbol = '₺'; + break; + // 非洲 + case 'ZAR': + currencySymbol = 'R'; + break; + default: + currencySymbol = currency; + break; + } + } + + // 根据货币和地区决定货币符号位置(参考国际标准) + return this.getCurrencyPosition(currencySymbol, numStr, currency, locale); + } + + /** + * 获取货币符号位置 + * @param symbol 货币符号 + * @param numStr 数字字符串 + * @param currency 货币代码 + * @param locale 语言代码 + * @returns 格式化后的货币字符串 + */ + private getCurrencyPosition(symbol : string, numStr : string, currency : string, locale : string) : string { + const currencyCode = currency.toUpperCase(); + + // 符号在前面的货币(无空格) + const prefixNoSpace = ['USD', 'CAD', 'AUD', 'HKD', 'SGD', 'TWD', 'GBP', 'CNY', 'RMB', 'JPY']; + // 符号在前面的货币(有空格) + const prefixWithSpace = ['BRL', 'MXN', 'KRW', 'INR', 'THB', 'VND', 'IDR', 'PHP', 'ILS', 'TRY']; + // 符号在后面的货币(有空格) + const suffixWithSpace = ['EUR', 'CHF', 'RUB', 'MYR', 'SAR', 'AED', 'ZAR']; + + if (prefixNoSpace.includes(currencyCode)) { + return `${symbol}${numStr}`; + } else if (prefixWithSpace.includes(currencyCode)) { + return `${symbol} ${numStr}`; + } else if (suffixWithSpace.includes(currencyCode)) { + return `${numStr} ${symbol}`; + } else { + // 默认根据语言决定 + if (locale.startsWith('en') || locale.startsWith('zh')) { + return `${symbol}${numStr}`; + } else { + return `${numStr} ${symbol}`; + } + } + } + + /** + * 格式化百分比 + * @param numStr 数字字符串 + * @param originalValue 原始数值 + * @returns 格式化后的百分比字符串 + */ + private formatPercent(numStr : string, originalValue : number) : string { + // 将数值乘以100并添加百分号 + const percentValue = originalValue * 100; + return `${percentValue}%`; + } + /** + * 获取翻译消息 + * @param key 翻译键 + * @param locale 语言代码 + * @returns 翻译消息或null + */ + private getMessage(key : string, locale : string) : StringOrNull { + const messages = this.ops.messages; + if (messages[locale] == null) { + return null; + } + + const localeMessages = messages[locale] as UTSJSONObjectOrNull; + return this.getNestedValue(localeMessages, key); + } + + /** + * 获取嵌套对象的值 + * @param obj 对象 + * @param path 路径,如 'user.name' + * @returns 值或null + */ + private getNestedValue(obj : UTSJSONObjectOrNull, path : string) : StringOrNull { + const keys = path.split('.'); + + let getAny : GetAnyTypeOrNull = null; + + getAny = (objdata : AnyOrNull) : AnyOrNull => { + let realGetAny = getAny!; + let path : StringOrNull = keys.shift() + if (objdata == null) return null; + if ( + typeof objdata == 'string' || + typeof objdata == 'number' + ) return objdata + if (path == null) return null; + return realGetAny((objdata! as UTSJSONObject).getAny(path)); + } + + let current : AnyOrNull = getAny(obj); + + if (typeof current == 'number') return current.toString() + return typeof current == 'string' ? current : null; + } + + /** + * 处理复数形式 + * @param message 包含复数的消息 + * @param count 数量 + * @param locale 语言代码 + * @returns 选择的复数形式 + */ + private handlePlural(message : string, count : number, locale : string) : string { + const choices = message.split('|').map((choice : string) : string => choice.trim()); + const choicesLength = choices.length; + + // 获取复数规则 + let pluralRule = this.ops.pluralRule; + if (this.ops.pluralRules.has(locale)) { + pluralRule = this.ops.pluralRules.get(locale)!; + } + + // 应用复数规则 + let index = 0; + if (pluralRule != null) { + // 第有理数无法类型嵌套,暂不支持设置为null + index = pluralRule(count, choicesLength, null); + } + + // 确保索引在有效范围内 + const safeIndex = Math.max(0, Math.min(index, choicesLength - 1)); + let result = choices[safeIndex] + if (result == '' || result == null) { + result = choices[0] + } + if (result == '' || result == null) { + result = message + } + + return result; + } + + /** + * 字符串插值处理 + * @param message 消息模板 + * @param values 插值参数 + * @returns 插值后的字符串 + */ + private interpolate(message : string, values : UTSJSONObjectOrArray) : string { + let msg = message; + if (Array.isArray(values)) { + // 处理位置插值 {0}, {1}, {2}... + // #ifndef APP-ANDROID + msg = message.replace(/\{(\d+)\}/g, (match : string, key : string, index : number) : string => { + const value = values[parseInt(key)]; + + if (value != null) { + let result = typeof value == 'number' ? value.toString() : value as string + return result; + } + return match; // 保持原样如果没有找到值 + }); + // #endif + // #ifdef APP-ANDROID + msg = message.replace(/\{(\d+)\}/g, (match : string, key : string, offset : number, str : string) : string => { + const value = values[parseInt(key)]; + if (value != null) { + let result = typeof value == 'number' ? value.toString() : value as string + return result; + } + return match; // 保持原样如果没有找到值 + }); + // #endif + } else if (values instanceof UTSJSONObject) { + if (UTSJSONObject.keys(values).length == 0) { + return message; + } + // 处理命名插值 {name}比如{count},{n}等 + // #ifndef APP-ANDROID + msg = message.replace(/\{([^}]+)\}/g, (match : string, key : string, index : number) : string => { + const value = values[key]; + if (value != null) { + return value as string; + } + return match; // 保持原样如果没有找到值 + }); + // #endif + // #ifdef APP-ANDROID + msg = message.replace(/\{([^}]+)\}/g, (match : string, key : string, offset : number, str : string) : string => { + const value = values[key]; + if (value != null) { + if (typeof value == 'string') return value; + if (typeof value == 'number') return value.toString(); + + } + return match; // 保持原样如果没有找到值 + }); + // #endif + } + + + + return msg; + } +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/instans/localLanuage/en.json b/uni_modules/x-vuei18n-s/instans/localLanuage/en.json new file mode 100644 index 0000000..108b6d9 --- /dev/null +++ b/uni_modules/x-vuei18n-s/instans/localLanuage/en.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "Cancel", + "confirm": "Confirm", + "success": "Success", + "fail": "Failed", + "warn": "Warning", + "info": "Info", + "clear":"Clear", + "pickerTitle":"Please select", + "calendar":{ + "year": "Year", + "month": "Month", + "day": "Day", + "hour": "Hour", + "minute": "Minute", + "second": "Second", + "titleCurrentMonth":"{0} {1}", + "monthCountSelected":"{count} months", + "selectedStatus":"{count} days selected | No date selected | Selected | End date not selected", + "rangStatus":"Start | End | Today", + "tips":"Max {count} days", + "currentMonthTitle":"This month", + "week":"Mon | Tue | Wed | Thu | Fri | Sat | Sun" + }, + "betweentTime": { + "start": "Start time", + "end": "End time", + "quiakListTitle":"Today | This week | This month | This year | This quarter", + "quiakListTitle2":"Last {count} days", + "quiakListTitle3":"Previous {count} years", + "title":"Please select time", + "splite":"to" + }, + "uploadFile":{ + "title":"Select file", + "uploadStatus":"Pending upload | Uploading... | Upload failed | Upload successful | Exceeds size", + "tips1":"Deletion prohibited during upload", + "tips2":"Deletion prohibited for uploaded files" + }, + "pickerSelected":{ + "placeholder":"Please enter keywords", + "search":"Search", + "selected":"{count} items selected", + "claer":"Clear selection", + "selectedMode":"Currently in single selection mode", + "selectedALl":"Select all" + }, + "tree":{ + "changeTitle":"Modify content", + "addTitle":"Add subordinate", + "inputTitle":"Title", + "inputId":"Identifier ID", + "inputTips1":"Do not repeat, auto-generate when empty" + }, + "input":{ + "placeholder":"Please select or fill in" + }, + "inputTag":{ + "placeholder": "Please enter and press Enter", + "tips": "Cannot be empty", + "tips2": "Exceeds maximum limit: {count}", + "btnText": "Add Tag" + }, + "keyboard":{ + "placeholder":"Safe keyboard for secure input", + "space":"Space", + "confirm":"Confirm" + }, + "pickerTime":{ + "hour":"Hour", + "minute":"Minute", + "second":"Second" + }, + "cascader":{ + "placeholder":"Please select", + "currentPlaceholder":"Select current" + }, + "pickerDate":{ + "placeholder":"Please select time", + "year":"Year", + "month":"Month", + "day":"Day", + "hour":"Hour", + "minute":"Minute", + "second":"Second" + }, + "uploadMedia":{ + "tips1":"Dragging sort not allowed during upload", + "videoPreview":"Video preview", + "close":"Close", + "systemError":"System error", + "limitMaxCount":"Exceeded max upload count", + "uploadStatus":"Pending upload | Uploading... | Upload failed | Upload successful | Exceeds size" + }, + "checkbox":{ + "tips":"Exceeds maximum selection" + }, + "weekbar":{ + "week":"Mon | Tue | Wed | Thu | Fri | Sat | Sun" + }, + "pagination":{ + "prev": "Previous", + "next": "Next" + }, + "search":{ + "placeholder":"Enter keywords", + "cancel":"Cancel" + }, + "xmore":{ + "off": "Expand more", + "on": "Collapse more" + }, + "empty":{ + "moreLabel": "No more data", + "errorLabel": "Error~", + "btnLabel": "Retry", + "title":"No data" + }, + "xloading":{ + "label":"Loading..." + }, + "actionModal":{ + "title":"Reminder", + "btnText":"Confirm" + }, + "actionMenu":{ + "title":"Please select", + "btnText":"Confirm" + }, + "pullRefresh":{ + "status_1":"Refreshing", + "status_2":"Pull down more", + "status_3":"Release to refresh", + "status_4":"Refresh done", + "status_5":"Refresh failed" + }, + "virtualList":{ + "status_0":"Pull down more", + "status_1":"Release to refresh", + "status_2":"Refreshing", + "status_3":"Cancel refresh", + "status_4":"Refresh timeout, retry", + "status_5":"Refresh done" + }, + "imageResize":{ + "ok":"Done", + "cancel":"Cancel", + "reset":"Reset" + }, + "colorView":{ + "rgb":"RGB", + "hub":"Spectrum", + "grid":"Palette", + "alpha":"Alpha", + "hex":"HEX", + "r":"Red", + "g":"Green", + "b":"Blue" + }, + "modal": { + "title": "Title" + }, + "mention": { + "placeholder": "Enter content, @select friend, press confirm" + }, + "slideVerify": { + "tipsText": "Drag to position", + "tipsTextSuccess": "Verified", + "tipsTextFail": "Verification failed" + }, + "xRequest":{ + "error":"Server error:", + "success":"Success", + "hostFailEmpty":"Domain empty", + "loading":"Loading" + } + } +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/instans/localLanuage/ja.json b/uni_modules/x-vuei18n-s/instans/localLanuage/ja.json new file mode 100644 index 0000000..6b6195b --- /dev/null +++ b/uni_modules/x-vuei18n-s/instans/localLanuage/ja.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "キャンセル", + "confirm": "確認", + "success": "成功", + "fail": "失敗", + "warn": "警告", + "info": "情報", + "clear":"クリア", + "pickerTitle":"選択してください", + "calendar":{ + "year": "年", + "month": "月", + "day": "日", + "hour": "時", + "minute": "分", + "second": "秒", + "titleCurrentMonth":"{0}年{1}月", + "monthCountSelected":"{count}ヶ月", + "selectedStatus":"選択済み{count}日 | 日付未選択 | 選択済み | 終了日未選択", + "rangStatus":"開始 | 終了 | 本日", + "tips":"最大選択{count}日", + "currentMonthTitle":"今月", + "week":"月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日 | 日曜日" + }, + "betweentTime": { + "start": "開始時間", + "end": "終了時間", + "quiakListTitle":"本日 | 今週 | 今月 | 今年 | 今四半期", + "quiakListTitle2":"最近{count}日", + "quiakListTitle3":"前{count}年", + "title":"時間を選択してください", + "splite":"から" + }, + "uploadFile":{ + "title":"ファイルを選択", + "uploadStatus":"アップロード待機 | アップロード中... | アップロード失敗 | アップロード成功 | サイズ超過", + "tips1":"アップロード中は削除禁止", + "tips2":"アップロード済みファイルは削除禁止" + }, + "pickerSelected":{ + "placeholder":"キーワードを入力してください", + "search":"検索", + "selected":"選択済み{count}項目", + "claer":"選択をクリア", + "selectedMode":"現在は単一選択モード", + "selectedALl":"すべて選択" + }, + "tree":{ + "changeTitle":"内容を変更", + "addTitle":"下位を追加", + "inputTitle":"タイトル", + "inputId":"識別ID", + "inputTips1":"重複しないでください、空の場合は自動生成" + }, + "input":{ + "placeholder":"選択または入力してください" + }, + "inputTag":{ + "placeholder":"入力してEnterを押してください", + "tips":"空にできません", + "tips2":"制限最大数を超過:{count}", + "btnText":"タグを追加" + }, + "keyboard":{ + "placeholder":"安全キーボードで安心入力", + "space":"スペース", + "confirm":"確認" + }, + "pickerTime":{ + "hour":"時間", + "minute":"分", + "second":"秒数" + }, + "cascader":{ + "placeholder":"選択してください", + "currentPlaceholder":"本級を選択" + }, + "pickerDate":{ + "placeholder":"時間を選択してください", + "year":"年", + "month":"月", + "day":"日", + "hour":"時", + "minute":"分", + "second":"秒" + }, + "uploadMedia":{ + "tips1":"アップロード中はドラッグソート禁止", + "videoPreview":"ビデオプレビュー", + "close":"閉じる", + "systemError":"システム異常", + "limitMaxCount":"最大アップロード数を超過", + "uploadStatus":"アップロード待機 | アップロード中... | アップロード失敗 | アップロード成功 | サイズ超過" + }, + "checkbox":{ + "tips":"最大選択数を超過" + }, + "weekbar":{ + "week":"月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日 | 日曜日" + }, + "pagination":{ + "prev": "前のページ", + "next": "次のページ" + }, + "search":{ + "placeholder":"キーワードを入力", + "cancel":"キャンセル" + }, + "xmore":{ + "off": "もっと展開", + "on": "もっと収納" + }, + "empty":{ + "moreLabel": "データなし", + "errorLabel": "エラー", + "btnLabel": "リトライ", + "title":"データなし" + }, + "xloading":{ + "label":"ロード中..." + }, + "actionModal":{ + "title":"リマインダー", + "btnText":"確認" + }, + "actionMenu":{ + "title":"選択してください", + "btnText":"確認" + }, + "pullRefresh":{ + "status_1":"リフレッシュ中", + "status_2":"さらに下に引っ張る", + "status_3":"離してリフレッシュ", + "status_4":"リフレッシュ完了", + "status_5":"リフレッシュ失敗" + }, + "virtualList":{ + "status_0":"さらに下に引っ張る", + "status_1":"離してリフレッシュ", + "status_2":"リフレッシュ中", + "status_3":"リフレッシュキャンセル", + "status_4":"リフレッシュタイムアウト、リトライ", + "status_5":"リフレッシュ完了" + }, + "imageResize":{ + "ok":"完了", + "cancel":"キャンセル", + "reset":"リセット" + }, + "colorView":{ + "rgb":"RGB", + "hub":"スペクトル", + "grid":"カラーパレット", + "alpha":"透明度", + "hex":"HEX", + "r":"赤", + "g":"緑", + "b":"青" + }, + "modal": { + "title": "タイトル" + }, + "mention": { + "placeholder": "内容を入力、@で友達選択、確認押す" + }, + "slideVerify": { + "tipsText": "指定位置にドラッグ", + "tipsTextSuccess": "検証成功", + "tipsTextFail": "検証失敗" + }, + "xRequest":{ + "error":"サーバーエラー:", + "success":"操作成功", + "hostFailEmpty":"リクエストドメイン未入力", + "loading":"ロード中" + } + } +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/instans/localLanuage/ko.json b/uni_modules/x-vuei18n-s/instans/localLanuage/ko.json new file mode 100644 index 0000000..5689303 --- /dev/null +++ b/uni_modules/x-vuei18n-s/instans/localLanuage/ko.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "취소", + "confirm": "확인", + "success": "성공", + "fail": "실패", + "warn": "경고", + "info": "정보", + "clear":"지우기", + "pickerTitle":"선택하세요", + "calendar":{ + "year": "년", + "month": "월", + "day": "일", + "hour": "시", + "minute": "분", + "second": "초", + "titleCurrentMonth":"{0}년{1}월", + "monthCountSelected":"{count}개월", + "selectedStatus":"선택됨{count}일 | 날짜 미선택 | 선택됨 | 종료일 미선택", + "rangStatus":"시작 | 종료 | 오늘", + "tips":"최대선택{count}일", + "currentMonthTitle":"이번 달", + "week":"월요일 | 화요일 | 수요일 | 목요일 | 금요일 | 토요일 | 일요일" + }, + "betweentTime": { + "start": "시작 시간", + "end": "종료 시간", + "quiakListTitle":"오늘 | 이번 주 | 이번 달 | 올해 | 이번 분기", + "quiakListTitle2":"최근 {count}일", + "quiakListTitle3":"이전 {count}년", + "title":"시간을 선택하세요", + "splite":"부터" + }, + "uploadFile":{ + "title":"파일 선택", + "uploadStatus":"업로드 대기 | 업로드 중... | 업로드 실패 | 업로드 성공 | 크기 초과", + "tips1":"업로드 중 삭제 금지", + "tips2":"업로드된 파일 삭제 금지" + }, + "pickerSelected":{ + "placeholder":"키워드를 입력하세요", + "search":"검색", + "selected":"선택됨{count}개", + "claer":"선택 지우기", + "selectedMode":"현재 단일 선택 모드", + "selectedALl":"모두 선택" + }, + "tree":{ + "changeTitle":"내용 수정", + "addTitle":"하위 추가", + "inputTitle":"제목", + "inputId":"식별 ID", + "inputTips1":"중복하지 마세요, 비어있으면 자동 생성" + }, + "input":{ + "placeholder":"선택하거나 입력하세요" + }, + "inputTag":{ + "placeholder":"입력 후 엔터를 누르세요", + "tips":"비워둘 수 없습니다", + "tips2":"최대 수 초과:{count}", + "btnText":"태그 추가" + }, + "keyboard":{ + "placeholder":"안전한 키보드로 안심 입력", + "space":"스페이스", + "confirm":"확인" + }, + "pickerTime":{ + "hour":"시간", + "minute":"분", + "second":"초수" + }, + "cascader":{ + "placeholder":"선택하세요", + "currentPlaceholder":"본급 선택" + }, + "pickerDate":{ + "placeholder":"시간을 선택하세요", + "year":"년", + "month":"월", + "day":"일", + "hour":"시", + "minute":"분", + "second":"초" + }, + "uploadMedia":{ + "tips1":"업로드 중 드래그 정렬 금지", + "videoPreview":"비디오 미리보기", + "close":"닫기", + "systemError":"시스템 이상", + "limitMaxCount":"최대 업로드 수 초과", + "uploadStatus":"업로드 대기 | 업로드 중... | 업로드 실패 | 업로드 성공 | 크기 초과" + }, + "checkbox":{ + "tips":"최대 선택 수 초과" + }, + "weekbar":{ + "week":"월요일 | 화요일 | 수요일 | 목요일 | 금요일 | 토요일 | 일요일" + }, + "pagination":{ + "prev": "이전 페이지", + "next": "다음 페이지" + }, + "search":{ + "placeholder":"키워드 입력", + "cancel":"취소" + }, + "xmore":{ + "off": "더 펼치기", + "on": "더 접기" + }, + "empty":{ + "moreLabel": "데이터 없음", + "errorLabel": "오류", + "btnLabel": "재시도", + "title":"데이터 없음" + }, + "xloading":{ + "label":"로드 중..." + }, + "actionModal":{ + "title":"리마인더", + "btnText":"확인" + }, + "actionMenu":{ + "title":"선택하세요", + "btnText":"확인" + }, + "pullRefresh":{ + "status_1":"새로고침 중", + "status_2":"더 아래로 끌기", + "status_3":"놓아서 새로고침", + "status_4":"새로고침 완료", + "status_5":"새로고침 실패" + }, + "virtualList":{ + "status_0":"더 아래로 끌기", + "status_1":"놓아서 새로고침", + "status_2":"새로고침 중", + "status_3":"새로고침 취소", + "status_4":"새로고침 타임아웃, 재시도", + "status_5":"새로고침 완료" + }, + "imageResize":{ + "ok":"완료", + "cancel":"취소", + "reset":"리셋" + }, + "colorView":{ + "rgb":"RGB", + "hub":"스펙트럼", + "grid":"팔레트", + "alpha":"투명도", + "hex":"HEX", + "r":"빨강", + "g":"녹색", + "b":"파랑" + }, + "modal": { + "title": "제목" + }, + "mention": { + "placeholder": "내용 입력, @로 친구 선택, 확인 누르기" + }, + "slideVerify": { + "tipsText": "지정 위치로 드래그", + "tipsTextSuccess": "검증 성공", + "tipsTextFail": "검증 실패" + }, + "xRequest":{ + "error":"서버 오류:", + "success":"작업 성공", + "hostFailEmpty":"요청 도메인 미입력", + "loading":"로드 중" + } + } +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/instans/localLanuage/zh-Hans.json b/uni_modules/x-vuei18n-s/instans/localLanuage/zh-Hans.json new file mode 100644 index 0000000..82d5e43 --- /dev/null +++ b/uni_modules/x-vuei18n-s/instans/localLanuage/zh-Hans.json @@ -0,0 +1,181 @@ +{ + "tmui4x": { + "cancel": "取消", + "confirm": "确认", + "success": "成功", + "fail": "失败", + "warn": "警告", + "info": "提醒", + "clear":"清空", + "pickerTitle":"请选择", + "calendar":{ + "year": "年", + "month": "月", + "day": "日", + "hour": "时", + "minute": "分", + "second": "秒", + "titleCurrentMonth":"{0}年{1}月", + "monthCountSelected":"{count}月", + "selectedStatus":"已选择{count}日 | 未选择日期 | 已选择 | 未选择结束日期", + "rangStatus":"开始 | 结束 | 本日", + "tips":"最大选择{count}日", + "currentMonthTitle":"本月", + "week":"周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日" + }, + "betweentTime": { + "start": "开始时间", + "end": "结束时间", + "quiakListTitle":"本日 | 本周 | 本月 | 本年 | 本季度", + "quiakListTitle2":"最近{count}天", + "quiakListTitle3":"前{count}年", + "title":"请选择时间", + "splite":"至" + }, + "uploadFile":{ + "title":"选择文件", + "uploadStatus":"待上传 | 上传中... | 上传失败 | 上传成功 | 超过大小", + "tips1":"上传中禁止删除", + "tips2":"已上传文件禁止删除" + }, + "pickerSelected":{ + "placeholder":"请输入关键词", + "search":"搜索", + "selected":"已选择{count}项", + "claer":"清空选择", + "selectedMode":"当前为单选模式", + "selectedALl":"选择所有" + }, + "tree":{ + "changeTitle":"修改内容", + "addTitle":"添加下级", + "inputTitle":"标题", + "inputId":"标识ID", + "inputTips1":"不要重复,空时自动生成" + }, + "input":{ + "placeholder":"请选择或者填写" + }, + + "inputTag":{ + "placeholder":"请输入并回车", + "tips":"不能为空", + "tips2":"超过限制最大数:{count}", + "btnText":"添加标签" + }, + "keyboard":{ + "placeholder":"安全键盘放心输入", + "space":"空格", + "confirm":"确认" + }, + "pickerTime":{ + "hour":"小时", + "minute":"分钟", + "second":"秒数" + }, + "cascader":{ + "placeholder":"请选择", + "currentPlaceholder":"选择本级" + }, + "pickerDate":{ + "placeholder":"请选择时间", + "year":"年", + "month":"月", + "day":"日", + "hour":"时", + "minute":"分", + "second":"秒" + }, + + "uploadMedia":{ + "tips1":"上传中不允许拖动排序", + "videoPreview":"视频预览", + "close":"关闭", + "systemError":"系统异常", + "limitMaxCount":"已超最大上传数量", + "uploadStatus":"待上传 | 上传中... | 上传失败 | 上传成功 | 超过大小" + }, + "checkbox":{ + "tips":"超过最大选择" + }, + "weekbar":{ + "week": "周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日" + }, + "pagination":{ + "prev": "上一页", + "next": "下一页" + }, + "search":{ + "placeholder":"请输入关键词", + "cancel":"取消" + }, + "xmore":{ + "off": "展开更多", + "on": "收起更多" + }, + "empty":{ + "moreLabel": "没有更多数据啦", + "errorLabel": "出错啦~", + "btnLabel": "点击重试", + "title":"当前没有数据" + }, + "xloading":{ + "label":"加载中..." + }, + "actionModal":{ + "title":"提醒", + "btnText":"确认" + }, + "actionMenu":{ + "title":"请选择", + "btnText":"确认" + }, + "pullRefresh":{ + "status_1":"正在刷新", + "status_2":"继续下拉", + "status_3":"松开刷新", + "status_4":"刷新完成", + "status_5":"刷新失败" + }, + "virtualList":{ + "status_0":"继续下拉", + "status_1":"松开刷新", + "status_2":"刷新中", + "status_3":"取消刷新", + "status_4":"刷新超时,点击重试", + "status_5":"刷新完成" + }, + "imageResize":{ + "ok":"完成", + "cancel":"取消", + "reset":"还原" + }, + "colorView":{ + "rgb":"RGB", + "hub":"光谱", + "grid":"色卡", + "alpha":"透明度", + "hex":"HEX", + "r":"红色", + "g":"绿色", + "b":"蓝色" + }, + "modal": { + "title": "标题" + }, + "mention": { + "placeholder": "请输入内容,@选择朋友,按确认完成" + }, + "slideVerify": { + "tipsText": "请拖动到指定位置", + "tipsTextSuccess": "验证成功", + "tipsTextFail": "验证失败" + }, + "xRequest":{ + "error":"服务器错误:", + "success":"操作成功", + "hostFailEmpty":"未填请求域名", + "loading":"加载中" + } + } +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/instans/localLanuage/zh-Hant.json b/uni_modules/x-vuei18n-s/instans/localLanuage/zh-Hant.json new file mode 100644 index 0000000..9831a40 --- /dev/null +++ b/uni_modules/x-vuei18n-s/instans/localLanuage/zh-Hant.json @@ -0,0 +1,179 @@ +{ + "tmui4x": { + "cancel": "取消", + "confirm": "確認", + "success": "成功", + "fail": "失敗", + "warn": "警告", + "info": "提醒", + "clear":"清空", + "pickerTitle":"請選擇", + "calendar":{ + "year": "年", + "month": "月", + "day": "日", + "hour": "時", + "minute": "分", + "second": "秒", + "titleCurrentMonth":"{0}年{1}月", + "monthCountSelected":"{count}月", + "selectedStatus":"已選擇{count}日 | 未選擇日期 | 已選擇 | 未選擇結束日期", + "rangStatus":"開始 | 結束 | 本日", + "tips":"最大選擇{count}日", + "currentMonthTitle":"本月", + "week":"週一 | 週二 | 週三 | 週四 | 週五 | 週六 | 週日" + }, + "betweentTime": { + "start": "開始時間", + "end": "結束時間", + "quiakListTitle":"本日 | 本週 | 本月 | 本年 | 本季度", + "quiakListTitle2":"最近{count}天", + "quiakListTitle3":"前{count}年", + "title":"請選擇時間", + "splite":"至" + }, + "uploadFile":{ + "title":"選擇檔案", + "uploadStatus":"待上傳 | 上傳中... | 上傳失敗 | 上傳成功 | 超過大小", + "tips1":"上傳中禁止刪除", + "tips2":"已上傳檔案禁止刪除" + }, + "pickerSelected":{ + "placeholder":"請輸入關鍵詞", + "search":"搜尋", + "selected":"已選擇{count}項", + "claer":"清空選擇", + "selectedMode":"當前為單選模式", + "selectedALl":"選擇所有" + }, + "tree":{ + "changeTitle":"修改內容", + "addTitle":"添加下級", + "inputTitle":"標題", + "inputId":"標識ID", + "inputTips1":"不要重複,空時自動生成" + }, + "input":{ + "placeholder":"請選擇或者填寫" + }, + "inputTag":{ + "placeholder":"請輸入並回車", + "tips":"不能為空", + "tips2":"超過限制最大數:{count}", + "btnText":"添加標籤" + }, + "keyboard":{ + "placeholder":"安全鍵盤放心輸入", + "space":"空格", + "confirm":"確認" + }, + "pickerTime":{ + "hour":"小時", + "minute":"分鐘", + "second":"秒數" + }, + "cascader":{ + "placeholder":"請選擇", + "currentPlaceholder":"選擇本級" + }, + "pickerDate":{ + "placeholder":"請選擇時間", + "year":"年", + "month":"月", + "day":"日", + "hour":"時", + "minute":"分", + "second":"秒" + }, + "uploadMedia":{ + "tips1":"上傳中不允许拖動排序", + "videoPreview":"視頻預覽", + "close":"關閉", + "systemError":"系統異常", + "limitMaxCount":"已超最大上傳數量", + "uploadStatus":"待上傳 | 上傳中... | 上傳失敗 | 上傳成功 | 超過大小" + }, + "checkbox":{ + "tips":"超過最大選擇" + }, + "weekbar":{ + "week":"週一 | 週二 | 週三 | 週四 | 週五 | 週六 | 週日" + }, + "pagination":{ + "prev": "上一頁", + "next": "下一頁" + }, + "search":{ + "placeholder":"請輸入關鍵詞", + "cancel":"取消" + }, + "xmore":{ + "off": "展開更多", + "on": "收起更多" + }, + "empty":{ + "moreLabel": "沒有更多數據啦", + "errorLabel": "出錯啦~", + "btnLabel": "點擊重試", + "title":"當前沒有數據" + }, + "xloading":{ + "label":"加載中..." + }, + "actionModal":{ + "title":"提醒", + "btnText":"確認" + }, + "actionMenu":{ + "title":"請選擇", + "btnText":"確認" + }, + "pullRefresh":{ + "status_1":"正在刷新", + "status_2":"繼續下拉", + "status_3":"鬆開刷新", + "status_4":"刷新完成", + "status_5":"刷新失敗" + }, + "virtualList":{ + "status_0":"繼續下拉", + "status_1":"鬆開刷新", + "status_2":"刷新中", + "status_3":"取消刷新", + "status_4":"刷新超時,點擊重試", + "status_5":"刷新完成" + }, + "imageResize":{ + "ok":"完成", + "cancel":"取消", + "reset":"還原" + }, + "colorView":{ + "rgb":"RGB", + "hub":"光譜", + "grid":"色卡", + "alpha":"透明度", + "hex":"HEX", + "r": "紅色", + "g": "綠色", + "b": "藍色" + }, + "modal": { + "title": "標題" + }, + "mention": { + "placeholder": "請輸入內容,@選擇朋友,按確認完成" + }, + "slideVerify": { + "tipsText": "請拖動到指定位置", + "tipsTextSuccess": "驗證成功", + "tipsTextFail": "驗證失敗" + }, + "xRequest":{ + "error":"服務器錯誤:", + "success":"操作成功", + "hostFailEmpty":"未填請求域名", + "loading":"加載中" + } + } +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/interface.uts b/uni_modules/x-vuei18n-s/interface.uts new file mode 100644 index 0000000..045e314 --- /dev/null +++ b/uni_modules/x-vuei18n-s/interface.uts @@ -0,0 +1,417 @@ +// 统一类型定义 - 替换联合类型 +export type StringOrNull = string | null +export type NumberOrNull = number | null +export type StringOrNumber = string | number +export type StringOrNumberOrNull = string | number | null +export type DateOrNumberOrString = Date | number | string +export type UTSJSONObjectOrNull = UTSJSONObject | null +export type UTSJSONObjectOrArray = UTSJSONObject | Array +export type AnyOrNull = any | null +export type StringOrMessageFunction = string | MessageFunction +export type StringOrVoid = string | void +export type GetAnyType = (obj : AnyOrNull) => AnyOrNull +export type I18nOptionsOrNull = I18nOptions | null +export type NumberFormatOrNull = NumberFormat | null +export type DateTimeFormatOrNull = DateTimeFormat | null +export type GetAnyTypeOrNull = GetAnyType | null + +/** + * 警告处理器类型 - 用于处理国际化过程中的警告信息 + * @param msg 警告消息内容 + * @param err 可选的错误对象 + */ +export type WarnHandler = (msg : StringOrNumberOrNull, err ?: Error) => void + +/** + * 基础复数规则函数类型 - 定义基本的复数形式选择逻辑 + * @param choice 数量值 + * @param choicesLength 可选择的复数形式数量 + * @returns 选择的复数形式索引 + */ +export type BasePluralRule = (choice : number, choicesLength : number) => number + +/** + * 复数规则类型 - 扩展的复数规则,支持回退到原始规则 + * @param choice 数量值 + * @param choicesLength 可选择的复数形式数量 + * @param orgRule 可选的原始复数规则 + * @returns 选择的复数形式索引 + */ +export type PluralRule = (choice : number, choicesLength : number, orgRule ?: BasePluralRule) => number + +/** + * 消息上下文类型 - 包含消息处理所需的所有上下文信息 + */ +export type MessageContext = { + /** 列表参数 */ + list : Array + /** 命名参数对象 */ + named : UTSJSONObject + /** 复数索引 */ + pluralIndex : number + /** 复数规则函数 */ + pluralRule ?: PluralRule + /** 原始复数规则函数 */ + orgPluralRule ?: BasePluralRule + /** 字符串修饰器函数 */ + modifier : (str : string) => string + /** 消息内容或消息函数 */ + message : StringOrMessageFunction + /** 消息类型 */ + type : string + /** 插值函数 */ + interpolate : (val : any) => string + /** 值标准化函数 */ + normalize : (values : Array) => Array + /** 参数值数组 */ + values : Array +} + +/** + * 消息函数类型 - 接收上下文并返回格式化后的字符串 + * @param ctx 消息上下文 + * @returns 格式化后的消息字符串 + */ +export type MessageFunction = (ctx : MessageContext) => string + +/** + * 消息函数返回值类型 + */ +export type MessageFunctionReturn = StringOrNumber + +/** + * 数字格式化选项类型 - 基于 ECMA-402 Intl.NumberFormat 标准 + */ +export type NumberFormat = { + /** 数字样式:'decimal'(十进制)、'currency'(货币)、'percent'(百分比) */ + style ?: string + /** 货币代码,如 'USD'、'EUR'、'CNY' */ + currency ?: string + /** 本地化代码 */ + local ?: string + /** 货币显示方式:'symbol'(符号)、'code'(代码)、'name'(名称) */ + currencyDisplay ?: string + /** 是否使用千分位分组 */ + useGrouping ?: boolean + /** 最小整数位数 */ + minimumIntegerDigits ?: number + /** 最小小数位数 */ + minimumFractionDigits ?: number + /** 最大小数位数 */ + maximumFractionDigits ?: number + /** 最小有效数字位数 */ + minimumSignificantDigits ?: number + /** 最大有效数字位数 */ + maximumSignificantDigits ?: number +} +/** + * 数字格式化选项类型(必填版本)- 所有字段都是必需的 + */ +export type NumberFormatOpts = { + /** 数字样式 */ + style : string + /** 本地化代码 */ + local : string + /** 货币代码 */ + currency : string + /** 货币显示方式 */ + currencyDisplay : string + /** 是否使用千分位分组 */ + useGrouping : boolean + /** 最小整数位数 */ + minimumIntegerDigits : number + /** 最小小数位数 */ + minimumFractionDigits : number | null + /** 最大小数位数 */ + maximumFractionDigits : number | null + /** 最小有效数字位数 */ + minimumSignificantDigits : number | null + /** 最大有效数字位数 */ + maximumSignificantDigits : number | null +} + +/** + * 数字格式化配置映射 - 语言代码 -> 格式名称 -> 格式配置 + */ +export type NumberFormats = Map> + +/** + * 日期时间格式化选项类型 - 基于 ECMA-402 Intl.DateTimeFormat 标准 + */ +export type DateTimeFormat = { + /** 本地化匹配算法:'lookup' 或 'best fit' */ + localeMatcher ?: string + /** 本地化代码 */ + local ?: string + /** 日历系统,如 'gregory'、'chinese'、'islamic'、'buddhist'、'coptic'、'dangi'、'ethioaa'、'ethiopic'、'hebrew'、'indian'、'iso8601'、'japanese'、'persian'、'roc' */ + calendar ?: string + /** 数字系统,如 'arab'、'arabext'、'bali'、'beng'、'deva'、'fullwide'、'gujr'、'guru'、'hanidec'、'khmr'、'knda'、'laoo'、'latn'、'limb'、'mlym'、'mong'、'mymr'、'orya'、'tamldec'、'telu'、'thai'、'tibt' */ + numberingSystem ?: string + /** 时区标识符,如 'UTC'、'Asia/Shanghai'、'America/New_York' */ + timeZone ?: string + /** 是否使用12小时制 */ + hour12 ?: boolean + /** 小时周期:'h11'(0-11 with AM/PM)、'h12'(1-12 with AM/PM)、'h23'(0-23)、'h24'(1-24) */ + hourCycle ?: string + /** 格式匹配算法:'basic' 或 'best fit' */ + formatMatcher ?: string + /** 日期分隔符:用于连接年月日的字符,如 '-'、'/'、'.' 等。设置后将输出纯数字格式(如 2025-5-3),忽略语言默认的文字后缀 */ + dateSeparator ?: string + /** 星期显示:'long'(Monday)、'short'(Mon)、'narrow'(M) */ + weekday ?: string + /** 纪元显示:'long'(Anno Domini)、'short'(AD)、'narrow'(A) */ + era ?: string + /** 年份显示:'numeric'(2023)、'2-digit'(23) */ + year ?: string + /** 月份显示:'numeric'(1)、'2-digit'(01)、'long'(January)、'short'(Jan)、'narrow'(J) */ + month ?: string + /** 日期显示:'numeric'(1)、'2-digit'(01) */ + day ?: string + /** 时段显示:'long'(in the morning)、'short'(AM)、'narrow'(a) */ + dayPeriod ?: string + /** 小时显示:'numeric'(1)、'2-digit'(01) */ + hour ?: string + /** 分钟显示:'numeric'(1)、'2-digit'(01) */ + minute ?: string + /** 秒显示:'numeric'(1)、'2-digit'(01) */ + second ?: string + /** 小数秒位数:0-3,控制毫秒显示精度 */ + fractionalSecondDigits ?: number + /** 时区名称显示:'long'(Pacific Standard Time)、'short'(PST)、'shortOffset'(GMT-8)、'longOffset'(GMT-08:00)、'shortGeneric'(PT)、'longGeneric'(Pacific Time) */ + timeZoneName ?: string + /** 日期样式:'full'、'long'、'medium'、'short' - 与单独的日期组件选项互斥 */ + dateStyle ?: string + /** 时间样式:'full'、'long'、'medium'、'short' - 与单独的时间组件选项互斥 */ + timeStyle ?: string +} + +export type DateTimeFormatReal = { + /** 本地化匹配算法:'lookup' 或 'best fit' */ + localeMatcher : string + /** 本地化代码 */ + local : string + /** 日历系统,如 'gregory'、'chinese'、'islamic'、'buddhist'、'coptic'、'dangi'、'ethioaa'、'ethiopic'、'hebrew'、'indian'、'iso8601'、'japanese'、'persian'、'roc' */ + calendar : string + /** 数字系统,如 'arab'、'arabext'、'bali'、'beng'、'deva'、'fullwide'、'gujr'、'guru'、'hanidec'、'khmr'、'knda'、'laoo'、'latn'、'limb'、'mlym'、'mong'、'mymr'、'orya'、'tamldec'、'telu'、'thai'、'tibt' */ + numberingSystem : string + /** 时区标识符,如 'UTC'、'Asia/Shanghai'、'America/New_York' */ + timeZone : string + /** 是否使用12小时制 */ + hour12 : boolean + /** 小时周期:'h11'(0-11 with AM/PM)、'h12'(1-12 with AM/PM)、'h23'(0-23)、'h24'(1-24) */ + hourCycle : string + /** 格式匹配算法:'basic' 或 'best fit' */ + formatMatcher : string + /** 日期分隔符:用于连接年月日的字符,如 '-'、'/'、'.' 等。设置后将输出纯数字格式(如 2025-5-3),忽略语言默认的文字后缀 */ + dateSeparator : string + /** 星期显示:'long'(Monday)、'short'(Mon)、'narrow'(M) */ + weekday : string + /** 纪元显示:'long'(Anno Domini)、'short'(AD)、'narrow'(A) */ + era : string + /** 年份显示:'numeric'(2023)、'2-digit'(23) */ + year : string + /** 月份显示:'numeric'(1)、'2-digit'(01)、'long'(January)、'short'(Jan)、'narrow'(J) */ + month : string + /** 日期显示:'numeric'(1)、'2-digit'(01) */ + day : string + /** 时段显示:'long'(in the morning)、'short'(AM)、'narrow'(a) */ + dayPeriod : string + /** 小时显示:'numeric'(1)、'2-digit'(01) */ + hour : string + /** 分钟显示:'numeric'(1)、'2-digit'(01) */ + minute : string + /** 秒显示:'numeric'(1)、'2-digit'(01) */ + second : string + /** 小数秒位数:0-3,控制毫秒显示精度 */ + fractionalSecondDigits : number + /** 时区名称显示:'long'(Pacific Standard Time)、'short'(PST)、'shortOffset'(GMT-8)、'longOffset'(GMT-08:00)、'shortGeneric'(PT)、'longGeneric'(Pacific Time) */ + timeZoneName : string + /** 日期样式:'full'、'long'、'medium'、'short' - 与单独的日期组件选项互斥 */ + dateStyle : string + /** 时间样式:'full'、'long'、'medium'、'short' - 与单独的时间组件选项互斥 */ + timeStyle : string +} + +/** + * 日期时间格式化配置映射 - 语言代码 -> 格式名称 -> 格式配置 + */ +export type DateTimeFormats = Map> +/** + * I18n配置选项类型(可选版本)- 用于初始化国际化实例 + */ +export type I18nOptions = { + /** 当前语言代码,如 'en-US'、'zh-CN' */ + locale ?: string + /** 回退语言代码,当当前语言缺少翻译时使用 */ + fallbackLocale ?: string + /** 翻译消息对象,按语言代码组织 */ + messages ?: UTSJSONObject + /** 日期时间格式化配置 */ + datetimeFormats ?: DateTimeFormats + /** 数字格式化配置 */ + numberFormats ?: NumberFormats + /** 字符串修饰器映射 */ + modifiers ?: Map + /** 复数规则映射,按语言代码组织 */ + pluralRules ?: Map + /** 缺失翻译处理函数 */ + missing ?: ((locale : string, key : string, instance ?: any, type ?: string) => StringOrVoid) | null + /** 是否显示缺失翻译警告 */ + missingWarn ?: boolean + /** 是否显示回退语言警告 */ + fallbackWarn ?: boolean + /** 是否回退到根实例 */ + fallbackRoot ?: boolean + /** 是否启用回退格式化 */ + fallbackFormat ?: boolean + /** 是否允许未解析的翻译键 */ + unresolving ?: boolean + /** 翻译后处理函数 */ + postTranslation ?: ((str : string, key : string) => string) | null + /** 是否警告HTML消息 */ + warnHtmlMessage ?: boolean + /** 是否转义参数 */ + escapeParameter ?: boolean + /** 是否继承父级语言设置 */ + inheritLocale ?: boolean + /** 警告处理器 */ + warnHandler ?: WarnHandler + /** 默认复数规则 */ + pluralRule ?: PluralRule + /** 是否全局注入 */ + globalInjection ?: boolean + /** 是否允许组合式API */ + allowComposition ?: boolean + /** 是否使用遗留模式 */ + legacy ?: boolean +} +/** + * I18n配置选项类型(必填版本)- 内部使用的完整配置对象 + * 参考语言代码标准:https://xnxy.github.io/2024/06/11/%E5%9B%BD%E9%99%85%E5%8C%96%E4%B8%AD%E5%B8%B8%E7%94%A8BCP-47%20Code%E5%92%8C%E8%AF%AD%E8%A8%80%E5%AF%B9%E7%85%A7%E8%A1%A8/ + */ +export type I18nOptionsReally = { + /** 当前语言代码,如 'en-US'、'zh-CN' */ + locale : string + /** 回退语言代码,当当前语言缺少翻译时使用 */ + fallbackLocale : string + /** 翻译消息对象,按语言代码组织 */ + messages : UTSJSONObject + /** 日期时间格式化配置 */ + datetimeFormats : DateTimeFormats + /** 数字格式化配置 */ + numberFormats : NumberFormats + /** 字符串修饰器映射 */ + modifiers : Map + /** 复数规则映射,按语言代码组织 */ + pluralRules : Map + /** 缺失翻译处理函数 */ + missing : ((locale : string, key : string, instance ?: any, type ?: string) => StringOrVoid) | null + /** 是否显示缺失翻译警告 */ + missingWarn : boolean + /** 是否显示回退语言警告 */ + fallbackWarn : boolean + /** 是否回退到根实例 */ + fallbackRoot : boolean + /** 是否启用回退格式化 */ + fallbackFormat : boolean + /** 是否允许未解析的翻译键 */ + unresolving : boolean + /** 翻译后处理函数 */ + postTranslation : ((str : string, key : string) => string) | null + /** 是否警告HTML消息 */ + warnHtmlMessage : boolean + /** 是否转义参数 */ + escapeParameter : boolean + /** 是否继承父级语言设置 */ + inheritLocale : boolean + /** 警告处理器 */ + warnHandler : WarnHandler + /** 默认复数规则 */ + pluralRule : PluralRule + /** 是否全局注入 */ + globalInjection : boolean + /** 是否允许组合式API */ + allowComposition : boolean + /** 是否使用遗留模式 */ + legacy : boolean +} +/** + * uniapp-x下的tmui4x附带的多语言插件,现面向所有用户开放本语言插件。 + * @author tmui4x + * @copyright https://tmui.design + * @date 2025/7/8 + */ +export interface Tmui4xI18nTml { + /** 实例配置,可以动态修改本配置 **/ + ops : I18nOptionsReally + /** 设置语言 */ + setLocale(local : string) : void; + /** + * 获取语言 + * @returns {string} 当前设置的语言 + */ + getLocale() : string; + /** + * 获取回退语言 + * @returns {string} 当前回退的语言 + */ + getFallbackLocale() : string; + /** 设置回退语言 */ + setFallbackLocale(local : string) :void; + /** 全量填充配置 **/ + setOptions(args : I18nOptions|null):void; + /** + * 翻译方法 - 参考 Vue I18n 实现(UTS类型安全优化版本) + * @param key 翻译键 + * @param args 可选参数:数字(用于复数)、对象(用于插值)、字符串(locale)等同原vueI18n使用方式 + * @param opts 可选的第二个参数当args为复数数字,key中函数 | 时,此opts起效且必须为utsjsonobject格式等同原vueI18n使用方式 + * @returns 翻译后的字符串 + */ + t(key : string, ...argsopts : Array) : string; + /** + * 数字格式化方法 - 参考 Vue I18n 实现 + * @param val 要格式化的数字 + * @param name 格式化名称模板,如果不存在以opts为准,如果opts也没有则取默认值。 + * @param opts 格式化选项 + * @returns 格式化后的字符串 + */ + n(val : number, formatName ?: string, opts ?: NumberFormat) : string; + /** + * 日期时间格式化方法 - 参考 Vue I18n 实现 + * @param val 要格式化的日期时间值(Date对象、时间戳数字或日期字符串) + * @param formatName 格式化名称模板,如果不存在以opts为准,如果opts也没有则取默认值 + * @param opts 格式化选项 + * @returns 格式化后的字符串 + */ + d(val : DateOrNumberOrString, formatName ?: string, opts ?: DateTimeFormat) : string; + /** + * 动态添加语言的新字段 + * @param {string} local 语言 + * @param {UTSJSONObject} newMessage 键值及字段。 + */ + mergeLocaleMessage (local : string, newMessage : UTSJSONObject) : void; + /** + * 检测翻译键是否存在 - 参考 Vue I18n 的 te 方法实现 + * @param {string} key 翻译键,支持嵌套路径如 'user.name' + * @param {string} locale 可选的语言代码,不提供则使用当前语言 + * @returns {boolean} 存在返回true,不存在返回false + */ + te(key : string, locale ?: string) : boolean; + /** + * 相对时间 + * @param {string,number,Date} timeValue 时间差(毫秒) + * @param {string} unit 首选单位,它会自动进阶更高的维度,比如提供秒,超过60秒以分为单位进阶。 + * @param {string} locale 可选语言,不提供以默认创建的设置为准。 + * @returns {string} 格式化后的时间字符串 + */ + rt(timeValues ?: number | Date | string, units ?: string, locale ?: string) : string; + /** + * 获取可用语言列表 + * @returns {string[]} + */ + availableLocales() : string[] +} +/** + * 导出Tmui4xI18n国际化核心类 + */ +export { Tmui4xI18n } from './instans/i18n' \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/package.json b/uni_modules/x-vuei18n-s/package.json new file mode 100644 index 0000000..82b88e5 --- /dev/null +++ b/uni_modules/x-vuei18n-s/package.json @@ -0,0 +1,97 @@ +{ + "id": "x-vuei18n-s", + "displayName": "uts Uvue i18n 多语言插件", + "version": "1.0.0", + "description": "本插件为单文件版本的uts多语言插件具体见readme", + "keywords": [ + "tmui4x,uts,i18n,多语言" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.71" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "√", + "i18n": "√", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/readme.md b/uni_modules/x-vuei18n-s/readme.md new file mode 100644 index 0000000..0f4e0f7 --- /dev/null +++ b/uni_modules/x-vuei18n-s/readme.md @@ -0,0 +1,397 @@ +# x-vuei18n-s + +一个为 UniApp-X 设计的国际化(i18n)插件,提供完整的多语言支持功能。 +本库为tmui4x提供多语言支持,同时也是开源免费的,不需要tmui4x授权,您即可导入和下载使用 +使用时请按照文档安装和使用。 +使用方式几乎与源Vu8I18n一致基本没有变化,所以你看我下面的文档和看官方的文档都可以,但部分函数还是有差异的 +[源官方文档链接](https://vue-i18n.intlify.dev/guide/essentials/started.html) + +## 特性 + +- 🌍 多语言翻译支持 +- 🔢 复数形式处理 +- 📅 日期时间格式化 +- 💰 数字格式化 +- ⏰ 相对时间格式化 +- 🎯 插值和参数替换 +- 🔄 语言回退机制 +- 📱 跨平台兼容 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | 支持 | 支持 | + +## 安装 + +将插件复制到项目的 `uni_modules` 目录下即可。 +地区语言代码标准见[打开链接](https://xnxy.github.io/2024/06/11/%E5%9B%BD%E9%99%85%E5%8C%96%E4%B8%AD%E5%B8%B8%E7%94%A8BCP-47%20Code%E5%92%8C%E8%AF%AD%E8%A8%80%E5%AF%B9%E7%85%A7%E8%A1%A8/) + +## 在TMUI4x项目中使用 + +### 前置条件 +你已经使用并安装tmui4x组件库,那么会自带集成,但需要你复制本插件到您的项目中,目录 +```您的项目 > uni_modules > x-vuei18n-s``` +接着安装语言包 +```uts +import App from './App' +import {xui} from "@/uni_modules/tmx-ui/index.uts" +import {Tmui4xOptions} from "@/uni_modules/tmx-ui/interface.uts" + +import en from "@/uni_modules/tmx-ui/localLanuage/en.json" +import zhHans from "@/uni_modules/tmx-ui/localLanuage/zh-Hans.json" +import zhHant from "@/uni_modules/tmx-ui/localLanuage/zh-Hant.json" +import ko from "@/uni_modules/tmx-ui/localLanuage/ko.json" +import ja from "@/uni_modules/tmx-ui/localLanuage/ja.json" +// 下方是组件的语言包,以及你自己定义的语言包与组件合并即可。共用一个实例。 +const messages : UTSJSONObject = { + "en":{ + ...en, + "hellow":"Hi~" + }, + "zh-Hans":{ + ...zhHans, + "hellow":"哈喽" + }, + "zh-Hant":zhHant, + "ko":ko, + "ja":ja +} +import { createSSRApp } from 'vue' +export function createApp() { + const app = createSSRApp(App) + // 配置语言包 + app.use(xui,{i18nOptions:{locale:"zh-Hans",messages}} as Tmui4xOptions) + return { + app + } +} + +``` + +### 在Uvue内使用 + +#### 组合式模板内 +```uts +import {xStore} from "@/uni_modules/tmx-ui/index.uts" +const i18n = xStore.xConfig.i18n +console.log(i18n.t('xx.x')) +``` +uts内导入后可以在模板内使用 +```vue +{{i18n.t('xx.x')}} +``` + +#### 选项式模板内 +它已经集成了,不需要向组合式那样再导入. +```uts +export default { + methods:{ + test():string{ + return this!.i18n.t('xx.x') + } + } +} +``` +它已经集成了,不需要向组合式那样再导入. +```vue +{{i18n!.t('xx.x')}} +``` + +### 在任意Uts中使用 + +```uts +import {xStore} from "@/uni_modules/tmx-ui/index.uts" +const i18n = xStore.xConfig.i18n +console.log(i18n.t('xx.x')) +``` + + +## 作为插件集成到您应用中(非tmui4x项目) + +### 前置条件 +你需要在main.uts中安装插件 +```uts +import { tmxI18n} from "@/uni_modules/x-vuei18n-s/index.uts" +import { I18nOptions} from "@/uni_modules/x-vuei18n-s/interface.uts" + +const config = {locale:'zh'} as I18nOptions +app.use(tmxI18n,config) + +``` + +**在下面的2和3取得的i18n均为多语言实例,你可以调用前面的实例方法动态添加语言或者切语言等** + +### 1.在Vue模板内使用 + +```vue + {{i18n.t('cnacel')}} +``` +### 2.在组合式代码内使用 + +```ts + import {getCurrentInstance} from "vue" + const i18n = getCurrentInstance()?.proxy?.$i18n() + //可选 + console.log(i18n?.t('confirm')) + //断言 + console.log(i18n!.t('confirm')) +``` + +### 3.在选项式代码内使用 + +```ts + export default { + methods:{ + test():string{ + return this!.i18n.t('confirm') + } + } + } + +``` + +### 4.在任意文件中使用 +这里说的是你脱离了vue模板,比如在非setup和选项式中使用时,前面的方式就不行了,因为前面是依赖于vue实例。 +此种方式是只使用插件模式不需要在main.uts中app.use安装本插件,即可在任意位置导入使用。包括在vue模板内(不分组合式和选项都能用) +如果你想在模板内使用本方式 +**不要再使用i18n变量名了** +因为本身在模板内就有全局的i18n。 + +任意uts代码中 +```uts +import { $i18n } from "@/uni_modules/x-vuei18n-s/index.uts" +const la = $i18n() +// uts文件中就可以使用了。 +console.log(la.t('xx.x.x.')) +//模板内 + +``` +vue模板内 +```uts +import { $i18n } from "@/uni_modules/x-vuei18n-s/index.uts" +const la = $i18n() +``` +```vue +{{la.t('xx.x.x.')}} +``` + +## 快速开始 + +### 基本使用 + +```typescript +import { $i18n} from "@/uni_modules/x-vuei18n-s/index.uts" +const i18n = $i18n(); +``` + + +```typescript +// 设置中文消息 +const zhMessages: UTSJSONObject = { + 'hello': '你好', + 'welcome': '欢迎使用UniApp-X', + 'user': { + 'name': '用户名', + 'age': '年龄' + }, + 'items': { + 'apple': '苹果 | 苹果们 | {count}个苹果' + }, + 'greeting': '你好,{name}!' +} + +// 设置英文消息 +const enMessages: UTSJSONObject = { + 'hello': 'Hello', + 'welcome': 'Welcome to UniApp-X', + 'user': { + 'name': 'Username', + 'age': 'Age' + }, + 'items': { + 'apple': 'apple | apples | {count} of apple' + }, + 'greeting': 'Hello, {name}!' +} +i18n.mergeLocaleMessage('zh',zhMessages) +i18n.mergeLocaleMessage('en',enMessages) +// 设置当前语言 +i18n.setLocale('zh') +``` + +## API 文档 + +### 创建实例 + +如果是在uvue模板内,可以参照文档尾部的使用方法。 + +```typescript +import { $i18n} from "@/uni_modules/x-vuei18n-s/index.uts" +const i18n = $i18n(); +``` + +### 翻译方法 t() + +基本翻译: +```typescript +i18n.t('hello') // '你好' +i18n.t('user.name') // '用户名' +``` + +带参数的翻译: +```typescript +i18n.t('greeting', { name: '张三' }) // '你好,张三!' +``` + +复数形式: +```typescript +i18n.t('items.apple', 1) // '苹果' +i18n.t('items.apple', 2) // '苹果们' +i18n.t('items.apple', 5, { count: 5 }) // '5个苹果' +``` + +### 数字格式化 n() + +```typescript +// 基本数字格式化 +i18n.n(1234.56) // '1234.56' + +// 货币格式化 +i18n.n(1234.56, null, { + style: 'currency', + currency: 'CNY' +}) // '¥1,234.56' + +// 百分比格式化 +i18n.n(0.85, null, { + style: 'percent' +}) // '85%' +``` + +### 日期时间格式化 d() + +```typescript +const date = new Date() + +// 基本日期格式化 +i18n.d(date) // '2024/1/15' + +// 自定义格式 +i18n.d(date, null, { + year: 'numeric', + month: 'long', + day: 'numeric' +}) // '2024年1月15日' + +// 时间格式化 +i18n.d(date, null, { + hour: '2-digit', + minute: '2-digit', + second: '2-digit' +}) // '14:30:25' +``` + +### 相对时间格式化 rt() + +```typescript +// 相对于当前时间 +i18n.rt(new Date()) // '刚刚' + +// 指定时间字符串 +i18n.rt('2025-7-8 20:4:50', 'second') // '6个月后' + +// 时间戳 +i18n.rt(Date.now() + 3600000, 'minute') // '1小时后' + +// 自动单位进阶 +i18n.rt(Date.now() + 90000, 'second') // '1分钟后' (90秒自动转为分钟) +``` + +### 翻译键存在性检测 te() + +```typescript +// 检测翻译键是否存在 +i18n.te('hello') // true +i18n.te('user.name') // true +i18n.te('nonexistent.key') // false + +// 检测指定语言中的翻译键 +i18n.te('hello', 'zh') // true +i18n.te('hello', 'en') // true +i18n.te('hello', 'fr') // false (如果没有法语语言包) + +// 检测嵌套键 +i18n.te('user.settings.theme') // true +i18n.te('user.nonexistent') // false +``` + +### 语言管理 + +```typescript +// 获取当前语言 +const currentLocale = i18n.getLocale() // 'zh' + +// 设置语言 +i18n.setLocale('en') + +// 获取可用语言列表 +const locales = i18n.availableLocales() // ['zh', 'en'] + +// 动态添加语言内容 +i18n.mergeLocaleMessage('zh', { + 'newKey': '新内容' +}) +``` + +## 高级功能 + +### 复数规则自定义 + +```typescript +// pluralRule +const i18n.ops = (choice: number, choicesLength: number) => { + // 自定义复数规则 + if (choicesLength === 2) { + return choice === 1 ? 1 : 0 + } + return choice === 0 ? 0 : choice === 1 ? 1 : 2 + } +} +``` + +### 回退语言设置 + +```typescript +i18n.setLocale('zh') +i18n.setFallbackLocale('en') +``` + +### 预定义格式 + +```typescript +// 数字格式预定义 +i18n.ops.numberFormats.set('zh', new Map([ + ['currency', { + style: 'currency', + currency: 'CNY', + currencyDisplay: 'symbol' + }] +])) + +// 使用预定义格式 +i18n.n(1234.56, 'currency') // '¥1,234.56' +``` + + +## 注意事项 + +1. 消息对象必须使用 `UTSJSONObject` 类型 +2. 复数形式使用 `|` 分隔不同的形式 +3. 插值参数使用 `{key}` 格式 +4. 相对时间会自动选择最合适的单位 +5. 支持嵌套的消息键(如 `user.name`) + + +## 许可证 + +请不要随意更改源码,你仅有使用权。 diff --git a/uni_modules/x-vuei18n-s/utssdk/app-android/config.json b/uni_modules/x-vuei18n-s/utssdk/app-android/config.json new file mode 100644 index 0000000..beefb01 --- /dev/null +++ b/uni_modules/x-vuei18n-s/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "20" +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/utssdk/app-android/index.vue b/uni_modules/x-vuei18n-s/utssdk/app-android/index.vue new file mode 100644 index 0000000..a178b62 --- /dev/null +++ b/uni_modules/x-vuei18n-s/utssdk/app-android/index.vue @@ -0,0 +1,195 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/utssdk/app-ios/config.json b/uni_modules/x-vuei18n-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..721b81e --- /dev/null +++ b/uni_modules/x-vuei18n-s/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "9" +} \ No newline at end of file diff --git a/uni_modules/x-vuei18n-s/utssdk/app-ios/index.vue b/uni_modules/x-vuei18n-s/utssdk/app-ios/index.vue new file mode 100644 index 0000000..e0915ee --- /dev/null +++ b/uni_modules/x-vuei18n-s/utssdk/app-ios/index.vue @@ -0,0 +1,212 @@ + + + + \ No newline at end of file diff --git a/uni_modules/x-window-grey/changelog.md b/uni_modules/x-window-grey/changelog.md new file mode 100644 index 0000000..2340915 --- /dev/null +++ b/uni_modules/x-window-grey/changelog.md @@ -0,0 +1,2 @@ +## 1.0.0(2024-08-31) +首次发布 diff --git a/uni_modules/x-window-grey/package.json b/uni_modules/x-window-grey/package.json new file mode 100644 index 0000000..ed4c559 --- /dev/null +++ b/uni_modules/x-window-grey/package.json @@ -0,0 +1,82 @@ +{ + "id": "x-window-grey", + "displayName": "x-window-grey", + "version": "1.0.0", + "description": "x-window-grey", + "keywords": [ + "x-window-grey" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "", + "data": "", + "permissions": "" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u", + "alipay": "u" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "u" + }, + "App": { + "app-android": "u", + "app-ios": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-window-grey/readme.md b/uni_modules/x-window-grey/readme.md new file mode 100644 index 0000000..587d4e4 --- /dev/null +++ b/uni_modules/x-window-grey/readme.md @@ -0,0 +1,36 @@ +# x-window-grey +### 开发文档 +[TMUI4.0文档](https://xui.tmui.design/) +[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369) + +主要用于特殊时间时的整体app变灰,比如国家哀悼日,让页面变灰色. + +理论上uniapp也支持,uniappx也支持. + +### 说明 +这是tmui4.0|XUI的原生插件附赠插件 + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| x | 支持 | 支持 | 支持 | - | + + + +### 使用 + +如果是安卓请务必打自定义基座,如果ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。 + +**需要注意的是** +变灰只针对当前窗口所有内容,如果你想任何页面,自动变灰,你可能需要自行封装,然后在onShow中执行变灰操作. + +```ts + +import { setWindowGrey,removeWindowGrey } from "@/uni_modules/x-window-grey"; +// 让页面变灰 +setWindowGrey() +// 恢复页面 +removeWindowGrey() + +``` diff --git a/uni_modules/x-window-grey/utssdk/app-android/config.json b/uni_modules/x-window-grey/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/x-window-grey/utssdk/app-android/index.uts b/uni_modules/x-window-grey/utssdk/app-android/index.uts new file mode 100644 index 0000000..939c088 --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/app-android/index.uts @@ -0,0 +1,27 @@ +import Paint from 'android.graphics.Paint'; +import ColorMatrix from 'android.graphics.ColorMatrix'; +import ColorMatrixColorFilter from 'android.graphics.ColorMatrixColorFilter'; +import View from 'android.view.View'; +import ViewGroup from 'android.view.ViewGroup'; +export function setWindowGrey(ele:any|null=null) { + let paint = new Paint() + let colorMatrix = new ColorMatrix() + colorMatrix.setSaturation((0).toFloat()) + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + + paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)) + + decorView.setLayerType(View.LAYER_TYPE_HARDWARE,paint) +} +export function removeWindowGrey(ele:any|null=null) { + let paint = new Paint() + let colorMatrix = new ColorMatrix() + colorMatrix.setSaturation((1).toFloat()) + let decorView = UTSAndroid.getUniActivity()!.window.decorView as ViewGroup + paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)) + + decorView.setLayerType(View.LAYER_TYPE_HARDWARE,paint) +} + + + diff --git a/uni_modules/x-window-grey/utssdk/app-harmony/index.uts b/uni_modules/x-window-grey/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..a5a57bc --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/app-harmony/index.uts @@ -0,0 +1,14 @@ +import window from '@ohos.window'; + +// window.getLastWindow(UTSHarmony.getUIAbilityContext()).then((win:window.Window)=>{ +// win.setWindowColorSpace(window.ColorSpace.WIDE_GAMUT) +// }) + +export function setWindowGrey(ele:any|null=null) { + + + +} +export function removeWindowGrey(ele:any|null=null) { + +} \ No newline at end of file diff --git a/uni_modules/x-window-grey/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-window-grey/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-window-grey/utssdk/app-ios/config.json b/uni_modules/x-window-grey/utssdk/app-ios/config.json new file mode 100644 index 0000000..3312828 --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} diff --git a/uni_modules/x-window-grey/utssdk/app-ios/index.uts b/uni_modules/x-window-grey/utssdk/app-ios/index.uts new file mode 100644 index 0000000..e454774 --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/app-ios/index.uts @@ -0,0 +1,30 @@ +import { UIViewController, UIView, UIWindow, UIScreen, UIColor } from 'UIKit'; +import { CIFilter } from 'CoreImage'; + +let greayUview : UIView | null = null; +export function setWindowGrey(ele:any|null=null) { + if (UTSiOS.available("iOS 13.0, *")) { + let winsize = UIScreen.main.bounds as CGRect; + let view = new UIView(); + view.backgroundColor = UIColor.lightGray + + view.frame = winsize; + view.isUserInteractionEnabled = false; + view.layer.compositingFilter = "saturationBlendMode" + let paret = UTSiOS.getCurrentViewController() + greayUview = view; + DispatchQueue.main.async(execute = () : void => { + paret.view.addSubview(greayUview!) + + }) + } + + +} +export function removeWindowGrey(ele:any|null=null) { + DispatchQueue.main.async(execute = () : void => { + if (greayUview != null) { + greayUview!.removeFromSuperview(); + } + }) +} \ No newline at end of file diff --git a/uni_modules/x-window-grey/utssdk/interface.uts b/uni_modules/x-window-grey/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-window-grey/utssdk/mp-weixin/index.uts b/uni_modules/x-window-grey/utssdk/mp-weixin/index.uts new file mode 100644 index 0000000..85ecab6 --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/mp-weixin/index.uts @@ -0,0 +1,8 @@ +export function setWindowGrey(ele:UniElement) { + ele.style.setProperty('filter', 'grayscale(1)') +} +export function removeWindowGrey(ele:UniElement) { + // ele.style.removeProperty('filter') + ele.style.setProperty('filter', 'none') + +} \ No newline at end of file diff --git a/uni_modules/x-window-grey/utssdk/unierror.uts b/uni_modules/x-window-grey/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-window-grey/utssdk/web/index.uts b/uni_modules/x-window-grey/utssdk/web/index.uts new file mode 100644 index 0000000..001d3a0 --- /dev/null +++ b/uni_modules/x-window-grey/utssdk/web/index.uts @@ -0,0 +1,8 @@ +export function setWindowGrey(ele:any|null=null) { + let dom = document.body; + dom.style.setProperty('filter', 'grayscale(1)') +} +export function removeWindowGrey(ele:any|null=null) { + let dom = document.body; + dom.style.removeProperty('filter') +} \ No newline at end of file diff --git a/uni_modules/x-zip-s/changelog.md b/uni_modules/x-zip-s/changelog.md new file mode 100644 index 0000000..4768e08 --- /dev/null +++ b/uni_modules/x-zip-s/changelog.md @@ -0,0 +1,4 @@ +## 1.0.1(2025-08-17) +* 鸿蒙原生支持。 +## 1.0.0(2024-12-18) +* 对指定目录/文件进行压缩并返回压缩文件路径以便上传和管理. diff --git a/uni_modules/x-zip-s/package.json b/uni_modules/x-zip-s/package.json new file mode 100644 index 0000000..99ad62a --- /dev/null +++ b/uni_modules/x-zip-s/package.json @@ -0,0 +1,100 @@ +{ + "id": "x-zip-s", + "displayName": "应用内文件压缩和解压zip", + "version": "1.0.1", + "description": "可以对你的应用文件数据进行压缩目录和解压zip文件", + "keywords": [ + "zip,压缩,解压" +], + "repository": "", + "engines": { + "HBuilderX": "^3.6.8", + "uni-app": "", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "10.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "-", + "vue3": "-" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "-", + "nvue": "-", + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-", + "alipay": "-", + "toutiao": "-", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "21" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "x" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/x-zip-s/readme.md b/uni_modules/x-zip-s/readme.md new file mode 100644 index 0000000..5e4014a --- /dev/null +++ b/uni_modules/x-zip-s/readme.md @@ -0,0 +1,47 @@ +# x-zip-s +### 开发文档 + +压缩和解压插件,目前仅支持zip格式.主要可以对app的数据缓存文件进行压缩,然后上传到服务器使用的场景. + +### 兼容性 + +| Harmony | IOS | Android | WEB | 小程序 | +| --- | --- | --- | --- | --- | +| 支持 | 支持 | 支持 | x | x | + + +### 使用 + +如果是安卓请务必打自定义基座,如果ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。 + + +```ts + +import { addZip,unZip,addZipAndSaveDisk } from "@/uni_modules/x-zip-s" +/** + * 压缩文件 + * target,需要压缩的目录,如:uni.env.CACHE_PATH+'/dir/' + * filepath,添加的压缩的文件路径及名称如:uni.env.CACHE_PATH + 'test.zip' + */ +addZip(target,filepath,(pathfile:string)=>{ + //压缩成功后返回路径 + console.log(pathfile) +}) +/** + * 解压文件 + * path:待解压的文件路径 + * target:解压至目标目录 + */ +unZip(path,target) + +/** + * ios,鸿蒙 Next专用函数,压缩成功后会直接打开系统手机 + * 存储器,提示保存到icloud或者手机文件夹,你可以通过mac电脑同步保存. + */ +// #ifdef APP-IOS || APP-HARMONY +addZipAndSaveDisk(target,filepath,(pathfile:string)=>{ + console.log(pathfile) +}) +// #endif + +``` diff --git a/uni_modules/x-zip-s/utssdk/app-android/config.json b/uni_modules/x-zip-s/utssdk/app-android/config.json new file mode 100644 index 0000000..0e8a84d --- /dev/null +++ b/uni_modules/x-zip-s/utssdk/app-android/config.json @@ -0,0 +1,6 @@ +{ + "minSdkVersion": "21", + "dependencies":[ + "org.apache.commons:commons-compress:1.27.1" + ] +} \ No newline at end of file diff --git a/uni_modules/x-zip-s/utssdk/app-android/index.uts b/uni_modules/x-zip-s/utssdk/app-android/index.uts new file mode 100644 index 0000000..5972646 --- /dev/null +++ b/uni_modules/x-zip-s/utssdk/app-android/index.uts @@ -0,0 +1,102 @@ + +import ArchiveEntry from "org.apache.commons.compress.archivers.ArchiveEntry"; +import ArchiveStreamFactory from "org.apache.commons.compress.archivers.ArchiveStreamFactory"; +import ZipArchiveInputStream from "org.apache.commons.compress.archivers.zip.ZipArchiveInputStream"; +import ZipArchiveEntry from "org.apache.commons.compress.archivers.zip.ZipArchiveEntry"; +import ZipArchiveOutputStream from "org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream"; +import IOUtils from "org.apache.commons.compress.utils.IOUtils"; +import File from "java.io.File"; +import FileOutputStream from "java.io.FileOutputStream"; +import IOException from "java.io.IOException"; +import InputStream from "java.io.InputStream"; +import ArchiveStreamProvider from 'org.apache.commons.compress.archivers.ArchiveStreamProvider' +import URL from 'java.net.URL'; +import FileInputStream from 'java.io.FileInputStream'; +import BufferedInputStream from 'java.io.BufferedInputStream'; +import BufferedOutputStream from 'java.io.BufferedOutputStream'; +// import { FileManager } from "ZIPFoundation" +import ArchiveInputStream from 'org.apache.commons.compress.archivers.ArchiveInputStream'; +import Deflater from 'java.util.zip.Deflater'; + +function compressDirectoryToZipFile(rootDir : File,sourceDir : File,zipOut : ZipArchiveOutputStream) { + // 获取目录下的所有文件和子目录 + let listfiles = sourceDir.listFiles(); + if(listfiles==null) return; + listfiles.forEach(file => { + let relativePath = file.absolutePath.substring(rootDir.absolutePath.length + 1) + if (file.isDirectory) { + // 如果是目录,创建一个目录条目(以 "/" 结尾) + let dirEntry = new ZipArchiveEntry(relativePath + "/") + zipOut.putArchiveEntry(dirEntry) + zipOut.closeArchiveEntry() + // 递归压缩子目录 + compressDirectoryToZipFile(rootDir, file, zipOut) + } else { + // 如果是文件,创建文件条目并写入内容 + let fileEntry = new ZipArchiveEntry(relativePath) + zipOut.putArchiveEntry(fileEntry) + let bis = BufferedInputStream(FileInputStream(file)); + let buffer = ByteArray(1024) + var len : Int = bis.read(buffer) + while (len != -1) { + zipOut.write(buffer, 0, len) + len = bis.read(buffer) + } + zipOut.closeArchiveEntry() + } + }) + + +} + +export const addZip = (path : string, target : string,callback:(path:string)=>void) => { + let sourceDirectory = new File(UTSAndroid.convert2AbsFullPath(path)) + // 检查源目录是否存在 + if (!sourceDirectory.exists() || !sourceDirectory.isDirectory) { + throw IllegalArgumentException("Source directory does not exist or is not a directory") + } + let fos = new FileOutputStream(UTSAndroid.convert2AbsFullPath(target)) + let zipOut = ZipArchiveOutputStream(fos) + // 设置压缩方法 + zipOut.setMethod(ZipArchiveOutputStream.DEFLATED) + zipOut.setLevel(Deflater.BEST_SPEED) + // 压缩目录 + compressDirectoryToZipFile(sourceDirectory, sourceDirectory, zipOut) + callback(UTSAndroid.convert2AbsFullPath(target)) +} +export const addZipAndSaveDisk = (path : string, filename : string, callback : (path : string) => void) => { + +} + + +export const unZip = (path : string, target : string) => { + let failepath = UTSAndroid.convert2AbsFullPath(path) + let targetpath = UTSAndroid.convert2AbsFullPath(target) + let outputDir = new File(targetpath); + if (!outputDir.exists()) { + outputDir.mkdirs(); + } + + let fis = new FileInputStream(failepath); + let zipIn = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.ZIP, fis) as ZipArchiveInputStream + let entry = zipIn.getNextEntry(); + + while (entry != null) { + console.log(entry.getName()) + let outputFile = new File(outputDir, entry.getName()) + if (entry.isDirectory()) { + outputFile.mkdirs() + } else { + outputFile.parentFile?.mkdirs() + let bos = new BufferedOutputStream(FileOutputStream(outputFile)) + let buffer = new ByteArray(1024) + var len : Int = zipIn.read(buffer) + while (len != -1) { + bos.write(buffer, 0, len); + len = zipIn.read(buffer) + } + } + entry = zipIn.getNextEntry(); + } + +} \ No newline at end of file diff --git a/uni_modules/x-zip-s/utssdk/app-harmony/config.json b/uni_modules/x-zip-s/utssdk/app-harmony/config.json new file mode 100644 index 0000000..1dbf396 --- /dev/null +++ b/uni_modules/x-zip-s/utssdk/app-harmony/config.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "x_zip_s": "./lib/x_zip_s.har" + } +} \ No newline at end of file diff --git a/uni_modules/x-zip-s/utssdk/app-harmony/index.uts b/uni_modules/x-zip-s/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..a13833c --- /dev/null +++ b/uni_modules/x-zip-s/utssdk/app-harmony/index.uts @@ -0,0 +1,38 @@ +import { x_createTestFile, x_addZip, x_unZip,x_addZipAndSaveDisk } from "x_zip_s" + +/** + * 测试函数 + */ +export const testZipFile = ()=>{ + x_createTestFile(UTSHarmony.getCurrentWindow()!.getUIContext()) +} + +/** + * 压缩文件或者文件夹 + * @description 必须是沙盒路径 + * @param path 待压缩的文件夹 x/x + * @param target 压缩后存放的文件路径如x/x.zip + */ +export const addZip = (path : string, target : string,callback:(path:string)=>void) => { + x_addZip(path,target,callback) +} + +/** + * 压缩文件至系统手机目录 + * @description 必须是沙盒路径 + * @param path 文件路径如:x.zip + * @param filename 保存的文件名 + */ +export const addZipAndSaveDisk = (path : string, filename:string,callback:(path:string)=>void) => { + x_addZipAndSaveDisk(UTSHarmony.getCurrentWindow()!.getUIContext(),path,filename,callback) +} + +/** + * 解压缩文件 + * @description 必须是沙盒路径 + * @param path 文件路径如:x/x.zip + * @param target 解压至目录文件夹 x/x + */ +export const unZip = (path : string, target : string) => { + x_unZip(path,target) +} diff --git a/uni_modules/x-zip-s/utssdk/app-harmony/lib/x_zip_s.har b/uni_modules/x-zip-s/utssdk/app-harmony/lib/x_zip_s.har new file mode 100644 index 0000000..10a486a Binary files /dev/null and b/uni_modules/x-zip-s/utssdk/app-harmony/lib/x_zip_s.har differ diff --git a/uni_modules/x-zip-s/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/x-zip-s/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/x-zip-s/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/x-zip-s/utssdk/app-ios/config.json b/uni_modules/x-zip-s/utssdk/app-ios/config.json new file mode 100644 index 0000000..29240e4 --- /dev/null +++ b/uni_modules/x-zip-s/utssdk/app-ios/config.json @@ -0,0 +1,9 @@ +{ + "deploymentTarget": "12", + "dependencies-pods": [ + { + "name": "ZIPFoundation", + "version": "0.9.19" + } + ] +} diff --git a/uni_modules/x-zip-s/utssdk/app-ios/index.uts b/uni_modules/x-zip-s/utssdk/app-ios/index.uts new file mode 100644 index 0000000..cc52d8b --- /dev/null +++ b/uni_modules/x-zip-s/utssdk/app-ios/index.uts @@ -0,0 +1,113 @@ +import { Archive } from "ZIPFoundation" +import { URL, FileManager, URLResourceKey, CharacterSet } from 'Foundation'; +import { UIDocumentBrowserAction, UIDocumentPickerViewController, UIDocumentPickerMode, UIViewController } from 'UIKit'; + +/** + * 压缩文件或者文件夹 + * @description 必须是沙盒路径 + * @param path 待压缩的文件夹 x/x + * @param target 压缩后存放的文件路径如x/x.zip + */ +export const addZip = (path : string, target : string,callback:(path:string)=>void) => { + + let fileManager = FileManager.default + let archiveURL = new URL(fileURLWithPath = UTSiOS.convert2AbsFullPath(target)) + + console.log(archiveURL.path, '----') + let socurl = new URL(fileURLWithPath = UTSiOS.convert2AbsFullPath(path)) + + let archive = UTSiOS.try(new Archive(url = archiveURL, accessMode = Archive.AccessMode.create), "?") + if (archive == null) { + console.log("archiveURL:fail", archive) + callback('') + return; + } + + let enumerator : FileManager.DirectoryEnumerator = fileManager.enumerator(at = socurl, includingPropertiesForKeys = [URLResourceKey.isRegularFileKey, URLResourceKey.isDirectoryKey])! + let fileURL : URL | null = enumerator.nextObject() as URL | null + let i = 1 + while (fileURL != null) { + let str = fileURL!.path.replace(socurl.path, '') as String + str = str.replace('/private', '') as String + let relativePath = str.trimmingCharacters(in = new CharacterSet(charactersIn = "/")) + if (!fileManager.fileExists(atPath = fileURL!.path)) { + fileURL = enumerator.nextObject() as URL | null + continue; + } + let parentstr = fileURL!.path.substring(0, fileURL!.path.lastIndexOf("/")) + let parentUrl = new URL(fileURLWithPath = parentstr.replace('/private', '')) + UTSiOS.try(archive!.addEntry(with = relativePath, fileURL = fileURL!), '?') + fileURL = enumerator.nextObject() as URL | null + i += 1; + } + console.log("zip:ok", archiveURL.path) + callback(archiveURL.path) +} + +/** + * 压缩文件至系统手机目录 + * @description 必须是沙盒路径 + * @param path 文件路径如:x/x.zip + * @param filename 保存的文件名 + */ +export const addZipAndSaveDisk = (path : string, filename:string,callback:(path:string)=>void) => { + let fileManager = FileManager.default + let downloadsDirectory = FileManager.default.temporaryDirectory + let archiveURL = downloadsDirectory as URL + archiveURL.appendPathComponent(filename) + console.log(archiveURL.path, '----') + let socurl = new URL(fileURLWithPath = UTSiOS.convert2AbsFullPath(path)) + let archive = UTSiOS.try(new Archive(url = archiveURL, accessMode = Archive.AccessMode.create), "?") + if (archive == null) { + console.log("archiveURL:fail", archive) + callback('') + return; + } + + let enumerator : FileManager.DirectoryEnumerator = fileManager.enumerator(at = socurl, includingPropertiesForKeys = [URLResourceKey.isRegularFileKey, URLResourceKey.isDirectoryKey])! + let fileURL : URL | null = enumerator.nextObject() as URL | null + let i = 1 + while (fileURL != null) { + let str = fileURL!.path.replace(socurl.path, '') as String + str = str.replace('/private', '') as String + + let relativePath = str.trimmingCharacters(in = new CharacterSet(charactersIn = "/")) + if (!fileManager.fileExists(atPath = fileURL!.path)) { + fileURL = enumerator.nextObject() as URL | null + continue; + } + let parentstr = fileURL!.path.substring(0, fileURL!.path.lastIndexOf("/")) + let parentUrl = new URL(fileURLWithPath = parentstr.replace('/private', '')) + + // relativePath = relativePath.substring((relativePath.lastIndexOf("/")+1).toInt()) + UTSiOS.try(archive!.addEntry(with = relativePath, fileURL = fileURL!), '?') + console.log("序号:", i, str) + fileURL = enumerator.nextObject() as URL | null + + i += 1; + + } + console.log("zip:ok", archiveURL.path) + let documentPicker = new UIDocumentPickerViewController(url = archiveURL, in = UIDocumentPickerMode.exportToService) + let rootview = UTSiOS.getCurrentViewController() as UIViewController + rootview.present(documentPicker, animated = true, completion = nil) + callback(archiveURL.path) +} + +/** + * 解压缩文件 + * @description 必须是沙盒路径 + * @param path 文件路径如:x/x.zip + * @param target 解压至目录文件夹 x/x + */ +export const unZip = (path : string, target : string) => { + let fileManager = FileManager.default + let targetpath = new URL(fileURLWithPath = UTSiOS.convert2AbsFullPath(target)) + let zippathfile = new URL(fileURLWithPath = UTSiOS.convert2AbsFullPath(path)) + let result = UTSiOS.try(fileManager.unzipItem(at = zippathfile, to = targetpath), "?") + if (result == null) { + console.log("unzip:fail", result) + return; + } + console.log("unzip:ok") +} \ No newline at end of file diff --git a/uni_modules/x-zip-s/utssdk/interface.uts b/uni_modules/x-zip-s/utssdk/interface.uts new file mode 100644 index 0000000..e69de29 diff --git a/uni_modules/x-zip-s/utssdk/unierror.uts b/uni_modules/x-zip-s/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/utils/icon.uts b/utils/icon.uts new file mode 100644 index 0000000..114a934 --- /dev/null +++ b/utils/icon.uts @@ -0,0 +1,101 @@ +/** + * 图标:设计稿字符 → RemixIcon 名称 映射 + * ------------------------------------------------------------ + * 设计稿里用「▦ ✓ ⚑」等字符当图标,真机渲染效果差且不统一。 + * 这里统一转成 RemixIcon(https://remixicon.com/)名称,由 x-icon 渲染。 + * + * 用法:`` + * 若传入的本身就是 RemixIcon 名(含 '-'),原样返回,可直接透传。 + * + * ⚠⚠ 本文件导出的函数**不要直接写在 .uvue 的 template 里**! + * uvue 编译器会把模板里的「import 函数」编译成 `unref(toRemixIcon)(x)`, + * App 端 Kotlin 报:找不到名称"invoke" / Function invocation 'toRemixIcon(...)' expected。 + * 正确做法:在页面 script 里包一层本文件内定义的函数再给模板用: + * function entryIcon(g : string) : string { return toRemixIcon(g) } + * (hr-lrow / hr-tip / hr-empty 是在 computed 里调用的,没问题。) + */ +const ICON_MAP : Map = new Map([ + // 列表 / 文件 / 数据 + ['▦', 'layout-grid-line'], + ['▤', 'file-list-3-line'], + ['▣', 'monitor-line'], + ['▢', 'clipboard-line'], + ['▥', 'bar-chart-2-line'], + // 状态 + ['✓', 'check-line'], + ['✗', 'close-line'], + ['✕', 'close-line'], + ['×', 'close-line'], + ['!', 'error-warning-line'], + ['⚠', 'alarm-warning-line'], + ['ℹ', 'information-line'], + ['?', 'question-line'], + ['? ', 'question-line'], + // 操作 + ['⚑', 'flag-line'], + ['+', 'add-line'], + ['+', 'add-line'], + ['⇅', 'arrow-up-down-line'], + ['⇄', 'arrow-left-right-line'], + ['↦', 'route-line'], + ['✎', 'edit-line'], + ['⌕', 'search-line'], + ['⋯', 'more-fill'], + ['…', 'more-fill'], + ['⟨', 'more-fill'], + // 导航 + ['⌂', 'home-3-line'], + ['⌗', 'qr-scan-line'], + ['☺', 'user-3-line'], + ['✉', 'mail-line'], + ['☎', 'phone-line'], + ['⚙', 'settings-3-line'], + ['›', 'arrow-right-s-line'], + ['‹', 'arrow-left-s-line'], + ['⌄', 'arrow-down-s-line'], + ['⌃', 'arrow-up-s-line'], + // 业务 + ['♡', 'heart-pulse-line'], + ['★', 'star-line'], + ['☆', 'star-line'], + ['◔', 'time-line'], + ['◍', 'bubble-chart-line'], + ['⚡', 'flashlight-line'], + ['◈', 'apps-2-line'], + ['☣', 'biohazard-line'], + ['✦', 'sparkling-line'], + // 播放器 + ['▶', 'play-fill'], + ['▸', 'play-line'], + ['⏸', 'pause-line'], + ['⤢', 'fullscreen-line'], + ['⏮', 'skip-back-line'], + ['⏭', 'skip-forward-line'], + // 分隔 / 其它 + ['—', 'subtract-line'], + ['·', 'more-line'] +]) + +/** 字符图标 → RemixIcon 名;已是 RemixIcon 名则原样返回 */ +export function toRemixIcon(glyph : string) : string { + if (glyph == null || glyph == '') { return '' } + const mapped = ICON_MAP.get(glyph) + if (mapped != null) { return mapped } + // 含 '-' 视为已经是 remixicon 名称,直接透传 + if (glyph.indexOf('-') > -1) { return glyph } + return 'checkbox-blank-circle-line' +} + +/** 主题 → 图标底色 / 图标色(保持设计稿的四色语义) */ +export type HrThemeColor = { + bg : string + color : string +} + +export function themeColor(theme : string) : HrThemeColor { + if (theme == 'pri') { return { bg: '#EFF6FF', color: '#2563EB' } as HrThemeColor } + if (theme == 'red') { return { bg: '#FEF2F2', color: '#DC2626' } as HrThemeColor } + if (theme == 'amb') { return { bg: '#FEF3C7', color: '#D97706' } as HrThemeColor } + if (theme == 'grn') { return { bg: '#ECFDF5', color: '#059669' } as HrThemeColor } + return { bg: '#F3F4F6', color: '#6B7280' } as HrThemeColor +} diff --git a/utils/injury.uts b/utils/injury.uts new file mode 100644 index 0000000..2a527af --- /dev/null +++ b/utils/injury.uts @@ -0,0 +1,426 @@ +/** + * 伤情标记(2D 人体图鉴)数据模型 + JSON 编解码 + * ------------------------------------------------------------------ + * 设计要点: + * 1. 部位热区坐标全部是「相对人体图宽/高的百分比」,与屏宽无关, + * 所以 APP 与 H5、不同机型都能落在同一处(人体图本身固定 192×368rpx)。 + * 2. id 按「视野」命名(armVL = 图左边那条胳膊),name 按「伤员自身」命名。 + * 左侧卧位/仰卧位会影响左右判断,因此正面:图的左侧 = 伤员右侧。 + * 这一点对临床很重要(「左前臂骨折」标到右手是事故级错误)。 + * 3. HrInjury 的字段全是基础类型(string / number),可直接 JSON 序列化, + * 后端按同结构返回即可回显。 + */ + +/* ============================ 类型 ============================ */ + +/** 人体图鉴的一个可点部位(热区) */ +export type HrBodyPart = { + /** 部位 id(按人体图视野命名,同一 id 在正/背面几何位置相同) */ + id : string + /** 部位名(按伤员自身左右命名,正面与背面不同) */ + name : string + /** 所属视野:front 正面 / back 背面 */ + side : string + /** 热区左上角 x(占人体图宽 %) */ + x : number + /** 热区左上角 y(占人体图高 %) */ + y : number + /** 热区宽(%) */ + w : number + /** 热区高(%) */ + h : number + /** 默认标记锚点 x(%) */ + mx : number + /** 默认标记锚点 y(%) */ + my : number +} + +/** 一处伤情标记(字段均为基础类型,可直接 JSON 序列化) */ +export type HrInjury = { + /** 唯一 id */ + id : string + /** 图上显示的编号,从 1 开始,随增删自动重排 */ + no : number + /** front 正面 / back 背面 */ + side : string + /** 部位 id */ + partId : string + /** 部位名(伤员自身左右) */ + partName : string + /** 标记点 x(%) */ + x : number + /** 标记点 y(%) */ + y : number + /** 伤口长轴方向,0~179 度(0 横、90 竖) */ + rot : number + /** 性质:开放性外伤 / 裂伤 / 骨折 … */ + nature : string + /** 尺寸:如 4×2cm */ + size : string + /** 出血情况:活动性出血 / 渗血 / 已止血 / 无出血 */ + bleeding : string + /** 详情描述 */ + desc : string +} + +/* ============================ 部位热区 ============================ */ + +/** + * 构建一侧的人体部位热区。 + * 热区用「不重叠的竖条划分」覆盖人体轮廓,避免点到夹缝没反应、 + * 也避免两个热区重叠导致点到哪个不确定。 + * 正面(观察者视角):图的左侧对应伤员的右侧。 + */ +function buildParts(side : string) : HrBodyPart[] { + const flip = side == 'front' + const armViewLeft = flip ? '右上肢' : '左上肢' + const armViewRight = flip ? '左上肢' : '右上肢' + const legViewLeft = flip ? '右下肢' : '左下肢' + const legViewRight = flip ? '左下肢' : '右下肢' + + return [ + { id: 'head', name: '头部', side: side, x: 33, y: 0, w: 34, h: 15, mx: 50, my: 8 } as HrBodyPart, + { id: 'neck', name: '颈部', side: side, x: 38, y: 15, w: 24, h: 8, mx: 50, my: 19 } as HrBodyPart, + { id: 'chest', name: '胸部', side: side, x: 26, y: 23, w: 48, h: 15, mx: 50, my: 30 } as HrBodyPart, + { id: 'abdomen', name: '腹部', side: side, x: 26, y: 38, w: 48, h: 10, mx: 50, my: 43 } as HrBodyPart, + { id: 'pelvis', name: '骨盆', side: side, x: 26, y: 48, w: 48, h: 10, mx: 50, my: 53 } as HrBodyPart, + { id: 'armVL', name: armViewLeft, side: side, x: 5, y: 18, w: 19, h: 36, mx: 14, my: 33 } as HrBodyPart, + { id: 'armVR', name: armViewRight, side: side, x: 76, y: 18, w: 19, h: 36, mx: 86, my: 33 } as HrBodyPart, + { id: 'legVL', name: legViewLeft, side: side, x: 26, y: 58, w: 19, h: 42, mx: 35, my: 79 } as HrBodyPart, + { id: 'legVR', name: legViewRight, side: side, x: 55, y: 58, w: 19, h: 42, mx: 65, my: 79 } as HrBodyPart + ] +} + +/** 正面部位热区 */ +export const HR_FRONT_PARTS : HrBodyPart[] = buildParts('front') +/** 背面部位热区 */ +export const HR_BACK_PARTS : HrBodyPart[] = buildParts('back') + +/** 按视野取部位表 */ +export function partsOf(side : string) : HrBodyPart[] { + if (side == 'back') { return HR_BACK_PARTS } + return HR_FRONT_PARTS +} + +/** 按 id 取部位;取不到返回 null */ +export function findPart(side : string, partId : string) : HrBodyPart | null { + const list = partsOf(side) + for (let i = 0; i < list.length; i++) { + if (list[i].id == partId) { return list[i] } + } + return null +} + +/** 按部位名取部位(用户手动改部位时用);取不到返回 null */ +export function findPartByName(side : string, name : string) : HrBodyPart | null { + const list = partsOf(side) + for (let i = 0; i < list.length; i++) { + if (list[i].name == name) { return list[i] } + } + return null +} + +/** 取部位名,取不到时回退为「待确认」 */ +export function partNameOf(side : string, partId : string) : string { + const p = findPart(side, partId) + if (p == null) { return '待确认部位' } + return p!.name +} + +/* ============================ 选项 / 默认值 ============================ */ + +/** 伤口性质 */ +export const HR_NATURE_OPTIONS : string[] = [ + '开放性外伤', '裂伤', '擦伤', '挫伤', '刺伤', '切割伤', + '烧伤', '挤压伤', '闭合性骨折', '开放性骨折', '关节脱位', '贯通伤', '动物咬伤' +] + +/** 出血情况(同时决定标记颜色) */ +export const HR_BLEEDING_OPTIONS : string[] = ['活动性出血', '渗血', '已止血', '无出血'] + +/** 尺寸常用值(点选即填,也可手输) */ +export const HR_SIZE_PRESETS : string[] = ['1×1cm', '2×2cm', '4×2cm', '5×3cm', '8×4cm', '>10cm'] + +/** 伤口走向常用角度(长轴无方向,180 度 = 0 度,故只需 0~179) */ +export const HR_ROT_PRESETS : number[] = [0, 45, 90, 135] + +/** 新增标记时的默认出血情况 */ +export const HR_DEFAULT_BLEEDING : string = '渗血' +/** 新增标记时的默认尺寸 */ +export const HR_DEFAULT_SIZE : string = '4×2cm' + +/** 性质 → 该性质常见的描述补语(用于自动生成默认描述,方便快速填写) */ +function natureTail(nature : string) : string { + if (nature == '开放性外伤') { return '创缘不整,未见异物' } + if (nature == '裂伤') { return '创缘整齐,深及皮下' } + if (nature == '擦伤') { return '表皮剥脱,创面污染' } + if (nature == '挫伤') { return '局部肿胀压痛,无开放伤口' } + if (nature == '刺伤') { return '创口小、伤道深,需探查异物' } + if (nature == '切割伤') { return '创缘整齐,注意肌腱神经损伤' } + if (nature == '烧伤') { return '创面潮红,需记录面积与深度' } + if (nature == '挤压伤') { return '肢体肿胀张力高,警惕骨筋膜室综合征' } + if (nature == '闭合性骨折') { return '畸形、反常活动、骨擦感' } + if (nature == '开放性骨折') { return '骨折端外露,已覆盖并固定' } + if (nature == '关节脱位') { return '关节畸形、弹性固定、活动受限' } + if (nature == '贯通伤') { return '可见入口与出口,警惕深部脏器损伤' } + if (nature == '动物咬伤') { return '创面污染重,需清创并评估狂犬病暴露' } + return '待补充伤情描述' +} + +/** 由出血情况推荐一个性质(默认填充用) */ +export function defaultNature(bleeding : string) : string { + if (bleeding == '活动性出血' || bleeding == '渗血') { return '开放性外伤' } + return '挫伤' +} + +/** + * 自动生成默认描述。 + * 例:左上肢 开放性外伤(4×2cm),渗血,创缘不整,未见异物。 + */ +export function defaultInjuryDesc(partName : string, nature : string, size : string, bleeding : string) : string { + let s = partName + ' ' + nature + if (size != '') { s += '(' + size + ')' } + if (bleeding != '') { s += ',' + bleeding } + return s + ',' + natureTail(nature) + '。' +} + +/* ============================ 颜色 / 尺寸换算 ============================ */ + +/** 出血情况 → 标记编号底色(沿用全站四色语义:红=危重、橙=重伤、绿=轻伤、灰=无) */ +export function bleedingColor(bleeding : string) : string { + if (bleeding == '活动性出血') { return '#DC2626' } + if (bleeding == '渗血') { return '#F59E0B' } + if (bleeding == '已止血') { return '#10B981' } + return '#9CA3AF' +} + +/** 出血情况 → 伤口长轴条的填充色(比底色浅,避免压住编号) */ +export function bleedingBarColor(bleeding : string) : string { + if (bleeding == '活动性出血') { return '#FCA5A5' } + if (bleeding == '渗血') { return '#FCD34D' } + if (bleeding == '已止血') { return '#6EE7B7' } + return '#E5E7EB' +} + +/** 出血情况 → 全站主题名(hr-lrow 等组件用) */ +export function bleedingTheme(bleeding : string) : string { + if (bleeding == '活动性出血') { return 'red' } + if (bleeding == '渗血') { return 'amb' } + if (bleeding == '已止血') { return 'grn' } + return 'default' +} + +/** 取字符串开头连续的整数(「4×2cm」→ 4,「>10cm」→ 0) */ +function leadingInt(s : string) : number { + let v = 0 + let seen = false + for (let i = 0; i < s.length; i++) { + const c = s.charAt(i) + // ⚠ UTS 里 charCodeAt 返回的是可空 Number?,必须先判空再比较,否则编译报错 + const code = c.charCodeAt(0) + if (code == null) { break } + const n = code! + if (n >= 48 && n <= 57) { + v = v * 10 + (n - 48) + seen = true + } else { + break + } + } + return seen ? v : 0 +} + +/** + * 尺寸 → 人体图上伤口长轴条的显示长度(rpx)。 + * 约定 1cm ≈ 9rpx(人体图 192rpx 宽 ≈ 40cm 实际体宽,比例接近),夹在 44~132rpx。 + */ +export function sizeBarWidth(size : string) : number { + const n = leadingInt(size) + if (n <= 0) { return 56 } + let w = 40 + n * 9 + if (w < 44) { w = 44 } + if (w > 132) { w = 132 } + return Math.round(w) +} + +/* ============================ 增删改辅助 ============================ */ + +let hrInjurySeq : number = 0 + +/** 生成唯一 id(时间戳 + 自增序号,避免同一毫秒内重复) */ +export function newInjuryId() : string { + hrInjurySeq += 1 + return 'inj' + Date.now().toString() + '_' + hrInjurySeq.toString() +} + +/** 复制一处标记(保证 draft / 列表 / 原对象互不共享引用) */ +export function copyInjury(m : HrInjury) : HrInjury { + return { + id: m.id, no: m.no, side: m.side, partId: m.partId, partName: m.partName, + x: m.x, y: m.y, rot: m.rot, nature: m.nature, size: m.size, + bleeding: m.bleeding, desc: m.desc + } as HrInjury +} + +/** + * 重排编号(1 起)并返回**新数组**。 + * 必须返回新数组:uvue 里原地改数组元素不会触发刷新, + * 而编号要和人体图上的圆点严格一致,所以统一走「重建数组 + 重新赋值」。 + */ +export function renumberInjuries(list : HrInjury[]) : HrInjury[] { + const out : HrInjury[] = [] + for (let i = 0; i < list.length; i++) { + const m = copyInjury(list[i]) + m.no = i + 1 + out.push(m) + } + return out +} + +/** 过滤掉指定 id,返回新数组(excludeId 传空串表示不过滤) */ +export function excludeInjury(list : HrInjury[], excludeId : string) : HrInjury[] { + const out : HrInjury[] = [] + for (let i = 0; i < list.length; i++) { + if (excludeId == '' || list[i].id != excludeId) { out.push(list[i]) } + } + return out +} + +/** 按 id 取标记;取不到返回 null(点标记进编辑态时用) */ +export function findInjury(list : HrInjury[], id : string) : HrInjury | null { + for (let i = 0; i < list.length; i++) { + if (list[i].id == id) { return list[i] } + } + return null +} + +/** 按视野过滤标记(正面图 / 背面图各取各的) */ +export function injuriesOfSide(list : HrInjury[], side : string) : HrInjury[] { + const out : HrInjury[] = [] + for (let i = 0; i < list.length; i++) { + if (list[i].side == side) { out.push(list[i]) } + } + return out +} + +/** + * 计算新标记的落点。 + * 同一部位反复标记时按固定环序错开,避免编号圆点完全重叠看不出有几个。 + * @returns [x, y](百分比) + */ +export function nextMarkAnchor(side : string, partId : string, existing : HrInjury[], excludeId : string) : number[] { + const p = findPart(side, partId) + let bx = 50 + let by = 30 + if (p != null) { + bx = p!.mx + by = p!.my + } + + let n = 0 + for (let i = 0; i < existing.length; i++) { + const m = existing[i] + if (m.side == side && m.partId == partId && (excludeId == '' || m.id != excludeId)) { n += 1 } + } + + const ox : number[] = [0, 8, -8, 0, 0, 7, -7, 5, -5] + const oy : number[] = [0, 0, 0, 6, -6, 6, -6, -5, 5] + const k = n % 9 + + let x = bx + ox[k] + let y = by + oy[k] + if (x < 4) { x = 4 } + if (x > 96) { x = 96 } + if (y < 3) { y = 3 } + if (y > 97) { y = 97 } + return [x, y] +} + +/* ============================ JSON 编解码 ============================ */ + +/** 标记列表 → JSON 字符串(保存草稿 / 提交后端都用它) */ +export function injuriesToJson(list : HrInjury[]) : string { + const s = JSON.stringify(list) + if (s == null) { return '[]' } + return s +} + +function objStr(o : UTSJSONObject, key : string, def : string) : string { + const v = o.getString(key) + if (v == null) { return def } + return v +} + +function objNum(o : UTSJSONObject, key : string, def : number) : number { + const v = o.getNumber(key) + if (v == null) { return def } + return v +} + +function clamp(v : number, min : number, max : number) : number { + if (v < min) { return min } + if (v > max) { return max } + return v +} + +/** + * JSON 字符串 → 标记列表(回显)。 + * 逐字段带默认值兜底:后端字段缺失、手工粘贴的残缺 JSON 都不会让页面崩。 + */ +export function injuriesFromJson(json : string) : HrInjury[] { + const out : HrInjury[] = [] + if (json == null) { return out } + if (json.trim() == '') { return out } + + const arr = JSON.parseArray(json) + if (arr == null) { return out } + + for (let i = 0; i < arr.length; i++) { + const o = arr[i] + let side = objStr(o, 'side', 'front') + if (side != 'front' && side != 'back') { side = 'front' } + + let partId = objStr(o, 'partId', '') + let partName = objStr(o, 'partName', '') + // 允许只存部位名(老数据 / 手工 JSON):反查回 id + if (partId == '' && partName != '') { + const byName = findPartByName(side, partName) + if (byName != null) { partId = byName!.id } + } + if (partId == '') { partId = 'head' } + if (partName == '') { partName = partNameOf(side, partId) } + + const m = { + id: objStr(o, 'id', ''), + no: objNum(o, 'no', i + 1), + side: side, + partId: partId, + partName: partName, + x: clamp(objNum(o, 'x', 50), 2, 98), + y: clamp(objNum(o, 'y', 30), 2, 98), + rot: clamp(objNum(o, 'rot', 0), 0, 179), + nature: objStr(o, 'nature', '开放性外伤'), + size: objStr(o, 'size', ''), + bleeding: objStr(o, 'bleeding', HR_DEFAULT_BLEEDING), + desc: objStr(o, 'desc', '') + } as HrInjury + + if (m.id == '') { m.id = newInjuryId() } + if (m.desc == '') { m.desc = defaultInjuryDesc(m.partName, m.nature, m.size, m.bleeding) } + out.push(m) + } + return out +} + +/** 标记列表 → 按视野分组统计,用于概览文案 */ +export function injurySummary(list : HrInjury[]) : string { + if (list.length == 0) { return '暂无伤情标记' } + let active = 0 + for (let i = 0; i < list.length; i++) { + if (list[i].bleeding == '活动性出血') { active += 1 } + } + if (active > 0) { + return '共 ' + list.length.toString() + ' 处标记,其中 ' + active.toString() + ' 处活动性出血' + } + return '共 ' + list.length.toString() + ' 处标记' +} diff --git a/utils/nav.uts b/utils/nav.uts new file mode 100644 index 0000000..1359f62 --- /dev/null +++ b/utils/nav.uts @@ -0,0 +1,42 @@ +/** + * 页面导航封装 + * 所有跳转统一走这里,便于集中做「角色权限拦截 / 埋点 / 登录校验」。 + */ +import { canAccess } from './role.uts' + +/** 普通跳转(保留当前页) */ +export function navTo(url : string) : void { + if (!canAccess(url)) { + uni.showToast({ title: '当前角色无权访问该页面', icon: 'none' }) + return + } + uni.navigateTo({ url: url }) +} + +/** 替换当前页(不可返回) */ +export function redirectTo(url : string) : void { + uni.redirectTo({ url: url }) +} + +/** 关闭所有页面并打开 */ +export function relaunchTo(url : string) : void { + uni.reLaunch({ url: url }) +} + +/** 返回上一页 */ +export function navBack() : void { + uni.navigateBack() +} + +/** Tab 切换(uni-app x 无原生 tabBar,用 reLaunch 保证栈干净) */ +export function switchTab(url : string) : void { + uni.reLaunch({ url: url }) +} + +/** uni.showToast 支持的 icon 取值 */ +export type HrToastIcon = 'success' | 'error' | 'fail' | 'exception' | 'loading' | 'none' + +/** 轻提示(统一出口,避免页面直接散落 uni.showToast) */ +export function toast(title : string, icon : HrToastIcon = 'none') : void { + uni.showToast({ title: title, icon: icon, duration: 1600 }) +} diff --git a/utils/quiz.uts b/utils/quiz.uts new file mode 100644 index 0000000..48a88fc --- /dev/null +++ b/utils/quiz.uts @@ -0,0 +1,80 @@ +/** + * 答题状态(顺序练习 / 答题卡共用) + * 用 reassign 方式更新数组,保证 uvue 下响应式可靠触发。 + */ +import { reactive } from 'vue' +import { quizQuestions } from '@/mock/index.uts' + +export type HrQuizState = { + /** 每题已选选项下标,-1 表示未作答 */ + answers : number[] + /** 是否标记 */ + marked : boolean[] + /** 当前题号(从 0 开始) */ + current : number + /** 是否已交卷 */ + submitted : boolean +} + +function emptyAnswers() : number[] { + const arr : number[] = [] + for (let i = 0; i < quizQuestions.length; i++) { arr.push(-1) } + return arr +} + +function emptyMarks() : boolean[] { + const arr : boolean[] = [] + for (let i = 0; i < quizQuestions.length; i++) { arr.push(false) } + return arr +} + +export const quizState = reactive({ + answers: emptyAnswers(), + marked: emptyMarks(), + current: 0, + submitted: false +} as HrQuizState) + +/** 设置某题答案 */ +export function setAnswer(index : number, option : number) : void { + const arr : number[] = [] + for (let i = 0; i < quizState.answers.length; i++) { + arr.push(i == index ? option : quizState.answers[i]) + } + quizState.answers = arr +} + +/** 切换标记 */ +export function toggleMark(index : number) : void { + const arr : boolean[] = [] + for (let i = 0; i < quizState.marked.length; i++) { + arr.push(i == index ? !quizState.marked[i] : quizState.marked[i]) + } + quizState.marked = arr +} + +/** 已答数量 */ +export function answeredCount() : number { + let n = 0 + for (let i = 0; i < quizState.answers.length; i++) { + if (quizState.answers[i] >= 0) { n++ } + } + return n +} + +/** 标记数量 */ +export function markedCount() : number { + let n = 0 + for (let i = 0; i < quizState.marked.length; i++) { + if (quizState.marked[i]) { n++ } + } + return n +} + +/** 重置 */ +export function resetQuiz() : void { + quizState.answers = emptyAnswers() + quizState.marked = emptyMarks() + quizState.current = 0 + quizState.submitted = false +} diff --git a/utils/request.uts b/utils/request.uts new file mode 100644 index 0000000..89b796a --- /dev/null +++ b/utils/request.uts @@ -0,0 +1,17 @@ +/** + * 数据请求层(当前为 mock) + * ------------------------------------------------------------ + * 全局统一模拟 1s 的请求耗时;请求返回前列表页应展示 xSkeleton 骨架屏。 + * 后续对接真实接口时,只需把 mockRequest 的实现换成 uni.request 封装, + * 页面层(loading 开关 + 骨架屏)完全不用改。 + */ + +/** 统一模拟请求时长(ms) */ +export const MOCK_REQUEST_DELAY : number = 1000 + +/** 模拟一次数据请求:delay 后回调 onDone */ +export function mockRequest(onDone : () => void, delay : number = MOCK_REQUEST_DELAY) : void { + setTimeout(() => { + onDone() + }, delay) +} diff --git a/utils/role.uts b/utils/role.uts new file mode 100644 index 0000000..fa09ca9 --- /dev/null +++ b/utils/role.uts @@ -0,0 +1,162 @@ +/** + * 角色 / 会话 / TabBar 配置 + * ------------------------------------------------------------ + * 双角色设计核心: + * - 救援人员端(rescuer):首页(日常学习) / 事件(执行态) / 我的 —— 按「任务状态」分 Tab + * - 仓管人员端(keeper):扫码 / 仓库 / 设备 / 消息 / 我 —— 按「工作对象」分 Tab + * 不同角色的 TabBar 与可用操作页面由本文件统一裁决,页面内不要硬编码角色判断。 + */ +import { reactive } from 'vue' +import { xStore } from "@/uni_modules/tmx-ui/index.uts" +import { TABBAR_ITEM_INFO } from "@/uni_modules/tmx-ui/interface.uts" +import { rescuerUser, keeperUser } from "@/mock/index.uts" +import { HrRole, HrUser } from "@/mock/types.uts" +import { hrUnread, badgeText } from "@/utils/unread.uts" + +/** 当前登录会话 */ +export type HrSession = { + /** 角色 */ + role : HrRole + /** 姓名 */ + name : string + /** 头像文字 */ + avatar : string + /** 职称 */ + title : string + /** 科室 */ + dept : string + /** 工号 */ + jobNo : string + /** 角色中文名 */ + roleLabel : string + /** 能力标签 */ + tags : string[] + /** 累计学时 */ + hours : number + /** 完成课程 */ + courseCount : number + /** 有效证书 */ + certCount : number + /** 是否已登录 */ + logged : boolean +} + +const guest : HrSession = { + role: 'rescuer', name: '未登录', avatar: '医', title: '', dept: '', jobNo: '', + roleLabel: '', tags: [] as string[], hours: 0, courseCount: 0, certCount: 0, logged: false +} as HrSession + +/** 全局会话(页面统一从这里取用户信息) */ +export const hrSession = reactive(guest as HrSession) + +/** 按角色登录 */ +export function loginAs(role : HrRole) : void { + const u : HrUser = role == 'keeper' ? keeperUser : rescuerUser + hrSession.role = u.role + hrSession.name = u.name + hrSession.avatar = u.avatar + hrSession.title = u.title + hrSession.dept = u.dept + hrSession.jobNo = u.jobNo + hrSession.roleLabel = u.roleLabel + hrSession.tags = u.tags + hrSession.hours = u.hours + hrSession.courseCount = u.courseCount + hrSession.certCount = u.certCount + hrSession.logged = true +} + +/** 退出登录 */ +export function logout() : void { + hrSession.role = 'rescuer' + hrSession.name = '未登录' + hrSession.avatar = '医' + hrSession.logged = false +} + +/* ============================ TabBar ============================ */ + +/** + * 救援人员端 3 Tab:首页 / 事件 / 我的 + * 事件 Tab 的角标取自全局未读数(查看事件列表后清零 → 角标隐藏)。 + */ +export function rescuerTabs() : TABBAR_ITEM_INFO[] { + return [ + { title: '首页', icon: 'home-3-line', selectedIcon: 'home-3-fill', color: '#9CA3AF', selectedColor: '#2563EB' } as TABBAR_ITEM_INFO, + { title: '事件', icon: 'alarm-warning-line', selectedIcon: 'alarm-warning-fill', color: '#9CA3AF', selectedColor: '#2563EB', dotLabel: badgeText(hrUnread.events) } as TABBAR_ITEM_INFO, + { title: '我的', icon: 'user-3-line', selectedIcon: 'user-3-fill', color: '#9CA3AF', selectedColor: '#2563EB' } as TABBAR_ITEM_INFO + ] +} + +/** 仓管人员端 5 Tab:扫码 / 仓库 / 设备 / 消息 / 我 */ +export function keeperTabs() : TABBAR_ITEM_INFO[] { + return [ + { title: '扫码', icon: 'qr-scan-line', selectedIcon: 'qr-scan-fill', color: '#9CA3AF', selectedColor: '#2563EB' } as TABBAR_ITEM_INFO, + { title: '仓库', icon: 'archive-line', selectedIcon: 'archive-fill', color: '#9CA3AF', selectedColor: '#2563EB' } as TABBAR_ITEM_INFO, + { title: '设备', icon: 'settings-3-line', selectedIcon: 'settings-3-fill', color: '#9CA3AF', selectedColor: '#2563EB' } as TABBAR_ITEM_INFO, + { title: '消息', icon: 'mail-line', selectedIcon: 'mail-fill', color: '#9CA3AF', selectedColor: '#2563EB', dotLabel: badgeText(hrUnread.messages) } as TABBAR_ITEM_INFO, + { title: '我', icon: 'user-3-line', selectedIcon: 'user-3-fill', color: '#9CA3AF', selectedColor: '#2563EB' } as TABBAR_ITEM_INFO + ] +} + +/** + * 取当前角色的 TabBar 项 + * 每次调用重新构造数组 → 未读数变化时调用方的 computed 会重新求值(角标随之隐藏)。 + */ +export function currentTabs() : TABBAR_ITEM_INFO[] { + return hrSession.role == 'keeper' ? keeperTabs() : rescuerTabs() +} + +/** 当前角色 Tab 对应的页面路径(顺序与 currentTabs 一致) */ +export function currentTabPages() : string[] { + if (hrSession.role == 'keeper') { + return [ + '/pages/warehouse/scan', + '/pages/warehouse/stock', + '/pages/warehouse/devices', + '/pages/message/index', + '/pages/mine/index' + ] + } + return [ + '/pages/home/index', + '/pages/event/index', + '/pages/mine/index' + ] +} + +/** 同步 TabBar 配置进 tmx-ui 全局状态(x-tabbar 会读取) */ +export function syncTabbar(activeIndex : number) : void { + xStore.xTabbarConfig.list = currentTabs() + xStore.xTabbarConfig.tabbarActiveIndex = activeIndex +} + +function rescueHas(arr : string[], p : string) : boolean { + let hit = false + for (let i = 0; i < arr.length; i++) { + if (arr[i] == p) { hit = true; break } + } + return hit +} + +function keeperHas(arr : string[], p : string) : boolean { + let hit = false + for (let i = 0; i < arr.length; i++) { + if (arr[i] == p) { hit = true; break } + } + return hit +} + +/** + * 某个角色是否可访问某页面 + * 用于「可用操作页面的区分」:仓管端不出现检伤/事件工作台,救援端不出现出入库。 + */ +export function canAccess(path : string) : boolean { + const keeperOnly : string[] = ['/pages/warehouse/scan', '/pages/warehouse/stock', '/pages/warehouse/goods-detail', '/pages/warehouse/devices', '/pages/warehouse/device-detail', '/pages/message/index'] + const rescuerOnly : string[] = ['/pages/home/index', '/pages/event/index', '/pages/event/detail', '/pages/triage/victims', '/pages/triage/create', '/pages/triage/detail', '/pages/triage/batch-treat', '/pages/triage/batch-transfer', '/pages/triage/transfer', '/pages/triage/treat-records', '/pages/triage/offline-sync', '/pages/course/library', '/pages/course/subject', '/pages/course/media', '/pages/course/practice', '/pages/course/quiz', '/pages/course/answer-card', '/pages/study/exams', '/pages/study/certificates', '/pages/study/wrong-book', '/pages/study/center', '/pages/message/list', '/pages/message/contacts'] + const p = path.split('?')[0] + if (hrSession.role == 'keeper') { + return rescueHas(rescuerOnly, p) ? false : true + } + return keeperHas(keeperOnly, p) ? false : true +} diff --git a/utils/unread.uts b/utils/unread.uts new file mode 100644 index 0000000..abc4966 --- /dev/null +++ b/utils/unread.uts @@ -0,0 +1,43 @@ +/** + * 未读角标状态(全站唯一来源) + * ------------------------------------------------------------ + * 角标 = 未读数。对应内容被查看后置 0 → 角标自动隐藏。 + * + * 使用: + * - TabBar:`utils/role.uts` 里用 `badgeText(hrUnread.events)` 生成 dotLabel + * - 列表行:`` + * - 页面「查看后」:onPageShow 里调 markEventsRead() / markMessagesRead() + */ +import { reactive } from 'vue' + +export type HrUnread = { + /** 事件 TabBar 角标(救援人员端 · 事件 Tab) */ + events : number + /** 消息 TabBar 角标(仓管人员端 · 消息 Tab) */ + messages : number + /** 「我的」页消息中心入口 / 消息中心分组角标 */ + msgCenter : number +} + +/** 全局未读数 */ +export const hrUnread = reactive({ + events: 4, + messages: 4, + msgCenter: 4 +} as HrUnread) + +/** 角标文案:0 时返回空串 —— x-badge 收到空 label 会自行隐藏,无需额外判断 */ +export function badgeText(n : number) : string { + return n > 0 ? n.toString() : '' +} + +/** 查看事件列表后调用(救援端事件 Tab 页 onPageShow) */ +export function markEventsRead() : void { + hrUnread.events = 0 +} + +/** 查看消息中心后调用(消息页 onPageShow) */ +export function markMessagesRead() : void { + hrUnread.messages = 0 + hrUnread.msgCenter = 0 +}