Parse AtCoder problem statement into sections
目前為
// ==UserScript==
// @name spoiled competitive programming
// @namespace http://tampermonkey.net/
// @version 0.1
// @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 and style them
const downloadButton = document.createElement('button');
downloadButton.textContent = 'Download English Markdown';
downloadButton.style.position = 'fixed';
downloadButton.style.left = '10px';
downloadButton.style.bottom = '90px';
downloadButton.style.zIndex = '1000';
downloadButton.style.padding = '10px';
downloadButton.style.backgroundColor = '#4CAF50';
downloadButton.style.color = 'white';
downloadButton.style.border = 'none';
downloadButton.style.borderRadius = '5px';
downloadButton.style.cursor = 'pointer';
const openMarkdownButton = document.createElement('button');
openMarkdownButton.textContent = 'Open English Markdown in New Tab';
openMarkdownButton.style.position = 'fixed';
openMarkdownButton.style.left = '10px';
openMarkdownButton.style.bottom = '50px';
openMarkdownButton.style.zIndex = '1000';
openMarkdownButton.style.padding = '10px';
openMarkdownButton.style.backgroundColor = '#4CAF50';
openMarkdownButton.style.color = 'white';
openMarkdownButton.style.border = 'none';
openMarkdownButton.style.borderRadius = '5px';
openMarkdownButton.style.cursor = 'pointer';
const openHtmlButton = document.createElement('button');
openHtmlButton.textContent = 'Open English HTML in New Tab';
openHtmlButton.style.position = 'fixed';
openHtmlButton.style.left = '10px';
openHtmlButton.style.bottom = '10px';
openHtmlButton.style.zIndex = '1000';
openHtmlButton.style.padding = '10px';
openHtmlButton.style.backgroundColor = '#4CAF50';
openHtmlButton.style.color = 'white';
openHtmlButton.style.border = 'none';
openHtmlButton.style.borderRadius = '5px';
openHtmlButton.style.cursor = 'pointer';
// Append the buttons to the body
document.body.appendChild(downloadButton);
document.body.appendChild(openMarkdownButton);
document.body.appendChild(openHtmlButton);
// Function to extract English parts and remove Katex, returning HTML
function extractHtml() {
const englishParts = document.querySelectorAll('span.lang-en');
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 download button
downloadButton.addEventListener('click', () => {
const markdownContent = htmlToMarkdown(extractHtml());
// Create a blob and download the Markdown file
const blob = new Blob([markdownContent], { type: 'text/markdown' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'atcoder_english_extract.md';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
});
// Event listener for open Markdown button
openMarkdownButton.addEventListener('click', () => {
const markdownContent = htmlToMarkdown(extractHtml());
// 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
openHtmlButton.addEventListener('click', () => {
const htmlContent = extractHtml();
// 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();
}
})();