|
| 1 | +;(function(){ |
| 2 | +var W = window, D = document, SW = screen.width, SH = screen.height, ON = 'addEventListener', HI = 'createElement', ID = 'getElementById', U, DEV = ('file://'===location.origin); |
| 3 | +;(function(){ if(screen.width > screen.height){ return } // phone only debug |
| 4 | + var add = function(){ if(console.view){ return } (console.view = document[HI]('textarea')).style="position:fixed; z-index:99999; inset:0; width:100%; height:4em; padding: 0; background:rgba(100%,100%,100%,0.8); color:black; transition: 0.5s all; white-space: pre-wrap; overflow-wrap: break-word; word-break: break-all;"; console.view.readOnly = 1; setTimeout(function(){D.body.appendChild(console.view);},99); console.view.onclick = function(eve){ console.view.style.height = ('4em'==console.view.style.height)?'50vh':'4em' ; console.view.select(); D.execCommand('copy'); navigator.clipboard.writeText(console.view.value) } } |
| 5 | + console.log = console.warn = console.error = function(...args){ if(console.off){ return } add(); console.view.value += JSON.stringify(args).slice(1,-1); console.view.scrollTop = console.view.scrollHeight; } |
| 6 | + window.onerror = window.onunhandledrejection = console.log; |
| 7 | +}()); |
| 8 | +var tmp = D[HI]('meta'); tmp.name = 'viewport'; tmp.content = 'width=device-width, initial-scale=1, interactive-widget=resizes-content'; D.head.appendChild(tmp); |
| 9 | +//(tmp=D[HI]('link')).rel="stylesheet"; tmp.href=((D.currentScript||'').src||'').replace('.js','.css'); D.head.appendChild(tmp); // auto-add CSS? |
| 10 | +W.parent === W && ((tmp = D.head.parentNode.style)['overscroll-behavior-y'] = 'contain') && (tmp['background-color'] = 'var(--fill)'); |
| 11 | +function LOAD(src, h, s){ (s = D[HI]('script')).onload = h; s.src = src; D.head.appendChild(s) }; |
| 12 | +function MAP(scroll, screen){ return (scroll / screen)>>0 }; // scroll, screen |
| 13 | +kit = function(){}; |
| 14 | +// dip, dive, into, eat, lid, tin, key, face |
| 15 | +kit.ear = function(h,e,v){ (v=v||W)[ON](e=(h.call?(h.where=e):(e.where=h,(h=e).where))||'',h); h.off = function(){ v.removeEventListener(e,h) }; W===v&&kit.up(e,'ear'); return h; }; |
| 16 | +kit.say = function(d,e,v,s){ (v=v||W).dispatchEvent(new CustomEvent(e=e||'',{detail:d,bubbles:true})); !s&&(W===v)&&kit.up(d,e) }; |
| 17 | +kit.up = function up(data,type,tmp){ |
| 18 | + if(W === W.parent){ return } |
| 19 | + if(U === data){ return } // TODO: BUG? maybe allow? |
| 20 | + if('message' == type){ return } |
| 21 | + //console.log(location.pathname.split('/').slice(-1)[0], "SENDING UP", type, data); |
| 22 | + W.parent.postMessage({detail:data,type:type,wrap:1},DEV?'*':location.origin); |
| 23 | +} |
| 24 | +W[ON]('message',function(eve,data,i,tmp){ |
| 25 | + if(W === eve.source){ return } |
| 26 | + if(eve.origin !== (DEV?'null':location.origin)){//.replace('file://','')||'null')){ |
| 27 | + eve.preventDefault(); |
| 28 | + eve.stopImmediatePropagation(); |
| 29 | + eve.stopPropagation(); |
| 30 | + return; |
| 31 | + } |
| 32 | + if(U === (data = eve.data||eve.detail)){ return } // TODO: BUG? maybe allow? |
| 33 | + if(!(i = kit.views.get(eve.source))){ // no iframe view? then message coming down to us from above. |
| 34 | + //console.log(location.pathname.split('/').slice(-1)[0], "GOT FROM ABOVE:", eve); |
| 35 | + kit.say(data.data||data.detail,data.type,0,1); |
| 36 | + return; |
| 37 | + } |
| 38 | + if('ear'==data.type){ kit.ear(data.detail||data.data,function hear(eve){ if(!(i||'').contentWindow){hear.off(); return } i.contentWindow.postMessage({data:eve.detail||eve.data,type:eve.type,wrap:-1}, DEV?'*':location.origin) }); return; } |
| 39 | + kit.say(data.data||data.detail,data.type,i); |
| 40 | +}); |
| 41 | +kit.views = new Map; |
| 42 | +(kit.watch = new MutationObserver(function(eve,b,low){eve.forEach(function(changes){changes.addedNodes.forEach(function(node){ //console.log("observed change on", node); |
| 43 | + node.dispatchEvent(new CustomEvent('join '+node.nodeName.toLowerCase(), {bubbles:true})); |
| 44 | + node.dispatchEvent(new CustomEvent('join', {bubbles:true})); |
| 45 | + //low = kit.watch.low(node, low); |
| 46 | +})}); |
| 47 | + //console.log(location.pathname.split('/').slice(-1)[0], "LOWEST", low, kit.watch.low(D.body), D.body.scrollHeight); |
| 48 | + kit.up({height:D.body.scrollHeight,width:D.body.scrollWidth},'style'); |
| 49 | +})).observe(D.documentElement||D,{childList:true,subtree:true,characterData:true}); |
| 50 | + |
| 51 | +kit.watch.low = function(v,l,f){ f='getBoundingClientRect'; return Math.max(((v[f]?v[f]():'').bottom||0) + (W.pageYOffset || D.documentElement.scrollTop),l||0) } |
| 52 | +kit.ear('join iframe',kit.add=function(eve){ |
| 53 | + //console.log(location.pathname.split('/').slice(-1)[0], "JOIN"); |
| 54 | + kit.views.set(eve.target.contentWindow, eve.target); |
| 55 | +}); |
| 56 | +kit.ear('style',function(eve,i){ |
| 57 | + if(!eve.target || !eve.target.style){ return } |
| 58 | + //console.log(location.pathname.split('/').slice(-1)[0], "resize:", eve.target, eve.detail); |
| 59 | + var h = (eve.detail||'').height; if(h) eve.target.style.height = isNaN(h) ? h : h+'px'; |
| 60 | + var w = (eve.detail||'').width; if(w) eve.target.style.width = isNaN(w) ? w : w+'px'; |
| 61 | +},document); |
| 62 | +kit.http = {createServer: function(h){ |
| 63 | + h.listen = function(port,ip,cb){cb&&cb()}; |
| 64 | + return kit.server = h; |
| 65 | +},serve: function(req, res){ if(W.parent !== W){ return } |
| 66 | + kit.fs.createReadStream(req.url).pipe(res); |
| 67 | +},req:function(path,body){ return this._last={url:path, |
| 68 | + method:body?'POST':'GET',body:body, |
| 69 | + headers:{},rawHeaders:[],rawTrailers:[], |
| 70 | + socket:tmp={},client:tmp,connection:tmp, |
| 71 | + resume: function(){}, |
| 72 | + pause: function(){}, |
| 73 | + isPaused: function(){} |
| 74 | +}},res:function(end){ return {_req:this._last, |
| 75 | + end: end||kit.http.end, |
| 76 | + getHeader: function(){}, |
| 77 | + setHeader: function(name, value){}, |
| 78 | + writeHead: function(statusCode,headers){}, |
| 79 | + write: function(data){}, |
| 80 | + pipe: function(){} |
| 81 | +}},end:function(data,id,i){ |
| 82 | + id = this._req.url.replace(location.__dirname,'').replace('file://','')/*.replace('.html','')*/.split('#')[0]; |
| 83 | + //console.log("http.end", id, data, 'URL:', this._req.url); |
| 84 | + //(i = ((data||'').src? data : (D[ID](id) || D[HI]('iframe')))).id || (i.id = id); |
| 85 | + (i = D[ID](id) || D[HI]('iframe')).id || (i.id = id); |
| 86 | + D.querySelectorAll('.main').forEach(function(e){ e.classList.remove('main') }); |
| 87 | + i.className = 'main page'; i.src||(i===D.body)||(i.srcdoc = data, D.body.appendChild(i)); location.hash = i.id; // TODO: BUG? Prevent double hash change |
| 88 | +}}; |
| 89 | +W[ON]('submit', function(eve, act){ eve.preventDefault(); |
| 90 | + act = (eve.target.action||'').replace(location.__dirname+'/','').split('#')[0]; |
| 91 | + //console.log(location.pathname.split('/').slice(-1)[0], 'submit', act); |
| 92 | + (kit.server||kit.http.serve)( |
| 93 | + kit.http.req(act,Object.fromEntries(new FormData(eve.target))), |
| 94 | + kit.http.res() |
| 95 | + ); |
| 96 | +}); |
| 97 | +location.__dirname = location.href.split('/').slice(0,-1).join('/'); |
| 98 | +Object.defineProperty(location, 'path', { |
| 99 | + get(){ return kit.path }, |
| 100 | + set(path){ if(!path){ return } |
| 101 | + path = path.replace(location.__dirname,''); |
| 102 | + if('.' == path[0]){ path = path.slice(1) } |
| 103 | + if('/' == path[0]){ path = path.slice(1) } |
| 104 | + //console.log(location.pathname.split('/').slice(-1)[0], 'path=', path, kit.path); |
| 105 | + if(kit.path === (kit.path = path)){ return } |
| 106 | + (kit.server||kit.http.serve)(kit.http.req(path),kit.http.res()); |
| 107 | + } |
| 108 | +}); |
| 109 | +kit.querystring = { |
| 110 | + parse: function(qs){ return Object.fromEntries((new URLSearchParams(qs)).entries()) } |
| 111 | +} |
| 112 | +kit.fs = {files:{}, |
| 113 | + createReadStream(url){ url = (url||'').replace(location.__dirname+'/','').split('#')[0]; |
| 114 | + //console.log("fs.cRS:", url); |
| 115 | + var data = this.files[url], end = 0, tmp; |
| 116 | + return {_:{}, |
| 117 | + on(eve,cb){ this._[eve] = cb; 'open'==eve&&setTimeout(cb, 0); return this }, // fake immediate open |
| 118 | + pipe(dest){ var rs = this, i; |
| 119 | + if(end){ return dest } end = 1; |
| 120 | + function load(){ (data = i).onload = 0;; |
| 121 | + if(!data){ return (tmp=rs._.error)&&tmp({code:'ENOENT'}) } |
| 122 | + (tmp=rs._.data)&&tmp(data); |
| 123 | + (tmp=rs._.end)&&tmp(); |
| 124 | + dest.end(data); |
| 125 | + }; |
| 126 | + if(i = D[ID](url)){ setTimeout(load,0) } |
| 127 | + else { |
| 128 | + (i = D[HI]('iframe')).onload = load |
| 129 | + i.id = (i.src = url)/*.replace('.html','')*/; D.body.appendChild(i); |
| 130 | + } |
| 131 | + //setTimeout(i.onload,0); |
| 132 | + return dest; |
| 133 | + } |
| 134 | + }; |
| 135 | + }, readFileSync: function(path){ |
| 136 | + |
| 137 | + }, readFile: function(path,opt,cb){ |
| 138 | + |
| 139 | + }, writeFileSync: function(path,data){ |
| 140 | + |
| 141 | + }, writeFile: function(path,data,opt,cb){ |
| 142 | + |
| 143 | + }, createWriteStream: function(path,opt){ |
| 144 | + |
| 145 | + }, readdir: function(path,cb){ |
| 146 | + |
| 147 | + } |
| 148 | +}; |
| 149 | +W[ON]('DOMContentLoaded',function(m){ |
| 150 | + //m = D[HI]('main'); while(D.body.firstChild){ m.appendChild(D.body.firstChild) } D.body.appendChild(m); |
| 151 | + m=D.body;m.className = 'main page'; m.id = (kit.path = location.href.replace(location.__dirname+'/','').split('#')[0])/*.replace('.html','')*/; |
| 152 | + //console.log(location.pathname.split('/').slice(-1)[0], "kit hash add!"); |
| 153 | + (function(){ function change(eve){ eve = eve||''; eve = eve.detail||eve.data||eve; |
| 154 | + var hash = (eve.newURL||'').split('#')[1]||''; |
| 155 | + if('.' == hash[0]){ location.hash = hash.slice(1); return; } |
| 156 | + if('/' == hash[0]){ location.hash = hash.slice(1); return; } |
| 157 | + //console.log(location.pathname.split('/').slice(-1)[0], "kit hashchange", hash, 'eve:', eve); |
| 158 | + if(!eve && !hash){ return } |
| 159 | + location.path = hash; |
| 160 | + eve && kit.up({newURL: eve.newURL, oldURL: eve.oldURL},'hashchange'); |
| 161 | + }; W[ON]('hashchange',change) }()); |
| 162 | + kit.up('','load'); |
| 163 | + return; |
| 164 | + //if(location.hash){ kit.say('','hashchange') } |
| 165 | +}); |
| 166 | +}()); |
0 commit comments