Codeforces_spoiler_tutorial

Wrap spoilers in Codeforces tutorial in spoiler blocks

Per 15-05-2020. Zie de nieuwste versie.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==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 });



})()