// ==UserScript==
// @name 木金网课助手|免费题库
// @version 4.17.2
// @description 一键安装,一键使用,内置详细使用教程,支持手机和平板|免费题库|超星学习通|智慧树|知到|智慧职教|雨课堂|中国大学mooc|自动答题|自动刷课|自动答题||支持倍速|后台挂机,本脚本仅供个人研究学习使用,请勿用于非法用途,产生一切法律责任用户自行承担。具体的功能请查看脚本悬浮窗中的教程页面,木金官网 https://wk.bobo91.com。示,支持 【超星学习通】 【知到智慧树】 【职教云】 【智慧职教】 【中国大学MOOC】 等网课的学习,作业。具体的功能请查看脚本悬浮窗中的教程页面。
// @author 木金
// @match *://*.zhihuishu.com/*
// @match *://*.hike-teaching-center.polymas.com/*
// @match *://*.chaoxing.com/*
// @match *://*.xuexitong.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 *://*.jxgmxy.com/*
// @match *://*.jnzyjsxy.cn/*
// @match *://*.sslibrary.com/*
// @match *://*.xuexi365.com/*
// @match *://*.icve.com.cn/*
// @match *://*.ai.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/*
// @match *://*.yuketang.cn/*
// @grant GM_info
// @grant GM_getTab
// @grant GM_saveTab
// @grant GM_setValue
// @grant GM_getValue
// @grant unsafeWindow
// @grant GM_listValues
// @grant GM_deleteValue
// @grant GM_notification
// @grant GM_xmlhttpRequest
// @grant GM_getResourceText
// @grant GM_addValueChangeListener
// @grant GM_removeValueChangeListener
// @run-at document-start
// @namespace https://wk.bobo91.com/
// @homepage https://wk.bobo91.com/
// @source https://wk.bobo91.com/
// @icon https://wk.bobo91.com/logo.png
// @connect enncy.cn
// @connect icodef.com
// @connect dati.bobo91.com
// @connect *
// @connect ocsjs.com
// @connect zaizhexue.top
// @connect localhost
// @connect 127.0.0.1
// @antifeature payment
// @grant GM_addStyle
// @match *://chaoxing.com/*
// @match *://*.smjyxy.cn/*
// @match *://*.gdufemooc.cn/*
// @connect aliyuncs.com
// ==/UserScript==
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
(function(global2, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2.OCS = {}));
})(this, function(exports2) {
"use strict";
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
function isObject$2(value) {
var type = typeof value;
return value != null && (type == "object" || type == "function");
}
var isObject_1 = isObject$2;
var freeGlobal$1 = typeof commonjsGlobal == "object" && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
var _freeGlobal = freeGlobal$1;
var freeGlobal = _freeGlobal;
var freeSelf = typeof self == "object" && self && self.Object === Object && self;
var root$2 = freeGlobal || freeSelf || Function("return this")();
var _root = root$2;
var root$1 = _root;
var now$1 = function() {
return root$1.Date.now();
};
var now_1 = now$1;
var reWhitespace = /\s/;
function trimmedEndIndex$1(string) {
var index = string.length;
while (index-- && reWhitespace.test(string.charAt(index))) {
}
return index;
}
var _trimmedEndIndex = trimmedEndIndex$1;
var trimmedEndIndex = _trimmedEndIndex;
var reTrimStart = /^\s+/;
function baseTrim$1(string) {
return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
}
var _baseTrim = baseTrim$1;
var root = _root;
var Symbol$3 = root.Symbol;
var _Symbol = Symbol$3;
var Symbol$2 = _Symbol;
var objectProto$1 = Object.prototype;
var hasOwnProperty = objectProto$1.hasOwnProperty;
var nativeObjectToString$1 = objectProto$1.toString;
var symToStringTag$1 = Symbol$2 ? Symbol$2.toStringTag : void 0;
function getRawTag$1(value) {
var isOwn = hasOwnProperty.call(value, symToStringTag$1), tag = value[symToStringTag$1];
try {
value[symToStringTag$1] = void 0;
var unmasked = true;
} catch (e) {
}
var result = nativeObjectToString$1.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag$1] = tag;
} else {
delete value[symToStringTag$1];
}
}
return result;
}
var _getRawTag = getRawTag$1;
var objectProto = Object.prototype;
var nativeObjectToString = objectProto.toString;
function objectToString$2(value) {
return nativeObjectToString.call(value);
}
var _objectToString = objectToString$2;
var Symbol$1 = _Symbol, getRawTag = _getRawTag, objectToString$1 = _objectToString;
var nullTag = "[object Null]", undefinedTag = "[object Undefined]";
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : void 0;
function baseGetTag$1(value) {
if (value == null) {
return value === void 0 ? undefinedTag : nullTag;
}
return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString$1(value);
}
var _baseGetTag = baseGetTag$1;
function isObjectLike$1(value) {
return value != null && typeof value == "object";
}
var isObjectLike_1 = isObjectLike$1;
var baseGetTag = _baseGetTag, isObjectLike = isObjectLike_1;
var symbolTag = "[object Symbol]";
function isSymbol$1(value) {
return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag;
}
var isSymbol_1 = isSymbol$1;
var baseTrim = _baseTrim, isObject$1 = isObject_1, isSymbol = isSymbol_1;
var NAN = 0 / 0;
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
var reIsBinary = /^0b[01]+$/i;
var reIsOctal = /^0o[0-7]+$/i;
var freeParseInt = parseInt;
function toNumber$1(value) {
if (typeof value == "number") {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject$1(value)) {
var other = typeof value.valueOf == "function" ? value.valueOf() : value;
value = isObject$1(other) ? other + "" : other;
}
if (typeof value != "string") {
return value === 0 ? value : +value;
}
value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
}
var toNumber_1 = toNumber$1;
var isObject = isObject_1, now = now_1, toNumber = toNumber_1;
var FUNC_ERROR_TEXT = "Expected a function";
var nativeMax = Math.max, nativeMin = Math.min;
function debounce(func, wait, options) {
var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
if (typeof func != "function") {
throw new TypeError(FUNC_ERROR_TEXT);
}
wait = toNumber(wait) || 0;
if (isObject(options)) {
leading = !!options.leading;
maxing = "maxWait" in options;
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
trailing = "trailing" in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs, thisArg = lastThis;
lastArgs = lastThis = void 0;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
lastInvokeTime = time;
timerId = setTimeout(timerExpired, wait);
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall;
return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = void 0;
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = void 0;
return result;
}
function cancel() {
if (timerId !== void 0) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = void 0;
}
function flush() {
return timerId === void 0 ? result : trailingEdge(now());
}
function debounced() {
var time = now(), isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === void 0) {
return leadingEdge(lastCallTime);
}
if (maxing) {
clearTimeout(timerId);
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === void 0) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
var debounce_1$1 = debounce;
const $ = {
uuid() {
return "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === "x" ? r : r & 3 | 8;
return v.toString(16);
});
},
random(min, max) {
return Math.round(Math.random() * (max - min)) + min;
},
async sleep(period) {
return new Promise((resolve) => {
setTimeout(resolve, period);
});
},
isInBrowser() {
return typeof window !== "undefined" && typeof window.document !== "undefined";
},
elementToRawObject(el) {
return {
innerText: el == null ? void 0 : el.innerText,
innerHTML: el == null ? void 0 : el.innerHTML,
textContent: el == null ? void 0 : el.textContent
};
},
onresize(el, handler) {
const resize = debounce_1$1(() => {
if (el.parentNode === null) {
window.removeEventListener("resize", resize);
} else {
handler(el);
}
}, 200);
resize();
window.addEventListener("resize", resize);
},
isInTopWindow() {
return self === top;
},
createCenteredPopupWindow(url, winName, opts) {
const { width, height, scrollbars, resizable } = opts;
const LeftPosition = screen.width ? (screen.width - width) / 2 : 0;
const TopPosition = screen.height ? (screen.height - height) / 2 : 0;
const settings = "height=" + height + ",width=" + width + ",top=" + TopPosition + ",left=" + LeftPosition + ",scrollbars=" + (scrollbars ? "yes" : "no") + ",resizable=" + (resizable ? "yes" : "no");
return window.open(url, winName, settings);
},
transition: async (el, properties, duration_ms, val, options) => {
return new Promise((resolve) => {
const original_val = Reflect.get(el.style, properties) || "";
el.style.transition = `${String(properties)} ${duration_ms}s ${(options == null ? void 0 : options.timing_function) || "ease-in-out"}`;
Reflect.set(el.style, properties, val);
el.addEventListener("transitionend", function handler() {
el.removeEventListener("transitionend", handler);
setTimeout(() => {
Reflect.set(el.style, properties, original_val);
setTimeout(() => {
el.style.transition = "";
}, duration_ms * 1e3);
}, ((options == null ? void 0 : options.reset_ms) || 0) * 1e3);
resolve();
});
});
}
};
const $string = {
humpToTarget(value, target) {
return value.replace(/([A-Z])/g, target + "$1").toLowerCase().split(target).slice(1).join(target);
}
};
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(text2) {
return new StringUtils(text2);
}
toString() {
return this._text;
}
}
const $const = {
TAB_UID: "_uid_",
TAB_URLS: "_urls_",
TAB_CURRENT_PANEL_NAME: "_current_panel_name_"
};
function domSearch(wrapper, root2 = window.document) {
const obj = /* @__PURE__ */ 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 = /* @__PURE__ */ 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).filter(Boolean) : item.map((fun) => fun(root2))
);
});
return obj;
}
var src = {
compareTwoStrings,
findBestMatch
};
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 = /* @__PURE__ */ 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 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 clearString(str, ...exclude) {
exclude.push(...["①②③④⑤⑥⑦⑧⑨"]);
return str.trim().toLocaleLowerCase().replace(RegExp(`[^\\u2E80-\\u9FFFA-Za-z0-9${exclude.join("")}]*`, "g"), "");
}
function normalizeString(str) {
return clearString(
str.replace(/[,。!?;:""''、()【】《》\s]/g, "").replace(/[,.\-!?;:'"()[\]<>]/g, "").replace(/[a-zA-Z0-9]/g, (c) => String.fromCharCode(c.charCodeAt(0) - 65248)).replace(/%/g, "%")
);
}
function answerNormalizedMatch(answers, options) {
const _answers = answers.map(removeRedundant).map(normalizeString);
const _options = options.map(removeRedundant).map(normalizeString);
return _answers.length !== 0 ? _options.map((opt, i) => {
let level = 0;
if (opt) {
for (const ans of _answers) {
if (ans === opt) {
level = 2;
break;
} else if (ans.includes(opt)) {
level = 1;
}
}
}
return { opt, original: options[i], level };
}).filter(({ level }) => level > 0).sort((a, b) => b.level - a.level).map(({ original }) => original) : [];
}
function answerSimilar(answers, options) {
const _answers = answers.map(removeRedundant).map((a) => clearString(a));
const _options = options.map(removeRedundant).map((o) => clearString(o));
const similar = _answers.length !== 0 ? _options.map((option) => {
if (option.trim() === "") {
return { rating: 0, target: "" };
}
return src.findBestMatch(option, _answers).bestMatch;
}) : _options.map(() => ({ rating: 0, target: "" }));
return similar;
}
function answerSimilarWithGap(answers, options) {
var _a, _b;
const _answers = answers.map(removeRedundant).map((a) => clearString(a));
const _options = options.map(removeRedundant).map((o) => clearString(o));
if (_answers.length === 0) {
return _options.map(() => ({ rating: 0, target: "", gap: 0 }));
}
const ratings = _options.map((option) => {
if (option.trim() === "") {
return { rating: 0, target: "" };
}
return src.findBestMatch(option, _answers).bestMatch;
});
const sortedRatings = [...ratings].sort((a, b) => b.rating - a.rating);
const maxRating = (_b = (_a = sortedRatings[0]) == null ? void 0 : _a.rating) != null ? _b : 0;
let secondRating = 0;
for (let i = 1; i < sortedRatings.length; i++) {
if (sortedRatings[i].rating < maxRating) {
secondRating = sortedRatings[i].rating;
break;
}
}
return ratings.map((r) => ({
...r,
gap: r.rating === maxRating ? maxRating - secondRating : 0
}));
}
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 removeRedundant(str) {
return (str == null ? void 0 : str.trim().replace(/^[A-Z]{1}[^A-Za-z0-9⺀-鿿]+([A-Za-z0-9⺀-鿿]+)/, "$1").replace(/^[A-Z]{1}([⺀-鿿][A-Za-z0-9⺀-鿿]*)/, "$1")) || "";
}
function request(url, opts) {
return new Promise((resolve, reject) => {
try {
const { responseType = "json", method = "get", type = "fetch", data = {}, headers = {} } = opts || {};
const env = $.isInBrowser() ? "browser" : "node";
if (type === "GM_xmlhttpRequest" && env === "browser") {
if (typeof GM_xmlhttpRequest !== "undefined") {
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;
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 (opts.anyStatus) {
resolve({ status: response.status, responseText: response.responseText || "" });
return;
}
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);
}
});
} else {
reject(new Error("GM_xmlhttpRequest is not defined"));
}
} else {
const fet = env === "node" ? require("node-fetch").default : fetch;
fet(url, { body: method === "post" ? JSON.stringify(data) : void 0, method, headers }).then((response) => {
if (opts.anyStatus) {
response.text().then((text2) => resolve({ status: response.status, responseText: text2 })).catch(reject);
return;
}
if (responseType === "json") {
response.json().then(resolve).catch(reject);
} else {
response.text().then(resolve).catch(reject);
}
}).catch((error) => {
reject(new Error(error));
});
}
} catch (error) {
reject(error);
}
});
}
var lib = {};
var start$1 = {};
var interfaces = {};
var common$1 = {};
var events = { exports: {} };
var R = typeof Reflect === "object" ? Reflect : null;
var ReflectApply = R && typeof R.apply === "function" ? R.apply : function ReflectApply2(target, receiver, args) {
return Function.prototype.apply.call(target, receiver, args);
};
var ReflectOwnKeys;
if (R && typeof R.ownKeys === "function") {
ReflectOwnKeys = R.ownKeys;
} else if (Object.getOwnPropertySymbols) {
ReflectOwnKeys = function ReflectOwnKeys2(target) {
return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
};
} else {
ReflectOwnKeys = function ReflectOwnKeys2(target) {
return Object.getOwnPropertyNames(target);
};
}
function ProcessEmitWarning(warning) {
if (console && console.warn)
console.warn(warning);
}
var NumberIsNaN = Number.isNaN || function NumberIsNaN2(value) {
return value !== value;
};
function EventEmitter() {
EventEmitter.init.call(this);
}
events.exports = EventEmitter;
events.exports.once = once;
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = void 0;
EventEmitter.prototype._eventsCount = 0;
EventEmitter.prototype._maxListeners = void 0;
var defaultMaxListeners = 10;
function checkListener(listener) {
if (typeof listener !== "function") {
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
}
}
Object.defineProperty(EventEmitter, "defaultMaxListeners", {
enumerable: true,
get: function() {
return defaultMaxListeners;
},
set: function(arg) {
if (typeof arg !== "number" || arg < 0 || NumberIsNaN(arg)) {
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + ".");
}
defaultMaxListeners = arg;
}
});
EventEmitter.init = function() {
if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) {
this._events = /* @__PURE__ */ Object.create(null);
this._eventsCount = 0;
}
this._maxListeners = this._maxListeners || void 0;
};
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
if (typeof n !== "number" || n < 0 || NumberIsNaN(n)) {
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + ".");
}
this._maxListeners = n;
return this;
};
function _getMaxListeners(that) {
if (that._maxListeners === void 0)
return EventEmitter.defaultMaxListeners;
return that._maxListeners;
}
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
return _getMaxListeners(this);
};
EventEmitter.prototype.emit = function emit(type) {
var args = [];
for (var i = 1; i < arguments.length; i++)
args.push(arguments[i]);
var doError = type === "error";
var events2 = this._events;
if (events2 !== void 0)
doError = doError && events2.error === void 0;
else if (!doError)
return false;
if (doError) {
var er;
if (args.length > 0)
er = args[0];
if (er instanceof Error) {
throw er;
}
var err = new Error("Unhandled error." + (er ? " (" + er.message + ")" : ""));
err.context = er;
throw err;
}
var handler = events2[type];
if (handler === void 0)
return false;
if (typeof handler === "function") {
ReflectApply(handler, this, args);
} else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
ReflectApply(listeners[i], this, args);
}
return true;
};
function _addListener(target, type, listener, prepend) {
var m;
var events2;
var existing;
checkListener(listener);
events2 = target._events;
if (events2 === void 0) {
events2 = target._events = /* @__PURE__ */ Object.create(null);
target._eventsCount = 0;
} else {
if (events2.newListener !== void 0) {
target.emit(
"newListener",
type,
listener.listener ? listener.listener : listener
);
events2 = target._events;
}
existing = events2[type];
}
if (existing === void 0) {
existing = events2[type] = listener;
++target._eventsCount;
} else {
if (typeof existing === "function") {
existing = events2[type] = prepend ? [listener, existing] : [existing, listener];
} else if (prepend) {
existing.unshift(listener);
} else {
existing.push(listener);
}
m = _getMaxListeners(target);
if (m > 0 && existing.length > m && !existing.warned) {
existing.warned = true;
var w = new Error("Possible EventEmitter memory leak detected. " + existing.length + " " + String(type) + " listeners added. Use emitter.setMaxListeners() to increase limit");
w.name = "MaxListenersExceededWarning";
w.emitter = target;
w.type = type;
w.count = existing.length;
ProcessEmitWarning(w);
}
}
return target;
}
EventEmitter.prototype.addListener = function addListener(type, listener) {
return _addListener(this, type, listener, false);
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.prependListener = function prependListener(type, listener) {
return _addListener(this, type, listener, true);
};
function onceWrapper() {
if (!this.fired) {
this.target.removeListener(this.type, this.wrapFn);
this.fired = true;
if (arguments.length === 0)
return this.listener.call(this.target);
return this.listener.apply(this.target, arguments);
}
}
function _onceWrap(target, type, listener) {
var state2 = { fired: false, wrapFn: void 0, target, type, listener };
var wrapped = onceWrapper.bind(state2);
wrapped.listener = listener;
state2.wrapFn = wrapped;
return wrapped;
}
EventEmitter.prototype.once = function once2(type, listener) {
checkListener(listener);
this.on(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) {
checkListener(listener);
this.prependListener(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.removeListener = function removeListener(type, listener) {
var list, events2, position, i, originalListener;
checkListener(listener);
events2 = this._events;
if (events2 === void 0)
return this;
list = events2[type];
if (list === void 0)
return this;
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0)
this._events = /* @__PURE__ */ Object.create(null);
else {
delete events2[type];
if (events2.removeListener)
this.emit("removeListener", type, list.listener || listener);
}
} else if (typeof list !== "function") {
position = -1;
for (i = list.length - 1; i >= 0; i--) {
if (list[i] === listener || list[i].listener === listener) {
originalListener = list[i].listener;
position = i;
break;
}
}
if (position < 0)
return this;
if (position === 0)
list.shift();
else {
spliceOne(list, position);
}
if (list.length === 1)
events2[type] = list[0];
if (events2.removeListener !== void 0)
this.emit("removeListener", type, originalListener || listener);
}
return this;
};
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) {
var listeners, events2, i;
events2 = this._events;
if (events2 === void 0)
return this;
if (events2.removeListener === void 0) {
if (arguments.length === 0) {
this._events = /* @__PURE__ */ Object.create(null);
this._eventsCount = 0;
} else if (events2[type] !== void 0) {
if (--this._eventsCount === 0)
this._events = /* @__PURE__ */ Object.create(null);
else
delete events2[type];
}
return this;
}
if (arguments.length === 0) {
var keys = Object.keys(events2);
var key;
for (i = 0; i < keys.length; ++i) {
key = keys[i];
if (key === "removeListener")
continue;
this.removeAllListeners(key);
}
this.removeAllListeners("removeListener");
this._events = /* @__PURE__ */ Object.create(null);
this._eventsCount = 0;
return this;
}
listeners = events2[type];
if (typeof listeners === "function") {
this.removeListener(type, listeners);
} else if (listeners !== void 0) {
for (i = listeners.length - 1; i >= 0; i--) {
this.removeListener(type, listeners[i]);
}
}
return this;
};
function _listeners(target, type, unwrap) {
var events2 = target._events;
if (events2 === void 0)
return [];
var evlistener = events2[type];
if (evlistener === void 0)
return [];
if (typeof evlistener === "function")
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}
EventEmitter.prototype.listeners = function listeners(type) {
return _listeners(this, type, true);
};
EventEmitter.prototype.rawListeners = function rawListeners(type) {
return _listeners(this, type, false);
};
EventEmitter.listenerCount = function(emitter, type) {
if (typeof emitter.listenerCount === "function") {
return emitter.listenerCount(type);
} else {
return listenerCount.call(emitter, type);
}
};
EventEmitter.prototype.listenerCount = listenerCount;
function listenerCount(type) {
var events2 = this._events;
if (events2 !== void 0) {
var evlistener = events2[type];
if (typeof evlistener === "function") {
return 1;
} else if (evlistener !== void 0) {
return evlistener.length;
}
}
return 0;
}
EventEmitter.prototype.eventNames = function eventNames() {
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};
function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = 0; i < n; ++i)
copy[i] = arr[i];
return copy;
}
function spliceOne(list, index) {
for (; index + 1 < list.length; index++)
list[index] = list[index + 1];
list.pop();
}
function unwrapListeners(arr) {
var ret = new Array(arr.length);
for (var i = 0; i < ret.length; ++i) {
ret[i] = arr[i].listener || arr[i];
}
return ret;
}
function once(emitter, name) {
return new Promise(function(resolve, reject) {
function errorListener(err) {
emitter.removeListener(name, resolver);
reject(err);
}
function resolver() {
if (typeof emitter.removeListener === "function") {
emitter.removeListener("error", errorListener);
}
resolve([].slice.call(arguments));
}
eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
if (name !== "error") {
addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
}
});
}
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
if (typeof emitter.on === "function") {
eventTargetAgnosticAddListener(emitter, "error", handler, flags);
}
}
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
if (typeof emitter.on === "function") {
if (flags.once) {
emitter.once(name, listener);
} else {
emitter.on(name, listener);
}
} else if (typeof emitter.addEventListener === "function") {
emitter.addEventListener(name, function wrapListener(arg) {
if (flags.once) {
emitter.removeEventListener(name, wrapListener);
}
listener(arg);
});
} else {
throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
}
}
var __importDefault$2 = commonjsGlobal && commonjsGlobal.__importDefault || function(mod) {
return mod && mod.__esModule ? mod : { "default": mod };
};
Object.defineProperty(common$1, "__esModule", { value: true });
common$1.CommonEventEmitter = void 0;
const events_1$1 = __importDefault$2(events.exports);
class CommonEventEmitter extends events_1$1.default {
on(eventName, listener) {
return super.on(eventName.toString(), listener);
}
once(eventName, listener) {
return super.once(eventName.toString(), listener);
}
emit(eventName, ...args) {
return super.emit(eventName.toString(), ...args);
}
off(eventName, listener) {
return super.off(eventName.toString(), listener);
}
}
common$1.CommonEventEmitter = CommonEventEmitter;
var config$1 = {};
Object.defineProperty(config$1, "__esModule", { value: true });
var cors = {};
var utils = {};
var common = {};
var store = {};
var store_provider = {};
var _const = {};
Object.defineProperty(_const, "__esModule", { value: true });
_const.$const = void 0;
_const.$const = {
TAB_UID: "_uid_",
TAB_URLS: "_urls_",
TAB_CURRENT_PANEL_NAME: "_current_panel_name_"
};
var __awaiter$3 = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(store_provider, "__esModule", { value: true });
store_provider.GMStoreProvider = store_provider.MemoryStoreProvider = store_provider.LocalStoreChangeEvent = void 0;
const const_1$1 = _const;
class LocalStoreChangeEvent extends Event {
constructor() {
super(...arguments);
this.key = "";
}
}
store_provider.LocalStoreChangeEvent = LocalStoreChangeEvent;
class MemoryStoreProvider {
get(key, defaultValue) {
var _a;
return (_a = Reflect.get(MemoryStoreProvider._source.store, key)) !== null && _a !== void 0 ? _a : defaultValue;
}
set(key, value) {
var _a;
const pre = Reflect.get(MemoryStoreProvider._source.store, key);
Reflect.set(MemoryStoreProvider._source.store, key, value);
(_a = MemoryStoreProvider.storeListeners.get(key)) === null || _a === void 0 ? void 0 : _a.forEach((lis) => lis(value, pre));
}
delete(key) {
Reflect.deleteProperty(MemoryStoreProvider._source.store, key);
}
list() {
return Object.keys(MemoryStoreProvider._source.store);
}
getTab(key) {
return __awaiter$3(this, void 0, void 0, function* () {
return Reflect.get(MemoryStoreProvider._source.tab, key);
});
}
setTab(key, value) {
var _a;
return __awaiter$3(this, void 0, void 0, function* () {
Reflect.set(MemoryStoreProvider._source.tab, key, value);
(_a = MemoryStoreProvider.tabListeners.get(key)) === null || _a === void 0 ? void 0 : _a.forEach((lis) => lis(value, this.getTab(key)));
});
}
addChangeListener(key, listener) {
const listeners = MemoryStoreProvider.storeListeners.get(key) || [];
listeners.push(listener);
MemoryStoreProvider.storeListeners.set(key, listeners);
}
removeChangeListener(listener) {
MemoryStoreProvider.tabListeners.forEach((lis, key) => {
const index = lis.findIndex((l) => l === listener);
if (index !== -1) {
lis.splice(index, 1);
MemoryStoreProvider.tabListeners.set(key, lis);
}
});
}
addTabChangeListener(key, listener) {
const listeners = MemoryStoreProvider.tabListeners.get(key) || [];
listeners.push(listener);
MemoryStoreProvider.tabListeners.set(key, listeners);
}
removeTabChangeListener(key, listener) {
const listeners = MemoryStoreProvider.tabListeners.get(key) || [];
const index = listeners.findIndex((l) => l === listener);
if (index !== -1) {
listeners.splice(index, 1);
MemoryStoreProvider.tabListeners.set(key, listeners);
}
}
}
MemoryStoreProvider._source = { store: {}, tab: {} };
MemoryStoreProvider.storeListeners = /* @__PURE__ */ new Map();
MemoryStoreProvider.tabListeners = /* @__PURE__ */ new Map();
store_provider.MemoryStoreProvider = MemoryStoreProvider;
class GMStoreProvider {
constructor() {
if (self === top && typeof globalThis.GM_listValues !== "undefined") {
for (const val of GM_listValues()) {
if (val.startsWith("_tab_change_")) {
GM_deleteValue(val);
}
}
}
}
getTabChangeHandleKey(tabUid, key) {
return `_tab_change_${tabUid}_${key}`;
}
get(key, defaultValue) {
return GM_getValue(key, defaultValue);
}
set(key, value) {
GM_setValue(key, value);
}
delete(key) {
GM_deleteValue(key);
}
list() {
return GM_listValues();
}
getTab(key) {
return new Promise((resolve, reject) => {
GM_getTab((tab = {}) => resolve(Reflect.get(tab, key)));
});
}
setTab(key, value) {
return new Promise((resolve, reject) => {
GM_getTab((tab = {}) => {
Reflect.set(tab, key, value);
GM_saveTab(tab);
this.set(this.getTabChangeHandleKey(Reflect.get(tab, const_1$1.$const.TAB_UID), key), value);
resolve();
});
});
}
addChangeListener(key, listener) {
return GM_addValueChangeListener(key, (_, pre, curr, remote) => {
listener(curr, pre, remote);
});
}
removeChangeListener(listenerId) {
if (typeof listenerId === "number") {
GM_removeValueChangeListener(listenerId);
}
}
addTabChangeListener(key, listener) {
return __awaiter$3(this, void 0, void 0, function* () {
const uid = yield this.getTab(const_1$1.$const.TAB_UID);
return GM_addValueChangeListener(this.getTabChangeHandleKey(uid, key), (_, pre, curr) => {
listener(curr, pre);
});
});
}
removeTabChangeListener(key, listener) {
return this.removeChangeListener(listener);
}
}
store_provider.GMStoreProvider = GMStoreProvider;
(function(exports3) {
Object.defineProperty(exports3, "__esModule", { value: true });
exports3.$store = exports3.MemoryStoreProvider = exports3.GMStoreProvider = void 0;
const store_provider_1 = store_provider;
var store_provider_2 = store_provider;
Object.defineProperty(exports3, "GMStoreProvider", { enumerable: true, get: function() {
return store_provider_2.GMStoreProvider;
} });
Object.defineProperty(exports3, "MemoryStoreProvider", { enumerable: true, get: function() {
return store_provider_2.MemoryStoreProvider;
} });
exports3.$store = typeof globalThis.unsafeWindow === "undefined" ? new store_provider_1.MemoryStoreProvider() : new store_provider_1.GMStoreProvider();
})(store);
(function(exports3) {
var __awaiter2 = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest2 = commonjsGlobal && commonjsGlobal.__rest || function(s, e) {
var t2 = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t2[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t2[p[i]] = s[p[i]];
}
return t2;
};
var __importDefault2 = commonjsGlobal && commonjsGlobal.__importDefault || function(mod) {
return mod && mod.__esModule ? mod : { "default": mod };
};
Object.defineProperty(exports3, "__esModule", { value: true });
exports3.resolveCustomElementName = exports3.$ = void 0;
const debounce_12 = __importDefault2(debounce_1$1);
const store_12 = store;
exports3.$ = {
createConfigProxy(script2) {
var _a, _b;
const proxy = new Proxy(script2.cfg, {
set(target, propertyKey, value) {
const key = exports3.$.namespaceKey(script2.namespace, propertyKey);
store_12.$store.set(key, value);
return Reflect.set(target, propertyKey, value);
},
get(target, propertyKey) {
const value = store_12.$store.get(exports3.$.namespaceKey(script2.namespace, propertyKey));
Reflect.set(target, propertyKey, value);
return value;
}
});
for (const key in script2.configs) {
if (Object.prototype.hasOwnProperty.call(script2.configs, key)) {
const element = Reflect.get(script2.configs, key);
Reflect.set(proxy, key, store_12.$store.get(exports3.$.namespaceKey(script2.namespace, key), element.defaultValue));
}
}
if (script2.namespace) {
proxy.notes = (_b = (_a = script2.configs) === null || _a === void 0 ? void 0 : _a.notes) === null || _b === void 0 ? void 0 : _b.defaultValue;
}
return proxy;
},
getAllRawConfigs(scripts) {
const object = {};
for (const script2 of scripts) {
for (const key in script2.configs) {
if (Object.prototype.hasOwnProperty.call(script2.configs, key)) {
const _a = script2.configs[key], element = __rest2(_a, ["label"]);
Reflect.set(object, exports3.$.namespaceKey(script2.namespace, key), Object.assign({ label: exports3.$.namespaceKey(script2.namespace, key) }, element));
}
}
}
return object;
},
getMatchedScripts(projects, urls) {
const scripts = [];
for (const project2 of projects) {
for (const key in project2.scripts) {
if (Object.prototype.hasOwnProperty.call(project2.scripts, key)) {
const script2 = project2.scripts[key];
const script_matches_urls = script2.matches.map((u) => Array.isArray(u) ? u[1] : u);
const script_excludes_urls = (script2.excludes || []).map((u) => Array.isArray(u) ? u[1] : u);
if (project2.domains === void 0 || project2.domains.length === 0 || project2.domains.some((d) => urls.some((url) => new URL(url).origin.includes(d)))) {
if (script_excludes_urls.some((u) => urls.some((url) => RegExp(u).test(url)))) {
continue;
}
if (script_matches_urls.some((u) => urls.some((url) => RegExp(u).test(url)))) {
scripts.push(script2);
}
}
}
}
}
return scripts;
},
namespaceKey(namespace, key) {
return namespace ? namespace + "." + key.toString() : key.toString();
},
uuid() {
return "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === "x" ? r : r & 3 | 8;
return v.toString(16);
});
},
random(min, max) {
return Math.round(Math.random() * (max - min)) + min;
},
sleep(period) {
return __awaiter2(this, void 0, void 0, function* () {
return new Promise((resolve) => {
setTimeout(resolve, period);
});
});
},
isInBrowser() {
return typeof window !== "undefined" && typeof window.document !== "undefined";
},
onresize(el, handler) {
const resize = (0, debounce_12.default)(() => {
if (el.parentNode === null) {
window.removeEventListener("resize", resize);
} else {
handler(el);
}
}, 200);
resize();
window.addEventListener("resize", resize);
},
loadCustomElements(elements2) {
for (const element of elements2) {
const name = resolveCustomElementName(element, "-");
if (customElements.get(name) === void 0) {
customElements.define(name, element);
}
}
},
isInTopWindow() {
return self === top;
},
createCenteredPopupWindow(url, winName, opts) {
const { width, height, scrollbars, resizable } = opts;
const LeftPosition = screen.width ? (screen.width - width) / 2 : 0;
const TopPosition = screen.height ? (screen.height - height) / 2 : 0;
const settings = "height=" + height + ",width=" + width + ",top=" + TopPosition + ",left=" + LeftPosition + ",scrollbars=" + (scrollbars ? "yes" : "no") + ",resizable=" + (resizable ? "yes" : "no");
return window.open(url, winName, settings);
},
waitForElement(selector, opts) {
return this.waitFor(() => {
return typeof selector === "function" ? selector() : document.querySelector(selector);
}, opts);
},
waitFor(predicate, opts) {
return new Promise((resolve, reject) => {
let timeout;
const interval = setInterval(() => {
const result = predicate();
if (result) {
clearInterval(interval);
timeout && clearTimeout(timeout);
resolve(result);
}
}, (opts === null || opts === void 0 ? void 0 : opts.check_period_ms) || 1e3);
if (opts === null || opts === void 0 ? void 0 : opts.timeout_seconds) {
timeout = setTimeout(() => {
clearInterval(interval);
resolve(void 0);
}, ((opts === null || opts === void 0 ? void 0 : opts.timeout_seconds) || 10) * 1e3);
}
});
}
};
function resolveCustomElementName(el, target) {
return el.name.replace(/([A-Z])/g, target + "$1").toLowerCase().split(target).slice(1).join(target);
}
exports3.resolveCustomElementName = resolveCustomElementName;
})(common);
var ui = {};
var dom = {};
Object.defineProperty(dom, "__esModule", { value: true });
dom.enableElementTouchDraggable = dom.enableElementDraggable = dom.$$el = dom.$el = dom.h = void 0;
const common_1$5 = common;
function h(element, attrsOrChildren, childrenOrHandler) {
let name = "";
if (typeof element === "function") {
name = (0, common_1$5.resolveCustomElementName)(element, "-");
} else {
name = element;
}
const el = document.createElement(name);
if (attrsOrChildren) {
if (Array.isArray(attrsOrChildren)) {
for (const child of attrsOrChildren) {
if (typeof child === "function") {
el.append(document.createElement(child.name));
} else {
el.append(child);
}
}
} else if (typeof attrsOrChildren === "string") {
el.append(attrsOrChildren);
} else {
const attrs = attrsOrChildren;
for (const key in attrs) {
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
if (key === "style") {
Object.assign(el.style, attrs[key]);
} else {
const value = attrs[key];
Reflect.set(el, key, value);
}
}
}
}
}
if (childrenOrHandler) {
if (typeof childrenOrHandler === "function") {
childrenOrHandler.call(el, el);
} else if (Array.isArray(childrenOrHandler)) {
for (const child of childrenOrHandler) {
if (typeof child === "function") {
el.append(document.createElement(child.name));
} else {
el.append(child);
}
}
} else if (typeof childrenOrHandler === "string") {
el.append(childrenOrHandler);
}
}
return el;
}
dom.h = h;
function $el(selector, root2 = window.document) {
const el = root2.querySelector(selector);
return el === null ? void 0 : el;
}
dom.$el = $el;
function $$el(selector, root2 = window.document) {
return Array.from(root2.querySelectorAll(selector));
}
dom.$$el = $$el;
function enableElementDraggable(header2, target, ondrag) {
let pos1 = 0;
let pos2 = 0;
let pos3 = 0;
let pos4 = 0;
header2.addEventListener("mousedown", dragMouseDown);
function dragMouseDown(e) {
e = e || window.event;
pos3 = e.clientX;
pos4 = e.clientY;
document.addEventListener("mouseup", closeDragElement);
document.addEventListener("mousemove", elementDrag);
}
function elementDrag(e) {
e.stopPropagation();
e = e || window.event;
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
target.style.top = Math.max(target.offsetTop - pos2, 10) + "px";
target.style.left = target.offsetLeft - pos1 + "px";
}
function closeDragElement() {
ondrag === null || ondrag === void 0 ? void 0 : ondrag();
document.removeEventListener("mouseup", closeDragElement);
document.removeEventListener("mousemove", elementDrag);
}
}
dom.enableElementDraggable = enableElementDraggable;
function enableElementTouchDraggable(header2, target, ondrag) {
let pos1 = 0;
let pos2 = 0;
let pos3 = 0;
let pos4 = 0;
header2.addEventListener("touchstart", dragTouchStart);
function dragTouchStart(e) {
e = e || window.event;
const touch = e.touches[0];
pos3 = touch.clientX;
pos4 = touch.clientY;
document.addEventListener("touchend", closeDragElement);
document.addEventListener("touchcancel", closeDragElement);
document.addEventListener("touchmove", elementDrag, { capture: true, passive: false });
}
function elementDrag(e) {
e.stopPropagation();
e.preventDefault();
e = e || window.event;
const touch = e.touches[0];
pos1 = pos3 - touch.clientX;
pos2 = pos4 - touch.clientY;
pos3 = touch.clientX;
pos4 = touch.clientY;
target.style.top = Math.max(target.offsetTop - pos2, 10) + "px";
target.style.left = target.offsetLeft - pos1 + "px";
}
function closeDragElement() {
ondrag === null || ondrag === void 0 ? void 0 : ondrag();
document.removeEventListener("touchend", closeDragElement);
document.removeEventListener("touchcancel", closeDragElement);
document.removeEventListener("touchmove", elementDrag, { capture: true });
}
}
dom.enableElementTouchDraggable = enableElementTouchDraggable;
var elements$1 = {};
Object.defineProperty(elements$1, "__esModule", { value: true });
elements$1.$elements = void 0;
elements$1.$elements = {
tooltipContainer: void 0,
root: void 0,
currentScriptPanel: void 0,
wrapper: void 0
};
var tampermonkey = {};
(function(exports3) {
Object.defineProperty(exports3, "__esModule", { value: true });
exports3.$gm = void 0;
exports3.$gm = {
unsafeWindow: typeof globalThis.unsafeWindow === "undefined" ? globalThis.window : globalThis.unsafeWindow,
isInGMContext() {
return typeof GM_info !== "undefined";
},
getInfos() {
return typeof GM_info === "undefined" ? void 0 : GM_info;
},
getTab(callback) {
return typeof GM_getTab === "undefined" ? void 0 : GM_getTab(callback);
},
notification(content, options) {
var _a;
const { onclick, ondone, important, duration = 30, silent = true, extraTitle = "" } = options || {};
const { icon, name } = ((_a = exports3.$gm.getInfos()) === null || _a === void 0 ? void 0 : _a.script) || {};
GM_notification({
title: name + (extraTitle ? "-" + extraTitle : ""),
text: content,
image: icon || "",
highlight: important,
onclick,
ondone,
silent,
timeout: duration * 1e3
});
},
getMetadataFromScriptHead(key) {
var _a, _b;
const metadataString = (_a = this.getInfos()) === null || _a === void 0 ? void 0 : _a.scriptMetaStr;
if (!metadataString) {
return [];
} else {
const metadata = ((_b = metadataString.match(/\/\/\s+==UserScript==([\s\S]+)\/\/\s+==\/UserScript==/)) === null || _b === void 0 ? void 0 : _b[1]) || "";
const metadataList = (metadata.match(/\/\/\s+@(.+?)\s+(.*?)(?:\n|$)/g) || []).map((line) => {
const words = line.match(/[\S]+/g) || [];
return {
key: (words[1] || "").replace("@", ""),
value: words.slice(2).join(" ")
};
});
return metadataList.filter((l) => l.key === key).map((l) => l.value);
}
}
};
})(tampermonkey);
Object.defineProperty(ui, "__esModule", { value: true });
ui.$ui = void 0;
const common_1$4 = common;
const dom_1$6 = dom;
const elements_1$2 = elements$1;
const tampermonkey_1$1 = tampermonkey;
function getPageZoom() {
const zoom = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("zoom") || "1");
return Number.isFinite(zoom) && zoom > 0 ? zoom : 1;
}
ui.$ui = {
tooltip(target, position) {
target.setAttribute("data-title", target.title);
if (tampermonkey_1$1.$gm.isInGMContext()) {
target.removeAttribute("title");
}
const container2 = () => elements_1$2.$elements.tooltipContainer;
const isVisible = () => {
var _a;
return (_a = container2()) === null || _a === void 0 ? void 0 : _a.classList.contains("show");
};
let showTimer;
let autoHideTimer;
let lastTouchTime = 0;
const computePlacement = () => {
const el = container2();
if (!el) {
return;
}
const zoom = getPageZoom();
const margin = 8;
const rect = target.getBoundingClientRect();
const tipRect = el.getBoundingClientRect();
const vw = document.documentElement.clientWidth;
const vh = document.documentElement.clientHeight;
let placement = (position === null || position === void 0 ? void 0 : position.startsWith("top")) ? "top" : "bottom";
const fits = placement === "bottom" ? rect.bottom + margin + tipRect.height <= vh - margin : rect.top - margin - tipRect.height >= margin;
if (!fits) {
placement = placement === "bottom" ? "top" : "bottom";
}
const top2 = placement === "bottom" ? rect.bottom + margin : rect.top - margin - tipRect.height;
const align = (position === null || position === void 0 ? void 0 : position.endsWith("left")) ? "left" : (position === null || position === void 0 ? void 0 : position.endsWith("right")) ? "right" : "center";
let left;
if (align === "left") {
left = rect.left;
} else if (align === "right") {
left = rect.right - tipRect.width;
} else {
left = rect.left + rect.width / 2 - tipRect.width / 2;
}
left = Math.max(margin, Math.min(left, vw - margin - tipRect.width));
const arrowLeft = Math.max(6, Math.min(rect.left + rect.width / 2 - left - 4, tipRect.width - 14));
el.classList.remove("tooltip-top", "tooltip-bottom");
el.classList.add(placement === "bottom" ? "tooltip-bottom" : "tooltip-top");
el.style.setProperty("--tooltip-arrow-left", arrowLeft + "px");
el.style.top = top2 / zoom + "px";
el.style.left = left / zoom + "px";
};
const onScrollOrResize = () => {
if (!target.isConnected) {
hide();
return;
}
computePlacement();
};
const onDocumentMouseOver = (e) => {
if (!target.contains(e.target)) {
hide();
}
};
const onDocumentTouchStart = (e) => {
const el = container2();
const path = e.composedPath();
if (!path.includes(target) && !(el && path.includes(el))) {
hide();
}
};
const bindWhileVisible = () => {
window.addEventListener("scroll", onScrollOrResize, true);
window.addEventListener("resize", onScrollOrResize);
document.addEventListener("mouseover", onDocumentMouseOver, true);
document.addEventListener("touchstart", onDocumentTouchStart, true);
};
const unbindWhileVisible = () => {
window.removeEventListener("scroll", onScrollOrResize, true);
window.removeEventListener("resize", onScrollOrResize);
document.removeEventListener("mouseover", onDocumentMouseOver, true);
document.removeEventListener("touchstart", onDocumentTouchStart, true);
};
const show = () => {
const el = container2();
const dataTitle = target.getAttribute("data-title");
if (!el || !dataTitle) {
hide();
return;
}
el.innerHTML = dataTitle.split("\n").join(" ${text2}
") || "";
el.__owner = target;
computePlacement();
void el.offsetWidth;
el.classList.add("show");
bindWhileVisible();
};
function hide(owner) {
const el = container2();
if (!el) {
return;
}
if (owner && el.__owner !== owner) {
return;
}
el.classList.remove("show");
el.__owner = void 0;
clearTimeout(autoHideTimer);
unbindWhileVisible();
}
target.addEventListener("mouseenter", () => {
if (Date.now() - lastTouchTime < 500) {
return;
}
clearTimeout(showTimer);
showTimer = setTimeout(show, 100);
});
target.addEventListener("mouseleave", () => {
clearTimeout(showTimer);
hide(target);
});
target.addEventListener("click", show);
target.addEventListener("blur", () => hide(target));
target.addEventListener("touchstart", () => {
var _a;
lastTouchTime = Date.now();
clearTimeout(autoHideTimer);
if (isVisible() && ((_a = container2()) === null || _a === void 0 ? void 0 : _a.__owner) === target) {
hide(target);
} else {
show();
autoHideTimer = setTimeout(() => hide(target), 3e3);
}
});
return target;
},
scriptPanel(script2, store2, opts) {
var _a, _b, _c, _d;
const scriptPanel = (0, dom_1$6.h)("script-panel-element", { name: script2.name });
const notesExpandedKey = `_notes_expanded_${script2.fullName()}`;
scriptPanel.setNotesExpanded(store2.get(notesExpandedKey, true));
scriptPanel.notesHeader.addEventListener("click", () => {
const expanded = !scriptPanel.isNotesExpanded();
scriptPanel.setNotesExpanded(expanded);
store2.set(notesExpandedKey, expanded);
});
scriptPanel.notesHeader.title = "点击收缩 / 展开";
this.tooltip(scriptPanel.notesHeader);
const updateNotesVisibility = (content) => {
scriptPanel.notesContainer.style.display = (content === null || content === void 0 ? void 0 : content.trim()) ? "" : "none";
};
script2.onConfigChange("notes", (pre, curr) => {
scriptPanel.notesBody.innerHTML = script2.cfg.notes || "";
updateNotesVisibility(script2.cfg.notes);
});
script2.panel = scriptPanel;
scriptPanel.notesBody.innerHTML = ((_b = (_a = script2.configs) === null || _a === void 0 ? void 0 : _a.notes) === null || _b === void 0 ? void 0 : _b.defaultValue) || "";
updateNotesVisibility((_d = (_c = script2.configs) === null || _c === void 0 ? void 0 : _c.notes) === null || _d === void 0 ? void 0 : _d.defaultValue);
let configs = /* @__PURE__ */ Object.create({});
const elList = [];
for (const key in script2.configs) {
if (Object.prototype.hasOwnProperty.call(script2.configs, key)) {
const cfg = script2.configs[key];
if (cfg.separator) {
elList.push(this.configsArea(this.configs(script2.namespace, store2, configs || {}, opts === null || opts === void 0 ? void 0 : opts.onload, script2)));
elList.push((0, dom_1$6.h)("div", { className: "separator", style: { margin: "0px 8px" } }, cfg.separator));
configs = /* @__PURE__ */ Object.create({});
}
configs[key] = cfg;
}
}
if (Object.keys(configs).length > 0) {
elList.push(this.configsArea(this.configs(script2.namespace, store2, configs || {}, opts === null || opts === void 0 ? void 0 : opts.onload, script2)));
}
scriptPanel.configsContainer.replaceChildren(...elList);
return scriptPanel;
},
configsArea(configElements) {
const configsContainer = (0, dom_1$6.h)("div", { className: "configs card" });
const configsBody = (0, dom_1$6.h)("div", { className: "configs-body" });
configsBody.append(...Object.entries(configElements).map(([key, el]) => el));
configsContainer.append(configsBody);
return configsContainer;
},
configs(namespace, store2, configs, onload, script2) {
const resolveSlot = (slot) => typeof slot === "function" ? slot.call(script2, script2 === null || script2 === void 0 ? void 0 : script2.cfg) : slot;
const elements2 = /* @__PURE__ */ Object.create({});
for (const key in configs) {
if (Object.prototype.hasOwnProperty.call(configs, key)) {
const config2 = configs[key];
if (config2.label !== void 0) {
const element = (0, dom_1$6.h)("config-element", {
key: common_1$4.$.namespaceKey(namespace, key),
tag: config2.tag,
sync: config2.sync,
attrs: config2.attrs,
_onload: function(el) {
var _a;
(_a = config2.onload) === null || _a === void 0 ? void 0 : _a.call(this, el);
onload === null || onload === void 0 ? void 0 : onload(el);
},
defaultValue: config2.defaultValue,
options: config2.options,
showIf: config2.showIf,
elementClassName: config2.elementClassName,
labelClassName: config2.labelClassName,
providerClassName: config2.providerClassName,
enableForAttribute: config2.enableForAttribute,
prefixSlot: resolveSlot(config2.prefixSlot),
suffixSlot: resolveSlot(config2.suffixSlot)
});
element.store = store2;
element.label.textContent = config2.label;
elements2[key] = element;
}
}
}
return elements2;
},
notes(lines, tag = "ul") {
return (0, dom_1$6.h)(tag, lines.map((line) => (0, dom_1$6.h)("li", Array.isArray(line) ? line.map((node) => typeof node === "string" ? (0, dom_1$6.h)("div", { innerHTML: node }) : node) : [typeof line === "string" ? (0, dom_1$6.h)("div", { innerHTML: line }) : line])));
},
copy(name, value) {
return (0, dom_1$6.h)("span", "📄" + name, (btn) => {
btn.className = "copy";
btn.addEventListener("click", () => {
btn.innerText = "已复制√";
navigator.clipboard.writeText(value);
setTimeout(() => {
btn.innerText = "📄" + name;
}, 500);
});
});
},
preventText(opts) {
const { name, delay = 3, autoRemove = true, ondefault, onprevent } = opts;
const span = (0, dom_1$6.h)("span", name);
span.style.textDecoration = "underline";
span.style.cursor = "pointer";
span.onclick = () => {
clearTimeout(id);
if (autoRemove) {
span.remove();
}
onprevent === null || onprevent === void 0 ? void 0 : onprevent(span);
};
const id = setTimeout(() => {
if (autoRemove) {
span.remove();
}
ondefault(span);
}, delay * 1e3);
return span;
},
space(children, options) {
return (0, dom_1$6.h)("div", { className: "space" }, (div) => {
var _a, _b, _c;
for (let index = 0; index < children.length; index++) {
const child = (0, dom_1$6.h)("span", { className: "space-item" }, [children[index]]);
child.style.display = "inline-block";
const x = (_a = options === null || options === void 0 ? void 0 : options.x) !== null && _a !== void 0 ? _a : 12;
const y = (_b = options === null || options === void 0 ? void 0 : options.y) !== null && _b !== void 0 ? _b : 0;
if (index > 0) {
child.style.marginLeft = x / 2 + "px";
child.style.marginRight = x / 2 + "px";
child.style.marginTop = y / 2 + "px";
child.style.marginBottom = y / 2 + "px";
} else {
child.style.marginRight = x / 2 + "px";
child.style.marginBottom = y / 2 + "px";
}
div.append(child);
if (index !== children.length - 1) {
div.append((0, dom_1$6.h)("span", [(_c = options === null || options === void 0 ? void 0 : options.separator) !== null && _c !== void 0 ? _c : " "]));
}
}
});
},
button(text2, attrs, handler) {
return (0, dom_1$6.h)("input", Object.assign({ type: "button" }, attrs), function(btn) {
btn.value = text2 || "";
btn.classList.add("base-style-button");
handler === null || handler === void 0 ? void 0 : handler.apply(this, [btn]);
});
}
};
(function(exports3) {
var __createBinding = commonjsGlobal && commonjsGlobal.__createBinding || (Object.create ? function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() {
return m[k];
} };
}
Object.defineProperty(o, k2, desc);
} : function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
o[k2] = m[k];
});
var __exportStar = commonjsGlobal && commonjsGlobal.__exportStar || function(m, exports4) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports4, p))
__createBinding(exports4, m, p);
};
Object.defineProperty(exports3, "__esModule", { value: true });
__exportStar(common, exports3);
__exportStar(ui, exports3);
__exportStar(dom, exports3);
__exportStar(elements$1, exports3);
__exportStar(tampermonkey, exports3);
__exportStar(store, exports3);
__exportStar(_const, exports3);
})(utils);
(function(exports3) {
var __awaiter2 = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports3, "__esModule", { value: true });
exports3.cors = exports3.CorsEventEmitter = void 0;
const utils_12 = utils;
const common_12 = common;
const const_12 = _const;
const store_12 = store;
class CorsEventEmitter {
constructor() {
this.eventMap = /* @__PURE__ */ new Map();
}
eventKey(name) {
return "cors.events." + name;
}
tempKey(...args) {
return ["_temp_", ...args].join(".");
}
keyOfReturn(id) {
return this.tempKey("event", id, "return");
}
keyOfArguments(id) {
return this.tempKey("event", id, "arguments");
}
keyOfState(id) {
return this.tempKey("event", id, "state");
}
emit(name, args = [], callback) {
store_12.$store.getTab(const_12.$const.TAB_UID).then((uid) => {
const id = common_12.$.uuid().replace(/-/g, "");
const key = uid + "." + this.eventKey(name);
store_12.$store.set(this.keyOfState(id), 0);
store_12.$store.set(this.keyOfArguments(id), args);
setTimeout(() => {
const listenerId = store_12.$store.addChangeListener(this.keyOfState(id), () => {
store_12.$store.removeChangeListener(listenerId);
callback === null || callback === void 0 ? void 0 : callback(store_12.$store.get(this.keyOfReturn(id)));
store_12.$store.delete(this.keyOfState(id));
store_12.$store.delete(this.keyOfReturn(id));
store_12.$store.delete(this.keyOfArguments(id));
}) || 0;
store_12.$store.set(key, (store_12.$store.get(key) ? String(store_12.$store.get(key)).split(",") : []).concat(id).join(","));
}, 100);
}).catch(console.error);
}
on(name, handler) {
return new Promise((resolve) => {
store_12.$store.getTab(const_12.$const.TAB_UID).then((uid) => {
const key = uid + "." + this.eventKey(name);
const originId = this.eventMap.get(key);
if (originId) {
resolve(originId);
} else {
const id = store_12.$store.addChangeListener(key, (curr, pre, remote) => __awaiter2(this, void 0, void 0, function* () {
if (remote) {
if (curr === void 0) {
return;
}
const list = String(curr).split(",");
const id2 = list.pop();
if (id2) {
store_12.$store.set(this.keyOfReturn(id2), yield handler(store_12.$store.get(this.keyOfArguments(id2))));
setTimeout(() => {
store_12.$store.set(this.keyOfState(id2), 1);
store_12.$store.set(key, list.join(","));
}, 100);
}
}
})) || 0;
this.eventMap.set(key, id);
resolve(id);
}
}).catch(console.error);
});
}
off(name) {
const key = this.eventKey(name);
const originId = this.eventMap.get(key);
if (originId) {
this.eventMap.delete(key);
store_12.$store.removeChangeListener(originId);
}
}
defineTopFunction(func) {
if (utils_12.$gm.isInGMContext() === false) {
return () => {
};
}
const event_name = "_top_function_." + getFuncId(func);
if (self === top) {
exports3.cors.on(event_name, (args) => __awaiter2(this, void 0, void 0, function* () {
return yield func(...args);
}));
}
return (...args) => __awaiter2(this, void 0, void 0, function* () {
if (self === top) {
return yield func(...args);
}
const res = yield new Promise((resolve, reject) => {
try {
exports3.cors.emit(event_name, args, (val) => {
resolve(val);
});
} catch (e) {
reject(e);
}
});
return res;
});
}
}
exports3.CorsEventEmitter = CorsEventEmitter;
if (typeof GM_listValues !== "undefined" && self === top) {
window.onload = () => {
store_12.$store.list().forEach((key) => {
if (/_temp_.event.[0-9a-z]{32}.(state|return|arguments)/.test(key)) {
store_12.$store.delete(key);
}
if (/_top_function_.*/.test(key)) {
store_12.$store.delete(key);
}
if (/[0-9a-z]{32}.cors.events/.test(key)) {
store_12.$store.delete(key);
}
});
};
}
exports3.cors = new CorsEventEmitter();
function getFuncId(fn) {
if (typeof fn !== "function") {
throw new Error("first argument in defineTopFunction() is not Function!");
}
const str = fn.toString();
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = (hash << 5) - hash + str.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash).toString(36).padStart(16, "0").slice(-16);
}
})(cors);
var project = {};
Object.defineProperty(project, "__esModule", { value: true });
project.Project = void 0;
class Project {
constructor({ name, domains, scripts }) {
this.name = name;
this.domains = domains;
for (const key in scripts) {
if (Object.prototype.hasOwnProperty.call(scripts, key)) {
const element = scripts[key];
element.projectName = name;
}
}
this.scripts = scripts;
}
static create(opts) {
return new Project(opts);
}
}
project.Project = Project;
var script = {};
var __importDefault$1 = commonjsGlobal && commonjsGlobal.__importDefault || function(mod) {
return mod && mod.__esModule ? mod : { "default": mod };
};
Object.defineProperty(script, "__esModule", { value: true });
script.Script = script.BaseScript = void 0;
const common_1$3 = common;
const start_1$1 = start$1;
const store_1$1 = store;
const common_2 = common$1;
const events_1 = __importDefault$1(events.exports);
class BaseScript extends common_2.CommonEventEmitter {
}
script.BaseScript = BaseScript;
class Script extends BaseScript {
get configs() {
if (!this._resolvedConfigs) {
this._resolvedConfigs = typeof this._configs === "function" ? this._configs() : this._configs;
}
return this._resolvedConfigs;
}
set configs(c) {
this._configs = c;
}
constructor({ name, namespace, matches: matches2, excludes, configs, hideInPanel, onstart, onactive, oncomplete, onbeforeunload, onrender, onhistorychange, onhistorychanged, methods, priority }) {
super();
this.excludes = [];
this.cfg = {};
this.methods = /* @__PURE__ */ Object.create({});
this.event = new events_1.default();
this.name = name;
this.namespace = namespace;
this.matches = matches2;
this.excludes = excludes;
this._configs = configs;
this.hideInPanel = hideInPanel;
this.onstart = this.errorHandler(onstart);
this.onactive = this.errorHandler(onactive);
this.oncomplete = this.errorHandler(oncomplete);
this.onbeforeunload = this.errorHandler(onbeforeunload);
this.onrender = this.errorHandler(onrender);
this.onhistorychange = this.errorHandler(onhistorychange);
this.onhistorychanged = this.errorHandler(onhistorychanged);
this.methods = (methods === null || methods === void 0 ? void 0 : methods.bind(this)()) || /* @__PURE__ */ Object.create({});
this.priority = priority !== null && priority !== void 0 ? priority : 0;
if (this.methods) {
for (const key in methods) {
if (Reflect.has(this.methods, key) && typeof this.methods[key] !== "function") {
Reflect.set(this.methods, key, this.errorHandler(this.methods[key]));
}
}
}
}
onConfigChange(key, handler) {
const _key = common_1$3.$.namespaceKey(this.namespace, key.toString());
return store_1$1.$store.addChangeListener(_key, (curr, pre, remote) => {
handler(curr, pre, !!remote);
});
}
offConfigChange(listener) {
store_1$1.$store.removeChangeListener(listener);
}
fullName() {
return this.projectName ? `${this.projectName}-${this.name}` : this.name;
}
withEvents() {
return this;
}
hidePanel() {
this.setPanelHidden(true);
}
showPanel() {
this.setPanelHidden(false);
}
togglePanel() {
this.setPanelHidden(!this.hideInPanel);
}
isPanelHidden() {
return !!this.hideInPanel;
}
setPanelHidden(hidden) {
this.hideInPanel = hidden;
start_1$1.$win === null || start_1$1.$win === void 0 ? void 0 : start_1$1.$win.refreshPanel();
}
errorHandler(func) {
return (...args) => {
try {
return func === null || func === void 0 ? void 0 : func.apply(this, args);
} catch (err) {
console.error(err);
if (err instanceof Error) {
this.emit("scripterror", err.message);
} else {
this.emit("scripterror", String(err));
}
}
};
}
}
script.Script = Script;
(function(exports3) {
var __createBinding = commonjsGlobal && commonjsGlobal.__createBinding || (Object.create ? function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() {
return m[k];
} };
}
Object.defineProperty(o, k2, desc);
} : function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
o[k2] = m[k];
});
var __exportStar = commonjsGlobal && commonjsGlobal.__exportStar || function(m, exports4) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports4, p))
__createBinding(exports4, m, p);
};
Object.defineProperty(exports3, "__esModule", { value: true });
__exportStar(common$1, exports3);
__exportStar(config$1, exports3);
__exportStar(cors, exports3);
__exportStar(project, exports3);
__exportStar(script, exports3);
__exportStar(store_provider, exports3);
})(interfaces);
var customWindow = {};
var elements = {};
var config = {};
var _interface = {};
Object.defineProperty(_interface, "__esModule", { value: true });
_interface.IElement = void 0;
class IElement extends HTMLElement {
connectedCallback() {
}
disconnectedCallback() {
}
adoptedCallback() {
}
attributeChangedCallback(name, oldValue, newValue) {
}
}
_interface.IElement = IElement;
Object.defineProperty(config, "__esModule", { value: true });
config.ConfigElement = void 0;
const ui_1 = ui;
const dom_1$5 = dom;
const interface_1$6 = _interface;
class ConfigElement extends interface_1$6.IElement {
constructor(store2) {
super();
this.label = (0, dom_1$5.h)("label");
this.wrapper = (0, dom_1$5.h)("div", { className: "config-wrapper" });
this.key = "";
this.store = store2;
}
get value() {
return this.store.get(this.key, this.defaultValue);
}
set value(value) {
this.provider.value = value;
this.store.set(this.key, value);
}
connectedCallback() {
var _a, _b, _c;
switch (this.tag) {
case "select": {
this.provider = (0, dom_1$5.h)("select");
const value = this.store.get(this.key, this.defaultValue);
for (const item of this.options || []) {
const option = ui_1.$ui.tooltip((0, dom_1$5.h)("option"));
if (Array.isArray(item)) {
option.value = item[0];
option.textContent = (_a = item[1]) !== null && _a !== void 0 ? _a : item[0];
if (item[2]) {
option.title = item[2];
}
if (String(item[0]) === String(value)) {
option.selected = true;
option.toggleAttribute("selected");
}
this.provider.add(option);
} else {
option.value = item.value;
option.textContent = (_b = item.label) !== null && _b !== void 0 ? _b : item.value;
if (item.title) {
option.title = item.title;
}
if (String(item.value) === String(value)) {
option.selected = true;
option.toggleAttribute("selected");
}
this.provider.add(option);
}
}
this.provider.onchange = () => {
this.store.set(this.key, this.provider.value);
};
break;
}
case "textarea": {
this.provider = (0, dom_1$5.h)("textarea");
this.provider.value = this.store.get(this.key, this.defaultValue);
this.provider.onchange = () => {
this.store.set(this.key, this.provider.value);
};
break;
}
default: {
this.provider = (0, dom_1$5.h)("input");
if (["checkbox", "radio"].some((t2) => {
var _a2;
return t2 === ((_a2 = this.attrs) === null || _a2 === void 0 ? void 0 : _a2.type);
})) {
this.provider.checked = this.store.get(this.key, this.defaultValue);
const provider2 = this.provider;
provider2.onchange = () => {
this.store.set(this.key, provider2.checked);
};
} else {
this.provider.value = this.store.get(this.key, this.defaultValue);
this.provider.setAttribute("value", this.provider.value);
this.provider.onchange = () => {
const { min, max, type } = this.attrs || {};
if (type === "number") {
if (this.provider.value.trim() === "") {
this.provider.value = this.defaultValue;
this.store.set(this.key, this.defaultValue);
return;
}
const val = parseFloat(this.provider.value);
const _min = min ? parseFloat(min) : void 0;
const _max = max ? parseFloat(max) : void 0;
if (_min && val < _min) {
this.provider.value = _min.toString();
this.store.set(this.key, parseFloat(this.provider.value));
} else if (_max && val > _max) {
this.provider.value = _max.toString();
this.store.set(this.key, parseFloat(this.provider.value));
} else {
this.store.set(this.key, val);
}
} else {
this.store.set(this.key, this.provider.value);
}
};
}
break;
}
}
if (this.enableForAttribute) {
this.provider.setAttribute("id", this.key);
this.label.setAttribute("for", this.key);
}
if (this.labelClassName) {
this.label.className = this.labelClassName;
}
if (this.providerClassName) {
this.provider.className = this.providerClassName;
}
if (this.elementClassName) {
this.className = this.elementClassName;
}
if (this.prefixSlot !== void 0 || this.suffixSlot !== void 0) {
const toNode = (slot, className) => typeof slot === "string" ? (0, dom_1$5.h)("span", { className, innerHTML: slot }) : slot;
const children = [];
if (this.prefixSlot !== void 0) {
children.push(toNode(this.prefixSlot, "config-prefix"));
}
children.push(this.provider);
if (this.suffixSlot !== void 0) {
children.push(toNode(this.suffixSlot, "config-suffix"));
}
this.wrapper.replaceChildren((0, dom_1$5.h)("div", { className: "config-provider-container" }, children));
} else {
this.wrapper.replaceChildren(this.provider);
}
this.append(this.label, this.wrapper);
for (const key in this.attrs) {
if (key === "style") {
Object.assign(this.provider.style, this.attrs[key]);
continue;
}
if (Object.prototype.hasOwnProperty.call(this.attrs, key)) {
Reflect.set(this.provider, key, Reflect.get(this.attrs, key));
}
}
if (this.sync) {
this.store.addChangeListener(this.key, (curr) => {
this.provider.value = curr;
});
}
ui_1.$ui.tooltip(this.provider);
if (this.showIf) {
let show_if = false;
if (Array.isArray(this.showIf)) {
if (typeof this.showIf[0] !== "string") {
throw new Error("EUS Config.showIf first element must be a string");
}
const val = this.store.get(this.showIf[0], false) || false;
const res = this.showIf[1].call(null, val, val, this.store);
show_if = Boolean(res);
} else {
show_if = this.store.get(this.showIf, false) || false;
}
if (show_if) {
this.style.display = "";
} else {
this.style.display = "none";
}
if (Array.isArray(this.showIf)) {
if (typeof this.showIf[1] !== "function") {
throw new Error("EUS Config.showIf second element must be a function");
}
this.store.addChangeListener(this.showIf[0], (curr, pre) => {
if (this.isConnected) {
if (this.showIf && Array.isArray(this.showIf)) {
const res = this.showIf[1].call(null, curr, pre, this.store);
if (res) {
this.style.display = "";
} else {
this.style.display = "none";
}
}
}
});
} else {
this.store.addChangeListener(this.showIf, (curr) => {
if (this.isConnected) {
const res = Boolean(curr);
if (res) {
this.style.display = "";
} else {
this.style.display = "none";
}
}
});
}
}
(_c = this._onload) === null || _c === void 0 ? void 0 : _c.call(this.provider, this);
}
}
config.ConfigElement = ConfigElement;
var container = {};
Object.defineProperty(container, "__esModule", { value: true });
container.ContainerElement = void 0;
const common_1$2 = common;
const dom_1$4 = dom;
const interface_1$5 = _interface;
class ContainerElement extends interface_1$5.IElement {
constructor() {
super(...arguments);
this.header = (0, dom_1$4.h)("header-element");
this.body = (0, dom_1$4.h)("div", { className: "body", clientHeight: window.innerHeight / 2 });
this.footer = (0, dom_1$4.h)("div", { className: "footer" });
}
connectedCallback() {
this.append(this.header, this.body, this.footer);
const stopScrollPropagation = (e) => e.stopPropagation();
this.addEventListener("wheel", stopScrollPropagation);
this.addEventListener("touchmove", stopScrollPropagation);
common_1$2.$.onresize(this, (cont) => {
cont.body.style.maxHeight = window.innerHeight - this.header.clientHeight - 64 + "px";
cont.body.style.maxWidth = window.innerWidth - 50 + "px";
});
}
}
container.ContainerElement = ContainerElement;
var dropdown = {};
Object.defineProperty(dropdown, "__esModule", { value: true });
dropdown.DropdownElement = void 0;
const interface_1$4 = _interface;
const dom_1$3 = dom;
class DropdownElement extends interface_1$4.IElement {
constructor() {
super(...arguments);
this.triggerElement = (0, dom_1$3.h)("button");
this.content = (0, dom_1$3.h)("div", { className: "dropdown-content" });
this.trigger = "hover";
this.hideDelay = 50;
}
connectedCallback() {
this.append(this.triggerElement, this.content);
this.classList.add("dropdown");
if (this.trigger === "click") {
this.triggerElement.onclick = () => {
this.content.classList.toggle("show");
};
this.removeDocumentClickHandler();
this.documentClickHandler = (e) => {
if (this.content.classList.contains("show") && e.composedPath().includes(this) === false) {
this.content.classList.remove("show");
}
};
document.addEventListener("click", this.documentClickHandler);
} else {
let hideTimer;
const show = () => {
if (hideTimer !== void 0) {
clearTimeout(hideTimer);
hideTimer = void 0;
}
this.content.classList.add("show");
};
const hide = () => {
if (hideTimer !== void 0) {
clearTimeout(hideTimer);
}
hideTimer = setTimeout(() => {
this.content.classList.remove("show");
hideTimer = void 0;
}, this.hideDelay);
};
this.triggerElement.onmouseenter = show;
this.triggerElement.onmouseleave = hide;
this.content.onmouseenter = show;
this.content.onmouseleave = hide;
}
this.content.onclick = () => {
this.content.classList.remove("show");
};
}
disconnectedCallback() {
this.removeDocumentClickHandler();
}
removeDocumentClickHandler() {
if (this.documentClickHandler) {
document.removeEventListener("click", this.documentClickHandler);
this.documentClickHandler = void 0;
}
}
}
dropdown.DropdownElement = DropdownElement;
var header = {};
Object.defineProperty(header, "__esModule", { value: true });
header.HeaderElement = void 0;
const interface_1$3 = _interface;
class HeaderElement extends interface_1$3.IElement {
connectedCallback() {
this.append(this.visualSwitcher || "");
}
}
header.HeaderElement = HeaderElement;
var message = {};
Object.defineProperty(message, "__esModule", { value: true });
message.MessageElement = void 0;
const dom_1$2 = dom;
const interface_1$2 = _interface;
class MessageElement extends interface_1$2.IElement {
constructor() {
super(...arguments);
this.closer = (0, dom_1$2.h)("span", { className: "message-closer" }, "x");
this.contentContainer = (0, dom_1$2.h)("span", { className: "message-content-container" });
this.type = "info";
this.content = "";
this.closeable = true;
}
connectedCallback() {
var _a;
this.classList.add(this.type);
if (typeof this.content === "string") {
this.contentContainer.innerHTML = this.content;
} else {
this.contentContainer.append(this.content);
}
this.duration = Math.max((_a = this.duration) !== null && _a !== void 0 ? _a : 5, 0);
this.append(this.contentContainer);
if (this.closeable) {
this.append(this.closer);
this.closer.addEventListener("click", () => {
var _a2;
(_a2 = this.onClose) === null || _a2 === void 0 ? void 0 : _a2.call(this);
this.remove();
});
}
if (this.duration) {
setTimeout(() => {
var _a2;
(_a2 = this.onClose) === null || _a2 === void 0 ? void 0 : _a2.call(this);
this.remove();
}, this.duration * 1e3);
}
}
}
message.MessageElement = MessageElement;
var modal$1 = {};
var __awaiter$2 = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(modal$1, "__esModule", { value: true });
modal$1.ModalElement = void 0;
const common_1$1 = common;
const dom_1$1 = dom;
const tampermonkey_1 = tampermonkey;
const interface_1$1 = _interface;
class ModalElement extends interface_1$1.IElement {
constructor() {
super(...arguments);
this._title = (0, dom_1$1.h)("div", { className: "modal-title" });
this.body = (0, dom_1$1.h)("div", { className: "modal-body" });
this.footerContainer = (0, dom_1$1.h)("div", { className: "modal-footer" });
this.modalInput = (0, dom_1$1.h)("input", { className: "modal-input" });
this.modalInputType = "input";
this.type = "alert";
this.content = "";
this.inputDefaultValue = "";
this.placeholder = "";
this.modalStyle = {};
}
connectedCallback() {
var _a;
this.classList.add(this.type);
Object.assign(this.style, this.modalStyle || {});
const profile = (0, dom_1$1.h)("div", {
innerText: this.profile || "弹窗来自: 木金 " + (((_a = tampermonkey_1.$gm.getInfos()) === null || _a === void 0 ? void 0 : _a.script.version) || ""),
className: "modal-profile"
});
this._title.innerText = this.title;
this.body.append(typeof this.content === "string" ? (0, dom_1$1.h)("div", { innerHTML: this.content }) : this.content);
if (this.modalInputType === "textarea") {
this.modalInput = (0, dom_1$1.h)("textarea", { className: "modal-input", style: { height: "100px" } });
}
this.modalInput.placeholder = this.placeholder || "";
this.modalInput.value = this.inputDefaultValue || "";
this.append(profile, this._title, this.body, this.footerContainer);
this.style.width = (this.width || 400) + "px";
if (this.footer === void 0) {
this.footerContainer.append(this.modalInput);
if (this.cancelButton === void 0) {
this.cancelButton = (0, dom_1$1.h)("button", { className: "modal-cancel-button" });
this.cancelButton.innerText = this.cancelButtonText || "取消";
this.cancelButton.onclick = () => {
var _a2, _b;
(_a2 = this.onCancel) === null || _a2 === void 0 ? void 0 : _a2.call(this);
(_b = this.onClose) === null || _b === void 0 ? void 0 : _b.call(this);
this.remove();
};
}
if (this.confirmButton === void 0) {
this.confirmButton = (0, dom_1$1.h)("button", { className: "modal-confirm-button" });
this.confirmButton.innerText = this.confirmButtonText || "确定";
this.confirmButton.onclick = () => __awaiter$2(this, void 0, void 0, function* () {
var _b, _c;
if ((yield (_b = this.onConfirm) === null || _b === void 0 ? void 0 : _b.call(this, this.modalInput.value)) !== false) {
this.remove();
(_c = this.onClose) === null || _c === void 0 ? void 0 : _c.call(this, this.modalInput.value);
}
});
}
this.cancelButton && this.footerContainer.append(this.cancelButton);
this.confirmButton && this.footerContainer.append(this.confirmButton);
if (this.type === "simple") {
this.footerContainer.remove();
} else if (this.type === "prompt") {
this.modalInput.focus();
}
} else {
this.footerContainer.append(this.footer);
}
common_1$1.$.onresize(this.body, (modal2) => {
this.body.style.maxHeight = window.innerHeight - 100 + "px";
this.body.style.maxWidth = window.innerWidth - 50 + "px";
});
}
}
modal$1.ModalElement = ModalElement;
var script_panel = {};
Object.defineProperty(script_panel, "__esModule", { value: true });
script_panel.ScriptPanelElement = void 0;
const dom_1 = dom;
const interface_1 = _interface;
class ScriptPanelElement extends interface_1.IElement {
constructor() {
super(...arguments);
this.separator = (0, dom_1.h)("div", { className: "separator" });
this.notesContainer = (0, dom_1.h)("div", { className: "notes card" });
this.notesHeader = (0, dom_1.h)("div", { className: "notes-header" });
this.notesBody = (0, dom_1.h)("div", { className: "notes-body" });
this.configsContainer = (0, dom_1.h)("div", { className: "configs-container card" });
this.body = (0, dom_1.h)("div", { className: "script-panel-body" });
this.lockWrapper = (0, dom_1.h)("div", { className: "lock-wrapper" });
}
connectedCallback() {
this.separator.innerText = this.name || "";
this.notesHeader.append((0, dom_1.h)("span", { className: "notes-title" }, [(0, dom_1.h)("span", { className: "notes-info-icon" }, "i"), "提示"]), (0, dom_1.h)("span", { className: "notes-collapse-icon" }, "▼"));
this.notesContainer.append(this.notesHeader);
this.notesContainer.append(this.notesBody);
this.append(this.separator);
this.append(this.notesContainer);
this.append(this.configsContainer);
this.append(this.body);
}
setNotesExpanded(expanded) {
this.notesContainer.classList.toggle("collapsed", !expanded);
}
isNotesExpanded() {
return !this.notesContainer.classList.contains("collapsed");
}
}
script_panel.ScriptPanelElement = ScriptPanelElement;
(function(exports3) {
Object.defineProperty(exports3, "__esModule", { value: true });
exports3.definedCustomElements = exports3.ScriptPanelElement = exports3.ModalElement = exports3.MessageElement = exports3.HeaderElement = exports3.ContainerElement = exports3.ConfigElement = void 0;
const config_1 = config;
const container_1 = container;
const dropdown_1 = dropdown;
const header_1 = header;
const message_1 = message;
const modal_1 = modal$1;
const script_panel_1 = script_panel;
var config_2 = config;
Object.defineProperty(exports3, "ConfigElement", { enumerable: true, get: function() {
return config_2.ConfigElement;
} });
var container_2 = container;
Object.defineProperty(exports3, "ContainerElement", { enumerable: true, get: function() {
return container_2.ContainerElement;
} });
var header_2 = header;
Object.defineProperty(exports3, "HeaderElement", { enumerable: true, get: function() {
return header_2.HeaderElement;
} });
var message_2 = message;
Object.defineProperty(exports3, "MessageElement", { enumerable: true, get: function() {
return message_2.MessageElement;
} });
var modal_2 = modal$1;
Object.defineProperty(exports3, "ModalElement", { enumerable: true, get: function() {
return modal_2.ModalElement;
} });
var script_panel_2 = script_panel;
Object.defineProperty(exports3, "ScriptPanelElement", { enumerable: true, get: function() {
return script_panel_2.ScriptPanelElement;
} });
exports3.definedCustomElements = [
config_1.ConfigElement,
container_1.ContainerElement,
header_1.HeaderElement,
modal_1.ModalElement,
message_1.MessageElement,
script_panel_1.ScriptPanelElement,
dropdown_1.DropdownElement
];
})(elements);
var __awaiter$1 = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = commonjsGlobal && commonjsGlobal.__rest || function(s, e) {
var t2 = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t2[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t2[p[i]] = s[p[i]];
}
return t2;
};
Object.defineProperty(customWindow, "__esModule", { value: true });
customWindow.modal = customWindow.CustomWindow = void 0;
const _1 = interfaces;
const elements_1$1 = elements;
const utils_1 = utils;
const start_1 = start$1;
const minimizeSvg = '';
const expandSvg = '';
class CustomWindow {
constructor(projects, inputStoreProvider, config2) {
this.messageContainer = (0, utils_1.h)("div", { className: "message-container" });
this.menuBar = utils_1.$ui.tooltip(
(0, utils_1.h)("div", { className: "header-menu-bar", title: "菜单栏-可拖动区域", style: { display: "flex", width: "100%" } }),
"top"
);
this.extraMenuBar = (0, utils_1.h)("div", { className: "extra-menu-bar" });
this.defaults = {
urls: (urls) => urls && urls.length ? urls : [location.href],
panelName: (name) => name || this.config.render.defaultPanelName || ""
};
this.projects = projects;
this.inputStoreProvider = inputStoreProvider;
this.config = config2;
handleLowLevelBrowser();
utils_1.$.loadCustomElements(elements_1$1.definedCustomElements);
this.wrapper = (0, utils_1.h)("div");
utils_1.$elements.tooltipContainer = (0, utils_1.h)("div", { className: "tooltip-container" });
utils_1.$elements.wrapper = this.wrapper;
this.root = this.wrapper.attachShadow({ mode: "closed" });
utils_1.$elements.root = this.root;
this.container = (0, utils_1.h)("container-element");
this.root.append(this.container);
const styles = config2.render.styles.map((s) => (0, utils_1.h)("style", s));
this.container.append(...styles, this.messageContainer);
new MutationObserver(() => this.layoutViewportTopMessages()).observe(this.messageContainer, { childList: true });
const handlePosition = () => {
const pos = config2.store.getPosition();
if (pos.x > document.documentElement.clientWidth || pos.x < 0) {
config2.store.setPosition(10, 10);
}
if (pos.y > document.documentElement.clientHeight || pos.y < 0) {
config2.store.setPosition(10, 10);
}
this.container.style.left = pos.x + "px";
this.container.style.top = pos.y + "px";
const positionHandler = () => {
config2.store.setPosition(this.container.offsetLeft, this.container.offsetTop);
};
(0, utils_1.enableElementDraggable)(this.menuBar, this.container, positionHandler);
(0, utils_1.enableElementTouchDraggable)(this.menuBar, this.container, positionHandler);
};
const handleVisible = () => {
window.addEventListener("click", (e) => {
if (e.detail === Math.max(config2.render.switchPoint, 3)) {
this.container.style.top = e.y + "px";
this.container.style.left = e.x + "px";
config2.store.setPosition(e.x, e.y);
this.setVisual("normal");
}
});
};
const initCorsModalSystem = () => {
_1.cors.on("modal", (args) => __awaiter$1(this, void 0, void 0, function* () {
const [type, _attrs] = args || [];
return new Promise((resolve, reject) => {
const attrs = _attrs;
attrs.onCancel = () => resolve("");
attrs.onConfirm = resolve;
attrs.onClose = resolve;
modal(type, attrs);
});
}));
};
const initCorsMessageSystem = () => {
_1.cors.on("message", (args) => __awaiter$1(this, void 0, void 0, function* () {
const [type, attrs] = args || [];
console.log("message", type, attrs);
this.message(type, attrs);
}));
};
const switchVisual = () => {
this.setVisual(config2.store.getVisual() === "hidden" ? "normal" : "hidden");
};
window.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.key === config2.render.switchKey) {
e.stopPropagation();
e.preventDefault();
switchVisual();
}
}, { capture: true });
_1.cors.on("switch-visual", () => {
switchVisual();
});
handleVisible();
this.setVisual(config2.store.getVisual());
(() => __awaiter$1(this, void 0, void 0, function* () {
const urls = yield config2.store.getRenderURLs();
const currentPanelName = yield config2.store.getCurrentPanelName();
yield this.rerender(this.defaults.urls(urls), this.defaults.panelName(currentPanelName));
}))();
initCorsModalSystem();
initCorsMessageSystem();
handlePosition();
this.setFontSize(config2.render.fontsize);
}
rerender(urls, currentPanelName) {
return __awaiter$1(this, void 0, void 0, function* () {
this.initHeader(urls, currentPanelName);
yield this.renderBody(currentPanelName);
});
}
initHeader(urls, currentPanelName) {
const title = this.config.render.title;
const profile = utils_1.$ui.tooltip((0, utils_1.h)("div", { className: "profile", title: "菜单栏(可拖动区域)" }, (el) => {
if (title instanceof HTMLElement) {
el.append(title);
} else {
el.innerHTML = title || "无标题";
}
}));
const scriptDropdowns = [];
for (const project2 of this.projects) {
const dropdown2 = (0, utils_1.h)("dropdown-element");
let selected = false;
const options = [];
const scripts = utils_1.$.getMatchedScripts([project2], urls).filter((s) => !s.hideInPanel);
if (scripts.length) {
for (const key in project2.scripts) {
if (Object.prototype.hasOwnProperty.call(project2.scripts, key)) {
const script2 = project2.scripts[key];
if (!script2.hideInPanel) {
const optionSelected = isCurrentPanel(project2.name, script2, currentPanelName);
const option = (0, utils_1.h)("div", { className: "dropdown-option" }, script2.name);
if (optionSelected) {
option.classList.add("active");
}
if (selected !== true && optionSelected) {
selected = true;
}
option.onclick = () => __awaiter$1(this, void 0, void 0, function* () {
yield this.config.store.setCurrentPanelName(project2.name + "-" + script2.name);
});
options.push(option);
}
}
}
if (selected) {
dropdown2.classList.add("active");
}
dropdown2.triggerElement = (0, utils_1.h)("div", { className: "dropdown-trigger-element" }, project2.name);
dropdown2.content.append(...options);
scriptDropdowns.push(dropdown2);
}
}
const isMinimize = () => this.config.store.getVisual() === "minimize";
const visualSwitcher = utils_1.$ui.tooltip((0, utils_1.h)("div", {
className: "switch ",
title: isMinimize() ? "点击展开窗口" : "点击最小化窗口",
innerHTML: isMinimize() ? expandSvg : minimizeSvg,
onclick: () => {
this.setVisual(isMinimize() ? "normal" : "minimize");
visualSwitcher.title = isMinimize() ? "点击展开窗口" : "点击最小化窗口";
visualSwitcher.innerHTML = isMinimize() ? expandSvg : minimizeSvg;
}
}));
this.container.header.visualSwitcher = visualSwitcher;
this.container.header.replaceChildren();
this.menuBar.replaceChildren(profile, ...scriptDropdowns, this.container.header.visualSwitcher || "");
this.container.header.append((0, utils_1.h)("div", { style: { width: "100%" } }, [
this.menuBar,
(0, utils_1.h)("div", { style: { display: "flex", width: "100%" } }, [this.extraMenuBar])
]));
}
renderBody(currentPanelName) {
var _a;
return __awaiter$1(this, void 0, void 0, function* () {
for (const project2 of this.projects) {
for (const key in project2.scripts) {
if (Object.prototype.hasOwnProperty.call(project2.scripts, key)) {
const script2 = project2.scripts[key];
if (isCurrentPanel(project2.name, script2, currentPanelName)) {
const panel = utils_1.$ui.scriptPanel(script2, this.inputStoreProvider);
script2.projectName = project2.name;
script2.panel = panel;
script2.header = this.container.header;
utils_1.$elements.currentScriptPanel = panel;
this.container.body.replaceChildren(panel);
(_a = script2.onrender) === null || _a === void 0 ? void 0 : _a.call(script2, { panel, header: this.container.header });
script2.emit("render", { panel, header: this.container.header });
}
}
}
}
});
}
setFontSize(fontsize) {
this.container.style.font = `${fontsize}px Menlo, Monaco, Consolas, 'Courier New', monospace`;
}
setVisual(value) {
this.container.className = "";
if (value === "minimize") {
this.container.classList.add("minimize");
} else if (value === "hidden") {
this.container.classList.add("hidden");
} else {
this.container.classList.add("normal");
}
this.config.store.setVisual(value);
}
changeRenderURLs(urls) {
return __awaiter$1(this, void 0, void 0, function* () {
const currentPanelName = yield this.config.store.getCurrentPanelName();
yield this.rerender(this.defaults.urls(urls), this.defaults.panelName(currentPanelName));
});
}
changePanel(currentPanelName) {
return __awaiter$1(this, void 0, void 0, function* () {
const urls = (yield this.config.store.getRenderURLs()) || [location.href];
yield this.rerender(this.defaults.urls(urls), this.defaults.panelName(currentPanelName));
});
}
refreshPanel() {
return __awaiter$1(this, void 0, void 0, function* () {
const urls = this.defaults.urls((yield this.config.store.getRenderURLs()) || [location.href]);
let currentPanelName = this.defaults.panelName(yield this.config.store.getCurrentPanelName());
const visibleScripts = utils_1.$.getMatchedScripts(this.projects, urls).filter((s) => !s.hideInPanel);
const isCurrentVisible = visibleScripts.some((s) => isCurrentPanel(s.projectName, s, currentPanelName));
if (!isCurrentVisible && visibleScripts.length > 0) {
currentPanelName = visibleScripts[0].fullName();
}
yield this.rerender(urls, currentPanelName);
});
}
pin(script2) {
return __awaiter$1(this, void 0, void 0, function* () {
if (script2.projectName) {
yield this.config.store.setCurrentPanelName(`${script2.projectName}-${script2.name}`);
} else if (script2.namespace) {
yield this.config.store.setCurrentPanelName(script2.namespace);
} else {
console.warn("[ERROR]", `${script2.name} 无法置顶, projectName 与 namespace 都为 undefined`);
}
});
}
minimize() {
this.setVisual("minimize");
}
normal() {
this.setVisual("normal");
}
hidden() {
this.setVisual("hidden");
}
message(type, attrs) {
if (typeof attrs === "string") {
attrs = { content: attrs };
}
const message2 = (0, utils_1.h)("message-element", Object.assign({ type }, attrs));
this.messageContainer.append(message2);
requestAnimationFrame(() => {
const rect = message2.getBoundingClientRect();
const outOfViewport = rect.left < 0 || rect.top < 0 || rect.right > window.innerWidth || rect.bottom > window.innerHeight;
if (outOfViewport) {
message2.classList.add("message-viewport-top");
this.layoutViewportTopMessages();
}
});
return message2;
}
layoutViewportTopMessages() {
let top2 = 12;
const gap = 8;
const messages = this.messageContainer.querySelectorAll("message-element.message-viewport-top");
for (const el of Array.from(messages)) {
el.style.top = top2 + "px";
top2 += el.offsetHeight + gap;
}
}
menu(label, config2) {
return __awaiter$1(this, void 0, void 0, function* () {
this.extraMenuBar.style.display = "flex";
const btn = (0, utils_1.h)("button", label);
btn.addEventListener("click", () => {
if (config2.scriptPanelLink) {
this.pin(config2.scriptPanelLink).then(() => {
this.normal();
}).catch(console.error);
}
});
if (config2.scriptPanelLink) {
const full_name = (config2.scriptPanelLink.projectName ? config2.scriptPanelLink.projectName + " -> " : "") + config2.scriptPanelLink.name;
btn.title = "快捷跳转:" + full_name;
btn.setAttribute("data-name", (config2.scriptPanelLink.projectName + "-" + config2.scriptPanelLink.name).replace(/\s/g, "_"));
btn.classList.add("script-panel-link");
}
this.extraMenuBar.append(utils_1.$ui.tooltip(btn));
const name = yield utils_1.$store.getTab(utils_1.$const.TAB_CURRENT_PANEL_NAME);
if (config2.scriptPanelLink) {
if (isCurrentPanel(config2.scriptPanelLink.projectName, config2.scriptPanelLink, name)) {
this.extraMenuBar.querySelectorAll(".script-panel-link").forEach((el) => el.classList.remove("active"));
btn.classList.add("active");
}
}
return btn;
});
}
mount(parent) {
parent.children[utils_1.$.random(0, parent.children.length - 1)].after(this.wrapper);
}
}
customWindow.CustomWindow = CustomWindow;
function isCurrentPanel(projectName, script2, currentPanelName) {
return projectName + "-" + script2.name === currentPanelName || script2.namespace === currentPanelName;
}
function handleLowLevelBrowser() {
if (typeof Element.prototype.replaceChildren === "undefined") {
Element.prototype.replaceChildren = function(...nodes) {
this.innerHTML = "";
for (const node of nodes) {
this.append(node);
}
};
}
}
function modal(type, attrs, parent = (start_1.$win === null || start_1.$win === void 0 ? void 0 : start_1.$win.container) || utils_1.$elements.root || document.body) {
const { maskCloseable = true, onConfirm, onCancel, onClose, notification: notify, notificationOptions, duration } = attrs, _attrs = __rest(attrs, ["maskCloseable", "onConfirm", "onCancel", "onClose", "notification", "notificationOptions", "duration"]);
if (notify) {
utils_1.$gm.notification(typeof _attrs.content === "string" ? _attrs.content : _attrs.content.textContent || "", notificationOptions);
}
const wrapper = (0, utils_1.h)("div", { className: "modal-wrapper" }, (wrapper2) => {
const modal2 = (0, utils_1.h)("modal-element", Object.assign({
onConfirm(val) {
return __awaiter$1(this, void 0, void 0, function* () {
const isClose = yield onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm.apply(modal2, [val]);
if (isClose !== false) {
wrapper2.remove();
}
return isClose;
});
},
onCancel() {
onCancel === null || onCancel === void 0 ? void 0 : onCancel.apply(modal2);
wrapper2.remove();
},
onClose(val) {
onClose === null || onClose === void 0 ? void 0 : onClose.apply(modal2, [val]);
wrapper2.remove();
},
type
}, _attrs));
wrapper2.append(modal2);
modal2.addEventListener("click", (e) => {
e.stopPropagation();
});
if (maskCloseable) {
wrapper2.addEventListener("click", () => {
onClose === null || onClose === void 0 ? void 0 : onClose.apply(modal2);
wrapper2.remove();
});
}
});
if (duration) {
setTimeout(() => {
wrapper.remove();
}, duration * 1e3);
}
parent.append(wrapper);
return wrapper;
}
customWindow.modal = modal;
var __awaiter = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = commonjsGlobal && commonjsGlobal.__importDefault || function(mod) {
return mod && mod.__esModule ? mod : { "default": mod };
};
Object.defineProperty(start$1, "__esModule", { value: true });
start$1.addFunctionEventListener = start$1.start = start$1.$win = void 0;
const interfaces_1 = interfaces;
const custom_window_1 = customWindow;
const common_1 = common;
const const_1 = _const;
const elements_1 = elements$1;
const store_1 = store;
const debounce_1 = __importDefault(debounce_1$1);
let mounted = false;
function start(startConfig) {
return __awaiter(this, void 0, void 0, function* () {
startConfig.projects = startConfig.projects.map((p) => {
for (const key in p.scripts) {
if (Object.prototype.hasOwnProperty.call(p.scripts, key)) {
p.scripts[key].cfg = common_1.$.createConfigProxy(p.scripts[key]);
}
}
return p;
});
const scripts = common_1.$.getMatchedScripts(startConfig.projects, [location.href]).sort((a, b) => b.priority - a.priority);
scripts.forEach((script2) => {
var _a;
script2.startConfig = startConfig;
script2.emit("start", startConfig);
(_a = script2.onstart) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig);
});
const uid = yield store_1.$store.getTab(const_1.$const.TAB_UID);
if (uid === void 0) {
yield store_1.$store.setTab(const_1.$const.TAB_UID, common_1.$.uuid());
}
const urls = yield store_1.$store.getTab(const_1.$const.TAB_URLS);
yield store_1.$store.setTab(const_1.$const.TAB_URLS, Array.from(new Set((urls || []).concat(location.href))));
let active = false;
if (document.readyState === "interactive") {
active = true;
mount(startConfig);
scripts.forEach((script2) => {
var _a;
return (_a = script2.onactive) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig);
});
} else if (document.readyState === "complete") {
mount(startConfig);
scripts.forEach((script2) => {
var _a;
return (_a = script2.onactive) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig);
});
scripts.forEach((script2) => {
var _a;
return (_a = script2.oncomplete) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig);
});
}
document.addEventListener("readystatechange", () => {
mount(startConfig);
if (document.readyState === "interactive" && active === false) {
scripts.forEach((script2) => {
var _a;
script2.emit("active", startConfig);
(_a = script2.onactive) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig);
});
}
if (document.readyState === "complete") {
scripts.forEach((script2) => {
var _a;
script2.emit("complete");
(_a = script2.oncomplete) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig);
});
}
});
window.addEventListener("hashchange", () => {
scripts.forEach((script2) => {
var _a;
script2.emit("hashchange", startConfig);
(_a = script2.onhashchange) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig);
});
});
history.pushState = addFunctionEventListener(history, "pushState");
history.replaceState = addFunctionEventListener(history, "replaceState");
window.addEventListener("pushState", () => {
scripts.forEach((script2) => {
var _a;
script2.emit("historychange", "push", startConfig);
(_a = script2.onhistorychange) === null || _a === void 0 ? void 0 : _a.call(script2, "push", startConfig);
});
const new_scripts = common_1.$.getMatchedScripts(startConfig.projects, [location.href]).sort((a, b) => b.priority - a.priority);
new_scripts.forEach((ns) => {
var _a;
ns.emit("historychanged", "pushed", startConfig);
(_a = ns.onhistorychanged) === null || _a === void 0 ? void 0 : _a.call(ns, "pushed", startConfig);
});
});
window.addEventListener("replaceState", () => {
scripts.forEach((script2) => {
var _a;
script2.emit("historychange", "replace", startConfig);
(_a = script2.onhistorychange) === null || _a === void 0 ? void 0 : _a.call(script2, "replace", startConfig);
});
const new_scripts = common_1.$.getMatchedScripts(startConfig.projects, [location.href]).sort((a, b) => b.priority - a.priority);
new_scripts.forEach((ns) => {
var _a;
ns.emit("historychanged", "replaced", startConfig);
(_a = ns.onhistorychanged) === null || _a === void 0 ? void 0 : _a.call(ns, "replaced", startConfig);
});
});
window.addEventListener("beforeunload", (e) => {
var _a;
let prevent;
for (const script2 of scripts) {
script2.emit("beforeunload");
if ((_a = script2.onbeforeunload) === null || _a === void 0 ? void 0 : _a.call(script2, startConfig)) {
prevent = true;
}
}
if (prevent) {
e.preventDefault();
e.returnValue = true;
return true;
}
});
});
}
start$1.start = start;
function addFunctionEventListener(obj, type) {
const origin = obj[type];
return function(...args) {
const res = origin.apply(this, args);
const e = new Event(type.toString());
e.arguments = args;
window.dispatchEvent(e);
return res;
};
}
start$1.addFunctionEventListener = addFunctionEventListener;
function mount(startConfig) {
return __awaiter(this, void 0, void 0, function* () {
if (mounted === true) {
return;
}
mounted = true;
if (startConfig === void 0 || startConfig.renderConfig === void 0) {
console.warn("the script will not have ui because the renderConfig is not defined.");
return;
}
if (self !== top && startConfig.renderConfig) {
window.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.key === "o") {
e.stopPropagation();
e.preventDefault();
interfaces_1.cors.emit("switch-visual", []);
}
}, { capture: true });
}
if (self === top) {
const { projects, renderConfig } = startConfig;
if (typeof renderConfig.renderScript === "undefined") {
console.warn("the script will not have ui because the RenderScript is not defined.");
return;
}
const scripts = common_1.$.getMatchedScripts(projects, [location.href]).filter((s) => !!s.hideInPanel === false);
if (scripts.length <= 0) {
return;
}
const RenderScript2 = renderConfig.renderScript;
const win = new custom_window_1.CustomWindow(startConfig.projects, store_1.$store, {
render: {
title: renderConfig.title,
styles: renderConfig.styles,
defaultPanelName: renderConfig.defaultPanelName,
fontsize: RenderScript2.cfg.fontsize,
switchPoint: RenderScript2.cfg.switchPoint,
switchKey: "o"
},
store: {
getPosition: () => {
return { x: RenderScript2.cfg.x, y: RenderScript2.cfg.y };
},
setPosition: (x, y) => {
RenderScript2.cfg.x = x;
RenderScript2.cfg.y = y;
},
getVisual: () => {
return RenderScript2.cfg.visual;
},
setVisual: (size) => {
RenderScript2.cfg.visual = size;
},
getRenderURLs() {
return __awaiter(this, void 0, void 0, function* () {
return yield store_1.$store.getTab(const_1.$const.TAB_URLS);
});
},
setRenderURLs(urls) {
return __awaiter(this, void 0, void 0, function* () {
return yield store_1.$store.setTab(const_1.$const.TAB_URLS, urls);
});
},
getCurrentPanelName() {
return __awaiter(this, void 0, void 0, function* () {
return yield store_1.$store.getTab(const_1.$const.TAB_CURRENT_PANEL_NAME);
});
},
setCurrentPanelName(name) {
return __awaiter(this, void 0, void 0, function* () {
return yield store_1.$store.setTab(const_1.$const.TAB_CURRENT_PANEL_NAME, name);
});
}
}
});
RenderScript2.onConfigChange("fontsize", (fs) => {
win.setFontSize(fs);
});
store_1.$store.addTabChangeListener(const_1.$const.TAB_URLS, (0, debounce_1.default)((curr, pre) => {
if (JSON.stringify(curr) === JSON.stringify(pre)) {
return;
}
win.changeRenderURLs(curr);
}, 2e3));
store_1.$store.addTabChangeListener(const_1.$const.TAB_CURRENT_PANEL_NAME, (curr, pre) => {
if (curr === pre) {
return;
}
win.changePanel(curr);
updateMenusState(win, curr);
});
win.mount(startConfig.mountElement || document.body);
elements_1.$elements.tooltipContainer && win.container.append(elements_1.$elements.tooltipContainer);
start$1.$win = win;
}
});
}
function updateMenusState(win, name) {
var _a;
win.root.querySelectorAll(".extra-menu-bar .script-panel-link").forEach((el) => el.classList.remove("active"));
(_a = win.root.querySelector('.extra-menu-bar [data-name="' + name.replace(/\s/g, "_") + '"]')) === null || _a === void 0 ? void 0 : _a.classList.add("active");
}
var render = {};
(function(exports3) {
Object.defineProperty(exports3, "__esModule", { value: true });
exports3.$menu = exports3.$message = exports3.$modal = exports3.createRenderScript = void 0;
const script_1 = script;
const ui_12 = ui;
const dom_12 = dom;
const custom_window_12 = customWindow;
const start_12 = start$1;
const interfaces_12 = interfaces;
const createRenderScript = (config2) => new script_1.Script({
name: (config2 === null || config2 === void 0 ? void 0 : config2.name) || "窗口设置",
matches: (config2 === null || config2 === void 0 ? void 0 : config2.matches) || [["所有", /.*/]],
namespace: "render.panel",
configs: {
notes: {
defaultValue: ui_12.$ui.notes([
[
"如果需要隐藏整个窗口,可以点击下方隐藏按钮,",
"隐藏后可以快速三击屏幕中的任意地方",
"来重新在鼠标位置显示窗口。"
],
"窗口连续点击显示的次数可以自定义,默认为三次",
["窗口快捷键列表:", "ctrl + o : 隐藏/打开 面板"]
]).outerHTML
},
x: { defaultValue: window.innerWidth * 0.1 },
y: { defaultValue: window.innerWidth * 0.1 },
visual: { defaultValue: "normal" },
firstCloseAlert: {
defaultValue: true
},
fontsize: {
label: "字体大小(像素)",
attrs: { type: "number", min: 12, max: 24, step: 1 },
defaultValue: 14
},
switchPoint: {
label: "窗口显示连点(次数)",
attrs: {
type: "number",
min: 3,
max: 10,
step: 1,
title: "设置当连续点击屏幕 N 次时,可以进行面板的 隐藏/显示 切换,默认连续点击屏幕三下"
},
defaultValue: 3
}
},
methods() {
return {
pin: (script2) => start_12.$win === null || start_12.$win === void 0 ? void 0 : start_12.$win.pin(script2),
minimize: () => start_12.$win === null || start_12.$win === void 0 ? void 0 : start_12.$win.minimize(),
setPosition: (x, y) => {
if (start_12.$win) {
start_12.$win.config.store.setPosition(x, y);
start_12.$win.container.style.left = x + "px";
start_12.$win.container.style.top = y + "px";
}
},
normal: () => {
start_12.$win === null || start_12.$win === void 0 ? void 0 : start_12.$win.normal();
}
};
},
onrender({ panel }) {
const closeBtn = (0, dom_12.h)("button", { className: "base-style-button" }, "隐藏窗口");
closeBtn.onclick = () => {
if (this.cfg.firstCloseAlert) {
exports3.$modal.confirm({
content: ui_12.$ui.notes([
"隐藏脚本页面后,快速点击页面三下(可以在悬浮窗设置中调整次数)即可重新显示脚本。如果三下无效,可以尝试删除脚本重新安装。",
"请确认是否关闭。(此后不再显示此弹窗)"
]),
onConfirm: () => {
start_12.$win === null || start_12.$win === void 0 ? void 0 : start_12.$win.hidden();
this.cfg.firstCloseAlert = false;
}
});
} else {
start_12.$win === null || start_12.$win === void 0 ? void 0 : start_12.$win.hidden();
}
};
panel.body.replaceChildren((0, dom_12.h)("hr"), closeBtn);
}
});
exports3.createRenderScript = createRenderScript;
function _modal(type, attrs, parent) {
if (self === top) {
return (0, custom_window_12.modal)(type, attrs, parent);
} else {
interfaces_12.cors.emit("modal", [type, attrs], (args) => {
var _a, _b, _c;
if (args) {
(_a = attrs.onConfirm) === null || _a === void 0 ? void 0 : _a.call(attrs, args);
} else {
(_b = attrs.onCancel) === null || _b === void 0 ? void 0 : _b.call(attrs);
}
(_c = attrs.onClose) === null || _c === void 0 ? void 0 : _c.call(attrs, args);
});
}
}
exports3.$modal = {
confirm: (attrs, parent) => _modal("confirm", attrs, parent),
alert: (attrs, parent) => _modal("alert", attrs, parent),
prompt: (attrs, parent) => _modal("prompt", attrs, parent),
simple: (attrs, parent) => _modal("simple", attrs, parent)
};
function _message(type, attrs) {
if (self === top) {
return start_12.$win === null || start_12.$win === void 0 ? void 0 : start_12.$win.message(type, attrs);
} else {
if (typeof attrs === "string") {
attrs = { content: attrs };
} else if (typeof attrs.content !== "string") {
attrs.content = attrs.content.innerHTML;
}
interfaces_12.cors.emit("message", [type, attrs]);
}
}
exports3.$message = {
info: (attrs) => _message("info", attrs),
success: (attrs) => _message("success", attrs),
warn: (attrs) => _message("warn", attrs),
error: (attrs) => _message("error", attrs)
};
function $menu(label, config2) {
if (self !== top) {
return;
}
return start_12.$win === null || start_12.$win === void 0 ? void 0 : start_12.$win.menu(label, config2);
}
exports3.$menu = $menu;
})(render);
(function(exports3) {
var __createBinding = commonjsGlobal && commonjsGlobal.__createBinding || (Object.create ? function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() {
return m[k];
} };
}
Object.defineProperty(o, k2, desc);
} : function(o, m, k, k2) {
if (k2 === void 0)
k2 = k;
o[k2] = m[k];
});
var __exportStar = commonjsGlobal && commonjsGlobal.__exportStar || function(m, exports4) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports4, p))
__createBinding(exports4, m, p);
};
Object.defineProperty(exports3, "__esModule", { value: true });
exports3.start = void 0;
var start_12 = start$1;
Object.defineProperty(exports3, "start", { enumerable: true, get: function() {
return start_12.start;
} });
__exportStar(utils, exports3);
__exportStar(render, exports3);
__exportStar(elements, exports3);
__exportStar(interfaces, exports3);
})(lib);
const ListOfActions = [
"click",
"check",
"dblclick",
"bringToFront",
"dragAndDrop",
"fill",
"focus",
"hover",
"screenshot",
"selectOption",
"setInputFiles",
"tap",
"press",
"reload",
"waitForRequest",
"waitForResponse",
"waitForSelector",
"keyboard.type",
"keyboard.press",
"mouse.wheel",
"mouse.click",
"mouse.dblclick",
"mouse.down",
"mouse.up",
"mouse.move"
];
const mouseIdleRequireActions = [
"click",
"dblclick",
"dragAndDrop",
"fill",
"hover",
"tap",
"press",
"keyboard.type",
"keyboard.press",
"mouse.wheel",
"mouse.click",
"mouse.dblclick",
"mouse.down",
"mouse.up",
"mouse.move"
];
class RemotePlaywright {
static async getRemotePage(show_debug_cursor, logger) {
if (this.currentPage) {
return this.currentPage;
}
if (!this.authToken) {
try {
this.authToken = await request("http://localhost:15319/get-actions-key", {
type: "GM_xmlhttpRequest",
method: "get",
responseType: "text"
});
this.currentPage = this.createRemotePage(this.authToken, { show_debug_cursor, logger });
return this.currentPage;
} catch (e) {
console.log(e);
return void 0;
}
} else {
this.currentPage = this.createRemotePage(this.authToken, { show_debug_cursor, logger });
return this.currentPage;
}
}
static createRemotePage(authToken, configs) {
const page = /* @__PURE__ */ Object.create({});
configs = configs || {};
configs.logger = configs.logger || console.debug;
for (const property of ListOfActions) {
Reflect.set(page, property, async (...args) => {
var _a, _b, _c;
let data;
if (mouseIdleRequireActions.includes(property)) {
await waitForMouseIdle();
}
if (property === "click") {
if (args[0] instanceof Element) {
const el = args[0];
const options = args[1] || {};
await scrollToElement(el);
await $.sleep(500);
const rect = el.getBoundingClientRect();
const elFromPoint = (_a = lib.$elements.root) == null ? void 0 : _a.elementFromPoint(
rect.left + rect.width / 2,
rect.top + rect.height / 2
);
if (elFromPoint && lib.$elements.root && lib.$elements.root.contains(elFromPoint)) {
const panel = lib.$elements.root.querySelector("container-element");
if (panel) {
lib.$message.info({ content: "检测到脚本阻挡点击位置,已自动移开", duration: 2 });
await $.transition(panel, "left", 0.1, rect.left + rect.width / 2 + 100 + "px", { reset_ms: 1 });
}
}
if (configs == null ? void 0 : configs.show_debug_cursor) {
showMousePointer(el);
}
data = {
page: window.location.href,
property: "mouse.click",
args: [
rect.left + rect.width / 2,
rect.top + rect.height / 2,
{
button: options.button,
clickCount: options.clickCount,
delay: options.delay
}
]
};
} else if (typeof args[0] === "string") {
const el = document.querySelector(args[0]);
if (el) {
await scrollToElement(el);
if (configs == null ? void 0 : configs.show_debug_cursor) {
showMousePointer(el);
}
}
}
}
if (!data) {
data = { page: window.location.href, property, args };
}
(_b = configs == null ? void 0 : configs.logger) == null ? void 0 : _b.call(configs, "[RP]: ", JSON.stringify(data));
try {
const res = await request("/ocs-script-actions", {
type: "fetch",
method: "post",
responseType: ["waitForRequest", "waitForResponse", "reload"].includes(property) ? "json" : "text",
headers: {
"auth-token": authToken
},
data
});
return res;
} catch (e) {
(_c = configs == null ? void 0 : configs.logger) == null ? void 0 : _c.call(configs, "[RP-ERROR]: ", JSON.stringify(data));
return void 0;
}
});
}
console.log(page);
return page;
}
}
RemotePlaywright.authToken = "";
RemotePlaywright.currentPage = void 0;
function scrollToElement(el) {
el.scrollIntoView({ behavior: "smooth", block: "center" });
return $.sleep(200);
}
function showMousePointer(el) {
setTimeout(() => {
const rect = el.getBoundingClientRect();
const div = document.createElement("div");
div.textContent = "";
div.style.position = "fixed";
div.style.zIndex = "99999";
div.style.width = "20px";
div.style.height = "20px";
div.style.border = "2px solid red";
div.style.borderRadius = "50%";
div.style.left = rect.left + rect.width / 2 - 11 + "px";
div.style.top = rect.top + rect.height / 2 - 11 + "px";
document.body.append(div);
setTimeout(() => {
div.remove();
}, 500);
}, 100);
}
function waitForMouseIdle(timeout = 200) {
return new Promise((resolve) => {
let timer;
const default_timer = setTimeout(() => {
window.removeEventListener("mousemove", onMouseMove);
resolve();
}, timeout);
function onMouseMove() {
clearTimeout(default_timer);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
window.removeEventListener("mousemove", onMouseMove);
resolve();
}, timeout);
}
window.addEventListener("mousemove", onMouseMove);
});
}
function defaultWorkTypeResolver(ctx) {
function count(selector) {
let c = 0;
for (const option of ctx.elements.options || []) {
if ((option == null ? void 0 : option.querySelector(selector)) !== null) {
c++;
}
}
return c;
}
return count('[type="radio"]') === 2 ? "judgement" : count('[type="radio"]') > 2 ? "single" : count('[type="checkbox"]') > 2 ? "multiple" : count("textarea") >= 1 ? "completion" : void 0;
}
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;
}
function resolvePlainAnswer(answer) {
const resolve = answer.trim().replace(/[,,.。.、 #]/g, "").trim();
if (isPlainAnswer(resolve)) {
return resolve;
}
}
function isProgramAnswer(answer) {
const code = (answer != null ? answer : "").trim();
if (!code)
return false;
if (!/[;|;]/.test(code))
return false;
let score = 0;
const strong = [
/#include\s*[<"]/,
/#define\s+\w/,
/#!\//,
/\b(?:int|void|float|double|char|long|short)\s+main\s*\(/,
/\bfunction\s+\w+\s*\(/,
/\bdef\s+\w+\s*\(/,
/\bpublic\s+(?:class|static|void|int|float|double|String|final)\b/,
/\bprivate\s+(?:class|static|void|int|float|double|String|final)\b/,
/\bprotected\s+(?:class|static|void|int|float|double|String|final)\b/,
/\bprintf\s*\(/,
/\bscanf\s*\(/,
/\bcout\s*<,
/\bcin\s*>>/,
/System\.out\./,
/console\.log\s*\(/,
/\bpackage\s+[\w.]+\s*;/,
/\bimport\s+[\w.*]+\s*;/,
/\bclass\s+\w+\s*\{/,
/\bstruct\s+\w+\s*\{/
];
for (const re2 of strong)
if (re2.test(code))
score += 2;
const medium = [
/=>/,
/->/,
/::/,
/\+\+/,
/--/,
/[+\-*/%]=/,
/\bnew\s+\w+\s*\(/,
/\bfor\s*\(/,
/\bwhile\s*\(/,
/\bif\s*\(/,
/\bswitch\s*\(/,
/\btypedef\s+/,
/\b(?:int|float|double|char|void|bool|boolean|long|short|String|auto|const|let|var)\s+\w+/,
/\bsizeof\s*\(/,
/\bmalloc\s*\(/,
/\bfree\s*\(/,
/\bcout\b/,
/\bcin\b/
];
for (const re2 of medium)
if (re2.test(code))
score += 1;
if (/\{/.test(code) && /\}/.test(code))
score += 1;
if (/;/.test(code))
score += 1;
return score >= 2;
}
function splitAnswer(answer, separators = ["===", "#", "---", "###", "|", ";", ";"]) {
answer = answer.trim();
if (answer.length === 0) {
return [];
}
separators = separators.length === 0 ? ["===", "#", "---", "###", "|", ";", ";"] : separators;
separators = separators.filter((el) => el.trim().length > 0);
if (isProgramAnswer(answer)) {
separators = separators.filter((el) => el !== ";" && el !== "|" && el !== ";");
}
try {
const json = JSON.parse(answer);
if (Array.isArray(json)) {
return json.map(String).map((el) => el.trim()).filter((el) => el.length > 0);
}
} catch {
for (const sep of separators) {
if (answer.split(sep).length > 1) {
return answer.split(sep).map((el) => el.trim()).filter((el) => el.length > 0);
}
}
}
return [answer];
}
function resolveSingle(answers, options, separators) {
const allAnswer = answers.map((a) => splitAnswer(a, separators)).flat();
const optionStrings = options.map(removeRedundant);
const normalizedResult = answerNormalizedMatch(allAnswer, optionStrings);
if (normalizedResult.length) {
const index = optionStrings.findIndex((opt) => opt === normalizedResult[0]);
if (index !== -1) {
return { finish: true, option: options[index] };
}
}
const ratings = answerSimilar(allAnswer, optionStrings);
let bestIndex = -1;
let bestRating = 0;
ratings.forEach((r, i) => {
if (r.rating > bestRating) {
bestRating = r.rating;
bestIndex = i;
}
});
if (bestIndex !== -1 && bestRating > 0.6) {
return {
finish: true,
option: options[bestIndex],
ratings: ratings.map((r) => r.rating)
};
}
for (const answer of allAnswer) {
const ans = resolvePlainAnswer(StringUtils.nowrap(answer, "").trim());
if (ans && ans.length === 1) {
const index = ans.charCodeAt(0) - 65;
if (optionStrings[index] !== void 0) {
return { finish: true, option: options[index] };
}
}
}
if (allAnswer.length > 1) {
const merged = allAnswer.join("");
const r = resolveSingle([merged], options, separators);
if (r.finish) {
return r;
}
}
return { finish: false, allAnswer, options: optionStrings };
}
function resolveMultiple(resultAnswers, options, separators) {
const optionStrings = options.map(removeRedundant);
const groups = [];
for (let i = 0; i < resultAnswers.length; i++) {
const answers = splitAnswer(resultAnswers[i].trim(), separators);
const normalizedGroup = {
options: [],
answers: [],
ratings: [],
similarSum: 0,
similarCount: 0
};
const normalizedOptions = answerNormalizedMatch(answers, optionStrings);
for (const opt of normalizedOptions) {
const idx = optionStrings.indexOf(opt);
if (idx !== -1) {
const matchedAns = answers.find((a) => {
const na2 = normalizeString(removeRedundant(a));
const no2 = normalizeString(removeRedundant(opt));
return na2 === no2 || na2.includes(no2);
});
if (!matchedAns)
continue;
normalizedGroup.options.push(options[idx]);
normalizedGroup.answers.push(matchedAns);
const na = normalizeString(removeRedundant(matchedAns));
const no = normalizeString(removeRedundant(opt));
const rating = na === no ? 1 : 0.8;
normalizedGroup.ratings.push(rating);
normalizedGroup.similarSum += rating;
normalizedGroup.similarCount += 1;
}
}
const normalizedDisambiguated = disambiguateSimilarOptions(normalizedGroup.options, normalizedGroup.ratings);
const normalizedKeptIndices = normalizedDisambiguated.map((opt) => normalizedGroup.options.indexOf(opt));
normalizedGroup.options = normalizedDisambiguated;
normalizedGroup.answers = normalizedKeptIndices.map((idx) => normalizedGroup.answers[idx]);
normalizedGroup.ratings = normalizedKeptIndices.map((idx) => normalizedGroup.ratings[idx]);
normalizedGroup.similarCount = normalizedGroup.options.length;
normalizedGroup.similarSum = normalizedGroup.ratings.reduce((a, b) => a + b, 0);
const ratingGroup = { options: [], answers: [], ratings: [], similarSum: 0, similarCount: 0 };
const ratings = answerSimilarWithGap(answers, optionStrings);
for (let j = 0; j < ratings.length; j++) {
if (ratings[j].rating > 0.6) {
ratingGroup.options.push(options[j]);
ratingGroup.answers.push(ratings[j].target);
ratingGroup.ratings.push(ratings[j].rating);
ratingGroup.similarSum += ratings[j].rating;
ratingGroup.similarCount += 1;
}
}
const disambiguated = disambiguateSimilarOptions(ratingGroup.options, ratingGroup.ratings);
const keptIndices = disambiguated.map((opt) => ratingGroup.options.indexOf(opt));
ratingGroup.options = disambiguated;
ratingGroup.answers = keptIndices.map((idx) => ratingGroup.answers[idx]);
ratingGroup.ratings = keptIndices.map((idx) => ratingGroup.ratings[idx]);
ratingGroup.similarCount = ratingGroup.options.length;
ratingGroup.similarSum = ratingGroup.ratings.reduce((a, b) => a + b, 0);
const best = [normalizedGroup, ratingGroup].sort(
(a, b) => b.similarCount * 100 + b.similarSum - a.similarCount * 100 - a.similarSum
)[0];
groups[i] = best;
}
const sorted = groups.filter((g) => g.similarCount !== 0).sort((a, b) => {
const bsc = b.similarCount * 100;
const asc = a.similarCount * 100;
return bsc + b.similarSum - asc - a.similarSum;
});
if (sorted[0]) {
return { finish: true, options: sorted[0].options, groups: sorted };
}
const plainOptions = [];
for (const answer of resultAnswers) {
const ans = StringUtils.nowrap(answer, "").trim();
if (resolvePlainAnswer(ans)) {
for (const char of ans) {
const index = char.charCodeAt(0) - 65;
if (options[index] !== void 0) {
plainOptions.push(options[index]);
}
}
}
}
if (plainOptions.length) {
return { finish: true, plainOptions: [...new Set(plainOptions)] };
}
return { finish: false };
}
function disambiguateSimilarOptions(options, ratings, threshold = 0.6) {
if (options.length <= 1)
return options;
const normalized = options.map((o) => normalizeString(removeRedundant(o)));
const eliminated = /* @__PURE__ */ new Set();
for (let i = 0; i < options.length; i++) {
if (eliminated.has(i))
continue;
for (let j = i + 1; j < options.length; j++) {
if (eliminated.has(j))
continue;
const pairwise = src.findBestMatch(normalized[i], [normalized[j]]).bestMatch.rating;
if (pairwise > threshold) {
if (ratings[i] >= ratings[j]) {
eliminated.add(j);
} else {
eliminated.add(i);
break;
}
}
}
}
return options.filter((_, i) => !eliminated.has(i));
}
const CORRECT_WORDS = ["是", "对", "正确", "确定", "√", "对的", "是的", "正确的", "true", "True", "T", "yes", "1"];
const INCORRECT_WORDS = [
"非",
"否",
"错",
"错误",
"×",
"X",
"错的",
"不对",
"不正确的",
"不正确",
"不是",
"不是的",
"false",
"False",
"F",
"no",
"0"
];
function resolveJudgement(answerGroups, options) {
for (const answers of answerGroups) {
const answerShowCorrect = answers.find((a) => matches(a, CORRECT_WORDS));
const answerShowIncorrect = answers.find((a) => matches(a, INCORRECT_WORDS));
if (answerShowCorrect || answerShowIncorrect) {
for (const option of options) {
const textShowCorrect = matches(option, CORRECT_WORDS);
const textShowIncorrect = matches(option, INCORRECT_WORDS);
if (answerShowCorrect && textShowCorrect) {
return { finish: true, option };
}
if (answerShowIncorrect && textShowIncorrect) {
return { finish: true, option };
}
}
return { finish: false };
}
}
return { finish: false };
}
function matches(target, words) {
return words.some(
(word) => clearString(removeRedundant(word), "√", "×") === clearString(removeRedundant(target), "√", "×")
);
}
function isJudgementOptions(options) {
if (options.length !== 2)
return false;
const hasCorrect = options.some((opt) => matches(opt, CORRECT_WORDS));
const hasIncorrect = options.some((opt) => matches(opt, INCORRECT_WORDS));
return hasCorrect && hasIncorrect;
}
function resolveCompletion(answerGroups, blankCount, separators) {
for (const answers of answerGroups) {
let ans = answers.filter((a) => a);
if (ans.length === 1) {
ans = splitAnswer(ans[0], separators);
}
if (ans.length !== 0 && (ans.length === blankCount || blankCount === 1)) {
if (ans.length === blankCount) {
return { finish: true, answers: ans };
} else if (blankCount === 1) {
return { finish: true, answers: [ans.join(" ")] };
}
}
}
return { finish: false };
}
function createDefaultQuestionResolver(ctx, optionText) {
const toText = (o, i) => optionText ? optionText(o, i) : o.innerText;
return {
async single(infos, options, handler) {
const optionTexts = options.map((o, i) => toText(o, i));
if (isJudgementOptions(optionTexts.map((o) => o.trim()))) {
const answerGroups = infos.map((info) => info.results.map((res) => res.answer));
const result2 = resolveJudgement(answerGroups, optionTexts);
if (result2.finish && result2.option !== void 0) {
const index = optionTexts.indexOf(result2.option);
const opt = index !== -1 ? options[index] : options[0];
await handler("judgement", result2.option, opt, ctx);
}
return result2;
}
const answers = infos.map((info) => info.results.map((res) => res.answer)).flat();
const result = resolveSingle(answers, optionTexts, ctx.answerSeparators);
if (result.finish && result.option !== void 0) {
const index = optionTexts.indexOf(result.option);
const opt = index !== -1 ? options[index] : options[0];
await handler("single", result.option, opt, ctx);
}
return result;
},
async multiple(infos, options, handler) {
var _a;
const resultAnswers = infos.map((info) => info.results.map((res) => res.answer)).flat();
const optionTexts = options.map((o, i) => toText(o, i));
const result = resolveMultiple(resultAnswers, optionTexts, ctx.answerSeparators);
const resolvedOptions = result.finish ? (_a = result.options) != null ? _a : result.plainOptions : void 0;
if (result.finish && resolvedOptions) {
for (const optText of resolvedOptions) {
const index = optionTexts.indexOf(optText);
const opt = index !== -1 ? options[index] : options[0];
await handler("multiple", optText, opt, ctx);
}
}
return result;
},
async judgement(infos, options, handler) {
const answerGroups = infos.map((info) => info.results.map((res) => res.answer));
const optionTexts = options.map((o, i) => toText(o, i));
const result = resolveJudgement(answerGroups, optionTexts);
if (result.finish && result.option !== void 0) {
const index = optionTexts.indexOf(result.option);
const opt = index !== -1 ? options[index] : options[0];
await handler("judgement", result.option, opt, ctx);
}
return result;
},
async completion(infos, options, handler) {
const answerGroups = infos.map((info) => info.results.map((res) => res.answer));
const result = resolveCompletion(answerGroups, options.length, ctx.answerSeparators);
if (result.finish && result.answers) {
for (let i = 0; i < result.answers.length; i++) {
await handler("completion", result.answers[i], options[i], ctx);
}
}
return result;
}
};
}
const AnswerWrapperHandlerConfig = {
timeout_seconds: 60
};
async function defaultAnswerWrapperHandler(answererWrappers, env) {
const searchInfos = [];
const temp = JSON.parse(JSON.stringify(answererWrappers));
if (temp.length === 0) {
throw new Error("题库配置不能为空,请配置后重新开始自动答题。");
}
if (env.title === void 0)
env.title = "";
if (env.options === void 0)
env.options = "";
if (env.type === void 0)
env.type = "unknown";
if (env.images === void 0)
env.images = [];
if (env.suggestion_title === void 0)
env.suggestion_title = "";
if (env.suggestion_options === void 0)
env.suggestion_options = "";
await Promise.all(
temp.map(async (wrapper) => {
var _a;
const {
name = "未知题库",
homepage = "#",
method = "get",
type = "fetch",
contentType = "json",
responseType = "json",
headers = {},
data: wrapperData = {},
handler = "return (res)=> [JSON.stringify(res), undefined]"
} = wrapper;
if (method.toLocaleLowerCase() === "post") {
if (!Object.keys(headers).some((k) => k.toLowerCase() === "content-type")) {
headers["Content-Type"] = "application/json";
}
}
try {
let results = [];
let requestData;
let url;
if (method.toLocaleLowerCase() === "get") {
url = new URL(resolvePlaceHolder(wrapper.url, { encodeURI: true }));
Object.keys(wrapperData).forEach((key) => {
url.searchParams.set(key, resolvePlaceHolder(wrapperData[key]));
});
requestData = {};
} else if (method.toLocaleLowerCase() === "post") {
url = new URL(wrapper.url);
const data = /* @__PURE__ */ Object.create({});
Object.keys(wrapperData).forEach((key) => {
if (typeof wrapperData[key] === "object" && Reflect.has(wrapperData[key], "handler")) {
const handler2 = Function(Reflect.get(wrapperData[key], "handler"))();
if (typeof handler2 !== "function") {
throw new Error("data 字段解析器必须返回一个函数");
}
const result = handler2(env);
Reflect.set(data, key, result);
} else {
Reflect.set(data, key, resolvePlaceHolder(wrapperData[key]));
}
});
requestData = data;
} else {
throw new Error("不支持的请求方式");
}
const responseData = await Promise.race([
request(url.toString(), {
method,
responseType: responseType || contentType,
data: requestData,
type,
headers: JSON.parse(JSON.stringify(headers || {}))
}),
$.sleep(((_a = AnswerWrapperHandlerConfig.timeout_seconds) != null ? _a : 60) * 1e3)
]);
if (responseData === void 0) {
throw new Error("题库请求超时,可能是题库问题,或者请检查网络或者重试。");
}
const responseHandler = Function(handler)();
if (typeof responseHandler !== "function") {
throw new Error("handler 响应处理器必须返回一个函数");
}
const info = responseHandler(responseData);
if (info && Array.isArray(info)) {
if (info.every((item) => Array.isArray(item))) {
results = results.concat(
info.map((item) => ({
question: item[0],
answer: item[1],
extra_data: item[2] || {}
}))
);
} else {
results.push({
question: info[0],
answer: info[1],
extra_data: info[2] || {}
});
}
}
searchInfos.push({
url: wrapper.url,
name,
homepage,
results,
response: responseData,
data: requestData
});
} catch (error) {
console.error(error);
searchInfos.push({
url: wrapper.url,
name,
homepage,
results: [],
response: void 0,
data: void 0,
error: (error == null ? void 0 : error.message) || "题库连接失败"
});
}
})
);
function resolvePlaceHolder(data, options) {
if (typeof data === "string") {
const matches2 = data.match(/\${(.*?)}/g) || [];
matches2.forEach((placeHolder) => {
const value = env[placeHolder.replace(/\${(.*)}/, "$1")];
data = data.replace(placeHolder, (options == null ? void 0 : options.encodeURI) ? encodeURIComponent(value) : value);
});
} else if (typeof data === "object") {
const keys = Object.keys(data);
for (const key of keys) {
data[key] = resolvePlaceHolder(data[key], options);
}
}
return data;
}
return searchInfos;
}
class AnswerWrapperParser {
static fromObject(json) {
const aw = json;
if (aw && Array.isArray(aw)) {
if (aw.length) {
for (let i = 0; i < aw.length; i++) {
const item = aw[i];
if (typeof item.name !== "string") {
throw new Error(`第 ${i + 1} 个题库的 名字(name) 为空`);
}
if (typeof item.url !== "string") {
throw new Error(`第 ${i + 1} 个题库的 接口地址(url) 为空`);
}
if (typeof item.handler !== "string") {
throw new Error(`第 ${i + 1} 个题库的 解析器(handler) 为空`);
}
if (item.headers && typeof item.headers !== "object") {
throw new Error(`第 ${i + 1} 个题库的 头部信息(header) 应为 对象 格式`);
}
if (item.data && typeof item.data !== "object") {
throw new Error(`第 ${i + 1} 个题库的 提交数据(data) 应为 对象 格式`);
}
const contentTypes = ["json", "text"];
if (item.contentType && contentTypes.every((i2) => i2 !== item.contentType)) {
throw new Error(`第 ${i + 1} 个题库的 contentType 必须为以下选项中的一个 ${contentTypes.join(", ")}`);
}
const methods = ["post", "get"];
if (item.method && methods.every((i2) => i2 !== item.method)) {
throw new Error(`第 ${i + 1} 个题库的 method 必须为以下选项中的一个 ${methods.join(", ")}`);
}
const types = ["fetch", "GM_xmlhttpRequest"];
if (item.type && types.every((i2) => i2 !== item.type)) {
throw new Error(`第 ${i + 1} 个题库的 type 必须为以下选项中的一个 ${types.join(", ")}`);
}
}
return aw;
} else {
throw new Error("题库为空!");
}
} else {
throw new Error("题库配置格式错误!");
}
}
static fromJSONString(json) {
const raw = json.toString();
try {
return JSON.parse(raw);
} catch {
throw new Error(`格式错误,必须为:json字符串`);
}
}
static fromBase64(base64) {
return this.fromJSONString(Buffer.from(base64, "base64").toString("utf8"));
}
static from(value) {
if (typeof value === "string") {
if (/^\s*https?:\/\//.test(value)) {
throw new Error("已不支持从链接加载题库配置,请直接粘贴题库配置内容,或使用「一键获取题库」功能。");
}
return this.fromJSONString(value);
} else {
return this.fromObject(value);
}
}
}
class OCSWorker extends lib.CommonEventEmitter {
constructor(opts) {
super();
this.isRunning = false;
this.isClose = false;
this.isStop = false;
this.totalQuestionCount = 0;
this.opts = opts;
}
startRootObserver() {
var _a, _b;
const cfg = this.opts.rootObserver;
if (!(cfg == null ? void 0 : cfg.enabled) || this.rootObserverTimer !== void 0) {
return;
}
const interval = (_a = cfg.checkIntervalMs) != null ? _a : 1e3;
const lostTimeout = (_b = cfg.lostTimeoutMs) != null ? _b : 1e3;
this.rootObserverTimer = setInterval(() => {
var _a2, _b2;
if (this.isClose) {
this.stopRootObserver();
return;
}
const alive = typeof this.opts.root === "string" ? !!document.querySelector(this.opts.root) : this.opts.root.some((el) => el.isConnected);
if (alive) {
this.rootLostSince = void 0;
return;
}
(_a2 = this.rootLostSince) != null ? _a2 : this.rootLostSince = Date.now();
if (Date.now() - this.rootLostSince >= lostTimeout) {
this.stopRootObserver();
(_b2 = cfg.onRootLost) == null ? void 0 : _b2.call(cfg);
if (!this.isClose) {
lib.$message.warn({
content: "⚠️ 题目元素已从页面消失(页面可能已跳转或刷新),答题程序已自动关闭。",
duration: 0
});
}
this.emit("close");
}
}, interval);
}
stopRootObserver() {
if (this.rootObserverTimer !== void 0) {
clearInterval(this.rootObserverTimer);
this.rootObserverTimer = void 0;
}
this.rootLostSince = void 0;
}
async doWork(options) {
var _a, _b, _c, _d, _e, _f;
this.emit("start");
this.isRunning = true;
this.once("close", () => {
this.isClose = true;
this.stopRootObserver();
});
this.startRootObserver();
this.on("stop", () => {
this.isStop = true;
});
this.on("continuate", () => {
this.isStop = false;
});
const questionRoots = typeof this.opts.root === "string" ? Array.from(document.querySelectorAll(this.opts.root)) : this.opts.root;
this.totalQuestionCount += questionRoots.length;
if (options == null ? void 0 : options.enable_debug) {
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
};
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.options = (_d = ctx.elements.options) == null ? void 0 : _d.filter(Boolean);
if (typeof this.opts.work === "object") {
ctx.type = this.opts.work.type === void 0 ? defaultWorkTypeResolver(ctx) : typeof this.opts.work.type === "string" ? this.opts.work.type : this.opts.work.type(ctx);
}
results.push({
requested: false,
resolved: false,
ctx
});
await ((_f = (_e = this.opts).onQuestionDetected) == null ? void 0 : _f.call(_e, results[results.length - 1], results));
}
if (options == null ? void 0 : options.enable_debug) {
console.debug("上下文已初始化: ", results);
}
const requestThread = async (index) => {
var _a2, _b2, _c2;
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);
}
ctx.searchInfos = [];
if (options == null ? void 0 : options.enable_debug) {
console.groupEnd();
console.group(
"开始搜题: ",
(_a2 = ctx.elements.title) == null ? void 0 : _a2.map((t2) => t2 == null ? void 0 : t2.innerText).filter(Boolean).join(", ").slice(0, 20)
);
console.log("ctx", result.ctx);
}
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);
}
result.ctx = ctx;
result.requested = true;
result.error = error;
if (options == null ? void 0 : options.enable_debug) {
console.log("搜题结果: ", ctx.searchInfos);
}
await ((_c2 = (_b2 = this.opts).onResultsUpdate) == null ? void 0 : _c2.call(_b2, results[index], index, results));
};
const waitForRequested = async (result) => {
return new Promise((resolve, reject) => {
const interval = setInterval(() => {
if ((result == null ? void 0 : result.requested) === true) {
clearInterval(interval);
clearTimeout(timeout);
resolve();
}
}, 200);
const timeout = setTimeout(() => {
clearInterval(interval);
reject(new Error("答题超时!"));
}, (AnswerWrapperHandlerConfig.timeout_seconds + 10) * 1e3);
});
};
const resolverThread = async () => {
var _a2, _b2, _c2, _d2;
for (let index = 0; index < results.length; index++) {
const result = results[index];
let error;
let res;
if (this.isClose === true) {
this.isRunning = false;
return;
}
try {
if (this.isStop) {
await waitForContinuate(() => this.isStop);
}
await waitForRequested(result);
} catch (err) {
}
try {
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 = createDefaultQuestionResolver(
result.ctx,
this.opts.work.optionText
)[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.log(
"答题完成: ",
(_b2 = (_a2 = result.ctx) == null ? void 0 : _a2.elements.title) == null ? void 0 : _b2.map((t2) => t2 == null ? void 0 : t2.innerText).join(", ").slice(0, 20),
result
);
}
await ((_d2 = (_c2 = this.opts).onResultsUpdate) == null ? void 0 : _d2.call(_c2, 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()));
}
}
}
}
class CustomOCSWorker extends lib.CommonEventEmitter {
constructor(opts) {
super();
this.isRunning = false;
this.isClose = false;
this.isStop = false;
this.opts = opts;
}
async doWork(options) {
var _a, _b, _c, _d, _e, _f, _g, _h;
this.emit("start");
this.isRunning = true;
this.once("close", () => {
this.isClose = true;
});
this.on("stop", () => {
this.isStop = true;
});
this.on("continuate", () => {
this.isStop = false;
});
const questions = await ((_b = (_a = this.opts).questions) == null ? void 0 : _b.call(_a));
if (options == null ? void 0 : options.enable_debug) {
console.debug("开始答题", this);
console.debug("题目数量: ", this.opts.questions.length);
}
const results = [];
for (let index = 0; index < questions.length; index++) {
if (this.isClose === true) {
this.isRunning = false;
return;
}
if (this.isStop) {
await waitForContinuate(() => this.isStop);
}
const question = questions[index];
results[index] = {
question: question.text,
requested: false,
resolved: false,
searchInfos: [],
type: question.type,
finish: false,
error: ""
};
try {
const infos = await this.opts.answerer(question.text);
results[index].searchInfos = infos.map((i) => ({
name: i.name,
homepage: i.homepage,
results: i.results.map((r) => [r.question, r.answer, r.extra_data || {}]),
error: i.error
}));
results[index].requested = true;
(_d = (_c = this.opts).onResultsUpdate) == null ? void 0 : _d.call(_c, results[index], index, results);
try {
const resolved = await this.opts.resolver(infos);
results[index].finish = resolved.finish;
results[index].error = resolved.error;
results[index].resolved = true;
} catch (err) {
results[index].finish = false;
results[index].error = err instanceof Error ? err.message : String(err);
results[index].resolved = true;
}
(_f = (_e = this.opts).onResultsUpdate) == null ? void 0 : _f.call(_e, results[index], index, results);
} catch (err) {
results[index].requested = true;
results[index].resolved = false;
results[index].finish = true;
results[index].error = err instanceof Error ? err.message : String(err);
(_h = (_g = this.opts).onResultsUpdate) == null ? void 0 : _h.call(_g, results[index], index, results);
}
await lib.$.sleep(this.opts.period);
}
}
}
async function waitForContinuate(isStopping) {
if (isStopping()) {
await new Promise((resolve, reject) => {
const interval = setInterval(() => {
if (isStopping() === false) {
clearInterval(interval);
resolve();
}
}, 200);
});
}
}
function getDefaults() {
return {
async: false,
baseUrl: null,
breaks: false,
extensions: null,
gfm: true,
headerIds: true,
headerPrefix: "",
highlight: null,
hooks: null,
langPrefix: "language-",
mangle: true,
pedantic: false,
renderer: null,
sanitize: false,
sanitizer: null,
silent: false,
smartypants: false,
tokenizer: null,
walkTokens: null,
xhtml: false
};
}
let defaults = getDefaults();
function changeDefaults(newDefaults) {
defaults = newDefaults;
}
const escapeTest = /[&<>"']/;
const escapeReplace = new RegExp(escapeTest.source, "g");
const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, "g");
const escapeReplacements = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'"
};
const getEscapeReplacement = (ch) => escapeReplacements[ch];
function escape(html2, encode) {
if (encode) {
if (escapeTest.test(html2)) {
return html2.replace(escapeReplace, getEscapeReplacement);
}
} else {
if (escapeTestNoEncode.test(html2)) {
return html2.replace(escapeReplaceNoEncode, getEscapeReplacement);
}
}
return html2;
}
const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
function unescape(html2) {
return html2.replace(unescapeTest, (_, n) => {
n = n.toLowerCase();
if (n === "colon")
return ":";
if (n.charAt(0) === "#") {
return n.charAt(1) === "x" ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1));
}
return "";
});
}
const caret = /(^|[^\[])\^/g;
function edit(regex, opt) {
regex = typeof regex === "string" ? regex : regex.source;
opt = opt || "";
const obj = {
replace: (name, val) => {
val = val.source || val;
val = val.replace(caret, "$1");
regex = regex.replace(name, val);
return obj;
},
getRegex: () => {
return new RegExp(regex, opt);
}
};
return obj;
}
const nonWordAndColonTest = /[^\w:]/g;
const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
function cleanUrl(sanitize, base, href) {
if (sanitize) {
let prot;
try {
prot = decodeURIComponent(unescape(href)).replace(nonWordAndColonTest, "").toLowerCase();
} catch (e) {
return null;
}
if (prot.indexOf("javascript:") === 0 || prot.indexOf("vbscript:") === 0 || prot.indexOf("data:") === 0) {
return null;
}
}
if (base && !originIndependentUrl.test(href)) {
href = resolveUrl(base, href);
}
try {
href = encodeURI(href).replace(/%25/g, "%");
} catch (e) {
return null;
}
return href;
}
const baseUrls = {};
const justDomain = /^[^:]+:\/*[^/]*$/;
const protocol = /^([^:]+:)[\s\S]*$/;
const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
function resolveUrl(base, href) {
if (!baseUrls[" " + base]) {
if (justDomain.test(base)) {
baseUrls[" " + base] = base + "/";
} else {
baseUrls[" " + base] = rtrim(base, "/", true);
}
}
base = baseUrls[" " + base];
const relativeBase = base.indexOf(":") === -1;
if (href.substring(0, 2) === "//") {
if (relativeBase) {
return href;
}
return base.replace(protocol, "$1") + href;
} else if (href.charAt(0) === "/") {
if (relativeBase) {
return href;
}
return base.replace(domain, "$1") + href;
} else {
return base + href;
}
}
const noopTest = { exec: function noopTest2() {
} };
function splitCells(tableRow, count) {
const row = tableRow.replace(/\|/g, (match, offset, str) => {
let escaped = false, curr = offset;
while (--curr >= 0 && str[curr] === "\\")
escaped = !escaped;
if (escaped) {
return "|";
} else {
return " |";
}
}), cells = row.split(/ \|/);
let i = 0;
if (!cells[0].trim()) {
cells.shift();
}
if (cells.length > 0 && !cells[cells.length - 1].trim()) {
cells.pop();
}
if (cells.length > count) {
cells.splice(count);
} else {
while (cells.length < count)
cells.push("");
}
for (; i < cells.length; i++) {
cells[i] = cells[i].trim().replace(/\\\|/g, "|");
}
return cells;
}
function rtrim(str, c, invert) {
const l = str.length;
if (l === 0) {
return "";
}
let suffLen = 0;
while (suffLen < l) {
const currChar = str.charAt(l - suffLen - 1);
if (currChar === c && !invert) {
suffLen++;
} else if (currChar !== c && invert) {
suffLen++;
} else {
break;
}
}
return str.slice(0, l - suffLen);
}
function findClosingBracket(str, b) {
if (str.indexOf(b[1]) === -1) {
return -1;
}
const l = str.length;
let level = 0, i = 0;
for (; i < l; i++) {
if (str[i] === "\\") {
i++;
} else if (str[i] === b[0]) {
level++;
} else if (str[i] === b[1]) {
level--;
if (level < 0) {
return i;
}
}
}
return -1;
}
function checkSanitizeDeprecation(opt) {
if (opt && opt.sanitize && !opt.silent) {
console.warn("marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options");
}
}
function repeatString(pattern, count) {
if (count < 1) {
return "";
}
let result = "";
while (count > 1) {
if (count & 1) {
result += pattern;
}
count >>= 1;
pattern += pattern;
}
return result + pattern;
}
function outputLink(cap, link, raw, lexer) {
const href = link.href;
const title = link.title ? escape(link.title) : null;
const text2 = cap[1].replace(/\\([\[\]])/g, "$1");
if (cap[0].charAt(0) !== "!") {
lexer.state.inLink = true;
const token = {
type: "link",
raw,
href,
title,
text: text2,
tokens: lexer.inlineTokens(text2)
};
lexer.state.inLink = false;
return token;
}
return {
type: "image",
raw,
href,
title,
text: escape(text2)
};
}
function indentCodeCompensation(raw, text2) {
const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
if (matchIndentToCode === null) {
return text2;
}
const indentToCode = matchIndentToCode[1];
return text2.split("\n").map((node) => {
const matchIndentInNode = node.match(/^\s+/);
if (matchIndentInNode === null) {
return node;
}
const [indentInNode] = matchIndentInNode;
if (indentInNode.length >= indentToCode.length) {
return node.slice(indentToCode.length);
}
return node;
}).join("\n");
}
class Tokenizer {
constructor(options) {
this.options = options || defaults;
}
space(src2) {
const cap = this.rules.block.newline.exec(src2);
if (cap && cap[0].length > 0) {
return {
type: "space",
raw: cap[0]
};
}
}
code(src2) {
const cap = this.rules.block.code.exec(src2);
if (cap) {
const text2 = cap[0].replace(/^ {1,4}/gm, "");
return {
type: "code",
raw: cap[0],
codeBlockStyle: "indented",
text: !this.options.pedantic ? rtrim(text2, "\n") : text2
};
}
}
fences(src2) {
const cap = this.rules.block.fences.exec(src2);
if (cap) {
const raw = cap[0];
const text2 = indentCodeCompensation(raw, cap[3] || "");
return {
type: "code",
raw,
lang: cap[2] ? cap[2].trim().replace(this.rules.inline._escapes, "$1") : cap[2],
text: text2
};
}
}
heading(src2) {
const cap = this.rules.block.heading.exec(src2);
if (cap) {
let text2 = cap[2].trim();
if (/#$/.test(text2)) {
const trimmed = rtrim(text2, "#");
if (this.options.pedantic) {
text2 = trimmed.trim();
} else if (!trimmed || / $/.test(trimmed)) {
text2 = trimmed.trim();
}
}
return {
type: "heading",
raw: cap[0],
depth: cap[1].length,
text: text2,
tokens: this.lexer.inline(text2)
};
}
}
hr(src2) {
const cap = this.rules.block.hr.exec(src2);
if (cap) {
return {
type: "hr",
raw: cap[0]
};
}
}
blockquote(src2) {
const cap = this.rules.block.blockquote.exec(src2);
if (cap) {
const text2 = cap[0].replace(/^ *>[ \t]?/gm, "");
const top2 = this.lexer.state.top;
this.lexer.state.top = true;
const tokens = this.lexer.blockTokens(text2);
this.lexer.state.top = top2;
return {
type: "blockquote",
raw: cap[0],
tokens,
text: text2
};
}
}
list(src2) {
let cap = this.rules.block.list.exec(src2);
if (cap) {
let raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line, nextLine, rawLine, itemContents, endEarly;
let bull = cap[1].trim();
const isordered = bull.length > 1;
const list = {
type: "list",
raw: "",
ordered: isordered,
start: isordered ? +bull.slice(0, -1) : "",
loose: false,
items: []
};
bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
if (this.options.pedantic) {
bull = isordered ? bull : "[*+-]";
}
const itemRegex = new RegExp(`^( {0,3}${bull})((?:[ ][^\\n]*)?(?:\\n|$))`);
while (src2) {
endEarly = false;
if (!(cap = itemRegex.exec(src2))) {
break;
}
if (this.rules.block.hr.test(src2)) {
break;
}
raw = cap[0];
src2 = src2.substring(raw.length);
line = cap[2].split("\n", 1)[0].replace(/^\t+/, (t2) => " ".repeat(3 * t2.length));
nextLine = src2.split("\n", 1)[0];
if (this.options.pedantic) {
indent = 2;
itemContents = line.trimLeft();
} else {
indent = cap[2].search(/[^ ]/);
indent = indent > 4 ? 1 : indent;
itemContents = line.slice(indent);
indent += cap[1].length;
}
blankLine = false;
if (!line && /^ *$/.test(nextLine)) {
raw += nextLine + "\n";
src2 = src2.substring(nextLine.length + 1);
endEarly = true;
}
if (!endEarly) {
const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`);
const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`);
const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);
while (src2) {
rawLine = src2.split("\n", 1)[0];
nextLine = rawLine;
if (this.options.pedantic) {
nextLine = nextLine.replace(/^ {1,4}(?=( {4})*[^ ])/g, " ");
}
if (fencesBeginRegex.test(nextLine)) {
break;
}
if (headingBeginRegex.test(nextLine)) {
break;
}
if (nextBulletRegex.test(nextLine)) {
break;
}
if (hrRegex.test(src2)) {
break;
}
if (nextLine.search(/[^ ]/) >= indent || !nextLine.trim()) {
itemContents += "\n" + nextLine.slice(indent);
} else {
if (blankLine) {
break;
}
if (line.search(/[^ ]/) >= 4) {
break;
}
if (fencesBeginRegex.test(line)) {
break;
}
if (headingBeginRegex.test(line)) {
break;
}
if (hrRegex.test(line)) {
break;
}
itemContents += "\n" + nextLine;
}
if (!blankLine && !nextLine.trim()) {
blankLine = true;
}
raw += rawLine + "\n";
src2 = src2.substring(rawLine.length + 1);
line = nextLine.slice(indent);
}
}
if (!list.loose) {
if (endsWithBlankLine) {
list.loose = true;
} else if (/\n *\n *$/.test(raw)) {
endsWithBlankLine = true;
}
}
if (this.options.gfm) {
istask = /^\[[ xX]\] /.exec(itemContents);
if (istask) {
ischecked = istask[0] !== "[ ] ";
itemContents = itemContents.replace(/^\[[ xX]\] +/, "");
}
}
list.items.push({
type: "list_item",
raw,
task: !!istask,
checked: ischecked,
loose: false,
text: itemContents
});
list.raw += raw;
}
list.items[list.items.length - 1].raw = raw.trimRight();
list.items[list.items.length - 1].text = itemContents.trimRight();
list.raw = list.raw.trimRight();
const l = list.items.length;
for (i = 0; i < l; i++) {
this.lexer.state.top = false;
list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
if (!list.loose) {
const spacers = list.items[i].tokens.filter((t2) => t2.type === "space");
const hasMultipleLineBreaks = spacers.length > 0 && spacers.some((t2) => /\n.*\n/.test(t2.raw));
list.loose = hasMultipleLineBreaks;
}
}
if (list.loose) {
for (i = 0; i < l; i++) {
list.items[i].loose = true;
}
}
return list;
}
}
html(src2) {
const cap = this.rules.block.html.exec(src2);
if (cap) {
const token = {
type: "html",
raw: cap[0],
pre: !this.options.sanitizer && (cap[1] === "pre" || cap[1] === "script" || cap[1] === "style"),
text: cap[0]
};
if (this.options.sanitize) {
const text2 = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
token.type = "paragraph";
token.text = text2;
token.tokens = this.lexer.inline(text2);
}
return token;
}
}
def(src2) {
const cap = this.rules.block.def.exec(src2);
if (cap) {
const tag = cap[1].toLowerCase().replace(/\s+/g, " ");
const href = cap[2] ? cap[2].replace(/^<(.*)>$/, "$1").replace(this.rules.inline._escapes, "$1") : "";
const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline._escapes, "$1") : cap[3];
return {
type: "def",
tag,
raw: cap[0],
href,
title
};
}
}
table(src2) {
const cap = this.rules.block.table.exec(src2);
if (cap) {
const item = {
type: "table",
header: splitCells(cap[1]).map((c) => {
return { text: c };
}),
align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */),
rows: cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, "").split("\n") : []
};
if (item.header.length === item.align.length) {
item.raw = cap[0];
let l = item.align.length;
let i, j, k, row;
for (i = 0; i < l; i++) {
if (/^ *-+: *$/.test(item.align[i])) {
item.align[i] = "right";
} else if (/^ *:-+: *$/.test(item.align[i])) {
item.align[i] = "center";
} else if (/^ *:-+ *$/.test(item.align[i])) {
item.align[i] = "left";
} else {
item.align[i] = null;
}
}
l = item.rows.length;
for (i = 0; i < l; i++) {
item.rows[i] = splitCells(item.rows[i], item.header.length).map((c) => {
return { text: c };
});
}
l = item.header.length;
for (j = 0; j < l; j++) {
item.header[j].tokens = this.lexer.inline(item.header[j].text);
}
l = item.rows.length;
for (j = 0; j < l; j++) {
row = item.rows[j];
for (k = 0; k < row.length; k++) {
row[k].tokens = this.lexer.inline(row[k].text);
}
}
return item;
}
}
}
lheading(src2) {
const cap = this.rules.block.lheading.exec(src2);
if (cap) {
return {
type: "heading",
raw: cap[0],
depth: cap[2].charAt(0) === "=" ? 1 : 2,
text: cap[1],
tokens: this.lexer.inline(cap[1])
};
}
}
paragraph(src2) {
const cap = this.rules.block.paragraph.exec(src2);
if (cap) {
const text2 = cap[1].charAt(cap[1].length - 1) === "\n" ? cap[1].slice(0, -1) : cap[1];
return {
type: "paragraph",
raw: cap[0],
text: text2,
tokens: this.lexer.inline(text2)
};
}
}
text(src2) {
const cap = this.rules.block.text.exec(src2);
if (cap) {
return {
type: "text",
raw: cap[0],
text: cap[0],
tokens: this.lexer.inline(cap[0])
};
}
}
escape(src2) {
const cap = this.rules.inline.escape.exec(src2);
if (cap) {
return {
type: "escape",
raw: cap[0],
text: escape(cap[1])
};
}
}
tag(src2) {
const cap = this.rules.inline.tag.exec(src2);
if (cap) {
if (!this.lexer.state.inLink && /^/i.test(cap[0])) {
this.lexer.state.inLink = false;
}
if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
this.lexer.state.inRawBlock = true;
} else if (this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
this.lexer.state.inRawBlock = false;
}
return {
type: this.options.sanitize ? "text" : "html",
raw: cap[0],
inLink: this.lexer.state.inLink,
inRawBlock: this.lexer.state.inRawBlock,
text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0]
};
}
}
link(src2) {
const cap = this.rules.inline.link.exec(src2);
if (cap) {
const trimmedUrl = cap[2].trim();
if (!this.options.pedantic && /^$/.test(trimmedUrl)) {
return;
}
const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), "\\");
if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
return;
}
} else {
const lastParenIndex = findClosingBracket(cap[2], "()");
if (lastParenIndex > -1) {
const start2 = cap[0].indexOf("!") === 0 ? 5 : 4;
const linkLen = start2 + cap[1].length + lastParenIndex;
cap[2] = cap[2].substring(0, lastParenIndex);
cap[0] = cap[0].substring(0, linkLen).trim();
cap[3] = "";
}
}
let href = cap[2];
let title = "";
if (this.options.pedantic) {
const link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
if (link) {
href = link[1];
title = link[3];
}
} else {
title = cap[3] ? cap[3].slice(1, -1) : "";
}
href = href.trim();
if (/^$/.test(trimmedUrl)) {
href = href.slice(1);
} else {
href = href.slice(1, -1);
}
}
return outputLink(cap, {
href: href ? href.replace(this.rules.inline._escapes, "$1") : href,
title: title ? title.replace(this.rules.inline._escapes, "$1") : title
}, cap[0], this.lexer);
}
}
reflink(src2, links) {
let cap;
if ((cap = this.rules.inline.reflink.exec(src2)) || (cap = this.rules.inline.nolink.exec(src2))) {
let link = (cap[2] || cap[1]).replace(/\s+/g, " ");
link = links[link.toLowerCase()];
if (!link) {
const text2 = cap[0].charAt(0);
return {
type: "text",
raw: text2,
text: text2
};
}
return outputLink(cap, link, cap[0], this.lexer);
}
}
emStrong(src2, maskedSrc, prevChar = "") {
let match = this.rules.inline.emStrong.lDelim.exec(src2);
if (!match)
return;
if (match[3] && prevChar.match(/[\p{L}\p{N}]/u))
return;
const nextChar = match[1] || match[2] || "";
if (!nextChar || nextChar && (prevChar === "" || this.rules.inline.punctuation.exec(prevChar))) {
const lLength = match[0].length - 1;
let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
const endReg = match[0][0] === "*" ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
endReg.lastIndex = 0;
maskedSrc = maskedSrc.slice(-1 * src2.length + lLength);
while ((match = endReg.exec(maskedSrc)) != null) {
rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
if (!rDelim)
continue;
rLength = rDelim.length;
if (match[3] || match[4]) {
delimTotal += rLength;
continue;
} else if (match[5] || match[6]) {
if (lLength % 3 && !((lLength + rLength) % 3)) {
midDelimTotal += rLength;
continue;
}
}
delimTotal -= rLength;
if (delimTotal > 0)
continue;
rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
const raw = src2.slice(0, lLength + match.index + (match[0].length - rDelim.length) + rLength);
if (Math.min(lLength, rLength) % 2) {
const text3 = raw.slice(1, -1);
return {
type: "em",
raw,
text: text3,
tokens: this.lexer.inlineTokens(text3)
};
}
const text2 = raw.slice(2, -2);
return {
type: "strong",
raw,
text: text2,
tokens: this.lexer.inlineTokens(text2)
};
}
}
}
codespan(src2) {
const cap = this.rules.inline.code.exec(src2);
if (cap) {
let text2 = cap[2].replace(/\n/g, " ");
const hasNonSpaceChars = /[^ ]/.test(text2);
const hasSpaceCharsOnBothEnds = /^ /.test(text2) && / $/.test(text2);
if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
text2 = text2.substring(1, text2.length - 1);
}
text2 = escape(text2, true);
return {
type: "codespan",
raw: cap[0],
text: text2
};
}
}
br(src2) {
const cap = this.rules.inline.br.exec(src2);
if (cap) {
return {
type: "br",
raw: cap[0]
};
}
}
del(src2) {
const cap = this.rules.inline.del.exec(src2);
if (cap) {
return {
type: "del",
raw: cap[0],
text: cap[2],
tokens: this.lexer.inlineTokens(cap[2])
};
}
}
autolink(src2, mangle2) {
const cap = this.rules.inline.autolink.exec(src2);
if (cap) {
let text2, href;
if (cap[2] === "@") {
text2 = escape(this.options.mangle ? mangle2(cap[1]) : cap[1]);
href = "mailto:" + text2;
} else {
text2 = escape(cap[1]);
href = text2;
}
return {
type: "link",
raw: cap[0],
text: text2,
href,
tokens: [
{
type: "text",
raw: text2,
text: text2
}
]
};
}
}
url(src2, mangle2) {
let cap;
if (cap = this.rules.inline.url.exec(src2)) {
let text2, href;
if (cap[2] === "@") {
text2 = escape(this.options.mangle ? mangle2(cap[0]) : cap[0]);
href = "mailto:" + text2;
} else {
let prevCapZero;
do {
prevCapZero = cap[0];
cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
} while (prevCapZero !== cap[0]);
text2 = escape(cap[0]);
if (cap[1] === "www.") {
href = "http://" + cap[0];
} else {
href = cap[0];
}
}
return {
type: "link",
raw: cap[0],
text: text2,
href,
tokens: [
{
type: "text",
raw: text2,
text: text2
}
]
};
}
}
inlineText(src2, smartypants2) {
const cap = this.rules.inline.text.exec(src2);
if (cap) {
let text2;
if (this.lexer.state.inRawBlock) {
text2 = this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0];
} else {
text2 = escape(this.options.smartypants ? smartypants2(cap[0]) : cap[0]);
}
return {
type: "text",
raw: cap[0],
text: text2
};
}
}
}
const block = {
newline: /^(?: *(?:\n|$))+/,
code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
fences: /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
list: /^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,
html: "^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))",
def: /^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,
table: noopTest,
lheading: /^((?:.|\n(?!\n))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
_paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
text: /^[^\n]+/
};
block._label = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
block.def = edit(block.def).replace("label", block._label).replace("title", block._title).getRegex();
block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
block.listItemStart = edit(/^( *)(bull) */).replace("bull", block.bullet).getRegex();
block.list = edit(block.list).replace(/bull/g, block.bullet).replace("hr", "\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def", "\\n+(?=" + block.def.source + ")").getRegex();
block._tag = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
block._comment = /|$)/;
block.html = edit(block.html, "i").replace("comment", block._comment).replace("tag", block._tag).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
block.paragraph = edit(block._paragraph).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
block.blockquote = edit(block.blockquote).replace("paragraph", block.paragraph).getRegex();
block.normal = { ...block };
block.gfm = {
...block.normal,
table: "^ *([^\\n ].*\\|.*)\\n {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"
};
block.gfm.table = edit(block.gfm.table).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
block.gfm.paragraph = edit(block._paragraph).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("|lheading", "").replace("table", block.gfm.table).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
block.pedantic = {
...block.normal,
html: edit(
`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)|
\n";
}
return '" + (escaped ? code : escape(code, true)) + "
\n";
}
blockquote(quote) {
return `' + (escaped ? code : escape(code, true)) + "
${quote}
`;
}
html(html2) {
return html2;
}
heading(text2, level, raw, slugger) {
if (this.options.headerIds) {
const id = this.options.headerPrefix + slugger.slug(raw);
return `
\n" : "
\n";
}
list(body, ordered, start2) {
const type = ordered ? "ol" : "ul", startatt = ordered && start2 !== 1 ? ' start="' + start2 + '"' : "";
return "<" + type + startatt + ">\n" + body + "" + type + ">\n";
}
listitem(text2) {
return `
${text2}`;
}
br() {
return this.options.xhtml ? "An error occurred:
" + escape(e.message + "", true) + ""; if (async) { return Promise.resolve(msg2); } if (callback) { callback(null, msg2); return; } return msg2; } if (async) { return Promise.reject(e); } if (callback) { callback(e); return; } throw e; }; } function parseMarkdown(lexer, parser) { return (src2, opt, callback) => { if (typeof opt === "function") { callback = opt; opt = null; } const origOpt = { ...opt }; opt = { ...marked.defaults, ...origOpt }; const throwError = onError(opt.silent, opt.async, callback); if (typeof src2 === "undefined" || src2 === null) { return throwError(new Error("marked(): input parameter is undefined or null")); } if (typeof src2 !== "string") { return throwError(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(src2) + ", string expected")); } checkSanitizeDeprecation(opt); if (opt.hooks) { opt.hooks.options = opt; } if (callback) { const highlight = opt.highlight; let tokens; try { if (opt.hooks) { src2 = opt.hooks.preprocess(src2); } tokens = lexer(src2, opt); } catch (e) { return throwError(e); } const done = function(err) { let out; if (!err) { try { if (opt.walkTokens) { marked.walkTokens(tokens, opt.walkTokens); } out = parser(tokens, opt); if (opt.hooks) { out = opt.hooks.postprocess(out); } } catch (e) { err = e; } } opt.highlight = highlight; return err ? throwError(err) : callback(null, out); }; if (!highlight || highlight.length < 3) { return done(); } delete opt.highlight; if (!tokens.length) return done(); let pending = 0; marked.walkTokens(tokens, function(token) { if (token.type === "code") { pending++; setTimeout(() => { highlight(token.text, token.lang, function(err, code) { if (err) { return done(err); } if (code != null && code !== token.text) { token.text = code; token.escaped = true; } pending--; if (pending === 0) { done(); } }); }, 0); } }); if (pending === 0) { done(); } return; } if (opt.async) { return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src2) : src2).then((src3) => lexer(src3, opt)).then((tokens) => opt.walkTokens ? Promise.all(marked.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens).then((tokens) => parser(tokens, opt)).then((html2) => opt.hooks ? opt.hooks.postprocess(html2) : html2).catch(throwError); } try { if (opt.hooks) { src2 = opt.hooks.preprocess(src2); } const tokens = lexer(src2, opt); if (opt.walkTokens) { marked.walkTokens(tokens, opt.walkTokens); } let html2 = parser(tokens, opt); if (opt.hooks) { html2 = opt.hooks.postprocess(html2); } return html2; } catch (e) { return throwError(e); } }; } function marked(src2, opt, callback) { return parseMarkdown(Lexer.lex, Parser.parse)(src2, opt, callback); } marked.options = marked.setOptions = function(opt) { marked.defaults = { ...marked.defaults, ...opt }; changeDefaults(marked.defaults); return marked; }; marked.getDefaults = getDefaults; marked.defaults = defaults; marked.use = function(...args) { const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} }; args.forEach((pack) => { const opts = { ...pack }; opts.async = marked.defaults.async || opts.async || false; if (pack.extensions) { pack.extensions.forEach((ext) => { if (!ext.name) { throw new Error("extension name required"); } if (ext.renderer) { const prevRenderer = extensions.renderers[ext.name]; if (prevRenderer) { extensions.renderers[ext.name] = function(...args2) { let ret = ext.renderer.apply(this, args2); if (ret === false) { ret = prevRenderer.apply(this, args2); } return ret; }; } else { extensions.renderers[ext.name] = ext.renderer; } } if (ext.tokenizer) { if (!ext.level || ext.level !== "block" && ext.level !== "inline") { throw new Error("extension level must be 'block' or 'inline'"); } if (extensions[ext.level]) { extensions[ext.level].unshift(ext.tokenizer); } else { extensions[ext.level] = [ext.tokenizer]; } if (ext.start) { if (ext.level === "block") { if (extensions.startBlock) { extensions.startBlock.push(ext.start); } else { extensions.startBlock = [ext.start]; } } else if (ext.level === "inline") { if (extensions.startInline) { extensions.startInline.push(ext.start); } else { extensions.startInline = [ext.start]; } } } } if (ext.childTokens) { extensions.childTokens[ext.name] = ext.childTokens; } }); opts.extensions = extensions; } if (pack.renderer) { const renderer = marked.defaults.renderer || new Renderer(); for (const prop in pack.renderer) { const prevRenderer = renderer[prop]; renderer[prop] = (...args2) => { let ret = pack.renderer[prop].apply(renderer, args2); if (ret === false) { ret = prevRenderer.apply(renderer, args2); } return ret; }; } opts.renderer = renderer; } if (pack.tokenizer) { const tokenizer = marked.defaults.tokenizer || new Tokenizer(); for (const prop in pack.tokenizer) { const prevTokenizer = tokenizer[prop]; tokenizer[prop] = (...args2) => { let ret = pack.tokenizer[prop].apply(tokenizer, args2); if (ret === false) { ret = prevTokenizer.apply(tokenizer, args2); } return ret; }; } opts.tokenizer = tokenizer; } if (pack.hooks) { const hooks = marked.defaults.hooks || new Hooks(); for (const prop in pack.hooks) { const prevHook = hooks[prop]; if (Hooks.passThroughHooks.has(prop)) { hooks[prop] = (arg) => { if (marked.defaults.async) { return Promise.resolve(pack.hooks[prop].call(hooks, arg)).then((ret2) => { return prevHook.call(hooks, ret2); }); } const ret = pack.hooks[prop].call(hooks, arg); return prevHook.call(hooks, ret); }; } else { hooks[prop] = (...args2) => { let ret = pack.hooks[prop].apply(hooks, args2); if (ret === false) { ret = prevHook.apply(hooks, args2); } return ret; }; } } opts.hooks = hooks; } if (pack.walkTokens) { const walkTokens = marked.defaults.walkTokens; opts.walkTokens = function(token) { let values = []; values.push(pack.walkTokens.call(this, token)); if (walkTokens) { values = values.concat(walkTokens.call(this, token)); } return values; }; } marked.setOptions(opts); }); }; marked.walkTokens = function(tokens, callback) { let values = []; for (const token of tokens) { values = values.concat(callback.call(marked, token)); switch (token.type) { case "table": { for (const cell of token.header) { values = values.concat(marked.walkTokens(cell.tokens, callback)); } for (const row of token.rows) { for (const cell of row) { values = values.concat(marked.walkTokens(cell.tokens, callback)); } } break; } case "list": { values = values.concat(marked.walkTokens(token.items, callback)); break; } default: { if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) { marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) { values = values.concat(marked.walkTokens(token[childTokens], callback)); }); } else if (token.tokens) { values = values.concat(marked.walkTokens(token.tokens, callback)); } } } } return values; }; marked.parseInline = parseMarkdown(Lexer.lexInline, Parser.parseInline); marked.Parser = Parser; marked.parser = Parser.parse; marked.Renderer = Renderer; marked.TextRenderer = TextRenderer; marked.Lexer = Lexer; marked.lexer = Lexer.lex; marked.Tokenizer = Tokenizer; marked.Slugger = Slugger; marked.Hooks = Hooks; marked.parse = marked; marked.options; marked.setOptions; marked.use; marked.walkTokens; marked.parseInline; Parser.parse; Lexer.lex; /*! @license DOMPurify 3.4.16 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.16/LICENSE */ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _iterableToArrayLimit(r, l) { var t2 = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t2) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t2 = t2.call(r)).next, 0 === l) { if (Object(t2) !== t2) return; f = false; } else for (; !(f = (e = i.call(t2)).done) && (a.push(e.value), a.length !== l); f = true) ; } catch (r2) { o = true, n = r2; } finally { try { if (!f && null != t2.return && (u = t2.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t2 = {}.toString.call(r).slice(8, -1); return "Object" === t2 && r.constructor && (t2 = r.constructor.name), "Map" === t2 || "Set" === t2 ? Array.from(r) : "Arguments" === t2 || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t2) ? _arrayLikeToArray(r, a) : void 0; } } const entries = Object.entries; const setPrototypeOf = Object.setPrototypeOf; const isFrozen = Object.isFrozen; const getPrototypeOf = Object.getPrototypeOf; const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; let freeze = Object.freeze; let seal = Object.seal; let create = Object.create; let _ref = typeof Reflect !== "undefined" && Reflect; let apply = _ref.apply; let construct = _ref.construct; if (!freeze) freeze = function freeze2(x) { return x; }; if (!seal) seal = function seal2(x) { return x; }; if (!apply) apply = function apply2(func, thisArg) { for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) args[_key - 2] = arguments[_key]; return func.apply(thisArg, args); }; if (!construct) construct = function construct2(Func) { for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) args[_key2 - 1] = arguments[_key2]; return new Func(...args); }; const arrayForEach = unapply(Array.prototype.forEach); const arrayLastIndexOf = unapply(Array.prototype.lastIndexOf); const arrayPop = unapply(Array.prototype.pop); const arrayPush = unapply(Array.prototype.push); const arraySplice = unapply(Array.prototype.splice); const arrayIsArray = Array.isArray; const stringToLowerCase = unapply(String.prototype.toLowerCase); const stringToString = unapply(String.prototype.toString); const stringMatch = unapply(String.prototype.match); const stringReplace = unapply(String.prototype.replace); const stringIndexOf = unapply(String.prototype.indexOf); const stringTrim = unapply(String.prototype.trim); const numberToString = unapply(Number.prototype.toString); const booleanToString = unapply(Boolean.prototype.toString); const bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString); const symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString); const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); const objectToString = unapply(Object.prototype.toString); const regExpTest = unapply(RegExp.prototype.test); const typeErrorCreate = unconstruct(TypeError); function unapply(func) { return function(thisArg) { if (thisArg instanceof RegExp) thisArg.lastIndex = 0; for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) args[_key3 - 1] = arguments[_key3]; return apply(func, thisArg, args); }; } function unconstruct(Func) { return function() { for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) args[_key4] = arguments[_key4]; return construct(Func, args); }; } function addToSet(set, array) { let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase; if (setPrototypeOf) setPrototypeOf(set, null); if (!arrayIsArray(array)) return set; let l = array.length; while (l--) { let element = array[l]; if (typeof element === "string") { const lcElement = transformCaseFunc(element); if (lcElement !== element) { if (!isFrozen(array)) array[l] = lcElement; element = lcElement; } } set[element] = true; } return set; } function cleanArray(array) { for (let index = 0; index < array.length; index++) if (!objectHasOwnProperty(array, index)) array[index] = null; return array; } function clone(object) { const newObject = create(null); for (const _ref2 of entries(object)) { var _ref3 = _slicedToArray(_ref2, 2); const property = _ref3[0]; const value = _ref3[1]; if (objectHasOwnProperty(object, property)) { if (arrayIsArray(value)) newObject[property] = cleanArray(value); else if (value && typeof value === "object" && value.constructor === Object) newObject[property] = clone(value); else newObject[property] = value; } } return newObject; } function stringifyValue(value) { switch (typeof value) { case "string": return value; case "number": return numberToString(value); case "boolean": return booleanToString(value); case "bigint": return bigintToString ? bigintToString(value) : "0"; case "symbol": return symbolToString ? symbolToString(value) : "Symbol()"; case "undefined": return objectToString(value); case "function": case "object": { if (value === null) return objectToString(value); const valueAsRecord = value; const valueToString = lookupGetter(valueAsRecord, "toString"); if (typeof valueToString === "function") { const stringified = valueToString(valueAsRecord); return typeof stringified === "string" ? stringified : objectToString(stringified); } return objectToString(value); } default: return objectToString(value); } } function lookupGetter(object, prop) { while (object !== null) { const desc = getOwnPropertyDescriptor(object, prop); if (desc) { if (desc.get) return unapply(desc.get); if (typeof desc.value === "function") return unapply(desc.value); } object = getPrototypeOf(object); } function fallbackValue() { return null; } return fallbackValue; } function isRegex(value) { try { regExpTest(value, ""); return true; } catch (_unused) { return false; } } const html$1 = freeze([ "a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr" ]); const svg$1 = freeze([ "svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern" ]); const svgFilters = freeze([ "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence" ]); const svgDisallowed = freeze([ "animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use" ]); const mathMl$1 = freeze([ "math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts" ]); const mathMlDisallowed = freeze([ "maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none" ]); const text = freeze(["#text"]); const html = freeze([ "accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "command", "commandfor", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "exportparts", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inert", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "part", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "slot", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns" ]); const svg = freeze([ "accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dominant-baseline", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "pointer-events", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-orientation", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "vector-effect", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan" ]); const mathMl = freeze([ "accent", "accentunder", "align", "bevelled", "close", "columnalign", "columnlines", "columnspacing", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lquote", "lspace", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns" ]); const xml = freeze([ "xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink" ]); const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g); const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g); const TMPLIT_EXPR = seal(/\${[\w\W]*/g); const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); const ARIA_ATTR = seal(/^aria-[\-\w]+$/); const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i); const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g); const DOCTYPE_NAME = seal(/^html$/i); const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); const ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g); const COMMENT_MARKUP_PROBE = seal(/<[/\w]/g); const FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i); const SELF_CLOSING_TAG = seal(/\/>/i); const NODE_TYPE = { element: 1, attribute: 2, text: 3, cdataSection: 4, entityReference: 5, entityNode: 6, processingInstruction: 7, comment: 8, document: 9, documentType: 10, documentFragment: 11, notation: 12 }; const LITERAL_TEXT_ELEMENT_NAMES = [ "style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript" ]; const LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES)); const LITERAL_TEXT_CLOSE = function() { const map = {}; arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, (name) => { map[name] = seal(new RegExp("" + name + "(?=[\\t\\n\\f\\r />])", "i")); }); return freeze(map); }(); const getGlobal = function getGlobal2() { return typeof window === "undefined" ? null : window; }; const _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) { if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") return null; let suffix = null; const ATTR_NAME = "data-tt-policy-suffix"; if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) suffix = purifyHostElement.getAttribute(ATTR_NAME); const policyName = "dompurify" + (suffix ? "#" + suffix : ""); try { return trustedTypes.createPolicy(policyName, { createHTML(html2) { return html2; }, createScriptURL(scriptUrl) { return scriptUrl; } }); } catch (_) { console.warn("TrustedTypes policy " + policyName + " could not be created."); return null; } }; const _createHooksMap = function _createHooksMap2() { return { afterSanitizeAttributes: [], afterSanitizeElements: [], afterSanitizeShadowDOM: [], beforeSanitizeAttributes: [], beforeSanitizeElements: [], beforeSanitizeShadowDOM: [], uponSanitizeAttribute: [], uponSanitizeElement: [], uponSanitizeShadowNode: [] }; }; const _resolveSetOption = function _resolveSetOption2(cfg, key, fallback, options) { return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback; }; const _resolveObjectOption = function _resolveObjectOption2(cfg, key, makeFallback) { const value = objectHasOwnProperty(cfg, key) ? cfg[key] : void 0; return value && typeof value === "object" ? clone(value) : makeFallback(); }; function createDOMPurify() { let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal(); const DOMPurify = (root2) => createDOMPurify(root2); DOMPurify.version = "3.4.16"; DOMPurify.removed = []; if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) { DOMPurify.isSupported = false; return DOMPurify; } let document2 = window2.document; const originalDocument = document2; const currentScript = originalDocument.currentScript; window2.DocumentFragment; const HTMLTemplateElement = window2.HTMLTemplateElement, Node2 = window2.Node, Element2 = window2.Element, NodeFilter2 = window2.NodeFilter; window2.NamedNodeMap === void 0 && (window2.NamedNodeMap || window2.MozNamedAttrMap); window2.HTMLFormElement; const DOMParser2 = window2.DOMParser, trustedTypes = window2.trustedTypes; const ElementPrototype = Element2.prototype; const cloneNode = lookupGetter(ElementPrototype, "cloneNode"); const remove = lookupGetter(ElementPrototype, "remove"); const removeAttributeNode = lookupGetter(ElementPrototype, "removeAttributeNode"); const getNextSibling = lookupGetter(ElementPrototype, "nextSibling"); const getChildNodes = lookupGetter(ElementPrototype, "childNodes"); const getParentNode = lookupGetter(ElementPrototype, "parentNode"); const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot"); const getAttributes = lookupGetter(ElementPrototype, "attributes"); const getNodeType = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeType") : null; const getNodeName = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeName") : null; const getOwnerDocument = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "ownerDocument") : null; const _readNodeType = function _readNodeType2(node) { return getNodeType ? getNodeType(node) : node.nodeType; }; const _readNodeName = function _readNodeName2(node) { return getNodeName ? getNodeName(node) : node.nodeName; }; if (typeof HTMLTemplateElement === "function") { const template = document2.createElement("template"); if (template.content && template.content.ownerDocument) document2 = template.content.ownerDocument; } let trustedTypesPolicy; let emptyHTML = ""; let defaultTrustedTypesPolicy; let defaultTrustedTypesPolicyResolved = false; let IN_TRUSTED_TYPES_POLICY = 0; const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy2() { if (IN_TRUSTED_TYPES_POLICY > 0) throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.'); }; const _createTrustedHTML = function _createTrustedHTML2(html2) { _assertNotInTrustedTypesPolicy(); IN_TRUSTED_TYPES_POLICY++; try { return trustedTypesPolicy.createHTML(html2); } finally { IN_TRUSTED_TYPES_POLICY--; } }; const _createTrustedScriptURL = function _createTrustedScriptURL2(scriptUrl) { _assertNotInTrustedTypesPolicy(); IN_TRUSTED_TYPES_POLICY++; try { return trustedTypesPolicy.createScriptURL(scriptUrl); } finally { IN_TRUSTED_TYPES_POLICY--; } }; const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy2() { if (!defaultTrustedTypesPolicyResolved) { defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); defaultTrustedTypesPolicyResolved = true; } return defaultTrustedTypesPolicy; }; const _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName; const importNode = originalDocument.importNode; let hooks = _createHooksMap(); DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0; const MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, TMPLIT_EXPR$1 = TMPLIT_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE, CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT; let IS_ALLOWED_URI$1 = IS_ALLOWED_URI; let ALLOWED_TAGS = null; const DEFAULT_ALLOWED_TAGS = addToSet({}, [ ...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text ]); let ALLOWED_ATTR = null; const DEFAULT_ALLOWED_ATTR = addToSet({}, [ ...html, ...svg, ...mathMl, ...xml ]); let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, { tagNameCheck: { writable: true, configurable: false, enumerable: true, value: null }, attributeNameCheck: { writable: true, configurable: false, enumerable: true, value: null }, allowCustomizedBuiltInElements: { writable: true, configurable: false, enumerable: true, value: false } })); let FORBID_TAGS = null; let FORBID_ATTR = null; const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, { tagCheck: { writable: true, configurable: false, enumerable: true, value: null }, attributeCheck: { writable: true, configurable: false, enumerable: true, value: null } })); let ALLOW_ARIA_ATTR = true; let ALLOW_DATA_ATTR = true; let ALLOW_UNKNOWN_PROTOCOLS = false; let ALLOW_SELF_CLOSE_IN_ATTR = true; let SAFE_FOR_TEMPLATES = false; let SAFE_FOR_XML = true; let WHOLE_DOCUMENT = false; let SET_CONFIG = false; let SET_CONFIG_ALLOWED_TAGS = null; let SET_CONFIG_ALLOWED_ATTR = null; let FORCE_BODY = false; let RETURN_DOM = false; let RETURN_DOM_FRAGMENT = false; let RETURN_TRUSTED_TYPE = false; let SANITIZE_DOM = true; let SANITIZE_NAMED_PROPS = false; const SANITIZE_NAMED_PROPS_PREFIX = "user-content-"; let KEEP_CONTENT = true; let IN_PLACE = false; let USE_PROFILES = {}; let FORBID_CONTENTS = null; const DEFAULT_FORBID_CONTENTS = addToSet({}, [ "annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", "selectedcontent", "style", "svg", "template", "thead", "title", "video", "xmp" ]); let DATA_URI_TAGS = null; const DEFAULT_DATA_URI_TAGS = addToSet({}, [ "audio", "video", "img", "source", "image", "track" ]); let URI_SAFE_ATTRIBUTES = null; const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [ "alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns" ]); const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML"; const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; let NAMESPACE = HTML_NAMESPACE; let IS_EMPTY_INPUT = false; let ALLOWED_NAMESPACES = null; const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [ MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE ], stringToString); const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze([ "mi", "mo", "mn", "ms", "mtext" ]); let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS); const DEFAULT_HTML_INTEGRATION_POINTS = freeze(["annotation-xml"]); let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS); const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [ "title", "style", "font", "a", "script" ]); let PARSER_MEDIA_TYPE = null; const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"]; const DEFAULT_PARSER_MEDIA_TYPE = "text/html"; let transformCaseFunc = null; let CONFIG = null; const formElement = document2.createElement("form"); const isRegexOrFunction = function isRegexOrFunction2(testValue) { return testValue instanceof RegExp || testValue instanceof Function; }; const _parseConfig = function _parseConfig2() { let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; if (CONFIG && CONFIG === cfg) return; if (!cfg || typeof cfg !== "object") cfg = {}; cfg = clone(cfg); PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE; transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase; ALLOWED_TAGS = _resolveSetOption(cfg, "ALLOWED_TAGS", DEFAULT_ALLOWED_TAGS, { transform: transformCaseFunc }); ALLOWED_ATTR = _resolveSetOption(cfg, "ALLOWED_ATTR", DEFAULT_ALLOWED_ATTR, { transform: transformCaseFunc }); ALLOWED_NAMESPACES = _resolveSetOption(cfg, "ALLOWED_NAMESPACES", DEFAULT_ALLOWED_NAMESPACES, { transform: stringToString }); URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, "ADD_URI_SAFE_ATTR", DEFAULT_URI_SAFE_ATTRIBUTES, { transform: transformCaseFunc, base: DEFAULT_URI_SAFE_ATTRIBUTES }); DATA_URI_TAGS = _resolveSetOption(cfg, "ADD_DATA_URI_TAGS", DEFAULT_DATA_URI_TAGS, { transform: transformCaseFunc, base: DEFAULT_DATA_URI_TAGS }); FORBID_CONTENTS = _resolveSetOption(cfg, "FORBID_CONTENTS", DEFAULT_FORBID_CONTENTS, { transform: transformCaseFunc }); FORBID_TAGS = _resolveSetOption(cfg, "FORBID_TAGS", clone({}), { transform: transformCaseFunc }); FORBID_ATTR = _resolveSetOption(cfg, "FORBID_ATTR", clone({}), { transform: transformCaseFunc }); USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false; ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; RETURN_DOM = cfg.RETURN_DOM || false; RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; FORCE_BODY = cfg.FORCE_BODY || false; SANITIZE_DOM = cfg.SANITIZE_DOM !== false; SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; KEEP_CONTENT = cfg.KEEP_CONTENT !== false; IN_PLACE = cfg.IN_PLACE || false; IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE; MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(cfg, "MATHML_TEXT_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS)); HTML_INTEGRATION_POINTS = _resolveObjectOption(cfg, "HTML_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS)); const customElementHandling = _resolveObjectOption(cfg, "CUSTOM_ELEMENT_HANDLING", () => create(null)); CUSTOM_ELEMENT_HANDLING = create(null); if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; seal(CUSTOM_ELEMENT_HANDLING); if (SAFE_FOR_TEMPLATES) ALLOW_DATA_ATTR = false; if (RETURN_DOM_FRAGMENT) RETURN_DOM = true; if (USE_PROFILES) { ALLOWED_TAGS = addToSet({}, text); ALLOWED_ATTR = create(null); if (USE_PROFILES.html === true) { addToSet(ALLOWED_TAGS, html$1); addToSet(ALLOWED_ATTR, html); } if (USE_PROFILES.svg === true) { addToSet(ALLOWED_TAGS, svg$1); addToSet(ALLOWED_ATTR, svg); addToSet(ALLOWED_ATTR, xml); } if (USE_PROFILES.svgFilters === true) { addToSet(ALLOWED_TAGS, svgFilters); addToSet(ALLOWED_ATTR, svg); addToSet(ALLOWED_ATTR, xml); } if (USE_PROFILES.mathMl === true) { addToSet(ALLOWED_TAGS, mathMl$1); addToSet(ALLOWED_ATTR, mathMl); addToSet(ALLOWED_ATTR, xml); } } EXTRA_ELEMENT_HANDLING.tagCheck = null; EXTRA_ELEMENT_HANDLING.attributeCheck = null; if (objectHasOwnProperty(cfg, "ADD_TAGS")) { if (typeof cfg.ADD_TAGS === "function") EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS; else if (arrayIsArray(cfg.ADD_TAGS)) { if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) ALLOWED_TAGS = clone(ALLOWED_TAGS); addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); } } if (objectHasOwnProperty(cfg, "ADD_ATTR")) { if (typeof cfg.ADD_ATTR === "function") EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR; else if (arrayIsArray(cfg.ADD_ATTR)) { if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) ALLOWED_ATTR = clone(ALLOWED_ATTR); addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); } } if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) { if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS); addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc); } if (KEEP_CONTENT) ALLOWED_TAGS["#text"] = true; if (WHOLE_DOCUMENT) addToSet(ALLOWED_TAGS, [ "html", "head", "body" ]); if (ALLOWED_TAGS.table) { addToSet(ALLOWED_TAGS, ["tbody"]); delete FORBID_TAGS.tbody; } if (cfg.TRUSTED_TYPES_POLICY) { if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.'); if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.'); const previousTrustedTypesPolicy = trustedTypesPolicy; trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY; try { emptyHTML = _createTrustedHTML(""); } catch (error) { trustedTypesPolicy = previousTrustedTypesPolicy; throw error; } } else if (cfg.TRUSTED_TYPES_POLICY === null) { trustedTypesPolicy = void 0; emptyHTML = ""; } else { if (trustedTypesPolicy === void 0) trustedTypesPolicy = _getDefaultTrustedTypesPolicy(); if (trustedTypesPolicy && typeof emptyHTML === "string") emptyHTML = _createTrustedHTML(""); } if (freeze) freeze(cfg); CONFIG = cfg; }; const ALL_SVG_TAGS = addToSet({}, [ ...svg$1, ...svgFilters, ...svgDisallowed ]); const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]); const _checkSvgNamespace = function _checkSvgNamespace2(tagName, parent, parentTagName) { if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "svg"; if (parent.namespaceURI === MATHML_NAMESPACE) return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); return Boolean(ALL_SVG_TAGS[tagName]); }; const _checkMathMlNamespace = function _checkMathMlNamespace2(tagName, parent, parentTagName) { if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "math"; if (parent.namespaceURI === SVG_NAMESPACE) return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName]; return Boolean(ALL_MATHML_TAGS[tagName]); }; const _checkHtmlNamespace = function _checkHtmlNamespace2(tagName, parent, parentTagName) { if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) return false; if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) return false; return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); }; const _checkValidNamespace = function _checkValidNamespace2(element) { let parent = getParentNode(element); if (!parent || !parent.tagName) parent = { namespaceURI: NAMESPACE, tagName: "template" }; const tagName = stringToLowerCase(element.tagName); const parentTagName = stringToLowerCase(parent.tagName); if (!ALLOWED_NAMESPACES[element.namespaceURI]) return false; if (element.namespaceURI === SVG_NAMESPACE) return _checkSvgNamespace(tagName, parent, parentTagName); if (element.namespaceURI === MATHML_NAMESPACE) return _checkMathMlNamespace(tagName, parent, parentTagName); if (element.namespaceURI === HTML_NAMESPACE) return _checkHtmlNamespace(tagName, parent, parentTagName); if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) return true; return false; }; const _forceRemove = function _forceRemove2(node) { arrayPush(DOMPurify.removed, { element: node }); try { getParentNode(node).removeChild(node); } catch (_) { remove(node); if (!getParentNode(node)) throw typeErrorCreate("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place"); } }; const _stripAttributeNode = function _stripAttributeNode2(element, attribute, name) { try { removeAttributeNode(element, attribute); } catch (_) { try { element.removeAttribute(name); } catch (_2) { } } }; const _neutralizeRoot = function _neutralizeRoot2(root2) { _neutralizeSubtree(root2); const childNodes = getChildNodes(root2); if (childNodes) { const snapshot = []; arrayForEach(childNodes, (child) => { arrayPush(snapshot, child); }); arrayForEach(snapshot, (child) => { try { remove(child); } catch (_) { } }); } const attributes = getAttributes(root2); if (attributes) for (let i = attributes.length - 1; i >= 0; --i) { const attribute = attributes[i]; const name = attribute && attribute.name; if (typeof name === "string") _stripAttributeNode(root2, attribute, name); } }; const _removeAttribute = function _removeAttribute2(name, element, attr) { if (!attr) try { attr = element.getAttributeNode(name); } catch (_) { attr = null; } arrayPush(DOMPurify.removed, { attribute: attr || null, from: element }); try { if (attr) removeAttributeNode(element, attr); else element.removeAttribute(name); } catch (_) { try { element.removeAttribute(name); } catch (_2) { } } if (name === "is") { if (RETURN_DOM || RETURN_DOM_FRAGMENT) try { _forceRemove(element); } catch (_) { } else try { element.setAttribute(name, ""); } catch (_) { } } }; const _stripDisallowedAttributes = function _stripDisallowedAttributes2(element) { const attributes = getAttributes(element); if (!attributes) return; for (let i = attributes.length - 1; i >= 0; --i) { const attribute = attributes[i]; const name = attribute && attribute.name; if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) continue; _stripAttributeNode(element, attribute, name); } }; const _neutralizeSubtree = function _neutralizeSubtree2(root2) { const stack = [root2]; while (stack.length > 0) { const node = stack.pop(); if (_readNodeType(node) === NODE_TYPE.element) _stripDisallowedAttributes(node); const childNodes = getChildNodes(node); if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]); } }; const _isPatchLinkageAttribute = function _isPatchLinkageAttribute2(lcName, lcTag) { if (!SAFE_FOR_XML) return false; if (lcName === "patchsrc") return true; return lcName === "for" && lcTag !== "label" && lcTag !== "output"; }; const _neutralizePatchLinkage = function _neutralizePatchLinkage2(root2) { if (!SAFE_FOR_XML) return; const stack = [root2]; while (stack.length > 0) { const node = stack.pop(); const nodeType = _readNodeType(node); if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) { try { remove(node); } catch (_) { } continue; } if (nodeType === NODE_TYPE.element) { const element = node; const lcTag = transformCaseFunc(_readNodeName(node)); try { if (element.hasAttribute && element.hasAttribute("patchsrc")) element.removeAttribute("patchsrc"); if (element.hasAttribute && element.hasAttribute("for") && _isPatchLinkageAttribute("for", lcTag)) element.removeAttribute("for"); } catch (_) { } } const childNodes = getChildNodes(node); if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]); } }; const _initDocument = function _initDocument2(dirty) { let doc = null; let leadingWhitespace = null; if (FORCE_BODY) dirty = "
${answer.trim()}
`; } } }, onResultsUpdate(current, _, res) { var _a; if (current.result) { CommonProject.scripts.workResults.methods.setResults(simplifyWorkResult(res, titleTransform)); } if ((_a = current.result) == null ? void 0 : _a.finish) { BackgroundProject.scripts.data.methods.addQuestionCacheFromWorkResult( simplifyWorkResult([current], titleTransform) ); } CommonProject.scripts.workResults.methods.updateWorkStateByResults(res); } }); worker.doWork({ enable_debug: BackgroundProject.scripts.dev.cfg.enable_answerer_debug }).then(() => { lib.$message.info({ content: "作业/考试完成,请自行检查后保存或提交。", duration: 0 }); worker.emit("done"); CommonProject.scripts.workResults.cfg.questionPositionSyncHandlerType = "zhs-hike"; }); return worker; } function optimizeSecond(second) { if (second > 3600) { return `${Math.floor(second / 3600)}小时${Math.floor(second % 3600 / 60)}分钟`; } else if (second > 60) { return `${Math.floor(second / 60)}分钟${second % 60}秒`; } else { return `${second}秒`; } } function autoStop(stopTime2) { var _a, _b; clearInterval(state$4.study.stopInterval); (_a = state$4.study.stopMessage) == null ? void 0 : _a.remove(); if (stopTime2 !== "0") { let stopCount = parseFloat(stopTime2) * 60 * 60; state$4.study.stopInterval = setInterval(() => { var _a2; if (stopCount > 0) { if (getPopupCaptcha() === null) { stopCount--; } } else { clearInterval(state$4.study.stopInterval); state$4.study.stop = true; (_a2 = lib.$el("video")) == null ? void 0 : _a2.pause(); lib.$modal.alert({ content: "脚本暂停,已获得今日平时分,如需继续观看,请刷新页面。" }); } }, 1e3); const val = ((_b = (ZHSProject.scripts["gxk-study"].configs.stopTime.options || []).find( (t2) => t2[0] === stopTime2 )) == null ? void 0 : _b[0]) || "0"; const date = new Date(); date.setMinutes(date.getMinutes() + parseFloat(val) * 60); state$4.study.stopMessage = lib.$message.info({ duration: 0, content: `在 ${date.toLocaleTimeString()} 脚本将自动暂停` }); } } const MIN_VIEWPORT_WIDTH = 1280; const MIN_VIEWPORT_HEIGHT = 720; function ensureWideViewport() { const { innerWidth: width, innerHeight: height } = window; if (width >= MIN_VIEWPORT_WIDTH && height >= MIN_VIEWPORT_HEIGHT) { return; } lib.$modal.confirm({ title: "界面分辨率提示", content: lib.h("div", {}, [ "当前界面分辨率过小,可能影响学习、播放等自动点击功能,点击确定自动调整界面尺寸。", lib.h("div", { style: { fontSize: "12px", color: "#999", marginTop: "8px" } }, "如需恢复请刷新界面") ]), confirmButtonText: "确定", cancelButtonText: "暂不调整", onConfirm: () => { adjustViewportScale(width, height); } }); } function adjustViewportScale(width, height) { const scale = Math.min(1, Math.min(width / MIN_VIEWPORT_WIDTH, height / MIN_VIEWPORT_HEIGHT)); if (scale >= 1) { return; } const styleId = "ocs-viewport-scale-style"; let style = document.getElementById(styleId); if (style === null) { style = document.createElement("style"); style.id = styleId; document.head.append(style); } style.innerText = `html { zoom: ${scale}; }`; lib.$message.success({ duration: 5, content: `已自动调整缩放至 ${Math.round(scale * 100)}%,以满足 1280x720 最小分辨率要求` }); } function fixProcessBar() { const bar = document.querySelector(".controlsBar"); if (bar) { bar.style.display = "block"; bar.style.zIndex = "2"; bar.style.overflow = ""; } } function closeDialogRead() { const div = document.querySelector(".dialog-read"); if (div) { div.style.display = "none"; } } function finishAlert() { lib.$modal.alert({ content: "检测到当前视频全部播放完毕,如果还有未完成的视频请刷新重试,或者打开复习模式。" }); } const refTableCache = /* @__PURE__ */ new Map(); function unpackBits(packed, offset, count, dims) { const bytesPerGlyph = dims / 8; const out = new Uint8Array(count * dims); for (let i = 0; i < count; i++) { const pBase = offset + i * bytesPerGlyph; const oBase = i * dims; for (let b = 0; b < bytesPerGlyph; b++) { const byte = packed[pBase + b]; for (let k = 0; k < 8; k++) { out[oBase + b * 8 + k] = byte >> 7 - k & 1; } } } return out; } function loadRefTable(url) { let cached = refTableCache.get(url); if (!cached) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), 3e4); cached = fetch(url, { signal: controller.signal }).then((r) => r.arrayBuffer()).then((buf) => { const dv = new DataView(buf); const magic = String.fromCharCode(dv.getUint8(0), dv.getUint8(1), dv.getUint8(2), dv.getUint8(3)); if (magic !== "FRB2") { throw new Error("[font-decrypt] 无效的特征表格式: " + magic); } const count = dv.getUint32(4, true); const threshold = dv.getUint32(8, true); const gc = dv.getUint32(12, true); const gf = dv.getUint32(16, true); const cps = new Uint32Array(count); let off = 20; for (let i = 0; i < count; i++, off += 4) { cps[i] = dv.getUint32(off, true); } const packed = new Uint8Array(buf); const coarse = unpackBits(packed, off, count, gc * gc); off += count * gc * gc / 8; const fine = unpackBits(packed, off, count, gf * gf); return { count, cps, coarse, fine, gc, gf, threshold }; }); cached = cached.then((table) => { clearTimeout(timer); return table; }).catch((err) => { clearTimeout(timer); refTableCache.delete(url); throw err; }); refTableCache.set(url, cached); } return cached; } const WORKER_TIMEOUT = 3e4; const WORKER_SOURCE = ` 'use strict'; var RENDER = 360, SQ = 480, BASELINE = 384, SHORTLIST = 40, INK_THRESHOLD = 40; var renderCv = null; function getRenderCtx() { if (!renderCv) { renderCv = new OffscreenCanvas(SQ, SQ); renderCv.ctx = renderCv.getContext('2d', { willReadFrequently: true }); } return renderCv.ctx; } var covCv = {}; function isCoveredByFont(fontFamily, ch) { var render = function (fallback) { var cv = covCv[fallback]; if (!cv) { cv = new OffscreenCanvas(200, 200); cv.ctx = cv.getContext('2d', { willReadFrequently: true }); covCv[fallback] = cv; } var ctx = cv.ctx; ctx.clearRect(0, 0, 200, 200); ctx.fillStyle = '#fff'; ctx.font = '120px "' + fontFamily + '", ' + fallback; ctx.textBaseline = 'middle'; ctx.fillText(ch, 10, 100); return ctx.getImageData(0, 0, 200, 200).data; }; var a = render('serif'); var b = render('sans-serif'); var diff = 0; for (var i = 3; i < a.length; i += 4) { diff += Math.abs(a[i] - b[i]); } return diff < 1000; } function renderGlyph(fontFamily, ch, table) { var ctx = getRenderCtx(); ctx.clearRect(0, 0, SQ, SQ); ctx.fillStyle = '#fff'; ctx.font = RENDER + 'px "' + fontFamily + '"'; ctx.textBaseline = 'alphabetic'; var advance = ctx.measureText(ch).width; ctx.fillText(ch, (SQ - advance) / 2, BASELINE); var px = ctx.getImageData(0, 0, SQ, SQ).data; var hasInk = false; for (var i = 3; i < px.length; i += 4) { if (px[i] > INK_THRESHOLD) { hasInk = true; break; } } if (!hasInk) { return null; } var W = SQ + 1; var ii = new Uint32Array(W * W); for (var y = 0; y < SQ; y++) { var rowSum = 0; var srcRow = y * SQ * 4; var dstRow = (y + 1) * W; var upRow = y * W; for (var x = 0; x < SQ; x++) { rowSum += px[srcRow + x * 4 + 3]; ii[dstRow + x + 1] = ii[upRow + x + 1] + rowSum; } } var box = function (n) { var b = SQ / n; var area = b * b; var out = new Uint8Array(n * n); for (var gy = 0; gy < n; gy++) { for (var gx = 0; gx < n; gx++) { var y0 = gy * b; var x0 = gx * b; var sum = ii[(y0 + b) * W + x0 + b] - ii[y0 * W + x0 + b] - ii[(y0 + b) * W + x0] + ii[y0 * W + x0]; out[gy * n + gx] = sum / area > table.threshold ? 1 : 0; } } return out; }; return { coarse: box(table.gc), fine: box(table.gf) }; } function bitDistance(tableArr, idx, dims, q) { var s = 0; var base = idx * dims; for (var i = 0; i < dims; i++) { if (tableArr[base + i] !== q[i]) { s++; } } return s; } function crackChar(table, feat) { var count = table.count; var dists = new Float64Array(count); for (var i = 0; i < count; i++) { dists[i] = bitDistance(table.coarse, i, table.gc * table.gc, feat.coarse); } var sorted = Float64Array.from(dists); sorted.sort(); var threshold = sorted[Math.min(SHORTLIST, count) - 1]; var idx = []; for (var j = 0; j < count; j++) { if (dists[j] <= threshold) { idx.push(j); } } var bestI = -1, best = Infinity, second = Infinity; for (var k = 0; k < idx.length; k++) { var d = bitDistance(table.fine, idx[k], table.gf * table.gf, feat.fine); if (d < best) { second = best; best = d; bestI = idx[k]; } else if (d < second) { second = d; } } return { ch: String.fromCodePoint(table.cps[bestI]), margin: second > 0 ? 1 - best / second : 1 }; } self.onmessage = function (e) { var msg = e.data; (async function () { if (typeof FontFace === 'undefined' || typeof OffscreenCanvas === 'undefined' || !self.fonts) { throw new Error('worker env unsupported'); } var family = 'font-decrypt-w-' + Math.random().toString(36).slice(2); var source = typeof msg.fontSource === 'string' ? 'url("' + msg.fontSource + '")' : msg.fontSource; var face = new FontFace(family, source, msg.fontWeight ? { weight: msg.fontWeight } : {}); await face.load(); self.fonts.add(face); var table = { count: msg.count, cps: msg.cps, coarse: msg.coarse, fine: msg.fine, gc: msg.gc, gf: msg.gf, threshold: msg.threshold }; var map = {}; var details = []; var uniq = msg.chars; for (var i = 0; i < uniq.length; i++) { var ch = uniq[i]; if (!isCoveredByFont(family, ch)) { map[ch] = ch; continue; } var feat = renderGlyph(family, ch, table); if (!feat) { map[ch] = ch; continue; } var r = crackChar(table, feat); map[ch] = r.ch; details.push({ from: ch, to: r.ch, margin: +r.margin.toFixed(3) }); self.postMessage({ type: 'progress', done: i + 1, total: uniq.length }); } self.postMessage({ type: 'result', map: map, details: details }); })().catch(function (err) { self.postMessage({ type: 'error', message: String((err && err.message) || err) }); }); }; `; function crackFontInWorker(fontSource, chars, config2, table) { return new Promise((resolve) => { if (typeof Worker === "undefined" || typeof OffscreenCanvas === "undefined") { return resolve(null); } let worker; try { const url = URL.createObjectURL(new Blob([WORKER_SOURCE], { type: "application/javascript" })); worker = new Worker(url); URL.revokeObjectURL(url); } catch { return resolve(null); } let settled = false; const timer = setTimeout(() => done(null), WORKER_TIMEOUT); const done = (r) => { if (!settled) { settled = true; clearTimeout(timer); worker.terminate(); resolve(r); } }; worker.onerror = () => done(null); worker.onmessage = (e) => { var _a; const msg2 = e.data; if (msg2.type === "progress") { (_a = config2.onProgress) == null ? void 0 : _a.call(config2, msg2.done, msg2.total); } else if (msg2.type === "result") { done({ map: msg2.map, details: msg2.details }); } else if (msg2.type === "error") { done(null); } }; worker.postMessage({ fontSource, chars, fontWeight: config2.fontWeight, count: table.count, cps: table.cps, coarse: table.coarse, fine: table.fine, gc: table.gc, gf: table.gf, threshold: table.threshold }); }); } const RENDER = 360; const SQ = 480; const BASELINE = 384; const SHORTLIST = 40; const INK_THRESHOLD = 40; let renderCanvas; function getRenderCanvas() { if (!renderCanvas) { const cv = document.createElement("canvas"); cv.width = SQ; cv.height = SQ; renderCanvas = { cv, ctx: cv.getContext("2d", { willReadFrequently: true }) }; } return renderCanvas; } function renderGlyph(fontFamily, ch, table) { const { ctx } = getRenderCanvas(); ctx.clearRect(0, 0, SQ, SQ); ctx.fillStyle = "#fff"; ctx.font = `${RENDER}px "${fontFamily}"`; ctx.textBaseline = "alphabetic"; const advance = ctx.measureText(ch).width; ctx.fillText(ch, (SQ - advance) / 2, BASELINE); const px = ctx.getImageData(0, 0, SQ, SQ).data; let hasInk = false; for (let i = 3; i < px.length; i += 4) { if (px[i] > INK_THRESHOLD) { hasInk = true; break; } } if (!hasInk) { return null; } const W = SQ + 1; const ii = new Uint32Array(W * W); for (let y = 0; y < SQ; y++) { let rowSum = 0; const srcRow = y * SQ * 4; const dstRow = (y + 1) * W; const upRow = y * W; for (let x = 0; x < SQ; x++) { rowSum += px[srcRow + x * 4 + 3]; ii[dstRow + x + 1] = ii[upRow + x + 1] + rowSum; } } const box = (n) => { const b = SQ / n; const area = b * b; const out = new Uint8Array(n * n); for (let gy = 0; gy < n; gy++) { for (let gx = 0; gx < n; gx++) { const y0 = gy * b; const x0 = gx * b; const sum = ii[(y0 + b) * W + x0 + b] - ii[y0 * W + x0 + b] - ii[(y0 + b) * W + x0] + ii[y0 * W + x0]; out[gy * n + gx] = sum / area > table.threshold ? 1 : 0; } } return out; }; return { coarse: box(table.gc), fine: box(table.gf) }; } const coverageCanvasCache = {}; function isCoveredByFont(fontFamily, ch) { const render2 = (fallback) => { var _a; const key = fontFamily + "|" + fallback; const cv = (_a = coverageCanvasCache[key]) != null ? _a : coverageCanvasCache[key] = (() => { const c = document.createElement("canvas"); c.width = 200; c.height = 200; return c; })(); const ctx = cv.getContext("2d", { willReadFrequently: true }); ctx.clearRect(0, 0, 200, 200); ctx.fillStyle = "#fff"; ctx.font = `120px "${fontFamily}", ${fallback}`; ctx.textBaseline = "middle"; ctx.fillText(ch, 10, 100); return ctx.getImageData(0, 0, 200, 200).data; }; const a = render2("serif"); const b = render2("sans-serif"); let diff = 0; for (let i = 3; i < a.length; i += 4) { diff += Math.abs(a[i] - b[i]); } return diff < 1e3; } function bitDistance(tableArr, idx, dims, q) { let s = 0; const base = idx * dims; for (let i = 0; i < dims; i++) { if (tableArr[base + i] !== q[i]) { s++; } } return s; } function crackChar(table, feat) { const { count, cps, coarse, fine, gc, gf } = table; const dists = new Float64Array(count); for (let i = 0; i < count; i++) { dists[i] = bitDistance(coarse, i, gc * gc, feat.coarse); } const sorted = Float64Array.from(dists); sorted.sort(); const threshold = sorted[Math.min(SHORTLIST, count) - 1]; const idx = []; for (let i = 0; i < count; i++) { if (dists[i] <= threshold) { idx.push(i); } } let bestI = -1; let best = Infinity; let second = Infinity; for (let k = 0; k < idx.length; k++) { const i = idx[k]; const d = bitDistance(fine, i, gf * gf, feat.fine); if (d < best) { second = best; best = d; bestI = i; } else if (d < second) { second = d; } } return { ch: String.fromCodePoint(cps[bestI]), best, second, margin: second > 0 ? 1 - best / second : 1 }; } async function crackFont(fontSource, chars, config2) { var _a; const table = await loadRefTable(config2.refTableUrl); const uniq = [...new Set(chars)].filter((c) => c.trim() !== ""); if (config2.useWorker !== false) { const r = await crackFontInWorker(fontSource, uniq, config2, table); if (r) { return r; } } const family = "font-decrypt-" + Math.random().toString(36).slice(2); const source = typeof fontSource === "string" ? `url("${fontSource}")` : fontSource; const face = new FontFace(family, source, config2.fontWeight ? { weight: config2.fontWeight } : {}); await Promise.race([ face.load(), new Promise((resolve, reject) => setTimeout(() => reject(new Error("[font-decrypt] 字体加载超时")), 15e3)) ]); document.fonts.add(face); const map = {}; const details = []; for (let i = 0; i < uniq.length; i++) { const ch = uniq[i]; if (!isCoveredByFont(family, ch)) { map[ch] = ch; continue; } const feat = renderGlyph(family, ch, table); if (!feat) { map[ch] = ch; continue; } const r = crackChar(table, feat); map[ch] = r.ch; details.push({ from: ch, to: r.ch, margin: +r.margin.toFixed(3) }); (_a = config2.onProgress) == null ? void 0 : _a.call(config2, i + 1, uniq.length); if (i % 10 === 9) { await new Promise((resolve) => setTimeout(resolve, 0)); } } return { map, details }; } function decryptText(text2, map) { return [...text2].map((c) => { var _a; return (_a = map[c]) != null ? _a : c; }).join(""); } function decryptElements(roots, map) { var _a; for (const root2 of Array.isArray(roots) ? roots : [roots]) { const walker = document.createTreeWalker(root2, NodeFilter.SHOW_TEXT); const nodes = []; while (walker.nextNode()) { nodes.push(walker.currentNode); } for (const node of nodes) { node.nodeValue = decryptText((_a = node.nodeValue) != null ? _a : "", map); } } } function collectChars(roots) { var _a; let text2 = ""; for (const root2 of Array.isArray(roots) ? roots : [roots]) { text2 += (_a = root2.textContent) != null ? _a : ""; } return text2; } function findFontUrls(doc = document) { var _a, _b; const urls = /* @__PURE__ */ new Set(); for (const sheet of Array.from(doc.styleSheets)) { try { for (const rule of Array.from(sheet.cssRules)) { if (rule instanceof CSSFontFaceRule) { const m = /url\(["']?([^"')]+)["']?\)/.exec(rule.style.getPropertyValue("src")); if (m) { urls.add(new URL(m[1], location.href).href); } } } } catch { } } const perf = (_b = (_a = doc.defaultView) == null ? void 0 : _a.performance) != null ? _b : performance; for (const entry of perf.getEntriesByType("resource")) { if (/\.(ttf|otf|woff2?)(\?|$)/i.test(entry.name)) { urls.add(entry.name); } } return [...urls]; } function extractFontFromStyle(doc, fontFamilyMarker) { var _a, _b; const styleEl = Array.from(doc.head.querySelectorAll("style")).find((s) => { var _a2; return (_a2 = s.textContent) == null ? void 0 : _a2.includes(fontFamilyMarker); }); const base64 = (_b = (_a = styleEl == null ? void 0 : styleEl.textContent) == null ? void 0 : _a.match(/base64,([\w\W]+?)['")]/)) == null ? void 0 : _b[1]; if (!base64) { return void 0; } const raw = window.atob(base64); const buffer = new Uint8Array(raw.length); for (let i = 0; i < raw.length; i++) { buffer[i] = raw.charCodeAt(i); } return buffer.buffer; } function listFontFaces(doc = document) { var _a, _b; const faces = []; for (const sheet of Array.from(doc.styleSheets)) { try { for (const rule of Array.from(sheet.cssRules)) { if (rule instanceof CSSFontFaceRule) { const family = rule.style.getPropertyValue("font-family").replace(/["']/g, "").trim(); const m = /url\(["']?([^"')]+)["']?\)/.exec(rule.style.getPropertyValue("src")); if (family && m) { const base = (_b = (_a = doc.location) == null ? void 0 : _a.href) != null ? _b : location.href; faces.push({ family, src: m[1].startsWith("data:") ? m[1] : new URL(m[1], base).href }); } } } } catch { } } return faces; } class FontDecryptor { constructor(fontSource, config2) { this.map = {}; this.queue = Promise.resolve(); this.fontSource = fontSource; this.config = config2; } static async create(fontSource, config2) { await loadRefTable(config2.refTableUrl); return new FontDecryptor(fontSource, config2); } get size() { return Object.keys(this.map).length; } decrypt(els) { return this.enqueue(async () => { const chars = collectChars(els); const newChars = [...new Set(chars)].filter((c) => c.trim() !== "" && !(c in this.map)); if (newChars.length) { const useWorker = newChars.length > 20 ? this.config.useWorker : false; const r = await crackFont(this.fontSource, newChars, { ...this.config, useWorker }); Object.assign(this.map, r.map); } decryptElements(els, this.map); }); } waitForIdle() { return this.queue; } enqueue(task) { const run = this.queue.then(task, task); this.queue = run.catch(() => void 0); return run; } } function watchElements(root2, selector, onFound, options) { var _a, _b; const target = root2 instanceof Document ? (_a = root2.body) != null ? _a : root2.documentElement : root2; const debounceMs = (_b = options == null ? void 0 : options.debounceMs) != null ? _b : 50; let stopped = false; let timer; let running = false; let rescan = false; const scan = async () => { if (stopped || running) { rescan = !stopped; return; } running = true; try { const els = Array.from(target.querySelectorAll(selector)); if (els.length) { await onFound(els); } } catch (err) { console.error("[font-decrypt] watchElements 回调执行失败:", err); } finally { running = false; if (rescan && !stopped) { rescan = false; schedule(); } } }; const schedule = () => { if (stopped) { return; } clearTimeout(timer); timer = window.setTimeout(() => { timer = void 0; scan(); }, debounceMs); }; const observer = new MutationObserver(schedule); observer.observe(target, { childList: true, subtree: true, characterData: true }); scan(); return { stop: () => { stopped = true; clearTimeout(timer); timer = void 0; observer.disconnect(); }, isBusy: () => timer !== void 0 || running || rescan }; } const CX_SECRET_REF_TABLE_URL = "https://cdn.ocsjs.com/resources/font/font_ref_cx.bin"; const HIGHT_PLAYBACK_RATE_WARNS = [ "⚠️高倍速、夜间、白天大量运行 等情况\n可能导致学习记录清空/回退", "⚠️超星后台可以看到学习时长,请谨慎设置", "⚠️如已清空/回退,请降低倍速至1-2倍" ]; let top$1 = globalThis.top; try { top$1.jobs = top$1.jobs || []; top$1.currentMedia = top$1.currentMedia || void 0; } catch { } const state$3 = { study: { videojs: /* @__PURE__ */ Object.create({}), hacked: false, answererWrapperUnsetMessage: void 0, playbackRateWarningListenerId: 0 } }; const CXProject = lib.Project.create({ name: "超星学习通", domains: [ "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", "jxgmxy.com", "jnzyjsxy.cn", "smjyxy.cn", "sslibrary.com", "xuexi365.com" ], scripts: { env: new lib.Script({ name: "环境准备脚本", matches: [["所有页面", /.*/]], hideInPanel: true, onstart() { try { let _self = self; let _try_count = 10; while (_self.parent !== void 0 && _try_count > 0) { if (_self.location.href.includes("/mycourse/studentstudy")) { top$1 = _self; console.log("[ocsjs] top change to " + top$1.location.href); break; } else { _try_count--; _self = _self.parent; } } } catch (e) { console.warn("[ocsjs] fail of find top"); console.warn(e); top$1 = globalThis.top; } } }), guide: new lib.Script({ name: "💡 使用提示", matches: [ ["首页", "https://www.chaoxing.com"], ["旧版个人首页", "chaoxing.com/space/index"], ["新版个人首页", "chaoxing.com/base"], ["学习页面", "chaoxing.com/mycourse"], ["新版学习页面", "chaoxing.com/mooc2-ans/mycourse"] ], namespace: "cx.guide", configs: { notes: { defaultValue: createSteps(["登录网课平台", "进入任意视频、作业/考试界面", "等待脚本自动运行"]).outerHTML } }, oncomplete() { if (["mycourse/studentstudy"].some((path) => location.href.includes(path))) { lib.$message.success("已进入学习页面,请等待自动运行..."); return; } if (self !== top$1) return; lib.$message.info("请手动进入视频、作业、考试页面,脚本会自动运行。"); }, onrender({ panel }) { if (lib.$gm.isInGMContext()) { const gotoPanel = (scriptKey) => { const target = CXProject.scripts[scriptKey]; target.projectName = CXProject.name; BackgroundProject.scripts.render.methods.pin(target); }; panel.body.replaceChildren( lib.h("hr"), lib.$ui.button("👉 前往学习设置", {}, (btn) => { btn.style.marginRight = "12px"; btn.onclick = () => gotoPanel("study"); }), lib.$ui.button("👉 前往作业设置", {}, (btn) => { btn.onclick = () => gotoPanel("work"); }) ); } } }), study: new lib.Script({ name: "🖥️ 课程学习", namespace: "cx.new.study", matches: [ ["任务点页面", "/knowledge/cards"], ["阅读任务点", "/readsvr/book/mooc"] ], configs: { notes: { defaultValue: lib.$ui.notes([ ["任务点不是顺序执行,如果某一个任务没有动", "请查看是否有其他任务正在学习,耐心等待即可。"], "闯关模式请注意题库如果没完成,需要自己完成才能解锁章节。", "请勿凌晨刷课,部分学校课程可能会清空进度。", ["⚠️目前超星倍速风控严重,如果高倍速", "被平台清空进度,请调到1-2倍速学习!"] ]).outerHTML }, playbackRate: { ...playbackRate$1, attrs: { title: HIGHT_PLAYBACK_RATE_WARNS.join("\n") } }, volume, videoQuizStrategy: { label: "视频内题目", tag: "select", options: [ ["random", "随机答题"], ["ignore", "忽略"] ], attrs: { title: "视频有时在学习过程中会弹出题目,这个好像并不计算在分数内,所以可以忽略,视频可以正常观看,这里提供几个方法处理题目" }, defaultValue: "random" }, mode: { label: "跳转模式", tag: "select", options: [ ["next", "完成后跳转下一节", "完成小节后,自动点击下一节按钮"], ["job", "完成后跳转未完成任务点", "如果未找到任务点,则会直接结束脚本运行,目前处于试验阶段。"], ["manually", "完成后暂停,等待手动跳转", "适用于自己手动运行"] ], defaultValue: "next" }, restudy: { label: "复习模式", attrs: { title: "已经完成的视频继续学习", type: "checkbox" }, defaultValue: false }, enables: { ...dropdownStyle, label: "高级设置", attrs: { type: "checkbox" }, defaultValue: false }, autoJumpToUnFinishJob: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "自动前往首个任务点", attrs: { type: "checkbox", title: "进入学习界面后自动前往未完成的任务点,如果关闭则从当前任务点往下学习 (积分课、智慧课程等课程 建议关闭)" }, defaultValue: true }, forceLearn: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "强制学习", attrs: { title: "视频一般分为:非任务点、任务点、和已完成任务点,当遇到“非任务点”时需要开启此选项才会进行学习", type: "checkbox" }, defaultValue: false }, backToFirstWhenFinish: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "完成全部后重新学习", attrs: { type: "checkbox", title: "当章节已经学习完成至最后一章时,跳转到第一个章节重新开始学习。" }, defaultValue: false }, showTextareaWhenEdit: { elementClassName: "config-details", label: "编辑时显示自定义编辑框", showIf: "cx.new.study.enables", attrs: { type: "checkbox", title: "超星默认禁止在编辑框中复制粘贴,开启此选项可以在文本框编辑时生成一个自定义编辑框进行编辑,脚本会将内容同步到编辑框中。" }, defaultValue: true }, notifyWhenHasFaceRecognition: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "出现人脸识别时通知我", attrs: { type: "checkbox" }, defaultValue: true }, enableMedia: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "视频/音频自动播放", attrs: { type: "checkbox", title: "开启:音频和视频的自动播放" }, defaultValue: true }, enablePPT: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "PPT/书籍自动完成", attrs: { type: "checkbox", title: "开启:PPT/书籍自动翻阅" }, defaultValue: true }, enableChapterTest: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "章节测试自动答题", attrs: { type: "checkbox", title: "开启:章节测试自动答题" }, defaultValue: true }, enableHyperlink: { elementClassName: "config-details", showIf: "cx.new.study.enables", label: "链接任务自动完成", attrs: { type: "checkbox", title: "开启:链接任务自动完成" }, defaultValue: true } }, onrender({ panel }) { var _a; if (!((_a = CommonProject.scripts.settings.cfg.answererWrappers) == null ? void 0 : _a.length)) { answerWrapperEmptyWarning(10); } this.offConfigChange(state$3.study.playbackRateWarningListenerId); state$3.study.playbackRateWarningListenerId = this.onConfigChange("playbackRate", (playbackRate2) => { if (playbackRate2 > 2) { lib.$modal.alert({ title: "⚠️高倍速警告 (倍速 >= 2)", content: lib.$ui.notes(HIGHT_PLAYBACK_RATE_WARNS), maskCloseable: false, confirmButtonText: "我已知晓风险" }); } }) || 0; }, async onactive() { if (/\/readsvr\/book\/mooc/.test(location.href)) { if (document.querySelector("#reader")) { require(["reader"], (_reader) => { waitForElement(".readerPager").then(() => { setTimeout(async () => { var _a; const jumper = document.querySelector("#pagejump"); if ((_reader == null ? void 0 : _reader.goPage) && jumper) { const timing = parseInt(((_a = new URL(location.href).searchParams.get("timing")) == null ? void 0 : _a.toString()) || "60") + 3; console.log(timing); await $.sleep(timing * 1e3); jumper.value = "5"; jumper.dispatchEvent(new Event("change")); console.log("已跳转正文页"); await $.sleep(timing * 1e3); jumper.value = "7"; jumper.dispatchEvent(new Event("change")); console.log("已跳转封底页"); await $.sleep(timing * 1e3); Array.from(document.querySelectorAll(".readerPager")).filter((el) => el.style.zIndex === "101")[0].click(); console.log("阅读完成"); } }, 3e3); }); }); } else { $console.log("正在完成书籍/PPT..."); setTimeout(() => { readweb.goto(epage); }, 5e3); } return; } if (/\/knowledge\/cards/.test(location.href)) { const updateMediaState = () => { if (top$1.currentMedia) { top$1.currentMedia.playbackRate = parseFloat(this.cfg.playbackRate.toString()); top$1.currentMedia.volume = this.cfg.volume; } }; this.onConfigChange("playbackRate", updateMediaState); this.onConfigChange("volume", updateMediaState); await study({ ...this.cfg, playbackRate: parseFloat(this.cfg.playbackRate.toString()) }); } } }), work: new lib.Script({ name: "✍️ 作业考试脚本", matches: [ ["作业页面", "/mooc2/work/dowork"], ["考试整卷预览页面", "/mooc2/exam/preview"] ], namespace: "cx.new.work", configs: { notes: workNotes$1 }, async oncomplete() { const isExam2 = /\/exam\/preview/.test(location.href); commonWork(this, { workerProvider: (opts) => workOrExam$1(isExam2 ? "exam" : "work", { ...opts, preview_mode: true }) }); } }), autoRead: new lib.Script({ name: "🖥️ 自动阅读", matches: [ ["阅读页面", "/ztnodedetailcontroller/visitnodedetail"], ["课程目录", /chaoxing.com\/course\/\d+\.html/], ["课程目录", /chaoxing.com\/mooc-ans\/course\/\d+\.html/], ["积分课阅读课程目录", "/mooc-ans/zt/portal"] ], namespace: "cx.new.auto-read", configs: { notes: { defaultValue: lib.$ui.notes(["点击任意章节开始自动阅读", "阅读任务次日才会统计阅读时长"]).outerHTML }, restartAfterFinish: { label: "无限阅读", attrs: { type: "checkbox", title: "阅读完成最后一章后从头第一章继续阅读" }, defaultValue: false } }, oncomplete() { BackgroundProject.scripts.render.methods.pin(this); lib.$message.info("请手动点击任意章节开始自动阅读"); if (location.href.includes("/ztnodedetailcontroller/visitnodedetail") === false) { startAtFirst(); return; } let top2 = 0; const interval = setInterval(() => { top2 += (document.documentElement.scrollHeight - window.innerHeight) / 60; window.scrollTo({ behavior: "smooth", top: top2 }); }, 1e3); setTimeout(() => { clearInterval(interval); const next2 = lib.$el(".nodeItem.r i"); if (next2) { next2.click(); } else { if (this.cfg.restartAfterFinish) { setTimeout(() => startAtFirst(), 3e3); lib.$message.info({ content: "即将重新从头开始阅读", duration: 10 }); $console.log("即将重新从头开始阅读"); } else { lib.$message.success({ content: "阅读任务已完成", duration: 0 }); $console.log("未检测到下一页"); } } }, (60 + 3) * 1e3); function startAtFirst() { const texts = lib.$$el(".course_section .chapterText"); if (texts.length) { texts[0].click(); } } } }), pageRedirect: new lib.Script({ name: "章节页面自动切换脚本", matches: [["课程任务页面", "pageHeader=0"]], hideInPanel: true, async oncomplete() { if (top$1 === window) { const a = document.querySelector('a[title="章节"]'); if (a) { await $.sleep(1e3); a.click(); lib.$message.info({ content: "已经为您自动切换到章节列表页面,手动进入任意章节即可开始自动学习!" }); } } } }), versionRedirect: new lib.Script({ name: "版本切换脚本", matches: [ ["", "mooc2=0"], ["", "mycourse/studentcourse"], ["", "work/getAllWork"], ["", "work/doHomeWorkNew"], ["", "exam/test\\?"] ], hideInPanel: true, async oncomplete() { if (top$1 === window) { lib.$message.warn({ content: "网课助手不支持旧版超星, 即将切换到超星新版, 如有其他第三方插件请关闭, 可能有兼容问题导致频繁切换。", duration: 0 }); await $.sleep(2e3); await waitForFaceRecognition(); const experience = document.querySelector(".experience"); if (experience) { experience.click(); } else { const newUrl = new URL(window.location.href); if (window.location.href.includes("mooc-ans/mycourse/studentstudy")) { newUrl.pathname = "/mycourse/studentstudy"; } const params = newUrl.searchParams; let changed = false; if (params.get("mooc2") !== "1") { params.set("mooc2", "1"); changed = true; } if (params.get("newMooc") !== "true") { params.set("newMooc", "true"); changed = true; } if (changed) window.location.replace(newUrl); } } } }), examRedirect: new lib.Script({ name: "考试整卷预览脚本", hideInPanel: true, matches: [ ["新版考试页面", "exam-ans/exam/test/reVersionTestStartNew"], ["新版考试页面2", "mooc-ans/exam/test/reVersionTestStartNew"] ], configs: { notes: workNotes$1 }, oncomplete() { var _a, _b; if ((_b = (_a = lib.$gm.unsafeWindow.document.querySelector(".mark_info")) == null ? void 0 : _a.textContent) == null ? void 0 : _b.includes("不允许整卷预览")) { lib.$message.warn({ content: lib.$ui.notes([ "由于当前考试禁止整卷预览,各题为独立新页面,只能一个个答题", "在考完前禁止手动切换题目,否则会导致重复答题!", "完成后或者开考前请手动删除搜索结果!", "想加快速度请更改通用-全局设置-高级设置-搜题间隔,设置为 1-3 秒即可。" ]), duration: 0 }); const isExam2 = /\/exam\/test/.test(location.href); const workOptions = CommonProject.scripts.settings.methods.getWorkOptions(); BackgroundProject.scripts.render.methods.pin(this); commonWork(this, { start_delay_seconds: workOptions.period, workerProvider: (opts) => workOrExam$1(isExam2 ? "exam" : "work", { ...opts, preview_mode: false, thread: 1 }) }); return; } lib.$message.info({ content: "即将跳转到整卷预览页面进行考试。" }); setTimeout(() => lib.$gm.unsafeWindow.topreview(), 3e3); } }), rateHack: new lib.Script({ name: "屏蔽倍速限制", hideInPanel: true, matches: [["", "/ananas/modules/video/"]], onstart() { rateHack(); } }), copyHack: new lib.Script({ name: "屏蔽复制粘贴限制", hideInPanel: true, matches: [["所有页面", /.*/]], methods() { return { hackEditorPaste() { var _a, _b; try { const instants = ((_b = (_a = lib.$gm.unsafeWindow) == null ? void 0 : _a.UE) == null ? void 0 : _b.instants) || []; for (const key in instants) { const ue = instants[key]; if (ue == null ? void 0 : ue.textarea) { ue.body.addEventListener("click", async () => { if (CXProject.scripts.study.cfg.showTextareaWhenEdit) { const defaultText = lib.h("span", { innerHTML: ue.textarea.value }).textContent; lib.$modal.prompt({ content: "请在此文本框进行编辑,防止超星无法复制粘贴。(如需关闭请前往设置: 课程学习-编辑时显示自定义编辑框)", width: 800, inputDefaultValue: defaultText || "", modalInputType: "textarea", onConfirm: (val = "") => { ue.setContent( val.split("\n").map((line) => `${line}
`).join("") ); } }); } }); if (lib.$gm.unsafeWindow.editorPaste) { ue.removeListener("beforepaste", lib.$gm.unsafeWindow.editorPaste); } if (lib.$gm.unsafeWindow.myEditor_paste) { ue.removeListener("beforepaste", lib.$gm.unsafeWindow.myEditor_paste); } } } } catch { } } }; }, oncomplete() { const hackInterval = setInterval(() => { if (typeof lib.$gm.unsafeWindow.UE !== "undefined") { clearInterval(hackInterval); this.methods.hackEditorPaste(); console.log("已解除输入框无法复制粘贴限制"); } }, 500); } }), studyDispatcher: new lib.Script({ name: "课程学习调度器", matches: [["课程学习页面", "/mycourse/studentstudy"]], namespace: "cx.new.study-dispatcher", hideInPanel: true, async oncomplete() { let chapters = await CXAnalyses.waitForChapterInfos(); const params = new URLSearchParams(window.location.href); const mooc = params.get("mooc2"); if (mooc === null) { params.set("mooc2", "1"); window.location.replace(decodeURIComponent(params.toString())); return; } if (CXProject.scripts.study.cfg.autoJumpToUnFinishJob) { chapters = chapters.filter((chapter) => chapter.unFinishCount !== 0); if (chapters.length === 0) { lib.$message.warn({ content: "页面任务点数量为空! 请刷新重试!" }); } else { const params2 = new URLSearchParams(window.location.href); const courseId = params2.get("courseId"); const classId = params2.get("clazzid"); if (lib.$$el(`.posCatalog_active[id="cur${chapters[0].chapterId}"]`).length === 0) { lib.$gm.unsafeWindow.getTeacherAjax(courseId, classId, chapters[0].chapterId); } await $.sleep(1e3); } } await $.sleep(1e3); CXAnalyses.scrollToActiveChapter(); } }), cxSecretFontRecognize: new lib.Script({ name: "繁体字识别", hideInPanel: true, matches: [ ["题目页面", "work/doHomeWorkNew"], ["考试整卷预览", "/mooc2/exam/preview"], ["作业", "/mooc2/work/dowork"] ], async oncomplete() { await mappingRecognize(); } }), jfkGuide: new lib.Script({ name: "💡 积分课使用提示", matches: [["积分课页面", "/plaza"]], namespace: "cx.jfk.guide", configs: { notes: { defaultValue: createSteps(["进入课程", "开启复习模式,并关闭自动下一章", "课程完成后手动切换"]).outerHTML + lib.$ui.notes(["⚠️ 如果由脚本进行自动跳转会出现乱跳转的可能,请手动切换课程。"]).outerHTML } }, oncomplete(...args) { BackgroundProject.scripts.render.methods.pin(this); } }) } }); function workOrExam$1(type = "work", { answererWrappers, period, thread, redundanceWordsText, answerSeparators, preview_mode }) { lib.$message.info(`开始${type === "work" ? "作业" : "考试"}`); if (preview_mode) { CommonProject.scripts.workResults.methods.init({ questionPositionSyncHandlerType: "cx" }); } const workOrExamQuestionTitleTransform = (titles) => { const is_multiple_question = titles.length > 1; const images = []; const optimizationTitle = titles.map((el, i) => { var _a, _b; if (el) { const titleCloneEl = el.cloneNode(true); const childNodes = titleCloneEl.childNodes; if (i === 0) { (_a = childNodes[0]) == null ? void 0 : _a.remove(); (_b = childNodes[0]) == null ? void 0 : _b.remove(); } const extracted = extractTextWithImages(titleCloneEl); images.push(...extracted.images); return extracted.text; } return ""; }).join("\n"); const text2 = removeRedundantWords( StringUtils.of(optimizationTitle).nowrap(is_multiple_question ? "\n" : " ").nospace().toString().trim(), redundanceWordsText.split("\n") ); return { text: text2, images }; }; const workOrExamQuestionTitleText = (titles) => workOrExamQuestionTitleTransform(titles).text; const worker = new OCSWorker({ root: ".questionLi", elements: { title: (root2) => lib.$$el( !preview_mode ? [".splitS-left .mark_name", ".line_wid_half.fl,.line_wid_half.fr"].join(",") : [ ":scope > h3", ":scope > div:not(.stem_answer,.mark_answer)", ":scope > p", ".line_wid_half.fl,.line_wid_half.fr" ].join(","), root2 ).filter((e) => { var _a; return !!((_a = e.textContent) == null ? void 0 : _a.trim()); }), options: ".answerBg .answer_p, .textDIV, .eidtDiv", type: type === "exam" ? 'input[name^="type"]' : 'input[id^="answertype"]', lineAnswerInput: ".line_answer input[name^=answer]", lineSelectBox: ".line_answer_ct .selectBox ", reading: ".reading_answer", filling: ".filling_answer" }, thread: thread != null ? thread : 1, answerSeparators: answerSeparators.split(",").map((s) => s.trim()), answerer: createCommonAnswerer({ titleTransform: (elements2, ctx) => { if (elements2.title) { return workOrExamQuestionTitleTransform(elements2.title); } return ""; }, optionsTransform: (elements2, ctx) => { var _a, _b; const typeInput = (_a = elements2.type) == null ? void 0 : _a[0]; const type2 = (typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0) || "unknown"; ctx.type = type2; if (type2 === "completion") return ""; const optResults = ((_b = ctx.elements.options) != null ? _b : []).filter(Boolean).map((o) => extractTextWithImages(o)); return { text: optResults.map((r) => r.text).join("\n"), images: optResults.flatMap((r) => r.images) }; }, answererWrappers, period }), work: async (ctx) => { var _a, _b; const { elements: elements2, searchInfos } = ctx; const type2 = getQuestionType( parseInt(((_a = elements2.type.find((t2) => { var _a2; return (_a2 = t2.getAttribute("name")) == null ? void 0 : _a2.match(/type\d+/); })) == null ? void 0 : _a.getAttribute("value")) || "-1") ); if (type2 && (type2 === "completion" || type2 === "multiple" || type2 === "judgement" || type2 === "single")) { const resolver = createDefaultQuestionResolver(ctx, (o) => extractTextWithImages(o).text)[type2]; return await resolver(searchInfos, elements2.options, async (type3, answer, option) => { var _a2, _b2, _c; if (type3 === "judgement" || type3 === "single" || type3 === "multiple") { if ((option == null ? void 0 : option.parentElement) && lib.$$el('[class*="check_answer"]', option.parentElement).length === 0) { option.click(); await $.sleep(500); } } else if (type3 === "completion" && answer.trim()) { const text2 = option == null ? void 0 : option.querySelector("textarea"); const textareaFrame = option == null ? void 0 : option.querySelector("iframe"); if (text2) { text2.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 = lib.$el("[onclick*=saveQuestion]", (_b2 = option == null ? void 0 : option.parentElement) == null ? void 0 : _b2.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 && elements2.lineAnswerInput && ans.filter(Boolean).length === elements2.lineSelectBox.length) { for (let index = 0; index < elements2.lineSelectBox.length; index++) { const box = elements2.lineSelectBox[index]; if (ans[index]) { (_b = lib.$el(`li[data=${ans[index]}] a`, box)) == null ? void 0 : _b.click(); await $.sleep(200); } } return { finish: true }; } } return { finish: false }; } else if (type2 && type2 === "fill") { return readerAndFillHandle(searchInfos, elements2.filling); } else if (type2 && type2 === "reader") { return readerAndFillHandle(searchInfos, elements2.reading); } return { finish: false }; }, onQuestionDetected(current) { if (preview_mode) { return; } updateDynamicResult(current, workOrExamQuestionTitleText); }, async onResultsUpdate(current, _, res) { var _a, _b; if (!preview_mode) { updateDynamicResult(current, workOrExamQuestionTitleText); if ((_a = current.result) == null ? void 0 : _a.finish) { BackgroundProject.scripts.data.methods.addQuestionCacheFromWorkResult( simplifyWorkResult([current], workOrExamQuestionTitleText) ); } return; } CommonProject.scripts.workResults.methods.setResults(simplifyWorkResult(res, workOrExamQuestionTitleText)); CommonProject.scripts.workResults.methods.updateWorkStateByResults(res); if ((_b = current.result) == null ? void 0 : _b.finish) { BackgroundProject.scripts.data.methods.addQuestionCacheFromWorkResult( simplifyWorkResult([current], workOrExamQuestionTitleText) ); } } }); if (preview_mode) { worker.doWork({ enable_debug: BackgroundProject.scripts.dev.cfg.enable_answerer_debug }).then(() => { lib.$message.info({ content: "作业/考试完成,请自行检查后保存或提交。", duration: 0 }); worker.emit("done"); }).catch((err) => { console.error(err); lib.$message.error("答题程序发生错误 : " + err.message); }); } else { const getNextBtn = () => document.querySelector('[onclick="getTheNextQuestion(1)"]'); let next2 = getNextBtn(); (async () => { while (next2 && worker.isClose === false) { await worker.doWork({ enable_debug: BackgroundProject.scripts.dev.cfg.enable_answerer_debug }); lib.$message.info({ content: "已完成,即将下一题", duration: 0 }); await $.sleep(3e3); next2 = getNextBtn(); next2 == null ? void 0 : next2.click(); await $.sleep(1e3); } lib.$message.success({ content: "作业/考试完成,请自行检查后保存或提交。", duration: 0 }); worker.emit("done"); CommonProject.scripts.workResults.cfg.questionPositionSyncHandlerType = "cx"; })(); } return worker; } async function mappingRecognize(doc = document) { const fontBuffer = extractFontFromStyle(doc, "font-cxsecret"); if (!fontBuffer) { $console.log("未检测到加密文字。"); return; } const fonts = CXAnalyses.getSecretFont(doc); if (fonts.length === 0) { return; } const t2 = Date.now(); try { const { map, details } = await crackFont(fontBuffer, collectChars(fonts), { refTableUrl: CX_SECRET_REF_TABLE_URL, onProgress: (done, total) => console.log(`加密文字识别中 ${done}/${total}`) }); const lowMargin = details.filter((d) => d.margin < 0.3); if (lowMargin.length > 0) { const msg2 = `有 ${lowMargin.length} 个字符识别置信度较低,可能存在误差`; $console.warn(msg2); console.log(msg2, lowMargin); } decryptElements(fonts, map); fonts.forEach((el) => el.classList.remove("font-cxsecret")); lib.$message.info("文字解密完成,耗时 " + ((Date.now() - t2) / 1e3).toFixed(1) + " 秒"); } catch (err) { $console.error("加密文字识别失败:", String(err)); } } const CXAnalyses = { isInSpecialMode() { return Array.from((top$1 == null ? void 0 : top$1.document.querySelectorAll(".catalog_points_sa,.catalog_points_er")) || []).length !== 0; }, async isStuckInBreakingMode() { if (this.isInSpecialMode()) { const chapter = top$1 == null ? void 0 : top$1.document.querySelector(".posCatalog_active"); if (chapter) { const id = chapter.getAttribute("id"); if (id) { const counter = await lib.$store.getTab("chapter_counter") || /* @__PURE__ */ 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 lib.$store.setTab("chapter_counter", counter); return res; } } } return false; }, isInFinalTab() { const tabs = Array.from((top$1 == null ? void 0 : top$1.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((top$1 == null ? void 0 : top$1.document.querySelectorAll(".posCatalog_select")) || []).pop()) == null ? void 0 : _a.classList.contains("posCatalog_active"); }, isFinishedAllChapters() { return this.getChapterInfos().every((chapter) => chapter.unFinishCount === 0); }, getChapterInfos() { return Array.from((top$1 == null ? void 0 : top$1.document.querySelectorAll('[onclick^="getTeacherAjax"]')) || []).map((el) => { var _a, _b, _c; return { element: el, 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") }; }); }, scrollToActiveChapter() { const activeChapter = top$1 == null ? void 0 : top$1.document.querySelector(".posCatalog_active"); if (activeChapter) { activeChapter.scrollIntoView({ behavior: "smooth", block: "center" }); } }, waitForChapterInfos(timeout = 10) { return new Promise((resolve, reject) => { const interval = setInterval(() => { const res = this.getChapterInfos(); if (res.length > 0) { clearInterval(interval); clearInterval(to); resolve(res); } }, 1e3); const to = setTimeout(() => { clearInterval(interval); resolve([]); }, timeout * 1e3); }); }, getSecretFont(doc = document) { return Array.from(doc.querySelectorAll(".font-cxsecret")).map((font) => { const after = font.querySelector(".after"); return after === null ? font : after; }); }, isCurrentChapterFinished() { const job = top$1 == null ? void 0 : top$1.document.querySelector(".posCatalog_active"); if (job) { if (job.querySelector(".icon_Completed") !== null) { return true; } } return false; } }; function rateHack() { state$3.study.hacked = false; let dragCount = 0; try { hack(); window.document.addEventListener("readystatechange", hack); window.addEventListener("load", hack); } catch (e) { console.error(e); } function hack() { const videojs = lib.$gm.unsafeWindow.videojs; const Ext = lib.$gm.unsafeWindow.Ext; if (typeof videojs !== "undefined" && typeof Ext !== "undefined") { if (state$3.study.hacked) { return; } state$3.study.hacked = true; const _origin = videojs.getPlugin("seekBarControl"); const plugin = videojs.extend(videojs.getPlugin("plugin"), { constructor: function(videoExt, data) { const _sendLog = data.sendLog; data.sendLog = (...args) => { var _a; if (args[1] === "drag") { dragCount++; if (dragCount > 100) { dragCount = 0; (_a = lib.$el("video")) == null ? void 0 : _a.pause(); } } else { _sendLog.apply(data, args); } }; _origin.apply(_origin.prototype, [videoExt, data]); } }); videojs.registerPlugin("seekBarControl", plugin); Ext.define("ans.VideoJs", { override: "ans.VideoJs", constructor: function(data) { this.addEvents(["seekstart"]); this.mixins.observable.constructor.call(this, data); const vjs = videojs(data.videojs, this.params2VideoOpt(data.params), function() { }); Ext.fly(data.videojs).on("contextmenu", function(f) { f.preventDefault(); }); Ext.fly(data.videojs).on("keydown", function(f) { if (f.keyCode === 32 || f.keyCode === 37 || f.keyCode === 39 || f.keyCode === 107) { f.preventDefault(); } }); if (vjs.videoJsResolutionSwitcher) { vjs.on("resolutionchange", function() { const cr = vjs.currentResolution(); const re2 = cr.sources ? cr.sources[0].res : false; Ext.setCookie("resolution", re2); }); } if (vjs.videoJsPlayLine) { vjs.on("playlinechange", function() { const cp = vjs.currentPlayline(); Ext.setCookie("net", cp.net); }); } } }); } } } async function study(opts) { var _a; await $.sleep(3e3); const searchedJobs = []; let searching = true; let attachmentCount = ((_a = lib.$gm.unsafeWindow.attachments) == null ? void 0 : _a.length) || 0; const wait_timeout = 3 + attachmentCount * 2; setTimeout(() => { searching = false; }, Math.min(wait_timeout, 10) * 1e3); const runJobs = async () => { const job = 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(); top$1._preChapterId = ""; const next2 = async () => { if (CXAnalyses.isInFinalTab()) { if (await CXAnalyses.isStuckInBreakingMode()) { return lib.$modal.alert({ content: "检测到当前课程为闯关模式(有小旗帜图标), 但是已经重复进入多次,应该是章节测试没有完成,或者其他情况导致,请手动完成章节测试,然后手动点击下一章。" }); } } if (CXAnalyses.isInFinalChapter()) { let content = ""; if (opts.backToFirstWhenFinish) { content = "已经抵达最后一个章节,10秒后返回第一个章节重新开始。"; setTimeout(() => { var _a2; (_a2 = top$1 == null ? void 0 : top$1.document.querySelector(".posCatalog_name")) == null ? void 0 : _a2.click(); }, 10 * 1e3); lib.$message.info({ content, duration: 30 }); } else { if (CXAnalyses.isFinishedAllChapters()) { content = "全部任务点已完成!"; } else { content = "已经抵达最后一个章节!但仍然有任务点未完成,请手动切换至未完成的章节。"; } lib.$modal.alert({ content }); } CommonProject.scripts.settings.methods.notificationBySetting(content, { duration: 0, extraTitle: "超星学习通学习脚本" }); return; } if (CXProject.scripts.study.cfg.mode === "job") { if (CXAnalyses.isInFinalTab()) { const elements2 = CXAnalyses.getChapterInfos().filter((el) => { var _a2; return el.unFinishCount > 0 || ((_a2 = el.element.parentElement) == null ? void 0 : _a2.classList.contains("posCatalog_active")); }).map((el) => el.element.parentElement); if (elements2.length === 0) { const content = "全部任务点已完成!"; lib.$modal.alert({ content }); CommonProject.scripts.settings.methods.notificationBySetting(content, { duration: 0, extraTitle: "超星学习通学习脚本" }); return; } let nextChapter = elements2[0]; const currentIndex = elements2.findIndex((el) => el.classList.contains("posCatalog_active")); if (currentIndex !== -1 && currentIndex + 1 < elements2.length) { nextChapter = elements2[currentIndex + 1]; CXAnalyses.scrollToActiveChapter(); setTimeout(() => { var _a2; (_a2 = nextChapter.querySelector(".posCatalog_name")) == null ? void 0 : _a2.click(); }, 1e3); } } } else if (CXProject.scripts.study.cfg.mode === "next") { const curCourseId = lib.$el("#curCourseId", top$1 == null ? void 0 : top$1.document); const curChapterId = lib.$el("#curChapterId", top$1 == null ? void 0 : top$1.document); const curClazzId = lib.$el("#curClazzId", top$1 == null ? void 0 : top$1.document); const count = lib.$$el("#prev_tab .prev_ul li", top$1 == null ? void 0 : top$1.document); if (curChapterId && curCourseId && curClazzId) { top$1._preChapterId = curChapterId.value; CXAnalyses.scrollToActiveChapter(); await $.sleep(200); top$1 == null ? void 0 : top$1.PCount.next(count.length.toString(), curChapterId.value, curCourseId.value, curClazzId.value, ""); } else { $console.warn("参数错误,无法跳转下一章,请尝试手动切换。"); } } else { $console.warn("未知的跳转模式,请联系作者反馈"); } }; if (CXProject.scripts.study.cfg.mode !== "manually") { const msg2 = "页面任务点已完成,即将跳转。"; lib.$message.success({ content: msg2 }); $console.info(msg2); await $.sleep(5e3); next2(); } else { const msg2 = "页面任务点已完成,自动跳转已关闭,请手动跳转。"; lib.$message.warn({ content: msg2, duration: 0 }); $console.warn(msg2); } } function 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; } function searchJob(opts, searchedJobs) { const knowCardWin = lib.$gm.unsafeWindow; const searchJobElement = (root2) => { return domSearch( { videojs: "#video,#audio", chapterTest: ".TiMu", read: "#img.imglook", pptWithAudio: ".swiper-container", hyperlink: "#hyperlink", timereader: 'iframe[name="bookifame"][src*="timing"]' }, root2.contentWindow.document ); }; const search = (root2) => { var _a, _b, _c, _d; const win = root2.contentWindow; const { videojs, read, chapterTest, hyperlink, pptWithAudio, timereader } = searchJobElement(root2); if (win && (videojs || read || chapterTest || hyperlink || pptWithAudio || timereader)) { 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) { if (!CXProject.scripts.study.cfg.enableMedia) { const msg2 = `音视频自动学习功能已被关闭(在上方菜单栏,超星学习通-课程学习中开启)。${jobName} 即将跳过`; lib.$message.warn({ content: msg2, duration: 10 }); $console.warn(msg2); } else { if (work_type === "job" || work_type === "finished" && opts.restudy || work_type === "not-job" && opts.forceLearn) { func = () => { const msg2 = `即将${work_type === "finished" && opts.restudy ? "重新" : work_type === "not-job" && opts.forceLearn ? "强制" : ""}播放 : ` + jobName; lib.$message.info({ content: msg2 }); $console.log(msg2); return JobRunner.media(opts, win.document); }; } } } else if (chapterTest) { if (!CXProject.scripts.study.cfg.enableChapterTest) { const msg2 = `章节测试自动答题功能已被关闭(在上方菜单栏,超星学习通-课程学习中开启)。${jobName} 即将跳过`; lib.$message.warn({ content: msg2, duration: 10 }); $console.warn(msg2); } else { const status = win.document.querySelector(".testTit_status"); if (status == null ? void 0 : status.classList.contains("testTit_status_complete")) { const msg2 = `章节测试已完成 : ` + jobName; lib.$message.success({ content: msg2 }); $console.log(msg2); } else { if (work_type === "job" || work_type === "not-job" && CommonProject.scripts.settings.cfg["work-when-no-job"]) { const workOptions = CommonProject.scripts.settings.methods.getWorkOptions(); if (workOptions.answererWrappers === void 0 || workOptions.answererWrappers.length === 0) { answerWrapperEmptyWarning(0); } else { func = () => { const msg2 = `开始答题 : ` + jobName; lib.$message.info({ content: msg2 }); $console.log(msg2); return JobRunner.chapter(root2, workOptions); }; } } if (work_type === "not-job" && CommonProject.scripts.settings.cfg["work-when-no-job"] === false) { const msg2 = `当前作业 ${jobName} 不是任务点,但待完成,如需开启自动答题请前往:通用-全局设置,开启强制答题。`; lib.$message.warn({ content: msg2 }); $console.warn(msg2); } } } } else if (read || pptWithAudio || timereader) { if (!CXProject.scripts.study.cfg.enablePPT) { const msg2 = `PPT/书籍阅读功能已被关闭(在上方菜单栏,超星学习通-课程学习中开启)。${jobName} 即将跳过`; lib.$message.warn({ content: msg2, duration: 10 }); $console.warn(msg2); } else { if (attachment.job) { func = () => { const msg2 = `正在学习 : ` + jobName; lib.$message.info({ content: msg2 }); $console.log(msg2); if (read) { return JobRunner.read(win); } else if (timereader) { return JobRunner.timereader(timereader); } else { return JobRunner.readPPTWithAudio(win); } }; } } } else if (hyperlink) { if (!CXProject.scripts.study.cfg.enableHyperlink) { const msg2 = `链接任务点已被关闭(在上方菜单栏,超星学习通-课程学习中开启)。${jobName} 即将跳过`; lib.$message.warn({ content: msg2, duration: 10 }); $console.warn(msg2); } else { if (attachment.job) { func = () => { const msg2 = `正在完成链接阅读任务 : ` + jobName; lib.$message.info({ content: msg2 }); $console.log(msg2); return JobRunner.hyperlink(hyperlink); }; } } } const job2 = { mid: attachment.property.mid, attachment, func }; searchedJobs.push(job2); return job2; } } }; let job; for (const iframe of searchIFrame(knowCardWin.document)) { job = search(iframe); if (job) { return job; } } return job; } function fixedVideoProgress() { if (state$3.study.videojs) { const { bar } = domSearch({ bar: ".vjs-control-bar" }, state$3.study.videojs); if (bar) { bar.style.opacity = "1"; } } } const JobRunner = { async media(setting, doc) { const { playbackRate: playbackRate2 = 1, volume: volume2 = 0 } = setting; const media = await waitForMedia({ root: doc }); const { videojs } = domSearch({ videojs: "#video,#audio" }, doc); if (!videojs || !media) { $console.error("视频检测不到,请尝试刷新或者手动切换下一章。"); return; } state$3.study.videojs = videojs; top$1.currentMedia = media; fixedVideoProgress(); if (setting.videoQuizStrategy === "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(() => { const errorDiv = doc.querySelector(".vjs-modal-dialog-content"); if (["视频文件损坏", "网络错误导致视频下载中途失败", "视频因格式不支持", "网络的问题无法加载"].some( (s) => errorDiv == null ? void 0 : errorDiv.innerText.includes(s) )) { $console.error("检测到视频加载失败,即将跳过视频。"); lib.$message.error("检测到视频加载失败,即将跳过视频。"); setTimeout(resolve, 3e3); } }, 3e3); const playFunction = async () => { if (hasFaceRecognition()) await waitForFaceRecognition(); if (hasNewFaceRecognition()) await waitForNewFaceRecognition(); if (media.ended === false) { await $.sleep(1e3); media.play(); media.playbackRate = playbackRate2; } }; media.addEventListener("pause", playFunction); media.addEventListener("ended", () => { media.removeEventListener("pause", playFunction); $console.log("视频播放完毕"); clearInterval(reloadInterval); resolve(); }); $console.log("视频开始播放"); media.volume = volume2; media.currentTime = 0; setTimeout(() => { playMedia(() => media.play()).then(() => { media.playbackRate = playbackRate2; }).catch(reject); }, 200); }); }, async read(win) { const finishJob = win.finishJob; if (finishJob) finishJob(); await $.sleep(3e3); }, async timereader(iframe) { var _a, _b; const src2 = ((_a = iframe.getAttribute("src")) == null ? void 0 : _a.toString()) || ""; const timing = src2 ? parseInt(((_b = new URL(src2).searchParams.get("timing")) == null ? void 0 : _b.toString()) || "60") : 60; lib.$message.info({ content: `正在学习长时阅读任务,请稍等,不要切换..(预计${(timing + 3) * 3}秒)`, duration: (timing + 3) * 3 }); await $.sleep((timing + 3) * 3 * 1e3); lib.$message.success("长时阅读任务完成!"); await $.sleep(5e3); }, async chapter(frame, { answererWrappers, period, upload, thread, stopSecondWhenFinish, redundanceWordsText, answerSeparators }) { if (answererWrappers === void 0 || answererWrappers.length === 0) { return answerWrapperEmptyWarning(0); } $console.info("开始章节测试"); const visual_state = BackgroundProject.scripts.render.cfg.visual; const frameWindow = frame.contentWindow; const { TiMu } = domSearchAll({ TiMu: ".TiMu" }, frameWindow.document); CORSUtils.panelNormal(); CommonProject.scripts.workResults.methods.init(); CORSUtils.pinWorkPanel(); const chapterTestTaskQuestionTitleTransform = (titles) => { const images = []; const removed = removeRedundantWords( titles.map((t2) => { if (!t2) return ""; const extracted = extractTextWithImages(t2); images.push(...extracted.images); return extracted.text; }).join(","), redundanceWordsText.split("\n") ); const text2 = removed.trim().replace(/^\d+[。、.]/, "").replace(/(\d+\.\d+分)/, "").replace(/\(..题, \d+?分\)/, "").replace(/\(..题, \d+\.\d+分\)/, "").replace(/[[(【(](..题|名词解释|完形填空|阅读理解)[\])】)]/, "").trim(); return { text: text2, images }; }; const chapterTestTaskQuestionTitleText = (titles) => chapterTestTaskQuestionTitleTransform(titles).text; const worker = new OCSWorker({ root: TiMu, elements: { title: [ (root2) => lib.$el(".Zy_TItle .clearfix", root2), (root2) => lib.$el(".firstUlList", root2), (root2) => lib.$el(".secondUlList", root2) ], options: "ul li .after,ul li textarea,ul textarea,ul li label:not(.before)", type: 'input[id^="answertype"]', lineSelectBox: ".thirdUlList .dept_select" }, thread: thread != null ? thread : 1, answerSeparators: answerSeparators.split(",").map((s) => s.trim()), answerer: createCommonAnswerer({ titleTransform: (elements2, ctx) => chapterTestTaskQuestionTitleTransform(elements2.title), optionsTransform: (elements2, ctx) => { var _a, _b; const typeInput = (_a = elements2.type) == null ? void 0 : _a[0]; const type = (typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0) || "unknown"; ctx.type = type; if (type === "completion") return ""; const optResults = ((_b = ctx.elements.options) != null ? _b : []).filter(Boolean).map((o) => extractTextWithImages(o)); return { text: optResults.map((r) => r.text).join("\n"), images: optResults.flatMap((r) => r.images) }; }, answererWrappers, period }), work: async (ctx) => { var _a; const { elements: elements2, searchInfos } = ctx; const typeInput = elements2.type[0]; const type = typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0; if (type && (type === "completion" || type === "multiple" || type === "judgement" || type === "single")) { const resolver = createDefaultQuestionResolver(ctx, (o) => extractTextWithImages(o).text)[type]; const handler = (type2, answer, option, ctx2) => { var _a2, _b, _c, _d, _e, _f, _g; if (type2 === "judgement" || type2 === "single" || type2 === "multiple") { const checked = ((_b = (_a2 = option == null ? void 0 : option.parentElement) == null ? void 0 : _a2.querySelector("label input")) == null ? void 0 : _b.getAttribute("checked")) === "checked" || ((_c = option == null ? void 0 : option.parentElement) == null ? void 0 : _c.getAttribute("aria-checked")) === "true"; if (checked) ; else { option == null ? void 0 : option.click(); } } else if (type2 === "completion" && answer.trim()) { const text2 = (_d = option == null ? void 0 : option.parentElement) == null ? void 0 : _d.querySelector("textarea"); const textareaFrame = (_e = option == null ? void 0 : option.parentElement) == null ? void 0 : _e.querySelector("iframe"); if (text2) { text2.value = answer; } if (textareaFrame == null ? void 0 : textareaFrame.contentDocument) { textareaFrame.contentDocument.body.innerHTML = answer; } if ((_f = option == null ? void 0 : option.parentElement) == null ? void 0 : _f.parentElement) { (_g = lib.$el("[onclick*=saveQuestion]", option.parentElement.parentElement)) == null ? void 0 : _g.click(); } } }; return await resolver(searchInfos, elements2.options, handler); } else if (type && type === "line") { const select = (el, opt_val) => { const selected = el.querySelector(`option[selected]`); const opt = el.querySelector(`option[value="${opt_val}"]`); selected == null ? void 0 : selected.removeAttribute("selected"); if (opt) { opt.setAttribute("selected", ""); } }; for (const answers of searchInfos.map((info) => info.results.map((res) => res.answer))) { for (const ans of answers) { const splited_ans = splitAnswer(ans); if (splited_ans.length !== 0 && elements2.lineSelectBox.length === splited_ans.length) { for (let index = 0; index < elements2.lineSelectBox.length; index++) { const box = elements2.lineSelectBox[index]; if (splited_ans[index]) { select(box, splited_ans[index]); const text2 = (_a = box.parentElement) == null ? void 0 : _a.querySelector(".chosen-single span"); if (text2) text2.textContent = splited_ans[index]; 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; CommonProject.scripts.workResults.methods.setResults(simplifyWorkResult(res, chapterTestTaskQuestionTitleText)); if ((_a = curr.result) == null ? void 0 : _a.finish) { BackgroundProject.scripts.data.methods.addQuestionCacheFromWorkResult( simplifyWorkResult([curr], chapterTestTaskQuestionTitleText) ); } CommonProject.scripts.workResults.methods.updateWorkStateByResults(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; const commonSetting = CommonProject.scripts.settings.cfg; if (commonSetting["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 (commonSetting["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 = commonSetting["randomWork-completeTexts-textarea"].split("\n").filter(Boolean); const text2 = completeTexts[Math.floor(Math.random() * completeTexts.length)]; const textareaFrame = (_j = option == null ? void 0 : option.parentElement) == null ? void 0 : _j.querySelector("iframe"); if (text2) { if (textarea) { textarea.value = text2; } if (textareaFrame == null ? void 0 : textareaFrame.contentDocument) { textareaFrame.contentDocument.body.innerHTML = text2; } } else { $console.error("请设置随机填空的文案"); } await $.sleep(500); } } } }, async onElementSearched(elements2) { const typeInput = elements2.type[0]; const type = typeInput ? getQuestionType(parseInt(typeInput.value)) : void 0; if (type === "judgement") { elements2.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 if (opt === "對") { option.textContent = "√"; } else if (opt === "錯") { 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({ enable_debug: BackgroundProject.scripts.dev.cfg.enable_answerer_debug }); const msg2 = `答题完成,将等待 ${stopSecondWhenFinish} 秒后进行保存或提交。`; $console.info(msg2); lib.$message.info({ content: msg2, duration: stopSecondWhenFinish }); await $.sleep(stopSecondWhenFinish * 1e3); await worker.uploadHandler({ type: upload, results, async callback(finishedRate, uploadable) { const msg22 = `完成率 ${finishedRate.toFixed(2)}% : ${uploadable ? "3秒后将自动提交" : "3秒后将自动保存"} `; $console.info(msg22); lib.$message.success({ content: msg22, duration: 3 }); await $.sleep(3e3); if (uploadable) { frameWindow.btnBlueSubmit(); await $.sleep(3e3); frameWindow.submitCheckTimes(); top$1.$("#workpop").hide(); } else { frameWindow.alert = () => { }; frameWindow.noSubmit(); } } }); if (visual_state === "minimize" && BackgroundProject.scripts.render.cfg.visual !== "minimize") { CORSUtils.panelMinimize(); } 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); } }; 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 readerAndFillHandle(searchInfos, list) { var _a; 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 && list.length !== 0) { for (let index = 0; index < ans.length; index++) { const item = list[index]; if (item) { (_a = lib.$el(`span.saveSingleSelect[data="${ans[index]}"]`, item)) == null ? void 0 : _a.click(); await $.sleep(200); } } return { finish: true }; } } return { finish: false }; } function hasFaceRecognition() { const faces = lib.$$el("#fcqrimg", top$1 == null ? void 0 : top$1.document); let active = false; for (const face of faces) { const src2 = face.getAttribute("src"); if (src2) { active = true; break; } } return active; } function hasNewFaceRecognition() { const faces = lib.$$el(".chapterVideoFaceMaskDiv", top$1 == null ? void 0 : top$1.document); let active = false; for (const face of faces) { if (face.style.display !== "none") { active = true; break; } } return active; } function waitForNewFaceRecognition() { let notified = false; return new Promise((resolve) => { const interval = setInterval(() => { const active = hasNewFaceRecognition(); if (active) { if (!notified) { notified = true; const msg2 = "检测到人脸识别,请手动进行识别后脚本才会继续运行。"; if (CXProject.scripts.study.cfg.notifyWhenHasFaceRecognition) { CommonProject.scripts.settings.methods.notificationBySetting(msg2, { duration: 0 }); } lib.$message.warn({ content: msg2, duration: 0 }); $console.warn(msg2); } } else { clearInterval(interval); resolve(); } }, 3e3); }); } function waitForFaceRecognition() { let notified = false; return new Promise((resolve) => { const interval = setInterval(() => { const active = hasFaceRecognition(); if (active) { if (!notified) { notified = true; const msg2 = "检测到人脸识别,请手动进行识别后脚本才会继续运行。"; if (CXProject.scripts.study.cfg.notifyWhenHasFaceRecognition) { CommonProject.scripts.settings.methods.notificationBySetting(msg2, { duration: 0 }); } lib.$message.warn({ content: msg2, duration: 0 }); $console.warn(msg2); } } else { clearInterval(interval); resolve(); } }, 3e3); }); } const CORSUtils = { pinWorkPanel: lib.cors.defineTopFunction(() => { BackgroundProject.scripts.render.methods.pin(CommonProject.scripts.workResults); }), panelNormal: lib.cors.defineTopFunction(() => { BackgroundProject.scripts.render.methods.normal(); }), panelMinimize: lib.cors.defineTopFunction(() => { BackgroundProject.scripts.render.methods.minimize(); }) }; const state$2 = { study: { currentMedia: void 0, currentStudyLockId: 0, playbackRateWarningListenerId: 0, courseLengthListenerId: 0 } }; const $msg_and_log$1 = (type, msg2) => { lib.$message[type](msg2); $console[type](msg2); }; const _StudyLock = class { constructor() { _StudyLock.auto_inc++; this.id = _StudyLock.auto_inc; state$2.study.currentStudyLockId = this.id; } canStudy() { return this.id === state$2.study.currentStudyLockId; } static getLock() { return new _StudyLock(); } }; let StudyLock = _StudyLock; StudyLock.auto_inc = 0; const IcveMoocProject = lib.Project.create({ name: "智慧职教", domains: [ "icve.com.cn", "ai.icve.com.cn", "course.icve.com.cn", "courshare.cn", "webtrn.cn" ], scripts: { guide: new lib.Script({ name: "💡 使用提示", matches: [ ["个人首页", "icve.com.cn/studycenter"], ["学习页面", "icve.com.cn/study/directory"], ["MOOC学院-个人首页", "user.icve.com.cn"], ["MOOC学院-首页", "mooc.icve.com.cn"], ["AI课程首页", "ai.icve.com.cn/app/my-excellent-home"] ], namespace: "icve.guide", configs: { notes: { defaultValue: createSteps(["点击任意课程进入", "点击任意章节进入学习", "等待脚本自动运行"]).outerHTML } }, oncomplete() { BackgroundProject.scripts.render.methods.pin(this); } }), studyCenter: new lib.Script({ name: "🖥️ 智慧职教-学习中心", namespace: "icve.study.center", matches: [ ["学习中心页面", "/study/directory/dir_course.html"], ["课程列表", "icve.com.cn/study/directory/directory_list.html"] ], configs: { playbackRate: playbackRate$1, volume, currentCourseUrlList: { defaultValue: [] } }, async oncomplete() { if (location.href.includes("icve.com.cn/study/directory/directory_list.html")) { await waitForElement(".h_cells a"); this.cfg.currentCourseUrlList = Array.from(document.querySelectorAll(".h_cells a")).map( (a) => a.href ); return; } if (this.cfg.currentCourseUrlList.length === 0) { try { const url = "https://www.icve.com.cn/study/directory/directory_list.html?courseId=" + new URL(location.href).searchParams.get("courseId"); const res = await fetch(url).then((res2) => res2.text()); const doc = new DOMParser().parseFromString(res, "text/html"); this.cfg.currentCourseUrlList = Array.from(doc.querySelectorAll(".h_cells a")).map( (a) => a.href ); } catch (e) { console.error(e); lib.$message.error("课程列表获取失败,请刷新页面重试。"); return; } } BackgroundProject.scripts.render.methods.pin(this); this.onConfigChange("playbackRate", (playbackRate2) => { state$2.study.currentMedia && (state$2.study.currentMedia.playbackRate = parseFloat(playbackRate2.toString())); }); this.onConfigChange("volume", (v) => state$2.study.currentMedia && (state$2.study.currentMedia.volume = v)); const study2 = async () => { var _a; const res = await Promise.race([waitForElement("video, audio"), waitForElement(".docBox")]); if (res) { const jobName = ((_a = document.querySelector(".tabsel.seled")) == null ? void 0 : _a.getAttribute("title")) || "-"; lib.$message.info("开始任务:" + jobName); $console.log(`任务 ${jobName} 开始。`); if (document.querySelector("video, audio")) { const media = await waitForMedia(); state$2.study.currentMedia = media; media.volume = this.cfg.volume; await new Promise((resolve, reject) => { try { console.log(document.hasFocus()); window.focus(); lib.$gm.unsafeWindow.jwplayer().onComplete(async () => { $console.log("视频/音频播放完成。"); await $.sleep(3e3); resolve(); }); const play = () => { lib.$gm.unsafeWindow.jwplayer().play(); lib.$gm.unsafeWindow.jwplayer().play(); media.playbackRate = parseFloat(this.cfg.playbackRate.toString()); }; media.addEventListener("pause", async () => { if (!media.ended) { await $.sleep(1e3); playMedia(play); } }); playMedia(play); } catch (err) { reject(err); } }); } lib.$message.success(`任务 ${jobName} 完成,三秒后下一章`); $console.log(`任务 ${jobName} 完成,三秒后下一章`); } else { $console.error(`不支持的任务页面,请跟作者进行反馈。三秒后下一章`); } await $.sleep(3e3); next2(); }; const next2 = () => { for (let index = 0; index < this.cfg.currentCourseUrlList.length; index++) { const url = this.cfg.currentCourseUrlList[index]; const nextUrl = this.cfg.currentCourseUrlList[index + 1]; if (new URL(url).hash === new URL(location.href).hash) { if (!nextUrl) { lib.$modal.alert({ content: "全部任务已完成" }); CommonProject.scripts.settings.methods.notificationBySetting("全部任务点已完成!", { duration: 0, extraTitle: "智慧职教学习脚本" }); return; } else { window.location.href = this.cfg.currentCourseUrlList[index + 1]; } } } }; study2(); } }), study: new lib.Script({ name: "🖥️ MOOC学院-课程学习", namespace: "icve.study.main", matches: [["课程学习页面", "/learnspace/learn/learn/templateeight/index.action"]], configs: { notes: { defaultValue: lib.$ui.notes([ "如果视频无法播放,可以手动点击其他任务跳过视频。", "经过测试视频倍速最多二倍,否则会判定无效。", "手动进入作业页面才能使用自动答题。" ]).outerHTML }, playbackRate: playbackRate$1, volume, restudy, showScrollBar: { label: "显示右侧滚动条", attrs: { type: "checkbox" }, defaultValue: true }, expandAll: { label: "展开所有章节", attrs: { type: "checkbox" }, defaultValue: true }, switchPeriod: { label: "下一章节切换间隔(秒)", defaultValue: 10, attrs: { type: "number", min: 0, max: 999, step: 1 } } }, onrender() { this.offConfigChange(state$2.study.playbackRateWarningListenerId); state$2.study.playbackRateWarningListenerId = this.onConfigChange("playbackRate", (playbackRate2) => { if (playbackRate2 > 4) { lib.$modal.alert({ title: "⚠️高倍速警告", content: lib.$ui.notes(["高倍速可能导致视频无法完成!"]) }); } }) || 0; }, async oncomplete() { var _a; BackgroundProject.scripts.render.methods.pin(this); await $.sleep(3e3); this.onConfigChange("volume", (v) => state$2.study.currentMedia && (state$2.study.currentMedia.volume = v)); this.onConfigChange( "playbackRate", (r) => state$2.study.currentMedia && (state$2.study.currentMedia.playbackRate = parseFloat(r.toString())) ); const mainContentWin = (_a = lib.$el("#mainContent")) == null ? void 0 : _a.contentWindow; if (mainContentWin) { lib.$modal.confirm({ content: lib.h("div", [ "是否开始自动学习当前章节?", lib.h("br"), "你也可以选择任意的章节进行点击,脚本会自动学习,并一直往下寻找章节。" ]), cancelButtonText: "我想手动选择章节", confirmButtonText: "开始学习", async onConfirm() { study2(StudyLock.getLock()); scrollToJob(); } }); } if (this.cfg.showScrollBar) { const bar = lib.$el(".dumascroll_area", mainContentWin.document); bar && (bar.style.overflow = "auto"); } if (this.cfg.expandAll) { lib.$$el(".s_sectionlist,.s_sectionwrap", mainContentWin.document).forEach((el) => el.style.display = "block"); } for (const job of lib.$$el(".s_point[itemtype]", mainContentWin.document)) { job.addEventListener("click", (e) => { const lock = StudyLock.getLock(); if (e.isTrusted) { if (job.getAttribute("itemtype") === "exam") { return lib.$message.info({ duration: 60, content: "检测到您手动选择了作业/考试章节,将不会自动跳转,请完成后手动选择其他章节,脚本会自动学习。" }); } else { lib.$message.info("检测到章节切换,即将自动学习..."); } } setTimeout(() => { study2(lock); }, 3e3); }); } const scrollToJob = () => { var _a2; return (_a2 = lib.$el(".s_pointerct", mainContentWin.document)) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" }); }; const study2 = async (studyLock) => { var _a2; const iframe = lib.$el("iframe", mainContentWin.document); const win = iframe == null ? void 0 : iframe.contentWindow; if (win) { const doc = win.document; if (iframe.src.includes("content_video.action") || iframe.src.includes("content_audio.action")) { $console.log("视频/音频播放中..."); try { const media = await waitForMedia({ root: doc }); state$2.study.currentMedia = media; media.playbackRate = parseFloat(this.cfg.playbackRate.toString()); media.volume = this.cfg.volume; media.currentTime = 0; await new Promise((resolve, reject) => { try { win.jwplayer().onComplete(async () => { $console.log("视频/音频播放完成。"); await $.sleep(3e3); resolve(); }); media.addEventListener("pause", async () => { if (!media.ended) { await Promise.race([ waitForPopupQuestion(doc), handleContinueDialog() ]); await $.sleep(1e3); playMedia(() => media.play()); } }); playMedia(() => media.play()); } catch (err) { reject(err); } }); } catch (err) { lib.$message.error(String(err)); } } else if (iframe.src.includes("content_doc.action")) { await $.sleep(5e3); } } $console.log(this.cfg.switchPeriod + " 秒后切换下一章节。"); await $.sleep(this.cfg.switchPeriod * 1e3); if (studyLock.canStudy()) { let nextEl; let isBellowCurrentJob = false; const jobs = lib.$$el(".s_point[itemtype]", mainContentWin.document); for (let index = 0; index < jobs.length; index++) { const job = jobs[index]; if (job.classList.contains("s_pointerct")) { isBellowCurrentJob = true; } else if (isBellowCurrentJob) { if (job.querySelector(".done_icon_show") === null || this.cfg.restudy) { $console.log("下一章:", job.title || ((_a2 = lib.$el(".s_pointti", job)) == null ? void 0 : _a2.title) || "未知"); nextEl = job; break; } } } if (nextEl) { nextEl.click(); scrollToJob(); } else { lib.$modal.alert({ content: "全部任务已完成" }); CommonProject.scripts.settings.methods.notificationBySetting("全部任务点已完成!", { duration: 0, extraTitle: "智慧职教学习脚本" }); } } }; } }), work: new lib.Script({ name: "✍️ 作业考试脚本", matches: [["作业考试页面", "/exam"]], namespace: "icve.work", configs: { notes: { defaultValue: lib.$ui.notes([ "自动答题前请在 “通用-全局设置” 中设置题库配置。", "可以搭配 “通用-在线搜题” 一起使用。", "请手动进入作业考试页面才能使用自动答题。" ]).outerHTML } }, async oncomplete() { lib.$message.warn({ content: "自动答题时请勿切换题目,否则可能导致重复搜题或者脚本卡主。", duration: 0 }); const resetToBegin = () => { var _a; (_a = document.querySelectorAll(`.sheet_nums [id*="sheetSeq"]`).item(0)) == null ? void 0 : _a.click(); }; commonWork(this, { workerProvider: work, beforeRunning: async () => { resetToBegin(); await $.sleep(1e3); }, onRestart: () => resetToBegin() }); } }), workDispatcher: new lib.Script({ name: "作业调度脚本", matches: [ ["作业进入页面", "/platformwebapi/student/exam/"], ["确认作业页面", "/student/exam/studentExam_studentInfo.action"] ], hideInPanel: true, oncomplete() { if (/\/platformwebapi\/student\/exam/.test(window.location.href)) { lib.cors.on("icve-work-start", () => { setTimeout(() => { lib.$gm.unsafeWindow.openExamInfo(); }, 3e3); }); } if (/\/student\/exam\/studentExam_studentInfo.action/.test(window.location.href)) { setTimeout(() => { lib.$gm.unsafeWindow.enterExamPage(); }, 3e3); } } }), "ai-study": new lib.Script({ name: "🖥️ AI课程", namespace: "icve.ai.study", matches: [ ["课程页面", "ai.icve.com.cn/app/coursedetails-excellent"], ["课程页面", "ai.icve.com.cn/app/my-excellent-home"], ["学习页面", "ai.icve.com.cn/excellent-study"] ], configs: { notes: { defaultValue: lib.$ui.notes([ [ "如果脚本卡死或者您不想学习,", "可以点击其他任意章节继续进行学习。", "PPT请勿加快点击,否则可能无法记录学习进度。" ] ]).outerHTML }, volume, playbackRate: { label: "视频倍速", tag: "select", options: [1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.5, 4, 6, 8, 16].map((rate) => [ rate.toString(), rate + " x" ]), defaultValue: "1" }, autoOpenAllChapter: { label: "自动打开全部章节", attrs: { title: "如果没有打开全部章节,那么当任务点达到当前章节最后一个时将无法跳转到其他章节列表!", type: "checkbox" }, defaultValue: true }, restudy }, onhistorychange(type) { if (type !== "replace") { return; } if (location.href.includes("kcnr")) { location.reload(); } }, async oncomplete(type) { if (document.location.href.includes("ai.icve.com.cn/app/my-excellent-home")) { return lib.$message.info("点击任意课程开始自动学习"); } BackgroundProject.scripts.render.methods.pin(this); this.onConfigChange("volume", (val) => { if (state$2.study.currentMedia) { state$2.study.currentMedia.volume = parseFloat(val.toString()); } }); this.onConfigChange("playbackRate", (val) => { if (state$2.study.currentMedia) { state$2.study.currentMedia.playbackRate = parseFloat(val.toString()); } }); const waitForLoad2 = () => { return new Promise((resolve) => { const check = () => { if (document.querySelector(".contentBox")) { resolve(); } else { setTimeout(check, 100); } }; check(); }); }; const closeStudyContinueDialog = () => { return new Promise((resolve) => { let stop = false; const check = () => { var _a, _b; if (document.querySelector(".el-message-box__wrapper")) { (_a = lib.$el(".el-message-box__wrapper")) == null ? void 0 : _a.remove(); (_b = lib.$el(".v-modal")) == null ? void 0 : _b.remove(); resolve(); } else { !stop && setTimeout(check, 100); } }; check(); setTimeout(() => { stop = true; resolve(); }, 3 * 1e3); }); }; await waitForLoad2(); await closeStudyContinueDialog(); await waitForLoad2(); await $.sleep(3e3); $msg_and_log$1("info", "即将打开全部章节列表,请稍等"); const openAllChapter = async () => { var _a; const model = lib.$modal.simple({ maskCloseable: false, footer: void 0, content: "正在展开全部章节列表,请耐心等待不要操作..." }); const not_scrolled_titles = Array.from(document.querySelectorAll(".one-title")).filter( (el) => !el.querySelector(".zhankai") ); const waitForChapterOpen = (title) => { return new Promise((resolve) => { let stop = false; const check = () => { var _a2; const parent = (_a2 = title.parentElement) == null ? void 0 : _a2.parentElement; const content = parent == null ? void 0 : parent.querySelector(".panel-content"); if ((content == null ? void 0 : content.style.display) !== "none" && ((content == null ? void 0 : content.querySelectorAll(".node").length) || 0) > 0) { resolve(); } else { !stop && setTimeout(check, 100); } }; check(); setTimeout(() => { stop = true; resolve(); }, 10 * 1e3); }); }; for (const nst of not_scrolled_titles) { try { (_a = nst.querySelector(".jiantou")) == null ? void 0 : _a.click(); nst.focus(); nst.scrollIntoView({ behavior: "smooth", block: "center" }); await waitForChapterOpen(nst); await $.sleep(1e3); } catch (e) { $console.error("打开章节失败", e); } } model == null ? void 0 : model.remove(); }; if (this.cfg.autoOpenAllChapter) await openAllChapter(); let study_id = ""; document.querySelectorAll(".node").forEach((el) => { el.addEventListener("click", () => { study2(study_id = Math.random().toString(36).substr(2, 9)); }); }); const study2 = async (id) => { var _a; $msg_and_log$1("info", "即将开始学习:" + (((_a = lib.$el(".contentBox")) == null ? void 0 : _a.__vue__.nrdata.name) || "未知任务点")); await $.sleep(3e3); await (async () => { var _a2; const active = document.querySelector(".panelList .node.active"); active == null ? void 0 : active.focus(); active == null ? void 0 : active.scrollIntoView({ behavior: "smooth", block: "center" }); if ((active == null ? void 0 : active.querySelector(".wc")) && !this.cfg.restudy) { return $msg_and_log$1("info", "当前任务已完成,即将跳过"); } const vue = (_a2 = lib.$el(".FilePreview")) == null ? void 0 : _a2.__vue__; const img = lib.$el(".ql-editor"); const work2 = lib.$el(".shiti"); if (work2) { return $msg_and_log$1("warn", "检测到当前为作业任务,请完成课程后手动进入自动答题。"); } else if (img) { return $msg_and_log$1("warn", "检测到当前为图片任务,即将跳过"); } else { if (!vue) { return lib.$message.error({ content: "获取课程数据失败,或者未知任务点,即将跳过" }); } const watchOffice = async () => { const total = vue.photoList.length; for (let index = 0; index < total + 1; index++) { if (id !== study_id) return; vue.next(); await $.sleep(3e3); } }; lib.$message.info("开始学习"); if (["video", "audio"].includes(vue.curType)) { await closeStudyContinueDialog(); await watchMedia$2(); } else if (["office", "ppt"].includes(vue.curType)) { await watchOffice(); if (id !== study_id) return; await $.sleep(1e3); } else { $msg_and_log$1("warn", "未知的任务点,即将跳过"); } } })(); if (id !== study_id) return; const next2 = getNext(); if (!next2) { return $msg_and_log$1("warn", "没有找到下一章节!"); } $msg_and_log$1("info", "即将进入下一章节"); await $.sleep(3e3); if (id !== study_id) return; next2.click(); }; const getNext = () => { const list = Array.from(document.querySelectorAll(".panelList .node")); for (let index = 0; index < list.length; index++) { const element = list[index]; if (element.classList.contains("active")) { return list[index + 1]; } } }; study2(study_id); } }), "ai-work": new lib.Script({ name: "✍️ AI作业", namespace: "icve.ai.work", matches: [["作业页面", "ai.icve.com.cn/preview-exam"]], configs: { notes: { defaultValue: lib.$ui.notes([ "自动答题前请在 “通用-全局设置” 中设置题库配置。", "可以搭配 “通用-在线搜题” 一起使用。", "请手动进入作业考试页面才能使用自动答题。", "自动答题时请勿切换题目,否则可能导致重复搜题或者脚本卡主!" ]).outerHTML } }, oncomplete() { lib.$message.warn({ content: "自动答题时请勿切换题目,否则可能导致重复搜题或者脚本卡主。", duration: 0 }); const resetToBegin = () => { var _a; (_a = document.querySelectorAll(`.list-box span`).item(0)) == null ? void 0 : _a.click(); }; commonWork(this, { workerProvider: aiWork, beforeRunning: async () => { resetToBegin(); await $.sleep(1e3); }, onRestart: () => resetToBegin() }); } }) } }); async function watchMedia$2() { const media = await waitForMedia(); media.volume = parseFloat(IcveMoocProject.scripts["ai-study"].cfg.volume.toString()); media.playbackRate = parseFloat(IcveMoocProject.scripts["ai-study"].cfg.playbackRate.toString()); state$2.study.currentMedia = media; const success = await playMedia(() => media.play()); if (!success) { return; } return new Promise((resolve, reject) => { media.addEventListener("ended", () => { resolve(); }); media.addEventListener("pause", () => { setTimeout(() => { if (media.ended) { resolve(); } else if (media.paused) { media.play(); media.volume = parseFloat(IcveMoocProject.scripts["ai-study"].cfg.volume.toString()); media.playbackRate = parseFloat(IcveMoocProject.scripts["ai-study"].cfg.playbackRate.toString()); } }, 1e3); }); }); } function work({ answererWrappers, period, thread, answerSeparators }) { lib.$message.info("开始作业"); CommonProject.scripts.workResults.methods.init({ dynamic: true }); console.log({ answererWrappers, period, thread }); const titleTransformWithImages = (titles) => { const images = []; const text2 = titles.filter((t2) => (t2 == null ? void 0 : t2.innerText) || (t2 == null ? void 0 : t2.querySelector("img"))).map((t2) => { var _a, _b; if (t2) { const title = t2.cloneNode(true); (_a = title.querySelector('[name*="questionIndex"]')) == null ? void 0 : _a.remove(); (_b = title.querySelector(".q_score")) == null ? void 0 : _b.remove(); const extracted = extractTextWithImages(title); images.push(...extracted.images); return extracted.text.trim().replace(/^、/, "") || ""; } return ""; }).join(","); return { text: text2, images }; }; const titleTransform = (titles) => titleTransformWithImages(titles).text; let totalQuestionCount = 0; let requestedCount = 0; let resolvedCount = 0; function getType(options) { const radio_len = options.map((o) => o.querySelector('[type="radio"]')).reduce((a, b) => { return a + (b ? 1 : 0); }, 0); return radio_len > 0 ? radio_len === 2 ? "judgement" : "single" : options.some((o) => o.querySelector('[type="checkbox"]')) ? "multiple" : options.some((o) => o.querySelector("textarea")) ? "completion" : options.some((o) => o.querySelector(".fillblank_input input")) ? "fill-blank" : void 0; } const worker = new OCSWorker({ root: ".q_content", elements: { title: '.divQuestionTitle, [name="fillblankTitle"]', options: ".questionOptions .q_option, .questionOptions.divTextarea, .answerOption" }, thread: thread != null ? thread : 1, answerSeparators: answerSeparators.split(",").map((s) => s.trim()), answerer: createCommonAnswerer({ titleTransform: (elements2, _ctx) => titleTransformWithImages(elements2.title), optionsTransform: (elements2, ctx) => { var _a; const type = getType(ctx.elements.options) || "unknown"; ctx.type = type; if (type === "completion") return ""; const optResults = ((_a = ctx.elements.options) != null ? _a : []).filter(Boolean).map((o) => extractTextWithImages(o)); return { text: optResults.map((r) => r.text).join("\n"), images: optResults.flatMap((r) => r.images) }; }, answererWrappers, period }), async work(ctx) { const options = ctx.elements.options; const type = getType(options); if (!type) { throw new Error("无法获取题目类型!"); } if (type === "fill-blank") { const inputs = options.map((o) => Array.from(o.querySelectorAll(".fillblank_input input"))).flat(); for (const searchInfo of ctx.searchInfos) { for (const result of searchInfo.results) { const answers = splitAnswer(result.answer); if (answers.length === inputs.length) { for (let index = 0; index < inputs.length; index++) { inputs[index].value = answers[index]; } return { finish: true }; } } } } else { const resolver = createDefaultQuestionResolver(ctx, (o) => extractTextWithImages(o).text)[type]; const res = await resolver(ctx.searchInfos, ctx.elements.options, (type2, answer, option) => { var _a, _b; if (type2 === "judgement" || type2 === "single" || type2 === "multiple") { if (option.querySelector(".checkbox_on") === null) { (_a = lib.$el("div", option)) == null ? void 0 : _a.click(); } } else if (type2 === "completion" && answer.trim()) { const text2 = option.querySelector("textarea"); const textIframe = option.querySelector('iframe[id*="ueditor"]'); if (text2) { text2.value = answer; } if (textIframe) { const view = (_b = textIframe.contentWindow) == null ? void 0 : _b.document.querySelector("body.view > p"); if (view) { view.innerText = answer; } } } }); return res; } return { finish: false }; }, onElementSearched(elements2, root2) { console.log("elements", elements2); }, onQuestionDetected(currentResult) { updateDynamicResult(currentResult, titleTransform); }, onResultsUpdate(currentResult) { var _a; updateDynamicResult(currentResult, titleTransform); if (currentResult.resolved) { totalQuestionCount++; requestedCount++; resolvedCount++; if ((_a = currentResult.result) == null ? void 0 : _a.finish) { BackgroundProject.scripts.data.methods.addQuestionCacheFromWorkResult( simplifyWorkResult([currentResult], titleTransform) ); } CommonProject.scripts.workResults.methods.updateWorkState({ totalQuestionCount, requestedCount, resolvedCount }); } } }); const getNextBtn = () => document.querySelector(".paging_next"); let next2 = getNextBtn(); (async () => { while (next2 && worker.isClose === false) { await worker.doWork({ enable_debug: BackgroundProject.scripts.dev.cfg.enable_answerer_debug }); await $.sleep(1e3); next2 = getNextBtn(); if (next2.style.display === "none") { break; } else { next2 == null ? void 0 : next2.click(); await $.sleep(1e3); } } lib.$message.success({ content: "作业/考试完成,请自行检查后保存或提交。", duration: 0 }); worker.emit("done"); CommonProject.scripts.workResults.cfg.questionPositionSyncHandlerType = "icve"; })(); dynamicWorkTips(worker); return worker; } function aiWork({ answererWrappers, period, thread, answerSeparators }) { lib.$message.info("开始作业"); CommonProject.scripts.workResults.methods.init({ dynamic: true }); console.log({ answererWrappers, period, thread }); const titleTransform = (titles) => { const images = []; const text2 = titles.filter((t2) => (t2 == null ? void 0 : t2.innerText) || (t2 == null ? void 0 : t2.querySelector("img"))).map((t2) => { if (t2) { const extracted = extractTextWithImages(t2); images.push(...extracted.images); return extracted.text.replace(/\s+/g, " ").trim() || ""; } return ""; }).join(","); return { text: text2, images }; }; const titleText = (titles) => titleTransform(titles).text; let totalQuestionCount = 0; let requestedCount = 0; let resolvedCount = 0; function getType(options) { const radio_len = options.map((o) => o.querySelector('[type="radio"]')).reduce((a, b) => { return a + (b ? 1 : 0); }, 0); return radio_len > 0 ? radio_len === 2 ? "judgement" : "single" : options.some((o) => o.querySelector('[type="checkbox"]')) ? "multiple" : options.some((o) => o.querySelector("textarea")) || options.some((o) => o.classList.contains("ivu-input")) ? "completion" : options.some((o) => o.querySelector(".fillblank_input input")) ? "fill-blank" : void 0; } const worker = new OCSWorker({ root: ".content-item", elements: { title: ".questions-content [class*=title-content]", options: "label[class*=group-item],.ivu-input-wrapper input" }, thread: thread != null ? thread : 1, answerSeparators: answerSeparators.split(",").map((s) => s.trim()), answerer: createCommonAnswerer({ titleTransform: (elements2, _ctx) => titleTransform(elements2.title), optionsTransform: (elements2, ctx) => { ctx.type = getType(ctx.elements.options) || "unknown"; const optResults = ctx.elements.options.map((o) => extractTextWithImages(o)); return { text: optResults.map((r) => r.text).join("\n"), images: optResults.flatMap((r) => r.images) }; }, answererWrappers, period }), work: { optionText: (o) => extractTextWithImages(o).text, type: (ctx) => { return getType(ctx.elements.options); }, async handler(type, answer, option, ctx) { if (type === "judgement" || type === "single" || type === "multiple") { if (option.querySelector(".ivu-radio-checked") === null) { option == null ? void 0 : option.click(); } } else if (type === "completion" && answer.trim()) { if (option.tagName === "INPUT") { option.focus(); await $.sleep(100); option.value = answer.trim(); await $.sleep(100); option.dispatchEvent(new Event("input", { bubbles: true })); await $.sleep(100); option.blur(); await $.sleep(100); } } } }, onElementSearched(elements2, root2) { console.log("elements", elements2); }, onQuestionDetected(currentResult) { updateDynamicResult(currentResult, titleText); }, onResultsUpdate(currentResult) { var _a; updateDynamicResult(currentResult, titleText); if (currentResult.resolved) { totalQuestionCount++; requestedCount++; resolvedCount++; if ((_a = currentResult.result) == null ? void 0 : _a.finish) { BackgroundProject.scripts.data.methods.addQuestionCacheFromWorkResult( simplifyWorkResult([currentResult], titleText) ); } CommonProject.scripts.workResults.methods.updateWorkState({ totalQuestionCount, requestedCount, resolvedCount }); } } }); const getNextBtn = () => document.querySelector("div.center_btn > button:nth-child(2)"); let next2 = getNextBtn(); (async () => { while (next2 && worker.isClose === false) { await worker.doWork({ enable_debug: BackgroundProject.scripts.dev.cfg.enable_answerer_debug }); await $.sleep(1e3); next2 = getNextBtn(); if (next2.getAttribute("disabled")) { break; } else { next2 == null ? void 0 : next2.click(); await $.sleep(1e3); } } lib.$message.success({ content: "作业/考试完成,请自行检查后保存或提交。", duration: 0 }); worker.emit("done"); CommonProject.scripts.workResults.cfg.questionPositionSyncHandlerType = "icve"; })(); dynamicWorkTips(worker); return worker; } function waitForPopupQuestion(dom2) { return new Promise((resolve) => { const interval = setInterval(() => { var _a, _b; const el = lib.$el(".popup-test", dom2); if (el) { clearInterval(interval); const right_answer = ((_a = lib.$el("#right_answer", el)) == null ? void 0 : _a.value) || "A"; for (const answer of right_answer.split("")) { const item = lib.$el(`li.test-item-cell[curval="${answer}"]`, el); item == null ? void 0 : item.click(); } (_b = lib.$el('[name="save_btn"]', el)) == null ? void 0 : _b.click(); setTimeout(() => { var _a2; (_a2 = lib.$el('[name="continue_btn"]', el)) == null ? void 0 : _a2.click(); resolve(); }, 3e3); } }, 1e3); setTimeout(() => { clearInterval(interval); resolve(); console.log("未找到弹窗,继续执行"); }, 60 * 1e3); }); } function handleContinueDialog() { return new Promise((resolve, reject) => { const interval = setInterval(() => { const el = document.querySelector(".layui-layer-btn0"); if (el) { el.click(); setTimeout(() => { clearInterval(interval); resolve(); }, 1e3); } }, 3e3); setTimeout(() => { clearInterval(interval); resolve(); console.log("未找到弹窗,继续执行"); }, 60 * 1e3); }); } const state$1 = { studying: false, studyingId: "", media: null }; const work_pages = [ ["资源库keep作业页面", "study/spockeepTest"], ["资源库job作业页面", "study/spocjobTest"], ["资源库考试", "study/spoctest"], ["课堂测试作业界面", "study/courseteaching/test/homeWork"], ["作业页面", "icve-study/coursePreview/jobTes"], ["考试页面", "icve-study/coursePreview/test"], ["考试页面", "icve-study/test"], ["资源库测验页面", "icve-study/coursePreview/keepTest"] ]; const isWork = () => { return window.location.href.includes("icve-study/coursePreview/jobTes") || window.location.href.includes("icve-study/coursePreview/keepTest") || window.location.href.includes("study/spockeepTest") || window.location.href.includes("study/spocjobTest") || window.location.href.includes("study/courseteaching/test/homeWork"); }; const isExam = () => { return window.location.href.includes("icve-study/coursePreview/test") || window.location.href.includes("icve-study/test") || window.location.href.includes("study/spoctest"); }; const ZJYProject = lib.Project.create({ name: "职教云", domains: ["icve.com.cn", "zjy2.icve.com.cn", "zyk.icve.com.cn"], scripts: { guide: new lib.Script({ name: "🖥️ 使用提示", matches: [ ["学习页面", "zjy2.icve.com.cn/study"], ["资源库", "zyk.icve.com.cn/icve-study/"] ], namespace: "zjy.study.guide", configs: { notes: { defaultValue: createSteps(["登录网课平台", "点击任意章节进入学习", "等待脚本自动运行"]).outerHTML } } }), v2: new lib.Script({ name: "旧版切换器", matches: [["新版智慧职教", "zjy2.icve.com.cn/study/v2/"]], hideInPanel: true, oncomplete() { $msg.info("脚本只支持旧版职教云,即将跳转到旧版职教云页面..."); lib.$modal.alert({ title: "提示", content: "脚本只支持旧版职教云,即将跳转到旧版职教云页面...", maskCloseable: false }); setTimeout(() => { location.href = "/study/index"; }, 5e3); } }), dispatcher: new lib.Script({ name: "调度器", matches: [ ["学习页面", "zjy2.icve.com.cn/study"], ["资源库", "zyk.icve.com.cn/icve-study/"], ["内容资源页面", "zjy2.icve.com.cn/study/studentFast/classroomNow"], ["在线课堂学习页面", "zjy2.icve.com.cn/study/studentFast/courseware"], ["课堂作业测试界面", "zjy2.icve.com.cn/study/courseteaching/test/homeWork"] ], hideInPanel: true, methods() { return { dispatch: async () => { var _a, _b, _c; if (["zjy2.icve.com.cn/study/studentFast/classroomNow"].some((i) => window.location.href.includes(i))) { await waitForElement(".classroom_activities .active_list"); const courseData = getCourseDataInClassroomNowPage(); console.log(courseData); const courseId = ((_c = (_b = (_a = document.querySelector(".teacherLayout")) == null ? void 0 : _a.__vue__) == null ? void 0 : _b.courseInfo) == null ? void 0 : _c.id) || ""; if (!courseData || !courseId) { return; } ZJYProject.scripts.study.cfg.currentCourseId = courseId; ZJYProject.scripts.study.cfg.courseList = courseData; lib.$message.success("课程数据获取成功,请点击课程章节开始学习"); } else if ([ "zyk.icve.com.cn/icve-study/coursePreview/courseware", "zjy2.icve.com.cn/study/coursePreview/spoccourseIndex/courseware", "zjy2.icve.com.cn/study/studentFast/courseware" ].some((i) => window.location.href.includes(i))) { const isClassroomNowStudy = location.href.includes("zjy2.icve.com.cn/study/studentFast/courseware"); ZJYProject.scripts.study.methods.main(isClassroomNowStudy ? "classroomNow" : "normal"); } else if (work_pages.map(([_, p]) => p).some((i) => window.location.href.includes(i))) { ZJYProject.scripts.work.methods.main(); } } }; }, onhistorychange(type) { if (type === "push") { this.methods.dispatch(); } }, oncomplete() { this.methods.dispatch(); } }), study: new lib.Script({ matches: [ ["学习页面", "zjy2.icve.com.cn/study/coursePreview/spoccourseIndex/courseware"], ["在线课堂学习页面", "zjy2.icve.com.cn/studentFast/courseware"], ["资源库学习页面", "zyk.icve.com.cn/icve-study/coursePreview/courseware"] ], name: "✍️ 课程学习", namespace: "zjy.study.main", configs: { notes: { defaultValue: lib.$ui.notes([ ["如果脚本卡死或者您不想学习,", "可以点击其他任意章节继续进行学习。"], "提示:职教云无法使用倍速。" ]).outerHTML }, volume, playbackRate: { label: "视频倍速", tag: "select", options: [1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.5, 4, 6, 8].map((rate) => [ rate.toString(), rate + " x" ]), defaultValue: "1" }, pptReadPeriod: { label: "PPT 阅读每页停留时间(秒)", defaultValue: 1, attrs: { type: "number", min: 1, step: 1, max: 10 } }, currentCourseId: { defaultValue: "" }, courseList: { defaultValue: [] } }, methods() { return { main: async (type) => { var _a; const id = new URL(window.location.href).searchParams.get(type === "classroomNow" ? "activityId" : "id"); if (!id) { return; } if (state$1.studying && id === state$1.studyingId) { return; } state$1.studyingId = id; state$1.studying = true; this.onConfigChange("volume", (val) => { if (state$1.media) { state$1.media.volume = parseFloat(val.toString()); } }); this.onConfigChange("playbackRate", (val) => { if (state$1.media) { state$1.media.playbackRate = parseFloat(val.toString()); } }); await waitForLoad(); setTimeout(() => { var _a2, _b; (_a2 = lib.$el(".el-message-box__wrapper")) == null ? void 0 : _a2.remove(); (_b = lib.$el(".v-modal")) == null ? void 0 : _b.remove(); }, 3e3); await waitForLoad(); if (type === "normal") { const courseId = getUniqueCourseId(); if (!courseId) { lib.$message.error({ content: "获取课程数据失败,请手动刷新页面" }); return; } const not_same_class = !ZJYProject.scripts.study.cfg.currentCourseId || ZJYProject.scripts.study.cfg.currentCourseId !== courseId; if (not_same_class || !ZJYProject.scripts.study.cfg.courseList || ZJYProject.scripts.study.cfg.courseList.length === 0) { const courseData = await getCourseData(); if (!courseData) { return; } ZJYProject.scripts.study.cfg.currentCourseId = courseId; ZJYProject.scripts.study.cfg.courseList = courseData; } } const courseInfo = ZJYProject.scripts.study.cfg.courseList.find((i) => i.id === id); if (!courseInfo) { const btn = lib.h("button", { className: "base-style-button" }, "修复数据"); btn.onclick = async () => { const courseId = getUniqueCourseId(); if (!courseId) { lib.$message.error({ content: "获取课程数据失败!" }); return; } const courseData = await getCourseData(); if (!courseData) { return; } ZJYProject.scripts.study.cfg.currentCourseId = courseId; ZJYProject.scripts.study.cfg.courseList = courseData; lib.$modal.simple({ title: "提示", content: "数据已修复完毕,请刷新页面重新尝试运行。" }); }; const err = "获取课程信息失败,请手动刷新页面,或者尝试修复数据:"; lib.$message.error({ content: lib.h("span", [err, btn]), duration: 0 }); $console.error(err); return; } const vue = getVueBindElement(); const courseType = vue.curType === "video" ? "video" : (courseInfo == null ? void 0 : courseInfo.fileType) || ""; const started_url = window.location.href; let msg2 = "开始学习:" + courseType + "-" + courseInfo.name; lib.$message.success(msg2); $console.info(msg2); if (["ppt", "doc", "pptx", "docx", "pdf", "txt", "ppt文档", "xls", "xlsx"].some((i) => courseType === i)) { await watchFile(this.cfg.pptReadPeriod); } else if (["video", "audio", "mp4", "mp3", "flv", "wav", "视频"].some((i) => courseType === i)) { const text2 = ((_a = lib.$el(".guide")) == null ? void 0 : _a.textContent) || ""; msg2 = `任务点 ${courseInfo.name},不支持播放。`; if (text2.includes("很抱歉,您的浏览器不支持播放此类文件") || text2.includes("此视频暂无法播放")) { msg2 = `任务点 ${courseInfo.name},不支持播放。`; lib.$message.error(msg2); $console.error(msg2); } else { await watchMedia$1(); } } else if (["png", "jpg", "图片"].some((i) => courseType === i)) { msg2 = `已查看图片任务点 ${courseInfo.name},即将跳过。`; lib.$message.info(msg2); $console.info(msg2); } else { msg2 = `未知的任务点 ${courseInfo.name},类型 ${courseType},请跟作者进行反馈。`; lib.$message.error(msg2); $console.error(msg2); } if (started_url === window.location.href) { msg2 = "任务点结束,五秒后下一章"; lib.$message.warn("如果职教云一直卡在显示:“资源类型无法学习,请核对数据!” 请手动切换下一章。"); lib.$message.info(msg2); $console.info(msg2); await $.sleep(5e3); await next(type); } } }; } }), work: new lib.Script({ matches: work_pages, name: "✍️ 作业考试脚本", namespace: "zjy.work.main", configs: { notes: { defaultValue: lib.$ui.notes([ "自动答题前请在 “通用-全局设置” 中设置题库配置。", "可以搭配 “通用-在线搜题” 一起使用。", "请手动进入作业考试页面才能使用自动答题。" ]).outerHTML } }, methods() { return { main: async () => { if (isWork() || isExam()) { await waitForQuestions(); commonWork(this, { workerProvider: (opt) => workOrExam(isWork() ? "work" : "exam", opt) }); } } }; } }) } }); async function watchMedia$1() { const media = await waitForMedia(); media.volume = parseFloat(ZJYProject.scripts.study.cfg.volume.toString()); media.playbackRate = parseFloat(ZJYProject.scripts.study.cfg.playbackRate.toString()); state$1.media = media; const success = await playMedia(() => media.play()); if (!success) { return; } return new Promise((resolve, reject) => { media.addEventListener("ended", () => { resolve(); }); media.addEventListener("pause", () => { setTimeout(() => { if (media.ended) { resolve(); } else if (media.paused) { media.play(); media.volume = parseFloat(ZJYProject.scripts.study.cfg.volume.toString()); media.playbackRate = parseFloat(ZJYProject.scripts.study.cfg.playbackRate.toString()); } }, 1e3); }); }); } async function watchFile(pptReadPeriod) { var _a, _b; const vue = getPPTVueBindElement(); if (!vue) { return; } while (true) { const [current, total] = ((_b = (_a = document.querySelector(".preview .page")) == null ? void 0 : _a.textContent) == null ? void 0 : _b.trim().replace("上一页", "").replace("下一页", "").split("/").map((i) => parseInt(i.trim()))) || []; if (!current || !total) { break; } if (current >= total) { break; } try { vue.next && vue.next(); } catch { } try { vue.skip && vue.skip(); } catch { } await $.sleep(pptReadPeriod * 1e3); } } function getUniqueCourseId() { var _a, _b, _c, _d; return ((_d = (_c = (_b = (_a = document.querySelector(".coursePreviewIndex")) == null ? void 0 : _a.__vue__) == null ? void 0 : _b.list) == null ? void 0 : _c[0]) == null ? void 0 : _d.courseId) || ""; } function isZyk() { return location.href.includes("zyk.icve.com.cn"); } function getVueBindElement() { var _a, _b; return ((_a = lib.$el(".guide")) == null ? void 0 : _a.__vue__) || ((_b = lib.$el(".teach")) == null ? void 0 : _b.__vue__); } function getPPTVueBindElement() { var _a, _b, _c; return ((_a = lib.$el(".FilePreview")) == null ? void 0 : _a.__vue__) || ((_b = lib.$el(".guide")) == null ? void 0 : _b.__vue__) || ((_c = lib.$el(".teach")) == null ? void 0 : _c.__vue__); } async function next(type) { var _a; const field = type === "classroomNow" ? "activityId" : "id"; const id = new URL(window.location.href).searchParams.get(field); let nextObject; const data = ZJYProject.scripts.study.cfg.courseList; const start_index = data.findIndex((i) => i.id === id); for (let index = start_index + 1; index < data.length; index++) { const item = data[index]; if (["测验", "讨论"].some((i) => item.fileType === i)) { continue; } nextObject = item; break; } if (id && nextObject) { const vue = getVueBindElement(); if (((_a = vue == null ? void 0 : vue.nextObj) == null ? void 0 : _a.id) && nextObject.id === vue.nextObj.id) { vue.preNext(vue.nextObj); return; } await $.sleep(3e3); const url = new URL(window.location.href); if (nextObject.courseDesignId) { url.searchParams.set("courseDesignId", nextObject.courseDesignId); } url.searchParams.set(field, nextObject.id); window.location.replace(url.href); } else { lib.$message.success({ duration: 0, content: "全部任务已完成。" }); $console.info("全部任务已完成。"); CommonProject.scripts.settings.methods.notificationBySetting("全部任务点已完成!", { duration: 0, extraTitle: "职教云学习脚本" }); state$1.studying = false; } } function getCourseDataInClassroomNowPage() { var _a, _b, _c; const list = ((_b = (_a = document.querySelector(".classroom_activities")) == null ? void 0 : _a.__vue__) == null ? void 0 : _b.activeList) || []; const data = []; const temp = JSON.parse(JSON.stringify(list)); while (temp.length > 0) { const item = temp.shift(); if (((_c = item == null ? void 0 : item.children) == null ? void 0 : _c.length) > 0) { temp.unshift(...item.children); } else { data.push({ name: item.title, id: item.activityId, fileType: item.fileType, courseDesignId: item.courseDesignId, levelName: item.levelName || "" }); } } return data; } async function getCourseData() { var _a; const getDataList = () => { var _a2, _b, _c; const list = ((_b = (_a2 = document.querySelector(".coursePreviewIndex")) == null ? void 0 : _a2.__vue__) == null ? void 0 : _b.list) || []; const data = []; const temp = JSON.parse(JSON.stringify(list)); while (temp.length > 0) { const item = temp.shift(); if (((_c = item == null ? void 0 : item.children) == null ? void 0 : _c.length) > 0) { temp.unshift(...item.children); } else { data.push({ name: item.name, id: item.id, fileType: item.fileType, levelName: item.levelName || "", courseDesignId: item.courseDesignId || "" }); } } return data; }; if (isZyk() === false) { const progress = lib.h("div"); const modal_content = lib.h("div", [ lib.h("div", { className: "notes card" }, [ lib.$ui.notes([ "职教云由于大章节之间无自动下一节按钮,需要在课程开始前", "由程序读取全部章节数据,这样才能自动运行", "数据只需读取一遍即可,后续无需重新读取" ]) ]), progress ]); let force_pause = false; const modal2 = lib.$modal.confirm({ content: modal_content, maskCloseable: false, title: "正在获取课程数据中,请勿操作...", confirmButton: null, cancelButtonText: "强制暂停", onCancel() { force_pause = true; } }); const kejianListEl = document.querySelector(".kejianList"); if (!kejianListEl) { lib.$message.error({ content: "获取课程数据失败,请手动刷新页面" }); return void 0; } if (kejianListEl.style.display === "none") { (_a = Array.from(document.querySelectorAll(".courseBtn div.customBtn")).find((el) => { var _a2; return (_a2 = el.textContent) == null ? void 0 : _a2.includes("课件目录"); })) == null ? void 0 : _a.click(); await $.sleep(1e3); } const folders = []; while (true) { const itemsElList = Array.from(document.querySelectorAll(".items")); const unsaved = itemsElList.find((item) => folders.includes(item) === false); if (!unsaved) { break; } const list = getDataList(); const course_info = list.find( (item) => { var _a2; return `${item.levelName || ""}${item.name}`.replace(/\s/g, "") === (((_a2 = unsaved.textContent) == null ? void 0 : _a2.trim().replace(/\s/g, "")) || ""); } ); if (!course_info || ["父节点", "子节点"].includes(course_info.fileType) === false) { folders.push(unsaved); continue; } if (force_pause) { const err = "已强制暂停,请手动刷新页面后才能重新运行"; lib.$message.error({ content: err, duration: 0 }); lib.$modal.alert({ content: err }); return void 0; } folders.push(unsaved); if (modal2) { progress.innerHTML = "" + answer.trim().replace(/&/g, "&").replace(//g, ">").replace(/\n+/g, "
") + "
"; const containerId = (_a = iframe.closest('[id^="ueditor-"]')) == null ? void 0 : _a.id; const ue = (_b = iframe.ownerDocument.defaultView) == null ? void 0 : _b.UE; if (containerId && ue) { try { const editor = ue.getEditor(containerId); editor.ready(() => editor.setContent(html2)); return; } catch (err) { $console.warn("[answer] UEditor API 填充失败,尝试直接写入:", String(err)); } } const body = (_c = iframe.contentDocument) == null ? void 0 : _c.body; if (body) { body.innerHTML = html2; body.dispatchEvent(new Event("input", { bubbles: true })); } } async function submitYktCurrentQuestion(doc, order) { const hasStatusMark = () => { var _a, _b; const item = doc.querySelector(`.problems-aside .subject-item.J_order[data-order="${order}"]`); return !!(item == null ? void 0 : item.querySelector(".icon-status")) || !!((_b = (_a = item == null ? void 0 : item.querySelector(".text-status")) == null ? void 0 : _a.textContent) == null ? void 0 : _b.includes("未批改")); }; for (let attempt = 0; attempt < 2; attempt++) { const submitBtn = Array.from( doc.querySelectorAll(".problem-box button.el-button--primary") ).find((b) => { var _a; return ((_a = b.textContent) == null ? void 0 : _a.trim().includes("提交")) && !b.disabled && !b.classList.contains("is-disabled"); }); if (!submitBtn) { return attempt > 0 ? hasStatusMark() : false; } submitBtn.click(); await lib.$.sleep(1e3); const waitStart = Date.now(); while (Date.now() - waitStart < 1e4) { if (hasStatusMark()) { return true; } await lib.$.sleep(300); } } $console.error("未检测到完成状态。"); return false; } async function waitYktQuestionReady(prevMarker, doc, timeoutMs = 15e3) { var _a, _b; const start2 = Date.now(); while (Date.now() - start2 < timeoutMs) { const marker = currentYktQuestionMarker(doc); if (marker && marker !== prevMarker) { break; } await lib.$.sleep(200); } let stable = 0; while (Date.now() - start2 < timeoutMs) { await decryptYktNow(doc); const hasContent = !!((_b = (_a = doc.querySelector(".container-problem .problem-body")) == null ? void 0 : _a.textContent) == null ? void 0 : _b.trim()); const hasCipher = !!doc.querySelector( `.container-problem ${YKT_ENCRYPTED_SELECTOR}, .container-problem .xuetangx-com-font-decrypting` ); if (hasContent && !hasCipher) { stable++; if (stable >= 2) { return; } } else { stable = 0; } await lib.$.sleep(200); } $console.warn(`[answer] 等待题目就绪超时(${timeoutMs}ms),将就绪状态降级继续。`); } const YKT_BLANK_INPUT_SELECTOR = 'input.blank-item-dynamic, input[placeholder="输入答案"]'; function extractYktTitleText(el) { if (!el.querySelector(YKT_BLANK_INPUT_SELECTOR)) { return extractTextWithImages(el).text; } const clone2 = el.cloneNode(true); for (const input of Array.from(clone2.querySelectorAll(YKT_BLANK_INPUT_SELECTOR))) { input.replaceWith("____"); } return extractTextWithImages(clone2).text; } function createYktAnswerWorker({ answererWrappers, period, thread, redundanceWordsText, answerSeparators }) { const redundanceWords = redundanceWordsText.split("\n").filter(Boolean); const titleTransform = (titles) => titles.filter((t2) => t2 == null ? void 0 : t2.innerText).map( (t2) => t2 ? removeRedundantWords( StringUtils.of(extractYktTitleText(t2)).nowrap(" ").nospace().toString().trim(), redundanceWords ) : "" ).join(","); const optionText = (option) => { const input = option.querySelector("input"); if ((input == null ? void 0 : input.value) === "true") { return "对"; } if ((input == null ? void 0 : input.value) === "false") { return "错"; } const textEl = option.querySelector(".radioText, .checkboxText"); return extractTextWithImages(textEl != null ? textEl : option).text; }; let totalQuestionCount = 0; let requestedCount = 0; let resolvedCount = 0; const questionRootRef = []; const worker = new OCSWorker({ root: questionRootRef, rootObserver: { enabled: true, onRootLost: () => { CommonProject.scripts.workResults.methods.clearResults(); CommonProject.scripts.workResults.methods.refreshState(); } }, elements: { title: (root2) => { const pb = lib.$$el(".problem-body", root2); return pb.length ? pb : lib.$$el(".item-body > div", root2).slice(0, 1); }, type: ".item-type", options: (root2) => { const labels = lib.$$el('ul[class*="list-unstyled"] li label', root2); if (labels.length) { return labels; } const editors = lib.$$el('iframe[id^="ueditor_"]', root2); if (editors.length) { return editors; } const blanks = lib.$$el(YKT_BLANK_INPUT_SELECTOR, root2); return blanks.length ? blanks : lib.$$el("textarea", root2); } }, thread: thread != null ? thread : 1, answerSeparators: answerSeparators.split(",").map((s) => s.trim()), answerer: createCommonAnswerer({ titleTransform: (elements2) => titleTransform(elements2.title), optionsTransform: (elements2, ctx) => { var _a, _b, _c, _d; ctx.type = parseYktQuestionType((_c = (_b = (_a = elements2.type) == null ? void 0 : _a[0]) == null ? void 0 : _b.textContent) != null ? _c : ""); if (ctx.type === "completion") { return ""; } return ((_d = elements2.options) != null ? _d : []).map((o) => optionText(o)).join("\n"); }, answererWrappers, period }), work: async (ctx) => { var _a, _b, _c; const type = (_b = (_a = ctx.type) != null ? _a : defaultWorkTypeResolver(ctx)) != null ? _b : "single"; const resolver = createDefaultQuestionResolver(ctx, (o) => optionText(o))[type]; if (!resolver) { return { finish: false }; } return await resolver( ctx.searchInfos, (_c = ctx.elements.options) != null ? _c : [], async (t2, answer, option) => { var _a2; if (t2 === "judgement" || t2 === "single" || t2 === "multiple") { if (option && !option.classList.contains("is-checked") && ((_a2 = option.querySelector("input")) == null ? void 0 : _a2.checked) !== true) { option.click(); await lib.$.sleep(300); } } else if (t2 === "completion" && answer.trim()) { if ((option == null ? void 0 : option.tagName) === "IFRAME") { fillYktUEditor(option, answer); await lib.$.sleep(300); } else { const input = (option == null ? void 0 : option.tagName) === "TEXTAREA" || (option == null ? void 0 : option.tagName) === "INPUT" ? option : option == null ? void 0 : option.querySelector("textarea,input"); if (input) { input.value = answer; input.dispatchEvent(new Event("input", { bubbles: true })); await lib.$.sleep(200); } } } } ); }, onQuestionDetected(current) { updateDynamicResult(current, titleTransform); }, onResultsUpdate(current, _, res) { var _a; updateDynamicResult(current, titleTransform); if (current.result) { totalQuestionCount++; requestedCount++; resolvedCount++; } if ((_a = current.result) == null ? void 0 : _a.finish) { BackgroundProject.scripts.data.methods.addQuestionCacheFromWorkResult( simplifyWorkResult([current], titleTransform) ); } CommonProject.scripts.workResults.methods.updateWorkState({ totalQuestionCount, requestedCount, resolvedCount }); } }); return { worker, questionRootRef }; } async function waitYktCaptcha(doc) { const getCaptcha = () => doc.querySelector("#homework-automation-risk-challenge"); if (!getCaptcha()) { return; } $console.warn("[answer] 检测到平台风控验证码,等待手动完成..."); const message2 = lib.$message.warn({ content: "检测到平台风控验证码,请手动完成验证,完成后将自动继续答题。", duration: 0 }); CommonProject.scripts.settings.methods.notificationBySetting( "雨课堂脚本:检测到平台风控验证码,请手动完成验证,完成后将自动继续答题。", { duration: 0 } ); await new Promise((resolve) => { const interval = setInterval(() => { if (!getCaptcha()) { clearInterval(interval); resolve(); } }, 1e3); }); message2 == null ? void 0 : message2.remove(); lib.$message.success("验证码已完成,继续自动答题。"); } async function waitYktWorkConfirmDialog(doc) { const getDialog = () => { const els = Array.from( doc.querySelectorAll(".homework-problem-change-guard-dialog,.homework-problem-batch-submit-dialog") ); if (els.some( (e) => { var _a; return ((_a = e == null ? void 0 : e.parentElement) == null ? void 0 : _a.classList.contains("el-dialog__wrapper")) && (e == null ? void 0 : e.parentElement.style.display) !== "none"; } )) { return true; } }; if (!getDialog()) { return; } $console.warn("[answer] 检测到作业存在未保存答案,等待手动确认..."); const message2 = lib.$message.warn({ content: "检测到作业存在未保存答案,请手动确认 。", duration: 0 }); CommonProject.scripts.settings.methods.notificationBySetting("雨课堂脚本:检测到作业存在未保存答案,请手动确认 。", { duration: 0 }); await new Promise((resolve) => { const interval = setInterval(() => { if (!getDialog()) { clearInterval(interval); resolve(); } }, 1e3); }); message2 == null ? void 0 : message2.remove(); } async function runYktAnswerLoop(worker, questionRootRef, doc) { var _a, _b, _c; const allResults = []; try { await ensureYktFontDecrypt(doc); } catch (err) { $console.error("字体解密初始化失败:", String(err)); } const getUnfinishedNavItems = () => Array.from(doc.querySelectorAll(".problems-aside .subject-item.J_order")).filter((el) => { var _a2, _b2; if (el.querySelector(".icon-status")) { return false; } if ((_b2 = (_a2 = el.querySelector(".text-status")) == null ? void 0 : _a2.textContent) == null ? void 0 : _b2.includes("未批改")) { return false; } return true; }); const processedOrders = /* @__PURE__ */ new Set(); const processedMarkers = /* @__PURE__ */ new Set(); let prevMarker = null; let completedAll = false; while (worker.isClose === false) { await waitYktCaptcha(doc); if (worker.isClose) { break; } const unfinished = getUnfinishedNavItems().filter( (el) => { var _a2; return !processedOrders.has((_a2 = el.getAttribute("data-order")) != null ? _a2 : ""); } ); if (unfinished.length === 0) { completedAll = true; break; } let target = unfinished.find((n) => n.classList.contains("active")); if (!target) { target = unfinished[0]; prevMarker = currentYktQuestionMarker(doc); target.click(); await lib.$.sleep(1e3); await waitYktWorkConfirmDialog(doc); } await waitYktQuestionReady(prevMarker, doc); const marker = currentYktQuestionMarker(doc); if (marker && processedMarkers.has(marker)) { $console.warn(`[answer] 题目 "${marker}" 重复出现(切换失败或状态未刷新),终止作答以防死循环。`); break; } if (marker) { processedMarkers.add(marker); } const order = (_a = target.getAttribute("data-order")) != null ? _a : ""; processedOrders.add(order); questionRootRef.splice( 0, questionRootRef.length, ...Array.from(doc.querySelectorAll(".container-problem .subject-item")) ); if (questionRootRef.length === 0) { break; } try { const results = await worker.doWork({ enable_debug: BackgroundProject.scripts.dev.cfg.enable_answerer_debug }); allResults.push(...results); const finished = !!((_c = (_b = results[0]) == null ? void 0 : _b.result) == null ? void 0 : _c.finish); if (finished) { const submitted = await submitYktCurrentQuestion(doc, order); if (!submitted) { $console.warn(`[answer] 本题提交失败: ${marker}`); } } await lib.$.sleep(1e3); await waitYktWorkConfirmDialog(doc); } catch (err) { $console.error("[answer] 答题异常,终止作答:", String(err)); break; } } return { results: allResults, completedAll }; } function createYktEmbeddedWorkLoop(opts, doc, onDone) { CommonProject.scripts.workResults.methods.init({ dynamic: true }); const { worker, questionRootRef } = createYktAnswerWorker(opts); dynamicWorkTips(worker); (async () => { const { results, completedAll } = await runYktAnswerLoop(worker, questionRootRef, doc); worker.emit("done"); const finishCount = results.filter((r) => { var _a; return (_a = r.result) == null ? void 0 : _a.finish; }).length; if (!completedAll) { lib.$message.warn({ content: `题目未全部完成(已作答提交 ${finishCount}/${results.length} 题),请手动检查剩余题目。`, duration: 0 }); } else { lib.$message.success({ content: `作业完成,全部 ${finishCount} 题已作答并逐题提交。` }); } onDone(); })(); return worker; } async function watch(options) { const set = async () => { var _a; await lib.$.sleep(1e3); const is_digital_human_video = !!document.querySelector(".digital-human-video-element-selector"); if (is_digital_human_video) { throw new Error("AI学伴视频请在学习内容中进入,不要在成绩单里进入。"); } else { const video_vue_data = (_a = document.querySelector(".xtplayer")) == null ? void 0 : _a.__vue__; if (video_vue_data) { video_vue_data.player.options.speed.value = parseFloat(options.playbackRate.toString()); video_vue_data.player.options.volume.value = options.volume; video_vue_data.player.init(); } } const media = await waitForElement("video", { timeout_seconds: 10 * 1e3 }); console.log("media", media); await lib.$.sleep(1e3); if (media) { media.currentTime = 1; } return media; }; lib.$message.info("开始播放"); return new Promise((resolve, reject) => { let currentVideo; let videoCheckInterval; let failCount = 0; const clearCheckInterval = () => { if (videoCheckInterval !== void 0) { clearInterval(videoCheckInterval); videoCheckInterval = void 0; } }; const bindEvents = (video) => { video.onpause = async () => { if (!video.ended) { await lib.$.sleep(1e3); video.play(); } }; video.onended = () => { clearCheckInterval(); $msg.success("视频学习完成"); resolve(); }; }; const watch2 = async () => { try { const media = await set(); if (!media) { failCount++; if (failCount >= 5) { reject(new Error("video not found!")); return; } lib.$message.info({ content: "未检测到视频,稍后重试..." }); setTimeout(watch2, 3e3); return; } failCount = 0; currentVideo = media; bindEvents(media); playMedia(() => media.play()); clearCheckInterval(); videoCheckInterval = setInterval(() => { if ((currentVideo == null ? void 0 : currentVideo.isConnected) === false) { clearCheckInterval(); lib.$message.info({ content: "检测到视频切换..." }); resolve(); } }, 3e3); } catch (e) { clearCheckInterval(); reject(e); } }; watch2(); }); } function definedProjects() { return [ ZHSProject, CXProject, IcveMoocProject, ZJYProject, ICourseProject, YKTProject, CommonProject, BackgroundProject ]; } exports2.$ = $; exports2.$const = $const; exports2.$elements = lib.$elements; exports2.$store = lib.$store; exports2.$string = $string; exports2.AnswerWrapperHandlerConfig = AnswerWrapperHandlerConfig; exports2.AnswerWrapperParser = AnswerWrapperParser; exports2.BackgroundProject = BackgroundProject; exports2.CXProject = CXProject; exports2.CommonProject = CommonProject; exports2.CustomOCSWorker = CustomOCSWorker; exports2.ICourseProject = ICourseProject; exports2.IcveMoocProject = IcveMoocProject; exports2.OCSWorker = OCSWorker; exports2.RemotePlaywright = RemotePlaywright; exports2.RenderScript = RenderScript; exports2.StringUtils = StringUtils; exports2.YKTProject = YKTProject; exports2.ZHSProject = ZHSProject; exports2.ZJYProject = ZJYProject; exports2.answerExactMatch = answerExactMatch; exports2.answerNormalizedMatch = answerNormalizedMatch; exports2.answerSimilar = answerSimilar; exports2.answerSimilarWithGap = answerSimilarWithGap; exports2.clearString = clearString; exports2.createDefaultQuestionResolver = createDefaultQuestionResolver; exports2.defaultAnswerWrapperHandler = defaultAnswerWrapperHandler; exports2.defaultWorkTypeResolver = defaultWorkTypeResolver; exports2.definedProjects = definedProjects; exports2.domSearch = domSearch; exports2.domSearchAll = domSearchAll; exports2.getAnswererConfigProvider = getAnswererConfigProvider; exports2.isPlainAnswer = isPlainAnswer; exports2.isProgramAnswer = isProgramAnswer; exports2.logoSvg = logoSvg; exports2.normalizeString = normalizeString; exports2.openAnswererConnect = openAnswererConnect; exports2.removeRedundant = removeRedundant; exports2.request = request; exports2.resolvePlainAnswer = resolvePlainAnswer; exports2.setAnswererConfigProvider = setAnswererConfigProvider; exports2.splitAnswer = splitAnswer; exports2.start = lib.start; exports2.waitForAnswererConfig = waitForAnswererConfig; Object.defineProperties(exports2, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); }); const STYLE = `/** easy-us 基础样式(通过 node_modules 软链引入,相对路径保证 Easy LESS 免配置直接编译) */ /** ===== 主题主色(一键更换) ===== */ /** 主色 */ /** 主色 hover 变浅 */ /** 主色浅色变体(禁用态等) */ /** 激活态浅底 */ /** 极浅底(提示卡片、hover 背景) */ /** 主色边框/竖条 */ /** focus 光环 */ /** 默认字体 */ /** 输入框默认边距 */ ul, ol { line-height: 26px; padding-left: 22px; margin: 0px; } a { color: #2b67ff; } hr { border-style: solid; border-color: #63636346; border-width: 0px; border-bottom: 1px solid #63636346; margin-block-start: 1em; margin-block-end: 1em; } .base-style-active-form-control { border: 1px solid #ffffff00; } .base-style-active-form-control:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .base-style-active-form-control:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .base-style-active-form-control:hover { background-color: #ebeef4; } .base-style-input { outline: none; border: 1px solid #ffffff00; padding: 2px 8px; margin: 0px; background-color: #eef2f7; border-radius: 8px; color: black; } .base-style-input::placeholder { color: #bababa; } .base-style-switch { appearance: none; -moz-appearance: none; -webkit-appearance: none; width: fit-content; min-width: 48px; height: 20px; border-radius: 100px; display: flex; align-items: center; padding: 2px 4px; transition: all 0.2s ease-in-out; width: auto; background: gainsboro; } .base-style-switch:checked { background: #2b67ff; } .base-style-switch:disabled { background-color: #f7f7f78b; } .base-style-switch:checked::before { transform: translate(24px, 0px); } .base-style-switch::before { background-color: #fff; border-radius: 9px; box-shadow: 0 2px 4px #00230b33; width: 14px; height: 14px; content: ''; } .base-style-button { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; } .base-style-button:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } .base-style-button + .base-style-button { margin-left: 12px; } .base-style-button:hover { background-color: #5e8cff; border-color: #5e8cff; } .base-style-button.danger { background-color: #f56c6c; border-color: #f56c6c; color: white; } .base-style-button.danger:hover { background-color: #f78989; border-color: #f78989; } .base-style-button:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } .base-style-button:disabled:active { box-shadow: none; } .base-style-button-secondary { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; color: #606266; background-color: white; border: 1px solid #dcdcdc; } .base-style-button-secondary:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } .base-style-button-secondary + .base-style-button-secondary { margin-left: 12px; } .base-style-button-secondary:hover { background-color: #5e8cff; border-color: #5e8cff; } .base-style-button-secondary.danger { background-color: #f56c6c; border-color: #f56c6c; color: white; } .base-style-button-secondary.danger:hover { background-color: #f78989; border-color: #f78989; } .base-style-button-secondary:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } .base-style-button-secondary:disabled:active { box-shadow: none; } .base-style-button-secondary:hover { color: #2b67ff; border-color: #c4d5ff; background-color: rgba(43, 103, 255, 0.06); } container-element.hidden { display: none; } container-element.minimize { min-width: unset; } container-element { position: fixed; top: 10%; left: 10%; z-index: 99999; text-align: left; min-width: 300px; width: max-content; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #636363; box-shadow: 0 0 24px -12px #3f3f3f; border-radius: 12px; letter-spacing: 0.5px; border: 1px solid #c1c1c1; background-color: #f5f5f5; } header-element { display: flex; align-items: center; border-radius: 12px 12px 0px 0px; user-select: none; padding-bottom: 0px; } header-element .extra-menu-bar { width: 100%; padding: 4px; padding-bottom: 4px; background-color: white; border-top: 1px solid #e8e8e8; /** 默认隐藏,一直到需要激活的时候再更改 */ display: none; } header-element .extra-menu-bar .script-panel-link { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; color: #606266; background-color: white; border: 1px solid #dcdcdc; padding-bottom: 2px; margin-bottom: 0px; } header-element .extra-menu-bar .script-panel-link:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } header-element .extra-menu-bar .script-panel-link + header-element .extra-menu-bar .script-panel-link { margin-left: 12px; } header-element .extra-menu-bar .script-panel-link:hover { background-color: #5e8cff; border-color: #5e8cff; } header-element .extra-menu-bar .script-panel-link.danger { background-color: #f56c6c; border-color: #f56c6c; color: white; } header-element .extra-menu-bar .script-panel-link.danger:hover { background-color: #f78989; border-color: #f78989; } header-element .extra-menu-bar .script-panel-link:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } header-element .extra-menu-bar .script-panel-link:disabled:active { box-shadow: none; } header-element .extra-menu-bar .script-panel-link:hover { color: #2b67ff; border-color: #c4d5ff; background-color: rgba(43, 103, 255, 0.06); } header-element .extra-menu-bar .script-panel-link.active { background-color: rgba(43, 103, 255, 0.1); border-color: #2b67ff; color: #2b67ff; } header-element .extra-menu-bar .script-panel-link + .script-panel-link { margin-left: 4px; } header-element .header-menu-bar { padding-top: 4px; border-top-left-radius: 12px; border-top-right-radius: 12px; background-color: #f5f7fa; align-items: center; gap: 0px; } header-element .profile { cursor: move; margin-right: 4px; } header-element .switch:hover { background-color: #e4e9f0; } header-element .close:hover { background-color: #ff000038; } header-element .switch, header-element .close { cursor: pointer; } header-element .dropdown { line-height: 20px; } header-element .dropdown .dropdown-trigger-element { padding: 2px 12px; border: none; border-top: 1px solid #00000000; border-radius: 8px 8px 0px 0px; font-weight: 500; color: #606266; background-color: transparent; cursor: pointer; transition: background-color 0.2s ease, color 0.2s ease; } header-element .dropdown .dropdown-trigger-element:hover { background-color: #ffffff80; color: #2b67ff; } header-element .dropdown.active .dropdown-trigger-element { --tab-border: 1px; --tab-border-color: #e8ecf1; --tab-bg: #ffffff; --tab-radius-limit: 8px; --tab-radius-grad: #0000 calc(69% - var(--tab-border)), var(--tab-border-color) calc(69% - var(--tab-border) + 0.25px), var(--tab-border-color) 69%, var(--tab-bg) calc(69% + 0.25px); --radius-start: radial-gradient(circle at top left, var(--tab-radius-grad)); --radius-end: radial-gradient(circle at top right, var(--tab-radius-grad)); position: relative; color: #2b67ff; font-weight: 600; padding: 2px 11px; background-color: var(--tab-bg); border: var(--tab-border) solid var(--tab-border-color); border-bottom: none; border-radius: var(--tab-radius-limit) var(--tab-radius-limit) 0 0; box-shadow: 0 1px 0 var(--tab-bg); } header-element .dropdown.active .dropdown-trigger-element::before { content: ''; z-index: 1; position: absolute; inset: auto calc(-1 * var(--tab-radius-limit)) -1px calc(-1 * var(--tab-radius-limit)); height: calc(var(--tab-radius-limit) + var(--tab-border)); transform: translate(0px, 1px); pointer-events: none; background-image: var(--radius-start), var(--radius-end), linear-gradient(var(--tab-bg), var(--tab-bg)); background-size: var(--tab-radius-limit) var(--tab-radius-limit), var(--tab-radius-limit) var(--tab-radius-limit), 100% var(--tab-border); background-position: top left, top right, bottom left; background-repeat: no-repeat; } header-element .switch { border-radius: 8px; line-height: 20px; margin-left: auto; transition: background-color 0.2s ease; } header-element .switch, header-element .close, header-element .profile { display: inline-flex; align-items: center; padding: 0px 8px; } .logo { width: 18px; height: 18px; cursor: pointer; } .project-selector { display: flex; align-items: center; } .project-selector select { background: #ffffff00; border-radius: 4px; border: 1px solid #63636346; padding: 4px; } .project-selector.expand-all { display: none; } .body { overflow: auto; width: auto; height: 100%; overscroll-behavior: contain; } script-panel-element { display: block; background-color: white; border-radius: 0px 0px 12px 12px; padding: 0px 8px 12px 8px; overflow: auto; } script-panel-element .script-panel-body { padding: 0px 8px; } script-panel-element + script-panel-element { margin-top: 12px; } .card + .card { margin-top: 12px; } .card { background-color: white; border-radius: 10px; padding: 0px 8px; } .notes { background: rgba(43, 103, 255, 0.06); border-left: 4px solid rgba(43, 103, 255, 0.4); border-radius: 4px 10px 10px 4px; width: -webkit-fill-available; margin: 0px 8px; line-height: 26px; letter-spacing: 1px; } .notes .notes-header { display: flex; justify-content: space-between; align-items: center; cursor: pointer; user-select: none; font-weight: bold; } .notes .notes-header .notes-title { display: inline-flex; align-items: center; gap: 4px; } .notes .notes-header .notes-info-icon { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 50%; background-color: #2b67ff; color: white; font-size: 10px; font-weight: bold; font-style: italic; line-height: 1; user-select: none; } .notes .notes-collapse-icon { font-size: 12px; transition: transform 0.2s; } .notes.collapsed .notes-body { display: none; } .notes.collapsed .notes-collapse-icon { transform: rotate(-90deg); } .secondary { font-size: 12px; color: #8b8b8b; } .tooltip-container { z-index: 99999999999999; padding: 6px 10px; color: white; background: rgba(0, 0, 0); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); position: fixed; white-space: normal; width: fit-content; max-width: 400px; height: auto; border-radius: 6px; line-height: 18px; touch-action: manipulation; /** 展开/收起动画:透明度 + 位移,方向随放置位置翻转 */ visibility: hidden; opacity: 0; pointer-events: none; transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s; /** 气泡尾巴:水平位置由 --tooltip-arrow-left 驱动,始终对准目标中心 */ /** 气泡在目标下方,尾巴朝上 */ /** 气泡在目标上方,尾巴朝下 */ } .tooltip-container.tooltip-bottom { transform: translateY(-4px); } .tooltip-container.tooltip-top { transform: translateY(4px); } .tooltip-container.show { visibility: visible; opacity: 1; transform: translateY(0); pointer-events: auto; } .tooltip-container::before { content: ''; position: absolute; left: var(--tooltip-arrow-left, 10px); width: 8px; height: 8px; background: inherit; transform: rotate(45deg); } .tooltip-container.tooltip-bottom::before { top: -4px; } .tooltip-container.tooltip-top::before { bottom: -4px; } /** 移动端(粗指针)适配:限宽并加大内边距 */ @media (pointer: coarse) { .tooltip-container { max-width: min(400px, 80vw); padding: 8px 12px; } } .configs-container.lock { filter: blur(1px); user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } .configs-container .lock-wrapper { cursor: not-allowed !important; border-radius: 4px; position: absolute; left: 0px; z-index: 1; display: inline-flex; align-items: center; justify-content: center; } .configs-container .lock-message { background-color: #ffffff7d; border-radius: 4px; box-shadow: 0px 0px 12px #6a6a6a98; padding: 2px; } .configs { display: table; background: #e1e1e107; width: -webkit-fill-available; } .configs .configs-body { display: table-row-group; } .configs .configs-body config-element + config-element label { padding-top: 4px; } .configs .configs-body config-element + config-element .config-wrapper { padding-top: 4px; } .configs .configs-body config-element { width: 100%; display: table-row; line-height: 26px; /** 前后插槽容器:仅作布局,抵消 > * 规则带来的底色与圆角 */ } .configs .configs-body config-element label { white-space: nowrap; color: #4e5969; display: table-cell; padding-right: 12px; text-align: left; vertical-align: top; margin-right: 12px; } .configs .configs-body config-element .config-wrapper { display: table-cell; vertical-align: middle; /** check box 的样式 */ } .configs .configs-body config-element .config-wrapper select { outline: none; border: none; border: 1px solid #e4e4e4; border-radius: 8px; padding: 2px 8px; border: 1px solid #ffffff00; } .configs .configs-body config-element .config-wrapper select:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .configs .configs-body config-element .config-wrapper select:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .configs .configs-body config-element .config-wrapper select:hover { background-color: #ebeef4; } .configs .configs-body config-element .config-wrapper textarea { padding: 2px 8px; outline: none; border: none; border: 1px solid #ffffff00; } .configs .configs-body config-element .config-wrapper textarea:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .configs .configs-body config-element .config-wrapper textarea:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .configs .configs-body config-element .config-wrapper textarea:hover { background-color: #ebeef4; } .configs .configs-body config-element .config-wrapper input:not([type='button']) { outline: none; padding: 2px 8px; margin: 0px; background-color: #eef2f7; border-radius: 8px; color: black; border: 1px solid #ffffff00; } .configs .configs-body config-element .config-wrapper input:not([type='button'])::placeholder { color: #bababa; } .configs .configs-body config-element .config-wrapper input:not([type='button']):focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .configs .configs-body config-element .config-wrapper input:not([type='button']):focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .configs .configs-body config-element .config-wrapper input:not([type='button']):hover { background-color: #ebeef4; } .configs .configs-body config-element .config-wrapper input[type='range'] { padding: 0px; } .configs .configs-body config-element .config-wrapper input[type='button'] { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; width: auto; padding: 4px 12px; } .configs .configs-body config-element .config-wrapper input[type='button']:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } .configs .configs-body config-element .config-wrapper input[type='button'] + .configs .configs-body config-element .config-wrapper input[type='button'] { margin-left: 12px; } .configs .configs-body config-element .config-wrapper input[type='button']:hover { background-color: #5e8cff; border-color: #5e8cff; } .configs .configs-body config-element .config-wrapper input[type='button'].danger { background-color: #f56c6c; border-color: #f56c6c; color: white; } .configs .configs-body config-element .config-wrapper input[type='button'].danger:hover { background-color: #f78989; border-color: #f78989; } .configs .configs-body config-element .config-wrapper input[type='button']:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } .configs .configs-body config-element .config-wrapper input[type='button']:disabled:active { box-shadow: none; } .configs .configs-body config-element .config-wrapper input[type='checkbox'] { appearance: none; -moz-appearance: none; -webkit-appearance: none; width: fit-content; min-width: 48px; height: 20px; border-radius: 100px; display: flex; align-items: center; padding: 2px 4px; transition: all 0.2s ease-in-out; width: auto; background: gainsboro; } .configs .configs-body config-element .config-wrapper input[type='checkbox']:checked { background: #2b67ff; } .configs .configs-body config-element .config-wrapper input[type='checkbox']:disabled { background-color: #f7f7f78b; } .configs .configs-body config-element .config-wrapper input[type='checkbox']:checked::before { transform: translate(24px, 0px); } .configs .configs-body config-element .config-wrapper input[type='checkbox']::before { background-color: #fff; border-radius: 9px; box-shadow: 0 2px 4px #00230b33; width: 14px; height: 14px; content: ''; } .configs .configs-body config-element .config-wrapper input:not([type='checkbox'], [type='radio'], [type='button']), .configs .configs-body config-element .config-wrapper textarea, .configs .configs-body config-element .config-wrapper select { width: -webkit-fill-available; font-size: inherit; } .configs .configs-body config-element .config-wrapper input[type='checkbox'], .configs .configs-body config-element .config-wrapper input[type='radio'], .configs .configs-body config-element .config-wrapper input[type='range'] { accent-color: #2b67ff; } .configs .configs-body config-element .config-wrapper > *:not(.tooltip) { background-color: #eef2f7; border-radius: 8px; color: black; float: right; } .configs .configs-body config-element .config-wrapper > .config-provider-container { display: inline-flex; align-items: center; gap: 6px; background-color: transparent; border-radius: 0px; padding: 0px; /** 插槽中的按钮:去除下外边距保持垂直居中,禁止收缩 */ /** 容器内的表单控件:恢复独立控件底色 */ } .configs .configs-body config-element .config-wrapper > .config-provider-container .config-prefix, .configs .configs-body config-element .config-wrapper > .config-provider-container .config-suffix { display: inline-flex; align-items: center; white-space: nowrap; line-height: 20px; flex-shrink: 0; } .configs .configs-body config-element .config-wrapper > .config-provider-container .base-style-button, .configs .configs-body config-element .config-wrapper > .config-provider-container .base-style-button-secondary { margin-bottom: 0px; white-space: nowrap; flex-shrink: 0; } .configs .configs-body config-element .config-wrapper > .config-provider-container > input:not([type='checkbox'], [type='radio'], [type='button']), .configs .configs-body config-element .config-wrapper > .config-provider-container > select, .configs .configs-body config-element .config-wrapper > .config-provider-container > textarea { width: auto; min-width: 60px; background-color: #eef2f7; } .configs .configs-body config-element .config-wrapper > *:disabled { cursor: not-allowed; background-color: #f7f7f78b; } .message-container { margin-bottom: 4px; position: absolute; bottom: 100%; left: 50%; width: 100%; transform: translate(-50%, 0px); min-width: 300px; z-index: 2; } .message-container message-element { display: flex; border-radius: 8px; padding: 4px 12px; margin-bottom: 4px; } .message-container message-element .message-content-container { margin-right: 8px; flex: auto; } .message-container message-element .message-text { letter-spacing: 1px; font-weight: bold; } .message-container message-element .message-closer { width: 18px; min-width: 18px; cursor: pointer; background-color: #ffffffb3; color: #a1a1a1; border-radius: 100%; text-align: center; height: 18px; vertical-align: middle; font-size: 12px; } .message-container message-element.error { background-color: #ffe6e6; color: #c70208; border: 1px solid #ff6b6ded; } .message-container message-element.info { background-color: #d5e1ff; color: #002991; border: 1px solid #aac2ff; } .message-container message-element.success { background-color: #e8ffe0; color: #3e8d0d; border: 1px solid #6fd91d; } .message-container message-element.warn { background-color: #ffefc8; color: #9b7400; border: 1px solid #ffc107; } modal-element { position: absolute; top: 50%; left: 50%; background-color: white; border-radius: 14px; box-shadow: 0px 0px 24px -12px black; border: 1px solid #929292; height: fit-content; transform: translate(-50%, -50%); padding: 12px 18px 18px 18px; font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; z-index: 99999999999; line-height: 24px; } modal-element .modal-profile { zoom: 0.9; color: #969696; user-select: none; margin-bottom: 4px; } modal-element .modal-title { font-size: 18px; font-weight: bold; user-select: none; } modal-element .modal-body { margin: 12px 0px; overflow: auto; } modal-element .modal-footer { display: flex; white-space: nowrap; justify-content: end; align-items: end; } modal-element .modal-footer > * + * { margin-left: 12px; } modal-element .modal-input { outline: none; padding: 2px 8px; margin: 0px; background-color: #eef2f7; border-radius: 8px; color: black; border: 1px solid #ffffff00; width: -webkit-fill-available; } modal-element .modal-input::placeholder { color: #bababa; } modal-element .modal-input:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } modal-element .modal-input:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } modal-element .modal-input:hover { background-color: #ebeef4; } modal-element .modal-cancel-button { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; color: gray; background-color: white; border: 1px solid #dcdcdc; } modal-element .modal-cancel-button:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } modal-element .modal-cancel-button + modal-element .modal-cancel-button { margin-left: 12px; } modal-element .modal-cancel-button:hover { background-color: #5e8cff; border-color: #5e8cff; } modal-element .modal-cancel-button.danger { background-color: #f56c6c; border-color: #f56c6c; color: white; } modal-element .modal-cancel-button.danger:hover { background-color: #f78989; border-color: #f78989; } modal-element .modal-cancel-button:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } modal-element .modal-cancel-button:disabled:active { box-shadow: none; } modal-element .modal-confirm-button { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; } modal-element .modal-confirm-button:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } modal-element .modal-confirm-button + modal-element .modal-confirm-button { margin-left: 12px; } modal-element .modal-confirm-button:hover { background-color: #5e8cff; border-color: #5e8cff; } modal-element .modal-confirm-button.danger { background-color: #f56c6c; border-color: #f56c6c; color: white; } modal-element .modal-confirm-button.danger:hover { background-color: #f78989; border-color: #f78989; } modal-element .modal-confirm-button:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } modal-element .modal-confirm-button:disabled:active { box-shadow: none; } modal-element.alert .modal-input, modal-element.alert .modal-cancel-button { display: none; } modal-element.alert .modal-confirm-button { margin: 0; } modal-element.prompt .modal-input, modal-element.prompt .modal-cancel-button, modal-element.prompt .modal-confirm-button { display: block; } modal-element.confirm .modal-input { display: none; } .modal-wrapper { width: 100%; height: 100%; z-index: 9999; position: fixed; top: 0px; left: 0px; z-index: 9999999; background-color: rgba(0, 0, 0, 0.265); color: #636363; font: 14px Menlo, Monaco, Consolas, 'Courier New', monospace; } .pointer { cursor: pointer; } .separator { display: flex; align-items: center; text-align: center; padding: 4px 0px 8px 0px; } .separator::before, .separator::after { content: ''; flex: 1; border-bottom: 1px solid #63636346; } .separator:not(:empty)::before { margin-right: 0.25em; } .separator:not(:empty)::after { margin-left: 0.25em; } container-element.minimize .body, container-element.minimize header-element .dropdown, container-element.minimize .footer { display: none; } container-element.minimize header-element { border-radius: 12px; padding-bottom: 8px; box-shadow: 0px 0px 24px -12px black; } .dropdown { position: relative; display: inline-block; } .dropdown.active .dropdown-trigger-element { color: #2b67ff; } .dropdown-trigger-element { cursor: pointer; } .dropdown-content { position: absolute; background-color: #ffffff; overflow: auto; box-shadow: 0 6px 16px 0 #00000014, 0 3px 6px -4px #0000001f; z-index: 1; border: 1px solid #e8ecf1; border-radius: 12px; padding: 4px; min-width: 120px; /** 下拉展开/收起动画:透明度 + 下滑 + 轻微缩放,让用户感知这是一个下拉框 */ display: block; visibility: hidden; opacity: 0; transform: translateY(-6px) scale(0.98); transform-origin: top center; pointer-events: none; transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s; } .dropdown-content.show { visibility: visible; opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; } .dropdown-content { cursor: pointer; z-index: 999; } .dropdown-content .dropdown-option { padding: 4px 12px; white-space: nowrap; border-radius: 8px; transition: background-color 0.2s ease, color 0.2s ease; } .dropdown-content .dropdown-option:hover { background-color: #f5f5f5; } .dropdown-content .dropdown-option.active { background-color: rgba(43, 103, 255, 0.1); color: #2b67ff; font-weight: 500; } .space { display: inline-flex; } .config-details { animation: fade-in 0.5s; } .config-details label { padding-left: 12px; } message-element { animation: show 0.5s; } script-panel-element > div, script-panel-link, container-element, modal-element { animation: fade-in 0.3s; } @keyframes show { 0% { transform: translateY(20px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes fade-out { 0% { opacity: 1; } 100% { opacity: 0; } } .checkbox-label { display: inline-block !important; position: relative; cursor: pointer; font-size: 16px; color: #2c3e50; } /* 隐藏原始复选框 */ .checkbox-input { position: absolute; opacity: 0; width: 0; height: 0; } /* 自定义按钮样式 */ .checkbox-label::after { content: ''; display: inline-block; border-radius: 50%; transition: all 0.1s ease; position: relative; margin-left: 4px; vertical-align: middle; } /* 向下箭头(未选中状态) */ .checkbox-label::before { content: '🔽'; position: absolute; width: 0; height: 0; right: 8px; transition: all 0.1s ease; z-index: 2; } /* 向上箭头(选中状态) */ .checked .checkbox-label::before { content: '🔼'; } /** 气泡自适应:不可视气泡固定显示在屏幕正上方(从顶部向下滑出自身高度) */ message-element.message-viewport-top { position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 99999; max-width: 90vw; animation: message-viewport-top-slide-down 0.25s ease; transition: top 0.2s ease; } @keyframes message-viewport-top-slide-down { from { transform: translateX(-50%) translateY(-100%); opacity: 0; } to { transform: translateX(-50%) translateY(0); opacity: 1; } } /** OCS 自定义样式 */ /** * OCS 自定义样式(已从 easy-us 样式中隔离) * 本文件仅包含与 easy-us/assets/css/style.css 不同或新增的自定义规则。 */ /** ===== 主题变量(对齐 easy-us 主题,跟随 @primary 一键更换) ===== */ /** 注意:本文件依赖 easy-us/assets/less/style.less 中的主题变量,需在其之后编译(见 style.less) */ /** 主色 */ /** 按钮颜色 */ /** 焦点边框/阴影 */ /** ===== 通用 mixin ===== */ /** 输入控件焦点样式 */ /** 输入控件焦点样式(非 checkbox/radio 时填充白底) */ /** 按钮基础样式 */ /** 按钮状态样式(需在次级样式之前调用,保证次级 hover 覆盖默认 hover) */ /** 次级按钮样式(白底灰边) */ /** 标签配色 */ a { color: #2b67ff; } .base-style-active-form-control:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .base-style-active-form-control:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .base-style-switch:checked { background: #2b67ff; } /** * 注意:.base-style-button / .base-style-button-secondary 与 easy-us 中的 mixin 同名, * easy-us 调用 .base-style-button() 时会把同名规则集的【内部嵌套规则】一并展开, * 因此这两个类的状态规则必须保持扁平写法(单独定义),不能嵌套在类内部。 */ .base-style-button { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; } .base-style-button:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } .base-style-button:hover { background-color: #5e8cff; border-color: #5e8cff; } .base-style-button:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } .base-style-button-secondary { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; color: #606266; background-color: white; border: 1px solid #dcdcdc; } .base-style-button-secondary:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } .base-style-button-secondary:hover { background-color: #5e8cff; border-color: #5e8cff; } .base-style-button-secondary:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } .base-style-button-secondary:hover { color: #2b67ff; border-color: #91b0ff; background-color: rgba(43, 103, 255, 0.06); } header-element .extra-menu-bar .script-panel-link { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; color: #606266; background-color: white; border: 1px solid #dcdcdc; padding-bottom: 2px; margin-bottom: 0px; } header-element .extra-menu-bar .script-panel-link:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } header-element .extra-menu-bar .script-panel-link:hover { background-color: #5e8cff; border-color: #5e8cff; } header-element .extra-menu-bar .script-panel-link:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } header-element .extra-menu-bar .script-panel-link:hover { color: #2b67ff; border-color: #91b0ff; background-color: rgba(43, 103, 255, 0.06); } header-element .extra-menu-bar .script-panel-link.active { background-color: rgba(43, 103, 255, 0.1); border-color: #2b67ff; color: #2b67ff; } header-element .dropdown .dropdown-trigger-element:hover { background-color: #ffffff80; color: #2b67ff; } header-element .dropdown.active .dropdown-trigger-element { --tab-border: 1px; --tab-border-color: #e8ecf1; --tab-bg: #ffffff; --tab-radius-limit: 8px; --tab-radius-grad: #0000 calc(69% - var(--tab-border)), var(--tab-border-color) calc(69% - var(--tab-border) + 0.25px), var(--tab-border-color) 69%, var(--tab-bg) calc(69% + 0.25px); --radius-start: radial-gradient(circle at top left, var(--tab-radius-grad)); --radius-end: radial-gradient(circle at top right, var(--tab-radius-grad)); position: relative; color: #2b67ff; font-weight: 600; padding: 2px 11px; background-color: var(--tab-bg); border: var(--tab-border) solid var(--tab-border-color); border-bottom: none; border-radius: var(--tab-radius-limit) var(--tab-radius-limit) 0 0; box-shadow: 0 1px 0 var(--tab-bg); } .notes { background: rgba(43, 103, 255, 0.06); border-left: 4px solid rgba(43, 103, 255, 0.4); border-radius: 4px 10px 10px 4px; width: -webkit-fill-available; margin: 0px 8px; line-height: 26px; letter-spacing: 1px; } .notes .notes-header .notes-info-icon { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 50%; background-color: #2b67ff; color: white; font-size: 10px; font-weight: bold; font-style: italic; line-height: 1; user-select: none; } .configs .configs-body config-element .config-wrapper select:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .configs .configs-body config-element .config-wrapper select:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .configs .configs-body config-element .config-wrapper textarea:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .configs .configs-body config-element .config-wrapper textarea:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .configs .configs-body config-element .config-wrapper input:not([type='button']):focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } .configs .configs-body config-element .config-wrapper input:not([type='button']):focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } .configs .configs-body config-element .config-wrapper input[type='button'] { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; width: auto; padding: 4px 12px; } .configs .configs-body config-element .config-wrapper input[type='button']:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } .configs .configs-body config-element .config-wrapper input[type='button']:hover { background-color: #5e8cff; border-color: #5e8cff; } .configs .configs-body config-element .config-wrapper input[type='button']:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } .configs .configs-body config-element .config-wrapper input[type='checkbox']:checked { background: #2b67ff; } .configs .configs-body config-element .config-wrapper input[type='checkbox'], .configs .configs-body config-element .config-wrapper input[type='radio'], .configs .configs-body config-element .config-wrapper input[type='range'] { accent-color: #2b67ff; } .message-container message-element.info { background-color: #d5e1ff; color: #002991; border: 1px solid #aac2ff; } modal-element .modal-input:focus { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); } modal-element .modal-input:focus:not([type='checkbox'], [type='radio']) { border: 1px solid #2b67ff; box-shadow: 0px 0px 4px rgba(43, 103, 255, 0.32); background-color: white !important; } modal-element .modal-cancel-button { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; color: gray; background-color: white; border: 1px solid #dcdcdc; } modal-element .modal-cancel-button:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } modal-element .modal-cancel-button:hover { background-color: #5e8cff; border-color: #5e8cff; } modal-element .modal-cancel-button:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } modal-element .modal-confirm-button { appearance: none; -moz-appearance: none; -webkit-appearance: none; border-radius: 4px; background-color: #2b67ff; border: 1px solid #2b67ff; color: white; cursor: pointer !important; transition: all 0.2s ease; } modal-element .modal-confirm-button:active { box-shadow: 0px 0px 8px rgba(43, 103, 255, 0.65); } modal-element .modal-confirm-button:hover { background-color: #5e8cff; border-color: #5e8cff; } modal-element .modal-confirm-button:disabled { background-color: #abc2ff; border-color: #abc2ff; color: white; cursor: not-allowed !important; } /** ===== 题库状态列表 ===== */ .answerer-status-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; } .answerer-status-list .answerer-status-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; border: 1px solid #e8e8e8; border-radius: 8px; background-color: #fafafa; } .answerer-status-list .answerer-status-item .name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .answerer-status-list .answerer-status-item .status { display: flex; align-items: center; gap: 8px; font-size: 12px; flex-shrink: 0; } .answerer-status-list .answerer-status-item .status .latency { color: #8c8c8c; } .answerer-status-list .answerer-status-item .status .badge { padding: 2px 8px; border-radius: 10px; } .answerer-status-list .answerer-status-item .status .badge.success { color: #52c41a; background-color: #f6ffed; border: 1px solid #b7eb8f; } .answerer-status-list .answerer-status-item .status .badge.error { color: #ff4d4f; background-color: #fff1f0; border: 1px solid #ffa39e; } .answerer-status-list .answerer-status-item .status .badge.timeout { color: #faad14; background-color: #fffbe6; border: 1px solid #ffe58f; } .answerer-status-list .answerer-status-item .status .badge.disabled { color: #8c8c8c; background-color: #f5f5f5; border: 1px solid #d9d9d9; } .dropdown.active .dropdown-trigger-element { color: #2b67ff; } .dropdown-content .dropdown-option.active { background-color: rgba(43, 103, 255, 0.1); color: #2b67ff; font-weight: 500; } /** ===== 搜索结果样式(从 easy-us 迁移,仅 OCS 项目使用) ===== */ .search-infos-num { width: 26px; margin: 2px; height: 20px; border-radius: 4px; display: inline-block; background-color: white; text-align: center; cursor: pointer; border: 1px solid #b6b6b6; } .search-infos-num.requested { border: 1px solid #789eff; color: #789eff; } .search-infos-num.active { background-color: #2b67ff !important; color: white; } .search-infos-num.error { border: 1px solid #ff8789ed; background-color: #ff6b6ded; color: white; } .search-infos-num.finish { background-color: #789eff; border: 1px solid #789eff; color: white; } search-infos-element { display: block; overflow: auto; } search-infos-element .search-result { margin-bottom: 12px; padding-left: 12px; } search-infos-element .search-result .question { font-weight: bold; max-height: 200px; overflow: auto; } search-infos-element .search-result .answer { color: #7c7c7c; } search-infos-element .search-result .answer code { border-bottom: 1px solid #dcdcdc; padding: 2px 0px; border-radius: 2px; margin: 4px; line-height: 22px; } search-infos-element .search-result .answer code + code { margin-left: 4px; } search-infos-element .search-result .search-result-answer-tag { padding: 2px 6px; border-radius: 2px; font-size: 12px; cursor: pointer; margin-right: 6px; } search-infos-element .search-result .search-result-answer-tag + .search-result-answer-tag { margin-left: 4px; } search-infos-element .search-result .search-result-answer-tag.blue { color: #2b67ff; background-color: rgba(43, 103, 255, 0.08); border: 1px solid rgba(43, 103, 255, 0.4); } search-infos-element .search-result .search-result-answer-tag.green { color: #52c41a; background-color: #f6ffed; border: 1px solid #b7eb8f; } search-infos-element .search-result .search-result-answer-tag.gray { color: #595959; background-color: #fafafa; border: 1px solid #d9d9d9; } search-infos-element .search-result .search-result-answer-tag.red { color: #ff4d4f; background-color: #fff1f0; border: 1px solid #ffa39e; } search-infos-element .search-result .search-result-answer-tag.yellow { color: #faad14; background-color: #fffbe6; border: 1px solid #ffe58f; } search-infos-element .search-result-question-type { background-color: rgba(43, 103, 255, 0.08); border: 1px solid rgba(43, 103, 255, 0.4); color: #2b67ff; margin-right: 8px; padding: 0px 4px; border-radius: 4px; } search-infos-element .error { color: #ff6b6ded; display: inline-block; padding-left: 12px; } .work-result-list { max-height: 400px; overflow: auto; } .work-result-question-container { position: absolute; width: 400px; left: -100%; top: 0px; background: white; border: 1px solid #cbcbcb; border-radius: 4px; box-shadow: 0px 0px 12px #d1cfcf; padding: 12px; } .work-result-question-container .close-search-result { font-size: 12px; margin-left: 8px; text-decoration: underline; color: gray; cursor: pointer; } .search-info-title { border: 1px solid #e1e1e1; border-radius: 4px; padding: 8px 12px; margin-bottom: 12px; line-height: 20px; overflow: auto; } .search-info-title .title-content { max-height: 200px; overflow: auto; } .search-info-details { margin-left: 4px; } .alert-info-wrapper { margin-bottom: 8px; margin-top: 8px; } .alert-info-wrapper .result-info { padding: 6px; text-align: center; border-radius: 6px; } .alert-info-wrapper .unresolved, .alert-info-wrapper .no-answer { color: #a1a1a1; background-color: #f7f7f7; } .alert-info-wrapper .warn { color: #d48806; background-color: #fffbe6; border: 1px solid #ffe58f; } .alert-info-wrapper .error { color: #ff4d4f; background-color: #fff1f0; border: 1px solid #ffa39e; } /** ===== 使用指南/控制台/Markdown 样式(从 easy-us 迁移,仅 OCS 项目使用) ===== */ .user-guide > li { padding: 4px 0px; } .copy, .question-title-extra-btn { margin-left: 4px; padding: 2px 4px; border-radius: 2px; box-shadow: 0 0 4px #b1b1b1; cursor: pointer !important; font-weight: normal; font-size: 12px; } .console { max-height: 300px; max-width: 400px; overflow: auto; background-color: #292929; padding: 12px 6px; color: #ececec; font-size: 12px; } .console .item { padding: 3px 0px; border-radius: 2px; } .console .item .time { color: #757575; } .console .item .info { background-color: rgba(43, 103, 255, 0.64); } .console .item .warn { background-color: #ffc107db; } .console .item .error { background-color: #f36c71cc; } .console .item .debug, .console .item .log { background-color: #9e9e9ec4; } .console *::selection { background-color: #ffffff6b; } .markdown { max-width: 400px; max-height: 50vh; overflow: auto; } .markdown code { padding: 2px 4px; background-color: #f0f0f0; border-radius: 6px; font-size: 12px; } .markdown blockquote { padding: 4px 4px 4px 12px; margin: 0px; color: #b5b5b5; border-left: #ababab 2px solid; } .markdown blockquote p { margin: 0px; } .markdown h1, .markdown h2, .markdown h3, .markdown h4, .markdown h5, .markdown h6, .markdown p { margin: 8px 0px; } /** ===== 动画 ===== */ @keyframes show { 0% { transform: translateY(20px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes fade-out { 0% { opacity: 1; } 100% { opacity: 0; } } /** ===== 边缘最小化图标模式 ===== */ container-element .edge-minimize-icon { display: none; } container-element.edge-minimize { min-width: unset; width: 64px; } container-element.edge-minimize header-element { display: none; } container-element.edge-minimize .message-container { left: 0; transform: none; } container-element.edge-minimize .edge-minimize-icon { display: flex; align-items: center; justify-content: center; width: 64px; height: 64px; cursor: pointer; user-select: none; } container-element.edge-minimize .edge-minimize-icon svg { width: 42px; height: 42px; } container-element.edge-minimize.edge-left { border-radius: 0 12px 12px 0; } container-element.edge-minimize.edge-right { border-radius: 12px 0 0 12px; } /** ===== 吸附过渡动画(仅在程序化吸附时临时添加) ===== */ container-element.edge-snapping { transition: left 0.2s ease, top 0.2s ease; } /** ===== 边缘拖放高亮区域 ===== */ .edge-drop-zone { position: fixed; top: 0; bottom: 0; width: 100px; z-index: 99998; pointer-events: none; opacity: 0; transition: opacity 0.15s ease; display: flex; align-items: center; justify-content: center; } .edge-drop-zone .edge-drop-zone-tip { writing-mode: vertical-rl; font-size: 20px; font-weight: bold; letter-spacing: 6px; color: rgba(43, 103, 255, 0.9); text-shadow: 0 0 8px rgba(255, 255, 255, 0.9); user-select: none; } .edge-drop-zone.show { opacity: 1; } .edge-drop-zone.zone-left { left: 0; background: linear-gradient(to right, rgba(43, 103, 255, 0.25), transparent); border-right: 2px solid rgba(43, 103, 255, 0.6); } .edge-drop-zone.zone-right { right: 0; background: linear-gradient(to left, rgba(43, 103, 255, 0.25), transparent); border-left: 2px solid rgba(43, 103, 255, 0.6); } container-element .edge-minimize-icon { touch-action: none; } header-element .profile { gap: 8px; } modal-element .modal-cancel-button:hover { color: white; } /** ===== 题库配置弹窗组件(src/utils/ui.ts 配套样式) ===== */ .aw-card { border: 1px solid #e3e8ee; border-radius: 8px; background-color: #fff; margin-bottom: 8px; overflow: hidden; transition: box-shadow 0.2s ease, border-color 0.2s ease; } .aw-card:hover { border-color: #b6c6dd; box-shadow: 0 2px 8px rgba(31, 35, 41, 0.08); } .aw-card-header { display: flex; align-items: center; gap: 8px; padding: 10px 12px; cursor: pointer; transition: background-color 0.15s ease; } .aw-card-header:hover { background-color: #f5f8fb; } .aw-card-name { font-weight: 600; font-size: 14px; color: #1f2329; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transition: opacity 0.2s ease; } .aw-card.disabled .aw-card-name { opacity: 0.45; } .aw-card-badge { flex: none; max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; line-height: 18px; color: #5a6b85; background-color: #eef2f7; border-radius: 999px; padding: 0 8px; } .aw-card-home { flex: none; text-decoration: none; font-size: 13px; line-height: 1; } .aw-card-home.no-home { opacity: 0.4; cursor: default; } .aw-card-status-group { display: inline-flex; align-items: center; gap: 6px; flex: none; } .aw-card-status { flex: none; font-size: 11px; line-height: 18px; padding: 0 8px; border-radius: 999px; background-color: #eef2f7; color: #5a6b85; white-space: nowrap; } .aw-card-status.probing { color: #9aa4b2; } .aw-card-status.success { background-color: #e8f7ee; color: #2e7d4f; } .aw-card-status.error, .aw-card-status.invalid { background-color: #fdeeee; color: #c0392b; } .aw-card-status.timeout { background-color: #fdf3e5; color: #b26a00; } .aw-card-status.disabled { background-color: #eef2f7; color: #8a94a6; } .aw-card-status.latency { background-color: #eef2f7; color: #5a6b85; } .aw-card-spacer { flex: 1; } .aw-card-chevron { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 20px; height: 20px; color: #9aa4b2; border-radius: 4px; transition: transform 0.2s ease; transform: rotate(-90deg); } .aw-card.expanded .aw-card-chevron { transform: rotate(0deg); } .aw-card-body { display: none; border-top: 1px solid #eef2f7; background-color: #f8fafc; padding: 10px 14px; } .aw-card.expanded .aw-card-body { display: block; } .aw-card-rows { list-style: none; padding: 0; margin: 0; } .aw-card-row { display: flex; align-items: flex-start; line-height: 22px; font-size: 13px; } .aw-card-label { flex: none; width: 64px; margin-right: 8px; color: #8a94a6; } .aw-card-value { word-break: break-all; color: #1f2329; } .aw-section-header { margin-top: 12px; margin-bottom: 8px; display: flex; align-items: center; flex-wrap: wrap; gap: 8px; } .aw-section-copy { padding: 2px 8px; font-size: 12px; margin-left: auto; } .aw-connect-hero { text-align: center; padding: 20px 16px; background-color: #f6f8fb; border: 1px solid #eef2f7; border-radius: 12px; margin-bottom: 16px; } .aw-connect-hero-icon { font-size: 28px; line-height: 1; margin-bottom: 8px; } .aw-connect-hero-title { font-size: 18px; font-weight: 700; color: #1f2329; margin-bottom: 6px; } .aw-connect-hero-subtitle { font-size: 13px; color: #5a6b85; line-height: 18px; } .aw-connect-hero-extra { font-size: 13px; color: #5a6b85; line-height: 18px; margin-top: 6px; } .aw-connect-hero-extra b { color: #1f2329; } .aw-steps { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 6px; margin: 12px 0; } .aw-step { display: flex; align-items: center; gap: 4px; font-size: 12px; color: #5a6b85; } .aw-step-num { flex: none; width: 16px; height: 16px; border-radius: 50%; background-color: #2b67ff; color: #fff; font-size: 11px; line-height: 16px; text-align: center; } .aw-step-arrow { color: #c1c9d4; font-size: 12px; } .aw-connect-status { display: none; padding: 10px 14px; border-radius: 8px; border: 1px solid transparent; font-size: 13px; line-height: 20px; text-align: center; margin-bottom: 12px; } .aw-connect-status.info { display: block; background-color: #eef4ff; border-color: #c9d9ff; color: #3f5de0; } .aw-connect-status.success { display: block; background-color: #e8f7ee; border-color: #b7e3c7; color: #2e7d4f; } .aw-connect-status.error { display: block; background-color: #fdeeee; border-color: #f5c6c6; color: #c0392b; } .aw-connect-btn { display: inline-flex; align-items: center; justify-content: center; padding: 4px 12px; font-size: 14px; font-weight: 600; color: #fff; background-color: #2b67ff; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.15s ease, opacity 0.15s ease; } .aw-connect-btn:hover:not(:disabled) { background-color: #5e8cff; } .aw-connect-btn:disabled { opacity: 0.75; cursor: not-allowed; } .aw-connect-btn.lg { padding: 8px 24px; font-size: 15px; } @keyframes ocs-spin { to { transform: rotate(360deg); } } .aw-spin { animation: ocs-spin 0.8s linear infinite; margin-right: 6px; } /** ===== 快捷菜单链接按钮(background.ts $menu 注册)淡入淡出动画 ===== */ .script-panel-link { animation: ocs-menu-fade-in 0.3s ease both; transition: opacity 0.25s ease, background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease; } .script-panel-link:hover { opacity: 0.85; } .script-panel-link.active { transition: opacity 0.25s ease, background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease; } @keyframes ocs-menu-fade-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } /** ===== 搜索结果面板:序号列表前的帮助图标(承载答题进度/序号解释提示) ===== */ .search-infos-help { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; margin-right: 4px; border-radius: 50%; border: 1px solid #c1c9d4; color: #9aa4b2; font-weight: bold; cursor: help; user-select: none; } .search-infos-help:hover { border-color: #2b67ff; color: #2b67ff; } .work-control-panel { display: flex; margin: 12px 0px; } `; /* eslint-disable no-undef */ ///