Codeforces_spoiler_tutorial

Wrap spoilers in Codeforces tutorial in spoiler blocks

Устаревшая версия за 15.05.2020. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Codeforces_spoiler_tutorial
// @version      0.1.0
// @description  Wrap spoilers in Codeforces tutorial in spoiler blocks
// @match        *://codeforces.com/blog/entry/*
// @match        *://codeforces.com/blog/entry/*
// @match        *://codeforces.com/contest/*
// @grant        GM_getValue
// @grant        GM_setValue
// @run-at       document-start
// @namespace    https://greasyfork.org/users/410786
// ==/UserScript==

(function(){

if(location.pathname.startsWith("/contest/")){
	window.addEventListener("DOMContentLoaded", function(){
		// Stores tutorial links. Sometimes it's not linked in some old contests, see  https://codeforces.com/blog/entry/7749?locale=en
		for(const element of document.querySelectorAll(".roundbox ul li a[href*='/blog/entry/'"))
			if(element.innerText.match(/Tutorial|Разбор задач/))
				GM_setValue("isTutorial"+element.href.match(/\/blog\/entry\/(\d+)/)[1], true)
	})
	return
}



function wrappedInSpoiler(node){
	while(node!==null){
		if(node.classList && node.classList.contains("spoiler")) return true;
		node=node.parentNode;
	}
	return false;
}

var newStyle=false

function wrapInSpoiler(nodes, spoilerTitle){
	if(!Array.isArray(nodes)) nodes=[nodes]
	if(nodes.length==0) return

	const spoilerElement=document.createElement("div")
	spoilerElement.classList.add("spoiler")
	spoilerElement.innerHTML='<b class="spoiler-title"></b><div class="spoiler-content" style="display: none;"></div>'
	spoilerElement.firstElementChild.innerText=spoilerTitle

	console.log("Wrapping in spoiler: ", nodes)
	//nodes[0].insertAdjacentElement('beforebegin', spoilerElement);
	nodes[0].parentNode.insertBefore(spoilerElement, nodes[0]);
	nodes.forEach(function(node){
		spoilerElement.lastElementChild.appendChild(node) // "If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position"
	})
}

function wrapOldStyle(){
	//const headerSelector="h2,h3,a[href^='/contest'][href*='/problem/']"
	const headerSelector="h2,h3,hr"
	for(const element of document.getElementsByClassName("content")[0].querySelectorAll(headerSelector)){
		const elements=[]
		let tmp=element.nextSibling
		console.log(tmp)
		while(tmp!==null && ((tmp instanceof Text) || !tmp.matches(headerSelector))){
			elements.push(tmp)
			tmp=tmp.nextSibling
		console.log(tmp)
		}
		wrapInSpoiler(elements, "Tutorial")
	}
}

const observer=new MutationObserver(function(mutationList, observer){
	for(const mutation of mutationList){
		for(const node of mutation.addedNodes){
			if(node instanceof Element && node.matches("div.roundbox.meta")){
				console.log("Detect meta box", "isTutorial"+location.href.match(/\/blog\/entry\/(\d+)/)[1])
				if(GM_getValue("isTutorial"+location.href.match(/\/blog\/entry\/(\d+)/)[1])){
					if(!newStyle) wrapOldStyle()
				}
				observer.disconnect()
				return
			}

			if(
				node.tagName==="SPAN" && node.style.padding==="0px 0.35em" &&
				node.firstChild instanceof Text &&
				["Tutorial of ", "Разбор задач "].includes(node.firstChild.nodeValue)
				//node.previousElementSibling.tagName==="IMG" && node.previousElementSibling.src.includes("paperclip")
			){
				if(!newStyle) wrapOldStyle()
				observer.disconnect()
				return
			}

			if(node.classList!==undefined && node.classList.contains("problemTutorial")){
				newStyle=true
				if(!wrappedInSpoiler(node)){
					var spoilerTitle='Tutorial'
					const problemcode=node.getAttribute("problemcode")
					if(problemcode) spoilerTitle+=' - '+problemcode

					wrapInSpoiler(node, spoilerTitle)
				}
			}
		}
	}
})
observer.observe(document, { childList: true, subtree: true });



})()