Makes the new SPAified C2 Wiki behave more like an ordinary website.
// ==UserScript==
// @name C2 Wiki Classic Edition
// @description Makes the new SPAified C2 Wiki behave more like an ordinary website.
// @version 1
// @grant GM.info
// @run-at document-start
// @match *://wiki.c2.com/
// @match *://wiki.c2.com/?*
// @license MIT
// @namespace https://greasyfork.org/users/833386
// ==/UserScript==
const tab2spaces = s => s.replace(/\t/g, " ")
String.prototype.replaceFunction = function(head, replacement) {
return this.replace(
new RegExp(`^((\\s*)${head.replace(/[.()]/g, '\\$&')} {)[\\S\\s]*?^\\2}`, 'm'),
(match, p1, p2) =>
p1 + tab2spaces(replacement).split('\n').map(line => p2 + line).join('\n') + "}"
)
}
const patch = s => tab2spaces(` const [
serialisePage,
deserialisePage
] = (() => {
const s = new XMLSerializer()
const p = new DOMParser()
return [
e => s.serializeToString(e),
es => p.parseFromString(es, "text/html").querySelector(".page")
]
})()`) + s.replaceFunction("try", `
[names, index, json] = await Promise.all([
fetch('names.txt').then(res => res.text()).then(text => text.split(/\\r?\\n/)),
fetch('c2-fed-index.json').then(res => res.json()),
fetch(database+title).then(res => res.json())
])
options.names = names
let page = rendered(title,json)
history.replaceState(serialisePage(page), null)
window.tab.insertBefore(page,null)
`).replaceFunction("window.onpopstate = async function(event)", `
if (event.state)
document.querySelector(".page").replaceWith(deserialisePage(event.state))
else
history.go(-1)
`).replaceFunction("async function internallinks(event)", `
const t = event.target
if (t.tagName !== 'A' || t.getAttribute('target') || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)
return
event.preventDefault()
const href = t.getAttribute('href'),
title = href.split('?').slice(-1)[0],
json = await fetch(database+title).then(res => res.json()),
page = rendered(title, json)
history.pushState(serialisePage(page),'',href)
document.querySelector(".page").replaceWith(page)
`)
let didPatch = false
document.addEventListener('readystatechange', e => {
if (!didPatch && document.readyState === "complete") {
let oops = document.createElement("div")
oops.style.cssText = "color: oldlace; background-color: maroon; position: absolute; z-index: 4"
oops.innerHTML = `
The script ${GM.info.script.name} has failed to perform its primary function.<br/>
This, in all likelihood, means that the front end of the C2 wiki has been overhauled.<br/>
You are welcome to write to <code>userscripts AT ylh DOT io</code> and ask for a fix.`
document.body.prepend(oops)
}
})
document.addEventListener('beforescriptexecute', e => {
const script = e.target
if (!script.matches('script[type="module"]:not(.greasy)'))
return
const html = script.innerHTML
if ((s => {
let h = 0, high = 0
for (let i = 0; i < s.length; i++) {
h = (h << 4) + s.charCodeAt(i)
if (high = h & 0xF0000000)
h ^= high >> 24
h &= ~high
}
return h
})(html) !== 0x086E878A) {
return
}
e.stopPropagation()
e.preventDefault()
const p = script.parentElement,
newModule = patch(html),
newScript = document.createElement('script')
script.remove()
newScript.setAttribute('type', "module")
newScript.classList.add("greasy")
newScript.innerHTML = newModule
p.appendChild(newScript)
const newStyle = document.createElement("style")
newStyle.innerHTML = ".page { all: initial; }"
document.head.querySelector('link[rel="stylesheet"]').after(newStyle)
didPatch = true
});