From 6855e7eca8347e01b2afbc5e75d14def82c4c55d Mon Sep 17 00:00:00 2001 From: defaultkavy Date: Sun, 19 May 2024 02:00:55 +0800 Subject: [PATCH] v0.2.3 new: Auto detect and add new post. --- dist/assets/index-BIoKxl_Q.js | 1 - ...{index-Cq-5lgfU.css => index-BMUJRc5c.css} | 2 +- dist/assets/index-DR9E_CfL.js | 1 + dist/index.html | 4 +- index.scss | 5 +- src/main.ts | 2 +- src/route/gallery/$gallery.ts | 84 +++++++++++++++++++ .../_$home.scss => gallery/_$gallery.scss} | 6 ++ src/route/home/$home.ts | 72 ---------------- src/route/posts/$post.ts | 25 +++--- src/structure/Post.ts | 26 ++++-- src/structure/Tag.ts | 24 +++++- src/structure/User.ts | 19 ++++- 13 files changed, 165 insertions(+), 106 deletions(-) delete mode 100644 dist/assets/index-BIoKxl_Q.js rename dist/assets/{index-Cq-5lgfU.css => index-BMUJRc5c.css} (84%) create mode 100644 dist/assets/index-DR9E_CfL.js create mode 100644 src/route/gallery/$gallery.ts rename src/route/{home/_$home.scss => gallery/_$gallery.scss} (52%) delete mode 100644 src/route/home/$home.ts diff --git a/dist/assets/index-BIoKxl_Q.js b/dist/assets/index-BIoKxl_Q.js deleted file mode 100644 index b7551a1..0000000 --- a/dist/assets/index-BIoKxl_Q.js +++ /dev/null @@ -1 +0,0 @@ -var wt=Object.defineProperty;var bt=(i,t,e)=>t in i?wt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var l=(i,t,e)=>(bt(i,typeof t!="symbol"?t+"":t,e),e),X=(i,t,e)=>{if(!t.has(i))throw TypeError("Cannot "+e)};var Q=(i,t,e)=>(X(i,t,"read from private field"),e?e.call(i):t.get(i)),Z=(i,t,e)=>{if(t.has(i))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(i):t.set(i,e)},tt=(i,t,e,s)=>(X(i,t,"write to private field"),s?s.call(i,e):t.set(i,e),e);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const n of r)if(n.type==="childList")for(const h of n.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&s(h)}).observe(document,{childList:!0,subtree:!0});function e(r){const n={};return r.integrity&&(n.integrity=r.integrity),r.referrerPolicy&&(n.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?n.credentials="include":r.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function s(r){if(r.ep)return;r.ep=!0;const n=e(r);fetch(r.href,n)}})();class M{constructor(){l(this,"__hidden",!1);l(this,"domEvents",{});l(this,"parent")}on(t,e,s){this.domEvents[t]||(this.domEvents[t]=new Map);const r=n=>e(n,this);return this.domEvents[t].set(e,r),this.dom.addEventListener(t,r,s),this}off(t,e,s){var n;const r=(n=this.domEvents[t])==null?void 0:n.get(e);return r&&this.dom.removeEventListener(t,r,s),this}once(t,e,s){const r=n=>{this.dom.removeEventListener(t,r,s),e(n,this)};return this.dom.addEventListener(t,r,s),this}hide(t,e=!0){return b.fluent(this,arguments,()=>this.__hidden,()=>{var s;if(t!==void 0)return t instanceof O?(this.__hidden=t.value,t.use(this,"hide")):this.__hidden=t,e&&((s=this.parent)==null||s.children.render()),this})}remove(){var t;return(t=this.parent)==null||t.children.remove(this).render(),this}replace(t){var e;return(e=this.parent)==null||e.children.replace(this,t).render(),this}contains(t){return t?t instanceof M?this.dom.contains(t.dom):t instanceof EventTarget?this.dom.contains(b(t).dom):this.dom.contains(t):!1}self(t){return t(this),this}inDOM(){return document.contains(this.dom)}isElement(){return this instanceof E}}class E extends M{constructor(e,s){super();l(this,"dom");l(this,"static_classes",new Set);this.dom=this.createDom(e,s),this.dom.$=this,this.setOptions(s)}createDom(e,s){return s!=null&&s.dom?s.dom:e==="svg"?document.createElementNS("http://www.w3.org/2000/svg","svg"):document.createElement(e)}setOptions(e){return this.id(e==null?void 0:e.id),e&&e.class&&this.class(...e.class),this}id(e){return $.fluent(this,arguments,()=>this.dom.id,()=>$.set(this.dom,"id",e))}class(...e){return $.fluent(this,arguments,()=>this.dom.classList,()=>{this.dom.classList.forEach(s=>this.static_classes.has(s)??this.dom.classList.remove(s)),this.dom.classList.add(...e.detype())})}addClass(...e){return $.fluent(this,arguments,()=>this,()=>{this.dom.classList.add(...e.detype())})}removeClass(...e){return $.fluent(this,arguments,()=>this,()=>{this.dom.classList.remove(...e.detype())})}staticClass(...e){return $.fluent(this,arguments,()=>this.static_classes,()=>{this.removeClass(...this.static_classes),this.static_classes.clear(),this.addStaticClass(...e)})}addStaticClass(...e){return $.fluent(this,arguments,()=>this,()=>{e.detype().forEach(s=>this.static_classes.add(s)),this.addClass(...e)})}removeStaticClass(...e){return $.fluent(this,arguments,()=>this,()=>{e.detype().forEach(s=>this.static_classes.delete(s)),this.removeClass(...e)})}css(e){return $.fluent(this,arguments,()=>this.dom.style,()=>{Object.assign(this.dom.style,e)})}attribute(e,s){return arguments.length?arguments.length===1?e===void 0?null:this.dom.getAttribute(e):arguments.length===2?e?(s===null?this.dom.removeAttribute(e):s!==void 0&&this.dom.setAttribute(e,`${s}`),this):this:this:null}tabIndex(e){return $.fluent(this,arguments,()=>this.dom.tabIndex,()=>$.set(this.dom,"tabIndex",e))}focus(){return this.dom.focus(),this}blur(){return this.dom.blur(),this}animate(e,s,r){const n=this.dom.animate(e,s);return r&&r(n),this}getAnimations(e){return this.dom.getAnimations(e)}get dataset(){return this.dom.dataset}domRect(e){const s=this.dom.getBoundingClientRect();if(!e)return s;const r=e instanceof E?e.dom.getBoundingClientRect():e;return{...s,top:s.top-r.top,left:s.left-r.left,right:s.right-r.left,bottom:s.bottom-r.top,x:s.x-r.x,y:s.y-r.y}}}class I extends M{constructor(e){super();l(this,"dom");this.dom=e,this.dom.$=this}domRect(e){const s={bottom:innerHeight,height:innerHeight,left:0,right:innerWidth,top:0,width:innerWidth,x:0,y:0};if(!e)return s;const r=e instanceof E?e.dom.getBoundingClientRect():e;return{...s,top:s.top-r.top,left:s.left-r.left,right:s.right-r.left,bottom:s.bottom-r.top,x:s.x-r.x,y:s.y-r.y}}static from(e){return e.$ instanceof I?e.$:new I(e)}}class G extends M{constructor(e){super();l(this,"dom");this.dom=new Text(e),this.dom.$=this}content(e){return $.fluent(this,arguments,()=>this.dom.textContent,()=>$.set(this.dom,"textContent",e))}}class _t{constructor(t){l(this,"$container");l(this,"$elementList",new Set);this.$container=t}add(t){if(typeof t=="string"){const e=new G(t);this.$elementList.add(e),e.parent=this.$container}else this.$elementList.add(t),t.parent=this.$container}remove(t){return this.$elementList.has(t)?(this.$elementList.delete(t),t.parent=void 0,this):this}removeAll(t=!0){this.$elementList.forEach(e=>this.remove(e)),t&&this.render()}replace(t,e){const s=this.array;return s.splice(s.indexOf(t),1,e),t.remove(),this.$elementList.clear(),s.forEach(r=>this.$elementList.add(r)),this}render(){const[t,e]=[this.array.map(r=>r.dom),Array.from(this.dom.childNodes)],s=[];for(;e.length||t.length;){const[r,n]=[e.at(0),t.at(0)];n?r?n!==r?(n.$.__hidden||(this.dom.insertBefore(n,r),s.push(n)),t.shift()):(n.$.__hidden&&this.dom.removeChild(n),t.shift(),e.shift()):(n.$.__hidden||this.dom.append(n),t.shift()):(r&&!s.includes(r)&&r.remove(),e.shift())}}get array(){return[...this.$elementList.values()]}get dom(){return this.$container.dom}}class O{constructor(t,e){l(this,"_value");l(this,"attributes",new Map);l(this,"linkStates",new Set);l(this,"options",{});this.set(t),e&&(this.options=e)}set(t){this._value=t,t instanceof O&&t.linkStates.add(this),this.update(),this.linkStates.forEach(e=>e.update())}update(){for(const[t,e]of this.attributes.entries())for(const s of e)t[s]instanceof Function?this.options.format?t[s](this.options.format(this.value)):t[s](this.value):s in t&&(t[s]=this.value)}toString(){return this.options.format?this.options.format(this.value):this.value instanceof Object?JSON.stringify(this.toJSON()):`${this.value}`}use(t,e){const s=this.attributes.get(t);s?s.add(e):this.attributes.set(t,new Set().add(e))}toJSON(){return this.value instanceof O?this.value.toJSON():this.value instanceof Object?O.toJSON(this.value):this.toString()}static toJSON(t){const e={};for(let[s,r]of Object.entries(t))r instanceof O?r=r.toJSON():r instanceof Object&&O.toJSON(r),Object.assign(e,{[s]:r});return e}get value(){return this._value instanceof O?this._value.value:this._value}}class D extends E{constructor(t,e){super(t,e)}autocapitalize(t){return $.fluent(this,arguments,()=>this.dom.autocapitalize,()=>$.set(this.dom,"autocapitalize",t))}innerText(t){return $.fluent(this,arguments,()=>this.dom.innerText,()=>$.set(this.dom,"innerText",t))}title(t){return $.fluent(this,arguments,()=>this.dom.title,()=>$.set(this.dom,"title",t))}dir(t){return $.fluent(this,arguments,()=>this.dom.dir,()=>$.set(this.dom,"dir",t))}translate(t){return $.fluent(this,arguments,()=>this.dom.translate,()=>$.set(this.dom,"translate",t))}popover(t){return $.fluent(this,arguments,()=>this.dom.popover,()=>$.set(this.dom,"popover",t))}spellcheck(t){return $.fluent(this,arguments,()=>this.dom.spellcheck,()=>$.set(this.dom,"spellcheck",t))}inert(t){return $.fluent(this,arguments,()=>this.dom.inert,()=>$.set(this.dom,"inert",t))}lang(t){return $.fluent(this,arguments,()=>this.dom.lang,()=>$.set(this.dom,"lang",t))}draggable(t){return $.fluent(this,arguments,()=>this.dom.draggable,()=>$.set(this.dom,"draggable",t))}hidden(t){return $.fluent(this,arguments,()=>this.dom.hidden,()=>$.set(this.dom,"hidden",t))}click(){return this.dom.click(),this}attachInternals(){return this.dom.attachInternals()}hidePopover(){return this.dom.hidePopover(),this}showPopover(){return this.dom.showPopover(),this}togglePopover(){return this.dom.togglePopover(),this}get accessKeyLabel(){return this.dom.accessKeyLabel}get offsetHeight(){return this.dom.offsetHeight}get offsetLeft(){return this.dom.offsetLeft}get offsetParent(){return $(this.dom.offsetParent)}get offsetTop(){return this.dom.offsetTop}get offsetWidth(){return this.dom.offsetWidth}}class p extends D{constructor(e,s){super(e,s);l(this,"children",new _t(this))}content(e){return $.fluent(this,arguments,()=>this,()=>{this.children.removeAll(!1),this.insert(e)})}insert(e){return $.fluent(this,arguments,()=>this,()=>{e instanceof Function&&(e=e(this)),e=$.orArrayResolve(e);for(const s of e)if(s!=null)if(s instanceof Array)this.insert(s);else if(s instanceof O){const r=new G(s.toString());s.use(r,"content"),this.children.add(r)}else this.children.add(s);this.children.render()})}clear(){return this.children.removeAll(),this}$(e){return $(this.dom.querySelector(e))}$all(e){return Array.from(this.dom.querySelectorAll(e)).map(s=>$(s))}get scrollHeight(){return this.dom.scrollHeight}get scrollWidth(){return this.dom.scrollWidth}scrollTop(e){return $.fluent(this,arguments,()=>this.dom.scrollTop,()=>$.set(this.dom,"scrollTop",e))}scrollLeft(e){return $.fluent(this,arguments,()=>this.dom.scrollLeft,()=>$.set(this.dom,"scrollLeft",e))}}class Ot extends p{constructor(t){super("a",t),this.dom.addEventListener("click",e=>{$.anchorPreventDefault&&e.preventDefault(),$.anchorHandler&&this.href()&&$.anchorHandler(this,e)})}href(t){return $.fluent(this,arguments,()=>this.dom.href,()=>{t&&(this.dom.href=t)})}target(t){return $.fluent(this,arguments,()=>this.dom.target??void 0,()=>{t&&(this.dom.target=t)})}}class xt extends E{constructor(t,e){super(t,e)}}var _;(i=>{function t(o,d,a,m){return d.length?(m(),o):a()}i.fluent=t;function e(o){return o instanceof Array?o:[o]}i.orArrayResolve=e;function s(o,d){return e(d).forEach(a=>{Object.getOwnPropertyNames(a.prototype).forEach(m=>{m!=="constructor"&&Object.defineProperty(o.prototype,m,Object.getOwnPropertyDescriptor(a.prototype,m)||Object.create(null))})}),o}i.mixin=s;function r(o,d,a){a!==void 0&&(o[d]=a)}i.set=r;function n(o){return new O(o)}i.state=n;function h(o){if(o.$)return o.$;if(o.nodeName.toLowerCase()==="body")return new p("body",{dom:o});if(o.nodeName.toLowerCase()==="#document")return I.from(o);if(o instanceof HTMLElement){const d=$.TagNameElementMap[o.tagName.toLowerCase()],a=d===p?new d(o.tagName,{dom:o}):new d({dom:o});if(a instanceof p)for(const m of Array.from(a.dom.childNodes))a.children.add($(m));return a}else if(o instanceof Text){const d=new G(o.textContent??"");return d.dom=o,d}else if(o instanceof SVGElement&&o.tagName.toLowerCase()==="svg")return new xt("svg",{dom:o});throw`$NODE.FROM: NOT SUPPORT TARGET ELEMENT TYPE (${o.nodeName})`}i.from=h})(_||(_={}));class x{static create(...t){const e=class{};return Object.getOwnPropertyNames(x.prototype).forEach(s=>{s!=="constructor"&&t.includes(s)&&Object.defineProperty(e.prototype,s,Object.getOwnPropertyDescriptor(x.prototype,s)||Object.create(null))}),e}disabled(t){return $.fluent(this,arguments,()=>this.dom.disabled,()=>$.set(this.dom,"disabled",t))}checkValidity(){return this.dom.checkValidity()}reportValidity(){return this.dom.reportValidity()}formAction(t){return $.fluent(this,arguments,()=>this.dom.formAction,()=>$.set(this.dom,"formAction",t))}formEnctype(t){return $.fluent(this,arguments,()=>this.dom.formEnctype,()=>$.set(this.dom,"formEnctype",t))}formMethod(t){return $.fluent(this,arguments,()=>this.dom.formMethod,()=>$.set(this.dom,"formMethod",t))}formNoValidate(t){return $.fluent(this,arguments,()=>this.dom.formNoValidate,()=>$.set(this.dom,"formNoValidate",t))}formTarget(t){return $.fluent(this,arguments,()=>this.dom.formTarget,()=>$.set(this.dom,"formTarget",t))}autocomplete(t){return $.fluent(this,arguments,()=>this.dom.autocomplete,()=>$.set(this.dom,"autocomplete",t))}name(t){return $.fluent(this,arguments,()=>this.dom.name,()=>$.set(this.dom,"name",t))}maxLength(t){return $.fluent(this,arguments,()=>this.dom.maxLength,()=>$.set(this.dom,"maxLength",t))}minLength(t){return $.fluent(this,arguments,()=>this.dom.minLength,()=>$.set(this.dom,"minLength",t))}required(t){return $.fluent(this,arguments,()=>this.dom.required,()=>$.set(this.dom,"required",t))}label(t){return $.fluent(this,arguments,()=>this.dom.label,()=>$.set(this.dom,"label",t))}get form(){return this.dom.form?$(this.dom.form):null}get validationMessage(){return this.dom.validationMessage}get validity(){return this.dom.validity}get willValidate(){return this.dom.willValidate}}class nt extends p{constructor(t){super("button",t)}type(t){return $.fluent(this,arguments,()=>this.dom.type,()=>$.set(this.dom,"type",t))}}_.mixin(nt,x.create("disabled","checkValidity","formAction","formEnctype","formMethod","formNoValidate","formTarget","reportValidity"));class ot extends p{constructor(t){super("form",t)}action(t){return $.fluent(this,arguments,()=>this.dom.formAction,()=>$.set(this.dom,"formAction",t))}enctype(t){return $.fluent(this,arguments,()=>this.dom.formEnctype,()=>$.set(this.dom,"formEnctype",t))}method(t){return $.fluent(this,arguments,()=>this.dom.formMethod,()=>$.set(this.dom,"formMethod",t))}noValidate(t){return $.fluent(this,arguments,()=>this.dom.formNoValidate,()=>$.set(this.dom,"formNoValidate",t))}acceptCharset(t){return $.fluent(this,arguments,()=>this.dom.acceptCharset,()=>$.set(this.dom,"acceptCharset",t))}target(t){return $.fluent(this,arguments,()=>this.dom.formTarget,()=>$.set(this.dom,"formTarget",t))}requestSubmit(){return this.dom.requestSubmit(),this}reset(){return this.dom.reset(),this}submit(){return this.dom.submit(),this}get length(){return this.dom.length}get elements(){return Array.from(this.dom.elements).map(t=>$(t))}}_.mixin(ot,x.create("checkValidity","reportValidity","autocomplete"));class at extends E{constructor(t){super("input",t)}value(t){return $.fluent(this,arguments,()=>this.type()==="number"?Number(this.dom.value):this.dom.value,()=>$.set(this.dom,"value",t,e=>{this.on("input",()=>{e.attributes.has(this.dom)!==!1&&(typeof e.value=="string"&&e.set(`${this.value()}`),typeof e.value=="number"&&e.set(Number(this.value())))})}))}type(t){return $.fluent(this,arguments,()=>this.dom.type,()=>$.set(this.dom,"type",t))}capture(t){return $.fluent(this,arguments,()=>this.dom.capture,()=>$.set(this.dom,"capture",t))}alt(t){return $.fluent(this,arguments,()=>this.dom.alt,()=>$.set(this.dom,"alt",t))}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>$.set(this.dom,"height",t))}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>$.set(this.dom,"width",t))}defaultValue(t){return $.fluent(this,arguments,()=>this.dom.defaultValue,()=>$.set(this.dom,"defaultValue",t))}dirName(t){return $.fluent(this,arguments,()=>this.dom.dirName,()=>$.set(this.dom,"dirName",t))}pattern(t){return $.fluent(this,arguments,()=>this.dom.pattern,()=>$.set(this.dom,"pattern",t))}placeholder(t){return $.fluent(this,arguments,()=>this.dom.placeholder,()=>$.set(this.dom,"placeholder",t))}readOnly(t){return $.fluent(this,arguments,()=>this.dom.readOnly,()=>$.set(this.dom,"readOnly",t))}selectionDirection(t){return $.fluent(this,arguments,()=>this.dom.selectionDirection,()=>$.set(this.dom,"selectionDirection",t))}selectionEnd(t){return $.fluent(this,arguments,()=>this.dom.selectionEnd,()=>$.set(this.dom,"selectionEnd",t))}selectionStart(t){return $.fluent(this,arguments,()=>this.dom.selectionStart,()=>$.set(this.dom,"selectionStart",t))}size(t){return $.fluent(this,arguments,()=>this.dom.size,()=>$.set(this.dom,"size",t))}src(t){return $.fluent(this,arguments,()=>this.dom.src,()=>$.set(this.dom,"src",t))}inputMode(t){return $.fluent(this,arguments,()=>this.dom.inputMode,()=>$.set(this.dom,"inputMode",t))}valueAsDate(t){return $.fluent(this,arguments,()=>this.dom.valueAsDate,()=>$.set(this.dom,"valueAsDate",t))}valueAsNumber(t){return $.fluent(this,arguments,()=>this.dom.valueAsNumber,()=>$.set(this.dom,"valueAsNumber",t))}webkitdirectory(t){return $.fluent(this,arguments,()=>this.dom.webkitdirectory,()=>$.set(this.dom,"webkitdirectory",t))}select(){return this.dom.select(),this}setCustomValidity(t){return this.dom.setCustomValidity(t),this}setRangeText(t,e,s,r){return typeof e=="number"&&typeof s=="number"&&this.dom.setRangeText(t,e,s,r),this.dom.setRangeText(t),this}setSelectionRange(t,e,s){return this.dom.setSelectionRange(t,e,s),this}showPicker(){return this.dom.showPicker(),this}get files(){return this.dom.files}get webkitEntries(){return this.dom.webkitEntries}get labels(){return Array.from(this.dom.labels??[]).map(t=>$(t))}}_.mixin(at,x.create("checkValidity","reportValidity","autocomplete","name","form","required","validationMessage","validity","willValidate","formAction","formEnctype","formMethod","formNoValidate","formTarget"));class ht extends p{constructor(t){super("label",t)}for(t){return $.fluent(this,arguments,()=>this.dom.htmlFor,()=>{$.set(this.dom,"htmlFor",t)})}get control(){return this.dom.control}}_.mixin(ht,x.create("form"));class Tt extends D{constructor(t){super("img",t)}async load(t){return new Promise(e=>{const s=this.once("load",()=>{e(s)});typeof t=="string"?s.src(t):t.then(r=>s.src(r))})}static resize(t,e){return new Promise(s=>{const r=new Image;if(r.addEventListener("load",()=>{const n=document.createElement("canvas"),h=n.getContext("2d");if(!h)throw"$Image.resize: context undefined";const o=r.width/r.height,[d,a,m]=[o>1,o<1,o===1],u=e instanceof Array?e[0]:a?e:e*o,c=e instanceof Array?e[1]:d?e:e/o;n.height=c,n.width=u,h.drawImage(r,0,0,u,c),s(n.toDataURL())},{once:!0}),t instanceof File){const n=new FileReader;n.addEventListener("load",()=>r.src=n.result),n.readAsDataURL(t)}else r.src=t})}alt(t){return $.fluent(this,arguments,()=>this.dom.alt,()=>$.set(this.dom,"alt",t))}crossOrigin(t){return $.fluent(this,arguments,()=>this.dom.crossOrigin,()=>$.set(this.dom,"crossOrigin",t))}decoding(t){return $.fluent(this,arguments,()=>this.dom.decoding,()=>$.set(this.dom,"decoding",t))}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>$.set(this.dom,"height",t))}isMap(t){return $.fluent(this,arguments,()=>this.dom.isMap,()=>$.set(this.dom,"isMap",t))}loading(t){return $.fluent(this,arguments,()=>this.dom.loading,()=>$.set(this.dom,"loading",t))}referrerPolicy(t){return $.fluent(this,arguments,()=>this.dom.referrerPolicy,()=>$.set(this.dom,"referrerPolicy",t))}sizes(t){return $.fluent(this,arguments,()=>this.dom.sizes,()=>$.set(this.dom,"sizes",t))}src(t){return $.fluent(this,arguments,()=>this.dom.src,()=>$.set(this.dom,"src",t))}srcset(t){return $.fluent(this,arguments,()=>this.dom.srcset,()=>$.set(this.dom,"srcset",t))}useMap(t){return $.fluent(this,arguments,()=>this.dom.useMap,()=>$.set(this.dom,"useMap",t))}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>$.set(this.dom,"width",t))}decode(){return this.dom.decode()}get complete(){return this.dom.complete}get currentSrc(){return this.dom.currentSrc}get naturalHeight(){return this.dom.naturalHeight}get naturalWidth(){return this.dom.naturalWidth}get x(){return this.dom.x}get y(){return this.dom.y}}class Et extends p{constructor(t){super("canvas",t)}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>{$.set(this.dom,"height",t)})}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>{$.set(this.dom,"width",t)})}captureStream(t){return this.dom.captureStream(t)}getContext(t,e){return this.dom.getContext(t)}toBlob(t,e,s){return this.dom.toBlob(t,e,s),this}toDataURL(t,e){return this.dom.toDataURL(t,e)}transferControlToOffscreen(){return this.dom.transferControlToOffscreen()}}class Lt extends p{constructor(t){super("dialog",t)}open(t){return $.fluent(this,arguments,()=>this.dom.open,()=>$.set(this.dom,"open",t))}returnValue(t){return $.fluent(this,arguments,()=>this.dom.returnValue,()=>$.set(this.dom,"returnValue",t))}close(){return this.dom.close(),this}show(){return this.dom.show(),this}showModal(){return this.dom.showModal(),this}}class ut{on(t,e){return this.events.on(t,e),this}off(t,e){return this.events.off(t,e),this}once(t,e){return this.events.once(t,e),this}}class V{constructor(){l(this,"eventMap",new Map)}register(...t){return t.forEach(e=>{const s=new et(e);this.eventMap.set(s.name,s)}),this}delete(t){return this.eventMap.delete(t),this}fire(t,...e){const s=this.get(t);return s instanceof et&&s.fire(...e),this}on(t,e){return this.get(t).add(e),this}off(t,e){return this.get(t).delete(e),this}once(t,e){const s=(...r)=>{this.get(t).delete(s),e(...r)};return this.get(t).add(s),this}get(t){const e=this.eventMap.get(t);if(!e)throw new Error("EVENT NOT EXIST");return e}}class et{constructor(t){l(this,"name");l(this,"callbackList",new Set);this.name=t}fire(...t){this.callbackList.forEach(e=>e(...t))}add(t){this.callbackList.add(t)}delete(t){this.callbackList.delete(t)}}class dt extends p{constructor(e){super("view",e);l(this,"view_cache",new Map);l(this,"event",new V().register("switch"));l(this,"content_id",null)}setView(e,s){return this.view_cache.set(e,s),this}deleteView(e){return this.view_cache.delete(e),this}deleteAllView(){return this.view_cache.clear(),this}switchView(e){const s=this.view_cache.get(e);return s===void 0?this:(this.content(s),this.content_id=e,this.event.fire("switch",e),this)}}class ct extends p{constructor(t){super("select")}add(t){return this.insert(t),this}item(t){return $(this.dom.item(t))}namedItem(t){return $(this.dom.namedItem(t))}multiple(t){return $.fluent(this,arguments,()=>this.dom.multiple,()=>$.set(this.dom,"multiple",t))}get length(){return this.dom.length}get size(){return this.dom.size}get options(){return Array.from(this.dom.options).map(t=>$(t))}get selectedIndex(){return this.dom.selectedIndex}get selectedOptions(){return Array.from(this.dom.selectedOptions).map(t=>$(t))}value(t){return $.fluent(this,arguments,()=>this.dom.value,()=>$.set(this.dom,"value",t))}get labels(){return Array.from(this.dom.labels??[]).map(t=>$(t))}}_.mixin(ct,x.create("checkValidity","reportValidity","autocomplete","name","form","required","disabled","validationMessage","validity","willValidate"));class lt extends p{constructor(t){super("option",t)}defaultSelected(t){return $.fluent(this,arguments,()=>this.dom.defaultSelected,()=>$.set(this.dom,"defaultSelected",t))}selected(t){return $.fluent(this,arguments,()=>this.dom.selected,()=>$.set(this.dom,"selected",t))}text(t){return $.fluent(this,arguments,()=>this.dom.text,()=>$.set(this.dom,"text",t))}value(t){return $.fluent(this,arguments,()=>this.dom.value,()=>$.set(this.dom,"value",t))}get form(){return this.dom.form?$(this.dom.form):null}get index(){return this.dom.index}}_.mixin(lt,x.create("form","disabled","label"));class mt extends p{constructor(t){super("optgroup",t)}disabled(t){return $.fluent(this,arguments,()=>this.dom.disabled,()=>$.set(this.dom,"disabled",t))}}_.mixin(mt,x.create("disabled","label"));class ft extends p{constructor(t){super("textarea",t)}cols(t){return $.fluent(this,arguments,()=>this.dom.cols,()=>$.set(this.dom,"cols",t))}wrap(t){return $.fluent(this,arguments,()=>this.dom.wrap,()=>$.set(this.dom,"wrap",t))}value(t){return $.fluent(this,arguments,()=>this.dom.value,()=>$.set(this.dom,"value",t))}defaultValue(t){return $.fluent(this,arguments,()=>this.dom.defaultValue,()=>$.set(this.dom,"defaultValue",t))}dirName(t){return $.fluent(this,arguments,()=>this.dom.dirName,()=>$.set(this.dom,"dirName",t))}placeholder(t){return $.fluent(this,arguments,()=>this.dom.placeholder,()=>$.set(this.dom,"placeholder",t))}readOnly(t){return $.fluent(this,arguments,()=>this.dom.readOnly,()=>$.set(this.dom,"readOnly",t))}selectionDirection(t){return $.fluent(this,arguments,()=>this.dom.selectionDirection,()=>$.set(this.dom,"selectionDirection",t))}selectionEnd(t){return $.fluent(this,arguments,()=>this.dom.selectionEnd,()=>$.set(this.dom,"selectionEnd",t))}selectionStart(t){return $.fluent(this,arguments,()=>this.dom.selectionStart,()=>$.set(this.dom,"selectionStart",t))}type(t){return $.fluent(this,arguments,()=>this.dom.type,()=>$.set(this.dom,"type",t))}inputMode(t){return $.fluent(this,arguments,()=>this.dom.inputMode,()=>$.set(this.dom,"inputMode",t))}select(){return this.dom.select(),this}setCustomValidity(t){return this.dom.setCustomValidity(t),this}setRangeText(t,e,s,r){return typeof e=="number"&&typeof s=="number"&&this.dom.setRangeText(t,e,s,r),this.dom.setRangeText(t),this}setSelectionRange(t,e,s){return this.dom.setSelectionRange(t,e,s),this}get labels(){return Array.from(this.dom.labels??[]).map(t=>$(t))}}_.mixin(ft,x.create("checkValidity","reportValidity","autocomplete","name","form","required","disabled","minLength","maxLength","validationMessage","validity","willValidate"));var H;class St extends p{constructor(e){super("async",e);Z(this,H,!1)}await(e){return e.then(s=>this._loaded(s)),this}_loaded(e){tt(this,H,!0),this.replace(e),this.dom.dispatchEvent(new Event("load"))}get loaded(){return Q(this,H)}}H=new WeakMap;class Mt extends E{constructor(t,e){super(t,e)}autoplay(t){return $.fluent(this,arguments,()=>this.dom.autoplay,()=>$.set(this.dom,"autoplay",t))}get buffered(){return this.dom.buffered}controls(t){return $.fluent(this,arguments,()=>this.dom.controls,()=>$.set(this.dom,"controls",t))}crossOrigin(t){return $.fluent(this,arguments,()=>this.dom.crossOrigin,()=>$.set(this.dom,"crossOrigin",t))}get currentSrc(){return this.dom.currentSrc}currentTime(t){return $.fluent(this,arguments,()=>this.dom.currentTime,()=>$.set(this.dom,"currentTime",t))}defaultMuted(t){return $.fluent(this,arguments,()=>this.dom.defaultMuted,()=>$.set(this.dom,"defaultMuted",t))}defaultPlaybackRate(t){return $.fluent(this,arguments,()=>this.dom.defaultPlaybackRate,()=>$.set(this.dom,"defaultPlaybackRate",t))}disableRemotePlayback(t){return $.fluent(this,arguments,()=>this.dom.disableRemotePlayback,()=>$.set(this.dom,"disableRemotePlayback",t))}get duration(){return this.dom.duration}get ended(){return this.dom.ended}get error(){return this.dom.error}loop(t){return $.fluent(this,arguments,()=>this.dom.loop,()=>$.set(this.dom,"loop",t))}mediaKeys(t){return $.fluent(this,arguments,()=>this.dom.mediaKeys,()=>$.set(this.dom,"setMediaKeys",[t]))}muted(t){return $.fluent(this,arguments,()=>this.dom.muted,()=>$.set(this.dom,"muted",t))}get networkState(){return this.dom.networkState}get paused(){return this.dom.paused}playbackRate(t){return $.fluent(this,arguments,()=>this.dom.playbackRate,()=>$.set(this.dom,"playbackRate",t))}get played(){return this.dom.played}preload(t){return $.fluent(this,arguments,()=>this.dom.preload,()=>$.set(this.dom,"preload",t))}preservesPitch(t){return $.fluent(this,arguments,()=>this.dom.preservesPitch,()=>$.set(this.dom,"preservesPitch",t))}get readyState(){return this.dom.readyState}get remote(){return this.dom.remote}get seekable(){return this.dom.seekable}get seeking(){return this.dom.seeking}sinkId(t){return $.fluent(this,arguments,()=>this.dom.sinkId,()=>$.set(this.dom,"setSinkId",[t]))}src(t){return $.fluent(this,arguments,()=>this.dom.src,()=>$.set(this.dom,"src",t))}srcObject(t){return $.fluent(this,arguments,()=>this.dom.srcObject,()=>$.set(this.dom,"srcObject",t))}get textTracks(){return this.dom.textTracks}volume(t){return $.fluent(this,arguments,()=>this.dom.volume,()=>$.set(this.dom,"volume",t))}addTextTrack(t,e,s){return this.dom.addTextTrack(t,e,s)}canPlayType(t){return this.dom.canPlayType(t)}fastSeek(t){return this.dom.fastSeek(t),this}load(){return this.dom.load(),this}pause(){return this.dom.pause(),this}async play(){return await this.dom.play(),this}get isPlaying(){return this.currentTime()>0&&!this.paused&&!this.ended&&this.readyState>2}}class Pt extends Mt{constructor(t){super("video",t)}disablePictureInPicture(t){return $.fluent(this,arguments,()=>this.dom.disablePictureInPicture,()=>$.set(this.dom,"disablePictureInPicture",t))}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>$.set(this.dom,"height",t))}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>$.set(this.dom,"width",t))}playsInline(t){return $.fluent(this,arguments,()=>this.dom.playsInline,()=>$.set(this.dom,"playsInline",t))}poster(t){return $.fluent(this,arguments,()=>this.dom.poster,()=>$.set(this.dom,"poster",t))}get videoHeight(){return this.dom.videoHeight}get videoWidth(){return this.dom.videoWidth}cancelVideoFrameCallback(t){return this.dom.cancelVideoFrameCallback(t),this}getVideoPlaybackQuality(){return this.dom.getVideoPlaybackQuality()}requestPictureInPicture(){return this.dom.requestPictureInPicture()}requestVideoFrameCallback(t){return this.dom.requestVideoFrameCallback(t)}}function b(i){if(typeof i>"u"||i===null||i instanceof M)return i;if(typeof i=="string"){if(i.startsWith("::"))return Array.from(document.querySelectorAll(i.replace(/^::/,""))).map(t=>b(t));if(i.startsWith(":"))return b(document.querySelector(i.replace(/^:/,"")));if(i in b.TagNameElementMap){const t=b.TagNameElementMap[i];return t===D?new D(i):t===p?new p(i):new t}else return new p(i)}if(i instanceof Node)return i.$?i.$:_.from(i);throw`$: NOT SUPPORT TARGET ELEMENT TYPE ('${i}')`}(i=>{i.anchorHandler=null,i.anchorPreventDefault=!1,i.TagNameElementMap={document:I,body:p,a:Ot,p,pre:p,code:p,blockquote:p,strong:p,h1:p,h2:p,h3:p,h4:p,h5:p,h6:p,div:p,ol:p,ul:p,dl:p,li:p,input:at,label:ht,button:nt,form:ot,img:Tt,dialog:Lt,canvas:Et,view:dt,select:ct,option:lt,optgroup:mt,textarea:ft,video:Pt,async:St};function t(u,c,f,y){return c.length?(y(),u):f()}i.fluent=t;function e(u){return u instanceof Array?u:[u]}i.orArrayResolve=e;function s(u,c){return _.mixin(u,c)}i.mixin=s;function r(u,c,f,y){if(f!==void 0){if(f instanceof O){f.use(u,c),u[c]instanceof Function?u[c](...f.value):u[c]=f.value,y&&y(f);return}u[c]instanceof Function?u[c](...f):u[c]=f}}i.set=r;function n(u,c){return new O(u,c)}i.state=n;async function h(u,c){return new Promise(f=>{const y=new FileReader;y.onload=w=>{const v=i("img");if(v.once("load",L=>{const q=i("canvas"),Y=q.getContext("2d"),N=v.height()/v.width(),[J,K]=[N>1?c/N:c,N>1?c:c*N];q.height(K).width(J),Y==null||Y.drawImage(v.dom,0,0,J,K),f(q.toDataURL(u.type))}),!w.target)throw"$.resize(): e.target is null";v.src(w.target.result)},y.readAsDataURL(u)})}i.resize=h;function o(u=1){return parseInt(getComputedStyle(document.documentElement).fontSize)*u}i.rem=o;function d(u){const c=new DOMParser().parseFromString(u,"text/html").body;return Array.from(c.children).map(f=>i(f))}i.html=d;function a(u,c,f){if(typeof c=="number")return Array(c).fill("").map(w=>{const v=y(u)?u[0](...u.slice(1)):i(u);return f&&f(v),v});{const w=[];for(const v of c){const L=u instanceof Function?u(...v):y(u)?u[0](...u.slice(1)):i(u);v instanceof Function?v(L):(v instanceof M||typeof v=="string")&&L.content(v),w.push(L)}return w}function y(w){return w instanceof Array&&w[0]instanceof Function}}i.builder=a;function m(u,c){return Object.assign(i.TagNameElementMap,{[u]:c}),i.TagNameElementMap}i.registerTagName=m})(b||(b={}));globalThis.$=b;Array.prototype.detype=function(...i){return this.filter(t=>{if(i.length)for(const e of i)return typeof t!=typeof e;else return t!==void 0})};class pt extends p{constructor(e){super("layout",e);l(this,"_property",{ROW_MAX_HEIGHT:200,GAP:0,IS_RENDERING:!1,RENDER_REQUEST:!1,COLUNM:1,TYPE:"justified",ROOT:null,THRESHOLD:null});this.css({display:"block",position:"relative"}),new ResizeObserver(s=>{this.inDOM()&&(this.render(),this.scrollCompute(),this.dom.dispatchEvent(new Event("resize")))}).observe(this.dom),document.addEventListener("scroll",s=>{s.target===this.root().dom&&this.scrollCompute()})}type(e){return $.fluent(this,arguments,()=>this._property.TYPE,()=>$.set(this._property,"TYPE",e))}maxHeight(e){return $.fluent(this,arguments,()=>this._property.ROW_MAX_HEIGHT,()=>$.set(this._property,"ROW_MAX_HEIGHT",e))}column(e){return $.fluent(this,arguments,()=>this._property.COLUNM,()=>$.set(this._property,"COLUNM",e))}gap(e){return $.fluent(this,arguments,()=>this._property.GAP,()=>$.set(this._property,"GAP",e))}root(e){return $.fluent(this,arguments,()=>this._property.ROOT??$(document),()=>$.set(this._property,"ROOT",e))}threshold(e){return $.fluent(this,arguments,()=>this._property.THRESHOLD??innerHeight,()=>$.set(this._property,"THRESHOLD",e))}get COL_WIDTH(){return(this.offsetWidth-this._property.GAP*(this._property.COLUNM-1))/this._property.COLUNM}computeLayout(){return this._property.TYPE==="justified"?this.justifiedCompute():this.justifiedCompute()}justifiedCompute(){const e=[],s=this.offsetWidth;for(const r of this.children.array){const n=$(r);if(!(n instanceof E))continue;const h=n.attribute("layout-item-ratio"),o=h?parseFloat(h):n.dom.offsetWidth/n.dom.offsetHeight,d={$node:n,ratio:o};let a=e.at(-1);(!a||a.heightm+=f.ratio);const u=m+o,c=(s-this._property.GAP*a.items.length)/u;a.items.push(d),a.ratio=u,a.height=c}return e}waterfallCompute(){const e=[],s=this.COL_WIDTH,r=()=>{if(e.lengthn.height-h.height)[0]};for(const n of this.children.array){const h=$(n);if(!(h instanceof E))continue;const o=h.attribute("layout-item-ratio"),d=o?parseFloat(o):h.dom.offsetWidth/h.dom.offsetHeight,a={$node:h,ratio:d},m=r();let u=0;m.items.forEach(y=>u+=y.ratio);const c=s/(m.height+s/d),f=s/c;m.items.push(a),m.ratio=c,m.height=f}return e}render(){if(this._property.TYPE==="justified"){const e=this.justifiedCompute();let s=0;for(const r of e){let n=0;r.height>this._property.ROW_MAX_HEIGHT&&(r.height=this._property.ROW_MAX_HEIGHT);for(const h of r.items){const o=h.ratio*r.height;h.$node.css({position:"absolute",height:`${r.height}px`,width:`${o}px`,top:`${s}px`,left:`${n}px`}),h.$node.attribute("layout-item-ratio",h.ratio),n+=r.height*h.ratio+this._property.GAP}s+=r.height+this._property.GAP}this.css({height:`${s}px`})}else if(this._property.TYPE="waterfall"){const e=this.waterfallCompute(),s=this.COL_WIDTH;let r=0;for(const n of e){let h=0;for(const o of n.items){const d=s/o.ratio;o.$node.css({position:"absolute",height:`${d}px`,width:`${s}px`,top:`${h}px`,left:`${r}px`}),o.$node.attribute("layout-item-ratio",o.ratio),h+=d+this._property.GAP}r+=s+this._property.GAP}if(e.length){const n=e.sort((h,o)=>o.height-h.height)[0];this.css({height:`${n.height+n.items.length*this._property.GAP}px`})}}return this}scrollCompute(){if(this.inDOM()===!1)return;const e=this.threshold();this.children.array.forEach(s=>{if(!s.isElement())return;const r=s.domRect();r.bottom<-e||r.top>innerHeight+e?s.hide(!0,!1):s.hide(!1,!1)}),this.children.render()}}$.registerTagName("layout",pt);class gt{constructor(t,e){l(this,"path");l(this,"builder");this.path=t,this.builder=e instanceof Function?e:s=>e}}class $t{constructor(t){l(this,"id");l(this,"content");l(this,"events",new V().register("open","load"));this.id=t}}_.mixin($t,ut);const g=class g{constructor(t,e){l(this,"routeMap",new Map);l(this,"recordMap",new Map);l(this,"$view");l(this,"events",new V().register("notfound","load"));l(this,"basePath");l(this,"popstate",(()=>{history.state.index>g.index||history.state.indexr.resolvePath()),g.recoveryScrollPosition(),g.events.fire("pathchange",{prevURL:e,nextURL:g.currentPath,navigation:"Forward"}),this}static back(){const t=g.currentPath;return history.back(),g.currentPath=new URL(location.href),g.events.fire("pathchange",{prevURL:t,nextURL:g.currentPath,navigation:"Back"}),this}static replace(t){if(t===void 0)return this;if(typeof t=="string"&&!t.startsWith(location.origin)&&(t=location.origin+t),t=new URL(t),t.origin!==location.origin)return this;if(t.href===location.href)return this;const e=g.currentPath;return history.replaceState({index:g.index},"",t),g.currentPath=new URL(location.href),$.routers.forEach(s=>s.resolvePath(t.pathname)),g.events.fire("pathchange",{prevURL:e,nextURL:g.currentPath,navigation:"Forward"}),this}setStateData(t,e){return history.state.data===void 0&&(history.state.data={}),history.state.data[t]=e,this}resolvePath(t=location.pathname){if(!t.startsWith(this.basePath))return;t=t.replace(this.basePath,"/").replace("//","/");let e=!1;const s=n=>{const h=this.recordMap.get(n);return h?(e=!0,h.content&&!this.$view.contains(h.content)&&this.$view.switchView(n),h.events.fire("open",{path:t,record:h}),!0):!1},r=(n,h,o)=>{const d=new $t(n);let a=h.builder({params:o,record:d,loaded:()=>{d.events.fire("load",{path:n,record:d}),this.events.fire("load",{path:n})}});typeof a=="string"&&(a=new G(a)),a!==void 0&&(d.content=a,this.recordMap.set(n,d),this.$view.setView(n,a).switchView(n),d.events.fire("open",{path:t,record:d}),e=!0)};for(const[n,h]of this.routeMap.entries()){if(n instanceof Function){const u=n(t);u&&(s(u)||r(u,h,void 0));continue}const[o,d]=[n.split("/").map(u=>`/${u}`),t.split("/").map(u=>`/${u}`)];o.shift(),d.shift();const a={};let m="";for(let u=0;un=!0;this.events.fire("notfound",{path:t,preventDefault:h}),n||this.$view.clear()}}static recoveryScrollPosition(){const t=this.getScrollHistory(this.index,location.href);t?document.documentElement.scrollTop=t.scroll:(document.documentElement.scrollTop=0,this.setScrollHistory(this.index,location.href,0))}static getScrollHistory(t,e){const s=this.scrollHistoryData;return!s||!s[t]?null:s[t].href===e?s[t]:null}static setScrollHistory(t,e,s){let r=this.scrollHistoryData;if(!r)r={[t]:{href:e,scroll:s}},sessionStorage.setItem(this.SCROLL_HISTORY_KEY,JSON.stringify(r));else{const n=r[t];if(n&&n.href!==e){let h=0;for(;r[t+h];)delete r[t+h],h++}r[t]={href:e,scroll:s},sessionStorage.setItem(this.SCROLL_HISTORY_KEY,JSON.stringify(r))}return r[t]}static get scrollHistoryData(){const t=sessionStorage.getItem(this.SCROLL_HISTORY_KEY);return t?JSON.parse(t):null}static on(t,e){return this.events.on(t,e),this}static off(t,e){return this.events.off(t,e),this}static once(t,e){return this.events.once(t,e),this}};l(g,"index",0),l(g,"events",new V().register("pathchange","notfound","load")),l(g,"currentPath",new URL(location.href)),l(g,"SCROLL_HISTORY_KEY","$router_scroll_history");let T=g;_.mixin(T,ut);window.addEventListener("scroll",()=>{T.setScrollHistory(T.index,location.href,document.documentElement.scrollTop)});Object.assign($,{routers:new Set,open(i){return T.open(i)},replace(i){return T.replace(i)},back(){return T.back()}});class Rt{constructor(t){Object.assign(this,t),this.api.endsWith("/")&&(this.api=this.api.slice(0,-1))}}class z{constructor(t){Object.assign(this,t)}static async fetch(t,e){const s=await fetch(`${t.api}/tags/${e}.json`);return new this(await s.json())}static async fetchMultiple(t,e,s=1e3){let r="";if(e)for(const[d,a]of Object.entries(e))if(a instanceof Array)r+=`&search[${d}]=${a}`;else if(a instanceof Object)for(const[m,u]of Object.entries(a))r+=`&search[${d}${m}]=${u}`;else r+=`&search[${d}]=${a}`;return(await(await fetch(`${t.api}/tags.json?limit=${s}${r}`)).json()).map(d=>{const a=new this(d);return this.manager.set(a.id,a),a})}}l(z,"manager",new Map);var P=(i=>(i[i.General=0]="General",i[i.Artist=1]="Artist",i[i.Copyright=3]="Copyright",i[i.Character=4]="Character",i[i.Meta=5]="Meta",i))(P||{});class C{constructor(t){Object.assign(this,t)}static async fetch(t,e){const s=await fetch(`${t.api}/posts/${e}.json`);return new this(await s.json())}static async fetchMultiple(t,e,s=200){let r="";if(e)for(const[d,a]of Object.entries(e))if(a instanceof Array)r+=`&search[${d}]=${a}`;else if(a instanceof Object)for(const[m,u]of Object.entries(a))r+=`&search[${d}${m}]=${u}`;else r+=`&search[${d}]=${a}`;return(await(await fetch(`${t.api}/users.json?limit=${s}${r}`)).json()).map(d=>{const a=new this(d);return this.manager.set(a.id,a),a})}}l(C,"manager",new Map);const B=1e3,j=B*60,W=j*60,F=W*24,At=F*7,k=new Intl.RelativeTimeFormat("en",{style:"long"});function Ct(i){i=Math.floor(i);const t=i/B,e=i/j,s=i/W,r=i/F,n=i%1e3,h=Math.floor(i%6e4/1e3),o=Math.floor(i%36e5/6e4),d=Math.floor(i%(36e5*24)/36e5),a=h.toString().padStart(2,"0"),m=o.toString().padStart(2,"0"),u=d.toString().padStart(2,"0");return{seconds:t,minutes:e,hours:s,days:r,mil:n,s:h,min:o,h:d,ss:a,mm:m,hh:u}}function It(i,t=Date.now()){const e=i-t,s=Math.abs(e);if(sr.update$()),r}static async fetchMultiple(t,e,s=20){let r="";if(e)if(typeof e=="string")r=e;else{r+="&tags=";for(const[a,m]of Object.entries(e)){if(a==="tags"){r+=`${m}`;continue}r.at(-1)!=="="&&(r+=" "),r+=`${a}:${m}`}}const h=await(await fetch(`${t.api}/posts.json?limit=${s}${r}&_method=get`)).json(),o=h.map(a=>{const m=new U(a);return this.manager.set(m.id,m),m}),d=[...new Set(h.map(a=>[a.approver_id,a.uploader_id].detype(null)).flat())];return C.fetchMultiple(t,{id:d}).then(()=>o.forEach(a=>a.update$())),o}update$(){var t,e;this.uploader$.set(((t=this.uploader)==null?void 0:t.name)??this.uploader_id),this.approver$.set(((e=this.approver)==null?void 0:e.name)??this.approver_id??"None"),this.created_date$.set(It(+new Date(this.created_at))),this.favorites$.set(this.fav_count),this.score$.set(this.score)}get pathname(){return`/posts/${this.id}`}get uploader(){return C.manager.get(this.uploader_id)}get approver(){return this.approver_id?C.manager.get(this.approver_id):null}get isVideo(){return this.file_ext==="mp4"||this.file_ext==="webm"||this.file_ext==="zip"}get tags(){const t=this.tag_string.split(" ");return[...z.manager.values()].filter(e=>t.includes(e.name))}};l(U,"manager",new Map);let A=U;class Nt extends pt{constructor(){super(),this.addStaticClass("post-grid"),this.type("waterfall").column(5).maxHeight(300).gap(10)}}class st extends p{constructor(e){super("post");l(this,"post");l(this,"$video");l(this,"duration$",$.state(""));this.post=e,this.$video=this.post.isVideo?$("video").width(this.post.image_width).height(this.post.image_height).disablePictureInPicture(!0).loop(!0).muted(!0).hide(!0):null,this.attribute("filetype",this.post.file_ext),this.durationUpdate(),this.build()}build(){var s,r;let e;(s=this.$video)==null||s.on("playing",(n,h)=>{e=setInterval(()=>{this.durationUpdate()},100)}),(r=this.$video)==null||r.on("pause",()=>{clearInterval(e),this.durationUpdate()}),this.content([this.post.isVideo?$("span").class("duration").content(this.duration$):null,$("a").href(this.post.pathname).content(n=>[this.$video,$("img").width(this.post.image_width).height(this.post.image_height).src(this.post.preview_file_url).loading("lazy").once("load",(h,o)=>{this.post.isVideo||o.src(this.post.large_file_url)})]).on("mouseenter",()=>{var n,h;(n=this.$video)!=null&&n.isPlaying||(h=this.$video)==null||h.src(this.post.large_file_url).hide(!1).play().catch(o=>{})}).on("mouseleave",()=>{var n;(n=this.$video)==null||n.pause().currentTime(0).hide(!0)})])}durationUpdate(){if(!this.$video)return;const e=Ct(this.post.media_asset.duration*1e3-this.$video.currentTime()*1e3);this.duration$.set(`${e.hh}:${e.mm}:${e.ss}`)}}const kt=new gt(i=>{if(i==="/posts"||i==="/")return"/"},({record:i})=>{const t=$("page").id("root");async function e(r){const n=await A.fetchMultiple(R,r.length?{tags:r}:void 0,100),h=new Nt().content([n.filter(c=>c.file_url).map(c=>new st(c))]).on("resize",()=>{u()});u();let o=n.at(-1),d=!1,a=n.length!==100;const m=$("div").class("loader").content(a?"It's End":"Loading...");return window.addEventListener("scroll",async()=>{if(!h.inDOM()||a||d||document.documentElement.scrollTopf.file_url).map(f=>new st(f))).render(),c.length!==100&&(m.content("It's End"),a=!0),o=c.at(-1),d=!1}),{$grid:h,$loader:m};function u(){if(innerWidth<350)h.column(1);else if(innerWidth<700)h.column(2);else{const c=Math.round(innerWidth/300);h.column(c)}}}const s=new Map;return i.on("open",async()=>{const r=new URL(location.href).searchParams.get("tags")??"",n=s.get(r);if(n){t.content(n),n.render();return}else t.clear();const{$grid:h,$loader:o}=await e(r);t.content([h,o]),h.render(),s.set(r,h),T.recoveryScrollPosition()}),t});class yt{constructor(t){Object.assign(this,t)}static async fetch(t,e){const s=await fetch(`${t.api}/artist_commentaries/${e}.json`);return new this(await s.json())}static async fetchMultiple(t,e,s=200){let r="";if(e)for(const[d,a]of Object.entries(e))if(a instanceof Array)r+=`&search[${d}]=${a}`;else if(a instanceof Object)for(const[m,u]of Object.entries(a))r+=`&search[${d}${m}]=${u}`;else r+=`&search[${d}]=${a}`;return(await(await fetch(`${t.api}/artist_commentaries.json?limit=${s}${r}`)).json()).map(d=>{const a=new this(d);return this.manager.set(a.id,a),a})}}l(yt,"manager",new Map);const Dt=new gt("/posts/:id",({params:i})=>{if(!Number(i.id))return"404";const t={$viewer:$("div").class("viewer"),$tags:$("div").class("post-tags"),$commentary:$("section").class("commentary")},e={uploader$:$.state("loading..."),approver$:$.state("loading..."),date$:$.state("loading..."),size$:$.state("loading..."),dimension$:$.state("loading..."),favorites$:$.state(0),score$:$.state(0),ext$:$.state("loading...")};async function s(){const r=A.manager.get(+i.id)??await A.fetch(R,+i.id);t.$viewer.content([r.isVideo?$("video").src(r.file_ext==="zip"?r.large_file_url:r.file_url).controls(!0):$("img").src(r.large_file_url).once("load",(o,d)=>{d.src(r.file_url)})]),e.uploader$.set(r.uploader$),e.approver$.set(r.approver$),e.date$.set(r.created_date$),e.size$.set(Ht(r.file_size)),e.dimension$.set(`${r.image_width}x${r.image_height}`),e.favorites$.set(r.favorites$),e.score$.set(r.score$),e.ext$.set(r.file_ext.toUpperCase()),n();async function n(){const o=await z.fetchMultiple(R,{name:{_space:r.tag_string}}),[d,a,m,u,c]=[o.filter(y=>y.category===P.Artist),o.filter(y=>y.category===P.Character),o.filter(y=>y.category===P.General),o.filter(y=>y.category===P.Meta),o.filter(y=>y.category===P.Copyright)];t.$tags.content([f("Artist",d),f("Character",a),f("Copyright",c),f("Meta",u),f("General",m)]);function f(y,w){const v=new Intl.NumberFormat("en",{notation:"compact"});return w.length?[$("h3").content(y),$("section").content([w.map(L=>$("div").class("tag").content([$("a").class("tag-name").content(L.name).href(`/posts?tags=${L.name}`),$("span").class("tag-post-count").content(`${v.format(L.post_count)}`)]))])]:null}}h();async function h(){const o=(await yt.fetchMultiple(R,{post:{_id:r.id}})).at(0);if(!o)return t.$commentary.content("No commentary");t.$commentary.content([o.original_title?$("h3").content(o.original_title):null,$("pre").content(o.original_description)])}}return s(),$("page").id("post").content([$("div").class("main").content([t.$viewer,$("h3").content("Artist's Commentary"),t.$commentary.content("loading...")]),$("div").class("sidebar").content([$("section").class("post-info").content([new S("id").name("Post").value(`#${i.id}`),new S("uploader").name("Uploader").value(e.uploader$),new S("approver").name("Approver").value(e.approver$),new S("date").name("Date").value(e.date$),new S("size").name("Size").value([e.size$,e.dimension$]),new S("file").name("File Type").value(e.ext$),$("div").class("inline").content([new S("favorites").name("Favorites").value(e.favorites$),new S("score").name("Score").value(e.score$)]),$("a").content("Copy link").href(`${R.api}${location.pathname}`).on("click",(r,n)=>{navigator.clipboard.writeText(n.href()),n.content("Copied!"),setTimeout(()=>{n.content("Copy link")},2e3)})]),t.$tags.content("loading...")])])});class S extends p{constructor(e){super("div");l(this,"$name",$("span").class("property-name"));l(this,"$values",$("div").class("property-values"));this.staticClass("property").attribute("property-id",e),this.content([this.$name,this.$values])}name(e){return this.$name.content(e),this}value(e){const s=$.orArrayResolve(e);return this.$values.content(s.map(r=>$("span").staticClass("property-value").content(r))),this}}const R=new Rt({api:"https://danbooru.donmai.us",name:"Testbooru"}),vt=new T("/");$.anchorPreventDefault=!0;$.anchorHandler=i=>{$.open(i.href())};$(document.body).content([$("app").content([vt.$view])]);vt.addRoute([kt,Dt]).listen(); diff --git a/dist/assets/index-Cq-5lgfU.css b/dist/assets/index-BMUJRc5c.css similarity index 84% rename from dist/assets/index-Cq-5lgfU.css rename to dist/assets/index-BMUJRc5c.css index 553edbf..22e53d4 100644 --- a/dist/assets/index-Cq-5lgfU.css +++ b/dist/assets/index-BMUJRc5c.css @@ -1 +1 @@ -post{display:block}post[filetype=mp4] span.duration,post[filetype=webm] span.duration,post[filetype=zip] span.duration{background-color:#fff;color:#000}post span.duration{position:absolute;background-color:#00000050;bottom:.3rem;right:.3rem;padding:2px 4px;border-radius:4px;font-size:12px;text-transform:uppercase;z-index:2}post img{border-radius:10px;height:100%;width:100%}post video{border-radius:10px;height:100%;width:100%;object-fit:cover;position:absolute}#post section{background-color:#2f2f45;border-radius:20px;padding:20px}#post div.main{width:calc(100vw - 300px - 4rem);padding-right:10px;display:flex;flex-direction:column}@media (max-width: 800px){#post div.main{width:100%}}#post div.main::-webkit-scrollbar{background-color:#000;width:4px}#post div.main::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}#post div.main>h3{padding-left:1rem;margin-block:1rem}#post div.main div.viewer{height:calc(100vh - 2rem);display:flex;justify-content:center;align-items:center;background-color:#000;border-radius:20px;overflow:hidden}#post div.main div.viewer img{max-width:100%;max-height:100%}#post div.main div.viewer video{max-width:100%;max-height:100%}#post div.main section.commentary *{text-wrap:wrap;word-break:break-word}#post div.sidebar{position:fixed;top:1rem;right:1rem;display:flex;flex-direction:column;gap:.4rem;width:300px;overflow:scroll;overflow-x:hidden;height:calc(100vh - 2rem);border-radius:20px}@media (max-width: 800px){#post div.sidebar{position:relative;width:100%;overflow:visible;height:100%;padding-inline:1rem;padding-bottom:1rem}}#post div.sidebar::-webkit-scrollbar{background-color:#000;width:0px}#post div.sidebar::-webkit-scrollbar-thumb{background-color:#aeaeec}#post div.sidebar h3{padding-left:1rem;margin-block:.6rem}#post div.sidebar .post-info{background-color:#2f2f45;border-radius:20px;padding:20px;display:flex;flex-direction:column;gap:.4rem}#post div.sidebar div.property{display:flex;gap:.6rem;align-items:center}#post div.sidebar div.property div.property-values{display:flex;gap:.4rem}#post div.sidebar div.property div.property-values span.property-value{background-color:#525278;color:#aeaeec;padding:2px 4px;border-radius:4px}#post div.sidebar div.inline{display:flex;gap:1rem}#post div.sidebar div.post-tags{display:flex;flex-direction:column;gap:.2rem}#post div.sidebar div.post-tags div.tag{align-items:center}#post div.sidebar div.post-tags div.tag a.tag-name{word-break:break-word;color:#d1d1ee;text-decoration:none}#post div.sidebar div.post-tags div.tag span.tag-post-count{background-color:#525278;color:#aeaeec;padding:0 4px;border-radius:4px;font-size:12px;margin-left:.4rem}page#root .loader{text-align:center;padding-block:2rem}body{background-color:#1e1e2c;color:#d1d1ee;margin:0;font-family:Microsoft Yahei;font-size:14px}body::-webkit-scrollbar{background-color:#000;width:8px}body::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}app{display:block}app view{display:block}app view page{min-height:100%;padding:1rem;display:block} +post{display:block}post[filetype=mp4] span.duration,post[filetype=webm] span.duration,post[filetype=zip] span.duration{background-color:#fff;color:#000}post span.duration{position:absolute;background-color:#00000050;bottom:.3rem;right:.3rem;padding:2px 4px;border-radius:4px;font-size:12px;text-transform:uppercase;z-index:2}post img{border-radius:10px;height:100%;width:100%}post video{border-radius:10px;height:100%;width:100%;object-fit:cover;position:absolute}#post section{background-color:#2f2f45;border-radius:20px;padding:20px}#post div.main{width:calc(100vw - 300px - 4rem);padding-right:10px;display:flex;flex-direction:column}@media (max-width: 800px){#post div.main{width:100%}}#post div.main::-webkit-scrollbar{background-color:#000;width:4px}#post div.main::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}#post div.main>h3{padding-left:1rem;margin-block:1rem}#post div.main div.viewer{height:calc(100vh - 2rem);display:flex;justify-content:center;align-items:center;background-color:#000;border-radius:20px;overflow:hidden}#post div.main div.viewer img{max-width:100%;max-height:100%}#post div.main div.viewer video{max-width:100%;max-height:100%}#post div.main section.commentary *{text-wrap:wrap;word-break:break-word}#post div.sidebar{position:fixed;top:1rem;right:1rem;display:flex;flex-direction:column;gap:.4rem;width:300px;overflow:scroll;overflow-x:hidden;height:calc(100vh - 2rem);border-radius:20px}@media (max-width: 800px){#post div.sidebar{position:relative;width:100%;overflow:visible;height:100%;padding-inline:1rem;padding-bottom:1rem}}#post div.sidebar::-webkit-scrollbar{background-color:#000;width:0px}#post div.sidebar::-webkit-scrollbar-thumb{background-color:#aeaeec}#post div.sidebar h3{padding-left:1rem;margin-block:.6rem}#post div.sidebar .post-info{background-color:#2f2f45;border-radius:20px;padding:20px;display:flex;flex-direction:column;gap:.4rem}#post div.sidebar div.property{display:flex;gap:.6rem;align-items:center}#post div.sidebar div.property div.property-values{display:flex;gap:.4rem}#post div.sidebar div.property div.property-values span.property-value{background-color:#525278;color:#aeaeec;padding:2px 4px;border-radius:4px}#post div.sidebar div.inline{display:flex;gap:1rem}#post div.sidebar div.post-tags{display:flex;flex-direction:column;gap:.2rem}#post div.sidebar div.post-tags div.tag{align-items:center}#post div.sidebar div.post-tags div.tag a.tag-name{word-break:break-word;color:#d1d1ee;text-decoration:none}#post div.sidebar div.post-tags div.tag span.tag-post-count{background-color:#525278;color:#aeaeec;padding:0 4px;border-radius:4px;font-size:12px;margin-left:.4rem}page#root layout *{transition:all .3s ease}page#root .loader{text-align:center;padding-block:2rem}html{overflow-x:hidden}body{background-color:#1e1e2c;color:#d1d1ee;margin:0;font-family:Microsoft Yahei;font-size:14px}body::-webkit-scrollbar{background-color:#000;width:8px}body::-webkit-scrollbar-thumb{background-color:#aeaeec;border-radius:2px}app{display:block}app view{display:block}app view page{min-height:100%;padding:1rem;display:block} diff --git a/dist/assets/index-DR9E_CfL.js b/dist/assets/index-DR9E_CfL.js new file mode 100644 index 0000000..6ebe47d --- /dev/null +++ b/dist/assets/index-DR9E_CfL.js @@ -0,0 +1 @@ +var _t=Object.defineProperty;var bt=(i,t,e)=>t in i?_t(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var c=(i,t,e)=>(bt(i,typeof t!="symbol"?t+"":t,e),e),Q=(i,t,e)=>{if(!t.has(i))throw TypeError("Cannot "+e)};var Z=(i,t,e)=>(Q(i,t,"read from private field"),e?e.call(i):t.get(i)),tt=(i,t,e)=>{if(t.has(i))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(i):t.set(i,e)},et=(i,t,e,s)=>(Q(i,t,"write to private field"),s?s.call(i,e):t.set(i,e),e);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const n of r)if(n.type==="childList")for(const h of n.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&s(h)}).observe(document,{childList:!0,subtree:!0});function e(r){const n={};return r.integrity&&(n.integrity=r.integrity),r.referrerPolicy&&(n.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?n.credentials="include":r.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function s(r){if(r.ep)return;r.ep=!0;const n=e(r);fetch(r.href,n)}})();class M{constructor(){c(this,"__hidden",!1);c(this,"domEvents",{});c(this,"parent")}on(t,e,s){this.domEvents[t]||(this.domEvents[t]=new Map);const r=n=>e(n,this);return this.domEvents[t].set(e,r),this.dom.addEventListener(t,r,s),this}off(t,e,s){var n;const r=(n=this.domEvents[t])==null?void 0:n.get(e);return r&&this.dom.removeEventListener(t,r,s),this}once(t,e,s){const r=n=>{this.dom.removeEventListener(t,r,s),e(n,this)};return this.dom.addEventListener(t,r,s),this}hide(t,e=!0){return _.fluent(this,arguments,()=>this.__hidden,()=>{var s;if(t!==void 0)return t instanceof O?(this.__hidden=t.value,t.use(this,"hide")):this.__hidden=t,e&&((s=this.parent)==null||s.children.render()),this})}remove(){var t;return(t=this.parent)==null||t.children.remove(this).render(),this}replace(t){var e;return(e=this.parent)==null||e.children.replace(this,t).render(),this}contains(t){return t?t instanceof M?this.dom.contains(t.dom):t instanceof EventTarget?this.dom.contains(_(t).dom):this.dom.contains(t):!1}self(t){return t(this),this}inDOM(){return document.contains(this.dom)}isElement(){return this instanceof E}}class E extends M{constructor(e,s){super();c(this,"dom");c(this,"static_classes",new Set);this.dom=this.createDom(e,s),this.dom.$=this,this.setOptions(s)}createDom(e,s){return s!=null&&s.dom?s.dom:e==="svg"?document.createElementNS("http://www.w3.org/2000/svg","svg"):document.createElement(e)}setOptions(e){return this.id(e==null?void 0:e.id),e&&e.class&&this.class(...e.class),this}id(e){return $.fluent(this,arguments,()=>this.dom.id,()=>$.set(this.dom,"id",e))}class(...e){return $.fluent(this,arguments,()=>this.dom.classList,()=>{this.dom.classList.forEach(s=>this.static_classes.has(s)??this.dom.classList.remove(s)),this.dom.classList.add(...e.detype())})}addClass(...e){return $.fluent(this,arguments,()=>this,()=>{this.dom.classList.add(...e.detype())})}removeClass(...e){return $.fluent(this,arguments,()=>this,()=>{this.dom.classList.remove(...e.detype())})}staticClass(...e){return $.fluent(this,arguments,()=>this.static_classes,()=>{this.removeClass(...this.static_classes),this.static_classes.clear(),this.addStaticClass(...e)})}addStaticClass(...e){return $.fluent(this,arguments,()=>this,()=>{e.detype().forEach(s=>this.static_classes.add(s)),this.addClass(...e)})}removeStaticClass(...e){return $.fluent(this,arguments,()=>this,()=>{e.detype().forEach(s=>this.static_classes.delete(s)),this.removeClass(...e)})}css(e){return $.fluent(this,arguments,()=>this.dom.style,()=>{Object.assign(this.dom.style,e)})}attribute(e,s){return arguments.length?arguments.length===1?e===void 0?null:this.dom.getAttribute(e):arguments.length===2?e?(s===null?this.dom.removeAttribute(e):s!==void 0&&this.dom.setAttribute(e,`${s}`),this):this:this:null}tabIndex(e){return $.fluent(this,arguments,()=>this.dom.tabIndex,()=>$.set(this.dom,"tabIndex",e))}focus(){return this.dom.focus(),this}blur(){return this.dom.blur(),this}animate(e,s,r){const n=this.dom.animate(e,s);return r&&r(n),this}getAnimations(e){return this.dom.getAnimations(e)}get dataset(){return this.dom.dataset}domRect(e){const s=this.dom.getBoundingClientRect();if(!e)return s;const r=e instanceof E?e.dom.getBoundingClientRect():e;return{...s,top:s.top-r.top,left:s.left-r.left,right:s.right-r.left,bottom:s.bottom-r.top,x:s.x-r.x,y:s.y-r.y}}}class I extends M{constructor(e){super();c(this,"dom");this.dom=e,this.dom.$=this}domRect(e){const s={bottom:innerHeight,height:innerHeight,left:0,right:innerWidth,top:0,width:innerWidth,x:0,y:0};if(!e)return s;const r=e instanceof E?e.dom.getBoundingClientRect():e;return{...s,top:s.top-r.top,left:s.left-r.left,right:s.right-r.left,bottom:s.bottom-r.top,x:s.x-r.x,y:s.y-r.y}}static from(e){return e.$ instanceof I?e.$:new I(e)}}class Ot{constructor(t){c(this,"$container");c(this,"childList",new Set);this.$container=t}add(t,e=-1){if(e===-1||this.childList.size-1===e)this.childList.add(t),t.parent=this.$container;else{const s=[...this.childList];s.splice(e,0,t),this.childList.clear(),s.forEach(r=>this.childList.add(r))}}remove(t){return this.childList.has(t)?(this.childList.delete(t),t.parent=void 0,this):this}removeAll(t=!0){this.childList.forEach(e=>this.remove(e)),t&&this.render()}replace(t,e){const s=this.array;return s.splice(s.indexOf(t),1,e),t.remove(),this.childList.clear(),s.forEach(r=>this.childList.add(r)),this}render(){const[t,e]=[this.array.map(r=>r.dom),Array.from(this.dom.childNodes)],s=[];for(;e.length||t.length;){const[r,n]=[e.at(0),t.at(0)];n?r?n!==r?(n.$.__hidden||(this.dom.insertBefore(n,r),s.push(n)),t.shift()):(n.$.__hidden&&this.dom.removeChild(n),t.shift(),e.shift()):(n.$.__hidden||this.dom.append(n),t.shift()):(r&&!s.includes(r)&&r.remove(),e.shift())}}get array(){return[...this.childList.values()]}get dom(){return this.$container.dom}}class O{constructor(t,e){c(this,"_value");c(this,"attributes",new Map);c(this,"linkStates",new Set);c(this,"options",{});this.set(t),e&&(this.options=e)}set(t){this._value=t,t instanceof O&&t.linkStates.add(this),this.update(),this.linkStates.forEach(e=>e.update())}update(){for(const[t,e]of this.attributes.entries())for(const s of e)t[s]instanceof Function?this.options.format?t[s](this.options.format(this.value)):t[s](this.value):s in t&&(t[s]=this.value)}toString(){return this.options.format?this.options.format(this.value):this.value instanceof Object?JSON.stringify(this.toJSON()):`${this.value}`}use(t,e){const s=this.attributes.get(t);s?s.add(e):this.attributes.set(t,new Set().add(e))}toJSON(){return this.value instanceof O?this.value.toJSON():this.value instanceof Object?O.toJSON(this.value):this.toString()}static toJSON(t){const e={};for(let[s,r]of Object.entries(t))r instanceof O?r=r.toJSON():r instanceof Object&&O.toJSON(r),Object.assign(e,{[s]:r});return e}get value(){return this._value instanceof O?this._value.value:this._value}}class V extends M{constructor(e){super();c(this,"dom");this.dom=new Text(e),this.dom.$=this}content(e){return $.fluent(this,arguments,()=>this.dom.textContent,()=>$.set(this.dom,"textContent",e))}}class j extends E{constructor(t,e){super(t,e)}autocapitalize(t){return $.fluent(this,arguments,()=>this.dom.autocapitalize,()=>$.set(this.dom,"autocapitalize",t))}innerText(t){return $.fluent(this,arguments,()=>this.dom.innerText,()=>$.set(this.dom,"innerText",t))}title(t){return $.fluent(this,arguments,()=>this.dom.title,()=>$.set(this.dom,"title",t))}dir(t){return $.fluent(this,arguments,()=>this.dom.dir,()=>$.set(this.dom,"dir",t))}translate(t){return $.fluent(this,arguments,()=>this.dom.translate,()=>$.set(this.dom,"translate",t))}popover(t){return $.fluent(this,arguments,()=>this.dom.popover,()=>$.set(this.dom,"popover",t))}spellcheck(t){return $.fluent(this,arguments,()=>this.dom.spellcheck,()=>$.set(this.dom,"spellcheck",t))}inert(t){return $.fluent(this,arguments,()=>this.dom.inert,()=>$.set(this.dom,"inert",t))}lang(t){return $.fluent(this,arguments,()=>this.dom.lang,()=>$.set(this.dom,"lang",t))}draggable(t){return $.fluent(this,arguments,()=>this.dom.draggable,()=>$.set(this.dom,"draggable",t))}hidden(t){return $.fluent(this,arguments,()=>this.dom.hidden,()=>$.set(this.dom,"hidden",t))}click(){return this.dom.click(),this}attachInternals(){return this.dom.attachInternals()}hidePopover(){return this.dom.hidePopover(),this}showPopover(){return this.dom.showPopover(),this}togglePopover(){return this.dom.togglePopover(),this}get accessKeyLabel(){return this.dom.accessKeyLabel}get offsetHeight(){return this.dom.offsetHeight}get offsetLeft(){return this.dom.offsetLeft}get offsetParent(){return $(this.dom.offsetParent)}get offsetTop(){return this.dom.offsetTop}get offsetWidth(){return this.dom.offsetWidth}}class p extends j{constructor(e,s){super(e,s);c(this,"children",new Ot(this));c(this,"__position_cursor",0)}content(e){return $.fluent(this,arguments,()=>this,()=>{this.children.removeAll(!1),this.insert(e)})}insert(e,s=-1){return $.fluent(this,arguments,()=>this,()=>{e instanceof Function&&(e=e(this)),e=$.orArrayResolve(e),this.__position_cursor=s<0?this.children.array.length+s:s;for(const r of e)if(r!=null){if(r instanceof Array)this.insert(r,this.__position_cursor);else if(typeof r=="string")this.children.add(new V(r),s);else if(r instanceof O){const n=new V(r.toString());r.use(n,"content"),this.children.add(n,s)}else this.children.add(r,s);this.__position_cursor+=1}this.children.render()})}clear(){return this.children.removeAll(),this}$(e){return $(this.dom.querySelector(e))}$all(e){return Array.from(this.dom.querySelectorAll(e)).map(s=>$(s))}get scrollHeight(){return this.dom.scrollHeight}get scrollWidth(){return this.dom.scrollWidth}scrollTop(e){return $.fluent(this,arguments,()=>this.dom.scrollTop,()=>$.set(this.dom,"scrollTop",e))}scrollLeft(e){return $.fluent(this,arguments,()=>this.dom.scrollLeft,()=>$.set(this.dom,"scrollLeft",e))}}class Tt extends p{constructor(t){super("a",t),this.dom.addEventListener("click",e=>{$.anchorPreventDefault&&e.preventDefault(),$.anchorHandler&&this.href()&&$.anchorHandler(this,e)})}href(t){return $.fluent(this,arguments,()=>this.dom.href,()=>{t&&(this.dom.href=t)})}target(t){return $.fluent(this,arguments,()=>this.dom.target??void 0,()=>{t&&(this.dom.target=t)})}}class Lt extends E{constructor(t,e){super(t,e)}}var b;(i=>{function t(o,d,a,l){return d.length?(l(),o):a()}i.fluent=t;function e(o){return o instanceof Array?o:[o]}i.orArrayResolve=e;function s(o,d){return e(d).forEach(a=>{Object.getOwnPropertyNames(a.prototype).forEach(l=>{l!=="constructor"&&Object.defineProperty(o.prototype,l,Object.getOwnPropertyDescriptor(a.prototype,l)||Object.create(null))})}),o}i.mixin=s;function r(o,d,a){a!==void 0&&(o[d]=a)}i.set=r;function n(o){return new O(o)}i.state=n;function h(o){if(o.$)return o.$;if(o.nodeName.toLowerCase()==="body")return new p("body",{dom:o});if(o.nodeName.toLowerCase()==="#document")return I.from(o);if(o instanceof HTMLElement){const d=$.TagNameElementMap[o.tagName.toLowerCase()],a=d===p?new d(o.tagName,{dom:o}):new d({dom:o});if(a instanceof p)for(const l of Array.from(a.dom.childNodes))a.children.add($(l));return a}else if(o instanceof Text){const d=new V(o.textContent??"");return d.dom=o,d}else if(o instanceof SVGElement&&o.tagName.toLowerCase()==="svg")return new Lt("svg",{dom:o});throw`$NODE.FROM: NOT SUPPORT TARGET ELEMENT TYPE (${o.nodeName})`}i.from=h})(b||(b={}));class T{static create(...t){const e=class{};return Object.getOwnPropertyNames(T.prototype).forEach(s=>{s!=="constructor"&&t.includes(s)&&Object.defineProperty(e.prototype,s,Object.getOwnPropertyDescriptor(T.prototype,s)||Object.create(null))}),e}disabled(t){return $.fluent(this,arguments,()=>this.dom.disabled,()=>$.set(this.dom,"disabled",t))}checkValidity(){return this.dom.checkValidity()}reportValidity(){return this.dom.reportValidity()}formAction(t){return $.fluent(this,arguments,()=>this.dom.formAction,()=>$.set(this.dom,"formAction",t))}formEnctype(t){return $.fluent(this,arguments,()=>this.dom.formEnctype,()=>$.set(this.dom,"formEnctype",t))}formMethod(t){return $.fluent(this,arguments,()=>this.dom.formMethod,()=>$.set(this.dom,"formMethod",t))}formNoValidate(t){return $.fluent(this,arguments,()=>this.dom.formNoValidate,()=>$.set(this.dom,"formNoValidate",t))}formTarget(t){return $.fluent(this,arguments,()=>this.dom.formTarget,()=>$.set(this.dom,"formTarget",t))}autocomplete(t){return $.fluent(this,arguments,()=>this.dom.autocomplete,()=>$.set(this.dom,"autocomplete",t))}name(t){return $.fluent(this,arguments,()=>this.dom.name,()=>$.set(this.dom,"name",t))}maxLength(t){return $.fluent(this,arguments,()=>this.dom.maxLength,()=>$.set(this.dom,"maxLength",t))}minLength(t){return $.fluent(this,arguments,()=>this.dom.minLength,()=>$.set(this.dom,"minLength",t))}required(t){return $.fluent(this,arguments,()=>this.dom.required,()=>$.set(this.dom,"required",t))}label(t){return $.fluent(this,arguments,()=>this.dom.label,()=>$.set(this.dom,"label",t))}get form(){return this.dom.form?$(this.dom.form):null}get validationMessage(){return this.dom.validationMessage}get validity(){return this.dom.validity}get willValidate(){return this.dom.willValidate}}class at extends p{constructor(t){super("button",t)}type(t){return $.fluent(this,arguments,()=>this.dom.type,()=>$.set(this.dom,"type",t))}}b.mixin(at,T.create("disabled","checkValidity","formAction","formEnctype","formMethod","formNoValidate","formTarget","reportValidity"));class ht extends p{constructor(t){super("form",t)}action(t){return $.fluent(this,arguments,()=>this.dom.formAction,()=>$.set(this.dom,"formAction",t))}enctype(t){return $.fluent(this,arguments,()=>this.dom.formEnctype,()=>$.set(this.dom,"formEnctype",t))}method(t){return $.fluent(this,arguments,()=>this.dom.formMethod,()=>$.set(this.dom,"formMethod",t))}noValidate(t){return $.fluent(this,arguments,()=>this.dom.formNoValidate,()=>$.set(this.dom,"formNoValidate",t))}acceptCharset(t){return $.fluent(this,arguments,()=>this.dom.acceptCharset,()=>$.set(this.dom,"acceptCharset",t))}target(t){return $.fluent(this,arguments,()=>this.dom.formTarget,()=>$.set(this.dom,"formTarget",t))}requestSubmit(){return this.dom.requestSubmit(),this}reset(){return this.dom.reset(),this}submit(){return this.dom.submit(),this}get length(){return this.dom.length}get elements(){return Array.from(this.dom.elements).map(t=>$(t))}}b.mixin(ht,T.create("checkValidity","reportValidity","autocomplete"));class ut extends E{constructor(t){super("input",t)}value(t){return $.fluent(this,arguments,()=>this.type()==="number"?Number(this.dom.value):this.dom.value,()=>$.set(this.dom,"value",t,e=>{this.on("input",()=>{e.attributes.has(this.dom)!==!1&&(typeof e.value=="string"&&e.set(`${this.value()}`),typeof e.value=="number"&&e.set(Number(this.value())))})}))}type(t){return $.fluent(this,arguments,()=>this.dom.type,()=>$.set(this.dom,"type",t))}capture(t){return $.fluent(this,arguments,()=>this.dom.capture,()=>$.set(this.dom,"capture",t))}alt(t){return $.fluent(this,arguments,()=>this.dom.alt,()=>$.set(this.dom,"alt",t))}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>$.set(this.dom,"height",t))}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>$.set(this.dom,"width",t))}defaultValue(t){return $.fluent(this,arguments,()=>this.dom.defaultValue,()=>$.set(this.dom,"defaultValue",t))}dirName(t){return $.fluent(this,arguments,()=>this.dom.dirName,()=>$.set(this.dom,"dirName",t))}pattern(t){return $.fluent(this,arguments,()=>this.dom.pattern,()=>$.set(this.dom,"pattern",t))}placeholder(t){return $.fluent(this,arguments,()=>this.dom.placeholder,()=>$.set(this.dom,"placeholder",t))}readOnly(t){return $.fluent(this,arguments,()=>this.dom.readOnly,()=>$.set(this.dom,"readOnly",t))}selectionDirection(t){return $.fluent(this,arguments,()=>this.dom.selectionDirection,()=>$.set(this.dom,"selectionDirection",t))}selectionEnd(t){return $.fluent(this,arguments,()=>this.dom.selectionEnd,()=>$.set(this.dom,"selectionEnd",t))}selectionStart(t){return $.fluent(this,arguments,()=>this.dom.selectionStart,()=>$.set(this.dom,"selectionStart",t))}size(t){return $.fluent(this,arguments,()=>this.dom.size,()=>$.set(this.dom,"size",t))}src(t){return $.fluent(this,arguments,()=>this.dom.src,()=>$.set(this.dom,"src",t))}inputMode(t){return $.fluent(this,arguments,()=>this.dom.inputMode,()=>$.set(this.dom,"inputMode",t))}valueAsDate(t){return $.fluent(this,arguments,()=>this.dom.valueAsDate,()=>$.set(this.dom,"valueAsDate",t))}valueAsNumber(t){return $.fluent(this,arguments,()=>this.dom.valueAsNumber,()=>$.set(this.dom,"valueAsNumber",t))}webkitdirectory(t){return $.fluent(this,arguments,()=>this.dom.webkitdirectory,()=>$.set(this.dom,"webkitdirectory",t))}select(){return this.dom.select(),this}setCustomValidity(t){return this.dom.setCustomValidity(t),this}setRangeText(t,e,s,r){return typeof e=="number"&&typeof s=="number"&&this.dom.setRangeText(t,e,s,r),this.dom.setRangeText(t),this}setSelectionRange(t,e,s){return this.dom.setSelectionRange(t,e,s),this}showPicker(){return this.dom.showPicker(),this}get files(){return this.dom.files}get webkitEntries(){return this.dom.webkitEntries}get labels(){return Array.from(this.dom.labels??[]).map(t=>$(t))}}b.mixin(ut,T.create("checkValidity","reportValidity","autocomplete","name","form","required","validationMessage","validity","willValidate","formAction","formEnctype","formMethod","formNoValidate","formTarget"));class dt extends p{constructor(t){super("label",t)}for(t){return $.fluent(this,arguments,()=>this.dom.htmlFor,()=>{$.set(this.dom,"htmlFor",t)})}get control(){return this.dom.control}}b.mixin(dt,T.create("form"));class Et extends j{constructor(t){super("img",t)}async load(t){return new Promise(e=>{const s=this.once("load",()=>{e(s)});typeof t=="string"?s.src(t):t.then(r=>s.src(r))})}static resize(t,e){return new Promise(s=>{const r=new Image;if(r.addEventListener("load",()=>{const n=document.createElement("canvas"),h=n.getContext("2d");if(!h)throw"$Image.resize: context undefined";const o=r.width/r.height,[d,a,l]=[o>1,o<1,o===1],u=e instanceof Array?e[0]:a?e:e*o,m=e instanceof Array?e[1]:d?e:e/o;n.height=m,n.width=u,h.drawImage(r,0,0,u,m),s(n.toDataURL())},{once:!0}),t instanceof File){const n=new FileReader;n.addEventListener("load",()=>r.src=n.result),n.readAsDataURL(t)}else r.src=t})}alt(t){return $.fluent(this,arguments,()=>this.dom.alt,()=>$.set(this.dom,"alt",t))}crossOrigin(t){return $.fluent(this,arguments,()=>this.dom.crossOrigin,()=>$.set(this.dom,"crossOrigin",t))}decoding(t){return $.fluent(this,arguments,()=>this.dom.decoding,()=>$.set(this.dom,"decoding",t))}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>$.set(this.dom,"height",t))}isMap(t){return $.fluent(this,arguments,()=>this.dom.isMap,()=>$.set(this.dom,"isMap",t))}loading(t){return $.fluent(this,arguments,()=>this.dom.loading,()=>$.set(this.dom,"loading",t))}referrerPolicy(t){return $.fluent(this,arguments,()=>this.dom.referrerPolicy,()=>$.set(this.dom,"referrerPolicy",t))}sizes(t){return $.fluent(this,arguments,()=>this.dom.sizes,()=>$.set(this.dom,"sizes",t))}src(t){return $.fluent(this,arguments,()=>this.dom.src,()=>$.set(this.dom,"src",t))}srcset(t){return $.fluent(this,arguments,()=>this.dom.srcset,()=>$.set(this.dom,"srcset",t))}useMap(t){return $.fluent(this,arguments,()=>this.dom.useMap,()=>$.set(this.dom,"useMap",t))}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>$.set(this.dom,"width",t))}decode(){return this.dom.decode()}get complete(){return this.dom.complete}get currentSrc(){return this.dom.currentSrc}get naturalHeight(){return this.dom.naturalHeight}get naturalWidth(){return this.dom.naturalWidth}get x(){return this.dom.x}get y(){return this.dom.y}}class xt extends p{constructor(t){super("canvas",t)}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>{$.set(this.dom,"height",t)})}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>{$.set(this.dom,"width",t)})}captureStream(t){return this.dom.captureStream(t)}getContext(t,e){return this.dom.getContext(t)}toBlob(t,e,s){return this.dom.toBlob(t,e,s),this}toDataURL(t,e){return this.dom.toDataURL(t,e)}transferControlToOffscreen(){return this.dom.transferControlToOffscreen()}}class St extends p{constructor(t){super("dialog",t)}open(t){return $.fluent(this,arguments,()=>this.dom.open,()=>$.set(this.dom,"open",t))}returnValue(t){return $.fluent(this,arguments,()=>this.dom.returnValue,()=>$.set(this.dom,"returnValue",t))}close(){return this.dom.close(),this}show(){return this.dom.show(),this}showModal(){return this.dom.showModal(),this}}class ct{on(t,e){return this.events.on(t,e),this}off(t,e){return this.events.off(t,e),this}once(t,e){return this.events.once(t,e),this}}class W{constructor(){c(this,"eventMap",new Map)}register(...t){return t.forEach(e=>{const s=new st(e);this.eventMap.set(s.name,s)}),this}delete(t){return this.eventMap.delete(t),this}fire(t,...e){const s=this.get(t);return s instanceof st&&s.fire(...e),this}on(t,e){return this.get(t).add(e),this}off(t,e){return this.get(t).delete(e),this}once(t,e){const s=(...r)=>{this.get(t).delete(s),e(...r)};return this.get(t).add(s),this}get(t){const e=this.eventMap.get(t);if(!e)throw new Error("EVENT NOT EXIST");return e}}class st{constructor(t){c(this,"name");c(this,"callbackList",new Set);this.name=t}fire(...t){this.callbackList.forEach(e=>e(...t))}add(t){this.callbackList.add(t)}delete(t){this.callbackList.delete(t)}}class lt extends p{constructor(e){super("view",e);c(this,"view_cache",new Map);c(this,"event",new W().register("switch"));c(this,"content_id",null)}setView(e,s){return this.view_cache.set(e,s),this}deleteView(e){return this.view_cache.delete(e),this}deleteAllView(){return this.view_cache.clear(),this}switchView(e){const s=this.view_cache.get(e);return s===void 0?this:(this.content(s),this.content_id=e,this.event.fire("switch",e),this)}}class mt extends p{constructor(t){super("select")}add(t){return this.insert(t),this}item(t){return $(this.dom.item(t))}namedItem(t){return $(this.dom.namedItem(t))}multiple(t){return $.fluent(this,arguments,()=>this.dom.multiple,()=>$.set(this.dom,"multiple",t))}get length(){return this.dom.length}get size(){return this.dom.size}get options(){return Array.from(this.dom.options).map(t=>$(t))}get selectedIndex(){return this.dom.selectedIndex}get selectedOptions(){return Array.from(this.dom.selectedOptions).map(t=>$(t))}value(t){return $.fluent(this,arguments,()=>this.dom.value,()=>$.set(this.dom,"value",t))}get labels(){return Array.from(this.dom.labels??[]).map(t=>$(t))}}b.mixin(mt,T.create("checkValidity","reportValidity","autocomplete","name","form","required","disabled","validationMessage","validity","willValidate"));class ft extends p{constructor(t){super("option",t)}defaultSelected(t){return $.fluent(this,arguments,()=>this.dom.defaultSelected,()=>$.set(this.dom,"defaultSelected",t))}selected(t){return $.fluent(this,arguments,()=>this.dom.selected,()=>$.set(this.dom,"selected",t))}text(t){return $.fluent(this,arguments,()=>this.dom.text,()=>$.set(this.dom,"text",t))}value(t){return $.fluent(this,arguments,()=>this.dom.value,()=>$.set(this.dom,"value",t))}get form(){return this.dom.form?$(this.dom.form):null}get index(){return this.dom.index}}b.mixin(ft,T.create("form","disabled","label"));class pt extends p{constructor(t){super("optgroup",t)}disabled(t){return $.fluent(this,arguments,()=>this.dom.disabled,()=>$.set(this.dom,"disabled",t))}}b.mixin(pt,T.create("disabled","label"));class gt extends p{constructor(t){super("textarea",t)}cols(t){return $.fluent(this,arguments,()=>this.dom.cols,()=>$.set(this.dom,"cols",t))}wrap(t){return $.fluent(this,arguments,()=>this.dom.wrap,()=>$.set(this.dom,"wrap",t))}value(t){return $.fluent(this,arguments,()=>this.dom.value,()=>$.set(this.dom,"value",t))}defaultValue(t){return $.fluent(this,arguments,()=>this.dom.defaultValue,()=>$.set(this.dom,"defaultValue",t))}dirName(t){return $.fluent(this,arguments,()=>this.dom.dirName,()=>$.set(this.dom,"dirName",t))}placeholder(t){return $.fluent(this,arguments,()=>this.dom.placeholder,()=>$.set(this.dom,"placeholder",t))}readOnly(t){return $.fluent(this,arguments,()=>this.dom.readOnly,()=>$.set(this.dom,"readOnly",t))}selectionDirection(t){return $.fluent(this,arguments,()=>this.dom.selectionDirection,()=>$.set(this.dom,"selectionDirection",t))}selectionEnd(t){return $.fluent(this,arguments,()=>this.dom.selectionEnd,()=>$.set(this.dom,"selectionEnd",t))}selectionStart(t){return $.fluent(this,arguments,()=>this.dom.selectionStart,()=>$.set(this.dom,"selectionStart",t))}type(t){return $.fluent(this,arguments,()=>this.dom.type,()=>$.set(this.dom,"type",t))}inputMode(t){return $.fluent(this,arguments,()=>this.dom.inputMode,()=>$.set(this.dom,"inputMode",t))}select(){return this.dom.select(),this}setCustomValidity(t){return this.dom.setCustomValidity(t),this}setRangeText(t,e,s,r){return typeof e=="number"&&typeof s=="number"&&this.dom.setRangeText(t,e,s,r),this.dom.setRangeText(t),this}setSelectionRange(t,e,s){return this.dom.setSelectionRange(t,e,s),this}get labels(){return Array.from(this.dom.labels??[]).map(t=>$(t))}}b.mixin(gt,T.create("checkValidity","reportValidity","autocomplete","name","form","required","disabled","minLength","maxLength","validationMessage","validity","willValidate"));var N;class Mt extends p{constructor(e){super("async",e);tt(this,N,!1)}await(e){return e.then(s=>this._loaded(s)),this}_loaded(e){et(this,N,!0),this.replace(e),this.dom.dispatchEvent(new Event("load"))}get loaded(){return Z(this,N)}}N=new WeakMap;class Pt extends E{constructor(t,e){super(t,e)}autoplay(t){return $.fluent(this,arguments,()=>this.dom.autoplay,()=>$.set(this.dom,"autoplay",t))}get buffered(){return this.dom.buffered}controls(t){return $.fluent(this,arguments,()=>this.dom.controls,()=>$.set(this.dom,"controls",t))}crossOrigin(t){return $.fluent(this,arguments,()=>this.dom.crossOrigin,()=>$.set(this.dom,"crossOrigin",t))}get currentSrc(){return this.dom.currentSrc}currentTime(t){return $.fluent(this,arguments,()=>this.dom.currentTime,()=>$.set(this.dom,"currentTime",t))}defaultMuted(t){return $.fluent(this,arguments,()=>this.dom.defaultMuted,()=>$.set(this.dom,"defaultMuted",t))}defaultPlaybackRate(t){return $.fluent(this,arguments,()=>this.dom.defaultPlaybackRate,()=>$.set(this.dom,"defaultPlaybackRate",t))}disableRemotePlayback(t){return $.fluent(this,arguments,()=>this.dom.disableRemotePlayback,()=>$.set(this.dom,"disableRemotePlayback",t))}get duration(){return this.dom.duration}get ended(){return this.dom.ended}get error(){return this.dom.error}loop(t){return $.fluent(this,arguments,()=>this.dom.loop,()=>$.set(this.dom,"loop",t))}mediaKeys(t){return $.fluent(this,arguments,()=>this.dom.mediaKeys,()=>$.set(this.dom,"setMediaKeys",[t]))}muted(t){return $.fluent(this,arguments,()=>this.dom.muted,()=>$.set(this.dom,"muted",t))}get networkState(){return this.dom.networkState}get paused(){return this.dom.paused}playbackRate(t){return $.fluent(this,arguments,()=>this.dom.playbackRate,()=>$.set(this.dom,"playbackRate",t))}get played(){return this.dom.played}preload(t){return $.fluent(this,arguments,()=>this.dom.preload,()=>$.set(this.dom,"preload",t))}preservesPitch(t){return $.fluent(this,arguments,()=>this.dom.preservesPitch,()=>$.set(this.dom,"preservesPitch",t))}get readyState(){return this.dom.readyState}get remote(){return this.dom.remote}get seekable(){return this.dom.seekable}get seeking(){return this.dom.seeking}sinkId(t){return $.fluent(this,arguments,()=>this.dom.sinkId,()=>$.set(this.dom,"setSinkId",[t]))}src(t){return $.fluent(this,arguments,()=>this.dom.src,()=>$.set(this.dom,"src",t))}srcObject(t){return $.fluent(this,arguments,()=>this.dom.srcObject,()=>$.set(this.dom,"srcObject",t))}get textTracks(){return this.dom.textTracks}volume(t){return $.fluent(this,arguments,()=>this.dom.volume,()=>$.set(this.dom,"volume",t))}addTextTrack(t,e,s){return this.dom.addTextTrack(t,e,s)}canPlayType(t){return this.dom.canPlayType(t)}fastSeek(t){return this.dom.fastSeek(t),this}load(){return this.dom.load(),this}pause(){return this.dom.pause(),this}async play(){return await this.dom.play(),this}get isPlaying(){return this.currentTime()>0&&!this.paused&&!this.ended&&this.readyState>2}}class Rt extends Pt{constructor(t){super("video",t)}disablePictureInPicture(t){return $.fluent(this,arguments,()=>this.dom.disablePictureInPicture,()=>$.set(this.dom,"disablePictureInPicture",t))}height(t){return $.fluent(this,arguments,()=>this.dom.height,()=>$.set(this.dom,"height",t))}width(t){return $.fluent(this,arguments,()=>this.dom.width,()=>$.set(this.dom,"width",t))}playsInline(t){return $.fluent(this,arguments,()=>this.dom.playsInline,()=>$.set(this.dom,"playsInline",t))}poster(t){return $.fluent(this,arguments,()=>this.dom.poster,()=>$.set(this.dom,"poster",t))}get videoHeight(){return this.dom.videoHeight}get videoWidth(){return this.dom.videoWidth}cancelVideoFrameCallback(t){return this.dom.cancelVideoFrameCallback(t),this}getVideoPlaybackQuality(){return this.dom.getVideoPlaybackQuality()}requestPictureInPicture(){return this.dom.requestPictureInPicture()}requestVideoFrameCallback(t){return this.dom.requestVideoFrameCallback(t)}}function _(i){if(typeof i>"u"||i===null||i instanceof M)return i;if(typeof i=="string"){if(i.startsWith("::"))return Array.from(document.querySelectorAll(i.replace(/^::/,""))).map(t=>_(t));if(i.startsWith(":"))return _(document.querySelector(i.replace(/^:/,"")));if(i in _.TagNameElementMap){const t=_.TagNameElementMap[i];return t===j?new j(i):t===p?new p(i):new t}else return new p(i)}if(i instanceof Node)return i.$?i.$:b.from(i);throw`$: NOT SUPPORT TARGET ELEMENT TYPE ('${i}')`}(i=>{i.anchorHandler=null,i.anchorPreventDefault=!1,i.TagNameElementMap={document:I,body:p,a:Tt,p,pre:p,code:p,blockquote:p,strong:p,h1:p,h2:p,h3:p,h4:p,h5:p,h6:p,div:p,ol:p,ul:p,dl:p,li:p,input:ut,label:dt,button:at,form:ht,img:Et,dialog:St,canvas:xt,view:lt,select:mt,option:ft,optgroup:pt,textarea:gt,video:Rt,async:Mt};function t(u,m,g,f){return m.length?(f(),u):g()}i.fluent=t;function e(u){return u instanceof Array?u:[u]}i.orArrayResolve=e;function s(u,m){return b.mixin(u,m)}i.mixin=s;function r(u,m,g,f){if(g!==void 0){if(g instanceof O){g.use(u,m),u[m]instanceof Function?u[m](...g.value):u[m]=g.value,f&&f(g);return}u[m]instanceof Function?u[m](...g):u[m]=g}}i.set=r;function n(u,m){return new O(u,m)}i.state=n;async function h(u,m){return new Promise(g=>{const f=new FileReader;f.onload=w=>{const v=i("img");if(v.once("load",H=>{const q=i("canvas"),z=q.getContext("2d"),D=v.height()/v.width(),[K,X]=[D>1?m/D:m,D>1?m:m*D];q.height(X).width(K),z==null||z.drawImage(v.dom,0,0,K,X),g(q.toDataURL(u.type))}),!w.target)throw"$.resize(): e.target is null";v.src(w.target.result)},f.readAsDataURL(u)})}i.resize=h;function o(u=1){return parseInt(getComputedStyle(document.documentElement).fontSize)*u}i.rem=o;function d(u){const m=new DOMParser().parseFromString(u,"text/html").body;return Array.from(m.children).map(g=>i(g))}i.html=d;function a(u,m,g){if(typeof m=="number")return Array(m).fill("").map(w=>{const v=f(u)?u[0](...u.slice(1)):i(u);return g&&g(v),v});{const w=[];for(const v of m){const H=u instanceof Function?u(...v):f(u)?u[0](...u.slice(1)):i(u);v instanceof Function?v(H):(v instanceof M||typeof v=="string")&&H.content(v),w.push(H)}return w}function f(w){return w instanceof Array&&w[0]instanceof Function}}i.builder=a;function l(u,m){return Object.assign(i.TagNameElementMap,{[u]:m}),i.TagNameElementMap}i.registerTagName=l})(_||(_={}));globalThis.$=_;Array.prototype.detype=function(...i){return this.filter(t=>{if(i.length)for(const e of i)return typeof t!=typeof e;else return t!==void 0})};class At extends p{constructor(e){super("layout",e);c(this,"_property",{ROW_MAX_HEIGHT:200,GAP:0,IS_RENDERING:!1,RENDER_REQUEST:!1,COLUNM:1,TYPE:"justified",ROOT:null,THRESHOLD:null});this.css({display:"block",position:"relative"}),new ResizeObserver(s=>{this.inDOM()&&(this.render(),this.scrollCompute(),this.dom.dispatchEvent(new Event("resize")))}).observe(this.dom),document.addEventListener("scroll",s=>{s.target===this.root().dom&&this.scrollCompute()})}type(e){return $.fluent(this,arguments,()=>this._property.TYPE,()=>$.set(this._property,"TYPE",e))}maxHeight(e){return $.fluent(this,arguments,()=>this._property.ROW_MAX_HEIGHT,()=>$.set(this._property,"ROW_MAX_HEIGHT",e))}column(e){return $.fluent(this,arguments,()=>this._property.COLUNM,()=>$.set(this._property,"COLUNM",e))}gap(e){return $.fluent(this,arguments,()=>this._property.GAP,()=>$.set(this._property,"GAP",e))}root(e){return $.fluent(this,arguments,()=>this._property.ROOT??$(document),()=>$.set(this._property,"ROOT",e))}threshold(e){return $.fluent(this,arguments,()=>this._property.THRESHOLD??innerHeight,()=>$.set(this._property,"THRESHOLD",e))}get COL_WIDTH(){return(this.offsetWidth-this._property.GAP*(this._property.COLUNM-1))/this._property.COLUNM}computeLayout(){return this._property.TYPE==="justified"?this.justifiedCompute():this.justifiedCompute()}justifiedCompute(){const e=[],s=this.offsetWidth;for(const r of this.children.array){const n=$(r);if(!(n instanceof E))continue;const h=n.attribute("layout-item-ratio"),o=h?parseFloat(h):n.dom.offsetWidth/n.dom.offsetHeight,d={$node:n,ratio:o};let a=e.at(-1);(!a||a.heightl+=g.ratio);const u=l+o,m=(s-this._property.GAP*a.items.length)/u;a.items.push(d),a.ratio=u,a.height=m}return e}waterfallCompute(){const e=[],s=this.COL_WIDTH,r=()=>{if(e.lengthn.height-h.height)[0]};for(const n of this.children.array){const h=$(n);if(!(h instanceof E))continue;const o=h.attribute("layout-item-ratio"),d=o?parseFloat(o):h.dom.offsetWidth/h.dom.offsetHeight,a={$node:h,ratio:d},l=r();let u=0;l.items.forEach(f=>u+=f.ratio);const m=s/(l.height+s/d),g=s/m;l.items.push(a),l.ratio=m,l.height=g}return e}render(){if(this._property.TYPE==="justified"){const e=this.justifiedCompute();let s=0;for(const r of e){let n=0;r.height>this._property.ROW_MAX_HEIGHT&&(r.height=this._property.ROW_MAX_HEIGHT);for(const h of r.items){const o=h.ratio*r.height;h.$node.css({position:"absolute",height:`${r.height}px`,width:`${o}px`,top:`${s}px`,left:`${n}px`}),h.$node.attribute("layout-item-ratio",h.ratio),n+=r.height*h.ratio+this._property.GAP}s+=r.height+this._property.GAP}this.css({height:`${s}px`})}else if(this._property.TYPE="waterfall"){const e=this.waterfallCompute(),s=this.COL_WIDTH;let r=0;for(const n of e){let h=0;for(const o of n.items){const d=s/o.ratio;o.$node.css({position:"absolute",height:`${d}px`,width:`${s}px`,top:`${h}px`,left:`${r}px`}),o.$node.attribute("layout-item-ratio",o.ratio),h+=d+this._property.GAP}r+=s+this._property.GAP}if(e.length){const n=e.sort((h,o)=>o.height-h.height)[0];this.css({height:`${n.height+n.items.length*this._property.GAP}px`})}}return this.scrollCompute(),this}scrollCompute(){if(this.inDOM()===!1)return;const e=this.threshold();this.children.array.forEach(s=>{if(!s.isElement())return;const r=s.domRect();r.bottom<-e||r.top>innerHeight+e?s.hide(!0,!1):s.hide(!1,!1)}),this.children.render()}}$.registerTagName("layout",At);class $t{constructor(t,e){c(this,"path");c(this,"builder");this.path=t,this.builder=e instanceof Function?e:s=>e}}class yt{constructor(t){c(this,"id");c(this,"content");c(this,"events",new W().register("open","load"));this.id=t}}b.mixin(yt,ct);const y=class y{constructor(t,e){c(this,"routeMap",new Map);c(this,"recordMap",new Map);c(this,"$view");c(this,"events",new W().register("notfound","load"));c(this,"basePath");c(this,"popstate",(()=>{history.state.index>y.index||history.state.indexr.resolvePath()),y.recoveryScrollPosition(),y.events.fire("pathchange",{prevURL:e,nextURL:y.currentPath,navigation:"Forward"}),this}static back(){const t=y.currentPath;return history.back(),y.currentPath=new URL(location.href),y.events.fire("pathchange",{prevURL:t,nextURL:y.currentPath,navigation:"Back"}),this}static replace(t){if(t===void 0)return this;if(typeof t=="string"&&!t.startsWith(location.origin)&&(t=location.origin+t),t=new URL(t),t.origin!==location.origin)return this;if(t.href===location.href)return this;const e=y.currentPath;return history.replaceState({index:y.index},"",t),y.currentPath=new URL(location.href),$.routers.forEach(s=>s.resolvePath(t.pathname)),y.events.fire("pathchange",{prevURL:e,nextURL:y.currentPath,navigation:"Forward"}),this}setStateData(t,e){return history.state.data===void 0&&(history.state.data={}),history.state.data[t]=e,this}resolvePath(t=location.pathname){if(!t.startsWith(this.basePath))return;t=t.replace(this.basePath,"/").replace("//","/");let e=!1;const s=n=>{const h=this.recordMap.get(n);return h?(e=!0,h.content&&!this.$view.contains(h.content)&&this.$view.switchView(n),h.events.fire("open",{path:t,record:h}),!0):!1},r=(n,h,o)=>{const d=new yt(n);let a=h.builder({params:o,record:d,loaded:()=>{d.events.fire("load",{path:n,record:d}),this.events.fire("load",{path:n})}});typeof a=="string"&&(a=new V(a)),a!==void 0&&(d.content=a,this.recordMap.set(n,d),this.$view.setView(n,a).switchView(n),d.events.fire("open",{path:t,record:d}),e=!0)};for(const[n,h]of this.routeMap.entries()){if(n instanceof Function){const u=n(t);u&&(s(u)||r(u,h,void 0));continue}const[o,d]=[n.split("/").map(u=>`/${u}`),t.split("/").map(u=>`/${u}`)];o.shift(),d.shift();const a={};let l="";for(let u=0;un=!0;this.events.fire("notfound",{path:t,preventDefault:h}),n||this.$view.clear()}}static recoveryScrollPosition(){const t=this.getScrollHistory(this.index,location.href);t?document.documentElement.scrollTop=t.scroll:(document.documentElement.scrollTop=0,this.setScrollHistory(this.index,location.href,0))}static getScrollHistory(t,e){const s=this.scrollHistoryData;return!s||!s[t]?null:s[t].href===e?s[t]:null}static setScrollHistory(t,e,s){let r=this.scrollHistoryData;if(!r)r={[t]:{href:e,scroll:s}},sessionStorage.setItem(this.SCROLL_HISTORY_KEY,JSON.stringify(r));else{const n=r[t];if(n&&n.href!==e){let h=0;for(;r[t+h];)delete r[t+h],h++}r[t]={href:e,scroll:s},sessionStorage.setItem(this.SCROLL_HISTORY_KEY,JSON.stringify(r))}return r[t]}static get scrollHistoryData(){const t=sessionStorage.getItem(this.SCROLL_HISTORY_KEY);return t?JSON.parse(t):null}static on(t,e){return this.events.on(t,e),this}static off(t,e){return this.events.off(t,e),this}static once(t,e){return this.events.once(t,e),this}};c(y,"index",0),c(y,"events",new W().register("pathchange","notfound","load")),c(y,"currentPath",new URL(location.href)),c(y,"SCROLL_HISTORY_KEY","$router_scroll_history");let L=y;b.mixin(L,ct);window.addEventListener("scroll",()=>{L.setScrollHistory(L.index,location.href,document.documentElement.scrollTop)});Object.assign($,{routers:new Set,open(i){return L.open(i)},replace(i){return L.replace(i)},back(){return L.back()}});class Ct{constructor(t){Object.assign(this,t),this.api.endsWith("/")&&(this.api=this.api.slice(0,-1))}}const It=new Intl.NumberFormat("en",{notation:"compact"});class B{constructor(t){c(this,"post_count$",$.state(0,{format:t=>`${It.format(t)}`}));c(this,"name$",$.state(""));Object.assign(this,t),this.$update()}static async fetch(t,e){var n;const s=await fetch(`${t.api}/tags/${e}.json`).then(async h=>await h.json()),r=((n=this.manager.get(s.id))==null?void 0:n.update(s))??new this(s);return this.manager.set(r.id,r),r}static async fetchMultiple(t,e,s=1e3){let r="";if(e)for(const[d,a]of Object.entries(e))if(a instanceof Array)r+=`&search[${d}]=${a}`;else if(a instanceof Object)for(const[l,u]of Object.entries(a))r+=`&search[${d}${l}]=${u}`;else r+=`&search[${d}]=${a}`;return(await(await fetch(`${t.api}/tags.json?limit=${s}${r}`)).json()).map(d=>{var l;const a=((l=this.manager.get(d.id))==null?void 0:l.update(d))??new this(d);return this.manager.set(a.id,a),a})}update(t){return Object.assign(this,t),this.$update(),this}$update(){this.post_count$.set(this.post_count),this.name$.set(this.name)}}c(B,"manager",new Map);var P=(i=>(i[i.General=0]="General",i[i.Artist=1]="Artist",i[i.Copyright=3]="Copyright",i[i.Character=4]="Character",i[i.Meta=5]="Meta",i))(P||{});class C{constructor(t){c(this,"name$",$.state("loding..."));Object.assign(this,t),this.update$()}static async fetch(t,e){var n;const s=await fetch(`${t.api}/users/${e}.json`).then(async h=>await h.json()),r=((n=this.manager.get(s.id))==null?void 0:n.update(s))??new this(s);return this.manager.set(r.id,r),r}static async fetchMultiple(t,e,s=200){let r="";if(e)for(const[d,a]of Object.entries(e))if(a instanceof Array)r+=`&search[${d}]=${a}`;else if(a instanceof Object)for(const[l,u]of Object.entries(a))r+=`&search[${d}${l}]=${u}`;else r+=`&search[${d}]=${a}`;return(await(await fetch(`${t.api}/users.json?limit=${s}${r}`)).json()).map(d=>{const a=new this(d);return this.manager.set(a.id,a),a})}update(t){return Object.assign(this,t),this.update$(),this}update$(){this.name$.set(this.name)}}c(C,"manager",new Map);const J=1e3,F=J*60,U=F*60,G=U*24,Nt=G*7,k=new Intl.RelativeTimeFormat("en",{style:"long"});function Ht(i){i=Math.floor(i);const t=i/J,e=i/F,s=i/U,r=i/G,n=i%1e3,h=Math.floor(i%6e4/1e3),o=Math.floor(i%36e5/6e4),d=Math.floor(i%(36e5*24)/36e5),a=h.toString().padStart(2,"0"),l=o.toString().padStart(2,"0"),u=d.toString().padStart(2,"0");return{seconds:t,minutes:e,hours:s,days:r,mil:n,s:h,min:o,h:d,ss:a,mm:l,hh:u}}function Dt(i,t=Date.now()){const e=i-t,s=Math.abs(e);if(sawait h.json()),r=((n=this.manager.get(s.id))==null?void 0:n.update(s))??new this(s);return this.manager.set(r.id,r),C.fetchMultiple(t,{id:[r.uploader_id,r.approver_id].detype(null)}).then(()=>r.update$()),r}static async fetchMultiple(t,e,s=20){let r="";if(e)if(typeof e=="string")r=e;else{r+="&tags=";for(const[a,l]of Object.entries(e)){if(a==="tags"){r+=`${l}`;continue}r.at(-1)!=="="&&(r+=" "),r+=`${a}:${l}`}}const h=await(await fetch(`${t.api}/posts.json?limit=${s}${r}&_method=get`)).json(),o=h.map(a=>{var u;const l=((u=this.manager.get(a.id))==null?void 0:u.update(a))??new this(a);return this.manager.set(l.id,l),l});if(!o.length)return o;const d=[...new Set(h.map(a=>[a.approver_id,a.uploader_id].detype(null)).flat())];return C.fetchMultiple(t,{id:d}).then(()=>o.forEach(a=>a.update$())),o}update$(){var t,e,s;this.uploader$.set(((t=this.uploader)==null?void 0:t.name$)??this.uploader_id.toString()),this.approver$.set(((e=this.approver)==null?void 0:e.name$)??((s=this.approver_id)==null?void 0:s.toString())??"None"),this.created_date$.set(Dt(+new Date(this.created_at))),this.favorites$.set(this.fav_count),this.score$.set(this.score)}update(t){return Object.assign(this,t),this.update$(),this}get pathname(){return`/posts/${this.id}`}get uploader(){return C.manager.get(this.uploader_id)}get approver(){return this.approver_id?C.manager.get(this.approver_id):null}get isVideo(){return this.file_ext==="mp4"||this.file_ext==="webm"||this.file_ext==="zip"}get tags(){const t=this.tag_string.split(" ");return[...B.manager.values()].filter(e=>t.includes(e.name))}}c(R,"manager",new Map);class Y extends p{constructor(e){super("post");c(this,"post");c(this,"$video");c(this,"duration$",$.state(""));this.post=e,this.$video=this.post.isVideo?$("video").width(this.post.image_width).height(this.post.image_height).disablePictureInPicture(!0).loop(!0).muted(!0).hide(!0):null,this.attribute("filetype",this.post.file_ext),this.durationUpdate(),this.build()}build(){var s,r;let e;(s=this.$video)==null||s.on("playing",(n,h)=>{e=setInterval(()=>{this.durationUpdate()},100)}),(r=this.$video)==null||r.on("pause",()=>{clearInterval(e),this.durationUpdate()}),this.content([this.post.isVideo?$("span").class("duration").content(this.duration$):null,$("a").href(this.post.pathname).content(n=>[this.$video,$("img").width(this.post.image_width).height(this.post.image_height).src(this.post.preview_file_url).loading("lazy").once("load",(h,o)=>{this.post.isVideo||o.src(this.post.large_file_url)})]).on("mouseenter",()=>{var n,h;(n=this.$video)!=null&&n.isPlaying||(h=this.$video)==null||h.src(this.post.large_file_url).hide(!1).play().catch(o=>{})}).on("mouseleave",()=>{var n;(n=this.$video)==null||n.pause().currentTime(0).hide(!0)})])}durationUpdate(){if(!this.$video)return;const e=Ht(this.post.media_asset.duration*1e3-this.$video.currentTime()*1e3);this.duration$.set(`${e.hh}:${e.mm}:${e.ss}`)}}const A=100,Vt=new $t(i=>{if(i==="/posts"||i==="/")return"/"},({record:i})=>{const t=$("page").id("root");async function e(r){const n=await R.fetchMultiple(S,r.length?{tags:r}:void 0,A),h=n.filter(f=>f.file_url),o=$("layout").class("post-grid").type("waterfall").column(5).maxHeight(300).gap(10).content([h.map(f=>new Y(f))]).on("resize",()=>{g()});g();let d=n.at(1),a=n.at(-1),l=!1,u=n.length!==A;const m=$("div").class("loader").content(u?"It's End":"Loading...");return window.addEventListener("scroll",async()=>{if(!o.inDOM()||u||l||document.documentElement.scrollTopw.file_url).map(w=>new Y(w))).render(),f.length!==A&&(m.content("It's End"),u=!0),a=f.at(-1),l=!1}),setInterval(async()=>{if(!o.inDOM()||document.documentElement.scrollTop!==0)return;const f=await R.fetchMultiple(S,r.length?{tags:r,id:`${d.id+2}..`}:{id:`${d.id+2}..`},A),w=f.filter(v=>v.file_url);f.length&&(d=f.at(0)),w.length&&o.insert(w.map(v=>new Y(v)),0).render()},1e4),{$layout:o,$loader:m};function g(){if(innerWidth<350)o.column(1);else if(innerWidth<700)o.column(2);else{const f=Math.round(innerWidth/300);o.column(f)}}}const s=new Map;return i.on("open",async()=>{const r=new URL(location.href).searchParams.get("tags")??"",n=s.get(r);if(n){t.content(n),n.render();return}else t.clear();const{$layout:h,$loader:o}=await e(r);t.content([h,o]),h.render(),s.set(r,h),L.recoveryScrollPosition()}),t});class vt{constructor(t){Object.assign(this,t)}static async fetch(t,e){const s=await fetch(`${t.api}/artist_commentaries/${e}.json`);return new this(await s.json())}static async fetchMultiple(t,e,s=200){let r="";if(e)for(const[d,a]of Object.entries(e))if(a instanceof Array)r+=`&search[${d}]=${a}`;else if(a instanceof Object)for(const[l,u]of Object.entries(a))r+=`&search[${d}${l}]=${u}`;else r+=`&search[${d}]=${a}`;return(await(await fetch(`${t.api}/artist_commentaries.json?limit=${s}${r}`)).json()).map(d=>{const a=new this(d);return this.manager.set(a.id,a),a})}}c(vt,"manager",new Map);const jt=new $t("/posts/:id",({params:i})=>{if(!Number(i.id))return"404";const t={$viewer:$("div").class("viewer"),$tags:$("div").class("post-tags"),$commentary:$("section").class("commentary")},e={uploader$:$.state("loading..."),approver$:$.state("loading..."),date$:$.state("loading..."),size$:$.state("loading..."),dimension$:$.state("loading..."),favorites$:$.state(0),score$:$.state(0),ext$:$.state("loading...")};async function s(){const r=R.manager.get(+i.id)??await R.fetch(S,+i.id);t.$viewer.content([r.isVideo?$("video").src(r.file_ext==="zip"?r.large_file_url:r.file_url).controls(!0):$("img").src(r.large_file_url).once("load",(o,d)=>{d.src(r.file_url)})]),e.uploader$.set(r.uploader$),e.approver$.set(r.approver$),e.date$.set(r.created_date$),e.size$.set(kt(r.file_size)),e.dimension$.set(`${r.image_width}x${r.image_height}`),e.favorites$.set(r.favorites$),e.score$.set(r.score$),e.ext$.set(r.file_ext.toUpperCase()),n(),h();async function n(){const o=await B.fetchMultiple(S,{name:{_space:r.tag_string}}),[d,a,l,u,m]=[o.filter(f=>f.category===P.Artist),o.filter(f=>f.category===P.Character),o.filter(f=>f.category===P.General),o.filter(f=>f.category===P.Meta),o.filter(f=>f.category===P.Copyright)];t.$tags.content([g("Artist",d),g("Character",a),g("Copyright",m),g("Meta",u),g("General",l)]);function g(f,w){return w.length?[$("h3").content(f),$("section").content([w.map(v=>$("div").class("tag").content([$("a").class("tag-name").content(v.name).href(`/posts?tags=${v.name}`),$("span").class("tag-post-count").content(v.post_count$)]))])]:null}}async function h(){const o=(await vt.fetchMultiple(S,{post:{_id:r.id}})).at(0);if(!o)return t.$commentary.content("No commentary");t.$commentary.content([o.original_title?$("h3").content(o.original_title):null,$("pre").content(o.original_description)])}}return s(),$("page").id("post").content([$("div").class("main").content([t.$viewer,$("h3").content("Artist's Commentary"),t.$commentary.content("loading...")]),$("div").class("sidebar").content([$("section").class("post-info").content([new x("id").name("Post").value(`#${i.id}`),new x("uploader").name("Uploader").value(e.uploader$),new x("approver").name("Approver").value(e.approver$),new x("date").name("Date").value(e.date$),new x("size").name("Size").value([e.size$,e.dimension$]),new x("file").name("File Type").value(e.ext$),$("div").class("inline").content([new x("favorites").name("Favorites").value(e.favorites$),new x("score").name("Score").value(e.score$)]),$("a").content("Copy link").href(`${S.api}${location.pathname}`).on("click",(r,n)=>{navigator.clipboard.writeText(n.href()),n.content("Copied!"),setTimeout(()=>{n.content("Copy link")},2e3)})]),t.$tags.content("loading...")])])});class x extends p{constructor(e){super("div");c(this,"$name",$("span").class("property-name"));c(this,"$values",$("div").class("property-values"));this.staticClass("property").attribute("property-id",e),this.content([this.$name,this.$values])}name(e){return this.$name.content(e),this}value(e){const s=$.orArrayResolve(e);return this.$values.content(s.map(r=>$("span").staticClass("property-value").content(r))),this}}const S=new Ct({api:"https://danbooru.donmai.us",name:"Testbooru"}),wt=new L("/");$.anchorPreventDefault=!0;$.anchorHandler=i=>{$.open(i.href())};$(document.body).content([$("app").content([wt.$view])]);wt.addRoute([Vt,jt]).listen(); diff --git a/dist/index.html b/dist/index.html index 0263aa2..f17ee7e 100644 --- a/dist/index.html +++ b/dist/index.html @@ -5,8 +5,8 @@ Danbooru Viewer v0.1 - - + + diff --git a/index.scss b/index.scss index c2c12ef..bdc11a8 100644 --- a/index.scss +++ b/index.scss @@ -1,8 +1,11 @@ @import '/src/component/PostGrid/$PostGrid'; @import '/src/component/PostTile/$PostTile'; @import '/src/route/posts/$post'; -@import '/src/route/home/$home'; +@import '/src/route/gallery/$gallery'; +html { + overflow-x: hidden; +} body { background-color: #1e1e2c; color: #d1d1ee; diff --git a/src/main.ts b/src/main.ts index 3dec0c7..7b4dba4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,7 @@ import '@elexis/layout'; import '@elexis/router'; import { Booru } from './structure/Booru'; import { Router } from '@elexis/router'; -import { home_route } from './route/home/$home'; +import { home_route } from './route/gallery/$gallery'; import { posts_route } from './route/posts/$post'; export const booru = new Booru({ diff --git a/src/route/gallery/$gallery.ts b/src/route/gallery/$gallery.ts new file mode 100644 index 0000000..4a4d99d --- /dev/null +++ b/src/route/gallery/$gallery.ts @@ -0,0 +1,84 @@ +import { Route, Router } from "@elexis/router"; +import { Post } from "../../structure/Post"; +import { booru } from "../../main"; +import { $PostGrid } from "../../component/PostGrid/$PostGrid"; +import { $PostTile } from "../../component/PostTile/$PostTile"; +const MAX_POST_LENGTH = 100; +export const home_route = new Route((path) => { + if (path === '/posts' || path === '/') return '/'; +}, ({record}) => { + const $page = $('page').id('root'); + async function load(tags: string) { + const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags} : undefined, MAX_POST_LENGTH) + const filtered_posts = posts.filter(post => post.file_url); + const $layout = $('layout').class('post-grid').type('waterfall').column(5).maxHeight(300).gap(10) + .content([ + filtered_posts.map(post => new $PostTile(post)) + ]).on('resize', () => { resizeCheck() }); + resizeCheck(); + let FIRST_POST = posts.at(1)!; + let LAST_POST = posts.at(-1)!; + let SCROLL_LOADED = false; + let POST_ENDED = posts.length !== MAX_POST_LENGTH; + const $loader = $('div').class('loader').content( POST_ENDED ? `It's End` : 'Loading...'); + window.addEventListener('scroll', async () => { + if (!$layout.inDOM()) return; + if (POST_ENDED) return; + if (SCROLL_LOADED) return; + if (document.documentElement.scrollTop < document.documentElement.scrollHeight - innerHeight * 3) return; + SCROLL_LOADED = true; + const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags, id: `..${LAST_POST.id - 1}`} : {id: `..${LAST_POST.id - 1}`}, MAX_POST_LENGTH) + $layout.insert( + posts.filter(post => post.file_url).map(post => new $PostTile(post)) + ).render(); + if (posts.length !== MAX_POST_LENGTH) { + $loader.content(`It's End`); + POST_ENDED = true; + } + LAST_POST = posts.at(-1)!; + SCROLL_LOADED = false; + }) + + setInterval(async () => { + if (!$layout.inDOM()) return; + if (document.documentElement.scrollTop !== 0) return; + const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags, id: `${FIRST_POST.id + 2}..`} : {id: `${FIRST_POST.id + 2}..`}, MAX_POST_LENGTH) + const filtered_posts = posts.filter(post => post.file_url) + if (posts.length) FIRST_POST = posts.at(0)!; + if (filtered_posts.length) $layout.insert(filtered_posts.map(post => new $PostTile(post)), 0).render(); + }, 10_000) + + return {$layout, $loader} + + function resizeCheck() { + if (innerWidth < 350) $layout.column(1); + else if (innerWidth < 700) $layout.column(2); + else { + const col = Math.round(innerWidth / 300) + $layout.column(col); + } + } + } + + const gridManager = new Map(); + record.on('open', async () => { + const tags = new URL(location.href).searchParams.get('tags') ?? ''; + const $cacheGrid = gridManager.get(tags); + if ($cacheGrid) { + $page.content($cacheGrid); + $cacheGrid.render(); + return; + } else { + $page.clear(); + } + const {$layout, $loader} = await load(tags); + $page.content([ + $layout, + $loader + ]); + $layout.render(); + gridManager.set(tags, $layout); + Router.recoveryScrollPosition(); + }) + return $page; +}) \ No newline at end of file diff --git a/src/route/home/_$home.scss b/src/route/gallery/_$gallery.scss similarity index 52% rename from src/route/home/_$home.scss rename to src/route/gallery/_$gallery.scss index b8eb88c..9c0dd58 100644 --- a/src/route/home/_$home.scss +++ b/src/route/gallery/_$gallery.scss @@ -1,4 +1,10 @@ page#root { + + layout { + * { + transition: all 0.3s ease; + } + } .loader { text-align: center; padding-block: 2rem; diff --git a/src/route/home/$home.ts b/src/route/home/$home.ts deleted file mode 100644 index f311fdf..0000000 --- a/src/route/home/$home.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Route, Router } from "@elexis/router"; -import { Post } from "../../structure/Post"; -import { booru } from "../../main"; -import { $PostGrid } from "../../component/PostGrid/$PostGrid"; -import { $PostTile } from "../../component/PostTile/$PostTile"; - -export const home_route = new Route((path) => { - if (path === '/posts' || path === '/') return '/'; -}, ({record}) => { - const $page = $('page').id('root'); - async function load(tags: string) { - const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags} : undefined, 100) - const $grid = new $PostGrid().content([ - posts.filter(post => post.file_url).map(post => new $PostTile(post)) - ]).on('resize', () => { resizeCheck() }); - resizeCheck(); - let last_post = posts.at(-1)!; - let loaded = false; - let ended = posts.length !== 100; - const $loader = $('div').class('loader').content( ended ? `It's End` : 'Loading...'); - window.addEventListener('scroll', async () => { - if (!$grid.inDOM()) return; - if (ended) return; - if (loaded) return; - if (document.documentElement.scrollTop < document.documentElement.scrollHeight - innerHeight * 3) return; - loaded = true; - const posts = await Post.fetchMultiple(booru, tags.length ? {tags: tags, id: `..${last_post.id - 1}`} : {id: `..${last_post.id - 1}`}, 100) - $grid.insert( - posts.filter(post => post.file_url).map(post => new $PostTile(post)) - ).render(); - if (posts.length !== 100) { - $loader.content(`It's End`); - ended = true; - } - last_post = posts.at(-1)!; - loaded = false; - }) - - return {$grid, $loader} - - function resizeCheck() { - if (innerWidth < 350) $grid.column(1); - else if (innerWidth < 700) $grid.column(2); - else { - const col = Math.round(innerWidth / 300) - $grid.column(col); - } - } - } - - const gridManager = new Map(); - record.on('open', async () => { - const tags = new URL(location.href).searchParams.get('tags') ?? ''; - const $cacheGrid = gridManager.get(tags); - if ($cacheGrid) { - $page.content($cacheGrid); - $cacheGrid.render(); - return; - } else { - $page.clear(); - } - const {$grid, $loader} = await load(tags); - $page.content([ - $grid, - $loader - ]); - $grid.render(); - gridManager.set(tags, $grid); - Router.recoveryScrollPosition(); - }) - return $page; -}) \ No newline at end of file diff --git a/src/route/posts/$post.ts b/src/route/posts/$post.ts index 86e4f9b..031fa37 100644 --- a/src/route/posts/$post.ts +++ b/src/route/posts/$post.ts @@ -14,8 +14,8 @@ export const posts_route = new Route('/posts/:id', ({params}) => { $commentary: $('section').class('commentary') } const value = { - uploader$: $.state('loading...'), - approver$: $.state('loading...'), + uploader$: $.state('loading...'), + approver$: $.state('loading...'), date$: $.state('loading...'), size$: $.state('loading...'), dimension$: $.state(`loading...`), @@ -39,6 +39,8 @@ export const posts_route = new Route('/posts/:id', ({params}) => { value.score$.set(post.score$) value.ext$.set(post.file_ext.toUpperCase()) loadTags(); + loadCommentary(); + async function loadTags() { const tags = await Tag.fetchMultiple(booru, {name: {_space: post.tag_string}}); const [artist_tags, char_tags, gen_tags, meta_tags, copy_tags] = [ @@ -57,19 +59,17 @@ export const posts_route = new Route('/posts/:id', ({params}) => { ]) function tag_category(category: string, tags: Tag[]) { - const INTL_number = new Intl.NumberFormat('en', {notation: 'compact'}) return tags.length ? [ $('h3').content(category), $('section').content([ tags.map(tag => $('div').class('tag').content([ $('a').class('tag-name').content(tag.name).href(`/posts?tags=${tag.name}`), - $('span').class('tag-post-count').content(`${INTL_number.format(tag.post_count)}`) + $('span').class('tag-post-count').content(tag.post_count$) ])) ]) ] : null } } - loadCommentary(); async function loadCommentary() { const commentary = (await ArtistCommentary.fetchMultiple(booru, {post: {_id: post.id}})).at(0); if (!commentary) return ele.$commentary.content('No commentary'); @@ -99,13 +99,14 @@ export const posts_route = new Route('/posts/:id', ({params}) => { new $Property('favorites').name('Favorites').value(value.favorites$), new $Property('score').name('Score').value(value.score$) ]), - $('a').content('Copy link').href(`${booru.api}${location.pathname}`).on('click', (e, $a) => { - navigator.clipboard.writeText($a.href()); - $a.content('Copied!'); - setTimeout(() => { - $a.content('Copy link') - }, 2000); - }) + $('a').content('Copy link').href(`${booru.api}${location.pathname}`) + .on('click', (e, $a) => { + navigator.clipboard.writeText($a.href()); + $a.content('Copied!'); + setTimeout(() => { + $a.content('Copy link') + }, 2000); + }) ]), ele.$tags.content('loading...') ]) diff --git a/src/structure/Post.ts b/src/structure/Post.ts index 391ec16..4a5972b 100644 --- a/src/structure/Post.ts +++ b/src/structure/Post.ts @@ -7,8 +7,8 @@ export interface PostOptions {} export interface Post extends PostData {} export class Post { static manager = new Map(); - uploader$ = $.state(this.uploader?.name ?? this.uploader_id); - approver$ = $.state(this.approver?.name ?? this.approver_id ?? 'None'); + uploader$ = $.state(this.uploader?.name$ ?? this.uploader_id?.toString()); + approver$ = $.state(this.approver?.name$ ?? this.approver_id?.toString() ?? 'None'); created_date$ = $.state(``); favorites$ = $.state(this.fav_count); score$ = $.state(this.score); @@ -18,10 +18,11 @@ export class Post { } static async fetch(booru: Booru, id: id) { - const req = await fetch(`${booru.api}/posts/${id}.json`); - const post = new this(await req.json()); - User.fetchMultiple(booru, {id: [post.uploader_id, post.approver_id].detype(null)}).then(() => post.update$()); - return post; + const data = await fetch(`${booru.api}/posts/${id}.json`).then(async data => await data.json()) as PostData; + const instance = this.manager.get(data.id)?.update(data) ?? new this(data); + this.manager.set(instance.id, instance); + User.fetchMultiple(booru, {id: [instance.uploader_id, instance.approver_id].detype(null)}).then(() => instance.update$()); + return instance; } static async fetchMultiple(booru: Booru, tags?: Partial | string, limit = 20) { @@ -40,23 +41,30 @@ export class Post { const req = await fetch(`${booru.api}/posts.json?limit=${limit}${tagsQuery}&_method=get`); const dataArray: PostData[] = await req.json(); const list = dataArray.map(data => { - const instance = new Post(data); + const instance = this.manager.get(data.id)?.update(data) ?? new this(data); this.manager.set(instance.id, instance); return instance; }); + if (!list.length) return list; const userIds = [...new Set(dataArray.map(data => [data.approver_id, data.uploader_id].detype(null)).flat())]; User.fetchMultiple(booru, {id: userIds}).then(() => list.forEach(post => post.update$())); return list; } update$() { - this.uploader$.set(this.uploader?.name ?? this.uploader_id); - this.approver$.set(this.approver?.name ?? this.approver_id ?? 'None'); + this.uploader$.set(this.uploader?.name$ ?? this.uploader_id.toString()); + this.approver$.set(this.approver?.name$ ?? this.approver_id?.toString() ?? 'None'); this.created_date$.set(dateFrom(+new Date(this.created_at))); this.favorites$.set(this.fav_count); this.score$.set(this.score); } + update(data: PostData) { + Object.assign(this, data); + this.update$(); + return this; + } + get pathname() { return `/posts/${this.id}` } get uploader() { return User.manager.get(this.uploader_id); } get approver() { if (this.approver_id) return User.manager.get(this.approver_id); else return null } diff --git a/src/structure/Tag.ts b/src/structure/Tag.ts index 36ba14e..7815299 100644 --- a/src/structure/Tag.ts +++ b/src/structure/Tag.ts @@ -1,17 +1,22 @@ import type { Booru } from "./Booru"; +const INTL_number = new Intl.NumberFormat('en', {notation: 'compact'}) export interface TagOptions {} export interface Tag extends TagData {} export class Tag { static manager = new Map(); + post_count$ = $.state(0, {format: (value) => `${INTL_number.format(value)}`}); + name$ = $.state(''); constructor(data: TagData) { Object.assign(this, data); + this.$update(); } static async fetch(booru: Booru, id: id) { - const req = await fetch(`${booru.api}/tags/${id}.json`); - const post = new this(await req.json()); - return post; + const data = await fetch(`${booru.api}/tags/${id}.json`).then(async data => await data.json()) as TagData; + const instance = this.manager.get(data.id)?.update(data) ?? new this(data); + this.manager.set(instance.id, instance); + return instance; } static async fetchMultiple(booru: Booru, search?: Partial, limit = 1000) { @@ -30,12 +35,23 @@ export class Tag { const req = await fetch(`${booru.api}/tags.json?limit=${limit}${searchQuery}`); const dataArray: TagData[] = await req.json(); const list = dataArray.map(data => { - const instance = new this(data); + const instance = this.manager.get(data.id)?.update(data) ?? new this(data); this.manager.set(instance.id, instance); return instance; }); return list; } + + update(data: TagData) { + Object.assign(this, data); + this.$update(); + return this; + } + + $update() { + this.post_count$.set(this.post_count); + this.name$.set(this.name); + } } export interface TagData { diff --git a/src/structure/User.ts b/src/structure/User.ts index 5f56916..f3bb1ee 100644 --- a/src/structure/User.ts +++ b/src/structure/User.ts @@ -4,14 +4,17 @@ export class UserOptions {} export interface User extends UserOptions, UserData {} export class User { static manager = new Map(); + name$ = $.state('loding...'); constructor(data: UserData) { Object.assign(this, data); + this.update$(); } static async fetch(booru: Booru, id: id) { - const req = await fetch(`${booru.api}/posts/${id}.json`); - const post = new this(await req.json()); - return post; + const data = await fetch(`${booru.api}/users/${id}.json`).then(async data => await data.json()) as UserData; + const instance = this.manager.get(data.id)?.update(data) ?? new this(data); + this.manager.set(instance.id, instance); + return instance; } static async fetchMultiple(booru: Booru, search?: Partial, limit = 200) { @@ -36,6 +39,16 @@ export class User { }); return list; } + + update(data: UserData) { + Object.assign(this, data); + this.update$(); + return this; + } + + update$() { + this.name$.set(this.name); + } } export interface UserData {