OptiYan

EYanIDE 优化

  1. // ==UserScript==
  2. // @name OptiYan
  3. // @namespace http://lunarine.cc/
  4. // @version 2024.1.2
  5. // @description EYanIDE 优化
  6. // @author Liu Baicheng
  7. // @match http://121.36.38.167/
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
  9. // @grant unsafeWindow
  10. // @license MIT
  11. // @resource css https://unpkg.com/mdui@1.0.2/dist/css/mdui.min.css
  12. // @grant GM_getResourceURL
  13. // @grant GM_getResourceText
  14. // @grant GM_addStyle
  15. // @grant GM_xmlhttpRequest
  16. // @grant GM_notification
  17. // @grant GM_setValue
  18. // @grant GM_getValue
  19. // @grant GM_registerMenuCommand
  20. // @require https://cdn.jsdelivr.net/npm/mdui@1.0.2/dist/js/mdui.min.js
  21. // @connect api.mkc.icu
  22. // ==/UserScript==
  23.  
  24. (function () {
  25. 'use strict';
  26.  
  27. const spans = document.querySelectorAll('span.lm_title');
  28. var title;
  29. // 遍历并输出内容为 main.cpp 的 span
  30. spans.forEach(span => {
  31. if (span.textContent.trim() === 'main.cpp') {
  32. title = span;
  33. }
  34. });
  35.  
  36. function classOptimize() {
  37.  
  38. let divs = document.querySelectorAll('div.ui.dropdown.selection');
  39.  
  40. // 遍历并删除这些 div
  41. divs.forEach(div => {
  42. div.remove();
  43. });
  44.  
  45. divs = document.querySelectorAll("div.right.menu");
  46.  
  47. // 遍历并删除这些 div
  48. divs.forEach(div => {
  49. div.remove();
  50. });
  51.  
  52.  
  53. var compilerOptionsInput = document.getElementById('compiler-options');
  54. compilerOptionsInput.value = "-O3";
  55. var comilerArgsInput = document.getElementById('command-line-arguments');
  56. comilerArgsInput.remove();
  57. var navbar = document.getElementById("site-navigation");
  58. let optibar = document.createElement('div');
  59. optibar.classList.add("right");
  60. optibar.classList.add("menu");
  61. navbar.appendChild(optibar);
  62.  
  63. let tdiv = document.createElement('div');
  64. tdiv.className = "item no-right-padding borderless";
  65. tdiv.id = "userbar"
  66. optibar.appendChild(tdiv);
  67.  
  68. // let tbutton = document.createElement('button');
  69. // tbutton.className = "ui labeled icon button";
  70. // tbutton.id = "optiso";
  71. // tbutton.innerHTML = `<i class="search icon"></i><span>搜索</span>`;
  72. // tdiv.appendChild(tbutton);
  73.  
  74. // tbutton.onclick = function () {
  75. // let input = unsafeWindow.stdinEditor.getValue();
  76. // console.log(input);
  77. // tbutton.classList.add('loading');
  78. // requestGPT(input).then(response => {
  79. // unsafeWindow.sourceEditor.setValue(response);
  80. // tbutton.classList.remove('loading');
  81. // });
  82. // };
  83. }
  84.  
  85. function formatCppTemplateLine(line) {
  86. const templateRegex = /(\btemplate\b|\bvector\b|\bmap\b|\bset\b|\bp(?:air|queue)\b|<.*>)/;
  87. if (templateRegex.test(line.trim())) {
  88. return line
  89. .replace(/\s*(<|>)\s*/g, '$1')
  90. .replace(/>(\w)/g, '> $1');
  91. }
  92. return line;
  93. }
  94.  
  95. function formatCppCode(code) {
  96. code = code.replace(/\/\*[\s\S]*?\*\//g, '');
  97. code = code.replace(/\/\/.*$/gm, '');
  98. const lines = code.split('\n');
  99. let formattedLines = [];
  100. let indentLevel = 0;
  101. const indentSpace = ' ';
  102. let inStruct = false;
  103.  
  104. for (let i = 0; i < lines.length; i++) {
  105. let line = lines[i].trim();
  106. const isEndOfStructWithVar = line.match(/}\s*[a-zA-Z_][a-zA-Z0-9_]*\s*\[?\s*[^;]*;/);
  107.  
  108. if (line.includes('{') && !line.endsWith('{')) {
  109. line = line.replace(/\s*{\s*/g, ' {\n' + indentSpace.repeat(indentLevel + 1));
  110. }
  111.  
  112. if (line.startsWith('struct')) {
  113. inStruct = true;
  114. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  115. indentLevel++;
  116. continue;
  117. }
  118.  
  119. if (line.endsWith('};') || isEndOfStructWithVar) {
  120. if (indentLevel) indentLevel--;
  121. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  122. inStruct = false;
  123.  
  124. if (isEndOfStructWithVar) {
  125. continue;
  126. }
  127. formattedLines.push('');
  128. continue;
  129. }
  130.  
  131. if (inStruct) {
  132. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  133. continue;
  134. }
  135.  
  136. if (line.startsWith('#include')) {
  137. line = line.replace(/#include\s*<\s*([\w./+-]+)\s*>/g, '#include <$1>');
  138. formattedLines.push(line);
  139. continue;
  140. }
  141.  
  142. if (line === 'using namespace std;') {
  143. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  144. formattedLines.push('');
  145. continue;
  146. }
  147.  
  148. if (line.endsWith(')') && lines[i + 1] && lines[i + 1].trim() === '{') {
  149. line += ' {';
  150. i++;
  151. }
  152.  
  153. line = line.replace(/\s*([+\-*/=<>&|]+)\s*/g, ' $1 ');
  154. line = line.replace(/\s*,\s*/g, ', ');
  155. line = line.replace(/\s*([+\-]{2})\s*/g, '$1');
  156. line = line.replace(/\s*;\s*/g, '; ');
  157. line = line.replace(/\)\s*(?=[a-zA-Z+\-*/])/g, ') ');
  158.  
  159. line = line.replace(/(?<=[+\*/])\s*\(/g, ' (');
  160. line = line.replace(/(?<!\S)-\s*\(/g, '-(');
  161. line = line.replace(/\b(for|while|if|else|switch|case|do)\s*(?=[({])/g, '$1 ');
  162.  
  163. line = formatCppTemplateLine(line);
  164. line = line.replace(/!\s*=\s*/g, '!= ');
  165.  
  166.  
  167. if (line.endsWith('}')) {
  168. if (indentLevel) indentLevel--;
  169. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  170. if (indentLevel === 0 && !inStruct && line.endsWith('}')) {
  171. formattedLines.push('');
  172. }
  173. continue;
  174. }
  175.  
  176. if (line.includes("}")) {
  177. indentLevel--;
  178. }
  179.  
  180. if (line.includes(') {')) {
  181. if (indentLevel === 0 && !inStruct && formattedLines[formattedLines.length - 1] != '') {
  182. formattedLines.push('');
  183. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  184. indentLevel++;
  185. continue;
  186. }
  187. }
  188.  
  189. if (line) {
  190. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  191. }
  192.  
  193. if (line.endsWith('{')) {
  194. indentLevel++;
  195. }
  196. }
  197.  
  198. return formattedLines.join('\n').trim();
  199. }
  200.  
  201. function formatCode() {
  202. const res = formatCppCode(unsafeWindow.sourceEditor.getValue());
  203. unsafeWindow.sourceEditor.setValue(res);
  204. }
  205.  
  206. classOptimize();
  207.  
  208. document.addEventListener('keydown', function (event) {
  209. if (event.ctrlKey && event.altKey) {
  210. formatCode(); // 调用目标函数
  211. mdui.snackbar({
  212. message: '代码格式化成功'
  213. });
  214. } else if (event.keyCode === 122) { // F11
  215. event.preventDefault();
  216. unsafeWindow.run();
  217. } else if (event.keyCode === 116) { // F5
  218. event.preventDefault();
  219. } else if (event.ctrlKey && event.keyCode === 82) { // Ctrl+R
  220. event.preventDefault();
  221. } else if (event.ctrlKey && event.keyCode === 121) { // Ctrl+R
  222. event.preventDefault();
  223. } else if (event.keyCode == 83 && event.ctrlKey) {
  224. event.preventDefault();
  225. saveFile();
  226. }
  227. });
  228.  
  229. unsafeWindow.formatCppCode = formatCppCode;
  230. formatCode();
  231.  
  232. window.addEventListener('load', function () {
  233. var footer = document.querySelector('#site-footer');
  234. if (footer) {
  235. var span = document.createElement('span');
  236. span.id = 'optiyan-line';
  237. span.textContent = 'OptiYan 已加载 Version: V1.1.0';
  238. span.style.color = "#fff";
  239. span.style.float = "left";
  240. span.style.left = "0";
  241. span.style.textAlign = "left";
  242. span.style.width = "fit-content";
  243. footer.appendChild(span);
  244. }
  245. var runBtn = document.getElementById('run-btn-label');
  246. runBtn.textContent = 'Run (F11 / Ctrl + ↵)';
  247. });
  248.  
  249. function updateColor() {
  250. let status = document.getElementById("status-line");
  251. if (status) {
  252. if (status.innerText.includes('Error')) {
  253. const sitefooter = document.querySelector('#site-footer');
  254. const linefooter = document.querySelector('#status-line');
  255.  
  256. sitefooter.style.backgroundColor = "#c14343";
  257. linefooter.style.backgroundColor = "#c14343";
  258. } else if (status.innerText.includes('Accept')) {
  259. const sitefooter = document.querySelector('#site-footer');
  260. const linefooter = document.querySelector('#status-line');
  261. sitefooter.style.backgroundColor = "#05a705";
  262. linefooter.style.backgroundColor = "#05a705";
  263. } else {
  264. const sitefooter = document.querySelector('#site-footer');
  265. const linefooter = document.querySelector('#status-line');
  266. sitefooter.style.backgroundColor = "#9775fa";
  267. linefooter.style.backgroundColor = "#9775fa";
  268. }
  269. } else {
  270. const sitefooter = document.querySelector('#site-footer');
  271. const linefooter = document.querySelector('#status-line');
  272. sitefooter.style.backgroundColor = "#9775fa";
  273. linefooter.style.backgroundColor = "#9775fa";
  274. }
  275.  
  276. }
  277.  
  278. let script = document.createElement('script');
  279. script.src = "https://unpkg.com/mdui@1.0.2/dist/js/mdui.min.js?v=20240817";
  280.  
  281. script.onload = function () {
  282. console.log('mdui 已加载');
  283. };
  284.  
  285. document.body.appendChild(script);
  286. console.log(GM_getResourceURL("css"), GM_getResourceText("css"));
  287. GM_addStyle(GM_getResourceText("css"));
  288.  
  289. setInterval(updateColor, 100);
  290.  
  291. var userbar = document.getElementById('userbar');
  292. //var fileList = document.getElementById('fileList');
  293. var loginButton = document.createElement('button');
  294. loginButton.className = "ui labeled icon button";
  295. loginButton.innerHTML = `<i class="user icon"></i><span>登陆</span>`;
  296. loginButton.style.marginRight = "5px";
  297. loginButton.addEventListener('click', function () {
  298. login();
  299. });
  300. var registerButton = document.createElement('button');
  301. registerButton.className = "ui labeled icon button";
  302. registerButton.innerHTML = `<i class="add icon"></i><span>注册</span>`;
  303. registerButton.style.marginRight = "5px";
  304. registerButton.addEventListener('click', function () {
  305. register();
  306. });
  307. var logoutButton = document.createElement('button');
  308. logoutButton.innerHTML = `<i class="sign-out icon"></i><span>退出登录</span>`;
  309. logoutButton.className = "ui labeled icon button";
  310. logoutButton.addEventListener('click', function () {
  311. logout();
  312. });
  313.  
  314. var saveButton = document.createElement('button');
  315. saveButton.innerHTML = `<i class="save icon"></i><span>保存文件 (Ctrl + S)</span>`;
  316. saveButton.style.marginRight = "5px";
  317. saveButton.className = "ui labeled icon button";
  318. saveButton.addEventListener('click', function () {
  319. saveFile();
  320. });
  321.  
  322. var deleteButton = document.createElement('button');
  323. deleteButton.innerHTML = `<i class="trash icon"></i><span>删除文件</span>`;
  324. deleteButton.style.marginRight = "5px";
  325. deleteButton.className = "ui red labeled icon button";
  326. deleteButton.addEventListener('click', function () {
  327. deleteFile();
  328. });
  329.  
  330. var userMessage = document.createElement('div');
  331. userMessage.classList.add('ui');
  332. userMessage.classList.add('site-link');
  333. userMessage.style.marginRight = "30px";
  334.  
  335. var openButton = document.createElement('button');
  336. openButton.innerHTML = `<i class="file icon"></i><span>打开文件</span>`;
  337. openButton.style.marginRight = "5px";
  338. openButton.className = "ui labeled icon button";
  339. openButton.addEventListener('click', function () {
  340. var filename = prompt('请输入文件名');
  341. if (filename != null && filename.length >= 1) {
  342. loadFile(filename);
  343. mdui.snackbar({
  344. message: '文件加载成功'
  345. });
  346. } else {
  347. mdui.snackbar({
  348. message: '文件加载失败'
  349. });
  350. }
  351. openButton.classList.remove('loading');
  352. });
  353.  
  354. // 初始化用户界面
  355. function updateUI() {
  356. userbar.innerHTML = '';
  357. if (isLoggedIn) {
  358. userMessage.innerText = "已登录为 @" + Gusername;
  359. userbar.appendChild(userMessage);
  360. userbar.appendChild(saveButton);
  361. if(title.innerText != "main.cpp") userbar.appendChild(deleteButton);
  362. userbar.appendChild(openButton);
  363. userbar.appendChild(logoutButton);
  364. } else {
  365. userbar.appendChild(loginButton);
  366. userbar.appendChild(registerButton);
  367. }
  368. }
  369.  
  370. let token = localStorage.getItem('token');
  371. let Gusername = localStorage.getItem('username');
  372. let isLoggedIn = !!token; // 如果 token 存在,则 isLoggedIn 为 true
  373.  
  374. function login() {
  375. var username = prompt('请输入用户名');
  376. var password = prompt('请输入密码');
  377. loginButton.classList.add('loading');
  378. GM_xmlhttpRequest({
  379. method: 'POST',
  380. url: 'http://api.mkc.icu/login',
  381. headers: {
  382. 'Content-Type': 'application/json'
  383. },
  384. data: JSON.stringify({
  385. username: username,
  386. password: password
  387. }),
  388. onload: function (response) {
  389. var data = JSON.parse(response.responseText);
  390. if (data.token) {
  391. mdui.snackbar({
  392. message: '登录成功'
  393. });
  394. token = data.token;
  395. isLoggedIn = true;
  396. Gusername = username;
  397. localStorage.setItem('token', token); // 保存 token 到 localStorage
  398. localStorage.setItem('username', username);
  399. loginButton.classList.remove('loading');
  400. updateUI();
  401. openFile();
  402. } else {
  403. mdui.snackbar({
  404. message: '登录失败'
  405. });
  406. }
  407. },
  408. onerror: function (error) {
  409. console.error('登录请求错误:', error);
  410. }
  411. });
  412. }
  413.  
  414. function register() {
  415. var username = prompt('请输入用户名');
  416. var password = prompt('请输入密码');
  417.  
  418. const a = Math.floor(Math.random() * (9999 - 1000 + 1)) + 1000;
  419. const b = Math.floor(Math.random() * (9999 - 1000 + 1)) + 1000;
  420. var answer = prompt(`请输入 ${a} + ${b} 的答案`);
  421.  
  422. if (answer != a + b) {
  423. mdui.snackbar({
  424. message: `注册失败:你是人机嘛?`
  425. });
  426. return;
  427. }
  428. registerButton.classList.add('loading');
  429. GM_xmlhttpRequest({
  430. method: 'POST',
  431. url: 'http://api.mkc.icu/register',
  432. headers: {
  433. 'Content-Type': 'application/json'
  434. },
  435. data: JSON.stringify({
  436. username: username,
  437. password: password
  438. }),
  439. onload: function (response) {
  440. var data = JSON.parse(response.responseText);
  441. if (data.message === '注册成功') {
  442. token = data.token;
  443. isLoggedIn = true;
  444. Gusername = username;
  445. localStorage.setItem('token', token); // 保存 token 到 localStorage
  446. localStorage.setItem('username', username);
  447. mdui.snackbar({
  448. message: '注册成功'
  449. });
  450. registerButton.classList.remove('loading');
  451. updateUI();
  452. openFile();
  453. } else {
  454. mdui.snackbar({
  455. message: `注册失败:${data.message}`
  456. });
  457. }
  458. },
  459. onerror: function (error) {
  460. console.error('注册请求错误:', error);
  461. }
  462. });
  463. }
  464.  
  465. function saveFile() {
  466. if (!isLoggedIn) {
  467. mdui.snackbar({
  468. message: `请先登录!`
  469. });
  470. return;
  471. }
  472. var filename;
  473. if (title.innerText == "main.cpp") filename = prompt('请输入文件名');
  474. else filename = title.innerText;
  475. if (filename == null || filename == "" || filename.length <= 1) {
  476. mdui.snackbar({
  477. message: `文件名不能为空!`
  478. });
  479. return;
  480. }
  481. var content = unsafeWindow.sourceEditor.getValue();
  482. saveButton.classList.add('loading');
  483. GM_xmlhttpRequest({
  484. method: 'POST',
  485. url: 'http://api.mkc.icu/files',
  486. headers: {
  487. 'Content-Type': 'application/json',
  488. },
  489. data: JSON.stringify({
  490. token: token, // 将token放入body中
  491. filename: filename,
  492. content: content
  493. }),
  494. onload: function (response) {
  495. try {
  496. var data = JSON.parse(response.responseText);
  497. title.innerText = filename + ".cpp";
  498. if (data.message === '文件保存成功') {
  499. openFile();
  500. mdui.snackbar({
  501. message: `文件保存成功!`
  502. });
  503. saveButton.classList.remove('loading');
  504. updateUI();
  505.  
  506. } else {
  507. mdui.snackbar({
  508. message: `保存失败:${data.message}`
  509. });
  510. saveButton.classList.remove('loading');
  511. }
  512. } catch (e) {
  513. console.error('解析响应时出错:', e);
  514. }
  515. },
  516. onerror: function (error) {
  517. console.error('保存文件请求错误:', error);
  518. }
  519. });
  520. }
  521.  
  522. function deleteFile() {
  523. if (!isLoggedIn) {
  524. alert('请先登录');
  525. return;
  526. }
  527. var filename;
  528. if (title.innerText == "main.cpp") filename = prompt('请输入文件名');
  529. else {
  530. filename = title.innerText;
  531. filename = filename.replace(/\.[^/.]+$/, "");
  532. }
  533. if (filename == '') {
  534. alert('文件名不能为空!');
  535. return;
  536. }
  537. var content = unsafeWindow.sourceEditor.getValue();
  538. deleteButton.classList.add('loading');
  539. GM_xmlhttpRequest({
  540. method: 'POST',
  541. url: 'http://api.mkc.icu/delete',
  542. headers: {
  543. 'Content-Type': 'application/json',
  544. },
  545. data: JSON.stringify({
  546. token: token, // 将token放入body中
  547. filename: filename
  548. }),
  549. onload: function (response) {
  550. try {
  551. var data = JSON.parse(response.responseText);
  552. if (data.message === '文件删除成功') {
  553. openFile();
  554. mdui.snackbar({
  555. message: `文件删除成功!`
  556. });
  557. deleteButton.classList.remove('loading');
  558. updateUI();
  559. } else {
  560. mdui.snackbar({
  561. message: `文件删除失败:${data.message}`
  562. });
  563. deleteButton.classList.remove('loading');
  564. }
  565. } catch (e) {
  566. console.error('解析响应时出错:', e);
  567. }
  568. },
  569. onerror: function (error) {
  570. console.error('删除文件请求错误:', error);
  571. }
  572. });
  573. }
  574.  
  575. function openFile() {
  576. if (!isLoggedIn) {
  577. mdui.snackbar({
  578. message: `请先登录!`
  579. });
  580. return;
  581. }
  582.  
  583. GM_xmlhttpRequest({
  584. method: 'GET',
  585. url: `http://api.mkc.icu/files?token=${encodeURIComponent(token)}`,
  586. headers: {
  587. 'Content-Type': 'application/json',
  588. },
  589. onload: function (response) {
  590. try {
  591. unsafeWindow.stdoutEditor.setValue("当前文件:");
  592. var data = JSON.parse(response.responseText);
  593. if (data.files && data.files.length > 0) {
  594. data.files.forEach(filename => {
  595. unsafeWindow.stdoutEditor.setValue(unsafeWindow.stdoutEditor.getValue() + "\n - " + filename);
  596. });
  597. unsafeWindow.stdoutEditor.setValue(unsafeWindow.stdoutEditor.getValue() + '\n输入文件名称加载。');
  598. } else {
  599. mdui.snackbar({
  600. message: `你还没有保存过文件......`
  601. });
  602. }
  603. } catch (e) {
  604. console.error('解析响应时出错:', e);
  605. }
  606. },
  607. onerror: function (error) {
  608. console.error('打开文件请求错误:', error);
  609. }
  610. });
  611. }
  612.  
  613. function loadFile(filename) {
  614. openButton.classList.add('loading');
  615. GM_xmlhttpRequest({
  616. method: 'GET',
  617. url: `http://api.mkc.icu/files/${filename}?token=${encodeURIComponent(token)}`,
  618. onload: function (response) {
  619. var data = JSON.parse(response.responseText);
  620. unsafeWindow.sourceEditor.setValue(data.file); // 将文件内容加载到编辑器中
  621. title.innerText = filename + ".cpp";
  622. openButton.classList.remove('loading');
  623. document.title = filename + " - EYanIDE"
  624. updateUI();
  625. },
  626. onerror: function (error) {
  627. console.error('Error:', error);
  628. openButton.classList.remove('loading');
  629. }
  630. });
  631. }
  632.  
  633. openFile();
  634.  
  635. function logout() {
  636. token = null;
  637. localStorage.removeItem('token');
  638. isLoggedIn = false;
  639. Gusername = '';
  640. localStorage.removeItem('username');
  641. updateUI();
  642. mdui.snackbar({
  643. message: `已注销`
  644. });
  645. }
  646.  
  647. updateUI();
  648. })();