// ==UserScript== // @name 组卷网 (学科网) 试卷处理 // @version 1.0.0 // @description 排版组卷网试卷,使其处于可以打印状态 // @author HiRoger0001 // @match https://zujuan.xkw.com/* // @icon https://zujuan.xkw.com/favicon.ico // @grant GM_notification // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @require https://fastly.jsdelivr.net/npm/sweetalert2@11 // @namespace https://zujuan.xkw.com/ // ==/UserScript== imgMaps = { "3845f266f2826ada0b825caba49c64b5": `a`, "0a6936d370d6a238a608ca56f87198de": `a`, // "99a4658ab94306d39aedda17deed7216": "a = ", "2c94bb12cee76221e13f9ef955b0aab1": "b", "14a9ff0a382e947c7b5473c3d8154dd7": "b", "071a7e733d466949ac935b4b8ee8d183": "c", "5c02bc0c74292b1e8f395f90935d3174": "d", "99a4658ab94306d39aedda17deed7216": "d = ", "7c98c59cd4749afdd21e73529fc84323": "d = ", "168b3e4b1d6f04226fa2687a72a268b4": "e", "041a7c8fc017f596542c5e6ec7d1c40b": "e", // "14a9ff0a382e947c7b5473c3d8154dd7": "f", "276509f01529d982ab21e479a4619268": "g", "3eabd5f3a86afe49dcd70571e2b96cfd": "h", // "071a7e733d466949ac935b4b8ee8d183": "i", // "071a7e733d466949ac935b4b8ee8d183": "j", "f0a532e15e232cb4b99a8d4d07c89575": "k", "0f85fca60a11e1af2bf50138d0e3fe62": "l", "294f5ba74cdf695fc9a8a8e52f421328": "m", "b6a24198bd04c29321ae5dc5a28fe421": "n", "0f3cb8d72bb2e281b943b3b430138ef7": "n = ", // "071a7e733d466949ac935b4b8ee8d183": "o", "b1010846eeec6c9da29640f5aa3f8738": "p", "df5be1440d099f464ef46dee39de6010": "p = ", "9aa8a716a31b0f51b70fdf9bdb257909": "q", "11bc05f41215f9894e11d1df0465751a": "r", "c5873c01192b7d33b7483f444f90b5b0": "s", "36a1b09c653185842513e24ebba60bb3": "t", // "071a7e733d466949ac935b4b8ee8d183": "u", "bc13a607ac0c7f76d252d7cb1bb040fd": "v", // "071a7e733d466949ac935b4b8ee8d183": "w", "81dea63b8ce3e51adf66cf7b9982a248": "x", "d053b14c8588eee2acbbe44fc37a6886": "y", "e81e59019989b7dc2fb59b037ef6e010": "z", "5963abe8f421bd99a2aaa94831a951e9": "A", "7f9e8449aad35c5d840a3395ea86df6d": "B", "c5db41a1f31d6baee7c69990811edb9f": "C", "8455657dde27aabe6adb7b188e031c11": "D", "2a30f3a8b673cc28bd90c50cf1a35281": "E", "a0ed1ec316bc54c37c4286c208f55667": "F", "895dc3dc3a6606ff487a4c4863e18509": "G", "73465a1f9aa03481295bf6bd3c6903ac": "H", "e105760638b22b26ff8bec4354255e4c": "I", // "e105760638b22b26ff8bec4354255e4c": "J", "cf3834d7ec7531f3c3c0ce9b286f7a49": "K", "0c88d9142df6ba8e43c1a93bd04a1362": "L", "ac047e91852b91af639feec23a9598b2": "M", "54a5d7d3b6b63fe5c24c3907b7a8eaa3": "N", "1dde8112e8eb968fd042418dd632759e": "O", "dad2a36927223bd70f426ba06aea4b45": "P", "acc290b44635265137fdf13146b6a6d9": "Q", "4aa0df7f1e45f9de29e802c7f19a4f64": "R", "cf231f8f86fb922df4ca0c87f044cec3": "S", "a454a2c91ace8ef50412a6adf91f8086": "S", "0b68df477b3ee45ac0f725db00d465a1": "T", "b52b4f24969673c863b5aff4fb6751ce": "U", "be54e84508decfcce6d2fcbe6c8c1a92": "V", "478abdd84506a8ef759e353a238db6c9": `V`, "91edc7e2d4811f5ea6c01284cf00393a": "W", "f022950e0faa45b617d497b01b5292b9": "X", "54a829fdd8ec0f3b7ede883cf2c3e53b": "Y", // "e105760638b22b26ff8bec4354255e4c": "S", "bdaa19de263700a15fcf213d64a8cd57": "1", // "bdaa19de263700a15fcf213d64a8cd57": "1", // "bdaa19de263700a15fcf213d64a8cd57": "1", // "bdaa19de263700a15fcf213d64a8cd57": "1", // "bdaa19de263700a15fcf213d64a8cd57": "1", "e170f206fdbbd834aad7580c727e2cc6": "α", "5b5858ee1ce52b251816757257a11c29": "β", "074c228ffc7b1e306f8410afe7bc4b5c": "ω", "c24095e409b025db711f14be783a406c": "θ", "1c0ad7e7853a069537387b5192f73844": "σ", "70f5389990c3a0c5373f3bd9fb2454c9": "π", "ed2d1ecae9c649cc3c89f9ce0c063208": "π", "35e2d7c958e99bcd9d7f251c19ee3544": "2π", "6581916f5a65edfea257c804efee007e": "φ", "171102a883b22fe6ca578efc8926f5b8": "ρ", "1100379a4385b9ce064847bc21760adc": "μ", "06b09bec6122ff51834335344ae13f29": "ν", "df64046e91b047037f19e4032e3b6de3": "λ", // "06b09bec6122ff51834335344ae13f29": "α", // "06b09bec6122ff51834335344ae13f29": "α", // "06b09bec6122ff51834335344ae13f29": "α", // "06b09bec6122ff51834335344ae13f29": "α", // "06b09bec6122ff51834335344ae13f29": "α", // "1c0ad7e7853a069537387b5192f73844": "α", "f52a58fbaf4fea03567e88a9f0f6e37e": "AB", "01c74a907dda6bb7d9d56d009d9df253": "A, B", "b79dd200766db27fb90d6bd1992cf658": "AB", "9d78abbad68bbbf12af10cd40ef4c353": "CD", "0dc5c9827dfd0be5a9c85962d6ccbfb1": "BC", "60ef95894ceebaf236170e8832dcf7e3": "AC", "20a541b81584a032f571159ea152c85a": "AP", "7bef5239ddbb0972700ce01daf9ee7cf": "ABC", "15c0dbe3c080c4c4636c64803e5c1f76": "△ABC", "411b38a18046fea8e9fab1f9f9b80a5f": "ABCD", "01e04a5b59cced25ab7057d03fe3c0ad": "BCD", "2777840758e70e7dbbc18cef8f3d6d2b": "AA1", // "2777840758e70e7dbbc18cef8f3d6d2b": "BB1", "9d88bf46ad08f9677c37eed1d0369329": "CC1", "22adbc0da438220f9cace11b629d799b": "DD1", "11ddc92d84d188c66b435664a7e7b5a4": "A1B1", "394c5d2f55221975503be8aa18022480": "A1D1", "e168672b47d7e64dc1b404f8882c7dcf": "BCC1B1", "2d9a8181f7a7fe7f3fac872ce9534f15": "ACC1A1", "5ebb05874eb3353d754af24c9974273e": "ADD1A1", "6e09725691ee7851f54c0dee86b2bf55": "ABCD – A1B1C1D1", "42d3a82b8e587ee890467835bc4e854c": "ABC – A1B1C1", "411461db15ee8086332c531e086c40c7": "MN", "7a5f1641947153c80b987320885a2b57": "PQ", "a43b2faa4f81f32d94612dce724e772b": "R", // 粗体! "7ac87434324956e4145e38ad92a1aa95": "R", // 粗体! "d41042207515dd2e8349c805e6aee400": `z`, // 共轭复数 // "09f86f37ec8e15846bd731ab4fcdbacd": `f ( x )`, // "942c2141d01bde6b48210c56a17fc75e": `y = f ( x )`, // "4fe7d5809da02c15a43a0e9a898b9086": `f ( x )`, // "51c530f4b7491b95acb8ce3eef9aa09d": `y = f ( x )`, "7ee31829d0d4d5f779a957d7df8058ab": "xOy", "c3e5af20b2f8c1fba4470f9650989e51": "Ox", "acbc6a613224461ade69362d46550474": "–1", // "0585b6c0f156eecf9662b9846d4eb693": "PABCD", // "20a541b81584a032f571159ea152c85a": "AP", // "20a541b81584a032f571159ea152c85a": "AP", // "20a541b81584a032f571159ea152c85a": "AP", // "20a541b81584a032f571159ea152c85a": "AP", // "20a541b81584a032f571159ea152c85a": "AP", // "bdaa19de263700a15fcf213d64a8cd57": "1", // "bdaa19de263700a15fcf213d64a8cd57": "1", // "bdaa19de263700a15fcf213d64a8cd57": "1", "e72adb45c60c2f63b46e65ff787302bf": "a1", "3e88093a749c0d46e0ee931ecfaff925": "a2", "6c1ccc6c74b8754e9bcbb3f39a11b6f1": "a3", // "e72adb45c60c2f63b46e65ff787302bf": "a1", "80b53eab97158937f92039c1e133b0f1": "h1", "f285174fbf90a9742de57c1e53224cff": "h2", "e8e8854159e7443b5fe53436bf9e367f": "h3", "2e9b0f5f44abbc6544a2f672b025b013": "l1", "3f6f17bc385bafb37e8f964e5eb99cd0": "l2", "77ab1256702aef4e9f1a5eb6c12ecc96": `m1`, "1fbd67f60f04c278bdd867fdb3979dfb": `m2`, // "1fbd67f60f04c278bdd867fdb3979dfb": `m2`, // "27c44826e58f11a58d3a6c233fc5df2d": `n1`, // "27c44826e58f11a58d3a6c233fc5df2d": `n1`, // "27c44826e58f11a58d3a6c233fc5df2d": `n1`, "27c44826e58f11a58d3a6c233fc5df2d": `n1`, "215b1424b299b737554386b090af8316": `n2`, "d70f2244d643d2393618288de6c13e6e": `n3`, // "0b428e5d2e2f7ecbe7e83b1eee336278": `q0`, "56b2087eadbbd0dab72b7483b9181585": "+q", "0b428e5d2e2f7ecbe7e83b1eee336278": `q0`, // "0b428e5d2e2f7ecbe7e83b1eee336278": `q1`, // "0b428e5d2e2f7ecbe7e83b1eee336278": `q2`, "a2833ddbe58a6f4e7585c69c698f0d2a": "r0", "0d9fd58e71dcae6cafaf9037d20ebd76": `t0`, "87c7eb49a823f757461cd5260757b088": `t1`, // "0d9fd58e71dcae6cafaf9037d20ebd76": `t0`, "6f58888df91890a19a1aa7511d19703f": `v0`, "f44c235d8b49207ad3f2d77dc5d6cf20": `v1`, "814f55724f7ee57bd395eb3b95393c68": `v2`, // "478abdd84506a8ef759e353a238db6c9": `t0`, // "478abdd84506a8ef759e353a238db6c9": `t0`, // "478abdd84506a8ef759e353a238db6c9": `t0`, "d23d96b9e0d40658127563525193bde4": `vm`, "fc4eeb9cd408e73eb33347083df8cf33": `vx`, "e9d18c7a49171a8b0df7e0741ffe1cc0": `vy`, "79b752f0f189e5d8666daea73e145dff": `x0`, // x_0 "c814128ea2139e33db94ea590e7c2223": `x1`, "aec19b68e3add9d5bfcc6269a1855b87": `x2`, "291c25fc6a69d6d0ccfb8d839b9b4462": `x3`, "8ce7ae90d808f05e86ea063238e4b2f9": `x1, x2`, "26d8dafc71b106f39f4e15442220897b": `x1 < x2`, "2210f152080d9a68a97c805f5c1cde96": `x1 > x2`, "93c54705d32dc6820f1a90eec2225dcf": `x2x1`, // "2210f152080d9a68a97c805f5c1cde96": `x3`, // "97c01fdc7bc471af0b264a04aef0823e": `B1`, "024e2379c58191758f8bd7602a6bcb9f": `A1`, "b34a75c2a392f235c5f07b91d9fb58d5": `A2`, "76f1eb87ce12491e171c43b238a6ecf7": `A3`, "c41d793c851a2f72f787913ba23e459c": `B0`, "97c01fdc7bc471af0b264a04aef0823e": `B1`, "43a71fc9c0068109dad1382354570665": `B2`, "b1241216f3c1cb5e73043dd1037f556d": "C1", "b628d87cb667a0a31766a88c6c426324": "E0", "522230546d4b802094e86ceb48c2ba38": "E1", "0b4f150ab98bde511e0f65d9bafab031": "E2", "8b15fa17c704f1988d059ba69a7ce304": "Ek", "ef1c7229e345be3a4857b91d27126c88": "Ek", "c6c6eb14380e627b6d3194192d234d4c": "ΔE", "31c972b26b45c4ba54c6f169557d4080": "ΔE", "b519e5794ef9932b64715619adf860db": "F0", "f5076289823db419f94e9c0c8f4aafd9": "F1", "a3fb78c5f885034612c0e030b920143d": "F2", "84abbfb85a00f48b5db11eeb76b8d134": "I0", "2f1ac49b4139636fb1809fe970b23a87": "I1", "2d1a0fd1ad044a9ecfcba672779bd678": "I2", // "ef1c7229e345be3a4857b91d27126c88": "I0", "172722d11ea7e01411fa06dbb82f46ee": "L1", "9fbd49bf20f987c05b4d36e31549075c": "L2", "87f93f4e10d9672fa6bd67243bc23d4a": "L3", "23f919bd3dde10dbbc076f7ec5149699": "O1", "3c4f6f74444b2b7947fc6e35c8d62322": "O2", "ce2581ae160692cd7e2686226fe5e2c6": "Rx", "9d784ac902fe86e7bdcdd3fa5cc3ba83": "Rg", "be9b4a83b9aebebf29de0c4406ebf894": "R0", "9efc18a5bb2e53586331b2a58538a48b": "R1", "19f20f21a9d50b61dac519a3ddab539d": "R2", "bb9a33203d5812270ca911b3502c923e": "R1", "9c69fdea31c367d1f7e7bbd245d1ed56": "R2", "5a2c4640b2bee411935f588fc5433c74": "R3", // "172722d11ea7e01411fa06dbb82f46ee": "L1", // "5a2c4640b2bee411935f588fc5433c74": "R3", // "5a2c4640b2bee411935f588fc5433c74": "R3", "54f562eb3c2a45d65cba066d712825a5": "S0", "e097c8d4c948de063796bd19f85b3a9a": "S1", "1e0bd63f55069a3bc870915010b39225": "S2", "6899bf9cadae2ccdb14cbc87d4f280ee": "S3", "0f30f56664446f32dbbc2c5f12a99374": "S4", "08eb71ecf8d733b6932f4680874dbbf3": "Sn", "635ccd929471d564cc9d2d96266b34d1": "T0", // "dbe5cb81b72e94f92d2aaecd553daac2": "U0", // "dbe5cb81b72e94f92d2aaecd553daac2": "U0", "dbe5cb81b72e94f92d2aaecd553daac2": "U0", // "dbe5cb81b72e94f92d2aaecd553daac2": "U0", // "dbe5cb81b72e94f92d2aaecd553daac2": "U0", "a2e01e75a7ca05585d6d8e6207004f7c": "V0", "1c9e573ec93341e027774f3575846952": "V1", "9d9c8a02f5ec8bbbc2f8cb0c4952a39c": "V2", "00caa3b28e26231108f7c81bca82bc2b": "ω0", }; const additionalStyles = /*css*/` /* 页面显示部分 */ .ai-entry.fixed, .aside-pop.activity-btn { display: none !important; } /* #zujuanjs-reformatted-content { background: #fff; } */ html > body { overflow: auto !important; } .zujuanjs-print-btn { position: fixed; bottom: 10px; right: 10px; z-index: 9999; padding: 4px 6px; border-radius: 3px; background-color: white; box-shadow: 3px 3px 10px rgba(0,0,0,0.2); margin-left: 5px; transition: .3s; text-decoration: none; color: #333; font-size: 12px; cursor: pointer; } .ques-src { font-size: 0.8em; color: #444444; font-family: "Microsoft YaHei UI"; font-weight: lighter; } .ques-src:before { content: "["; } .ques-src:after { content: "]"; } .replaced-formula { font-family: 'Times New Roman', '方正书宋_GBK', serif; white-space: nowrap; } .dot-emphasis { position: relative; } .dot-emphasis:before { content: ""; background: black; position: absolute; width: 2px; height: 2px; border-radius: 50%; margin: 0 0.44em; top: 1.1em; left: 0; text-align: center; user-select: none; z-index: -1; print-color-adjust: exact; } wave { text-decoration-style: wavy; text-decoration-line: underline; text-underline-position: auto; text-decoration-thickness: from-font; } u { text-decoration-thickness: from-font; } .nowrap-wrapper { white-space: nowrap; } .flex-wrapper { display: flex; gap: 15px; } ol.question-ol { counter-reset: question-ol-counter; margin-left: 32px; li { counter-increment: question-ol-counter; list-style: auto; *[style*="text-indent:28px;"] { text-indent: 0 !important; } *[style*="margin-left:28px;"] { margin-left: 0 !important; } } li::marker { content: "(" counter(question-ol-counter) ") "; width: 32px; } } #zujuanjs-reformatted-content { margin: 3px; position: relative; } @media screen { #zujuanjs-reformatted-content { width: 19.5cm; } } /* @font-face { font-family: 'TNRBold'; src: local('Times New Roman'); font-weight: bold; unicode-range: U+0000-007F; } */ /* @font-face { font-family: "CondensedXDX"; src: local("方正细等线_GBK"); font-stretch: condensed; } */ .zujuanjs-question { padding: 0; margin-bottom: 12px; font-size: 16px; font-family: "Times New Roman", "方正书宋_GBK", SimSun, SimSun-ExtB; font-variant-ligatures: discretionary-ligatures; line-height: 24px; break-inside: avoid; text-align: justify; text-spacing-trim: trim-start; .chn-punc { font-family: "Noto Serif SC", SimSun, SimSun-ExtB; } .added-title { text-align: center; text-indent: 0 !important; [style*="text-indent:28px;"] { text-indent: 0 !important; } } img:not([src*="quesimg/Upload/formula"]) { right: 10px; } img[src*="quesimg/Upload/formula"] { margin-bottom: 2.2px; /* margin-left: 0.2em; margin-right: 0.2em; */ } *[style*="font-size:14px"] { font-size: inherit !important; } *[style*="font-family:楷体"], .kaiti { font-family: "Times New Roman", "方正楷体_GBK", 楷体, SimSun-ExtB !important; } *[style*="text-indent:28px;"]:not(.added-title *, ol.question-ol *) { text-indent: 2em !important; } b:not(.zujuanjs-english b, .replaced-formula b), b[style*="font-family:楷体"]:not(.zujuanjs-english b) { font-weight: normal; font-family: "Helvetica LT Pro", "方正黑体_GBK", "Microsoft YaHei UI" !important; } /* i[style*="font-family: Times New Roman"]:not(.zujuanjs-english i):before, i[style*="font-family: Times New Roman"]:not(.zujuanjs-english i):after { content: " "; } */ sup { margin-top: -6px; } sub { margin-bottom: -6px; } sup, sub { display: inline-block; text-indent: 0 !important; font-size: 0.75em; } table[name="optionsTable"] { margin-left: 1.5em; width: calc(100% - 1.5em) !important; border-spacing: 0; td { padding-left: 1.7em; text-indent: -1.7em; } } ol.question-ol table[name="optionsTable"] { margin-left: 0; width: 100%; } td[style*="border-width:1px 1px 1px 1px"] { border-width: 0.5px !important; } span[name="subquesnub"] + table[name="optionsTable"] { margin-left: 0.5em; } table:not(table[name="optionsTable"]) { margin: auto; width: auto !important; text-align: center; td { padding-left: 2px; padding-right: 2px; } } } .zujuanjs-section-title { font-size: 16px; font-family: "Helvetica LT Pro", "方正黑体_GBK", "Microsoft YaHei UI" !important; margin: 20px 0 10px; break-after: avoid; } .zujuanjs-english .zujuanjs-section-title { display: none; } .zujuanjs-english .zujuanjs-question { font-family: "Minion Pro", "方正细等线_GBK", SimSun, SimSun-ExtB; font-variant-ligatures: normal; [style*="font-family: Times New Roman;"] { font-family: "Minion Pro", "方正细等线_GBK", SimSun, SimSun-ExtB !important; } .exam-item__cnt > :nth-last-child(1 of p) { margin-bottom: 12px; } .exam-item__cnt > p:last-child { margin-bottom: 0; } /* font-weight: 300; b { font-weight: 400; } */ } #page-title { text-align: center; font-size: 2em; font-weight: bold; margin: 20px 0; } .font-preview { border: 1px solid #ddd; padding: 10px; margin-top: 10px; } @page { font-size: 12px; font-family: "Jetbrains Mono", "方正细黑一_GBK"; font-weight: 200; margin: 2cm; @top-left { content: var(--current-datetime); } @top-right { content: var(--page-title); } @bottom-right { content: counter(page) " / " counter(pages); } } `; function loadExternalScript(src, callback) { const script = document.createElement('script'); script.src = src; // script.async = true; // script.type = 'module'; // 如果是 ES6 模块 script.onload = () => { console.log(`脚本 ${src} 加载成功`); if (callback) callback(null, script); }; script.onerror = () => { console.error(`脚本 ${src} 加载失败`); if (callback) callback(new Error(`Failed to load script: ${src}`), script); }; document.head.appendChild(script); } function replaceDotEmphases(father) { father.querySelectorAll('dot').forEach(element => { // 获取原始文本内容 const text = element.textContent; // 清空原元素内容 element.innerHTML = ''; // 遍历每个字符 for (const char of text) { if (!(char.match(/\s/))) { const span = document.createElement('span'); span.className = 'dot-emphasis'; span.textContent = char; element.appendChild(span); } else { element.appendChild(document.createTextNode(char)); } } }); } const isChineseChar = (char) => { if (!char) return false; return /[\u4e00-\u9fa5]/.test(char); }; function addSpacesAroundElements(father, selector) { // 2. 获取所有符合选择器的元素 // 注意:我们需要从后往前遍历,或者在插入节点时小心处理, // 但因为我们是在元素“外部”插入兄弟节点,不会影响元素本身的索引位置, // 所以直接从前往后遍历也是安全的。 const elements = father.querySelectorAll(selector); elements.forEach(el => { // --- 处理前面的情况 --- let prevNode = el.previousSibling; // 如果前一个节点是文本节点,且最后一个字符是汉字 if (prevNode && prevNode.nodeType === Node.TEXT_NODE) { const textContent = prevNode.textContent; if (textContent.length > 0) { const lastChar = textContent.slice(-1); // 取最后一个字符 if (isChineseChar(lastChar)) { // 在元素前插入一个空格 el.parentNode.insertBefore(document.createTextNode(' '), el); } } } // --- 处理后面的情况 --- let nextNode = el.nextSibling; // 如果后一个节点是文本节点,且第一个字符是汉字 if (nextNode && nextNode.nodeType === Node.TEXT_NODE) { const textContent = nextNode.textContent; if (textContent.length > 0) { const firstChar = textContent.charAt(0); // 取第一个字符 if (isChineseChar(firstChar)) { // 在元素后插入一个空格 // insertBefore 的第二个参数如果是 null,则追加到末尾 el.parentNode.insertBefore(document.createTextNode(' '), nextNode); } } } }); } function replaceImgWithFormula(root, imgMaps) { if (!imgMaps || typeof imgMaps !== 'object') return; // 获取页面上所有的 img 标签 const allImages = root.querySelectorAll('img'); allImages.forEach(img => { const src = img.src; if (!src) return; // 遍历 imgMaps 寻找匹配项 // 注意:如果 imgMaps 很大,这里内部循环依然可能慢。 // 最佳策略是:如果 src 格式固定(例如末尾是 hash),可以直接提取 hash 去查表。 // 假设我们不知道 src 的具体格式,只能包含匹配,则需遍历 keys。 for (const [key, htmlContent] of Object.entries(imgMaps)) { if (src.includes(key)) { const span = document.createElement('span'); span.className = 'replaced-formula'; span.innerHTML = `${htmlContent}`; if (img.parentNode) { img.parentNode.replaceChild(span, img); } // 找到匹配后跳出内层循环,避免重复处理 break; } } }); } function optimizeConditionsChoice(father) { const tables = father.querySelectorAll('table[name="optionsTable"]'); tables.forEach(table => { // 获取表格的可见文本内容(去除多余空白) const text = table.innerText || table.textContent; // 判断是否同时匹配两个正则 if (!(text.includes("不充分") && text.includes("不必要") && (text.includes("充要") || text.includes("充分必要")))) { return; } table.style.tableLayout = 'unset'; // 获取表格内所有的 td 元素 (转换为数组以便操作,避免实时集合带来的问题) const allCells = Array.from(table.querySelectorAll('td')); if (allCells.length === 0) return; // 如果没有单元格,跳过 // 策略:保留第一个现有的 tr 作为目标行,将其他所有 tr 中的 td 都移过来 // 或者:创建一个全新的 tr 放在 tbody 最前面。 // 这里采用:找到第一个 tr,把其他所有 td 都追加进去。 let targetRow = table.querySelector('tr'); // 如果表格里完全没有 tr (极少见,但为了健壮性),创建一个 if (!targetRow) { targetRow = document.createElement('tr'); // 尝试放入 tbody,如果没有 tbody 则直接放入 table const tbody = table.querySelector('tbody') || table; tbody.appendChild(targetRow); } // 遍历所有单元格,将它们移动到 targetRow allCells.forEach(cell => { // appendChild 会将节点从原位置移动到新位置 targetRow.appendChild(cell); }); // (可选) 清理空的 tr 行 // 移动完单元格后,原来的 tr 可能变空了。如果你想清理掉空的行,可以解开下面注释: const allRows = Array.from(table.querySelectorAll('tr')); allRows.forEach(row => { if (row !== targetRow && row.cells.length === 0) { row.remove(); } }); }); } function centerParaImages(father) { const paragraphs = father.querySelectorAll('p'); paragraphs.forEach(p => { // --- 第一步:清理只包含   的 span --- // 获取 p 下所有的 span 标签 const spans = p.querySelectorAll('span'); spans.forEach(span => { const htmlContent = span.innerHTML; // 正则表达式:匹配由一个或多个   组成的字符串,允许前后有空白字符 const onlyNbspRegex = /^\s*( )+\s*$/i; if (onlyNbspRegex.test(htmlContent)) { span.remove(); } }); // 重新获取清理后的所有子节点 const childNodes = Array.from(p.childNodes); // 过滤出元素节点 const elementNodes = childNodes.filter(node => node.nodeType === Node.ELEMENT_NODE); // 过滤出非空白文本节点 // 注意:此时之前的   span 已被移除,这里主要检查是否残留了其他文字 const textNodes = childNodes.filter(node => node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== '' ); if ( elementNodes.length === 1 && elementNodes[0].tagName === 'IMG' && textNodes.length === 0 ) { p.style.textAlign = 'center'; } }); } /** * 重新排列表格中的 td 元素 * @param {HTMLTableElement} table - 目标 table 元素 * @param {number} mode - 排列模式:1, 2, 或 4 */ function reorganizeTable(table, mode) { // 1. 基础验证 if (!(table instanceof HTMLTableElement)) { console.error("第一个参数必须是一个 table 元素"); return; } // 获取所有的 td 元素 (将类数组转换为数组以便操作) const tds = Array.from(table.querySelectorAll('td')); // 验证 td 数量是否恰好为 4 if (tds.length !== 4) { console.error("表格中必须恰好包含 4 个 td 元素"); return; } // 2. 清空表格中现有的所有 tr (但保留 td 引用) // 注意:直接清空 innerHTML 会导致 tds 变成 detached 节点,我们需要保留它们 table.innerHTML = ''; // 3. 根据 mode 进行重组 if (mode === 4) { // --- 模式 4: 所有 td 放到同一个 tr 中 --- const tr = document.createElement('tr'); tds.forEach(td => tr.appendChild(td)); table.appendChild(tr); } else if (mode === 2) { // --- 模式 2: 前两个一个 tr,后两个一个 tr --- const tr1 = document.createElement('tr'); tr1.appendChild(tds[0]); tr1.appendChild(tds[1]); table.appendChild(tr1); const tr2 = document.createElement('tr'); tr2.appendChild(tds[2]); tr2.appendChild(tds[3]); table.appendChild(tr2); } else if (mode === 1) { // --- 模式 1: 每个 td 放到单独的 tr 中 --- tds.forEach(td => { const tr = document.createElement('tr'); tr.appendChild(td); table.appendChild(tr); }); } else { console.error("第二个参数必须是 1, 2 或 4"); } } function removeAbundantTables(root) { const allowedTexts = ['A.A', 'B.B', 'C.C', 'D.D']; // 获取 root 下所有的 table 元素 const tables = root.querySelectorAll('table'); tables.forEach(table => { const tds = table.querySelectorAll('td'); // 如果没有 td,跳过(可选) if (tds.length === 0) return; // 检查所有 td 的内容是否都在允许列表中 const allMatch = Array.from(tds).every(td => { const text = td.textContent.trim(); return allowedTexts.includes(text); }); // 如果所有 td 都匹配,则移除该 table if (allMatch) { table.remove(); } }); } /** * * @param {string} selector * @returns {Element | null} */ function getFocusedElement(selector) { const selection = window.getSelection(); // 如果没有选区或选区范围为空,返回 null if (!selection || selection.rangeCount === 0) { return null; } // 获取光标所在的节点(通常是文本节点或元素节点) const anchorNode = selection.anchorNode; if (!anchorNode) return null; // 如果光标在文本节点中,我们需要找它的父元素 // 如果光标直接在元素上,就用它自己 const targetElement = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode; const closestElement = targetElement.closest(selector); return closestElement; } /** * 检索 root 元素下所有的 "bk" 元素,如果其内容仅由下划线组成,则替换为特定格式。 * @param {Element} root - 要检索的根 DOM 元素 */ function addIndexToBlanks(root) { if (!root) { return; } // 1. 选择所有带有 "index" 属性的 "bk" 元素 // 注意:这里假设 "bk" 是标签名。如果是类名,请改为 '.bk[index]' const bkElements = root.querySelectorAll('bk[index]'); bkElements.forEach((element) => { // 2. 获取元素的文本内容并去除首尾空格 const textContent = element.textContent.trim(); // 3. 使用正则表达式检查内容是否只包含一个或多个下划线 // ^ 表示开头, _+ 表示一个或多个下划线, $ 表示结尾 if (/^_{1,10}$/.test(textContent)) { // 4. 获取 index 属性值 const idx = element.getAttribute('index'); // 5. 替换内容 if (idx !== null) { element.innerHTML = `     ${idx}     `; } } }); } /** * @param {Element} elem - 元素 */ const addTitleBeforeElement = (function () { let currentIndex = 0; // 初始索引 // 核心功能函数 /** * @param {Element} elem - 元素 */ function addTitle(elem) { const p = document.createElement('div'); p.className = 'added-title'; const b = document.createElement('b'); b.textContent = String.fromCharCode(65 + currentIndex); p.appendChild(b); if (elem && elem.parentNode) { elem.parentNode.insertBefore(p, elem); } currentIndex++; } // 添加重置方法到函数对象上 addTitle.reset = function () { currentIndex = 0; console.log('索引已重置为 A'); }; return addTitle; })(); function optimizeChinesePunc(root) { // 定义替换规则 const rules = [ { regex: /(? { let text = textNode.nodeValue; let modified = false; rules.forEach(rule => { if (rule.regex.test(text)) { text = text.replace(rule.regex, rule.replacement); modified = true; } }); // 针对中文标点包装的特殊处理 // 注意:如果在文本节点内插入 HTML 标签,需要将文本节点分裂 const chinesePunctuationRegex = /([“”‘’,。?!()[]《》【】:;、.]|……|——)/g; if (chinesePunctuationRegex.test(text)) { // 使用 split 和 join 或者 replace 来构建新的 HTML 结构 // 这里为了演示,我们直接替换整个 nodeValue 为带 span 的 HTML // 但要注意,nodeValue 不能直接放 HTML,需要用 range 替换 const tempDiv = document.createElement('div'); // 先处理前面的英文标点转换 // text = text // .replace(/(?!\d\.?\d)\./g, '.') // .replace(/, ?/g, ',') // .replace(/\? ?/g, '?') // .replace(/!/g, '!') // .replace(/: ?/g, ':') // .replace(/; ?/g, ';'); // 包装中文标点 const html = text.replace(chinesePunctuationRegex, '$1'); tempDiv.innerHTML = html; // 将生成的 DOM 节点替换原来的文本节点 const parent = textNode.parentNode; while (tempDiv.firstChild) { parent.insertBefore(tempDiv.firstChild, textNode); } parent.removeChild(textNode); } else if (modified) { textNode.nodeValue = text; } }); } /** * 为特定标题下的题目添加字母序号 * @param {HTMLElement} root - 父元素 DOM 节点 */ function addEnglishSectionLetters(root) { if (!root) return; // 获取所有直接子元素 (转换为数组以便遍历) const children = Array.from(root.children); let isTargetSection = false; // 标记当前是否处于目标板块(语法填空/阅读理解) let charCode = 65; // ASCII码,65代表'A' children.forEach(child => { // 检查是否为标题元素 if (child.classList.contains('zujuanjs-section-title')) { const titleText = child.innerText || child.textContent; // 判断标题内容是否包含关键词 if (titleText.includes('语法填空') || titleText.includes('阅读理解')) { isTargetSection = true; charCode = 65; // 遇到新标题,重置字母为 A } else { isTargetSection = false; // 其他标题则退出目标模式 } return; // 标题处理完毕,继续下一次循环 } // 检查是否为题目元素 if (child.classList.contains('zujuanjs-question')) { if (isTargetSection) { // 创建新的 p 元素 const addedTitle = document.createElement('div'); addedTitle.className = 'added-title'; // 设置内容 A, B ... addedTitle.innerHTML = `${String.fromCharCode(charCode)}`; // 插入到题目元素的最开始 child.prepend(addedTitle); // 字母递增 charCode++; } } }); } /** * * @param {Element} root */ const removeWidthInImg = (root) => { if (!root) return; const images = root.querySelectorAll('img'); images.forEach((img) => { img.removeAttribute('width'); }); }; /** * @param {Element} root - 搜索范围的根节点 (例如 document.body) */ function fixPunctuationWrapping(root) { if (!root) return; // 定义两类标点 const rightPuncRegex = /^[,。?!;、.”’]/; // 句首禁止出现的标点 const leftPuncRegex = /[(【《“‘]/; // 行尾禁止出现的标点 const targetSelector = 'img, i, .replaced-formula'; const elements = root.querySelectorAll('.chn-punc'); elements.forEach(el => { const text = el.textContent.trim(); if (!text) return; // 逻辑 A: 如果是以靠右标点开头 -> 包裹 [前一个] + [当前] if (rightPuncRegex.test(text)) { const prev = el.previousSibling; if (prev && prev.nodeType === Node.ELEMENT_NODE && prev.matches(targetSelector)) { const wrapper = document.createElement('span'); wrapper.className = 'nowrap-wrapper'; el.parentNode.insertBefore(wrapper, prev); wrapper.appendChild(prev); wrapper.appendChild(el); } } // 逻辑 B: 如果是以靠左标点结尾 -> 包裹 [当前] + [后一个] else if (leftPuncRegex.test(text.slice(-1))) { const next = el.nextSibling; if (next && next.nodeType === Node.ELEMENT_NODE && next.matches(targetSelector)) { const wrapper = document.createElement('span'); wrapper.className = 'nowrap-wrapper'; el.parentNode.insertBefore(wrapper, el); wrapper.appendChild(el); wrapper.appendChild(next); } } }); } /** * 将可编辑区域中选中的内容用指定标签包裹 * @param {string} tagName - HTML标签名 (例如: 'span', 'b', 'div') * @param {object} attributes - (可选) 标签的属性对象 (例如: {class: 'highlight', style: 'color:red'}) */ function wrapSelectedText(tagName, attributes = {}) { const selection = window.getSelection(); if (!selection.rangeCount) { console.warn("未检测到选中的内容"); return; } const range = selection.getRangeAt(0); // 3. 提取选中的内容 // extractContents() 会将选区内容从DOM中移除,并返回一个 DocumentFragment const selectedContent = range.extractContents(); const wrapper = document.createElement(tagName); // 5. 设置元素的属性 (如 class, id, style 等) for (const [key, value] of Object.entries(attributes)) { wrapper.setAttribute(key, value); } wrapper.appendChild(selectedContent); range.insertNode(wrapper); // selection.removeAllRanges(); } /** * 检查并自动为题目内容添加题号 * @param {HTMLElement} root - 检索的根节点 */ function addQuestionNumbers(root) { // 1. 检索所有目标元素 .exam-item__cnt // 使用 querySelectorAll 在指定 root 范围内查找 const questions = root.querySelectorAll('.zujuanjs-question .exam-item__cnt'); if (questions.length === 0) return; // 如果没有找到题目,直接结束 // 2. 检测是否存在已有的题号 // 正则解释:^\s*\d+\. // ^ 表示字符串开头 // \s* 表示允许开头有任意空白符(空格、换行等) // \d+ 表示一个或多个数字 // \. 表示实际的点号 // const hasNumberRegex = /^\s*\d+\./; // // 检查数组中是否【至少有一个】元素匹配已有题号的格式 // const hasExistingNumber = Array.from(questions).some(q => // hasNumberRegex.test(q.innerText.trim()) // ); let count = 1; questions.forEach(q => { // 这里假设是顺序生成题号 1., 2., 3. ... // 如果你需要提取特定逻辑,可以在这里修改 count 的计算方式 // q.innerHTML = `${count}. ${q.innerHTML}`; q.insertBefore(document.createTextNode(`${count}. `), q.firstChild); count++; }); console.log(`✅ 已为 ${questions.length} 道题目添加题号`); } /** * 将元素内的图片提取出来,与该元素并列,并共同包裹在一个新父元素中 * @param {HTMLElement} elem - 目标 DOM 元素 */ function wrapQuestionWithFlex(elem) { // 1. 获取 elem 内部所有的 img 元素 (转为数组以便操作) const images = Array.from(elem.querySelectorAll('img:not([src*="quesimg/Upload/formula"])')); // 如果没有图片,直接返回,不做任何操作 if (images.length === 0) return; // 2. 获取 elem 的父节点,用于后续插入操作 const parent = elem.parentNode; if (!parent) return; // 如果 elem 没有父节点(比如是body),则无法进行同级操作 // 3. 创建一个新的父容器 (用于包裹图片和 elem) const newWrapper = document.createElement('div'); // 给个类名方便调试样式,比如设置 display: flex newWrapper.className = 'flex-wrapper'; // 4. 将图片移动到 wrapper 中 // 注意:appendChild 移动现有元素时,会自动将其从原位置移除 newWrapper.appendChild(elem); images.forEach(img => { newWrapper.appendChild(img); }); // 6. 将新的 wrapper 插入到 DOM 树中(替换原来 elem 的位置) parent.appendChild(newWrapper); } /** * 格式化 exam-item__cnt 下的内容 * 功能: * 1. 按换行分段(支持
和 块级元素) * 2. 识别 (1), (2) 并转换为 ol/li 结构 * 3. 中间的非编号段落会自动归属到上一个编号项下 * 4. 完整保留 img, b, span 等内部标签 * 5. 【新增】自动移除 li 开头原有的 (1) 等编号标记 * * @param {HTMLElement} root - 根元素 */ function formatExamContent(root) { if (!root) return; const items = Array.from(root.querySelectorAll('div.exam-item__cnt')); // 定义哪些标签被视为“块级元素” const blockTags = new Set(['DIV', 'P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'UL', 'OL', 'LI', 'TABLE', 'SECTION', 'ARTICLE', 'HEADER', 'FOOTER', 'FIGURE', 'BLOCKQUOTE']); items.forEach(item => { // 1. 【预处理】将 innerHTML 转为 DOM 结构 const tempDiv = document.createElement('div'); tempDiv.innerHTML = item.innerHTML; let lines = []; let currentLineNodes = []; // 2. 遍历所有子节点,进行“物理分行” const nodes = Array.from(tempDiv.childNodes); nodes.forEach(node => { if (node.nodeName === 'BR') { lines.push([...currentLineNodes]); currentLineNodes = []; } else if (blockTags.has(node.nodeName)) { if (currentLineNodes.length > 0) { lines.push([...currentLineNodes]); currentLineNodes = []; } lines.push([node]); } else { currentLineNodes.push(node); } }); // 3. 处理最后一行 if (currentLineNodes.length > 0) { lines.push(currentLineNodes); } // 4. 清空原内容,开始重组 item.innerHTML = ''; let currentOl = null; lines.forEach(lineNodes => { // 获取纯文本用于判断 const lineText = lineNodes.map(n => n.textContent).join('').trim(); // 正则匹配:以 (数字) 或 (数字) 开头 const isNumbered = /^\(\d+\)|^(\d+)/.test(lineText); const rowWrapper = document.createElement('div'); lineNodes.forEach(node => rowWrapper.appendChild(node)); if (isNumbered) { // --- 是编号段落 --- if (!currentOl) { currentOl = document.createElement('ol'); currentOl.className = "question-ol"; item.appendChild(currentOl); } const li = document.createElement('li'); // 我们遍历 wrapper 里的子节点,如果是文本节点,就进行替换 // 这样可以精准删除 "(1)" 而不影响后面的 Array.from(rowWrapper.childNodes).forEach(node => { if (node.nodeType === Node.TEXT_NODE) { // 使用正则替换掉开头的 (数字) 或 (数字)以及紧随其后的空格 node.textContent = node.textContent.replace(/^\(\d+\)|^(\d+)/, ''); } }); // 将清洗后的内容移入 li while (rowWrapper.firstChild) { li.appendChild(rowWrapper.firstChild); } currentOl.appendChild(li); } else { // --- 是普通段落 --- if (currentOl) { currentOl.appendChild(rowWrapper); } else { item.appendChild(rowWrapper); } } }); }); } GM_addStyle(additionalStyles); loadExternalScript('https://cdn.jsdelivr.net/npm/pangu@7/dist/browser/pangu.umd.js'); const usernameElement = document.querySelector('.user-nickname'); const username = usernameElement ? usernameElement.innerText : '未知用户'; function checkIn() { const signInBtn = document.querySelector('a.sign-in-btn'); const daySignInBtn = document.querySelector('a.day-sign-in'); if (signInBtn) signInBtn.click(); if (daySignInBtn) daySignInBtn.click(); console.log("已签到!"); } function canCheckIn() { const signedInLink = document.querySelector( '.user-assets-box a.assets-method[href="/score_task/"]' ); return !signedInLink || signedInLink.textContent.trim() !== '已签到'; } function signInLogic() { if (canCheckIn()) { checkIn(); } } function debug() { console.log("是否可签到:", canCheckIn()); signInLogic(); } window.addEventListener('load', debug, false); const buildBtn = document.createElement('a'); buildBtn.className = 'zujuanjs-print-btn'; buildBtn.innerHTML = `排版试卷`; document.body.appendChild(buildBtn); buildBtn.onclick = showPreDialog; function showPreDialog() { const savedSepPage = GM_getValue('sepPage', false); const savedShowSource = GM_getValue('showSource', false); Swal.fire({ title: '排版设置', width: 600, html: /*html*/`
`, confirmButtonText: '开始排版', showCancelButton: true, didOpen: () => { const sepPageCheckbox = document.getElementById('sep-page-checkbox'); const showSourceCheckbox = document.getElementById('show-source-checkbox'); const preview = document.getElementById('font-preview'); sepPageCheckbox.checked = savedSepPage; showSourceCheckbox.checked = savedShowSource; updatePreview(); }, preConfirm: () => { const sepPage = document.getElementById('sep-page-checkbox').checked; const showSource = document.getElementById('show-source-checkbox').checked; GM_setValue('sepPage', sepPage); GM_setValue('showSource', showSource); } }).then(async res => { if (!res.isConfirmed) return; performPrint(); }); } function performPrint() { const body = buildContent(); document.body.innerHTML = ''; document.body.appendChild(body); // window.print(); } function buildContent() { if (document.title === "组卷中心" || document.title === "个人题库") { const titleElem = document.querySelector(".exam-title .title-txt") || document.querySelector("#pui_maintitle"); document.title = titleElem.innerText; } document.documentElement.style.setProperty('--page-title', `"${document.title.replace("-组卷网", "")}"`); const today = new Date(); const dateString = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}` + ` ${String(today.getHours()).padStart(2, '0')}:${String(today.getMinutes()).padStart(2, '0')}`; // 将日期传给 CSS 变量 document.documentElement.style.setProperty('--current-datetime', `"${dateString}"`); const root = document.createElement('div'); root.id = 'zujuanjs-reformatted-content'; const sepPage = GM_getValue('sepPage'); const showSource = GM_getValue('showSource'); const isEnglish = document.getElementById("is-english-checkbox").checked; if (isEnglish) { root.classList.add("zujuanjs-english"); } const answers = []; document.querySelectorAll('.sec-title, .tk-quest-item.quesroot') .forEach(node => { if (node.classList.contains('sec-title')) { const span = node.querySelector('span'); if (span) { const t = document.createElement('div'); t.className = 'zujuanjs-section-title'; t.textContent = span.textContent.trim(); root.appendChild(t); } return; } const q = document.createElement('div'); q.className = 'zujuanjs-question'; if (sepPage) { q.style.breakBefore = "page"; } const quesAddInfoElem = node.querySelector("a.add-exam-btn"); if (quesAddInfoElem) { quesAddInfoElem.style.display = "none"; q.appendChild(quesAddInfoElem); } if (showSource) { const questionSource = node.querySelector(".ques-additional .ques-src"); if (questionSource) { q.appendChild(questionSource); if (quesAddInfoElem) { const abbrTitle = quesAddInfoElem.getAttribute("questitle"); // if (abbrTitle) { questionSource.textContent += `:${abbrTitle}`; } } } } const wrap = node.querySelector('.wrapper.quesdiv'); if (!wrap) return; const cnt = wrap.querySelector('.exam-item__cnt'); if (cnt) q.appendChild(cnt.cloneNode(true)); // const opt = wrap.querySelector('.exam-item__opt'); // if (opt) { // opt.querySelector('.knowledge-box')?.remove(); // if (includeA) q.appendChild(opt.cloneNode(true)); // else if (atEnd) answers.push(opt.cloneNode(true)); // } root.appendChild(q); }); replaceDotEmphases(root); removeAbundantTables(root); addSpacesAroundElements(root, `i, .replaced-formula, img[src*="quesimg/Upload/formula"]`); optimizeConditionsChoice(root); centerParaImages(root); removeWidthInImg(root); if (!isEnglish) { formatExamContent(root); optimizeChinesePunc(root); fixPunctuationWrapping(root); } else { addIndexToBlanks(root); root.innerHTML = root.innerHTML.replace(/(/g, " ("); root.innerHTML = root.innerHTML.replace(/)/g, ") "); root.innerHTML = root.innerHTML.replace(/([\u0000-\u00ff]),([\u0000-\u00ff])/g, `$1, $2`); root.innerHTML = root.innerHTML.replace(/([\u0000-\u00ff]).([\u0000-\u00ff])/g, `$1. $2`); root.innerHTML = root.innerHTML.replace(/([\u0000-\u00ff])?([\u0000-\u00ff])/g, `$1? $2`); root.innerHTML = root.innerHTML.replace(/([\u0000-\u00ff])!([\u0000-\u00ff])/g, `$1! $2`); root.innerHTML = root.innerHTML.replace(/([\u0000-\u00ff]):([\u0000-\u00ff])/g, `$1: $2`); root.innerHTML = root.innerHTML.replace(/ /g, " "); const grammarBlanksPrompt = /阅读下.短文..?根据短文内容(或括号内所给词的恰当形式)?填空.(在未给.?提示词的空白处仅填写.*个.当的单词..?在给出提示词的空白处用括号内所给词的正确形式填空。)?(请在答题.指定区域作答。)?/g; // let count = 0; // root.innerHTML = root.innerHTML.replace(grammarBlanksPrompt, () => { // char = String.fromCharCode(65 + count); // count++; // return /*html*/`

${char}

`; // }); root.innerHTML = root.innerHTML.replace(grammarBlanksPrompt, ""); addEnglishSectionLetters(root); } replaceImgWithFormula(root, imgMaps); // root.innerHTML = root.innerHTML.replace(/阅读下列短文,根据短文内容填空。在未给提示词的空白处仅填写.*个恰当的单词,在给出提示词的空白处用括号内所给词的正确形式填空。请在答题卡指定区域作答。/g, ``); // root.innerHTML = root.innerHTML.replace(/([\u4e00-\u9fff])”/g, `$1`); // root.innerHTML = root.innerHTML.replace(/”([\u4e00-\u9fff])/g, `$1`); // root.innerHTML = root.innerHTML.replace(/([\u4e00-\u9fff])“/g, `$1`); pangu.spacingNode(root); // root.contentEditable = true; setTimeout(() => { root.contentEditable = true; // root.addEventListener("keydown") }, 2000); return root; } document.addEventListener('keydown', (e) => { // console.log(e); if (e.ctrlKey && e.shiftKey) { const key = e.key; if (key === "_") { wrapSelectedText("sub"); } else if (key === "+") { wrapSelectedText("sup"); } } if (e.ctrlKey && e.shiftKey && e.altKey) { // 获取按下的数字键 (兼容主键盘和数字小键盘) const key = e.key; console.log(key); if (key === ")") { addQuestionNumbers(document.getElementById("zujuanjs-reformatted-content")); } if (key === "A") { const targetElement = getFocusedElement("p"); if (targetElement) { addTitleBeforeElement(targetElement); } } else if (key === "Q") { addTitleBeforeElement.reset(); } if (key === "ArrowRight") { const targetElement = getFocusedElement("p:has(img)"); if (targetElement) { targetElement.querySelector("img").style.position = "absolute"; } } else if (key === "ArrowUp") { const targetElement = getFocusedElement("p:has(img)"); if (targetElement) { targetElement.querySelector("img").style.marginTop = "-22px"; } } if (key === "X") { const targetElement = getFocusedElement("div, p, table"); if (targetElement) { targetElement.remove(); } } if (key === "E") { wrapSelectedText("p", { class: "added-title" }); } if (key === "P") { const targetElement = getFocusedElement("div.exam-item__cnt"); if (targetElement) { wrapQuestionWithFlex(targetElement); } } if (key === "Enter") { const targetElement = getFocusedElement("div.zujuanjs-section-title, div.zujuanjs-question"); if (targetElement) { targetElement.style.breakBefore = "page"; } } if (key === "K") { wrapSelectedText("span", { class: "kaiti" }); } let mode = null; if (key === '!') { mode = 1; } if (key === '@') { mode = 2; } if (key === '$') { mode = 4; } if (mode) { const targetTable = getFocusedElement("table"); if (targetTable) { reorganizeTable(targetTable, mode); } } // e.preventDefault(); } }, { capture: true });