// ==UserScript== // @name AI课考帮 // @namespace npm/vite-plugin-monkey // @version 1.0.13 // @description // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAIAAABl4DQWAAAAAXNSR0IB2cksfwAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+kLGAEeMgK2quMAAAgpSURBVEjHRVZbjFbVGV3fPue/zX2GGRiY4WJBFEQCji2ixdYLeKmtVlpMRWKitiZtYzXpxaQxNtH0oQ99aZs+NLRNk5q+mAhGqzRVSxQRZdCOIIpFnNG5OMzA3P6Z/+zv+1Yfzi/unIdzcrLX3t/a+1trybZb73I6AUDEefuOrVdtvqRn6eJSIYEAJOgAAQdJOEjASRIkYXAA8/PZ4Kfjrx4+8fzL/SSFAoAOuebWXSSFuH7Lhgd237ZscetkjGfm5qYoCzFCKCRAgPmAGwEiR6cDpSRpS3xFpdCUpmcGx/+49/mj75whIRC5+ubvivO+Xdvvvv3acdW/jZ79y9wcRAiI1DEBEQGAQGg0SF4pSEIEgAAgH2gu3dFZaYDs/es/9z9/DGCy8kvrv/H1zQ/evX3g/PQ9gyOvZxkBuBMgHTk4CVJIuruZCEgnKQDd6x/u/TV95fz8lqbS1k2rP3j/o9Gx6QDB/Xfd8Em1umdw9GwWrRY9Ro/qWfSaWqaeRYtqUTWqZkp3UzU1VzNVV8vfae5qQ9F+fmZyyrnn3h1OS++/c1tHS+XJ9wbnzQAyPz/k5RLkzuaObZ1LuisVIc9l2ZsT43snPwN4ZalyaaWJAgDDtYWXqzP5pE8cTw9P71m++KtXXywnDu9HZ9uOUyN0R51JAQGRPa2LHli7bnkxIpuCJCh3otAM8OOp848NHL19Se/O1RcTAPjmex/cdfq4lIsiAojF+I9Luz/sP572LG4+MDlrUZEPEgAgv1m1emdnlo79GTqXHyNIVtZgyQ0rmjqeXLvhzbEx0uuTYqy+/t/GazYzERIe9cPzc909S9KGUvL+uVl+gQ4Aj/Us35UcD2PvkQIBGjewvS9UFgPCOCUeV3a0LczMJXQBAAo9jp+vnRoqrum1GEGOzNZWtJRSaK2aZYwGEISIbKk07PbToTqQ3zbvuH4iWXvopaNvDxzv6ur68ubLr9i4IUmwZvlS0L6o2DyOTaBSDB2tAGqUYqmcitYQI7OYYxF4aFmpcepFLGqEk+XV/cMNN35/d80cgKQp3R/ddcsvHvpBqVjMexcETGnmUePIRDEtoFywTFU9BRVReaFHiM2zp6UAaAQxvNBz7f0/IyVZ3Jm0t0qSQPDb/hMr979w75235bQBAJ2qMId5HJ8sdLWbmZkHqCJGRmWmqMVdzU0NQ4dIpylcnz04AEihd2natSiUilJIUSyExoaHXzw4OzcbzCR/3MUc7jCHmp2bYTRTC7AINURlVEZdnc2GhQWa5cX+661ToaUpNDVICEgSKaT5AlIsDI6MCF1gASY0qiEa1KDuWeTcgkZPoRlj9FqW894VAHUsZCgUReTkqVPS1g0RJiGkiTQ3JO2tUimLoOZGj5KrhBvUYEYzqEkSPJrWLECzfEFRg/np4WFEylQmqohxz5a2UCggBEmCtDYl3V1SLoFO57KOVlDpSje40TyHpirVTN2jB5pCc3IMWTxUC1BytMqo1LhjXTnXQ0mT0N5KM5jB/J7F7d1NFXEVmrjBLSedZjCHqpMWLUjMoMoYGdWjHYkypK0y5xiuQq1vVenXm4KAUimDFCWjXpokj2xcLR5hCjPWoevUC1koFLgQPVqARqgjmmeRURHtBVsCFfwvk88ymv5wK567ueU7vW2IcXkiT6zrfXplcXlTGWZwh6v456fqHpIgzmx6jjVlZApVZEo1EAIyyC/ZcP18eXWYw7s16UrQE69Z9OnV3TN/bFgTpjL278OV35b2VlCZC4Wgzoy7VmuBkEJKNWaWMkbEDNFDkrg7owN4cL77qba57plRDBkGXajkZ4mPi8Bu+layaRNNp2arLY3lXPPy68uoUjCoQZDf71SiCiDumsW8VwkcK1V2D83+ftvXLslmePztYI6mFl+3Qfr6ks5F9Pj6wIcF2JWXra03qxvcaY6ongQBqc7oKWLk/ILN11Usd2QARxtb+vYeeHzH5ju+d99FPd2FNASSwODw2HMH33r4D8+8+rtH4JZbQSKyZdmSaql0YiGDmlAkGqOnyGKSZYwkvpBxgVCQrl39q32HH//7v+G++9qNXe0t+w/2n56sApAkAQ2WQYJPT/cNDbx0Xc8bI9PbB6pIU8Iki1l1Pl2Yz9Y0Bo5ldduTzzcPSKGQXLTchkYRs6feOAlzACgVpVhEsQgzmnLyHP5zQDQDEM4v2OhE2tsLolmShdn5dGR89rKmEs3qrlTPEHUPDK2tmJv36RmUK/nvcCFvAPx4UA69IrlSisCBmapPz4SW5u5SZXLyXPrO0OwtlxSuCn44I0kRYd386hWEzk5mStWAC/YlInjntWPZ7LgIIJIvdvxcDSSnZ7Z2dHQWy0c/PpP+6djkTSubnrgovfH4Qp5cBMQFmkQAho52nzhXD36SJ6nwkyNDNjwC1c9zlUAglbI4b17SOzMzu++NI0mla1UlZt9c0bAmxmenGZwgxR3uQoqT7hCRJEAdQSDCECQEJkEqFTilWJBSSUpFKZakWHj0iq+saGl79shrH02cTbqWrjo0Nt8rceeq1u2V5Mz57KNozjxfMY9jAJGmcAeAECQEBBERKRbywIeQSJr2tbb9+PK+Ve2dh04df+ZYf7FQkPVXXOeuMYs/vbjx7vU9CdKTM35yOo5acj5TgzjFIQ4xwGqREhwwBBc46ZCKszlJlzW3dbe0VTU7cOLYcyfelRAqlQZZv/k60qPGmC0s9+qPNq64rHPRokpTKaTGRBmUISIoQ2SIFEWIEKUoghIGMUjV9OzczAfjI/vefXtifj6EUC5XQpr+HyMvwHz/Q1YUAAAAAElFTkSuQmCC // @match *://*.chaoxing.com/* // @match *://*.hejtxy.edu.cn/* // @match *://*.zhihuishu.com/* // @match *://*.chaoxing.com/* // @match *://*.edu.cn/* // @match *://*.org.cn/* // @match *://*.xueyinonline.com/* // @match *://*.hnsyu.net/* // @match *://*.qutjxjy.cn/* // @match *://*.ynny.cn/* // @match *://*.hnvist.cn/* // @match *://*.fjlecb.cn/* // @match *://*.gdhkmooc.com/* // @match *://*.cugbonline.cn/* // @match *://*.zjelib.cn/* // @match *://*.cqrspx.cn/* // @match *://*.neauce.com/* // @match *://*.zhihui-yun.com/* // @match *://*.cqie.cn/* // @match *://*.ccqmxx.com/* // @match *://*.icve.com.cn/* // @match *://*.course.icve.com.cn/* // @match *://*.courshare.cn/* // @match *://*.webtrn.cn/* // @match *://*.zjy2.icve.com.cn/* // @match *://*.zyk.icve.com.cn/* // @match *://*.icourse163.org/* // @require https://cdn.jsdelivr.net/npm/vue@3.5.16/dist/vue.global.prod.js // @grant GM_addStyle // @grant GM_addValueChangeListener // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant unsafeWindow // ==/UserScript== (function (vue) { 'use strict'; var __typeError = (msg) => { throw TypeError(msg); }; var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value); var _schema, _config, _scripts; var _GM_addValueChangeListener = (() => typeof GM_addValueChangeListener != "undefined" ? GM_addValueChangeListener : void 0)(); var _GM_getValue = (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)(); var _GM_setValue = (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)(); var _GM_xmlhttpRequest = (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)(); var _unsafeWindow = (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)(); const _sfc_main$1 = { __name: "Form", setup(__props, { expose: __expose }) { const container = vue.ref(null); function createRow(label, right) { let span = document.createElement("span"); span.innerText = label; container.value.appendChild(span); container.value.appendChild(right); span.className += "left"; right.className += "right"; } vue.ref([]); function setData(config) { container.value.innerHTML = ""; const data = []; config.iterate((name, schema) => { data.push({ name, schema }); }); data.forEach(({ name, schema }) => { let input; if ("range" in schema) { input = document.createElement("input"); input.type = "range"; input.min = schema.range[0]; input.max = schema.range[1]; input.step = schema.range[2]; input.addEventListener("change", (e) => config.set(name, e.target.value)); input.value = _GM_getValue(name); createRow(schema.name || name, input); } else if ("fill" in schema) { input = document.createElement("input"); input.type = "text"; input.addEventListener("keyup", (e) => config.set(name, e.target.value)); input.value = _GM_getValue(name); createRow(schema.name || name, input); } else if ("select" in schema) { input = document.createElement("select"); createRow(schema.name || name, input); schema.select.forEach(([value, title]) => { const option = new Option(title, value); if (_GM_getValue(name) == value) { option.selected = true; } input.appendChild(option); }); input.addEventListener("change", (e) => config.set(name, e.target.value)); } else if ("check" in schema) { input = document.createElement("input"); input.type = "checkbox"; input.value = schema.check; if (_GM_getValue(name) == input.value) { input.checked = true; } createRow(schema.name || name, input); input.addEventListener("change", (e) => config.set(name, e.target.checked)); } else if ("radio" in schema) { input = document.createElement("input"); input.type = "radio"; createRow(schema.name || name, input); input.addEventListener("change", (e) => config.set(name, e.target.checked)); } }); } vue.onMounted(() => { document.createElement("input"); }); __expose({ setData }); return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("div", { class: "form-container", ref_key: "container", ref: container }, null, 512); }; } }; const _sfc_main = { __name: "AppWin", props: { msg: String }, setup(__props, { expose: __expose }) { vue.ref(0); vue.ref("Vue"); vue.ref("auto"); let isMinimized = vue.ref(false); const header = vue.ref(null); const floatWindow = vue.ref(null); const form = vue.ref(null); let isDragging = false; let offsetX = 0; let offsetY = 0; function handleToggleMinimized() { isMinimized.value = !isMinimized.value; } function bindConfig(config) { config.addEventListener("change", (e) => console.log(e)); form.value.setData(config); } __expose({ bindConfig }); vue.onMounted(() => { let elHeader = header.value; let elWindow = floatWindow.value; if (elHeader) { elHeader.addEventListener("mousedown", function(e) { isDragging = true; const rect = elWindow.getBoundingClientRect(); offsetX = e.clientX - rect.left; offsetY = e.clientY - rect.top; elWindow.style.zIndex = "999999"; e.preventDefault(); }); document.addEventListener("mousemove", function(e) { if (isDragging) { elWindow.style.left = `${e.clientX - offsetX}px`; elWindow.style.top = `${e.clientY - offsetY}px`; } }); document.addEventListener("mouseup", function() { isDragging = false; elWindow.style.zIndex = "99999"; }); const links = elHeader.querySelectorAll(".tm-float-header-link"); links.forEach((link) => { const menu = link.querySelector(".dropdown-menu"); link.addEventListener("mouseenter", function() { const rect = this.getBoundingClientRect(); menu.style.display = "block"; menu.style.top = `${rect.height}px`; menu.style.left = "0"; menu.style.width = `${rect.width}px`; }); link.addEventListener("mouseleave", function() { menu.style.display = "none"; }); menu.addEventListener("mousedown", function(event2) { menu.style.display = "none"; event2.stopPropagation(); }); }); } }); return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("div", { id: "tm-float-window", style: vue.normalizeStyle({ height: vue.unref(isMinimized) ? header.value.offsetHeight : "auto" }), ref_key: "floatWindow", ref: floatWindow }, [ vue.createElementVNode("div", { id: "tm-float-header", ref_key: "header", ref: header }, [ _cache[0] || (_cache[0] = vue.createElementVNode("div", { class: "header-main" }, " AI考学帮 ", -1)), vue.createElementVNode("span", { id: "minimize-btn", title: "缩小/展开窗口", onClick: handleToggleMinimized }, vue.toDisplayString(vue.unref(isMinimized) ? "+" : "-"), 1) ], 512), vue.createElementVNode("div", { id: "tm-float-content", style: vue.normalizeStyle({ display: vue.unref(isMinimized) ? "none" : "block" }) }, [ vue.createVNode(_sfc_main$1, { ref_key: "form", ref: form }, null, 512) ], 4) ], 4); }; } }; class Config extends EventTarget { constructor() { super(); __privateAdd(this, _schema, {}); } set(key, value, schema) { if (schema == null) { _GM_setValue(key, value); } else { __privateGet(this, _schema)[key] = schema; if (_GM_getValue(key) == null) { _GM_setValue(key, value); } } } get(key, defaultValue) { return _GM_getValue(key) || defaultValue; } getSchema() { return __privateGet(this, _schema); } iterate(fn) { Object.entries(__privateGet(this, _schema)).forEach(([name, schema]) => fn(name, schema)); } listValues() { const ret = {}; Object.entries(__privateGet(this, _schema)).forEach(([name, schema]) => { ret[name] = _GM_getValue(name); }); return ret; } } _schema = new WeakMap(); function getDefaultExportFromCjs(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; } var typr_js$1; var hasRequiredTypr_js; function requireTypr_js() { if (hasRequiredTypr_js) return typr_js$1; hasRequiredTypr_js = 1; var Typr2 = {}; Typr2.parse = function(buff) { var bin = Typr2._bin; var data = new Uint8Array(buff); var offset = 0; bin.readFixed(data, offset); offset += 4; var numTables = bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; var tags = ["cmap", "head", "hhea", "maxp", "hmtx", "name", "OS/2", "post", "loca", "glyf", "kern", "CFF ", "GPOS", "GSUB", "SVG "]; var obj = { _data: data }; var tabs = {}; for (var i = 0; i < numTables; i++) { var tag = bin.readASCII(data, offset, 4); offset += 4; bin.readUint(data, offset); offset += 4; var toffset = bin.readUint(data, offset); offset += 4; var length = bin.readUint(data, offset); offset += 4; tabs[tag] = { offset: toffset, length }; } for (var i = 0; i < tags.length; i++) { var t = tags[i]; if (tabs[t]) obj[t.trim()] = Typr2[t.trim()].parse(data, tabs[t].offset, tabs[t].length, obj); } return obj; }; Typr2._tabOffset = function(data, tab) { var bin = Typr2._bin; var numTables = bin.readUshort(data, 4); var offset = 12; for (var i = 0; i < numTables; i++) { var tag = bin.readASCII(data, offset, 4); offset += 4; bin.readUint(data, offset); offset += 4; var toffset = bin.readUint(data, offset); offset += 4; bin.readUint(data, offset); offset += 4; if (tag == tab) return toffset; } return 0; }; Typr2._bin = { 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 = Typr2._bin.readShort(data, o); return num / 16384; }, readInt: function(buff, p) { var a = Typr2._bin.t.uint8; a[0] = buff[p + 3]; a[1] = buff[p + 2]; a[2] = buff[p + 1]; a[3] = buff[p]; return Typr2._bin.t.int32[0]; }, readInt8: function(buff, p) { var a = Typr2._bin.t.uint8; a[0] = buff[p]; return Typr2._bin.t.int8[0]; }, readShort: function(buff, p) { var a = Typr2._bin.t.uint8; a[1] = buff[p]; a[0] = buff[p + 1]; return Typr2._bin.t.int16[0]; }, readUshort: function(buff, p) { return buff[p] << 8 | buff[p + 1]; }, readUshorts: function(buff, p, len) { var arr = []; for (var i = 0; i < len; i++) arr.push(Typr2._bin.readUshort(buff, p + i * 2)); return arr; }, readUint: function(buff, p) { var a = Typr2._bin.t.uint8; a[3] = buff[p]; a[2] = buff[p + 1]; a[1] = buff[p + 2]; a[0] = buff[p + 3]; return Typr2._bin.t.uint32[0]; }, readUint64: function(buff, p) { return Typr2._bin.readUint(buff, p) * (4294967295 + 1) + Typr2._bin.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; }, 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 = Typr2._bin._tdec; if (tdec && p == 0 && l == buff.length) return tdec["decode"](buff); return Typr2._bin.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; } }; Typr2._bin.t = { buff: new ArrayBuffer(8) }; Typr2._bin.t.int8 = new Int8Array(Typr2._bin.t.buff); Typr2._bin.t.uint8 = new Uint8Array(Typr2._bin.t.buff); Typr2._bin.t.int16 = new Int16Array(Typr2._bin.t.buff); Typr2._bin.t.uint16 = new Uint16Array(Typr2._bin.t.buff); Typr2._bin.t.int32 = new Int32Array(Typr2._bin.t.buff); Typr2._bin.t.uint32 = new Uint32Array(Typr2._bin.t.buff); Typr2._lctf = {}; Typr2._lctf.parse = function(data, offset, length, font, subt) { var bin = Typr2._bin; var obj = {}; var offset0 = offset; bin.readFixed(data, offset); offset += 4; var offScriptList = bin.readUshort(data, offset); offset += 2; var offFeatureList = bin.readUshort(data, offset); offset += 2; var offLookupList = bin.readUshort(data, offset); offset += 2; obj.scriptList = Typr2._lctf.readScriptList(data, offset0 + offScriptList); obj.featureList = Typr2._lctf.readFeatureList(data, offset0 + offFeatureList); obj.lookupList = Typr2._lctf.readLookupList(data, offset0 + offLookupList, subt); return obj; }; Typr2._lctf.readLookupList = function(data, offset, subt) { var bin = Typr2._bin; var offset0 = offset; var obj = []; var count = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < count; i++) { var noff = bin.readUshort(data, offset); offset += 2; var lut = Typr2._lctf.readLookupTable(data, offset0 + noff, subt); obj.push(lut); } return obj; }; Typr2._lctf.readLookupTable = function(data, offset, subt) { var bin = Typr2._bin; var offset0 = offset; var obj = { tabs: [] }; obj.ltype = bin.readUshort(data, offset); offset += 2; obj.flag = bin.readUshort(data, offset); offset += 2; var cnt = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < cnt; i++) { var noff = bin.readUshort(data, offset); offset += 2; var tab = subt(data, obj.ltype, offset0 + noff); obj.tabs.push(tab); } return obj; }; Typr2._lctf.numOfOnes = function(n) { var num = 0; for (var i = 0; i < 32; i++) if ((n >>> i & 1) != 0) num++; return num; }; Typr2._lctf.readClassDef = function(data, offset) { var bin = Typr2._bin; var obj = []; var format = bin.readUshort(data, offset); offset += 2; if (format == 1) { var startGlyph = bin.readUshort(data, offset); offset += 2; var glyphCount = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < glyphCount; i++) { obj.push(startGlyph + i); obj.push(startGlyph + i); obj.push(bin.readUshort(data, offset)); offset += 2; } } if (format == 2) { var count = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < count; i++) { obj.push(bin.readUshort(data, offset)); offset += 2; obj.push(bin.readUshort(data, offset)); offset += 2; obj.push(bin.readUshort(data, offset)); offset += 2; } } return obj; }; Typr2._lctf.getInterval = function(tab, val) { for (var i = 0; i < tab.length; i += 3) { var start = tab[i], end = tab[i + 1]; tab[i + 2]; if (start <= val && val <= end) return i; } return -1; }; Typr2._lctf.readValueRecord = function(data, offset, valFmt) { var bin = Typr2._bin; var arr = []; arr.push(valFmt & 1 ? bin.readShort(data, offset) : 0); offset += valFmt & 1 ? 2 : 0; arr.push(valFmt & 2 ? bin.readShort(data, offset) : 0); offset += valFmt & 2 ? 2 : 0; arr.push(valFmt & 4 ? bin.readShort(data, offset) : 0); offset += valFmt & 4 ? 2 : 0; arr.push(valFmt & 8 ? bin.readShort(data, offset) : 0); offset += valFmt & 8 ? 2 : 0; return arr; }; Typr2._lctf.readCoverage = function(data, offset) { var bin = Typr2._bin; var cvg = {}; cvg.fmt = bin.readUshort(data, offset); offset += 2; var count = bin.readUshort(data, offset); offset += 2; if (cvg.fmt == 1) cvg.tab = bin.readUshorts(data, offset, count); if (cvg.fmt == 2) cvg.tab = bin.readUshorts(data, offset, count * 3); return cvg; }; Typr2._lctf.coverageIndex = function(cvg, val) { var tab = cvg.tab; if (cvg.fmt == 1) return tab.indexOf(val); if (cvg.fmt == 2) { var ind = Typr2._lctf.getInterval(tab, val); if (ind != -1) return tab[ind + 2] + (val - tab[ind]); } return -1; }; Typr2._lctf.readFeatureList = function(data, offset) { var bin = Typr2._bin; var offset0 = offset; var obj = []; var count = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < count; i++) { var tag = bin.readASCII(data, offset, 4); offset += 4; var noff = bin.readUshort(data, offset); offset += 2; obj.push({ tag: tag.trim(), tab: Typr2._lctf.readFeatureTable(data, offset0 + noff) }); } return obj; }; Typr2._lctf.readFeatureTable = function(data, offset) { var bin = Typr2._bin; bin.readUshort(data, offset); offset += 2; var lookupCount = bin.readUshort(data, offset); offset += 2; var indices = []; for (var i = 0; i < lookupCount; i++) indices.push(bin.readUshort(data, offset + 2 * i)); return indices; }; Typr2._lctf.readScriptList = function(data, offset) { var bin = Typr2._bin; var offset0 = offset; var obj = {}; var count = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < count; i++) { var tag = bin.readASCII(data, offset, 4); offset += 4; var noff = bin.readUshort(data, offset); offset += 2; obj[tag.trim()] = Typr2._lctf.readScriptTable(data, offset0 + noff); } return obj; }; Typr2._lctf.readScriptTable = function(data, offset) { var bin = Typr2._bin; var offset0 = offset; var obj = {}; var defLangSysOff = bin.readUshort(data, offset); offset += 2; obj.default = Typr2._lctf.readLangSysTable(data, offset0 + defLangSysOff); var langSysCount = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < langSysCount; i++) { var tag = bin.readASCII(data, offset, 4); offset += 4; var langSysOff = bin.readUshort(data, offset); offset += 2; obj[tag.trim()] = Typr2._lctf.readLangSysTable(data, offset0 + langSysOff); } return obj; }; Typr2._lctf.readLangSysTable = function(data, offset) { var bin = Typr2._bin; var obj = {}; bin.readUshort(data, offset); offset += 2; obj.reqFeature = bin.readUshort(data, offset); offset += 2; var featureCount = bin.readUshort(data, offset); offset += 2; obj.features = bin.readUshorts(data, offset, featureCount); return obj; }; Typr2.CFF = {}; Typr2.CFF.parse = function(data, offset, length) { var bin = Typr2._bin; data = new Uint8Array(data.buffer, offset, length); offset = 0; data[offset]; offset++; data[offset]; offset++; data[offset]; offset++; data[offset]; offset++; var ninds = []; offset = Typr2.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 = Typr2.CFF.readIndex(data, offset, tdinds); var topDicts = []; for (var i = 0; i < tdinds.length - 1; i++) topDicts.push(Typr2.CFF.readDict(data, offset + tdinds[i], offset + tdinds[i + 1])); offset += tdinds[tdinds.length - 1]; var topdict = topDicts[0]; var sinds = []; offset = Typr2.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]; Typr2.CFF.readSubrs(data, offset, topdict); if (topdict.CharStrings) { offset = topdict.CharStrings; var sinds = []; offset = Typr2.CFF.readIndex(data, offset, sinds); var cstr = []; for (var i = 0; i < sinds.length - 1; i++) cstr.push(bin.readBytes(data, offset + sinds[i], sinds[i + 1] - sinds[i])); topdict.CharStrings = cstr; } if (topdict.Encoding) topdict.Encoding = Typr2.CFF.readEncoding(data, topdict.Encoding, topdict.CharStrings.length); if (topdict.charset) topdict.charset = Typr2.CFF.readCharset(data, topdict.charset, topdict.CharStrings.length); if (topdict.Private) { offset = topdict.Private[1]; topdict.Private = Typr2.CFF.readDict(data, offset, offset + topdict.Private[0]); if (topdict.Private.Subrs) Typr2.CFF.readSubrs(data, offset + topdict.Private.Subrs, topdict.Private); } var obj = {}; for (var p in topdict) { if (["FamilyName", "FullName", "Notice", "version", "Copyright"].indexOf(p) != -1) obj[p] = strings[topdict[p] - 426 + 35]; else obj[p] = topdict[p]; } return obj; }; Typr2.CFF.readSubrs = function(data, offset, obj) { var bin = Typr2._bin; var gsubinds = []; offset = Typr2.CFF.readIndex(data, offset, gsubinds); var bias, nSubrs = gsubinds.length; if (nSubrs < 1240) bias = 107; else if (nSubrs < 33900) bias = 1131; else bias = 32768; obj.Bias = bias; obj.Subrs = []; for (var i = 0; i < gsubinds.length - 1; i++) obj.Subrs.push(bin.readBytes(data, offset + gsubinds[i], gsubinds[i + 1] - gsubinds[i])); }; Typr2.CFF.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]; Typr2.CFF.glyphByUnicode = function(cff, code) { for (var i = 0; i < cff.charset.length; i++) if (cff.charset[i] == code) return i; return -1; }; Typr2.CFF.glyphBySE = function(cff, charcode) { if (charcode < 0 || charcode > 255) return -1; return Typr2.CFF.glyphByUnicode(cff, Typr2.CFF.tableSE[charcode]); }; Typr2.CFF.readEncoding = function(data, offset, num) { Typr2._bin; var array = [".notdef"]; var format = data[offset]; offset++; if (format == 0) { var nCodes = data[offset]; offset++; for (var i = 0; i < nCodes; i++) array.push(data[offset + i]); } else throw "error: unknown encoding format: " + format; return array; }; Typr2.CFF.readCharset = function(data, offset, num) { var bin = Typr2._bin; 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; }; Typr2.CFF.readIndex = function(data, offset, inds) { var bin = Typr2._bin; var count = bin.readUshort(data, offset); offset += 2; var offsize = data[offset]; offset++; if (offsize == 1) for (var i = 0; i < count + 1; i++) inds.push(data[offset + i]); else if (offsize == 2) for (var i = 0; i < count + 1; i++) inds.push(bin.readUshort(data, offset + i * 2)); else if (offsize == 3) for (var i = 0; i < count + 1; i++) inds.push(bin.readUint(data, offset + i * 3 - 1) & 16777215); else if (count != 0) throw "unsupported offset size: " + offsize + ", count: " + count; offset += (count + 1) * offsize; return offset - 1; }; Typr2.CFF.getCharString = function(data, offset, o) { var bin = Typr2._bin; 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; }; Typr2.CFF.readCharString = function(data, offset, length) { var end = offset + length; var bin = Typr2._bin; 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; }; Typr2.CFF.readDict = function(data, offset, end) { var bin = Typr2._bin; 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", 0, 0, "LanguageGroup", "ExpansionFactor", "initialRandomSeed", "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend", 0, 0, 0, 0, 0, 0, "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; }; Typr2.cmap = {}; Typr2.cmap.parse = function(data, offset, length) { data = new Uint8Array(data.buffer, offset, length); offset = 0; var bin = Typr2._bin; var obj = {}; bin.readUshort(data, offset); offset += 2; var numTables = bin.readUshort(data, offset); offset += 2; var offs = []; obj.tables = []; for (var i = 0; i < numTables; i++) { var platformID = bin.readUshort(data, offset); offset += 2; var encodingID = bin.readUshort(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 = bin.readUshort(data, noffset); if (format == 0) subt = Typr2.cmap.parse0(data, noffset); else if (format == 4) subt = Typr2.cmap.parse4(data, noffset); else if (format == 6) subt = Typr2.cmap.parse6(data, noffset); else if (format == 12) subt = Typr2.cmap.parse12(data, noffset); else console.log("unknown format: " + format, platformID, encodingID, noffset); obj.tables.push(subt); } if (obj[id] != null) throw "multiple tables for one platform+encoding"; obj[id] = tind; } return obj; }; Typr2.cmap.parse0 = function(data, offset) { var bin = Typr2._bin; var obj = {}; obj.format = bin.readUshort(data, offset); 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; }; Typr2.cmap.parse4 = function(data, offset) { var bin = Typr2._bin; var offset0 = offset; var obj = {}; obj.format = bin.readUshort(data, offset); offset += 2; var length = bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; var segCountX2 = bin.readUshort(data, offset); offset += 2; var segCount = segCountX2 / 2; obj.searchRange = bin.readUshort(data, offset); offset += 2; obj.entrySelector = bin.readUshort(data, offset); offset += 2; obj.rangeShift = bin.readUshort(data, offset); offset += 2; obj.endCount = bin.readUshorts(data, offset, segCount); offset += segCount * 2; offset += 2; obj.startCount = bin.readUshorts(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 = bin.readUshorts(data, offset, segCount); offset += segCount * 2; obj.glyphIdArray = []; while (offset < offset0 + length) { obj.glyphIdArray.push(bin.readUshort(data, offset)); offset += 2; } return obj; }; Typr2.cmap.parse6 = function(data, offset) { var bin = Typr2._bin; var obj = {}; obj.format = bin.readUshort(data, offset); 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; }; Typr2.cmap.parse12 = function(data, offset) { var bin = Typr2._bin; var obj = {}; obj.format = bin.readUshort(data, offset); offset += 2; offset += 2; bin.readUint(data, offset); offset += 4; bin.readUint(data, offset); offset += 4; var nGroups = bin.readUint(data, offset); offset += 4; obj.groups = []; for (var i = 0; i < nGroups; i++) { var off = offset + i * 12; var startCharCode = bin.readUint(data, off + 0); var endCharCode = bin.readUint(data, off + 4); var startGlyphID = bin.readUint(data, off + 8); obj.groups.push([startCharCode, endCharCode, startGlyphID]); } return obj; }; Typr2.glyf = {}; Typr2.glyf.parse = function(data, offset, length, font) { var obj = []; for (var g = 0; g < font.maxp.numGlyphs; g++) obj.push(null); return obj; }; Typr2.glyf._parseGlyf = function(font, g) { var bin = Typr2._bin; var data = font._data; var offset = Typr2._tabOffset(data, "glyf") + font.loca[g]; if (font.loca[g] == font.loca[g + 1]) return null; 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; }; Typr2.GPOS = {}; Typr2.GPOS.parse = function(data, offset, length, font) { return Typr2._lctf.parse(data, offset, length, font, Typr2.GPOS.subt); }; Typr2.GPOS.subt = function(data, ltype, offset) { if (ltype != 2) return null; var bin = Typr2._bin, offset0 = offset, tab = {}; tab.format = bin.readUshort(data, offset); offset += 2; var covOff = bin.readUshort(data, offset); offset += 2; tab.coverage = Typr2._lctf.readCoverage(data, covOff + offset0); tab.valFmt1 = bin.readUshort(data, offset); offset += 2; tab.valFmt2 = bin.readUshort(data, offset); offset += 2; var ones1 = Typr2._lctf.numOfOnes(tab.valFmt1); var ones2 = Typr2._lctf.numOfOnes(tab.valFmt2); if (tab.format == 1) { tab.pairsets = []; var count = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < count; i++) { var psoff = bin.readUshort(data, offset); offset += 2; psoff += offset0; var pvcount = bin.readUshort(data, psoff); psoff += 2; var arr = []; for (var j = 0; j < pvcount; j++) { var gid2 = bin.readUshort(data, psoff); psoff += 2; var value1, value2; if (tab.valFmt1 != 0) { value1 = Typr2._lctf.readValueRecord(data, psoff, tab.valFmt1); psoff += ones1 * 2; } if (tab.valFmt2 != 0) { value2 = Typr2._lctf.readValueRecord(data, psoff, tab.valFmt2); psoff += ones2 * 2; } arr.push({ gid2, val1: value1, val2: value2 }); } tab.pairsets.push(arr); } } if (tab.format == 2) { var classDef1 = bin.readUshort(data, offset); offset += 2; var classDef2 = bin.readUshort(data, offset); offset += 2; var class1Count = bin.readUshort(data, offset); offset += 2; var class2Count = bin.readUshort(data, offset); offset += 2; tab.classDef1 = Typr2._lctf.readClassDef(data, offset0 + classDef1); tab.classDef2 = Typr2._lctf.readClassDef(data, offset0 + classDef2); tab.matrix = []; for (var i = 0; i < class1Count; i++) { var row = []; for (var j = 0; j < class2Count; j++) { var value1 = null, value2 = null; if (tab.valFmt1 != 0) { value1 = Typr2._lctf.readValueRecord(data, offset, tab.valFmt1); offset += ones1 * 2; } if (tab.valFmt2 != 0) { value2 = Typr2._lctf.readValueRecord(data, offset, tab.valFmt2); offset += ones2 * 2; } row.push({ val1: value1, val2: value2 }); } tab.matrix.push(row); } } return tab; }; Typr2.GSUB = {}; Typr2.GSUB.parse = function(data, offset, length, font) { return Typr2._lctf.parse(data, offset, length, font, Typr2.GSUB.subt); }; Typr2.GSUB.subt = function(data, ltype, offset) { var bin = Typr2._bin, offset0 = offset, tab = {}; if (ltype != 1 && ltype != 4 && ltype != 5) return null; tab.fmt = bin.readUshort(data, offset); offset += 2; var covOff = bin.readUshort(data, offset); offset += 2; tab.coverage = Typr2._lctf.readCoverage(data, covOff + offset0); if (ltype == 1) { if (tab.fmt == 1) { tab.delta = bin.readShort(data, offset); offset += 2; } else if (tab.fmt == 2) { var cnt = bin.readUshort(data, offset); offset += 2; tab.newg = bin.readUshorts(data, offset, cnt); offset += tab.newg.length * 2; } } else if (ltype == 4) { tab.vals = []; var cnt = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < cnt; i++) { var loff = bin.readUshort(data, offset); offset += 2; tab.vals.push(Typr2.GSUB.readLigatureSet(data, offset0 + loff)); } } else if (ltype == 5) { if (tab.fmt == 2) { var cDefOffset = bin.readUshort(data, offset); offset += 2; tab.cDef = Typr2._lctf.readClassDef(data, offset0 + cDefOffset); tab.scset = []; var subClassSetCount = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < subClassSetCount; i++) { var scsOff = bin.readUshort(data, offset); offset += 2; tab.scset.push(scsOff == 0 ? null : Typr2.GSUB.readSubClassSet(data, offset0 + scsOff)); } } else console.log("unknown table format", tab.fmt); } return tab; }; Typr2.GSUB.readSubClassSet = function(data, offset) { var rUs = Typr2._bin.readUshort, offset0 = offset, lset = []; var cnt = rUs(data, offset); offset += 2; for (var i = 0; i < cnt; i++) { var loff = rUs(data, offset); offset += 2; lset.push(Typr2.GSUB.readSubClassRule(data, offset0 + loff)); } return lset; }; Typr2.GSUB.readSubClassRule = function(data, offset) { var rUs = Typr2._bin.readUshort, rule = {}; var gcount = rUs(data, offset); offset += 2; var scount = rUs(data, offset); offset += 2; rule.input = []; for (var i = 0; i < gcount - 1; i++) { rule.input.push(rUs(data, offset)); offset += 2; } rule.substLookupRecords = Typr2.GSUB.readSubstLookupRecords(data, offset, scount); return rule; }; Typr2.GSUB.readSubstLookupRecords = function(data, offset, cnt) { var rUs = Typr2._bin.readUshort; var out = []; for (var i = 0; i < cnt; i++) { out.push(rUs(data, offset), rUs(data, offset + 2)); offset += 4; } return out; }; Typr2.GSUB.readChainSubClassSet = function(data, offset) { var bin = Typr2._bin, offset0 = offset, lset = []; var cnt = bin.readUshort(data, offset); offset += 2; for (var i = 0; i < cnt; i++) { var loff = bin.readUshort(data, offset); offset += 2; lset.push(Typr2.GSUB.readChainSubClassRule(data, offset0 + loff)); } return lset; }; Typr2.GSUB.readChainSubClassRule = function(data, offset) { var bin = Typr2._bin, rule = {}; var pps = ["backtrack", "input", "lookahead"]; for (var pi = 0; pi < pps.length; pi++) { var cnt = bin.readUshort(data, offset); offset += 2; if (pi == 1) cnt--; rule[pps[pi]] = bin.readUshorts(data, offset, cnt); offset += rule[pps[pi]].length * 2; } var cnt = bin.readUshort(data, offset); offset += 2; rule.subst = bin.readUshorts(data, offset, cnt * 2); offset += rule.subst.length * 2; return rule; }; Typr2.GSUB.readLigatureSet = function(data, offset) { var bin = Typr2._bin, offset0 = offset, lset = []; var lcnt = bin.readUshort(data, offset); offset += 2; for (var j = 0; j < lcnt; j++) { var loff = bin.readUshort(data, offset); offset += 2; lset.push(Typr2.GSUB.readLigature(data, offset0 + loff)); } return lset; }; Typr2.GSUB.readLigature = function(data, offset) { var bin = Typr2._bin, lig = { chain: [] }; lig.nglyph = bin.readUshort(data, offset); offset += 2; var ccnt = bin.readUshort(data, offset); offset += 2; for (var k = 0; k < ccnt - 1; k++) { lig.chain.push(bin.readUshort(data, offset)); offset += 2; } return lig; }; Typr2.head = {}; Typr2.head.parse = function(data, offset, length) { var bin = Typr2._bin; 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; }; Typr2.hhea = {}; Typr2.hhea.parse = function(data, offset, length) { var bin = Typr2._bin; var obj = {}; bin.readFixed(data, offset); offset += 4; obj.ascender = bin.readShort(data, offset); offset += 2; obj.descender = bin.readShort(data, offset); offset += 2; obj.lineGap = bin.readShort(data, offset); offset += 2; obj.advanceWidthMax = bin.readUshort(data, offset); offset += 2; obj.minLeftSideBearing = bin.readShort(data, offset); offset += 2; obj.minRightSideBearing = bin.readShort(data, offset); offset += 2; obj.xMaxExtent = bin.readShort(data, offset); offset += 2; obj.caretSlopeRise = bin.readShort(data, offset); offset += 2; obj.caretSlopeRun = bin.readShort(data, offset); offset += 2; obj.caretOffset = bin.readShort(data, offset); offset += 2; offset += 4 * 2; obj.metricDataFormat = bin.readShort(data, offset); offset += 2; obj.numberOfHMetrics = bin.readUshort(data, offset); offset += 2; return obj; }; Typr2.hmtx = {}; Typr2.hmtx.parse = function(data, offset, length, font) { var bin = Typr2._bin; var obj = {}; obj.aWidth = []; obj.lsBearing = []; var aw = 0, lsb = 0; for (var i = 0; i < font.maxp.numGlyphs; i++) { if (i < font.hhea.numberOfHMetrics) { aw = bin.readUshort(data, offset); offset += 2; lsb = bin.readShort(data, offset); offset += 2; } obj.aWidth.push(aw); obj.lsBearing.push(lsb); } return obj; }; Typr2.kern = {}; Typr2.kern.parse = function(data, offset, length, font) { var bin = Typr2._bin; var version = bin.readUshort(data, offset); offset += 2; if (version == 1) return Typr2.kern.parseV1(data, offset - 2, length, font); var nTables = bin.readUshort(data, offset); offset += 2; 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 = Typr2.kern.readFormat0(data, offset, map); else throw "unknown kern table format: " + format; } return map; }; Typr2.kern.parseV1 = function(data, offset, length, font) { var bin = Typr2._bin; bin.readFixed(data, offset); offset += 4; var nTables = bin.readUint(data, offset); offset += 4; 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 >>> 8; format &= 15; if (format == 0) offset = Typr2.kern.readFormat0(data, offset, map); else throw "unknown kern table format: " + format; } return map; }; Typr2.kern.readFormat0 = function(data, offset, map) { var bin = Typr2._bin; var pleft = -1; var nPairs = bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; for (var j = 0; j < nPairs; j++) { var left = bin.readUshort(data, offset); offset += 2; var right = bin.readUshort(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; }; Typr2.loca = {}; Typr2.loca.parse = function(data, offset, length, font) { var bin = Typr2._bin; 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; }; Typr2.maxp = {}; Typr2.maxp.parse = function(data, offset, length) { var bin = Typr2._bin; var obj = {}; var ver = bin.readUint(data, offset); offset += 4; obj.numGlyphs = bin.readUshort(data, offset); offset += 2; if (ver == 65536) { obj.maxPoints = bin.readUshort(data, offset); offset += 2; obj.maxContours = bin.readUshort(data, offset); offset += 2; obj.maxCompositePoints = bin.readUshort(data, offset); offset += 2; obj.maxCompositeContours = bin.readUshort(data, offset); offset += 2; obj.maxZones = bin.readUshort(data, offset); offset += 2; obj.maxTwilightPoints = bin.readUshort(data, offset); offset += 2; obj.maxStorage = bin.readUshort(data, offset); offset += 2; obj.maxFunctionDefs = bin.readUshort(data, offset); offset += 2; obj.maxInstructionDefs = bin.readUshort(data, offset); offset += 2; obj.maxStackElements = bin.readUshort(data, offset); offset += 2; obj.maxSizeOfInstructions = bin.readUshort(data, offset); offset += 2; obj.maxComponentElements = bin.readUshort(data, offset); offset += 2; obj.maxComponentDepth = bin.readUshort(data, offset); offset += 2; } return obj; }; Typr2.name = {}; Typr2.name.parse = function(data, offset, length) { var bin = Typr2._bin; var obj = {}; bin.readUshort(data, offset); offset += 2; var count = bin.readUshort(data, offset); offset += 2; bin.readUshort(data, offset); offset += 2; var offset0 = offset; for (var i = 0; i < count; i++) { var platformID = bin.readUshort(data, offset); offset += 2; var encodingID = bin.readUshort(data, offset); offset += 2; var languageID = bin.readUshort(data, offset); offset += 2; var nameID = bin.readUshort(data, offset); offset += 2; var length = bin.readUshort(data, offset); offset += 2; var noffset = bin.readUshort(data, offset); offset += 2; var plat = "p" + platformID; if (obj[plat] == null) obj[plat] = {}; 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 cname = names[nameID]; var soff = offset0 + count * 12 + noffset; var str; if (platformID == 0) str = bin.readUnicode(data, soff, length / 2); else if (platformID == 3 && encodingID == 0) str = bin.readUnicode(data, soff, length / 2); else if (encodingID == 0) str = bin.readASCII(data, soff, length); else if (encodingID == 1) str = bin.readUnicode(data, soff, length / 2); else if (encodingID == 3) str = bin.readUnicode(data, soff, length / 2); else if (platformID == 1) { str = bin.readASCII(data, soff, length); console.log("reading unknown MAC encoding " + encodingID + " as ASCII"); } else throw "unknown encoding " + encodingID + ", platformID: " + platformID; obj[plat][cname] = str; obj[plat]._lang = languageID; } for (var p in obj) if (obj[p].postScriptName != null && obj[p]._lang == 1033) return obj[p]; for (var p in obj) if (obj[p].postScriptName != null && obj[p]._lang == 3084) return obj[p]; for (var p in obj) if (obj[p].postScriptName != null) return obj[p]; var tname; for (var p in obj) { tname = p; break; } console.log("returning name table with languageID " + obj[tname]._lang); return obj[tname]; }; Typr2["OS/2"] = {}; Typr2["OS/2"].parse = function(data, offset, length) { var bin = Typr2._bin; var ver = bin.readUshort(data, offset); offset += 2; var obj = {}; if (ver == 0) Typr2["OS/2"].version0(data, offset, obj); else if (ver == 1) Typr2["OS/2"].version1(data, offset, obj); else if (ver == 2 || ver == 3 || ver == 4) Typr2["OS/2"].version2(data, offset, obj); else if (ver == 5) Typr2["OS/2"].version5(data, offset, obj); else throw "unknown OS/2 table version: " + ver; return obj; }; Typr2["OS/2"].version0 = function(data, offset, obj) { var bin = Typr2._bin; 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.readInt8(data, offset), bin.readInt8(data, offset + 1), bin.readInt8(data, offset + 2), bin.readInt8(data, offset + 3)]; 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; }; Typr2["OS/2"].version1 = function(data, offset, obj) { var bin = Typr2._bin; offset = Typr2["OS/2"].version0(data, offset, obj); obj.ulCodePageRange1 = bin.readUint(data, offset); offset += 4; obj.ulCodePageRange2 = bin.readUint(data, offset); offset += 4; return offset; }; Typr2["OS/2"].version2 = function(data, offset, obj) { var bin = Typr2._bin; offset = Typr2["OS/2"].version1(data, offset, obj); obj.sxHeight = bin.readShort(data, offset); offset += 2; obj.sCapHeight = bin.readShort(data, offset); offset += 2; obj.usDefault = bin.readUshort(data, offset); offset += 2; obj.usBreak = bin.readUshort(data, offset); offset += 2; obj.usMaxContext = bin.readUshort(data, offset); offset += 2; return offset; }; Typr2["OS/2"].version5 = function(data, offset, obj) { var bin = Typr2._bin; offset = Typr2["OS/2"].version2(data, offset, obj); obj.usLowerOpticalPointSize = bin.readUshort(data, offset); offset += 2; obj.usUpperOpticalPointSize = bin.readUshort(data, offset); offset += 2; return offset; }; Typr2.post = {}; Typr2.post.parse = function(data, offset, length) { var bin = Typr2._bin; 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; }; Typr2.SVG = {}; Typr2.SVG.parse = function(data, offset, length) { var bin = Typr2._bin; 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; }; Typr2.SVG.toPath = function(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.firstChild; while (svg.tagName != "svg") svg = svg.nextSibling; var vb = svg.getAttribute("viewBox"); if (vb) vb = vb.trim().split(" ").map(parseFloat); else vb = [0, 0, 1e3, 1e3]; Typr2.SVG._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; }; Typr2.SVG._toPath = function(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") Typr2.SVG._toPath(nd.children, pth, cfl); else if (tn == "path") { pth.cmds.push(cfl ? cfl : "#000000"); var d = nd.getAttribute("d"); var toks = Typr2.SVG._tokens(d); Typr2.SVG._toksToPath(toks, pth); pth.cmds.push("X"); } else if (tn == "defs") ; else console.log(tn, nd); } }; Typr2.SVG._tokens = function(d) { var ts = [], off = 0, rn = false, cn = ""; while (off < d.length) { var cc = d.charCodeAt(off), ch = d.charAt(off); off++; var isNum = 48 <= cc && cc <= 57 || ch == "." || ch == "-"; if (rn) { if (ch == "-") { 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); } } if (rn) ts.push(parseFloat(cn)); return ts; }; Typr2.SVG._toksToPath = function(ts, pth) { var i = 0, x = 0, y = 0, ox = 0, oy = 0; var pc = { M: 2, L: 2, H: 1, V: 1, S: 4, C: 6 }; var cmds = pth.cmds, crds = pth.crds; while (i < ts.length) { var cmd = ts[i]; i++; if (cmd == "z") { cmds.push("Z"); x = ox; y = oy; } else { var cmu = cmd.toUpperCase(); var ps = pc[cmu], reps = Typr2.SVG._reps(ts, i, ps); for (var j = 0; j < reps; j++) { 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 == "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 - 4, 0); 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 console.log("Unknown SVG command " + cmd); } } } }; Typr2.SVG._reps = function(ts, off, ps) { var i = off; while (i < ts.length) { if (typeof ts[i] == "string") break; i += ps; } return (i - off) / ps; }; if (Typr2 == null) Typr2 = {}; if (Typr2.U == null) Typr2.U = {}; Typr2.U.codeToGlyph = function(font, code) { var cmap = font.cmap; var tind = -1; if (cmap.p0e4 != null) tind = cmap.p0e4; else if (cmap.p3e1 != null) tind = cmap.p3e1; else if (cmap.p1e0 != null) tind = cmap.p1e0; if (tind == -1) throw "no familiar platform and encoding!"; var tab = cmap.tables[tind]; if (tab.format == 0) { if (code >= tab.map.length) return 0; return tab.map[code]; } else if (tab.format == 4) { var sind = -1; for (var i = 0; i < tab.endCount.length; i++) if (code <= tab.endCount[i]) { sind = i; break; } if (sind == -1) return 0; if (tab.startCount[sind] > code) return 0; 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]; return gli & 65535; } else if (tab.format == 12) { if (code > tab.groups[tab.groups.length - 1][1]) return 0; for (var i = 0; i < tab.groups.length; i++) { var grp = tab.groups[i]; if (grp[0] <= code && code <= grp[1]) return grp[2] + (code - grp[0]); } return 0; } else throw "unknown cmap table format " + tab.format; }; Typr2.U.glyphToPath = function(font, gid) { var path = { cmds: [], crds: [] }; if (font.SVG && font.SVG.entries[gid]) { var p = font.SVG.entries[gid]; if (p == null) return path; if (typeof p == "string") { p = Typr2.SVG.toPath(p); font.SVG.entries[gid] = p; } return p; } else if (font.CFF) { var state = { x: 0, y: 0, stack: [], nStems: 0, haveWidth: false, width: font.CFF.Private ? font.CFF.Private.defaultWidthX : 0, open: false }; Typr2.U._drawCFF(font.CFF.CharStrings[gid], state, font.CFF, path); } else if (font.glyf) { Typr2.U._drawGlyf(gid, font, path); } return path; }; Typr2.U._drawGlyf = function(gid, font, path) { var gl = font.glyf[gid]; if (gl == null) gl = font.glyf[gid] = Typr2.glyf._parseGlyf(font, gid); if (gl != null) { if (gl.noc > -1) Typr2.U._simpleGlyph(gl, path); else Typr2.U._compoGlyph(gl, font, path); } }; Typr2.U._simpleGlyph = function(gl, 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) Typr2.U.P.moveTo(p, gl.xs[pr], gl.ys[pr]); else { Typr2.U.P.moveTo(p, x, y); continue; } } else { if (prOnCurve) Typr2.U.P.moveTo(p, gl.xs[pr], gl.ys[pr]); else Typr2.U.P.moveTo(p, (gl.xs[pr] + x) / 2, (gl.ys[pr] + y) / 2); } } if (onCurve) { if (prOnCurve) Typr2.U.P.lineTo(p, x, y); } else { if (nxOnCurve) Typr2.U.P.qcurveTo(p, x, y, gl.xs[nx], gl.ys[nx]); else Typr2.U.P.qcurveTo(p, x, y, (x + gl.xs[nx]) / 2, (y + gl.ys[nx]) / 2); } } Typr2.U.P.closePath(p); } }; Typr2.U._compoGlyph = function(gl, font, p) { for (var j = 0; j < gl.parts.length; j++) { var path = { cmds: [], crds: [] }; var prt = gl.parts[j]; Typr2.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]); } }; Typr2.U._getGlyphClass = function(g, cd) { var intr = Typr2._lctf.getInterval(cd, g); return intr == -1 ? 0 : cd[intr + 2]; }; Typr2.U.getPairAdjustment = function(font, g1, g2) { if (font.GPOS) { var ltab = null; for (var i = 0; i < font.GPOS.featureList.length; i++) { var fl = font.GPOS.featureList[i]; if (fl.tag == "kern") { for (var j = 0; j < fl.tab.length; j++) if (font.GPOS.lookupList[fl.tab[j]].ltype == 2) ltab = font.GPOS.lookupList[fl.tab[j]]; } } if (ltab) { for (var i = 0; i < ltab.tabs.length; i++) { var tab = ltab.tabs[i]; var ind = Typr2._lctf.coverageIndex(tab.coverage, g1); if (ind == -1) continue; var adj; if (tab.format == 1) { var right = tab.pairsets[ind]; for (var j = 0; j < right.length; j++) if (right[j].gid2 == g2) adj = right[j]; if (adj == null) continue; } else if (tab.format == 2) { var c1 = Typr2.U._getGlyphClass(g1, tab.classDef1); var c2 = Typr2.U._getGlyphClass(g2, tab.classDef2); var adj = tab.matrix[c1][c2]; } return adj.val1[2]; } } } if (font.kern) { var ind1 = font.kern.glyph1.indexOf(g1); if (ind1 != -1) { var ind2 = font.kern.rval[ind1].glyph2.indexOf(g2); if (ind2 != -1) return font.kern.rval[ind1].vals[ind2]; } } return 0; }; Typr2.U.stringToGlyphs = function(font, str) { var gls = []; for (var i = 0; i < str.length; i++) { var cc = str.codePointAt(i); if (cc > 65535) i++; gls.push(Typr2.U.codeToGlyph(font, cc)); } var gsub = font["GSUB"]; if (gsub == null) return gls; var llist = gsub.lookupList, flist = gsub.featureList; var wsep = '\n " ,.:;!?() ،'; var R = "آأؤإاةدذرزوٱٲٳٵٶٷڈډڊڋڌڍڎڏڐڑڒړڔڕږڗژڙۀۃۄۅۆۇۈۉۊۋۍۏےۓەۮۯܐܕܖܗܘܙܞܨܪܬܯݍݙݚݛݫݬݱݳݴݸݹࡀࡆࡇࡉࡔࡧࡩࡪࢪࢫࢬࢮࢱࢲࢹૅેૉ૊૎૏ૐ૑૒૝ૡ૤૯஁ஃ஄அஉ஌எஏ஑னப஫஬"; var L = "ꡲ્૗"; for (var ci = 0; ci < gls.length; ci++) { var gl = gls[ci]; var slft = ci == 0 || wsep.indexOf(str[ci - 1]) != -1; var srgt = ci == gls.length - 1 || wsep.indexOf(str[ci + 1]) != -1; if (!slft && R.indexOf(str[ci - 1]) != -1) slft = true; if (!srgt && R.indexOf(str[ci]) != -1) srgt = true; if (!srgt && L.indexOf(str[ci + 1]) != -1) srgt = true; if (!slft && L.indexOf(str[ci]) != -1) slft = true; var feat = null; if (slft) feat = srgt ? "isol" : "init"; else feat = srgt ? "fina" : "medi"; for (var fi = 0; fi < flist.length; fi++) { if (flist[fi].tag != feat) continue; for (var ti = 0; ti < flist[fi].tab.length; ti++) { var tab = llist[flist[fi].tab[ti]]; if (tab.ltype != 1) continue; Typr2.U._applyType1(gls, ci, tab); } } } var cligs = ["rlig", "liga", "mset"]; for (var ci = 0; ci < gls.length; ci++) { var gl = gls[ci]; var rlim = Math.min(3, gls.length - ci - 1); for (var fi = 0; fi < flist.length; fi++) { var fl = flist[fi]; if (cligs.indexOf(fl.tag) == -1) continue; for (var ti = 0; ti < fl.tab.length; ti++) { var tab = llist[fl.tab[ti]]; for (var j = 0; j < tab.tabs.length; j++) { if (tab.tabs[j] == null) continue; var ind = Typr2._lctf.coverageIndex(tab.tabs[j].coverage, gl); if (ind == -1) continue; if (tab.ltype == 4) { var vals = tab.tabs[j].vals[ind]; for (var k = 0; k < vals.length; k++) { var lig = vals[k], rl = lig.chain.length; if (rl > rlim) continue; var good = true; for (var l = 0; l < rl; l++) if (lig.chain[l] != gls[ci + (1 + l)]) good = false; if (!good) continue; gls[ci] = lig.nglyph; for (var l = 0; l < rl; l++) gls[ci + l + 1] = -1; } } else if (tab.ltype == 5) { var ltab = tab.tabs[j]; if (ltab.fmt != 2) continue; var cind = Typr2._lctf.getInterval(ltab.cDef, gl); var cls = ltab.cDef[cind + 2], scs = ltab.scset[cls]; for (var i = 0; i < scs.length; i++) { var sc = scs[i], inp = sc.input; if (inp.length > rlim) continue; var good = true; for (var l = 0; l < inp.length; l++) { var cind2 = Typr2._lctf.getInterval(ltab.cDef, gls[ci + 1 + l]); if (cind == -1 && ltab.cDef[cind2 + 2] != inp[l]) { good = false; break; } } if (!good) continue; var lrs = sc.substLookupRecords; for (var k = 0; k < lrs.length; k += 2) { lrs[k]; lrs[k + 1]; } } } } } } } return gls; }; Typr2.U._applyType1 = function(gls, ci, tab) { var gl = gls[ci]; for (var j = 0; j < tab.tabs.length; j++) { var ttab = tab.tabs[j]; var ind = Typr2._lctf.coverageIndex(ttab.coverage, gl); if (ind == -1) continue; if (ttab.fmt == 1) gls[ci] = gls[ci] + ttab.delta; else gls[ci] = ttab.newg[ind]; } }; Typr2.U.glyphsToPath = function(font, gls, clr) { var tpath = { cmds: [], crds: [] }; var x = 0; for (var i = 0; i < gls.length; i++) { var gid = gls[i]; if (gid == -1) continue; var gid2 = i < gls.length - 1 && gls[i + 1] != -1 ? gls[i + 1] : 0; var path = Typr2.U.glyphToPath(font, gid); for (var j = 0; j < path.crds.length; j += 2) { tpath.crds.push(path.crds[j] + x); tpath.crds.push(path.crds[j + 1]); } if (clr) tpath.cmds.push(clr); for (var j = 0; j < path.cmds.length; j++) tpath.cmds.push(path.cmds[j]); if (clr) tpath.cmds.push("X"); x += font.hmtx.aWidth[gid]; if (i < gls.length - 1) x += Typr2.U.getPairAdjustment(font, gid, gid2); } return tpath; }; Typr2.U.pathToSVG = function(path, prec) { if (prec == null) prec = 5; var out = [], co = 0, lmap = { M: 2, L: 2, Q: 4, C: 6 }; for (var i = 0; i < path.cmds.length; i++) { var cmd = path.cmds[i], cn = co + (lmap[cmd] ? lmap[cmd] : 0); out.push(cmd); while (co < cn) { var c = path.crds[co++]; out.push(parseFloat(c.toFixed(prec)) + (co == cn ? "" : " ")); } } return out.join(""); }; Typr2.U.pathToContext = function(path, ctx) { var c = 0, crds = path.crds; for (var j = 0; j < path.cmds.length; j++) { var cmd = path.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(); } } }; Typr2.U.P = {}; Typr2.U.P.moveTo = function(p, x, y) { p.cmds.push("M"); p.crds.push(x, y); }; Typr2.U.P.lineTo = function(p, x, y) { p.cmds.push("L"); p.crds.push(x, y); }; Typr2.U.P.curveTo = function(p, a, b, c, d, e, f) { p.cmds.push("C"); p.crds.push(a, b, c, d, e, f); }; Typr2.U.P.qcurveTo = function(p, a, b, c, d) { p.cmds.push("Q"); p.crds.push(a, b, c, d); }; Typr2.U.P.closePath = function(p) { p.cmds.push("Z"); }; Typr2.U._drawCFF = function(cmds, state, font, 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 o = { val: 0, size: 0 }; while (i < cmds.length) { Typr2.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() + font.Private.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() + font.Private.nominalWidthX; } nStems += stack.length >> 1; stack.length = 0; haveWidth = true; } else if (v == "o4") { if (stack.length > 1 && !haveWidth) { width = stack.shift() + font.Private.nominalWidthX; haveWidth = true; } if (open) Typr2.U.P.closePath(p); y += stack.pop(); Typr2.U.P.moveTo(p, x, y); open = true; } else if (v == "o5") { while (stack.length > 0) { x += stack.shift(); y += stack.shift(); Typr2.U.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; Typr2.U.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(); Typr2.U.P.curveTo(p, c1x, c1y, c2x, c2y, x, y); index += 6; } if (v == "o24") { x += stack.shift(); y += stack.shift(); Typr2.U.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(); Typr2.U.P.curveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); Typr2.U.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(); Typr2.U.P.curveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); Typr2.U.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(); Typr2.U.P.curveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); Typr2.U.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(); } Typr2.U.P.curveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); Typr2.U.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 = Typr2.CFF.glyphBySE(font, bchar); var aind = Typr2.CFF.glyphBySE(font, achar); Typr2.U._drawCFF(font.CharStrings[bind], state, font, p); state.x = adx; state.y = ady; Typr2.U._drawCFF(font.CharStrings[aind], state, font, p); } if (open) { Typr2.U.P.closePath(p); open = false; } } else if (v == "o19" || v == "o20") { var hasWidthArg; hasWidthArg = stack.length % 2 !== 0; if (hasWidthArg && !haveWidth) { width = stack.shift() + font.Private.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() + font.Private.nominalWidthX; haveWidth = true; } y += stack.pop(); x += stack.pop(); if (open) Typr2.U.P.closePath(p); Typr2.U.P.moveTo(p, x, y); open = true; } else if (v == "o22") { if (stack.length > 1 && !haveWidth) { width = stack.shift() + font.Private.nominalWidthX; haveWidth = true; } x += stack.pop(); if (open) Typr2.U.P.closePath(p); Typr2.U.P.moveTo(p, x, y); open = true; } else if (v == "o25") { while (stack.length > 6) { x += stack.shift(); y += stack.shift(); Typr2.U.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(); Typr2.U.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(); Typr2.U.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; Typr2.U.P.curveTo(p, c1x, c1y, c2x, c2y, x, y); } } else if (v == "o10" || v == "o29") { var obj = v == "o10" ? font.Private : 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; Typr2.U._drawCFF(subr, state, font, 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 & -3; 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; } Typr2.U.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; }; typr_js$1 = Typr2; return typr_js$1; } var typr_jsExports = requireTypr_js(); const Typr = getDefaultExportFromCjs(typr_jsExports); var md5$2 = { exports: {} }; var md5$1 = md5$2.exports; var hasRequiredMd5; function requireMd5() { if (hasRequiredMd5) return md5$2.exports; hasRequiredMd5 = 1; (function(module) { (function($2) { function safeAdd(x, y) { var lsw = (x & 65535) + (y & 65535); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return msw << 16 | lsw & 65535; } function bitRotateLeft(num, cnt) { return num << cnt | num >>> 32 - cnt; } function md5cmn(q, a, b, x, s, t) { return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b); } function md5ff(a, b, c, d, x, s, t) { return md5cmn(b & c | ~b & d, a, b, x, s, t); } function md5gg(a, b, c, d, x, s, t) { return md5cmn(b & d | c & ~d, a, b, x, s, t); } function md5hh(a, b, c, d, x, s, t) { return md5cmn(b ^ c ^ d, a, b, x, s, t); } function md5ii(a, b, c, d, x, s, t) { return md5cmn(c ^ (b | ~d), a, b, x, s, t); } function binlMD5(x, len) { x[len >> 5] |= 128 << len % 32; x[(len + 64 >>> 9 << 4) + 14] = len; var i; var olda; var oldb; var oldc; var oldd; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for (i = 0; i < x.length; i += 16) { olda = a; oldb = b; oldc = c; oldd = d; a = md5ff(a, b, c, d, x[i], 7, -680876936); d = md5ff(d, a, b, c, x[i + 1], 12, -389564586); c = md5ff(c, d, a, b, x[i + 2], 17, 606105819); b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330); a = md5ff(a, b, c, d, x[i + 4], 7, -176418897); d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426); c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341); b = md5ff(b, c, d, a, x[i + 7], 22, -45705983); a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416); d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417); c = md5ff(c, d, a, b, x[i + 10], 17, -42063); b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162); a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682); d = md5ff(d, a, b, c, x[i + 13], 12, -40341101); c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290); b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329); a = md5gg(a, b, c, d, x[i + 1], 5, -165796510); d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632); c = md5gg(c, d, a, b, x[i + 11], 14, 643717713); b = md5gg(b, c, d, a, x[i], 20, -373897302); a = md5gg(a, b, c, d, x[i + 5], 5, -701558691); d = md5gg(d, a, b, c, x[i + 10], 9, 38016083); c = md5gg(c, d, a, b, x[i + 15], 14, -660478335); b = md5gg(b, c, d, a, x[i + 4], 20, -405537848); a = md5gg(a, b, c, d, x[i + 9], 5, 568446438); d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690); c = md5gg(c, d, a, b, x[i + 3], 14, -187363961); b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501); a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467); d = md5gg(d, a, b, c, x[i + 2], 9, -51403784); c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473); b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734); a = md5hh(a, b, c, d, x[i + 5], 4, -378558); d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463); c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562); b = md5hh(b, c, d, a, x[i + 14], 23, -35309556); a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060); d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353); c = md5hh(c, d, a, b, x[i + 7], 16, -155497632); b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640); a = md5hh(a, b, c, d, x[i + 13], 4, 681279174); d = md5hh(d, a, b, c, x[i], 11, -358537222); c = md5hh(c, d, a, b, x[i + 3], 16, -722521979); b = md5hh(b, c, d, a, x[i + 6], 23, 76029189); a = md5hh(a, b, c, d, x[i + 9], 4, -640364487); d = md5hh(d, a, b, c, x[i + 12], 11, -421815835); c = md5hh(c, d, a, b, x[i + 15], 16, 530742520); b = md5hh(b, c, d, a, x[i + 2], 23, -995338651); a = md5ii(a, b, c, d, x[i], 6, -198630844); d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415); c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905); b = md5ii(b, c, d, a, x[i + 5], 21, -57434055); a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571); d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606); c = md5ii(c, d, a, b, x[i + 10], 15, -1051523); b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799); a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359); d = md5ii(d, a, b, c, x[i + 15], 10, -30611744); c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380); b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649); a = md5ii(a, b, c, d, x[i + 4], 6, -145523070); d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379); c = md5ii(c, d, a, b, x[i + 2], 15, 718787259); b = md5ii(b, c, d, a, x[i + 9], 21, -343485551); a = safeAdd(a, olda); b = safeAdd(b, oldb); c = safeAdd(c, oldc); d = safeAdd(d, oldd); } return [a, b, c, d]; } function binl2rstr(input) { var i; var output = ""; var length32 = input.length * 32; for (i = 0; i < length32; i += 8) { output += String.fromCharCode(input[i >> 5] >>> i % 32 & 255); } return output; } function rstr2binl(input) { var i; var output = []; output[(input.length >> 2) - 1] = void 0; for (i = 0; i < output.length; i += 1) { output[i] = 0; } var length8 = input.length * 8; for (i = 0; i < length8; i += 8) { output[i >> 5] |= (input.charCodeAt(i / 8) & 255) << i % 32; } return output; } function rstrMD5(s) { return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)); } function rstrHMACMD5(key, data) { var i; var bkey = rstr2binl(key); var ipad = []; var opad = []; var hash; ipad[15] = opad[15] = void 0; if (bkey.length > 16) { bkey = binlMD5(bkey, key.length * 8); } for (i = 0; i < 16; i += 1) { ipad[i] = bkey[i] ^ 909522486; opad[i] = bkey[i] ^ 1549556828; } hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)); } function rstr2hex(input) { var hexTab = "0123456789abcdef"; var output = ""; var x; var i; for (i = 0; i < input.length; i += 1) { x = input.charCodeAt(i); output += hexTab.charAt(x >>> 4 & 15) + hexTab.charAt(x & 15); } return output; } function str2rstrUTF8(input) { return unescape(encodeURIComponent(input)); } function rawMD5(s) { return rstrMD5(str2rstrUTF8(s)); } function hexMD5(s) { return rstr2hex(rawMD5(s)); } function rawHMACMD5(k, d) { return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)); } function hexHMACMD5(k, d) { return rstr2hex(rawHMACMD5(k, d)); } function md52(string, key, raw) { if (!key) { if (!raw) { return hexMD5(string); } return rawMD5(string); } if (!raw) { return hexHMACMD5(key, string); } return rawHMACMD5(key, string); } if (module.exports) { module.exports = md52; } else { $2.md5 = md52; } })(md5$1); })(md5$2); return md5$2.exports; } var md5Exports = requireMd5(); const md5 = getDefaultExportFromCjs(md5Exports); const typr_js = Typr; const $ = { sleep: (time) => { return new Promise((resolve) => setTimeout((_) => resolve(), time)); } }; let $el$1 = function(query, root = document) { return root.querySelector(query); }; let $$el = function(query, root = document) { return root.querySelectorAll(query); }; let $console = { log: (...args) => { console.info.apply(null, args); }, info: (...args) => { console.info.apply(null, args); }, error: (...args) => { console.info.apply(null, args); }, warn: (...args) => { console.warn.apply(null, args); } }; let $message = { success: () => { }, warn: () => { }, info: () => { } }; let $alert = function({ content }) { console.log(content); }; const state$3 = { study: { videojs: Object.create({}), answererWrapperUnsetMessage: void 0 } }; const $h = (tag, content) => { let el = document.createElement(tag); el.textContent = Array.isArray(content) ? content.join("") : content; }; function domSearch(wrapper, root2 = window.document) { const obj = Object.create({}); Reflect.ownKeys(wrapper).forEach((key) => { const item = wrapper[key.toString()]; Reflect.set( obj, key, typeof item === "string" ? root2.querySelector(item) : typeof item === "function" ? item(root2) : item.map((fun) => fun(root2)) ); }); return obj; } function domSearchAll(wrapper, root2 = window.document) { const obj = Object.create({}); Reflect.ownKeys(wrapper).forEach((key) => { const item = wrapper[key.toString()]; Reflect.set( obj, key, typeof item === "string" ? Array.from(root2.querySelectorAll(item)) : typeof item === "function" ? item(root2) : item.map((fun) => fun(root2)) ); }); return obj; } function waitTask(fn, timeout = 10) { return new Promise((resolve, reject) => { function exec() { const context = {}; const ret = fn(context); if (context.done) { resolve(ret); } if (timeout--) { setTimeout(exec, 1e3); } else { reject(); } } exec(); }); } function optimizationElementWithImage(root2, clone_node = false) { const clone = clone_node ? root2.cloneNode(true) : root2; for (const img of Array.from(clone.querySelectorAll("img"))) { const src2 = document.createElement("span"); src2.innerText = img.src; src2.style.fontSize = "0px"; img.after(src2); } return clone; } function getTopWindow() { let topWindow2 = window.top; try { let _self = _unsafeWindow; let _try_count = 10; while (_self.parent !== void 0 && _try_count > 0) { if (_self.location.href.includes("/mycourse/studentstudy")) { topWindow2 = _self; console.log("[ocsjs] top change to :" + topWindow2.location.href); break; } else { _try_count--; _self = _self.parent; } } } catch (e) { console.warn("[ocsjs] fail of find top"); console.warn(e); topWindow2 = window.top; } try { topWindow2.typrMapping = topWindow2.typrMapping || void 0; topWindow2.jobs = topWindow2.jobs || []; topWindow2.currentMedia = topWindow2.currentMedia || void 0; } catch { } return topWindow2; } const topWindow$2 = getTopWindow(); function waitForNewFaceRecognition(showWarn) { let notified = false; return new Promise((resolve) => { const interval = setInterval(() => { const faces = $$el(".chapterVideoFaceMaskDiv", topWindow$2 == null ? void 0 : topWindow$2.document); let active = false; for (const face of faces) { if (face.style.display !== "none") { active = true; break; } } if (active) { if (!notified) { notified = true; const msg = "检测到人脸识别,请手动进行识别后脚本才会继续运行。"; if (showWarn) { $message.warn({ content: msg, duration: 0 }); $console.warn(msg); } } } else { clearInterval(interval); resolve(); } }, 3e3); }); } function waitForFaceRecognition(showWarn) { let notified = false; return new Promise((resolve) => { const interval = setInterval(() => { const faces = $$el("#fcqrimg", topWindow$2 == null ? void 0 : topWindow$2.document); let active = false; for (const face of faces) { const src2 = face.getAttribute("src"); if (src2) { active = true; break; } } if (active) { if (!notified) { notified = true; const msg = "检测到人脸识别,请手动进行识别后脚本才会继续运行。"; if (showWarn) { $message.warn({ content: msg, duration: 0 }); $console.warn(msg); } } } else { clearInterval(interval); resolve(); } }, 3e3); }); } function getQuestionType(val) { return val === 0 ? "single" : val === 1 ? "multiple" : val === 3 ? "judgement" : [2, 4, 5, 6, 7, 8, 9, 10].some((t2) => t2 === val) ? "completion" : val === 11 ? "line" : val === 14 ? "fill" : val === 15 ? "reader" : void 0; } async function waitForContinuate(isStopping) { if (isStopping()) { await new Promise((resolve, reject) => { const interval = setInterval(() => { if (isStopping() === false) { clearInterval(interval); resolve(); } }, 200); }); } } async function loadTyprMapping() { console.log("正在加载繁体字库。"); try { return await request("http://aiqbank.jmgx.top/gmscript/table.json"); } catch (err) { $console.error("载繁体字库加载失败,请刷新页面重试:", String(err)); } } async function request(url, method = "GET", data = {}, headers = { "Content-Type": "application/json" }, responseType = "json") { const contentType = headers["Content-Type"] || headers["content-type"]; const requestData = contentType === "application/x-www-form-urlencoded" ? new URLSearchParams(data).toString() : Object.keys(data).length ? JSON.stringify(data) : void 0; return new Promise((resolve, reject) => { _GM_xmlhttpRequest({ url, method: method.toUpperCase(), data: requestData, headers: Object.keys(headers).length ? headers : void 0, responseType: responseType === "json" ? "json" : void 0, onload: (response) => { if (response.status === 200) { if (responseType === "json") { try { resolve(JSON.parse(response.responseText)); } catch (error) { reject(error); } } else { resolve(response.responseText || ""); } } else { reject(response.responseText); } }, onerror: (err) => { console.error("GM_xmlhttpRequest error", err); reject(err); } }); }); } async function mappingRecognize(doc = document) { var _a, _b; let typrMapping = Object.create({}); let topWin = getTopWindow(); try { topWin.typrMapping = topWin.typrMapping || await loadTyprMapping(); typrMapping = window.typrMapping; } catch { typrMapping = await loadTyprMapping(); } typrMapping = await loadTyprMapping(); const fontFaceEl = Array.from(doc.head.querySelectorAll("style")).find( (style) => { var _a2; return (_a2 = style.textContent) == null ? void 0 : _a2.includes("font-cxsecret"); } ); const base64ToUint8Array = (base64) => { const data = window.atob(base64); const buffer = new Uint8Array(data.length); for (let i = 0; i < data.length; ++i) { buffer[i] = data.charCodeAt(i); } return buffer; }; const fontMap = typrMapping; if (fontFaceEl && Object.keys(fontMap).length > 0) { const font = (_b = (_a = fontFaceEl.textContent) == null ? void 0 : _a.match(/base64,([\w\W]+?)'/)) == null ? void 0 : _b[1]; if (font) { console.log("正在识别繁体字"); const code = typr_js.parse(base64ToUint8Array(font)); const match = {}; for (let i = 19968; i < 40870; i++) { const Glyph = typr_js.U.codeToGlyph(code, i); if (!Glyph) continue; const path = typr_js.U.glyphToPath(code, Glyph); const hex = md5(JSON.stringify(path)).slice(24); match[i.toString()] = fontMap[hex]; } const fonts = getSecretFont(doc); fonts.forEach((el, index) => { let html = el.innerHTML; for (const key in match) { const word = String.fromCharCode(parseInt(key)); const value = String.fromCharCode(match[key]); if (word === value) { continue; } while (html.indexOf(word) !== -1) { html = html.replace(word, value); } } el.innerHTML = html; el.classList.remove("font-cxsecret"); }); console.log("识别繁体字完成。"); } else { console.log("未检测到繁体字。"); } } } function getSecretFont(doc = document) { return Array.from(doc.querySelectorAll(".font-cxsecret")).map((font) => { const after = font.querySelector(".after"); return after === null ? font : after; }); } const chapterTestTaskQuestionTitleTransform = (titles) => { let removed = titles.map((t2) => t2 == null ? void 0 : t2.innerText).join("\n"); return removed.trim().replace(/^\d+[。、.]/, "").replace(/(\d+\.\d+分)/, "").replace(/\(..题, \d+?分\)/, "").replace(/\(..题, \d+\.\d+分\)/, "").replace(/[[(【(](..题|名词解释|完形填空|阅读理解)[\])】)]/, "").trim(); }; class AI { constructor(apiTokenId) { this.apiTokenId = apiTokenId; } test() { this.search("选择题 1 + 2 = ? 选项 A: 1, B: 2, D: 4, C:3 直接给答案选项字母"); } search(query, category, subject = "") { let apiTokenId = this.apiTokenId; return new Promise((resolve, reject) => { request("http://aiqbank.jmgx.top/api/bank/ai", "post", { apiTokenId, query, category, subject }).then((data) => { let answer = (data.content || data).answer; resolve(answer); }).catch((e) => { alert("搜题出错," + e); console.log(e); reject(e); }); }); } } class StringUtils { constructor(_text) { this._text = _text; } static nowrap(str, replace_str) { return (str == null ? void 0 : str.replace(/\n/g, replace_str)) || ""; } nowrap(replace_str) { this._text = StringUtils.nowrap(this._text, replace_str); return this; } static nospace(str) { return (str == null ? void 0 : str.replace(/ +/g, " ")) || ""; } nospace() { this._text = StringUtils.nospace(this._text); return this; } static noSpecialChar(str) { return (str == null ? void 0 : str.replace(/[^\w\s]/gi, "")) || ""; } noSpecialChar() { this._text = StringUtils.noSpecialChar(this._text); return this; } static max(str, len) { return str.length > len ? str.substring(0, len) + "..." : str; } max(len) { this._text = StringUtils.max(this._text, len); return this; } static hide(str, start2, end, replacer = "*") { return str.substring(0, start2) + str.substring(start2, end).replace(/./g, replacer) + str.substring(end); } hide(start2, end, replacer = "*") { this._text = StringUtils.hide(this._text, start2, end, replacer); return this; } static of(text) { return new StringUtils(text); } toString() { return this._text; } } function clearString(str, ...exclude) { return str.trim().toLocaleLowerCase().replace(RegExp(`[^一-龥A-Za-z0-9${exclude.join("")}]*`, "g"), ""); } function areArgsValid(mainString, targetStrings) { if (typeof mainString !== "string") return false; if (!Array.isArray(targetStrings)) return false; if (!targetStrings.length) return false; if (targetStrings.find(function(s) { return typeof s !== "string"; })) return false; return true; } function compareTwoStrings(first, second) { first = first.replace(/\s+/g, ""); second = second.replace(/\s+/g, ""); if (first === second) return 1; if (first.length < 2 || second.length < 2) return 0; let firstBigrams = new Map(); for (let i = 0; i < first.length - 1; i++) { const bigram = first.substring(i, i + 2); const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) + 1 : 1; firstBigrams.set(bigram, count); } let intersectionSize = 0; for (let i = 0; i < second.length - 1; i++) { const bigram = second.substring(i, i + 2); const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) : 0; if (count > 0) { firstBigrams.set(bigram, count - 1); intersectionSize++; } } return 2 * intersectionSize / (first.length + second.length - 2); } function findBestMatch(mainString, targetStrings) { if (!areArgsValid(mainString, targetStrings)) throw new Error("Bad arguments: First argument should be a string, second should be an array of strings"); const ratings = []; let bestMatchIndex = 0; for (let i = 0; i < targetStrings.length; i++) { const currentTargetString = targetStrings[i]; const currentRating = compareTwoStrings(mainString, currentTargetString); ratings.push({ target: currentTargetString, rating: currentRating }); if (currentRating > ratings[bestMatchIndex].rating) { bestMatchIndex = i; } } const bestMatch = ratings[bestMatchIndex]; return { ratings, bestMatch, bestMatchIndex }; } function removeRedundant(str) { return (str == null ? void 0 : str.trim().replace(/[A-Z]{1}[^A-Za-z0-9一-龥]+([A-Za-z0-9一-龥]+)/, "$1")) || ""; } function answerSimilar(answers, options) { const _answers = answers.map(removeRedundant); const _options = options.map(removeRedundant); const similar = _answers.length !== 0 ? _options.map((option) => { if (option.trim() === "") { return { rating: 0, target: "" }; } return findBestMatch(option, _answers).bestMatch; }) : _options.map(() => ({ rating: 0, target: "" })); return similar; } function answerExactMatch(answers, options) { const _answers = answers.map(removeRedundant); const _options = options.map(removeRedundant); const result = _answers.length !== 0 ? _options.filter((option) => { return _answers.find((answer) => answer.trim() === option.trim()); }) : []; return result; } function splitAnswer$1(answer, separators = ["===", "#", "---", "###", "|", ";", ";"]) { answer = answer.trim(); if (answer.length === 0) { return []; } separators = separators.length === 0 ? ["===", "#", "---", "###", "|", ";", ";"] : separators; separators = separators.filter((el) => el.trim().length > 0); try { const json = JSON.parse(answer); if (Array.isArray(json)) { return json.map(String).filter((el) => el.trim().length > 0); } } catch { for (const sep of separators) { if (answer.split(sep).length > 1) { return answer.split(sep).filter((el) => el.trim().length > 0); } } } return [answer]; } function resolvePlainAnswer(answer) { const resolve = answer.trim().replace(/[,,、 ]/g, "").trim(); if (isPlainAnswer(resolve)) { return resolve; } } function isPlainAnswer(answer) { answer = answer.trim(); if (answer.length > 8 || !/[A-Z]/.test(answer)) { return false; } const counter = {}; let min = 0; for (let i = 0; i < answer.length; i++) { if (answer.charCodeAt(i) < min) { return false; } min = answer.charCodeAt(i); counter[min] = (counter[min] || 0) + 1; } for (const key in counter) { if (counter[key] !== 1) { return false; } } return true; } class defaultQuestionResolver { constructor(ctx) { this.ctx = ctx; } async single(infos, options, handler) { var _a; console.log("resolver 答单选题 ctx", this.ctx); const allAnswer = infos.map((res) => res.results.map((res2) => splitAnswer$1(res2.answer, this.ctx.answerSeparators)).flat()).flat(); const optionStrings = options.map((o) => removeRedundant(o == null ? void 0 : o.innerText)); if (this.ctx.answerMatchMode === "similar") { const ratings = answerSimilar(allAnswer, optionStrings); let index = -1; let max = 0; let ans = ""; ratings.forEach((rating, i) => { if (rating.rating > max) { max = rating.rating; index = i; ans = rating.target; } }); if (index !== -1 && max > 0.6) { await handler("single", ans, options[index], this.ctx); return { finish: true, ratings: ratings.map((r) => r.rating) }; } } else if (this.ctx.answerMatchMode === "exact") { const result = answerExactMatch(allAnswer, optionStrings); const index = optionStrings.findIndex((option) => result.includes(option)); if (result.length) { await handler("single", (_a = options[index]) == null ? void 0 : _a.innerText, options[index], this.ctx); return { finish: true }; } } for (const info of infos) { for (const res of info.results) { const ans = StringUtils.nowrap(res.answer, "").trim(); if (ans.length === 1 && /[A-Z]/.test(ans)) { const index = ans.charCodeAt(0) - 65; if (options[index] === void 0) { continue; } await handler("single", options[index].innerText, options[index], this.ctx); return { finish: true, option: options[index] }; } } } return { finish: false, allAnswer, options: optionStrings }; } async multiple(infos, options, handler) { var _a; const targetAnswers = []; const targetOptions = []; const similar_list = []; const exact_list = []; const results = infos.map((info) => info.results).flat(); for (let i = 0; i < results.length; i++) { const result = results[i]; const answers = splitAnswer$1(result.answer.trim(), this.ctx.answerSeparators); if (this.ctx.answerMatchMode === "similar") { const matchResult = { options: [], answers: [], ratings: [], similarSum: 0, similarCount: 0 }; for (const option of options) { const ans = answers.find( (answer) => answer.includes(removeRedundant(option.textContent || option.innerText)) ); if (ans) { matchResult.options.push(option); matchResult.answers.push(ans); matchResult.ratings.push(1); matchResult.similarSum += 1; matchResult.similarCount += 1; } } const ratingResult = { options: [], answers: [], ratings: [], similarSum: 0, similarCount: 0 }; const ratings = answerSimilar( answers, options.map((o) => removeRedundant(o.innerText)) ); for (let j = 0; j < ratings.length; j++) { const rating = ratings[j]; if (rating.rating > 0.6) { ratingResult.options.push(options[j]); ratingResult.answers.push(ratings[j].target); ratingResult.ratings.push(ratings[j].rating); ratingResult.similarSum += rating.rating; ratingResult.similarCount += 1; } } if (matchResult.similarSum > ratingResult.similarSum) { similar_list[i] = matchResult; } else { similar_list[i] = ratingResult; } } else if (this.ctx.answerMatchMode === "exact") { exact_list[i] = answerExactMatch( answers, options.map((o) => removeRedundant(o.innerText)) ).map((option) => options.find((o) => removeRedundant(o.innerText) === option)).filter(Boolean); } } if (this.ctx.answerMatchMode === "similar") { const sorted_similar_list = similar_list.filter((i) => i.similarCount !== 0).sort((a, b) => { const bsc = b.similarCount * 100; const asc = a.similarCount * 100; const bss = b.similarSum; const ass = a.similarSum; return bsc + bss - asc + ass; }); if (sorted_similar_list[0]) { for (let i = 0; i < sorted_similar_list[0].options.length; i++) { await handler("multiple", sorted_similar_list[0].answers[i], sorted_similar_list[0].options[i], this.ctx); } return { finish: true, sorted_similar_list, targetOptions, targetAnswers }; } } else if (this.ctx.answerMatchMode === "exact") { const sorted_exact_list = exact_list.sort((a, b) => b.length - a.length); if ((_a = sorted_exact_list[0]) == null ? void 0 : _a.length) { for (let i = 0; i < sorted_exact_list[0].length; i++) { await handler("multiple", sorted_exact_list[0][i].innerText, sorted_exact_list[0][i], this.ctx); } return { finish: true, sorted_exact_list: sorted_exact_list.map((i) => i.map((e) => e.innerText)), targetOptions, targetAnswers }; } } const plainOptions = []; for (const result of results) { const ans = StringUtils.nowrap(result.answer, "").trim(); const plainAnswer = resolvePlainAnswer(ans); if (plainAnswer) { for (const char of ans) { const index = char.charCodeAt(0) - 65; if (options[index] === void 0) { continue; } await handler("single", options[index].innerText, options[index], this.ctx); plainOptions.push(options[index]); } } } if (plainOptions.length) { return { finish: true, plainOptions }; } else { return { finish: false }; } } async judgement(infos, options, handler) { for (const answers of infos.map((info) => info.results.map((res) => res.answer))) { let matches = function(target, options2) { return options2.some( (option) => clearString(removeRedundant(option), "√", "×") === clearString(removeRedundant(target), "√", "×") ); }; const correctWords = [ "是", "对", "正确", "确定", "√", "对的", "是的", "正确的", "true", "True", "T", "yes", "1" ]; const incorrectWords = [ "非", "否", "错", "错误", "×", "X", "错的", "不对", "不正确的", "不正确", "不是", "不是的", "false", "False", "F", "no", "0" ]; const answerShowCorrect = answers.find((answer) => matches(answer, correctWords)); const answerShowIncorrect = answers.find((answer) => matches(answer, incorrectWords)); if (answerShowCorrect || answerShowIncorrect) { let option; for (const el of options) { const textShowCorrect = matches(el.innerText, correctWords); const textShowIncorrect = matches(el.innerText, incorrectWords); if (answerShowCorrect && textShowCorrect) { option = el; await handler("judgement", answerShowCorrect, el, this.ctx); break; } if (answerShowIncorrect && textShowIncorrect) { option = el; await handler("judgement", answerShowIncorrect, el, this.ctx); break; } } return { finish: true, option }; } } return { finish: false }; } async completion(infos, options, handler) { for (const answers of infos.map((info) => info.results.map((res) => res.answer))) { let ans = answers.filter((ans2) => ans2); if (ans.length === 1) { ans = splitAnswer$1(ans[0], this.ctx.answerSeparators); } if (ans.length !== 0 && (ans.length === options.length || options.length === 1)) { if (ans.length === options.length) { for (let index = 0; index < options.length; index++) { const element = options[index]; await handler("completion", ans[index], element, this.ctx); } return { finish: true }; } else if (options.length === 1) { await handler("completion", ans.join(" "), options[0], this.ctx); return { finish: true }; } return { finish: false }; } } return { finish: false }; } } class Worker extends EventTarget { constructor(config, opts) { super(); this.isRunning = false; this.isClose = false; this.isStop = false; this.totalQuestionCount = 0; this.config = config; this.opts = opts; } emit() { const e = new Event(event); this.dispatchEvent(e); } on(type, listener) { return this.addEventListener(type, listener); } once(type, listener) { let inst = this.on(type, (e) => { listener(e); this.removeEventListener(type, inst); }); return inst; } async doWork(options = {}) { var _a, _b, _c, _d; this.emit("start"); this.isRunning = true; this.once("close", () => { this.isClose = true; }); this.on("stop", () => { this.isStop = true; }); this.on("continuate", () => { this.isStop = false; }); let root = this.opts.root; const questionRoots = typeof root === "string" ? Array.from(document.querySelectorAll(root)) : root; this.totalQuestionCount += questionRoots.length; console.debug("开始答题", this); console.debug("题目数量: ", questionRoots.length); console.debug("父节点列表: ", questionRoots); const results = []; if (questionRoots.length === 0) { throw new Error("未找到任何题目,答题结束。"); } for (const questionRoot of questionRoots) { const ctx = { searchInfos: [], root: questionRoot, elements: domSearchAll(this.opts.elements, questionRoot), type: void 0, answerSeparators: this.opts.answerSeparators, answerMatchMode: this.opts.answerMatchMode || "similar" }; await ((_b = (_a = this.opts).onElementSearched) == null ? void 0 : _b.call(_a, ctx.elements, questionRoot)); ctx.elements.title = (_c = ctx.elements.title) == null ? void 0 : _c.filter(Boolean); ctx.elements.title = ctx.elements.title; ctx.elements.options = (_d = ctx.elements.options) == null ? void 0 : _d.filter(Boolean); results.push({ requested: false, resolved: false, ctx }); } if (options == null ? void 0 : options.enable_debug) { console.debug("上下文已初始化: ", results); } const requestThread = async (index) => { let error; const result = results[index]; const ctx = result.ctx || {}; if (this.isClose === true) { this.isRunning = false; return; } if (this.isStop) { await waitForContinuate(() => this.isStop); } if (typeof this.opts.work === "object") { if (this.opts.work.type) { if (this.opts.work.type === "string") { ctx.type = this.opts.work.type; } else { ctx.type = this.opts.work.type(ctx); } } else { ctx.type = defaultWorkTypeResolver(ctx); } } ctx.searchInfos = []; if (options == null ? void 0 : options.enable_debug) { console.debug("开始搜题: ", result.ctx); } console.log("worker 开始搜题"); try { ctx.searchInfos = await this.opts.answerer(ctx.elements, ctx) || []; ctx.searchInfos.forEach((info) => { info.results = info.results.map((ans) => { ans.answer = ans.answer ? ans.answer.trim() : ""; return ans; }); }); } catch (err) { error = String(err); alert("代码 0001:" + error); throw err; } result.ctx = ctx; result.requested = true; result.error = error; if (options == null ? void 0 : options.enable_debug) { console.debug("搜题完成: ", index, result.ctx); } if (this.opts.onResultsUpdate) { await this.opts.onResultsUpdate.call(this.opts, results[index], index, results); } }; const resolverThread = async () => { var _a2, _b2; const waitForRequested = async (result) => { return new Promise((resolve, reject) => { waitTask((context) => { if ((result == null ? void 0 : result.requested) === true) { context.done = true; } }, 60 * 1e3).then((_) => { resolve(); }).catch((_) => { reject(new Error("答题超时!")); }); }); }; for (let index = 0; index < results.length; index++) { const result = results[index]; let error; let res; try { if (this.isClose === true) { this.isRunning = false; return; } if (this.isStop) { await waitForContinuate(() => this.isStop); } await waitForRequested(result); console.log(result.ctx, result.ctx.searchInfos.length); if (result.ctx && result.ctx.searchInfos.length !== 0) { if (typeof this.opts.work === "object") { if (result.ctx.elements.options) { if (result.ctx.type) { const resolver = defaultQuestionResolver(result.ctx)[result.ctx.type]; const handler = this.opts.work.handler; res = await resolver(result.ctx.searchInfos, result.ctx.elements.options, handler); } else { error = "题目类型解析失败, 请自行提供解析器, 或者忽略此题。"; } } else { error = "elements.options 为空 ! 使用默认处理器, 必须提供题目选项的选择器。"; } } else { const work2 = this.opts.work; res = await work2(result.ctx); } } else { error = "搜索不到答案, 请重新运行, 或者忽略此题。"; } } catch (err) { error = (err == null ? void 0 : err.message) || err; } result.error = error; result.result = res || { finish: false }; result.resolved = true; if (options == null ? void 0 : options.enable_debug) { console.debug("答题完成: ", index, result); } await ((_b2 = (_a2 = this.opts).onResultsUpdate) == null ? void 0 : _b2.call(_a2, result, index, results)); } }; const requestThreadHandler = async () => { const locks = []; const waitForLock = () => { return new Promise((resolve, reject) => { const interval = setInterval(() => { if (locks.length > 0) { const lock = locks.shift(); if (lock) { resolve(lock); clearInterval(interval); clearTimeout(timeout); } } }, 100); const timeout = setTimeout(() => { clearInterval(interval); reject(new Error("获取线程锁超时!")); }, 3 * 60 * 1e3); }); }; const requestThreads = []; for (let index = 0; index < results.length; index++) { requestThreads.push(() => requestThread(index)); } for (let index = 0; index < (this.opts.thread || 1); index++) { locks.push(index + 1); } let requestFinished = 0; const promises = []; for (let index = 0; index < (this.opts.thread || 1); index++) { promises.push(async () => { try { while (requestFinished < results.length && requestThreads.length > 0 && this.isClose === false) { const thread = requestThreads.shift(); if (thread) { const lock = await waitForLock(); await thread(); requestFinished++; locks.push(lock); } } } catch (err) { console.error(err); } }); } await Promise.all(promises.map((f) => f())); }; await Promise.all([resolverThread(), requestThreadHandler()]); this.isRunning = false; return results; } uploadHandler(options) { var _a; const { results, type, callback } = options; if (type !== "nomove") { let finished = 0; for (const result of results) { if ((_a = result.result) == null ? void 0 : _a.finish) { finished++; } } const rate = results.length === 0 ? 0 : finished / results.length * 100; if (type === "force") { return callback(rate, true); } else { return callback(rate, type === "save" ? false : rate >= parseFloat(type.toString())); } } } } const topWindow$1 = getTopWindow(); class JobRunner { constructor(config) { this.config = config; } getConfig() { return this.config; } async playMedia(playFunction) { const tryPlayMedia = () => { return new Promise((resolve, reject) => { try { const playRes = playFunction(); if (playRes) { playRes.then(resolve).catch(reject); } else { resolve(); } } catch (err) { reject(err); } }); }; try { await tryPlayMedia(); return true; } catch (err) { console.error(err); if (String(err).includes(`failed because the user didn't interact with the document first`)) { $modal.alert({ content: "播放音视频失败,由于浏览器的用户隐私保护措施,如果要播放带有音量的视频,或者某些无法自动播放音视频的网站,您必须先点击一次页面上的任意位置脚本才能进行音视频的播放,后续无需重新点击。", onClose: async () => { await tryPlayMedia(); } }); return true; } else if (String(err).includes("The element has no supported sources")) { $console.error("当前视频无法播放。"); } else { $console.error("播放视频时发生未知错误:" + String(err)); } return false; } } fixedVideoProgress() { if (state$3.study.videojs) { const { bar } = domSearch({ bar: ".vjs-control-bar" }, state$3.study.videojs); if (bar) { bar.style.opacity = "1"; } } } async waitForMedia(options) { var _a; const res = await Promise.race([ new Promise((resolve, reject) => { const interval = setInterval(() => { const video = ((options == null ? void 0 : options.root) || document).querySelector( `${(options == null ? void 0 : options.videoSelector) || "video"},${(options == null ? void 0 : options.audioSelector) || "audio"}` ); if (video && (!(options == null ? void 0 : options.filter) || options.filter(video))) { clearInterval(interval); resolve(video); } }, 200); }), $.sleep((_a = options == null ? void 0 : options.timeout) != null ? _a : 3 * 60 * 1e3) ]); if (res) { return res; } else { throw new Error("视频/音频未找到,或者加载超时。"); } } async media(doc) { const config = this.getConfig(); const { playbackRate = 1, volume = 0 } = config.listValues(); const media = await this.waitForMedia({ root: doc }); const { videojs } = domSearch({ videojs: "#video,#audio" }, doc); if (!videojs || !media) { $console.error("视频检测不到,请尝试刷新或者手动切换下一章。"); return; } state$3.study.videojs = videojs; topWindow$1.currentMedia = media; this.fixedVideoProgress(); let setting = config.get("videoQuizStrategy") === "random"; setting = "random"; if (setting === "random") { const loop = async () => { var _a; const submitBtn = () => doc.querySelector("#videoquiz-submit"); if (submitBtn()) { const list = Array.from(doc.querySelectorAll(".ans-videoquiz-opt label")); const answer = list[Math.floor(Math.random() * list.length)]; answer == null ? void 0 : answer.click(); (_a = submitBtn()) == null ? void 0 : _a.click(); await $.sleep(3e3); const container2 = doc.querySelector("#video .ans-videoquiz"); const components = Array.from(doc.querySelectorAll(".x-component-default")); if (container2) { container2.remove(); } if (components.length) { for (const com of components) { com.style.display = "none"; } } } await $.sleep(3e3); await loop(); }; loop(); } return new Promise((resolve, reject) => { const reloadInterval = setInterval(() => { if (["视频文件损坏", "网络错误导致视频下载中途失败"].some((s) => doc.documentElement.innerText.includes(s))) { $console.error("检测到视频加载失败,即将跳过视频。"); $message.error("检测到视频加载失败,即将跳过视频。"); setTimeout(resolve, 3e3); } }, 3e3); const playFunction = async () => { const showFaceWarn = config.get("notifyWhenHasFaceRecognition") == 1; await waitForFaceRecognition(showFaceWarn); await waitForNewFaceRecognition(showFaceWarn); if (media.ended === false) { await $.sleep(1e3); media.play(); media.playbackRate = playbackRate; } }; media.addEventListener("pause", playFunction); media.addEventListener("ended", () => { media.removeEventListener("pause", playFunction); $console.log("视频播放完毕"); clearInterval(reloadInterval); resolve(); }); $console.log("视频开始播放"); media.volume = volume; media.currentTime = 0; setTimeout(() => { this.playMedia(() => media.play()).then(() => { media.playbackRate = playbackRate; }).catch(reject); }, 200); }); } async read(win) { const finishJob = win.finishJob; if (finishJob) finishJob(); await $.sleep(3e3); } removeRedundantWords(str, words) { for (const word of words.map((w) => w.trim())) { str = str.replace(word, ""); } return str; } answerWrapperEmptyWarning(duration) { const setting = lib.h("button", { className: "base-style-button-secondary" }, "通用-全局设置"); if (state$3.study.answererWrapperUnsetMessage === void 0) { state$3.study.answererWrapperUnsetMessage = lib.$message.warn({ content: lib.h("span", {}, ["检测到未设置题库配置,将无法自动答题,请切换到 ", setting, " 页面进行配置。"]), duration }); } } async chapter(frame) { const config = this.getConfig(); let { answererWrappers, period, upload, thread, stopSecondWhenFinish, redundanceWordsText, answerSeparators, answerMatchMode } = config.listValues(); redundanceWordsText = [ "单选题(必考)", "填空题(必考)", "多选题(必考)", "(单选题)", "(多选题)", "(判断题)", "(填空题)", "【单选题】", "【多选题】", "【填空题】", "【判断题】", "【單選题】", "【多選题】", "【判斷题】", "【Single Choice】", "【Multiple Choice】", "【single choice】", "【multiple choice】", "【True or False】" ].join("\n"), answerSeparators = ["===", "#", "---", "###", "|", ";", ";"].join(","), answerMatchMode = "similar"; $message.info({ content: $h("div", ["正在答题中,答题结果请前往:通用-搜索结果 进行查看"]), duration: 10 }); $console.info("开始章节测试"); const frameWindow = frame.contentWindow; const { TiMu } = domSearchAll({ TiMu: ".TiMu" }, frameWindow.document); const worker = new Worker(config, { root: TiMu, elements: { title: ".Zy_TItle .clearfix", options: "ul li .after,ul li textarea,ul textarea,ul li label:not(.before)", type: 'input[id^="answertype"]', lineAnswerInput: ".line_answer input[name^=answer]", lineSelectBox: ".line_answer_ct .selectBox " }, thread: thread != null ? thread : 1, answerMatchMode, answerer: async (elements22, ctx) => { const typeInput = elements22.type[0]; const type = typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0; let title = chapterTestTaskQuestionTitleTransform(elements22.title); if (title) { let ai = new AI(this.getConfig().get("apiTokenId")); if (type == "single" || type == "multiple" || type == "judgement") { let prompt = [ title ]; let judgeMap = {}; elements22.options.forEach((option) => { let prev = option.parentNode.querySelector(".fl.before") || option.parentNode.parentNode.querySelector(".fl.before"); prompt.push((prev == null ? void 0 : prev.innerText) + ". " + option.innerText); judgeMap[prev.innerText] = option.innerText; }); console.log(prompt.join("\n")); let answer = await ai.search(prompt.join("\n"), type); if (type == "judgement") { answer = judgeMap[answer]; } return [{ results: [{ answer, question: title }] }]; } else if (type == "completion") { let prompt = [ title ]; let answer = await ai.search(prompt.join("\n"), type); return [{ results: [{ answer, question: title }] }]; } } else { throw new Error("题目为空,请查看题目是否为空,或者忽略此题"); } }, work: async (ctx) => { var _a; const { elements, searchInfos } = ctx; const typeInput = elements.type[0]; const type = typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0; if (type && (type === "completion" || type === "multiple" || type === "judgement" || type === "single")) { const resolverObj = new defaultQuestionResolver(ctx); const resolver = resolverObj[type]; const handler = (type2, answer, option, ctx2) => { var _a2, _b, _c; if (type2 === "judgement" || type2 === "single" || type2 === "multiple") { let checked = false; if (option && option.parentElement) { checked = ((_b = (_a2 = option.parentElement) == null ? void 0 : _a2.querySelector("label input")) == null ? void 0 : _b.getAttribute("checked")) === "checked"; checked = checked || ((_c = option.parentElement) == null ? void 0 : _c.getAttribute("aria-checked")) == "true"; } if (!checked) { if (option) option.click(); } } else if (type2 === "completion" && answer.trim()) { let text, textareaFrame; if (option && option.parentElement) { text = option.parentElement.querySelector("textarea"); textareaFrame = option.parentElement.querySelector("iframe"); } if (text) { text.value = answer; } if (textareaFrame == null ? void 0 : textareaFrame.contentDocument) { textareaFrame.contentDocument.body.innerHTML = answer; } } }; return await resolver.call( resolverObj, searchInfos, elements.options.map((option) => optimizationElementWithImage(option)), handler ); } else if (type && type === "line") { for (const answers of searchInfos.map((info) => info.results.map((res) => res.answer))) { let ans = answers; if (ans.length === 1) { ans = splitAnswer(ans[0]); } if (ans.filter(Boolean).length !== 0 && elements2.lineAnswerInput) { for (let index = 0; index < elements2.lineSelectBox.length; index++) { const box = elements2.lineSelectBox[index]; if (ans[index]) { (_a = $el(`li[data=${ans[index]}] a`, box)) == null ? void 0 : _a.click(); await $.sleep(200); } } return { finish: true }; } } return { finish: false }; } return { finish: false }; }, async onResultsUpdate(curr, _, res) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; if ((_a = curr.result) == null ? void 0 : _a.finish) ; console.log("得到了答案", curr, res); if (((_b = curr.result) == null ? void 0 : _b.finish) === false && curr.resolved === true) { const options = ((_d = (_c = curr.ctx) == null ? void 0 : _c.elements) == null ? void 0 : _d.options) || []; const typeInput = (_f = (_e = curr.ctx) == null ? void 0 : _e.elements) == null ? void 0 : _f.type[0]; const type = typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0; console.log("选择题部分", options); if (config.get("randomWork-choice") && (type === "judgement" || type === "single" || type === "multiple")) { $console.log("正在随机作答"); const option = options[Math.floor(Math.random() * options.length)]; (_h = (_g = option == null ? void 0 : option.parentElement) == null ? void 0 : _g.querySelector("a,label")) == null ? void 0 : _h.click(); } else if (config.get("randomWork-complete") && type === "completion") { $console.log("正在随机作答"); for (const option of options) { const textarea = (_i = option == null ? void 0 : option.parentElement) == null ? void 0 : _i.querySelector("textarea"); const completeTexts = config.get("randomWork-completeTexts-textarea").split("\n").filter(Boolean); const text = completeTexts[Math.floor(Math.random() * completeTexts.length)]; const textareaFrame = (_j = option == null ? void 0 : option.parentElement) == null ? void 0 : _j.querySelector("iframe"); if (text) { if (textarea) { textarea.value = text; } if (textareaFrame == null ? void 0 : textareaFrame.contentDocument) { textareaFrame.contentDocument.body.innerHTML = text; } } else { $console.error("请设置随机填空的文案"); } await $.sleep(500); } } } }, async onElementSearched(elements22) { const typeInput = elements22.type[0]; const type = typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0; if (type === "judgement") { elements22.options.forEach((option) => { var _a; const opt = ((_a = option == null ? void 0 : option.textContent) == null ? void 0 : _a.trim()) || ""; if (opt.includes("对") || opt.includes("错")) ; else if (opt === "True") { option.textContent = "√"; } else if (opt === "False") { option.textContent = "x"; } else { const ri = option.querySelector(".ri"); const span = document.createElement("span"); span.innerText = ri ? "√" : "×"; option.appendChild(span); } }); } } }); const results = await worker.doWork(); const msg = `答题完成,将等待 ${stopSecondWhenFinish} 秒后进行保存或提交。`; $console.info(msg); $message.info({ content: msg, duration: stopSecondWhenFinish }); await $.sleep(stopSecondWhenFinish * 1e3); await worker.uploadHandler({ type: upload, results, async callback(finishedRate, uploadable) { const msg2 = `完成率 ${finishedRate.toFixed(2)}% : ${uploadable ? "3秒后将自动提交" : "3秒后将自动保存"} `; $console.info(msg2); $message.success({ content: msg2, duration: 3 }); await $.sleep(3e3); if (uploadable) { frameWindow.btnBlueSubmit(); await $.sleep(3e3); frameWindow.submitCheckTimes(); topWindow$1.$("#workpop").hide(); } else { frameWindow.alert = () => { }; frameWindow.noSubmit(); } } }); worker.emit("done"); } async readPPTWithAudio(win) { var _a; win.document.querySelectorAll("audio").forEach((audio) => { audio.addEventListener("play", () => { audio.muted = true; }); }); const len = win.document.querySelectorAll(".swiper-container .swiper-slide").length; for (let index = 0; index < len; index++) { (_a = win.swiperNext) == null ? void 0 : _a.call(win); await $.sleep(1e3); } await $.sleep(3e3); } async hyperlink(a) { const _click = a.onclick; a.onclick = () => false; a.click(); a.onclick = _click; await $.sleep(3e3); } } const topWindow = getTopWindow(); class Project { constructor() { __privateAdd(this, _config, new Config()); __privateAdd(this, _scripts, []); } setConfig(config) { __privateSet(this, _config, config); } setScripts(scripts) { __privateSet(this, _scripts, scripts); } getConfig() { return __privateGet(this, _config); } onConfigChange(field, fn) { _GM_addValueChangeListener(field, (_, pre, curr, remote) => { fn(pre, curr); }); } guid() { return {}; } matchDomain() { return __privateGet(this, _config).get("domains").find((d) => new RegExp(d).test(location.host)); } matchScripts() { const match = __privateGet(this, _scripts).filter((s) => { return s.matches.find((m) => { let r = m[1]; if (!(r instanceof RegExp)) { r = new RegExp(r); } return new RegExp(r).test(location.href); }); }); return match; } matchAndRun() { if (this.matchDomain()) { const scripts = this.matchScripts(); top.console.log(scripts); mappingRecognize(); scripts.forEach((s) => { s.worker && s.worker.apply(this); }); } } onrender({ panel }) { } async oncomplete() { } } _config = new WeakMap(); _scripts = new WeakMap(); class CXProject extends Project { constructor() { super(); const config = new Config(); this.setConfig(config); config.set("domains", [ "localhost:9000", "chaoxing.com", "edu.cn", "org.cn", "xueyinonline.com", "hnsyu.net", "qutjxjy.cn", "ynny.cn", "hnvist.cn", "fjlecb.cn", "gdhkmooc.com", "cugbonline.cn", "zjelib.cn", "cqrspx.cn", "neauce.com", "zhihui-yun.com", "cqie.cn", "ccqmxx.com", "asnc.jxjy.chaoxing.com", "jxjy.hejtxy.edu.cn" ]); config.set("playbackRate", 1, { select: [1, 2, 4, 6, 8, 16, 32, 64].map((i) => [i, `${i}倍`]), name: "播放倍速" }); config.set("volume", 0.5, { range: [0, 1, 0.1], name: "音量" }); config.set("enableMedia", 1, { check: 1, name: "音视频自动播放" }); config.set("enableChapterTest", 1, { check: 1, name: "章节测试自动答题" }); config.set("enablePPT", 1, { check: 1, name: "PPT/书籍自动播放" }); config.set("enableHyperlink", 1, { check: 1, name: "链接任务自动完成" }); config.set("notifyWhenHasFaceRecognition", 1, { check: 1, name: "出现人脸识别时通知我" }); config.set("workWhenNotJob", 1, { check: 1, name: "强制答题" }); config.set("answerMatchMode", 0, { select: [ ["similar", "相似匹配", "答案相似度达到60%以上就匹配"], ["exact", "精确匹配", "答案必须完全一致才匹配"] ], name: "答案匹配模式" }); config.set("restudy", 1, { check: 1, name: "复习模式" }); config.set("studyMode", 0, { select: [ ["next", "完成后跳转下一节"], ["job", "完成后跳转未完成任务点"], ["manually", "完成后暂停,等待手动跳转"] ], name: "跳转模式" }); config.set("upload", "save", { select: [ ["save", "自动保存"], ["nomove", "不保存也不提交"], ["100", "每个题目都查到答案才自动提交"], ["force", "强制自动提交"] ], name: "自动答题完成后的动作" }); config.set("stopSecondWhenFinish", 3, { select: [1, 2, 3, 4, 5].map((i) => [i, `${i}秒`]), name: "自动答题脚本结束后暂停的时间" }); config.set("apiTokenId", "", { fill: 1, "name": "题库 token ID" }); const scripts = []; scripts.push({ name: "🖥️ 课程学习", matches: [ ["任务点页面", "/knowledge/cards"], ["阅读任务点", "/readsvr/book/mooc"] ], worker: this.study }, { name: "✍️ 作业考试脚本", matches: [ ["新版考试页面", "exam-ans/exam/test/reVersionTestStartNew"], ["新版考试页面2", "mooc-ans/exam/test/reVersionTestStartNew"], ["作业页面", "/mooc2/work/dowork"], ["作业页面", "/file-service/pwd"] ], worker: this.workOrExam }, { name: "🖥️ 自动阅读", matches: [ ["阅读页面", "/ztnodedetailcontroller/visitnodedetail"], ["课程目录", /chaoxing.com\/course\/\d+\.html/], ["课程目录", /chaoxing.com\/mooc-ans\/course\/\d+\.html/] ], worker: this.autoRead }, { name: "课程学习调度器", matches: [ ["课程学习页面", "/mycourse/studentstudy"] ], worker: this.studyDispatcher }, { name: "章节页面自动切换脚本", matches: [["课程任务页面", "pageHeader=0"]], worker: this.pageRedirect }); this.setScripts(scripts); } isInFinalTab() { const tabs = Array.from((topWindow == null ? void 0 : topWindow.document.querySelectorAll(".prev_ul li")) || []); if (tabs.length === 0) { return true; } return tabs[tabs.length - 1].classList.contains("active"); } isInFinalChapter() { var _a; return (_a = Array.from((topWindow == null ? void 0 : topWindow.document.querySelectorAll(".posCatalog_select")) || []).pop()) == null ? void 0 : _a.classList.contains("posCatalog_active"); } isFinishedAllChapters() { return this.getChapterInfos().every((chapter) => chapter.unFinishCount === 0); } isCurrentChapterFinished() { const job = topWindow == null ? void 0 : topWindow.document.querySelector(".posCatalog_active"); if (job) { if (job.querySelector(".icon_Completed") !== null) { return true; } } return false; } checkChapterFinishedAndSkip(is_in_last_tab) { var _a; if (this.isCurrentChapterFinished() || is_in_last_tab) { let start2 = false; const jobs = Array.from((topWindow == null ? void 0 : topWindow.document.querySelectorAll(".posCatalog_select:not(.firstLayer)")) || []); for (const job of jobs) { if (job.classList.contains("posCatalog_active")) { start2 = true; continue; } if (start2) { if (job.querySelector(".icon_Completed") !== null) { continue; } if (job.querySelector(".jobUnfinishCount") !== null) { (_a = job.querySelector(".posCatalog_name")) == null ? void 0 : _a.click(); return true; } } } } return false; } searchIFrame(root2) { var _a, _b; let list = Array.from(root2.querySelectorAll("iframe")); const result = []; while (list.length) { const frame = list.shift(); try { if (frame && ((_a = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _a.document)) { result.push(frame); const frames = (_b = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _b.document.querySelectorAll("iframe"); list = list.concat(Array.from(frames || [])); } } catch (e) { console.log(e.message); } } return result; } searchJob(opts, searchedJobs) { const config = this.getConfig(); const jobRunner = new JobRunner(config); const knowCardWin = _unsafeWindow; const searchJobElement = (root2) => { return domSearch( { videojs: "#video,#audio", chapterTest: ".TiMu", read: "#img.imglook", pptWithAudio: ".swiper-container", hyperlink: "#hyperlink" }, root2.contentWindow.document ); }; const search = (root2) => { var _a, _b, _c, _d; const win = root2.contentWindow; const { videojs, read, chapterTest, hyperlink, pptWithAudio } = searchJobElement(root2); if (win && (videojs || read || chapterTest || hyperlink || pptWithAudio)) { const frame_data_str = ((_a = win.frameElement) == null ? void 0 : _a.getAttribute("data")) || ((_d = (_c = (_b = win.frameElement) == null ? void 0 : _b.contentWindow) == null ? void 0 : _c.parent.frameElement) == null ? void 0 : _d.getAttribute("data")) || "{}"; const frame_data = JSON.parse(frame_data_str); const target_jobid = frame_data.jobid || frame_data._jobid; if (!target_jobid) { return; } const attachment = knowCardWin.attachments.find((attachment2) => { const attachment_jobid = attachment2.jobid || attachment2.property._jobid; if (!attachment_jobid) { return false; } return String(attachment_jobid) === String(target_jobid); }); if (attachment && searchedJobs.find((job2) => job2.mid === attachment.property.mid) === void 0) { const { name, title, bookname, author } = attachment.property; const jobName = name || title || (bookname ? bookname + author : void 0) || "未知任务"; const work_type = attachment.job ? "job" : attachment.isPassed ? "finished" : "not-job"; let func; if (videojs) { const config2 = this.getConfig(); if (!config2.get("enableMedia") == "1") { const msg = `音视频自动学习功能已被关闭。${jobName} 即将跳过`; $message.warn({ content: msg, duration: 10 }); $console.warn(msg); } else { if (work_type === "job" || work_type === "finished" && config2.get("restudy") || work_type === "not-job" && opts.forceLearn) { func = () => { const msg = `即将${work_type === "finished" && config2.get("restudy") ? "重新" : work_type === "not-job" && opts.forceLearn ? "强制" : ""}播放 : ` + jobName; $message.info({ content: msg }); $console.log(msg); return jobRunner.media(win.document); }; } } } else if (chapterTest) { if (!config.get("enableChapterTest")) { const msg = `章节测试自动答题功能已被关闭。${jobName} 即将跳过`; $message.warn({ content: msg, duration: 10 }); $console.warn(msg); } else { try { const status = win.document.querySelector(".testTit_status"); if (status == null ? void 0 : status.classList.contains("testTit_status_complete")) { const msg = `章节测试已完成 : ` + jobName; $message.success({ content: msg }); $console.log(msg); } else { if (work_type === "job" || work_type === "not-job" && config.get("workWhenNotJob")) { func = () => { const msg = `开始答题 : ` + jobName; $message.info({ content: msg }); return jobRunner.chapter(root2, {}); }; } if (work_type === "not-job" && config.get("workWhenNotJob") != 1) { const msg = `当前作业 ${jobName} 不是任务点,但待完成,如需开启自动答题请前往:通用-全局设置,开启强制答题。`; $message.warn({ content: msg }); $console.warn(msg); } } } catch (e) { } } } else if (read || pptWithAudio) { if (!config.get("enablePPT")) { const msg = `PPT/书籍阅读功能已被关闭。${jobName} 即将跳过`; $message.warn({ content: msg, duration: 10 }); $console.warn(msg); } else { if (attachment.job) { func = () => { const msg = `正在学习 : ` + jobName; $message.info({ content: msg }); $console.log(msg); if (read) { return jobRunner.read(win); } else { return jobRunner.readPPTWithAudio(win); } }; } } } else if (hyperlink) { if (!config.get("enableHyperlink")) { const msg = `链接任务点已被关闭。${jobName} 即将跳过`; $message.warn({ content: msg, duration: 10 }); $console.warn(msg); } else { if (attachment.job) { func = () => { const msg = `正在完成链接阅读任务 : ` + jobName; $message.info({ content: msg }); $console.log(msg); return jobRunner.hyperlink(hyperlink); }; } } } const job2 = { mid: attachment.property.mid, attachment, func }; searchedJobs.push(job2); return job2; } } }; let job; for (const iframe of this.searchIFrame(knowCardWin.document)) { job = search(iframe); if (job) { return job; } } return job; } async __study(opts) { var _a; await $.sleep(3e3); const searchedJobs = []; let searching = true; const config = this.getConfig(); let attachmentCount = ((_a = _unsafeWindow.attachments) == null ? void 0 : _a.length) || 0; setTimeout(() => { searching = false; }, 10 * 1e3); const runJobs = async () => { const job = this.searchJob(opts, searchedJobs); if (job && job.func) { try { await job.func(); } catch (e) { $console.error("未知错误", e); } await $.sleep(1e3); await runJobs(); } else if (attachmentCount > 0) { attachmentCount--; await $.sleep(1e3); await runJobs(); } else if (searching) { await $.sleep(1e3); await runJobs(); } }; await runJobs(); window.top._preChapterId = ""; const next2 = async () => { if (this.isInFinalTab()) { if (await this.isStuckInBreakingMode()) { return $alert({ content: "检测到此章节重复进入, 为了避免无限重复, 请自行手动完成后手动点击下一章, 或者刷新重试。" }); } } if (this.isInFinalChapter()) { let content = ""; if (config.get("backToFirstWhenFinish")) { content = "已经抵达最后一个章节,10秒后返回第一个章节重新开始。"; setTimeout(() => { var _a2; (_a2 = topWindow == null ? void 0 : window.top.document.querySelector(".posCatalog_name")) == null ? void 0 : _a2.click(); }, 10 * 1e3); $message.info({ content, duration: 30 }); } else { if (this.isFinishedAllChapters()) { content = "全部任务点已完成!"; } else { content = "已经抵达最后一个章节!但仍然有任务点未完成,请手动切换至未完成的章节。"; } $alert({ content }); } return; } if (config.get("studyMode") === "job") { if (await this.checkChapterFinishedAndSkip(this.isInFinalTab()) === false) { const content = "全部任务点已完成!"; $alert({ content }); } } else if (config.get("studyMode") === "next") { const curCourseId = $el$1("#curCourseId", topWindow == null ? void 0 : topWindow.document); const curChapterId = $el$1("#curChapterId", topWindow == null ? void 0 : topWindow.document); const curClazzId = $el$1("#curClazzId", topWindow == null ? void 0 : topWindow.document); const count = $$el("#prev_tab .prev_ul li", topWindow == null ? void 0 : topWindow.document); if (curChapterId && curCourseId && curClazzId) { topWindow._preChapterId = curChapterId.value; topWindow == null ? void 0 : topWindow.PCount.next(count.length.toString(), curChapterId.value, curCourseId.value, curClazzId.value, ""); } else { $console.warn("参数错误,无法跳转下一章,请尝试手动切换。"); } } else { $console.warn("未知的跳转模式,请联系作者反馈"); } }; if (config.get("studyMode") !== "manually") { const msg = "页面任务点已完成,即将跳转。"; $message.success({ content: msg }); $console.info(msg); await $.sleep(5e3); next2(); } else { const msg = "页面任务点已完成,自动跳转已关闭,请手动跳转。"; $message.warn({ content: msg, duration: 0 }); $console.warn(msg); } } async study() { const config = this.getConfig(); if (/\/readsvr\/book\/mooc/.test(location.href)) { $console.log("正在完成书籍/PPT..."); setTimeout(() => { readweb.goto(epage); }, 5e3); return; } if (/\/knowledge\/cards/.test(location.href)) { const updateMediaState = () => { if (topWindow.currentMedia) { topWindow.currentMedia.playbackRate = parseFloat(config.get("playbackRate").toString()); topWindow.currentMedia.volume = config.get("volume"); } }; this.onConfigChange("playbackRate", updateMediaState); this.onConfigChange("volume", updateMediaState); await this.__study(); } } getChapterInfos() { return Array.from((topWindow == null ? void 0 : topWindow.document.querySelectorAll('[onclick^="getTeacherAjax"]')) || []).map((el) => { var _a, _b, _c; return { chapterId: (_b = (_a = el.getAttribute("onclick")) == null ? void 0 : _a.match(/\('(.*)','(.*)','(.*)'\)/)) == null ? void 0 : _b[3], unFinishCount: parseInt(((_c = el.parentElement.querySelector(".jobUnfinishCount")) == null ? void 0 : _c.value) || "0") }; }); } studyDispatcher() { let self = this; waitTask((context) => { const ret = self.getChapterInfos(); if (ret.length) { context.done = true; } return ret; }).then((chapters) => { chapters = chapters.filter((chapter) => chapter.unFinishCount !== 0); if (chapters.length === 0) { $console.log({ content: "页面任务点数量为空! 请刷新重试!" }); } else { const params2 = new URLSearchParams(window.location.href); const courseId = params2.get("courseId"); const classId = params2.get("clazzid"); setTimeout(() => { if (document.querySelectorAll(`.posCatalog_active[id="cur${chapters[0].chapterId}"]`).length === 0) { _unsafeWindow.getTeacherAjax(courseId, classId, chapters[0].chapterId); } }, 1e3); } }); } workOrExam() { let isExam = /\/exam\/preview/.test(location.href); const worker = new Worker(this.getConfig(), { root: ".questionLi", elements: { title: [ (root2) => $el$1("h3", root2) ], options: ".answerBg .answer_p, .textDIV, .eidtDiv", type: isExam ? 'input[name^="type"]' : 'input[id^="answertype"]', lineAnswerInput: ".line_answer input[name^=answer]", lineSelectBox: ".line_answer_ct .selectBox ", reading: ".reading_answer", filling: ".filling_answer", typeName: 'input[name^="typeName"]' }, thread: 1, answerSeparators: [","], answerMatchMode: "", answerer: async (elements22, ctx) => { const typeInput = elements22.type[0]; let type = typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0; console.log(elements22.typeName); type = elements22.typeName[0].value == "多选题" ? "multiple" : "single"; let title = chapterTestTaskQuestionTitleTransform(elements22.title); if (title) { let ai = new AI(this.getConfig().get("apiTokenId")); if (type == "single" || type == "multiple" || type == "judgement") { let prompt = [title]; let judgeMap = {}; elements22.options.forEach((option) => { let choiceMark = option.parentNode.querySelector(".addChoice") || option.parentNode.querySelector(".addMultipleChoice"); if (choiceMark) { let choiceText = option.parentNode.querySelector(".fl.answer_p"); prompt.push((choiceMark == null ? void 0 : choiceMark.innerText) + ". " + (choiceText == null ? void 0 : choiceText.innerText)); judgeMap[choiceMark == null ? void 0 : choiceMark.innerText] = choiceText == null ? void 0 : choiceText.innerText; } else { let prev = option.parentNode.querySelector(".fl.answer_p"); prompt.push((prev == null ? void 0 : prev.innerText) + ". " + (option == null ? void 0 : option.innerText)); judgeMap[prev == null ? void 0 : prev.innerText] = option == null ? void 0 : option.innerText; } }); try { let answer = await ai.search(prompt.join("\n"), type); if (type == "judgement") { answer = judgeMap[answer]; } answer = answer.split("").join(","); return [{ results: [{ answer, question: title }] }]; } catch (e) { alert("搜题失败" + e); } } else if (type == "completion") { let prompt = [title]; let answer = await ai.search(prompt.join("\n"), type); return [{ results: [{ answer, question: title }] }]; } } else { throw new Error("题目为空,请查看题目是否为空,或者忽略此题"); } }, work: async (ctx) => { var _a; const { elements: elements22, searchInfos } = ctx; const typeInput = elements22.type[0]; let type2 = getQuestionType(parseInt(typeInput.value)); type2 = elements22.typeName[0].value == "多选题" ? "multiple" : "single"; if (type2 && (type2 === "completion" || type2 === "multiple" || type2 === "judgement" || type2 === "single")) { const resolver = new defaultQuestionResolver(ctx); const fn = resolver[type2]; return await fn.call( resolver, searchInfos, elements22.options.map((option) => optimizationElementWithImage(option)), async (type3, answer, option) => { var _a2, _b, _c; if (type3 === "judgement" || type3 === "single" || type3 === "multiple") { if ((option == null ? void 0 : option.parentElement) && $$el('[class*="check_answer"]', option.parentElement).length === 0) { option.click(); await $.sleep(500); } } else if (type3 === "completion" && answer.trim()) { const text = option == null ? void 0 : option.querySelector("textarea"); const textareaFrame = option == null ? void 0 : option.querySelector("iframe"); if (text) { text.value = answer; } if (textareaFrame == null ? void 0 : textareaFrame.contentDocument) { textareaFrame.contentDocument.body.innerHTML = answer; } if ((_a2 = option == null ? void 0 : option.parentElement) == null ? void 0 : _a2.parentElement) { (_c = $el$1("[onclick*=saveQuestion]", (_b = option == null ? void 0 : option.parentElement) == null ? void 0 : _b.parentElement)) == null ? void 0 : _c.click(); await $.sleep(500); } } } ); } else if (type2 && type2 === "line") { for (const answers of searchInfos.map((info) => info.results.map((res) => res.answer))) { let ans = answers; if (ans.length === 1) { ans = splitAnswer(ans[0]); } if (ans.filter(Boolean).length !== 0 && elements22.lineAnswerInput) { for (let index = 0; index < elements22.lineSelectBox.length; index++) { const box = elements22.lineSelectBox[index]; if (ans[index]) { (_a = $el$1(`li[data=${ans[index]}] a`, box)) == null ? void 0 : _a.click(); await $.sleep(200); } } return { finish: true }; } } return { finish: false }; } else if (type2 && type2 === "fill") { return readerAndFillHandle(searchInfos, elements22.filling); } else if (type2 && type2 === "reader") { return readerAndFillHandle(searchInfos, elements22.reading); } return { finish: false }; }, onResultsUpdate(current, _, res) { var _a; if ((_a = current.result) == null ? void 0 : _a.finish) ; setTimeout((e) => document.querySelector(".nextDiv a.jb_btn").click(), 3e3); } }); worker.doWork().then(() => { worker.emit("done"); }).catch((err) => { console.error(err); }); return worker; } autoRead() { } pageRedirect() { } guid() { } isInSpecialMode() { return Array.from((topWindow == null ? void 0 : topWindow.document.querySelectorAll(".catalog_points_sa,.catalog_points_er")) || []).length !== 0; } async isStuckInBreakingMode() { if (this.isInSpecialMode()) { const chapter = topWindow == null ? void 0 : topWindow.document.querySelector(".posCatalog_active"); if (chapter) { const id = chapter.getAttribute("id"); if (id) { const counter = await $store.getTab("chapter_counter") || Object.create({}); let count = Reflect.get(counter, id); count = count ? count + 1 : 1; Reflect.set(counter, id, count); let res = false; if (count >= 3) { Reflect.set(counter, id, 1); res = true; } await $store.setTab("chapter_counter", counter); return res; } } } return false; } isInFinalTab() { Array.from((topWindow == null ? void 0 : topWindow.document.querySelectorAll(".prev_ul li")) || []); if (topWindow) { let el = topWindow.document.querySelector(".prev_ul li"); if (el) { return el.classList.contains("active"); } } } isInFinalChapter() { if (topWindow) { let el = topWindow.document.querySelector(".posCatalog_select"); if (el) { return el.classList.contains("posCatalog_active"); } } } isFinishedAllChapters() { return this.getChapterInfos().every((chapter) => chapter.unFinishCount === 0); } } let project = new CXProject(); let isTopWin = window.self === window.top; if (isTopWin) { const app = vue.createApp(_sfc_main); const appWin = app.mount( (() => { const div = document.createElement("div"); div.style.position = "absolute"; div.style.zIndex = "99999"; const root = div.attachShadow({ mode: "closed" }); document.body.append(div); var mc = document.createElement("style"); mc.innerHTML = ` :host { all: initial; display: block; } input{ border:1px solid #555; } .read-the-docs { color: #888; } :host { all: initial; display: block; } *{ font-size:12px; line-height:12px; text-align:left; } #tm-float-window { position: fixed; top: 100px; left: 100px; background-color: #ffffff; border: 1px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.3); z-index: 99999; padding: 0; font-family: Arial, sans-serif; user-select: none; display: flex; flex-direction: column; transition: height 0.2s ease; border-radius:5px; } #tm-float-header { background-color: #007bff; color: white; padding: 8px; cursor: move; user-select: none; display: flex; justify-content: space-between; align-items: center; position: relative; gap: 10px; } .header-main { display: flex; align-items: center; gap: 10px; flex: 1; } .tm-float-header-link { color: white; text-decoration: underline; cursor: pointer; position: relative; white-space: nowrap; } .tm-float-header-link:hover { text-decoration: none; } .dropdown-menu { display: none; position: absolute; background-color: #f9f9f9; border: 1px solid #ddd; box-shadow: 0px 8px 16px rgba(0,0,0,0.2); z-index: 1000; padding: 0; margin: 0; top: 100%; left: 0; min-width: max-content; width: fit-content; } .dropdown-menu a { color: black; padding: 5px 16px; text-decoration: none; display: block; } .dropdown-menu a:hover { background-color: #007bff; color:#fff; } #tm-float-content { flex: 1; padding: 10px; overflow: auto; box-sizing:border-box; } #minimize-btn { cursor: pointer; color: white; font-weight: bold; font-size: 16px; user-select: none; margin-left: 16px; } .form-container { display: grid; grid-template-columns: auto 1fr; gap: 10px; box-sizing:border-box; width:100%; } .form-container .left { justify-self: start; white-space:nowrap; } .form-container .right { justify-self: end; white-space:nowrap; } .form-container input[type=text].right, .form-container input[type=range].right, .form-container select.right { justify-self: end; white-space:nowrap; width:100%; } .form-container input[type=checkbox].right, .form-container input[type=radio].right { justify-self: start; white-space:nowrap; width:auto; } input[type="text"], select { width: 100%; box-sizing: border-box; padding: 2px 2px; border-color:#999; background:#fff; } .form-container .left > * { max-width:100%; display:block; margin-top:10px; } .form-container .right > * { max-width:100%; display:block; margin-top:10px; } .divider { display: flex; align-items: center; text-align: center; padding: 10px 0; text-align: center; grid-column: span 2; } .divider::before, .divider::after { content: ''; flex: 1; border-bottom: 2px solid #ddd; } .divider span { padding: 0 10px; background: #fff; color:#555; } `; root.appendChild(mc); return root; })() ); appWin.bindConfig(project.getConfig()); } project.matchAndRun(); })(Vue);