您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Parse AtCoder problem statement into sections
当前为
// ==UserScript== // @name spoiled competitive programming // @namespace http://tampermonkey.net/ // @version 0.2 // @description Parse AtCoder problem statement into sections // @author Harui (totally helped by GPT-4o) // @match https://atcoder.jp/contests/*/tasks/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Create buttons for Japanese const openMarkdownButtonJa = document.createElement('button'); openMarkdownButtonJa.textContent = '新しいタブで日本語のMarkdownを開く'; openMarkdownButtonJa.style.position = 'fixed'; openMarkdownButtonJa.style.left = '10px'; openMarkdownButtonJa.style.bottom = '145px'; openMarkdownButtonJa.style.zIndex = '1000'; openMarkdownButtonJa.style.padding = '10px'; openMarkdownButtonJa.style.backgroundColor = '#4CAF50'; openMarkdownButtonJa.style.color = 'white'; openMarkdownButtonJa.style.border = 'none'; openMarkdownButtonJa.style.borderRadius = '5px'; openMarkdownButtonJa.style.cursor = 'pointer'; const openHtmlButtonJa = document.createElement('button'); openHtmlButtonJa.textContent = '新しいタブで日本語のHTMLを開く'; openHtmlButtonJa.style.position = 'fixed'; openHtmlButtonJa.style.left = '10px'; openHtmlButtonJa.style.bottom = '100px'; openHtmlButtonJa.style.zIndex = '1000'; openHtmlButtonJa.style.padding = '10px'; openHtmlButtonJa.style.backgroundColor = '#4CAF50'; openHtmlButtonJa.style.color = 'white'; openHtmlButtonJa.style.border = 'none'; openHtmlButtonJa.style.borderRadius = '5px'; openHtmlButtonJa.style.cursor = 'pointer'; // Append the buttons to the body document.body.appendChild(openMarkdownButtonJa); document.body.appendChild(openHtmlButtonJa); // Event listener for open Markdown button (Japanese) openMarkdownButtonJa.addEventListener('click', () => { const markdownContent = htmlToMarkdown(extractHtml('ja')); // Open the Markdown content in a new tab const newTab = window.open(); newTab.document.open(); newTab.document.write('<pre>' + markdownContent + '</pre>'); newTab.document.close(); }); // Event listener for open HTML button (Japanese) openHtmlButtonJa.addEventListener('click', () => { const htmlContent = htmlToAnkiHtml(extractHtml('ja')); // Open the HTML content in a new tab const newTab = window.open(); newTab.document.open(); newTab.document.write(htmlContent); newTab.document.close(); }); // Create buttons and style them const openMarkdownButtonEn = document.createElement('button'); openMarkdownButtonEn.textContent = 'Open English Markdown in New Tab'; openMarkdownButtonEn.style.position = 'fixed'; openMarkdownButtonEn.style.left = '10px'; openMarkdownButtonEn.style.bottom = '55px'; openMarkdownButtonEn.style.zIndex = '1000'; openMarkdownButtonEn.style.padding = '10px'; openMarkdownButtonEn.style.backgroundColor = '#4CAF50'; openMarkdownButtonEn.style.color = 'white'; openMarkdownButtonEn.style.border = 'none'; openMarkdownButtonEn.style.borderRadius = '5px'; openMarkdownButtonEn.style.cursor = 'pointer'; const openHtmlButtonEn = document.createElement('button'); openHtmlButtonEn.textContent = 'Open English HTML in New Tab'; openHtmlButtonEn.style.position = 'fixed'; openHtmlButtonEn.style.left = '10px'; openHtmlButtonEn.style.bottom = '10px'; openHtmlButtonEn.style.zIndex = '1000'; openHtmlButtonEn.style.padding = '10px'; openHtmlButtonEn.style.backgroundColor = '#4CAF50'; openHtmlButtonEn.style.color = 'white'; openHtmlButtonEn.style.border = 'none'; openHtmlButtonEn.style.borderRadius = '5px'; openHtmlButtonEn.style.cursor = 'pointer'; // Append the buttons to the body document.body.appendChild(openMarkdownButtonEn); document.body.appendChild(openHtmlButtonEn); // Function to extract English parts and remove Katex, returning HTML function extractHtml(lang) { console.log(lang); const englishParts = document.querySelectorAll(`span.lang-${lang}`); const problemTitle = document.title; let htmlContent = `<h1>${problemTitle}</h1>\n\n`; englishParts.forEach(part => { // Clone the part to avoid modifying the original document const clone = part.cloneNode(true); // Remove "Copy" buttons const copyButtons = clone.querySelectorAll('.btn-copy, .btn-pre, .div-btn-copy'); copyButtons.forEach(button => button.remove()); // Remove Katex elements const katexElements = clone.querySelectorAll('.katex'); katexElements.forEach(katex => { const tex = katex.querySelector('.katex-mathml annotation'); if (tex) { const textNode = document.createTextNode(tex.textContent); katex.parentNode.replaceChild(textNode, katex); } }); // Append HTML content htmlContent += clone.outerHTML + '\n\n'; }); return htmlContent; } // Event listener for open Markdown button openMarkdownButtonEn.addEventListener('click', () => { const markdownContent = htmlToMarkdown(extractHtml('en')); // Open the Markdown content in a new tab const newTab = window.open(); newTab.document.open(); newTab.document.write('<pre>' + markdownContent + '</pre>'); newTab.document.close(); }); // Event listener for open HTML button openHtmlButtonEn.addEventListener('click', () => { const htmlContent = extractHtml('en'); // Open the HTML content in a new tab const newTab = window.open(); newTab.document.open(); newTab.document.write(htmlContent); newTab.document.close(); }); // Function to convert HTML to Markdown function htmlToMarkdown(html) { // Simple conversion rules const rules = [ { regex: /<h3>(.*?)<\/h3>/g, replacement: '\n### $1\n' }, { regex: /<h2>(.*?)<\/h2>/g, replacement: '\n## $1\n' }, { regex: /<h1>(.*?)<\/h1>/g, replacement: '\n# $1\n' }, { regex: /<p>(.*?)<\/p>/g, replacement: '$1\n' }, { regex: /<ul>(.*?)<\/ul>/gs, replacement: '$1' }, { regex: /<li>(.*?)<\/li>/g, replacement: '- $1' }, { regex: /<pre.*?>(.*?)<\/pre>/gs, replacement: '\n\n``` \n$1\n```' }, { regex: /<var>(.*?)<\/var>/g, replacement: '`$1`' }, { regex: /<div.*?>(.*?)<\/div>/gs, replacement: '$1' }, { regex: /<span.*?>(.*?)<\/span>/g, replacement: '$1' }, { regex: /<section.*?>(.*?)<\/section>/gs, replacement: '$1' }, { regex: /<hr>/g, replacement: '---' }, { regex: /<br>/g, replacement: '\n' } ]; // Apply rules let markdown = html; rules.forEach(rule => { markdown = markdown.replace(rule.regex, rule.replacement); }); // Remove any remaining HTML tags markdown = markdown.replace(/<\/?[^>]+(>|$)/g, ""); return markdown.trim(); } // Function to convert HTML to Anki HTML function htmlToAnkiHtml(html) { // Simple conversion rules const rules = [ { regex: /<h3>(.*?)<\/h3>/g, replacement: '\n<h3>$1</h3>\n' }, { regex: /<h2>(.*?)<\/h2>/g, replacement: '\n<h2>$1</h2>\n' }, { regex: /<h1>(.*?)<\/h1>/g, replacement: '\n<h1>$1</h1>\n' }, { regex: /<p>(.*?)<\/p>/g, replacement: '<p>$1</p>\n' }, { regex: /<ul>(.*?)<\/ul>/gs, replacement: '$1' }, { regex: /<li>(.*?)<\/li>/g, replacement: '<li>$1</li>' }, { regex: /<pre.*?>(.*?)<\/pre>/gs, replacement: '\n\n<pre>\n$1\n</pre>' }, { regex: /<var>(.*?)<\/var>/g, replacement: '<var>$1</var>' }, { regex: /<div.*?>(.*?)<\/div>/gs, replacement: '<div>$1</div>' }, { regex: /<span.*?>(.*?)<\/span>/g, replacement: '<span><anki-mathjax>$1</anki-mathjax></span>' }, { regex: /<section.*?>(.*?)<\/section>/gs, replacement: '<section>$1</section>' }, { regex: /<hr>/g, replacement: '<hr>' }, { regex: /<br>/g, replacement: '<br>' }, { regex: /\$(.*?)\$/g, replacement: '$1' } // Convert TeX to Anki TeX ]; // Apply rules let ankiHtml = html; rules.forEach(rule => { ankiHtml = ankiHtml.replace(rule.regex, rule.replacement); }); return ankiHtml.trim(); } })();