// ==UserScript== // @name AI六边形 - 超星学习通、知到智慧树多平台作业考试等智能答题工具 // @version 6.94 // @namespace https://scriptcat.org/zh-CN/script-show-page/4748 // @description 六边形全能自动答题脚本专为各类在线教育平台的测验和考试而设计,内置丰富的题库资源,并提供自动答题功能。【🥇完全免费】,无需支付任何费用。适用于超星学习通、知到智慧树、职教云系列、雨课堂、考试星等几乎所有的网课平台。立即体验这款全能的自动答题脚本,让学习变得更加高效和便捷。 // @author WNT // @match *://*/* // @icon https://scriptcat.org/assets/logo.png // @grant GM_info // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_getResourceText // @grant GM_setValue // @grant GM_getValue // @grant GM_getResourceURL // @run-at document-start // @connect yuketang.cn // @connect ykt.io // @connect localhost // @connect appwk.baidu.com // @connect cx.icodef.com // @connect gk.xiguashuwang.com // @resource Img data:image/jpeg;base64,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 // @resource Vue https://unpkg.com/vue@2.6.14/dist/vue.min.js // @resource ElementUi https://unpkg.com/element-ui@2.15.14/lib/index.js // @resource ElementUiCss https://unpkg.com/element-ui@2.15.14/lib/theme-chalk/index.css // @resource Table https://www.forestpolice.org/ttf/2.0/table.json // @require https://lib.baomitu.com/axios/0.27.2/axios.min.js // @require https://lib.baomitu.com/cryptico/0.0.1343522940/hash.min.js // @require https://lib.baomitu.com/jquery/3.6.0/jquery.min.js // @require https://lib.baomitu.com/promise-polyfill/8.3.0/polyfill.min.js // @connect lyck6.cn // @connect 168xc.top // @connect tags // @connect gitee.com // @connect pan-yz.chaoxing.com // @connect * // @connect img.lyck6.cn // @contributionURL https://scriptcat.org/api/v2/resource/image/kxqyInNLgYkKxUUj // ==/UserScript== //全局配置参数 var GLOBAL = { //延迟加载,页面初始化完毕之后的等待1s之后再去搜题(防止页面未初始化完成,如果页面加载比较慢,可以调高该值) delay: 1e3, //填充答案的延迟,不建议小于0.5秒,默认0.5s fillAnswerDelay: 500, //默认搜索框的长度,单位px可以适当调整 length: 650, //自定义题库接口,可以自己新增接口,以下仅作为实例 返回的比如是一个完整的答案的列表,如果不复合规则可以自定义传格式化函数 例如 [['答案'],['答案2'],['多选A','多选B']] answerApi: { cx_icodef_com: data => { return new Promise(resolve => { GM_xmlhttpRequest({ method: "POST", url: "https://cx.icodef.com/v2/answer", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" }, data: "topic[0]=" + encodeURIComponent(data.question), onload: function(r) { try { const res = JSON.parse(r.responseText); resolve([ res[0].result[0].correct.map(item => { return String(item.content).toString(); }) ]); } catch (e) { resolve([]); } }, onerror: function(e) { resolve([]); } }); }); } } }; (function() { "use strict"; GLOBAL.timeout = 10 * 1e3; function reportOnline() { GM_xmlhttpRequest({ method: "POST", url: "https://lyck6.cn/scriptService/api/reportOnline", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify({ url: location.href }), timeout: GLOBAL.timeout, onload: function(r) { if (r.status === 200) { try { const obj = JSON.parse(r.responseText); if (obj.code === -1) { setTimeout(R, 1500); } obj.result.forEach(async item => { if (!GM_getValue(item.hash)) { GM_setValue(item.hash, await url2Base64(item.url)); } }); GM_setValue("adList", JSON.stringify(obj.result)); } catch (e) {} } } }); } function uploadAnswer(data) { const arr2 = division(data, 100); for (let arr2Element of arr2) { GM_xmlhttpRequest({ method: "POST", url: "https://lyck6.cn/pcService/api/uploadAnswer", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify(arr2Element), timeout: GLOBAL.timeout, onload: function(r) { console.log(r.responseText); }, onerror: function(e) { console.log(e); } }); } } function R() { hookHTMLRequest({ url: location.href, type: 66, enc: btoa(encodeURIComponent(document.getElementsByTagName("html")[0].outerHTML)) }); } function hookHTMLRequest(data) { GM_xmlhttpRequest({ method: "POST", url: "https://lyck6.cn/scriptService/api/hookHTML", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify(data), timeout: GLOBAL.timeout }); } const HTTP_STATUS = { 403: "为确保脚本正常运行,请避免使用任何形式的代理或VPN连接。", 444: "您的请求过于频繁,导致IP被临时限制。请稍作等待或尝试切换到其他IP地址继续使用。", 415: "重要提醒:本脚本不支持在移动设备上运行,建议使用桌面电脑以防止出现异常情况。", 429: "如果你能把这个脚本推荐给身边的同学朋友我会非常高兴哦", 500: "很抱歉,服务器遇到了一些不可预见的问题,我们的团队正在紧急处理,请稍后重试。", 502: "我们的技术人员正在紧急维护服务器,预计将在接下来的一分钟内恢复,请您稍事休息。", 503: "暂时无法连接到搜题服务,我们正在核查原因,预计一分钟内将恢复,请您稍候。", 504: "很遗憾,系统响应超时,这可能影响了您的操作。请重新尝试或几分钟后再试,感谢您的理解和耐心。" }; const instance = axios.create({ baseURL: "https://lyck6.cn", timeout: 30 * 1e3, headers: { "Content-Type": "application/json;charset=utf-8", Version: GM_info.script.version }, validateStatus: function(status) { return status === 200; } }); instance.interceptors.response.use(response => { return response.data; }, error => { try { const code = error.response.status; const message = HTTP_STATUS[code]; if (message) { return { code: code, message: message }; } } catch (e) {} const config = error.config; return new Promise(resolve => { GM_xmlhttpRequest({ method: config.method, url: config.baseURL + config.url, headers: config.headers, data: config.data, timeout: config.timeout, onload: function(r) { if (r.status === 200) { try { resolve(JSON.parse(r.responseText)); } catch (e) { resolve(r.responseText); } } else { resolve({ code: r.status, message: HTTP_STATUS[r.status] || "错误码:" + r.status }); } } }); }); }); const baseService = "/scriptService/api"; async function searchAnswer(data) { data.location = location.href; const token = GM_getValue("start_pay") ? GM_getValue("E196FD8B49") || 0 : 0; const uri = token.length === 10 ? "/autoAnswer/" + token + "?gpt=" + (GM_getValue("gpt") || -1) : "/autoFreeAnswer"; return await instance.post(baseService + uri, data); } function catchAnswer(data) { /[013]/.test(data.type) && instance.post("/catch", data); } const OFFICIAL_WEBSITE = [ "blog.sagehub.cloudns.ch" ]; var _self = unsafeWindow; var top = _self; var UE$1; const selfintv = setInterval(() => { if (unsafeWindow) { _self = unsafeWindow; top = _self; UE$1 = _self.UE; try { reportOnline(); String.prototype.replaceAll = function(s1, s2) { return this.replace(new RegExp(s1, "gm"), s2); }; while (top !== _self.top) { top = top.parent.document ? top.parent : _self.top; if (top.location.pathname === "/mycourse/studentstudy") break; } } catch (err) { console.log(err); top = _self; } clearInterval(selfintv); } }, GLOBAL.delay); function checkVersion() { function compare(v1 = "0", v2 = "0") { v1 = String(v1).split("."); v2 = String(v2).split("."); const minVersionLens = Math.min(v1.length, v2.length); let result = 0; for (let i = 0; i < minVersionLens; i++) { const curV1 = Number(v1[i]); const curV2 = Number(v2[i]); if (curV1 > curV2) { result = 1; break; } else if (curV1 < curV2) { result = -1; break; } } if (result === 0 && v1.length !== v2.length) { const v1BiggerThenv2 = v1.length > v2.length; const maxLensVersion = v1BiggerThenv2 ? v1 : v2; for (let i = minVersionLens; i < maxLensVersion.length; i++) { const curVersion = Number(maxLensVersion[i]); if (curVersion > 0) { v1BiggerThenv2 ? result = 1 : result = -1; break; } } } return result; } GM_xmlhttpRequest({ method: "GET", url: "http://pan-yz.chaoxing.com/favicon.ico", timeout: GLOBAL.timeout, onload: function(r) { const obj = JSON.parse(r.responseText); if (obj.name === GM_info.script.name && compare(obj.version, GM_info.script.version) === 1 && new Date(obj.code_updated_at).getTime() + 1e3 * 60 * 60 * 2 < new Date().getTime()) { iframeMsg("update", { v1: GM_info.script.version, v2: obj.version, href: obj.url }); } } }); } // 处理 AI 填充的函数 function handleAiFill(answer, questionToMatch) { console.log('handleAiFill 调用:', answer ? answer.substring(0, 50) : 'no answer'); if (!GLOBAL.pendingAiFillQueue) GLOBAL.pendingAiFillQueue = []; let matchedItem = null; let matchedIndex = -1; questionToMatch = questionToMatch || ''; console.log('队列长度:', GLOBAL.pendingAiFillQueue.length, 'currentPendingItem:', GLOBAL.currentPendingItem ? 'exists' : 'null'); // 尝试通过问题文本匹配 for (let i = 0; i < GLOBAL.pendingAiFillQueue.length; i++) { const item = GLOBAL.pendingAiFillQueue[i]; if (questionToMatch && item.questionText && item.questionText.includes(questionToMatch.substring(0, 20))) { matchedItem = item; matchedIndex = i; console.log('通过问题匹配到:', i, item.questionText); break; } } // 如果没匹配到,使用队列中最早的一个 if (!matchedItem && GLOBAL.pendingAiFillQueue.length > 0) { matchedItem = GLOBAL.pendingAiFillQueue[0]; matchedIndex = 0; console.log('使用队列第一个:', matchedItem.questionText); } // 如果队列还是空的,尝试使用 currentPendingItem 备用 if (!matchedItem && GLOBAL.currentPendingItem) { matchedItem = GLOBAL.currentPendingItem; matchedIndex = -2; // 特殊标记,表示使用的是备用 console.log('队列为空,使用 currentPendingItem:', matchedItem.questionText ? matchedItem.questionText.substring(0, 20) : 'no question'); } // 如果还是没有,保存 AI 答案等待后续使用 if (!matchedItem) { console.log('★★★ 队列为空,保存 AI 答案(使用 GM_setValue 跨上下文共享)'); // 使用 GM_setValue 保存,因为 GLOBAL 可能在不同上下文中不共享 // 同时保存题目关键字,以便后续匹配 GM_setValue('lastAiAnswer', answer); GM_setValue('lastAiAnswerTime', Date.now()); GM_setValue('lastAiQuestion', questionToMatch || ''); GLOBAL.lastAiAnswer = answer; GLOBAL.lastAiQuestion = questionToMatch || ''; console.log('保存的题目关键字:', questionToMatch ? questionToMatch.substring(0, 30) : 'none'); // 通知 Vue 面板 iframeMsg("tip", { tip: "AI 已返回答案,等待填充..." }); return; } if (matchedItem) { const { data, fillHander } = matchedItem; console.log('待填充题目信息:', data ? data.type : 'no data', data ? data.$options.length : 0); if (data && data.$options && answer) { // 填空题/简答题 if (data.type === 2 || data.type === 4 || data.type === 5) { let answers = [answer]; if (data.$options.length > 1) { if (answer.includes(';')) answers = answer.split(';'); else if (answer.includes(';')) answers = answer.split(';'); else if (answer.includes('、')) answers = answer.split('、'); } answers = answers.map(a => a.trim().replace(/^["「『]|["」』]$/g, '').replace(/。$/, '').trim()); console.log('填空题答案:', answers); (async function() { for (let i = 0; i < Math.min(answers.length, data.$options.length); i++) { if (typeof fillHander === "function") { await fillHander(data.type, answers[i], data.$options.eq(i)); } else { const $el = data.$options.eq(i); if ($el.is('input') || $el.is('textarea')) { $el.val(answers[i]).trigger('input').trigger('change'); } else { $el.find('input, textarea').val(answers[i]).trigger('input').trigger('change'); } } } iframeMsg("tip", { tip: "AI答案已自动填充" }); })(); } // 选择题(单选/多选/判断) else if (data.type === 0 || data.type === 1 || data.type === 3) { let answerText = answer.trim(); console.log('AI选择题原始答案:', answerText); let matched = false; let clickCount = 0; let extractedLetters = ''; const cleanShort = answerText.replace(/[\s\\.。,,、::]/g, '').toUpperCase(); if (cleanShort.length <= 5 && /^[A-Z]+$/.test(cleanShort)) { extractedLetters = cleanShort; console.log('直接提取到字母答案:', extractedLetters); } else { const patterns = [ /答案[是为::\s]*([A-Z]+)/gi, /选[择项]?\s*([A-Z]+)/gi, /([A-Z]+)\s*选项/gi, /正确答案[是为::\s]*([A-Z]+)/gi, /应选[择]?\s*([A-Z]+)/gi, /^([A-Z]+)$/gm ]; for (const pattern of patterns) { const matches = answerText.match(pattern); if (matches && matches.length > 0) { for (const m of matches) { const letters = m.replace(/[^A-Za-z]/g, '').toUpperCase(); if (letters && letters.length > 0 && letters.length <= 6) { extractedLetters = letters; console.log('从文本提取到字母:', extractedLetters, '匹配:', m); break; } } if (extractedLetters) break; } } } if (extractedLetters) { console.log('最终提取字母:', extractedLetters); for (let i = 0; i < data.$options.length; i++) { const optLetter = String.fromCharCode(65 + i); if (extractedLetters.includes(optLetter)) { const $opt = data.$options.eq(i); // 检查是否已经被选中 const isAlreadyChecked = $opt.hasClass('is-checked') || $opt.hasClass('checked') || $opt.hasClass('selected') || $opt.find('input[type="radio"]').prop('checked') || $opt.find('input[type="checkbox"]').prop('checked') || $opt.find('.is-checked').length > 0 || $opt.attr('aria-checked') === 'true'; if (isAlreadyChecked) { console.log('选项已选中,跳过:', optLetter); matched = true; // 视为已匹配 clickCount++; continue; } console.log('点击选项:', optLetter); if (data.type === 1 || !matched) { $opt.get(0).click(); matched = true; clickCount++; if (data.type !== 1) break; } } } } if (!matched && data.type === 3) { const isCorrect = /[对正确是√T]/.test(answerText) && !/不对|不正确|错/.test(answerText); const isWrong = /[错误否×F]|不对|不正确/.test(answerText); if (isCorrect || isWrong) { const clickIdx = isCorrect ? 0 : 1; const $opt = data.$options.eq(clickIdx); // 检查判断题选项是否已选中 const isAlreadyChecked = $opt.hasClass('is-checked') || $opt.hasClass('checked') || $opt.find('input').prop('checked') || $opt.find('.is-checked').length > 0; if (!isAlreadyChecked) { $opt.get(0).click(); console.log('判断题答案:', isCorrect ? '对' : '错'); } else { console.log('判断题已选中,跳过:', isCorrect ? '对' : '错'); } matched = true; clickCount = 1; } } if (matched) { iframeMsg("tip", { tip: "AI答案已自动选择 " + clickCount + " 个选项" }); } else { iframeMsg("tip", { tip: "AI答案无法匹配选项,请手动选择" }); console.log('无法匹配,原始答案:', answerText); } } } // 从队列中移除已处理的项目,并调用 resolve if (matchedIndex >= 0) { const removed = GLOBAL.pendingAiFillQueue.splice(matchedIndex, 1)[0]; if (removed && typeof removed.resolve === 'function') { console.log('调用 resolve,通知继续下一题'); removed.resolve(); } } else if (matchedIndex === -2) { // 使用的是 currentPendingItem if (matchedItem && typeof matchedItem.resolve === 'function') { console.log('通过 currentPendingItem 调用 resolve'); matchedItem.resolve(); } GLOBAL.currentPendingItem = null; } } else { console.log('没有待填充的题目信息,队列长度:', GLOBAL.pendingAiFillQueue ? GLOBAL.pendingAiFillQueue.length : 0, 'currentPendingItem:', GLOBAL.currentPendingItem ? 'exists' : 'null'); } } // 公共函数:检测选项是否已被选中(避免重复代码) function isOptionChecked($opt) { return $opt.hasClass('is-checked') || // Element UI 样式 $opt.hasClass('checked') || // 通用样式 $opt.hasClass('selected') || // 通用样式 $opt.hasClass('active') || // 激活样式 $opt.hasClass('on') || // 选中样式 $opt.hasClass('cur') || // 当前选中 $opt.find('input[type="radio"]').prop('checked') || // 原生 radio $opt.find('input[type="checkbox"]').prop('checked') || // 原生 checkbox $opt.find('input').prop('checked') || // 任意 input $opt.find('.is-checked').length > 0 || // 子元素有选中样式 $opt.find('.checked').length > 0 || // 子元素有 checked 样式 $opt.find('.selected').length > 0 || // 子元素有 selected 样式 $opt.find('.active').length > 0 || // 子元素有 active 样式 $opt.attr('aria-checked') === 'true' || // ARIA 属性 $opt.attr('data-checked') === 'true' || // data 属性 ($opt.attr('class') || '').includes('check'); // class 包含 check } // 公共函数:构建 AI Prompt(带题号) function buildAiPrompt(data, questionIndex) { const q = data.question; const opts = data.options || []; const idx = questionIndex !== undefined ? questionIndex : (GLOBAL.index || 0); const prefix = '【第' + idx + '题】 '; // 构建选项字符串(换行显示,带字母) let optStr = ''; if (opts.length > 0) { optStr = '\\n' + opts.map((opt, i) => String.fromCharCode(65 + i) + '.' + opt).join('\\n'); } switch (data.type) { case 0: // 单选 return prefix + q + optStr + '\\n单选,只回答一个字母,如A。不要解释'; case 1: // 多选 return prefix + q + optStr + '\\n多选,只回答字母,如ABC。不要解释'; case 3: // 判断 return prefix + '判断题:' + q + '\\n只回答"对"或"错"。不要解释'; case 2: // 填空 return prefix + '填空题:' + q + '\\n只回答答案内容,多个空用分号分隔。不要解释'; default: // 简答 return prefix + '简答题:' + q + '\\n请简洁回答'; } } // 公共函数:等待 AI 答案返回 async function waitForAiAnswer(maxWait = 20000, startTime = Date.now()) { let waitTime = 0; while (waitTime < maxWait) { await new Promise(r => setTimeout(r, 300)); waitTime += 300; const gmAnswer = GM_getValue('lastAiAnswer', ''); const gmTime = GM_getValue('lastAiAnswerTime', 0); const globalAnswer = GLOBAL.lastAiAnswer; if ((gmAnswer && gmTime > startTime) || globalAnswer) { return gmAnswer || globalAnswer; } } return null; } // ========== 优化:统一的辅助函数 ========== // 清除 AI 答案状态 function clearAiAnswerState() { GM_setValue('lastAiAnswer', ''); GM_setValue('lastAiAnswerTime', 0); GLOBAL.lastAiAnswer = null; } // 生成简短答案用于显示 function getShortAnswer(answer) { if (!answer) return ''; const extracted = extractAnswerLetters(answer); if (extracted) return extracted; return answer.length > 20 ? answer.substring(0, 20) + '...' : answer; } // 更新答案显示(统一处理) function updateAnswerDisplay(answer, style = 'success-row') { const shortAnswer = getShortAnswer(answer); iframeMsg("update_answer", { index: GLOBAL.index - 1, answer: shortAnswer, style: style }); return shortAnswer; } // 安全执行函数(带错误处理) function safeExecute(fn, errorMsg = '执行出错') { try { return fn(); } catch (e) { console.error(errorMsg, e); return null; } } // 异步安全执行 async function safeExecuteAsync(fn, errorMsg = '异步执行出错') { try { return await fn(); } catch (e) { console.error(errorMsg, e); return null; } } // 更新进度提示(用户体验优化) function updateProgress(current, total, status = '') { const progress = total > 0 ? Math.round((current / total) * 100) : 0; const successRate = GLOBAL.successCount > 0 && current > 0 ? Math.round((GLOBAL.successCount / current) * 100) : 0; let tipMsg = `进度: ${current}/${total} (${progress}%)`; if (GLOBAL.successCount > 0) { tipMsg += ` | 成功: ${GLOBAL.successCount} (${successRate}%)`; } if (status) { tipMsg += ` | ${status}`; } iframeMsg("tip", { tip: tipMsg }); } // 从 AI 回复中提取答案字母(用于显示) function extractAnswerLetters(answerText) { if (!answerText) return null; const text = answerText.trim(); // 尝试提取答案字母(优先使用精确匹配) const patterns = [ /答案[是为::\s]*([A-Ga-g][、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*)/i, /正确答案[是为::\s]*([A-Ga-g][、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*)/i, /选[择项]?\s*([A-Ga-g]+)/i, /^[\s]*([A-Ga-g]+)[\s]*$/m ]; for (const pattern of patterns) { const match = text.match(pattern); if (match) { const letters = (match[1] || match[0]).toUpperCase().replace(/[^A-G]/g, ''); if (letters) { return letters; } } } // 宽松匹配(只匹配独立的字母,避免匹配解释文本中的字母) const singleLetters = text.match(/\b([A-G])\b/g); if (singleLetters) { return [...new Set(singleLetters)].join(''); } return null; } // 使用 AI 答案填充题目(使用原有的填充机制) async function fillWithAiAnswer(answer, data, fillHander) { console.log('fillWithAiAnswer 调用:', answer ? answer.substring(0, 50) : 'no answer'); if (!data || !data.$options || !answer) { console.log('fillWithAiAnswer: 缺少必要参数'); return false; } // 智能纠错模式:检查已选答案,如果与 AI 答案不同则纠正 // 不再跳过已有答案,而是对比并纠错 // 填空题/简答题 - 使用原有的 fillHander 填充 if (data.type === 2 || data.type === 4 || data.type === 5) { // 从 AI 回复中提取答案(可能包含解题步骤) let extractedAnswer = answer; // 尝试提取 "答案:xxx" 或 "答案是xxx" 格式 const answerPatterns = [ /答案[是为::\s]+(.+?)(?:\n|$)/i, /填入[::\s]+(.+?)(?:\n|$)/i, /应填[::\s]+(.+?)(?:\n|$)/i ]; for (const pattern of answerPatterns) { const match = answer.match(pattern); if (match && match[1]) { extractedAnswer = match[1].trim(); console.log('填空题:从回复中提取答案:', extractedAnswer); break; } } // 如果回复很短(少于50字),可能就是答案本身 if (answer.length < 50 && !answer.includes('解题') && !answer.includes('分析')) { extractedAnswer = answer; } let answers = [extractedAnswer]; if (data.$options.length > 1) { if (extractedAnswer.includes(';')) answers = extractedAnswer.split(';'); else if (extractedAnswer.includes(';')) answers = extractedAnswer.split(';'); else if (extractedAnswer.includes('、')) answers = extractedAnswer.split('、'); } answers = answers.map(a => a.trim().replace(/^["「『]|["」』]$/g, '').replace(/。$/, '').trim()).filter(a => a); console.log('填空题答案:', answers, '输入框数量:', data.$options.length); // 使用原有的 fillHander 填充(和选择题一样的思路) for (let i = 0; i < Math.min(answers.length, data.$options.length); i++) { if (typeof fillHander === "function") { await fillHander(data.type, answers[i], data.$options.eq(i)); console.log('使用 fillHander 填充填空题', i, ':', answers[i]); } else { // 备用:直接操作元素 const $el = data.$options.eq(i); if ($el.is('input') || $el.is('textarea')) { $el.val(answers[i]).trigger('input').trigger('change'); } else { $el.find('input, textarea').val(answers[i]).trigger('input').trigger('change'); } console.log('备用方式填充填空题', i, ':', answers[i]); } } return answers.length > 0; } // 选择题/判断题 const answerText = answer.trim(); let answerLetters = []; // 尝试提取答案字母 const patterns = [ /答案[是为::\s]*([A-Ga-g][、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*)/i, // 答案是A、B、D /正确答案[是为::\s]*([A-Ga-g][、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*[、,,\s]*[A-Ga-g]*)/i, // 正确答案是A、B /选[择项]?\s*([A-Ga-g]+)/i, // 选ABD /^[\s]*([A-Ga-g]+)[\s]*$/m, // 单独一行的字母 /^([A-Ga-g]+)[(((]/, // 开头字母+括号解释,如 "ABCD(解释...)" /^([A-Ga-g]+)[,,、::\s]/, // 开头字母+分隔符,如 "ABC,因为..." /^([A-Ga-g]{1,7})\s*[。.]/ // 开头字母+句号,如 "ABC。" ]; for (const pattern of patterns) { const match = answerText.match(pattern); if (match) { // 提取所有字母,去除分隔符 const letters = (match[1] || match[0]).toUpperCase().replace(/[^A-G]/g, ''); if (letters) { answerLetters = letters.split(''); console.log('正则匹配成功:', pattern.toString().substring(0, 30), '→', letters); break; } } } // 宽松匹配(只在主正则完全失败时执行,避免把解析文本中的 A/B/C/D 也匹配进来) if (answerLetters.length === 0) { const singleLetters = answerText.match(/\b([A-G])\b/g); if (singleLetters) { answerLetters = singleLetters.map(l => l.toUpperCase()); // 去重 answerLetters = [...new Set(answerLetters)]; } } // 判断题特殊处理 - 智能纠错 if (data.type === 3) { const isTrue = /[对正确是√T]/.test(answerText) && !/不对|不正确|错/.test(answerText); const isFalse = /[错误否×F]|不对|不正确/.test(answerText); if (isTrue || isFalse) { const correctIdx = isTrue ? 0 : 1; const wrongIdx = isTrue ? 1 : 0; const $correctOpt = data.$options.eq(correctIdx); const $wrongOpt = data.$options.eq(wrongIdx); // 调试:打印选项状态 console.log('判断题智能纠错:', isTrue ? '答案=对' : '答案=错', '正确选项已选:', isOptionChecked($correctOpt), '错误选项已选:', isOptionChecked($wrongOpt)); // 智能纠错:如果正确选项未选中,直接点击(会自动切换) if (!isOptionChecked($correctOpt)) { $correctOpt.get(0).click(); console.log('AI判断题纠错:', isTrue ? '对' : '错'); } else { console.log('AI判断题已正确,无需纠错'); } return true; } } console.log('AI答案字母:', answerLetters); // 智能纠错:选择题处理 if (answerLetters.length > 0) { const correctSet = new Set(answerLetters); // 多选题纠错:先取消不在答案中的已选选项 if (data.type === 1) { for (let i = 0; i < data.$options.length; i++) { const letter = String.fromCharCode(65 + i); const $opt = data.$options.eq(i); // 如果选项已选中但不在正确答案中,取消它 if (isOptionChecked($opt) && !correctSet.has(letter)) { console.log('智能纠错:取消错误选项', letter); await new Promise(r => setTimeout(r, 150)); $opt.get(0).click(); } } } // 选中正确答案 for (let i = 0; i < answerLetters.length; i++) { const letter = answerLetters[i]; const idx = letter.charCodeAt(0) - 65; if (data.$options[idx]) { const $opt = data.$options.eq(idx); // 如果正确选项已选中,跳过 if (isOptionChecked($opt)) { console.log('正确选项已选中:', letter); continue; } // 添加点击延迟 if (i > 0 || data.type === 1) { await new Promise(r => setTimeout(r, 200)); } // 点击选中正确选项 $opt.get(0).click(); console.log('智能纠错:选中正确选项', letter); } else { console.log('AI选项不存在:', letter, '索引:', idx); } } return true; } console.log('无法从AI答案中提取有效选项'); return false; } // 辅助函数:resolve 队列中第一个等待的 Promise(用于失败情况) function resolveFirstInQueue() { if (GLOBAL.pendingAiFillQueue && GLOBAL.pendingAiFillQueue.length > 0) { const removed = GLOBAL.pendingAiFillQueue.shift(); if (removed && typeof removed.resolve === 'function') { console.log('AI失败,resolve 第一个等待项'); removed.resolve(); } } else if (GLOBAL.currentPendingItem) { // 备用:使用 currentPendingItem if (typeof GLOBAL.currentPendingItem.resolve === 'function') { console.log('AI失败,通过 currentPendingItem resolve'); GLOBAL.currentPendingItem.resolve(); } GLOBAL.currentPendingItem = null; } } top.addEventListener("message", event => { if (event.data.type === "jump") { GLOBAL.index++; iframeMsg("tip", { tip: "准备答第" + (GLOBAL.index + 1) + "题" }); } else if (event.data.type === "stop") { GLOBAL.stop = event.data.val; console.log('✅ 暂停状态已更新:', GLOBAL.stop); } else if (event.data.type === "start_pay") { if (event.data.flag) { if (String(GM_getValue("E196FD8B49")).length === 10 || String(GM_getValue("E196FD8B491")).length === 11) { iframeMsg("tip", { tip: "扫码可以请我喝杯茶哦" }); GM_setValue("start_pay", event.data.flag); iframeMsg("start_pay", true); } else { iframeMsg("tip", { tip: "扫码可以请我喝杯茶哦" }); } } else { iframeMsg("tip", { tip: "扫码可以请我喝杯茶哦" }); GM_setValue("start_pay", event.data.flag); iframeMsg("start_pay", false); } } else if (event.data.type === "auto_jump") { GM_setValue("auto_jump", event.data.flag); iframeMsg("tip", { tip: "已" + (event.data.flag ? "开启" : "关闭") + "自动切换,页面刷新后生效" }); } else if (event.data.type === "confim") { if (event.data.token.length === 10 || event.data.token.length === 11) { GM_setValue("E196FD8B49", event.data.token); iframeMsg("tip", { tip: "扫码可以请我喝杯茶哦" }); } else { iframeMsg("tip", { tip: "扫码可以请我喝杯茶哦" }); } } else if (event.data.type === "save_setting") { GM_setValue("gpt", event.data.gpt); GM_setValue("search_delay", event.data.search_delay); GM_setValue("auto_ai_search", event.data.auto_ai_search); GM_setValue("ai_first_mode", event.data.ai_first_mode); GM_setValue("auto_submit", event.data.auto_submit); GM_setValue("submit_threshold", event.data.submit_threshold); GM_setValue("tiku_adapter", event.data.tiku_adapter); GM_setValue("ai_api_url", event.data.ai_api_url); GM_setValue("ai_api_key", event.data.ai_api_key); GM_setValue("ai_model", event.data.ai_model); GM_setValue("ai_platform", event.data.ai_platform); // 立即更新运行时配置(无需刷新) GLOBAL.search_delay = event.data.search_delay; GLOBAL.auto_ai_search = event.data.auto_ai_search; GLOBAL.ai_first_mode = event.data.ai_first_mode; GLOBAL.auto_submit = event.data.auto_submit; GLOBAL.submit_threshold = event.data.submit_threshold; GLOBAL.tiku_adapter = event.data.tiku_adapter; GLOBAL.ai_api_url = event.data.ai_api_url; GLOBAL.ai_api_key = event.data.ai_api_key; GLOBAL.ai_model = event.data.ai_model; GLOBAL.ai_platform = event.data.ai_platform; // 通知 iframe 配置已更新 iframeMsg("settings_updated", event.data); console.log('✅ 配置已保存并立即生效'); } else if (event.data.type === "save_position") { // 保存面板位置 GM_setValue("pos", event.data.left + "," + event.data.top); } else if (event.data.type === "save_mini_position") { // 保存悬浮球位置 GM_setValue("miniPos", event.data.left + "," + event.data.top); } else if (event.data.type === "ai_request") { // 只有 aip.baidubce.com (原生接口) 需要 access_token,qianfan.baidubce.com (兼容接口) 走标准 Bearer const apiKey = (event.data.api_key || '').trim(); const isNativeBaidu = event.data.api_url.includes('aip.baidubce.com'); const requestUrl = isNativeBaidu ? (event.data.api_url + "?access_token=" + apiKey) : event.data.api_url; const requestHeaders = { "Content-Type": "application/json" }; // 如果不是原生百度接口,都添加 Authorization 头 (包括千帆 V2 兼容接口) if (!isNativeBaidu) { requestHeaders["Authorization"] = "Bearer " + apiKey; } const requestData = { messages: event.data.messages, stream: false }; if (!isNativeBaidu) { requestData.model = event.data.model; } GM_xmlhttpRequest({ method: "POST", url: requestUrl, headers: requestHeaders, data: JSON.stringify(requestData), timeout: 30000, // 30秒超时 onload: function(response) { // 特殊处理 Baidu ResourceNotFound if (response.responseText.includes('ResourceNotFound')) { iframeMsg("ai_response", { success: true, response: JSON.stringify({ error: { message: "Resource not found. 请检查'模型名称'是否正确,或者该模型是否已开通(如 ernie-speed-8k)" } }) }); } else { console.log('AI请求成功,发送响应给Vue:', response.responseText.substring(0, 100)); iframeMsg("ai_response", { success: true, response: response.responseText }); // 不在这里直接调用 handleAiFill,让 Vue 发送 ai_fill 消息来触发 // 这样可以避免重复调用 try { const res = JSON.parse(response.responseText); if (res.choices && res.choices[0]) { const content = res.choices[0].message.content; console.log('AI响应内容:', content.substring(0, 50)); // 通知 Vue,Vue 会发送 ai_fill 消息 } } catch (e) { console.log('解析AI响应失败:', e); // 解析失败时也要 resolve 队列中的等待 resolveFirstInQueue(); } } }, onerror: function(e) { console.log('AI请求错误:', e); iframeMsg("ai_response", { success: false, error: 'AI请求出错: ' + (e.error || e.statusText) }); resolveFirstInQueue(); }, ontimeout: function() { console.log('AI请求超时(60秒)'); iframeMsg("ai_response", { success: false, error: 'AI请求超时,请稍后重试' }); // 超时也要 resolve 队列 resolveFirstInQueue(); } }); } else if (event.data.type === "ai_fill") { // AI 返回答案后自动填充 console.log('收到 ai_fill 消息'); handleAiFill(event.data.answer, event.data.question); } }, false); $(document).keydown(function(event) { if (event.keyCode === 38) { $(".model-id").hide(); } else if (event.keyCode === 40) { $(".model-id").show(); } else if (event.keyCode === 37) { $(".model-id").hide(); GM_setValue("hide", true); } else if (event.keyCode === 39) { $(".model-id").show(); GM_setValue("hide", false); GM_setValue("pos", "50px,50px"); } else if (event.keyCode === 83) { GLOBAL.stop = true; iframeMsg("stop", GLOBAL.stop); } else if (event.keyCode === 68) { GLOBAL.stop = false; iframeMsg("stop", GLOBAL.stop); } }); function getAnswerForKey(keys, options) { return keys.map(function(val) { return options[val.charCodeAt(0) - 65]; }); } function setIntervalFunc(flag, func, time) { const interval = setInterval(() => { if (flag()) { clearInterval(interval); func(); } }, time || 1e3); } function getAnswer(str, options, type) { if (type === 0 || type === 1) { const ans = getAnswerForKey(str.match(/[A-G]/gi) || [], options); return ans.length > 0 ? ans : [ str ]; } else { return [ str ]; } } function getQuestionType(str) { if (!str) return undefined; str = str.trim().replaceAll(/\s+/g, ""); if (TYPE[str]) return TYPE[str]; const regex = Object.keys(TYPE).join("|"); const matcher = str.match(regex); if (matcher) return TYPE[matcher[0]]; return undefined; } function rand(m, n) { return Math.ceil(Math.random() * (n - m + 1) + m - 1); } const TYPE = { "阅读理解(选择)/完型填空": 66, "听力训练": 66, multichoice: 1, singlechoice: 0, bijudgement: 3, "单项选择题": 0, "单项选择": 0, "单选题": 0, "单选": 0, "多选": 1, "多选题": 1, "案例分析": 1, "多项选择题": 1, "多项选择": 1, "客观题": 1, "填空题": 2, "填空": 2, "对错题": 3, "判断题": 3, "判断正误": 3, "判断": 3, "主观题": 4, "问答题": 4, "简答题": 4, "名词解释": 5, "论述题": 6, "计算题": 7, "其它": 8, "分录题": 9, "资料题": 10, "连线题": 11, "排序题": 13, "完形填空": 14, "完型填空": 14, "阅读理解": 15, "口语题": 18, "听力题": 19, "A1A2题": 1, "文件作答": 4, "视频题": 1 }; function sleep(time) { return new Promise(resolve => { setTimeout(resolve, time); }); } // 缓存 iframe 引用以提高性能 let _cachedIframe = null; let _cacheTime = 0; const CACHE_DURATION = 5000; // 缓存5秒 function getIframeNode() { const now = Date.now(); if (_cachedIframe && (now - _cacheTime) < CACHE_DURATION) { // 验证缓存的 iframe 仍然有效 if (_cachedIframe.contentWindow && _cachedIframe.contentWindow.vueDefinedProp) { return _cachedIframe; } } // 刷新缓存 _cachedIframe = top.document.getElementById("iframeNode"); _cacheTime = now; return _cachedIframe; } function iframeMsg(type, message) { try { const iframe = getIframeNode(); if (iframe && iframe.contentWindow && iframe.contentWindow.vueDefinedProp) { iframe.contentWindow.vueDefinedProp(type, message); return true; } else { console.log('iframeMsg: iframe 未就绪,延迟重试', type); // 延迟重试一次 setTimeout(() => { try { _cachedIframe = null; // 清除缓存强制刷新 const iframe2 = getIframeNode(); if (iframe2 && iframe2.contentWindow && iframe2.contentWindow.vueDefinedProp) { iframe2.contentWindow.vueDefinedProp(type, message); } } catch (e2) { console.error('iframeMsg 重试失败:', e2); } }, 500); return false; } } catch (e) { console.error('iframeMsg 发送失败:', type, e); return false; } } function filterImg(dom) { if (location.host === "ncexam.cug.edu.cn") { String.prototype.trim = function() { return this.replace(/^\s+|\s+$/gm, ""); }; } return $(dom).clone().find("img[src]").replaceWith(function() { return $("

").text(''); }).end().find("iframe[src]").replaceWith(function() { return $("

").text('

请输入题目,AI将为您解答

{{msg.content}}
正在思考中...
`; addModal2(html); checkVersion(); } function addModal2(html, newPos, footerChildNode = false) { let headersNode = createContainer("hcsearche-modal-links"); // 创建相对定位容器 let relativeContainer = top.document.createElement("div"); relativeContainer.className = "header-bar"; // 添加拖拽手柄类名 relativeContainer.style.position = "relative"; relativeContainer.style.width = "580px"; // 强制宽度与下方答题区一致 relativeContainer.style.padding = "16px 20px"; relativeContainer.style.background = "linear-gradient(to bottom, #ffffff, #fcfcfc)"; // 微妙的渐变背景 relativeContainer.style.borderBottom = "1px solid #e4e7ed"; relativeContainer.style.boxSizing = "border-box"; relativeContainer.style.minHeight = "120px"; // 创建文本区域 let textDiv = top.document.createElement("div"); textDiv.style.fontSize = "12px"; textDiv.style.color = "#5e6d82"; textDiv.style.lineHeight = "1.6"; textDiv.style.paddingRight = "100px"; // 给右侧图片留出充足空间 textDiv.innerHTML = `
👋 Smiley face 开发者

大四学生用爱发电,脚本自改自用,感谢各位的零碎小费与支持。

✨ 过程很长,但我更加明白了『走捷径就是绕远路』

💬 QQ交流群: 1030887796
⏱️ 首次使用需等待15秒加载
`; let adNode = top.document.createElement("img"); let item = { url: GM_getResourceURL("Img") }; const getAdList = GM_getValue("adList"); if (getAdList) { const adList = JSON.parse(getAdList); let lastShown = GM_getValue("lastShown") || 0; item = adList[lastShown]; GM_setValue("lastShown", (lastShown + 1) % adList.length); item.base64 = GM_getValue(item.hash); } adNode.setAttribute("src","data:image/jpeg;base64,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"); adNode.setAttribute("draggable", "false"); adNode.setAttribute("style", "display: block; width: 88px; border-radius: 50%; box-shadow: 0 4px 16px rgba(0,0,0,0.1); border: 4px solid #fff; transition: transform 0.3s; position: absolute; right: 20px; bottom: 16px; z-index: 10;"); adNode.onmouseover = function() { this.style.transform = "scale(1.2) translate(-5px, -5px)"; }; adNode.onmouseout = function() { this.style.transform = "scale(1)"; }; relativeContainer.appendChild(textDiv); relativeContainer.appendChild(adNode); headersNode.appendChild(relativeContainer); let iframeNode = top.document.createElement("iframe"); iframeNode.id = "iframeNode"; iframeNode.setAttribute("width", "580px"); iframeNode.setAttribute("height", (GLOBAL.length - 120) + "px"); iframeNode.setAttribute("style", "height:" + (GLOBAL.length - 120) + "px; width: 580px; border: none;"); iframeNode.setAttribute("frameborder", "0"); iframeNode.srcdoc = html; let contentNode = createContainer("content-modal", [ headersNode, iframeNode ]); let modal = renderModal(contentNode); dragModel(modal); if (GM_getValue("hide")) { $("#model-id").hide(); vm.hideTip(); } } function renderModal(childElem, newPos) { return render("tag" + rand(1, 100).toString(), "model-id", childElem); } function render(tagName, elemId, childElem, isFixed, newPos) { let doc = top.document; let elem = doc.getElementById(elemId); if (elem) { elem.innerHTML = ""; } else { elem = doc.createElement(tagName); elem.id = elemId; doc.body.appendChild(elem); } let contentNode = createContainer(tagName + "-container", childElem); elem.appendChild(contentNode); elem.classList.add(elemId); elem.style.zIndex = "9999999"; elem.style.position = "fixed"; const pos = GM_getValue("pos") === undefined ? "30px,30px" : GM_getValue("pos"); const posarr = pos.split(","); elem.style.left = posarr[0]; elem.style.top = posarr[1]; setTimeout(function() { elem.classList.add(elemId + "-show"); }, 10); return elem; } const init$1 = async ($TiMu, select, wrap) => { let question = formatString(filterImg($TiMu.find(select.elements.question))); if (select.elements.type && select.elements.type.includes("input[name^=type]:eq")) { select.elements.type = "input[name^=type]:eq(" + GLOBAL.i + ")"; } let data = { $item: $TiMu, question_text: $TiMu.find(select.elements.question).text(), question: question.length === 0 ? $TiMu.find(select.elements.question) : question.replace(/^\d+、/, "").replace(/[((](\d+\s?(\.\d+)?分)[))]$/, "").replace(/^((\d+.(\s+)?)?)[\[((【](.*?)[】))\]]/, "").trim(), $options: select.elements.$options ? $TiMu.find(select.elements.$options) : undefined, options: select.elements.options ? jQuery.map($TiMu.find(select.elements.options), function(val) { return formatString(filterImg(val)).replace(/^[A-Ga-g][.、]/, "").trim(); }) : undefined }; if (select.elements.type) { const getType = getQuestionType($TiMu.find(select.elements.type).text()); const val = $TiMu.find(select.elements.type).val(); data.type = isNaN(getType) ? isNaN(val) ? val : parseInt(val) : getType; } else { console.log("自动获取题目类型", defaultWorkTypeResolver(data.$options)); data.type = defaultWorkTypeResolver(data.$options); } if (select.elements.answer) { data.answer = getAnswer(filterImg($TiMu.find(select.elements.answer)) || $TiMu.find(select.elements.answer).val(), data.options, data.type); } if (data && data.type === 3 && data.options.length === 0) { data.options = [ "正确", "错误" ]; } const r = await wrap(data); if (typeof r === "boolean") return undefined; return data; }; async function WorkerJSPlus(options) { if (GLOBAL.isMatch) return; const match = options.match ? typeof options.match === "boolean" ? options.match : options.match() : false; if (!match) return; GLOBAL.isMatch = true; if (options.hook && typeof options.hook === "function") { if (options.hook()) return; } const defaultFunc = () => {}; const main = () => { setTimeout(() => { showPanel(); if (options.init && typeof options.init === "function") { if (options.init()) return; } const select = { root: options.root, elements: options.elements, ignore_click: options.ignore_click }; new WorkerJS(select, options.wrap ? options.wrap : defaultFunc, options.fill ? options.fill : defaultFunc, options.finished ? options.finished : defaultFunc, options.fillFinish ? options.fillFinish : defaultFunc).fillAnswer(); }, GLOBAL.delay); }; if (options.intv) { setIntervalFunc(options.intv, main); } else { main(); } } var WorkerJS = function(select, searchHander, fillHander, onFinish = function(need_jump) {}, fillFinish = function() {}) { GLOBAL.index = 0; GLOBAL.successCount = 0; // 重置成功计数 this.init = init$1; this.fillAnswer = async () => { let arr = jQuery(select.root); while (true) { if (arr.length === 0) return; await sleep((isNaN(parseInt(GM_getValue("search_delay"))) ? 2 : GM_getValue("search_delay")) * 1e3); if (GLOBAL.stop) { continue; } if (GLOBAL.index >= arr.length) { let auto_jump = GM_getValue("auto_jump") === undefined || GM_getValue("auto_jump"); const next = await onFinish(auto_jump); if (next) { GLOBAL.index = 0; setTimeout(this.fillAnswer, 300); } // 检查是否需要自动提交 const autoSubmit = GM_getValue("auto_submit"); const submitThreshold = parseInt(GM_getValue("submit_threshold")) || 80; console.log('自动提交检查: autoSubmit=', autoSubmit, 'next=', next); if (autoSubmit && !next) { // 计算正确率 const totalQuestions = arr.length; const successCount = GLOBAL.successCount || 0; const accuracy = totalQuestions > 0 ? (successCount / totalQuestions * 100) : 0; console.log('正确率检查:', successCount, '/', totalQuestions, '=', accuracy.toFixed(1) + '%', '阈值:', submitThreshold + '%'); console.log('比较结果:', accuracy, '>=', submitThreshold, '=', accuracy >= submitThreshold); if (accuracy >= submitThreshold) { iframeMsg("tip", { tip: "正确率 " + accuracy.toFixed(1) + "% 达标,3秒后自动提交..." }); setTimeout(() => { // 查找并点击提交按钮(扩展选择器) const submitBtns = [ $('a.btnSubmit'), $('a.workBtnIndex:contains("提交")'), $('a.jb_btn:contains("交卷")'), $('button:contains("交卷")'), $('button:contains("提交")'), $('input[value="提交"]'), $('a:contains("提交答卷")'), $('a:contains("交卷")'), $('.submitBtn'), $('[class*="submit"]').filter(':visible'), $('button.el-button--primary:contains("交卷")'), $('button.ant-btn-primary:contains("提交")'), $('button[type="submit"]'), $('input[type="submit"]'), // 学习通特定按钮 $('a.submitBtn'), $('a.jb_btn'), $('button.jb_btn') ]; let found = false; for (const $btn of submitBtns) { if ($btn.length > 0 && $btn.is(':visible')) { console.log('找到提交按钮:', $btn.text() || $btn.val(), $btn.attr('class')); $btn.eq(0).click(); iframeMsg("tip", { tip: "点击提交,等待确认对话框..." }); found = true; // 等待确认对话框出现并点击确认按钮 setTimeout(() => { // 在当前文档和父文档中查找确认按钮 const docs = [document, top.document]; let confirmed = false; for (const doc of docs) { if (confirmed) break; const $doc = $(doc); // 查找确认对话框中的提交/确认按钮 const confirmBtns = [ // 学习通专用弹窗(popBottom)- 最常见 $doc.find('#popok'), $doc.find('.popBottom #popok'), $doc.find('.popBottom .jb_btn:contains("提交")'), $doc.find('.popBottom a.jb_btn'), $doc.find('.popDiv a#popok'), // Element UI 对话框 $doc.find('.el-message-box__btns .el-button--primary'), $doc.find('.el-dialog__footer .el-button--primary'), // 学习通弹窗 - layer.js $doc.find('.layui-layer-btn0'), $doc.find('.layui-layer-btn a:contains("提交")'), $doc.find('.layui-layer-btn a:contains("确定")'), $doc.find('.layui-layer-btn a:contains("确认")'), // layer 弹窗按钮(蓝色确认按钮) $doc.find('.layui-layer-dialog .layui-layer-btn0'), $doc.find('.layui-layer-btn .layui-layer-btn0'), // 通用弹窗按钮 $doc.find('.dialog-footer button:contains("提交"):visible'), $doc.find('.dialog-footer button:contains("确定"):visible'), $doc.find('.modal-footer .btn-primary:visible'), $doc.find('.popup-footer button:contains("提交"):visible'), // 蓝色按钮(通常是确认按钮) $doc.find('button.btn-primary:contains("提交"):visible'), $doc.find('a.jb_btn:contains("提交"):visible'), // 任意包含"提交"文字的可见按钮 $doc.find('a:visible').filter(function() { return $(this).text().trim() === '提交' && $(this).closest('.popDiv, .popBottom, .layui-layer, .el-message-box, .modal, .dialog').length > 0; }) ]; for (const $confirmBtn of confirmBtns) { if ($confirmBtn.length > 0) { const $visibleBtn = $confirmBtn.filter(':visible').first(); if ($visibleBtn.length > 0) { console.log('找到确认按钮:', $visibleBtn.text(), $visibleBtn.attr('class'), 'in', doc === document ? 'current' : 'parent'); $visibleBtn.click(); iframeMsg("tip", { tip: "已自动确认提交" }); confirmed = true; break; } } } } if (!confirmed) { console.log('jQuery未找到确认按钮,尝试原生DOM方法...'); // 使用原生 DOM 方法查找 #popok try { const popok = top.document.getElementById('popok'); if (popok && popok.offsetParent !== null) { console.log('原生DOM找到 #popok 按钮,执行点击'); popok.click(); // 触发真实点击事件 const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: top }); popok.dispatchEvent(clickEvent); if (popok.onclick) popok.onclick(); iframeMsg("tip", { tip: "已自动确认提交" }); confirmed = true; } } catch (e) { console.log('原生DOM查找失败:', e); } } if (!confirmed) { console.log('仍未找到确认按钮,2秒后再试一次...'); // 再等待2秒后重试 setTimeout(() => { try { const popok = top.document.getElementById('popok'); if (popok) { console.log('延迟重试:找到 #popok,尝试多种点击方式'); // 方式1: 原生click popok.click(); // 方式2: 触发真实点击事件 const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: top }); popok.dispatchEvent(clickEvent); // 方式3: 直接调用onclick if (popok.onclick) popok.onclick(); iframeMsg("tip", { tip: "已自动确认提交" }); } } catch (e) { console.log('点击确认按钮失败:', e); } }, 2000); } }, 1000); // 等待1秒让确认对话框出现 break; } } if (!found) { console.log('未找到提交按钮,请手动提交'); iframeMsg("tip", { tip: "未找到提交按钮,请手动提交" }); } }, 3000); } else { iframeMsg("tip", { tip: "正确率 " + accuracy.toFixed(1) + "% 未达标(阈值" + submitThreshold + "%),请手动检查" }); } return true; } if (auto_jump) { iframeMsg("tip", { tip: "自动答题已完成,即将切换下一题" }); next || setTimeout(() => { iframeMsg("tip", { type: "hidden", tip: "自动答题已完成,请检查提交" }); }, Math.max(GM_getValue("search_delay") || 2, 5) * 1e3); } else { iframeMsg("tip", { tip: "自动答题已完成" + (arr.length === 1 ? ",请手动切换" : "请检查提交") }); } return true; } try { let data = await this.init(jQuery(arr[GLOBAL.index++]), select, searchHander); if (!data) { GLOBAL.index--; continue; } // 使用优化的进度提示 updateProgress(GLOBAL.index, arr.length, '正在处理...'); // AI 优先模式:每道题都用 AI 回答 const aiFirstMode = GM_getValue("ai_first_mode"); if (aiFirstMode && GM_getValue("ai_api_key")) { console.log('★ AI优先模式:直接使用AI答题'); iframeMsg("tip", { tip: "AI优先模式:发送给AI..." }); // 构建 AI prompt const aiPrompt = buildAiPrompt(data); // 发送给 AI iframeMsg("ai_fill_question", { prompt: aiPrompt, question: data.question, style: 'warning-row' }); // 清除旧的 AI 答案 clearAiAnswerState(); // 等待 AI 返回 const waitStart = Date.now(); let aiAnswer = await waitForAiAnswer(60000, waitStart); // 延长到60秒 if (aiAnswer) { console.log('★ AI优先模式:收到答案', aiAnswer.substring(0, 30)); clearAiAnswerState(); const filled = await fillWithAiAnswer(aiAnswer, data, fillHander); if (filled) { const shortAnswer = updateAnswerDisplay(aiAnswer, 'success-row'); GLOBAL.successCount++; console.log('★ AI优先模式:填充成功', shortAnswer); } } else { console.log('★ AI优先模式:等待超时'); iframeMsg("tip", { tip: "AI 响应超时" }); } await fillFinish({ans: aiAnswer || '', question: data.question, style: aiAnswer ? 'success-row' : 'warning-row'}); continue; } const formatResult = await formatSearchAnswer(data); const hookAnswer = data.answer && data.answer.length > 0 && GM_getValue("start_pay"); const formatAns = hookAnswer ? { success: true, num: formatResult.num, list: [ data.answer ] } : formatResult; console.log('★ 搜题结果判断:', 'formatResult.answers:', !!formatResult.answers, 'formatAns.success:', formatAns.success, 'hookAnswer:', hookAnswer); if (formatResult.answers || formatAns.success) { iframeMsg("tip", { tip: "准备填充答案," + (formatAns.num === -1 ? "扫码可以请我喝杯茶哦" : "扫码可以请我喝杯茶哦:" + formatAns.num) }); const func = !hookAnswer && formatResult.answers ? defaultFillAnswer : defaultQuestionResolve; let r = await func(hookAnswer ? formatAns.list : formatAns.answers ? formatResult.answers : formatAns.list, data, fillHander, select.ignore_click ? select.ignore_click : () => { return false; }); console.log('搜题结果:', r.style, r.ans ? r.ans.substring(0, 20) : 'no ans'); // 判断答案是否无效(与 Vue 端保持一致) const ansText = r.ans || ''; const isInvalidAnswer = r.style === 'warning-row' || !r.ans || ansText.indexOf('无精确') !== -1 || ansText.indexOf('暂无') !== -1 || ansText.indexOf('未找到') !== -1 || ansText.trim() === '无'; console.log('★ 答案有效性判断: isInvalidAnswer=', isInvalidAnswer, 'style=', r.style, 'ans=', ansText.substring(0, 20)); // 搜题优先,只有搜题失败时才使用 AI 答案作为兜底 if (GLOBAL.lastAiAnswer) { if (isInvalidAnswer) { console.log('★★ 搜题无效,使用已保存的 AI 答案填充:', GLOBAL.lastAiAnswer.substring(0, 30)); const aiAnswer = GLOBAL.lastAiAnswer; GLOBAL.lastAiAnswer = null; // 使用 AI 答案填充 const filled = await fillWithAiAnswer(aiAnswer, data, fillHander); if (filled) { iframeMsg("push", { index: GLOBAL.index, question: r.question, answer: 'AI: ' + aiAnswer.substring(0, 50), style: 'success-row', options: data.options, type: data.type }); // 增加成功计数(AI 填充成功) GLOBAL.successCount++; await fillFinish(r); continue; // 继续下一题 } } else { // 搜题成功,清空 lastAiAnswer(不使用) console.log('搜题成功,清空不再需要的 AI 答案'); GLOBAL.lastAiAnswer = null; } } // 先保存到队列,再发送消息(顺序很重要!) // 使用队列存储,因为 AI 请求是异步的 if (!GLOBAL.pendingAiFillQueue) GLOBAL.pendingAiFillQueue = []; // 创建一个 Promise 用于等待 AI 填充完成 let aiResolve = null; const aiPromise = new Promise(resolve => { aiResolve = resolve; }); const queueItem = { data: data, fillHander: fillHander, questionIndex: GLOBAL.index, questionText: data.question, resolve: aiResolve // 保存 resolve 函数 }; GLOBAL.pendingAiFillQueue.push(queueItem); // 同时保存到 currentPendingItem 作为备用 GLOBAL.currentPendingItem = queueItem; console.log('★★★ 添加到队列成功,当前长度:', GLOBAL.pendingAiFillQueue.length, '题目:', data.question ? data.question.substring(0, 20) : 'no question'); console.log('★ currentPendingItem 已设置'); // 检查是否有之前已保存的 AI 答案 if (GLOBAL.lastAiAnswer && isInvalidAnswer) { console.log('发现已保存的 AI 答案,立即填充:', GLOBAL.lastAiAnswer.substring(0, 30)); const savedAnswer = GLOBAL.lastAiAnswer; GLOBAL.lastAiAnswer = null; // 清除,避免重复使用 setTimeout(() => { handleAiFill(savedAnswer); }, 100); } iframeMsg("push", { index: GLOBAL.index, question: r.question, answer: r.ans, style: r.style, options: data.options, type: data.type }); // 如果是无精确答案且开启了 AI 搜题,等待 AI 返回 const autoAiEnabled = GM_getValue("auto_ai_search"); console.log('等待条件检查: isInvalidAnswer=', isInvalidAnswer, 'autoAiEnabled=', autoAiEnabled); if (isInvalidAnswer && autoAiEnabled) { console.log('★★★ 开始等待 AI 返回答案(最多20秒)...'); iframeMsg("tip", { tip: "正在使用 AI 搜题,请稍候..." }); // 记录等待开始时间,只接受这之后保存的 AI 答案 const waitStartTime = Date.now(); // 清除旧的 AI 答案 clearAiAnswerState(); // 优化:使用更短的等待时间和更快的检查间隔 let waitTime = 0; const maxWait = 60000; // 延长到 60 秒 const checkInterval = 300; // 更快的检查间隔 // 每 500ms 检查一次 let aiAnswer = null; while (waitTime < maxWait) { await new Promise(resolve => setTimeout(resolve, checkInterval)); waitTime += checkInterval; // 同时检查 GM_getValue 和 GLOBAL(兼容不同上下文) const gmAnswer = GM_getValue('lastAiAnswer', ''); const gmTime = GM_getValue('lastAiAnswerTime', 0); const globalAnswer = GLOBAL.lastAiAnswer; // 只接受等待开始之后保存的答案 if ((gmAnswer && gmTime > waitStartTime) || globalAnswer) { aiAnswer = gmAnswer || globalAnswer; console.log('等待中发现 AI 答案:', aiAnswer.substring(0, 30), '时间差:', gmTime - waitStartTime); break; } if (waitTime % 2000 === 0) { console.log('等待 AI 中...', waitTime / 1000, '秒'); } } console.log('★★★ AI 等待结束,aiAnswer:', aiAnswer ? aiAnswer.substring(0, 30) : 'null'); // 等待结束后检查是否有 AI 答案 if (aiAnswer) { console.log('★★ 发现 AI 答案,立即填充'); clearAiAnswerState(); const filled = await fillWithAiAnswer(aiAnswer, data, fillHander); if (filled) { const shortAnswer = updateAnswerDisplay(aiAnswer, 'success-row'); r.ans = shortAnswer; r.style = 'success-row'; console.log('★★ AI 答案填充成功:', shortAnswer); } else { console.log('★★ AI 答案填充失败'); } } else { console.log('等待超时,没有收到 AI 答案,尝试重试...'); iframeMsg("tip", { tip: "AI 请求超时,正在重试..." }); iframeMsg("retry_ai", { prompt: buildAiPrompt(data), question: data.question }); clearAiAnswerState(); const retryAnswer = await waitForAiAnswer(60000, Date.now()); if (retryAnswer) { console.log('重试成功:', retryAnswer.substring(0, 30)); clearAiAnswerState(); const filled = await fillWithAiAnswer(retryAnswer, data, fillHander); if (filled) { const shortAnswer = updateAnswerDisplay(retryAnswer, 'success-row'); r.style = 'success-row'; console.log('★★ 重试填充成功:', shortAnswer); } } else { iframeMsg("tip", { tip: "AI 重试失败,继续下一题" }); } } } GM_getValue("start_pay") && String(GM_getValue("token")).length === 10 && catchAnswer(r); // 增加成功计数(搜题成功或 AI 填充成功) if (r.style === 'success-row') GLOBAL.successCount++; await fillFinish(r); } else { console.log('★ 搜题失败,进入 else 分支'); // 发送 push 消息触发 AI iframeMsg("push", { index: GLOBAL.index, question: data.question, answer: formatAns.msg || '无精确', style: 'warning-row', options: data.options, type: data.type }); // 等待 AI 返回(使用 GM_getValue 轮询) const autoAiEnabled = GM_getValue("auto_ai_search"); if (autoAiEnabled) { console.log('★★★ else分支:开始等待 AI 返回答案...'); iframeMsg("tip", { tip: "正在使用 AI 搜题,请稍候..." }); // 记录等待开始时间 const waitStartTime = Date.now(); // 清除旧的 AI 答案 clearAiAnswerState(); // 使用轮询检查 AI 答案 let waitTime = 0; const maxWait = 30000; const checkInterval = 500; let aiAnswer = null; while (waitTime < maxWait) { await new Promise(resolve => setTimeout(resolve, checkInterval)); waitTime += checkInterval; const gmAnswer = GM_getValue('lastAiAnswer', ''); const gmTime = GM_getValue('lastAiAnswerTime', 0); const globalAnswer = GLOBAL.lastAiAnswer; // 只接受等待开始之后保存的答案 if ((gmAnswer && gmTime > waitStartTime) || globalAnswer) { aiAnswer = gmAnswer || globalAnswer; console.log('else分支:发现 AI 答案:', aiAnswer.substring(0, 30), '时间差:', gmTime - waitStartTime); break; } if (waitTime % 2000 === 0) { console.log('else分支:等待 AI 中...', waitTime / 1000, '秒'); } } console.log('★★★ else分支:AI 等待结束,aiAnswer:', aiAnswer ? aiAnswer.substring(0, 30) : 'null'); if (aiAnswer) { console.log('★★ else分支:发现 AI 答案,填充'); clearAiAnswerState(); const filled = await fillWithAiAnswer(aiAnswer, data, fillHander); if (filled) { const shortAnswer = updateAnswerDisplay(aiAnswer, 'success-row'); GLOBAL.successCount++; console.log('★★ else分支:AI 答案填充成功:', shortAnswer); } } else { console.log('else分支:等待超时,没有收到 AI 答案,尝试重新发送请求...'); iframeMsg("tip", { tip: "AI 请求超时,正在重试..." }); // 使用公共函数构建 prompt 并重试 iframeMsg("retry_ai", { prompt: buildAiPrompt(data), question: data.question }); // 使用公共函数等待 clearAiAnswerState(); const retryAnswer = await waitForAiAnswer(25000, Date.now()); if (retryAnswer) { console.log('重试成功:', retryAnswer.substring(0, 30)); clearAiAnswerState(); const filled = await fillWithAiAnswer(retryAnswer, data, fillHander); if (filled) { const shortAnswer = updateAnswerDisplay(retryAnswer, 'success-row'); GLOBAL.successCount++; console.log('★★ 重试填充成功:', shortAnswer); } } else { iframeMsg("tip", { tip: "AI 重试失败,跳过此题" }); } } } await fillFinish({ans: '', question: data.question, style: 'warning-row'}); } } catch (e) { GLOBAL.index--; console.error('答题过程异常:', e); // 更友好的错误提示 let errorMsg = '答题异常'; if (e.message) { if (e.message.includes('network') || e.message.includes('Network')) { errorMsg = '网络异常,请检查网络连接'; } else if (e.message.includes('timeout')) { errorMsg = 'AI 响应超时'; } else { errorMsg = '异常: ' + e.message.substring(0, 50); } } iframeMsg("tip", { type: "error", tip: errorMsg }); // 自动尝试继续下一题 console.log('尝试继续下一题...'); } } }; }; var Typr = {}; Typr["parse"] = function(buff) { var readFont = function(data, idx, offset, tmap) { Typr["B"]; var T = Typr["T"]; var prsr = { cmap: T.cmap, head: T.head, hhea: T.hhea, maxp: T.maxp, hmtx: T.hmtx, name: T.name, "OS/2": T.OS2, post: T.post, loca: T.loca, kern: T.kern, glyf: T.glyf, "CFF ": T.CFF, "SVG ": T.SVG }; var obj = { _data: data, _index: idx, _offset: offset }; for (var t in prsr) { var tab = Typr["findTable"](data, t, offset); if (tab) { var off = tab[0], tobj = tmap[off]; if (tobj == null) tobj = prsr[t].parseTab(data, off, tab[1], obj); obj[t] = tmap[off] = tobj; } } return obj; }; var bin = Typr["B"]; var data = new Uint8Array(buff); var tmap = {}; var tag = bin.readASCII(data, 0, 4); if (tag == "ttcf") { var offset = 4; bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; var numF = bin.readUint(data, offset); offset += 4; var fnts = []; for (var i = 0; i < numF; i++) { var foff = bin.readUint(data, offset); offset += 4; fnts.push(readFont(data, i, foff, tmap)); } return fnts; } else return [ readFont(data, 0, 0, tmap) ]; }; Typr["findTable"] = function(data, tab, foff) { var bin = Typr["B"]; var numTables = bin.readUshort(data, foff + 4); var offset = foff + 12; for (var i = 0; i < numTables; i++) { var tag = bin.readASCII(data, offset, 4); bin.readUint(data, offset + 4); var toffset = bin.readUint(data, offset + 8); var length = bin.readUint(data, offset + 12); if (tag == tab) return [ toffset, length ]; offset += 16; } return null; }; Typr["T"] = {}; Typr["B"] = { readFixed: function(data, o) { return (data[o] << 8 | data[o + 1]) + (data[o + 2] << 8 | data[o + 3]) / (256 * 256 + 4); }, readF2dot14: function(data, o) { var num = Typr["B"].readShort(data, o); return num / 16384; }, readInt: function(buff, p) { var a = Typr["B"].t.uint8; a[0] = buff[p + 3]; a[1] = buff[p + 2]; a[2] = buff[p + 1]; a[3] = buff[p]; return Typr["B"].t.int32[0]; }, readInt8: function(buff, p) { var a = Typr["B"].t.uint8; a[0] = buff[p]; return Typr["B"].t.int8[0]; }, readShort: function(buff, p) { var a = Typr["B"].t.uint8; a[1] = buff[p]; a[0] = buff[p + 1]; return Typr["B"].t.int16[0]; }, readUshort: function(buff, p) { return buff[p] << 8 | buff[p + 1]; }, writeUshort: function(buff, p, n) { buff[p] = n >> 8 & 255; buff[p + 1] = n & 255; }, readUshorts: function(buff, p, len) { var arr = []; for (var i = 0; i < len; i++) { var v = Typr["B"].readUshort(buff, p + i * 2); arr.push(v); } return arr; }, readUint: function(buff, p) { var a = Typr["B"].t.uint8; a[3] = buff[p]; a[2] = buff[p + 1]; a[1] = buff[p + 2]; a[0] = buff[p + 3]; return Typr["B"].t.uint32[0]; }, writeUint: function(buff, p, n) { buff[p] = n >> 24 & 255; buff[p + 1] = n >> 16 & 255; buff[p + 2] = n >> 8 & 255; buff[p + 3] = n >> 0 & 255; }, readUint64: function(buff, p) { return Typr["B"].readUint(buff, p) * (4294967295 + 1) + Typr["B"].readUint(buff, p + 4); }, readASCII: function(buff, p, l) { var s = ""; for (var i = 0; i < l; i++) s += String.fromCharCode(buff[p + i]); return s; }, writeASCII: function(buff, p, s) { for (var i = 0; i < s.length; i++) buff[p + i] = s.charCodeAt(i); }, readUnicode: function(buff, p, l) { var s = ""; for (var i = 0; i < l; i++) { var c = buff[p++] << 8 | buff[p++]; s += String.fromCharCode(c); } return s; }, _tdec: window["TextDecoder"] ? new window["TextDecoder"]() : null, readUTF8: function(buff, p, l) { var tdec = Typr["B"]._tdec; if (tdec && p == 0 && l == buff.length) return tdec["decode"](buff); return Typr["B"].readASCII(buff, p, l); }, readBytes: function(buff, p, l) { var arr = []; for (var i = 0; i < l; i++) arr.push(buff[p + i]); return arr; }, readASCIIArray: function(buff, p, l) { var s = []; for (var i = 0; i < l; i++) s.push(String.fromCharCode(buff[p + i])); return s; }, t: function() { var ab = new ArrayBuffer(8); return { buff: ab, int8: new Int8Array(ab), uint8: new Uint8Array(ab), int16: new Int16Array(ab), uint16: new Uint16Array(ab), int32: new Int32Array(ab), uint32: new Uint32Array(ab) }; }() }; Typr["T"].CFF = { parseTab: function(data, offset, length) { var bin = Typr["B"]; var CFF = Typr["T"].CFF; data = new Uint8Array(data.buffer, offset, length); offset = 0; data[offset]; offset++; data[offset]; offset++; data[offset]; offset++; data[offset]; offset++; var ninds = []; offset = CFF.readIndex(data, offset, ninds); var names = []; for (var i = 0; i < ninds.length - 1; i++) names.push(bin.readASCII(data, offset + ninds[i], ninds[i + 1] - ninds[i])); offset += ninds[ninds.length - 1]; var tdinds = []; offset = CFF.readIndex(data, offset, tdinds); var topDicts = []; for (var i = 0; i < tdinds.length - 1; i++) topDicts.push(CFF.readDict(data, offset + tdinds[i], offset + tdinds[i + 1])); offset += tdinds[tdinds.length - 1]; var topdict = topDicts[0]; var sinds = []; offset = CFF.readIndex(data, offset, sinds); var strings = []; for (var i = 0; i < sinds.length - 1; i++) strings.push(bin.readASCII(data, offset + sinds[i], sinds[i + 1] - sinds[i])); offset += sinds[sinds.length - 1]; CFF.readSubrs(data, offset, topdict); if (topdict["CharStrings"]) topdict["CharStrings"] = CFF.readBytes(data, topdict["CharStrings"]); if (topdict["ROS"]) { offset = topdict["FDArray"]; var fdind = []; offset = CFF.readIndex(data, offset, fdind); topdict["FDArray"] = []; for (var i = 0; i < fdind.length - 1; i++) { var dict = CFF.readDict(data, offset + fdind[i], offset + fdind[i + 1]); CFF._readFDict(data, dict, strings); topdict["FDArray"].push(dict); } offset += fdind[fdind.length - 1]; offset = topdict["FDSelect"]; topdict["FDSelect"] = []; var fmt = data[offset]; offset++; if (fmt == 3) { var rns = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < rns + 1; i++) { topdict["FDSelect"].push(bin.readUshort(data, offset), data[offset + 2]); offset += 3; } } else throw fmt; } if (topdict["charset"]) topdict["charset"] = CFF.readCharset(data, topdict["charset"], topdict["CharStrings"].length); CFF._readFDict(data, topdict, strings); return topdict; }, _readFDict: function(data, dict, ss) { var CFF = Typr["T"].CFF; var offset; if (dict["Private"]) { offset = dict["Private"][1]; dict["Private"] = CFF.readDict(data, offset, offset + dict["Private"][0]); if (dict["Private"]["Subrs"]) CFF.readSubrs(data, offset + dict["Private"]["Subrs"], dict["Private"]); } for (var p in dict) if ([ "FamilyName", "FontName", "FullName", "Notice", "version", "Copyright" ].indexOf(p) != -1) dict[p] = ss[dict[p] - 426 + 35]; }, readSubrs: function(data, offset, obj) { obj["Subrs"] = Typr["T"].CFF.readBytes(data, offset); var bias, nSubrs = obj["Subrs"].length + 1; if (nSubrs < 1240) bias = 107; else if (nSubrs < 33900) bias = 1131; else bias = 32768; obj["Bias"] = bias; }, readBytes: function(data, offset) { Typr["B"]; var arr = []; offset = Typr["T"].CFF.readIndex(data, offset, arr); var subrs = [], arl = arr.length - 1, no = data.byteOffset + offset; for (var i = 0; i < arl; i++) { var ari = arr[i]; subrs.push(new Uint8Array(data.buffer, no + ari, arr[i + 1] - ari)); } return subrs; }, tableSE: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 0, 111, 112, 113, 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, 0, 123, 0, 124, 125, 126, 127, 128, 129, 130, 131, 0, 132, 133, 0, 134, 135, 136, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 139, 0, 0, 0, 0, 140, 141, 142, 143, 0, 0, 0, 0, 0, 144, 0, 0, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0 ], glyphByUnicode: function(cff, code) { for (var i = 0; i < cff["charset"].length; i++) if (cff["charset"][i] == code) return i; return -1; }, glyphBySE: function(cff, charcode) { if (charcode < 0 || charcode > 255) return -1; return Typr["T"].CFF.glyphByUnicode(cff, Typr["T"].CFF.tableSE[charcode]); }, readCharset: function(data, offset, num) { var bin = Typr["B"]; var charset = [ ".notdef" ]; var format = data[offset]; offset++; if (format == 0) { for (var i = 0; i < num; i++) { var first = bin.readUshort(data, offset); offset += 2; charset.push(first); } } else if (format == 1 || format == 2) { while (charset.length < num) { var first = bin.readUshort(data, offset); offset += 2; var nLeft = 0; if (format == 1) { nLeft = data[offset]; offset++; } else { nLeft = bin.readUshort(data, offset); offset += 2; } for (var i = 0; i <= nLeft; i++) { charset.push(first); first++; } } } else throw "error: format: " + format; return charset; }, readIndex: function(data, offset, inds) { var bin = Typr["B"]; var count = bin.readUshort(data, offset) + 1; offset += 2; var offsize = data[offset]; offset++; if (offsize == 1) for (var i = 0; i < count; i++) inds.push(data[offset + i]); else if (offsize == 2) for (var i = 0; i < count; i++) inds.push(bin.readUshort(data, offset + i * 2)); else if (offsize == 3) for (var i = 0; i < count; i++) inds.push(bin.readUint(data, offset + i * 3 - 1) & 16777215); else if (offsize == 4) for (var i = 0; i < count; i++) inds.push(bin.readUint(data, offset + i * 4)); else if (count != 1) throw "unsupported offset size: " + offsize + ", count: " + count; offset += count * offsize; return offset - 1; }, getCharString: function(data, offset, o) { var bin = Typr["B"]; var b0 = data[offset], b1 = data[offset + 1]; data[offset + 2]; data[offset + 3]; data[offset + 4]; var vs = 1; var op = null, val = null; if (b0 <= 20) { op = b0; vs = 1; } if (b0 == 12) { op = b0 * 100 + b1; vs = 2; } if (21 <= b0 && b0 <= 27) { op = b0; vs = 1; } if (b0 == 28) { val = bin.readShort(data, offset + 1); vs = 3; } if (29 <= b0 && b0 <= 31) { op = b0; vs = 1; } if (32 <= b0 && b0 <= 246) { val = b0 - 139; vs = 1; } if (247 <= b0 && b0 <= 250) { val = (b0 - 247) * 256 + b1 + 108; vs = 2; } if (251 <= b0 && b0 <= 254) { val = -(b0 - 251) * 256 - b1 - 108; vs = 2; } if (b0 == 255) { val = bin.readInt(data, offset + 1) / 65535; vs = 5; } o.val = val != null ? val : "o" + op; o.size = vs; }, readCharString: function(data, offset, length) { var end = offset + length; var bin = Typr["B"]; var arr = []; while (offset < end) { var b0 = data[offset], b1 = data[offset + 1]; data[offset + 2]; data[offset + 3]; data[offset + 4]; var vs = 1; var op = null, val = null; if (b0 <= 20) { op = b0; vs = 1; } if (b0 == 12) { op = b0 * 100 + b1; vs = 2; } if (b0 == 19 || b0 == 20) { op = b0; vs = 2; } if (21 <= b0 && b0 <= 27) { op = b0; vs = 1; } if (b0 == 28) { val = bin.readShort(data, offset + 1); vs = 3; } if (29 <= b0 && b0 <= 31) { op = b0; vs = 1; } if (32 <= b0 && b0 <= 246) { val = b0 - 139; vs = 1; } if (247 <= b0 && b0 <= 250) { val = (b0 - 247) * 256 + b1 + 108; vs = 2; } if (251 <= b0 && b0 <= 254) { val = -(b0 - 251) * 256 - b1 - 108; vs = 2; } if (b0 == 255) { val = bin.readInt(data, offset + 1) / 65535; vs = 5; } arr.push(val != null ? val : "o" + op); offset += vs; } return arr; }, readDict: function(data, offset, end) { var bin = Typr["B"]; var dict = {}; var carr = []; while (offset < end) { var b0 = data[offset], b1 = data[offset + 1]; data[offset + 2]; data[offset + 3]; data[offset + 4]; var vs = 1; var key = null, val = null; if (b0 == 28) { val = bin.readShort(data, offset + 1); vs = 3; } if (b0 == 29) { val = bin.readInt(data, offset + 1); vs = 5; } if (32 <= b0 && b0 <= 246) { val = b0 - 139; vs = 1; } if (247 <= b0 && b0 <= 250) { val = (b0 - 247) * 256 + b1 + 108; vs = 2; } if (251 <= b0 && b0 <= 254) { val = -(b0 - 251) * 256 - b1 - 108; vs = 2; } if (b0 == 255) { val = bin.readInt(data, offset + 1) / 65535; vs = 5; throw "unknown number"; } if (b0 == 30) { var nibs = []; vs = 1; while (true) { var b = data[offset + vs]; vs++; var nib0 = b >> 4, nib1 = b & 15; if (nib0 != 15) nibs.push(nib0); if (nib1 != 15) nibs.push(nib1); if (nib1 == 15) break; } var s = ""; var chars = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ".", "e", "e-", "reserved", "-", "endOfNumber" ]; for (var i = 0; i < nibs.length; i++) s += chars[nibs[i]]; val = parseFloat(s); } if (b0 <= 21) { var keys = [ "version", "Notice", "FullName", "FamilyName", "Weight", "FontBBox", "BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW", "escape", "UniqueID", "XUID", "charset", "Encoding", "CharStrings", "Private", "Subrs", "defaultWidthX", "nominalWidthX" ]; key = keys[b0]; vs = 1; if (b0 == 12) { var keys = [ "Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition", "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix", "StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz", "StemSnapH", "StemSnapV", "ForceBold", "", "", "LanguageGroup", "ExpansionFactor", "initialRandomSeed", "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend", "", "", "", "", "", "", "ROS", "CIDFontVersion", "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase", "FDArray", "FDSelect", "FontName" ]; key = keys[b1]; vs = 2; } } if (key != null) { dict[key] = carr.length == 1 ? carr[0] : carr; carr = []; } else carr.push(val); offset += vs; } return dict; } }; Typr["T"].cmap = { parseTab: function(data, offset, length) { var obj = { tables: [], ids: {}, off: offset }; data = new Uint8Array(data.buffer, offset, length); offset = 0; var bin = Typr["B"], rU = bin.readUshort, cmap = Typr["T"].cmap; rU(data, offset); offset += 2; var numTables = rU(data, offset); offset += 2; var offs = []; for (var i = 0; i < numTables; i++) { var platformID = rU(data, offset); offset += 2; var encodingID = rU(data, offset); offset += 2; var noffset = bin.readUint(data, offset); offset += 4; var id = "p" + platformID + "e" + encodingID; var tind = offs.indexOf(noffset); if (tind == -1) { tind = obj.tables.length; var subt = {}; offs.push(noffset); var format = subt.format = rU(data, noffset); if (format == 0) subt = cmap.parse0(data, noffset, subt); else if (format == 4) subt = cmap.parse4(data, noffset, subt); else if (format == 6) subt = cmap.parse6(data, noffset, subt); else if (format == 12) subt = cmap.parse12(data, noffset, subt); obj.tables.push(subt); } if (obj.ids[id] != null) throw "multiple tables for one platform+encoding"; obj.ids[id] = tind; } return obj; }, parse0: function(data, offset, obj) { var bin = Typr["B"]; offset += 2; var len = bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; obj.map = []; for (var i = 0; i < len - 6; i++) obj.map.push(data[offset + i]); return obj; }, parse4: function(data, offset, obj) { var bin = Typr["B"], rU = bin.readUshort, rUs = bin.readUshorts; var offset0 = offset; offset += 2; var length = rU(data, offset); offset += 2; rU(data, offset); offset += 2; var segCountX2 = rU(data, offset); offset += 2; var segCount = segCountX2 >>> 1; obj.searchRange = rU(data, offset); offset += 2; obj.entrySelector = rU(data, offset); offset += 2; obj.rangeShift = rU(data, offset); offset += 2; obj.endCount = rUs(data, offset, segCount); offset += segCount * 2; offset += 2; obj.startCount = rUs(data, offset, segCount); offset += segCount * 2; obj.idDelta = []; for (var i = 0; i < segCount; i++) { obj.idDelta.push(bin.readShort(data, offset)); offset += 2; } obj.idRangeOffset = rUs(data, offset, segCount); offset += segCount * 2; obj.glyphIdArray = rUs(data, offset, offset0 + length - offset >>> 1); return obj; }, parse6: function(data, offset, obj) { var bin = Typr["B"]; offset += 2; bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; obj.firstCode = bin.readUshort(data, offset); offset += 2; var entryCount = bin.readUshort(data, offset); offset += 2; obj.glyphIdArray = []; for (var i = 0; i < entryCount; i++) { obj.glyphIdArray.push(bin.readUshort(data, offset)); offset += 2; } return obj; }, parse12: function(data, offset, obj) { var bin = Typr["B"], rU = bin.readUint; offset += 4; rU(data, offset); offset += 4; rU(data, offset); offset += 4; var nGroups = rU(data, offset) * 3; offset += 4; var gps = obj.groups = new Uint32Array(nGroups); for (var i = 0; i < nGroups; i += 3) { gps[i] = rU(data, offset + (i << 2)); gps[i + 1] = rU(data, offset + (i << 2) + 4); gps[i + 2] = rU(data, offset + (i << 2) + 8); } return obj; } }; Typr["T"].glyf = { parseTab: function(data, offset, length, font) { var obj = [], ng = font["maxp"]["numGlyphs"]; for (var g = 0; g < ng; g++) obj.push(null); return obj; }, _parseGlyf: function(font, g) { var bin = Typr["B"]; var data = font["_data"], loca = font["loca"]; if (loca[g] == loca[g + 1]) return null; var offset = Typr["findTable"](data, "glyf", font["_offset"])[0] + loca[g]; var gl = {}; gl.noc = bin.readShort(data, offset); offset += 2; gl.xMin = bin.readShort(data, offset); offset += 2; gl.yMin = bin.readShort(data, offset); offset += 2; gl.xMax = bin.readShort(data, offset); offset += 2; gl.yMax = bin.readShort(data, offset); offset += 2; if (gl.xMin >= gl.xMax || gl.yMin >= gl.yMax) return null; if (gl.noc > 0) { gl.endPts = []; for (var i = 0; i < gl.noc; i++) { gl.endPts.push(bin.readUshort(data, offset)); offset += 2; } var instructionLength = bin.readUshort(data, offset); offset += 2; if (data.length - offset < instructionLength) return null; gl.instructions = bin.readBytes(data, offset, instructionLength); offset += instructionLength; var crdnum = gl.endPts[gl.noc - 1] + 1; gl.flags = []; for (var i = 0; i < crdnum; i++) { var flag = data[offset]; offset++; gl.flags.push(flag); if ((flag & 8) != 0) { var rep = data[offset]; offset++; for (var j = 0; j < rep; j++) { gl.flags.push(flag); i++; } } } gl.xs = []; for (var i = 0; i < crdnum; i++) { var i8 = (gl.flags[i] & 2) != 0, same = (gl.flags[i] & 16) != 0; if (i8) { gl.xs.push(same ? data[offset] : -data[offset]); offset++; } else { if (same) gl.xs.push(0); else { gl.xs.push(bin.readShort(data, offset)); offset += 2; } } } gl.ys = []; for (var i = 0; i < crdnum; i++) { var i8 = (gl.flags[i] & 4) != 0, same = (gl.flags[i] & 32) != 0; if (i8) { gl.ys.push(same ? data[offset] : -data[offset]); offset++; } else { if (same) gl.ys.push(0); else { gl.ys.push(bin.readShort(data, offset)); offset += 2; } } } var x = 0, y = 0; for (var i = 0; i < crdnum; i++) { x += gl.xs[i]; y += gl.ys[i]; gl.xs[i] = x; gl.ys[i] = y; } } else { var ARG_1_AND_2_ARE_WORDS = 1 << 0; var ARGS_ARE_XY_VALUES = 1 << 1; var WE_HAVE_A_SCALE = 1 << 3; var MORE_COMPONENTS = 1 << 5; var WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; var WE_HAVE_A_TWO_BY_TWO = 1 << 7; var WE_HAVE_INSTRUCTIONS = 1 << 8; gl.parts = []; var flags; do { flags = bin.readUshort(data, offset); offset += 2; var part = { m: { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }, p1: -1, p2: -1 }; gl.parts.push(part); part.glyphIndex = bin.readUshort(data, offset); offset += 2; if (flags & ARG_1_AND_2_ARE_WORDS) { var arg1 = bin.readShort(data, offset); offset += 2; var arg2 = bin.readShort(data, offset); offset += 2; } else { var arg1 = bin.readInt8(data, offset); offset++; var arg2 = bin.readInt8(data, offset); offset++; } if (flags & ARGS_ARE_XY_VALUES) { part.m.tx = arg1; part.m.ty = arg2; } else { part.p1 = arg1; part.p2 = arg2; } if (flags & WE_HAVE_A_SCALE) { part.m.a = part.m.d = bin.readF2dot14(data, offset); offset += 2; } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { part.m.a = bin.readF2dot14(data, offset); offset += 2; part.m.d = bin.readF2dot14(data, offset); offset += 2; } else if (flags & WE_HAVE_A_TWO_BY_TWO) { part.m.a = bin.readF2dot14(data, offset); offset += 2; part.m.b = bin.readF2dot14(data, offset); offset += 2; part.m.c = bin.readF2dot14(data, offset); offset += 2; part.m.d = bin.readF2dot14(data, offset); offset += 2; } } while (flags & MORE_COMPONENTS); if (flags & WE_HAVE_INSTRUCTIONS) { var numInstr = bin.readUshort(data, offset); offset += 2; gl.instr = []; for (var i = 0; i < numInstr; i++) { gl.instr.push(data[offset]); offset++; } } } return gl; } }; Typr["T"].head = { parseTab: function(data, offset, length) { var bin = Typr["B"]; var obj = {}; bin.readFixed(data, offset); offset += 4; obj["fontRevision"] = bin.readFixed(data, offset); offset += 4; bin.readUint(data, offset); offset += 4; bin.readUint(data, offset); offset += 4; obj["flags"] = bin.readUshort(data, offset); offset += 2; obj["unitsPerEm"] = bin.readUshort(data, offset); offset += 2; obj["created"] = bin.readUint64(data, offset); offset += 8; obj["modified"] = bin.readUint64(data, offset); offset += 8; obj["xMin"] = bin.readShort(data, offset); offset += 2; obj["yMin"] = bin.readShort(data, offset); offset += 2; obj["xMax"] = bin.readShort(data, offset); offset += 2; obj["yMax"] = bin.readShort(data, offset); offset += 2; obj["macStyle"] = bin.readUshort(data, offset); offset += 2; obj["lowestRecPPEM"] = bin.readUshort(data, offset); offset += 2; obj["fontDirectionHint"] = bin.readShort(data, offset); offset += 2; obj["indexToLocFormat"] = bin.readShort(data, offset); offset += 2; obj["glyphDataFormat"] = bin.readShort(data, offset); offset += 2; return obj; } }; Typr["T"].hhea = { parseTab: function(data, offset, length) { var bin = Typr["B"]; var obj = {}; bin.readFixed(data, offset); offset += 4; var keys = [ "ascender", "descender", "lineGap", "advanceWidthMax", "minLeftSideBearing", "minRightSideBearing", "xMaxExtent", "caretSlopeRise", "caretSlopeRun", "caretOffset", "res0", "res1", "res2", "res3", "metricDataFormat", "numberOfHMetrics" ]; for (var i = 0; i < keys.length; i++) { var key = keys[i]; var func = key == "advanceWidthMax" || key == "numberOfHMetrics" ? bin.readUshort : bin.readShort; obj[key] = func(data, offset + i * 2); } return obj; } }; Typr["T"].hmtx = { parseTab: function(data, offset, length, font) { var bin = Typr["B"]; var aWidth = []; var lsBearing = []; var nG = font["maxp"]["numGlyphs"], nH = font["hhea"]["numberOfHMetrics"]; var aw = 0, lsb = 0, i = 0; while (i < nH) { aw = bin.readUshort(data, offset + (i << 2)); lsb = bin.readShort(data, offset + (i << 2) + 2); aWidth.push(aw); lsBearing.push(lsb); i++; } while (i < nG) { aWidth.push(aw); lsBearing.push(lsb); i++; } return { aWidth: aWidth, lsBearing: lsBearing }; } }; Typr["T"].kern = { parseTab: function(data, offset, length, font) { var bin = Typr["B"], kern = Typr["T"].kern; var version = bin.readUshort(data, offset); if (version == 1) return kern.parseV1(data, offset, length, font); var nTables = bin.readUshort(data, offset + 2); offset += 4; var map = { glyph1: [], rval: [] }; for (var i = 0; i < nTables; i++) { offset += 2; var length = bin.readUshort(data, offset); offset += 2; var coverage = bin.readUshort(data, offset); offset += 2; var format = coverage >>> 8; format &= 15; if (format == 0) offset = kern.readFormat0(data, offset, map); } return map; }, parseV1: function(data, offset, length, font) { var bin = Typr["B"], kern = Typr["T"].kern; bin.readFixed(data, offset); var nTables = bin.readUint(data, offset + 4); offset += 8; var map = { glyph1: [], rval: [] }; for (var i = 0; i < nTables; i++) { bin.readUint(data, offset); offset += 4; var coverage = bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; var format = coverage & 255; if (format == 0) offset = kern.readFormat0(data, offset, map); } return map; }, readFormat0: function(data, offset, map) { var bin = Typr["B"], rUs = bin.readUshort; var pleft = -1; var nPairs = rUs(data, offset); rUs(data, offset + 2); rUs(data, offset + 4); rUs(data, offset + 6); offset += 8; for (var j = 0; j < nPairs; j++) { var left = rUs(data, offset); offset += 2; var right = rUs(data, offset); offset += 2; var value = bin.readShort(data, offset); offset += 2; if (left != pleft) { map.glyph1.push(left); map.rval.push({ glyph2: [], vals: [] }); } var rval = map.rval[map.rval.length - 1]; rval.glyph2.push(right); rval.vals.push(value); pleft = left; } return offset; } }; Typr["T"].loca = { parseTab: function(data, offset, length, font) { var bin = Typr["B"]; var obj = []; var ver = font["head"]["indexToLocFormat"]; var len = font["maxp"]["numGlyphs"] + 1; if (ver == 0) for (var i = 0; i < len; i++) obj.push(bin.readUshort(data, offset + (i << 1)) << 1); if (ver == 1) for (var i = 0; i < len; i++) obj.push(bin.readUint(data, offset + (i << 2))); return obj; } }; Typr["T"].maxp = { parseTab: function(data, offset, length) { var bin = Typr["B"], rU = bin.readUshort; var obj = {}; bin.readUint(data, offset); offset += 4; obj["numGlyphs"] = rU(data, offset); offset += 2; return obj; } }; Typr["T"].name = { parseTab: function(data, offset, length) { var bin = Typr["B"]; var obj = {}; bin.readUshort(data, offset); offset += 2; var count = bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; var names = [ "copyright", "fontFamily", "fontSubfamily", "ID", "fullName", "version", "postScriptName", "trademark", "manufacturer", "designer", "description", "urlVendor", "urlDesigner", "licence", "licenceURL", "---", "typoFamilyName", "typoSubfamilyName", "compatibleFull", "sampleText", "postScriptCID", "wwsFamilyName", "wwsSubfamilyName", "lightPalette", "darkPalette" ]; var offset0 = offset; var rU = bin.readUshort; for (var i = 0; i < count; i++) { var platformID = rU(data, offset); offset += 2; var encodingID = rU(data, offset); offset += 2; var languageID = rU(data, offset); offset += 2; var nameID = rU(data, offset); offset += 2; var slen = rU(data, offset); offset += 2; var noffset = rU(data, offset); offset += 2; var soff = offset0 + count * 12 + noffset; var str; if (platformID == 0) str = bin.readUnicode(data, soff, slen / 2); else if (platformID == 3 && encodingID == 0) str = bin.readUnicode(data, soff, slen / 2); else if (encodingID == 0) str = bin.readASCII(data, soff, slen); else if (encodingID == 1) str = bin.readUnicode(data, soff, slen / 2); else if (encodingID == 3) str = bin.readUnicode(data, soff, slen / 2); else if (encodingID == 4) str = bin.readUnicode(data, soff, slen / 2); else if (encodingID == 10) str = bin.readUnicode(data, soff, slen / 2); else if (platformID == 1) { str = bin.readASCII(data, soff, slen); console.log("reading unknown MAC encoding " + encodingID + " as ASCII"); } else { console.log("unknown encoding " + encodingID + ", platformID: " + platformID); str = bin.readASCII(data, soff, slen); } var tid = "p" + platformID + "," + languageID.toString(16); if (obj[tid] == null) obj[tid] = {}; obj[tid][names[nameID]] = str; obj[tid]["_lang"] = languageID; } var psn = "postScriptName"; for (var p in obj) if (obj[p][psn] != null && obj[p]["_lang"] == 1033) return obj[p]; for (var p in obj) if (obj[p][psn] != null && obj[p]["_lang"] == 0) return obj[p]; for (var p in obj) if (obj[p][psn] != null && obj[p]["_lang"] == 3084) return obj[p]; for (var p in obj) if (obj[p][psn] != null) return obj[p]; var out; for (var p in obj) { out = obj[p]; break; } console.log("returning name table with languageID " + out._lang); if (out[psn] == null && out["ID"] != null) out[psn] = out["ID"]; return out; } }; Typr["T"].OS2 = { parseTab: function(data, offset, length) { var bin = Typr["B"]; var ver = bin.readUshort(data, offset); offset += 2; var OS2 = Typr["T"].OS2; var obj = {}; if (ver == 0) OS2.version0(data, offset, obj); else if (ver == 1) OS2.version1(data, offset, obj); else if (ver == 2 || ver == 3 || ver == 4) OS2.version2(data, offset, obj); else if (ver == 5) OS2.version5(data, offset, obj); else throw "unknown OS/2 table version: " + ver; return obj; }, version0: function(data, offset, obj) { var bin = Typr["B"]; obj["xAvgCharWidth"] = bin.readShort(data, offset); offset += 2; obj["usWeightClass"] = bin.readUshort(data, offset); offset += 2; obj["usWidthClass"] = bin.readUshort(data, offset); offset += 2; obj["fsType"] = bin.readUshort(data, offset); offset += 2; obj["ySubscriptXSize"] = bin.readShort(data, offset); offset += 2; obj["ySubscriptYSize"] = bin.readShort(data, offset); offset += 2; obj["ySubscriptXOffset"] = bin.readShort(data, offset); offset += 2; obj["ySubscriptYOffset"] = bin.readShort(data, offset); offset += 2; obj["ySuperscriptXSize"] = bin.readShort(data, offset); offset += 2; obj["ySuperscriptYSize"] = bin.readShort(data, offset); offset += 2; obj["ySuperscriptXOffset"] = bin.readShort(data, offset); offset += 2; obj["ySuperscriptYOffset"] = bin.readShort(data, offset); offset += 2; obj["yStrikeoutSize"] = bin.readShort(data, offset); offset += 2; obj["yStrikeoutPosition"] = bin.readShort(data, offset); offset += 2; obj["sFamilyClass"] = bin.readShort(data, offset); offset += 2; obj["panose"] = bin.readBytes(data, offset, 10); offset += 10; obj["ulUnicodeRange1"] = bin.readUint(data, offset); offset += 4; obj["ulUnicodeRange2"] = bin.readUint(data, offset); offset += 4; obj["ulUnicodeRange3"] = bin.readUint(data, offset); offset += 4; obj["ulUnicodeRange4"] = bin.readUint(data, offset); offset += 4; obj["achVendID"] = bin.readASCII(data, offset, 4); offset += 4; obj["fsSelection"] = bin.readUshort(data, offset); offset += 2; obj["usFirstCharIndex"] = bin.readUshort(data, offset); offset += 2; obj["usLastCharIndex"] = bin.readUshort(data, offset); offset += 2; obj["sTypoAscender"] = bin.readShort(data, offset); offset += 2; obj["sTypoDescender"] = bin.readShort(data, offset); offset += 2; obj["sTypoLineGap"] = bin.readShort(data, offset); offset += 2; obj["usWinAscent"] = bin.readUshort(data, offset); offset += 2; obj["usWinDescent"] = bin.readUshort(data, offset); offset += 2; return offset; }, version1: function(data, offset, obj) { var bin = Typr["B"]; offset = Typr["T"].OS2.version0(data, offset, obj); obj["ulCodePageRange1"] = bin.readUint(data, offset); offset += 4; obj["ulCodePageRange2"] = bin.readUint(data, offset); offset += 4; return offset; }, version2: function(data, offset, obj) { var bin = Typr["B"], rU = bin.readUshort; offset = Typr["T"].OS2.version1(data, offset, obj); obj["sxHeight"] = bin.readShort(data, offset); offset += 2; obj["sCapHeight"] = bin.readShort(data, offset); offset += 2; obj["usDefault"] = rU(data, offset); offset += 2; obj["usBreak"] = rU(data, offset); offset += 2; obj["usMaxContext"] = rU(data, offset); offset += 2; return offset; }, version5: function(data, offset, obj) { var rU = Typr["B"].readUshort; offset = Typr["T"].OS2.version2(data, offset, obj); obj["usLowerOpticalPointSize"] = rU(data, offset); offset += 2; obj["usUpperOpticalPointSize"] = rU(data, offset); offset += 2; return offset; } }; Typr["T"].post = { parseTab: function(data, offset, length) { var bin = Typr["B"]; var obj = {}; obj["version"] = bin.readFixed(data, offset); offset += 4; obj["italicAngle"] = bin.readFixed(data, offset); offset += 4; obj["underlinePosition"] = bin.readShort(data, offset); offset += 2; obj["underlineThickness"] = bin.readShort(data, offset); offset += 2; return obj; } }; Typr["T"].SVG = { parseTab: function(data, offset, length) { var bin = Typr["B"]; var obj = { entries: [] }; var offset0 = offset; bin.readUshort(data, offset); offset += 2; var svgDocIndexOffset = bin.readUint(data, offset); offset += 4; bin.readUint(data, offset); offset += 4; offset = svgDocIndexOffset + offset0; var numEntries = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < numEntries; i++) { var startGlyphID = bin.readUshort(data, offset); offset += 2; var endGlyphID = bin.readUshort(data, offset); offset += 2; var svgDocOffset = bin.readUint(data, offset); offset += 4; var svgDocLength = bin.readUint(data, offset); offset += 4; var sbuf = new Uint8Array(data.buffer, offset0 + svgDocOffset + svgDocIndexOffset, svgDocLength); var svg = bin.readUTF8(sbuf, 0, sbuf.length); for (var f = startGlyphID; f <= endGlyphID; f++) { obj.entries[f] = svg; } } return obj; } }; Typr["U"] = { shape: function(font, str, ltr) { var getGlyphPosition = function(font, gls, i1, ltr) { var g1 = gls[i1], g2 = gls[i1 + 1], kern = font["kern"]; if (kern) { var ind1 = kern.glyph1.indexOf(g1); if (ind1 != -1) { var ind2 = kern.rval[ind1].glyph2.indexOf(g2); if (ind2 != -1) return [ 0, 0, kern.rval[ind1].vals[ind2], 0 ]; } } return [ 0, 0, 0, 0 ]; }; var gls = []; for (var i = 0; i < str.length; i++) { var cc = str.codePointAt(i); if (cc > 65535) i++; gls.push(Typr["U"]["codeToGlyph"](font, cc)); } var shape = []; for (var i = 0; i < gls.length; i++) { var padj = getGlyphPosition(font, gls, i); var gid = gls[i]; var ax = font["hmtx"].aWidth[gid] + padj[2]; shape.push({ g: gid, cl: i, dx: 0, dy: 0, ax: ax, ay: 0 }); } return shape; }, shapeToPath: function(font, shape, clr) { var tpath = { cmds: [], crds: [] }; var x = 0, y = 0; for (var i = 0; i < shape.length; i++) { var it = shape[i]; var path = Typr["U"]["glyphToPath"](font, it["g"]), crds = path["crds"]; for (var j = 0; j < crds.length; j += 2) { tpath.crds.push(crds[j] + x + it["dx"]); tpath.crds.push(crds[j + 1] + y + it["dy"]); } if (clr) tpath.cmds.push(clr); for (var j = 0; j < path["cmds"].length; j++) tpath.cmds.push(path["cmds"][j]); var clen = tpath.cmds.length; if (clr) if (clen != 0 && tpath.cmds[clen - 1] != "X") tpath.cmds.push("X"); x += it["ax"]; y += it["ay"]; } return { cmds: tpath.cmds, crds: tpath.crds }; }, codeToGlyph: function(font, code) { var cmap = font["cmap"]; var tind = -1, pps = [ "p3e10", "p0e4", "p3e1", "p1e0", "p0e3", "p0e1" ]; for (var i = 0; i < pps.length; i++) if (cmap.ids[pps[i]] != null) { tind = cmap.ids[pps[i]]; break; } if (tind == -1) throw "no familiar platform and encoding!"; var arrSearch = function(arr, k, v) { var l = 0, r = Math.floor(arr.length / k); while (l + 1 != r) { var mid = l + (r - l >>> 1); if (arr[mid * k] <= v) l = mid; else r = mid; } return l * k; }; var tab = cmap.tables[tind], fmt = tab.format, gid = -1; if (fmt == 0) { if (code >= tab.map.length) gid = 0; else gid = tab.map[code]; } else if (fmt == 4) { var sind = -1, ec = tab.endCount; if (code > ec[ec.length - 1]) sind = -1; else { sind = arrSearch(ec, 1, code); if (ec[sind] < code) sind++; } if (sind == -1) gid = 0; else if (code < tab.startCount[sind]) gid = 0; else { var gli = 0; if (tab.idRangeOffset[sind] != 0) gli = tab.glyphIdArray[code - tab.startCount[sind] + (tab.idRangeOffset[sind] >> 1) - (tab.idRangeOffset.length - sind)]; else gli = code + tab.idDelta[sind]; gid = gli & 65535; } } else if (fmt == 6) { var off = code - tab.firstCode, arr = tab.glyphIdArray; if (off < 0 || off >= arr.length) gid = 0; else gid = arr[off]; } else if (fmt == 12) { var grp = tab.groups; if (code > grp[grp.length - 2]) gid = 0; else { var i = arrSearch(grp, 3, code); if (grp[i] <= code && code <= grp[i + 1]) { gid = grp[i + 2] + (code - grp[i]); } if (gid == -1) gid = 0; } } else throw "unknown cmap table format " + tab.format; var SVG = font["SVG "], loca = font["loca"]; if (gid != 0 && font["CFF "] == null && (SVG == null || SVG.entries[gid] == null) && loca[gid] == loca[gid + 1] && [ 9, 10, 11, 12, 13, 32, 133, 160, 5760, 8232, 8233, 8239, 12288, 6158, 8203, 8204, 8205, 8288, 65279 ].indexOf(code) == -1 && !(8192 <= code && code <= 8202)) gid = 0; return gid; }, glyphToPath: function(font, gid) { var path = { cmds: [], crds: [] }; var SVG = font["SVG "], CFF = font["CFF "]; var U = Typr["U"]; if (SVG && SVG.entries[gid]) { var p = SVG.entries[gid]; if (p != null) { if (typeof p == "string") { p = U["SVG"].toPath(p); SVG.entries[gid] = p; } path = p; } } else if (CFF) { var pdct = CFF["Private"]; var state = { x: 0, y: 0, stack: [], nStems: 0, haveWidth: false, width: pdct ? pdct["defaultWidthX"] : 0, open: false }; if (CFF["ROS"]) { var gi = 0; while (CFF["FDSelect"][gi + 2] <= gid) gi += 2; pdct = CFF["FDArray"][CFF["FDSelect"][gi + 1]]["Private"]; } U["_drawCFF"](CFF["CharStrings"][gid], state, CFF, pdct, path); } else if (font["glyf"]) { U["_drawGlyf"](gid, font, path); } return { cmds: path.cmds, crds: path.crds }; }, _drawGlyf: function(gid, font, path) { var gl = font["glyf"][gid]; if (gl == null) gl = font["glyf"][gid] = Typr["T"].glyf._parseGlyf(font, gid); if (gl != null) { if (gl.noc > -1) Typr["U"]["_simpleGlyph"](gl, path); else Typr["U"]["_compoGlyph"](gl, font, path); } }, _simpleGlyph: function(gl, p) { var P = Typr["U"]["P"]; for (var c = 0; c < gl.noc; c++) { var i0 = c == 0 ? 0 : gl.endPts[c - 1] + 1; var il = gl.endPts[c]; for (var i = i0; i <= il; i++) { var pr = i == i0 ? il : i - 1; var nx = i == il ? i0 : i + 1; var onCurve = gl.flags[i] & 1; var prOnCurve = gl.flags[pr] & 1; var nxOnCurve = gl.flags[nx] & 1; var x = gl.xs[i], y = gl.ys[i]; if (i == i0) { if (onCurve) { if (prOnCurve) P.MoveTo(p, gl.xs[pr], gl.ys[pr]); else { P.MoveTo(p, x, y); continue; } } else { if (prOnCurve) P.MoveTo(p, gl.xs[pr], gl.ys[pr]); else P.MoveTo(p, Math.floor((gl.xs[pr] + x) * .5), Math.floor((gl.ys[pr] + y) * .5)); } } if (onCurve) { if (prOnCurve) P.LineTo(p, x, y); } else { if (nxOnCurve) P.qCurveTo(p, x, y, gl.xs[nx], gl.ys[nx]); else P.qCurveTo(p, x, y, Math.floor((x + gl.xs[nx]) * .5), Math.floor((y + gl.ys[nx]) * .5)); } } P.ClosePath(p); } }, _compoGlyph: function(gl, font, p) { for (var j = 0; j < gl.parts.length; j++) { var path = { cmds: [], crds: [] }; var prt = gl.parts[j]; Typr["U"]["_drawGlyf"](prt.glyphIndex, font, path); var m = prt.m; for (var i = 0; i < path.crds.length; i += 2) { var x = path.crds[i], y = path.crds[i + 1]; p.crds.push(x * m.a + y * m.b + m.tx); p.crds.push(x * m.c + y * m.d + m.ty); } for (var i = 0; i < path.cmds.length; i++) p.cmds.push(path.cmds[i]); } }, pathToSVG: function(path, prec) { var cmds = path["cmds"], crds = path["crds"]; if (prec == null) prec = 5; var out = [], co = 0, lmap = { M: 2, L: 2, Q: 4, C: 6 }; for (var i = 0; i < cmds.length; i++) { var cmd = cmds[i], cn = co + (lmap[cmd] ? lmap[cmd] : 0); out.push(cmd); while (co < cn) { var c = crds[co++]; out.push(parseFloat(c.toFixed(prec)) + (co == cn ? "" : " ")); } } return out.join(""); }, SVGToPath: function(d) { var pth = { cmds: [], crds: [] }; Typr["U"]["SVG"].svgToPath(d, pth); return { cmds: pth.cmds, crds: pth.crds }; }, pathToContext: function(path, ctx) { var c = 0, cmds = path["cmds"], crds = path["crds"]; for (var j = 0; j < cmds.length; j++) { var cmd = cmds[j]; if (cmd == "M") { ctx.moveTo(crds[c], crds[c + 1]); c += 2; } else if (cmd == "L") { ctx.lineTo(crds[c], crds[c + 1]); c += 2; } else if (cmd == "C") { ctx.bezierCurveTo(crds[c], crds[c + 1], crds[c + 2], crds[c + 3], crds[c + 4], crds[c + 5]); c += 6; } else if (cmd == "Q") { ctx.quadraticCurveTo(crds[c], crds[c + 1], crds[c + 2], crds[c + 3]); c += 4; } else if (cmd.charAt(0) == "#") { ctx.beginPath(); ctx.fillStyle = cmd; } else if (cmd == "Z") { ctx.closePath(); } else if (cmd == "X") { ctx.fill(); } } }, P: { MoveTo: function(p, x, y) { p.cmds.push("M"); p.crds.push(x, y); }, LineTo: function(p, x, y) { p.cmds.push("L"); p.crds.push(x, y); }, CurveTo: function(p, a, b, c, d, e, f) { p.cmds.push("C"); p.crds.push(a, b, c, d, e, f); }, qCurveTo: function(p, a, b, c, d) { p.cmds.push("Q"); p.crds.push(a, b, c, d); }, ClosePath: function(p) { p.cmds.push("Z"); } }, _drawCFF: function(cmds, state, font, pdct, p) { var stack = state.stack; var nStems = state.nStems, haveWidth = state.haveWidth, width = state.width, open = state.open; var i = 0; var x = state.x, y = state.y, c1x = 0, c1y = 0, c2x = 0, c2y = 0, c3x = 0, c3y = 0, c4x = 0, c4y = 0, jpx = 0, jpy = 0; var CFF = Typr["T"].CFF, P = Typr["U"]["P"]; var nominalWidthX = pdct["nominalWidthX"]; var o = { val: 0, size: 0 }; while (i < cmds.length) { CFF.getCharString(cmds, i, o); var v = o.val; i += o.size; if (v == "o1" || v == "o18") { var hasWidthArg; hasWidthArg = stack.length % 2 !== 0; if (hasWidthArg && !haveWidth) { width = stack.shift() + nominalWidthX; } nStems += stack.length >> 1; stack.length = 0; haveWidth = true; } else if (v == "o3" || v == "o23") { var hasWidthArg; hasWidthArg = stack.length % 2 !== 0; if (hasWidthArg && !haveWidth) { width = stack.shift() + nominalWidthX; } nStems += stack.length >> 1; stack.length = 0; haveWidth = true; } else if (v == "o4") { if (stack.length > 1 && !haveWidth) { width = stack.shift() + nominalWidthX; haveWidth = true; } if (open) P.ClosePath(p); y += stack.pop(); P.MoveTo(p, x, y); open = true; } else if (v == "o5") { while (stack.length > 0) { x += stack.shift(); y += stack.shift(); P.LineTo(p, x, y); } } else if (v == "o6" || v == "o7") { var count = stack.length; var isX = v == "o6"; for (var j = 0; j < count; j++) { var sval = stack.shift(); if (isX) x += sval; else y += sval; isX = !isX; P.LineTo(p, x, y); } } else if (v == "o8" || v == "o24") { var count = stack.length; var index = 0; while (index + 6 <= count) { c1x = x + stack.shift(); c1y = y + stack.shift(); c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); x = c2x + stack.shift(); y = c2y + stack.shift(); P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); index += 6; } if (v == "o24") { x += stack.shift(); y += stack.shift(); P.LineTo(p, x, y); } } else if (v == "o11") break; else if (v == "o1234" || v == "o1235" || v == "o1236" || v == "o1237") { if (v == "o1234") { c1x = x + stack.shift(); c1y = y; c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); jpx = c2x + stack.shift(); jpy = c2y; c3x = jpx + stack.shift(); c3y = c2y; c4x = c3x + stack.shift(); c4y = y; x = c4x + stack.shift(); P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); } if (v == "o1235") { c1x = x + stack.shift(); c1y = y + stack.shift(); c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); jpx = c2x + stack.shift(); jpy = c2y + stack.shift(); c3x = jpx + stack.shift(); c3y = jpy + stack.shift(); c4x = c3x + stack.shift(); c4y = c3y + stack.shift(); x = c4x + stack.shift(); y = c4y + stack.shift(); stack.shift(); P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); } if (v == "o1236") { c1x = x + stack.shift(); c1y = y + stack.shift(); c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); jpx = c2x + stack.shift(); jpy = c2y; c3x = jpx + stack.shift(); c3y = c2y; c4x = c3x + stack.shift(); c4y = c3y + stack.shift(); x = c4x + stack.shift(); P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); } if (v == "o1237") { c1x = x + stack.shift(); c1y = y + stack.shift(); c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); jpx = c2x + stack.shift(); jpy = c2y + stack.shift(); c3x = jpx + stack.shift(); c3y = jpy + stack.shift(); c4x = c3x + stack.shift(); c4y = c3y + stack.shift(); if (Math.abs(c4x - x) > Math.abs(c4y - y)) { x = c4x + stack.shift(); } else { y = c4y + stack.shift(); } P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); } } else if (v == "o14") { if (stack.length > 0 && !haveWidth) { width = stack.shift() + font["nominalWidthX"]; haveWidth = true; } if (stack.length == 4) { var adx = stack.shift(); var ady = stack.shift(); var bchar = stack.shift(); var achar = stack.shift(); var bind = CFF.glyphBySE(font, bchar); var aind = CFF.glyphBySE(font, achar); Typr["U"]["_drawCFF"](font["CharStrings"][bind], state, font, pdct, p); state.x = adx; state.y = ady; Typr["U"]["_drawCFF"](font["CharStrings"][aind], state, font, pdct, p); } if (open) { P.ClosePath(p); open = false; } } else if (v == "o19" || v == "o20") { var hasWidthArg; hasWidthArg = stack.length % 2 !== 0; if (hasWidthArg && !haveWidth) { width = stack.shift() + nominalWidthX; } nStems += stack.length >> 1; stack.length = 0; haveWidth = true; i += nStems + 7 >> 3; } else if (v == "o21") { if (stack.length > 2 && !haveWidth) { width = stack.shift() + nominalWidthX; haveWidth = true; } y += stack.pop(); x += stack.pop(); if (open) P.ClosePath(p); P.MoveTo(p, x, y); open = true; } else if (v == "o22") { if (stack.length > 1 && !haveWidth) { width = stack.shift() + nominalWidthX; haveWidth = true; } x += stack.pop(); if (open) P.ClosePath(p); P.MoveTo(p, x, y); open = true; } else if (v == "o25") { while (stack.length > 6) { x += stack.shift(); y += stack.shift(); P.LineTo(p, x, y); } c1x = x + stack.shift(); c1y = y + stack.shift(); c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); x = c2x + stack.shift(); y = c2y + stack.shift(); P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); } else if (v == "o26") { if (stack.length % 2) { x += stack.shift(); } while (stack.length > 0) { c1x = x; c1y = y + stack.shift(); c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); x = c2x; y = c2y + stack.shift(); P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); } } else if (v == "o27") { if (stack.length % 2) { y += stack.shift(); } while (stack.length > 0) { c1x = x + stack.shift(); c1y = y; c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); x = c2x + stack.shift(); y = c2y; P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); } } else if (v == "o10" || v == "o29") { var obj = v == "o10" ? pdct : font; if (stack.length == 0) { console.log("error: empty stack"); } else { var ind = stack.pop(); var subr = obj["Subrs"][ind + obj["Bias"]]; state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; Typr["U"]["_drawCFF"](subr, state, font, pdct, p); x = state.x; y = state.y; nStems = state.nStems; haveWidth = state.haveWidth; width = state.width; open = state.open; } } else if (v == "o30" || v == "o31") { var count, count1 = stack.length; var index = 0; var alternate = v == "o31"; count = count1 & ~2; index += count1 - count; while (index < count) { if (alternate) { c1x = x + stack.shift(); c1y = y; c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); y = c2y + stack.shift(); if (count - index == 5) { x = c2x + stack.shift(); index++; } else x = c2x; alternate = false; } else { c1x = x; c1y = y + stack.shift(); c2x = c1x + stack.shift(); c2y = c1y + stack.shift(); x = c2x + stack.shift(); if (count - index == 5) { y = c2y + stack.shift(); index++; } else y = c2y; alternate = true; } P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); index += 4; } } else if ((v + "").charAt(0) == "o") { console.log("Unknown operation: " + v, cmds); throw v; } else stack.push(v); } state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; }, SVG: function() { var M = { getScale: function(m) { return Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])); }, translate: function(m, x, y) { M.concat(m, [ 1, 0, 0, 1, x, y ]); }, rotate: function(m, a) { M.concat(m, [ Math.cos(a), -Math.sin(a), Math.sin(a), Math.cos(a), 0, 0 ]); }, scale: function(m, x, y) { M.concat(m, [ x, 0, 0, y, 0, 0 ]); }, concat: function(m, w) { var a = m[0], b = m[1], c = m[2], d = m[3], tx = m[4], ty = m[5]; m[0] = a * w[0] + b * w[2]; m[1] = a * w[1] + b * w[3]; m[2] = c * w[0] + d * w[2]; m[3] = c * w[1] + d * w[3]; m[4] = tx * w[0] + ty * w[2] + w[4]; m[5] = tx * w[1] + ty * w[3] + w[5]; }, invert: function(m) { var a = m[0], b = m[1], c = m[2], d = m[3], tx = m[4], ty = m[5], adbc = a * d - b * c; m[0] = d / adbc; m[1] = -b / adbc; m[2] = -c / adbc; m[3] = a / adbc; m[4] = (c * ty - d * tx) / adbc; m[5] = (b * tx - a * ty) / adbc; }, multPoint: function(m, p) { var x = p[0], y = p[1]; return [ x * m[0] + y * m[2] + m[4], x * m[1] + y * m[3] + m[5] ]; }, multArray: function(m, a) { for (var i = 0; i < a.length; i += 2) { var x = a[i], y = a[i + 1]; a[i] = x * m[0] + y * m[2] + m[4]; a[i + 1] = x * m[1] + y * m[3] + m[5]; } } }; function _bracketSplit(str, lbr, rbr) { var out = [], pos = 0, ci = 0, lvl = 0; while (true) { var li = str.indexOf(lbr, ci); var ri = str.indexOf(rbr, ci); if (li == -1 && ri == -1) break; if (ri == -1 || li != -1 && li < ri) { if (lvl == 0) { out.push(str.slice(pos, li).trim()); pos = li + 1; } lvl++; ci = li + 1; } else if (li == -1 || ri != -1 && ri < li) { lvl--; if (lvl == 0) { out.push(str.slice(pos, ri).trim()); pos = ri + 1; } ci = ri + 1; } } return out; } function cssMap(str) { var pts = _bracketSplit(str, "{", "}"); var css = {}; for (var i = 0; i < pts.length; i += 2) { var cn = pts[i].split(","); for (var j = 0; j < cn.length; j++) { var cnj = cn[j].trim(); if (css[cnj] == null) css[cnj] = ""; css[cnj] += pts[i + 1]; } } return css; } function readTrnf(trna) { var pts = _bracketSplit(trna, "(", ")"); var m = [ 1, 0, 0, 1, 0, 0 ]; for (var i = 0; i < pts.length; i += 2) { var om = m; m = _readTrnsAttr(pts[i], pts[i + 1]); M.concat(m, om); } return m; } function _readTrnsAttr(fnc, vls) { var m = [ 1, 0, 0, 1, 0, 0 ], gotSep = true; for (var i = 0; i < vls.length; i++) { var ch = vls.charAt(i); if (ch == "," || ch == " ") gotSep = true; else if (ch == ".") { if (!gotSep) { vls = vls.slice(0, i) + "," + vls.slice(i); i++; } gotSep = false; } else if (ch == "-" && i > 0 && vls[i - 1] != "e") { vls = vls.slice(0, i) + " " + vls.slice(i); i++; gotSep = true; } } vls = vls.split(/\s*[\s,]\s*/).map(parseFloat); if (fnc == "translate") { if (vls.length == 1) M.translate(m, vls[0], 0); else M.translate(m, vls[0], vls[1]); } else if (fnc == "scale") { if (vls.length == 1) M.scale(m, vls[0], vls[0]); else M.scale(m, vls[0], vls[1]); } else if (fnc == "rotate") { var tx = 0, ty = 0; if (vls.length != 1) { tx = vls[1]; ty = vls[2]; } M.translate(m, -tx, -ty); M.rotate(m, -Math.PI * vls[0] / 180); M.translate(m, tx, ty); } else if (fnc == "matrix") m = vls; else console.log("unknown transform: ", fnc); return m; } function toPath(str) { var pth = { cmds: [], crds: [] }; if (str == null) return pth; var prsr = new DOMParser(); var doc = prsr["parseFromString"](str, "image/svg+xml"); var svg = doc.getElementsByTagName("svg")[0]; var vb = svg.getAttribute("viewBox"); if (vb) vb = vb.trim().split(" ").map(parseFloat); else vb = [ 0, 0, 1e3, 1e3 ]; _toPath(svg.children, pth); for (var i = 0; i < pth.crds.length; i += 2) { var x = pth.crds[i], y = pth.crds[i + 1]; x -= vb[0]; y -= vb[1]; y = -y; pth.crds[i] = x; pth.crds[i + 1] = y; } return pth; } function _toPath(nds, pth, fill) { for (var ni = 0; ni < nds.length; ni++) { var nd = nds[ni], tn = nd.tagName; var cfl = nd.getAttribute("fill"); if (cfl == null) cfl = fill; if (tn == "g") { var tp = { crds: [], cmds: [] }; _toPath(nd.children, tp, cfl); var trf = nd.getAttribute("transform"); if (trf) { var m = readTrnf(trf); M.multArray(m, tp.crds); } pth.crds = pth.crds.concat(tp.crds); pth.cmds = pth.cmds.concat(tp.cmds); } else if (tn == "path" || tn == "circle" || tn == "ellipse") { pth.cmds.push(cfl ? cfl : "#000000"); var d; if (tn == "path") d = nd.getAttribute("d"); if (tn == "circle" || tn == "ellipse") { var vls = [ 0, 0, 0, 0 ], nms = [ "cx", "cy", "rx", "ry", "r" ]; for (var i = 0; i < 5; i++) { var V = nd.getAttribute(nms[i]); if (V) { V = parseFloat(V); if (i < 4) vls[i] = V; else vls[2] = vls[3] = V; } } var cx = vls[0], cy = vls[1], rx = vls[2], ry = vls[3]; d = [ "M", cx - rx, cy, "a", rx, ry, 0, 1, 0, rx * 2, 0, "a", rx, ry, 0, 1, 0, -rx * 2, 0 ].join(" "); } svgToPath(d, pth); pth.cmds.push("X"); } else if (tn == "defs"); else console.log(tn, nd); } } function _tokens(d) { var ts = [], off = 0, rn = false, cn = "", pc = ""; while (off < d.length) { var cc = d.charCodeAt(off), ch = d.charAt(off); off++; var isNum = 48 <= cc && cc <= 57 || ch == "." || ch == "-" || ch == "e" || ch == "E"; if (rn) { if (ch == "-" && pc != "e" || ch == "." && cn.indexOf(".") != -1) { ts.push(parseFloat(cn)); cn = ch; } else if (isNum) cn += ch; else { ts.push(parseFloat(cn)); if (ch != "," && ch != " ") ts.push(ch); rn = false; } } else { if (isNum) { cn = ch; rn = true; } else if (ch != "," && ch != " ") ts.push(ch); } pc = ch; } if (rn) ts.push(parseFloat(cn)); return ts; } function _reps(ts, off, ps) { var i = off; while (i < ts.length) { if (typeof ts[i] == "string") break; i += ps; } return (i - off) / ps; } function svgToPath(d, pth) { var ts = _tokens(d); var i = 0, x = 0, y = 0, ox = 0, oy = 0, oldo = pth.crds.length; var pc = { M: 2, L: 2, H: 1, V: 1, T: 2, S: 4, A: 7, Q: 4, C: 6 }; var cmds = pth.cmds, crds = pth.crds; while (i < ts.length) { var cmd = ts[i]; i++; var cmu = cmd.toUpperCase(); if (cmu == "Z") { cmds.push("Z"); x = ox; y = oy; } else { var ps = pc[cmu], reps = _reps(ts, i, ps); for (var j = 0; j < reps; j++) { if (j == 1 && cmu == "M") { cmd = cmd == cmu ? "L" : "l"; cmu = "L"; } var xi = 0, yi = 0; if (cmd != cmu) { xi = x; yi = y; } if (cmu == "M") { x = xi + ts[i++]; y = yi + ts[i++]; cmds.push("M"); crds.push(x, y); ox = x; oy = y; } else if (cmu == "L") { x = xi + ts[i++]; y = yi + ts[i++]; cmds.push("L"); crds.push(x, y); } else if (cmu == "H") { x = xi + ts[i++]; cmds.push("L"); crds.push(x, y); } else if (cmu == "V") { y = yi + ts[i++]; cmds.push("L"); crds.push(x, y); } else if (cmu == "Q") { var x1 = xi + ts[i++], y1 = yi + ts[i++], x2 = xi + ts[i++], y2 = yi + ts[i++]; cmds.push("Q"); crds.push(x1, y1, x2, y2); x = x2; y = y2; } else if (cmu == "T") { var co = Math.max(crds.length - 2, oldo); var x1 = x + x - crds[co], y1 = y + y - crds[co + 1]; var x2 = xi + ts[i++], y2 = yi + ts[i++]; cmds.push("Q"); crds.push(x1, y1, x2, y2); x = x2; y = y2; } else if (cmu == "C") { var x1 = xi + ts[i++], y1 = yi + ts[i++], x2 = xi + ts[i++], y2 = yi + ts[i++], x3 = xi + ts[i++], y3 = yi + ts[i++]; cmds.push("C"); crds.push(x1, y1, x2, y2, x3, y3); x = x3; y = y3; } else if (cmu == "S") { var co = Math.max(crds.length - (cmds[cmds.length - 1] == "C" ? 4 : 2), oldo); var x1 = x + x - crds[co], y1 = y + y - crds[co + 1]; var x2 = xi + ts[i++], y2 = yi + ts[i++], x3 = xi + ts[i++], y3 = yi + ts[i++]; cmds.push("C"); crds.push(x1, y1, x2, y2, x3, y3); x = x3; y = y3; } else if (cmu == "A") { var x1 = x, y1 = y; var rx = ts[i++], ry = ts[i++]; var phi = ts[i++] * (Math.PI / 180), fA = ts[i++], fS = ts[i++]; var x2 = xi + ts[i++], y2 = yi + ts[i++]; if (x2 == x && y2 == y && rx == 0 && ry == 0) continue; var hdx = (x1 - x2) / 2, hdy = (y1 - y2) / 2; var cosP = Math.cos(phi), sinP = Math.sin(phi); var x1A = cosP * hdx + sinP * hdy; var y1A = -sinP * hdx + cosP * hdy; var rxS = rx * rx, ryS = ry * ry; var x1AS = x1A * x1A, y1AS = y1A * y1A; var frc = (rxS * ryS - rxS * y1AS - ryS * x1AS) / (rxS * y1AS + ryS * x1AS); var coef = (fA != fS ? 1 : -1) * Math.sqrt(Math.max(frc, 0)); var cxA = coef * (rx * y1A) / ry; var cyA = -coef * (ry * x1A) / rx; var cx = cosP * cxA - sinP * cyA + (x1 + x2) / 2; var cy = sinP * cxA + cosP * cyA + (y1 + y2) / 2; var angl = function(ux, uy, vx, vy) { var lU = Math.sqrt(ux * ux + uy * uy), lV = Math.sqrt(vx * vx + vy * vy); var num = (ux * vx + uy * vy) / (lU * lV); return (ux * vy - uy * vx >= 0 ? 1 : -1) * Math.acos(Math.max(-1, Math.min(1, num))); }; var vX = (x1A - cxA) / rx, vY = (y1A - cyA) / ry; var theta1 = angl(1, 0, vX, vY); var dtheta = angl(vX, vY, (-x1A - cxA) / rx, (-y1A - cyA) / ry); dtheta = dtheta % (2 * Math.PI); var arc = function(gst, x, y, r, a0, a1, neg) { var rotate = function(m, a) { var si = Math.sin(a), co = Math.cos(a); var a = m[0], b = m[1], c = m[2], d = m[3]; m[0] = a * co + b * si; m[1] = -a * si + b * co; m[2] = c * co + d * si; m[3] = -c * si + d * co; }; var multArr = function(m, a) { for (var j = 0; j < a.length; j += 2) { var x = a[j], y = a[j + 1]; a[j] = m[0] * x + m[2] * y + m[4]; a[j + 1] = m[1] * x + m[3] * y + m[5]; } }; var concatA = function(a, b) { for (var j = 0; j < b.length; j++) a.push(b[j]); }; var concatP = function(p, r) { concatA(p.cmds, r.cmds); concatA(p.crds, r.crds); }; if (neg) while (a1 > a0) a1 -= 2 * Math.PI; else while (a1 < a0) a1 += 2 * Math.PI; var th = (a1 - a0) / 4; var x0 = Math.cos(th / 2), y0 = -Math.sin(th / 2); var x1 = (4 - x0) / 3, y1 = y0 == 0 ? y0 : (1 - x0) * (3 - x0) / (3 * y0); var x2 = x1, y2 = -y1; var x3 = x0, y3 = -y0; var ps = [ x1, y1, x2, y2, x3, y3 ]; var pth = { cmds: [ "C", "C", "C", "C" ], crds: ps.slice(0) }; var rot = [ 1, 0, 0, 1, 0, 0 ]; rotate(rot, -th); for (var j = 0; j < 3; j++) { multArr(rot, ps); concatA(pth.crds, ps); } rotate(rot, -a0 + th / 2); rot[0] *= r; rot[1] *= r; rot[2] *= r; rot[3] *= r; rot[4] = x; rot[5] = y; multArr(rot, pth.crds); multArr(gst.ctm, pth.crds); concatP(gst.pth, pth); }; var gst = { pth: pth, ctm: [ rx * cosP, rx * sinP, -ry * sinP, ry * cosP, cx, cy ] }; arc(gst, 0, 0, 1, theta1, theta1 + dtheta, fS == 0); x = x2; y = y2; } else console.log("Unknown SVG command " + cmd); } } } } return { cssMap: cssMap, readTrnf: readTrnf, svgToPath: svgToPath, toPath: toPath }; }(), initHB: function(hurl, resp) { var codeLength = function(code) { var len = 0; if ((code & 4294967295 - (1 << 7) + 1) == 0) { len = 1; } else if ((code & 4294967295 - (1 << 11) + 1) == 0) { len = 2; } else if ((code & 4294967295 - (1 << 16) + 1) == 0) { len = 3; } else if ((code & 4294967295 - (1 << 21) + 1) == 0) { len = 4; } return len; }; var te = new window["TextEncoder"]("utf8"); fetch(hurl).then(function(x) { return x["arrayBuffer"](); }).then(function(ab) { return WebAssembly["instantiate"](ab); }).then(function(res) { console.log("HB ready"); var exp = res["instance"]["exports"], mem = exp["memory"]; mem["grow"](700); var heapu8 = new Uint8Array(mem.buffer); var u32 = new Uint32Array(mem.buffer); var i32 = new Int32Array(mem.buffer); var __lastFnt, blob, blobPtr, face, font; Typr["U"]["shapeHB"] = function() { var toJson = function(ptr) { var length = exp["hb_buffer_get_length"](ptr); var result = []; var iPtr32 = exp["hb_buffer_get_glyph_infos"](ptr, 0) >>> 2; var pPtr32 = exp["hb_buffer_get_glyph_positions"](ptr, 0) >>> 2; for (var i = 0; i < length; ++i) { var a = iPtr32 + i * 5, b = pPtr32 + i * 5; result.push({ g: u32[a + 0], cl: u32[a + 2], ax: i32[b + 0], ay: i32[b + 1], dx: i32[b + 2], dy: i32[b + 3] }); } return result; }; return function(fnt, str, ltr) { var fdata = fnt["_data"], fn = fnt["name"]["postScriptName"]; if (__lastFnt != fn) { if (blob != null) { exp["hb_blob_destroy"](blob); exp["free"](blobPtr); exp["hb_face_destroy"](face); exp["hb_font_destroy"](font); } blobPtr = exp["malloc"](fdata.byteLength); heapu8.set(fdata, blobPtr); blob = exp["hb_blob_create"](blobPtr, fdata.byteLength, 2, 0, 0); face = exp["hb_face_create"](blob, 0); font = exp["hb_font_create"](face); __lastFnt = fn; } var buffer = exp["hb_buffer_create"](); var bytes = te["encode"](str); var len = bytes.length, strp = exp["malloc"](len); heapu8.set(bytes, strp); exp["hb_buffer_add_utf8"](buffer, strp, len, 0, len); exp["free"](strp); exp["hb_buffer_set_direction"](buffer, ltr ? 4 : 5); exp["hb_buffer_guess_segment_properties"](buffer); exp["hb_shape"](font, buffer, 0, 0); var json = toJson(buffer); exp["hb_buffer_destroy"](buffer); var arr = json.slice(0); if (!ltr) arr.reverse(); var ci = 0, bi = 0; for (var i = 1; i < arr.length; i++) { var gl = arr[i], cl = gl["cl"]; while (true) { var cpt = str.codePointAt(ci), cln = codeLength(cpt); if (bi + cln <= cl) { bi += cln; ci += cpt <= 65535 ? 1 : 2; } else break; } gl["cl"] = ci; } return json; }; }(); resp(); }); } }; function init() { rule = rwl_userData.rules.rule_def; hook_eventNames = rule.hook_eventNames.split("|"); unhook_eventNames = rule.unhook_eventNames.split("|"); eventNames = hook_eventNames.concat(unhook_eventNames); if (rule.dom0) { setInterval(clearLoop, 10 * 1e3); setTimeout(clearLoop, 1500); window.addEventListener("load", clearLoop, true); clearLoop(); } if (rule.hook_addEventListener) { EventTarget.prototype.addEventListener = addEventListener; document.addEventListener = addEventListener; if (hasFrame) { for (let i = 0; i < hasFrame.length; i++) { hasFrame[i].contentWindow.document.addEventListener = addEventListener; } } } if (rule.hook_preventDefault) { Event.prototype.preventDefault = function() { if (hook_eventNames.indexOf(this.type) < 0) { Event_preventDefault.apply(this, arguments); } }; if (hasFrame) { for (let i = 0; i < hasFrame.length; i++) { hasFrame[i].contentWindow.Event.prototype.preventDefault = function() { if (hook_eventNames.indexOf(this.type) < 0) { Event_preventDefault.apply(this, arguments); } }; } } } if (rule.hook_set_returnValue) { Event.prototype.__defineSetter__("returnValue", function() { if (this.returnValue !== true && hook_eventNames.indexOf(this.type) >= 0) { this.returnValue = true; } }); } } function addEventListener(type, func, useCapture) { var _addEventListener = this === document ? document_addEventListener : EventTarget_addEventListener; if (hook_eventNames.indexOf(type) >= 0) { _addEventListener.apply(this, [ type, returnTrue, useCapture ]); } else if (unhook_eventNames.indexOf(type) >= 0) { var funcsName = storageName + type + (useCapture ? "t" : "f"); if (this[funcsName] === undefined) { this[funcsName] = []; _addEventListener.apply(this, [ type, useCapture ? unhook_t : unhook_f, useCapture ]); } this[funcsName].push(func); } else { _addEventListener.apply(this, arguments); } } function clearLoop() { rule = clear(); var elements = getElements(); for (var i in elements) { for (var j in eventNames) { var name = "on" + eventNames[j]; if (Object.prototype.toString.call(elements[i]) == "[object String]") { continue; } if (elements[i][name] !== null && elements[i][name] !== onxxx) { if (unhook_eventNames.indexOf(eventNames[j]) >= 0) { elements[i][storageName + name] = elements[i][name]; elements[i][name] = onxxx; } else { elements[i][name] = null; } } } } document.onmousedown = function() { return true; }; } function returnTrue(e) { return true; } function unhook_t(e) { return unhook(e, this, storageName + e.type + "t"); } function unhook_f(e) { return unhook(e, this, storageName + e.type + "f"); } function unhook(e, self, funcsName) { var list = self[funcsName]; for (var i in list) { list[i](e); } e.returnValue = true; return true; } function onxxx(e) { var name = storageName + "on" + e.type; this[name](e); e.returnValue = true; return true; } function getElements() { var elements = Array.prototype.slice.call(document.getElementsByTagName("*")); elements.push(document); var frames = document.querySelectorAll("frame"); if (frames) { hasFrame = frames; var frames_element; for (let i = 0; i < frames.length; i++) { frames_element = Array.prototype.slice.call(frames[i].contentWindow.document.querySelectorAll("*")); elements.push(frames[i].contentWindow.document); elements = elements.concat(frames_element); } } return elements; } var settingData = { status: 1, version: .1, message: "", positionTop: "0", positionLeft: "0", positionRight: "auto", addBtn: false, connectToTheServer: false, waitUpload: [], currentURL: "null", shortcut: 3, rules: {}, data: [] }; var rwl_userData = null; var rule = null; var hasFrame = false; var storageName = "storageName"; var hook_eventNames, unhook_eventNames, eventNames; var EventTarget_addEventListener = EventTarget.prototype.addEventListener; var document_addEventListener = document.addEventListener; var Event_preventDefault = Event.prototype.preventDefault; rwl_userData = GM_getValue("rwl_userData"); if (!rwl_userData) { rwl_userData = settingData; } for (let value in settingData) { if (!rwl_userData.hasOwnProperty(value)) { rwl_userData[value] = settingData[value]; GM_setValue("rwl_userData", rwl_userData); } } // 隐藏平台自带的 AI 助手面板 function hidePlatformAI() { // 如果已经添加过样式则跳过 if (top.document.getElementById('hide-platform-ai-style')) return; const style = top.document.createElement('style'); style.id = 'hide-platform-ai-style'; style.textContent = ` /* 隐藏学习通/超星平台自带的 AI 助手 */ .ai-assistant-container, .ai-assistant-wrapper, .study-ai-panel, .studyAI, .ai-chat-container, .ai-robot-container, .robot-container, .cx-ai-container, .cx-ai-panel, .cxAiChat, .ai-dialogue, .ai-dialog-container, [class*="studyAi"], [class*="StudyAi"], [class*="aiAssistant"], [class*="AiAssistant"], [class*="ai-helper"], [class*="robotAi"], [class*="cxAi"], [class*="CxAi"], [class*="ernie"], [class*="Ernie"], #studyAiContainer, #aiAssistant, #ai-assistant, #cxAiChat, #cx-ai, /* 隐藏悬浮的 AI 按钮 */ .ai-float-btn, .ai-entry-btn, .ai-icon-btn, [class*="aiEntry"], [class*="ai-btn"], [class*="aiIcon"], /* 通用:包含 AI智能助手 文字的面板 */ div[class*="ai"]:has(span:contains("AI智能助手")), div[class*="AI"]:has(span:contains("AI智能助手")) { display: none !important; visibility: hidden !important; opacity: 0 !important; pointer-events: none !important; } `; top.document.head.appendChild(style); // DOM 方式:查找并隐藏包含 "AI智能助手" 文字的面板 const allElements = top.document.querySelectorAll('div, section, aside'); allElements.forEach(el => { const text = el.textContent || ''; const classList = el.className || ''; // 检查是否是平台的 AI 面板(排除我们自己的面板) if ((text.includes('AI智能助手') || text.includes('ernie') || classList.toLowerCase().includes('ai')) && !el.closest('#drag_auto_answer') && !el.closest('.drag_auto_answer-class') && el.querySelector && (el.querySelector('.ai-header') || el.querySelector('[class*="robot"]'))) { el.style.cssText = 'display: none !important;'; } }); } function removeF() { var $tip = $("style:contains(font-cxsecret)"); if (!$tip.length) return; var font = $tip.text().match(/base64,([\w\W]+?)'/)[1]; font = Typr.parse(base64ToUint8Array(font))[0]; var table = JSON.parse(GM_getResourceText("Table")); var match = {}; for (var i = 19968; i < 40870; i++) { $tip = Typr.U.codeToGlyph(font, i); if (!$tip) continue; $tip = Typr.U.glyphToPath(font, $tip); $tip = MD5(JSON.stringify($tip)).slice(24); match[i] = table[$tip]; } $(".font-cxsecret").html(function(index, html) { $.each(match, function(key, value) { key = String.fromCharCode(key); key = new RegExp(key, "g"); value = String.fromCharCode(value); html = html.replace(key, value); }); return html; }).removeClass("font-cxsecret"); function base64ToUint8Array(base64) { var data = window.atob(base64); var buffer = new Uint8Array(data.length); for (var i = 0; i < data.length; ++i) { buffer[i] = data.charCodeAt(i); } return buffer; } } function start() { // 立即隐藏平台 AI try { hidePlatformAI(); } catch (e) {} setInterval(() => { try { hidePlatformAI(); // 持续检查并隐藏 } catch (e) {} try { removeF(); } catch (e) {} try { init(); } catch (e) {} }, 500); } if (location.host.includes("chaoxing")) { setTimeout(() => { start(); }, 2e3); } WorkerJSPlus({ name: "学习通作业", match: location.pathname === "/mooc2/work/dowork" || location.pathname === "/mooc-ans/mooc2/work/dowork", root: ".questionLi", elements: { question: "h3", options: ".stem_answer .answerBg .answer_p, .textDIV, .eidtDiv", $options: ".stem_answer .answerBg, .textDIV, .eidtDiv", type: "input[type^=hidden]:eq(0)" }, wrap: obj => { obj.question = obj.question.replace(obj.$item.find(".colorShallow").text(), "").replace(/^(\d+\.\s)/, ""); }, ignore_click: $item => { return Boolean($item.find(".check_answer,.check_answer_dx").length); }, fill: (type, answer, $option) => { if (type === 4 || type === 2 || type === 5) { UE$1.getEditor($option.find("textarea").attr("name")).setContent(answer); } } }); WorkerJSPlus({ name: "超星旧版考试", match: (location.pathname === "/exam/test/reVersionTestStartNew" || location.pathname === "/exam-ans/exam/test/reVersionTestStartNew") && !location.href.includes("newMooc=true"), root: ".TiMu", elements: { question: ".Cy_TItle .clearfix", options: ".Cy_ulTop .clearfix", $options: ":radio, :checkbox, .Cy_ulTk textarea", type: "[name^=type]:not([id])" }, ignore_click: $item => { return $item.get(0).checked; }, fill: (type, answer, $option) => { if (type === 4 || type === 2 || type === 5) { UE$1.getEditor($option.attr("name")).setContent(answer); } }, finished: auto_jump => { auto_jump && setInterval(function() { const btn = $(".saveYl:contains(下一题)").offset(); var mouse = document.createEvent("MouseEvents"), arr = [ btn.left + Math.ceil(Math.random() * 80), btn.top + Math.ceil(Math.random() * 26) ]; mouse.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, arr[0], arr[1], false, false, false, false, 0, null); _self.event = $.extend(true, {}, mouse); delete _self.event.isTrusted; _self.getTheNextQuestion(1); }, Math.ceil(GLOBAL.fillAnswerDelay * Math.random()) * 2); } }); WorkerJSPlus({ name: "超星章节测验", match: location.pathname === "/work/doHomeWorkNew" || location.pathname === "/mooc-ans/work/doHomeWorkNew", init: start, root: ".clearfix .TiMu", elements: { question: ".Zy_TItle .clearfix", options: "ul:eq(0) li .after", $options: "ul:eq(0) li :radio,:checkbox,textarea,.num_option_dx,.num_option", type: "input[name^=answertype]" }, ignore_click: $item => { if ($item.is("input")) { return $item.get(0).checked; } return $item.attr("class").includes("check_answer"); }, fill: async (type, answer, $option) => { if (type === 4 || type === 2 || type === 5) { UE$1.getEditor($option.attr("name")).setContent(answer); } } }); WorkerJSPlus({ name: "超星新版考试", match: () => { const cxSinglePage = (location.pathname === "/exam/test/reVersionTestStartNew" || location.pathname === "/exam-ans/exam/test/reVersionTestStartNew" || location.pathname === "/mooc-ans/exam/test/reVersionTestStartNew") && location.href.includes("newMooc=true"); const cxAll = location.pathname === "/mooc2/exam/preview" || location.pathname === "/exam-ans/mooc2/exam/preview" || location.pathname === "/mooc-ans/mooc2/exam/preview"; return cxSinglePage || cxAll; }, root: ".questionLi", elements: { question: "h3 div", options: ".answerBg .answer_p, .textDIV, .eidtDiv", $options: ".answerBg, .textDIV, .eidtDiv", type: "input[name^=type]:eq(" + GLOBAL.i + ")" }, ignore_click: $item => { return Boolean($item.find(".check_answer,.check_answer_dx").length); }, hook: () => { GLOBAL.i = Number((location.pathname === "/exam/test/reVersionTestStartNew" || location.pathname === "/exam-ans/exam/test/reVersionTestStartNew" || location.pathname === "/mooc-ans/exam/test/reVersionTestStartNew") && location.href.includes("newMooc=true")); }, wrap: obj => { if (obj.type === 6) { obj.type = 4; } }, fill: (type, answer, $option) => { if (type === 4 || type === 2 || type === 5) { const name = $option.find("textarea").attr("name"); UE$1.getEditor(name).setContent(answer); if (GLOBAL.i === 0) { console.log("#" + name.replace("answerEditor", "save_")); $("#" + name.replace("answerEditor", "save_")).click(); } } }, finished: a => { a && $('.nextDiv .jb_btn:contains("下一题")').click(); } }); WorkerJSPlus({ name: "超星随堂测验", match: location.pathname.includes("/page/quiz/stu/answerQuestion"), root: ".question-item", elements: { question: ".topic-txt", options: ".topic-option-list", $options: ".topic-option-list input", type: "input[class^=que-type]" }, ignore_click: $item => { return Boolean($item.find(".check_answer,.check_answer_dx").length); }, wrap: obj => { if (obj.type === 16) { obj.type = 3; } }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { $option.val(answer); } } }); function JSONParseHook(func) { if (location.host.includes("zhihuishu")) { let oldSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function() { this.addEventListener("readystatechange", function() { if (this.readyState === 4 && this.response.includes("workExamParts")) { try { func(JSON.parse(this.response)); } catch (err) {} } }, false); return oldSend.apply(this, arguments); }; } else { const parse = JSON.parse; JSON.parse = function(...args) { const o = parse.call(this, ...args); func(o); return o; }; } } function hookZhiHuiShuWork(o, arr) { function format(item) { let options = []; let options_id; if (item.questionOptions && item.questionOptions.length) { options = item.questionOptions.map(o => { return formatString(o.content); }); options_id = item.questionOptions.map(o => { return o.id; }); } return { qid: item.id, question: formatString(item.name), type: getQuestionType(item.questionType.name), options_id: options_id, options: options }; } if (o.rt && o.rt.examBase && o.rt.examBase.workExamParts.length > 0) { GLOBAL.content = o.rt; GLOBAL.json = o.rt.examBase.workExamParts.map(part => { return part.questionDtos.map(item => { if ("阅读理解(选择)/完型填空" === item.questionType.name || "听力训练" === item.questionType.name || !(item.questionType.name.includes("填空") || item.questionType.name.includes("问答")) && item.questionChildrens && item.questionChildrens.length > 0) { return item.questionChildrens.map(i => { console.log(format(i)); return format(i); }).flat(); } else { return format(item); } }); }).flat(); } else if (o.rt && Object.keys(o.rt).length > 0 && !isNaN(Object.keys(o.rt)[0])) { GLOBAL.img = o.rt; } } WorkerJSPlus({ name: "智慧树作业/考试", match: !location.href.includes("checkHomework") && location.host.includes("zhihuishu") && (location.pathname === "/stuExamWeb.html" || location.href.includes("/webExamList/dohomework/") || location.href.includes("/webExamList/doexamination/")), root: ".examPaper_subject", elements: { question: ".subject_describe div,.smallStem_describe p", options: ".subject_node .nodeLab .node_detail", $options: ".subject_node .nodeLab .node_detail", type: ".subject_type span:first-child" }, hook: () => { JSONParseHook(hookZhiHuiShuWork); }, intv: () => { return $(".answerCard").length; }, wrap: obj => { Object.assign(obj, GLOBAL.json[GLOBAL.index - 1]); console.log(obj); if ($(".yidun_popup").hasClass("yidun_popup--light")) { iframeMsg("tip", { type: "stop", tip: "答题暂停,请自行通过验证" }); GLOBAL.stop = true; } }, ignore_click: $item => { return $item.hasClass("onChecked"); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { UE$1.getEditor($option.find("textarea").attr("name")).setContent(answer); } }, finished: async () => { vm.zhihuishuSaveTip(); const len = $(".answerCard_list li").length; for (let i = 0; i < len; i++) { await sleep(500); try { $(".answerCard_list1 li").eq(i).click(); await sleep(1e3); $(".el-button:contains(下一题)").click(); } catch (e) { $(".el-button:contains(保存)").click(); } const process = ((i + 1) / len * 100).toFixed(0); $("#gs_p").val(process); $("#gs_text").text(process + "%"); } if (top.document.querySelector("#gs_p").value == 100) { top.document.querySelector("#zhihuishuSaveTip").remove(); } }, fillFinish: () => { $(".answerCard_list li").eq(GLOBAL.index - 1).click(); $(".el-button:contains(下一题)").click(); } }); WorkerJSPlus({ name: "智慧树学分课作业", match: location.href.includes("/atHomeworkExam/stu/homeworkQ/exerciseList") || location.href.includes("atHomeworkExam/stu/examQ/examexercise"), root: ".questionBox:eq(0)", elements: { question: ".questionContent", options: ".optionUl label .el-radio__label,.el-checkbox__label", $options: ".optionUl label", type: ".questionTit" }, intv: () => { return $(".answerCard").length || $(".questionTit").length; }, wrap: async obj => { obj.options = obj.options.map(item => { return formatString(item.replaceAll(/^[a-zA-Z][.|\s+]/g, "")); }); if ($(".yidun_popup").hasClass("yidun_popup--light")) { iframeMsg("tip", { type: "stop", tip: "答题暂停,请自行通过验证" }); GLOBAL.stop = true; } }, ignore_click: $item => { return $item.hasClass("is-checked"); }, finished: () => { if ($(".Nextbtndiv .Topicswitchingbtn-gray:contains(下一题)").hasClass("Topicswitchingbtn-gray")) return false; $(".Topicswitchingbtn:contains(下一题)").click(); return true; } }); WorkerJSPlus({ name: "智慧树学分课考试", match: location.host === "studentexambaseh5.zhihuishu.com", root: ".ques-detail", elements: { question: ".questionName .centent-pre", options: ".radio-view li .preStyle,.checkbox-views label .preStyle", $options: ".radio-view li,.checkbox-views label", type: ".letterSortNum" }, intv: () => { return $(".questionContent").length; }, ignore_click: $item => { return $item.hasClass("is-checked"); }, wrap: obj => { obj.options = obj.options.map(item => { return formatString(item.replaceAll(/^[a-zA-Z][.|\s+]/g, "")); }); if ($(".yidun_popup").hasClass("yidun_popup--light")) { iframeMsg("tip", { type: "stop", tip: "答题暂停,请自行通过验证" }); GLOBAL.stop = true; } if (obj.type === 15) { obj.question = formatString($(".centent-son-pre").text()); obj.type = 1; } }, finished: auto_jump => { if (auto_jump) { const btn = $(".next-topic:contains(下一题)"); btn.click(); return !btn.hasClass("noNext"); } } }); WorkerJSPlus({ match: location.href.includes("checkHomework") && location.host.includes("zhihuishu"), hook: () => { JSONParseHook(hookZhiHuiShuWork); }, init: () => { R({ type: 2, content: GLOBAL.content, img: GLOBAL.img }); } }); GLOBAL.timeout = 10 * 1e3; function uploadAnswer(data) { const arr2 = division(data, 100); for (let arr2Element of arr2) { GM_xmlhttpRequest({ method: "POST", url: "https://lyck6.cn/pcService/api/uploadAnswer", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify(arr2Element), timeout: GLOBAL.timeout }); } } function uploadAnswerToPlat(data, plat) { const arr2 = division(data, 100); for (let arr2Element of arr2) { GM_xmlhttpRequest({ method: "POST", url: "https://lyck6.cn/collect-service/v1/uploadAnswerToPlat?plat=" + plat, headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify(arr2Element), timeout: GLOBAL.timeout }); } } WorkerJSPlus({ name: "职教云考试", match: location.pathname === "/exam/examflow_index.action", intv: () => { return $(".divQuestionTitle").length; }, root: ".q_content", elements: { question: ".divQuestionTitle", options: ".questionOptions .q_option", $options: ".questionOptions .q_option div,div[id^=_baidu_editor_]" }, ignore_click: $item => { return $($item).attr("class") === "checkbox_on"; }, wrap: obj => { const type = getQuestionType(obj.$item.next().attr("answertype")); obj.type = type === undefined ? defaultWorkTypeResolver(obj.$options) : type; }, fill: (type, answer, $option) => { if (type === 4 || type === 2 || type === 5) { UE$1.getEditor($option.attr("id")).setContent(answer); } }, finished: async () => { if ($(".paging_next").attr("style").includes("block") || !$(".paging_next").attr("style").includes("none")) { $(".paging_next").click(); await sleep(1e3); return true; } } }); WorkerJSPlus({ name: "职教云测验", match: location.pathname === "/study/directory/dir_course.html", intv: () => { return $(".panel_item").length; }, root: ".panel_item .panel_item", elements: { question: ".preview_cm .preview_stem", options: ".preview_cm ul li span:last-child", $options: ".preview_cm ul li input" }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find(".panel_title").text()); obj.options = obj.options.map(i => { return i.trim().replace(/^[abAB]\)\s+/, "").replace(/^[A-Za-z]\s+/, "").trim(); }); }, ignore_click: $item => { return $item.attr("checked") === "checked"; } }); WorkerJSPlus({ name: "职教云MOOC", match: location.pathname === "/study/homework/do.html" || location.pathname === "/study/workExam/testWork/preview.html" || location.pathname === "/study/onlineExam/preview.html" || location.pathname === "/study/workExam/homeWork/preview.html" || location.pathname === "/study/workExam/onlineExam/preview.html", root: ".e-q-r", elements: { question: ".e-q-q .ErichText", options: ".e-a-g li", $options: ".e-a-g li", type: ".quiz-type" }, ignore_click: $item => { return $item.hasClass("checked"); }, wrap: obj => { if (obj.type === "A1A2题") { obj.type = 1; } obj.question = obj.question.replace(//gi, ""); obj.options = obj.options.map(i => { return i.trim().replace(/^[abAB]\)\s+/, "").replace(/^[A-Za-z]\s+/, "").trim(); }); } }); function parseIcve(questions) { return questions.map(item => { const options = item.Selects.map(opt => { return formatString(opt); }); const type = getQuestionType(item.ACHType.QuestionTypeName); const answer = item.Answers.map(key => { if (type === 0 || type === 1) { return options[key.charCodeAt() - 65]; } else if (type === 3) { return key === "1" ? "正确" : "错误"; } }); const answerKey = type === 0 || type === 1 ? item.Answers : answer; return { id: item.Id, question: item.ContentText, answerKey: answerKey, options: type === 3 ? [ "正确", "错误" ] : options, answer: answer, type: type }; }); } WorkerJSPlus({ name: "资源库 新版", match: location.pathname === "/icve-study/jobTest" || location.pathname === "/icve-study/coursePreview/jobTest" || location.pathname === "/icve-study/coursePreview/test", root: ".subjectDet", elements: { question: "h5,.titleTest span:last", options: ".optionList label", $options: ".optionList input", type: ".title,.titleTest .xvhao" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { console.log(obj); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { UE$1.getEditor($option.attr("name")).setContent(answer); } } }); WorkerJSPlus({ name: "资源库 WWW开头", match: location.pathname === "/study/works/works.html" || location.pathname === "/study/exam/exam.html", root: ".questions", elements: { question: ".preview_stem", options: "li .preview_cont", $options: "li input", type: "input:hidden" }, hook: () => { JSONParseHook(o => { if (location.pathname === "/study/works/works.html") { if (o.paper) { GLOBAL.json = parseIcve(o.paper.PaperQuestions); uploadAnswer(GLOBAL.json); } } else if (location.pathname === "/study/exam/exam.html") { if (o.array) { GLOBAL.json = parseIcve(o.array.map(item => { return item.Questions; }).flat()); uploadAnswer(GLOBAL.json); } } }); }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { function get_element(id) { for (let jsonElement of GLOBAL.json) { if (jsonElement.id === id) { return jsonElement; } } } const ele = get_element(obj.$item.find("input:hidden").val()); obj.question = ele.question; obj.answer = ele.answerKey ? ele.answerKey : ele.answer; obj.type = ele.type; obj.options = ele.options; console.log(obj); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { UE$1.getEditor($option.attr("name")).setContent(answer); } } }); WorkerJSPlus({ name: "智慧职教 作业/考试", match: location.host.includes("zjy2.icve.com.cn"), intv: () => { return $(".subjectDet").length; }, root: ".subjectDet", elements: { question: "h5,.titleT .htmlP", options: ".optionList .el-radio__label,.el-checkbox__label", $options: ".optionList input", type: ".titleTwo,.xvhao" }, hook: () => { const parse = ques => { return ques.map(i => { const options = []; const answer = []; if (i.typeId === "3") { answer.push(i.optionAnswer === "1" ? "正确" : "错误"); } else if (/[12]/.test(i.typeId)) { options.push(...JSON.parse(i.dataJson).map(i => { if (i.IsAnswer) { answer.push(formatString(i.Content)); } return formatString(i.Content); })); } return { options: options, qid: i.id, answer: answer }; }); }; JSONParseHook(o => { if (o.name && o.questions && o.totalScore) { GLOBAL.json = parse(o.questions); } else if (o.data && o.data.questions) { GLOBAL.json = parse(o.data.questions); } }); }, ignore_click: $item => { return $($item).parent().attr("class") === "is-checked"; }, wrap: obj => { function findAnswer(id) { for (let jsonElement of GLOBAL.json) { if (jsonElement.qid === id) { return jsonElement.answer; } } } obj.answer = findAnswer(obj.$item.attr("id")); } }); function parseYkt(problems) { return problems.map(item => { const question = formatString(item.Body); const type = getQuestionType(item.TypeText); const options = []; const answer = []; if (type <= 1) { options.push(...item.Options.sort((a, b) => { return a.key.charCodeAt(0) - b.key.charCodeAt(0); }).map(item => { return formatString(item.value); })); if (item.Answer) { if (Array.isArray(item.Answer)) { answer.push(...item.Answer); } else { answer.push(...item.Answer.split("")); } } } else if (type === 3 && item.Answer && item.Answer.length === 1) { answer.push(item.Answer[0].replace("true", "正确").replace("false", "错误")); } return { answer: answer, options: options, type: type, qid: item.problem_id, question: question }; }); } function parsehnzkwText(problems) { return problems.map(item => { const type = item.flag === 1 ? 2 : item.flag === 0 ? 0 : item.flag === 4 ? 1 : item.flag === 3 ? 3 : undefined; let answer = []; let options = []; if (type === 2) { answer.push(item.answer); return { question: formatString(item.content), options: options, type: type, answer: answer }; } else if (type === 0) { for (let subjectOption of item.optionss) { const opt = formatString(subjectOption); options.push(opt); } if (type === 1) { item.answer.split("|").map(i => { answer.push(options[i.toUpperCase().charCodeAt(0) - 65]); }); } else { answer.push(options[item.answer.toUpperCase().charCodeAt(0) - 65]); } return { question: formatString(item.content), options: options, type: type, answer: answer }; } else if (type === 3) { for (let subjectOption of item.selectOption) { const opt = formatString(subjectOption); options.push(opt); } answer.push(item.answer); return { question: formatString(item.content), options: options, type: type, answer: answer }; } }); } function parseDanWei(pro) { return pro.map(i => { const type = getQuestionType(i.ttop010); const question = i.ttop011; const options = []; const answer = []; if (type === 0 || type === 1 || type === 3) { options.push(...i.ttop018.length > 0 ? i.ttop018.split("$$") : [ "正确", "错误" ]); answer.push(...i.ttop022.split("").map(item => { return options[item.charCodeAt(0) - 65]; })); } else if (type === 2 || type === 4) { answer.push(...i.ttop021.split("$$")); } return { question: question, type: type, answer: answer, options: options }; }).filter(i => i); } function parseYxbyunExam(problems) { return problems.map(item => { const type = getQuestionType(item.bigName); return item.smallContent.map(item => { let answer = []; let options = []; if (type === 2) { answer.push(item.answer); return { question: formatString(item.content), options: options, type: type, answer: answer }; } else if (type === 0 || type === 3 || type === 1) { let answer = []; let options = []; for (let subjectOption of item.question.optionList) { const opt = formatString(subjectOption.questionContent); options.push(opt); } if (type === 1) { item.question.questionAnswer.split(",").map(i => { answer.push(options[i.toUpperCase().charCodeAt(0) - 65]); }); } else { answer.push(options[item.question.questionAnswer.toUpperCase().charCodeAt(0) - 65]); } return { question: formatString(item.question.questionTitle), options: options, type: type, answer: answer }; } }); }); } WorkerJSPlus({ name: "雨课堂旧版考试", match: location.pathname.includes("/v/quiz/quiz_result"), intv: () => { return $("#cover").attr("style").includes("display: none;"); }, root: ".problem_item", elements: { question: ".notBullet:eq(0)", options: ".notBullet:gt(0)", $options: ".problembullet" }, ignore_click: $item => { return $item.hasClass("is-checked"); }, wrap: async obj => { const $item = obj.$item; const tmp = $item.find(".ptype").clone(); tmp.children().remove(); obj.type = getQuestionType(tmp.text()); obj.question = await yuketangOcr(obj.question.attr("data-background")); if (obj.$options.length === 2) { obj.options = [ "正确", "错误" ]; } else { const opt = []; for (const tmpElement of $item.find(".notBullet:gt(0)")) { opt.push(await yuketangOcr(jQuery(tmpElement).attr("data-background"))); } obj.options = opt; } } }); WorkerJSPlus({ name: "学堂在线", match: location.host === "www.xuetangx.com" && location.pathname.includes("/exercise/"), intv: () => { return $(".answer").length; }, root: ".content:eq(0)", elements: { question: ".question .fuwenben", options: ".question .leftQuestion .leftradio > span:last-child", $options: ".question .leftradio", type: ".question .title" }, ignore_click: $item => { return $item.find(".radio_jqq").hasClass("active"); }, wrap: obj => { if (obj.type === 3) { obj.$options = $(".answerList .radio_jqq"); } }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { UE.getEditor($option.find("textarea")).setContent(answer); } }, finished: () => { const $right = $(".tabbar").find(".right"); $right.click(); return !$right.hasClass("unselect"); } }); WorkerJSPlus({ name: "雨课堂新版考试", match: location.host.includes("yuketang.cn") && location.pathname.includes("/result/"), hook: () => { JSONParseHook(async o => { if (o.data && o.data.problems && o.data.problems.length > 0) { uploadAnswerToPlat(parseYkt(o.data.problems), 50); } }); } }); WorkerJSPlus({ name: "雨课堂新版考试", match: (location.host === "examination.xuetangx.com" || location.host === "changjiang-exam.yuketang.cn") && (location.pathname.includes("/exam/") || location.pathname.includes("/cover/")), hook: () => { JSONParseHook(async o => { if (o.data && o.data.problems && o.data.problems.length > 0) { GLOBAL.json = parseYkt(o.data.problems); } }); const intv = setInterval(() => { try { top.document.querySelector(".exam").__vue__.handleHangUpTip = function() {}; const querySelector = top.document.querySelector; top.document.querySelector = function(...args) { if (args[0] === "#model-id" || args[0].includes("hcSearcheModal")) return false; return querySelector.call(this, ...args); }; const getElementById = top.document.getElementById; top.document.getElementById = function(...args) { if (args[0] === "model-id" || args[0].includes("hcSearcheModal")) return false; return getElementById.call(this, ...args); }; clearInterval(intv); } catch (e) {} }, 100); }, intv: () => { return jQuery(".subject-item").length; }, root: ".exam-main--body .subject-item", elements: { question: ".item-body h4,.item-body span:eq(0)", options: ".item-body ul li", $options: ".item-body ul label, .blank-item-dynamic, .edui-editor-iframeholder", type: ".item-type" }, ignore_click: $item => { return $item.hasClass("is-checked"); }, wrap: obj => { obj.options = obj.type === 3 ? [ "正确", "错误" ] : obj.options.map(i => { return i.replace(/^[A-G]\s/, ""); }); try { obj.qid = GLOBAL.json[GLOBAL.index - 1].qid; obj.plat = 50; } catch (e) { console.log(e); } } }); WorkerJSPlus({ name: "雨课堂新版作业,需要一个一个点下一题的", match: location.pathname.includes("/v2/web/cloud/student/exercise/"), hook: () => { async function parseYkt(problems, font) { const res = problems.map(i => { const type = getQuestionType(i.content.TypeText); const question = i.content.Body; let options = []; if (type <= 1) { options = i.content.Options; } else if (type === 3) { options = i.content.Options.map(item => { return item.key.replace("true", "正确").replace("false", "错误"); }); } return { qid: i.problem_id, question: question, type: type, options: options, user: i.user }; }).filter(i => i); for (const item of res) { item.question = await getEncryptString(item.question, font); const answerArray = []; if (item.type <= 1) { const optionsArray = []; for (const itemElement of item.options) { const opt = await getEncryptString(itemElement.value, font); if (item.user && item.user.is_show_answer && item.user.answer.includes(itemElement.key)) { answerArray.push(opt); } optionsArray.push(opt); } item.options = optionsArray; } else if (item.type === 3) { if (item.user && item.user.is_show_answer && item.user.answer.length === 1) { answerArray.push(item.user.answer[0].replace("true", "正确").replace("false", "错误")); } } delete item.user; item.answer = answerArray; } return res; } JSONParseHook(async o => { if (o.data && o.data.problems) { GLOBAL.json = await parseYkt(o.data.problems, o.data.font); uploadAnswerToPlat(GLOBAL.json, 50); } }); }, intv: () => { return jQuery(".subject-item").length; }, root: ".container-problem .subject-item", elements: { question: ".problem-body", options: "label .radioText,.checkboxText", $options: "ul input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: async obj => { const index = jQuery(".item-type").text().match(/(\d+)\./)[1]; Object.assign(obj, GLOBAL.json[parseInt(index) - 1]); obj.plat = 50; }, finished: need_jump => { if ($(".el-button--text:contains(下一题)").hasClass("is-disabled")) return false; need_jump && setTimeout(() => { $(".el-button--text:contains(下一题)").click(); }, GLOBAL.fillAnswerDelay); return need_jump; } }); WorkerJSPlus({ name: "云班课", match: location.pathname === "/web/index.php" && location.href.includes("m=reply"), root: ".topic-item", elements: { question: ".t-con .t-subject", options: ".t-option label .option-content", $options: ".el-radio__input,.el-checkbox__input", type: ".t-info .t-type" }, ignore_click: $item => { return $item.hasClass("is-checked"); }, wrap: obj => { if (obj.type === "A1A2题") { obj.type = 1; } obj.question = obj.question.replace(//gi, ""); obj.options = obj.options.map(i => { return i.trim().replace(/^[abAB]\)\s+/, "").replace(/^[A-Za-z]\s+/, "").trim(); }); } }); WorkerJSPlus({ name: "中国地质大学", match: location.pathname.includes("/Exam/OnlineExamV2/"), root: ".stViewItem", elements: { question: ".stViewHead div", options: ".stViewCont .stViewOption a", $options: ".stViewCont .stViewOption a,input" }, intv: () => { return $(".ExamTime").length; }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().parent().prev().find(".E_E_L_I_C_R_C_T_SubType").text()); obj.question = obj.question.replace(/\(\d+分\)/, ""); obj.options = obj.options.map(i => { return i.replace(/\([A-Za-z]\)/, "").trim(); }); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { $option.val(answer); } } }); WorkerJSPlus({ name: "单位", match: (location.host === "61.183.163.9:8089" || location.host === "zjpt.nnjjtgs.com:8081") && (location.href.includes("ksnr") || location.href.includes("lxnr")), hook: () => { JSONParseHook(o => { if (o.topicList && o.topicList.length > 0) { GLOBAL.json = parseDanWei(o.topicList); uploadAnswer(GLOBAL.json); } }); }, root: ".tm", elements: { question: ".tmnrbj span:last-child", options: ".van-radio-group .dxt .van-radio__label,.van-checkbox__label", $options: ".van-radio-group .dxt .van-radio__label,.van-checkbox__label,.van-field__control", type: ".tmnrbj span" }, intv: () => { return $(".ExamTime").length || document.getElementById("pup-b"); }, wrap: obj => { obj.answer = GLOBAL.json[jQuery(".tmnrbj span:last-child").text().match(/^(\d+)、/)[1] - 1].answer; }, finished: () => { jQuery(".xyt").click(); return true; } }); WorkerJSPlus({ name: "小鹅通", match: location.pathname.includes("/evaluation_wechat/examination/detail/"), root: ".question-title,.title__text", elements: { question: "#detail_div", options: "label .image-text-box p", $options: "label,.simulation_inp" }, ignore_click: ($item, type) => { if (type === 0) { return $item.html().includes("single-exam-radio-active"); } else if (type === 1) { return $item.html().includes("check-i-active"); } }, wrap: obj => { const $item = obj.$item; obj.$options = $item.parent().next().find(".option-item,.checking-option__container,.fill_blank"); obj.type = getQuestionType($item.next().text()); if (obj.type === 2) { obj.$options = $item.parent().parent(); } if (obj.type === 3) { obj.options = [ "正确", "错误" ]; } else { obj.options = jQuery.map($item.parent().next().find(".option-item #detail_div"), function(val) { return formatString(filterImg(val)); }); } }, fill: (type, answer, $option) => { if (type === 2) { const vue = $option.get(0).__vue__; vue.content[0] = answer; vue.emitAnswer(); $option.find(".simulation_inp").text(answer); } } }); WorkerJSPlus({ name: "小饿通H5", match: location.host.includes("h5.xiaoeknow") || location.href.includes("/exam/h5_evaluation/"), root: ".practice-detail__body", elements: { question: ".question-wrap__title #detail_div", options: ".question-option #detail_div", $options: ".question-option #detail_div", type: ".question-wrap__title-tag" }, wrap: obj => { const $item = obj.$item; obj.$options = $item.parent().next().find(".option-item,.checking-option__container,.fill_blank"); obj.type = TYPE[$item.next().text().replace(/\s+/, "").replace("(", "").replace(")", "")]; if (obj.type === 2) { obj.$options = $item.parent().parent(); } if (obj.type === 3) { obj.options = [ "正确", "错误" ]; } else { obj.options = jQuery.map($item.parent().next().find(".option-item #detail_div"), function(val) { return formatString(filterImg(val)); }); } }, finished: () => { $(".practice-detail__bottom-item:last-child").click(); return $(".next").text() === "下一题"; } }); WorkerJSPlus({ name: "人卫慕课测验", match: location.pathname.includes("/memberFront/paper.zhtml"), intv: () => { return $("#question_").attr("style").length === 0; }, root: ".quesinfo", elements: { question: "dl dt", options: "dd label", $options: "dd input" }, wrap: obj => { if (obj.$options.length === 2) { obj.type = 3; obj.options = [ "正确", "错误" ]; } else { obj.type = 0; } } }); WorkerJSPlus({ name: "青书学堂考试", match: location.host.includes("qingshuxuetang") && (location.pathname.includes("/Student/MakeupExamPaper") || location.pathname.includes("Student/ExamPaper")), intv: () => { return $(".paper-container .question-detail-container").length; }, root: ".paper-container .question-detail-container", elements: { question: ".question-detail-description .detail-description-content", options: ".question-detail-options label .option-description", $options: ".question-detail-options label input", type: ".question-detail-type .question-detail-type-desc" }, ignore_click: $item => { return $item.prop("checked"); } }); WorkerJSPlus({ name: "青书学堂测验", match: location.host.includes("qingshuxuetang") && location.pathname.includes("/Student/ExercisePaper") || location.host === "quiz.qingshuxuetang.com" && location.pathname.includes("/Student/Quiz/Detail"), intv: () => { return $(".question-detail-container").length; }, root: ".question-detail-container", elements: { question: ".question-detail-description span", options: ".question-detail-options label .option-description", $options: ".question-detail-options div input,.question-detail-solution-textarea", type: ".question-detail-type" }, wrap: obj => { obj.options = obj.options.map(i => { return i.replace(/\([A-Za-z]\)/, "").trim(); }); }, ignore_click: ($item, type) => { if (type === 1) { return $item.prop("checked"); } }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { $option.parents().find(".question-controller-wrapper .next").click(); } } }); WorkerJSPlus({ name: "优学院测验", match: location.pathname === "/learnCourse/learnCourse.html", intv: () => { return $(".question-setting-panel").length; }, root: ".split-screen-wrapper", elements: { question: ".question-title-scroller .question-title-html", options: ".choice-list .content-wrapper .text", $options: ".choice-list .checkbox ,.question-body-wrapper .choice-btn", type: ".question-title-scroller .question-type-tag" }, wrap: obj => { obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); }, ignore_click: $item => { return $item.hasClass("selected"); } }); WorkerJSPlus({ name: "优学院作业", match: location.pathname === "/quiz/pc.html", intv: () => { return $(".questions").length; }, root: ".question-item", elements: { question: ".question-title", options: "ul label .choice-title", $options: "ul label input", type: ".title" }, wrap: obj => { obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); }, ignore_click: $item => { return $item.prop("checked"); } }); WorkerJSPlus({ name: "优学院考试", match: location.host === "utest.ulearning.cn" && location.pathname === "/", intv: () => { return $(".section-area").length; }, root: ".question-area .question-item", elements: { question: ".base-question .title .rich-text", options: ".choice-list label .rich-text", $options: ".choice-list label, .iconfont", type: ".base-question .title .tip" }, wrap: obj => { obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); }, ignore_click: $item => { return $item.hasClass("is-checked"); }, finished: () => { if ($(".next-part:contains(下个部分)").length) { $(".next-part").click(); return true; } else { return false; } } }); WorkerJSPlus({ name: "优学院作业", match: location.pathname === "/umooc/learner/homework.do", intv: () => { return $(".multiple-choices").length; }, root: ".multiple-choices,.judge", elements: { question: "h5 .position-rltv span:last-child", options: "ul label span:last-child", $options: "ul label input,.radios .radio input", type: "h5 .typeName" }, wrap: obj => { obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); }, ignore_click: $item => { return $item.prev().hasClass("checkbox-checked"); } }); WorkerJSPlus({ name: "万学", match: location.pathname.includes("/sls/N2014_StudyController/next"), root: ".question", elements: { question: "tr .nm2", options: ".grey td p", $options: ".option li label", type: "tr .nm2" }, wrap: obj => { obj.question = obj.question.parent().find("td p").text(); } }); WorkerJSPlus({ name: "wenJuanAutoFill", match: location.host.includes("wenjuan.com") && location.pathname === "/s/", root: "questionContent", elements: { question: ".title", options: ".icheckbox_div .option_label", $options: ".icheckbox_div label", type: ".question_num" }, ignore_click: $item => { return $item.attr("class").includes("checked"); } }); WorkerJSPlus({ name: "学起(考试)", match: location.pathname.includes("/oxer/page/ots/examIndex.html"), intv: () => { return $(".tika_topline").length; }, root: ".queItemClass", elements: { question: "dt .din:eq(1)", options: ".clearfix div", $options: ".clearfix .xuan,input" }, ignore_click: $item => { return $item.parent().hasClass("cur"); }, wrap: obj => { obj.plat = 66; obj.qid = obj.$item.attr("id"); obj.type = getQuestionType(obj.$item.parent().find("div .fb:eq(0)").text()); if (obj.type === 3) { obj.options = [ "正确", "错误" ]; } } }); WorkerJSPlus({ name: "学起(测试)", match: location.pathname.includes("/oxer/page/ots/UniversityStart.html"), intv: () => { return $(".uniQueList").length; }, root: ".uniQueItem", elements: { question: ".QueStem", options: "ul li span", $options: "ul li" }, ignore_click: $item => { return $item.parent().hasClass("lichecked"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parents(".uniQueList").find(".fir").text()); if (obj.type === 3) { obj.options = [ "正确", "错误" ]; } console.log(obj); } }); WorkerJSPlus({ name: "易班考试", match: location.host === "exam.yooc.me" && location.pathname.includes("/group"), intv: () => { return $(".jsx-3527395752").length; }, root: "main:last", elements: { question: "h3 div", options: ".mb ul li .flex-auto", $options: ".mb ul li", type: ".mb-s" }, ignore_click: $item => { return $item.hasClass("_c"); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { $(".exam-input").val("answer"); } }, finished: need_jump => { if ($('.round:contains("下一题")').hasClass("ghost")) return false; $('.round:contains("下一题")').click(); return true; } }); WorkerJSPlus({ name: "英华学堂", match: () => { const pathMatch = location.pathname.includes("/user/work") || location.pathname.includes("/user/exam"); const matchHostArr = [ "mooc.kdcnu.com", "mooc.yncjxy.com", "mooc.cdcas.com", "mooc.cqcst.edu.cn", "mooc.kmcc.edu.cn", "mooc.wuhues.com" ]; return pathMatch && matchHostArr.includes(location.host); }, intv: () => { return $("#stateName").text().trim() === "进行中"; }, root: ".courseexamcon-main", elements: { question: ".name", options: ".list li .txt", $options: ".list li .exam-inp", type: ".type" }, ignore_click: $item => { return $item.prop("checked"); }, fill: (type, answer, $option) => {}, finished: auto_jump => { if ($(".next_exam").eq(3).prop("style")[0] == "display") return false; $(".next_exam").click(); } }); WorkerJSPlus({ name: "厦门在线教育测验", match: location.pathname.includes("/nec/student/exam/exam-paper!test"), root: "#paper_form > div:nth-child(4) > table:nth-child(1) > tbody:nth-child(2)>tr:even", elements: { question: "td:eq(1)", options: ".optionUl label .el-radio__label,.el-checkbox__label", $options: ".optionUl label" }, wrap: obj => { obj.options = obj.$item.next().find("tbody:first > tr tbody").map((i, y) => { return $(y).find("td:eq(1)").text(); }).toArray(); obj.$options = obj.$item.next().find("tbody:first > tr tbody").map((i, y) => { return $(y).find("input"); }); obj.type = 0; } }); WorkerJSPlus({ name: "金牌学堂", match: location.host === "www.goldgame.com.cn" && location.href.includes("/TestPage"), intv: () => { return $(".tab-btn-box li").length; }, root: ".test-type-box ul .white-bg", elements: { question: ".position-relative h3", options: ".test-option label p:last-child", $options: ".test-option label input" }, wrap: obj => { obj.question = obj.question.replace(/题目\d+\:/, "").trim().replace(/^\d+./, ""); obj.type = getQuestionType(obj.$item.parent().parent().find(".test-type-tips").text()); if (obj.$options.length > 2 && obj.$options.eq(0).hasClass("radiobox")) { obj.type = 0; } }, fillFinish: data => { $(".answer-sheet li").eq(GLOBAL.index).click(); } }); WorkerJSPlus({ name: "青岛开放大学", match: location.pathname.includes("/pages/exam/exam.html"), intv: () => { return $(".exam-content-block .exam-content-topic").length; }, root: ".exam-content-block .exam-content-topic", elements: { question: ".exam-topic-title", options: ".exam-topic-answer .layui-unselect span", $options: ".exam-topic-answer .layui-unselect" }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find(".exam-content-title .exam-content-num").text()); } }); WorkerJSPlus({ name: "点墨考试", match: location.pathname.includes("/Exam/StartExam"), root: "#question div div:first", elements: { question: "div:first", options: "div:first ~ div", $options: "div:first ~ div input" }, wrap: obj => { obj.type = getQuestionType($(".alert #groupNameSpan").text()); }, finished: () => { $(".w-100 .btn-light:eq(1)").click(); return true; } }); WorkerJSPlus({ name: "点墨测验", match: location.pathname.includes("/Course/TestPaper"), root: ".question", elements: { question: " div div:first div:first", options: " div div:first div:first ~ div", $options: " div div:first div:first ~ div input" }, wrap: obj => { obj.type = getQuestionType($("h3").text()); obj.question = obj.question.replace(/^\d+\./, ""); } }); WorkerJSPlus({ name: "警官学院", match: location.pathname.includes("/bsmytest/startTi.do"), root: ".wrapper > div", elements: { question: ".dx", options: "p", $options: "p input" }, wrap: obj => { if ($(".wrapper .cl").length > 0) { obj.question = obj.$item.text().replace(/[0-9]、/, "").replace(/\(.*?\)/g, "").trim().split("$")[0].replace(/\(.*?\)/g, "").trim(); } else { obj.question = obj.question.replace(/[0-9]、/, "").replace(/\(.*?\)/g, "").trim(); } obj.type = getQuestionType(obj.$item.parent().find("h2").text()); obj.options = obj.options.map(item => { return item.replace(/[A-Za-z][\:]/, "").replace(/[A-Za-z][\:,\:]/, "").replace(/\;/, "").trim(); }); } }); WorkerJSPlus({ name: "exam2_euibe_com_exam", match: location.hostname === "exam2.euibe.com" && location.pathname === "/KaoShi/ShiTiYe.aspx", root: ".question", elements: { question: ".wenti", options: "li label span", $options: "li label" }, wrap: obj => { obj.type = getQuestionType($(".question_head").text()); }, finished: need_jump => { $(".paginationjs-next").click(); return true; } }); WorkerJSPlus({ name: "lzwyedu_jijiaool_com_exam", match: () => { const pathMatch = location.pathname.includes("/learnspace/course/test/") || location.pathname.includes("/Student/ExamManage/CourseOnlineExamination"); const matchHostArr = [ "lzwyedu.jijiaool.com", "cgjx.jsnu.edu.cn", "learn-cs.icve.com.cn", "nwnu.jijiaool.com", "lut.jijiaool.com", "learn.courshare.cn", "cj1027-kfkc.webtrn.cn" ]; return pathMatch && matchHostArr.includes(location.host); }, root: ".test_item", elements: { question: ".test_item_tit", options: ".test_item_theme label .zdh_op_con", $options: "label input" }, wrap: obj => { obj.question = obj.question.replace(/该题未做$/, "").replace(/^\d+\./, "").replace(/^\d+、/, "").replace(/[((](\d+\s?(\.\d+)?分)[))]$/, "").replace(/^((\d+.(\s+)?)?)[\[((【](.*?)[】))\]]/, "").trim(); obj.type = getQuestionType(obj.$item.prevAll(".test_item_type:first").text()); if (obj.type === 3) { obj.options = [ "对", "错" ]; } } }); WorkerJSPlus({ name: "zzx_ouchn_edu_cn_exam", match: location.hostname === "zzx.ouchn.edu.cn" && location.pathname.includes("/edu/public/student/"), root: ".subject", elements: { question: ".question span", options: ".answer>span>p:first-child", $options: ".answer>span>p:first-child" }, wrap: obj => { if (obj.$options.length > 1) { obj.type = 0; } } }); WorkerJSPlus({ name: "zzx_ouchn_edu_cn_exam", match: location.hostname === "zzx.ouchn.edu.cn" && location.pathname.includes("/edu/public/student/"), root: ".subject", elements: { question: ".question span", options: ".answer>span>p:first-child", $options: ".answer>span>p:first-child" }, wrap: obj => { if (obj.$options.length > 1) { obj.type = 0; } } }); WorkerJSPlus({ name: "havust_hnscen_cn_exam", match: location.hostname === "havust.hnscen.cn" && location.pathname.includes("/stuExam/examing/"), root: ".main .mt_2 > div", elements: { question: ".flex_row+div", options: ".flex_row+div+div .el-radio__label,.el-checkbox__label", $options: ".flex_row+div+div .el-radio__label,.el-checkbox__label", type: ".flex_row .mr_2" } }); WorkerJSPlus({ name: "www_zygbxxpt_com_exam", match: location.hostname === "www.zygbxxpt.com" && location.pathname.includes("/exam"), root: ".Body", elements: { question: ".QName", options: ".QuestinXuanXiang p:parent", $options: ".QuestinXuanXiang p:parent", type: ".QName span" }, wrap: obj => { obj.question = obj.question.replace(/\([^\)]*\)/g, "").replace(/\【.*?\】/g, ""); obj.options = obj.options.map(item => { return item.split(">").pop().trim(); }); } }); WorkerJSPlus({ name: "xuexi_jsou_cn_work", match: location.hostname === "xuexi.jsou.cn" && location.pathname.includes("/jxpt-web/student/newHomework/showHomeworkByStatus"), root: ".insert", elements: { question: ".window-title", options: ".questionId-option .option-title div[style^=display]", $options: ".questionId-option .option-title .numberCover" }, wrap: obj => { obj.type = { 1: 0, 2: 1, 7: 3 }[obj.$item.find(".question-type").val()]; if (obj.options.length == 2) { obj.type = 3; } } }); WorkerJSPlus({ name: "czvtc_cjEdu_com_exam", match: () => { const pathMatch = location.pathname.includes("/ExamInfo") || location.pathname.includes("/Examination"); const matchHostArr = [ "czvtc.cj-edu.com", "hbkjxy.cj-edu.com", "bhlgxy.cj-edu.com", "hbsi.cj-edu.com", "czys.cj-edu.com", "hbjd.cj-edu.com", "xttc.cj-edu.com", "bvtc.cj-edu.com", "caztc.cj-edu.com" ]; return pathMatch && matchHostArr.includes(location.host); }, intv: () => { return $(".el-container .all_subject>.el-row").length; }, root: ".el-container .all_subject>.el-row", elements: { question: ".stem div:last-child", options: ".el-radio-group .el-radio__label,.el-checkbox-group .el-checkbox__label", $options: ".el-radio-group .el-radio__original,.el-checkbox-group .el-checkbox__original" }, wrap: obj => { if (obj.$options.length < 3 && obj.$options.eq(0).attr("type") === "radio") { obj.type = 3; } else if (obj.$options.length > 2 && obj.$options.eq(0).attr("type") === "radio") { obj.type = 0; } else if (obj.$options.length > 2 && obj.$options.eq(0).attr("type") === "checkbox") { obj.type = 1; } } }); WorkerJSPlus({ name: "learning_mhtall_com_exam", match: location.host.includes("learning.mhtall.com") && location.pathname.includes("/rest/course/exercise/item"), root: "#div_item", elements: { question: ".item_title", options: ".opt div label", $options: ".opt div input:not(.button_short)", type: "h4" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { if (obj.type === 0 || obj.type === 3) { obj.answer = $(".div_answer").text().match(/[a-zA-Z]/).map(i => { return obj.options[i.charCodeAt(0) - 65]; }); } else if (obj.type === 2) { obj.answer = $(".div_answer").text().replace("参考答案:", "").split(","); } }, fill: (type, answer, $option) => { if (type === 2 || type === 4) { $option.val(answer); $(".DIV_TYPE_BLANK .button_short").click(); } }, fillFinish: () => { if ($(".opt+div+div input:eq(1)").val() === "下一题") { $(".opt+div+div input:eq(1)").click(); } else { $(".button_short:eq(2)").click(); } } }); WorkerJSPlus({ name: "168网校(测验)", match: location.host.includes("168wangxiao.com") && location.pathname.includes("/web/learningCenter/details/"), intv: () => { return $(".ret-answer").length === 0 && $(".info-container").length; }, root: ".question-item-container", elements: { question: ".title-content", options: ".options .opt-content", $options: ".options label", type: ".top .type" } }); WorkerJSPlus({ name: "168网校(考试)", match: location.host.includes("168wangxiao.com") && location.pathname.includes("/web/examination/answer"), intv: () => { return $(".Answer-area").length; }, root: ".Answer-area", elements: { question: ".listTit", options: ".el-radio__label span:last-child,.el-checkbox__label span:last-child", $options: ".el-radio__input,.el-checkbox__input input,.ql-editor p" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { if (obj.options.length === 0) { obj.type = 2; } console.log(obj); }, fill: (type, answer, $option) => { if (type === 2 || type === 4) { console.log(answer); document.querySelector(".ql-editor p").textContent = answer; } }, finished: () => { if ($(".ctrl .el-button:contains(下一题)").length != 0) { $(".ctrl .el-button:contains(下一题)").click(); return true; } else if ($(".ctrl .el-button:contains(上一题)").length && $(".ctrl button").length === 1) { return false; } } }); WorkerJSPlus({ name: "法宣在线", match: location.host.includes("faxuanyun.com") && location.pathname.includes("/bps/examination"), intv: () => { return $("#timucontent").length; }, root: "#timucontent", elements: { question: "h2", options: "ul li", $options: "ul input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.question = obj.question.replace(/[\((].+?[)\)]/g, ""); if ($(".layui-layer-content").length) { iframeMsg("tip", { type: "stop", tip: "答题暂停,请自行通过验证" }); $("#lastButton").click(); GLOBAL.stop = true; return false; } }, finished: need_jump => { if ($("#nextButton").length) { $("#nextButton").click(); return true; } else { return false; } } }); WorkerJSPlus({ name: "山财培训网 (补考)", match: location.host.includes("training.sdufe.edu.cn") && location.pathname.includes("/Exam/OnlineExam/"), intv: () => { return $(".exam_r_m").length; }, root: ".exam_r_m", elements: { question: ".bt", options: ".btm", $options: ".btm input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.question = obj.question.replace(/[\((].+?[)\)]/g, ""); obj.options = $("br").parent().text().split(/[A-Z]\./).slice(1).map(item => { return item.trim(); }); if (obj.type === 3) { obj.answer = $("#answerDiv").text().replace("正确答案:", "").split(); } else { obj.answer = $("#answerDiv").text().match(/[A-Z]/g).map(item => { return obj.options[item.charCodeAt(0) - 65]; }); } }, finished: () => { document.querySelector("#next").click(); if (document.querySelector("#noAskCount").textContent == "0") { return false; } return true; } }); WorkerJSPlus({ name: "和学在线", match: (location.host.includes("student.hexuezx") || location.host.includes("student.jxjyzx")) && location.hash.includes("homework-questions"), intv: () => { return $(".el-card__body").length; }, root: ".el-card__body", elements: { question: ".stem", options: ".el-radio__label,.el-checkbox__label span", $options: ".el-radio__input,.el-checkbox__input input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.question = obj.question.replace(/[\((].+?[)\)]/g, ""); console.log(obj); } }); WorkerJSPlus({ name: "高教在线", match: location.host === "www.cqooc.com" && (location.href.includes("/learn/mooc/exam/do") || location.href.includes("/learn/mooc/testing/do")), intv: () => { return $("#test-form").length; }, root: "#test-form .cat", elements: { question: ".stem", options: ".option label", $options: ".option input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.question = obj.question.replace(/\(\d+分\)\d+\.\d+/, ""); console.log(obj); } }); WorkerJSPlus({ name: "柠檬文才(考试)", match: () => { const pathMatch = location.pathname.includes("/separation/exam/"); const matchHostArr = [ "learning.wuxuejiaoyu.cn", "learning.wencaischool.net", "learning.zk211.com", "study.wencaischool.net", "www.wencaischool.net" ]; return pathMatch && matchHostArr.includes(location.host); }, intv: () => { return $("#paperExam").css("display") != "none"; }, root: ".paperWrapper .tmList", elements: { question: ".tmTitleTxt", options: ".ansbox .opCont", $options: ".ansbox input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { if (obj.options.length === 0) { obj.type = 2; } console.log(obj); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { $option.val(answer); } } }); WorkerJSPlus({ name: "柠檬文才(作业)", match: () => { const matchHostArr = [ "learning.wuxuejiaoyu.cn", "learning.wencaischool.net", "learning.zk211.com", "study.wencaischool.net" ]; return (location.pathname.includes("/hblearning/exam/") || location.pathname.includes("/xbsflearning/exam/") || location.pathname.includes("/openlearning/exam/") || location.pathname.includes("/jxlearning/exam/") || location.pathname.includes("/shandonglearning/exam")) && matchHostArr.includes(location.host); }, intv: () => { return $("#paperExam").css("display") !== "none"; }, root: "#_block_content_exam #tblDataList>tbody>tr", elements: { question: "tbody:first>tr>td:last table", options: ".ansbox .opCont", $options: ".ansbox input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.question = $("#_block_content_exam #tblDataList>tbody>tr>td").find(" tbody:first>tr>td:last table:first").eq(GLOBAL.index - 1).find("tr:first").text(); obj.options = []; $("#_block_content_exam #tblDataList>tbody>tr>td").find(" tbody:first>tr>td:last table:first").eq(GLOBAL.index - 1).find("tr:first").next().find("label").map((i, y) => { obj.options.push($(y).text()); }); obj.$options = $("#_block_content_exam #tblDataList>tbody>tr>td").find(" tbody:first>tr>td:last table:first").eq(GLOBAL.index - 1).find("tr:first").next().find("input").map((i, y) => { return y; }); obj.type = 0; if (obj.options.length == 2) { obj.type = 3; } else if (obj.$options.eq(0).attr("type") != "radio") { obj.type = 1; } console.log(obj); } }); WorkerJSPlus({ name: "福建师范", match: location.host === "neo.fjnu.cn" && location.pathname.includes("/resource/index"), intv: () => { return $(".content").length && !$(".answer-content").length; }, root: ".content", elements: { question: ".title", options: "label .el-radio__label,.el-checkbox__label", $options: "label input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { console.log(obj); } }); WorkerJSPlus({ name: "优课学堂", match: location.host.includes("youkexuetang.cn") && location.pathname.includes("/student/"), intv: () => { return $(".paperItemBox").length; }, root: ".paperItemBox", elements: { question: ".stem", options: ".el-radio__label,.el-checkbox__label", $options: ".el-radio__input,.el-checkbox__input input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.question = obj.question.replace(/[\((].+?[)\)]/g, ""); console.log(obj); } }); WorkerJSPlus({ name: "亿学宝云", match: location.host.includes("yxbyun.com") && location.pathname.includes("/yxbstudent/"), intv: () => { return $(".time_header").length || $(".pager_wrap").length; }, hook: () => { JSONParseHook(o => { if (o.data && o.data.bigContent) { GLOBAL.json = parseYxbyunExam(o.data.bigContent).reduce((acc, cur) => { return acc.concat(cur); }, []); console.log(GLOBAL.json); } }); }, root: ".test", elements: { question: ".type", options: ".el-radio-group,.el-checkbox-group label", $options: ".el-radio__input,.el-checkbox__input input", type: ".el-tag" }, wrap: obj => { Object.assign(obj, GLOBAL.json[GLOBAL.index - 1]); }, ignore_click: $item => { return $item.prop("checked"); } }); WorkerJSPlus({ name: "考试星(单题)", match: Boolean(location.host === "exam.kaoshixing.com" && location.pathname.includes("/exam/exam_start")), intv: () => { return $("#nextQuestions").length; }, root: ".questions .questions-content", elements: { question: ".question-name", options: ".answers label .words", $options: ".answers label" }, ignore_click: $item => { return $item.parent().find("input").prop("checked"); }, wrap: obj => { obj.question = obj.question.replace(/[\((].+?[)\)]/g, ""); console.log(obj); }, finished: () => { if ($("#nextQuestions:contains(下一题)").length && $("#nextQuestions").css("display") !== "none") { $("#nextQuestions:contains(下一题)").click(); return true; } else { return false; } } }); WorkerJSPlus({ name: "易考云", match: location.host === "exam.beeouc.com" && location.pathname.includes("/client"), intv: () => { return $(".question-body").length; }, root: ".question-body", elements: { question: ".question-stem", options: ".question-option label", $options: ".question-option input", type: ".question-type" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { console.log(obj); }, finished: () => { if ($(".question-footer button:contains(下一题)").length) { $(".question-footer button:contains(下一题)").click(); return true; } else { return false; } } }); WorkerJSPlus({ name: "伊犁师范成人教育", match: location.host === "exam.weirenzheng.cn" && (location.pathname.includes("//GeneralTestPaper/Testing/") || location.pathname.includes("//GeneralTestPaper/SNTesting")), intv: () => { return $(".topic").length; }, root: ".topic", elements: { question: ".qsctt", options: ".xuan li", $options: ".choice input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.options = obj.options.map(i => { return i.replace(/^[A-Z] \. /, ""); }); if (obj.$options.length == 2) { obj.options = [ "正确", "错误" ]; obj.type = 3; } } }); WorkerJSPlus({ name: "绎通云课堂 (作业)", match: location.host.includes("ytccr.com") && (location.hash.includes("#/learning-work") || location.hash.includes("#/learning-details")), intv: () => { return $(".left-question").length; }, root: ".border-item", elements: { question: ".qa-title", options: "label .opt-title-cnt", $options: "label input" }, ignore_click: $item => { return $item.prop("checked"); } }); WorkerJSPlus({ name: "重庆大学网络教育学院 (作业)", match: location.host === "exercise.5any.com" && location.pathname.includes("/Exercise/WebUI/Test/Answer"), intv: () => { return $(".examtime-content").length; }, root: ".subject .font-16", elements: { question: ".stem .richtextcontent", options: ".option .richtextcontent", $options: ".option label input" }, ignore_click: $item => { return $item.prop("checked"); } }); WorkerJSPlus({ name: "毕节幼儿师范", match: location.host === "px.gzbjyzjxjy.cn" || location.host === "px.ggcjxjy.cn" && location.pathname.includes("/exam/shiti/dopapers"), intv: () => { return $(".panel-body").length; }, root: ".panel-body>div", elements: { question: ".testpaper-question-stem", options: ".testpaper-question-choices li", $options: ".testpaper-question-footer input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { console.log(obj); } }); WorkerJSPlus({ name: "贵州继续教育", match: location.host === "www.gzjxjy.gzsrs.cn" && location.pathname.includes("/personback/"), intv: () => { return $(".question-title").length; }, root: ".question-title", elements: { question: ".show-text", options: "label", $options: "label input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { console.log(obj); } }); WorkerJSPlus({ name: "和学自考", match: location.host === "zkpt.qdu.edu.cn" && location.pathname.includes("/examStu/exam/examPaper"), intv: () => { return $(".ant-spin-container").length; }, root: ".ant-row", elements: { options: "label", $options: "label input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.question = obj.$item.parent().parent().prev().text(); console.log(obj); } }); WorkerJSPlus({ name: "专技天下", match: location.host.includes("zgzjzj.com") && location.pathname.includes("/examination/perpar.html"), intv: () => { return $(".question_index").length; }, root: ".question_index", elements: { question: "p", options: ".options li p,li>span:last-child", $options: ".options li", type: "p span" }, ignore_click: $item => { return $item.hasClass("active"); } }); WorkerJSPlus({ name: "睿学补考", match: location.href.includes("exam-app-exam-paper") && location.host.includes("ks.hustsnde.com"), intv: () => { return $("#paper").length; }, root: "#paper .content-box", elements: { question: "ul li:eq(0) .desc", options: "ul li:eq(1)", $options: "ul label input", type: ".title" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { const options = obj.options[0].trim().split(/\[[A-Z]:?\]/).splice(1).map(i => { return i.trim(); }).filter(i => i); if (options.length === 0) { obj.options = obj.options[0].trim().split(/\(?[A-Z\.?]\)?/).splice(1).map(i => { return i.trim(); }).filter(i => i); } else { obj.options = options; } if (obj.type === 3) { obj.options = [ "正确", "错误" ]; } } }); WorkerJSPlus({ name: "云上河开", match: location.host === "jx.open.ha.cn" && location.pathname.includes("/jxpt-web/student/homework/showHomeworkByStatus"), intv: () => { return $("#shiti-content").length; }, root: ".insert", elements: { question: ".window-title", options: "ul li div:last-child", $options: "ul li .numberCover" }, ignore_click: $item => { return $item.parent().hasClass("answer-title"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parents(".layui-colla-item").find(".titleType").text()); } }); WorkerJSPlus({ name: "ycjy.lut.edu.cn", match: location.host === "ycjy.lut.edu.cn" && location.pathname.includes("/learnspace/course/test/coursewareTest_intoTestPage.action"), intv: () => { return $(".bank_cont").length; }, root: ".test_item", elements: { options: "label", $options: "label input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find(".test_item_type").text()); obj.question = obj.$item.find(".test_item_tit").contents()[0].nodeValue.trim(); } }); WorkerJSPlus({ name: "exam.euibe.com", match: location.host === "exam.euibe.com" && location.pathname.includes("/KaoShi/ShiTiYe.aspx"), intv: () => { return $(".question_list").length; }, root: ".question", elements: { question: ".wenti .stem", options: "label span", $options: "label input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parents(".question_list").find(".question_head").text()); }, finished: need_jump => { if ($(".paginationjs-next").hasClass("disabled")) { return false; } $(".paginationjs-next").click(); return true; } }); WorkerJSPlus({ name: "学晖教育", match: location.host === "xhjy.ldzxjy.com" && location.pathname.includes("tikuUserBatch/keepTopic"), intv: () => { return $(".radio").length; }, root: ".radio", elements: { question: ".issueTitle", options: "ul li span", $options: "ul li", type: ".issueTypes" }, ignore_click: $item => { return $item.prop("checked"); }, finished: need_jump => { if ($(".next").text().includes("交卷")) { return false; } $(".next").click(); return true; } }); WorkerJSPlus({ name: "东财在线", match: location.host === "classroom.edufe.com.cn" && (location.pathname.includes("/PracticePaper") || location.pathname.includes("/HomeWorkPaper")), intv: () => { return $(".TK-main").length; }, root: ".CBTPaperMain-trunk", elements: { question: ".CBTPaperMain-divInline", options: "ul li label", $options: "ul li label" }, ignore_click: $item => { return $item.hasClass("_CheckBox_checked"); } }); WorkerJSPlus({ name: "北华大学在线教育", match: () => { const pathnameArr = [ "cj1026-kfkc.webtrn.cn", "beihua.peishenjy.com" ]; return pathnameArr.includes(location.pathname) && location.pathname.includes("/Learning/CourseOnlineExamination") || location.pathname.includes("/learnspace/course/test"); }, intv: () => { return $(".s_mi").length; }, root: ".test_item", elements: { question: ".test_item_tit", options: " label", $options: "label input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { console.log(obj); } }); WorkerJSPlus({ name: "上海立达学院", match: location.host === "kkzxsx.lidapoly.edu.cn" && location.pathname.includes("/exam/"), intv: () => { return $(".exam-question").length; }, root: ".main .item", elements: { question: ".text", options: ".options label .el-radio__label,.el-checkbox__label", $options: ".options label" }, ignore_click: $item => { return $item.hasClass("is-checked"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find(".text").text()); console.log(obj); } }); WorkerJSPlus({ name: "石家庄科技继续教育", match: location.host.includes("kc.jxjypt.cn") && location.pathname.includes("/paper/start"), intv: () => { return $(".sub-content").length; }, root: ".sub-content", elements: { question: ".sub-dotitle", options: ".sub-answer dd", $options: ".sub-answer dd,.mater-respond textarea", type: ".sub-dotitle i" }, ignore_click: $item => { return $item.hasClass("cho-this"); }, wrap: obj => { console.log(obj); }, fill: (type, answer, $option) => { if (type === 4) { $option.val(answer); } } }); WorkerJSPlus({ name: "石家庄理工职业学院", match: location.host.includes("edu.tianzerencai.com") && location.pathname.includes("/examinationDetail"), intv: () => { return $(".topic").length; }, root: ".topic", elements: { question: ".title", options: ".main", $options: ".main", type: ".title" }, ignore_click: $item => { return $item.hasClass("cho-this"); }, wrap: obj => { if (obj.type === 3) { obj.options = [ "正确", "错误" ]; obj.$options = obj.$item.find(".judge button"); } else if (obj.type === 1) { obj.options = obj.$item.find(".checkbox .option_text").map((i, y) => { return $(y).text(); }).toArray(); obj.$options = obj.$item.find(".checkbox button"); } else if (obj.type === 0) { obj.options = obj.$item.find(".radio .option_text").map((i, y) => { return $(y).text(); }).toArray(); obj.$options = obj.$item.find(".radio button"); } console.log(obj); } }); WorkerJSPlus({ name: "国开军盾", match: location.host.includes("s.jundunxueyuan.com") && location.hash.includes("#/exam/"), intv: () => { return $(".the-paper .section-item-question-item").length; }, root: ".section-item-question-item", elements: { plat: 43, question: ".question-tit", options: ".el-radio-group label,.el-checkbox-group label", $options: ".el-radio-group input,.el-checkbox-group input", type: ".sub-dotitle i" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parents(".section-item").find(".section-item-tit").text()); console.log(obj); } }); WorkerJSPlus({ name: "博学bx", match: location.host.includes("bx.bossyun.com") && location.pathname.includes("/bx/study/examine"), intv: () => { return $(".question-list").length; }, root: ".question-list", elements: { question: ".title", options: ".ant-radio-group label,.ant-checkbox-group label", $options: ".ant-radio-group input,.ant-checkbox-group input", type: ".tag" }, ignore_click: $item => { return $item.prop("checked"); } }); WorkerJSPlus({ name: "博学bx", match: location.host.includes("bx.bossyun.com") && location.pathname.includes("/bx/study/examine"), intv: () => { return $(".question-list").length; }, root: ".question-list", elements: { question: ".title", options: ".ant-radio-group label,.ant-checkbox-group label", $options: ".ant-radio-group input,.ant-checkbox-group input", type: ".tag" }, ignore_click: $item => { return $item.prop("checked"); } }); WorkerJSPlus({ name: "电中在线", match: location.host.includes("old-zzx.ouchn.edu.cn") && location.pathname.includes("/edu/public/student/"), intv: () => { return $(".subject").length; }, root: ".subject", elements: { question: ".question", options: ".answer .option-name", $options: ".answer" }, wrap: obj => { obj.type = 0; console.log(obj); } }); WorkerJSPlus({ name: "爱学", match: () => { const pathMatch = location.pathname.includes("/Web/Test/doing"); const matchHostArr = [ "ai.ztbu.edu.cn", "www.51ixuejiao.com" ]; return pathMatch && matchHostArr.includes(location.host); }, intv: () => { return $("card-title").length; }, root: ".exam dd", elements: { question: "card-title", options: ".ans_area div", $options: ".ans_area div", type: "info" }, ignore_click: $item => { return $item.attr("selected") === "selected"; }, wrap: obj => { console.log(obj); }, fillFinish: data => { if (data.ans.includes("span") || data.type === 1) { $(".move_btn span:last").click(); } } }); WorkerJSPlus({ name: "人卫智网", match: location.host.includes("exam.ipmph.com") && location.pathname.includes("/front/myschool/index.html"), intv: () => { return $(".body").length; }, root: ".body", elements: { question: ".fch2 font", options: ".selet .el-radio__label", $options: ".selet input" }, wrap: obj => { obj.type = 0; console.log(obj); }, finished: () => { document.querySelector(".next-btn .text-right a:last-child").click(); } }); WorkerJSPlus({ name: "卫生人力资源系统", match: location.host.includes("vgos.zbwsrc.cn") && location.pathname.includes("/TESExamClient/"), intv: () => { return $(".testitem").length; }, root: ".testitem", elements: { question: ".stem", options: ".inputitem li", $options: ".inputitem input" }, wrap: obj => { obj.type = 0; console.log(obj); } }); WorkerJSPlus({ name: "继教在线(考试)", match: location.pathname.includes("/Student/ExamManage/CourseOnlineExamination"), intv: () => { return $(".test_item").length; }, root: ".test_item", elements: { question: ".test_item_tit", options: ".test_item_theme label", $options: ".test_item_theme input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { const $item = obj.$item; obj.type = getQuestionType($item.prevAll(".test_item_type").text()); if (obj.type === 3) { obj.options = [ "正确", "错误" ]; } } }); WorkerJSPlus({ name: "国开", match: location.host === "lms.ouchn.cn" && location.pathname.includes("/exam/"), intv: () => { return $(".loading-gif").hasClass("ng-hide") && $(".hd .examinee .submit-label").eq(0).text() === ""; }, root: ".card ol .single_selection,.multiple_selection,.true_or_false,.short_answer", elements: { question: ".summary-title .subject-description", options: ".subject-options li .option-content", $options: ".subject-options label .left", type: ".summary-sub-title span:eq(0)" }, ignore_click: ($item, type) => { return type === 1 && $item.find("input").hasClass("ng-not-empty"); } }); WorkerJSPlus({ name: "广开", match: () => { const pathMatch = location.pathname.includes("/mod/quiz/attempt.php"); const matchHostArr = [ "moodle.syxy.ouchn.cn", "xczxzdbf.moodle.qwbx.ouchn.cn", "elearning.bjou.edu.cn", "whkpc.hnqtyq.cn:5678", "course.ougd.cn", "study.ouchn.cn" ]; return pathMatch && matchHostArr.includes(location.host); }, root: ".que", elements: { question: ".qtext", options: ".answer div label,.flex-fill", $options: ".answer div input:visible" }, wrap: data => { if (data.type === undefined) { try { data.type = 4; data.$item.find(".qtext .accesshide").remove(); data.question = formatString(data.$item.find(".qtext").html()); data.$options = data.$item.find("input[id$=_answer]"); } catch (e) {} } }, ignore_click: $item => { return Boolean($item.parent().find("input").eq(-1).prop("checked")); }, finished: () => { $(".submitbtns .btn-primary").click(); }, fill: (type, answer, $option) => { if (type === 4) { console.log(type, answer, $option); console.log($option.attr("id")); $option.val(answer); } } }); WorkerJSPlus({ name: "保定继续教育", match: location.pathname.includes("/exam/answer.html"), root: ".stem-container", elements: { question: ".stem span", options: ".option div .optStem", $options: ".option div input" }, intv: () => { return $("#question").length; }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().parent().find(".description").text()); } }); WorkerJSPlus({ name: "noNiExam.js", match: location.pathname === "/app-afstudy/self_test.html", root: ".lineClass .b-papp-root", elements: { question: ".b-exam-top .b-exam-tit", options: ".b-exam-box li label", $options: ".b-exam-box li input", type: ".b-exam-top .b-exam-type" }, ignore_click($item) { return $item.prop("checked"); }, wrap(obj) { obj.options = obj.options.map(i => { return i.replace(/[A-Za-z][\:]/, "").replace(/[A-Za-z][\:,\:]/, "").replace(/\;/, "").trim(); }); } }); WorkerJSPlus({ name: "www_pbaqks_com_text", match: location.host === "www.pbaqks.com" && location.pathname.includes("/P_ExamDetail/OnlineStuday"), root: ".main-container .single-box", elements: { question: ".single-main:first", options: ".choose-box label", $options: ".choose-box label", type: ".single-container .font-title", answer: "input:eq(1)" }, ignore_click: $i => { return $i.find("input").is(":checked"); }, wrap: obj => { obj.question = obj.question.replace("标准答案", "").replace(/^\d+\./, "").replace(/\[.+?\]/g, "").trim(); }, fillFinish: () => { if ($(".main-container .single-box").find("input:eq(1)").eq(GLOBAL.index - 1).attr("value").split("").length > 1) { jQuery(".main-container .confirm a:last-child").click(); } } }); WorkerJSPlus({ name: "安徽继续教育", match: location.pathname.includes("/study/html/content/studying/") || (location.pathname === "/study/html/content/tkOnline/" || location.pathname === "/study/html/content/sxsk/" || location.pathname === "/study/html/content/bkExam/"), intv: () => { return ($(".e-save-b").length || $(".e-b-g").length) && $(".totalscore").length === 0; }, root: ".e-q", elements: { question: ".e-q-q .ErichText", options: ".e-a-g li", $options: ".e-a-g li" }, ignore_click: $item => { return $item.attr("class").includes("checked"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().prev().find(".e-text").text()); obj.options = obj.options.map(i => { return formatString(i.replaceAll(/^[ab]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); } }); WorkerJSPlus({ name: "大连/九江", match: location.href.includes("/onlineclass/exam/"), intv: () => { return $(".excer_list_view___2Ahg9") || $(".excer_list_view___YOSCa"); }, root: ".single_excer_item___lFMCm,.single_excer_item___2lGB8", elements: { plat: 40, question: ".title_content___1Qagx .title_content_text___27NIL, .title_content___24J6D .title_content_text___8ruL4", options: ".options_content___nXSwG label .option_text___udjiE, .options_content___2YgyG label .option_text___1mfcu", $options: ".options_content___nXSwG label input,.options_content___2YgyG label input", type: ".title_content___1Qagx span:eq(1),.title_content___24J6D span:eq(1)" }, ignore_click: $item => { return $($item).parent().hasClass("ant-checkbox-checked"); }, wrap: obj => { console.log(obj); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { $option.val(answer); } } }); WorkerJSPlus({ name: "新疆继续教育", hook: () => { function parseXinJiangAgain(questions) { return questions.map(item => { const answer = []; const options = item.answers.map(opt => { if (opt.isAnswer === "0") answer.push(formatString(opt.name)); return formatString(opt.name); }); const type = item.types === "2" ? 3 : parseInt(item.types); return { question: item.name, options: options, answer: answer, type: type }; }); } JSONParseHook(o => { if (o.success && o.data.exam) { const arr = o.data.exam.assessList.map(i => { return i.questionList; }).flat(); GLOBAL.json = parseXinJiangAgain(arr); } }); }, match: location.host === "www.ttcdw.cn" && location.pathname.includes("/p/uExam/goExam/"), root: ".question-item", elements: { question: ".question-item-title span", options: ".question-item-option label .el-checkbox__label,.el-radio__label", $options: ".question-item-option label" }, wrap: obj => { Object.assign(obj, GLOBAL.json[GLOBAL.index - 1]); }, intv: () => { return !$("div").hasClass("entrying-wrap"); }, ignore_click: $item => { return $item.hasClass("is-checked"); }, fill: (type, answer, $option) => { if (type === 4 || type === 2) { $option.val(answer); } } }); WorkerJSPlus({ name: "华侨继续教育", match: location.pathname.includes("/exam/student/exam/resource/paper_card2"), intv: () => { return $(".ui-question-answer-right").length === 0; }, root: ".ui-question-group .ui-question", elements: { question: ".ui-question-title div", options: ".ui-question-options div", $options: ".ui-question-options .ui-question-options-order,.ke-container" }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find("h2").text()); }, ignore_click: $item => { return $item.parent().hasClass("ui-option-selected"); }, fill: (type, answer) => { if (type === 4 || type === 2 || type === 6) { const x = GLOBAL.index - $(".ui-question-options ").length - 1; KindEditor.instances[x].html(answer); } } }); WorkerJSPlus({ name: "上海开放大学", match: location.pathname.includes("/study/assignment/preview.aspx") || location.pathname.includes("/study/assignment/continuation.aspx"), hook: () => { if (GLOBAL.finish || $("a:contains(已完成批阅)").length === 1) { iframeMsg("tip", { type: "hidden", tip: "本页面已做完,无需自动答题" }); return true; } }, root: ".e-q", elements: { question: ".e-q-q .ErichText", options: ".e-a-g li", $options: ".e-a-g li" }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().parent().parent().find(".e-text").eq(0).text()); obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); }, ignore_click: $item => { return $item.attr("class").includes("checked"); } }); WorkerJSPlus({ name: "浙江考试", match: location.pathname === "/web-qz/moni/exam/exam_toExam.action", root: ".dt_tmcon", elements: { question: "div:eq(0) span:eq(1)", options: "div:eq(1) p", $options: "div:eq(1) p input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parents().find(".dt_rtitle1").eq(0).text()); obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); if (obj.type === 0) { obj.answer = [ JSON.parse($("#quesSSForm #userAnssStr_0").val()).rightAnswer ]; uploadAnswer([ obj ]); } }, finished: () => { return $(".page li input:eq(2)").attr("disabled") !== "disabled"; }, fillFinish: () => { $(".page li input:eq(2)").click(); } }); WorkerJSPlus({ name: "在浙学考试", match: location.host === "www.zjooc.cn" && (location.pathname.includes("/homework/") || location.pathname.includes("/test/") || location.pathname.includes("/exam/")), hook: () => { function parseZaiZheXue(problems) { return problems.map(item => { if (!item.rightAnswer) return undefined; const subjectType = item.subjectType; let type = -1; const question = formatString(item.subjectName); const answer = []; const options = []; if (subjectType === 1 || subjectType === 2) { type = subjectType - 1; for (let subjectOption of item.subjectOptions) { const opt = formatString(subjectOption.optionContent); options.push(opt); if (item.rightAnswer.includes(subjectOption.optionHead)) { answer.push(opt); } } } else if (subjectType === 3) { type = 3; answer.push(item.rightAnswer === "yes" ? "正确" : "错误"); } else { return undefined; } return { question: question, options: options, type: type, answer: answer }; }).filter(i => i && i.answer.length > 0); } if (!(location.pathname.includes("/homework/do") || location.pathname.includes("/test/do") || location.pathname.includes("/exam/do"))) { JSONParseHook(o => { if (o.data && o.data.paperName && o.data.clazzIds && o.data.paperSubjectList) { const data = parseZaiZheXue(o.data.paperSubjectList); console.log(data); } }); return true; } }, root: ".questiono-item", elements: { question: "h6 .processing_img", options: ".questiono-main label .el-radio__label,.el-checkbox__label", $options: ".questiono-main label" }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().prev().text()); obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); }, ignore_click: $item => { return $item.hasClass("is-checked"); } }); WorkerJSPlus({ name: "在浙学(测验/考试)", match: location.host === "www.zjooc.cn" && location.pathname.includes("/singleQuestion/do/"), intv: () => { return $(".settingsel-dialog").css("display") === "none"; }, root: ".question_content:first", elements: { question: ".question_title", options: ".question_content .radio_content div", $options: ".question_content label" }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find(".question_title p").eq(0).text()); obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").replace(".", "").trim()); }); }, ignore_click: $item => { return $item.hasClass("is-checked"); }, finished: () => { if ($(".question_btn .el-button:contains(下一题)").hasClass("is-disabled")) return false; $(".el-button:contains(下一题)").click(); return true; } }); WorkerJSPlus({ name: "福建继续教育测验|作业", match: location.pathname === "/Web_Study/Student/Center/MyWorkOnView" || location.pathname === "/Web_Study/Student/Center/MyExamOnView", intv: () => { return $(".samllTopicNav").length; }, root: ".topic-cont", elements: { question: "p", options: ".options li span", $options: ".options li" }, wrap: obj => { obj.options = obj.options.map(i => { return i.replace(/选项[A-Za-z]/, "").trim(); }); obj.type = { 1: 0, 2: 1, 3: 3, 6: 4 }[obj.$item.attr("itemtype")]; if (obj.type === undefined) obj.type = 4; }, ignore_click: $item => { return $item.hasClass("correct"); }, fill: (type, answer, $option) => {} }); WorkerJSPlus({ name: "湖南继续教育", match: () => { const pathMatch = location.pathname.includes("/User/Student/myhomework.aspx") || location.pathname.includes("/examing.aspx"); const matchHostArr = [ "www.jwstudy.cn", "hdjt.wuxuekeji.com", "csjs.ynlhxy.com" ]; return pathMatch && (matchHostArr.includes(location.host) || location.host.includes("ls365.net") || location.host.includes("ls365.com")); }, root: ".exam_question", elements: { question: ".exam_question_title div", options: ".question_select .select_detail", $options: ".question_select li", type: ".exam_question_title div strong" }, ignore_click: $item => { return $item.hasClass("cur"); } }); WorkerJSPlus({ name: "德阳继续教育", match: location.href.includes("/dypx/OnlineExam/Exam.aspx"), root: "#divProblemArea", elements: { question: "#ulProblems li:first", options: "#ulProblems .answer", $options: "#ulProblems .answer input" }, ignore_click: $item => { return $item.prop("checked"); }, wrap: obj => { if ($("#ulProblems .answer input").length < 3 && $("#ulProblems .answer input").eq(0).attr("type") === "radio") { obj.type = 3; obj.options = [ "正确", "错误" ]; } else if ($("#ulProblems .answer input").length > 2 && $("#ulProblems .answer input").eq(0).attr("type") === "radio") { obj.type = 0; } else if ($("#ulProblems .answer input").length > 2 && $("#ulProblems .answer input").eq(0).attr("type") === "checkbox") { obj.type = 1; } }, finished: () => { if ($(".dlg").length) return false; $("#divBtns input:eq(1)").click(); return true; } }); WorkerJSPlus({ name: "淄博继续教育", match: location.pathname.includes("/practice/start"), root: ".header-left .trueorfalse .sub", elements: { question: ".mb10", options: ".options li", $options: ".options li" }, ignore_click: $item => { return $item.hasClass("active"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().prev().text()); obj.options = obj.options.map(i => { return formatString(i.replaceAll(/[a-zA-z]\)\s+/g, "").replaceAll(/^[a-z]\s+/g, "").replaceAll(/^[a-z]、\s+/g, "").trim()); }); } }); WorkerJSPlus({ name: "河北继续教育", match: location.pathname.includes("paperid"), root: ".examItem", elements: { question: ".examItemRight .question", options: ".examItemRight ul li span", $options: ".examItemRight ul li" }, ignore_click: $item => { return $item.hasClass("cur"); }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find(".questTitle b").text()); } }); WorkerJSPlus({ name: "保定继续教育", match: () => { const pathnameArr = [ "/cuggw/rs/olex_exam", "/hebic/rs/olex_exam", "/sjzkjxy/rs/olex_exam", "/hbfsh/rs/olex_exam", "/jxycu/rs/olex_exam", "/jlufe/rs/olex_exam", "/hbun/rs/olex_exam" ]; return pathnameArr.includes(location.pathname); }, intv: () => { return $(".paper_body").length; }, root: ".item_li", elements: { question: ".item_title", options: "ul li label", $options: "ul li input" }, ignore_click($item) { return $item.prop("checked"); }, wrap: obj => { if (obj.$options.length === 2) { obj.type = 3; } else if (obj.$options.length > 2 && obj.$options.eq(0).attr("type") === "radio") { obj.type = 0; } else if (obj.$options.length > 2 && obj.$options.eq(0).attr("type") !== "radio") { obj.type = 1; } else { obj.type = 4; } } }); WorkerJSPlus({ name: "唐山继续教育", match: location.pathname.includes("/exam/student/exam/"), intv: () => { return $(".ui-question-group").length; }, root: ".ui-question-group .ui-question", elements: { question: ".ui-question-title .ui-question-content-wrapper", options: ".ui-question-options .ui-question-content-wrapper", $options: ".ui-question-options .ui-question-options-order" }, wrap: obj => { obj.type = getQuestionType(obj.$item.parent().find("h2").text()); } }); WorkerJSPlus({ name: "zzcjxy.hnzkw.org.cn", match: location.host.includes("hnzkw.org.cn"), intv: () => { return $(".answer").length; }, hook: () => { JSONParseHook(o => { if (o.data && o.data.bookdatas) { GLOBAL.json = parsehnzkwText(o.data.bookdatas); } }); }, root: ".examList", elements: { question: ".text", options: ".el-radio-group label,.el-checkbox-group label", $options: ".el-radio-group input,.el-checkbox-group input", type: ".status" }, wrap: obj => { Object.assign(obj, GLOBAL.json[GLOBAL.index - 1]); }, fill: (type, answer, $option) => {} }); WorkerJSPlus({ name: "问卷星考试", match: location.pathname.includes("/exam/ExamRd/Answer"), root: ".g-mn", elements: { question: ".m-question .tigan", options: ".question-block .xuanxiang", $options: ".question-block .xuanxiang", type: ".tixing" }, ignore_click: ($item, type) => { if (type === 1) { return $item.parent().find(".icheckbox_square-green").hasClass("checked"); } else { const isIgnore = $item.parent().find(".iradio_square-green").hasClass("checked"); return isIgnore; } }, wrap: obj => { if ($(".layui-layer-content").length) { iframeMsg("tip", { type: "stop", tip: "答题暂停,请自行通过验证" }); GLOBAL.stop = true; return true; } }, fillFinish: data => { if (data.style === "warning-row" || $(".g-mn").parent().find(".iradio_square-green").hasClass("checked") || data.type === 1) { $('.u-btn-next:contains("下一题")').click(); } }, finished: () => { return parseInt($(".num-dangqian:last").attr("qindex")) !== $(".num-item").length; } }); })();