* 繁体字识别-字典匹配 * @see 参考 https://bbs.tampermonkey.net.cn/thread-2303-1-1.html
(doc: Document = document)
| 992 | * @see 参考 https://bbs.tampermonkey.net.cn/thread-2303-1-1.html |
| 993 | */ |
| 994 | async function mappingRecognize(doc: Document = document) { |
| 995 | let typrMapping = Object.create({}); |
| 996 | try { |
| 997 | // @ts-ignore |
| 998 | top.typrMapping = top.typrMapping || (await loadTyprMapping()); |
| 999 | // @ts-ignore |
| 1000 | typrMapping = top.typrMapping; |
| 1001 | } catch { |
| 1002 | // 超星考试可能嵌套其他平台中,所以会存在跨域,这里需要处理一下跨域情况,如果是跨域直接在当前页面加载字库 |
| 1003 | typrMapping = await loadTyprMapping(); |
| 1004 | } |
| 1005 | |
| 1006 | /** 判断是否有繁体字 */ |
| 1007 | const fontFaceEl = Array.from(doc.head.querySelectorAll('style')).find((style) => |
| 1008 | style.textContent?.includes('font-cxsecret') |
| 1009 | ); |
| 1010 | |
| 1011 | const base64ToUint8Array = (base64: string) => { |
| 1012 | const data = window.atob(base64); |
| 1013 | const buffer = new Uint8Array(data.length); |
| 1014 | for (let i = 0; i < data.length; ++i) { |
| 1015 | buffer[i] = data.charCodeAt(i); |
| 1016 | } |
| 1017 | return buffer; |
| 1018 | }; |
| 1019 | |
| 1020 | const fontMap = typrMapping; |
| 1021 | if (fontFaceEl && Object.keys(fontMap).length > 0) { |
| 1022 | // 解析font-cxsecret字体 |
| 1023 | const font = fontFaceEl.textContent?.match(/base64,([\w\W]+?)'/)?.[1]; |
| 1024 | |
| 1025 | if (font) { |
| 1026 | $console.log('正在识别繁体字'); |
| 1027 | |
| 1028 | const code = Typr.parse(base64ToUint8Array(font)); |
| 1029 | |
| 1030 | // 匹配解密字体 |
| 1031 | const match: any = {}; |
| 1032 | for (let i = 19968; i < 40870; i++) { |
| 1033 | // 中文[19968, 40869] |
| 1034 | const Glyph = Typr.U.codeToGlyph(code, i); |
| 1035 | if (!Glyph) continue; |
| 1036 | const path = Typr.U.glyphToPath(code, Glyph); |
| 1037 | const hex = md5(JSON.stringify(path)).slice(24); // 8位即可区分 |
| 1038 | match[i.toString()] = fontMap[hex]; |
| 1039 | } |
| 1040 | const fonts = CXAnalyses.getSecretFont(doc); |
| 1041 | // 替换加密字体 |
| 1042 | fonts.forEach((el, index) => { |
| 1043 | let html = el.innerHTML; |
| 1044 | for (const key in match) { |
| 1045 | const word = String.fromCharCode(parseInt(key)); |
| 1046 | const value = String.fromCharCode(match[key]); |
| 1047 | |
| 1048 | // 如果相同,则不需要替换 |
| 1049 | if (word === value) { |
| 1050 | continue; |
| 1051 | } |
no test coverage detected