(function () { addEventListener("DOMContentLoaded", async function () { let inherits = []; await refactorDocument(this.document, new Set(), inherits, new Set()); mergeInherits(inherits); }); // * `doc` - The document, can be this.document or a fetched doc. // * `propertiesSet` - Tracks property name overrides. // * `inherits` - Array of `{ link, page }`, link is HTML str of the parent link. // * `fetchUrls` - Set of fetch URLs, used to avoid infinite recursion. async function refactorDocument(doc, propertiesSet, inherits, fetchUrls) { refactorSections(doc, propertiesSet, fetchUrls); refactorSidebar(doc, propertiesSet); // fetch inherit docs and refactorDocument await fetchInherits(doc, propertiesSet, inherits, fetchUrls); } function refactorSections(doc, propertiesSet, fetchUrls) { refactorProperties(doc, propertiesSet, 'implementations'); doc.querySelectorAll('h2').forEach(function (d) { if (d.id.startsWith('deref-methods')) { let skipFirst = true; let insertPoint = d.nextElementSibling.nextElementSibling; d.querySelectorAll('a.struct').forEach(function (a) { if (skipFirst) { skipFirst = false; return; } if (fetchUrls.has(a.href)) { return; } fetchUrls.add(a.href); // unloaded mixin parent let title = doc.createElement('h2'); title.innerHTML = 'Inherits from ' + a.outerHTML; title.classList.add('inherit-fetch'); insertPoint.parentElement.insertBefore(title, insertPoint); let section = doc.createElement('div'); section.innerText = 'Loading...'; insertPoint.parentElement.insertBefore(section, insertPoint); insertPoint = section.nextElementSibling; a.remove(); }); refactorProperties(doc, propertiesSet, d.id); } }); } function refactorProperties(doc, propertiesSet, sectionId) { let implementations = doc.getElementById(sectionId); if (implementations == null) { return; } let implementationsList = implementations.nextSibling; let isDeref = implementations.innerHTML.indexOf("Methods from") !== -1; let derefFrom = ''; let derefIdPrefix = ''; if (isDeref) { let mixCut = sectionId.indexOf('%3C'); if (mixCut !== -1) { sectionId = sectionId.substring(0, mixCut); } derefIdPrefix = sectionId.replace('deref-methods', ''); let structA = implementations.querySelector('span a:nth-of-type(2)').outerHTML; derefFrom = ' from ' + structA; implementations.id = sectionId; implementations.innerHTML = "Methods from " + structA + '§'; } let properties = doc.createElement('h2'); properties.id = 'properties' + derefIdPrefix; properties.classList.add('small-section-header'); properties.innerHTML = 'Properties' + derefFrom + '§'; let propertiesList = doc.createElement('div'); propertiesList.id = 'properties' + derefIdPrefix + '-list'; // insert property sections before first impl sections. let insertPoint = doc.querySelector('#properties-insert-pt'); if (insertPoint == null) { insertPoint = doc.createElement('div'); insertPoint.id = 'properties-insert-pt'; implementations.parentElement.insertBefore(insertPoint, implementations); } insertPoint.parentElement.insertBefore(propertiesList, insertPoint); insertPoint.parentElement.insertBefore(properties, propertiesList); propertiesList.innerHTML = "
"; propertiesList = propertiesList.firstChild; implementationsList.querySelectorAll("details.method-toggle").forEach(function (e) { let t = e.querySelector("strong[data-tag='P'],strong[data-tag='c']"); if (t != null) { let mtdAnchor = e.querySelector('a.fn'); let propertyName = mtdAnchor.innerText; if (propertiesSet.has(propertyName)) { // override e.remove(); } else { propertiesSet.add(propertyName); t.remove(); let mtdSignature = mtdAnchor.parentElement; // same syntax as `widget_impl!` mtdSignature.innerHTML = mtdSignature.innerHTML .replace('fn ', '') .replace('
    &self,', '') .replace('&self, ', '') + ';'; propertiesList.appendChild(e); } } }); // remove empty sections if (implementationsList.querySelector("section.method") == null) { implementationsList.remove(); implementations.remove(); } else { implementationsList.querySelectorAll("details.implementors-toggle").forEach(function (e) { if (e.querySelector("section.method") == null) { e.remove(); } }); } } function refactorSidebar(doc, propertiesSet) { let sideBar = doc.querySelector('div.sidebar-elems section'); let repeats = new Set(); sideBar.querySelectorAll('h3').forEach(function (e) { if (e.innerText == "Methods" || e.innerText.indexOf("Methods from") !== -1) { e.firstChild.innerText = e.firstChild.innerText.replace('Deref', ''); let mixGenericsCut = e.firstChild.innerText.indexOf('<'); if (mixGenericsCut !== -1) { e.firstChild.innerText = e.firstChild.innerText.substring(0, mixGenericsCut); mixGenericsCut = e.firstChild.href.indexOf('%3C'); if (mixGenericsCut !== -1) { e.firstChild.href = e.firstChild.href.substring(0, mixGenericsCut); } } let mtdList = e.nextSibling; let propList = doc.createElement('ul'); mtdList.querySelectorAll('a').forEach(function (a) { if (propertiesSet.has(a.innerText)) { if (repeats.has(a.innerText)) { a.remove(); } else { repeats.add(a.innerText); propList.appendChild(a.parentElement); } } }); // insert property sections before first impl sections. // used here and by `mergeInherits` let insertPoint = doc.querySelector('#properties-side-insert-pt'); if (insertPoint == null) { insertPoint = doc.createElement('div'); insertPoint.id = 'properties-side-insert-pt'; sideBar.insertBefore(insertPoint, e); } if (propList.hasChildNodes()) { propList.classList.add('block'); let title = doc.createElement('h3'); let mtdsFrom = e.querySelector('a').href.indexOf('#deref-methods-'); if (mtdsFrom !== -1) { let parentName = e.innerText.substring("Methods from ".length); title.innerHTML = 'Properties from ' + parentName + ''; } else { title.innerHTML = 'Properties'; } sideBar.insertBefore(title, insertPoint); sideBar.insertBefore(propList, insertPoint); if (!mtdList.hasChildNodes()) { mtdList.remove(); e.remove(); } } } }); } async function fetchInherits(doc, propertiesSet, inherits, fetchUrls) { for (e of doc.querySelectorAll('h2.inherit-fetch')) { let page; let url = e.querySelector('a').href; let place = e.nextElementSibling; try { page = await fetch(url, { redirect: 'follow' }); if (!page.ok) { throw page.statusText; } var parser = new DOMParser(); if (page.redirected) { url = page.url; } page = parser.parseFromString(await page.text(), 'text/html'); let refresh = page.head.querySelector("meta[http-equiv='refresh']"); if (refresh != null && refresh.content.startsWith('0;URL=')) { url = refresh.content.replace('0;URL=', ''); page = await fetch(url, { redirect: 'follow' }); if (!page.ok) { throw page.statusText; } url = page.url; var parser = new DOMParser(); page = parser.parseFromString(await page.text(), 'text/html'); } } catch (error) { console.error("error fetching '" + url + "', " + error); place.innerText = error; continue; } e.classList.remove('inherit-fetch'); let link = e.querySelector('a').outerHTML; inherits.push({ link, page, url }); await refactorDocument(page, propertiesSet, inherits, fetchUrls); place.remove(); e.remove(); } } function mergeInherits(inherits) { let insertPoint = this.document.getElementById("properties-insert-pt"); let sideInsertPoint = this.document.getElementById("properties-side-insert-pt"); let insertedDocs = []; inherits.forEach(function (e) { // merge properties let side = e.page.querySelector('.sidebar-elems'); let parentProps = e.page.getElementById('properties'); if (parentProps != null) { let title = this.document.createElement('h2'); title.classList.add("small-section-header"); title.innerHTML = e.link; let name = title.querySelector('a').innerText; title.id = 'properties-' + name; title.innerHTML = "Properties from " + e.link + '§'; parentProps.nextElementSibling.id = title.id + "-list"; insertedDocs.push({ url: e.url, el: parentProps.nextElementSibling, }); insertPoint.parentElement.insertBefore(title, insertPoint); insertPoint.parentElement.insertBefore(parentProps.nextElementSibling, insertPoint); let sideTitle = side.querySelector('h3'); let sideTitleA = sideTitle.querySelector('a'); sideTitleA.innerText = title.innerText; sideTitleA.href = '#properties-' + name; let sideList = side.querySelector('ul'); sideInsertPoint.parentElement.insertBefore(sideTitle, sideInsertPoint); sideInsertPoint.parentElement.insertBefore(sideList, sideInsertPoint); } e.page.querySelectorAll('h2.small-section-header').forEach(function (e) { if (e.id.indexOf('properties-') !== -1) { let list = e.nextElementSibling; insertPoint.parentElement.insertBefore(e, insertPoint); insertPoint.parentElement.insertBefore(list, insertPoint); } }); side.querySelectorAll('h3').forEach(function (e) { if (e.querySelector('a').href.indexOf('#properties-') !== -1) { let sideList = e.nextElementSibling; sideInsertPoint.parentElement.insertBefore(e, sideInsertPoint); sideInsertPoint.parentElement.insertBefore(sideList, sideInsertPoint); } }); // merge methods let methodsInsertPoint = null; this.document.querySelectorAll('h2.small-section-header').forEach(function (e) { if (e.id.indexOf('deref-methods-') !== -1) { methodsInsertPoint = e; } }); if (methodsInsertPoint === null) { let impls = this.document.getElementById('implementations'); if (impls !== null) { methodsInsertPoint = impls.nextElementSibling.nextElementSibling; } else { methodsInsertPoint = insertPoint.nextElementSibling; } } else { methodsInsertPoint = methodsInsertPoint.nextElementSibling.nextElementSibling; } let methodsSideInsertPoint = null; sideInsertPoint.parentElement.querySelectorAll('h3').forEach(function (e) { let href = e.querySelector('a').href; if (href.indexOf('#deref-methods-') !== -1 || href.indexOf('#implementations') !== -1) { methodsSideInsertPoint = e; } }); if (methodsSideInsertPoint === null) { methodsSideInsertPoint = sideInsertPoint.nextElementSibling; } else { methodsSideInsertPoint = methodsSideInsertPoint.nextElementSibling.nextElementSibling; } let parentMethods = e.page.getElementById('implementations'); if (parentMethods != null) { let title = this.document.createElement('h2'); title.classList.add("small-section-header"); title.innerHTML = e.link; let name = title.querySelector('a').innerText; title.id = 'deref-methods-' + name; title.innerHTML = "Methods from " + e.link + '§'; let mtdList = this.document.createElement('div'); mtdList.classList.add("impl-items"); let mtdNames = new Set(); parentMethods.nextElementSibling.querySelectorAll('details.method-toggle').forEach(function (e) { let mtd = e.querySelector('h4').innerText; if (mtd.indexOf('&self') !== -1 || mtd.indexOf('&mut self') !== -1) { mtdNames.add(e.querySelector('h4 a').innerText); mtdList.appendChild(e); } }); if (mtdNames.size > 0) { methodsInsertPoint.parentElement.insertBefore(title, methodsInsertPoint); methodsInsertPoint.parentElement.insertBefore(mtdList, methodsInsertPoint); insertedDocs.push({ url: e.url, el: mtdList, }); let sideList = side.querySelector('a[href="#implementations"]').parentElement.nextElementSibling; sideList.querySelectorAll('a').forEach(function (a) { if (!mtdNames.has(a.innerText)) { a.parentElement.remove(); } }); let sideTitle = this.document.createElement('h3'); sideTitle.innerHTML = 'Methods from ' + name + ''; methodsSideInsertPoint.parentElement.insertBefore(sideTitle, methodsSideInsertPoint); methodsSideInsertPoint.parentElement.insertBefore(sideList, methodsSideInsertPoint); } } e.page.querySelectorAll('h2.small-section-header').forEach(function (e) { if (e.id.indexOf('deref-methods-') !== -1) { let list = e.nextElementSibling; methodsInsertPoint.parentElement.insertBefore(e, methodsInsertPoint); methodsInsertPoint.parentElement.insertBefore(list, methodsInsertPoint); } }); side.querySelectorAll('h3').forEach(function (e) { if (e.querySelector('a').href.indexOf('#deref-methods-') !== -1) { let sideList = e.nextElementSibling; methodsSideInsertPoint.parentElement.insertBefore(e, methodsSideInsertPoint); methodsSideInsertPoint.parentElement.insertBefore(sideList, methodsSideInsertPoint); } }); }); insertedDocs.forEach(function (e) { e.el.querySelectorAll('a').forEach(function (a) { let href_str = a.getAttribute('href'); if (!href_str.startsWith('#') || this.document.getElementById(href_str.slice(1)) === null) { let url = new URL(href_str, e.url); a.setAttribute('href', url.href); } }); }); document.querySelectorAll("div[id^='properties-']").forEach(function (e) { if (e.id.startsWith("properties-") && e.id.endsWith("-list") && e.querySelector('a') === null) { e.previousSibling.remove(); e.remove(); } }); } })();