CINXE.COM
<html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="favicon.gif"> <link rel="stylesheet" href="style.css"> </head> <body> <noscript> <center> <b>notice</b> <p>javascript required to view this site</p> <b>why</b> <p>measured improvement in server performance</p> <p>awesome incremental search</p> </center> </noscript> <div id=tab> <img src="spin.gif"> <p>This site uses features not available in older browsers.</a></p> </div> <script type=module> const uniq = (value, index, self) => self.indexOf(value) === index // L A U N C H let names = [] let index = {} let json = {} let inlinks = [] let infetch = fetch('inlinks.json').then(res => res.json()) let title = (location.search.match(/\w+/)||["WelcomeVisitors"])[0] let database = 'https://c2.com/wiki/remodel/pages/' let options = {titlesearch, fullsearch} window.tab.innerHTML = '' import {markup} from "./markup.js" import {hex_md5} from "./md5.js" 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) let style = `left: 0px; top: 0px; position: absolute;` page.setAttribute('style',style) window.tab.insertBefore(page,null) history.pushState({title,style},'',location.href) } catch (err) { trouble(err.message) window.tab.innerHTML = `page does not exist` } function trouble (msg) { console.error('trouble', msg) } // L O O P window.tab.addEventListener('click', internallinks) window.onpopstate = async function(event) { if (event.state) { let title = event.state.title let style = event.state.style let keep = window.tab.querySelector(`.page[data-title='${title}'][style='${style}']`) if (keep) { while(keep.nextElementSibling) { keep.nextSibling.remove() } } else { json = await fetch(database+title).then(res => res.json()) let page = rendered(title,json) page.setAttribute('style',style) window.tab.insertBefore(page,null) } } else { history.go(-1) } } async function internallinks(event) { if (event.target.tagName === 'A' && !event.target.getAttribute('target')) { event.preventDefault() let href = event.target.getAttribute('href') let title = href.split('?').slice(-1)[0] json = await fetch(database+title).then(res => res.json()) let page = rendered(title,json) page.style.left = event.pageX page.style.top = event.pageY page.style.position = 'absolute' let style = page.getAttribute('style') window.tab.insertBefore(page,null) history.pushState({title, style},'',href) } else { let keep = event.target.closest('.page') if (keep) { while(keep.nextElementSibling) { keep.nextSibling.remove() } } } } function rendered(title,json) { let div = document.createElement('div') div.innerHTML = render(title,json) return div.firstChild } function render(title,json) { if (Object.keys(json).length == 0) { trouble('Page unavailable until conversion completed.') } else { if (title == 'RandomPages') { const anyname = () => '*'+names[Math.floor(Math.random()*names.length)] json.text = json.text.replace(/\*\w+/g, anyname) } return `<div class="page" data-title="${title}">${head(title) + markup(json.text,options) + foot(json)}</div>` } } // F E A T U R E S window.inlinks = async function (e) { e.stopPropagation() let title = e.target.closest('.page').dataset.title const link = text => `<a href=?${text}>${text}</a>` if(!inlinks.length) {inlinks = await infetch} let report = e.target.parentNode.parentNode.nextSibling if (!report.innerHTML) { let found = inlinks[names.indexOf(title)].map(link => names[link]) report.innerHTML = `<p>${found.map(link).join('<br>')}</p>` } else { report.innerHTML = '' } } function excerptlink(name) { // [siten,slugn,titlen,md5wn,pagen] let pagen = index.pages.indexOf(name) let row = index.rows[index.rows.findIndex(row => row[4] == pagen)] let site = index.sites[row[0]] let title = index.titles[row[2]] let url = `http://${site}` let done = new Set() for (let row of index.rows.filter(row => row[4] == pagen)) { let site2 = index.sites[row[0]] let slug2 = index.slugs[row[1]] if (done.has(site2+slug2)) continue url += `/${site2 == site ? 'view' : site2}/${slug2}` done.add(site2+slug2) } return `<p>See fedwiki's <a href="${url}" target=_blank>${title}</a><p>` } function head(title) { let words = document.title = title.replace(/([a-z])([A-Z])/g, '$1 $2'); let menu = ` <button onclick=doexcerpts(event)>excerpted pages</button> <button onclick=doexport(event)>export to fedwiki</button>` return [ '<h1><img src="https://c2.com/sig/wiki.gif"><div>', `<span style="color:blue;cursor: pointer;" onclick=inlinks(event)>${words}</span>`, '</div></h1><div></div>', (title == 'WelcomeVisitors' ? `<p>${menu}</p><div></div>` : ''), (index.pages.includes(title) ? excerptlink(title) : '') ].join('') } function foot(json) { return [ '<hr>Last edit ', json.date ].join('') } window.doexcerpts = async function(e) { const link = text => `<a href=?${text}>${text}</a>` let report = e.target.parentNode.nextSibling if (!report.innerHTML) { report.innerHTML = `<p>${index.pages.slice().sort().map(link).join('<br>')}</p>` } else { report.innerHTML = '' } } window.doexport = async function(e) { e.stopPropagation() const asSlug = (title) => title.replace(/\s/g, '-').replace(/[^A-Za-z0-9-]/g, '').toLowerCase() let exports = {} let heads = window.tab.querySelectorAll('.page') for (let page of Array.from(heads)) { let title = page.querySelector('span').innerText let paras = page.innerText.split(/\n\n/) let date = new Date(paras.slice(-1)[0].split(' ').slice(-3).join(' ')).getTime() let story = paras.map(text => { let id = md5w(text) let wiki = title.replace(/ /g,'') return {type:'paragraph',text,wiki,id} }) let journal = [ {type:'create',date,item:JSON.parse(JSON.stringify(story))} ] exports[asSlug(title)] = {title,story,journal} } download(JSON.stringify(exports,null,2),'wiki-export-pages.json') } window.get = function(e) { const link = text => `<a href=?${text}>${text}</a>` var want = e.target.value if (want.length > 1) { var found = names.filter(function (e) { return e.includes(want) }) if (found.length) { return e.target.nextSibling.innerHTML = '<br>'+found.slice(0,500).map(link).join('<br>') } } } window.got = function (e) { if (!e) e = window.event; if ((e.keyCode || e.which) == '13') { e.target.value = '' e.target.nextSibling.innerHTML = '' } } function titlesearch() { return "<input type=text onInput='get(event)' onKeyPress='got(event)'><div></div>" } window.search = async function (e) { let url = `https://c2.com/cgi/fullSearch` if((e.keyCode || e.which) == '13') { let text = await fetch(`${url}?search=${e.target.value}`).then(res => res.text()) let html = text.replace(/ href=wiki/g,' href=').split('<br>').slice(1,-1) return e.target.nextSibling.innerHTML = '<br>'+html.join('<br>') } } function fullsearch() { return "<input type=text onKeyPress='search(event)'><dev></dev>" // return "<form action=\"https://c2.com/cgi/fullSearch\"><input type=text name=search></form>" } // U T I L I T I E S function download(string, file) { var data = "data:text/json;charset=utf-8," + encodeURIComponent(string); var anchor = document.createElement('a'); anchor.setAttribute("href", data); anchor.setAttribute("download", file); document.body.appendChild(anchor); // required for firefox anchor.click(); anchor.remove(); } function md5w(str) { let hash = hex_md5(str) return hash.slice(0,16)+'w' } </script> </body> </html>