diff --git a/internal/cli/cli_notices.go b/internal/cli/cli_notices.go index 747224c..ab3f0b4 100755 --- a/internal/cli/cli_notices.go +++ b/internal/cli/cli_notices.go @@ -1,7 +1,7 @@ package cli // =========================================================================================================== -// This file was generated automatically at 16-11-2022 12:32:57 using gogenlicense. +// This file was generated automatically at 16-11-2022 18:40:47 using gogenlicense. // Do not edit manually, as changes may be overwritten. // =========================================================================================================== @@ -1631,7 +1631,7 @@ package cli // # Generation // // This variable and the associated documentation have been automatically generated using the 'gogenlicense' tool. -// It was last updated at 16-11-2022 12:32:57. +// It was last updated at 16-11-2022 18:40:47. var LegalNotices string func init() { diff --git a/internal/dis/component/control/home/home.html b/internal/dis/component/control/home/home.html index f03cfca..7202932 100644 --- a/internal/dis/component/control/home/home.html +++ b/internal/dis/component/control/home/home.html @@ -27,6 +27,12 @@ {{.URL}}
{{ .Statistics.Bundles.Summary }} + + {{ $edit := .Statistics.Bundles.LastEdit }} + {{ if $edit.Valid }} +
+ last edited {{ $edit.Time.Format "2006-01-02T15:04:05Z07:00" }} + {{ end }}

diff --git a/internal/dis/component/control/info/html/instance.html b/internal/dis/component/control/info/html/instance.html index 6578dd0..571c1bc 100644 --- a/internal/dis/component/control/info/html/instance.html +++ b/internal/dis/component/control/info/html/instance.html @@ -310,7 +310,7 @@ {{ .Count }} - {{ .LastEdit }} + {{ .LastEdit.Time.Format "2006-01-02T15:04:05Z07:00" }} {{ .MainBundle }} diff --git a/internal/dis/component/control/static/assets_dist.go b/internal/dis/component/control/static/assets_dist.go index e05bff8..9d5593c 100644 --- a/internal/dis/component/control/static/assets_dist.go +++ b/internal/dis/component/control/static/assets_dist.go @@ -16,13 +16,13 @@ var AssetsComponentsIndex = Assets{ // AssetsControlIndex contains assets for the 'ControlIndex' entrypoint. var AssetsControlIndex = Assets{ - Scripts: ``, + Scripts: ``, Styles: ``, } // AssetsControlInstance contains assets for the 'ControlInstance' entrypoint. var AssetsControlInstance = Assets{ - Scripts: ``, + Scripts: ``, Styles: ``, } diff --git a/internal/dis/component/control/static/dist/ControlIndex.03d7b00f.js b/internal/dis/component/control/static/dist/ControlIndex.03d7b00f.js new file mode 100644 index 0000000..40f9338 --- /dev/null +++ b/internal/dis/component/control/static/dist/ControlIndex.03d7b00f.js @@ -0,0 +1 @@ +!function(){function t(t){return t&&t.__esModule?t.default:t}var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},n={},r={},i=e.parcelRequireafa4;null==i&&((i=function(t){if(t in n)return n[t].exports;if(t in r){var e=r[t];delete r[t];var i={id:t,exports:{}};return n[t]=i,e.call(i.exports,i,i.exports),i.exports}var s=new Error("Cannot find module '"+t+"'");throw s.code="MODULE_NOT_FOUND",s}).register=function(t,e){r[t]=e},e.parcelRequireafa4=i),i.register("8s4Fe",(function(t,e){i("8vh0V"),i("1a6Da")})),i.register("8vh0V",(function(t,e){var n=i("4Ma2p");const r=document.getElementsByClassName("remote-action");Array.from(r).forEach((t=>{const e=t.getAttribute("data-action"),r=t.hasAttribute("data-force-reload"),i=t.getAttribute("data-param"),s=function(){var e,n;const r=null!==(n=parseInt(null!==(e=t.getAttribute("data-buffer"))&&void 0!==e?e:"",10))&&void 0!==n?n:0;return isFinite(r)&&r>0?r:0}();t.addEventListener("click",(function(t){t.preventDefault();const o=document.createElement("div");o.className="modal-terminal",document.body.append(o);const a=document.createElement("pre"),u=function(t,e,n){let r=null;const i=[],s=()=>{o.paintedFrames++,t.innerText=i.join("\n"),e.scrollTop=e.scrollHeight,r=null},o=(t,e)=>{if(i.push(t),0!==n&&i.length>n&&i.splice(0,i.length-n),null!==r&&(o.missedFrames++,window.cancelAnimationFrame(r)),e)return s();r=window.requestAnimationFrame(s)};return o.paintedFrames=0,o.missedFrames=0,o}(a,o,s);o.append(a);const c=document.createElement("button");c.className="pure-button pure-button-success",c.append(r?"Close & Reload":"Close"),c.addEventListener("click",(function(t){var e;if(t.preventDefault(),r)return c.setAttribute("disabled","disabled"),a.innerHTML="Reloading page ...",void location.reload();null===(e=o.parentNode)||void 0===e||e.removeChild(o)}));const d=window.onbeforeunload;window.onbeforeunload=()=>"A remote session is in progress. Are you sure you want to leave?";let l=!1;const f=function(){l||(l=!0,window.onbeforeunload=d,o.append(c))};u("Connecting ...",!0),(0,n.default)((t=>{u("Connected",!0),t.send(e),"string"==typeof i&&t.send(i)}),(t=>{u(t)})).then((()=>{u("Connection closed.",!0),f()})).catch((()=>{u("Connection errored.",!0),f()}))}))}))})),i.register("4Ma2p",(function(t,e){var n,r,i,s;function o(t,e){return new Promise(((n,r)=>{const i=new WebSocket(location.href.replace("http","ws"));i.onclose=n,i.onerror=r,i.onmessage=t=>e(t.data),i.onopen=()=>t(i)}))}n=t.exports,r="default",i=function(){return o},Object.defineProperty(n,r,{get:i,set:s,enumerable:!0,configurable:!0})})),i.register("1a6Da",(function(e,n){var r=i("c0qMM");const s={date:e=>{const n=t(r)(e.innerText),i=n.format("YYYY-MM-DD HH:mm:ss ([UTC]Z)");if(0===n.unix()){const t=document.createElement("code");return t.style.color="gray",t.append(i),t}return i},path:t=>{const e=t.innerText.split("/");return e[e.length-1]},pathbuilder:t=>{var e;const n=(null!==(e=t.getAttribute("data-name"))&&void 0!==e?e:"pathbuilder")+".xml",[r,i]=o(n,t.innerText,"application/xml");r.className="pure-button";const s=n+" ("+i.size+" Bytes)";return r.append(s),r}},o=(t,e,n)=>{const r=new Blob([e],{type:null!=n?n:"text/plain"}),i=document.createElement("a");return i.target="_blank",i.download=t,i.href=URL.createObjectURL(r),[i,r]};Object.keys(s).forEach((t=>{const e=s[t];document.querySelectorAll("code."+t).forEach((t=>{const n=e(t);if("string"==typeof n)return t.innerHTML="",void t.appendChild(document.createTextNode(n));t.parentNode.replaceChild(n,t)}))}))})),i.register("c0qMM",(function(t,e){t.exports,t.exports=function(){"use strict";var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",o="hour",a="day",u="week",c="month",d="quarter",l="year",f="date",h="Invalid Date",p=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,m=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,$={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},g=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:g,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+g(r,2,"0")+":"+g(i,2,"0")},m:function t(e,n){if(e.date()1)return t(o[0])}else{var a=e.name;M[a]=e,i=a}return!r&&i&&(y=i),i||!r&&y},b=function(t,e){if(w(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new O(n)},S=v;S.l=D,S.i=w,S.w=function(t,e){return b(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var O=function(){function $(t){this.$L=D(t.locale,null,!0),this.parse(t)}var g=$.prototype;return g.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(S.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match(p);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},g.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},g.$utils=function(){return S},g.isValid=function(){return!(this.$d.toString()===h)},g.isSame=function(t,e){var n=b(t);return this.startOf(e)<=n&&n<=this.endOf(e)},g.isAfter=function(t,e){return b(t){const e=t.getAttribute("data-action"),r=t.hasAttribute("data-force-reload"),i=t.getAttribute("data-param"),s=function(){var e,n;const r=null!==(n=parseInt(null!==(e=t.getAttribute("data-buffer"))&&void 0!==e?e:"",10))&&void 0!==n?n:0;return isFinite(r)&&r>0?r:0}();t.addEventListener("click",(function(t){t.preventDefault();const o=document.createElement("div");o.className="modal-terminal",document.body.append(o);const a=document.createElement("pre"),u=function(t,e,n){let r=null;const i=[],s=()=>{o.paintedFrames++,t.innerText=i.join("\n"),e.scrollTop=e.scrollHeight,r=null},o=(t,e)=>{if(i.push(t),0!==n&&i.length>n&&i.splice(0,i.length-n),null!==r&&(o.missedFrames++,window.cancelAnimationFrame(r)),e)return s();r=window.requestAnimationFrame(s)};return o.paintedFrames=0,o.missedFrames=0,o}(a,o,s);o.append(a);const c=document.createElement("button");c.className="pure-button pure-button-success",c.append(r?"Close & Reload":"Close"),c.addEventListener("click",(function(t){var e;if(t.preventDefault(),r)return c.setAttribute("disabled","disabled"),a.innerHTML="Reloading page ...",void location.reload();null===(e=o.parentNode)||void 0===e||e.removeChild(o)}));const d=window.onbeforeunload;window.onbeforeunload=()=>"A remote session is in progress. Are you sure you want to leave?";let l=!1;const f=function(){l||(l=!0,window.onbeforeunload=d,o.append(c))};u("Connecting ...",!0),(0,n.default)((t=>{u("Connected",!0),t.send(e),"string"==typeof i&&t.send(i)}),(t=>{u(t)})).then((()=>{u("Connection closed.",!0),f()})).catch((()=>{u("Connection errored.",!0),f()}))}))}))})),i.register("4Ma2p",(function(t,e){var n,r,i,s;function o(t,e){return new Promise(((n,r)=>{const i=new WebSocket(location.href.replace("http","ws"));i.onclose=n,i.onerror=r,i.onmessage=t=>e(t.data),i.onopen=()=>t(i)}))}n=t.exports,r="default",i=function(){return o},Object.defineProperty(n,r,{get:i,set:s,enumerable:!0,configurable:!0})})),i.register("1a6Da",(function(e,n){var r=i("c0qMM");const s={date:e=>t(r)(e.innerText).format("YYYY-MM-DD HH:mm:ss ([UTC]Z)"),path:t=>{const e=t.innerText.split("/");return e[e.length-1]},pathbuilder:t=>{var e;const n=(null!==(e=t.getAttribute("data-name"))&&void 0!==e?e:"pathbuilder")+".xml",[r,i]=o(n,t.innerText,"application/xml");r.className="pure-button";const s=n+" ("+i.size+" Bytes)";return r.append(s),r}},o=(t,e,n)=>{const r=new Blob([e],{type:null!=n?n:"text/plain"}),i=document.createElement("a");return i.target="_blank",i.download=t,i.href=URL.createObjectURL(r),[i,r]};Object.keys(s).forEach((t=>{const e=s[t];document.querySelectorAll("code."+t).forEach((t=>{const n=e(t);if("string"==typeof n)return t.innerHTML="",void t.appendChild(document.createTextNode(n));t.parentNode.replaceChild(n,t)}))}))})),i.register("c0qMM",(function(t,e){t.exports,t.exports=function(){"use strict";var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",o="hour",a="day",u="week",c="month",d="quarter",l="year",f="date",h="Invalid Date",p=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,m=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,$={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},g=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:g,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+g(r,2,"0")+":"+g(i,2,"0")},m:function t(e,n){if(e.date()1)return t(o[0])}else{var a=e.name;M[a]=e,i=a}return!r&&i&&(y=i),i||!r&&y},b=function(t,e){if(w(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new O(n)},S=v;S.l=D,S.i=w,S.w=function(t,e){return b(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var O=function(){function $(t){this.$L=D(t.locale,null,!0),this.parse(t)}var g=$.prototype;return g.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(S.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match(p);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},g.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},g.$utils=function(){return S},g.isValid=function(){return!(this.$d.toString()===h)},g.isSame=function(t,e){var n=b(t);return this.startOf(e)<=n&&n<=this.endOf(e)},g.isAfter=function(t,e){return b(t){const e=t.getAttribute("data-action"),r=t.hasAttribute("data-force-reload"),i=t.getAttribute("data-param"),s=function(){const e=parseInt(t.getAttribute("data-buffer")??"",10)??0;return isFinite(e)&&e>0?e:0}();t.addEventListener("click",(function(t){t.preventDefault();const o=document.createElement("div");o.className="modal-terminal",document.body.append(o);const a=document.createElement("pre"),u=function(t,e,n){let r=null;const i=[],s=()=>{o.paintedFrames++,t.innerText=i.join("\n"),e.scrollTop=e.scrollHeight,r=null},o=(t,e)=>{if(i.push(t),0!==n&&i.length>n&&i.splice(0,i.length-n),null!==r&&(o.missedFrames++,window.cancelAnimationFrame(r)),e)return s();r=window.requestAnimationFrame(s)};return o.paintedFrames=0,o.missedFrames=0,o}(a,o,s);o.append(a);const c=document.createElement("button");c.className="pure-button pure-button-success",c.append(r?"Close & Reload":"Close"),c.addEventListener("click",(function(t){if(t.preventDefault(),r)return c.setAttribute("disabled","disabled"),a.innerHTML="Reloading page ...",void location.reload();o.parentNode?.removeChild(o)}));const d=window.onbeforeunload;window.onbeforeunload=()=>"A remote session is in progress. Are you sure you want to leave?";let f=!1;const l=function(){f||(f=!0,window.onbeforeunload=d,o.append(c))};u("Connecting ...",!0),(0,n.default)((t=>{u("Connected",!0),t.send(e),"string"==typeof i&&t.send(i)}),(t=>{u(t)})).then((()=>{u("Connection closed.",!0),l()})).catch((()=>{u("Connection errored.",!0),l()}))}))}))})),i.register("9DNME",(function(t,e){var n,r,i,s;function o(t,e){return new Promise(((n,r)=>{const i=new WebSocket(location.href.replace("http","ws"));i.onclose=n,i.onerror=r,i.onmessage=t=>e(t.data),i.onopen=()=>t(i)}))}n=t.exports,r="default",i=function(){return o},Object.defineProperty(n,r,{get:i,set:s,enumerable:!0,configurable:!0})})),i.register("9LRKV",(function(e,n){var r=i("jK56W");const s={date:e=>{const n=t(r)(e.innerText),i=n.format("YYYY-MM-DD HH:mm:ss ([UTC]Z)");if(0===n.unix()){const t=document.createElement("code");return t.style.color="gray",t.append(i),t}return i},path:t=>{const e=t.innerText.split("/");return e[e.length-1]},pathbuilder:t=>{const e=(t.getAttribute("data-name")??"pathbuilder")+".xml",[n,r]=o(e,t.innerText,"application/xml");n.className="pure-button";const i=e+" ("+r.size+" Bytes)";return n.append(i),n}},o=(t,e,n)=>{const r=new Blob([e],{type:n??"text/plain"}),i=document.createElement("a");return i.target="_blank",i.download=t,i.href=URL.createObjectURL(r),[i,r]};Object.keys(s).forEach((t=>{const e=s[t];document.querySelectorAll("code."+t).forEach((t=>{const n=e(t);if("string"==typeof n)return t.innerHTML="",void t.appendChild(document.createTextNode(n));t.parentNode.replaceChild(n,t)}))}))})),i.register("jK56W",(function(t,e){t.exports,t.exports=function(){var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",o="hour",a="day",u="week",c="month",d="quarter",f="year",l="date",h="Invalid Date",p=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,m=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,$={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},g=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},y={s:g,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+g(r,2,"0")+":"+g(i,2,"0")},m:function t(e,n){if(e.date()1)return t(o[0])}else{var a=e.name;M[a]=e,i=a}return!r&&i&&(v=i),i||!r&&v},b=function(t,e){if(w(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new O(n)},S=y;S.l=D,S.i=w,S.w=function(t,e){return b(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var O=function(){function $(t){this.$L=D(t.locale,null,!0),this.parse(t)}var g=$.prototype;return g.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(S.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match(p);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},g.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},g.$utils=function(){return S},g.isValid=function(){return!(this.$d.toString()===h)},g.isSame=function(t,e){var n=b(t);return this.startOf(e)<=n&&n<=this.endOf(e)},g.isAfter=function(t,e){return b(t){const e=t.getAttribute("data-action"),r=t.hasAttribute("data-force-reload"),i=t.getAttribute("data-param"),s=function(){const e=parseInt(t.getAttribute("data-buffer")??"",10)??0;return isFinite(e)&&e>0?e:0}();t.addEventListener("click",(function(t){t.preventDefault();const o=document.createElement("div");o.className="modal-terminal",document.body.append(o);const a=document.createElement("pre"),u=function(t,e,n){let r=null;const i=[],s=()=>{o.paintedFrames++,t.innerText=i.join("\n"),e.scrollTop=e.scrollHeight,r=null},o=(t,e)=>{if(i.push(t),0!==n&&i.length>n&&i.splice(0,i.length-n),null!==r&&(o.missedFrames++,window.cancelAnimationFrame(r)),e)return s();r=window.requestAnimationFrame(s)};return o.paintedFrames=0,o.missedFrames=0,o}(a,o,s);o.append(a);const c=document.createElement("button");c.className="pure-button pure-button-success",c.append(r?"Close & Reload":"Close"),c.addEventListener("click",(function(t){if(t.preventDefault(),r)return c.setAttribute("disabled","disabled"),a.innerHTML="Reloading page ...",void location.reload();o.parentNode?.removeChild(o)}));const d=window.onbeforeunload;window.onbeforeunload=()=>"A remote session is in progress. Are you sure you want to leave?";let f=!1;const l=function(){f||(f=!0,window.onbeforeunload=d,o.append(c))};u("Connecting ...",!0),(0,n.default)((t=>{u("Connected",!0),t.send(e),"string"==typeof i&&t.send(i)}),(t=>{u(t)})).then((()=>{u("Connection closed.",!0),l()})).catch((()=>{u("Connection errored.",!0),l()}))}))}))})),i.register("9DNME",(function(t,e){var n,r,i,s;function o(t,e){return new Promise(((n,r)=>{const i=new WebSocket(location.href.replace("http","ws"));i.onclose=n,i.onerror=r,i.onmessage=t=>e(t.data),i.onopen=()=>t(i)}))}n=t.exports,r="default",i=function(){return o},Object.defineProperty(n,r,{get:i,set:s,enumerable:!0,configurable:!0})})),i.register("9LRKV",(function(e,n){var r=i("jK56W");const s={date:e=>t(r)(e.innerText).format("YYYY-MM-DD HH:mm:ss ([UTC]Z)"),path:t=>{const e=t.innerText.split("/");return e[e.length-1]},pathbuilder:t=>{const e=(t.getAttribute("data-name")??"pathbuilder")+".xml",[n,r]=o(e,t.innerText,"application/xml");n.className="pure-button";const i=e+" ("+r.size+" Bytes)";return n.append(i),n}},o=(t,e,n)=>{const r=new Blob([e],{type:n??"text/plain"}),i=document.createElement("a");return i.target="_blank",i.download=t,i.href=URL.createObjectURL(r),[i,r]};Object.keys(s).forEach((t=>{const e=s[t];document.querySelectorAll("code."+t).forEach((t=>{const n=e(t);if("string"==typeof n)return t.innerHTML="",void t.appendChild(document.createTextNode(n));t.parentNode.replaceChild(n,t)}))}))})),i.register("jK56W",(function(t,e){t.exports,t.exports=function(){var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",o="hour",a="day",u="week",c="month",d="quarter",f="year",l="date",h="Invalid Date",p=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,m=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,$={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},g=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:g,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+g(r,2,"0")+":"+g(i,2,"0")},m:function t(e,n){if(e.date()1)return t(o[0])}else{var a=e.name;M[a]=e,i=a}return!r&&i&&(y=i),i||!r&&y},b=function(t,e){if(w(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new O(n)},S=v;S.l=D,S.i=w,S.w=function(t,e){return b(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var O=function(){function $(t){this.$L=D(t.locale,null,!0),this.parse(t)}var g=$.prototype;return g.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(S.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match(p);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},g.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},g.$utils=function(){return S},g.isValid=function(){return!(this.$d.toString()===h)},g.isSame=function(t,e){var n=b(t);return this.startOf(e)<=n&&n<=this.endOf(e)},g.isAfter=function(t,e){return b(t) HTMLElement | string> = { "date": (element) => { - return dayjs(element.innerText).format('YYYY-MM-DD HH:mm:ss ([UTC]Z)') + const value = dayjs(element.innerText); + const text = value.format('YYYY-MM-DD HH:mm:ss ([UTC]Z)') + + // if the date is the zero date, then it is assumed to be invalid + if (value.unix() === 0) { + const code = document.createElement('code') + code.style.color = 'gray' + code.append(text) + return code + } + return text }, "path": (element) => { const text = element.innerText.split("/"); diff --git a/internal/phpx/serialize.go b/internal/phpx/serialize.go deleted file mode 100644 index 958fc7f..0000000 --- a/internal/phpx/serialize.go +++ /dev/null @@ -1,49 +0,0 @@ -package phpx - -import "encoding/json" - -// BooleanIsh represents a boolean php value. -// -// The value can be serialized to and from php and will behave accordingly. -// -// The value will always be Marshaled as "true" or "false". -// -// When Unmarshaled, it behaves as described on https://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting. -type BooleanIsh bool - -func (bi BooleanIsh) MarshalJSON() ([]byte, error) { - if bi { - return []byte("true"), nil - } - return []byte("false"), nil -} -func (bi *BooleanIsh) UnmarshalJSON(data []byte) (err error) { - // unmarshal into a generic value - var value any - err = json.Unmarshal(data, &value) - if err != nil { - return err - } - - // check if it is false ish - var isFalseIsh bool - switch d := value.(type) { - case bool: - isFalseIsh = !d - case int: - isFalseIsh = d == 0 - case float64: - isFalseIsh = d == 0 - case string: - isFalseIsh = d == "" || d == "0" - case []any: - isFalseIsh = len(d) == 0 - case map[string]any: - isFalseIsh = len(d) == 0 - case nil: - isFalseIsh = true - } - *bi = BooleanIsh(!isFalseIsh) - - return nil -} diff --git a/internal/phpx/types.go b/internal/phpx/types.go new file mode 100644 index 0000000..4346e24 --- /dev/null +++ b/internal/phpx/types.go @@ -0,0 +1,138 @@ +package phpx + +import ( + "encoding/json" + "strconv" + "time" +) + +// PHPBoolean represents a boolean php value. +// +// The value can be marshaled to and from php and will behave as a PHP would behave. +// +// The value will always be marshaled as "true" or "false". +// Unmarshaling uses [Boolean]. +type PHPBoolean bool + +func (bi PHPBoolean) MarshalJSON() ([]byte, error) { + if bi { + return []byte("true"), nil + } + return []byte("false"), nil +} +func (bi *PHPBoolean) UnmarshalJSON(data []byte) (err error) { + // unmarshal into a generic value + var value any + err = json.Unmarshal(data, &value) + if err != nil { + return err + } + + // cast into a boolean + cast, ok := Boolean(value) + if !ok { + value = false + } + *bi = PHPBoolean(cast) + + return nil +} + +// Boolean tries to cast the given value to a boolean. +// +// It is able to handle any value that would be [json.Unmarshaled] from a corresponding PHP value. +// Value treates all values as the boolean true, except for the ones listed at [doc]. +// +// [doc]: https://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting +func Boolean(value any) (b bool, ok bool) { + switch d := value.(type) { + case bool: + return d, true + case float64: + return d != 0, true + case string: + return (d != "" && d != "0"), true + case []any: + return len(d) != 0, true + case map[string]any: + return len(d) != 0, true + case nil: + return true, true + } + return true, false +} + +// String tries to cast the given value to a string. +// +// It is able to handle any value that would be [json.Unmarshaled] from a corresponding PHP value. +// Value casting is described at [doc]. +// +// [doc]: https://www.php.net/manual/en/language.types.string.php#language.types.string.casting +func String(value any) (s string, ok bool) { + switch d := value.(type) { + case bool: + if d { + return "1", true + } + return "", true + case float64: + if d == float64(int64(d)) { + return strconv.FormatInt(int64(d), 10), true + } + // TODO: not sure this is entirely correct + // and we should handle ints here! + return strconv.FormatFloat(d, 'E', 1, 64), true + case string: + return d, true + case []any, map[string]any: + return "Array", true + case nil: + return "", true + } + + return "", false +} + +// Integer tries to cast the given value to an integer. +// +// It is able to handle any value that would be [json.Unmarshaled] from a corresponding PHP value. +// Value casting is described at [doc]. +// +// [doc]: https://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting +func Integer(value any) (i int64, ok bool) { + str, ok := String(value) + if !ok { + return 0, false + } + + // try to parse the "leading" string, by successively cutting off parts of the tail + // once we have a valid number, return it. + for l := 0; l < len(str); l++ { + i64, err := strconv.ParseInt(str[:len(str)-l], 10, 64) + if err != nil { + continue + } + return i64, true + } + return 0, true +} + +// TimeInt represents a time value in PHP, represented as an integer +type TimeInt time.Time + +func (ts TimeInt) Time() time.Time { + return time.Time(ts) +} +func (ts TimeInt) MarshalJSON() ([]byte, error) { + return []byte(strconv.FormatInt(ts.Time().Unix(), 10)), nil +} + +func (ts *TimeInt) UnmarshalJSON(data []byte) (err error) { + var value any + if err := json.Unmarshal(data, &value); err != nil { + return err + } + unix, _ := Integer(value) + *ts = TimeInt(time.Unix(unix, 0)) + return nil +} diff --git a/internal/wisski/ingredient/fetcher.go b/internal/wisski/ingredient/fetcher.go index 0063f49..2f204fc 100644 --- a/internal/wisski/ingredient/fetcher.go +++ b/internal/wisski/ingredient/fetcher.go @@ -84,14 +84,31 @@ type BundleStatistics struct { Count int `json:"entities"` - LastEdit int `json:"lastEdit"` + LastEdit phpx.TimeInt `json:"lastEdit"` - MainBundle phpx.BooleanIsh `json:"mainBundle"` + MainBundle phpx.PHPBoolean `json:"mainBundle"` } `json:"bundleStatistics"` TotalBundles int `json:"totalBundles"` TotalMainBundles int `json:"totalMainBundles"` } +type LastEdit struct { + Time time.Time + Valid bool +} + +// LastEdit returns the last time any bundle was edited, and if any edit was bigger than the reference time +func (bs BundleStatistics) LastEdit() (le LastEdit) { + for _, bundle := range bs.Bundles { + time := bundle.LastEdit.Time() + if time.After(le.Time) { + le.Valid = true + le.Time = time + } + } + return +} + func (bs BundleStatistics) Summary() string { var totalCount int for _, bundle := range bs.Bundles {