@shgroup/dsh-serenity-hooks 1.24.4 → 1.24.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -8,7 +8,7 @@ window.__ModuleLoader__.load({
8
8
  let react = require("react");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/SafeModePanel
11
- const css$3 = "/* SafeModePanel — 会话头部 Serenity 状态卡片(v1.22 UX 重构)\n * 卡片 → 点击 → 官方 Modal(body portal 遮罩 + 居中)\n * 模态内:tab 栏 + 分组(groupTitle 标题 + rowCard 行卡)——看齐官方 settings 设计语言\n * 遵循 web-styling.md:颜色只用 --dsw-alias-* 语义 token(明暗自适应);\n * 前缀 sp- 防冲突。 */\n\n/* ── 头部状态卡片(可点击) ── */\n\n.sp-card {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 30px;\n padding: 0 8px 0 14px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n color: inherit;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease),\n border-color var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-card:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n border-color: var(--dsw-alias-border-l2);\n}\n\n.sp-card:focus-visible {\n outline: 2px solid var(--dsw-alias-button-ghost-active-border);\n outline-offset: 1px;\n}\n\n.sp-card:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n/* 方案 O 盾牌版(v1.24.2):绿点 = Serenity 生效(恒绿);盾牌 = SAFE 状态\n * (琥珀空心盾 = SAFE OFF 未保护提醒 / 绿实心盾 = SAFE ON 保护中安心) */\n\n.sp-dot {\n flex: none;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--dsw-alias-state-success-primary);\n}\n\n.sp-dotOff {\n background: var(--dsw-alias-label-dimmed);\n}\n\n.sp-cardInactive {\n opacity: 0.85;\n}\n\n.sp-cardInactive .sp-brand {\n color: var(--dsw-alias-label-secondary);\n font-weight: 500;\n}\n\n.sp-brand {\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n.sp-ver {\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n font-family: var(--ds-font-family-code, monospace);\n}\n\n.sp-sep {\n flex: none;\n width: 1px;\n height: 14px;\n background: var(--dsw-alias-border-l1);\n}\n\n.sp-shield {\n display: inline-flex;\n width: 16px;\n height: 16px;\n flex: none;\n}\n\n.sp-shield svg {\n width: 16px;\n height: 16px;\n}\n\n.sp-statusWord {\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n white-space: nowrap;\n}\n\n/* SAFE OFF(未保护):琥珀——提醒,非错误(用户自己的开关选择) */\n.sp-cardUnprotected .sp-shield {\n color: var(--dsw-alias-state-warning-primary);\n}\n\n.sp-cardUnprotected .sp-statusWord {\n color: var(--dsw-alias-state-warning-primary);\n}\n\n/* SAFE ON(保护中):绿——安心 */\n.sp-cardProtected .sp-shield {\n color: var(--dsw-alias-state-success-primary);\n}\n\n.sp-cardProtected .sp-shield path:first-child {\n fill: color-mix(in srgb, var(--dsw-alias-state-success-primary) 18%, transparent);\n}\n\n.sp-cardProtected .sp-statusWord {\n color: var(--dsw-alias-state-success-primary);\n}\n\n/* 滑块快速开关(v1.24.4 方案 O 滑块变体):SAFE 文字保留 + 滑块——\n * 滑块左 = OFF(琥珀 ✗,写工具全开)/ 右 = ON(绿 ✓,写工具隐藏),开关隐喻表达开关状态 */\n.sp-switch {\n display: inline-flex;\n align-items: center;\n width: 30px;\n height: 17px;\n border-radius: 999px;\n position: relative;\n flex: none;\n cursor: pointer;\n transition: background 0.2s;\n}\n\n.sp-switchOff {\n background: color-mix(in srgb, var(--dsw-alias-state-warning-primary) 28%, var(--dsw-alias-border-l2));\n}\n\n.sp-switchOn {\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, var(--dsw-alias-border-l2));\n}\n\n.sp-switchThumb {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n border-radius: 50%;\n background: var(--dsw-alias-bg-module);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n position: absolute;\n top: 2px;\n transition: left 0.2s;\n}\n\n.sp-switchOff .sp-switchThumb {\n left: 2px;\n}\n\n.sp-switchOn .sp-switchThumb {\n left: 15px;\n}\n\n.sp-switchThumb svg {\n width: 8px;\n height: 8px;\n}\n\n.sp-switchOff .sp-switchThumb svg {\n color: var(--dsw-alias-state-warning-primary);\n}\n\n.sp-switchOn .sp-switchThumb svg {\n color: var(--dsw-alias-state-success-primary);\n}\n\n.sp-switchBusy {\n opacity: 0.6;\n cursor: default;\n}\n\n.sp-chev {\n color: var(--dsw-alias-label-dimmed);\n flex: none;\n}\n\n/* ── 官方 Modal 定制(宽度 + 内容紧凑) ── */\n\n.sp-modal {\n width: 520px;\n max-width: calc(100vw - 48px);\n}\n\n/* ── tab 栏 ── */\n\n.sp-tabs {\n display: flex;\n gap: 6px;\n padding: 0 2px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.sp-tab {\n flex: 1;\n padding: 8px 0;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-tab:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-tabOn {\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.2));\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n/* ── 模态内容 ── */\n\n.sp-modalBody {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding-top: 14px;\n /* 内容超出视口时 body 区滚动(兜底——不再截断);整卡不滚动 */\n overflow-y: auto;\n max-height: calc(100vh - 200px);\n}\n\n/* ── 分组(官方 settings 语言:groupTitle + rows) ── */\n\n.sp-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sp-groupHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.sp-groupTitle {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n/* 行卡(rowCard:border + radius + padding;值与 label 分离、长内容可换行) */\n.sp-row {\n display: flex;\n align-items: baseline;\n gap: 12px;\n min-width: 0;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-label {\n flex: none;\n width: 76px;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.sp-value {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n overflow-wrap: anywhere;\n}\n\n/* 安全模式动作区 */\n.sp-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 24px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-toggleLg {\n height: 30px;\n padding: 0 16px;\n font-size: 13px;\n}\n\n.sp-toggleOn {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 14%, transparent);\n color: var(--dsw-alias-state-error-primary);\n border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);\n}\n\n.sp-toggleOff {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-toggleIcon {\n flex: none;\n}\n\n.sp-toggleDesc {\n flex: 1;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* handyman 运行状态区块 */\n\n.sp-handymenToggle {\n flex: none;\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n cursor: pointer;\n}\n\n.sp-handymenToggle:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-handymenList {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 2px;\n}\n\n.sp-handymanItem {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n min-width: 0;\n}\n\n.sp-handymanHead {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.sp-handymanLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.sp-handymanRound {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-handymanTime {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-handymanResp {\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sp-handymenMore {\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n padding: 4px 12px;\n}\n\n/* 底部提示(配置入口引导) */\n.sp-hint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n padding: 8px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 10px;\n}\n";
11
+ const css$3 = "/* SafeModePanel — 会话头部 Serenity 状态卡片(v1.22 UX 重构)\n * 卡片 → 点击 → 官方 Modal(body portal 遮罩 + 居中)\n * 模态内:tab 栏 + 分组(groupTitle 标题 + rowCard 行卡)——看齐官方 settings 设计语言\n * 遵循 web-styling.md:颜色只用 --dsw-alias-* 语义 token(明暗自适应);\n * 前缀 sp- 防冲突。 */\n\n/* ── 头部状态卡片(可点击) ── */\n\n.sp-card {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 30px;\n padding: 0 8px 0 14px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n color: inherit;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease),\n border-color var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-card:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n border-color: var(--dsw-alias-border-l2);\n}\n\n.sp-card:focus-visible {\n outline: 2px solid var(--dsw-alias-button-ghost-active-border);\n outline-offset: 1px;\n}\n\n.sp-card:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n/* 方案 O 盾牌版(v1.24.2):绿点 = Serenity 生效(恒绿);盾牌 = SAFE 状态\n * (琥珀空心盾 = SAFE OFF 未保护提醒 / 绿实心盾 = SAFE ON 保护中安心) */\n\n.sp-dot {\n flex: none;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--dsw-alias-state-success-primary);\n}\n\n.sp-dotOff {\n background: var(--dsw-alias-label-dimmed);\n}\n\n.sp-cardInactive {\n opacity: 0.85;\n}\n\n.sp-cardInactive .sp-brand {\n color: var(--dsw-alias-label-secondary);\n font-weight: 500;\n}\n\n.sp-brand {\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n.sp-ver {\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n font-family: var(--ds-font-family-code, monospace);\n}\n\n.sp-sep {\n flex: none;\n width: 1px;\n height: 14px;\n background: var(--dsw-alias-border-l1);\n}\n\n.sp-shield {\n display: inline-flex;\n width: 16px;\n height: 16px;\n flex: none;\n}\n\n.sp-shield svg {\n width: 16px;\n height: 16px;\n}\n\n.sp-statusWord {\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n white-space: nowrap;\n}\n\n/* SAFE OFF(未保护):琥珀——提醒,非错误(用户自己的开关选择) */\n.sp-cardUnprotected .sp-shield {\n color: var(--dsw-alias-state-warning-primary);\n}\n\n.sp-cardUnprotected .sp-statusWord {\n color: var(--dsw-alias-state-warning-primary);\n}\n\n/* SAFE ON(保护中):绿——安心(设计稿 SVG fill=none:纯描边盾,与琥珀空心盾同构,颜色表达状态) */\n.sp-cardProtected .sp-shield {\n color: var(--dsw-alias-state-success-primary);\n}\n\n.sp-cardProtected .sp-statusWord {\n color: var(--dsw-alias-state-success-primary);\n}\n\n/* 滑块快速开关(v1.24.4 方案 O 滑块变体):SAFE 文字保留 + 滑块——\n * 滑块左 = OFF(琥珀 ✗,写工具全开)/ 右 = ON(绿 ✓,写工具隐藏),开关隐喻表达开关状态 */\n.sp-switch {\n display: inline-flex;\n align-items: center;\n width: 30px;\n height: 17px;\n border-radius: 999px;\n position: relative;\n flex: none;\n cursor: pointer;\n transition: background 0.2s;\n}\n\n.sp-switchOff {\n background: color-mix(in srgb, var(--dsw-alias-state-warning-primary) 28%, var(--dsw-alias-border-l2));\n}\n\n.sp-switchOn {\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, var(--dsw-alias-border-l2));\n}\n\n.sp-switchThumb {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n border-radius: 50%;\n background: #fff; /* 设计稿字面:滑块 thumb 恒白(暗色下也白,与彩色轨道对比——标准开关视觉) */\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n position: absolute;\n top: 2px;\n transition: left 0.2s;\n}\n\n.sp-switchOff .sp-switchThumb {\n left: 2px;\n}\n\n.sp-switchOn .sp-switchThumb {\n left: 15px;\n}\n\n.sp-switchThumb svg {\n width: 8px;\n height: 8px;\n}\n\n.sp-switchOff .sp-switchThumb svg {\n color: var(--dsw-alias-state-warning-primary);\n}\n\n.sp-switchOn .sp-switchThumb svg {\n color: var(--dsw-alias-state-success-primary);\n}\n\n.sp-switchBusy {\n opacity: 0.6;\n cursor: default;\n}\n\n.sp-chev {\n color: var(--dsw-alias-label-dimmed);\n flex: none;\n}\n\n/* ── 官方 Modal 定制(宽度 + 内容紧凑) ── */\n\n.sp-modal {\n width: 520px;\n max-width: calc(100vw - 48px);\n}\n\n/* ── tab 栏 ── */\n\n.sp-tabs {\n display: flex;\n gap: 6px;\n padding: 0 2px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.sp-tab {\n flex: 1;\n padding: 8px 0;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-tab:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-tabOn {\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.2));\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n/* ── 模态内容 ── */\n\n.sp-modalBody {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding-top: 14px;\n /* 内容超出视口时 body 区滚动(兜底——不再截断);整卡不滚动 */\n overflow-y: auto;\n max-height: calc(100vh - 200px);\n}\n\n/* ── 分组(官方 settings 语言:groupTitle + rows) ── */\n\n.sp-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sp-groupHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.sp-groupTitle {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n/* 行卡(rowCard:border + radius + padding;值与 label 分离、长内容可换行) */\n.sp-row {\n display: flex;\n align-items: baseline;\n gap: 12px;\n min-width: 0;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-label {\n flex: none;\n width: 76px;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.sp-value {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n overflow-wrap: anywhere;\n}\n\n/* 安全模式动作区 */\n.sp-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 24px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-toggleLg {\n height: 30px;\n padding: 0 16px;\n font-size: 13px;\n}\n\n.sp-toggleOn {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 14%, transparent);\n color: var(--dsw-alias-state-error-primary);\n border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);\n}\n\n.sp-toggleOff {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-toggleIcon {\n flex: none;\n}\n\n.sp-toggleDesc {\n flex: 1;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* handyman 运行状态区块 */\n\n.sp-handymenToggle {\n flex: none;\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n cursor: pointer;\n}\n\n.sp-handymenToggle:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-handymenList {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 2px;\n}\n\n.sp-handymanItem {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n min-width: 0;\n}\n\n.sp-handymanHead {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.sp-handymanLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.sp-handymanRound {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-handymanTime {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-handymanResp {\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sp-handymenMore {\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n padding: 4px 12px;\n}\n\n/* 底部提示(配置入口引导) */\n.sp-hint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n padding: 8px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 10px;\n}\n";
12
12
  if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"SafeModePanel\"]") === null) {
13
13
  const tag = document.createElement("style");
14
14
  tag.setAttribute("data-sp-css", "SafeModePanel");
@@ -604,6 +604,2537 @@ window.__ModuleLoader__.load({
604
604
  return null;
605
605
  }
606
606
  //#endregion
607
+ //#region node_modules/.pnpm/qrcode-generator@2.0.4/node_modules/qrcode-generator/dist/qrcode.mjs
608
+ /**
609
+ * qrcode
610
+ * @param typeNumber 1 to 40
611
+ * @param errorCorrectionLevel 'L','M','Q','H'
612
+ */
613
+ const qrcode = function(typeNumber, errorCorrectionLevel) {
614
+ const PAD0 = 236;
615
+ const PAD1 = 17;
616
+ let _typeNumber = typeNumber;
617
+ const _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];
618
+ let _modules = null;
619
+ let _moduleCount = 0;
620
+ let _dataCache = null;
621
+ const _dataList = [];
622
+ const _this = {};
623
+ const makeImpl = function(test, maskPattern) {
624
+ _moduleCount = _typeNumber * 4 + 17;
625
+ _modules = function(moduleCount) {
626
+ const modules = new Array(moduleCount);
627
+ for (let row = 0; row < moduleCount; row += 1) {
628
+ modules[row] = new Array(moduleCount);
629
+ for (let col = 0; col < moduleCount; col += 1) modules[row][col] = null;
630
+ }
631
+ return modules;
632
+ }(_moduleCount);
633
+ setupPositionProbePattern(0, 0);
634
+ setupPositionProbePattern(_moduleCount - 7, 0);
635
+ setupPositionProbePattern(0, _moduleCount - 7);
636
+ setupPositionAdjustPattern();
637
+ setupTimingPattern();
638
+ setupTypeInfo(test, maskPattern);
639
+ if (_typeNumber >= 7) setupTypeNumber(test);
640
+ if (_dataCache == null) _dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);
641
+ mapData(_dataCache, maskPattern);
642
+ };
643
+ const setupPositionProbePattern = function(row, col) {
644
+ for (let r = -1; r <= 7; r += 1) {
645
+ if (row + r <= -1 || _moduleCount <= row + r) continue;
646
+ for (let c = -1; c <= 7; c += 1) {
647
+ if (col + c <= -1 || _moduleCount <= col + c) continue;
648
+ if (0 <= r && r <= 6 && (c == 0 || c == 6) || 0 <= c && c <= 6 && (r == 0 || r == 6) || 2 <= r && r <= 4 && 2 <= c && c <= 4) _modules[row + r][col + c] = true;
649
+ else _modules[row + r][col + c] = false;
650
+ }
651
+ }
652
+ };
653
+ const getBestMaskPattern = function() {
654
+ let minLostPoint = 0;
655
+ let pattern = 0;
656
+ for (let i = 0; i < 8; i += 1) {
657
+ makeImpl(true, i);
658
+ const lostPoint = QRUtil.getLostPoint(_this);
659
+ if (i == 0 || minLostPoint > lostPoint) {
660
+ minLostPoint = lostPoint;
661
+ pattern = i;
662
+ }
663
+ }
664
+ return pattern;
665
+ };
666
+ const setupTimingPattern = function() {
667
+ for (let r = 8; r < _moduleCount - 8; r += 1) {
668
+ if (_modules[r][6] != null) continue;
669
+ _modules[r][6] = r % 2 == 0;
670
+ }
671
+ for (let c = 8; c < _moduleCount - 8; c += 1) {
672
+ if (_modules[6][c] != null) continue;
673
+ _modules[6][c] = c % 2 == 0;
674
+ }
675
+ };
676
+ const setupPositionAdjustPattern = function() {
677
+ const pos = QRUtil.getPatternPosition(_typeNumber);
678
+ for (let i = 0; i < pos.length; i += 1) for (let j = 0; j < pos.length; j += 1) {
679
+ const row = pos[i];
680
+ const col = pos[j];
681
+ if (_modules[row][col] != null) continue;
682
+ for (let r = -2; r <= 2; r += 1) for (let c = -2; c <= 2; c += 1) if (r == -2 || r == 2 || c == -2 || c == 2 || r == 0 && c == 0) _modules[row + r][col + c] = true;
683
+ else _modules[row + r][col + c] = false;
684
+ }
685
+ };
686
+ const setupTypeNumber = function(test) {
687
+ const bits = QRUtil.getBCHTypeNumber(_typeNumber);
688
+ for (let i = 0; i < 18; i += 1) {
689
+ const mod = !test && (bits >> i & 1) == 1;
690
+ _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
691
+ }
692
+ for (let i = 0; i < 18; i += 1) {
693
+ const mod = !test && (bits >> i & 1) == 1;
694
+ _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
695
+ }
696
+ };
697
+ const setupTypeInfo = function(test, maskPattern) {
698
+ const data = _errorCorrectionLevel << 3 | maskPattern;
699
+ const bits = QRUtil.getBCHTypeInfo(data);
700
+ for (let i = 0; i < 15; i += 1) {
701
+ const mod = !test && (bits >> i & 1) == 1;
702
+ if (i < 6) _modules[i][8] = mod;
703
+ else if (i < 8) _modules[i + 1][8] = mod;
704
+ else _modules[_moduleCount - 15 + i][8] = mod;
705
+ }
706
+ for (let i = 0; i < 15; i += 1) {
707
+ const mod = !test && (bits >> i & 1) == 1;
708
+ if (i < 8) _modules[8][_moduleCount - i - 1] = mod;
709
+ else if (i < 9) _modules[8][15 - i - 1 + 1] = mod;
710
+ else _modules[8][15 - i - 1] = mod;
711
+ }
712
+ _modules[_moduleCount - 8][8] = !test;
713
+ };
714
+ const mapData = function(data, maskPattern) {
715
+ let inc = -1;
716
+ let row = _moduleCount - 1;
717
+ let bitIndex = 7;
718
+ let byteIndex = 0;
719
+ const maskFunc = QRUtil.getMaskFunction(maskPattern);
720
+ for (let col = _moduleCount - 1; col > 0; col -= 2) {
721
+ if (col == 6) col -= 1;
722
+ while (true) {
723
+ for (let c = 0; c < 2; c += 1) if (_modules[row][col - c] == null) {
724
+ let dark = false;
725
+ if (byteIndex < data.length) dark = (data[byteIndex] >>> bitIndex & 1) == 1;
726
+ if (maskFunc(row, col - c)) dark = !dark;
727
+ _modules[row][col - c] = dark;
728
+ bitIndex -= 1;
729
+ if (bitIndex == -1) {
730
+ byteIndex += 1;
731
+ bitIndex = 7;
732
+ }
733
+ }
734
+ row += inc;
735
+ if (row < 0 || _moduleCount <= row) {
736
+ row -= inc;
737
+ inc = -inc;
738
+ break;
739
+ }
740
+ }
741
+ }
742
+ };
743
+ const createBytes = function(buffer, rsBlocks) {
744
+ let offset = 0;
745
+ let maxDcCount = 0;
746
+ let maxEcCount = 0;
747
+ const dcdata = new Array(rsBlocks.length);
748
+ const ecdata = new Array(rsBlocks.length);
749
+ for (let r = 0; r < rsBlocks.length; r += 1) {
750
+ const dcCount = rsBlocks[r].dataCount;
751
+ const ecCount = rsBlocks[r].totalCount - dcCount;
752
+ maxDcCount = Math.max(maxDcCount, dcCount);
753
+ maxEcCount = Math.max(maxEcCount, ecCount);
754
+ dcdata[r] = new Array(dcCount);
755
+ for (let i = 0; i < dcdata[r].length; i += 1) dcdata[r][i] = 255 & buffer.getBuffer()[i + offset];
756
+ offset += dcCount;
757
+ const rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
758
+ const modPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1).mod(rsPoly);
759
+ ecdata[r] = new Array(rsPoly.getLength() - 1);
760
+ for (let i = 0; i < ecdata[r].length; i += 1) {
761
+ const modIndex = i + modPoly.getLength() - ecdata[r].length;
762
+ ecdata[r][i] = modIndex >= 0 ? modPoly.getAt(modIndex) : 0;
763
+ }
764
+ }
765
+ let totalCodeCount = 0;
766
+ for (let i = 0; i < rsBlocks.length; i += 1) totalCodeCount += rsBlocks[i].totalCount;
767
+ const data = new Array(totalCodeCount);
768
+ let index = 0;
769
+ for (let i = 0; i < maxDcCount; i += 1) for (let r = 0; r < rsBlocks.length; r += 1) if (i < dcdata[r].length) {
770
+ data[index] = dcdata[r][i];
771
+ index += 1;
772
+ }
773
+ for (let i = 0; i < maxEcCount; i += 1) for (let r = 0; r < rsBlocks.length; r += 1) if (i < ecdata[r].length) {
774
+ data[index] = ecdata[r][i];
775
+ index += 1;
776
+ }
777
+ return data;
778
+ };
779
+ const createData = function(typeNumber, errorCorrectionLevel, dataList) {
780
+ const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);
781
+ const buffer = qrBitBuffer();
782
+ for (let i = 0; i < dataList.length; i += 1) {
783
+ const data = dataList[i];
784
+ buffer.put(data.getMode(), 4);
785
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber));
786
+ data.write(buffer);
787
+ }
788
+ let totalDataCount = 0;
789
+ for (let i = 0; i < rsBlocks.length; i += 1) totalDataCount += rsBlocks[i].dataCount;
790
+ if (buffer.getLengthInBits() > totalDataCount * 8) throw "code length overflow. (" + buffer.getLengthInBits() + ">" + totalDataCount * 8 + ")";
791
+ if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) buffer.put(0, 4);
792
+ while (buffer.getLengthInBits() % 8 != 0) buffer.putBit(false);
793
+ while (true) {
794
+ if (buffer.getLengthInBits() >= totalDataCount * 8) break;
795
+ buffer.put(PAD0, 8);
796
+ if (buffer.getLengthInBits() >= totalDataCount * 8) break;
797
+ buffer.put(PAD1, 8);
798
+ }
799
+ return createBytes(buffer, rsBlocks);
800
+ };
801
+ _this.addData = function(data, mode) {
802
+ mode = mode || "Byte";
803
+ let newData = null;
804
+ switch (mode) {
805
+ case "Numeric":
806
+ newData = qrNumber(data);
807
+ break;
808
+ case "Alphanumeric":
809
+ newData = qrAlphaNum(data);
810
+ break;
811
+ case "Byte":
812
+ newData = qr8BitByte(data);
813
+ break;
814
+ case "Kanji":
815
+ newData = qrKanji(data);
816
+ break;
817
+ default: throw "mode:" + mode;
818
+ }
819
+ _dataList.push(newData);
820
+ _dataCache = null;
821
+ };
822
+ _this.isDark = function(row, col) {
823
+ if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) throw row + "," + col;
824
+ return _modules[row][col];
825
+ };
826
+ _this.getModuleCount = function() {
827
+ return _moduleCount;
828
+ };
829
+ _this.make = function() {
830
+ if (_typeNumber < 1) {
831
+ let typeNumber = 1;
832
+ for (; typeNumber < 40; typeNumber++) {
833
+ const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);
834
+ const buffer = qrBitBuffer();
835
+ for (let i = 0; i < _dataList.length; i++) {
836
+ const data = _dataList[i];
837
+ buffer.put(data.getMode(), 4);
838
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber));
839
+ data.write(buffer);
840
+ }
841
+ let totalDataCount = 0;
842
+ for (let i = 0; i < rsBlocks.length; i++) totalDataCount += rsBlocks[i].dataCount;
843
+ if (buffer.getLengthInBits() <= totalDataCount * 8) break;
844
+ }
845
+ _typeNumber = typeNumber;
846
+ }
847
+ makeImpl(false, getBestMaskPattern());
848
+ };
849
+ _this.createTableTag = function(cellSize, margin) {
850
+ cellSize = cellSize || 2;
851
+ margin = typeof margin == "undefined" ? cellSize * 4 : margin;
852
+ let qrHtml = "";
853
+ qrHtml += "<table style=\"";
854
+ qrHtml += " border-width: 0px; border-style: none;";
855
+ qrHtml += " border-collapse: collapse;";
856
+ qrHtml += " padding: 0px; margin: " + margin + "px;";
857
+ qrHtml += "\">";
858
+ qrHtml += "<tbody>";
859
+ for (let r = 0; r < _this.getModuleCount(); r += 1) {
860
+ qrHtml += "<tr>";
861
+ for (let c = 0; c < _this.getModuleCount(); c += 1) {
862
+ qrHtml += "<td style=\"";
863
+ qrHtml += " border-width: 0px; border-style: none;";
864
+ qrHtml += " border-collapse: collapse;";
865
+ qrHtml += " padding: 0px; margin: 0px;";
866
+ qrHtml += " width: " + cellSize + "px;";
867
+ qrHtml += " height: " + cellSize + "px;";
868
+ qrHtml += " background-color: ";
869
+ qrHtml += _this.isDark(r, c) ? "#000000" : "#ffffff";
870
+ qrHtml += ";";
871
+ qrHtml += "\"/>";
872
+ }
873
+ qrHtml += "</tr>";
874
+ }
875
+ qrHtml += "</tbody>";
876
+ qrHtml += "</table>";
877
+ return qrHtml;
878
+ };
879
+ _this.createSvgTag = function(cellSize, margin, alt, title) {
880
+ let opts = {};
881
+ if (typeof arguments[0] == "object") {
882
+ opts = arguments[0];
883
+ cellSize = opts.cellSize;
884
+ margin = opts.margin;
885
+ alt = opts.alt;
886
+ title = opts.title;
887
+ }
888
+ cellSize = cellSize || 2;
889
+ margin = typeof margin == "undefined" ? cellSize * 4 : margin;
890
+ alt = typeof alt === "string" ? { text: alt } : alt || {};
891
+ alt.text = alt.text || null;
892
+ alt.id = alt.text ? alt.id || "qrcode-description" : null;
893
+ title = typeof title === "string" ? { text: title } : title || {};
894
+ title.text = title.text || null;
895
+ title.id = title.text ? title.id || "qrcode-title" : null;
896
+ const size = _this.getModuleCount() * cellSize + margin * 2;
897
+ let c, mc, r, mr, qrSvg = "", rect;
898
+ rect = "l" + cellSize + ",0 0," + cellSize + " -" + cellSize + ",0 0,-" + cellSize + "z ";
899
+ qrSvg += "<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"";
900
+ qrSvg += !opts.scalable ? " width=\"" + size + "px\" height=\"" + size + "px\"" : "";
901
+ qrSvg += " viewBox=\"0 0 " + size + " " + size + "\" ";
902
+ qrSvg += " preserveAspectRatio=\"xMinYMin meet\"";
903
+ qrSvg += title.text || alt.text ? " role=\"img\" aria-labelledby=\"" + escapeXml([title.id, alt.id].join(" ").trim()) + "\"" : "";
904
+ qrSvg += ">";
905
+ qrSvg += title.text ? "<title id=\"" + escapeXml(title.id) + "\">" + escapeXml(title.text) + "</title>" : "";
906
+ qrSvg += alt.text ? "<description id=\"" + escapeXml(alt.id) + "\">" + escapeXml(alt.text) + "</description>" : "";
907
+ qrSvg += "<rect width=\"100%\" height=\"100%\" fill=\"white\" cx=\"0\" cy=\"0\"/>";
908
+ qrSvg += "<path d=\"";
909
+ for (r = 0; r < _this.getModuleCount(); r += 1) {
910
+ mr = r * cellSize + margin;
911
+ for (c = 0; c < _this.getModuleCount(); c += 1) if (_this.isDark(r, c)) {
912
+ mc = c * cellSize + margin;
913
+ qrSvg += "M" + mc + "," + mr + rect;
914
+ }
915
+ }
916
+ qrSvg += "\" stroke=\"transparent\" fill=\"black\"/>";
917
+ qrSvg += "</svg>";
918
+ return qrSvg;
919
+ };
920
+ _this.createDataURL = function(cellSize, margin) {
921
+ cellSize = cellSize || 2;
922
+ margin = typeof margin == "undefined" ? cellSize * 4 : margin;
923
+ const size = _this.getModuleCount() * cellSize + margin * 2;
924
+ const min = margin;
925
+ const max = size - margin;
926
+ return createDataURL(size, size, function(x, y) {
927
+ if (min <= x && x < max && min <= y && y < max) {
928
+ const c = Math.floor((x - min) / cellSize);
929
+ const r = Math.floor((y - min) / cellSize);
930
+ return _this.isDark(r, c) ? 0 : 1;
931
+ } else return 1;
932
+ });
933
+ };
934
+ _this.createImgTag = function(cellSize, margin, alt) {
935
+ cellSize = cellSize || 2;
936
+ margin = typeof margin == "undefined" ? cellSize * 4 : margin;
937
+ const size = _this.getModuleCount() * cellSize + margin * 2;
938
+ let img = "";
939
+ img += "<img";
940
+ img += " src=\"";
941
+ img += _this.createDataURL(cellSize, margin);
942
+ img += "\"";
943
+ img += " width=\"";
944
+ img += size;
945
+ img += "\"";
946
+ img += " height=\"";
947
+ img += size;
948
+ img += "\"";
949
+ if (alt) {
950
+ img += " alt=\"";
951
+ img += escapeXml(alt);
952
+ img += "\"";
953
+ }
954
+ img += "/>";
955
+ return img;
956
+ };
957
+ const escapeXml = function(s) {
958
+ let escaped = "";
959
+ for (let i = 0; i < s.length; i += 1) {
960
+ const c = s.charAt(i);
961
+ switch (c) {
962
+ case "<":
963
+ escaped += "&lt;";
964
+ break;
965
+ case ">":
966
+ escaped += "&gt;";
967
+ break;
968
+ case "&":
969
+ escaped += "&amp;";
970
+ break;
971
+ case "\"":
972
+ escaped += "&quot;";
973
+ break;
974
+ default: escaped += c;
975
+ }
976
+ }
977
+ return escaped;
978
+ };
979
+ const _createHalfASCII = function(margin) {
980
+ const cellSize = 1;
981
+ margin = typeof margin == "undefined" ? 2 : margin;
982
+ const size = _this.getModuleCount() * cellSize + margin * 2;
983
+ const min = margin;
984
+ const max = size - margin;
985
+ let y, x, r1, r2, p;
986
+ const blocks = {
987
+ "██": "█",
988
+ "█ ": "▀",
989
+ " █": "▄",
990
+ " ": " "
991
+ };
992
+ const blocksLastLineNoMargin = {
993
+ "██": "▀",
994
+ "█ ": "▀",
995
+ " █": " ",
996
+ " ": " "
997
+ };
998
+ let ascii = "";
999
+ for (y = 0; y < size; y += 2) {
1000
+ r1 = Math.floor((y - min) / cellSize);
1001
+ r2 = Math.floor((y + 1 - min) / cellSize);
1002
+ for (x = 0; x < size; x += 1) {
1003
+ p = "█";
1004
+ if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) p = " ";
1005
+ if (min <= x && x < max && min <= y + 1 && y + 1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) p += " ";
1006
+ else p += "█";
1007
+ ascii += margin < 1 && y + 1 >= max ? blocksLastLineNoMargin[p] : blocks[p];
1008
+ }
1009
+ ascii += "\n";
1010
+ }
1011
+ if (size % 2 && margin > 0) return ascii.substring(0, ascii.length - size - 1) + Array(size + 1).join("▀");
1012
+ return ascii.substring(0, ascii.length - 1);
1013
+ };
1014
+ _this.createASCII = function(cellSize, margin) {
1015
+ cellSize = cellSize || 1;
1016
+ if (cellSize < 2) return _createHalfASCII(margin);
1017
+ cellSize -= 1;
1018
+ margin = typeof margin == "undefined" ? cellSize * 2 : margin;
1019
+ const size = _this.getModuleCount() * cellSize + margin * 2;
1020
+ const min = margin;
1021
+ const max = size - margin;
1022
+ let y, x, r, p;
1023
+ const white = Array(cellSize + 1).join("██");
1024
+ const black = Array(cellSize + 1).join(" ");
1025
+ let ascii = "";
1026
+ let line = "";
1027
+ for (y = 0; y < size; y += 1) {
1028
+ r = Math.floor((y - min) / cellSize);
1029
+ line = "";
1030
+ for (x = 0; x < size; x += 1) {
1031
+ p = 1;
1032
+ if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) p = 0;
1033
+ line += p ? white : black;
1034
+ }
1035
+ for (r = 0; r < cellSize; r += 1) ascii += line + "\n";
1036
+ }
1037
+ return ascii.substring(0, ascii.length - 1);
1038
+ };
1039
+ _this.renderTo2dContext = function(context, cellSize) {
1040
+ cellSize = cellSize || 2;
1041
+ const length = _this.getModuleCount();
1042
+ for (let row = 0; row < length; row++) for (let col = 0; col < length; col++) {
1043
+ context.fillStyle = _this.isDark(row, col) ? "black" : "white";
1044
+ context.fillRect(col * cellSize, row * cellSize, cellSize, cellSize);
1045
+ }
1046
+ };
1047
+ return _this;
1048
+ };
1049
+ qrcode.stringToBytes = function(s) {
1050
+ const bytes = [];
1051
+ for (let i = 0; i < s.length; i += 1) {
1052
+ const c = s.charCodeAt(i);
1053
+ bytes.push(c & 255);
1054
+ }
1055
+ return bytes;
1056
+ };
1057
+ /**
1058
+ * @param unicodeData base64 string of byte array.
1059
+ * [16bit Unicode],[16bit Bytes], ...
1060
+ * @param numChars
1061
+ */
1062
+ qrcode.createStringToBytes = function(unicodeData, numChars) {
1063
+ const unicodeMap = function() {
1064
+ const bin = base64DecodeInputStream(unicodeData);
1065
+ const read = function() {
1066
+ const b = bin.read();
1067
+ if (b == -1) throw "eof";
1068
+ return b;
1069
+ };
1070
+ let count = 0;
1071
+ const unicodeMap = {};
1072
+ while (true) {
1073
+ const b0 = bin.read();
1074
+ if (b0 == -1) break;
1075
+ const b1 = read();
1076
+ const b2 = read();
1077
+ const b3 = read();
1078
+ const k = String.fromCharCode(b0 << 8 | b1);
1079
+ unicodeMap[k] = b2 << 8 | b3;
1080
+ count += 1;
1081
+ }
1082
+ if (count != numChars) throw count + " != " + numChars;
1083
+ return unicodeMap;
1084
+ }();
1085
+ const unknownChar = "?".charCodeAt(0);
1086
+ return function(s) {
1087
+ const bytes = [];
1088
+ for (let i = 0; i < s.length; i += 1) {
1089
+ const c = s.charCodeAt(i);
1090
+ if (c < 128) bytes.push(c);
1091
+ else {
1092
+ const b = unicodeMap[s.charAt(i)];
1093
+ if (typeof b == "number") {
1094
+ if ((b & 255) == b) bytes.push(b);
1095
+ else {
1096
+ bytes.push(b >>> 8);
1097
+ bytes.push(b & 255);
1098
+ }
1099
+ } else bytes.push(unknownChar);
1100
+ }
1101
+ }
1102
+ return bytes;
1103
+ };
1104
+ };
1105
+ const QRMode = {
1106
+ MODE_NUMBER: 1,
1107
+ MODE_ALPHA_NUM: 2,
1108
+ MODE_8BIT_BYTE: 4,
1109
+ MODE_KANJI: 8
1110
+ };
1111
+ const QRErrorCorrectionLevel = {
1112
+ L: 1,
1113
+ M: 0,
1114
+ Q: 3,
1115
+ H: 2
1116
+ };
1117
+ const QRMaskPattern = {
1118
+ PATTERN000: 0,
1119
+ PATTERN001: 1,
1120
+ PATTERN010: 2,
1121
+ PATTERN011: 3,
1122
+ PATTERN100: 4,
1123
+ PATTERN101: 5,
1124
+ PATTERN110: 6,
1125
+ PATTERN111: 7
1126
+ };
1127
+ const QRUtil = function() {
1128
+ const PATTERN_POSITION_TABLE = [
1129
+ [],
1130
+ [6, 18],
1131
+ [6, 22],
1132
+ [6, 26],
1133
+ [6, 30],
1134
+ [6, 34],
1135
+ [
1136
+ 6,
1137
+ 22,
1138
+ 38
1139
+ ],
1140
+ [
1141
+ 6,
1142
+ 24,
1143
+ 42
1144
+ ],
1145
+ [
1146
+ 6,
1147
+ 26,
1148
+ 46
1149
+ ],
1150
+ [
1151
+ 6,
1152
+ 28,
1153
+ 50
1154
+ ],
1155
+ [
1156
+ 6,
1157
+ 30,
1158
+ 54
1159
+ ],
1160
+ [
1161
+ 6,
1162
+ 32,
1163
+ 58
1164
+ ],
1165
+ [
1166
+ 6,
1167
+ 34,
1168
+ 62
1169
+ ],
1170
+ [
1171
+ 6,
1172
+ 26,
1173
+ 46,
1174
+ 66
1175
+ ],
1176
+ [
1177
+ 6,
1178
+ 26,
1179
+ 48,
1180
+ 70
1181
+ ],
1182
+ [
1183
+ 6,
1184
+ 26,
1185
+ 50,
1186
+ 74
1187
+ ],
1188
+ [
1189
+ 6,
1190
+ 30,
1191
+ 54,
1192
+ 78
1193
+ ],
1194
+ [
1195
+ 6,
1196
+ 30,
1197
+ 56,
1198
+ 82
1199
+ ],
1200
+ [
1201
+ 6,
1202
+ 30,
1203
+ 58,
1204
+ 86
1205
+ ],
1206
+ [
1207
+ 6,
1208
+ 34,
1209
+ 62,
1210
+ 90
1211
+ ],
1212
+ [
1213
+ 6,
1214
+ 28,
1215
+ 50,
1216
+ 72,
1217
+ 94
1218
+ ],
1219
+ [
1220
+ 6,
1221
+ 26,
1222
+ 50,
1223
+ 74,
1224
+ 98
1225
+ ],
1226
+ [
1227
+ 6,
1228
+ 30,
1229
+ 54,
1230
+ 78,
1231
+ 102
1232
+ ],
1233
+ [
1234
+ 6,
1235
+ 28,
1236
+ 54,
1237
+ 80,
1238
+ 106
1239
+ ],
1240
+ [
1241
+ 6,
1242
+ 32,
1243
+ 58,
1244
+ 84,
1245
+ 110
1246
+ ],
1247
+ [
1248
+ 6,
1249
+ 30,
1250
+ 58,
1251
+ 86,
1252
+ 114
1253
+ ],
1254
+ [
1255
+ 6,
1256
+ 34,
1257
+ 62,
1258
+ 90,
1259
+ 118
1260
+ ],
1261
+ [
1262
+ 6,
1263
+ 26,
1264
+ 50,
1265
+ 74,
1266
+ 98,
1267
+ 122
1268
+ ],
1269
+ [
1270
+ 6,
1271
+ 30,
1272
+ 54,
1273
+ 78,
1274
+ 102,
1275
+ 126
1276
+ ],
1277
+ [
1278
+ 6,
1279
+ 26,
1280
+ 52,
1281
+ 78,
1282
+ 104,
1283
+ 130
1284
+ ],
1285
+ [
1286
+ 6,
1287
+ 30,
1288
+ 56,
1289
+ 82,
1290
+ 108,
1291
+ 134
1292
+ ],
1293
+ [
1294
+ 6,
1295
+ 34,
1296
+ 60,
1297
+ 86,
1298
+ 112,
1299
+ 138
1300
+ ],
1301
+ [
1302
+ 6,
1303
+ 30,
1304
+ 58,
1305
+ 86,
1306
+ 114,
1307
+ 142
1308
+ ],
1309
+ [
1310
+ 6,
1311
+ 34,
1312
+ 62,
1313
+ 90,
1314
+ 118,
1315
+ 146
1316
+ ],
1317
+ [
1318
+ 6,
1319
+ 30,
1320
+ 54,
1321
+ 78,
1322
+ 102,
1323
+ 126,
1324
+ 150
1325
+ ],
1326
+ [
1327
+ 6,
1328
+ 24,
1329
+ 50,
1330
+ 76,
1331
+ 102,
1332
+ 128,
1333
+ 154
1334
+ ],
1335
+ [
1336
+ 6,
1337
+ 28,
1338
+ 54,
1339
+ 80,
1340
+ 106,
1341
+ 132,
1342
+ 158
1343
+ ],
1344
+ [
1345
+ 6,
1346
+ 32,
1347
+ 58,
1348
+ 84,
1349
+ 110,
1350
+ 136,
1351
+ 162
1352
+ ],
1353
+ [
1354
+ 6,
1355
+ 26,
1356
+ 54,
1357
+ 82,
1358
+ 110,
1359
+ 138,
1360
+ 166
1361
+ ],
1362
+ [
1363
+ 6,
1364
+ 30,
1365
+ 58,
1366
+ 86,
1367
+ 114,
1368
+ 142,
1369
+ 170
1370
+ ]
1371
+ ];
1372
+ const G15 = 1335;
1373
+ const G18 = 7973;
1374
+ const G15_MASK = 21522;
1375
+ const _this = {};
1376
+ const getBCHDigit = function(data) {
1377
+ let digit = 0;
1378
+ while (data != 0) {
1379
+ digit += 1;
1380
+ data >>>= 1;
1381
+ }
1382
+ return digit;
1383
+ };
1384
+ _this.getBCHTypeInfo = function(data) {
1385
+ let d = data << 10;
1386
+ while (getBCHDigit(d) - getBCHDigit(G15) >= 0) d ^= G15 << getBCHDigit(d) - getBCHDigit(G15);
1387
+ return (data << 10 | d) ^ G15_MASK;
1388
+ };
1389
+ _this.getBCHTypeNumber = function(data) {
1390
+ let d = data << 12;
1391
+ while (getBCHDigit(d) - getBCHDigit(G18) >= 0) d ^= G18 << getBCHDigit(d) - getBCHDigit(G18);
1392
+ return data << 12 | d;
1393
+ };
1394
+ _this.getPatternPosition = function(typeNumber) {
1395
+ return PATTERN_POSITION_TABLE[typeNumber - 1];
1396
+ };
1397
+ _this.getMaskFunction = function(maskPattern) {
1398
+ switch (maskPattern) {
1399
+ case QRMaskPattern.PATTERN000: return function(i, j) {
1400
+ return (i + j) % 2 == 0;
1401
+ };
1402
+ case QRMaskPattern.PATTERN001: return function(i, j) {
1403
+ return i % 2 == 0;
1404
+ };
1405
+ case QRMaskPattern.PATTERN010: return function(i, j) {
1406
+ return j % 3 == 0;
1407
+ };
1408
+ case QRMaskPattern.PATTERN011: return function(i, j) {
1409
+ return (i + j) % 3 == 0;
1410
+ };
1411
+ case QRMaskPattern.PATTERN100: return function(i, j) {
1412
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
1413
+ };
1414
+ case QRMaskPattern.PATTERN101: return function(i, j) {
1415
+ return i * j % 2 + i * j % 3 == 0;
1416
+ };
1417
+ case QRMaskPattern.PATTERN110: return function(i, j) {
1418
+ return (i * j % 2 + i * j % 3) % 2 == 0;
1419
+ };
1420
+ case QRMaskPattern.PATTERN111: return function(i, j) {
1421
+ return (i * j % 3 + (i + j) % 2) % 2 == 0;
1422
+ };
1423
+ default: throw "bad maskPattern:" + maskPattern;
1424
+ }
1425
+ };
1426
+ _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
1427
+ let a = qrPolynomial([1], 0);
1428
+ for (let i = 0; i < errorCorrectLength; i += 1) a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0));
1429
+ return a;
1430
+ };
1431
+ _this.getLengthInBits = function(mode, type) {
1432
+ if (1 <= type && type < 10) switch (mode) {
1433
+ case QRMode.MODE_NUMBER: return 10;
1434
+ case QRMode.MODE_ALPHA_NUM: return 9;
1435
+ case QRMode.MODE_8BIT_BYTE: return 8;
1436
+ case QRMode.MODE_KANJI: return 8;
1437
+ default: throw "mode:" + mode;
1438
+ }
1439
+ else if (type < 27) switch (mode) {
1440
+ case QRMode.MODE_NUMBER: return 12;
1441
+ case QRMode.MODE_ALPHA_NUM: return 11;
1442
+ case QRMode.MODE_8BIT_BYTE: return 16;
1443
+ case QRMode.MODE_KANJI: return 10;
1444
+ default: throw "mode:" + mode;
1445
+ }
1446
+ else if (type < 41) switch (mode) {
1447
+ case QRMode.MODE_NUMBER: return 14;
1448
+ case QRMode.MODE_ALPHA_NUM: return 13;
1449
+ case QRMode.MODE_8BIT_BYTE: return 16;
1450
+ case QRMode.MODE_KANJI: return 12;
1451
+ default: throw "mode:" + mode;
1452
+ }
1453
+ else throw "type:" + type;
1454
+ };
1455
+ _this.getLostPoint = function(qrcode) {
1456
+ const moduleCount = qrcode.getModuleCount();
1457
+ let lostPoint = 0;
1458
+ for (let row = 0; row < moduleCount; row += 1) for (let col = 0; col < moduleCount; col += 1) {
1459
+ let sameCount = 0;
1460
+ const dark = qrcode.isDark(row, col);
1461
+ for (let r = -1; r <= 1; r += 1) {
1462
+ if (row + r < 0 || moduleCount <= row + r) continue;
1463
+ for (let c = -1; c <= 1; c += 1) {
1464
+ if (col + c < 0 || moduleCount <= col + c) continue;
1465
+ if (r == 0 && c == 0) continue;
1466
+ if (dark == qrcode.isDark(row + r, col + c)) sameCount += 1;
1467
+ }
1468
+ }
1469
+ if (sameCount > 5) lostPoint += 3 + sameCount - 5;
1470
+ }
1471
+ for (let row = 0; row < moduleCount - 1; row += 1) for (let col = 0; col < moduleCount - 1; col += 1) {
1472
+ let count = 0;
1473
+ if (qrcode.isDark(row, col)) count += 1;
1474
+ if (qrcode.isDark(row + 1, col)) count += 1;
1475
+ if (qrcode.isDark(row, col + 1)) count += 1;
1476
+ if (qrcode.isDark(row + 1, col + 1)) count += 1;
1477
+ if (count == 0 || count == 4) lostPoint += 3;
1478
+ }
1479
+ for (let row = 0; row < moduleCount; row += 1) for (let col = 0; col < moduleCount - 6; col += 1) if (qrcode.isDark(row, col) && !qrcode.isDark(row, col + 1) && qrcode.isDark(row, col + 2) && qrcode.isDark(row, col + 3) && qrcode.isDark(row, col + 4) && !qrcode.isDark(row, col + 5) && qrcode.isDark(row, col + 6)) lostPoint += 40;
1480
+ for (let col = 0; col < moduleCount; col += 1) for (let row = 0; row < moduleCount - 6; row += 1) if (qrcode.isDark(row, col) && !qrcode.isDark(row + 1, col) && qrcode.isDark(row + 2, col) && qrcode.isDark(row + 3, col) && qrcode.isDark(row + 4, col) && !qrcode.isDark(row + 5, col) && qrcode.isDark(row + 6, col)) lostPoint += 40;
1481
+ let darkCount = 0;
1482
+ for (let col = 0; col < moduleCount; col += 1) for (let row = 0; row < moduleCount; row += 1) if (qrcode.isDark(row, col)) darkCount += 1;
1483
+ const ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
1484
+ lostPoint += ratio * 10;
1485
+ return lostPoint;
1486
+ };
1487
+ return _this;
1488
+ }();
1489
+ const QRMath = function() {
1490
+ const EXP_TABLE = new Array(256);
1491
+ const LOG_TABLE = new Array(256);
1492
+ for (let i = 0; i < 8; i += 1) EXP_TABLE[i] = 1 << i;
1493
+ for (let i = 8; i < 256; i += 1) EXP_TABLE[i] = EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8];
1494
+ for (let i = 0; i < 255; i += 1) LOG_TABLE[EXP_TABLE[i]] = i;
1495
+ const _this = {};
1496
+ _this.glog = function(n) {
1497
+ if (n < 1) throw "glog(" + n + ")";
1498
+ return LOG_TABLE[n];
1499
+ };
1500
+ _this.gexp = function(n) {
1501
+ while (n < 0) n += 255;
1502
+ while (n >= 256) n -= 255;
1503
+ return EXP_TABLE[n];
1504
+ };
1505
+ return _this;
1506
+ }();
1507
+ const qrPolynomial = function(num, shift) {
1508
+ if (typeof num.length == "undefined") throw num.length + "/" + shift;
1509
+ const _num = function() {
1510
+ let offset = 0;
1511
+ while (offset < num.length && num[offset] == 0) offset += 1;
1512
+ const _num = new Array(num.length - offset + shift);
1513
+ for (let i = 0; i < num.length - offset; i += 1) _num[i] = num[i + offset];
1514
+ return _num;
1515
+ }();
1516
+ const _this = {};
1517
+ _this.getAt = function(index) {
1518
+ return _num[index];
1519
+ };
1520
+ _this.getLength = function() {
1521
+ return _num.length;
1522
+ };
1523
+ _this.multiply = function(e) {
1524
+ const num = new Array(_this.getLength() + e.getLength() - 1);
1525
+ for (let i = 0; i < _this.getLength(); i += 1) for (let j = 0; j < e.getLength(); j += 1) num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i)) + QRMath.glog(e.getAt(j)));
1526
+ return qrPolynomial(num, 0);
1527
+ };
1528
+ _this.mod = function(e) {
1529
+ if (_this.getLength() - e.getLength() < 0) return _this;
1530
+ const ratio = QRMath.glog(_this.getAt(0)) - QRMath.glog(e.getAt(0));
1531
+ const num = new Array(_this.getLength());
1532
+ for (let i = 0; i < _this.getLength(); i += 1) num[i] = _this.getAt(i);
1533
+ for (let i = 0; i < e.getLength(); i += 1) num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i)) + ratio);
1534
+ return qrPolynomial(num, 0).mod(e);
1535
+ };
1536
+ return _this;
1537
+ };
1538
+ const QRRSBlock = function() {
1539
+ const RS_BLOCK_TABLE = [
1540
+ [
1541
+ 1,
1542
+ 26,
1543
+ 19
1544
+ ],
1545
+ [
1546
+ 1,
1547
+ 26,
1548
+ 16
1549
+ ],
1550
+ [
1551
+ 1,
1552
+ 26,
1553
+ 13
1554
+ ],
1555
+ [
1556
+ 1,
1557
+ 26,
1558
+ 9
1559
+ ],
1560
+ [
1561
+ 1,
1562
+ 44,
1563
+ 34
1564
+ ],
1565
+ [
1566
+ 1,
1567
+ 44,
1568
+ 28
1569
+ ],
1570
+ [
1571
+ 1,
1572
+ 44,
1573
+ 22
1574
+ ],
1575
+ [
1576
+ 1,
1577
+ 44,
1578
+ 16
1579
+ ],
1580
+ [
1581
+ 1,
1582
+ 70,
1583
+ 55
1584
+ ],
1585
+ [
1586
+ 1,
1587
+ 70,
1588
+ 44
1589
+ ],
1590
+ [
1591
+ 2,
1592
+ 35,
1593
+ 17
1594
+ ],
1595
+ [
1596
+ 2,
1597
+ 35,
1598
+ 13
1599
+ ],
1600
+ [
1601
+ 1,
1602
+ 100,
1603
+ 80
1604
+ ],
1605
+ [
1606
+ 2,
1607
+ 50,
1608
+ 32
1609
+ ],
1610
+ [
1611
+ 2,
1612
+ 50,
1613
+ 24
1614
+ ],
1615
+ [
1616
+ 4,
1617
+ 25,
1618
+ 9
1619
+ ],
1620
+ [
1621
+ 1,
1622
+ 134,
1623
+ 108
1624
+ ],
1625
+ [
1626
+ 2,
1627
+ 67,
1628
+ 43
1629
+ ],
1630
+ [
1631
+ 2,
1632
+ 33,
1633
+ 15,
1634
+ 2,
1635
+ 34,
1636
+ 16
1637
+ ],
1638
+ [
1639
+ 2,
1640
+ 33,
1641
+ 11,
1642
+ 2,
1643
+ 34,
1644
+ 12
1645
+ ],
1646
+ [
1647
+ 2,
1648
+ 86,
1649
+ 68
1650
+ ],
1651
+ [
1652
+ 4,
1653
+ 43,
1654
+ 27
1655
+ ],
1656
+ [
1657
+ 4,
1658
+ 43,
1659
+ 19
1660
+ ],
1661
+ [
1662
+ 4,
1663
+ 43,
1664
+ 15
1665
+ ],
1666
+ [
1667
+ 2,
1668
+ 98,
1669
+ 78
1670
+ ],
1671
+ [
1672
+ 4,
1673
+ 49,
1674
+ 31
1675
+ ],
1676
+ [
1677
+ 2,
1678
+ 32,
1679
+ 14,
1680
+ 4,
1681
+ 33,
1682
+ 15
1683
+ ],
1684
+ [
1685
+ 4,
1686
+ 39,
1687
+ 13,
1688
+ 1,
1689
+ 40,
1690
+ 14
1691
+ ],
1692
+ [
1693
+ 2,
1694
+ 121,
1695
+ 97
1696
+ ],
1697
+ [
1698
+ 2,
1699
+ 60,
1700
+ 38,
1701
+ 2,
1702
+ 61,
1703
+ 39
1704
+ ],
1705
+ [
1706
+ 4,
1707
+ 40,
1708
+ 18,
1709
+ 2,
1710
+ 41,
1711
+ 19
1712
+ ],
1713
+ [
1714
+ 4,
1715
+ 40,
1716
+ 14,
1717
+ 2,
1718
+ 41,
1719
+ 15
1720
+ ],
1721
+ [
1722
+ 2,
1723
+ 146,
1724
+ 116
1725
+ ],
1726
+ [
1727
+ 3,
1728
+ 58,
1729
+ 36,
1730
+ 2,
1731
+ 59,
1732
+ 37
1733
+ ],
1734
+ [
1735
+ 4,
1736
+ 36,
1737
+ 16,
1738
+ 4,
1739
+ 37,
1740
+ 17
1741
+ ],
1742
+ [
1743
+ 4,
1744
+ 36,
1745
+ 12,
1746
+ 4,
1747
+ 37,
1748
+ 13
1749
+ ],
1750
+ [
1751
+ 2,
1752
+ 86,
1753
+ 68,
1754
+ 2,
1755
+ 87,
1756
+ 69
1757
+ ],
1758
+ [
1759
+ 4,
1760
+ 69,
1761
+ 43,
1762
+ 1,
1763
+ 70,
1764
+ 44
1765
+ ],
1766
+ [
1767
+ 6,
1768
+ 43,
1769
+ 19,
1770
+ 2,
1771
+ 44,
1772
+ 20
1773
+ ],
1774
+ [
1775
+ 6,
1776
+ 43,
1777
+ 15,
1778
+ 2,
1779
+ 44,
1780
+ 16
1781
+ ],
1782
+ [
1783
+ 4,
1784
+ 101,
1785
+ 81
1786
+ ],
1787
+ [
1788
+ 1,
1789
+ 80,
1790
+ 50,
1791
+ 4,
1792
+ 81,
1793
+ 51
1794
+ ],
1795
+ [
1796
+ 4,
1797
+ 50,
1798
+ 22,
1799
+ 4,
1800
+ 51,
1801
+ 23
1802
+ ],
1803
+ [
1804
+ 3,
1805
+ 36,
1806
+ 12,
1807
+ 8,
1808
+ 37,
1809
+ 13
1810
+ ],
1811
+ [
1812
+ 2,
1813
+ 116,
1814
+ 92,
1815
+ 2,
1816
+ 117,
1817
+ 93
1818
+ ],
1819
+ [
1820
+ 6,
1821
+ 58,
1822
+ 36,
1823
+ 2,
1824
+ 59,
1825
+ 37
1826
+ ],
1827
+ [
1828
+ 4,
1829
+ 46,
1830
+ 20,
1831
+ 6,
1832
+ 47,
1833
+ 21
1834
+ ],
1835
+ [
1836
+ 7,
1837
+ 42,
1838
+ 14,
1839
+ 4,
1840
+ 43,
1841
+ 15
1842
+ ],
1843
+ [
1844
+ 4,
1845
+ 133,
1846
+ 107
1847
+ ],
1848
+ [
1849
+ 8,
1850
+ 59,
1851
+ 37,
1852
+ 1,
1853
+ 60,
1854
+ 38
1855
+ ],
1856
+ [
1857
+ 8,
1858
+ 44,
1859
+ 20,
1860
+ 4,
1861
+ 45,
1862
+ 21
1863
+ ],
1864
+ [
1865
+ 12,
1866
+ 33,
1867
+ 11,
1868
+ 4,
1869
+ 34,
1870
+ 12
1871
+ ],
1872
+ [
1873
+ 3,
1874
+ 145,
1875
+ 115,
1876
+ 1,
1877
+ 146,
1878
+ 116
1879
+ ],
1880
+ [
1881
+ 4,
1882
+ 64,
1883
+ 40,
1884
+ 5,
1885
+ 65,
1886
+ 41
1887
+ ],
1888
+ [
1889
+ 11,
1890
+ 36,
1891
+ 16,
1892
+ 5,
1893
+ 37,
1894
+ 17
1895
+ ],
1896
+ [
1897
+ 11,
1898
+ 36,
1899
+ 12,
1900
+ 5,
1901
+ 37,
1902
+ 13
1903
+ ],
1904
+ [
1905
+ 5,
1906
+ 109,
1907
+ 87,
1908
+ 1,
1909
+ 110,
1910
+ 88
1911
+ ],
1912
+ [
1913
+ 5,
1914
+ 65,
1915
+ 41,
1916
+ 5,
1917
+ 66,
1918
+ 42
1919
+ ],
1920
+ [
1921
+ 5,
1922
+ 54,
1923
+ 24,
1924
+ 7,
1925
+ 55,
1926
+ 25
1927
+ ],
1928
+ [
1929
+ 11,
1930
+ 36,
1931
+ 12,
1932
+ 7,
1933
+ 37,
1934
+ 13
1935
+ ],
1936
+ [
1937
+ 5,
1938
+ 122,
1939
+ 98,
1940
+ 1,
1941
+ 123,
1942
+ 99
1943
+ ],
1944
+ [
1945
+ 7,
1946
+ 73,
1947
+ 45,
1948
+ 3,
1949
+ 74,
1950
+ 46
1951
+ ],
1952
+ [
1953
+ 15,
1954
+ 43,
1955
+ 19,
1956
+ 2,
1957
+ 44,
1958
+ 20
1959
+ ],
1960
+ [
1961
+ 3,
1962
+ 45,
1963
+ 15,
1964
+ 13,
1965
+ 46,
1966
+ 16
1967
+ ],
1968
+ [
1969
+ 1,
1970
+ 135,
1971
+ 107,
1972
+ 5,
1973
+ 136,
1974
+ 108
1975
+ ],
1976
+ [
1977
+ 10,
1978
+ 74,
1979
+ 46,
1980
+ 1,
1981
+ 75,
1982
+ 47
1983
+ ],
1984
+ [
1985
+ 1,
1986
+ 50,
1987
+ 22,
1988
+ 15,
1989
+ 51,
1990
+ 23
1991
+ ],
1992
+ [
1993
+ 2,
1994
+ 42,
1995
+ 14,
1996
+ 17,
1997
+ 43,
1998
+ 15
1999
+ ],
2000
+ [
2001
+ 5,
2002
+ 150,
2003
+ 120,
2004
+ 1,
2005
+ 151,
2006
+ 121
2007
+ ],
2008
+ [
2009
+ 9,
2010
+ 69,
2011
+ 43,
2012
+ 4,
2013
+ 70,
2014
+ 44
2015
+ ],
2016
+ [
2017
+ 17,
2018
+ 50,
2019
+ 22,
2020
+ 1,
2021
+ 51,
2022
+ 23
2023
+ ],
2024
+ [
2025
+ 2,
2026
+ 42,
2027
+ 14,
2028
+ 19,
2029
+ 43,
2030
+ 15
2031
+ ],
2032
+ [
2033
+ 3,
2034
+ 141,
2035
+ 113,
2036
+ 4,
2037
+ 142,
2038
+ 114
2039
+ ],
2040
+ [
2041
+ 3,
2042
+ 70,
2043
+ 44,
2044
+ 11,
2045
+ 71,
2046
+ 45
2047
+ ],
2048
+ [
2049
+ 17,
2050
+ 47,
2051
+ 21,
2052
+ 4,
2053
+ 48,
2054
+ 22
2055
+ ],
2056
+ [
2057
+ 9,
2058
+ 39,
2059
+ 13,
2060
+ 16,
2061
+ 40,
2062
+ 14
2063
+ ],
2064
+ [
2065
+ 3,
2066
+ 135,
2067
+ 107,
2068
+ 5,
2069
+ 136,
2070
+ 108
2071
+ ],
2072
+ [
2073
+ 3,
2074
+ 67,
2075
+ 41,
2076
+ 13,
2077
+ 68,
2078
+ 42
2079
+ ],
2080
+ [
2081
+ 15,
2082
+ 54,
2083
+ 24,
2084
+ 5,
2085
+ 55,
2086
+ 25
2087
+ ],
2088
+ [
2089
+ 15,
2090
+ 43,
2091
+ 15,
2092
+ 10,
2093
+ 44,
2094
+ 16
2095
+ ],
2096
+ [
2097
+ 4,
2098
+ 144,
2099
+ 116,
2100
+ 4,
2101
+ 145,
2102
+ 117
2103
+ ],
2104
+ [
2105
+ 17,
2106
+ 68,
2107
+ 42
2108
+ ],
2109
+ [
2110
+ 17,
2111
+ 50,
2112
+ 22,
2113
+ 6,
2114
+ 51,
2115
+ 23
2116
+ ],
2117
+ [
2118
+ 19,
2119
+ 46,
2120
+ 16,
2121
+ 6,
2122
+ 47,
2123
+ 17
2124
+ ],
2125
+ [
2126
+ 2,
2127
+ 139,
2128
+ 111,
2129
+ 7,
2130
+ 140,
2131
+ 112
2132
+ ],
2133
+ [
2134
+ 17,
2135
+ 74,
2136
+ 46
2137
+ ],
2138
+ [
2139
+ 7,
2140
+ 54,
2141
+ 24,
2142
+ 16,
2143
+ 55,
2144
+ 25
2145
+ ],
2146
+ [
2147
+ 34,
2148
+ 37,
2149
+ 13
2150
+ ],
2151
+ [
2152
+ 4,
2153
+ 151,
2154
+ 121,
2155
+ 5,
2156
+ 152,
2157
+ 122
2158
+ ],
2159
+ [
2160
+ 4,
2161
+ 75,
2162
+ 47,
2163
+ 14,
2164
+ 76,
2165
+ 48
2166
+ ],
2167
+ [
2168
+ 11,
2169
+ 54,
2170
+ 24,
2171
+ 14,
2172
+ 55,
2173
+ 25
2174
+ ],
2175
+ [
2176
+ 16,
2177
+ 45,
2178
+ 15,
2179
+ 14,
2180
+ 46,
2181
+ 16
2182
+ ],
2183
+ [
2184
+ 6,
2185
+ 147,
2186
+ 117,
2187
+ 4,
2188
+ 148,
2189
+ 118
2190
+ ],
2191
+ [
2192
+ 6,
2193
+ 73,
2194
+ 45,
2195
+ 14,
2196
+ 74,
2197
+ 46
2198
+ ],
2199
+ [
2200
+ 11,
2201
+ 54,
2202
+ 24,
2203
+ 16,
2204
+ 55,
2205
+ 25
2206
+ ],
2207
+ [
2208
+ 30,
2209
+ 46,
2210
+ 16,
2211
+ 2,
2212
+ 47,
2213
+ 17
2214
+ ],
2215
+ [
2216
+ 8,
2217
+ 132,
2218
+ 106,
2219
+ 4,
2220
+ 133,
2221
+ 107
2222
+ ],
2223
+ [
2224
+ 8,
2225
+ 75,
2226
+ 47,
2227
+ 13,
2228
+ 76,
2229
+ 48
2230
+ ],
2231
+ [
2232
+ 7,
2233
+ 54,
2234
+ 24,
2235
+ 22,
2236
+ 55,
2237
+ 25
2238
+ ],
2239
+ [
2240
+ 22,
2241
+ 45,
2242
+ 15,
2243
+ 13,
2244
+ 46,
2245
+ 16
2246
+ ],
2247
+ [
2248
+ 10,
2249
+ 142,
2250
+ 114,
2251
+ 2,
2252
+ 143,
2253
+ 115
2254
+ ],
2255
+ [
2256
+ 19,
2257
+ 74,
2258
+ 46,
2259
+ 4,
2260
+ 75,
2261
+ 47
2262
+ ],
2263
+ [
2264
+ 28,
2265
+ 50,
2266
+ 22,
2267
+ 6,
2268
+ 51,
2269
+ 23
2270
+ ],
2271
+ [
2272
+ 33,
2273
+ 46,
2274
+ 16,
2275
+ 4,
2276
+ 47,
2277
+ 17
2278
+ ],
2279
+ [
2280
+ 8,
2281
+ 152,
2282
+ 122,
2283
+ 4,
2284
+ 153,
2285
+ 123
2286
+ ],
2287
+ [
2288
+ 22,
2289
+ 73,
2290
+ 45,
2291
+ 3,
2292
+ 74,
2293
+ 46
2294
+ ],
2295
+ [
2296
+ 8,
2297
+ 53,
2298
+ 23,
2299
+ 26,
2300
+ 54,
2301
+ 24
2302
+ ],
2303
+ [
2304
+ 12,
2305
+ 45,
2306
+ 15,
2307
+ 28,
2308
+ 46,
2309
+ 16
2310
+ ],
2311
+ [
2312
+ 3,
2313
+ 147,
2314
+ 117,
2315
+ 10,
2316
+ 148,
2317
+ 118
2318
+ ],
2319
+ [
2320
+ 3,
2321
+ 73,
2322
+ 45,
2323
+ 23,
2324
+ 74,
2325
+ 46
2326
+ ],
2327
+ [
2328
+ 4,
2329
+ 54,
2330
+ 24,
2331
+ 31,
2332
+ 55,
2333
+ 25
2334
+ ],
2335
+ [
2336
+ 11,
2337
+ 45,
2338
+ 15,
2339
+ 31,
2340
+ 46,
2341
+ 16
2342
+ ],
2343
+ [
2344
+ 7,
2345
+ 146,
2346
+ 116,
2347
+ 7,
2348
+ 147,
2349
+ 117
2350
+ ],
2351
+ [
2352
+ 21,
2353
+ 73,
2354
+ 45,
2355
+ 7,
2356
+ 74,
2357
+ 46
2358
+ ],
2359
+ [
2360
+ 1,
2361
+ 53,
2362
+ 23,
2363
+ 37,
2364
+ 54,
2365
+ 24
2366
+ ],
2367
+ [
2368
+ 19,
2369
+ 45,
2370
+ 15,
2371
+ 26,
2372
+ 46,
2373
+ 16
2374
+ ],
2375
+ [
2376
+ 5,
2377
+ 145,
2378
+ 115,
2379
+ 10,
2380
+ 146,
2381
+ 116
2382
+ ],
2383
+ [
2384
+ 19,
2385
+ 75,
2386
+ 47,
2387
+ 10,
2388
+ 76,
2389
+ 48
2390
+ ],
2391
+ [
2392
+ 15,
2393
+ 54,
2394
+ 24,
2395
+ 25,
2396
+ 55,
2397
+ 25
2398
+ ],
2399
+ [
2400
+ 23,
2401
+ 45,
2402
+ 15,
2403
+ 25,
2404
+ 46,
2405
+ 16
2406
+ ],
2407
+ [
2408
+ 13,
2409
+ 145,
2410
+ 115,
2411
+ 3,
2412
+ 146,
2413
+ 116
2414
+ ],
2415
+ [
2416
+ 2,
2417
+ 74,
2418
+ 46,
2419
+ 29,
2420
+ 75,
2421
+ 47
2422
+ ],
2423
+ [
2424
+ 42,
2425
+ 54,
2426
+ 24,
2427
+ 1,
2428
+ 55,
2429
+ 25
2430
+ ],
2431
+ [
2432
+ 23,
2433
+ 45,
2434
+ 15,
2435
+ 28,
2436
+ 46,
2437
+ 16
2438
+ ],
2439
+ [
2440
+ 17,
2441
+ 145,
2442
+ 115
2443
+ ],
2444
+ [
2445
+ 10,
2446
+ 74,
2447
+ 46,
2448
+ 23,
2449
+ 75,
2450
+ 47
2451
+ ],
2452
+ [
2453
+ 10,
2454
+ 54,
2455
+ 24,
2456
+ 35,
2457
+ 55,
2458
+ 25
2459
+ ],
2460
+ [
2461
+ 19,
2462
+ 45,
2463
+ 15,
2464
+ 35,
2465
+ 46,
2466
+ 16
2467
+ ],
2468
+ [
2469
+ 17,
2470
+ 145,
2471
+ 115,
2472
+ 1,
2473
+ 146,
2474
+ 116
2475
+ ],
2476
+ [
2477
+ 14,
2478
+ 74,
2479
+ 46,
2480
+ 21,
2481
+ 75,
2482
+ 47
2483
+ ],
2484
+ [
2485
+ 29,
2486
+ 54,
2487
+ 24,
2488
+ 19,
2489
+ 55,
2490
+ 25
2491
+ ],
2492
+ [
2493
+ 11,
2494
+ 45,
2495
+ 15,
2496
+ 46,
2497
+ 46,
2498
+ 16
2499
+ ],
2500
+ [
2501
+ 13,
2502
+ 145,
2503
+ 115,
2504
+ 6,
2505
+ 146,
2506
+ 116
2507
+ ],
2508
+ [
2509
+ 14,
2510
+ 74,
2511
+ 46,
2512
+ 23,
2513
+ 75,
2514
+ 47
2515
+ ],
2516
+ [
2517
+ 44,
2518
+ 54,
2519
+ 24,
2520
+ 7,
2521
+ 55,
2522
+ 25
2523
+ ],
2524
+ [
2525
+ 59,
2526
+ 46,
2527
+ 16,
2528
+ 1,
2529
+ 47,
2530
+ 17
2531
+ ],
2532
+ [
2533
+ 12,
2534
+ 151,
2535
+ 121,
2536
+ 7,
2537
+ 152,
2538
+ 122
2539
+ ],
2540
+ [
2541
+ 12,
2542
+ 75,
2543
+ 47,
2544
+ 26,
2545
+ 76,
2546
+ 48
2547
+ ],
2548
+ [
2549
+ 39,
2550
+ 54,
2551
+ 24,
2552
+ 14,
2553
+ 55,
2554
+ 25
2555
+ ],
2556
+ [
2557
+ 22,
2558
+ 45,
2559
+ 15,
2560
+ 41,
2561
+ 46,
2562
+ 16
2563
+ ],
2564
+ [
2565
+ 6,
2566
+ 151,
2567
+ 121,
2568
+ 14,
2569
+ 152,
2570
+ 122
2571
+ ],
2572
+ [
2573
+ 6,
2574
+ 75,
2575
+ 47,
2576
+ 34,
2577
+ 76,
2578
+ 48
2579
+ ],
2580
+ [
2581
+ 46,
2582
+ 54,
2583
+ 24,
2584
+ 10,
2585
+ 55,
2586
+ 25
2587
+ ],
2588
+ [
2589
+ 2,
2590
+ 45,
2591
+ 15,
2592
+ 64,
2593
+ 46,
2594
+ 16
2595
+ ],
2596
+ [
2597
+ 17,
2598
+ 152,
2599
+ 122,
2600
+ 4,
2601
+ 153,
2602
+ 123
2603
+ ],
2604
+ [
2605
+ 29,
2606
+ 74,
2607
+ 46,
2608
+ 14,
2609
+ 75,
2610
+ 47
2611
+ ],
2612
+ [
2613
+ 49,
2614
+ 54,
2615
+ 24,
2616
+ 10,
2617
+ 55,
2618
+ 25
2619
+ ],
2620
+ [
2621
+ 24,
2622
+ 45,
2623
+ 15,
2624
+ 46,
2625
+ 46,
2626
+ 16
2627
+ ],
2628
+ [
2629
+ 4,
2630
+ 152,
2631
+ 122,
2632
+ 18,
2633
+ 153,
2634
+ 123
2635
+ ],
2636
+ [
2637
+ 13,
2638
+ 74,
2639
+ 46,
2640
+ 32,
2641
+ 75,
2642
+ 47
2643
+ ],
2644
+ [
2645
+ 48,
2646
+ 54,
2647
+ 24,
2648
+ 14,
2649
+ 55,
2650
+ 25
2651
+ ],
2652
+ [
2653
+ 42,
2654
+ 45,
2655
+ 15,
2656
+ 32,
2657
+ 46,
2658
+ 16
2659
+ ],
2660
+ [
2661
+ 20,
2662
+ 147,
2663
+ 117,
2664
+ 4,
2665
+ 148,
2666
+ 118
2667
+ ],
2668
+ [
2669
+ 40,
2670
+ 75,
2671
+ 47,
2672
+ 7,
2673
+ 76,
2674
+ 48
2675
+ ],
2676
+ [
2677
+ 43,
2678
+ 54,
2679
+ 24,
2680
+ 22,
2681
+ 55,
2682
+ 25
2683
+ ],
2684
+ [
2685
+ 10,
2686
+ 45,
2687
+ 15,
2688
+ 67,
2689
+ 46,
2690
+ 16
2691
+ ],
2692
+ [
2693
+ 19,
2694
+ 148,
2695
+ 118,
2696
+ 6,
2697
+ 149,
2698
+ 119
2699
+ ],
2700
+ [
2701
+ 18,
2702
+ 75,
2703
+ 47,
2704
+ 31,
2705
+ 76,
2706
+ 48
2707
+ ],
2708
+ [
2709
+ 34,
2710
+ 54,
2711
+ 24,
2712
+ 34,
2713
+ 55,
2714
+ 25
2715
+ ],
2716
+ [
2717
+ 20,
2718
+ 45,
2719
+ 15,
2720
+ 61,
2721
+ 46,
2722
+ 16
2723
+ ]
2724
+ ];
2725
+ const qrRSBlock = function(totalCount, dataCount) {
2726
+ const _this = {};
2727
+ _this.totalCount = totalCount;
2728
+ _this.dataCount = dataCount;
2729
+ return _this;
2730
+ };
2731
+ const _this = {};
2732
+ const getRsBlockTable = function(typeNumber, errorCorrectionLevel) {
2733
+ switch (errorCorrectionLevel) {
2734
+ case QRErrorCorrectionLevel.L: return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
2735
+ case QRErrorCorrectionLevel.M: return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
2736
+ case QRErrorCorrectionLevel.Q: return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
2737
+ case QRErrorCorrectionLevel.H: return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
2738
+ default: return;
2739
+ }
2740
+ };
2741
+ _this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {
2742
+ const rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);
2743
+ if (typeof rsBlock == "undefined") throw "bad rs block @ typeNumber:" + typeNumber + "/errorCorrectionLevel:" + errorCorrectionLevel;
2744
+ const length = rsBlock.length / 3;
2745
+ const list = [];
2746
+ for (let i = 0; i < length; i += 1) {
2747
+ const count = rsBlock[i * 3 + 0];
2748
+ const totalCount = rsBlock[i * 3 + 1];
2749
+ const dataCount = rsBlock[i * 3 + 2];
2750
+ for (let j = 0; j < count; j += 1) list.push(qrRSBlock(totalCount, dataCount));
2751
+ }
2752
+ return list;
2753
+ };
2754
+ return _this;
2755
+ }();
2756
+ const qrBitBuffer = function() {
2757
+ const _buffer = [];
2758
+ let _length = 0;
2759
+ const _this = {};
2760
+ _this.getBuffer = function() {
2761
+ return _buffer;
2762
+ };
2763
+ _this.getAt = function(index) {
2764
+ const bufIndex = Math.floor(index / 8);
2765
+ return (_buffer[bufIndex] >>> 7 - index % 8 & 1) == 1;
2766
+ };
2767
+ _this.put = function(num, length) {
2768
+ for (let i = 0; i < length; i += 1) _this.putBit((num >>> length - i - 1 & 1) == 1);
2769
+ };
2770
+ _this.getLengthInBits = function() {
2771
+ return _length;
2772
+ };
2773
+ _this.putBit = function(bit) {
2774
+ const bufIndex = Math.floor(_length / 8);
2775
+ if (_buffer.length <= bufIndex) _buffer.push(0);
2776
+ if (bit) _buffer[bufIndex] |= 128 >>> _length % 8;
2777
+ _length += 1;
2778
+ };
2779
+ return _this;
2780
+ };
2781
+ const qrNumber = function(data) {
2782
+ const _mode = QRMode.MODE_NUMBER;
2783
+ const _data = data;
2784
+ const _this = {};
2785
+ _this.getMode = function() {
2786
+ return _mode;
2787
+ };
2788
+ _this.getLength = function(buffer) {
2789
+ return _data.length;
2790
+ };
2791
+ _this.write = function(buffer) {
2792
+ const data = _data;
2793
+ let i = 0;
2794
+ while (i + 2 < data.length) {
2795
+ buffer.put(strToNum(data.substring(i, i + 3)), 10);
2796
+ i += 3;
2797
+ }
2798
+ if (i < data.length) {
2799
+ if (data.length - i == 1) buffer.put(strToNum(data.substring(i, i + 1)), 4);
2800
+ else if (data.length - i == 2) buffer.put(strToNum(data.substring(i, i + 2)), 7);
2801
+ }
2802
+ };
2803
+ const strToNum = function(s) {
2804
+ let num = 0;
2805
+ for (let i = 0; i < s.length; i += 1) num = num * 10 + chatToNum(s.charAt(i));
2806
+ return num;
2807
+ };
2808
+ const chatToNum = function(c) {
2809
+ if ("0" <= c && c <= "9") return c.charCodeAt(0) - "0".charCodeAt(0);
2810
+ throw "illegal char :" + c;
2811
+ };
2812
+ return _this;
2813
+ };
2814
+ const qrAlphaNum = function(data) {
2815
+ const _mode = QRMode.MODE_ALPHA_NUM;
2816
+ const _data = data;
2817
+ const _this = {};
2818
+ _this.getMode = function() {
2819
+ return _mode;
2820
+ };
2821
+ _this.getLength = function(buffer) {
2822
+ return _data.length;
2823
+ };
2824
+ _this.write = function(buffer) {
2825
+ const s = _data;
2826
+ let i = 0;
2827
+ while (i + 1 < s.length) {
2828
+ buffer.put(getCode(s.charAt(i)) * 45 + getCode(s.charAt(i + 1)), 11);
2829
+ i += 2;
2830
+ }
2831
+ if (i < s.length) buffer.put(getCode(s.charAt(i)), 6);
2832
+ };
2833
+ const getCode = function(c) {
2834
+ if ("0" <= c && c <= "9") return c.charCodeAt(0) - "0".charCodeAt(0);
2835
+ else if ("A" <= c && c <= "Z") return c.charCodeAt(0) - "A".charCodeAt(0) + 10;
2836
+ else switch (c) {
2837
+ case " ": return 36;
2838
+ case "$": return 37;
2839
+ case "%": return 38;
2840
+ case "*": return 39;
2841
+ case "+": return 40;
2842
+ case "-": return 41;
2843
+ case ".": return 42;
2844
+ case "/": return 43;
2845
+ case ":": return 44;
2846
+ default: throw "illegal char :" + c;
2847
+ }
2848
+ };
2849
+ return _this;
2850
+ };
2851
+ const qr8BitByte = function(data) {
2852
+ const _mode = QRMode.MODE_8BIT_BYTE;
2853
+ const _bytes = qrcode.stringToBytes(data);
2854
+ const _this = {};
2855
+ _this.getMode = function() {
2856
+ return _mode;
2857
+ };
2858
+ _this.getLength = function(buffer) {
2859
+ return _bytes.length;
2860
+ };
2861
+ _this.write = function(buffer) {
2862
+ for (let i = 0; i < _bytes.length; i += 1) buffer.put(_bytes[i], 8);
2863
+ };
2864
+ return _this;
2865
+ };
2866
+ const qrKanji = function(data) {
2867
+ const _mode = QRMode.MODE_KANJI;
2868
+ const stringToBytes = qrcode.stringToBytes;
2869
+ (function(c, code) {
2870
+ const test = stringToBytes(c);
2871
+ if (test.length != 2 || (test[0] << 8 | test[1]) != code) throw "sjis not supported.";
2872
+ })("友", 38726);
2873
+ const _bytes = stringToBytes(data);
2874
+ const _this = {};
2875
+ _this.getMode = function() {
2876
+ return _mode;
2877
+ };
2878
+ _this.getLength = function(buffer) {
2879
+ return ~~(_bytes.length / 2);
2880
+ };
2881
+ _this.write = function(buffer) {
2882
+ const data = _bytes;
2883
+ let i = 0;
2884
+ while (i + 1 < data.length) {
2885
+ let c = (255 & data[i]) << 8 | 255 & data[i + 1];
2886
+ if (33088 <= c && c <= 40956) c -= 33088;
2887
+ else if (57408 <= c && c <= 60351) c -= 49472;
2888
+ else throw "illegal char at " + (i + 1) + "/" + c;
2889
+ c = (c >>> 8 & 255) * 192 + (c & 255);
2890
+ buffer.put(c, 13);
2891
+ i += 2;
2892
+ }
2893
+ if (i < data.length) throw "illegal char at " + (i + 1);
2894
+ };
2895
+ return _this;
2896
+ };
2897
+ const byteArrayOutputStream = function() {
2898
+ const _bytes = [];
2899
+ const _this = {};
2900
+ _this.writeByte = function(b) {
2901
+ _bytes.push(b & 255);
2902
+ };
2903
+ _this.writeShort = function(i) {
2904
+ _this.writeByte(i);
2905
+ _this.writeByte(i >>> 8);
2906
+ };
2907
+ _this.writeBytes = function(b, off, len) {
2908
+ off = off || 0;
2909
+ len = len || b.length;
2910
+ for (let i = 0; i < len; i += 1) _this.writeByte(b[i + off]);
2911
+ };
2912
+ _this.writeString = function(s) {
2913
+ for (let i = 0; i < s.length; i += 1) _this.writeByte(s.charCodeAt(i));
2914
+ };
2915
+ _this.toByteArray = function() {
2916
+ return _bytes;
2917
+ };
2918
+ _this.toString = function() {
2919
+ let s = "";
2920
+ s += "[";
2921
+ for (let i = 0; i < _bytes.length; i += 1) {
2922
+ if (i > 0) s += ",";
2923
+ s += _bytes[i];
2924
+ }
2925
+ s += "]";
2926
+ return s;
2927
+ };
2928
+ return _this;
2929
+ };
2930
+ const base64EncodeOutputStream = function() {
2931
+ let _buffer = 0;
2932
+ let _buflen = 0;
2933
+ let _length = 0;
2934
+ let _base64 = "";
2935
+ const _this = {};
2936
+ const writeEncoded = function(b) {
2937
+ _base64 += String.fromCharCode(encode(b & 63));
2938
+ };
2939
+ const encode = function(n) {
2940
+ if (n < 0) throw "n:" + n;
2941
+ else if (n < 26) return 65 + n;
2942
+ else if (n < 52) return 97 + (n - 26);
2943
+ else if (n < 62) return 48 + (n - 52);
2944
+ else if (n == 62) return 43;
2945
+ else if (n == 63) return 47;
2946
+ else throw "n:" + n;
2947
+ };
2948
+ _this.writeByte = function(n) {
2949
+ _buffer = _buffer << 8 | n & 255;
2950
+ _buflen += 8;
2951
+ _length += 1;
2952
+ while (_buflen >= 6) {
2953
+ writeEncoded(_buffer >>> _buflen - 6);
2954
+ _buflen -= 6;
2955
+ }
2956
+ };
2957
+ _this.flush = function() {
2958
+ if (_buflen > 0) {
2959
+ writeEncoded(_buffer << 6 - _buflen);
2960
+ _buffer = 0;
2961
+ _buflen = 0;
2962
+ }
2963
+ if (_length % 3 != 0) {
2964
+ const padlen = 3 - _length % 3;
2965
+ for (let i = 0; i < padlen; i += 1) _base64 += "=";
2966
+ }
2967
+ };
2968
+ _this.toString = function() {
2969
+ return _base64;
2970
+ };
2971
+ return _this;
2972
+ };
2973
+ const base64DecodeInputStream = function(str) {
2974
+ const _str = str;
2975
+ let _pos = 0;
2976
+ let _buffer = 0;
2977
+ let _buflen = 0;
2978
+ const _this = {};
2979
+ _this.read = function() {
2980
+ while (_buflen < 8) {
2981
+ if (_pos >= _str.length) {
2982
+ if (_buflen == 0) return -1;
2983
+ throw "unexpected end of file./" + _buflen;
2984
+ }
2985
+ const c = _str.charAt(_pos);
2986
+ _pos += 1;
2987
+ if (c == "=") {
2988
+ _buflen = 0;
2989
+ return -1;
2990
+ } else if (c.match(/^\s$/)) continue;
2991
+ _buffer = _buffer << 6 | decode(c.charCodeAt(0));
2992
+ _buflen += 6;
2993
+ }
2994
+ const n = _buffer >>> _buflen - 8 & 255;
2995
+ _buflen -= 8;
2996
+ return n;
2997
+ };
2998
+ const decode = function(c) {
2999
+ if (65 <= c && c <= 90) return c - 65;
3000
+ else if (97 <= c && c <= 122) return c - 97 + 26;
3001
+ else if (48 <= c && c <= 57) return c - 48 + 52;
3002
+ else if (c == 43) return 62;
3003
+ else if (c == 47) return 63;
3004
+ else throw "c:" + c;
3005
+ };
3006
+ return _this;
3007
+ };
3008
+ const gifImage = function(width, height) {
3009
+ const _width = width;
3010
+ const _height = height;
3011
+ const _data = new Array(width * height);
3012
+ const _this = {};
3013
+ _this.setPixel = function(x, y, pixel) {
3014
+ _data[y * _width + x] = pixel;
3015
+ };
3016
+ _this.write = function(out) {
3017
+ out.writeString("GIF87a");
3018
+ out.writeShort(_width);
3019
+ out.writeShort(_height);
3020
+ out.writeByte(128);
3021
+ out.writeByte(0);
3022
+ out.writeByte(0);
3023
+ out.writeByte(0);
3024
+ out.writeByte(0);
3025
+ out.writeByte(0);
3026
+ out.writeByte(255);
3027
+ out.writeByte(255);
3028
+ out.writeByte(255);
3029
+ out.writeString(",");
3030
+ out.writeShort(0);
3031
+ out.writeShort(0);
3032
+ out.writeShort(_width);
3033
+ out.writeShort(_height);
3034
+ out.writeByte(0);
3035
+ const lzwMinCodeSize = 2;
3036
+ const raster = getLZWRaster(lzwMinCodeSize);
3037
+ out.writeByte(lzwMinCodeSize);
3038
+ let offset = 0;
3039
+ while (raster.length - offset > 255) {
3040
+ out.writeByte(255);
3041
+ out.writeBytes(raster, offset, 255);
3042
+ offset += 255;
3043
+ }
3044
+ out.writeByte(raster.length - offset);
3045
+ out.writeBytes(raster, offset, raster.length - offset);
3046
+ out.writeByte(0);
3047
+ out.writeString(";");
3048
+ };
3049
+ const bitOutputStream = function(out) {
3050
+ const _out = out;
3051
+ let _bitLength = 0;
3052
+ let _bitBuffer = 0;
3053
+ const _this = {};
3054
+ _this.write = function(data, length) {
3055
+ if (data >>> length != 0) throw "length over";
3056
+ while (_bitLength + length >= 8) {
3057
+ _out.writeByte(255 & (data << _bitLength | _bitBuffer));
3058
+ length -= 8 - _bitLength;
3059
+ data >>>= 8 - _bitLength;
3060
+ _bitBuffer = 0;
3061
+ _bitLength = 0;
3062
+ }
3063
+ _bitBuffer = data << _bitLength | _bitBuffer;
3064
+ _bitLength = _bitLength + length;
3065
+ };
3066
+ _this.flush = function() {
3067
+ if (_bitLength > 0) _out.writeByte(_bitBuffer);
3068
+ };
3069
+ return _this;
3070
+ };
3071
+ const getLZWRaster = function(lzwMinCodeSize) {
3072
+ const clearCode = 1 << lzwMinCodeSize;
3073
+ const endCode = (1 << lzwMinCodeSize) + 1;
3074
+ let bitLength = lzwMinCodeSize + 1;
3075
+ const table = lzwTable();
3076
+ for (let i = 0; i < clearCode; i += 1) table.add(String.fromCharCode(i));
3077
+ table.add(String.fromCharCode(clearCode));
3078
+ table.add(String.fromCharCode(endCode));
3079
+ const byteOut = byteArrayOutputStream();
3080
+ const bitOut = bitOutputStream(byteOut);
3081
+ bitOut.write(clearCode, bitLength);
3082
+ let dataIndex = 0;
3083
+ let s = String.fromCharCode(_data[dataIndex]);
3084
+ dataIndex += 1;
3085
+ while (dataIndex < _data.length) {
3086
+ const c = String.fromCharCode(_data[dataIndex]);
3087
+ dataIndex += 1;
3088
+ if (table.contains(s + c)) s = s + c;
3089
+ else {
3090
+ bitOut.write(table.indexOf(s), bitLength);
3091
+ if (table.size() < 4095) {
3092
+ if (table.size() == 1 << bitLength) bitLength += 1;
3093
+ table.add(s + c);
3094
+ }
3095
+ s = c;
3096
+ }
3097
+ }
3098
+ bitOut.write(table.indexOf(s), bitLength);
3099
+ bitOut.write(endCode, bitLength);
3100
+ bitOut.flush();
3101
+ return byteOut.toByteArray();
3102
+ };
3103
+ const lzwTable = function() {
3104
+ const _map = {};
3105
+ let _size = 0;
3106
+ const _this = {};
3107
+ _this.add = function(key) {
3108
+ if (_this.contains(key)) throw "dup key:" + key;
3109
+ _map[key] = _size;
3110
+ _size += 1;
3111
+ };
3112
+ _this.size = function() {
3113
+ return _size;
3114
+ };
3115
+ _this.indexOf = function(key) {
3116
+ return _map[key];
3117
+ };
3118
+ _this.contains = function(key) {
3119
+ return typeof _map[key] != "undefined";
3120
+ };
3121
+ return _this;
3122
+ };
3123
+ return _this;
3124
+ };
3125
+ const createDataURL = function(width, height, getPixel) {
3126
+ const gif = gifImage(width, height);
3127
+ for (let y = 0; y < height; y += 1) for (let x = 0; x < width; x += 1) gif.setPixel(x, y, getPixel(x, y));
3128
+ const b = byteArrayOutputStream();
3129
+ gif.write(b);
3130
+ const base64 = base64EncodeOutputStream();
3131
+ const bytes = b.toByteArray();
3132
+ for (let i = 0; i < bytes.length; i += 1) base64.writeByte(bytes[i]);
3133
+ base64.flush();
3134
+ return "data:image/gif;base64," + base64;
3135
+ };
3136
+ qrcode.stringToBytes;
3137
+ //#endregion
607
3138
  //#region src/client/accounts-api.ts
608
3139
  /** wire 账号 → 本地编辑行 */
609
3140
  function accountDraftFromWire(a) {
@@ -656,6 +3187,22 @@ window.__ModuleLoader__.load({
656
3187
  });
657
3188
  return `otpauth://totp/${encodeURIComponent(label)}?${params.toString()}`;
658
3189
  }
3190
+ /**
3191
+ * 生成 otpauth URI 的二维码 SVG(v1.24.6:配置 TOTP 时**扫码绑定**——
3192
+ * Authenticator 扫二维码即录入 secret,替代手动输入)。
3193
+ * typeNumber 0 = 自动选最小版本;纠错 M(平衡)。scalable SVG → CSS 控制显示尺寸。
3194
+ */
3195
+ function totpQrSvg(secret, label, issuer = "Serenity Home") {
3196
+ const uri = otpauthUriClient(secret, label, issuer);
3197
+ const qr = qrcode(0, "M");
3198
+ qr.addData(uri);
3199
+ qr.make();
3200
+ return qr.createSvgTag({
3201
+ cellSize: 4,
3202
+ margin: 2,
3203
+ scalable: true
3204
+ });
3205
+ }
659
3206
  /** 本地编辑行 → wire 账号(提交时;pass 字段携带) */
660
3207
  function accountToWire(d) {
661
3208
  return {
@@ -730,7 +3277,7 @@ window.__ModuleLoader__.load({
730
3277
  }
731
3278
  //#endregion
732
3279
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/AccountsEditor
733
- const css$2 = "/* AccountsEditor — DSH 设置面板「外部访问」区块(v1.22)\n * 与 SettingsSection ss-* 同设计语言:--dsw-alias-* 语义 token,明暗自适应。 */\n\n.ae-root {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n font-size: 13px;\n}\n\n.ae-warn {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n word-break: break-word;\n}\n\n.ae-block {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.ae-title {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.ae-desc {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n.ae-note {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* ── 监听设置 / 白名单输入行 ── */\n\n.ae-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.ae-label {\n flex: none;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.ae-input {\n flex: 1;\n min-width: 0;\n padding: 6px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n outline: none;\n}\n\n.ae-input:focus {\n border-color: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n}\n\n.ae-input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.ae-input.ae-port {\n flex: none;\n width: 76px;\n}\n\n/* ── 账号列表 ── */\n\n.ae-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-head {\n display: flex;\n gap: 8px;\n font-size: 11px;\n font-weight: 500;\n color: var(--dsw-alias-label-dimmed);\n padding: 0 2px;\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n\n.ae-item {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 6px 2px;\n}\n\n.ae-colUser { flex: 1.2; }\n.ae-colPass { flex: 1.6; }\n.ae-colTotp { flex: 2.2; min-width: 0; }\n.ae-colOp { flex: none; width: 48px; }\n\n/* ── v1.22.4 TOTP 第二因素 ── */\n\n.ae-totpBtn {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.ae-totpBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-totpPending {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n min-width: 0;\n}\n\n.ae-totpSecret {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n background: var(--dsw-alias-surface-raised, rgba(0, 0, 0, 0.25));\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 4px;\n padding: 2px 6px;\n color: var(--dsw-alias-label-secondary);\n word-break: break-all;\n}\n\n.ae-totpUri {\n font-size: 11px;\n color: var(--dsw-alias-accent, #3b82f6);\n text-decoration: none;\n}\n\n.ae-totpUri:hover {\n text-decoration: underline;\n}\n\n.ae-totpConfirm {\n max-width: 120px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n letter-spacing: 0.2em;\n}\n\n.ae-totpBadge {\n font-size: 12px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n}\n\n.ae-totpClear {\n display: flex;\n gap: 6px;\n align-items: center;\n}\n\n.ae-check {\n display: flex;\n gap: 8px;\n align-items: center;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n margin-top: 10px;\n cursor: pointer;\n}\n\n.ae-check input {\n accent-color: var(--dsw-alias-accent, #3b82f6);\n}\n\n.ae-del {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-del:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.12));\n}\n\n.ae-add {\n align-self: flex-start;\n padding: 5px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-add:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-wsSelect {\n margin-top: 8px;\n max-width: 100%;\n cursor: pointer;\n}\n\n/* ── 工作区白名单 chips ── */\n\n.ae-wsList {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.ae-wsChip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.14));\n}\n\n.ae-wsPath {\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n}\n\n.ae-wsDel {\n flex: none;\n width: 18px;\n height: 18px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--dsw-alias-label-dimmed);\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n}\n\n.ae-wsDel:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.18));\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n/* ── 错误 / 操作区 ── */\n\n.ae-error {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n word-break: break-word;\n}\n\n.ae-actions {\n display: flex;\n justify-content: flex-end;\n padding-top: 4px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n.ae-save {\n padding: 7px 24px;\n border: 0;\n border-radius: 8px;\n background: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n color: var(--dsw-alias-button-primary-fg, #fff);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.ae-save:hover:not(:disabled) {\n filter: brightness(1.08);\n}\n\n.ae-save:disabled {\n opacity: 0.6;\n cursor: default;\n}\n";
3280
+ const css$2 = "/* AccountsEditor — DSH 设置面板「外部访问」区块(v1.22)\n * 与 SettingsSection ss-* 同设计语言:--dsw-alias-* 语义 token,明暗自适应。 */\n\n.ae-root {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n font-size: 13px;\n}\n\n.ae-warn {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n word-break: break-word;\n}\n\n.ae-block {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.ae-title {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.ae-desc {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n.ae-note {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* ── 监听设置 / 白名单输入行 ── */\n\n.ae-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.ae-label {\n flex: none;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.ae-input {\n flex: 1;\n min-width: 0;\n padding: 6px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n outline: none;\n}\n\n.ae-input:focus {\n border-color: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n}\n\n.ae-input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.ae-input.ae-port {\n flex: none;\n width: 76px;\n}\n\n/* ── 账号列表 ── */\n\n.ae-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-head {\n display: flex;\n gap: 8px;\n font-size: 11px;\n font-weight: 500;\n color: var(--dsw-alias-label-dimmed);\n padding: 0 2px;\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n\n.ae-item {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 6px 2px;\n}\n\n.ae-colUser { flex: 1.2; }\n.ae-colPass { flex: 1.6; }\n.ae-colTotp { flex: 2.2; min-width: 0; }\n.ae-colOp { flex: none; width: 48px; }\n\n/* ── v1.22.4 TOTP 第二因素 ── */\n\n.ae-totpBtn {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.ae-totpBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-totpPending {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n min-width: 0;\n}\n\n/* v1.24.6:TOTP 绑定二维码(扫码即录入;scalable SVG,白底保证扫码识别) */\n.ae-totpQr {\n flex-basis: 100%;\n display: inline-flex;\n justify-content: center;\n padding: 8px;\n background: #fff;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n}\n\n.ae-totpQr svg {\n width: 132px;\n height: 132px;\n display: block;\n}\n\n.ae-totpSecret {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n background: var(--dsw-alias-surface-raised, rgba(0, 0, 0, 0.25));\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 4px;\n padding: 2px 6px;\n color: var(--dsw-alias-label-secondary);\n word-break: break-all;\n}\n\n.ae-totpUri {\n font-size: 11px;\n color: var(--dsw-alias-accent, #3b82f6);\n text-decoration: none;\n}\n\n.ae-totpUri:hover {\n text-decoration: underline;\n}\n\n.ae-totpConfirm {\n max-width: 120px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n letter-spacing: 0.2em;\n}\n\n.ae-totpBadge {\n font-size: 12px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n}\n\n.ae-totpClear {\n display: flex;\n gap: 6px;\n align-items: center;\n}\n\n.ae-check {\n display: flex;\n gap: 8px;\n align-items: center;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n margin-top: 10px;\n cursor: pointer;\n}\n\n.ae-check input {\n accent-color: var(--dsw-alias-accent, #3b82f6);\n}\n\n.ae-del {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-del:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.12));\n}\n\n.ae-add {\n align-self: flex-start;\n padding: 5px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-add:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-wsSelect {\n margin-top: 8px;\n max-width: 100%;\n cursor: pointer;\n}\n\n/* ── 工作区白名单 chips ── */\n\n.ae-wsList {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.ae-wsChip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.14));\n}\n\n.ae-wsPath {\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n}\n\n.ae-wsDel {\n flex: none;\n width: 18px;\n height: 18px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--dsw-alias-label-dimmed);\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n}\n\n.ae-wsDel:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.18));\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n/* ── 错误 / 操作区 ── */\n\n.ae-error {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n word-break: break-word;\n}\n\n.ae-actions {\n display: flex;\n justify-content: flex-end;\n padding-top: 4px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n.ae-save {\n padding: 7px 24px;\n border: 0;\n border-radius: 8px;\n background: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n color: var(--dsw-alias-button-primary-fg, #fff);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.ae-save:hover:not(:disabled) {\n filter: brightness(1.08);\n}\n\n.ae-save:disabled {\n opacity: 0.6;\n cursor: default;\n}\n";
734
3281
  if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"AccountsEditor\"]") === null) {
735
3282
  const tag = document.createElement("style");
736
3283
  tag.setAttribute("data-sp-css", "AccountsEditor");
@@ -947,7 +3494,7 @@ window.__ModuleLoader__.load({
947
3494
  type: "checkbox",
948
3495
  checked: totpEnabled,
949
3496
  onChange: (e) => setTotpEnabled(e.target.checked)
950
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "启用 Authenticator 第二因素(关闭时 TOTP 完全禁用;开启后可对账号绑定验证器,登录需输入 6 位码)" })]
3497
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "启用 Authenticator 登录(v1.24.6 二选一:开启后绑定验证器的账号可用密码 或 6 位验证码任一登录;关闭时 TOTP 完全禁用,仅密码)" })]
951
3498
  })
952
3499
  ]
953
3500
  }),
@@ -998,9 +3545,14 @@ window.__ModuleLoader__.load({
998
3545
  children: d.totpState === "pending" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
999
3546
  className: "ae-totpPending",
1000
3547
  children: [
3548
+ d.totpSecret !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3549
+ className: "ae-totpQr",
3550
+ title: "用 Authenticator(Google Authenticator / 1Password / Aegis)扫码绑定",
3551
+ dangerouslySetInnerHTML: { __html: totpQrSvg(d.totpSecret, `${d.user.trim() || "user"}@serenity`) }
3552
+ }),
1001
3553
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
1002
3554
  className: "ae-totpSecret",
1003
- title: "录入到 Authenticator(Google Authenticator / 1Password / Aegis)",
3555
+ title: "或手动录入到 Authenticator",
1004
3556
  children: d.totpSecret
1005
3557
  }),
1006
3558
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {